diff options
Diffstat (limited to 'net/mpls/af_mpls.c')
-rw-r--r-- | net/mpls/af_mpls.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index e120074157de..0ad8f7141be2 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -28,9 +28,9 @@ struct mpls_route { /* next hop label forwarding entry */ | |||
28 | struct rcu_head rt_rcu; | 28 | struct rcu_head rt_rcu; |
29 | u32 rt_label[MAX_NEW_LABELS]; | 29 | u32 rt_label[MAX_NEW_LABELS]; |
30 | u8 rt_protocol; /* routing protocol that set this entry */ | 30 | u8 rt_protocol; /* routing protocol that set this entry */ |
31 | u8 rt_labels:2, | 31 | u8 rt_labels; |
32 | rt_via_alen:6; | 32 | u8 rt_via_alen; |
33 | unsigned short rt_via_family; | 33 | u8 rt_via_table; |
34 | u8 rt_via[0]; | 34 | u8 rt_via[0]; |
35 | }; | 35 | }; |
36 | 36 | ||
@@ -201,7 +201,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
201 | } | 201 | } |
202 | } | 202 | } |
203 | 203 | ||
204 | err = neigh_xmit(rt->rt_via_family, out_dev, rt->rt_via, skb); | 204 | err = neigh_xmit(rt->rt_via_table, out_dev, rt->rt_via, skb); |
205 | if (err) | 205 | if (err) |
206 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", | 206 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", |
207 | __func__, err); | 207 | __func__, err); |
@@ -225,7 +225,7 @@ static const struct nla_policy rtm_mpls_policy[RTA_MAX+1] = { | |||
225 | struct mpls_route_config { | 225 | struct mpls_route_config { |
226 | u32 rc_protocol; | 226 | u32 rc_protocol; |
227 | u32 rc_ifindex; | 227 | u32 rc_ifindex; |
228 | u16 rc_via_family; | 228 | u16 rc_via_table; |
229 | u16 rc_via_alen; | 229 | u16 rc_via_alen; |
230 | u8 rc_via[MAX_VIA_ALEN]; | 230 | u8 rc_via[MAX_VIA_ALEN]; |
231 | u32 rc_label; | 231 | u32 rc_label; |
@@ -343,7 +343,7 @@ static int mpls_route_add(struct mpls_route_config *cfg) | |||
343 | goto errout; | 343 | goto errout; |
344 | 344 | ||
345 | err = -EINVAL; | 345 | err = -EINVAL; |
346 | if ((cfg->rc_via_family == AF_PACKET) && | 346 | if ((cfg->rc_via_table == NEIGH_LINK_TABLE) && |
347 | (dev->addr_len != cfg->rc_via_alen)) | 347 | (dev->addr_len != cfg->rc_via_alen)) |
348 | goto errout; | 348 | goto errout; |
349 | 349 | ||
@@ -376,7 +376,7 @@ static int mpls_route_add(struct mpls_route_config *cfg) | |||
376 | rt->rt_label[i] = cfg->rc_output_label[i]; | 376 | rt->rt_label[i] = cfg->rc_output_label[i]; |
377 | rt->rt_protocol = cfg->rc_protocol; | 377 | rt->rt_protocol = cfg->rc_protocol; |
378 | RCU_INIT_POINTER(rt->rt_dev, dev); | 378 | RCU_INIT_POINTER(rt->rt_dev, dev); |
379 | rt->rt_via_family = cfg->rc_via_family; | 379 | rt->rt_via_table = cfg->rc_via_table; |
380 | memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen); | 380 | memcpy(rt->rt_via, cfg->rc_via, cfg->rc_via_alen); |
381 | 381 | ||
382 | mpls_route_update(net, index, NULL, rt, &cfg->rc_nlinfo); | 382 | mpls_route_update(net, index, NULL, rt, &cfg->rc_nlinfo); |
@@ -448,15 +448,22 @@ static struct notifier_block mpls_dev_notifier = { | |||
448 | }; | 448 | }; |
449 | 449 | ||
450 | static int nla_put_via(struct sk_buff *skb, | 450 | static int nla_put_via(struct sk_buff *skb, |
451 | u16 family, const void *addr, int alen) | 451 | u8 table, const void *addr, int alen) |
452 | { | 452 | { |
453 | static const int table_to_family[NEIGH_NR_TABLES + 1] = { | ||
454 | AF_INET, AF_INET6, AF_DECnet, AF_PACKET, | ||
455 | }; | ||
453 | struct nlattr *nla; | 456 | struct nlattr *nla; |
454 | struct rtvia *via; | 457 | struct rtvia *via; |
458 | int family = AF_UNSPEC; | ||
455 | 459 | ||
456 | nla = nla_reserve(skb, RTA_VIA, alen + 2); | 460 | nla = nla_reserve(skb, RTA_VIA, alen + 2); |
457 | if (!nla) | 461 | if (!nla) |
458 | return -EMSGSIZE; | 462 | return -EMSGSIZE; |
459 | 463 | ||
464 | if (table <= NEIGH_NR_TABLES) | ||
465 | family = table_to_family[table]; | ||
466 | |||
460 | via = nla_data(nla); | 467 | via = nla_data(nla); |
461 | via->rtvia_family = family; | 468 | via->rtvia_family = family; |
462 | memcpy(via->rtvia_addr, addr, alen); | 469 | memcpy(via->rtvia_addr, addr, alen); |
@@ -599,21 +606,23 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
599 | struct rtvia *via = nla_data(nla); | 606 | struct rtvia *via = nla_data(nla); |
600 | if (nla_len(nla) < offsetof(struct rtvia, rtvia_addr)) | 607 | if (nla_len(nla) < offsetof(struct rtvia, rtvia_addr)) |
601 | goto errout; | 608 | goto errout; |
602 | cfg->rc_via_family = via->rtvia_family; | ||
603 | cfg->rc_via_alen = nla_len(nla) - | 609 | cfg->rc_via_alen = nla_len(nla) - |
604 | offsetof(struct rtvia, rtvia_addr); | 610 | offsetof(struct rtvia, rtvia_addr); |
605 | if (cfg->rc_via_alen > MAX_VIA_ALEN) | 611 | if (cfg->rc_via_alen > MAX_VIA_ALEN) |
606 | goto errout; | 612 | goto errout; |
607 | 613 | ||
608 | /* Validate the address family */ | 614 | /* Validate the address family */ |
609 | switch(cfg->rc_via_family) { | 615 | switch(via->rtvia_family) { |
610 | case AF_PACKET: | 616 | case AF_PACKET: |
617 | cfg->rc_via_table = NEIGH_LINK_TABLE; | ||
611 | break; | 618 | break; |
612 | case AF_INET: | 619 | case AF_INET: |
620 | cfg->rc_via_table = NEIGH_ARP_TABLE; | ||
613 | if (cfg->rc_via_alen != 4) | 621 | if (cfg->rc_via_alen != 4) |
614 | goto errout; | 622 | goto errout; |
615 | break; | 623 | break; |
616 | case AF_INET6: | 624 | case AF_INET6: |
625 | cfg->rc_via_table = NEIGH_ND_TABLE; | ||
617 | if (cfg->rc_via_alen != 16) | 626 | if (cfg->rc_via_alen != 16) |
618 | goto errout; | 627 | goto errout; |
619 | break; | 628 | break; |
@@ -686,7 +695,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
686 | if (rt->rt_labels && | 695 | if (rt->rt_labels && |
687 | nla_put_labels(skb, RTA_NEWDST, rt->rt_labels, rt->rt_label)) | 696 | nla_put_labels(skb, RTA_NEWDST, rt->rt_labels, rt->rt_label)) |
688 | goto nla_put_failure; | 697 | goto nla_put_failure; |
689 | if (nla_put_via(skb, rt->rt_via_family, rt->rt_via, rt->rt_via_alen)) | 698 | if (nla_put_via(skb, rt->rt_via_table, rt->rt_via, rt->rt_via_alen)) |
690 | goto nla_put_failure; | 699 | goto nla_put_failure; |
691 | dev = rtnl_dereference(rt->rt_dev); | 700 | dev = rtnl_dereference(rt->rt_dev); |
692 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) | 701 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) |
@@ -799,7 +808,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
799 | goto nort0; | 808 | goto nort0; |
800 | RCU_INIT_POINTER(rt0->rt_dev, lo); | 809 | RCU_INIT_POINTER(rt0->rt_dev, lo); |
801 | rt0->rt_protocol = RTPROT_KERNEL; | 810 | rt0->rt_protocol = RTPROT_KERNEL; |
802 | rt0->rt_via_family = AF_PACKET; | 811 | rt0->rt_via_table = NEIGH_LINK_TABLE; |
803 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); | 812 | memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len); |
804 | } | 813 | } |
805 | if (limit > LABEL_IPV6_EXPLICIT_NULL) { | 814 | if (limit > LABEL_IPV6_EXPLICIT_NULL) { |
@@ -809,7 +818,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) | |||
809 | goto nort2; | 818 | goto nort2; |
810 | RCU_INIT_POINTER(rt2->rt_dev, lo); | 819 | RCU_INIT_POINTER(rt2->rt_dev, lo); |
811 | rt2->rt_protocol = RTPROT_KERNEL; | 820 | rt2->rt_protocol = RTPROT_KERNEL; |
812 | rt2->rt_via_family = AF_PACKET; | 821 | rt2->rt_via_table = NEIGH_LINK_TABLE; |
813 | memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len); | 822 | memcpy(rt2->rt_via, lo->dev_addr, lo->addr_len); |
814 | } | 823 | } |
815 | 824 | ||