• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

attr.c

00001 /*
00002  * (C) 2008-2010 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 
00010 #include <libmnl/libmnl.h>
00011 #include <string.h>
00012 #include <values.h>     /* for INT_MAX */
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                 /* empty nested attributes are OK. */
00173                 if (attr_len == 0)
00174                         break;
00175                 /* if not empty, they must contain one header, eg. flag */
00176                 if (attr_len < MNL_ATTR_HDRLEN) {
00177                         errno = ERANGE;
00178                         return -1;
00179                 }
00180                 break;
00181         default:
00182                 /* make gcc happy. */
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         /* set start->nla_len in mnl_attr_nest_end() */
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 

Generated on Sun Dec 26 2010 22:23:55 for libmnl by  doxygen 1.7.1