1
2
3
4
5
6
7
8#include <linux/export.h>
9#include <linux/kernel.h>
10#include <linux/errno.h>
11#include <linux/jiffies.h>
12#include <linux/netdevice.h>
13#include <linux/skbuff.h>
14#include <linux/string.h>
15#include <linux/types.h>
16#include <net/netlink.h>
17
18static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
19 [NLA_U8] = sizeof(u8),
20 [NLA_U16] = sizeof(u16),
21 [NLA_U32] = sizeof(u32),
22 [NLA_U64] = sizeof(u64),
23 [NLA_MSECS] = sizeof(u64),
24 [NLA_NESTED] = NLA_HDRLEN,
25};
26
27static int validate_nla(const struct nlattr *nla, int maxtype,
28 const struct nla_policy *policy)
29{
30 const struct nla_policy *pt;
31 int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
32
33 if (type <= 0 || type > maxtype)
34 return 0;
35
36 pt = &policy[type];
37
38 BUG_ON(pt->type > NLA_TYPE_MAX);
39
40 switch (pt->type) {
41 case NLA_FLAG:
42 if (attrlen > 0)
43 return -ERANGE;
44 break;
45
46 case NLA_NUL_STRING:
47 if (pt->len)
48 minlen = min_t(int, attrlen, pt->len + 1);
49 else
50 minlen = attrlen;
51
52 if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
53 return -EINVAL;
54
55
56 case NLA_STRING:
57 if (attrlen < 1)
58 return -ERANGE;
59
60 if (pt->len) {
61 char *buf = nla_data(nla);
62
63 if (buf[attrlen - 1] == '\0')
64 attrlen--;
65
66 if (attrlen > pt->len)
67 return -ERANGE;
68 }
69 break;
70
71 case NLA_BINARY:
72 if (pt->len && attrlen > pt->len)
73 return -ERANGE;
74 break;
75
76 case NLA_NESTED_COMPAT:
77 if (attrlen < pt->len)
78 return -ERANGE;
79 if (attrlen < NLA_ALIGN(pt->len))
80 break;
81 if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
82 return -ERANGE;
83 nla = nla_data(nla) + NLA_ALIGN(pt->len);
84 if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
85 return -ERANGE;
86 break;
87 case NLA_NESTED:
88
89
90
91 if (attrlen == 0)
92 break;
93 default:
94 if (pt->len)
95 minlen = pt->len;
96 else if (pt->type != NLA_UNSPEC)
97 minlen = nla_attr_minlen[pt->type];
98
99 if (attrlen < minlen)
100 return -ERANGE;
101 }
102
103 return 0;
104}
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119int nla_validate(const struct nlattr *head, int len, int maxtype,
120 const struct nla_policy *policy)
121{
122 const struct nlattr *nla;
123 int rem, err;
124
125 nla_for_each_attr(nla, head, len, rem) {
126 err = validate_nla(nla, maxtype, policy);
127 if (err < 0)
128 goto errout;
129 }
130
131 err = 0;
132errout:
133 return err;
134}
135
136
137
138
139
140
141
142
143
144
145
146
147int
148nla_policy_len(const struct nla_policy *p, int n)
149{
150 int i, len = 0;
151
152 for (i = 0; i < n; i++, p++) {
153 if (p->len)
154 len += nla_total_size(p->len);
155 else if (nla_attr_minlen[p->type])
156 len += nla_total_size(nla_attr_minlen[p->type]);
157 }
158
159 return len;
160}
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
178 int len, const struct nla_policy *policy)
179{
180 const struct nlattr *nla;
181 int rem, err;
182
183 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
184
185 nla_for_each_attr(nla, head, len, rem) {
186 u16 type = nla_type(nla);
187
188 if (type > 0 && type <= maxtype) {
189 if (policy) {
190 err = validate_nla(nla, maxtype, policy);
191 if (err < 0)
192 goto errout;
193 }
194
195 tb[type] = (struct nlattr *)nla;
196 }
197 }
198
199 if (unlikely(rem > 0))
200 printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
201 "attributes.\n", rem);
202
203 err = 0;
204errout:
205 return err;
206}
207
208
209
210
211
212
213
214
215
216struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
217{
218 const struct nlattr *nla;
219 int rem;
220
221 nla_for_each_attr(nla, head, len, rem)
222 if (nla_type(nla) == attrtype)
223 return (struct nlattr *)nla;
224
225 return NULL;
226}
227
228
229
230
231
232
233
234
235
236
237
238
239
240size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
241{
242 size_t srclen = nla_len(nla);
243 char *src = nla_data(nla);
244
245 if (srclen > 0 && src[srclen - 1] == '\0')
246 srclen--;
247
248 if (dstsize > 0) {
249 size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
250
251 memset(dst, 0, dstsize);
252 memcpy(dst, src, len);
253 }
254
255 return srclen;
256}
257
258
259
260
261
262
263
264
265
266
267
268
269int nla_memcpy(void *dest, const struct nlattr *src, int count)
270{
271 int minlen = min_t(int, count, nla_len(src));
272
273 memcpy(dest, nla_data(src), minlen);
274
275 return minlen;
276}
277
278
279
280
281
282
283
284int nla_memcmp(const struct nlattr *nla, const void *data,
285 size_t size)
286{
287 int d = nla_len(nla) - size;
288
289 if (d == 0)
290 d = memcmp(nla_data(nla), data, size);
291
292 return d;
293}
294
295
296
297
298
299
300int nla_strcmp(const struct nlattr *nla, const char *str)
301{
302 int len = strlen(str) + 1;
303 int d = nla_len(nla) - len;
304
305 if (d == 0)
306 d = memcmp(nla_data(nla), str, len);
307
308 return d;
309}
310
311#ifdef CONFIG_NET
312
313
314
315
316
317
318
319
320
321
322
323
324struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
325{
326 struct nlattr *nla;
327
328 nla = (struct nlattr *) skb_put(skb, nla_total_size(attrlen));
329 nla->nla_type = attrtype;
330 nla->nla_len = nla_attr_size(attrlen);
331
332 memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
333
334 return nla;
335}
336EXPORT_SYMBOL(__nla_reserve);
337
338
339
340
341
342
343
344
345
346
347
348void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
349{
350 void *start;
351
352 start = skb_put(skb, NLA_ALIGN(attrlen));
353 memset(start, 0, NLA_ALIGN(attrlen));
354
355 return start;
356}
357EXPORT_SYMBOL(__nla_reserve_nohdr);
358
359
360
361
362
363
364
365
366
367
368
369
370
371struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
372{
373 if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
374 return NULL;
375
376 return __nla_reserve(skb, attrtype, attrlen);
377}
378EXPORT_SYMBOL(nla_reserve);
379
380
381
382
383
384
385
386
387
388
389
390void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
391{
392 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
393 return NULL;
394
395 return __nla_reserve_nohdr(skb, attrlen);
396}
397EXPORT_SYMBOL(nla_reserve_nohdr);
398
399
400
401
402
403
404
405
406
407
408
409void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
410 const void *data)
411{
412 struct nlattr *nla;
413
414 nla = __nla_reserve(skb, attrtype, attrlen);
415 memcpy(nla_data(nla), data, attrlen);
416}
417EXPORT_SYMBOL(__nla_put);
418
419
420
421
422
423
424
425
426
427
428void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
429{
430 void *start;
431
432 start = __nla_reserve_nohdr(skb, attrlen);
433 memcpy(start, data, attrlen);
434}
435EXPORT_SYMBOL(__nla_put_nohdr);
436
437
438
439
440
441
442
443
444
445
446
447int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
448{
449 if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
450 return -EMSGSIZE;
451
452 __nla_put(skb, attrtype, attrlen, data);
453 return 0;
454}
455EXPORT_SYMBOL(nla_put);
456
457
458
459
460
461
462
463
464
465
466int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
467{
468 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
469 return -EMSGSIZE;
470
471 __nla_put_nohdr(skb, attrlen, data);
472 return 0;
473}
474EXPORT_SYMBOL(nla_put_nohdr);
475
476
477
478
479
480
481
482
483
484
485int nla_append(struct sk_buff *skb, int attrlen, const void *data)
486{
487 if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
488 return -EMSGSIZE;
489
490 memcpy(skb_put(skb, attrlen), data, attrlen);
491 return 0;
492}
493EXPORT_SYMBOL(nla_append);
494#endif
495
496EXPORT_SYMBOL(nla_validate);
497EXPORT_SYMBOL(nla_policy_len);
498EXPORT_SYMBOL(nla_parse);
499EXPORT_SYMBOL(nla_find);
500EXPORT_SYMBOL(nla_strlcpy);
501EXPORT_SYMBOL(nla_memcpy);
502EXPORT_SYMBOL(nla_memcmp);
503EXPORT_SYMBOL(nla_strcmp);
504