libmnl
1.0.3
|
00001 /* 00002 * (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU Lesser General Public License as published 00006 * by the Free Software Foundation; either version 2.1 of the License, or 00007 * (at your option) any later version. 00008 */ 00009 #include <limits.h> /* for INT_MAX */ 00010 #include <libmnl/libmnl.h> 00011 #include <string.h> 00012 #include <errno.h> 00013 #include "internal.h" 00014 00038 uint16_t mnl_attr_get_type(const struct nlattr *attr) 00039 { 00040 return attr->nla_type & NLA_TYPE_MASK; 00041 } 00042 EXPORT_SYMBOL(mnl_attr_get_type); 00043 00051 uint16_t mnl_attr_get_len(const struct nlattr *attr) 00052 { 00053 return attr->nla_len; 00054 } 00055 EXPORT_SYMBOL(mnl_attr_get_len); 00056 00063 uint16_t mnl_attr_get_payload_len(const struct nlattr *attr) 00064 { 00065 return attr->nla_len - MNL_ATTR_HDRLEN; 00066 } 00067 EXPORT_SYMBOL(mnl_attr_get_payload_len); 00068 00075 void *mnl_attr_get_payload(const struct nlattr *attr) 00076 { 00077 return (void *)attr + MNL_ATTR_HDRLEN; 00078 } 00079 EXPORT_SYMBOL(mnl_attr_get_payload); 00080 00097 bool mnl_attr_ok(const struct nlattr *attr, int len) 00098 { 00099 return len >= (int)sizeof(struct nlattr) && 00100 attr->nla_len >= sizeof(struct nlattr) && 00101 (int)attr->nla_len <= len; 00102 } 00103 EXPORT_SYMBOL(mnl_attr_ok); 00104 00114 struct nlattr *mnl_attr_next(const struct nlattr *attr) 00115 { 00116 return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len)); 00117 } 00118 EXPORT_SYMBOL(mnl_attr_next); 00119 00134 int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max) 00135 { 00136 if (mnl_attr_get_type(attr) > max) { 00137 errno = EOPNOTSUPP; 00138 return -1; 00139 } 00140 return 1; 00141 } 00142 EXPORT_SYMBOL(mnl_attr_type_valid); 00143 00144 static int __mnl_attr_validate(const struct nlattr *attr, 00145 enum mnl_attr_data_type type, size_t exp_len) 00146 { 00147 uint16_t attr_len = mnl_attr_get_payload_len(attr); 00148 const char *attr_data = mnl_attr_get_payload(attr); 00149 00150 if (attr_len < exp_len) { 00151 errno = ERANGE; 00152 return -1; 00153 } 00154 switch(type) { 00155 case MNL_TYPE_FLAG: 00156 if (attr_len > 0) { 00157 errno = ERANGE; 00158 return -1; 00159 } 00160 break; 00161 case MNL_TYPE_NUL_STRING: 00162 if (attr_len == 0) { 00163 errno = ERANGE; 00164 return -1; 00165 } 00166 if (attr_data[attr_len-1] != '\0') { 00167 errno = EINVAL; 00168 return -1; 00169 } 00170 break; 00171 case MNL_TYPE_STRING: 00172 if (attr_len == 0) { 00173 errno = ERANGE; 00174 return -1; 00175 } 00176 break; 00177 case MNL_TYPE_NESTED: 00178 /* empty nested attributes are OK. */ 00179 if (attr_len == 0) 00180 break; 00181 /* if not empty, they must contain one header, eg. flag */ 00182 if (attr_len < MNL_ATTR_HDRLEN) { 00183 errno = ERANGE; 00184 return -1; 00185 } 00186 break; 00187 default: 00188 /* make gcc happy. */ 00189 break; 00190 } 00191 if (exp_len && attr_len > exp_len) { 00192 errno = ERANGE; 00193 return -1; 00194 } 00195 return 0; 00196 } 00197 00198 static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = { 00199 [MNL_TYPE_U8] = sizeof(uint8_t), 00200 [MNL_TYPE_U16] = sizeof(uint16_t), 00201 [MNL_TYPE_U32] = sizeof(uint32_t), 00202 [MNL_TYPE_U64] = sizeof(uint64_t), 00203 }; 00204 00214 int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type) 00215 { 00216 int exp_len; 00217 00218 if (type >= MNL_TYPE_MAX) { 00219 errno = EINVAL; 00220 return -1; 00221 } 00222 exp_len = mnl_attr_data_type_len[type]; 00223 return __mnl_attr_validate(attr, type, exp_len); 00224 } 00225 EXPORT_SYMBOL(mnl_attr_validate); 00226 00237 int 00238 mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, 00239 size_t exp_len) 00240 { 00241 if (type >= MNL_TYPE_MAX) { 00242 errno = EINVAL; 00243 return -1; 00244 } 00245 return __mnl_attr_validate(attr, type, exp_len); 00246 } 00247 EXPORT_SYMBOL(mnl_attr_validate2); 00248 00264 int 00265 mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, 00266 mnl_attr_cb_t cb, void *data) 00267 { 00268 int ret = MNL_CB_OK; 00269 const struct nlattr *attr; 00270 00271 mnl_attr_for_each(attr, nlh, offset) 00272 if ((ret = cb(attr, data)) <= MNL_CB_STOP) 00273 return ret; 00274 return ret; 00275 } 00276 EXPORT_SYMBOL(mnl_attr_parse); 00277 00292 int 00293 mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb, 00294 void *data) 00295 { 00296 int ret = MNL_CB_OK; 00297 const struct nlattr *attr; 00298 00299 mnl_attr_for_each_nested(attr, nested) 00300 if ((ret = cb(attr, data)) <= MNL_CB_STOP) 00301 return ret; 00302 return ret; 00303 } 00304 EXPORT_SYMBOL(mnl_attr_parse_nested); 00305 00325 int 00326 mnl_attr_parse_payload(const void *payload, size_t payload_len, 00327 mnl_attr_cb_t cb, void *data) 00328 { 00329 int ret = MNL_CB_OK; 00330 const struct nlattr *attr; 00331 00332 mnl_attr_for_each_payload(payload, payload_len) 00333 if ((ret = cb(attr, data)) <= MNL_CB_STOP) 00334 return ret; 00335 return ret; 00336 } 00337 EXPORT_SYMBOL(mnl_attr_parse_payload); 00338 00345 uint8_t mnl_attr_get_u8(const struct nlattr *attr) 00346 { 00347 return *((uint8_t *)mnl_attr_get_payload(attr)); 00348 } 00349 EXPORT_SYMBOL(mnl_attr_get_u8); 00350 00357 uint16_t mnl_attr_get_u16(const struct nlattr *attr) 00358 { 00359 return *((uint16_t *)mnl_attr_get_payload(attr)); 00360 } 00361 EXPORT_SYMBOL(mnl_attr_get_u16); 00362 00369 uint32_t mnl_attr_get_u32(const struct nlattr *attr) 00370 { 00371 return *((uint32_t *)mnl_attr_get_payload(attr)); 00372 } 00373 EXPORT_SYMBOL(mnl_attr_get_u32); 00374 00383 uint64_t mnl_attr_get_u64(const struct nlattr *attr) 00384 { 00385 uint64_t tmp; 00386 memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp)); 00387 return tmp; 00388 } 00389 EXPORT_SYMBOL(mnl_attr_get_u64); 00390 00397 const char *mnl_attr_get_str(const struct nlattr *attr) 00398 { 00399 return mnl_attr_get_payload(attr); 00400 } 00401 EXPORT_SYMBOL(mnl_attr_get_str); 00402 00413 void 00414 mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data) 00415 { 00416 struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh); 00417 uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len; 00418 00419 attr->nla_type = type; 00420 attr->nla_len = payload_len; 00421 memcpy(mnl_attr_get_payload(attr), data, len); 00422 nlh->nlmsg_len += MNL_ALIGN(payload_len); 00423 } 00424 EXPORT_SYMBOL(mnl_attr_put); 00425 00436 void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data) 00437 { 00438 mnl_attr_put(nlh, type, sizeof(uint8_t), &data); 00439 } 00440 EXPORT_SYMBOL(mnl_attr_put_u8); 00441 00451 void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data) 00452 { 00453 mnl_attr_put(nlh, type, sizeof(uint16_t), &data); 00454 } 00455 EXPORT_SYMBOL(mnl_attr_put_u16); 00456 00466 void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data) 00467 { 00468 mnl_attr_put(nlh, type, sizeof(uint32_t), &data); 00469 } 00470 EXPORT_SYMBOL(mnl_attr_put_u32); 00471 00481 void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data) 00482 { 00483 mnl_attr_put(nlh, type, sizeof(uint64_t), &data); 00484 } 00485 EXPORT_SYMBOL(mnl_attr_put_u64); 00486 00496 void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data) 00497 { 00498 mnl_attr_put(nlh, type, strlen(data), data); 00499 } 00500 EXPORT_SYMBOL(mnl_attr_put_str); 00501 00514 void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data) 00515 { 00516 mnl_attr_put(nlh, type, strlen(data)+1, data); 00517 } 00518 EXPORT_SYMBOL(mnl_attr_put_strz); 00519 00529 struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type) 00530 { 00531 struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh); 00532 00533 /* set start->nla_len in mnl_attr_nest_end() */ 00534 start->nla_type = NLA_F_NESTED | type; 00535 nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr)); 00536 00537 return start; 00538 } 00539 EXPORT_SYMBOL(mnl_attr_nest_start); 00540 00555 bool 00556 mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, 00557 uint16_t type, size_t len, const void *data) 00558 { 00559 if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen) 00560 return false; 00561 mnl_attr_put(nlh, type, len, data); 00562 return true; 00563 } 00564 EXPORT_SYMBOL(mnl_attr_put_check); 00565 00580 bool 00581 mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, 00582 uint16_t type, uint8_t data) 00583 { 00584 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data); 00585 } 00586 EXPORT_SYMBOL(mnl_attr_put_u8_check); 00587 00603 bool 00604 mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, 00605 uint16_t type, uint16_t data) 00606 { 00607 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data); 00608 } 00609 EXPORT_SYMBOL(mnl_attr_put_u16_check); 00610 00626 bool 00627 mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, 00628 uint16_t type, uint32_t data) 00629 { 00630 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data); 00631 } 00632 EXPORT_SYMBOL(mnl_attr_put_u32_check); 00633 00649 bool 00650 mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, 00651 uint16_t type, uint64_t data) 00652 { 00653 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data); 00654 } 00655 EXPORT_SYMBOL(mnl_attr_put_u64_check); 00656 00672 bool 00673 mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, 00674 uint16_t type, const char *data) 00675 { 00676 return mnl_attr_put_check(nlh, buflen, type, strlen(data), data); 00677 } 00678 EXPORT_SYMBOL(mnl_attr_put_str_check); 00679 00696 bool 00697 mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, 00698 uint16_t type, const char *data) 00699 { 00700 return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data); 00701 } 00702 EXPORT_SYMBOL(mnl_attr_put_strz_check); 00703 00714 struct nlattr * 00715 mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type) 00716 { 00717 if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen) 00718 return NULL; 00719 return mnl_attr_nest_start(nlh, type); 00720 } 00721 EXPORT_SYMBOL(mnl_attr_nest_start_check); 00722 00730 void 00731 mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start) 00732 { 00733 start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start; 00734 } 00735 EXPORT_SYMBOL(mnl_attr_nest_end); 00736 00744 void 00745 mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start) 00746 { 00747 nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start; 00748 } 00749 EXPORT_SYMBOL(mnl_attr_nest_cancel); 00750