aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/neighbour.h1
-rw-r--r--net/core/neighbour.c22
-rw-r--r--net/mpls/af_mpls.c35
3 files changed, 34 insertions, 24 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index afb8237b0a8c..d48b8ec8b5f4 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -226,6 +226,7 @@ enum {
226 NEIGH_ND_TABLE = 1, 226 NEIGH_ND_TABLE = 1,
227 NEIGH_DN_TABLE = 2, 227 NEIGH_DN_TABLE = 2,
228 NEIGH_NR_TABLES, 228 NEIGH_NR_TABLES,
229 NEIGH_LINK_TABLE = NEIGH_NR_TABLES /* Pseudo table for neigh_xmit */
229}; 230};
230 231
231static inline int neigh_parms_family(struct neigh_parms *p) 232static inline int neigh_parms_family(struct neigh_parms *p)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index cffaf00561e7..ad07990e943d 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2391,22 +2391,15 @@ void __neigh_for_each_release(struct neigh_table *tbl,
2391} 2391}
2392EXPORT_SYMBOL(__neigh_for_each_release); 2392EXPORT_SYMBOL(__neigh_for_each_release);
2393 2393
2394int neigh_xmit(int family, struct net_device *dev, 2394int neigh_xmit(int index, struct net_device *dev,
2395 const void *addr, struct sk_buff *skb) 2395 const void *addr, struct sk_buff *skb)
2396{ 2396{
2397 int err; 2397 int err = -EAFNOSUPPORT;
2398 if (family == AF_PACKET) { 2398 if (likely(index < NEIGH_NR_TABLES)) {
2399 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2400 addr, NULL, skb->len);
2401 if (err < 0)
2402 goto out_kfree_skb;
2403 err = dev_queue_xmit(skb);
2404 } else {
2405 struct neigh_table *tbl; 2399 struct neigh_table *tbl;
2406 struct neighbour *neigh; 2400 struct neighbour *neigh;
2407 2401
2408 err = -ENETDOWN; 2402 tbl = neigh_tables[index];
2409 tbl = neigh_find_table(family);
2410 if (!tbl) 2403 if (!tbl)
2411 goto out; 2404 goto out;
2412 neigh = __neigh_lookup_noref(tbl, addr, dev); 2405 neigh = __neigh_lookup_noref(tbl, addr, dev);
@@ -2417,6 +2410,13 @@ int neigh_xmit(int family, struct net_device *dev,
2417 goto out_kfree_skb; 2410 goto out_kfree_skb;
2418 err = neigh->output(neigh, skb); 2411 err = neigh->output(neigh, skb);
2419 } 2412 }
2413 else if (index == NEIGH_LINK_TABLE) {
2414 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2415 addr, NULL, skb->len);
2416 if (err < 0)
2417 goto out_kfree_skb;
2418 err = dev_queue_xmit(skb);
2419 }
2420out: 2420out:
2421 return err; 2421 return err;
2422out_kfree_skb: 2422out_kfree_skb:
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] = {
225struct mpls_route_config { 225struct 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
450static int nla_put_via(struct sk_buff *skb, 450static 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