diff options
Diffstat (limited to 'net/ipv6/ip6_tunnel.c')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 1e55866cead7..cc3bb201b8b0 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -315,6 +315,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) | |||
315 | 315 | ||
316 | t = netdev_priv(dev); | 316 | t = netdev_priv(dev); |
317 | t->parms = *p; | 317 | t->parms = *p; |
318 | t->net = dev_net(dev); | ||
318 | err = ip6_tnl_create2(dev); | 319 | err = ip6_tnl_create2(dev); |
319 | if (err < 0) | 320 | if (err < 0) |
320 | goto failed_free; | 321 | goto failed_free; |
@@ -374,7 +375,7 @@ static void | |||
374 | ip6_tnl_dev_uninit(struct net_device *dev) | 375 | ip6_tnl_dev_uninit(struct net_device *dev) |
375 | { | 376 | { |
376 | struct ip6_tnl *t = netdev_priv(dev); | 377 | struct ip6_tnl *t = netdev_priv(dev); |
377 | struct net *net = dev_net(dev); | 378 | struct net *net = t->net; |
378 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 379 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
379 | 380 | ||
380 | if (dev == ip6n->fb_tnl_dev) | 381 | if (dev == ip6n->fb_tnl_dev) |
@@ -741,7 +742,7 @@ int ip6_tnl_rcv_ctl(struct ip6_tnl *t, | |||
741 | { | 742 | { |
742 | struct __ip6_tnl_parm *p = &t->parms; | 743 | struct __ip6_tnl_parm *p = &t->parms; |
743 | int ret = 0; | 744 | int ret = 0; |
744 | struct net *net = dev_net(t->dev); | 745 | struct net *net = t->net; |
745 | 746 | ||
746 | if ((p->flags & IP6_TNL_F_CAP_RCV) || | 747 | if ((p->flags & IP6_TNL_F_CAP_RCV) || |
747 | ((p->flags & IP6_TNL_F_CAP_PER_PACKET) && | 748 | ((p->flags & IP6_TNL_F_CAP_PER_PACKET) && |
@@ -827,6 +828,9 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
827 | tstats->rx_packets++; | 828 | tstats->rx_packets++; |
828 | tstats->rx_bytes += skb->len; | 829 | tstats->rx_bytes += skb->len; |
829 | 830 | ||
831 | if (!net_eq(t->net, dev_net(t->dev))) | ||
832 | skb_scrub_packet(skb); | ||
833 | |||
830 | netif_rx(skb); | 834 | netif_rx(skb); |
831 | 835 | ||
832 | rcu_read_unlock(); | 836 | rcu_read_unlock(); |
@@ -895,7 +899,7 @@ int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | |||
895 | { | 899 | { |
896 | struct __ip6_tnl_parm *p = &t->parms; | 900 | struct __ip6_tnl_parm *p = &t->parms; |
897 | int ret = 0; | 901 | int ret = 0; |
898 | struct net *net = dev_net(t->dev); | 902 | struct net *net = t->net; |
899 | 903 | ||
900 | if (p->flags & IP6_TNL_F_CAP_XMIT) { | 904 | if (p->flags & IP6_TNL_F_CAP_XMIT) { |
901 | struct net_device *ldev = NULL; | 905 | struct net_device *ldev = NULL; |
@@ -945,8 +949,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
945 | int encap_limit, | 949 | int encap_limit, |
946 | __u32 *pmtu) | 950 | __u32 *pmtu) |
947 | { | 951 | { |
948 | struct net *net = dev_net(dev); | ||
949 | struct ip6_tnl *t = netdev_priv(dev); | 952 | struct ip6_tnl *t = netdev_priv(dev); |
953 | struct net *net = t->net; | ||
950 | struct net_device_stats *stats = &t->dev->stats; | 954 | struct net_device_stats *stats = &t->dev->stats; |
951 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 955 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
952 | struct ipv6_tel_txoption opt; | 956 | struct ipv6_tel_txoption opt; |
@@ -996,6 +1000,9 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
996 | goto tx_err_dst_release; | 1000 | goto tx_err_dst_release; |
997 | } | 1001 | } |
998 | 1002 | ||
1003 | if (!net_eq(t->net, dev_net(dev))) | ||
1004 | skb_scrub_packet(skb); | ||
1005 | |||
999 | /* | 1006 | /* |
1000 | * Okay, now see if we can stuff it in the buffer as-is. | 1007 | * Okay, now see if we can stuff it in the buffer as-is. |
1001 | */ | 1008 | */ |
@@ -1202,7 +1209,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1202 | int strict = (ipv6_addr_type(&p->raddr) & | 1209 | int strict = (ipv6_addr_type(&p->raddr) & |
1203 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); | 1210 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); |
1204 | 1211 | ||
1205 | struct rt6_info *rt = rt6_lookup(dev_net(dev), | 1212 | struct rt6_info *rt = rt6_lookup(t->net, |
1206 | &p->raddr, &p->laddr, | 1213 | &p->raddr, &p->laddr, |
1207 | p->link, strict); | 1214 | p->link, strict); |
1208 | 1215 | ||
@@ -1251,7 +1258,7 @@ ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) | |||
1251 | 1258 | ||
1252 | static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) | 1259 | static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) |
1253 | { | 1260 | { |
1254 | struct net *net = dev_net(t->dev); | 1261 | struct net *net = t->net; |
1255 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1262 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
1256 | int err; | 1263 | int err; |
1257 | 1264 | ||
@@ -1463,7 +1470,6 @@ static void ip6_tnl_dev_setup(struct net_device *dev) | |||
1463 | dev->mtu-=8; | 1470 | dev->mtu-=8; |
1464 | dev->flags |= IFF_NOARP; | 1471 | dev->flags |= IFF_NOARP; |
1465 | dev->addr_len = sizeof(struct in6_addr); | 1472 | dev->addr_len = sizeof(struct in6_addr); |
1466 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
1467 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 1473 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
1468 | } | 1474 | } |
1469 | 1475 | ||
@@ -1479,6 +1485,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev) | |||
1479 | struct ip6_tnl *t = netdev_priv(dev); | 1485 | struct ip6_tnl *t = netdev_priv(dev); |
1480 | 1486 | ||
1481 | t->dev = dev; | 1487 | t->dev = dev; |
1488 | t->net = dev_net(dev); | ||
1482 | dev->tstats = alloc_percpu(struct pcpu_tstats); | 1489 | dev->tstats = alloc_percpu(struct pcpu_tstats); |
1483 | if (!dev->tstats) | 1490 | if (!dev->tstats) |
1484 | return -ENOMEM; | 1491 | return -ENOMEM; |
@@ -1596,9 +1603,9 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, | |||
1596 | static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], | 1603 | static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[], |
1597 | struct nlattr *data[]) | 1604 | struct nlattr *data[]) |
1598 | { | 1605 | { |
1599 | struct ip6_tnl *t; | 1606 | struct ip6_tnl *t = netdev_priv(dev); |
1600 | struct __ip6_tnl_parm p; | 1607 | struct __ip6_tnl_parm p; |
1601 | struct net *net = dev_net(dev); | 1608 | struct net *net = t->net; |
1602 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1609 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
1603 | 1610 | ||
1604 | if (dev == ip6n->fb_tnl_dev) | 1611 | if (dev == ip6n->fb_tnl_dev) |
@@ -1699,14 +1706,24 @@ static struct xfrm6_tunnel ip6ip6_handler __read_mostly = { | |||
1699 | 1706 | ||
1700 | static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) | 1707 | static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) |
1701 | { | 1708 | { |
1709 | struct net *net = dev_net(ip6n->fb_tnl_dev); | ||
1710 | struct net_device *dev, *aux; | ||
1702 | int h; | 1711 | int h; |
1703 | struct ip6_tnl *t; | 1712 | struct ip6_tnl *t; |
1704 | LIST_HEAD(list); | 1713 | LIST_HEAD(list); |
1705 | 1714 | ||
1715 | for_each_netdev_safe(net, dev, aux) | ||
1716 | if (dev->rtnl_link_ops == &ip6_link_ops) | ||
1717 | unregister_netdevice_queue(dev, &list); | ||
1718 | |||
1706 | for (h = 0; h < HASH_SIZE; h++) { | 1719 | for (h = 0; h < HASH_SIZE; h++) { |
1707 | t = rtnl_dereference(ip6n->tnls_r_l[h]); | 1720 | t = rtnl_dereference(ip6n->tnls_r_l[h]); |
1708 | while (t != NULL) { | 1721 | while (t != NULL) { |
1709 | unregister_netdevice_queue(t->dev, &list); | 1722 | /* If dev is in the same netns, it has already |
1723 | * been added to the list by the previous loop. | ||
1724 | */ | ||
1725 | if (!net_eq(dev_net(t->dev), net)) | ||
1726 | unregister_netdevice_queue(t->dev, &list); | ||
1710 | t = rtnl_dereference(t->next); | 1727 | t = rtnl_dereference(t->next); |
1711 | } | 1728 | } |
1712 | } | 1729 | } |
@@ -1732,6 +1749,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
1732 | if (!ip6n->fb_tnl_dev) | 1749 | if (!ip6n->fb_tnl_dev) |
1733 | goto err_alloc_dev; | 1750 | goto err_alloc_dev; |
1734 | dev_net_set(ip6n->fb_tnl_dev, net); | 1751 | dev_net_set(ip6n->fb_tnl_dev, net); |
1752 | /* FB netdevice is special: we have one, and only one per netns. | ||
1753 | * Allowing to move it to another netns is clearly unsafe. | ||
1754 | */ | ||
1755 | ip6n->fb_tnl_dev->features |= NETIF_F_NETNS_LOCAL; | ||
1735 | 1756 | ||
1736 | err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev); | 1757 | err = ip6_fb_tnl_dev_init(ip6n->fb_tnl_dev); |
1737 | if (err < 0) | 1758 | if (err < 0) |