diff options
Diffstat (limited to 'net/decnet/dn_table.c')
-rw-r--r-- | net/decnet/dn_table.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 317904bb5896..bdbc3f431668 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c | |||
@@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern | |||
263 | return 0; | 263 | return 0; |
264 | } | 264 | } |
265 | 265 | ||
266 | static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi) | ||
267 | { | ||
268 | size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg)) | ||
269 | + nla_total_size(4) /* RTA_TABLE */ | ||
270 | + nla_total_size(2) /* RTA_DST */ | ||
271 | + nla_total_size(4); /* RTA_PRIORITY */ | ||
272 | |||
273 | /* space for nested metrics */ | ||
274 | payload += nla_total_size((RTAX_MAX * nla_total_size(4))); | ||
275 | |||
276 | if (fi->fib_nhs) { | ||
277 | /* Also handles the special case fib_nhs == 1 */ | ||
278 | |||
279 | /* each nexthop is packed in an attribute */ | ||
280 | size_t nhsize = nla_total_size(sizeof(struct rtnexthop)); | ||
281 | |||
282 | /* may contain a gateway attribute */ | ||
283 | nhsize += nla_total_size(4); | ||
284 | |||
285 | /* all nexthops are packed in a nested attribute */ | ||
286 | payload += nla_total_size(fi->fib_nhs * nhsize); | ||
287 | } | ||
288 | |||
289 | return payload; | ||
290 | } | ||
291 | |||
266 | static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | 292 | static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, |
267 | u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, | 293 | u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, |
268 | struct dn_fib_info *fi, unsigned int flags) | 294 | struct dn_fib_info *fi, unsigned int flags) |
@@ -335,17 +361,15 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id, | |||
335 | u32 pid = req ? req->pid : 0; | 361 | u32 pid = req ? req->pid : 0; |
336 | int err = -ENOBUFS; | 362 | int err = -ENOBUFS; |
337 | 363 | ||
338 | skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | 364 | skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL); |
339 | if (skb == NULL) | 365 | if (skb == NULL) |
340 | goto errout; | 366 | goto errout; |
341 | 367 | ||
342 | err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, | 368 | err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, |
343 | f->fn_type, f->fn_scope, &f->fn_key, z, | 369 | f->fn_type, f->fn_scope, &f->fn_key, z, |
344 | DN_FIB_INFO(f), 0); | 370 | DN_FIB_INFO(f), 0); |
345 | if (err < 0) { | 371 | /* failure implies BUG in dn_fib_nlmsg_size() */ |
346 | kfree_skb(skb); | 372 | BUG_ON(err < 0); |
347 | goto errout; | ||
348 | } | ||
349 | 373 | ||
350 | err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); | 374 | err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); |
351 | errout: | 375 | errout: |
@@ -807,10 +831,11 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create) | |||
807 | printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n"); | 831 | printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n"); |
808 | return NULL; | 832 | return NULL; |
809 | } | 833 | } |
810 | if ((t = kmalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), GFP_KERNEL)) == NULL) | ||
811 | return NULL; | ||
812 | 834 | ||
813 | memset(t, 0, sizeof(struct dn_fib_table)); | 835 | t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), |
836 | GFP_KERNEL); | ||
837 | if (t == NULL) | ||
838 | return NULL; | ||
814 | 839 | ||
815 | t->n = n; | 840 | t->n = n; |
816 | t->insert = dn_fib_table_insert; | 841 | t->insert = dn_fib_table_insert; |
@@ -818,7 +843,6 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create) | |||
818 | t->lookup = dn_fib_table_lookup; | 843 | t->lookup = dn_fib_table_lookup; |
819 | t->flush = dn_fib_table_flush; | 844 | t->flush = dn_fib_table_flush; |
820 | t->dump = dn_fib_table_dump; | 845 | t->dump = dn_fib_table_dump; |
821 | memset(t->data, 0, sizeof(struct dn_hash)); | ||
822 | hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]); | 846 | hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]); |
823 | 847 | ||
824 | return t; | 848 | return t; |