Blame view

lib/nlattr.c 12.5 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>
   */
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
7
  #include <linux/export.h>
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
8
9
10
11
12
13
14
15
  #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
  	[NLA_NESTED]	= NLA_HDRLEN,
9eca2eb99   Julian Anastasov   netlink: add minl...
23
24
25
26
  	[NLA_S8]	= sizeof(s8),
  	[NLA_S16]	= sizeof(s16),
  	[NLA_S32]	= sizeof(s32),
  	[NLA_S64]	= sizeof(s64),
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
27
  };
3654654f7   Jan Engelhardt   netlink: let nlms...
28
  static int validate_nla(const struct nlattr *nla, int maxtype,
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
29
  			const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
30
  {
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
31
  	const struct nla_policy *pt;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
32
  	int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
33

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

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

a5531a5d8   Thomas Graf   [NETLINK]: Improv...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  		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...
69
70
71
72
  	case NLA_BINARY:
  		if (pt->len && attrlen > pt->len)
  			return -ERANGE;
  		break;
1092cb219   Patrick McHardy   [NETLINK]: attr: ...
73
74
75
76
77
78
79
80
81
82
83
  	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...
84
85
86
87
88
89
  	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...
90
91
92
93
94
95
96
97
98
  	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...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  
  	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...
116
  int nla_validate(const struct nlattr *head, int len, int maxtype,
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
117
  		 const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
118
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
119
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
120
121
122
123
124
125
126
127
128
129
130
131
  	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;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
132
  EXPORT_SYMBOL(nla_validate);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
133
134
  
  /**
e487eb99c   Holger Eitzenberger   netlink: add nla_...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
   * 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...
149
  	for (i = 0; i < n; i++, p++) {
e487eb99c   Holger Eitzenberger   netlink: add nla_...
150
151
152
153
154
155
156
157
  		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;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
158
  EXPORT_SYMBOL(nla_policy_len);
e487eb99c   Holger Eitzenberger   netlink: add nla_...
159
160
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
161
162
163
164
165
   * 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...
166
   * @policy: validation policy
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
167
168
   *
   * Parses a stream of attributes and stores a pointer to each attribute in
b595076a1   Uwe Kleine-König   tree-wide: fix co...
169
   * the tb array accessible via the attribute type. Attributes with a type
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
170
171
172
173
174
   * 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...
175
176
  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...
177
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
178
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
179
180
181
182
183
  	int rem, err;
  
  	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
  
  	nla_for_each_attr(nla, head, len, rem) {
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
184
  		u16 type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
185
186
187
188
189
190
191
  
  		if (type > 0 && type <= maxtype) {
  			if (policy) {
  				err = validate_nla(nla, maxtype, policy);
  				if (err < 0)
  					goto errout;
  			}
3654654f7   Jan Engelhardt   netlink: let nlms...
192
  			tb[type] = (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
193
194
195
196
  		}
  	}
  
  	if (unlikely(rem > 0))
bfc5184b6   Michal Schmidt   netlink: rate-lim...
197
198
199
  		pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.
  ",
  				    rem, current->comm);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
200
201
202
203
204
  
  	err = 0;
  errout:
  	return err;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
205
  EXPORT_SYMBOL(nla_parse);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
206
207
208
209
210
211
212
213
214
  
  /**
   * 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...
215
  struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
216
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
217
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
218
219
220
  	int rem;
  
  	nla_for_each_attr(nla, head, len, rem)
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
221
  		if (nla_type(nla) == attrtype)
3654654f7   Jan Engelhardt   netlink: let nlms...
222
  			return (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
223
224
225
  
  	return NULL;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
226
  EXPORT_SYMBOL(nla_find);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
227
228
229
230
  
  /**
   * nla_strlcpy - Copy string attribute payload into a sized buffer
   * @dst: where to copy the string to
10b595aff   Julius Volz   netlink: Fix some...
231
   * @nla: attribute to copy the string from
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
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
   * @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;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
257
  EXPORT_SYMBOL(nla_strlcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
258
259
260
261
262
263
264
265
266
267
268
269
  
  /**
   * 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...
270
  int nla_memcpy(void *dest, const struct nlattr *src, int count)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
271
272
273
274
275
276
277
  {
  	int minlen = min_t(int, count, nla_len(src));
  
  	memcpy(dest, nla_data(src), minlen);
  
  	return minlen;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
278
  EXPORT_SYMBOL(nla_memcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  
  /**
   * 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;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
296
  EXPORT_SYMBOL(nla_memcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
297
298
299
300
301
302
303
304
  
  /**
   * 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)
  {
8b7b93243   Pablo Neira   netlink: don't co...
305
306
307
308
  	int len = strlen(str);
  	char *buf = nla_data(nla);
  	int attrlen = nla_len(nla);
  	int d;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
309

8b7b93243   Pablo Neira   netlink: don't co...
310
311
312
313
  	if (attrlen > 0 && buf[attrlen - 1] == '\0')
  		attrlen--;
  
  	d = attrlen - len;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
314
315
316
317
318
  	if (d == 0)
  		d = memcmp(nla_data(nla), str, len);
  
  	return d;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
319
  EXPORT_SYMBOL(nla_strcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
320

908002161   Herbert Xu   nlattr: Fix build...
321
  #ifdef CONFIG_NET
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  /**
   * __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...
346
  EXPORT_SYMBOL(__nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
347
348
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
   * __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...
367
  EXPORT_SYMBOL(__nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
368
369
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
   * 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...
388
  EXPORT_SYMBOL(nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
389
390
  
  /**
10b595aff   Julius Volz   netlink: Fix some...
391
   * nla_reserve_nohdr - reserve room for attribute without header
fe4944e59   Thomas Graf   [NETLINK]: Extend...
392
   * @skb: socket buffer to reserve room on
10b595aff   Julius Volz   netlink: Fix some...
393
   * @attrlen: length of attribute payload
fe4944e59   Thomas Graf   [NETLINK]: Extend...
394
395
396
397
398
399
400
401
402
403
404
405
406
   *
   * 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...
407
  EXPORT_SYMBOL(nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
408
409
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
   * __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...
427
  EXPORT_SYMBOL(__nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
428

fe4944e59   Thomas Graf   [NETLINK]: Extend...
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  /**
   * __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...
445
  EXPORT_SYMBOL(__nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
446
447
448
449
450
451
452
453
  
  /**
   * 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 ...
454
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
455
456
457
458
459
   * 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 ...
460
  		return -EMSGSIZE;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
461
462
463
464
  
  	__nla_put(skb, attrtype, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
465
  EXPORT_SYMBOL(nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
466

fe4944e59   Thomas Graf   [NETLINK]: Extend...
467
468
469
470
471
472
  /**
   * 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 ...
473
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
fe4944e59   Thomas Graf   [NETLINK]: Extend...
474
475
476
477
478
   * 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 ...
479
  		return -EMSGSIZE;
fe4944e59   Thomas Graf   [NETLINK]: Extend...
480
481
482
483
  
  	__nla_put_nohdr(skb, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
484
  EXPORT_SYMBOL(nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
485

01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
486
487
488
489
490
491
  /**
   * 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 ...
492
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
493
494
495
496
497
   * 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 ...
498
  		return -EMSGSIZE;
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
499
500
501
502
  
  	memcpy(skb_put(skb, attrlen), data, attrlen);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
503
504
  EXPORT_SYMBOL(nla_append);
  #endif