diff options
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r-- | net/ipv6/sit.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index aa6efc2ab55b..66cf0be4b679 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -82,7 +82,8 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne | |||
82 | 82 | ||
83 | static DEFINE_RWLOCK(ipip6_lock); | 83 | static DEFINE_RWLOCK(ipip6_lock); |
84 | 84 | ||
85 | static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) | 85 | static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, |
86 | __be32 remote, __be32 local) | ||
86 | { | 87 | { |
87 | unsigned h0 = HASH(remote); | 88 | unsigned h0 = HASH(remote); |
88 | unsigned h1 = HASH(local); | 89 | unsigned h1 = HASH(local); |
@@ -106,7 +107,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) | |||
106 | return NULL; | 107 | return NULL; |
107 | } | 108 | } |
108 | 109 | ||
109 | static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms) | 110 | static struct ip_tunnel **__ipip6_bucket(struct sit_net *sitn, |
111 | struct ip_tunnel_parm *parms) | ||
110 | { | 112 | { |
111 | __be32 remote = parms->iph.daddr; | 113 | __be32 remote = parms->iph.daddr; |
112 | __be32 local = parms->iph.saddr; | 114 | __be32 local = parms->iph.saddr; |
@@ -124,16 +126,17 @@ static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms) | |||
124 | return &tunnels[prio][h]; | 126 | return &tunnels[prio][h]; |
125 | } | 127 | } |
126 | 128 | ||
127 | static inline struct ip_tunnel **ipip6_bucket(struct ip_tunnel *t) | 129 | static inline struct ip_tunnel **ipip6_bucket(struct sit_net *sitn, |
130 | struct ip_tunnel *t) | ||
128 | { | 131 | { |
129 | return __ipip6_bucket(&t->parms); | 132 | return __ipip6_bucket(sitn, &t->parms); |
130 | } | 133 | } |
131 | 134 | ||
132 | static void ipip6_tunnel_unlink(struct ip_tunnel *t) | 135 | static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t) |
133 | { | 136 | { |
134 | struct ip_tunnel **tp; | 137 | struct ip_tunnel **tp; |
135 | 138 | ||
136 | for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) { | 139 | for (tp = ipip6_bucket(sitn, t); *tp; tp = &(*tp)->next) { |
137 | if (t == *tp) { | 140 | if (t == *tp) { |
138 | write_lock_bh(&ipip6_lock); | 141 | write_lock_bh(&ipip6_lock); |
139 | *tp = t->next; | 142 | *tp = t->next; |
@@ -143,9 +146,9 @@ static void ipip6_tunnel_unlink(struct ip_tunnel *t) | |||
143 | } | 146 | } |
144 | } | 147 | } |
145 | 148 | ||
146 | static void ipip6_tunnel_link(struct ip_tunnel *t) | 149 | static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t) |
147 | { | 150 | { |
148 | struct ip_tunnel **tp = ipip6_bucket(t); | 151 | struct ip_tunnel **tp = ipip6_bucket(sitn, t); |
149 | 152 | ||
150 | t->next = *tp; | 153 | t->next = *tp; |
151 | write_lock_bh(&ipip6_lock); | 154 | write_lock_bh(&ipip6_lock); |
@@ -153,15 +156,17 @@ static void ipip6_tunnel_link(struct ip_tunnel *t) | |||
153 | write_unlock_bh(&ipip6_lock); | 156 | write_unlock_bh(&ipip6_lock); |
154 | } | 157 | } |
155 | 158 | ||
156 | static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 159 | static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, |
160 | struct ip_tunnel_parm *parms, int create) | ||
157 | { | 161 | { |
158 | __be32 remote = parms->iph.daddr; | 162 | __be32 remote = parms->iph.daddr; |
159 | __be32 local = parms->iph.saddr; | 163 | __be32 local = parms->iph.saddr; |
160 | struct ip_tunnel *t, **tp, *nt; | 164 | struct ip_tunnel *t, **tp, *nt; |
161 | struct net_device *dev; | 165 | struct net_device *dev; |
162 | char name[IFNAMSIZ]; | 166 | char name[IFNAMSIZ]; |
167 | struct sit_net *sitn = net_generic(net, sit_net_id); | ||
163 | 168 | ||
164 | for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) { | 169 | for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { |
165 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) | 170 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) |
166 | return t; | 171 | return t; |
167 | } | 172 | } |
@@ -194,7 +199,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int | |||
194 | 199 | ||
195 | dev_hold(dev); | 200 | dev_hold(dev); |
196 | 201 | ||
197 | ipip6_tunnel_link(nt); | 202 | ipip6_tunnel_link(sitn, nt); |
198 | return nt; | 203 | return nt; |
199 | 204 | ||
200 | failed_free: | 205 | failed_free: |
@@ -378,13 +383,16 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) | |||
378 | 383 | ||
379 | static void ipip6_tunnel_uninit(struct net_device *dev) | 384 | static void ipip6_tunnel_uninit(struct net_device *dev) |
380 | { | 385 | { |
386 | struct net *net = dev_net(dev); | ||
387 | struct sit_net *sitn = net_generic(net, sit_net_id); | ||
388 | |||
381 | if (dev == ipip6_fb_tunnel_dev) { | 389 | if (dev == ipip6_fb_tunnel_dev) { |
382 | write_lock_bh(&ipip6_lock); | 390 | write_lock_bh(&ipip6_lock); |
383 | tunnels_wc[0] = NULL; | 391 | tunnels_wc[0] = NULL; |
384 | write_unlock_bh(&ipip6_lock); | 392 | write_unlock_bh(&ipip6_lock); |
385 | dev_put(dev); | 393 | dev_put(dev); |
386 | } else { | 394 | } else { |
387 | ipip6_tunnel_unlink(netdev_priv(dev)); | 395 | ipip6_tunnel_unlink(sitn, netdev_priv(dev)); |
388 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); | 396 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); |
389 | dev_put(dev); | 397 | dev_put(dev); |
390 | } | 398 | } |
@@ -436,7 +444,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
436 | err = -ENOENT; | 444 | err = -ENOENT; |
437 | 445 | ||
438 | read_lock(&ipip6_lock); | 446 | read_lock(&ipip6_lock); |
439 | t = ipip6_tunnel_lookup(iph->daddr, iph->saddr); | 447 | t = ipip6_tunnel_lookup(&init_net, iph->daddr, iph->saddr); |
440 | if (t == NULL || t->parms.iph.daddr == 0) | 448 | if (t == NULL || t->parms.iph.daddr == 0) |
441 | goto out; | 449 | goto out; |
442 | 450 | ||
@@ -556,7 +564,8 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
556 | iph = ip_hdr(skb); | 564 | iph = ip_hdr(skb); |
557 | 565 | ||
558 | read_lock(&ipip6_lock); | 566 | read_lock(&ipip6_lock); |
559 | if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { | 567 | if ((tunnel = ipip6_tunnel_lookup(&init_net, |
568 | iph->saddr, iph->daddr)) != NULL) { | ||
560 | secpath_reset(skb); | 569 | secpath_reset(skb); |
561 | skb->mac_header = skb->network_header; | 570 | skb->mac_header = skb->network_header; |
562 | skb_reset_network_header(skb); | 571 | skb_reset_network_header(skb); |
@@ -847,6 +856,8 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
847 | struct ip_tunnel_parm p; | 856 | struct ip_tunnel_parm p; |
848 | struct ip_tunnel_prl prl; | 857 | struct ip_tunnel_prl prl; |
849 | struct ip_tunnel *t; | 858 | struct ip_tunnel *t; |
859 | struct net *net = dev_net(dev); | ||
860 | struct sit_net *sitn = net_generic(net, sit_net_id); | ||
850 | 861 | ||
851 | switch (cmd) { | 862 | switch (cmd) { |
852 | case SIOCGETTUNNEL: | 863 | case SIOCGETTUNNEL: |
@@ -856,7 +867,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
856 | err = -EFAULT; | 867 | err = -EFAULT; |
857 | break; | 868 | break; |
858 | } | 869 | } |
859 | t = ipip6_tunnel_locate(&p, 0); | 870 | t = ipip6_tunnel_locate(net, &p, 0); |
860 | } | 871 | } |
861 | if (t == NULL) | 872 | if (t == NULL) |
862 | t = netdev_priv(dev); | 873 | t = netdev_priv(dev); |
@@ -882,7 +893,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
882 | if (p.iph.ttl) | 893 | if (p.iph.ttl) |
883 | p.iph.frag_off |= htons(IP_DF); | 894 | p.iph.frag_off |= htons(IP_DF); |
884 | 895 | ||
885 | t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL); | 896 | t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); |
886 | 897 | ||
887 | if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 898 | if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
888 | if (t != NULL) { | 899 | if (t != NULL) { |
@@ -897,12 +908,12 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
897 | break; | 908 | break; |
898 | } | 909 | } |
899 | t = netdev_priv(dev); | 910 | t = netdev_priv(dev); |
900 | ipip6_tunnel_unlink(t); | 911 | ipip6_tunnel_unlink(sitn, t); |
901 | t->parms.iph.saddr = p.iph.saddr; | 912 | t->parms.iph.saddr = p.iph.saddr; |
902 | t->parms.iph.daddr = p.iph.daddr; | 913 | t->parms.iph.daddr = p.iph.daddr; |
903 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 914 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
904 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 915 | memcpy(dev->broadcast, &p.iph.daddr, 4); |
905 | ipip6_tunnel_link(t); | 916 | ipip6_tunnel_link(sitn, t); |
906 | netdev_state_change(dev); | 917 | netdev_state_change(dev); |
907 | } | 918 | } |
908 | } | 919 | } |
@@ -934,7 +945,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
934 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 945 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
935 | goto done; | 946 | goto done; |
936 | err = -ENOENT; | 947 | err = -ENOENT; |
937 | if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) | 948 | if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL) |
938 | goto done; | 949 | goto done; |
939 | err = -EPERM; | 950 | err = -EPERM; |
940 | if (t == netdev_priv(ipip6_fb_tunnel_dev)) | 951 | if (t == netdev_priv(ipip6_fb_tunnel_dev)) |