libmnl  1.0.5
attr.c
1 /*
2  * (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  */
9 #include <limits.h> /* for INT_MAX */
10 #include <libmnl/libmnl.h>
11 #include <string.h>
12 #include <errno.h>
13 #include "internal.h"
14 
38 EXPORT_SYMBOL uint16_t mnl_attr_get_type(const struct nlattr *attr)
39 {
40  return attr->nla_type & NLA_TYPE_MASK;
41 }
42 
50 EXPORT_SYMBOL uint16_t mnl_attr_get_len(const struct nlattr *attr)
51 {
52  return attr->nla_len;
53 }
54 
61 EXPORT_SYMBOL uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
62 {
63  return attr->nla_len - MNL_ATTR_HDRLEN;
64 }
65 
72 EXPORT_SYMBOL void *mnl_attr_get_payload(const struct nlattr *attr)
73 {
74  return (void *)attr + MNL_ATTR_HDRLEN;
75 }
76 
93 EXPORT_SYMBOL bool mnl_attr_ok(const struct nlattr *attr, int len)
94 {
95  return len >= (int)sizeof(struct nlattr) &&
96  attr->nla_len >= sizeof(struct nlattr) &&
97  (int)attr->nla_len <= len;
98 }
99 
108 EXPORT_SYMBOL struct nlattr *mnl_attr_next(const struct nlattr *attr)
109 {
110  return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
111 }
112 
127 EXPORT_SYMBOL int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
128 {
129  if (mnl_attr_get_type(attr) > max) {
130  errno = EOPNOTSUPP;
131  return -1;
132  }
133  return 1;
134 }
135 
136 static int __mnl_attr_validate(const struct nlattr *attr,
137  enum mnl_attr_data_type type, size_t exp_len)
138 {
139  uint16_t attr_len = mnl_attr_get_payload_len(attr);
140  const char *attr_data = mnl_attr_get_payload(attr);
141 
142  if (attr_len < exp_len) {
143  errno = ERANGE;
144  return -1;
145  }
146  switch(type) {
147  case MNL_TYPE_FLAG:
148  if (attr_len > 0) {
149  errno = ERANGE;
150  return -1;
151  }
152  break;
153  case MNL_TYPE_NUL_STRING:
154  if (attr_len == 0) {
155  errno = ERANGE;
156  return -1;
157  }
158  if (attr_data[attr_len-1] != '\0') {
159  errno = EINVAL;
160  return -1;
161  }
162  break;
163  case MNL_TYPE_STRING:
164  if (attr_len == 0) {
165  errno = ERANGE;
166  return -1;
167  }
168  break;
169  case MNL_TYPE_NESTED:
170  /* empty nested attributes are OK. */
171  if (attr_len == 0)
172  break;
173  /* if not empty, they must contain one header, eg. flag */
174  if (attr_len < MNL_ATTR_HDRLEN) {
175  errno = ERANGE;
176  return -1;
177  }
178  break;
179  default:
180  /* make gcc happy. */
181  break;
182  }
183  if (exp_len && attr_len > exp_len) {
184  errno = ERANGE;
185  return -1;
186  }
187  return 0;
188 }
189 
190 static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
191  [MNL_TYPE_U8] = sizeof(uint8_t),
192  [MNL_TYPE_U16] = sizeof(uint16_t),
193  [MNL_TYPE_U32] = sizeof(uint32_t),
194  [MNL_TYPE_U64] = sizeof(uint64_t),
195  [MNL_TYPE_MSECS] = sizeof(uint64_t),
196 };
197 
207 EXPORT_SYMBOL int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
208 {
209  int exp_len;
210 
211  if (type >= MNL_TYPE_MAX) {
212  errno = EINVAL;
213  return -1;
214  }
215  exp_len = mnl_attr_data_type_len[type];
216  return __mnl_attr_validate(attr, type, exp_len);
217 }
218 
229 EXPORT_SYMBOL int mnl_attr_validate2(const struct nlattr *attr,
230  enum mnl_attr_data_type type,
231  size_t exp_len)
232 {
233  if (type >= MNL_TYPE_MAX) {
234  errno = EINVAL;
235  return -1;
236  }
237  return __mnl_attr_validate(attr, type, exp_len);
238 }
239 
255 EXPORT_SYMBOL int mnl_attr_parse(const struct nlmsghdr *nlh,
256  unsigned int offset, mnl_attr_cb_t cb,
257  void *data)
258 {
259  int ret = MNL_CB_OK;
260  const struct nlattr *attr;
261 
262  mnl_attr_for_each(attr, nlh, offset)
263  if ((ret = cb(attr, data)) <= MNL_CB_STOP)
264  return ret;
265  return ret;
266 }
267 
282 EXPORT_SYMBOL int mnl_attr_parse_nested(const struct nlattr *nested,
283  mnl_attr_cb_t cb, void *data)
284 {
285  int ret = MNL_CB_OK;
286  const struct nlattr *attr;
287 
288  mnl_attr_for_each_nested(attr, nested)
289  if ((ret = cb(attr, data)) <= MNL_CB_STOP)
290  return ret;
291  return ret;
292 }
293 
313 EXPORT_SYMBOL int mnl_attr_parse_payload(const void *payload,
314  size_t payload_len,
315  mnl_attr_cb_t cb, void *data)
316 {
317  int ret = MNL_CB_OK;
318  const struct nlattr *attr;
319 
320  mnl_attr_for_each_payload(payload, payload_len)
321  if ((ret = cb(attr, data)) <= MNL_CB_STOP)
322  return ret;
323  return ret;
324 }
325 
332 EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
333 {
334  return *((uint8_t *)mnl_attr_get_payload(attr));
335 }
336 
343 EXPORT_SYMBOL uint16_t mnl_attr_get_u16(const struct nlattr *attr)
344 {
345  return *((uint16_t *)mnl_attr_get_payload(attr));
346 }
347 
354 EXPORT_SYMBOL uint32_t mnl_attr_get_u32(const struct nlattr *attr)
355 {
356  return *((uint32_t *)mnl_attr_get_payload(attr));
357 }
358 
367 EXPORT_SYMBOL uint64_t mnl_attr_get_u64(const struct nlattr *attr)
368 {
369  uint64_t tmp;
370  memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
371  return tmp;
372 }
373 
380 EXPORT_SYMBOL const char *mnl_attr_get_str(const struct nlattr *attr)
381 {
382  return mnl_attr_get_payload(attr);
383 }
384 
395 EXPORT_SYMBOL void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
396  size_t len, const void *data)
397 {
398  struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
399  uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
400  int pad;
401 
402  attr->nla_type = type;
403  attr->nla_len = payload_len;
404  memcpy(mnl_attr_get_payload(attr), data, len);
405  pad = MNL_ALIGN(len) - len;
406  if (pad > 0)
407  memset(mnl_attr_get_payload(attr) + len, 0, pad);
408 
409  nlh->nlmsg_len += MNL_ALIGN(payload_len);
410 }
411 
421 EXPORT_SYMBOL void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
422  uint8_t data)
423 {
424  mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
425 }
426 
436 EXPORT_SYMBOL void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
437  uint16_t data)
438 {
439  mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
440 }
441 
451 EXPORT_SYMBOL void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
452  uint32_t data)
453 {
454  mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
455 }
456 
466 EXPORT_SYMBOL void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
467  uint64_t data)
468 {
469  mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
470 }
471 
481 EXPORT_SYMBOL void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
482  const char *data)
483 {
484  mnl_attr_put(nlh, type, strlen(data), data);
485 }
486 
499 EXPORT_SYMBOL void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
500  const char *data)
501 {
502  mnl_attr_put(nlh, type, strlen(data)+1, data);
503 }
504 
514 EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
515  uint16_t type)
516 {
517  struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
518 
519  /* set start->nla_len in mnl_attr_nest_end() */
520  start->nla_type = NLA_F_NESTED | type;
521  nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
522 
523  return start;
524 }
525 
540 EXPORT_SYMBOL bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
541  uint16_t type, size_t len,
542  const void *data)
543 {
544  if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
545  return false;
546  mnl_attr_put(nlh, type, len, data);
547  return true;
548 }
549 
563 EXPORT_SYMBOL bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
564  uint16_t type, uint8_t data)
565 {
566  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
567 }
568 
584 EXPORT_SYMBOL bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
585  uint16_t type, uint16_t data)
586 {
587  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
588 }
589 
605 EXPORT_SYMBOL bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
606  uint16_t type, uint32_t data)
607 {
608  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
609 }
610 
626 EXPORT_SYMBOL bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
627  uint16_t type, uint64_t data)
628 {
629  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
630 }
631 
647 EXPORT_SYMBOL bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
648  uint16_t type, const char *data)
649 {
650  return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
651 }
652 
669 EXPORT_SYMBOL bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
670  uint16_t type, const char *data)
671 {
672  return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
673 }
674 
685 EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
686  size_t buflen,
687  uint16_t type)
688 {
689  if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
690  return NULL;
691  return mnl_attr_nest_start(nlh, type);
692 }
693 
701 EXPORT_SYMBOL void mnl_attr_nest_end(struct nlmsghdr *nlh,
702  struct nlattr *start)
703 {
704  start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
705 }
706 
714 EXPORT_SYMBOL void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
715  struct nlattr *start)
716 {
717  nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
718 }
719 
EXPORT_SYMBOL int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
Definition: attr.c:127
EXPORT_SYMBOL int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data)
Definition: attr.c:255
EXPORT_SYMBOL bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data)
Definition: attr.c:605
EXPORT_SYMBOL bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data)
Definition: attr.c:584
EXPORT_SYMBOL void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data)
Definition: attr.c:481
EXPORT_SYMBOL int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb, void *data)
Definition: attr.c:282
EXPORT_SYMBOL void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data)
Definition: attr.c:466
EXPORT_SYMBOL void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
Definition: attr.c:714
EXPORT_SYMBOL uint32_t mnl_attr_get_u32(const struct nlattr *attr)
Definition: attr.c:354
EXPORT_SYMBOL struct nlattr * mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
Definition: attr.c:514
EXPORT_SYMBOL struct nlattr * mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type)
Definition: attr.c:685
EXPORT_SYMBOL const char * mnl_attr_get_str(const struct nlattr *attr)
Definition: attr.c:380
EXPORT_SYMBOL void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
Definition: attr.c:436
EXPORT_SYMBOL void * mnl_attr_get_payload(const struct nlattr *attr)
Definition: attr.c:72
EXPORT_SYMBOL int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
Definition: attr.c:207
EXPORT_SYMBOL uint16_t mnl_attr_get_type(const struct nlattr *attr)
Definition: attr.c:38
EXPORT_SYMBOL uint16_t mnl_attr_get_u16(const struct nlattr *attr)
Definition: attr.c:343
EXPORT_SYMBOL void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
Definition: attr.c:395
EXPORT_SYMBOL void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data)
Definition: attr.c:421
EXPORT_SYMBOL uint16_t mnl_attr_get_len(const struct nlattr *attr)
Definition: attr.c:50
EXPORT_SYMBOL bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data)
Definition: attr.c:563
EXPORT_SYMBOL bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data)
Definition: attr.c:647
EXPORT_SYMBOL bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data)
Definition: attr.c:669
EXPORT_SYMBOL bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data)
Definition: attr.c:626
EXPORT_SYMBOL void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
Definition: attr.c:451
EXPORT_SYMBOL bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data)
Definition: attr.c:540
EXPORT_SYMBOL int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data)
Definition: attr.c:313
EXPORT_SYMBOL bool mnl_attr_ok(const struct nlattr *attr, int len)
Definition: attr.c:93
EXPORT_SYMBOL void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
Definition: attr.c:701
EXPORT_SYMBOL struct nlattr * mnl_attr_next(const struct nlattr *attr)
Definition: attr.c:108
EXPORT_SYMBOL int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t exp_len)
Definition: attr.c:229
EXPORT_SYMBOL uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
Definition: attr.c:61
EXPORT_SYMBOL uint64_t mnl_attr_get_u64(const struct nlattr *attr)
Definition: attr.c:367
EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
Definition: attr.c:332
EXPORT_SYMBOL void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
Definition: attr.c:499
void * mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
Definition: nlmsg.c:187