aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-08-05 02:03:05 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:53:43 -0400
commitfe4944e59c357f945f81bc67edb7ed1392e875ad (patch)
tree9634365d416ac574442fc7e21e1eaa26a71a26d1
parente1ef4bf23b1ced0bf78a1c98289f746486e5c912 (diff)
[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>
-rw-r--r--include/net/netlink.h74
-rw-r--r--kernel/taskstats.c2
-rw-r--r--net/netlink/attr.c75
-rw-r--r--net/netlink/genetlink.c2
4 files changed, 141 insertions, 12 deletions
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 640c26a90cf1..3a5e40b1e045 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -35,6 +35,8 @@
35 * nlmsg_put() add a netlink message to an skb 35 * nlmsg_put() add a netlink message to an skb
36 * nlmsg_put_answer() callback based nlmsg_put() 36 * nlmsg_put_answer() callback based nlmsg_put()
37 * nlmsg_end() finanlize netlink message 37 * nlmsg_end() finanlize netlink message
38 * nlmsg_get_pos() return current position in message
39 * nlmsg_trim() trim part of message
38 * nlmsg_cancel() cancel message construction 40 * nlmsg_cancel() cancel message construction
39 * nlmsg_free() free a netlink message 41 * nlmsg_free() free a netlink message
40 * 42 *
@@ -80,8 +82,10 @@
80 * struct nlattr netlink attribtue header 82 * struct nlattr netlink attribtue header
81 * 83 *
82 * Attribute Construction: 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 * nla_put(skb, type, len, data) add attribute to skb 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 * Attribute Construction for Basic Types: 90 * Attribute Construction for Basic Types:
87 * nla_put_u8(skb, type, value) add u8 attribute to skb 91 * nla_put_u8(skb, type, value) add u8 attribute to skb
@@ -139,6 +143,7 @@
139 * nla_next(nla, remaining) get next netlink attribute 143 * nla_next(nla, remaining) get next netlink attribute
140 * nla_validate() validate a stream of attributes 144 * nla_validate() validate a stream of attributes
141 * nla_find() find attribute in stream of attributes 145 * nla_find() find attribute in stream of attributes
146 * nla_find_nested() find attribute in nested attributes
142 * nla_parse() parse and validate stream of attrs 147 * nla_parse() parse and validate stream of attrs
143 * nla_parse_nested() parse nested attribuets 148 * nla_parse_nested() parse nested attribuets
144 * nla_for_each_attr() loop over all attributes 149 * nla_for_each_attr() loop over all attributes
@@ -203,12 +208,18 @@ extern int nla_memcmp(const struct nlattr *nla, const void *data,
203extern int nla_strcmp(const struct nlattr *nla, const char *str); 208extern int nla_strcmp(const struct nlattr *nla, const char *str);
204extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, 209extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype,
205 int attrlen); 210 int attrlen);
211extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
206extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, 212extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype,
207 int attrlen); 213 int attrlen);
214extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
208extern void __nla_put(struct sk_buff *skb, int attrtype, 215extern void __nla_put(struct sk_buff *skb, int attrtype,
209 int attrlen, const void *data); 216 int attrlen, const void *data);
217extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen,
218 const void *data);
210extern int nla_put(struct sk_buff *skb, int attrtype, 219extern int nla_put(struct sk_buff *skb, int attrtype,
211 int attrlen, const void *data); 220 int attrlen, const void *data);
221extern int nla_put_nohdr(struct sk_buff *skb, int attrlen,
222 const void *data);
212 223
213/************************************************************************** 224/**************************************************************************
214 * Netlink Messages 225 * Netlink Messages
@@ -453,12 +464,13 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb,
453/** 464/**
454 * nlmsg_new - Allocate a new netlink message 465 * nlmsg_new - Allocate a new netlink message
455 * @size: maximum size of message 466 * @size: maximum size of message
467 * @flags: the type of memory to allocate.
456 * 468 *
457 * Use NLMSG_GOODSIZE if size isn't know and you need a good default size. 469 * Use NLMSG_GOODSIZE if size isn't know and you need a good default size.
458 */ 470 */
459static inline struct sk_buff *nlmsg_new(int size) 471static 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 @@ static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh)
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 */
500static 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 */
512static 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 * nlmsg_cancel - Cancel construction of a netlink message 521 * nlmsg_cancel - Cancel construction of a netlink message
484 * @skb: socket buffer the message is stored in 522 * @skb: socket buffer the message is stored in
485 * @nlh: netlink message header 523 * @nlh: netlink message header
@@ -489,9 +527,7 @@ static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh)
489 */ 527 */
490static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh) 528static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh)
491{ 529{
492 skb_trim(skb, (unsigned char *) nlh - skb->data); 530 return nlmsg_trim(skb, nlh);
493
494 return -1;
495} 531}
496 532
497/** 533/**
@@ -631,6 +667,18 @@ static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
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 */
676static 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 * nla_parse_nested - parse nested attributes 682 * nla_parse_nested - parse nested attributes
635 * @tb: destination array with maxtype+1 elements 683 * @tb: destination array with maxtype+1 elements
636 * @maxtype: maximum attribute type to be expected 684 * @maxtype: maximum attribute type to be expected
@@ -862,10 +910,7 @@ static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)
862 */ 910 */
863static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) 911static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
864{ 912{
865 if (start) 913 return nlmsg_trim(skb, start);
866 skb_trim(skb, (unsigned char *) start - skb->data);
867
868 return -1;
869} 914}
870 915
871/** 916/**
@@ -880,4 +925,13 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
880 nla_ok(pos, rem); \ 925 nla_ok(pos, rem); \
881 pos = nla_next(pos, &(rem))) 926 pos = nla_next(pos, &(rem)))
882 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)
936
883#endif 937#endif
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index e78187657330..2ed4040d0dc5 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -75,7 +75,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
75 /* 75 /*
76 * If new attributes are added, please revisit this allocation 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 if (!skb) 79 if (!skb)
80 return -ENOMEM; 80 return -ENOMEM;
81 81
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index dddbd15135a8..136e529e5780 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -255,6 +255,26 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
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 */
267void *__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 * nla_reserve - reserve room for attribute on the skb 278 * nla_reserve - reserve room for attribute on the skb
259 * @skb: socket buffer to reserve room on 279 * @skb: socket buffer to reserve room on
260 * @attrtype: attribute type 280 * @attrtype: attribute type
@@ -275,6 +295,24 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
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 */
307void *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 * __nla_put - Add a netlink attribute to a socket buffer 316 * __nla_put - Add a netlink attribute to a socket buffer
279 * @skb: socket buffer to add attribute to 317 * @skb: socket buffer to add attribute to
280 * @attrtype: attribute type 318 * @attrtype: attribute type
@@ -293,6 +331,22 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
293 memcpy(nla_data(nla), data, attrlen); 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 */
343void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data)
344{
345 void *start;
346
347 start = __nla_reserve_nohdr(skb, attrlen);
348 memcpy(start, data, attrlen);
349}
296 350
297/** 351/**
298 * nla_put - Add a netlink attribute to a socket buffer 352 * nla_put - Add a netlink attribute to a socket buffer
@@ -313,15 +367,36 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
313 return 0; 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 */
379int 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;
383
384 __nla_put_nohdr(skb, attrlen, data);
385 return 0;
386}
316 387
317EXPORT_SYMBOL(nla_validate); 388EXPORT_SYMBOL(nla_validate);
318EXPORT_SYMBOL(nla_parse); 389EXPORT_SYMBOL(nla_parse);
319EXPORT_SYMBOL(nla_find); 390EXPORT_SYMBOL(nla_find);
320EXPORT_SYMBOL(nla_strlcpy); 391EXPORT_SYMBOL(nla_strlcpy);
321EXPORT_SYMBOL(__nla_reserve); 392EXPORT_SYMBOL(__nla_reserve);
393EXPORT_SYMBOL(__nla_reserve_nohdr);
322EXPORT_SYMBOL(nla_reserve); 394EXPORT_SYMBOL(nla_reserve);
395EXPORT_SYMBOL(nla_reserve_nohdr);
323EXPORT_SYMBOL(__nla_put); 396EXPORT_SYMBOL(__nla_put);
397EXPORT_SYMBOL(__nla_put_nohdr);
324EXPORT_SYMBOL(nla_put); 398EXPORT_SYMBOL(nla_put);
399EXPORT_SYMBOL(nla_put_nohdr);
325EXPORT_SYMBOL(nla_memcpy); 400EXPORT_SYMBOL(nla_memcpy);
326EXPORT_SYMBOL(nla_memcmp); 401EXPORT_SYMBOL(nla_memcmp);
327EXPORT_SYMBOL(nla_strcmp); 402EXPORT_SYMBOL(nla_strcmp);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index a298f77cc3e3..75bb47a898dd 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -440,7 +440,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
440 struct sk_buff *skb; 440 struct sk_buff *skb;
441 int err; 441 int err;
442 442
443 skb = nlmsg_new(NLMSG_GOODSIZE); 443 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
444 if (skb == NULL) 444 if (skb == NULL)
445 return ERR_PTR(-ENOBUFS); 445 return ERR_PTR(-ENOBUFS);
446 446