[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 02705) Re: insufficient process when receiving IPv6 Router Solicitation
- To: kago@xxxxxxxxxxxxxx
- Subject: (usagi-users 02705) Re: insufficient process when receiving IPv6 Router Solicitation
- From: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@xxxxxxxxxxxxxx>
- Date: Thu, 18 Dec 2003 18:43:03 +0900 (JST)
- Cc: usagi-users@xxxxxxxxxxxxxx
- In-reply-to: <3FE1580C.2080004@jp.fujitsu.com>
- Organization: USAGI Project
- References: <3FE1580C.2080004@jp.fujitsu.com>
- Reply-to: usagi-users@xxxxxxxxxxxxxx
- Sender: "Hideaki YOSHIFUJI" <yoshfuji@xxxxxxxxxxxxxxxxxxxxxxxxx>
In article <3FE1580C.2080004@xxxxxxxxxxxxxx> (at Thu, 18 Dec 2003 16:32:28 +0900), Hiroaki Kago <kago@xxxxxxxxxxxxxx> says:
> I think that the processing which receives Router Solicitation
> Message is insufficient in the USAGI snap kernel-2.6-s20031208.
:
> I made a patch and fixed the problem. This patch referred
> to the USAGI snap kernel-2.4-s20031208.
Thank you for your notification.
But your patch seems buggy; cannot compile.
> + neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
> + if (neigh) {
> + int notify;
> + write_lock(&neigh->lock);
> + neigh_update(neigh, lladdr, NUD_STALE, 1, NEIGH_UPDATE_TYPE_IP6RS);
> + write_unlock(&neigh->lock);
> +#ifdef CONFIG_ARPD
> + if (notify > 0)
> + neigh_app_notify(neigh);
> +#endif
> + neigh_release(neigh);
> + }
> +out:
> + in6_dev_put(idev);
Well, because neigh_update() in usagi-linux24 is very different from
one in 2.6, you cannot use it blindly.
1. neigh_update lock neigh->lock, so dead lock occurs.
2. "notify" is not initialized.
3. because neigh_app_notfiy is done is neigh_update(), so
you don't need to do it outside.
4. NEIGH_UPDATE_TYPE_IP6RS is not defined.
I've committed revised version into our repository.
Index: include/net/ndisc.h
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/include/net/ndisc.h,v
retrieving revision 1.4
diff -u -r1.4 ndisc.h
--- include/net/ndisc.h 3 Jul 2003 05:10:39 -0000 1.4
+++ include/net/ndisc.h 18 Dec 2003 09:40:08 -0000
@@ -45,6 +45,11 @@
__u8 opt[0];
};
+struct rs_msg {
+ struct icmp6hdr icmph;
+ __u8 opt[0];
+};
+
struct ra_msg {
struct icmp6hdr icmph;
__u32 reachable_time;
Index: net/ipv6/ndisc.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux26/net/ipv6/ndisc.c,v
retrieving revision 1.38
diff -u -r1.38 ndisc.c
--- net/ipv6/ndisc.c 12 Dec 2003 14:01:43 -0000 1.38
+++ net/ipv6/ndisc.c 18 Dec 2003 09:40:08 -0000
@@ -999,6 +999,63 @@
}
}
+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(KERN_WARNING
+ "ICMP6 RS: can't find in6 device\n");
+ return;
+ }
+
+ /* Don't accept RS if we're not in router mode */
+ if (!idev->cnf.forwarding || idev->cnf.accept_ra)
+ 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(KERN_WARNING
+ "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, 1, 1);
+ 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;
@@ -1474,6 +1531,10 @@
ndisc_recv_na(skb);
break;
+ case NDISC_ROUTER_SOLICITATION:
+ ndisc_recv_rs(skb);
+ break;
+
case NDISC_ROUTER_ADVERTISEMENT:
ndisc_router_discovery(skb);
break;
--
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@xxxxxxxxxxxxxx>
GPG FP: 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA