diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-15 12:40:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-15 12:40:05 -0400 |
commit | 2ed0e21b30b53d3a94e204196e523e6c8f732b56 (patch) | |
tree | de2635426477d86338a9469ce09ba0626052288f /net/ipv6/sit.c | |
parent | 0fa213310cd8fa7a51071cdcf130e26fa56e9549 (diff) | |
parent | 9cbc1cb8cd46ce1f7645b9de249b2ce8460129bb (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1244 commits)
pkt_sched: Rename PSCHED_US2NS and PSCHED_NS2US
ipv4: Fix fib_trie rebalancing
Bluetooth: Fix issue with uninitialized nsh.type in DTL-1 driver
Bluetooth: Fix Kconfig issue with RFKILL integration
PIM-SM: namespace changes
ipv4: update ARPD help text
net: use a deferred timer in rt_check_expire
ieee802154: fix kconfig bool/tristate muckup
bonding: initialization rework
bonding: use is_zero_ether_addr
bonding: network device names are case sensative
bonding: elminate bad refcount code
bonding: fix style issues
bonding: fix destructor
bonding: remove bonding read/write semaphore
bonding: initialize before registration
bonding: bond_create always called with default parameters
x_tables: Convert printk to pr_err
netfilter: conntrack: optional reliable conntrack event delivery
list_nulls: add hlist_nulls_add_head and hlist_nulls_del
...
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r-- | net/ipv6/sit.c | 118 |
1 files changed, 96 insertions, 22 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 664ab82e03b2..68e52308e552 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * Roger Venning <r.venning@telstra.com>: 6to4 support | 15 | * Roger Venning <r.venning@telstra.com>: 6to4 support |
16 | * Nate Thompson <nate@thebog.net>: 6to4 support | 16 | * Nate Thompson <nate@thebog.net>: 6to4 support |
17 | * Fred Templin <fred.l.templin@boeing.com>: isatap support | 17 | * Fred Templin <fred.l.templin@boeing.com>: isatap support |
18 | * Sascha Hlusiak <mail@saschahlusiak.de>: stateless autoconf for isatap | ||
18 | */ | 19 | */ |
19 | 20 | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
@@ -80,7 +81,7 @@ struct sit_net { | |||
80 | static DEFINE_RWLOCK(ipip6_lock); | 81 | static DEFINE_RWLOCK(ipip6_lock); |
81 | 82 | ||
82 | static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, | 83 | static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, |
83 | __be32 remote, __be32 local) | 84 | struct net_device *dev, __be32 remote, __be32 local) |
84 | { | 85 | { |
85 | unsigned h0 = HASH(remote); | 86 | unsigned h0 = HASH(remote); |
86 | unsigned h1 = HASH(local); | 87 | unsigned h1 = HASH(local); |
@@ -89,18 +90,25 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, | |||
89 | 90 | ||
90 | for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) { | 91 | for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) { |
91 | if (local == t->parms.iph.saddr && | 92 | if (local == t->parms.iph.saddr && |
92 | remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 93 | remote == t->parms.iph.daddr && |
94 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | ||
95 | (t->dev->flags & IFF_UP)) | ||
93 | return t; | 96 | return t; |
94 | } | 97 | } |
95 | for (t = sitn->tunnels_r[h0]; t; t = t->next) { | 98 | for (t = sitn->tunnels_r[h0]; t; t = t->next) { |
96 | if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) | 99 | if (remote == t->parms.iph.daddr && |
100 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | ||
101 | (t->dev->flags & IFF_UP)) | ||
97 | return t; | 102 | return t; |
98 | } | 103 | } |
99 | for (t = sitn->tunnels_l[h1]; t; t = t->next) { | 104 | for (t = sitn->tunnels_l[h1]; t; t = t->next) { |
100 | if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) | 105 | if (local == t->parms.iph.saddr && |
106 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | ||
107 | (t->dev->flags & IFF_UP)) | ||
101 | return t; | 108 | return t; |
102 | } | 109 | } |
103 | if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) | 110 | t = sitn->tunnels_wc[0]; |
111 | if ((t != NULL) && (t->dev->flags & IFF_UP)) | ||
104 | return t; | 112 | return t; |
105 | return NULL; | 113 | return NULL; |
106 | } | 114 | } |
@@ -165,8 +173,14 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, | |||
165 | struct sit_net *sitn = net_generic(net, sit_net_id); | 173 | struct sit_net *sitn = net_generic(net, sit_net_id); |
166 | 174 | ||
167 | for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { | 175 | for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { |
168 | if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) | 176 | if (local == t->parms.iph.saddr && |
169 | return t; | 177 | remote == t->parms.iph.daddr && |
178 | parms->link == t->parms.link) { | ||
179 | if (create) | ||
180 | return NULL; | ||
181 | else | ||
182 | return t; | ||
183 | } | ||
170 | } | 184 | } |
171 | if (!create) | 185 | if (!create) |
172 | goto failed; | 186 | goto failed; |
@@ -209,6 +223,44 @@ failed: | |||
209 | return NULL; | 223 | return NULL; |
210 | } | 224 | } |
211 | 225 | ||
226 | static void ipip6_tunnel_rs_timer(unsigned long data) | ||
227 | { | ||
228 | struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *) data; | ||
229 | struct inet6_dev *ifp; | ||
230 | struct inet6_ifaddr *addr; | ||
231 | |||
232 | spin_lock(&p->lock); | ||
233 | ifp = __in6_dev_get(p->tunnel->dev); | ||
234 | |||
235 | read_lock_bh(&ifp->lock); | ||
236 | for (addr = ifp->addr_list; addr; addr = addr->if_next) { | ||
237 | struct in6_addr rtr; | ||
238 | |||
239 | if (!(ipv6_addr_type(&addr->addr) & IPV6_ADDR_LINKLOCAL)) | ||
240 | continue; | ||
241 | |||
242 | /* Send RS to guessed linklocal address of router | ||
243 | * | ||
244 | * Better: send to ff02::2 encapsuled in unicast directly | ||
245 | * to router-v4 instead of guessing the v6 address. | ||
246 | * | ||
247 | * Cisco/Windows seem to not set the u/l bit correctly, | ||
248 | * so we won't guess right. | ||
249 | */ | ||
250 | ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0); | ||
251 | if (!__ipv6_isatap_ifid(rtr.s6_addr + 8, | ||
252 | p->addr)) { | ||
253 | ndisc_send_rs(p->tunnel->dev, &addr->addr, &rtr); | ||
254 | } | ||
255 | } | ||
256 | read_unlock_bh(&ifp->lock); | ||
257 | |||
258 | mod_timer(&p->rs_timer, jiffies + HZ * p->rs_delay); | ||
259 | spin_unlock(&p->lock); | ||
260 | |||
261 | return; | ||
262 | } | ||
263 | |||
212 | static struct ip_tunnel_prl_entry * | 264 | static struct ip_tunnel_prl_entry * |
213 | __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) | 265 | __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) |
214 | { | 266 | { |
@@ -267,6 +319,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, | |||
267 | continue; | 319 | continue; |
268 | kp[c].addr = prl->addr; | 320 | kp[c].addr = prl->addr; |
269 | kp[c].flags = prl->flags; | 321 | kp[c].flags = prl->flags; |
322 | kp[c].rs_delay = prl->rs_delay; | ||
270 | c++; | 323 | c++; |
271 | if (kprl.addr != htonl(INADDR_ANY)) | 324 | if (kprl.addr != htonl(INADDR_ANY)) |
272 | break; | 325 | break; |
@@ -316,11 +369,23 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
316 | } | 369 | } |
317 | 370 | ||
318 | p->next = t->prl; | 371 | p->next = t->prl; |
372 | p->tunnel = t; | ||
319 | t->prl = p; | 373 | t->prl = p; |
320 | t->prl_count++; | 374 | t->prl_count++; |
375 | |||
376 | spin_lock_init(&p->lock); | ||
377 | setup_timer(&p->rs_timer, ipip6_tunnel_rs_timer, (unsigned long) p); | ||
321 | update: | 378 | update: |
322 | p->addr = a->addr; | 379 | p->addr = a->addr; |
323 | p->flags = a->flags; | 380 | p->flags = a->flags; |
381 | p->rs_delay = a->rs_delay; | ||
382 | if (p->rs_delay == 0) | ||
383 | p->rs_delay = IPTUNNEL_RS_DEFAULT_DELAY; | ||
384 | spin_lock(&p->lock); | ||
385 | del_timer(&p->rs_timer); | ||
386 | if (p->flags & PRL_DEFAULT) | ||
387 | mod_timer(&p->rs_timer, jiffies + 1); | ||
388 | spin_unlock(&p->lock); | ||
324 | out: | 389 | out: |
325 | write_unlock(&ipip6_lock); | 390 | write_unlock(&ipip6_lock); |
326 | return err; | 391 | return err; |
@@ -339,6 +404,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
339 | if ((*p)->addr == a->addr) { | 404 | if ((*p)->addr == a->addr) { |
340 | x = *p; | 405 | x = *p; |
341 | *p = x->next; | 406 | *p = x->next; |
407 | spin_lock(&x->lock); | ||
408 | del_timer(&x->rs_timer); | ||
409 | spin_unlock(&x->lock); | ||
342 | kfree(x); | 410 | kfree(x); |
343 | t->prl_count--; | 411 | t->prl_count--; |
344 | goto out; | 412 | goto out; |
@@ -349,13 +417,16 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
349 | while (t->prl) { | 417 | while (t->prl) { |
350 | x = t->prl; | 418 | x = t->prl; |
351 | t->prl = t->prl->next; | 419 | t->prl = t->prl->next; |
420 | spin_lock(&x->lock); | ||
421 | del_timer(&x->rs_timer); | ||
422 | spin_unlock(&x->lock); | ||
352 | kfree(x); | 423 | kfree(x); |
353 | t->prl_count--; | 424 | t->prl_count--; |
354 | } | 425 | } |
355 | } | 426 | } |
356 | out: | 427 | out: |
357 | write_unlock(&ipip6_lock); | 428 | write_unlock(&ipip6_lock); |
358 | return 0; | 429 | return err; |
359 | } | 430 | } |
360 | 431 | ||
361 | static int | 432 | static int |
@@ -446,7 +517,10 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
446 | err = -ENOENT; | 517 | err = -ENOENT; |
447 | 518 | ||
448 | read_lock(&ipip6_lock); | 519 | read_lock(&ipip6_lock); |
449 | t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); | 520 | t = ipip6_tunnel_lookup(dev_net(skb->dev), |
521 | skb->dev, | ||
522 | iph->daddr, | ||
523 | iph->saddr); | ||
450 | if (t == NULL || t->parms.iph.daddr == 0) | 524 | if (t == NULL || t->parms.iph.daddr == 0) |
451 | goto out; | 525 | goto out; |
452 | 526 | ||
@@ -481,8 +555,9 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
481 | iph = ip_hdr(skb); | 555 | iph = ip_hdr(skb); |
482 | 556 | ||
483 | read_lock(&ipip6_lock); | 557 | read_lock(&ipip6_lock); |
484 | if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), | 558 | tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, |
485 | iph->saddr, iph->daddr)) != NULL) { | 559 | iph->saddr, iph->daddr); |
560 | if (tunnel != NULL) { | ||
486 | secpath_reset(skb); | 561 | secpath_reset(skb); |
487 | skb->mac_header = skb->network_header; | 562 | skb->mac_header = skb->network_header; |
488 | skb_reset_network_header(skb); | 563 | skb_reset_network_header(skb); |
@@ -500,8 +575,7 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
500 | tunnel->dev->stats.rx_packets++; | 575 | tunnel->dev->stats.rx_packets++; |
501 | tunnel->dev->stats.rx_bytes += skb->len; | 576 | tunnel->dev->stats.rx_bytes += skb->len; |
502 | skb->dev = tunnel->dev; | 577 | skb->dev = tunnel->dev; |
503 | dst_release(skb->dst); | 578 | skb_dst_drop(skb); |
504 | skb->dst = NULL; | ||
505 | nf_reset(skb); | 579 | nf_reset(skb); |
506 | ipip6_ecn_decapsulate(iph, skb); | 580 | ipip6_ecn_decapsulate(iph, skb); |
507 | netif_rx(skb); | 581 | netif_rx(skb); |
@@ -563,8 +637,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
563 | if (dev->priv_flags & IFF_ISATAP) { | 637 | if (dev->priv_flags & IFF_ISATAP) { |
564 | struct neighbour *neigh = NULL; | 638 | struct neighbour *neigh = NULL; |
565 | 639 | ||
566 | if (skb->dst) | 640 | if (skb_dst(skb)) |
567 | neigh = skb->dst->neighbour; | 641 | neigh = skb_dst(skb)->neighbour; |
568 | 642 | ||
569 | if (neigh == NULL) { | 643 | if (neigh == NULL) { |
570 | if (net_ratelimit()) | 644 | if (net_ratelimit()) |
@@ -588,8 +662,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
588 | if (!dst) { | 662 | if (!dst) { |
589 | struct neighbour *neigh = NULL; | 663 | struct neighbour *neigh = NULL; |
590 | 664 | ||
591 | if (skb->dst) | 665 | if (skb_dst(skb)) |
592 | neigh = skb->dst->neighbour; | 666 | neigh = skb_dst(skb)->neighbour; |
593 | 667 | ||
594 | if (neigh == NULL) { | 668 | if (neigh == NULL) { |
595 | if (net_ratelimit()) | 669 | if (net_ratelimit()) |
@@ -639,7 +713,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
639 | if (tiph->frag_off) | 713 | if (tiph->frag_off) |
640 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); | 714 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); |
641 | else | 715 | else |
642 | mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; | 716 | mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; |
643 | 717 | ||
644 | if (mtu < 68) { | 718 | if (mtu < 68) { |
645 | stats->collisions++; | 719 | stats->collisions++; |
@@ -648,8 +722,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
648 | } | 722 | } |
649 | if (mtu < IPV6_MIN_MTU) | 723 | if (mtu < IPV6_MIN_MTU) |
650 | mtu = IPV6_MIN_MTU; | 724 | mtu = IPV6_MIN_MTU; |
651 | if (tunnel->parms.iph.daddr && skb->dst) | 725 | if (tunnel->parms.iph.daddr && skb_dst(skb)) |
652 | skb->dst->ops->update_pmtu(skb->dst, mtu); | 726 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); |
653 | 727 | ||
654 | if (skb->len > mtu) { | 728 | if (skb->len > mtu) { |
655 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); | 729 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); |
@@ -693,8 +767,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
693 | skb_reset_network_header(skb); | 767 | skb_reset_network_header(skb); |
694 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 768 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
695 | IPCB(skb)->flags = 0; | 769 | IPCB(skb)->flags = 0; |
696 | dst_release(skb->dst); | 770 | skb_dst_drop(skb); |
697 | skb->dst = &rt->u.dst; | 771 | skb_dst_set(skb, &rt->u.dst); |
698 | 772 | ||
699 | /* | 773 | /* |
700 | * Push down and install the IPIP header. | 774 | * Push down and install the IPIP header. |