Commit fe4944e59c357f945f81bc67edb7ed1392e875ad

Authored by Thomas Graf
Committed by David S. Miller
1 parent e1ef4bf23b

[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
... ... @@ -75,7 +75,7 @@
75 75 /*
76 76 * If new attributes are added, please revisit this allocation
77 77 */
78   - skb = nlmsg_new(size);
  78 + skb = nlmsg_new(size, GFP_KERNEL);
79 79 if (!skb)
80 80 return -ENOMEM;
81 81  
... ... @@ -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);
net/netlink/genetlink.c
... ... @@ -440,7 +440,7 @@
440 440 struct sk_buff *skb;
441 441 int err;
442 442  
443   - skb = nlmsg_new(NLMSG_GOODSIZE);
  443 + skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
444 444 if (skb == NULL)
445 445 return ERR_PTR(-ENOBUFS);
446 446