diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 2365eb0fb6a4..fad1af8ae1cf 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -136,7 +136,7 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) | |||
136 | **/ | 136 | **/ |
137 | 137 | ||
138 | static struct ip6_tnl * | 138 | static struct ip6_tnl * |
139 | ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) | 139 | ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) |
140 | { | 140 | { |
141 | unsigned h0 = HASH(remote); | 141 | unsigned h0 = HASH(remote); |
142 | unsigned h1 = HASH(local); | 142 | unsigned h1 = HASH(local); |
@@ -166,7 +166,7 @@ ip6_tnl_lookup(struct in6_addr *remote, struct in6_addr *local) | |||
166 | **/ | 166 | **/ |
167 | 167 | ||
168 | static struct ip6_tnl ** | 168 | static struct ip6_tnl ** |
169 | ip6_tnl_bucket(struct ip6_tnl_parm *p) | 169 | ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p) |
170 | { | 170 | { |
171 | struct in6_addr *remote = &p->raddr; | 171 | struct in6_addr *remote = &p->raddr; |
172 | struct in6_addr *local = &p->laddr; | 172 | struct in6_addr *local = &p->laddr; |
@@ -186,9 +186,9 @@ ip6_tnl_bucket(struct ip6_tnl_parm *p) | |||
186 | **/ | 186 | **/ |
187 | 187 | ||
188 | static void | 188 | static void |
189 | ip6_tnl_link(struct ip6_tnl *t) | 189 | ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) |
190 | { | 190 | { |
191 | struct ip6_tnl **tp = ip6_tnl_bucket(&t->parms); | 191 | struct ip6_tnl **tp = ip6_tnl_bucket(ip6n, &t->parms); |
192 | 192 | ||
193 | t->next = *tp; | 193 | t->next = *tp; |
194 | write_lock_bh(&ip6_tnl_lock); | 194 | write_lock_bh(&ip6_tnl_lock); |
@@ -202,11 +202,11 @@ ip6_tnl_link(struct ip6_tnl *t) | |||
202 | **/ | 202 | **/ |
203 | 203 | ||
204 | static void | 204 | static void |
205 | ip6_tnl_unlink(struct ip6_tnl *t) | 205 | ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) |
206 | { | 206 | { |
207 | struct ip6_tnl **tp; | 207 | struct ip6_tnl **tp; |
208 | 208 | ||
209 | for (tp = ip6_tnl_bucket(&t->parms); *tp; tp = &(*tp)->next) { | 209 | for (tp = ip6_tnl_bucket(ip6n, &t->parms); *tp; tp = &(*tp)->next) { |
210 | if (t == *tp) { | 210 | if (t == *tp) { |
211 | write_lock_bh(&ip6_tnl_lock); | 211 | write_lock_bh(&ip6_tnl_lock); |
212 | *tp = t->next; | 212 | *tp = t->next; |
@@ -228,12 +228,13 @@ ip6_tnl_unlink(struct ip6_tnl *t) | |||
228 | * created tunnel or NULL | 228 | * created tunnel or NULL |
229 | **/ | 229 | **/ |
230 | 230 | ||
231 | static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) | 231 | static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) |
232 | { | 232 | { |
233 | struct net_device *dev; | 233 | struct net_device *dev; |
234 | struct ip6_tnl *t; | 234 | struct ip6_tnl *t; |
235 | char name[IFNAMSIZ]; | 235 | char name[IFNAMSIZ]; |
236 | int err; | 236 | int err; |
237 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | ||
237 | 238 | ||
238 | if (p->name[0]) | 239 | if (p->name[0]) |
239 | strlcpy(name, p->name, IFNAMSIZ); | 240 | strlcpy(name, p->name, IFNAMSIZ); |
@@ -257,7 +258,7 @@ static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) | |||
257 | goto failed_free; | 258 | goto failed_free; |
258 | 259 | ||
259 | dev_hold(dev); | 260 | dev_hold(dev); |
260 | ip6_tnl_link(t); | 261 | ip6_tnl_link(ip6n, t); |
261 | return t; | 262 | return t; |
262 | 263 | ||
263 | failed_free: | 264 | failed_free: |
@@ -280,20 +281,22 @@ failed: | |||
280 | * matching tunnel or NULL | 281 | * matching tunnel or NULL |
281 | **/ | 282 | **/ |
282 | 283 | ||
283 | static struct ip6_tnl *ip6_tnl_locate(struct ip6_tnl_parm *p, int create) | 284 | static struct ip6_tnl *ip6_tnl_locate(struct net *net, |
285 | struct ip6_tnl_parm *p, int create) | ||
284 | { | 286 | { |
285 | struct in6_addr *remote = &p->raddr; | 287 | struct in6_addr *remote = &p->raddr; |
286 | struct in6_addr *local = &p->laddr; | 288 | struct in6_addr *local = &p->laddr; |
287 | struct ip6_tnl *t; | 289 | struct ip6_tnl *t; |
290 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | ||
288 | 291 | ||
289 | for (t = *ip6_tnl_bucket(p); t; t = t->next) { | 292 | for (t = *ip6_tnl_bucket(ip6n, p); t; t = t->next) { |
290 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 293 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
291 | ipv6_addr_equal(remote, &t->parms.raddr)) | 294 | ipv6_addr_equal(remote, &t->parms.raddr)) |
292 | return t; | 295 | return t; |
293 | } | 296 | } |
294 | if (!create) | 297 | if (!create) |
295 | return NULL; | 298 | return NULL; |
296 | return ip6_tnl_create(p); | 299 | return ip6_tnl_create(net, p); |
297 | } | 300 | } |
298 | 301 | ||
299 | /** | 302 | /** |
@@ -308,13 +311,15 @@ static void | |||
308 | ip6_tnl_dev_uninit(struct net_device *dev) | 311 | ip6_tnl_dev_uninit(struct net_device *dev) |
309 | { | 312 | { |
310 | struct ip6_tnl *t = netdev_priv(dev); | 313 | struct ip6_tnl *t = netdev_priv(dev); |
314 | struct net *net = dev_net(dev); | ||
315 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | ||
311 | 316 | ||
312 | if (dev == ip6_fb_tnl_dev) { | 317 | if (dev == ip6_fb_tnl_dev) { |
313 | write_lock_bh(&ip6_tnl_lock); | 318 | write_lock_bh(&ip6_tnl_lock); |
314 | tnls_wc[0] = NULL; | 319 | tnls_wc[0] = NULL; |
315 | write_unlock_bh(&ip6_tnl_lock); | 320 | write_unlock_bh(&ip6_tnl_lock); |
316 | } else { | 321 | } else { |
317 | ip6_tnl_unlink(t); | 322 | ip6_tnl_unlink(ip6n, t); |
318 | } | 323 | } |
319 | ip6_tnl_dst_reset(t); | 324 | ip6_tnl_dst_reset(t); |
320 | dev_put(dev); | 325 | dev_put(dev); |
@@ -407,7 +412,8 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | |||
407 | processing of the error. */ | 412 | processing of the error. */ |
408 | 413 | ||
409 | read_lock(&ip6_tnl_lock); | 414 | read_lock(&ip6_tnl_lock); |
410 | if ((t = ip6_tnl_lookup(&ipv6h->daddr, &ipv6h->saddr)) == NULL) | 415 | if ((t = ip6_tnl_lookup(&init_net, &ipv6h->daddr, |
416 | &ipv6h->saddr)) == NULL) | ||
411 | goto out; | 417 | goto out; |
412 | 418 | ||
413 | if (t->parms.proto != ipproto && t->parms.proto != 0) | 419 | if (t->parms.proto != ipproto && t->parms.proto != 0) |
@@ -690,7 +696,8 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
690 | 696 | ||
691 | read_lock(&ip6_tnl_lock); | 697 | read_lock(&ip6_tnl_lock); |
692 | 698 | ||
693 | if ((t = ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { | 699 | if ((t = ip6_tnl_lookup(&init_net, &ipv6h->saddr, |
700 | &ipv6h->daddr)) != NULL) { | ||
694 | if (t->parms.proto != ipproto && t->parms.proto != 0) { | 701 | if (t->parms.proto != ipproto && t->parms.proto != 0) { |
695 | read_unlock(&ip6_tnl_lock); | 702 | read_unlock(&ip6_tnl_lock); |
696 | goto discard; | 703 | goto discard; |
@@ -1197,6 +1204,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1197 | int err = 0; | 1204 | int err = 0; |
1198 | struct ip6_tnl_parm p; | 1205 | struct ip6_tnl_parm p; |
1199 | struct ip6_tnl *t = NULL; | 1206 | struct ip6_tnl *t = NULL; |
1207 | struct net *net = dev_net(dev); | ||
1208 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | ||
1200 | 1209 | ||
1201 | switch (cmd) { | 1210 | switch (cmd) { |
1202 | case SIOCGETTUNNEL: | 1211 | case SIOCGETTUNNEL: |
@@ -1205,7 +1214,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1205 | err = -EFAULT; | 1214 | err = -EFAULT; |
1206 | break; | 1215 | break; |
1207 | } | 1216 | } |
1208 | t = ip6_tnl_locate(&p, 0); | 1217 | t = ip6_tnl_locate(net, &p, 0); |
1209 | } | 1218 | } |
1210 | if (t == NULL) | 1219 | if (t == NULL) |
1211 | t = netdev_priv(dev); | 1220 | t = netdev_priv(dev); |
@@ -1226,7 +1235,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1226 | if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && | 1235 | if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && |
1227 | p.proto != 0) | 1236 | p.proto != 0) |
1228 | break; | 1237 | break; |
1229 | t = ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); | 1238 | t = ip6_tnl_locate(net, &p, cmd == SIOCADDTUNNEL); |
1230 | if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { | 1239 | if (dev != ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { |
1231 | if (t != NULL) { | 1240 | if (t != NULL) { |
1232 | if (t->dev != dev) { | 1241 | if (t->dev != dev) { |
@@ -1236,9 +1245,9 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1236 | } else | 1245 | } else |
1237 | t = netdev_priv(dev); | 1246 | t = netdev_priv(dev); |
1238 | 1247 | ||
1239 | ip6_tnl_unlink(t); | 1248 | ip6_tnl_unlink(ip6n, t); |
1240 | err = ip6_tnl_change(t, &p); | 1249 | err = ip6_tnl_change(t, &p); |
1241 | ip6_tnl_link(t); | 1250 | ip6_tnl_link(ip6n, t); |
1242 | netdev_state_change(dev); | 1251 | netdev_state_change(dev); |
1243 | } | 1252 | } |
1244 | if (t) { | 1253 | if (t) { |
@@ -1259,7 +1268,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1259 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) | 1268 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
1260 | break; | 1269 | break; |
1261 | err = -ENOENT; | 1270 | err = -ENOENT; |
1262 | if ((t = ip6_tnl_locate(&p, 0)) == NULL) | 1271 | if ((t = ip6_tnl_locate(net, &p, 0)) == NULL) |
1263 | break; | 1272 | break; |
1264 | err = -EPERM; | 1273 | err = -EPERM; |
1265 | if (t->dev == ip6_fb_tnl_dev) | 1274 | if (t->dev == ip6_fb_tnl_dev) |