aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-11-10 17:10:15 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:22:11 -0500
commit339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68 (patch)
tree499ad948863d2753ca10283dcf006ad28954538e /net/core
parenta94f723d595ee085f81b1788d18e031af7eeba91 (diff)
[NETLINK]: Do precise netlink message allocations where possible
Account for the netlink message header size directly in nlmsg_new() instead of relying on the caller calculate it correctly. Replaces error handling of message construction functions when constructing notifications with bug traps since a failure implies a bug in calculating the size of the skb. Signed-off-by: Thomas Graf <tgraf@suug.ch> Acked-by: Paul Moore <paul.moore@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/fib_rules.c24
-rw-r--r--net/core/neighbour.c17
-rw-r--r--net/core/rtnetlink.c39
3 files changed, 57 insertions, 23 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 4148e274a204..1df6cd4568d3 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -306,6 +306,22 @@ errout:
306 return err; 306 return err;
307} 307}
308 308
309static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
310 struct fib_rule *rule)
311{
312 size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr))
313 + nla_total_size(IFNAMSIZ) /* FRA_IFNAME */
314 + nla_total_size(4) /* FRA_PRIORITY */
315 + nla_total_size(4) /* FRA_TABLE */
316 + nla_total_size(4) /* FRA_FWMARK */
317 + nla_total_size(4); /* FRA_FWMASK */
318
319 if (ops->nlmsg_payload)
320 payload += ops->nlmsg_payload(rule);
321
322 return payload;
323}
324
309static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, 325static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
310 u32 pid, u32 seq, int type, int flags, 326 u32 pid, u32 seq, int type, int flags,
311 struct fib_rules_ops *ops) 327 struct fib_rules_ops *ops)
@@ -384,15 +400,13 @@ static void notify_rule_change(int event, struct fib_rule *rule,
384 struct sk_buff *skb; 400 struct sk_buff *skb;
385 int err = -ENOBUFS; 401 int err = -ENOBUFS;
386 402
387 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 403 skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL);
388 if (skb == NULL) 404 if (skb == NULL)
389 goto errout; 405 goto errout;
390 406
391 err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); 407 err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
392 if (err < 0) { 408 /* failure implies BUG in fib_rule_nlmsg_size() */
393 kfree_skb(skb); 409 BUG_ON(err < 0);
394 goto errout;
395 }
396 410
397 err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); 411 err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
398errout: 412errout:
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b4b478353b27..0e097ba14d73 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2410,20 +2410,27 @@ static struct file_operations neigh_stat_seq_fops = {
2410#endif /* CONFIG_PROC_FS */ 2410#endif /* CONFIG_PROC_FS */
2411 2411
2412#ifdef CONFIG_ARPD 2412#ifdef CONFIG_ARPD
2413static inline size_t neigh_nlmsg_size(void)
2414{
2415 return NLMSG_ALIGN(sizeof(struct ndmsg))
2416 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2417 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2418 + nla_total_size(sizeof(struct nda_cacheinfo))
2419 + nla_total_size(4); /* NDA_PROBES */
2420}
2421
2413static void __neigh_notify(struct neighbour *n, int type, int flags) 2422static void __neigh_notify(struct neighbour *n, int type, int flags)
2414{ 2423{
2415 struct sk_buff *skb; 2424 struct sk_buff *skb;
2416 int err = -ENOBUFS; 2425 int err = -ENOBUFS;
2417 2426
2418 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); 2427 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
2419 if (skb == NULL) 2428 if (skb == NULL)
2420 goto errout; 2429 goto errout;
2421 2430
2422 err = neigh_fill_info(skb, n, 0, 0, type, flags); 2431 err = neigh_fill_info(skb, n, 0, 0, type, flags);
2423 if (err < 0) { 2432 /* failure implies BUG in neigh_nlmsg_size() */
2424 kfree_skb(skb); 2433 BUG_ON(err < 0);
2425 goto errout;
2426 }
2427 2434
2428 err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); 2435 err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2429errout: 2436errout:
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 02f3c7947898..50d6cb40c6e3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -273,6 +273,25 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
273 a->tx_compressed = b->tx_compressed; 273 a->tx_compressed = b->tx_compressed;
274}; 274};
275 275
276static inline size_t if_nlmsg_size(int iwbuflen)
277{
278 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
279 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
280 + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */
281 + nla_total_size(sizeof(struct rtnl_link_ifmap))
282 + nla_total_size(sizeof(struct rtnl_link_stats))
283 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
284 + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */
285 + nla_total_size(4) /* IFLA_TXQLEN */
286 + nla_total_size(4) /* IFLA_WEIGHT */
287 + nla_total_size(4) /* IFLA_MTU */
288 + nla_total_size(4) /* IFLA_LINK */
289 + nla_total_size(4) /* IFLA_MASTER */
290 + nla_total_size(1) /* IFLA_OPERSTATE */
291 + nla_total_size(1) /* IFLA_LINKMODE */
292 + nla_total_size(iwbuflen);
293}
294
276static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 295static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
277 void *iwbuf, int iwbuflen, int type, u32 pid, 296 void *iwbuf, int iwbuflen, int type, u32 pid,
278 u32 seq, u32 change, unsigned int flags) 297 u32 seq, u32 change, unsigned int flags)
@@ -558,7 +577,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
558 struct sk_buff *nskb; 577 struct sk_buff *nskb;
559 char *iw_buf = NULL, *iw = NULL; 578 char *iw_buf = NULL, *iw = NULL;
560 int iw_buf_len = 0; 579 int iw_buf_len = 0;
561 int err, payload; 580 int err;
562 581
563 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); 582 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
564 if (err < 0) 583 if (err < 0)
@@ -587,9 +606,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
587 } 606 }
588#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ 607#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
589 608
590 payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) + 609 nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
591 nla_total_size(iw_buf_len));
592 nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL);
593 if (nskb == NULL) { 610 if (nskb == NULL) {
594 err = -ENOBUFS; 611 err = -ENOBUFS;
595 goto errout; 612 goto errout;
@@ -597,10 +614,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
597 614
598 err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK, 615 err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
599 NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0); 616 NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
600 if (err <= 0) { 617 /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
601 kfree_skb(nskb); 618 BUG_ON(err < 0);
602 goto errout;
603 }
604 619
605 err = rtnl_unicast(nskb, NETLINK_CB(skb).pid); 620 err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
606errout: 621errout:
@@ -639,15 +654,13 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
639 struct sk_buff *skb; 654 struct sk_buff *skb;
640 int err = -ENOBUFS; 655 int err = -ENOBUFS;
641 656
642 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 657 skb = nlmsg_new(if_nlmsg_size(0), GFP_KERNEL);
643 if (skb == NULL) 658 if (skb == NULL)
644 goto errout; 659 goto errout;
645 660
646 err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0); 661 err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
647 if (err < 0) { 662 /* failure implies BUG in if_nlmsg_size() */
648 kfree_skb(skb); 663 BUG_ON(err < 0);
649 goto errout;
650 }
651 664
652 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); 665 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
653errout: 666errout: