aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-15 12:40:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-15 12:40:05 -0400
commit2ed0e21b30b53d3a94e204196e523e6c8f732b56 (patch)
treede2635426477d86338a9469ce09ba0626052288f /net/ipv6/sit.c
parent0fa213310cd8fa7a51071cdcf130e26fa56e9549 (diff)
parent9cbc1cb8cd46ce1f7645b9de249b2ce8460129bb (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.c118
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 {
80static DEFINE_RWLOCK(ipip6_lock); 81static DEFINE_RWLOCK(ipip6_lock);
81 82
82static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, 83static 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
226static 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
212static struct ip_tunnel_prl_entry * 264static 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);
321update: 378update:
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);
324out: 389out:
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 }
356out: 427out:
357 write_unlock(&ipip6_lock); 428 write_unlock(&ipip6_lock);
358 return 0; 429 return err;
359} 430}
360 431
361static int 432static 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.