netdev
[Top] [All Lists]

Re: Source Specific Query of MLDv2 [PATCH]

To: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@xxxxxxxxxxxxxx>
Subject: Re: Source Specific Query of MLDv2 [PATCH]
From: David Stevens <dlstevens@xxxxxxxxxx>
Date: Wed, 11 Feb 2004 23:34:37 -0700
Cc: davem@xxxxxxxxxx, hibi665@xxxxxxx, netdev@xxxxxxxxxxx, "Hideaki YOSHIFUJI" <yoshfuji@xxxxxxxxxxxxxxxxxxxxxxxxx>, yoshfuji@xxxxxxxxxxxxxx
In-reply-to: <20040212.110328.103131455.yoshfuji@linux-ipv6.org>
Sender: netdev-bounce@xxxxxxxxxxx

"Hideaki YOSHIFUJI" <yoshfuji@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote on 02/11/2004 06:03:28 PM:

> You forgot to check if proto is IPPROTO_ICMPV6.
> (This is one reason why I want to check the icmpv6 code

> in icmpv6_rcv().)

Arg! You're right! I had no idea what you were talking
about with that comment about icmpv6_rcv() (the test can't be
done there, because it'll be discarded without it; I thought
you were looking for an optimization of some kind). Of course,
my tests are using ICMP (MLD and ECHO) and UDP packets that
didn't have MLD types where the ICMPv6 type code would be--
so the filter and exceptions all worked. :-(

What I intended is for ipv6_is_mld() to check this (not
assume that "skb" is ICMPv6 only). Fixed patch below [blush].
Thanks for the reviews,

+-DLS

diff -ruN linux-2.6.2/include/net/addrconf.h linux-2.6.2F2/include/net/addrconf.h
--- linux-2.6.2/include/net/addrconf.h 2004-02-03 19:44:17.000000000 -0800
+++ linux-2.6.2F2/include/net/addrconf.h 2004-02-11 21:03:10.000000000 -0800
@@ -98,6 +98,7 @@

extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
struct in6_addr *src_addr);
+extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);

extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);

diff -ruN linux-2.6.2/net/ipv6/ip6_input.c linux-2.6.2F2/net/ipv6/ip6_input.c
--- linux-2.6.2/net/ipv6/ip6_input.c 2004-02-03 19:44:14.000000000 -0800
+++ linux-2.6.2F2/net/ipv6/ip6_input.c 2004-02-11 21:00:03.000000000 -0800
@@ -168,11 +168,19 @@

smp_read_barrier_depends();
if (ipprot->flags & INET6_PROTO_FINAL) {
+ struct ipv6hdr *hdr;
+
if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
skb->csum = csum_sub(skb->csum,
    csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
cksum_sub++;

}
+ hdr = skb->nh.ipv6h;
+ if (ipv6_addr_is_multicast(&hdr->daddr) &&
+    !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
+    &hdr->saddr) &&
+    !ipv6_is_mld(skb, nexthdr))
+ goto discard;
}
if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
   !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
@@ -211,15 +219,14 @@

int ip6_mc_input(struct sk_buff *skb)
{
- struct ipv6hdr *hdr;
- int deliver = 0;
- int discard = 1;
+ struct ipv6hdr *hdr;
+ int deliver;

IP6_INC_STATS_BH(Ip6InMcastPkts);

hdr = skb->nh.ipv6h;
- if (ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, &hdr->saddr))
- deliver = 1;
+ deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) ||
+    ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);

/*
* IPv6 multicast router mode isnt currently supported.
@@ -238,23 +245,21 @@

if (deliver) {
skb2 = skb_clone(skb, GFP_ATOMIC);
+ dst_output(skb2);
} else {
- discard = 0;
- skb2 = skb;
+ dst_output(skb);
+ return 0;
}
-
- dst_output(skb2);

}
}
#endif

- if (deliver) {
- discard = 0;
+ if (likely(deliver)) {
ip6_input(skb);
+ return 0;
}
-
- if (discard)
- kfree_skb(skb);
+ /* discard */
+ kfree_skb(skb);

return 0;
}
diff -ruN linux-2.6.2/net/ipv6/mcast.c linux-2.6.2F2/net/ipv6/mcast.c
--- linux-2.6.2/net/ipv6/mcast.c 2004-02-03 19:44:28.000000000 -0800
+++ linux-2.6.2F2/net/ipv6/mcast.c 2004-02-11 21:01:52.000000000 -0800
@@ -901,6 +901,33 @@
}

/*
+ * identify MLD packets for MLD filter exceptions
+ */
+int ipv6_is_mld(struct sk_buff *skb, int nexthdr)
+{
+ struct icmp6hdr *pic;
+
+ if (nexthdr != IPPROTO_ICMPV6)
+ return 0;
+
+ if (!pskb_may_pull(skb, sizeof(struct icmp6hdr)))
+ return 0;
+
+ pic = (struct icmp6hdr *)skb->h.raw;
+
+ switch (pic->icmp6_type) {
+ case ICMPV6_MGM_QUERY:
+ case ICMPV6_MGM_REPORT:
+ case ICMPV6_MGM_REDUCTION:
+ case ICMPV6_MLD2_REPORT:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*
 * check if the interface/address pair is valid
 */
int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,

@@ -918,7 +945,7 @@
break;
}
if (mc) {
- if (!ipv6_addr_any(src_addr)) {
+ if (src_addr && !ipv6_addr_any(src_addr)) {
struct ip6_sf_list *psf;

spin_lock_bh(&mc->mca_lock);

(See attached file: mldx6.patch)

Attachment: mldx6.patch
Description: Binary data

<Prev in Thread] Current Thread [Next in Thread>