summaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-11-10 14:10:15 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-02 21:22:11 -0800
commit339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68 (patch)
tree499ad948863d2753ca10283dcf006ad28954538e /net/ipv6
parenta94f723d595ee085f81b1788d18e031af7eeba91 (diff)
downloadlinux-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/ipv6')
-rw-r--r--net/ipv6/addrconf.c70
-rw-r--r--net/ipv6/fib6_rules.c7
-rw-r--r--net/ipv6/route.c23
3 files changed, 56 insertions, 44 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6a98f68348cb..967ea320a9ca 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope)
static inline int inet6_ifaddr_msgsize(void)
{
- return nlmsg_total_size(sizeof(struct ifaddrmsg) +
- nla_total_size(16) +
- nla_total_size(sizeof(struct ifa_cacheinfo)) +
- 128);
+ return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+ + nla_total_size(16) /* IFA_ADDRESS */
+ + nla_total_size(sizeof(struct ifa_cacheinfo));
}
static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3329,10 +3328,8 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, RTM_NEWADDR, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout_ifa;
- }
+ /* failure implies BUG in inet6_ifaddr_msgsize() */
+ BUG_ON(err < 0);
err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
errout_ifa:
@@ -3351,10 +3348,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
goto errout;
err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet6_ifaddr_msgsize() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
errout:
@@ -3397,16 +3392,19 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
}
-/* Maximum length of ifinfomsg attributes */
-#define INET6_IFINFO_RTA_SPACE \
- RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
- RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \
- RTA_SPACE(sizeof(u32)) /* MTU */ + \
- RTA_SPACE(sizeof(int)) /* LINK */ + \
- RTA_SPACE(0) /* PROTINFO */ + \
- RTA_SPACE(sizeof(u32)) /* FLAGS */ + \
- RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \
- RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */
+static inline size_t inet6_if_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+ + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+ + nla_total_size(4) /* IFLA_MTU */
+ + nla_total_size(4) /* IFLA_LINK */
+ + nla_total_size( /* IFLA_PROTINFO */
+ nla_total_size(4) /* IFLA_INET6_FLAGS */
+ + nla_total_size(sizeof(struct ifla_cacheinfo))
+ + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
+ );
+}
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
u32 pid, u32 seq, int event, unsigned int flags)
@@ -3501,18 +3499,15 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
{
struct sk_buff *skb;
- int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE;
int err = -ENOBUFS;
- skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
+ skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet6_if_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
errout:
@@ -3520,10 +3515,12 @@ errout:
rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
}
-/* Maximum length of prefix_cacheinfo attributes */
-#define INET6_PREFIX_RTA_SPACE \
- RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \
- RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */
+static inline size_t inet6_prefix_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct prefixmsg))
+ + nla_total_size(sizeof(struct in6_addr))
+ + nla_total_size(sizeof(struct prefix_cacheinfo));
+}
static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
struct prefix_info *pinfo, u32 pid, u32 seq,
@@ -3569,18 +3566,15 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
struct prefix_info *pinfo)
{
struct sk_buff *skb;
- int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE;
int err = -ENOBUFS;
- skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC);
+ skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL)
goto errout;
err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in inet6_prefix_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
errout:
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 25804cb69cf0..d587dde5897e 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -232,6 +232,12 @@ static u32 fib6_rule_default_pref(void)
return 0x3FFF;
}
+static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
+{
+ return nla_total_size(16) /* dst */
+ + nla_total_size(16); /* src */
+}
+
static struct fib_rules_ops fib6_rules_ops = {
.family = AF_INET6,
.rule_size = sizeof(struct fib6_rule),
@@ -241,6 +247,7 @@ static struct fib_rules_ops fib6_rules_ops = {
.compare = fib6_rule_compare,
.fill = fib6_rule_fill,
.default_pref = fib6_rule_default_pref,
+ .nlmsg_payload = fib6_rule_nlmsg_payload,
.nlgroup = RTNLGRP_IPV6_RULE,
.policy = fib6_rule_policy,
.rules_list = &fib6_rules,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ad07c9087a7..a6472cb9054c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2006,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
return ip6_route_add(&cfg);
}
+static inline size_t rt6_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(16) /* RTA_SRC */
+ + nla_total_size(16) /* RTA_DST */
+ + nla_total_size(16) /* RTA_GATEWAY */
+ + nla_total_size(16) /* RTA_PREFSRC */
+ + nla_total_size(4) /* RTA_TABLE */
+ + nla_total_size(4) /* RTA_IIF */
+ + nla_total_size(4) /* RTA_OIF */
+ + nla_total_size(4) /* RTA_PRIORITY */
+ + nla_total_size(sizeof(struct rta_cacheinfo));
+}
+
static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
struct in6_addr *dst, struct in6_addr *src,
int iif, int type, u32 pid, u32 seq,
@@ -2200,7 +2214,6 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
struct sk_buff *skb;
u32 pid = 0, seq = 0;
struct nlmsghdr *nlh = NULL;
- int payload = sizeof(struct rtmsg) + 256;
int err = -ENOBUFS;
if (info) {
@@ -2210,15 +2223,13 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
seq = nlh->nlmsg_seq;
}
- skb = nlmsg_new(nlmsg_total_size(payload), gfp_any());
+ skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
if (skb == NULL)
goto errout;
err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
- if (err < 0) {
- kfree_skb(skb);
- goto errout;
- }
+ /* failure implies BUG in rt6_nlmsg_size() */
+ BUG_ON(err < 0);
err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
errout: