diff --git a/net/ipv6/route.c b/net/ipv6/route.c index eb3f1e4..cd141a5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -440,9 +440,26 @@ out: } #ifdef CONFIG_IPV6_ROUTER_PREF +struct ndisc_work { + struct work_struct work; + struct in6_addr mcaddr; + struct in6_addr target; + struct net_device *dev; +}; + +static void queue_ndisc(struct work_struct *work) +{ + struct ndisc_work *nw = + container_of(work, struct ndisc_work, work); + ndisc_send_ns(nw->dev, NULL, &nw->target, &nw->mcaddr, NULL); + kfree(nw); +} + static void rt6_probe(struct rt6_info *rt) { struct neighbour *neigh; + struct ndisc_work *nw; + /* * Okay, this does not seem to be appropriate * for now, however, we need to check if it @@ -457,15 +474,18 @@ static void rt6_probe(struct rt6_info *rt) read_lock_bh(&neigh->lock); if (!(neigh->nud_state & NUD_VALID) && time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { - struct in6_addr mcaddr; - struct in6_addr *target; neigh->updated = jiffies; read_unlock_bh(&neigh->lock); - target = (struct in6_addr *)&neigh->primary_key; - addrconf_addr_solict_mult(target, &mcaddr); - ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); + nw = kmalloc(sizeof(*nw), GFP_ATOMIC); + if (nw) { + memcpy(&nw->target, &neigh->primary_key, sizeof(struct in6_addr)); + addrconf_addr_solict_mult(&nw->target, &nw->mcaddr); + nw->dev = rt->dst.dev; + INIT_WORK(&nw->work, queue_ndisc); + schedule_work(&nw->work); + } } else { read_unlock_bh(&neigh->lock); }