Commit f845392f authored by David S. Miller's avatar David S. Miller

Merge bk://kernel.bkbits.net/jmorris/ipv6-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 6fee4e4e 5107a690
......@@ -6,6 +6,8 @@
#define MAX_RTR_SOLICITATIONS 3
#define RTR_SOLICITATION_INTERVAL (4*HZ)
#define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
#define TEMP_VALID_LIFETIME (7*86400)
#define TEMP_PREFERRED_LIFETIME (86400)
#define REGEN_MAX_RETRY (5)
......
......@@ -608,7 +608,9 @@ static void neigh_periodic_timer(unsigned long arg)
static __inline__ int neigh_max_probes(struct neighbour *n)
{
struct neigh_parms *p = n->parms;
return p->ucast_probes + p->app_probes + p->mcast_probes;
return (n->nud_state & NUD_PROBE ?
p->ucast_probes :
p->ucast_probes + p->app_probes + p->mcast_probes);
}
......
......@@ -1299,7 +1299,6 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
{
struct prefix_info *pinfo;
struct rt6_info *rt;
__u32 valid_lft;
__u32 prefered_lft;
int addr_type;
......@@ -1355,33 +1354,33 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
else
rt_expires = jiffies + valid_lft * HZ;
rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (rt->rt6i_flags&RTF_EXPIRES) {
if (pinfo->onlink == 0 || valid_lft == 0) {
ip6_del_rt(rt, NULL, NULL);
rt = NULL;
} else {
rt->rt6i_expires = rt_expires;
if (pinfo->onlink) {
struct rt6_info *rt;
rt = rt6_lookup(&pinfo->prefix, NULL, dev->ifindex, 1);
if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (rt->rt6i_flags&RTF_EXPIRES) {
if (valid_lft == 0) {
ip6_del_rt(rt, NULL, NULL);
rt = NULL;
} else {
rt->rt6i_expires = rt_expires;
}
}
} else if (valid_lft) {
addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES);
}
} else if (pinfo->onlink && valid_lft) {
addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES);
if (rt)
dst_release(&rt->u.dst);
}
if (rt)
dst_release(&rt->u.dst);
/* Try to figure out our local address for this prefix */
if (pinfo->autoconf && in6_dev->cnf.autoconf) {
struct inet6_ifaddr * ifp;
struct in6_addr addr;
int plen;
int create = 0;
plen = pinfo->prefix_len >> 3;
int create = 0, update_lft = 0;
if (pinfo->prefix_len == 64) {
memcpy(&addr, &pinfo->prefix, 8);
......@@ -1415,32 +1414,54 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
return;
}
create = 1;
update_lft = create = 1;
addrconf_dad_start(ifp);
}
if (ifp && valid_lft == 0) {
ipv6_del_addr(ifp);
ifp = NULL;
}
if (ifp) {
int flags;
unsigned long now;
#ifdef CONFIG_IPV6_PRIVACY
struct inet6_ifaddr *ift;
#endif
u32 stored_lft;
/* update lifetime (RFC2462 5.5.3 e) */
spin_lock(&ifp->lock);
ifp->valid_lft = valid_lft;
ifp->prefered_lft = prefered_lft;
ifp->tstamp = jiffies;
flags = ifp->flags;
ifp->flags &= ~IFA_F_DEPRECATED;
spin_unlock(&ifp->lock);
if (!(flags&IFA_F_TENTATIVE))
ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
0 : RTM_NEWADDR, ifp);
now = jiffies;
if (ifp->valid_lft > (now - ifp->tstamp) / HZ)
stored_lft = ifp->valid_lft - (now - ifp->tstamp) / HZ;
else
stored_lft = 0;
if (!update_lft && stored_lft) {
if (valid_lft > MIN_VALID_LIFETIME ||
valid_lft > stored_lft)
update_lft = 1;
else if (stored_lft <= MIN_VALID_LIFETIME) {
/* valid_lft <= stored_lft is always true */
/* XXX: IPsec */
update_lft = 0;
} else {
valid_lft = MIN_VALID_LIFETIME;
if (valid_lft < prefered_lft)
prefered_lft = valid_lft;
update_lft = 1;
}
}
if (update_lft) {
ifp->valid_lft = valid_lft;
ifp->prefered_lft = prefered_lft;
ifp->tstamp = now;
flags = ifp->flags;
ifp->flags &= ~IFA_F_DEPRECATED;
spin_unlock(&ifp->lock);
if (!(flags&IFA_F_TENTATIVE))
ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
0 : RTM_NEWADDR, ifp);
} else
spin_unlock(&ifp->lock);
#ifdef CONFIG_IPV6_PRIVACY
read_lock_bh(&in6_dev->lock);
......
......@@ -1239,7 +1239,6 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
memcpy(np->cork.opt, opt, opt->tot_len);
inet->cork.flags |= IPCORK_OPT;
/* need source address above miyazawa*/
exthdrlen += opt->opt_flen ? opt->opt_flen : 0;
}
dst_hold(&rt->u.dst);
np->cork.rt = rt;
......@@ -1252,6 +1251,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
length += exthdrlen;
transhdrlen += exthdrlen;
}
exthdrlen += opt ? opt->opt_flen : 0;
} else {
rt = np->cork.rt;
if (inet->cork.flags & IPCORK_OPT)
......
......@@ -624,6 +624,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
if (msg->msg_controllen) {
opt = &opt_space;
memset(opt, 0, sizeof(struct ipv6_txoptions));
opt->tot_len = sizeof(struct ipv6_txoptions);
err = datagram_send_ctl(msg, &fl, opt, &hlimit);
if (err < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment