提交 64506929 编写于 作者: S Sascha Hlusiak 提交者: David S. Miller

sit: stateless autoconf for isatap

be sent periodically. The rs_delay can be speficied when adding the
PRL entry and defaults to 15 minutes.

The RS is sent from every link local adress that's assigned to the
tunnel interface. It's directed to the (guessed) linklocal address
of the router and is sent through the tunnel.

Better: send to ff02::2 encapsuled in unicast directed to router-v4.
Signed-off-by: NSascha Hlusiak <contact@saschahlusiak.de>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 9af28511
...@@ -44,7 +44,7 @@ struct ip_tunnel_prl { ...@@ -44,7 +44,7 @@ struct ip_tunnel_prl {
__u16 flags; __u16 flags;
__u16 __reserved; __u16 __reserved;
__u32 datalen; __u32 datalen;
__u32 __reserved2; __u32 rs_delay;
/* data follows */ /* data follows */
}; };
......
...@@ -28,11 +28,18 @@ struct ip_tunnel ...@@ -28,11 +28,18 @@ struct ip_tunnel
unsigned int prl_count; /* # of entries in PRL */ unsigned int prl_count; /* # of entries in PRL */
}; };
/* ISATAP: default interval between RS in secondy */
#define IPTUNNEL_RS_DEFAULT_DELAY (900)
struct ip_tunnel_prl_entry struct ip_tunnel_prl_entry
{ {
struct ip_tunnel_prl_entry *next; struct ip_tunnel_prl_entry *next;
__be32 addr; __be32 addr;
u16 flags; u16 flags;
unsigned long rs_delay;
struct timer_list rs_timer;
struct ip_tunnel *tunnel;
spinlock_t lock;
}; };
#define IPTUNNEL_XMIT() do { \ #define IPTUNNEL_XMIT() do { \
......
...@@ -658,6 +658,7 @@ void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, ...@@ -658,6 +658,7 @@ void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
&icmp6h, NULL, &icmp6h, NULL,
send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0); send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0);
} }
EXPORT_SYMBOL(ndisc_send_rs);
static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb) static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* Roger Venning <r.venning@telstra.com>: 6to4 support * Roger Venning <r.venning@telstra.com>: 6to4 support
* Nate Thompson <nate@thebog.net>: 6to4 support * Nate Thompson <nate@thebog.net>: 6to4 support
* Fred Templin <fred.l.templin@boeing.com>: isatap support * Fred Templin <fred.l.templin@boeing.com>: isatap support
* Sascha Hlusiak <mail@saschahlusiak.de>: stateless autoconf for isatap
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -222,6 +223,44 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, ...@@ -222,6 +223,44 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net,
return NULL; return NULL;
} }
static void ipip6_tunnel_rs_timer(unsigned long data)
{
struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *) data;
struct inet6_dev *ifp;
struct inet6_ifaddr *addr;
spin_lock(&p->lock);
ifp = __in6_dev_get(p->tunnel->dev);
read_lock_bh(&ifp->lock);
for (addr = ifp->addr_list; addr; addr = addr->if_next) {
struct in6_addr rtr;
if (!(ipv6_addr_type(&addr->addr) & IPV6_ADDR_LINKLOCAL))
continue;
/* Send RS to guessed linklocal address of router
*
* Better: send to ff02::2 encapsuled in unicast directly
* to router-v4 instead of guessing the v6 address.
*
* Cisco/Windows seem to not set the u/l bit correctly,
* so we won't guess right.
*/
ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0);
if (!__ipv6_isatap_ifid(rtr.s6_addr + 8,
p->addr)) {
ndisc_send_rs(p->tunnel->dev, &addr->addr, &rtr);
}
}
read_unlock_bh(&ifp->lock);
mod_timer(&p->rs_timer, jiffies + HZ * p->rs_delay);
spin_unlock(&p->lock);
return;
}
static struct ip_tunnel_prl_entry * static struct ip_tunnel_prl_entry *
__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
{ {
...@@ -280,6 +319,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, ...@@ -280,6 +319,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
continue; continue;
kp[c].addr = prl->addr; kp[c].addr = prl->addr;
kp[c].flags = prl->flags; kp[c].flags = prl->flags;
kp[c].rs_delay = prl->rs_delay;
c++; c++;
if (kprl.addr != htonl(INADDR_ANY)) if (kprl.addr != htonl(INADDR_ANY))
break; break;
...@@ -329,11 +369,23 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) ...@@ -329,11 +369,23 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
} }
p->next = t->prl; p->next = t->prl;
p->tunnel = t;
t->prl = p; t->prl = p;
t->prl_count++; t->prl_count++;
spin_lock_init(&p->lock);
setup_timer(&p->rs_timer, ipip6_tunnel_rs_timer, (unsigned long) p);
update: update:
p->addr = a->addr; p->addr = a->addr;
p->flags = a->flags; p->flags = a->flags;
p->rs_delay = a->rs_delay;
if (p->rs_delay == 0)
p->rs_delay = IPTUNNEL_RS_DEFAULT_DELAY;
spin_lock(&p->lock);
del_timer(&p->rs_timer);
if (p->flags & PRL_DEFAULT)
mod_timer(&p->rs_timer, jiffies + 1);
spin_unlock(&p->lock);
out: out:
write_unlock(&ipip6_lock); write_unlock(&ipip6_lock);
return err; return err;
...@@ -352,6 +404,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) ...@@ -352,6 +404,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
if ((*p)->addr == a->addr) { if ((*p)->addr == a->addr) {
x = *p; x = *p;
*p = x->next; *p = x->next;
spin_lock(&x->lock);
del_timer(&x->rs_timer);
spin_unlock(&x->lock);
kfree(x); kfree(x);
t->prl_count--; t->prl_count--;
goto out; goto out;
...@@ -362,6 +417,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) ...@@ -362,6 +417,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
while (t->prl) { while (t->prl) {
x = t->prl; x = t->prl;
t->prl = t->prl->next; t->prl = t->prl->next;
spin_lock(&x->lock);
del_timer(&x->rs_timer);
spin_unlock(&x->lock);
kfree(x); kfree(x);
t->prl_count--; t->prl_count--;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册