00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <libmnl/libmnl.h>
00011 #include <string.h>
00012 #include <values.h>
00013 #include <errno.h>
00014 #include "internal.h"
00015
00039 EXPORT_SYMBOL uint16_t mnl_attr_get_type(const struct nlattr *attr)
00040 {
00041 return attr->nla_type & NLA_TYPE_MASK;
00042 }
00043
00051 EXPORT_SYMBOL uint16_t mnl_attr_get_len(const struct nlattr *attr)
00052 {
00053 return attr->nla_len;
00054 }
00055
00062 EXPORT_SYMBOL uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
00063 {
00064 return attr->nla_len - MNL_ATTR_HDRLEN;
00065 }
00066
00073 EXPORT_SYMBOL void *mnl_attr_get_payload(const struct nlattr *attr)
00074 {
00075 return (void *)attr + MNL_ATTR_HDRLEN;
00076 }
00077
00094 EXPORT_SYMBOL bool mnl_attr_ok(const struct nlattr *attr, int len)
00095 {
00096 return len >= (int)sizeof(struct nlattr) &&
00097 attr->nla_len >= sizeof(struct nlattr) &&
00098 (int)attr->nla_len <= len;
00099 }
00100
00110 EXPORT_SYMBOL struct nlattr *mnl_attr_next(const struct nlattr *attr)
00111 {
00112 return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
00113 }
00114
00129 EXPORT_SYMBOL int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
00130 {
00131 if (mnl_attr_get_type(attr) > max) {
00132 errno = EOPNOTSUPP;
00133 return -1;
00134 }
00135 return 1;
00136 }
00137
00138 static int __mnl_attr_validate(const struct nlattr *attr,
00139 enum mnl_attr_data_type type, size_t exp_len)
00140 {
00141 uint16_t attr_len = mnl_attr_get_payload_len(attr);
00142 const char *attr_data = mnl_attr_get_payload(attr);
00143
00144 if (attr_len < exp_len) {
00145 errno = ERANGE;
00146 return -1;
00147 }
00148 switch(type) {
00149 case MNL_TYPE_FLAG:
00150 if (attr_len > 0) {
00151 errno = ERANGE;
00152 return -1;
00153 }
00154 break;
00155 case MNL_TYPE_NUL_STRING:
00156 if (attr_len == 0) {
00157 errno = ERANGE;
00158 return -1;
00159 }
00160 if (attr_data[attr_len-1] != '\0') {
00161 errno = EINVAL;
00162 return -1;
00163 }
00164 break;
00165 case MNL_TYPE_STRING:
00166 if (attr_len == 0) {
00167 errno = ERANGE;
00168 return -1;
00169 }
00170 break;
00171 case MNL_TYPE_NESTED:
00172
00173 if (attr_len == 0)
00174 break;
00175
00176 if (attr_len < MNL_ATTR_HDRLEN) {
00177 errno = ERANGE;
00178 return -1;
00179 }
00180 break;
00181 default:
00182
00183 break;
00184 }
00185 if (exp_len && attr_len > exp_len) {
00186 errno = ERANGE;
00187 return -1;
00188 }
00189 return 0;
00190 }
00191
00192 static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
00193 [MNL_TYPE_U8] = sizeof(uint8_t),
00194 [MNL_TYPE_U16] = sizeof(uint16_t),
00195 [MNL_TYPE_U32] = sizeof(uint32_t),
00196 [MNL_TYPE_U64] = sizeof(uint64_t),
00197 };
00198
00208 EXPORT_SYMBOL int
00209 mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
00210 {
00211 int exp_len;
00212
00213 if (type >= MNL_TYPE_MAX) {
00214 errno = EINVAL;
00215 return -1;
00216 }
00217 exp_len = mnl_attr_data_type_len[type];
00218 return __mnl_attr_validate(attr, type, exp_len);
00219 }
00220
00231 EXPORT_SYMBOL int
00232 mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type,
00233 size_t exp_len)
00234 {
00235 if (type >= MNL_TYPE_MAX) {
00236 errno = EINVAL;
00237 return -1;
00238 }
00239 return __mnl_attr_validate(attr, type, exp_len);
00240 }
00241
00257 EXPORT_SYMBOL int
00258 mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset,
00259 mnl_attr_cb_t cb, void *data)
00260 {
00261 int ret = MNL_CB_OK;
00262 const struct nlattr *attr;
00263
00264 mnl_attr_for_each(attr, nlh, offset)
00265 if ((ret = cb(attr, data)) <= MNL_CB_STOP)
00266 return ret;
00267 return ret;
00268 }
00269
00284 EXPORT_SYMBOL int
00285 mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb,
00286 void *data)
00287 {
00288 int ret = MNL_CB_OK;
00289 const struct nlattr *attr;
00290
00291 mnl_attr_for_each_nested(attr, nested)
00292 if ((ret = cb(attr, data)) <= MNL_CB_STOP)
00293 return ret;
00294 return ret;
00295 }
00296
00303 EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
00304 {
00305 return *((uint8_t *)mnl_attr_get_payload(attr));
00306 }
00307
00314 EXPORT_SYMBOL uint16_t mnl_attr_get_u16(const struct nlattr *attr)
00315 {
00316 return *((uint16_t *)mnl_attr_get_payload(attr));
00317 }
00318
00325 EXPORT_SYMBOL uint32_t mnl_attr_get_u32(const struct nlattr *attr)
00326 {
00327 return *((uint32_t *)mnl_attr_get_payload(attr));
00328 }
00329
00338 EXPORT_SYMBOL uint64_t mnl_attr_get_u64(const struct nlattr *attr)
00339 {
00340 uint64_t tmp;
00341 memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
00342 return tmp;
00343 }
00344
00351 EXPORT_SYMBOL const char *mnl_attr_get_str(const struct nlattr *attr)
00352 {
00353 return mnl_attr_get_payload(attr);
00354 }
00355
00366 EXPORT_SYMBOL void
00367 mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
00368 {
00369 struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
00370 uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
00371
00372 attr->nla_type = type;
00373 attr->nla_len = payload_len;
00374 memcpy(mnl_attr_get_payload(attr), data, len);
00375 nlh->nlmsg_len += MNL_ALIGN(payload_len);
00376 }
00377
00388 EXPORT_SYMBOL void
00389 mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data)
00390 {
00391 mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
00392 }
00393
00403 EXPORT_SYMBOL void
00404 mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
00405 {
00406 mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
00407 }
00408
00418 EXPORT_SYMBOL void
00419 mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
00420 {
00421 mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
00422 }
00423
00433 EXPORT_SYMBOL void
00434 mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data)
00435 {
00436 mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
00437 }
00438
00448 EXPORT_SYMBOL void
00449 mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data)
00450 {
00451 mnl_attr_put(nlh, type, strlen(data), data);
00452 }
00453
00466 EXPORT_SYMBOL void
00467 mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
00468 {
00469 mnl_attr_put(nlh, type, strlen(data)+1, data);
00470 }
00471
00481 EXPORT_SYMBOL struct nlattr *
00482 mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
00483 {
00484 struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
00485
00486
00487 start->nla_type = NLA_F_NESTED | type;
00488 nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
00489
00490 return start;
00491 }
00492
00507 EXPORT_SYMBOL bool
00508 mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
00509 uint16_t type, size_t len, const void *data)
00510 {
00511 if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
00512 return false;
00513 mnl_attr_put(nlh, type, len, data);
00514 return true;
00515 }
00516
00531 EXPORT_SYMBOL bool
00532 mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
00533 uint16_t type, uint8_t data)
00534 {
00535 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
00536 }
00537
00553 EXPORT_SYMBOL bool
00554 mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
00555 uint16_t type, uint16_t data)
00556 {
00557 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
00558 }
00559
00575 EXPORT_SYMBOL bool
00576 mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
00577 uint16_t type, uint32_t data)
00578 {
00579 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
00580 }
00581
00597 EXPORT_SYMBOL bool
00598 mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
00599 uint16_t type, uint64_t data)
00600 {
00601 return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
00602 }
00603
00619 EXPORT_SYMBOL bool
00620 mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
00621 uint16_t type, const char *data)
00622 {
00623 return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
00624 }
00625
00642 EXPORT_SYMBOL bool
00643 mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
00644 uint16_t type, const char *data)
00645 {
00646 return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
00647 }
00648
00659 EXPORT_SYMBOL struct nlattr *
00660 mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type)
00661 {
00662 if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
00663 return NULL;
00664 return mnl_attr_nest_start(nlh, type);
00665 }
00666
00674 EXPORT_SYMBOL void
00675 mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
00676 {
00677 start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
00678 }
00679
00687 EXPORT_SYMBOL void
00688 mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
00689 {
00690 nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
00691 }
00692