diff options
-rw-r--r-- | net/ipv4/ip_gre.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d729ca820931..6209ab36cab7 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -162,7 +162,8 @@ static DEFINE_RWLOCK(ipgre_lock); | |||
162 | 162 | ||
163 | /* Given src, dst and key, find appropriate for input tunnel. */ | 163 | /* Given src, dst and key, find appropriate for input tunnel. */ |
164 | 164 | ||
165 | static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be32 key) | 165 | static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, |
166 | __be32 remote, __be32 local, __be32 key) | ||
166 | { | 167 | { |
167 | unsigned h0 = HASH(remote); | 168 | unsigned h0 = HASH(remote); |
168 | unsigned h1 = HASH(key); | 169 | unsigned h1 = HASH(key); |
@@ -198,7 +199,8 @@ static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be3 | |||
198 | return NULL; | 199 | return NULL; |
199 | } | 200 | } |
200 | 201 | ||
201 | static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms) | 202 | static struct ip_tunnel **__ipgre_bucket(struct ipgre_net *ign, |
203 | struct ip_tunnel_parm *parms) | ||
202 | { | 204 | { |
203 | __be32 remote = parms->iph.daddr; | 205 | __be32 remote = parms->iph.daddr; |
204 | __be32 local = parms->iph.saddr; | 206 | __be32 local = parms->iph.saddr; |
@@ -216,14 +218,15 @@ static struct ip_tunnel **__ipgre_bucket(struct ip_tunnel_parm *parms) | |||
216 | return &tunnels[prio][h]; | 218 | return &tunnels[prio][h]; |
217 | } | 219 | } |
218 | 220 | ||
219 | static inline struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t) | 221 | static inline struct ip_tunnel **ipgre_bucket(struct ipgre_net *ign, |
222 | struct ip_tunnel *t) | ||
220 | { | 223 | { |
221 | return __ipgre_bucket(&t->parms); | 224 | return __ipgre_bucket(ign, &t->parms); |
222 | } | 225 | } |
223 | 226 | ||
224 | static void ipgre_tunnel_link(struct ip_tunnel *t) | 227 | static void ipgre_tunnel_link(struct ipgre_net *ign, struct ip_tunnel *t) |
225 | { | 228 | { |
226 | struct ip_tunnel **tp = ipgre_bucket(t); | 229 | struct ip_tunnel **tp = ipgre_bucket(ign, t); |
227 | 230 | ||
228 | t->next = *tp; | 231 | t->next = *tp; |
229 | write_lock_bh(&ipgre_lock); | 232 | write_lock_bh(&ipgre_lock); |
@@ -231,11 +234,11 @@ static void ipgre_tunnel_link(struct ip_tunnel *t) | |||
231 | write_unlock_bh(&ipgre_lock); | 234 | write_unlock_bh(&ipgre_lock); |
232 | } | 235 | } |
233 | 236 | ||
234 | static void ipgre_tunnel_unlink(struct ip_tunnel *t) | 237 | static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t) |
235 | { | 238 | { |
236 | struct ip_tunnel **tp; | 239 | struct ip_tunnel **tp; |
237 | 240 | ||
238 | for (tp = ipgre_bucket(t); *tp; tp = &(*tp)->next) { | 241 | for (tp = ipgre_bucket(ign, t); *tp; tp = &(*tp)->next) { |
239 | if (t == *tp) { | 242 | if (t == *tp) { |
240 | write_lock_bh(&ipgre_lock); | 243 | write_lock_bh(&ipgre_lock); |
241 | *tp = t->next; | 244 | *tp = t->next; |
@@ -245,7 +248,8 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t) | |||
245 | } | 248 | } |
246 | } | 249 | } |
247 | 250 | ||
248 | static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 251 | static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, |
252 | struct ip_tunnel_parm *parms, int create) | ||
249 | { | 253 | { |
250 | __be32 remote = parms->iph.daddr; | 254 | __be32 remote = parms->iph.daddr; |
251 | __be32 local = parms->iph.saddr; | 255 | __be32 local = parms->iph.saddr; |
@@ -253,8 +257,9 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int | |||
253 | struct ip_tunnel *t, **tp, *nt; | 257 | struct ip_tunnel *t, **tp, *nt; |
254 | struct net_device *dev; | 258 | struct net_device *dev; |
255 | char name[IFNAMSIZ]; | 259 | char name[IFNAMSIZ]; |
260 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | ||
256 | 261 | ||
257 | for (tp = __ipgre_bucket(parms); (t = *tp) != NULL; tp = &t->next) { | 262 | for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) { |
258 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { | 263 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { |
259 | if (key == t->parms.i_key) | 264 | if (key == t->parms.i_key) |
260 | return t; | 265 | return t; |
@@ -285,7 +290,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int | |||
285 | goto failed_free; | 290 | goto failed_free; |
286 | 291 | ||
287 | dev_hold(dev); | 292 | dev_hold(dev); |
288 | ipgre_tunnel_link(nt); | 293 | ipgre_tunnel_link(ign, nt); |
289 | return nt; | 294 | return nt; |
290 | 295 | ||
291 | failed_free: | 296 | failed_free: |
@@ -295,7 +300,10 @@ failed_free: | |||
295 | 300 | ||
296 | static void ipgre_tunnel_uninit(struct net_device *dev) | 301 | static void ipgre_tunnel_uninit(struct net_device *dev) |
297 | { | 302 | { |
298 | ipgre_tunnel_unlink(netdev_priv(dev)); | 303 | struct net *net = dev_net(dev); |
304 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | ||
305 | |||
306 | ipgre_tunnel_unlink(ign, netdev_priv(dev)); | ||
299 | dev_put(dev); | 307 | dev_put(dev); |
300 | } | 308 | } |
301 | 309 | ||
@@ -369,7 +377,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
369 | } | 377 | } |
370 | 378 | ||
371 | read_lock(&ipgre_lock); | 379 | read_lock(&ipgre_lock); |
372 | t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((__be32*)p) + (grehlen>>2) - 1) : 0); | 380 | t = ipgre_tunnel_lookup(&init_net, iph->daddr, iph->saddr, |
381 | (flags&GRE_KEY) ? | ||
382 | *(((__be32*)p) + (grehlen>>2) - 1) : 0); | ||
373 | if (t == NULL || t->parms.iph.daddr == 0 || | 383 | if (t == NULL || t->parms.iph.daddr == 0 || |
374 | ipv4_is_multicast(t->parms.iph.daddr)) | 384 | ipv4_is_multicast(t->parms.iph.daddr)) |
375 | goto out; | 385 | goto out; |
@@ -602,7 +612,8 @@ static int ipgre_rcv(struct sk_buff *skb) | |||
602 | } | 612 | } |
603 | 613 | ||
604 | read_lock(&ipgre_lock); | 614 | read_lock(&ipgre_lock); |
605 | if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) { | 615 | if ((tunnel = ipgre_tunnel_lookup(&init_net, |
616 | iph->saddr, iph->daddr, key)) != NULL) { | ||
606 | secpath_reset(skb); | 617 | secpath_reset(skb); |
607 | 618 | ||
608 | skb->protocol = *(__be16*)(h + 2); | 619 | skb->protocol = *(__be16*)(h + 2); |
@@ -960,6 +971,8 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
960 | int err = 0; | 971 | int err = 0; |
961 | struct ip_tunnel_parm p; | 972 | struct ip_tunnel_parm p; |
962 | struct ip_tunnel *t; | 973 | struct ip_tunnel *t; |
974 | struct net *net = dev_net(dev); | ||
975 | struct ipgre_net *ign = net_generic(net, ipgre_net_id); | ||
963 | 976 | ||
964 | switch (cmd) { | 977 | switch (cmd) { |
965 | case SIOCGETTUNNEL: | 978 | case SIOCGETTUNNEL: |
@@ -969,7 +982,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
969 | err = -EFAULT; | 982 | err = -EFAULT; |
970 | break; | 983 | break; |
971 | } | 984 | } |
972 | t = ipgre_tunnel_locate(&p, 0); | 985 | t = ipgre_tunnel_locate(net, &p, 0); |
973 | } | 986 | } |
974 | if (t == NULL) | 987 | if (t == NULL) |
975 | t = netdev_priv(dev); | 988 | t = netdev_priv(dev); |
@@ -1001,7 +1014,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1001 | if (!(p.o_flags&GRE_KEY)) | 1014 | if (!(p.o_flags&GRE_KEY)) |
1002 | p.o_key = 0; | 1015 | p.o_key = 0; |
1003 | 1016 | ||
1004 | t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL); | 1017 | t = ipgre_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); |
1005 | 1018 | ||
1006 | if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 1019 | if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
1007 | if (t != NULL) { | 1020 | if (t != NULL) { |
@@ -1023,14 +1036,14 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1023 | err = -EINVAL; | 1036 | err = -EINVAL; |
1024 | break; | 1037 | break; |
1025 | } | 1038 | } |
1026 | ipgre_tunnel_unlink(t); | 1039 | ipgre_tunnel_unlink(ign, t); |
1027 | t->parms.iph.saddr = p.iph.saddr; | 1040 | t->parms.iph.saddr = p.iph.saddr; |
1028 | t->parms.iph.daddr = p.iph.daddr; | 1041 | t->parms.iph.daddr = p.iph.daddr; |
1029 | t->parms.i_key = p.i_key; | 1042 | t->parms.i_key = p.i_key; |
1030 | t->parms.o_key = p.o_key; | 1043 | t->parms.o_key = p.o_key; |
1031 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 1044 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
1032 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 1045 | memcpy(dev->broadcast, &p.iph.daddr, 4); |
1033 | ipgre_tunnel_link(t); | 1046 | ipgre_tunnel_link(ign, t); |
1034 | netdev_state_change(dev); | 1047 | netdev_state_change(dev); |
1035 | } | 1048 | } |
1036 | } | 1049 | } |
@@ -1063,7 +1076,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1063 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 1076 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
1064 | goto done; | 1077 | goto done; |
1065 | err = -ENOENT; | 1078 | err = -ENOENT; |
1066 | if ((t = ipgre_tunnel_locate(&p, 0)) == NULL) | 1079 | if ((t = ipgre_tunnel_locate(net, &p, 0)) == NULL) |
1067 | goto done; | 1080 | goto done; |
1068 | err = -EPERM; | 1081 | err = -EPERM; |
1069 | if (t == netdev_priv(ipgre_fb_tunnel_dev)) | 1082 | if (t == netdev_priv(ipgre_fb_tunnel_dev)) |