diff options
Diffstat (limited to 'net/mpls/af_mpls.c')
-rw-r--r-- | net/mpls/af_mpls.c | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index c70d750148b6..c32fc411a911 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c | |||
@@ -27,6 +27,8 @@ | |||
27 | */ | 27 | */ |
28 | #define MAX_MP_SELECT_LABELS 4 | 28 | #define MAX_MP_SELECT_LABELS 4 |
29 | 29 | ||
30 | #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1) | ||
31 | |||
30 | static int zero = 0; | 32 | static int zero = 0; |
31 | static int label_limit = (1 << 20) - 1; | 33 | static int label_limit = (1 << 20) - 1; |
32 | 34 | ||
@@ -317,7 +319,13 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, | |||
317 | } | 319 | } |
318 | } | 320 | } |
319 | 321 | ||
320 | err = neigh_xmit(nh->nh_via_table, out_dev, mpls_nh_via(rt, nh), skb); | 322 | /* If via wasn't specified then send out using device address */ |
323 | if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC) | ||
324 | err = neigh_xmit(NEIGH_LINK_TABLE, out_dev, | ||
325 | out_dev->dev_addr, skb); | ||
326 | else | ||
327 | err = neigh_xmit(nh->nh_via_table, out_dev, | ||
328 | mpls_nh_via(rt, nh), skb); | ||
321 | if (err) | 329 | if (err) |
322 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", | 330 | net_dbg_ratelimited("%s: packet transmission failed: %d\n", |
323 | __func__, err); | 331 | __func__, err); |
@@ -534,6 +542,10 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt, | |||
534 | if (!mpls_dev_get(dev)) | 542 | if (!mpls_dev_get(dev)) |
535 | goto errout; | 543 | goto errout; |
536 | 544 | ||
545 | if ((nh->nh_via_table == NEIGH_LINK_TABLE) && | ||
546 | (dev->addr_len != nh->nh_via_alen)) | ||
547 | goto errout; | ||
548 | |||
537 | RCU_INIT_POINTER(nh->nh_dev, dev); | 549 | RCU_INIT_POINTER(nh->nh_dev, dev); |
538 | 550 | ||
539 | return 0; | 551 | return 0; |
@@ -592,10 +604,14 @@ static int mpls_nh_build(struct net *net, struct mpls_route *rt, | |||
592 | goto errout; | 604 | goto errout; |
593 | } | 605 | } |
594 | 606 | ||
595 | err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table, | 607 | if (via) { |
596 | __mpls_nh_via(rt, nh)); | 608 | err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table, |
597 | if (err) | 609 | __mpls_nh_via(rt, nh)); |
598 | goto errout; | 610 | if (err) |
611 | goto errout; | ||
612 | } else { | ||
613 | nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC; | ||
614 | } | ||
599 | 615 | ||
600 | err = mpls_nh_assign_dev(net, rt, nh, oif); | 616 | err = mpls_nh_assign_dev(net, rt, nh, oif); |
601 | if (err) | 617 | if (err) |
@@ -677,9 +693,6 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg, | |||
677 | nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST); | 693 | nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST); |
678 | } | 694 | } |
679 | 695 | ||
680 | if (!nla_via) | ||
681 | goto errout; | ||
682 | |||
683 | err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh, | 696 | err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh, |
684 | rtnh->rtnh_ifindex, nla_via, | 697 | rtnh->rtnh_ifindex, nla_via, |
685 | nla_newdst); | 698 | nla_newdst); |
@@ -1118,6 +1131,7 @@ static int rtm_to_route_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1118 | 1131 | ||
1119 | cfg->rc_label = LABEL_NOT_SPECIFIED; | 1132 | cfg->rc_label = LABEL_NOT_SPECIFIED; |
1120 | cfg->rc_protocol = rtm->rtm_protocol; | 1133 | cfg->rc_protocol = rtm->rtm_protocol; |
1134 | cfg->rc_via_table = MPLS_NEIGH_TABLE_UNSPEC; | ||
1121 | cfg->rc_nlflags = nlh->nlmsg_flags; | 1135 | cfg->rc_nlflags = nlh->nlmsg_flags; |
1122 | cfg->rc_nlinfo.portid = NETLINK_CB(skb).portid; | 1136 | cfg->rc_nlinfo.portid = NETLINK_CB(skb).portid; |
1123 | cfg->rc_nlinfo.nlh = nlh; | 1137 | cfg->rc_nlinfo.nlh = nlh; |
@@ -1231,7 +1245,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
1231 | nla_put_labels(skb, RTA_NEWDST, nh->nh_labels, | 1245 | nla_put_labels(skb, RTA_NEWDST, nh->nh_labels, |
1232 | nh->nh_label)) | 1246 | nh->nh_label)) |
1233 | goto nla_put_failure; | 1247 | goto nla_put_failure; |
1234 | if (nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), | 1248 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC && |
1249 | nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), | ||
1235 | nh->nh_via_alen)) | 1250 | nh->nh_via_alen)) |
1236 | goto nla_put_failure; | 1251 | goto nla_put_failure; |
1237 | dev = rtnl_dereference(nh->nh_dev); | 1252 | dev = rtnl_dereference(nh->nh_dev); |
@@ -1257,7 +1272,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, | |||
1257 | nh->nh_labels, | 1272 | nh->nh_labels, |
1258 | nh->nh_label)) | 1273 | nh->nh_label)) |
1259 | goto nla_put_failure; | 1274 | goto nla_put_failure; |
1260 | if (nla_put_via(skb, nh->nh_via_table, | 1275 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC && |
1276 | nla_put_via(skb, nh->nh_via_table, | ||
1261 | mpls_nh_via(rt, nh), | 1277 | mpls_nh_via(rt, nh), |
1262 | nh->nh_via_alen)) | 1278 | nh->nh_via_alen)) |
1263 | goto nla_put_failure; | 1279 | goto nla_put_failure; |
@@ -1319,7 +1335,8 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt) | |||
1319 | 1335 | ||
1320 | if (nh->nh_dev) | 1336 | if (nh->nh_dev) |
1321 | payload += nla_total_size(4); /* RTA_OIF */ | 1337 | payload += nla_total_size(4); /* RTA_OIF */ |
1322 | payload += nla_total_size(2 + nh->nh_via_alen); /* RTA_VIA */ | 1338 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) /* RTA_VIA */ |
1339 | payload += nla_total_size(2 + nh->nh_via_alen); | ||
1323 | if (nh->nh_labels) /* RTA_NEWDST */ | 1340 | if (nh->nh_labels) /* RTA_NEWDST */ |
1324 | payload += nla_total_size(nh->nh_labels * 4); | 1341 | payload += nla_total_size(nh->nh_labels * 4); |
1325 | } else { | 1342 | } else { |
@@ -1328,7 +1345,9 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt) | |||
1328 | 1345 | ||
1329 | for_nexthops(rt) { | 1346 | for_nexthops(rt) { |
1330 | nhsize += nla_total_size(sizeof(struct rtnexthop)); | 1347 | nhsize += nla_total_size(sizeof(struct rtnexthop)); |
1331 | nhsize += nla_total_size(2 + nh->nh_via_alen); | 1348 | /* RTA_VIA */ |
1349 | if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) | ||
1350 | nhsize += nla_total_size(2 + nh->nh_via_alen); | ||
1332 | if (nh->nh_labels) | 1351 | if (nh->nh_labels) |
1333 | nhsize += nla_total_size(nh->nh_labels * 4); | 1352 | nhsize += nla_total_size(nh->nh_labels * 4); |
1334 | } endfor_nexthops(rt); | 1353 | } endfor_nexthops(rt); |