diff options
| -rw-r--r-- | include/net/netlink.h | 74 | ||||
| -rw-r--r-- | kernel/taskstats.c | 2 | ||||
| -rw-r--r-- | net/netlink/attr.c | 75 | ||||
| -rw-r--r-- | net/netlink/genetlink.c | 2 |
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, | |||
| 203 | extern int nla_strcmp(const struct nlattr *nla, const char *str); | 208 | extern int nla_strcmp(const struct nlattr *nla, const char *str); |
| 204 | extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, | 209 | extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, |
| 205 | int attrlen); | 210 | int attrlen); |
| 211 | extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen); | ||
| 206 | extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, | 212 | extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, |
| 207 | int attrlen); | 213 | int attrlen); |
| 214 | extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen); | ||
| 208 | extern void __nla_put(struct sk_buff *skb, int attrtype, | 215 | extern void __nla_put(struct sk_buff *skb, int attrtype, |
| 209 | int attrlen, const void *data); | 216 | int attrlen, const void *data); |
| 217 | extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen, | ||
| 218 | const void *data); | ||
| 210 | extern int nla_put(struct sk_buff *skb, int attrtype, | 219 | extern int nla_put(struct sk_buff *skb, int attrtype, |
| 211 | int attrlen, const void *data); | 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 | * 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 | */ |
| 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 @@ 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 | */ | ||
| 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 | * 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 | */ |
| 490 | static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh) | 528 | static 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 | */ | ||
| 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 | * 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 | */ |
| 863 | static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) | 911 | static 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 | */ | ||
| 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 | * 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 | */ | ||
| 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 | * __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 | */ | ||
| 343 | void __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 | */ | ||
| 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; | ||
| 383 | |||
| 384 | __nla_put_nohdr(skb, attrlen, data); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 316 | 387 | ||
| 317 | EXPORT_SYMBOL(nla_validate); | 388 | EXPORT_SYMBOL(nla_validate); |
| 318 | EXPORT_SYMBOL(nla_parse); | 389 | EXPORT_SYMBOL(nla_parse); |
| 319 | EXPORT_SYMBOL(nla_find); | 390 | EXPORT_SYMBOL(nla_find); |
| 320 | EXPORT_SYMBOL(nla_strlcpy); | 391 | EXPORT_SYMBOL(nla_strlcpy); |
| 321 | EXPORT_SYMBOL(__nla_reserve); | 392 | EXPORT_SYMBOL(__nla_reserve); |
| 393 | EXPORT_SYMBOL(__nla_reserve_nohdr); | ||
| 322 | EXPORT_SYMBOL(nla_reserve); | 394 | EXPORT_SYMBOL(nla_reserve); |
| 395 | EXPORT_SYMBOL(nla_reserve_nohdr); | ||
| 323 | EXPORT_SYMBOL(__nla_put); | 396 | EXPORT_SYMBOL(__nla_put); |
| 397 | EXPORT_SYMBOL(__nla_put_nohdr); | ||
| 324 | EXPORT_SYMBOL(nla_put); | 398 | EXPORT_SYMBOL(nla_put); |
| 399 | EXPORT_SYMBOL(nla_put_nohdr); | ||
| 325 | EXPORT_SYMBOL(nla_memcpy); | 400 | EXPORT_SYMBOL(nla_memcpy); |
| 326 | EXPORT_SYMBOL(nla_memcmp); | 401 | EXPORT_SYMBOL(nla_memcmp); |
| 327 | EXPORT_SYMBOL(nla_strcmp); | 402 | EXPORT_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 | ||
