aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet/dn_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/decnet/dn_table.c')
-rw-r--r--net/decnet/dn_table.c42
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
266static 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
266static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 292static 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);
351errout: 375errout:
@@ -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;