From jinmei@kame201.kame.net  Tue Jul 14 05:06:59 1998
Received: from kame201.kame.net (kame201.kame.net [203.178.141.201])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id FAA26632
          for <FreeBSD-gnats-submit@freebsd.org>; Tue, 14 Jul 1998 05:06:49 -0700 (PDT)
          (envelope-from jinmei@kame201.kame.net)
Received: (from jinmei@localhost)
	by kame201.kame.net (8.8.8/8.8.8) id VAA03050;
	Tue, 14 Jul 1998 21:05:11 +0900 (JST)
	(envelope-from jinmei)
Message-Id: <199807141205.VAA03050@kame201.kame.net>
Date: Tue, 14 Jul 1998 21:05:11 +0900 (JST)
From: jinmei@kame.net
Reply-To: jinmei@kame.net
To: FreeBSD-gnats-submit@freebsd.org
Subject: Multicast kludge does not work correctly
X-Send-Pr-Version: 3.2

>Number:         7281
>Category:       kern
>Synopsis:       [STABLE] Multicast kludge does not work correctly
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 14 05:10:01 PDT 1998
>Closed-Date:    Sat Jun 15 10:26:58 PDT 2002
>Last-Modified:  Sat Jun 15 10:26:58 PDT 2002
>Originator:     JINMEI Tatuya
>Release:        FreeBSD 2.2.6-RELEASE i386
>Organization:
KAME project
>Environment:

FreeBSD perfume.kame.net 2.2.6-RELEASE FreeBSD 2.2.6-RELEASE #5:
Mon Jul 13 15:52:36 JST 1998
jinmei@perfume.kame.net:/usr/src/sys/compile/PERFUME  i386

>Description:

If we join more than one multicast groups on an interface and then
delete the unicast address on the interface,
only one of them will be saved to multicast kludge area.

>How-To-Repeat:

0. Suppose that the IP address of ed0 is 10.0.0.1 and it's the only IP
   address on the interface.
1. Join 224.0.0.2 on ed0
2. Join 224.0.0.3 on ed0
3. # ifconfig ed0 delete 10.0.0.1
4. # ifconfig ed0 10.0.0.1
5. # netstat -ian
   there should be 224.0.0.2 and 224.0.0.3 on ed0, but only 224.0.0.3
   is printed.

>Fix:

This is because the way to use LIST_INSERT_HEAD is wrong in in_control()
and in_ifinit(). We should forward pointer before calling LIST_INSERT_HEAD.

I wrote a patch to solve this problem and applied it.
It seems that the problem is fixed.

I'll attach the patch to this mail.

Index: in.c
===================================================================
RCS file: /cvsroot/hydrangea-freebsd/sys/netinet/in.c,v
retrieving revision 1.1.1.1.12.2
diff -c -r1.1.1.1.12.2 in.c
*** in.c	1998/06/02 15:53:18	1.1.1.1.12.2
--- in.c	1998/07/14 10:19:54
***************
*** 461,469 ****
  		 */
  		IFP_TO_IA(oia->ia_ifp, ia);
  		if (ia) {	/* there is another address */
! 			struct in_multi *inm;
  			for(inm = oia->ia_multiaddrs.lh_first; inm;
! 			    inm = inm->inm_entry.le_next) {
  				IFAFREE(&inm->inm_ia->ia_ifa);
  				ia->ia_ifa.ifa_refcnt++;
  				inm->inm_ia = ia;
--- 461,470 ----
  		 */
  		IFP_TO_IA(oia->ia_ifp, ia);
  		if (ia) {	/* there is another address */
! 			struct in_multi *inm, *next;
  			for(inm = oia->ia_multiaddrs.lh_first; inm;
! 			    inm = next) {
! 				next = inm->inm_entry.le_next;
  				IFAFREE(&inm->inm_ia->ia_ifa);
  				ia->ia_ifa.ifa_refcnt++;
  				inm->inm_ia = ia;
***************
*** 472,484 ****
  			}
  			FREE(mk, M_IPMADDR);
  		} else {	/* last address on this if deleted, save */
! 			struct in_multi *inm;
  
  			LIST_INIT(&mk->mk_head);
  			mk->mk_ifp = ifp;
  
  			for(inm = oia->ia_multiaddrs.lh_first; inm;
! 			    inm = inm->inm_entry.le_next) {
  				LIST_INSERT_HEAD(&mk->mk_head, inm, inm_entry);
  			}
  
--- 473,486 ----
  			}
  			FREE(mk, M_IPMADDR);
  		} else {	/* last address on this if deleted, save */
! 			struct in_multi *inm, *next;
  
  			LIST_INIT(&mk->mk_head);
  			mk->mk_ifp = ifp;
  
  			for(inm = oia->ia_multiaddrs.lh_first; inm;
! 			    inm = next) {
! 				next = inm->inm_entry.le_next;
  				LIST_INSERT_HEAD(&mk->mk_head, inm, inm_entry);
  			}
  
***************
*** 609,618 ****
  		 */
  		for(mk = in_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
  			if(mk->mk_ifp == ifp) {
! 				struct in_multi *inm;
  
  				for(inm = mk->mk_head.lh_first; inm;
! 				    inm = inm->inm_entry.le_next) {
  					IFAFREE(&inm->inm_ia->ia_ifa);
  					ia->ia_ifa.ifa_refcnt++;
  					inm->inm_ia = ia;
--- 611,621 ----
  		 */
  		for(mk = in_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
  			if(mk->mk_ifp == ifp) {
! 				struct in_multi *inm, *next;
  
  				for(inm = mk->mk_head.lh_first; inm;
! 				    inm = next) {
! 					next = inm->inm_entry.le_next;
  					IFAFREE(&inm->inm_ia->ia_ifa);
  					ia->ia_ifa.ifa_refcnt++;
  					inm->inm_ia = ia;
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: wollman 
State-Changed-When: Fri Sep 11 12:05:27 PDT 1998 
State-Changed-Why:  
Fix looks correct, but relevant only to -stable. 
Can someone pick this up and run with it? 
State-Changed-From-To: suspended->closed 
State-Changed-By: johan 
State-Changed-When: Sat Jun 15 10:26:23 PDT 2002 
State-Changed-Why:  
problem was in 2.2.x only. 

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