diff options
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r-- | net/ipv6/sit.c | 61 |
1 files changed, 29 insertions, 32 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e85ddcd763d0..d0c1f2db7f21 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -70,10 +70,9 @@ static void ipip6_tunnel_setup(struct net_device *dev); | |||
70 | 70 | ||
71 | static int sit_net_id; | 71 | static int sit_net_id; |
72 | struct sit_net { | 72 | struct sit_net { |
73 | struct net_device *fb_tunnel_dev; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static struct net_device *ipip6_fb_tunnel_dev; | ||
76 | |||
77 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | 76 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; |
78 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; | 77 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; |
79 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; | 78 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; |
@@ -386,7 +385,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
386 | struct net *net = dev_net(dev); | 385 | struct net *net = dev_net(dev); |
387 | struct sit_net *sitn = net_generic(net, sit_net_id); | 386 | struct sit_net *sitn = net_generic(net, sit_net_id); |
388 | 387 | ||
389 | if (dev == ipip6_fb_tunnel_dev) { | 388 | if (dev == sitn->fb_tunnel_dev) { |
390 | write_lock_bh(&ipip6_lock); | 389 | write_lock_bh(&ipip6_lock); |
391 | tunnels_wc[0] = NULL; | 390 | tunnels_wc[0] = NULL; |
392 | write_unlock_bh(&ipip6_lock); | 391 | write_unlock_bh(&ipip6_lock); |
@@ -862,7 +861,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
862 | switch (cmd) { | 861 | switch (cmd) { |
863 | case SIOCGETTUNNEL: | 862 | case SIOCGETTUNNEL: |
864 | t = NULL; | 863 | t = NULL; |
865 | if (dev == ipip6_fb_tunnel_dev) { | 864 | if (dev == sitn->fb_tunnel_dev) { |
866 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 865 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
867 | err = -EFAULT; | 866 | err = -EFAULT; |
868 | break; | 867 | break; |
@@ -895,7 +894,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
895 | 894 | ||
896 | t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); | 895 | t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); |
897 | 896 | ||
898 | if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 897 | if (dev != sitn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
899 | if (t != NULL) { | 898 | if (t != NULL) { |
900 | if (t->dev != dev) { | 899 | if (t->dev != dev) { |
901 | err = -EEXIST; | 900 | err = -EEXIST; |
@@ -940,7 +939,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
940 | if (!capable(CAP_NET_ADMIN)) | 939 | if (!capable(CAP_NET_ADMIN)) |
941 | goto done; | 940 | goto done; |
942 | 941 | ||
943 | if (dev == ipip6_fb_tunnel_dev) { | 942 | if (dev == sitn->fb_tunnel_dev) { |
944 | err = -EFAULT; | 943 | err = -EFAULT; |
945 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 944 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
946 | goto done; | 945 | goto done; |
@@ -948,7 +947,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
948 | if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL) | 947 | if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL) |
949 | goto done; | 948 | goto done; |
950 | err = -EPERM; | 949 | err = -EPERM; |
951 | if (t == netdev_priv(ipip6_fb_tunnel_dev)) | 950 | if (t == netdev_priv(sitn->fb_tunnel_dev)) |
952 | goto done; | 951 | goto done; |
953 | dev = t->dev; | 952 | dev = t->dev; |
954 | } | 953 | } |
@@ -964,7 +963,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
964 | if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) | 963 | if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) |
965 | goto done; | 964 | goto done; |
966 | err = -EINVAL; | 965 | err = -EINVAL; |
967 | if (dev == ipip6_fb_tunnel_dev) | 966 | if (dev == sitn->fb_tunnel_dev) |
968 | goto done; | 967 | goto done; |
969 | err = -EFAULT; | 968 | err = -EFAULT; |
970 | if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) | 969 | if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) |
@@ -1047,7 +1046,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1047 | return 0; | 1046 | return 0; |
1048 | } | 1047 | } |
1049 | 1048 | ||
1050 | static int __init ipip6_fb_tunnel_init(struct net_device *dev) | 1049 | static int ipip6_fb_tunnel_init(struct net_device *dev) |
1051 | { | 1050 | { |
1052 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1051 | struct ip_tunnel *tunnel = netdev_priv(dev); |
1053 | struct iphdr *iph = &tunnel->parms.iph; | 1052 | struct iphdr *iph = &tunnel->parms.iph; |
@@ -1099,8 +1098,25 @@ static int sit_init_net(struct net *net) | |||
1099 | if (err < 0) | 1098 | if (err < 0) |
1100 | goto err_assign; | 1099 | goto err_assign; |
1101 | 1100 | ||
1101 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | ||
1102 | ipip6_tunnel_setup); | ||
1103 | if (!sitn->fb_tunnel_dev) { | ||
1104 | err = -ENOMEM; | ||
1105 | goto err_alloc_dev; | ||
1106 | } | ||
1107 | |||
1108 | sitn->fb_tunnel_dev->init = ipip6_fb_tunnel_init; | ||
1109 | dev_net_set(sitn->fb_tunnel_dev, net); | ||
1110 | |||
1111 | if ((err = register_netdev(sitn->fb_tunnel_dev))) | ||
1112 | goto err_reg_dev; | ||
1113 | |||
1102 | return 0; | 1114 | return 0; |
1103 | 1115 | ||
1116 | err_reg_dev: | ||
1117 | free_netdev(sitn->fb_tunnel_dev); | ||
1118 | err_alloc_dev: | ||
1119 | /* nothing */ | ||
1104 | err_assign: | 1120 | err_assign: |
1105 | kfree(sitn); | 1121 | kfree(sitn); |
1106 | err_alloc: | 1122 | err_alloc: |
@@ -1112,6 +1128,9 @@ static void sit_exit_net(struct net *net) | |||
1112 | struct sit_net *sitn; | 1128 | struct sit_net *sitn; |
1113 | 1129 | ||
1114 | sitn = net_generic(net, sit_net_id); | 1130 | sitn = net_generic(net, sit_net_id); |
1131 | rtnl_lock(); | ||
1132 | unregister_netdevice(sitn->fb_tunnel_dev); | ||
1133 | rtnl_unlock(); | ||
1115 | kfree(sitn); | 1134 | kfree(sitn); |
1116 | } | 1135 | } |
1117 | 1136 | ||
@@ -1126,7 +1145,6 @@ static void __exit sit_cleanup(void) | |||
1126 | 1145 | ||
1127 | rtnl_lock(); | 1146 | rtnl_lock(); |
1128 | sit_destroy_tunnels(); | 1147 | sit_destroy_tunnels(); |
1129 | unregister_netdevice(ipip6_fb_tunnel_dev); | ||
1130 | rtnl_unlock(); | 1148 | rtnl_unlock(); |
1131 | 1149 | ||
1132 | unregister_pernet_gen_device(sit_net_id, &sit_net_ops); | 1150 | unregister_pernet_gen_device(sit_net_id, &sit_net_ops); |
@@ -1143,32 +1161,11 @@ static int __init sit_init(void) | |||
1143 | return -EAGAIN; | 1161 | return -EAGAIN; |
1144 | } | 1162 | } |
1145 | 1163 | ||
1146 | ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | ||
1147 | ipip6_tunnel_setup); | ||
1148 | if (!ipip6_fb_tunnel_dev) { | ||
1149 | err = -ENOMEM; | ||
1150 | goto err1; | ||
1151 | } | ||
1152 | |||
1153 | ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; | ||
1154 | |||
1155 | if ((err = register_netdev(ipip6_fb_tunnel_dev))) | ||
1156 | goto err2; | ||
1157 | |||
1158 | err = register_pernet_gen_device(&sit_net_id, &sit_net_ops); | 1164 | err = register_pernet_gen_device(&sit_net_id, &sit_net_ops); |
1159 | if (err < 0) | 1165 | if (err < 0) |
1160 | goto err3; | 1166 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); |
1161 | 1167 | ||
1162 | out: | ||
1163 | return err; | 1168 | return err; |
1164 | err2: | ||
1165 | free_netdev(ipip6_fb_tunnel_dev); | ||
1166 | err1: | ||
1167 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); | ||
1168 | goto out; | ||
1169 | err3: | ||
1170 | unregister_netdevice(ipip6_fb_tunnel_dev); | ||
1171 | goto err1; | ||
1172 | } | 1169 | } |
1173 | 1170 | ||
1174 | module_init(sit_init); | 1171 | module_init(sit_init); |