NetBSD Problem Report #41005

From Wolfgang.Stukenbrock@nagler-company.com  Fri Mar 13 13:48:20 2009
Return-Path: <Wolfgang.Stukenbrock@nagler-company.com>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id B977563BE42
	for <gnats-bugs@gnats.NetBSD.org>; Fri, 13 Mar 2009 13:48:20 +0000 (UTC)
Message-Id: <20090313134818.2257B4EA9F9@s012.nagler-company.com>
Date: Fri, 13 Mar 2009 14:48:18 +0100 (CET)
From: Wolfgang.Stukenbrock@nagler-company.com
Reply-To: Wolfgang.Stukenbrock@nagler-company.com
To: gnats-bugs@gnats.NetBSD.org
Subject: kernel failed to select correct outgoing address for Multicast packets
X-Send-Pr-Version: 3.95

>Number:         41005
>Category:       kern
>Synopsis:       kernel failed to select correct outgoing address for Multicast packets
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Mar 13 13:50:00 +0000 2009
>Originator:     Wolfgang Stukenbrock
>Release:        NetBSD 4.0
>Organization:
Dr. Nagler & Company GmbH

>Environment:


System: NetBSD s012 4.0 NetBSD 4.0 (NSW-S012) #9: Fri Mar 13 12:31:52 CET 2009 wgstuken@s012:/usr/src/sys/arch/amd64/compile/NSW-S012 amd64
Architecture: x86_64
Machine: amd64
>Description:
	If alias addresses are defined on an interface, the kernel does not use the
	information passed to it by IP_MULTICAST_IF option. Instead it always uses
	the primary address of the interface.
	This will break e.g. gated on such interfaces.
	The problem is, that the information passed by IP_MULTICAST_IF is only used
	to select the interface itself in the call and to pass it back to user level
	on a call got getoption IP_MULTICAST_IF under some circumstances.
	But is is ignored when sending packets with .e.g. sendto().
	By the way, the current code when selecting the interface by pasing the interface
	index to the kernel (RFC1724) looks broken, because if the index 0 gets selected,
	the information is not stored and returned as expected. (recognized by source
	codde inspection) This patch will also solve this.
>How-To-Repeat:
	Setup an interface with an alias address (with a different subnet mask) on some machines
	and try to gated on it.
	remark: the different subnet mask will only lead to syslog output by gated that can be
	found in the log-file.
	You can also use tcpdump. You will see that all packets come from the primary addess, but
	gated will try to send half of then from the other address.
	You can also write a short test program: open a socket(RAW_IP), assign it to a the alias
	address to the multicast group, select that one as outgooing interface and send some
	data to that group. The wrong source address is in the packet on the wire.
>Fix:
	The best way to solve this problem seems to use the imo_multicas_addr information in any
	case - not only if the interface was selected via interface index.
	If there is still no address selected on outgooing multicast packets, then this information
	should be used, if it is still a valid address of the interface.
	If not, the old semantic by selecting the first one found is preserved.
	This may only be done if the outgooing interface for multicast packets is selected by
	an address specification. Therefore we need to check for RFC1724 setup here too.
	remark: the second parameter for the interface index in ip_multicast_if() is no longer
	used in any call after applying this patch. I haven't removed it, because it may be usefull
	to reuse it in the future again. Feel free to eleminate it ...


*** ip_output.c	2009/02/16 10:09:16	1.11
--- ip_output.c	2009/03/13 13:17:29
***************
*** 394,400 ****
--- 394,420 ----
  		if (in_nullhost(ip->ip_src)) {
  			struct in_ifaddr *xia;

+ 		    if (   IN_MULTICAST(ip->ip_dst.s_addr)
+ 			&& imo != NULL
+ 		        && ntohl(imo->imo_multicast_addr.s_addr) >> 24 != 0) /* RFC1724 section 3.3 */
+ 		      { /* use the stored multicast address from IP_MULTICAST_IF to locate the in_ifaddr structure */
+ 			  struct ifaddr *ifa;
+ 
+ 			  xia = NULL;
+ 			  IFADDR_FOREACH(ifa, ifp) { /* XXX special version of the IFP_TO_IA() macro ...*/
+ 			    if (ifa->ifa_addr->sa_family == AF_INET) {
+ 			      if (imo->imo_multicast_addr.s_addr == ifatoia(ifa)->ia_addr.sin_addr.s_addr) {
+ 				xia = ifatoia(ifa);
+ 				break;
+ 			      }
+ 			      if (xia == NULL) xia = ifatoia(ifa); /* default to previous behaviour if no match - use first addres */
+ 			    }
+ 			}
+ 		      }
+ 		      else
+ 		      {
  			IFP_TO_IA(ifp, xia);
+ 		      }
  			if (!xia) {
  				error = EADDRNOTAVAIL;
  				goto bad;
***************
*** 1683,1689 ****
  	struct ip_moptions *imo = *imop;
  	struct route ro;
  	struct sockaddr_in *dst;
- 	int ifindex;

  	if (imo == NULL) {
  		/*
--- 1703,1708 ----
***************
*** 1728,1743 ****
  		 * IP address.  Find the interface and confirm that
  		 * it supports multicasting.
  		 */
! 		ifp = ip_multicast_if(&addr, &ifindex);
  		if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
  			error = EADDRNOTAVAIL;
  			break;
  		}
  		imo->imo_multicast_ifp = ifp;
! 		if (ifindex)
! 			imo->imo_multicast_addr = addr;
! 		else
! 			imo->imo_multicast_addr.s_addr = INADDR_ANY;
  		break;

  	case IP_MULTICAST_TTL:
--- 1747,1759 ----
  		 * IP address.  Find the interface and confirm that
  		 * it supports multicasting.
  		 */
! 		ifp = ip_multicast_if(&addr, NULL);
  		if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
  			error = EADDRNOTAVAIL;
  			break;
  		}
  		imo->imo_multicast_ifp = ifp;
! 		imo->imo_multicast_addr = addr;
  		break;

  	case IP_MULTICAST_TTL:
***************
*** 1925,1930 ****
--- 1941,1947 ----
  			/* return the value user has set */
  			*addr = imo->imo_multicast_addr;
  		} else {
+ /* should never come here anymore - but kept for security reasons ... */
  			IFP_TO_IA(imo->imo_multicast_ifp, ia);
  			*addr = ia ? ia->ia_addr.sin_addr : zeroin_addr;
  		}

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.