diff options
-rw-r--r-- | include/net/ip_tunnels.h | 2 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 43 | ||||
-rw-r--r-- | net/ipv4/ip_vti.c | 2 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 3 |
5 files changed, 33 insertions, 21 deletions
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index c6acd9f8f877..5a76f2bef822 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h | |||
@@ -102,7 +102,7 @@ void ip_tunnel_dellink(struct net_device *dev, struct list_head *head); | |||
102 | int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, | 102 | int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, |
103 | struct rtnl_link_ops *ops, char *devname); | 103 | struct rtnl_link_ops *ops, char *devname); |
104 | 104 | ||
105 | void ip_tunnel_delete_net(struct ip_tunnel_net *itn); | 105 | void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops); |
106 | 106 | ||
107 | void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | 107 | void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, |
108 | const struct iphdr *tnl_params, const u8 protocol); | 108 | const struct iphdr *tnl_params, const u8 protocol); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 1f6eab66f7ce..bc3a76521deb 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -534,7 +534,7 @@ static int __net_init ipgre_init_net(struct net *net) | |||
534 | static void __net_exit ipgre_exit_net(struct net *net) | 534 | static void __net_exit ipgre_exit_net(struct net *net) |
535 | { | 535 | { |
536 | struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); | 536 | struct ip_tunnel_net *itn = net_generic(net, ipgre_net_id); |
537 | ip_tunnel_delete_net(itn); | 537 | ip_tunnel_delete_net(itn, &ipgre_link_ops); |
538 | } | 538 | } |
539 | 539 | ||
540 | static struct pernet_operations ipgre_net_ops = { | 540 | static struct pernet_operations ipgre_net_ops = { |
@@ -767,7 +767,7 @@ static int __net_init ipgre_tap_init_net(struct net *net) | |||
767 | static void __net_exit ipgre_tap_exit_net(struct net *net) | 767 | static void __net_exit ipgre_tap_exit_net(struct net *net) |
768 | { | 768 | { |
769 | struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); | 769 | struct ip_tunnel_net *itn = net_generic(net, gre_tap_net_id); |
770 | ip_tunnel_delete_net(itn); | 770 | ip_tunnel_delete_net(itn, &ipgre_tap_ops); |
771 | } | 771 | } |
772 | 772 | ||
773 | static struct pernet_operations ipgre_tap_net_ops = { | 773 | static struct pernet_operations ipgre_tap_net_ops = { |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index a351a003ee6b..a4d9126c7b51 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -350,7 +350,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) | |||
350 | struct flowi4 fl4; | 350 | struct flowi4 fl4; |
351 | struct rtable *rt; | 351 | struct rtable *rt; |
352 | 352 | ||
353 | rt = ip_route_output_tunnel(dev_net(dev), &fl4, | 353 | rt = ip_route_output_tunnel(tunnel->net, &fl4, |
354 | tunnel->parms.iph.protocol, | 354 | tunnel->parms.iph.protocol, |
355 | iph->daddr, iph->saddr, | 355 | iph->daddr, iph->saddr, |
356 | tunnel->parms.o_key, | 356 | tunnel->parms.o_key, |
@@ -365,7 +365,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) | |||
365 | } | 365 | } |
366 | 366 | ||
367 | if (!tdev && tunnel->parms.link) | 367 | if (!tdev && tunnel->parms.link) |
368 | tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); | 368 | tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); |
369 | 369 | ||
370 | if (tdev) { | 370 | if (tdev) { |
371 | hlen = tdev->hard_header_len + tdev->needed_headroom; | 371 | hlen = tdev->hard_header_len + tdev->needed_headroom; |
@@ -654,7 +654,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
654 | } | 654 | } |
655 | } | 655 | } |
656 | 656 | ||
657 | err = iptunnel_xmit(dev_net(dev), rt, skb, | 657 | err = iptunnel_xmit(tunnel->net, rt, skb, |
658 | fl4.saddr, fl4.daddr, protocol, | 658 | fl4.saddr, fl4.daddr, protocol, |
659 | ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df); | 659 | ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df); |
660 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | 660 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); |
@@ -821,11 +821,10 @@ static void ip_tunnel_dev_free(struct net_device *dev) | |||
821 | 821 | ||
822 | void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) | 822 | void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) |
823 | { | 823 | { |
824 | struct net *net = dev_net(dev); | ||
825 | struct ip_tunnel *tunnel = netdev_priv(dev); | 824 | struct ip_tunnel *tunnel = netdev_priv(dev); |
826 | struct ip_tunnel_net *itn; | 825 | struct ip_tunnel_net *itn; |
827 | 826 | ||
828 | itn = net_generic(net, tunnel->ip_tnl_net_id); | 827 | itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id); |
829 | 828 | ||
830 | if (itn->fb_tunnel_dev != dev) { | 829 | if (itn->fb_tunnel_dev != dev) { |
831 | ip_tunnel_del(netdev_priv(dev)); | 830 | ip_tunnel_del(netdev_priv(dev)); |
@@ -855,6 +854,10 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, | |||
855 | 854 | ||
856 | rtnl_lock(); | 855 | rtnl_lock(); |
857 | itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); | 856 | itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); |
857 | /* FB netdevice is special: we have one, and only one per netns. | ||
858 | * Allowing to move it to another netns is clearly unsafe. | ||
859 | */ | ||
860 | itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; | ||
858 | rtnl_unlock(); | 861 | rtnl_unlock(); |
859 | 862 | ||
860 | if (IS_ERR(itn->fb_tunnel_dev)) | 863 | if (IS_ERR(itn->fb_tunnel_dev)) |
@@ -864,28 +867,39 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, | |||
864 | } | 867 | } |
865 | EXPORT_SYMBOL_GPL(ip_tunnel_init_net); | 868 | EXPORT_SYMBOL_GPL(ip_tunnel_init_net); |
866 | 869 | ||
867 | static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head) | 870 | static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head, |
871 | struct rtnl_link_ops *ops) | ||
868 | { | 872 | { |
873 | struct net *net = dev_net(itn->fb_tunnel_dev); | ||
874 | struct net_device *dev, *aux; | ||
869 | int h; | 875 | int h; |
870 | 876 | ||
877 | for_each_netdev_safe(net, dev, aux) | ||
878 | if (dev->rtnl_link_ops == ops) | ||
879 | unregister_netdevice_queue(dev, head); | ||
880 | |||
871 | for (h = 0; h < IP_TNL_HASH_SIZE; h++) { | 881 | for (h = 0; h < IP_TNL_HASH_SIZE; h++) { |
872 | struct ip_tunnel *t; | 882 | struct ip_tunnel *t; |
873 | struct hlist_node *n; | 883 | struct hlist_node *n; |
874 | struct hlist_head *thead = &itn->tunnels[h]; | 884 | struct hlist_head *thead = &itn->tunnels[h]; |
875 | 885 | ||
876 | hlist_for_each_entry_safe(t, n, thead, hash_node) | 886 | hlist_for_each_entry_safe(t, n, thead, hash_node) |
877 | unregister_netdevice_queue(t->dev, head); | 887 | /* If dev is in the same netns, it has already |
888 | * been added to the list by the previous loop. | ||
889 | */ | ||
890 | if (!net_eq(dev_net(t->dev), net)) | ||
891 | unregister_netdevice_queue(t->dev, head); | ||
878 | } | 892 | } |
879 | if (itn->fb_tunnel_dev) | 893 | if (itn->fb_tunnel_dev) |
880 | unregister_netdevice_queue(itn->fb_tunnel_dev, head); | 894 | unregister_netdevice_queue(itn->fb_tunnel_dev, head); |
881 | } | 895 | } |
882 | 896 | ||
883 | void ip_tunnel_delete_net(struct ip_tunnel_net *itn) | 897 | void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops) |
884 | { | 898 | { |
885 | LIST_HEAD(list); | 899 | LIST_HEAD(list); |
886 | 900 | ||
887 | rtnl_lock(); | 901 | rtnl_lock(); |
888 | ip_tunnel_destroy(itn, &list); | 902 | ip_tunnel_destroy(itn, &list, ops); |
889 | unregister_netdevice_many(&list); | 903 | unregister_netdevice_many(&list); |
890 | rtnl_unlock(); | 904 | rtnl_unlock(); |
891 | } | 905 | } |
@@ -929,23 +943,21 @@ EXPORT_SYMBOL_GPL(ip_tunnel_newlink); | |||
929 | int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], | 943 | int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], |
930 | struct ip_tunnel_parm *p) | 944 | struct ip_tunnel_parm *p) |
931 | { | 945 | { |
932 | struct ip_tunnel *t, *nt; | 946 | struct ip_tunnel *t; |
933 | struct net *net = dev_net(dev); | ||
934 | struct ip_tunnel *tunnel = netdev_priv(dev); | 947 | struct ip_tunnel *tunnel = netdev_priv(dev); |
948 | struct net *net = tunnel->net; | ||
935 | struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); | 949 | struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); |
936 | 950 | ||
937 | if (dev == itn->fb_tunnel_dev) | 951 | if (dev == itn->fb_tunnel_dev) |
938 | return -EINVAL; | 952 | return -EINVAL; |
939 | 953 | ||
940 | nt = netdev_priv(dev); | ||
941 | |||
942 | t = ip_tunnel_find(itn, p, dev->type); | 954 | t = ip_tunnel_find(itn, p, dev->type); |
943 | 955 | ||
944 | if (t) { | 956 | if (t) { |
945 | if (t->dev != dev) | 957 | if (t->dev != dev) |
946 | return -EEXIST; | 958 | return -EEXIST; |
947 | } else { | 959 | } else { |
948 | t = nt; | 960 | t = tunnel; |
949 | 961 | ||
950 | if (dev->type != ARPHRD_ETHER) { | 962 | if (dev->type != ARPHRD_ETHER) { |
951 | unsigned int nflags = 0; | 963 | unsigned int nflags = 0; |
@@ -984,6 +996,7 @@ int ip_tunnel_init(struct net_device *dev) | |||
984 | } | 996 | } |
985 | 997 | ||
986 | tunnel->dev = dev; | 998 | tunnel->dev = dev; |
999 | tunnel->net = dev_net(dev); | ||
987 | strcpy(tunnel->parms.name, dev->name); | 1000 | strcpy(tunnel->parms.name, dev->name); |
988 | iph->version = 4; | 1001 | iph->version = 4; |
989 | iph->ihl = 5; | 1002 | iph->ihl = 5; |
@@ -994,8 +1007,8 @@ EXPORT_SYMBOL_GPL(ip_tunnel_init); | |||
994 | 1007 | ||
995 | void ip_tunnel_uninit(struct net_device *dev) | 1008 | void ip_tunnel_uninit(struct net_device *dev) |
996 | { | 1009 | { |
997 | struct net *net = dev_net(dev); | ||
998 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1010 | struct ip_tunnel *tunnel = netdev_priv(dev); |
1011 | struct net *net = tunnel->net; | ||
999 | struct ip_tunnel_net *itn; | 1012 | struct ip_tunnel_net *itn; |
1000 | 1013 | ||
1001 | itn = net_generic(net, tunnel->ip_tnl_net_id); | 1014 | itn = net_generic(net, tunnel->ip_tnl_net_id); |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 79b263da4168..e805e7b3030e 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -318,7 +318,7 @@ static int __net_init vti_init_net(struct net *net) | |||
318 | static void __net_exit vti_exit_net(struct net *net) | 318 | static void __net_exit vti_exit_net(struct net *net) |
319 | { | 319 | { |
320 | struct ip_tunnel_net *itn = net_generic(net, vti_net_id); | 320 | struct ip_tunnel_net *itn = net_generic(net, vti_net_id); |
321 | ip_tunnel_delete_net(itn); | 321 | ip_tunnel_delete_net(itn, &vti_link_ops); |
322 | } | 322 | } |
323 | 323 | ||
324 | static struct pernet_operations vti_net_ops = { | 324 | static struct pernet_operations vti_net_ops = { |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 51fc2a1dcdd3..87bd2952c733 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -286,7 +286,6 @@ static void ipip_tunnel_setup(struct net_device *dev) | |||
286 | dev->flags = IFF_NOARP; | 286 | dev->flags = IFF_NOARP; |
287 | dev->iflink = 0; | 287 | dev->iflink = 0; |
288 | dev->addr_len = 4; | 288 | dev->addr_len = 4; |
289 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
290 | dev->features |= NETIF_F_LLTX; | 289 | dev->features |= NETIF_F_LLTX; |
291 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 290 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
292 | 291 | ||
@@ -437,7 +436,7 @@ static int __net_init ipip_init_net(struct net *net) | |||
437 | static void __net_exit ipip_exit_net(struct net *net) | 436 | static void __net_exit ipip_exit_net(struct net *net) |
438 | { | 437 | { |
439 | struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); | 438 | struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); |
440 | ip_tunnel_delete_net(itn); | 439 | ip_tunnel_delete_net(itn, &ipip_link_ops); |
441 | } | 440 | } |
442 | 441 | ||
443 | static struct pernet_operations ipip_net_ops = { | 442 | static struct pernet_operations ipip_net_ops = { |