diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-11-10 14:10:15 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-02 21:22:11 -0800 |
commit | 339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68 (patch) | |
tree | 499ad948863d2753ca10283dcf006ad28954538e /net/core/fib_rules.c | |
parent | a94f723d595ee085f81b1788d18e031af7eeba91 (diff) | |
download | kernel_samsung_crespo-339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68.zip kernel_samsung_crespo-339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68.tar.gz kernel_samsung_crespo-339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68.tar.bz2 |
[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/fib_rules.c')
-rw-r--r-- | net/core/fib_rules.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 4148e27..1df6cd45 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -306,6 +306,22 @@ errout: return err; } +static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops, + struct fib_rule *rule) +{ + size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr)) + + nla_total_size(IFNAMSIZ) /* FRA_IFNAME */ + + nla_total_size(4) /* FRA_PRIORITY */ + + nla_total_size(4) /* FRA_TABLE */ + + nla_total_size(4) /* FRA_FWMARK */ + + nla_total_size(4); /* FRA_FWMASK */ + + if (ops->nlmsg_payload) + payload += ops->nlmsg_payload(rule); + + return payload; +} + static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, u32 pid, u32 seq, int type, int flags, struct fib_rules_ops *ops) @@ -384,15 +400,13 @@ static void notify_rule_change(int event, struct fib_rule *rule, struct sk_buff *skb; int err = -ENOBUFS; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL); if (skb == NULL) goto errout; err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); - if (err < 0) { - kfree_skb(skb); - goto errout; - } + /* failure implies BUG in fib_rule_nlmsg_size() */ + BUG_ON(err < 0); err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); errout: |