Commit fe4944e59c357f945f81bc67edb7ed1392e875ad
Committed by
David S. Miller
1 parent
e1ef4bf23b
Exists in
master
and in
4 other branches
[NETLINK]: Extend netlink messaging interface
Adds: nlmsg_get_pos() return current position in message nlmsg_trim() trim part of message nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr nla_put_nohdr(skb, len, data) add attribute w/o hdr nla_find_nested() find attribute in nested attributes Fixes nlmsg_new() to take allocation flags and consider size. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 4 changed files with 141 additions and 12 deletions Side-by-side Diff
include/net/netlink.h
... | ... | @@ -35,6 +35,8 @@ |
35 | 35 | * nlmsg_put() add a netlink message to an skb |
36 | 36 | * nlmsg_put_answer() callback based nlmsg_put() |
37 | 37 | * nlmsg_end() finanlize netlink message |
38 | + * nlmsg_get_pos() return current position in message | |
39 | + * nlmsg_trim() trim part of message | |
38 | 40 | * nlmsg_cancel() cancel message construction |
39 | 41 | * nlmsg_free() free a netlink message |
40 | 42 | * |
41 | 43 | |
... | ... | @@ -80,8 +82,10 @@ |
80 | 82 | * struct nlattr netlink attribtue header |
81 | 83 | * |
82 | 84 | * Attribute Construction: |
83 | - * nla_reserve(skb, type, len) reserve skb tailroom for an attribute | |
85 | + * nla_reserve(skb, type, len) reserve room for an attribute | |
86 | + * nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr | |
84 | 87 | * nla_put(skb, type, len, data) add attribute to skb |
88 | + * nla_put_nohdr(skb, len, data) add attribute w/o hdr | |
85 | 89 | * |
86 | 90 | * Attribute Construction for Basic Types: |
87 | 91 | * nla_put_u8(skb, type, value) add u8 attribute to skb |
... | ... | @@ -139,6 +143,7 @@ |
139 | 143 | * nla_next(nla, remaining) get next netlink attribute |
140 | 144 | * nla_validate() validate a stream of attributes |
141 | 145 | * nla_find() find attribute in stream of attributes |
146 | + * nla_find_nested() find attribute in nested attributes | |
142 | 147 | * nla_parse() parse and validate stream of attrs |
143 | 148 | * nla_parse_nested() parse nested attribuets |
144 | 149 | * nla_for_each_attr() loop over all attributes |
145 | 150 | |
146 | 151 | |
147 | 152 | |
... | ... | @@ -203,12 +208,18 @@ |
203 | 208 | extern int nla_strcmp(const struct nlattr *nla, const char *str); |
204 | 209 | extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, |
205 | 210 | int attrlen); |
211 | +extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen); | |
206 | 212 | extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, |
207 | 213 | int attrlen); |
214 | +extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen); | |
208 | 215 | extern void __nla_put(struct sk_buff *skb, int attrtype, |
209 | 216 | int attrlen, const void *data); |
217 | +extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen, | |
218 | + const void *data); | |
210 | 219 | extern int nla_put(struct sk_buff *skb, int attrtype, |
211 | 220 | int attrlen, const void *data); |
221 | +extern int nla_put_nohdr(struct sk_buff *skb, int attrlen, | |
222 | + const void *data); | |
212 | 223 | |
213 | 224 | /************************************************************************** |
214 | 225 | * Netlink Messages |
215 | 226 | |
216 | 227 | |
... | ... | @@ -453,12 +464,13 @@ |
453 | 464 | /** |
454 | 465 | * nlmsg_new - Allocate a new netlink message |
455 | 466 | * @size: maximum size of message |
467 | + * @flags: the type of memory to allocate. | |
456 | 468 | * |
457 | 469 | * Use NLMSG_GOODSIZE if size isn't know and you need a good default size. |
458 | 470 | */ |
459 | -static inline struct sk_buff *nlmsg_new(int size) | |
471 | +static inline struct sk_buff *nlmsg_new(int size, gfp_t flags) | |
460 | 472 | { |
461 | - return alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | |
473 | + return alloc_skb(size, flags); | |
462 | 474 | } |
463 | 475 | |
464 | 476 | /** |
... | ... | @@ -480,6 +492,32 @@ |
480 | 492 | } |
481 | 493 | |
482 | 494 | /** |
495 | + * nlmsg_get_pos - return current position in netlink message | |
496 | + * @skb: socket buffer the message is stored in | |
497 | + * | |
498 | + * Returns a pointer to the current tail of the message. | |
499 | + */ | |
500 | +static inline void *nlmsg_get_pos(struct sk_buff *skb) | |
501 | +{ | |
502 | + return skb->tail; | |
503 | +} | |
504 | + | |
505 | +/** | |
506 | + * nlmsg_trim - Trim message to a mark | |
507 | + * @skb: socket buffer the message is stored in | |
508 | + * @mark: mark to trim to | |
509 | + * | |
510 | + * Trims the message to the provided mark. Returns -1. | |
511 | + */ | |
512 | +static inline int nlmsg_trim(struct sk_buff *skb, void *mark) | |
513 | +{ | |
514 | + if (mark) | |
515 | + skb_trim(skb, (unsigned char *) mark - skb->data); | |
516 | + | |
517 | + return -1; | |
518 | +} | |
519 | + | |
520 | +/** | |
483 | 521 | * nlmsg_cancel - Cancel construction of a netlink message |
484 | 522 | * @skb: socket buffer the message is stored in |
485 | 523 | * @nlh: netlink message header |
... | ... | @@ -489,9 +527,7 @@ |
489 | 527 | */ |
490 | 528 | static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh) |
491 | 529 | { |
492 | - skb_trim(skb, (unsigned char *) nlh - skb->data); | |
493 | - | |
494 | - return -1; | |
530 | + return nlmsg_trim(skb, nlh); | |
495 | 531 | } |
496 | 532 | |
497 | 533 | /** |
... | ... | @@ -631,6 +667,18 @@ |
631 | 667 | } |
632 | 668 | |
633 | 669 | /** |
670 | + * nla_find_nested - find attribute in a set of nested attributes | |
671 | + * @nla: attribute containing the nested attributes | |
672 | + * @attrtype: type of attribute to look for | |
673 | + * | |
674 | + * Returns the first attribute which matches the specified type. | |
675 | + */ | |
676 | +static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype) | |
677 | +{ | |
678 | + return nla_find(nla_data(nla), nla_len(nla), attrtype); | |
679 | +} | |
680 | + | |
681 | +/** | |
634 | 682 | * nla_parse_nested - parse nested attributes |
635 | 683 | * @tb: destination array with maxtype+1 elements |
636 | 684 | * @maxtype: maximum attribute type to be expected |
... | ... | @@ -862,10 +910,7 @@ |
862 | 910 | */ |
863 | 911 | static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) |
864 | 912 | { |
865 | - if (start) | |
866 | - skb_trim(skb, (unsigned char *) start - skb->data); | |
867 | - | |
868 | - return -1; | |
913 | + return nlmsg_trim(skb, start); | |
869 | 914 | } |
870 | 915 | |
871 | 916 | /** |
... | ... | @@ -879,6 +924,15 @@ |
879 | 924 | for (pos = head, rem = len; \ |
880 | 925 | nla_ok(pos, rem); \ |
881 | 926 | pos = nla_next(pos, &(rem))) |
927 | + | |
928 | +/** | |
929 | + * nla_for_each_nested - iterate over nested attributes | |
930 | + * @pos: loop counter, set to current attribute | |
931 | + * @nla: attribute containing the nested attributes | |
932 | + * @rem: initialized to len, holds bytes currently remaining in stream | |
933 | + */ | |
934 | +#define nla_for_each_nested(pos, nla, rem) \ | |
935 | + nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem) | |
882 | 936 | |
883 | 937 | #endif |
kernel/taskstats.c
net/netlink/attr.c
... | ... | @@ -255,6 +255,26 @@ |
255 | 255 | } |
256 | 256 | |
257 | 257 | /** |
258 | + * __nla_reserve_nohdr - reserve room for attribute without header | |
259 | + * @skb: socket buffer to reserve room on | |
260 | + * @attrlen: length of attribute payload | |
261 | + * | |
262 | + * Reserves room for attribute payload without a header. | |
263 | + * | |
264 | + * The caller is responsible to ensure that the skb provides enough | |
265 | + * tailroom for the payload. | |
266 | + */ | |
267 | +void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen) | |
268 | +{ | |
269 | + void *start; | |
270 | + | |
271 | + start = skb_put(skb, NLA_ALIGN(attrlen)); | |
272 | + memset(start, 0, NLA_ALIGN(attrlen)); | |
273 | + | |
274 | + return start; | |
275 | +} | |
276 | + | |
277 | +/** | |
258 | 278 | * nla_reserve - reserve room for attribute on the skb |
259 | 279 | * @skb: socket buffer to reserve room on |
260 | 280 | * @attrtype: attribute type |
... | ... | @@ -275,6 +295,24 @@ |
275 | 295 | } |
276 | 296 | |
277 | 297 | /** |
298 | + * nla_reserve - reserve room for attribute without header | |
299 | + * @skb: socket buffer to reserve room on | |
300 | + * @len: length of attribute payload | |
301 | + * | |
302 | + * Reserves room for attribute payload without a header. | |
303 | + * | |
304 | + * Returns NULL if the tailroom of the skb is insufficient to store | |
305 | + * the attribute payload. | |
306 | + */ | |
307 | +void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen) | |
308 | +{ | |
309 | + if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) | |
310 | + return NULL; | |
311 | + | |
312 | + return __nla_reserve_nohdr(skb, attrlen); | |
313 | +} | |
314 | + | |
315 | +/** | |
278 | 316 | * __nla_put - Add a netlink attribute to a socket buffer |
279 | 317 | * @skb: socket buffer to add attribute to |
280 | 318 | * @attrtype: attribute type |
281 | 319 | |
... | ... | @@ -293,7 +331,23 @@ |
293 | 331 | memcpy(nla_data(nla), data, attrlen); |
294 | 332 | } |
295 | 333 | |
334 | +/** | |
335 | + * __nla_put_nohdr - Add a netlink attribute without header | |
336 | + * @skb: socket buffer to add attribute to | |
337 | + * @attrlen: length of attribute payload | |
338 | + * @data: head of attribute payload | |
339 | + * | |
340 | + * The caller is responsible to ensure that the skb provides enough | |
341 | + * tailroom for the attribute payload. | |
342 | + */ | |
343 | +void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) | |
344 | +{ | |
345 | + void *start; | |
296 | 346 | |
347 | + start = __nla_reserve_nohdr(skb, attrlen); | |
348 | + memcpy(start, data, attrlen); | |
349 | +} | |
350 | + | |
297 | 351 | /** |
298 | 352 | * nla_put - Add a netlink attribute to a socket buffer |
299 | 353 | * @skb: socket buffer to add attribute to |
300 | 354 | |
301 | 355 | |
302 | 356 | |
303 | 357 | |
304 | 358 | |
... | ... | @@ -313,15 +367,36 @@ |
313 | 367 | return 0; |
314 | 368 | } |
315 | 369 | |
370 | +/** | |
371 | + * nla_put_nohdr - Add a netlink attribute without header | |
372 | + * @skb: socket buffer to add attribute to | |
373 | + * @attrlen: length of attribute payload | |
374 | + * @data: head of attribute payload | |
375 | + * | |
376 | + * Returns -1 if the tailroom of the skb is insufficient to store | |
377 | + * the attribute payload. | |
378 | + */ | |
379 | +int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) | |
380 | +{ | |
381 | + if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) | |
382 | + return -1; | |
316 | 383 | |
384 | + __nla_put_nohdr(skb, attrlen, data); | |
385 | + return 0; | |
386 | +} | |
387 | + | |
317 | 388 | EXPORT_SYMBOL(nla_validate); |
318 | 389 | EXPORT_SYMBOL(nla_parse); |
319 | 390 | EXPORT_SYMBOL(nla_find); |
320 | 391 | EXPORT_SYMBOL(nla_strlcpy); |
321 | 392 | EXPORT_SYMBOL(__nla_reserve); |
393 | +EXPORT_SYMBOL(__nla_reserve_nohdr); | |
322 | 394 | EXPORT_SYMBOL(nla_reserve); |
395 | +EXPORT_SYMBOL(nla_reserve_nohdr); | |
323 | 396 | EXPORT_SYMBOL(__nla_put); |
397 | +EXPORT_SYMBOL(__nla_put_nohdr); | |
324 | 398 | EXPORT_SYMBOL(nla_put); |
399 | +EXPORT_SYMBOL(nla_put_nohdr); | |
325 | 400 | EXPORT_SYMBOL(nla_memcpy); |
326 | 401 | EXPORT_SYMBOL(nla_memcmp); |
327 | 402 | EXPORT_SYMBOL(nla_strcmp); |