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
38EXPORT_SYMBOL uint16_t mnl_attr_get_type(const struct nlattr *attr)
39{
40 return attr->nla_type & NLA_TYPE_MASK;
41}
42
50EXPORT_SYMBOL uint16_t mnl_attr_get_len(const struct nlattr *attr)
51{
52 return attr->nla_len;
53}
54
61EXPORT_SYMBOL uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
62{
63 return attr->nla_len - MNL_ATTR_HDRLEN;
64}
65
72EXPORT_SYMBOL void *mnl_attr_get_payload(const struct nlattr *attr)
73{
74 return (void *)attr + MNL_ATTR_HDRLEN;
75}
76
93EXPORT_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
108EXPORT_SYMBOL struct nlattr *mnl_attr_next(const struct nlattr *attr)
109{
110 return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
111}
112
127EXPORT_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
136static 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
190static 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
207EXPORT_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
229EXPORT_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
255EXPORT_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
282EXPORT_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
313EXPORT_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
332EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
333{
334 return *((uint8_t *)mnl_attr_get_payload(attr));
335}
336
343EXPORT_SYMBOL uint16_t mnl_attr_get_u16(const struct nlattr *attr)
344{
345 return *((uint16_t *)mnl_attr_get_payload(attr));
346}
347
354EXPORT_SYMBOL uint32_t mnl_attr_get_u32(const struct nlattr *attr)
355{
356 return *((uint32_t *)mnl_attr_get_payload(attr));
357}
358
367EXPORT_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
380EXPORT_SYMBOL const char *mnl_attr_get_str(const struct nlattr *attr)
381{
382 return mnl_attr_get_payload(attr);
383}
384
395EXPORT_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
421EXPORT_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
436EXPORT_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
451EXPORT_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
466EXPORT_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
481EXPORT_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
499EXPORT_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
514EXPORT_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
540EXPORT_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
563EXPORT_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
584EXPORT_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
605EXPORT_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
626EXPORT_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
647EXPORT_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
669EXPORT_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
685EXPORT_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
701EXPORT_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
714EXPORT_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
void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data)
Definition: attr.c:421
bool mnl_attr_ok(const struct nlattr *attr, int len)
Definition: attr.c:93
void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
Definition: attr.c:499
bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data)
Definition: attr.c:540
uint8_t mnl_attr_get_u8(const struct nlattr *attr)
Definition: attr.c:332
void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
Definition: attr.c:436
int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb, void *data)
Definition: attr.c:282
bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data)
Definition: attr.c:563
uint64_t mnl_attr_get_u64(const struct nlattr *attr)
Definition: attr.c:367
void * mnl_attr_get_payload(const struct nlattr *attr)
Definition: attr.c:72
void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data)
Definition: attr.c:481
bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data)
Definition: attr.c:669
bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data)
Definition: attr.c:584
uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
Definition: attr.c:61
int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
Definition: attr.c:207
void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data)
Definition: attr.c:466
int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data)
Definition: attr.c:255
uint16_t mnl_attr_get_len(const struct nlattr *attr)
Definition: attr.c:50
int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
Definition: attr.c:127
uint16_t mnl_attr_get_type(const struct nlattr *attr)
Definition: attr.c:38
bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data)
Definition: attr.c:626
struct nlattr * mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
Definition: attr.c:514
bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data)
Definition: attr.c:647
int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t exp_len)
Definition: attr.c:229
uint32_t mnl_attr_get_u32(const struct nlattr *attr)
Definition: attr.c:354
const char * mnl_attr_get_str(const struct nlattr *attr)
Definition: attr.c:380
void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
Definition: attr.c:451
struct nlattr * mnl_attr_next(const struct nlattr *attr)
Definition: attr.c:108
void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
Definition: attr.c:395
void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
Definition: attr.c:701
uint16_t mnl_attr_get_u16(const struct nlattr *attr)
Definition: attr.c:343
void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
Definition: attr.c:714
int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data)
Definition: attr.c:313
struct nlattr * mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type)
Definition: attr.c:685
bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data)
Definition: attr.c:605
void * mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
Definition: nlmsg.c:187