From marquard@austin.ibm.com  Sat Dec 30 14:27:04 1995
Received: from netmail1.austin.ibm.com (netmail1.austin.ibm.com [129.35.208.96])
          by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id OAA21974
          for <freebsd-gnats-submit@freebsd.org>; Sat, 30 Dec 1995 14:27:02 -0800 (PST)
Received: from mojave.austin.ibm.com (mojave.austin.ibm.com [129.35.128.45]) by netmail1.austin.ibm.com (8.6.12/8.6.11) with SMTP id QAA18937 for <FreeBSD-gnats-submit@freebsd.org>; Sat, 30 Dec 1995 16:27:00 -0600
Received: by mojave.austin.ibm.com (AIX 4.1/UCB 5.64/4.03-client-2.6)
          for FreeBSD-gnats-submit@freebsd.org at austin.ibm.com; id AA04008; Sat, 30 Dec 1995 16:26:55 -0600
Message-Id: <9512302226.AA04008@mojave.austin.ibm.com>
Date: Sat, 30 Dec 1995 16:26:55 -0600
From: marquard@austin.ibm.com
Reply-To: marquard@austin.ibm.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: Multicast problems on point-to-point interfaces
X-Send-Pr-Version: 3.2

>Number:         923
>Category:       kern
>Synopsis:       Multicast problems on point-to-point interfaces
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Dec 30 14:30:01 PST 1995
>Closed-Date:    Sat Jan 13 10:24:47 PST 1996
>Last-Modified:  Sat Jan 13 10:25:46 PST 1996
>Originator:     Dave Marquardt
>Release:        FreeBSD 2.1-STABLE i386
>Organization:
Individual
>Environment:

	Packard Bell Force 442CDT (75 MHz Pentium, 8MB RAM)
	Using tun0 interface, which is multicast capable
	No other interfaces (except loopback)

>Description:

	In attempting to run mrouted for multicast routing, I noted
	that tun0 has IFF_MULTICAST set, and tun0 along with a tunnel
	to a remote site should make mrouted work.

	Here's the mrouted configuration file I used:

	# mrouted configuration
	phyint 9.3.240.156
	tunnel 9.3.240.156 129.35.128.45

	Here's the state of tun0:

	tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
		inet 9.3.240.156 --> 9.3.240.14 netmask 0xff000000 

	When I run mrouted, I get this:

	lefse# mrouted -d -c ~drm/mrouted.conf
	debug level 2
	19:38:42.082 mrouted version 3.6
	19:38:42.480 Getting vifs from kernel interfaces
	19:38:42.490 installing tun0 (9.3.240.156 on subnet 9/8) as vif #0 - rate=0
	19:38:42.490 Getting vifs from /home/drm/mrouted.conf
	19:38:42.552 installing tunnel from 9.3.240.156 to 129.35.128.45 as vif #1 - rate=500
	19:38:42.554 Installing vifs in kernel...
	19:38:42.560 vif #0, phyint 9.3.240.156
	19:38:42.560 warning - can't join group 224.0.0.4 on interface 9.3.240.156: Can't assign requested address
	19:38:42.567 warning - can't join group 224.0.0.2 on interface 9.3.240.156: Can't assign requested address
	19:38:42.579 setsockopt IP_MULTICAST_IF 9.3.240.156: Can't assign requested address

	Upon code investigation, I discovered some problems in the
	code for both IP_ADD_MEMBERSHIP and IP_MULTICAST_IF.  In the
	case of adding a membership with a specific source address,
	specifying the interface on which to add the multicast group,
	we end up in this code in ip_setmoptions():

			INADDR_TO_IFP(mreq->imr_interface, ifp);

	The code for the INADDR_TO_IFP() macro is this:

	/*
	 * Macro for finding the interface (ifnet structure) corresponding to one
	 * of our IP addresses.
	 */
	#define INADDR_TO_IFP(addr, ifp) \
		/* struct in_addr addr; */ \
		/* struct ifnet *ifp; */ \
	{ \
		register struct in_ifaddr *ia; \
	\
		for (ia = in_ifaddr; \
		    ia != NULL && ((ia->ia_ifp->if_flags & IFF_POINTOPOINT)? \
			IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \
		    ia = ia->ia_next) \
			 continue; \
		(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
	}

	In the case of a point to point link like tun0, we check the
	DESTINATION address rather than the source address of the
	interface.  It seems to me we should either check the source,
	or both the source and destination, but not just the
	destination.

	A similar problem applies to the IP_MULTICAST_IF code.

>How-To-Repeat:

	Try to join a multicast group on tun0 or some other
	point-to-point interface that claims to support multicast,
	i.e. use the IP_ADD_MEMBERSHIP socket option with
	setsockopt().  mrouted has code like this.

	Try to set the outgoing multicast interface using the
	setsockopt() with the IP_MULTICAST_IF socket option.  Again,
	mrouted does this.

>Fix:
	
	My own thought is that the INADDR_TO_IFP() macro is wrong in
	the case of IFF_POINTOPOINT.  Here's a context diff:

*** 1.1	1995/12/30 01:55:07
--- in_var.h	1995/12/30 02:26:41
***************
*** 102,111 ****
  	register struct in_ifaddr *ia; \
  \
  	for (ia = in_ifaddr; \
! 	    ia != NULL && ((ia->ia_ifp->if_flags & IFF_POINTOPOINT)? \
! 		IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \
  	    ia = ia->ia_next) \
! 		 continue; \
  	(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
  }
  
--- 102,112 ----
  	register struct in_ifaddr *ia; \
  \
  	for (ia = in_ifaddr; \
! 	    ia != NULL && IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr; \
  	    ia = ia->ia_next) \
! 		 if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) \
! 			if (IA_DSTSIN(ia)->sin_addr.s_addr == (addr).s_addr) \
! 				break; \
  	(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
  }
  
	This should catch both the source and destination address of
	point to point links.

	Since INADDR_TO_IFP() seems to be used only with the multicast
	code, this change shouldn't mess anyone else up.
>Release-Note:
>Audit-Trail:

From: "Garrett A. Wollman" <wollman@lcs.mit.edu>
To: marquard@austin.ibm.com
Cc: FreeBSD-gnats-submit@freebsd.org, Bill Fenner <fenner@parc.xerox.com>
Subject: kern/923: Multicast problems on point-to-point interfaces
Date: Mon, 1 Jan 1996 14:16:48 -0500

 <<On Sat, 30 Dec 1995 16:26:55 -0600, marquard@austin.ibm.com said:
 
 > 	In attempting to run mrouted for multicast routing, I noted
 > 	that tun0 has IFF_MULTICAST set, and tun0 along with a tunnel
 > 	to a remote site should make mrouted work.
 
 > 	Here's the mrouted configuration file I used:
 
 > 	# mrouted configuration
 > 	phyint 9.3.240.156
 > 	tunnel 9.3.240.156 129.35.128.45
 
 Actually, this doesn't make any sense.  You should either disable the
 physical interface (`phyint x.x.x.x disabled') and just use a tunnel,
 or otherwise don't use a tunnel and run mrouted on the other side of
 the phyint.  (Otherwise, you will duplicate all your multicast
 traffic.)  This is not the cause of your problem, however.
 
 > 	In the case of a point to point link like tun0, we check the
 > 	DESTINATION address rather than the source address of the
 > 	interface.  It seems to me we should either check the source,
 > 	or both the source and destination, but not just the
 > 	destination.
 
 You have hit on a thorny problem.  The code is written in the way it
 is in order to support a ``half-router'' model of IP forwarding.
 Never mind that this breaks the IP reference model; a number of people
 complained about it not working last year, and so pains were taken to
 make it work despite the problems.  You have hit upon one of the most
 serious problems resulting from allowing half-router support: the IP
 model requires that an IP address /uniquely/ name an interface, and
 the half-router support breaks that completely.  We are unlikely to
 get the multicast people to change their software, because they are
 just following the rules.
 
 > 	This should catch both the source and destination address of
 > 	point to point links.
 
 This might be a workable solution, except in the half-router case.  I
 might just tell the half-router people ``Go away, you're broken'', but
 I'm not sure I want to do that.
 
 -GAWollman
 
 --
 Garrett A. Wollman   | Shashish is simple, it's discreet, it's brief. ... 
 wollman@lcs.mit.edu  | Shashish is the bonding of hearts in spite of distance.
 Opinions not those of| It is a bond more powerful than absence.  We like people
 MIT, LCS, ANA, or NSA| who like Shashish.  - Claude McKenzie + Florent Vollant

From: Bill Fenner <fenner@parc.xerox.com>
To: wollman@lcs.mit.edu
Cc: marquard@austin.ibm.com, FreeBSD-gnats-submit@freebsd.org,
        Bill Fenner <fenner@parc.xerox.com>
Subject: Re: kern/923: Multicast problems on point-to-point interfaces 
Date: Tue, 2 Jan 1996 17:14:56 PST

 In message <9601011916.AA11388@halloran-eldar.lcs.mit.edu> Garrett said:
 >We are unlikely to
 >get the multicast people to change their software, because they are
 >just following the rules.
 
 Actually, I have been doing some thinking on this topic.  There are two
 things that can be done:
 
 1) Make mrouted work in the case of non-''half-router'' situations.  This
 one is easy; check the point-to-point destination addresses first, then
 if you have no match check the source.  Note that you can't just check
 them both on the first pass, since non-point-to-point interfaces should
 be chosen over point-to-point interfaces.  An experimental patch follows
 (I have thought about this but haven't tested it)
 
 *** in_var.h.old	Tue Nov 14 14:52:43 1995
 --- in_var.h	Tue Jan  2 17:11:10 1996
 ***************
 *** 106,111 ****
 --- 106,117 ----
   		IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \
   	    ia = ia->ia_next) \
   		 continue; \
 + 	if (ia == NULL) \
 + 	    for (ia = in_ifaddr; \
 + 		ia != NULL && ia->ia_ifp->if_flags & IFF_POINTOPOINT && \
 + 		    IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr; \
 + 		ia = ia->ia_next) \
 + 		     continue; \
   	(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
   }
   
 
 2) Make mrouted work on a ''half-router''.  I'm not sure this is simple
 but I am percolating a couple of ideas.
 
   Bill

From: Bill Fenner <fenner@parc.xerox.com>
To: Bill Fenner <fenner@parc.xerox.com>
Cc: wollman@lcs.mit.edu, marquard@austin.ibm.com,
        FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/923: Multicast problems on point-to-point interfaces 
Date: Wed, 3 Jan 1996 07:04:47 PST

 In message <96Jan2.171459pst.177478@crevenia.parc.xerox.com> I wrote:
 >*** in_var.h.old	Tue Nov 14 14:52:43 1995
 >--- in_var.h	Tue Jan  2 17:11:10 1996
 
 Ugh.  I really shouldn't try writing code after two days of travel hell.
 Try this one:
 
 
 *** in_var.h.old	Tue Nov 14 14:52:43 1995
 --- in_var.h	Wed Jan  3 07:02:45 1996
 ***************
 *** 106,111 ****
 --- 106,118 ----
   		IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \
   	    ia = ia->ia_next) \
   		 continue; \
 + 	if (ia == NULL) \
 + 	    for (ia = in_ifaddr; \
 + 		ia != NULL; \
 + 		ia = ia->ia_next) \
 + 		    if (ia->ia_ifp->if_flags & IFF_POINTOPOINT && \
 + 			IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr) \
 + 			    break; \
   	(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
   }
   
   Bill
State-Changed-From-To: open->feedback 
State-Changed-By: wollman 
State-Changed-When: Wed Jan 3 12:25:05 PST 1996 
State-Changed-Why:  
A proposed change has been committed in rev 1.14 of in_var.h, 
supplied by Bill Fenner. 

From: Dave Marquardt <marquard@austin.ibm.com>
To: Bill Fenner <fenner@parc.xerox.com>
Cc: wollman@lcs.mit.edu, FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/923: Multicast problems on point-to-point interfaces 
Date: Mon, 08 Jan 1996 22:12:06 -0600

 On Wed, 3 Jan 1996 07:04:47 PST  Bill Fenner wrote:
 > In message <96Jan2.171459pst.177478@crevenia.parc.xerox.com> I wrote:
 > >*** in_var.h.old	Tue Nov 14 14:52:43 1995
 > >--- in_var.h	Tue Jan  2 17:11:10 1996
 > 
 > Ugh.  I really shouldn't try writing code after two days of travel hell.
 > Try this one:
 > 
 > 
 > *** in_var.h.old	Tue Nov 14 14:52:43 1995
 > --- in_var.h	Wed Jan  3 07:02:45 1996
 > ***************
 > *** 106,111 ****
 > --- 106,118 ----
 >   		IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \
 >   	    ia = ia->ia_next) \
 >   		 continue; \
 > + 	if (ia == NULL) \
 > + 	    for (ia = in_ifaddr; \
 > + 		ia != NULL; \
 > + 		ia = ia->ia_next) \
 > + 		    if (ia->ia_ifp->if_flags & IFF_POINTOPOINT && \
 > + 			IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr) \
                                                     ^^
 
 Seems like that should be ==, shouldn't it?  With !=, you quit on the
 first interface whose address DOESN'T match, which I don't think is
 what was intended.
 
 > + 			    break; \
 >   	(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
 >   }
 >   
 >   Bill
 
 --
 Dave Marquardt
 SMTP: marquard@austin.ibm.com
 VNET: MARQUARD at AUSTIN
 T/L 678-1139
 +1 512 838-1139
 
 

From: Bill Fenner <fenner@parc.xerox.com>
To: Dave Marquardt <marquard@austin.ibm.com>
Cc: Bill Fenner <fenner@parc.xerox.com>, wollman@lcs.mit.edu,
        FreeBSD-gnats-submit@freebsd.org
Subject: Re: kern/923: Multicast problems on point-to-point interfaces 
Date: Mon, 8 Jan 1996 23:32:04 PST

 In message <9601090412.AA41358@mojave.austin.ibm.com> Dave Marquardt wrote:
 >> + 		    if (ia->ia_ifp->if_flags & IFF_POINTOPOINT && \
 >> + 			IA_SIN(ia)->sin_addr.s_addr != (addr).s_addr) \
 >
 >Seems like that should be ==, shouldn't it?
 
 Yup.  I hereby swear off sending untested patches, it's too embarassing =)
 
   Bill
State-Changed-From-To: feedback->closed 
State-Changed-By: wollman 
State-Changed-When: Sat Jan 13 10:24:47 PST 1996 
State-Changed-Why:  
No feedback is good feedback :-) 
This problem is believed to be fixed in both -current and -stable. 
>Unformatted:
