src_addr = solicited_addr;
in6_ifa_put(ifp);
} else {
- if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
+ if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0))
return;
src_addr = &tmpaddr;
}
}
}
-static void ndisc_recv_rs(struct sk_buff *skb)
-{
- struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw;
- unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
- struct neighbour *neigh;
- struct inet6_dev *idev;
- struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
- struct ndisc_options ndopts;
- u8 *lladdr = NULL;
- int lladdrlen = 0;
-
- if (skb->len < sizeof(*rs_msg))
- return;
-
- idev = in6_dev_get(skb->dev);
- if (!idev) {
- if (net_ratelimit())
- ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
- return;
- }
-
- /* Don't accept RS if we're not in router mode */
- if (!idev->cnf.forwarding)
- goto out;
-
- /*
- * Don't update NCE if src = ::;
- * this implies that the source node has no ip address assigned yet.
- */
- if (ipv6_addr_any(saddr))
- goto out;
-
- /* Parse ND options */
- if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
- if (net_ratelimit())
- ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
- goto out;
- }
-
- if (ndopts.nd_opts_src_lladdr) {
- lladdr = (u8 *)(ndopts.nd_opts_src_lladdr + 1);
- lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
- if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len))
- goto out;
- }
-
- neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
- if (neigh) {
- neigh_update(neigh, lladdr, NUD_STALE,
- NEIGH_UPDATE_F_WEAK_OVERRIDE|
- NEIGH_UPDATE_F_OVERRIDE|
- NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
- neigh_release(neigh);
- }
-out:
- in6_dev_put(idev);
-}
-
static void ndisc_router_discovery(struct sk_buff *skb)
{
struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
return;
}
neigh->flags |= NTF_ROUTER;
+
+ /*
+ * If we where using an "all destinations on link" route
+ * delete it
+ */
+
+ rt6_purge_dflt_routers(RTF_ALLONLINK);
}
if (rt)
return;
}
- if (ipv6_addr_equal(dest, target)) {
+ if (ipv6_addr_cmp(dest, target) == 0) {
on_link = 1;
} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
ND_PRINTK2(KERN_WARNING
ndisc_recv_na(skb);
break;
- case NDISC_ROUTER_SOLICITATION:
- ndisc_recv_rs(skb);
- break;
-
case NDISC_ROUTER_ADVERTISEMENT:
ndisc_router_discovery(skb);
break;