Blame view

lib/nlattr.c 12.3 KB
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
1
2
3
4
5
6
  /*
   * NETLINK      Netlink attributes
   *
   * 		Authors:	Thomas Graf <tgraf@suug.ch>
   * 				Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
   */
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
7
8
9
10
11
12
13
14
15
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/jiffies.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <linux/string.h>
  #include <linux/types.h>
  #include <net/netlink.h>
3654654f7   Jan Engelhardt   netlink: let nlms...
16
  static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
17
18
19
20
  	[NLA_U8]	= sizeof(u8),
  	[NLA_U16]	= sizeof(u16),
  	[NLA_U32]	= sizeof(u32),
  	[NLA_U64]	= sizeof(u64),
c30bc9475   Johannes Berg   netlink: validate...
21
  	[NLA_MSECS]	= sizeof(u64),
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
22
23
  	[NLA_NESTED]	= NLA_HDRLEN,
  };
3654654f7   Jan Engelhardt   netlink: let nlms...
24
  static int validate_nla(const struct nlattr *nla, int maxtype,
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
25
  			const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
26
  {
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
27
  	const struct nla_policy *pt;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
28
  	int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
29

8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
30
  	if (type <= 0 || type > maxtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
31
  		return 0;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
32
  	pt = &policy[type];
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
33
34
  
  	BUG_ON(pt->type > NLA_TYPE_MAX);
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
35
36
37
38
39
  	switch (pt->type) {
  	case NLA_FLAG:
  		if (attrlen > 0)
  			return -ERANGE;
  		break;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
40

a5531a5d8   Thomas Graf   [NETLINK]: Improv...
41
42
43
44
45
  	case NLA_NUL_STRING:
  		if (pt->len)
  			minlen = min_t(int, attrlen, pt->len + 1);
  		else
  			minlen = attrlen;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
46

a5531a5d8   Thomas Graf   [NETLINK]: Improv...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  		if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL)
  			return -EINVAL;
  		/* fall through */
  
  	case NLA_STRING:
  		if (attrlen < 1)
  			return -ERANGE;
  
  		if (pt->len) {
  			char *buf = nla_data(nla);
  
  			if (buf[attrlen - 1] == '\0')
  				attrlen--;
  
  			if (attrlen > pt->len)
  				return -ERANGE;
  		}
  		break;
d30045a0b   Johannes Berg   [NETLINK]: introd...
65
66
67
68
  	case NLA_BINARY:
  		if (pt->len && attrlen > pt->len)
  			return -ERANGE;
  		break;
1092cb219   Patrick McHardy   [NETLINK]: attr: ...
69
70
71
72
73
74
75
76
77
78
79
  	case NLA_NESTED_COMPAT:
  		if (attrlen < pt->len)
  			return -ERANGE;
  		if (attrlen < NLA_ALIGN(pt->len))
  			break;
  		if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
  			return -ERANGE;
  		nla = nla_data(nla) + NLA_ALIGN(pt->len);
  		if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
  			return -ERANGE;
  		break;
ea5693ccc   Patrick McHardy   netlink: allow em...
80
81
82
83
84
85
  	case NLA_NESTED:
  		/* a nested attributes is allowed to be empty; if its not,
  		 * it must have a size of at least NLA_HDRLEN.
  		 */
  		if (attrlen == 0)
  			break;
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
86
87
88
89
90
91
92
93
94
  	default:
  		if (pt->len)
  			minlen = pt->len;
  		else if (pt->type != NLA_UNSPEC)
  			minlen = nla_attr_minlen[pt->type];
  
  		if (attrlen < minlen)
  			return -ERANGE;
  	}
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  
  	return 0;
  }
  
  /**
   * nla_validate - Validate a stream of attributes
   * @head: head of attribute stream
   * @len: length of attribute stream
   * @maxtype: maximum attribute type to be expected
   * @policy: validation policy
   *
   * Validates all attributes in the specified attribute stream against the
   * specified policy. Attributes with a type exceeding maxtype will be
   * ignored. See documenation of struct nla_policy for more details.
   *
   * Returns 0 on success or a negative error code.
   */
3654654f7   Jan Engelhardt   netlink: let nlms...
112
  int nla_validate(const struct nlattr *head, int len, int maxtype,
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
113
  		 const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
114
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
115
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  	int rem, err;
  
  	nla_for_each_attr(nla, head, len, rem) {
  		err = validate_nla(nla, maxtype, policy);
  		if (err < 0)
  			goto errout;
  	}
  
  	err = 0;
  errout:
  	return err;
  }
  
  /**
e487eb99c   Holger Eitzenberger   netlink: add nla_...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
   * nla_policy_len - Determin the max. length of a policy
   * @policy: policy to use
   * @n: number of policies
   *
   * Determines the max. length of the policy.  It is currently used
   * to allocated Netlink buffers roughly the size of the actual
   * message.
   *
   * Returns 0 on success or a negative error code.
   */
  int
  nla_policy_len(const struct nla_policy *p, int n)
  {
  	int i, len = 0;
e3fa3aff0   Lars Ellenberg   net: fix nla_poli...
144
  	for (i = 0; i < n; i++, p++) {
e487eb99c   Holger Eitzenberger   netlink: add nla_...
145
146
147
148
149
150
151
152
153
154
  		if (p->len)
  			len += nla_total_size(p->len);
  		else if (nla_attr_minlen[p->type])
  			len += nla_total_size(nla_attr_minlen[p->type]);
  	}
  
  	return len;
  }
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
155
156
157
158
159
   * nla_parse - Parse a stream of attributes into a tb buffer
   * @tb: destination array with maxtype+1 elements
   * @maxtype: maximum attribute type to be expected
   * @head: head of attribute stream
   * @len: length of attribute stream
10b595aff   Julius Volz   netlink: Fix some...
160
   * @policy: validation policy
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
161
162
   *
   * Parses a stream of attributes and stores a pointer to each attribute in
b595076a1   Uwe Kleine-König   tree-wide: fix co...
163
   * the tb array accessible via the attribute type. Attributes with a type
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
164
165
166
167
168
   * exceeding maxtype will be silently ignored for backwards compatibility
   * reasons. policy may be set to NULL if no validation is required.
   *
   * Returns 0 on success or a negative error code.
   */
3654654f7   Jan Engelhardt   netlink: let nlms...
169
170
  int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
  	      int len, const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
171
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
172
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
173
174
175
176
177
  	int rem, err;
  
  	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
  
  	nla_for_each_attr(nla, head, len, rem) {
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
178
  		u16 type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
179
180
181
182
183
184
185
  
  		if (type > 0 && type <= maxtype) {
  			if (policy) {
  				err = validate_nla(nla, maxtype, policy);
  				if (err < 0)
  					goto errout;
  			}
3654654f7   Jan Engelhardt   netlink: let nlms...
186
  			tb[type] = (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  		}
  	}
  
  	if (unlikely(rem > 0))
  		printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
  		       "attributes.
  ", rem);
  
  	err = 0;
  errout:
  	return err;
  }
  
  /**
   * nla_find - Find a specific attribute in a stream of attributes
   * @head: head of attribute stream
   * @len: length of attribute stream
   * @attrtype: type of attribute to look for
   *
   * Returns the first attribute in the stream matching the specified type.
   */
3654654f7   Jan Engelhardt   netlink: let nlms...
208
  struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
209
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
210
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
211
212
213
  	int rem;
  
  	nla_for_each_attr(nla, head, len, rem)
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
214
  		if (nla_type(nla) == attrtype)
3654654f7   Jan Engelhardt   netlink: let nlms...
215
  			return (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
216
217
218
219
220
221
222
  
  	return NULL;
  }
  
  /**
   * nla_strlcpy - Copy string attribute payload into a sized buffer
   * @dst: where to copy the string to
10b595aff   Julius Volz   netlink: Fix some...
223
   * @nla: attribute to copy the string from
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
   * @dstsize: size of destination buffer
   *
   * Copies at most dstsize - 1 bytes into the destination buffer.
   * The result is always a valid NUL-terminated string. Unlike
   * strlcpy the destination buffer is always padded out.
   *
   * Returns the length of the source buffer.
   */
  size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
  {
  	size_t srclen = nla_len(nla);
  	char *src = nla_data(nla);
  
  	if (srclen > 0 && src[srclen - 1] == '\0')
  		srclen--;
  
  	if (dstsize > 0) {
  		size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
  
  		memset(dst, 0, dstsize);
  		memcpy(dst, src, len);
  	}
  
  	return srclen;
  }
  
  /**
   * nla_memcpy - Copy a netlink attribute into another memory area
   * @dest: where to copy to memcpy
   * @src: netlink attribute to copy from
   * @count: size of the destination area
   *
   * Note: The number of bytes copied is limited by the length of
   *       attribute's payload. memcpy
   *
   * Returns the number of bytes copied.
   */
b057efd4d   Patrick McHardy   netlink: constify...
261
  int nla_memcpy(void *dest, const struct nlattr *src, int count)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
  {
  	int minlen = min_t(int, count, nla_len(src));
  
  	memcpy(dest, nla_data(src), minlen);
  
  	return minlen;
  }
  
  /**
   * nla_memcmp - Compare an attribute with sized memory area
   * @nla: netlink attribute
   * @data: memory area
   * @size: size of memory area
   */
  int nla_memcmp(const struct nlattr *nla, const void *data,
  			     size_t size)
  {
  	int d = nla_len(nla) - size;
  
  	if (d == 0)
  		d = memcmp(nla_data(nla), data, size);
  
  	return d;
  }
  
  /**
   * nla_strcmp - Compare a string attribute against a string
   * @nla: netlink string attribute
   * @str: another string
   */
  int nla_strcmp(const struct nlattr *nla, const char *str)
  {
  	int len = strlen(str) + 1;
  	int d = nla_len(nla) - len;
  
  	if (d == 0)
  		d = memcmp(nla_data(nla), str, len);
  
  	return d;
  }
908002161   Herbert Xu   nlattr: Fix build...
302
  #ifdef CONFIG_NET
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
  /**
   * __nla_reserve - reserve room for attribute on the skb
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it.
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
  {
  	struct nlattr *nla;
  
  	nla = (struct nlattr *) skb_put(skb, nla_total_size(attrlen));
  	nla->nla_type = attrtype;
  	nla->nla_len = nla_attr_size(attrlen);
  
  	memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen));
  
  	return nla;
  }
908002161   Herbert Xu   nlattr: Fix build...
327
  EXPORT_SYMBOL(__nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
328
329
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
   * __nla_reserve_nohdr - reserve room for attribute without header
   * @skb: socket buffer to reserve room on
   * @attrlen: length of attribute payload
   *
   * Reserves room for attribute payload without a header.
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the payload.
   */
  void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
  {
  	void *start;
  
  	start = skb_put(skb, NLA_ALIGN(attrlen));
  	memset(start, 0, NLA_ALIGN(attrlen));
  
  	return start;
  }
908002161   Herbert Xu   nlattr: Fix build...
348
  EXPORT_SYMBOL(__nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
349
350
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
   * nla_reserve - reserve room for attribute on the skb
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it.
   *
   * Returns NULL if the tailroom of the skb is insufficient to store
   * the attribute header and payload.
   */
  struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
  {
  	if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
  		return NULL;
  
  	return __nla_reserve(skb, attrtype, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
369
  EXPORT_SYMBOL(nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
370
371
  
  /**
10b595aff   Julius Volz   netlink: Fix some...
372
   * nla_reserve_nohdr - reserve room for attribute without header
fe4944e59   Thomas Graf   [NETLINK]: Extend...
373
   * @skb: socket buffer to reserve room on
10b595aff   Julius Volz   netlink: Fix some...
374
   * @attrlen: length of attribute payload
fe4944e59   Thomas Graf   [NETLINK]: Extend...
375
376
377
378
379
380
381
382
383
384
385
386
387
   *
   * Reserves room for attribute payload without a header.
   *
   * Returns NULL if the tailroom of the skb is insufficient to store
   * the attribute payload.
   */
  void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen)
  {
  	if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
  		return NULL;
  
  	return __nla_reserve_nohdr(skb, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
388
  EXPORT_SYMBOL(nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
389
390
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
   * __nla_put - Add a netlink attribute to a socket buffer
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
  			     const void *data)
  {
  	struct nlattr *nla;
  
  	nla = __nla_reserve(skb, attrtype, attrlen);
  	memcpy(nla_data(nla), data, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
408
  EXPORT_SYMBOL(__nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
409

fe4944e59   Thomas Graf   [NETLINK]: Extend...
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  /**
   * __nla_put_nohdr - Add a netlink attribute without header
   * @skb: socket buffer to add attribute to
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute payload.
   */
  void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
  {
  	void *start;
  
  	start = __nla_reserve_nohdr(skb, attrlen);
  	memcpy(start, data, attrlen);
  }
908002161   Herbert Xu   nlattr: Fix build...
426
  EXPORT_SYMBOL(__nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
427
428
429
430
431
432
433
434
  
  /**
   * nla_put - Add a netlink attribute to a socket buffer
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
bc3ed28ca   Thomas Graf   netlink: Improve ...
435
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
436
437
438
439
440
   * the attribute header and payload.
   */
  int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
  {
  	if (unlikely(skb_tailroom(skb) < nla_total_size(attrlen)))
bc3ed28ca   Thomas Graf   netlink: Improve ...
441
  		return -EMSGSIZE;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
442
443
444
445
  
  	__nla_put(skb, attrtype, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
446
  EXPORT_SYMBOL(nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
447

fe4944e59   Thomas Graf   [NETLINK]: Extend...
448
449
450
451
452
453
  /**
   * nla_put_nohdr - Add a netlink attribute without header
   * @skb: socket buffer to add attribute to
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
bc3ed28ca   Thomas Graf   netlink: Improve ...
454
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
fe4944e59   Thomas Graf   [NETLINK]: Extend...
455
456
457
458
459
   * the attribute payload.
   */
  int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
  {
  	if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
bc3ed28ca   Thomas Graf   netlink: Improve ...
460
  		return -EMSGSIZE;
fe4944e59   Thomas Graf   [NETLINK]: Extend...
461
462
463
464
  
  	__nla_put_nohdr(skb, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
465
  EXPORT_SYMBOL(nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
466

01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
467
468
469
470
471
472
  /**
   * nla_append - Add a netlink attribute without header or padding
   * @skb: socket buffer to add attribute to
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
   *
bc3ed28ca   Thomas Graf   netlink: Improve ...
473
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
474
475
476
477
478
   * the attribute payload.
   */
  int nla_append(struct sk_buff *skb, int attrlen, const void *data)
  {
  	if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen)))
bc3ed28ca   Thomas Graf   netlink: Improve ...
479
  		return -EMSGSIZE;
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
480
481
482
483
  
  	memcpy(skb_put(skb, attrlen), data, attrlen);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
484
485
  EXPORT_SYMBOL(nla_append);
  #endif
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
486

bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
487
  EXPORT_SYMBOL(nla_validate);
e487eb99c   Holger Eitzenberger   netlink: add nla_...
488
  EXPORT_SYMBOL(nla_policy_len);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
489
490
491
  EXPORT_SYMBOL(nla_parse);
  EXPORT_SYMBOL(nla_find);
  EXPORT_SYMBOL(nla_strlcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
492
493
494
  EXPORT_SYMBOL(nla_memcpy);
  EXPORT_SYMBOL(nla_memcmp);
  EXPORT_SYMBOL(nla_strcmp);