From nobody@FreeBSD.org  Mon Mar  8 18:52:51 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 0A825106567B
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  8 Mar 2010 18:52:51 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id ED0EC8FC13
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  8 Mar 2010 18:52:50 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o28IqoWo064506
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 8 Mar 2010 18:52:50 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o28IqoSQ064505;
	Mon, 8 Mar 2010 18:52:50 GMT
	(envelope-from nobody)
Message-Id: <201003081852.o28IqoSQ064505@www.freebsd.org>
Date: Mon, 8 Mar 2010 18:52:50 GMT
From: Petr Lampa <lampa@fit.vutbr.cz>
To: freebsd-gnats-submit@FreeBSD.org
Subject: mld sends packets to wrong destination with a bad checksum
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         144560
>Category:       kern
>Synopsis:       [mld] [patch] mld sends packets to wrong destination with a bad checksum
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    bms
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 08 19:00:15 UTC 2010
>Closed-Date:    Tue Apr 27 13:33:13 UTC 2010
>Last-Modified:  Tue Apr 27 13:33:13 UTC 2010
>Originator:     Petr Lampa
>Release:        FreeBSD 8.0-STABLE
>Organization:
FIT BUT
>Environment:
reeBSD xxx 8.0-STABLE FreeBSD 8.0-STABLE #1: Wed Jan  6 15:53:10 CET 2010     xxx:/usr/src/sys/i386/compile/XXXX
>Description:
This is a packet dump of MLDv1 listener report send to group ff05::1:3 (all dhcp-servers):

15:41:09.388798 IP6 fe80::230:48ff:fe30:8646 > ff05:1::1:3: HBH ICMP6, multica
st listener reportmax resp delay: 0 addr: ff05::1:3, length 24
0x0000:  3333 0001 0003 0030 4830 8646 86dd 6000  33.....0H0.F..`.
0x0010:  0000 0020 0001 fe80 0000 0000 0000 0230  ...............0
0x0020:  48ff fe30 8646 ff05 0001 0000 0000 0000  H..0.F..........
0x0030:  0000 0001 0003 3a00 0100 0502 0000 8300  ......:.........
0x0040:  b071 0000 0000 ff05 0000 0000 0000 0000  .q..............
0x0050:  0000 0001 0003                           ......

First, the destination address of packet is wrong (notice that multicast group at the packet end is ok), second, the checksum is also wrong (it should be b070 instead b071, router complains about this). 

The reason is incorrect scope embedding in mld_dispatch_packet():

#if 0
        (void)in6_setscope(&ip6->ip6_dst, ifp, NULL);   /* XXX LOR */
#else
        /*
         * XXX XXX Break some KPI rules to prevent an LOR which would
         * occur if we called in6_setscope() at transmission.
         * See comments at top of file.
         */
        MLD_EMBEDSCOPE(&ip6->ip6_dst, ifp->if_index);
#endif

The macro MLD_EMBEDSCOPE contains this:!!!

#define MLD_EMBEDSCOPE(pin6, zoneid) \
        (pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)

That's simply wrong, it should do at least this:

#define MLD_EMBEDSCOPE(pin6, zoneid) \
if (IN6_IS_SCOPE_LINKLOCAL(pin6) || IN6_IS_ADDR_MC_INTFACELOCAL(pin6)) \
        (pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)

The reason of wrong checksum is that checksum was calculated previously in mld_v1_transmit_report() with the correct destination address, so it's 1 less in my case (interface scope was 1). 

>How-To-Repeat:
Join any non-local IPv6 multicast group.
>Fix:
If ifp->if_index is really the correct value for scope, the following patch should be sufficient:

*** /usr/src/sys/netinet6/mld6.c.orig   2010-03-08 19:06:13.000000000 +0100
--- /usr/src/sys/netinet6/mld6.c        2010-03-08 19:07:40.000000000 +0100
***************
*** 196,201 ****
--- 196,202 ----
  MALLOC_DEFINE(M_MLD, "mld", "mld state");

  #define       MLD_EMBEDSCOPE(pin6, zoneid) \
+ if (IN6_IS_SCOPE_LINKLOCAL(pin6) || IN6_IS_ADDR_MC_INTFACELOCAL(pin6)) \
        (pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)

  /*


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: gavin 
Responsible-Changed-When: Mon Mar 8 19:44:38 UTC 2010 
Responsible-Changed-Why:  
Over to maintainer(s) 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144560 
Responsible-Changed-From-To: freebsd-net->bms 
Responsible-Changed-By: bms 
Responsible-Changed-When: Sat 10 Apr 2010 12:03:56 UTC 
Responsible-Changed-Why:  
take this 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144560 
State-Changed-From-To: open->patched 
State-Changed-By: bms 
State-Changed-When: Sat 10 Apr 2010 12:24:21 UTC 
State-Changed-Why:  
patch on HEAD 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144560 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/144560: commit references a PR
Date: Sat, 10 Apr 2010 12:24:30 +0000 (UTC)

 Author: bms
 Date: Sat Apr 10 12:24:21 2010
 New Revision: 206454
 URL: http://svn.freebsd.org/changeset/base/206454
 
 Log:
   When embedding the scope ID in MLDv1 output, check if the scope of the address
   being embedded is in fact link-local, before attempting to embed it.
   
   Note that this operation is a side-effect of trying to avoid recursion on
   the IN6 scope lock.
   
   PR:		144560
   Submitted by:	Petr Lampa
   MFC after:	3 days
 
 Modified:
   head/sys/netinet6/mld6.c
 
 Modified: head/sys/netinet6/mld6.c
 ==============================================================================
 --- head/sys/netinet6/mld6.c	Sat Apr 10 12:10:11 2010	(r206453)
 +++ head/sys/netinet6/mld6.c	Sat Apr 10 12:24:21 2010	(r206454)
 @@ -195,8 +195,10 @@ static int	sysctl_mld_ifinfo(SYSCTL_HAND
  static struct mtx		 mld_mtx;
  MALLOC_DEFINE(M_MLD, "mld", "mld state");
  
 -#define	MLD_EMBEDSCOPE(pin6, zoneid) \
 -	(pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)
 +#define	MLD_EMBEDSCOPE(pin6, zoneid)					\
 +	if (IN6_IS_SCOPE_LINKLOCAL(pin6) ||				\
 +	    IN6_IS_ADDR_MC_INTFACELOCAL(pin6))				\
 +		(pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)		\
  
  /*
   * VIMAGE-wide globals.
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/144560: commit references a PR
Date: Tue, 27 Apr 2010 13:28:06 +0000 (UTC)

 Author: bms
 Date: Tue Apr 27 13:27:51 2010
 New Revision: 207273
 URL: http://svn.freebsd.org/changeset/base/207273
 
 Log:
   MFC 206454:
     When embedding the scope ID in MLDv1 output, check if the scope of the address
     being embedded is in fact link-local, before attempting to embed it.
   
     Note that this operation is a side-effect of trying to avoid recursion on
     the IN6 scope lock.
   
   PR:		144560
   Submitted by:	Petr Lampa
 
 Modified:
   stable/8/sys/netinet6/mld6.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
   stable/8/sys/geom/sched/   (props changed)
 
 Modified: stable/8/sys/netinet6/mld6.c
 ==============================================================================
 --- stable/8/sys/netinet6/mld6.c	Tue Apr 27 12:50:42 2010	(r207272)
 +++ stable/8/sys/netinet6/mld6.c	Tue Apr 27 13:27:51 2010	(r207273)
 @@ -195,8 +195,10 @@ static int	sysctl_mld_ifinfo(SYSCTL_HAND
  static struct mtx		 mld_mtx;
  MALLOC_DEFINE(M_MLD, "mld", "mld state");
  
 -#define	MLD_EMBEDSCOPE(pin6, zoneid) \
 -	(pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)
 +#define	MLD_EMBEDSCOPE(pin6, zoneid)					\
 +	if (IN6_IS_SCOPE_LINKLOCAL(pin6) ||				\
 +	    IN6_IS_ADDR_MC_INTFACELOCAL(pin6))				\
 +		(pin6)->s6_addr16[1] = htons((zoneid) & 0xFFFF)		\
  
  /*
   * VIMAGE-wide globals.
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: bms 
State-Changed-When: Tue 27 Apr 2010 13:32:56 UTC 
State-Changed-Why:  
pullup on 8.x 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144560 
>Unformatted:
