| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 621e84d commit 5e6700b
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,6 +42,7 @@ struct ip_tunnel { | |||
| 42 | 42 | struct ip_tunnel __rcu *next; | |
| 43 | 43 | struct hlist_node hash_node; | |
| 44 | 44 | struct net_device *dev; | |
| 45 | + struct net *net; /* netns for packet i/o */ | ||
| 45 | 46 | ||
| 46 | 47 | int err_count; /* Number of arrived ICMP errors */ | |
| 47 | 48 | unsigned long err_time; /* Time when the last ICMP error | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -304,6 +304,7 @@ static struct net_device *__ip_tunnel_create(struct net *net, | |||
| 304 | 304 | ||
| 305 | 305 | tunnel = netdev_priv(dev); | |
| 306 | 306 | tunnel->parms = *parms; | |
| 307 | + tunnel->net = net; | ||
| 307 | 308 | ||
| 308 | 309 | err = register_netdevice(dev); | |
| 309 | 310 | if (err) | |
@@ -453,6 +454,9 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, | |||
| 453 | 454 | tstats->rx_bytes += skb->len; | |
| 454 | 455 | u64_stats_update_end(&tstats->syncp); | |
| 455 | 456 | ||
| 457 | + if (tunnel->net != dev_net(tunnel->dev)) | ||
| 458 | + skb_scrub_packet(skb); | ||
| 459 | + | ||
| 456 | 460 | if (tunnel->dev->type == ARPHRD_ETHER) { | |
| 457 | 461 | skb->protocol = eth_type_trans(skb, tunnel->dev); | |
| 458 | 462 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | |
@@ -541,7 +545,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 541 | 545 | tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); | |
| 542 | 546 | } | |
| 543 | 547 | ||
| 544 | - rt = ip_route_output_tunnel(dev_net(dev), &fl4, | ||
| 548 | + rt = ip_route_output_tunnel(tunnel->net, &fl4, | ||
| 545 | 549 | protocol, | |
| 546 | 550 | dst, tnl_params->saddr, | |
| 547 | 551 | tunnel->parms.o_key, | |
@@ -602,6 +606,9 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 602 | 606 | } | |
| 603 | 607 | #endif | |
| 604 | 608 | ||
| 609 | + if (tunnel->net != dev_net(dev)) | ||
| 610 | + skb_scrub_packet(skb); | ||
| 611 | + | ||
| 605 | 612 | if (tunnel->err_count > 0) { | |
| 606 | 613 | if (time_before(jiffies, | |
| 607 | 614 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | |
@@ -888,6 +895,7 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], | |||
| 888 | 895 | if (ip_tunnel_find(itn, p, dev->type)) | |
| 889 | 896 | return -EEXIST; | |
| 890 | 897 | ||
| 898 | + nt->net = net; | ||
| 891 | 899 | nt->parms = *p; | |
| 892 | 900 | err = register_netdevice(dev); | |
| 893 | 901 | if (err) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -466,14 +466,14 @@ isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) | |||
| 466 | 466 | ||
| 467 | 467 | static void ipip6_tunnel_uninit(struct net_device *dev) | |
| 468 | 468 | { | |
| 469 | - struct net *net = dev_net(dev); | ||
| 470 | - struct sit_net *sitn = net_generic(net, sit_net_id); | ||
| 469 | + struct ip_tunnel *tunnel = netdev_priv(dev); | ||
| 470 | + struct sit_net *sitn = net_generic(tunnel->net, sit_net_id); | ||
| 471 | 471 | ||
| 472 | 472 | if (dev == sitn->fb_tunnel_dev) { | |
| 473 | 473 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); | |
| 474 | 474 | } else { | |
| 475 | - ipip6_tunnel_unlink(sitn, netdev_priv(dev)); | ||
| 476 | - ipip6_tunnel_del_prl(netdev_priv(dev), NULL); | ||
| 475 | + ipip6_tunnel_unlink(sitn, tunnel); | ||
| 476 | + ipip6_tunnel_del_prl(tunnel, NULL); | ||
| 477 | 477 | } | |
| 478 | 478 | dev_put(dev); | |
| 479 | 479 | } | |
@@ -621,6 +621,8 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
| 621 | 621 | tstats->rx_packets++; | |
| 622 | 622 | tstats->rx_bytes += skb->len; | |
| 623 | 623 | ||
| 624 | + if (tunnel->net != dev_net(tunnel->dev)) | ||
| 625 | + skb_scrub_packet(skb); | ||
| 624 | 626 | netif_rx(skb); | |
| 625 | 627 | ||
| 626 | 628 | return 0; | |
@@ -803,7 +805,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 803 | 805 | goto tx_error; | |
| 804 | 806 | } | |
| 805 | 807 | ||
| 806 | - rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, | ||
| 808 | + rt = ip_route_output_ports(tunnel->net, &fl4, NULL, | ||
| 807 | 809 | dst, tiph->saddr, | |
| 808 | 810 | 0, 0, | |
| 809 | 811 | IPPROTO_IPV6, RT_TOS(tos), | |
@@ -858,6 +860,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 858 | 860 | tunnel->err_count = 0; | |
| 859 | 861 | } | |
| 860 | 862 | ||
| 863 | + if (tunnel->net != dev_net(dev)) | ||
| 864 | + skb_scrub_packet(skb); | ||
| 865 | + | ||
| 861 | 866 | /* | |
| 862 | 867 | * Okay, now see if we can stuff it in the buffer as-is. | |
| 863 | 868 | */ | |
@@ -944,7 +949,8 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
| 944 | 949 | iph = &tunnel->parms.iph; | |
| 945 | 950 | ||
| 946 | 951 | if (iph->daddr) { | |
| 947 | - struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, | ||
| 952 | + struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4, | ||
| 953 | + NULL, | ||
| 948 | 954 | iph->daddr, iph->saddr, | |
| 949 | 955 | 0, 0, | |
| 950 | 956 | IPPROTO_IPV6, | |
@@ -959,7 +965,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
| 959 | 965 | } | |
| 960 | 966 | ||
| 961 | 967 | if (!tdev && tunnel->parms.link) | |
| 962 | - tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); | ||
| 968 | + tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); | ||
| 963 | 969 | ||
| 964 | 970 | if (tdev) { | |
| 965 | 971 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | |
@@ -972,7 +978,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
| 972 | 978 | ||
| 973 | 979 | static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | |
| 974 | 980 | { | |
| 975 | - struct net *net = dev_net(t->dev); | ||
| 981 | + struct net *net = t->net; | ||
| 976 | 982 | struct sit_net *sitn = net_generic(net, sit_net_id); | |
| 977 | 983 | ||
| 978 | 984 | ipip6_tunnel_unlink(sitn, t); | |
@@ -1248,7 +1254,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
| 1248 | 1254 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | |
| 1249 | 1255 | dev->iflink = 0; | |
| 1250 | 1256 | dev->addr_len = 4; | |
| 1251 | - dev->features |= NETIF_F_NETNS_LOCAL; | ||
| 1252 | 1257 | dev->features |= NETIF_F_LLTX; | |
| 1253 | 1258 | } | |
| 1254 | 1259 | ||
@@ -1257,6 +1262,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
| 1257 | 1262 | struct ip_tunnel *tunnel = netdev_priv(dev); | |
| 1258 | 1263 | ||
| 1259 | 1264 | tunnel->dev = dev; | |
| 1265 | + tunnel->net = dev_net(dev); | ||
| 1260 | 1266 | ||
| 1261 | 1267 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | |
| 1262 | 1268 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | |
@@ -1277,6 +1283,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1277 | 1283 | struct sit_net *sitn = net_generic(net, sit_net_id); | |
| 1278 | 1284 | ||
| 1279 | 1285 | tunnel->dev = dev; | |
| 1286 | + tunnel->net = dev_net(dev); | ||
| 1280 | 1287 | strcpy(tunnel->parms.name, dev->name); | |
| 1281 | 1288 | ||
| 1282 | 1289 | iph->version = 4; | |
@@ -1564,16 +1571,27 @@ static struct xfrm_tunnel ipip_handler __read_mostly = { | |||
| 1564 | 1571 | ||
| 1565 | 1572 | static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) | |
| 1566 | 1573 | { | |
| 1574 | + struct net *net = dev_net(sitn->fb_tunnel_dev); | ||
| 1575 | + struct net_device *dev, *aux; | ||
| 1567 | 1576 | int prio; | |
| 1568 | 1577 | ||
| 1578 | + for_each_netdev_safe(net, dev, aux) | ||
| 1579 | + if (dev->rtnl_link_ops == &sit_link_ops) | ||
| 1580 | + unregister_netdevice_queue(dev, head); | ||
| 1581 | + | ||
| 1569 | 1582 | for (prio = 1; prio < 4; prio++) { | |
| 1570 | 1583 | int h; | |
| 1571 | 1584 | for (h = 0; h < HASH_SIZE; h++) { | |
| 1572 | 1585 | struct ip_tunnel *t; | |
| 1573 | 1586 | ||
| 1574 | 1587 | t = rtnl_dereference(sitn->tunnels[prio][h]); | |
| 1575 | 1588 | while (t != NULL) { | |
| 1576 | - unregister_netdevice_queue(t->dev, head); | ||
| 1589 | + /* If dev is in the same netns, it has already | ||
| 1590 | + * been added to the list by the previous loop. | ||
| 1591 | + */ | ||
| 1592 | + if (dev_net(t->dev) != net) | ||
| 1593 | + unregister_netdevice_queue(t->dev, | ||
| 1594 | + head); | ||
| 1577 | 1595 | t = rtnl_dereference(t->next); | |
| 1578 | 1596 | } | |
| 1579 | 1597 | } | |
@@ -1598,6 +1616,10 @@ static int __net_init sit_init_net(struct net *net) | |||
| 1598 | 1616 | goto err_alloc_dev; | |
| 1599 | 1617 | } | |
| 1600 | 1618 | dev_net_set(sitn->fb_tunnel_dev, net); | |
| 1619 | + /* FB netdevice is special: we have one, and only one per netns. | ||
| 1620 | + * Allowing to move it to another netns is clearly unsafe. | ||
| 1621 | + */ | ||
| 1622 | + sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; | ||
| 1601 | 1623 | ||
| 1602 | 1624 | err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); | |
| 1603 | 1625 | if (err) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments