Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nlattr.c
Go to the documentation of this file.
1 /*
2  * NETLINK Netlink attributes
3  *
4  * Authors: Thomas Graf <[email protected]>
5  * Alexey Kuznetsov <[email protected]>
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 
18 static 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),
25  [NLA_S8] = sizeof(s8),
26  [NLA_S16] = sizeof(s16),
27  [NLA_S32] = sizeof(s32),
28  [NLA_S64] = sizeof(s64),
29 };
30 
31 static int validate_nla(const struct nlattr *nla, int maxtype,
32  const struct nla_policy *policy)
33 {
34  const struct nla_policy *pt;
35  int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
36 
37  if (type <= 0 || type > maxtype)
38  return 0;
39 
40  pt = &policy[type];
41 
42  BUG_ON(pt->type > NLA_TYPE_MAX);
43 
44  switch (pt->type) {
45  case NLA_FLAG:
46  if (attrlen > 0)
47  return -ERANGE;
48  break;
49 
50  case NLA_NUL_STRING:
51  if (pt->len)
52  minlen = min_t(int, attrlen, pt->len + 1);
53  else
54  minlen = attrlen;
55 
56  if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
57  return -EINVAL;
58  /* fall through */
59 
60  case NLA_STRING:
61  if (attrlen < 1)
62  return -ERANGE;
63 
64  if (pt->len) {
65  char *buf = nla_data(nla);
66 
67  if (buf[attrlen - 1] == '\0')
68  attrlen--;
69 
70  if (attrlen > pt->len)
71  return -ERANGE;
72  }
73  break;
74 
75  case NLA_BINARY:
76  if (pt->len && attrlen > pt->len)
77  return -ERANGE;
78  break;
79 
80  case NLA_NESTED_COMPAT:
81  if (attrlen < pt->len)
82  return -ERANGE;
83  if (attrlen < NLA_ALIGN(pt->len))
84  break;
85  if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
86  return -ERANGE;
87  nla = nla_data(nla) + NLA_ALIGN(pt->len);
88  if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
89  return -ERANGE;
90  break;
91  case NLA_NESTED:
92  /* a nested attributes is allowed to be empty; if its not,
93  * it must have a size of at least NLA_HDRLEN.
94  */
95  if (attrlen == 0)
96  break;
97  default:
98  if (pt->len)
99  minlen = pt->len;
100  else if (pt->type != NLA_UNSPEC)
101  minlen = nla_attr_minlen[pt->type];
102 
103  if (attrlen < minlen)
104  return -ERANGE;
105  }
106 
107  return 0;
108 }
109 
123 int nla_validate(const struct nlattr *head, int len, int maxtype,
124  const struct nla_policy *policy)
125 {
126  const struct nlattr *nla;
127  int rem, err;
128 
129  nla_for_each_attr(nla, head, len, rem) {
130  err = validate_nla(nla, maxtype, policy);
131  if (err < 0)
132  goto errout;
133  }
134 
135  err = 0;
136 errout:
137  return err;
138 }
139 
151 int
152 nla_policy_len(const struct nla_policy *p, int n)
153 {
154  int i, len = 0;
155 
156  for (i = 0; i < n; i++, p++) {
157  if (p->len)
158  len += nla_total_size(p->len);
159  else if (nla_attr_minlen[p->type])
160  len += nla_total_size(nla_attr_minlen[p->type]);
161  }
162 
163  return len;
164 }
165 
181 int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
182  int len, const struct nla_policy *policy)
183 {
184  const struct nlattr *nla;
185  int rem, err;
186 
187  memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
188 
189  nla_for_each_attr(nla, head, len, rem) {
190  u16 type = nla_type(nla);
191 
192  if (type > 0 && type <= maxtype) {
193  if (policy) {
194  err = validate_nla(nla, maxtype, policy);
195  if (err < 0)
196  goto errout;
197  }
198 
199  tb[type] = (struct nlattr *)nla;
200  }
201  }
202 
203  if (unlikely(rem > 0))
204  printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
205  "attributes.\n", rem);
206 
207  err = 0;
208 errout:
209  return err;
210 }
211 
220 struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
221 {
222  const struct nlattr *nla;
223  int rem;
224 
225  nla_for_each_attr(nla, head, len, rem)
226  if (nla_type(nla) == attrtype)
227  return (struct nlattr *)nla;
228 
229  return NULL;
230 }
231 
244 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
245 {
246  size_t srclen = nla_len(nla);
247  char *src = nla_data(nla);
248 
249  if (srclen > 0 && src[srclen - 1] == '\0')
250  srclen--;
251 
252  if (dstsize > 0) {
253  size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
254 
255  memset(dst, 0, dstsize);
256  memcpy(dst, src, len);
257  }
258 
259  return srclen;
260 }
261 
273 int nla_memcpy(void *dest, const struct nlattr *src, int count)
274 {
275  int minlen = min_t(int, count, nla_len(src));
276 
277  memcpy(dest, nla_data(src), minlen);
278 
279  return minlen;
280 }
281 
288 int nla_memcmp(const struct nlattr *nla, const void *data,
289  size_t size)
290 {
291  int d = nla_len(nla) - size;
292 
293  if (d == 0)
294  d = memcmp(nla_data(nla), data, size);
295 
296  return d;
297 }
298 
304 int nla_strcmp(const struct nlattr *nla, const char *str)
305 {
306  int len = strlen(str) + 1;
307  int d = nla_len(nla) - len;
308 
309  if (d == 0)
310  d = memcmp(nla_data(nla), str, len);
311 
312  return d;
313 }
314 
315 #ifdef CONFIG_NET
316 
328 struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
329 {
330  struct nlattr *nla;
331 
332  nla = (struct nlattr *) skb_put(skb, nla_total_size(attrlen));
333  nla->nla_type = attrtype;
334  nla->nla_len = nla_attr_size(attrlen);
335 
336  memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
337 
338  return nla;
339 }
341 
352 void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
353 {
354  void *start;
355 
356  start = skb_put(skb, NLA_ALIGN(attrlen));
357  memset(start, 0, NLA_ALIGN(attrlen));
358 
359  return start;
360 }
362 
375 struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
376 {
377  if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
378  return NULL;
379 
380  return __nla_reserve(skb, attrtype, attrlen);
381 }
383 
394 void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
395 {
396  if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
397  return NULL;
398 
399  return __nla_reserve_nohdr(skb, attrlen);
400 }
402 
413 void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
414  const void *data)
415 {
416  struct nlattr *nla;
417 
418  nla = __nla_reserve(skb, attrtype, attrlen);
419  memcpy(nla_data(nla), data, attrlen);
420 }
422 
432 void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
433 {
434  void *start;
435 
436  start = __nla_reserve_nohdr(skb, attrlen);
437  memcpy(start, data, attrlen);
438 }
440 
451 int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
452 {
453  if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
454  return -EMSGSIZE;
455 
456  __nla_put(skb, attrtype, attrlen, data);
457  return 0;
458 }
460 
470 int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
471 {
472  if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
473  return -EMSGSIZE;
474 
475  __nla_put_nohdr(skb, attrlen, data);
476  return 0;
477 }
479 
489 int nla_append(struct sk_buff *skb, int attrlen, const void *data)
490 {
491  if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
492  return -EMSGSIZE;
493 
494  memcpy(skb_put(skb, attrlen), data, attrlen);
495  return 0;
496 }
498 #endif
499