Blame view

lib/nlattr.c 17.9 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>
6e237d099   David Ahern   netlink: Relax at...
16
17
18
19
20
  /* For these data types, attribute length should be exactly the given
   * size. However, to maintain compatibility with broken commands, if the
   * attribute length does not match the expected size a warning is emitted
   * to the user that the command is sending invalid data and needs to be fixed.
   */
28033ae4e   David Ahern   net: netlink: Upd...
21
  static const u8 nla_attr_len[NLA_TYPE_MAX+1] = {
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
22
23
24
25
  	[NLA_U8]	= sizeof(u8),
  	[NLA_U16]	= sizeof(u16),
  	[NLA_U32]	= sizeof(u32),
  	[NLA_U64]	= sizeof(u64),
9eca2eb99   Julian Anastasov   netlink: add minl...
26
27
28
29
  	[NLA_S8]	= sizeof(s8),
  	[NLA_S16]	= sizeof(s16),
  	[NLA_S32]	= sizeof(s32),
  	[NLA_S64]	= sizeof(s64),
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
30
  };
28033ae4e   David Ahern   net: netlink: Upd...
31
  static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = {
6e237d099   David Ahern   netlink: Relax at...
32
33
34
35
  	[NLA_U8]	= sizeof(u8),
  	[NLA_U16]	= sizeof(u16),
  	[NLA_U32]	= sizeof(u32),
  	[NLA_U64]	= sizeof(u64),
28033ae4e   David Ahern   net: netlink: Upd...
36
37
  	[NLA_MSECS]	= sizeof(u64),
  	[NLA_NESTED]	= NLA_HDRLEN,
6e237d099   David Ahern   netlink: Relax at...
38
39
40
41
  	[NLA_S8]	= sizeof(s8),
  	[NLA_S16]	= sizeof(s16),
  	[NLA_S32]	= sizeof(s32),
  	[NLA_S64]	= sizeof(s64),
28033ae4e   David Ahern   net: netlink: Upd...
42
  };
64c83d837   Jamal Hadi Salim   net netlink: Add ...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  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...
66
  static int validate_nla(const struct nlattr *nla, int maxtype,
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
67
  			const struct nla_policy *policy)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
68
  {
ef7c79ed6   Patrick McHardy   [NETLINK]: Mark n...
69
  	const struct nla_policy *pt;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
70
  	int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
71

8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
72
  	if (type <= 0 || type > maxtype)
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
73
  		return 0;
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
74
  	pt = &policy[type];
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
75
76
  
  	BUG_ON(pt->type > NLA_TYPE_MAX);
6e237d099   David Ahern   netlink: Relax at...
77
78
79
80
  	if (nla_attr_len[pt->type] && attrlen != nla_attr_len[pt->type]) {
  		pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.
  ",
  				    current->comm, type);
28033ae4e   David Ahern   net: netlink: Upd...
81
  	}
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
82
83
84
85
86
  	switch (pt->type) {
  	case NLA_FLAG:
  		if (attrlen > 0)
  			return -ERANGE;
  		break;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
87

64c83d837   Jamal Hadi Salim   net netlink: Add ...
88
89
90
91
92
  	case NLA_BITFIELD32:
  		if (attrlen != sizeof(struct nla_bitfield32))
  			return -ERANGE;
  
  		return validate_nla_bitfield32(nla, pt->validation_data);
a5531a5d8   Thomas Graf   [NETLINK]: Improv...
93
94
95
96
97
  	case NLA_NUL_STRING:
  		if (pt->len)
  			minlen = min_t(int, attrlen, pt->len + 1);
  		else
  			minlen = attrlen;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
98

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

8b7b93243   Pablo Neira   netlink: don't co...
393
394
395
396
  	if (attrlen > 0 && buf[attrlen - 1] == '\0')
  		attrlen--;
  
  	d = attrlen - len;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
397
398
399
400
401
  	if (d == 0)
  		d = memcmp(nla_data(nla), str, len);
  
  	return d;
  }
6d6a138f1   Fabian Frederick   lib/nlattr.c: mov...
402
  EXPORT_SYMBOL(nla_strcmp);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
403

908002161   Herbert Xu   nlattr: Fix build...
404
  #ifdef CONFIG_NET
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
  /**
   * __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 ...
420
  	nla = skb_put(skb, nla_total_size(attrlen));
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
421
422
423
424
425
426
427
  	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...
428
  EXPORT_SYMBOL(__nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
429
430
  
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
431
432
433
434
   * __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...
435
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
436
437
438
   *
   * 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...
439
   * attribute will have a 64-bit aligned nla_data() area.
089bf1a6a   Nicolas Dichtel   libnl: add more h...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
   *
   * 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...
455
456
457
458
459
460
461
462
463
464
465
   * __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...
466
  	return skb_put_zero(skb, NLA_ALIGN(attrlen));
fe4944e59   Thomas Graf   [NETLINK]: Extend...
467
  }
908002161   Herbert Xu   nlattr: Fix build...
468
  EXPORT_SYMBOL(__nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
469
470
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
   * 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...
489
  EXPORT_SYMBOL(nla_reserve);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
490
491
  
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
492
493
494
495
   * 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...
496
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
497
498
499
   *
   * 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...
500
   * attribute will have a 64-bit aligned nla_data() area.
089bf1a6a   Nicolas Dichtel   libnl: add more h...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
   *
   * 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...
522
   * nla_reserve_nohdr - reserve room for attribute without header
fe4944e59   Thomas Graf   [NETLINK]: Extend...
523
   * @skb: socket buffer to reserve room on
10b595aff   Julius Volz   netlink: Fix some...
524
   * @attrlen: length of attribute payload
fe4944e59   Thomas Graf   [NETLINK]: Extend...
525
526
527
528
529
530
531
532
533
534
535
536
537
   *
   * 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...
538
  EXPORT_SYMBOL(nla_reserve_nohdr);
fe4944e59   Thomas Graf   [NETLINK]: Extend...
539
540
  
  /**
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
   * __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...
558
  EXPORT_SYMBOL(__nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
559

fe4944e59   Thomas Graf   [NETLINK]: Extend...
560
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
561
562
563
564
565
   * __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...
566
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
   *
   * 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...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
   * __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...
597
  EXPORT_SYMBOL(__nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
598
599
600
601
602
603
604
605
  
  /**
   * 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 ...
606
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
607
608
609
610
611
   * 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 ...
612
  		return -EMSGSIZE;
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
613
614
615
616
  
  	__nla_put(skb, attrtype, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
617
  EXPORT_SYMBOL(nla_put);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
618

fe4944e59   Thomas Graf   [NETLINK]: Extend...
619
  /**
089bf1a6a   Nicolas Dichtel   libnl: add more h...
620
621
622
623
624
   * 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...
625
   * @padattr: attribute type for the padding
089bf1a6a   Nicolas Dichtel   libnl: add more h...
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
   *
   * 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...
648
649
650
651
652
   * 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 ...
653
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
fe4944e59   Thomas Graf   [NETLINK]: Extend...
654
655
656
657
658
   * 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 ...
659
  		return -EMSGSIZE;
fe4944e59   Thomas Graf   [NETLINK]: Extend...
660
661
662
663
  
  	__nla_put_nohdr(skb, attrlen, data);
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
664
  EXPORT_SYMBOL(nla_put_nohdr);
bfa83a9e0   Thomas Graf   [NETLINK]: Type-s...
665

01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
666
667
668
669
670
671
  /**
   * 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 ...
672
   * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
673
674
675
676
677
   * 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 ...
678
  		return -EMSGSIZE;
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
679

59ae1d127   Johannes Berg   networking: intro...
680
  	skb_put_data(skb, data, attrlen);
01480e1cf   Patrick McHardy   [NETLINK]: Add nl...
681
682
  	return 0;
  }
908002161   Herbert Xu   nlattr: Fix build...
683
684
  EXPORT_SYMBOL(nla_append);
  #endif