diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 21:02:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-18 21:02:35 -0400 |
commit | 334d094504c2fe1c44211ecb49146ae6bca8c321 (patch) | |
tree | d3c0f68e4b9f8e3d2ccc39e7dfe5de0534a5fad9 /net/ipv4/ipip.c | |
parent | d1a4be630fb068f251d64b62919f143c49ca8057 (diff) | |
parent | d1643d24c61b725bef399cc1cf2944b4c9c23177 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.26
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.26: (1090 commits)
[NET]: Fix and allocate less memory for ->priv'less netdevices
[IPV6]: Fix dangling references on error in fib6_add().
[NETLABEL]: Fix NULL deref in netlbl_unlabel_staticlist_gen() if ifindex not found
[PKT_SCHED]: Fix datalen check in tcf_simp_init().
[INET]: Uninline the __inet_inherit_port call.
[INET]: Drop the inet_inherit_port() call.
SCTP: Initialize partial_bytes_acked to 0, when all of the data is acked.
[netdrvr] forcedeth: internal simplifications; changelog removal
phylib: factor out get_phy_id from within get_phy_device
PHY: add BCM5464 support to broadcom PHY driver
cxgb3: Fix __must_check warning with dev_dbg.
tc35815: Statistics cleanup
natsemi: fix MMIO for PPC 44x platforms
[TIPC]: Cleanup of TIPC reference table code
[TIPC]: Optimized initialization of TIPC reference table
[TIPC]: Remove inlining of reference table locking routines
e1000: convert uint16_t style integers to u16
ixgb: convert uint16_t style integers to u16
sb1000.c: make const arrays static
sb1000.c: stop inlining largish static functions
...
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r-- | net/ipv4/ipip.c | 220 |
1 files changed, 143 insertions, 77 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index dbaed69de06a..149111f08e8d 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -115,49 +115,57 @@ | |||
115 | #include <net/ipip.h> | 115 | #include <net/ipip.h> |
116 | #include <net/inet_ecn.h> | 116 | #include <net/inet_ecn.h> |
117 | #include <net/xfrm.h> | 117 | #include <net/xfrm.h> |
118 | #include <net/net_namespace.h> | ||
119 | #include <net/netns/generic.h> | ||
118 | 120 | ||
119 | #define HASH_SIZE 16 | 121 | #define HASH_SIZE 16 |
120 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) | 122 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) |
121 | 123 | ||
124 | static int ipip_net_id; | ||
125 | struct ipip_net { | ||
126 | struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | ||
127 | struct ip_tunnel *tunnels_r[HASH_SIZE]; | ||
128 | struct ip_tunnel *tunnels_l[HASH_SIZE]; | ||
129 | struct ip_tunnel *tunnels_wc[1]; | ||
130 | struct ip_tunnel **tunnels[4]; | ||
131 | |||
132 | struct net_device *fb_tunnel_dev; | ||
133 | }; | ||
134 | |||
122 | static int ipip_fb_tunnel_init(struct net_device *dev); | 135 | static int ipip_fb_tunnel_init(struct net_device *dev); |
123 | static int ipip_tunnel_init(struct net_device *dev); | 136 | static int ipip_tunnel_init(struct net_device *dev); |
124 | static void ipip_tunnel_setup(struct net_device *dev); | 137 | static void ipip_tunnel_setup(struct net_device *dev); |
125 | 138 | ||
126 | static struct net_device *ipip_fb_tunnel_dev; | ||
127 | |||
128 | static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; | ||
129 | static struct ip_tunnel *tunnels_r[HASH_SIZE]; | ||
130 | static struct ip_tunnel *tunnels_l[HASH_SIZE]; | ||
131 | static struct ip_tunnel *tunnels_wc[1]; | ||
132 | static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; | ||
133 | |||
134 | static DEFINE_RWLOCK(ipip_lock); | 139 | static DEFINE_RWLOCK(ipip_lock); |
135 | 140 | ||
136 | static struct ip_tunnel * ipip_tunnel_lookup(__be32 remote, __be32 local) | 141 | static struct ip_tunnel * ipip_tunnel_lookup(struct net *net, |
142 | __be32 remote, __be32 local) | ||
137 | { | 143 | { |
138 | unsigned h0 = HASH(remote); | 144 | unsigned h0 = HASH(remote); |
139 | unsigned h1 = HASH(local); | 145 | unsigned h1 = HASH(local); |
140 | struct ip_tunnel *t; | 146 | struct ip_tunnel *t; |
147 | struct ipip_net *ipn = net_generic(net, ipip_net_id); | ||
141 | 148 | ||
142 | for (t = tunnels_r_l[h0^h1]; t; t = t->next) { | 149 | for (t = ipn->tunnels_r_l[h0^h1]; t; t = t->next) { |
143 | if (local == t->parms.iph.saddr && | 150 | if (local == t->parms.iph.saddr && |
144 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 151 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
145 | return t; | 152 | return t; |
146 | } | 153 | } |
147 | for (t = tunnels_r[h0]; t; t = t->next) { | 154 | for (t = ipn->tunnels_r[h0]; t; t = t->next) { |
148 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 155 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) |
149 | return t; | 156 | return t; |
150 | } | 157 | } |
151 | for (t = tunnels_l[h1]; t; t = t->next) { | 158 | for (t = ipn->tunnels_l[h1]; t; t = t->next) { |
152 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) | 159 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) |
153 | return t; | 160 | return t; |
154 | } | 161 | } |
155 | if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) | 162 | if ((t = ipn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) |
156 | return t; | 163 | return t; |
157 | return NULL; | 164 | return NULL; |
158 | } | 165 | } |
159 | 166 | ||
160 | static struct ip_tunnel **__ipip_bucket(struct ip_tunnel_parm *parms) | 167 | static struct ip_tunnel **__ipip_bucket(struct ipip_net *ipn, |
168 | struct ip_tunnel_parm *parms) | ||
161 | { | 169 | { |
162 | __be32 remote = parms->iph.daddr; | 170 | __be32 remote = parms->iph.daddr; |
163 | __be32 local = parms->iph.saddr; | 171 | __be32 local = parms->iph.saddr; |
@@ -172,19 +180,20 @@ static struct ip_tunnel **__ipip_bucket(struct ip_tunnel_parm *parms) | |||
172 | prio |= 1; | 180 | prio |= 1; |
173 | h ^= HASH(local); | 181 | h ^= HASH(local); |
174 | } | 182 | } |
175 | return &tunnels[prio][h]; | 183 | return &ipn->tunnels[prio][h]; |
176 | } | 184 | } |
177 | 185 | ||
178 | static inline struct ip_tunnel **ipip_bucket(struct ip_tunnel *t) | 186 | static inline struct ip_tunnel **ipip_bucket(struct ipip_net *ipn, |
187 | struct ip_tunnel *t) | ||
179 | { | 188 | { |
180 | return __ipip_bucket(&t->parms); | 189 | return __ipip_bucket(ipn, &t->parms); |
181 | } | 190 | } |
182 | 191 | ||
183 | static void ipip_tunnel_unlink(struct ip_tunnel *t) | 192 | static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t) |
184 | { | 193 | { |
185 | struct ip_tunnel **tp; | 194 | struct ip_tunnel **tp; |
186 | 195 | ||
187 | for (tp = ipip_bucket(t); *tp; tp = &(*tp)->next) { | 196 | for (tp = ipip_bucket(ipn, t); *tp; tp = &(*tp)->next) { |
188 | if (t == *tp) { | 197 | if (t == *tp) { |
189 | write_lock_bh(&ipip_lock); | 198 | write_lock_bh(&ipip_lock); |
190 | *tp = t->next; | 199 | *tp = t->next; |
@@ -194,9 +203,9 @@ static void ipip_tunnel_unlink(struct ip_tunnel *t) | |||
194 | } | 203 | } |
195 | } | 204 | } |
196 | 205 | ||
197 | static void ipip_tunnel_link(struct ip_tunnel *t) | 206 | static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t) |
198 | { | 207 | { |
199 | struct ip_tunnel **tp = ipip_bucket(t); | 208 | struct ip_tunnel **tp = ipip_bucket(ipn, t); |
200 | 209 | ||
201 | t->next = *tp; | 210 | t->next = *tp; |
202 | write_lock_bh(&ipip_lock); | 211 | write_lock_bh(&ipip_lock); |
@@ -204,15 +213,17 @@ static void ipip_tunnel_link(struct ip_tunnel *t) | |||
204 | write_unlock_bh(&ipip_lock); | 213 | write_unlock_bh(&ipip_lock); |
205 | } | 214 | } |
206 | 215 | ||
207 | static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 216 | static struct ip_tunnel * ipip_tunnel_locate(struct net *net, |
217 | struct ip_tunnel_parm *parms, int create) | ||
208 | { | 218 | { |
209 | __be32 remote = parms->iph.daddr; | 219 | __be32 remote = parms->iph.daddr; |
210 | __be32 local = parms->iph.saddr; | 220 | __be32 local = parms->iph.saddr; |
211 | struct ip_tunnel *t, **tp, *nt; | 221 | struct ip_tunnel *t, **tp, *nt; |
212 | struct net_device *dev; | 222 | struct net_device *dev; |
213 | char name[IFNAMSIZ]; | 223 | char name[IFNAMSIZ]; |
224 | struct ipip_net *ipn = net_generic(net, ipip_net_id); | ||
214 | 225 | ||
215 | for (tp = __ipip_bucket(parms); (t = *tp) != NULL; tp = &t->next) { | 226 | for (tp = __ipip_bucket(ipn, parms); (t = *tp) != NULL; tp = &t->next) { |
216 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) | 227 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) |
217 | return t; | 228 | return t; |
218 | } | 229 | } |
@@ -228,6 +239,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c | |||
228 | if (dev == NULL) | 239 | if (dev == NULL) |
229 | return NULL; | 240 | return NULL; |
230 | 241 | ||
242 | dev_net_set(dev, net); | ||
243 | |||
231 | if (strchr(name, '%')) { | 244 | if (strchr(name, '%')) { |
232 | if (dev_alloc_name(dev, name) < 0) | 245 | if (dev_alloc_name(dev, name) < 0) |
233 | goto failed_free; | 246 | goto failed_free; |
@@ -241,7 +254,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c | |||
241 | goto failed_free; | 254 | goto failed_free; |
242 | 255 | ||
243 | dev_hold(dev); | 256 | dev_hold(dev); |
244 | ipip_tunnel_link(nt); | 257 | ipip_tunnel_link(ipn, nt); |
245 | return nt; | 258 | return nt; |
246 | 259 | ||
247 | failed_free: | 260 | failed_free: |
@@ -251,12 +264,15 @@ failed_free: | |||
251 | 264 | ||
252 | static void ipip_tunnel_uninit(struct net_device *dev) | 265 | static void ipip_tunnel_uninit(struct net_device *dev) |
253 | { | 266 | { |
254 | if (dev == ipip_fb_tunnel_dev) { | 267 | struct net *net = dev_net(dev); |
268 | struct ipip_net *ipn = net_generic(net, ipip_net_id); | ||
269 | |||
270 | if (dev == ipn->fb_tunnel_dev) { | ||
255 | write_lock_bh(&ipip_lock); | 271 | write_lock_bh(&ipip_lock); |
256 | tunnels_wc[0] = NULL; | 272 | ipn->tunnels_wc[0] = NULL; |
257 | write_unlock_bh(&ipip_lock); | 273 | write_unlock_bh(&ipip_lock); |
258 | } else | 274 | } else |
259 | ipip_tunnel_unlink(netdev_priv(dev)); | 275 | ipip_tunnel_unlink(ipn, netdev_priv(dev)); |
260 | dev_put(dev); | 276 | dev_put(dev); |
261 | } | 277 | } |
262 | 278 | ||
@@ -305,7 +321,7 @@ static int ipip_err(struct sk_buff *skb, u32 info) | |||
305 | err = -ENOENT; | 321 | err = -ENOENT; |
306 | 322 | ||
307 | read_lock(&ipip_lock); | 323 | read_lock(&ipip_lock); |
308 | t = ipip_tunnel_lookup(iph->daddr, iph->saddr); | 324 | t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); |
309 | if (t == NULL || t->parms.iph.daddr == 0) | 325 | if (t == NULL || t->parms.iph.daddr == 0) |
310 | goto out; | 326 | goto out; |
311 | 327 | ||
@@ -401,7 +417,7 @@ out: | |||
401 | fl.fl4_daddr = eiph->saddr; | 417 | fl.fl4_daddr = eiph->saddr; |
402 | fl.fl4_tos = RT_TOS(eiph->tos); | 418 | fl.fl4_tos = RT_TOS(eiph->tos); |
403 | fl.proto = IPPROTO_IPIP; | 419 | fl.proto = IPPROTO_IPIP; |
404 | if (ip_route_output_key(&init_net, &rt, &key)) { | 420 | if (ip_route_output_key(dev_net(skb->dev), &rt, &key)) { |
405 | kfree_skb(skb2); | 421 | kfree_skb(skb2); |
406 | return 0; | 422 | return 0; |
407 | } | 423 | } |
@@ -414,7 +430,7 @@ out: | |||
414 | fl.fl4_daddr = eiph->daddr; | 430 | fl.fl4_daddr = eiph->daddr; |
415 | fl.fl4_src = eiph->saddr; | 431 | fl.fl4_src = eiph->saddr; |
416 | fl.fl4_tos = eiph->tos; | 432 | fl.fl4_tos = eiph->tos; |
417 | if (ip_route_output_key(&init_net, &rt, &fl) || | 433 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || |
418 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { | 434 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { |
419 | ip_rt_put(rt); | 435 | ip_rt_put(rt); |
420 | kfree_skb(skb2); | 436 | kfree_skb(skb2); |
@@ -465,7 +481,8 @@ static int ipip_rcv(struct sk_buff *skb) | |||
465 | const struct iphdr *iph = ip_hdr(skb); | 481 | const struct iphdr *iph = ip_hdr(skb); |
466 | 482 | ||
467 | read_lock(&ipip_lock); | 483 | read_lock(&ipip_lock); |
468 | if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { | 484 | if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev), |
485 | iph->saddr, iph->daddr)) != NULL) { | ||
469 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 486 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
470 | read_unlock(&ipip_lock); | 487 | read_unlock(&ipip_lock); |
471 | kfree_skb(skb); | 488 | kfree_skb(skb); |
@@ -528,7 +545,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
528 | 545 | ||
529 | if (!dst) { | 546 | if (!dst) { |
530 | /* NBMA tunnel */ | 547 | /* NBMA tunnel */ |
531 | if ((rt = (struct rtable*)skb->dst) == NULL) { | 548 | if ((rt = skb->rtable) == NULL) { |
532 | tunnel->stat.tx_fifo_errors++; | 549 | tunnel->stat.tx_fifo_errors++; |
533 | goto tx_error; | 550 | goto tx_error; |
534 | } | 551 | } |
@@ -543,7 +560,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
543 | .saddr = tiph->saddr, | 560 | .saddr = tiph->saddr, |
544 | .tos = RT_TOS(tos) } }, | 561 | .tos = RT_TOS(tos) } }, |
545 | .proto = IPPROTO_IPIP }; | 562 | .proto = IPPROTO_IPIP }; |
546 | if (ip_route_output_key(&init_net, &rt, &fl)) { | 563 | if (ip_route_output_key(dev_net(dev), &rt, &fl)) { |
547 | tunnel->stat.tx_carrier_errors++; | 564 | tunnel->stat.tx_carrier_errors++; |
548 | goto tx_error_icmp; | 565 | goto tx_error_icmp; |
549 | } | 566 | } |
@@ -664,7 +681,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev) | |||
664 | .tos = RT_TOS(iph->tos) } }, | 681 | .tos = RT_TOS(iph->tos) } }, |
665 | .proto = IPPROTO_IPIP }; | 682 | .proto = IPPROTO_IPIP }; |
666 | struct rtable *rt; | 683 | struct rtable *rt; |
667 | if (!ip_route_output_key(&init_net, &rt, &fl)) { | 684 | if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { |
668 | tdev = rt->u.dst.dev; | 685 | tdev = rt->u.dst.dev; |
669 | ip_rt_put(rt); | 686 | ip_rt_put(rt); |
670 | } | 687 | } |
@@ -672,7 +689,7 @@ static void ipip_tunnel_bind_dev(struct net_device *dev) | |||
672 | } | 689 | } |
673 | 690 | ||
674 | if (!tdev && tunnel->parms.link) | 691 | if (!tdev && tunnel->parms.link) |
675 | tdev = __dev_get_by_index(&init_net, tunnel->parms.link); | 692 | tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); |
676 | 693 | ||
677 | if (tdev) { | 694 | if (tdev) { |
678 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); | 695 | dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); |
@@ -687,16 +704,18 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
687 | int err = 0; | 704 | int err = 0; |
688 | struct ip_tunnel_parm p; | 705 | struct ip_tunnel_parm p; |
689 | struct ip_tunnel *t; | 706 | struct ip_tunnel *t; |
707 | struct net *net = dev_net(dev); | ||
708 | struct ipip_net *ipn = net_generic(net, ipip_net_id); | ||
690 | 709 | ||
691 | switch (cmd) { | 710 | switch (cmd) { |
692 | case SIOCGETTUNNEL: | 711 | case SIOCGETTUNNEL: |
693 | t = NULL; | 712 | t = NULL; |
694 | if (dev == ipip_fb_tunnel_dev) { | 713 | if (dev == ipn->fb_tunnel_dev) { |
695 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | 714 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { |
696 | err = -EFAULT; | 715 | err = -EFAULT; |
697 | break; | 716 | break; |
698 | } | 717 | } |
699 | t = ipip_tunnel_locate(&p, 0); | 718 | t = ipip_tunnel_locate(net, &p, 0); |
700 | } | 719 | } |
701 | if (t == NULL) | 720 | if (t == NULL) |
702 | t = netdev_priv(dev); | 721 | t = netdev_priv(dev); |
@@ -722,9 +741,9 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
722 | if (p.iph.ttl) | 741 | if (p.iph.ttl) |
723 | p.iph.frag_off |= htons(IP_DF); | 742 | p.iph.frag_off |= htons(IP_DF); |
724 | 743 | ||
725 | t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL); | 744 | t = ipip_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); |
726 | 745 | ||
727 | if (dev != ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 746 | if (dev != ipn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
728 | if (t != NULL) { | 747 | if (t != NULL) { |
729 | if (t->dev != dev) { | 748 | if (t->dev != dev) { |
730 | err = -EEXIST; | 749 | err = -EEXIST; |
@@ -737,12 +756,12 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
737 | break; | 756 | break; |
738 | } | 757 | } |
739 | t = netdev_priv(dev); | 758 | t = netdev_priv(dev); |
740 | ipip_tunnel_unlink(t); | 759 | ipip_tunnel_unlink(ipn, t); |
741 | t->parms.iph.saddr = p.iph.saddr; | 760 | t->parms.iph.saddr = p.iph.saddr; |
742 | t->parms.iph.daddr = p.iph.daddr; | 761 | t->parms.iph.daddr = p.iph.daddr; |
743 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 762 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
744 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 763 | memcpy(dev->broadcast, &p.iph.daddr, 4); |
745 | ipip_tunnel_link(t); | 764 | ipip_tunnel_link(ipn, t); |
746 | netdev_state_change(dev); | 765 | netdev_state_change(dev); |
747 | } | 766 | } |
748 | } | 767 | } |
@@ -770,15 +789,15 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
770 | if (!capable(CAP_NET_ADMIN)) | 789 | if (!capable(CAP_NET_ADMIN)) |
771 | goto done; | 790 | goto done; |
772 | 791 | ||
773 | if (dev == ipip_fb_tunnel_dev) { | 792 | if (dev == ipn->fb_tunnel_dev) { |
774 | err = -EFAULT; | 793 | err = -EFAULT; |
775 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | 794 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) |
776 | goto done; | 795 | goto done; |
777 | err = -ENOENT; | 796 | err = -ENOENT; |
778 | if ((t = ipip_tunnel_locate(&p, 0)) == NULL) | 797 | if ((t = ipip_tunnel_locate(net, &p, 0)) == NULL) |
779 | goto done; | 798 | goto done; |
780 | err = -EPERM; | 799 | err = -EPERM; |
781 | if (t->dev == ipip_fb_tunnel_dev) | 800 | if (t->dev == ipn->fb_tunnel_dev) |
782 | goto done; | 801 | goto done; |
783 | dev = t->dev; | 802 | dev = t->dev; |
784 | } | 803 | } |
@@ -822,6 +841,7 @@ static void ipip_tunnel_setup(struct net_device *dev) | |||
822 | dev->flags = IFF_NOARP; | 841 | dev->flags = IFF_NOARP; |
823 | dev->iflink = 0; | 842 | dev->iflink = 0; |
824 | dev->addr_len = 4; | 843 | dev->addr_len = 4; |
844 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
825 | } | 845 | } |
826 | 846 | ||
827 | static int ipip_tunnel_init(struct net_device *dev) | 847 | static int ipip_tunnel_init(struct net_device *dev) |
@@ -841,10 +861,11 @@ static int ipip_tunnel_init(struct net_device *dev) | |||
841 | return 0; | 861 | return 0; |
842 | } | 862 | } |
843 | 863 | ||
844 | static int __init ipip_fb_tunnel_init(struct net_device *dev) | 864 | static int ipip_fb_tunnel_init(struct net_device *dev) |
845 | { | 865 | { |
846 | struct ip_tunnel *tunnel = netdev_priv(dev); | 866 | struct ip_tunnel *tunnel = netdev_priv(dev); |
847 | struct iphdr *iph = &tunnel->parms.iph; | 867 | struct iphdr *iph = &tunnel->parms.iph; |
868 | struct ipip_net *ipn = net_generic(dev_net(dev), ipip_net_id); | ||
848 | 869 | ||
849 | tunnel->dev = dev; | 870 | tunnel->dev = dev; |
850 | strcpy(tunnel->parms.name, dev->name); | 871 | strcpy(tunnel->parms.name, dev->name); |
@@ -854,7 +875,7 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev) | |||
854 | iph->ihl = 5; | 875 | iph->ihl = 5; |
855 | 876 | ||
856 | dev_hold(dev); | 877 | dev_hold(dev); |
857 | tunnels_wc[0] = tunnel; | 878 | ipn->tunnels_wc[0] = tunnel; |
858 | return 0; | 879 | return 0; |
859 | } | 880 | } |
860 | 881 | ||
@@ -867,50 +888,98 @@ static struct xfrm_tunnel ipip_handler = { | |||
867 | static char banner[] __initdata = | 888 | static char banner[] __initdata = |
868 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; | 889 | KERN_INFO "IPv4 over IPv4 tunneling driver\n"; |
869 | 890 | ||
870 | static int __init ipip_init(void) | 891 | static void ipip_destroy_tunnels(struct ipip_net *ipn) |
892 | { | ||
893 | int prio; | ||
894 | |||
895 | for (prio = 1; prio < 4; prio++) { | ||
896 | int h; | ||
897 | for (h = 0; h < HASH_SIZE; h++) { | ||
898 | struct ip_tunnel *t; | ||
899 | while ((t = ipn->tunnels[prio][h]) != NULL) | ||
900 | unregister_netdevice(t->dev); | ||
901 | } | ||
902 | } | ||
903 | } | ||
904 | |||
905 | static int ipip_init_net(struct net *net) | ||
871 | { | 906 | { |
872 | int err; | 907 | int err; |
908 | struct ipip_net *ipn; | ||
873 | 909 | ||
874 | printk(banner); | 910 | err = -ENOMEM; |
911 | ipn = kzalloc(sizeof(struct ipip_net), GFP_KERNEL); | ||
912 | if (ipn == NULL) | ||
913 | goto err_alloc; | ||
875 | 914 | ||
876 | if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { | 915 | err = net_assign_generic(net, ipip_net_id, ipn); |
877 | printk(KERN_INFO "ipip init: can't register tunnel\n"); | 916 | if (err < 0) |
878 | return -EAGAIN; | 917 | goto err_assign; |
879 | } | ||
880 | 918 | ||
881 | ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), | 919 | ipn->tunnels[0] = ipn->tunnels_wc; |
920 | ipn->tunnels[1] = ipn->tunnels_l; | ||
921 | ipn->tunnels[2] = ipn->tunnels_r; | ||
922 | ipn->tunnels[3] = ipn->tunnels_r_l; | ||
923 | |||
924 | ipn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), | ||
882 | "tunl0", | 925 | "tunl0", |
883 | ipip_tunnel_setup); | 926 | ipip_tunnel_setup); |
884 | if (!ipip_fb_tunnel_dev) { | 927 | if (!ipn->fb_tunnel_dev) { |
885 | err = -ENOMEM; | 928 | err = -ENOMEM; |
886 | goto err1; | 929 | goto err_alloc_dev; |
887 | } | 930 | } |
888 | 931 | ||
889 | ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init; | 932 | ipn->fb_tunnel_dev->init = ipip_fb_tunnel_init; |
933 | dev_net_set(ipn->fb_tunnel_dev, net); | ||
934 | |||
935 | if ((err = register_netdev(ipn->fb_tunnel_dev))) | ||
936 | goto err_reg_dev; | ||
937 | |||
938 | return 0; | ||
890 | 939 | ||
891 | if ((err = register_netdev(ipip_fb_tunnel_dev))) | 940 | err_reg_dev: |
892 | goto err2; | 941 | free_netdev(ipn->fb_tunnel_dev); |
893 | out: | 942 | err_alloc_dev: |
943 | /* nothing */ | ||
944 | err_assign: | ||
945 | kfree(ipn); | ||
946 | err_alloc: | ||
894 | return err; | 947 | return err; |
895 | err2: | ||
896 | free_netdev(ipip_fb_tunnel_dev); | ||
897 | err1: | ||
898 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
899 | goto out; | ||
900 | } | 948 | } |
901 | 949 | ||
902 | static void __exit ipip_destroy_tunnels(void) | 950 | static void ipip_exit_net(struct net *net) |
903 | { | 951 | { |
904 | int prio; | 952 | struct ipip_net *ipn; |
905 | 953 | ||
906 | for (prio = 1; prio < 4; prio++) { | 954 | ipn = net_generic(net, ipip_net_id); |
907 | int h; | 955 | rtnl_lock(); |
908 | for (h = 0; h < HASH_SIZE; h++) { | 956 | ipip_destroy_tunnels(ipn); |
909 | struct ip_tunnel *t; | 957 | unregister_netdevice(ipn->fb_tunnel_dev); |
910 | while ((t = tunnels[prio][h]) != NULL) | 958 | rtnl_unlock(); |
911 | unregister_netdevice(t->dev); | 959 | kfree(ipn); |
912 | } | 960 | } |
961 | |||
962 | static struct pernet_operations ipip_net_ops = { | ||
963 | .init = ipip_init_net, | ||
964 | .exit = ipip_exit_net, | ||
965 | }; | ||
966 | |||
967 | static int __init ipip_init(void) | ||
968 | { | ||
969 | int err; | ||
970 | |||
971 | printk(banner); | ||
972 | |||
973 | if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { | ||
974 | printk(KERN_INFO "ipip init: can't register tunnel\n"); | ||
975 | return -EAGAIN; | ||
913 | } | 976 | } |
977 | |||
978 | err = register_pernet_gen_device(&ipip_net_id, &ipip_net_ops); | ||
979 | if (err) | ||
980 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
981 | |||
982 | return err; | ||
914 | } | 983 | } |
915 | 984 | ||
916 | static void __exit ipip_fini(void) | 985 | static void __exit ipip_fini(void) |
@@ -918,10 +987,7 @@ static void __exit ipip_fini(void) | |||
918 | if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) | 987 | if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) |
919 | printk(KERN_INFO "ipip close: can't deregister tunnel\n"); | 988 | printk(KERN_INFO "ipip close: can't deregister tunnel\n"); |
920 | 989 | ||
921 | rtnl_lock(); | 990 | unregister_pernet_gen_device(ipip_net_id, &ipip_net_ops); |
922 | ipip_destroy_tunnels(); | ||
923 | unregister_netdevice(ipip_fb_tunnel_dev); | ||
924 | rtnl_unlock(); | ||
925 | } | 991 | } |
926 | 992 | ||
927 | module_init(ipip_init); | 993 | module_init(ipip_init); |