diff options
-rw-r--r-- | include/net/ip_tunnels.h | 1 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 10 | ||||
-rw-r--r-- | net/ipv6/sit.c | 42 |
3 files changed, 42 insertions, 11 deletions
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index b0d982471a5c..781b3cf86a2f 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
@@ -42,6 +42,7 @@ struct ip_tunnel { | |||
42 | struct ip_tunnel __rcu *next; | 42 | struct ip_tunnel __rcu *next; |
43 | struct hlist_node hash_node; | 43 | struct hlist_node hash_node; |
44 | struct net_device *dev; | 44 | struct net_device *dev; |
45 | struct net *net; /* netns for packet i/o */ | ||
45 | 46 | ||
46 | int err_count; /* Number of arrived ICMP errors */ | 47 | int err_count; /* Number of arrived ICMP errors */ |
47 | unsigned long err_time; /* Time when the last ICMP error | 48 | unsigned long err_time; /* Time when the last ICMP error |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 3b00d81c8f1e..394cebc96d22 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -304,6 +304,7 @@ static struct net_device *__ip_tunnel_create(struct net *net, | |||
304 | 304 | ||
305 | tunnel = netdev_priv(dev); | 305 | tunnel = netdev_priv(dev); |
306 | tunnel->parms = *parms; | 306 | tunnel->parms = *parms; |
307 | tunnel->net = net; | ||
307 | 308 | ||
308 | err = register_netdevice(dev); | 309 | err = register_netdevice(dev); |
309 | if (err) | 310 | if (err) |
@@ -453,6 +454,9 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, | |||
453 | tstats->rx_bytes += skb->len; | 454 | tstats->rx_bytes += skb->len; |
454 | u64_stats_update_end(&tstats->syncp); | 455 | u64_stats_update_end(&tstats->syncp); |
455 | 456 | ||
457 | if (tunnel->net != dev_net(tunnel->dev)) | ||
458 | skb_scrub_packet(skb); | ||
459 | |||
456 | if (tunnel->dev->type == ARPHRD_ETHER) { | 460 | if (tunnel->dev->type == ARPHRD_ETHER) { |
457 | skb->protocol = eth_type_trans(skb, tunnel->dev); | 461 | skb->protocol = eth_type_trans(skb, tunnel->dev); |
458 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | 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 | tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); | 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 | protocol, | 549 | protocol, |
546 | dst, tnl_params->saddr, | 550 | dst, tnl_params->saddr, |
547 | tunnel->parms.o_key, | 551 | tunnel->parms.o_key, |
@@ -602,6 +606,9 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
602 | } | 606 | } |
603 | #endif | 607 | #endif |
604 | 608 | ||
609 | if (tunnel->net != dev_net(dev)) | ||
610 | skb_scrub_packet(skb); | ||
611 | |||
605 | if (tunnel->err_count > 0) { | 612 | if (tunnel->err_count > 0) { |
606 | if (time_before(jiffies, | 613 | if (time_before(jiffies, |
607 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { | 614 | tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { |
@@ -888,6 +895,7 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], | |||
888 | if (ip_tunnel_find(itn, p, dev->type)) | 895 | if (ip_tunnel_find(itn, p, dev->type)) |
889 | return -EEXIST; | 896 | return -EEXIST; |
890 | 897 | ||
898 | nt->net = net; | ||
891 | nt->parms = *p; | 899 | nt->parms = *p; |
892 | err = register_netdevice(dev); | 900 | err = register_netdevice(dev); |
893 | if (err) | 901 | if (err) |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index f639866b3dcf..97a0bfe2c293 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -466,14 +466,14 @@ isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) | |||
466 | 466 | ||
467 | static void ipip6_tunnel_uninit(struct net_device *dev) | 467 | static void ipip6_tunnel_uninit(struct net_device *dev) |
468 | { | 468 | { |
469 | struct net *net = dev_net(dev); | 469 | struct ip_tunnel *tunnel = netdev_priv(dev); |
470 | struct sit_net *sitn = net_generic(net, sit_net_id); | 470 | struct sit_net *sitn = net_generic(tunnel->net, sit_net_id); |
471 | 471 | ||
472 | if (dev == sitn->fb_tunnel_dev) { | 472 | if (dev == sitn->fb_tunnel_dev) { |
473 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); | 473 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); |
474 | } else { | 474 | } else { |
475 | ipip6_tunnel_unlink(sitn, netdev_priv(dev)); | 475 | ipip6_tunnel_unlink(sitn, tunnel); |
476 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); | 476 | ipip6_tunnel_del_prl(tunnel, NULL); |
477 | } | 477 | } |
478 | dev_put(dev); | 478 | dev_put(dev); |
479 | } | 479 | } |
@@ -621,6 +621,8 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
621 | tstats->rx_packets++; | 621 | tstats->rx_packets++; |
622 | tstats->rx_bytes += skb->len; | 622 | tstats->rx_bytes += skb->len; |
623 | 623 | ||
624 | if (tunnel->net != dev_net(tunnel->dev)) | ||
625 | skb_scrub_packet(skb); | ||
624 | netif_rx(skb); | 626 | netif_rx(skb); |
625 | 627 | ||
626 | return 0; | 628 | return 0; |
@@ -803,7 +805,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
803 | goto tx_error; | 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 | dst, tiph->saddr, | 809 | dst, tiph->saddr, |
808 | 0, 0, | 810 | 0, 0, |
809 | IPPROTO_IPV6, RT_TOS(tos), | 811 | IPPROTO_IPV6, RT_TOS(tos), |
@@ -858,6 +860,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
858 | tunnel->err_count = 0; | 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 | * Okay, now see if we can stuff it in the buffer as-is. | 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 | iph = &tunnel->parms.iph; | 949 | iph = &tunnel->parms.iph; |
945 | 950 | ||
946 | if (iph->daddr) { | 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 | iph->daddr, iph->saddr, | 954 | iph->daddr, iph->saddr, |
949 | 0, 0, | 955 | 0, 0, |
950 | IPPROTO_IPV6, | 956 | IPPROTO_IPV6, |
@@ -959,7 +965,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
959 | } | 965 | } |
960 | 966 | ||
961 | if (!tdev && tunnel->parms.link) | 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 | if (tdev) { | 970 | if (tdev) { |
965 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | 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 | static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) | 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 | struct sit_net *sitn = net_generic(net, sit_net_id); | 982 | struct sit_net *sitn = net_generic(net, sit_net_id); |
977 | 983 | ||
978 | ipip6_tunnel_unlink(sitn, t); | 984 | ipip6_tunnel_unlink(sitn, t); |
@@ -1248,7 +1254,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
1248 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 1254 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
1249 | dev->iflink = 0; | 1255 | dev->iflink = 0; |
1250 | dev->addr_len = 4; | 1256 | dev->addr_len = 4; |
1251 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
1252 | dev->features |= NETIF_F_LLTX; | 1257 | dev->features |= NETIF_F_LLTX; |
1253 | } | 1258 | } |
1254 | 1259 | ||
@@ -1257,6 +1262,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1257 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1262 | struct ip_tunnel *tunnel = netdev_priv(dev); |
1258 | 1263 | ||
1259 | tunnel->dev = dev; | 1264 | tunnel->dev = dev; |
1265 | tunnel->net = dev_net(dev); | ||
1260 | 1266 | ||
1261 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | 1267 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); |
1262 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 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 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1283 | struct sit_net *sitn = net_generic(net, sit_net_id); |
1278 | 1284 | ||
1279 | tunnel->dev = dev; | 1285 | tunnel->dev = dev; |
1286 | tunnel->net = dev_net(dev); | ||
1280 | strcpy(tunnel->parms.name, dev->name); | 1287 | strcpy(tunnel->parms.name, dev->name); |
1281 | 1288 | ||
1282 | iph->version = 4; | 1289 | iph->version = 4; |
@@ -1564,8 +1571,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = { | |||
1564 | 1571 | ||
1565 | static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) | 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 | int prio; | 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 | for (prio = 1; prio < 4; prio++) { | 1582 | for (prio = 1; prio < 4; prio++) { |
1570 | int h; | 1583 | int h; |
1571 | for (h = 0; h < HASH_SIZE; h++) { | 1584 | for (h = 0; h < HASH_SIZE; h++) { |
@@ -1573,7 +1586,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea | |||
1573 | 1586 | ||
1574 | t = rtnl_dereference(sitn->tunnels[prio][h]); | 1587 | t = rtnl_dereference(sitn->tunnels[prio][h]); |
1575 | while (t != NULL) { | 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 | t = rtnl_dereference(t->next); | 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 | goto err_alloc_dev; | 1616 | goto err_alloc_dev; |
1599 | } | 1617 | } |
1600 | dev_net_set(sitn->fb_tunnel_dev, net); | 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 | err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); | 1624 | err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); |
1603 | if (err) | 1625 | if (err) |