Blame view

lib/nlattr.c 17 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
2
3
4
5
6
7
  /*
   * NETLINK      Netlink attributes
   *
   * 		Authors:	Thomas Graf <tgraf@suug.ch>
   * 				Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
   */
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
8
  #include <linux/export.h>
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
9
10
11
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/jiffies.h>
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
12
13
14
15
  #include <linux/skbuff.h>
  #include <linux/string.h>
  #include <linux/types.h>
  #include <net/netlink.h>
32d84cdcf   Alexey Dobriyan   netlink: smaller ...
16
  static const u8 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
  };
64c83d837   Jamal Hadi Salim   net netlink: Add ...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  static int validate_nla_bitfield32(const struct nlattr *nla,
  				   u32 *valid_flags_allowed)
  {
  	const struct nla_bitfield32 *bf = nla_data(nla);
  	u32 *valid_flags_mask = valid_flags_allowed;
  
  	if (!valid_flags_allowed)
  		return -EINVAL;
  
  	/*disallow invalid bit selector */
  	if (bf->selector & ~*valid_flags_mask)
  		return -EINVAL;
  
  	/*disallow invalid bit values */
  	if (bf->value & ~*valid_flags_mask)
  		return -EINVAL;
  
  	/*disallow valid bit values that are not selected*/
  	if (bf->value & ~bf->selector)
  		return -EINVAL;
  
  	return 0;
  }
3654654f7   Jan Engelhardt   netlink: let nlms...
51
  static int validate_nla(const struct nlattr *nla, int maxtype,
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
52
  			const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
53
  {
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
54
  	const struct nla_policy *pt;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
55
  	int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
56

8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
57
  	if (type <= 0 || type > maxtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
58
  		return 0;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
59
  	pt = &policy[type];
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
60
61
  
  	BUG_ON(pt->type > NLA_TYPE_MAX);
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
62
63
64
65
66
  	switch (pt->type) {
  	case NLA_FLAG:
  		if (attrlen > 0)
  			return -ERANGE;
  		break;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
67

64c83d837   Jamal Hadi Salim   net netlink: Add ...
68
69
70
71
72
  	case NLA_BITFIELD32:
  		if (attrlen != sizeof(struct nla_bitfield32))
  			return -ERANGE;
  
  		return validate_nla_bitfield32(nla, pt->validation_data);
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
73
74
75
76
77
  	case NLA_NUL_STRING:
  		if (pt->len)
  			minlen = min_t(int, attrlen, pt->len + 1);
  		else
  			minlen = attrlen;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
78

a5531a5d8   Thomas Graf   [NETLINK]: Improv...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  		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...
97
98
99
100
  	case NLA_BINARY:
  		if (pt->len && attrlen > pt->len)
  			return -ERANGE;
  		break;
1092cb219   Patrick McHardy   [NETLINK]: attr: ...
101
102
103
104
105
106
107
108
109
110
111
  	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...
112
113
114
115
116
117
  	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...
118
119
120
121
122
123
124
125
126
  	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...
127
128
129
130
131
132
133
134
135
136
  
  	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
fceb6435e   Johannes Berg   netlink: pass ext...
137
   * @extack: extended ACK report struct
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
138
139
140
141
142
143
144
   *
   * 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...
145
  int nla_validate(const struct nlattr *head, int len, int maxtype,
fceb6435e   Johannes Berg   netlink: pass ext...
146
147
  		 const struct nla_policy *policy,
  		 struct netlink_ext_ack *extack)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
148
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
149
  	const struct nlattr *nla;
fceb6435e   Johannes Berg   netlink: pass ext...
150
  	int rem;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
151
152
  
  	nla_for_each_attr(nla, head, len, rem) {
fceb6435e   Johannes Berg   netlink: pass ext...
153
154
155
156
157
158
159
  		int err = validate_nla(nla, maxtype, policy);
  
  		if (err < 0) {
  			if (extack)
  				extack->bad_attr = nla;
  			return err;
  		}
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
160
  	}
fceb6435e   Johannes Berg   netlink: pass ext...
161
  	return 0;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
162
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
163
  EXPORT_SYMBOL(nla_validate);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
164
165
  
  /**
e487eb99c   Holger Eitzenberger   netlink: add nla_...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
   * 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...
180
  	for (i = 0; i < n; i++, p++) {
e487eb99c   Holger Eitzenberger   netlink: add nla_...
181
182
183
184
185
186
187
188
  		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...
189
  EXPORT_SYMBOL(nla_policy_len);
e487eb99c   Holger Eitzenberger   netlink: add nla_...
190
191
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
192
193
194
195
196
   * 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...
197
   * @policy: validation policy
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
198
199
   *
   * Parses a stream of attributes and stores a pointer to each attribute in
b595076a1   Uwe Kleine-König   tree-wide: fix co...
200
   * the tb array accessible via the attribute type. Attributes with a type
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
201
202
203
204
205
   * 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...
206
  int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
fceb6435e   Johannes Berg   netlink: pass ext...
207
208
  	      int len, const struct nla_policy *policy,
  	      struct netlink_ext_ack *extack)
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
214
215
  	int rem, err;
  
  	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
  
  	nla_for_each_attr(nla, head, len, rem) {
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
216
  		u16 type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
217
218
219
220
  
  		if (type > 0 && type <= maxtype) {
  			if (policy) {
  				err = validate_nla(nla, maxtype, policy);
fceb6435e   Johannes Berg   netlink: pass ext...
221
222
223
  				if (err < 0) {
  					if (extack)
  						extack->bad_attr = nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
224
  					goto errout;
fceb6435e   Johannes Berg   netlink: pass ext...
225
  				}
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
226
  			}
3654654f7   Jan Engelhardt   netlink: let nlms...
227
  			tb[type] = (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
228
229
230
231
  		}
  	}
  
  	if (unlikely(rem > 0))
bfc5184b6   Michal Schmidt   netlink: rate-lim...
232
233
234
  		pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.
  ",
  				    rem, current->comm);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
235
236
237
238
239
  
  	err = 0;
  errout:
  	return err;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
240
  EXPORT_SYMBOL(nla_parse);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
241
242
243
244
245
246
247
248
249
  
  /**
   * 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...
250
  struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
251
  {
3654654f7   Jan Engelhardt   netlink: let nlms...
252
  	const struct nlattr *nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
253
254
255
  	int rem;
  
  	nla_for_each_attr(nla, head, len, rem)
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
256
  		if (nla_type(nla) == attrtype)
3654654f7   Jan Engelhardt   netlink: let nlms...
257
  			return (struct nlattr *)nla;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
258
259
260
  
  	return NULL;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
261
  EXPORT_SYMBOL(nla_find);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
262
263
264
265
  
  /**
   * nla_strlcpy - Copy string attribute payload into a sized buffer
   * @dst: where to copy the string to
10b595aff   Julius Volz   netlink: Fix some...
266
   * @nla: attribute to copy the string from
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
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
   * @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...
292
  EXPORT_SYMBOL(nla_strlcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
293
294
  
  /**
2cf0c8b3e   Phil Sutter   netlink: Introduc...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
   * nla_strdup - Copy string attribute payload into a newly allocated buffer
   * @nla: attribute to copy the string from
   * @flags: the type of memory to allocate (see kmalloc).
   *
   * Returns a pointer to the allocated buffer or NULL on error.
   */
  char *nla_strdup(const struct nlattr *nla, gfp_t flags)
  {
  	size_t srclen = nla_len(nla);
  	char *src = nla_data(nla), *dst;
  
  	if (srclen > 0 && src[srclen - 1] == '\0')
  		srclen--;
  
  	dst = kmalloc(srclen + 1, flags);
  	if (dst != NULL) {
  		memcpy(dst, src, srclen);
  		dst[srclen] = '\0';
  	}
  	return dst;
  }
  EXPORT_SYMBOL(nla_strdup);
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
319
320
321
322
323
324
325
326
327
328
   * 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...
329
  int nla_memcpy(void *dest, const struct nlattr *src, int count)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
330
331
332
333
  {
  	int minlen = min_t(int, count, nla_len(src));
  
  	memcpy(dest, nla_data(src), minlen);
5899f0478   Jiri Benc   netlink: pad nla_...
334
335
  	if (count > minlen)
  		memset(dest + minlen, 0, count - minlen);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
336
337
338
  
  	return minlen;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
339
  EXPORT_SYMBOL(nla_memcpy);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  
  /**
   * 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...
357
  EXPORT_SYMBOL(nla_memcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
358
359
360
361
362
363
364
365
  
  /**
   * 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...
366
367
368
369
  	int len = strlen(str);
  	char *buf = nla_data(nla);
  	int attrlen = nla_len(nla);
  	int d;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
370

8b7b93243   Pablo Neira   netlink: don't co...
371
372
373
374
  	if (attrlen > 0 && buf[attrlen - 1] == '\0')
  		attrlen--;
  
  	d = attrlen - len;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
375
376
377
378
379
  	if (d == 0)
  		d = memcmp(nla_data(nla), str, len);
  
  	return d;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
380
  EXPORT_SYMBOL(nla_strcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
381

908002161   Herbert Xu   nlattr: Fix build...
382
  #ifdef CONFIG_NET
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  /**
   * __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;
4df864c1d   Johannes Berg   networking: make ...
398
  	nla = skb_put(skb, nla_total_size(attrlen));
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
399
400
401
402
403
404
405
  	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...
406
  EXPORT_SYMBOL(__nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
407
408
  
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
409
410
411
412
   * __nla_reserve_64bit - reserve room for attribute on the skb and align it
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
413
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
414
415
416
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it. It also ensure that this
11a995730   Nicolas Dichtel   libnl: fix help o...
417
   * attribute will have a 64-bit aligned nla_data() area.
089bf1a6a   Nicolas Dichtel   libnl: add more h...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype,
  				   int attrlen, int padattr)
  {
  	if (nla_need_padding_for_64bit(skb))
  		nla_align_64bit(skb, padattr);
  
  	return __nla_reserve(skb, attrtype, attrlen);
  }
  EXPORT_SYMBOL(__nla_reserve_64bit);
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
433
434
435
436
437
438
439
440
441
442
443
   * __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)
  {
b952f4dff   yuan linyu   net: manual clean...
444
  	return skb_put_zero(skb, NLA_ALIGN(attrlen));
fe4944e59   Thomas Graf   [NETLINK]: Extend...
445
  }
908002161   Herbert Xu   nlattr: Fix build...
446
  EXPORT_SYMBOL(__nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
447
448
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
   * 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...
467
  EXPORT_SYMBOL(nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
468
469
  
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
470
471
472
473
   * nla_reserve_64bit - reserve room for attribute on the skb and align it
   * @skb: socket buffer to reserve room on
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
474
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
475
476
477
   *
   * Adds a netlink attribute header to a socket buffer and reserves
   * room for the payload but does not copy it. It also ensure that this
11a995730   Nicolas Dichtel   libnl: fix help o...
478
   * attribute will have a 64-bit aligned nla_data() area.
089bf1a6a   Nicolas Dichtel   libnl: add more h...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
   *
   * Returns NULL if the tailroom of the skb is insufficient to store
   * the attribute header and payload.
   */
  struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype, int attrlen,
  				 int padattr)
  {
  	size_t len;
  
  	if (nla_need_padding_for_64bit(skb))
  		len = nla_total_size_64bit(attrlen);
  	else
  		len = nla_total_size(attrlen);
  	if (unlikely(skb_tailroom(skb) < len))
  		return NULL;
  
  	return __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
  }
  EXPORT_SYMBOL(nla_reserve_64bit);
  
  /**
10b595aff   Julius Volz   netlink: Fix some...
500
   * nla_reserve_nohdr - reserve room for attribute without header
fe4944e59   Thomas Graf   [NETLINK]: Extend...
501
   * @skb: socket buffer to reserve room on
10b595aff   Julius Volz   netlink: Fix some...
502
   * @attrlen: length of attribute payload
fe4944e59   Thomas Graf   [NETLINK]: Extend...
503
504
505
506
507
508
509
510
511
512
513
514
515
   *
   * 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...
516
  EXPORT_SYMBOL(nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
517
518
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
   * __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...
536
  EXPORT_SYMBOL(__nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
537

fe4944e59   Thomas Graf   [NETLINK]: Extend...
538
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
539
540
541
542
543
   * __nla_put_64bit - Add a netlink attribute to a socket buffer and align it
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
544
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
   *
   * The caller is responsible to ensure that the skb provides enough
   * tailroom for the attribute header and payload.
   */
  void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
  		     const void *data, int padattr)
  {
  	struct nlattr *nla;
  
  	nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
  	memcpy(nla_data(nla), data, attrlen);
  }
  EXPORT_SYMBOL(__nla_put_64bit);
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
   * __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...
575
  EXPORT_SYMBOL(__nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
576
577
578
579
580
581
582
583
  
  /**
   * 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 ...
584
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
585
586
587
588
589
   * 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 ...
590
  		return -EMSGSIZE;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
591
592
593
594
  
  	__nla_put(skb, attrtype, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
595
  EXPORT_SYMBOL(nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
596

fe4944e59   Thomas Graf   [NETLINK]: Extend...
597
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
598
599
600
601
602
   * nla_put_64bit - Add a netlink attribute to a socket buffer and align it
   * @skb: socket buffer to add attribute to
   * @attrtype: attribute type
   * @attrlen: length of attribute payload
   * @data: head of attribute payload
11a995730   Nicolas Dichtel   libnl: fix help o...
603
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
   *
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
   * the attribute header and payload.
   */
  int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
  		  const void *data, int padattr)
  {
  	size_t len;
  
  	if (nla_need_padding_for_64bit(skb))
  		len = nla_total_size_64bit(attrlen);
  	else
  		len = nla_total_size(attrlen);
  	if (unlikely(skb_tailroom(skb) < len))
  		return -EMSGSIZE;
  
  	__nla_put_64bit(skb, attrtype, attrlen, data, padattr);
  	return 0;
  }
  EXPORT_SYMBOL(nla_put_64bit);
  
  /**
fe4944e59   Thomas Graf   [NETLINK]: Extend...
626
627
628
629
630
   * 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 ...
631
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
fe4944e59   Thomas Graf   [NETLINK]: Extend...
632
633
634
635
636
   * 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 ...
637
  		return -EMSGSIZE;
fe4944e59   Thomas Graf   [NETLINK]: Extend...
638
639
640
641
  
  	__nla_put_nohdr(skb, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
642
  EXPORT_SYMBOL(nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
643

01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
644
645
646
647
648
649
  /**
   * 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 ...
650
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
651
652
653
654
655
   * 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 ...
656
  		return -EMSGSIZE;
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
657

59ae1d127   Johannes Berg   networking: intro...
658
  	skb_put_data(skb, data, attrlen);
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
659
660
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
661
662
  EXPORT_SYMBOL(nla_append);
  #endif