diff options
Diffstat (limited to 'net/decnet/dn_table.c')
-rw-r--r-- | net/decnet/dn_table.c | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 650f3380c98a..16c986ab1228 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c | |||
@@ -297,61 +297,75 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
297 | { | 297 | { |
298 | struct rtmsg *rtm; | 298 | struct rtmsg *rtm; |
299 | struct nlmsghdr *nlh; | 299 | struct nlmsghdr *nlh; |
300 | unsigned char *b = skb_tail_pointer(skb); | ||
301 | 300 | ||
302 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags); | 301 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags); |
303 | rtm = NLMSG_DATA(nlh); | 302 | if (!nlh) |
303 | return -EMSGSIZE; | ||
304 | |||
305 | rtm = nlmsg_data(nlh); | ||
304 | rtm->rtm_family = AF_DECnet; | 306 | rtm->rtm_family = AF_DECnet; |
305 | rtm->rtm_dst_len = dst_len; | 307 | rtm->rtm_dst_len = dst_len; |
306 | rtm->rtm_src_len = 0; | 308 | rtm->rtm_src_len = 0; |
307 | rtm->rtm_tos = 0; | 309 | rtm->rtm_tos = 0; |
308 | rtm->rtm_table = tb_id; | 310 | rtm->rtm_table = tb_id; |
309 | RTA_PUT_U32(skb, RTA_TABLE, tb_id); | ||
310 | rtm->rtm_flags = fi->fib_flags; | 311 | rtm->rtm_flags = fi->fib_flags; |
311 | rtm->rtm_scope = scope; | 312 | rtm->rtm_scope = scope; |
312 | rtm->rtm_type = type; | 313 | rtm->rtm_type = type; |
313 | if (rtm->rtm_dst_len) | ||
314 | RTA_PUT(skb, RTA_DST, 2, dst); | ||
315 | rtm->rtm_protocol = fi->fib_protocol; | 314 | rtm->rtm_protocol = fi->fib_protocol; |
316 | if (fi->fib_priority) | 315 | |
317 | RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority); | 316 | if (nla_put_u32(skb, RTA_TABLE, tb_id) < 0) |
317 | goto errout; | ||
318 | |||
319 | if (rtm->rtm_dst_len && | ||
320 | nla_put(skb, RTA_DST, 2, dst) < 0) | ||
321 | goto errout; | ||
322 | |||
323 | if (fi->fib_priority && | ||
324 | nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority) < 0) | ||
325 | goto errout; | ||
326 | |||
318 | if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) | 327 | if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) |
319 | goto rtattr_failure; | 328 | goto errout; |
329 | |||
320 | if (fi->fib_nhs == 1) { | 330 | if (fi->fib_nhs == 1) { |
321 | if (fi->fib_nh->nh_gw) | 331 | if (fi->fib_nh->nh_gw && |
322 | RTA_PUT(skb, RTA_GATEWAY, 2, &fi->fib_nh->nh_gw); | 332 | nla_put_le16(skb, RTA_GATEWAY, fi->fib_nh->nh_gw) < 0) |
323 | if (fi->fib_nh->nh_oif) | 333 | goto errout; |
324 | RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif); | 334 | |
335 | if (fi->fib_nh->nh_oif && | ||
336 | nla_put_u32(skb, RTA_OIF, fi->fib_nh->nh_oif) < 0) | ||
337 | goto errout; | ||
325 | } | 338 | } |
339 | |||
326 | if (fi->fib_nhs > 1) { | 340 | if (fi->fib_nhs > 1) { |
327 | struct rtnexthop *nhp; | 341 | struct rtnexthop *nhp; |
328 | struct rtattr *mp_head; | 342 | struct nlattr *mp_head; |
329 | if (skb_tailroom(skb) <= RTA_SPACE(0)) | 343 | |
330 | goto rtattr_failure; | 344 | if (!(mp_head = nla_nest_start(skb, RTA_MULTIPATH))) |
331 | mp_head = (struct rtattr *)skb_put(skb, RTA_SPACE(0)); | 345 | goto errout; |
332 | 346 | ||
333 | for_nexthops(fi) { | 347 | for_nexthops(fi) { |
334 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) | 348 | if (!(nhp = nla_reserve_nohdr(skb, sizeof(*nhp)))) |
335 | goto rtattr_failure; | 349 | goto errout; |
336 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | 350 | |
337 | nhp->rtnh_flags = nh->nh_flags & 0xFF; | 351 | nhp->rtnh_flags = nh->nh_flags & 0xFF; |
338 | nhp->rtnh_hops = nh->nh_weight - 1; | 352 | nhp->rtnh_hops = nh->nh_weight - 1; |
339 | nhp->rtnh_ifindex = nh->nh_oif; | 353 | nhp->rtnh_ifindex = nh->nh_oif; |
340 | if (nh->nh_gw) | 354 | |
341 | RTA_PUT(skb, RTA_GATEWAY, 2, &nh->nh_gw); | 355 | if (nh->nh_gw && |
356 | nla_put_le16(skb, RTA_GATEWAY, nh->nh_gw) < 0) | ||
357 | goto errout; | ||
358 | |||
342 | nhp->rtnh_len = skb_tail_pointer(skb) - (unsigned char *)nhp; | 359 | nhp->rtnh_len = skb_tail_pointer(skb) - (unsigned char *)nhp; |
343 | } endfor_nexthops(fi); | 360 | } endfor_nexthops(fi); |
344 | mp_head->rta_type = RTA_MULTIPATH; | ||
345 | mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head; | ||
346 | } | ||
347 | 361 | ||
348 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 362 | nla_nest_end(skb, mp_head); |
349 | return skb->len; | 363 | } |
350 | 364 | ||
365 | return nlmsg_end(skb, nlh); | ||
351 | 366 | ||
352 | nlmsg_failure: | 367 | errout: |
353 | rtattr_failure: | 368 | nlmsg_cancel(skb, nlh); |
354 | nlmsg_trim(skb, b); | ||
355 | return -EMSGSIZE; | 369 | return -EMSGSIZE; |
356 | } | 370 | } |
357 | 371 | ||
@@ -476,7 +490,7 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
476 | return 0; | 490 | return 0; |
477 | 491 | ||
478 | if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && | 492 | if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && |
479 | ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED) | 493 | ((struct rtmsg *)nlmsg_data(cb->nlh))->rtm_flags&RTM_F_CLONED) |
480 | return dn_cache_dump(skb, cb); | 494 | return dn_cache_dump(skb, cb); |
481 | 495 | ||
482 | s_h = cb->args[0]; | 496 | s_h = cb->args[0]; |