libmnl  1.0.3
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 uint16_t mnl_attr_get_type(const struct nlattr *attr)
39 {
40  return attr->nla_type & NLA_TYPE_MASK;
41 }
42 EXPORT_SYMBOL(mnl_attr_get_type);
43 
51 uint16_t mnl_attr_get_len(const struct nlattr *attr)
52 {
53  return attr->nla_len;
54 }
55 EXPORT_SYMBOL(mnl_attr_get_len);
56 
63 uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
64 {
65  return attr->nla_len - MNL_ATTR_HDRLEN;
66 }
67 EXPORT_SYMBOL(mnl_attr_get_payload_len);
68 
75 void *mnl_attr_get_payload(const struct nlattr *attr)
76 {
77  return (void *)attr + MNL_ATTR_HDRLEN;
78 }
79 EXPORT_SYMBOL(mnl_attr_get_payload);
80 
97 bool mnl_attr_ok(const struct nlattr *attr, int len)
98 {
99  return len >= (int)sizeof(struct nlattr) &&
100  attr->nla_len >= sizeof(struct nlattr) &&
101  (int)attr->nla_len <= len;
102 }
103 EXPORT_SYMBOL(mnl_attr_ok);
104 
114 struct nlattr *mnl_attr_next(const struct nlattr *attr)
115 {
116  return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
117 }
118 EXPORT_SYMBOL(mnl_attr_next);
119 
134 int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
135 {
136  if (mnl_attr_get_type(attr) > max) {
137  errno = EOPNOTSUPP;
138  return -1;
139  }
140  return 1;
141 }
142 EXPORT_SYMBOL(mnl_attr_type_valid);
143 
144 static int __mnl_attr_validate(const struct nlattr *attr,
145  enum mnl_attr_data_type type, size_t exp_len)
146 {
147  uint16_t attr_len = mnl_attr_get_payload_len(attr);
148  const char *attr_data = mnl_attr_get_payload(attr);
149 
150  if (attr_len < exp_len) {
151  errno = ERANGE;
152  return -1;
153  }
154  switch(type) {
155  case MNL_TYPE_FLAG:
156  if (attr_len > 0) {
157  errno = ERANGE;
158  return -1;
159  }
160  break;
161  case MNL_TYPE_NUL_STRING:
162  if (attr_len == 0) {
163  errno = ERANGE;
164  return -1;
165  }
166  if (attr_data[attr_len-1] != '\0') {
167  errno = EINVAL;
168  return -1;
169  }
170  break;
171  case MNL_TYPE_STRING:
172  if (attr_len == 0) {
173  errno = ERANGE;
174  return -1;
175  }
176  break;
177  case MNL_TYPE_NESTED:
178  /* empty nested attributes are OK. */
179  if (attr_len == 0)
180  break;
181  /* if not empty, they must contain one header, eg. flag */
182  if (attr_len < MNL_ATTR_HDRLEN) {
183  errno = ERANGE;
184  return -1;
185  }
186  break;
187  default:
188  /* make gcc happy. */
189  break;
190  }
191  if (exp_len && attr_len > exp_len) {
192  errno = ERANGE;
193  return -1;
194  }
195  return 0;
196 }
197 
198 static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
199  [MNL_TYPE_U8] = sizeof(uint8_t),
200  [MNL_TYPE_U16] = sizeof(uint16_t),
201  [MNL_TYPE_U32] = sizeof(uint32_t),
202  [MNL_TYPE_U64] = sizeof(uint64_t),
203 };
204 
214 int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
215 {
216  int exp_len;
217 
218  if (type >= MNL_TYPE_MAX) {
219  errno = EINVAL;
220  return -1;
221  }
222  exp_len = mnl_attr_data_type_len[type];
223  return __mnl_attr_validate(attr, type, exp_len);
224 }
225 EXPORT_SYMBOL(mnl_attr_validate);
226 
237 int
238 mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type,
239  size_t exp_len)
240 {
241  if (type >= MNL_TYPE_MAX) {
242  errno = EINVAL;
243  return -1;
244  }
245  return __mnl_attr_validate(attr, type, exp_len);
246 }
247 EXPORT_SYMBOL(mnl_attr_validate2);
248 
264 int
265 mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset,
266  mnl_attr_cb_t cb, void *data)
267 {
268  int ret = MNL_CB_OK;
269  const struct nlattr *attr;
270 
271  mnl_attr_for_each(attr, nlh, offset)
272  if ((ret = cb(attr, data)) <= MNL_CB_STOP)
273  return ret;
274  return ret;
275 }
276 EXPORT_SYMBOL(mnl_attr_parse);
277 
292 int
293 mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb,
294  void *data)
295 {
296  int ret = MNL_CB_OK;
297  const struct nlattr *attr;
298 
299  mnl_attr_for_each_nested(attr, nested)
300  if ((ret = cb(attr, data)) <= MNL_CB_STOP)
301  return ret;
302  return ret;
303 }
304 EXPORT_SYMBOL(mnl_attr_parse_nested);
305 
325 int
326 mnl_attr_parse_payload(const void *payload, size_t payload_len,
327  mnl_attr_cb_t cb, void *data)
328 {
329  int ret = MNL_CB_OK;
330  const struct nlattr *attr;
331 
332  mnl_attr_for_each_payload(payload, payload_len)
333  if ((ret = cb(attr, data)) <= MNL_CB_STOP)
334  return ret;
335  return ret;
336 }
337 EXPORT_SYMBOL(mnl_attr_parse_payload);
338 
345 uint8_t mnl_attr_get_u8(const struct nlattr *attr)
346 {
347  return *((uint8_t *)mnl_attr_get_payload(attr));
348 }
349 EXPORT_SYMBOL(mnl_attr_get_u8);
350 
357 uint16_t mnl_attr_get_u16(const struct nlattr *attr)
358 {
359  return *((uint16_t *)mnl_attr_get_payload(attr));
360 }
361 EXPORT_SYMBOL(mnl_attr_get_u16);
362 
369 uint32_t mnl_attr_get_u32(const struct nlattr *attr)
370 {
371  return *((uint32_t *)mnl_attr_get_payload(attr));
372 }
373 EXPORT_SYMBOL(mnl_attr_get_u32);
374 
383 uint64_t mnl_attr_get_u64(const struct nlattr *attr)
384 {
385  uint64_t tmp;
386  memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
387  return tmp;
388 }
389 EXPORT_SYMBOL(mnl_attr_get_u64);
390 
397 const char *mnl_attr_get_str(const struct nlattr *attr)
398 {
399  return mnl_attr_get_payload(attr);
400 }
401 EXPORT_SYMBOL(mnl_attr_get_str);
402 
413 void
414 mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
415 {
416  struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
417  uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
418 
419  attr->nla_type = type;
420  attr->nla_len = payload_len;
421  memcpy(mnl_attr_get_payload(attr), data, len);
422  nlh->nlmsg_len += MNL_ALIGN(payload_len);
423 }
424 EXPORT_SYMBOL(mnl_attr_put);
425 
436 void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data)
437 {
438  mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
439 }
440 EXPORT_SYMBOL(mnl_attr_put_u8);
441 
451 void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
452 {
453  mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
454 }
455 EXPORT_SYMBOL(mnl_attr_put_u16);
456 
466 void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
467 {
468  mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
469 }
470 EXPORT_SYMBOL(mnl_attr_put_u32);
471 
481 void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data)
482 {
483  mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
484 }
485 EXPORT_SYMBOL(mnl_attr_put_u64);
486 
496 void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data)
497 {
498  mnl_attr_put(nlh, type, strlen(data), data);
499 }
500 EXPORT_SYMBOL(mnl_attr_put_str);
501 
514 void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
515 {
516  mnl_attr_put(nlh, type, strlen(data)+1, data);
517 }
518 EXPORT_SYMBOL(mnl_attr_put_strz);
519 
529 struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
530 {
531  struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
532 
533  /* set start->nla_len in mnl_attr_nest_end() */
534  start->nla_type = NLA_F_NESTED | type;
535  nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
536 
537  return start;
538 }
539 EXPORT_SYMBOL(mnl_attr_nest_start);
540 
555 bool
556 mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
557  uint16_t type, size_t len, const void *data)
558 {
559  if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
560  return false;
561  mnl_attr_put(nlh, type, len, data);
562  return true;
563 }
564 EXPORT_SYMBOL(mnl_attr_put_check);
565 
580 bool
581 mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
582  uint16_t type, uint8_t data)
583 {
584  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
585 }
586 EXPORT_SYMBOL(mnl_attr_put_u8_check);
587 
603 bool
604 mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
605  uint16_t type, uint16_t data)
606 {
607  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
608 }
609 EXPORT_SYMBOL(mnl_attr_put_u16_check);
610 
626 bool
627 mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
628  uint16_t type, uint32_t data)
629 {
630  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
631 }
632 EXPORT_SYMBOL(mnl_attr_put_u32_check);
633 
649 bool
650 mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
651  uint16_t type, uint64_t data)
652 {
653  return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
654 }
655 EXPORT_SYMBOL(mnl_attr_put_u64_check);
656 
672 bool
673 mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
674  uint16_t type, const char *data)
675 {
676  return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
677 }
678 EXPORT_SYMBOL(mnl_attr_put_str_check);
679 
696 bool
697 mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
698  uint16_t type, const char *data)
699 {
700  return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
701 }
702 EXPORT_SYMBOL(mnl_attr_put_strz_check);
703 
714 struct nlattr *
715 mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type)
716 {
717  if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
718  return NULL;
719  return mnl_attr_nest_start(nlh, type);
720 }
721 EXPORT_SYMBOL(mnl_attr_nest_start_check);
722 
730 void
731 mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
732 {
733  start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
734 }
735 EXPORT_SYMBOL(mnl_attr_nest_end);
736 
744 void
745 mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
746 {
747  nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
748 }
749 EXPORT_SYMBOL(mnl_attr_nest_cancel);
750 
bool mnl_attr_ok(const struct nlattr *attr, int len)
Definition: attr.c:97
int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t exp_len)
Definition: attr.c:238
int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data)
Definition: attr.c:265
uint16_t mnl_attr_get_type(const struct nlattr *attr)
Definition: attr.c:38
bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data)
Definition: attr.c:697
struct nlattr * mnl_attr_next(const struct nlattr *attr)
Definition: attr.c:114
bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data)
Definition: attr.c:604
void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
Definition: attr.c:731
void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
Definition: attr.c:414
void * mnl_attr_get_payload(const struct nlattr *attr)
Definition: attr.c:75
uint16_t mnl_attr_get_u16(const struct nlattr *attr)
Definition: attr.c:357
uint16_t mnl_attr_get_len(const struct nlattr *attr)
Definition: attr.c:51
int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb, void *data)
Definition: attr.c:293
bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data)
Definition: attr.c:673
void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data)
Definition: attr.c:436
uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
Definition: attr.c:63
bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data)
Definition: attr.c:581
void * mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
Definition: nlmsg.c:195
bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data)
Definition: attr.c:627
bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data)
Definition: attr.c:556
int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
Definition: attr.c:134
void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
Definition: attr.c:745
uint8_t mnl_attr_get_u8(const struct nlattr *attr)
Definition: attr.c:345
int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data)
Definition: attr.c:326
uint64_t mnl_attr_get_u64(const struct nlattr *attr)
Definition: attr.c:383
void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data)
Definition: attr.c:481
const char * mnl_attr_get_str(const struct nlattr *attr)
Definition: attr.c:397
struct nlattr * mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type)
Definition: attr.c:715
void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
Definition: attr.c:466
struct nlattr * mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
Definition: attr.c:529
uint32_t mnl_attr_get_u32(const struct nlattr *attr)
Definition: attr.c:369
int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
Definition: attr.c:214
bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data)
Definition: attr.c:650
void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
Definition: attr.c:451
void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
Definition: attr.c:514
void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data)
Definition: attr.c:496