Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 Jan 1999 17:55:22 -0500 (EST)
From:      Bill Paul <wpaul@skynet.ctr.columbia.edu>
To:        current@FreeBSD.ORG
Subject:   SIOCADDMULTI doesn't work, proposed fix
Message-ID:  <199901312255.RAA01895@skynet.ctr.columbia.edu>

next in thread | raw e-mail | index | archive | help
After experimenting some more, I've come to the conclusion that trying to
manually add a non-IP ethernet multicast address doesn't work properly.
The ether_resolvemulti() assumes that addresses will be specified as
either AF_LINK or AF_INET; if the family is AF_LINK, it assumes that
a struct sockaddr_dl will be used. However, the user is supposed to
pass the address using a struct ifreq, and struct ifreq uses struct
sockaddr, not struct sockaddr_dl.

The original code in 2.2.x expected a struct sockaddr with a family
of AF_UNSPEC. This no longer works in 3.0, which breaks compatibility.
Among other things, the Columbia Appletalk port doesn't work because
of this.

As an aside, the equal() macro in /sys/net/if.c does a bcmp() using
sa_len as the length of the data to check, but doesn't account for
the possibility of sa_len being 0 (this makes it always return true,
which can yield false positives).

The patches included with this post change /sys/net/if.c and
/sys/net/if_ethersubr.c so that adding a mutlicast address with 
SIOCADDMULTI using a struct sockaddr and AF_UNSPEC works again. I would 
like Those Who Know More Than I (tm) to review these changes and offer 
criticisms and comments.

These patches are against 3.0-RELEASE but should apply to -current
and -stable as well.

-Bill

-- 
=============================================================================
-Bill Paul            (212) 854-6020 | System Manager, Master of Unix-Fu
Work:         wpaul@ctr.columbia.edu | Center for Telecommunications Research
Home:  wpaul@skynet.ctr.columbia.edu | Columbia University, New York City
=============================================================================
 "It is not I who am crazy; it is I who am mad!" - Ren Hoek, "Space Madness"
=============================================================================

*** if.c.orig	Sun Jan 31 17:13:01 1999
--- if.c	Sun Jan 31 17:10:36 1999
***************
*** 186,192 ****
  	register struct ifaddr *ifa;
  
  #define	equal(a1, a2) \
!   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  	    for (ifa = ifp->if_addrhead.tqh_first; ifa; 
  		 ifa = ifa->ifa_link.tqe_next) {
--- 186,193 ----
  	register struct ifaddr *ifa;
  
  #define	equal(a1, a2) \
!   (((struct sockaddr *)(a1))->sa_len && \
!    bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
  	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
  	    for (ifa = ifp->if_addrhead.tqh_first; ifa; 
  		 ifa = ifa->ifa_link.tqe_next) {
***************
*** 636,642 ****
  			return EOPNOTSUPP;
  
  		/* Don't let users screw up protocols' entries. */
! 		if (ifr->ifr_addr.sa_family != AF_LINK)
  			return EINVAL;
  
  		if (cmd == SIOCADDMULTI) {
--- 637,644 ----
  			return EOPNOTSUPP;
  
  		/* Don't let users screw up protocols' entries. */
! 		if (ifr->ifr_addr.sa_family != AF_LINK &&
! 			ifr->ifr_addr.sa_family != AF_UNSPEC)
  			return EINVAL;
  
  		if (cmd == SIOCADDMULTI) {
*** if_ethersubr.c.orig	Sun Jan 31 17:13:07 1999
--- if_ethersubr.c	Sun Jan 31 17:00:54 1999
***************
*** 778,783 ****
--- 778,800 ----
  	u_char *e_addr;
  
  	switch(sa->sa_family) {
+ 	case AF_UNSPEC:
+ 		e_addr = (u_char *)&sa->sa_data;
+ 		if ((e_addr[0] & 1) != 1)
+ 			return EADDRNOTAVAIL;
+ 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
+ 		       M_WAITOK);
+ 		sdl->sdl_len = sizeof *sdl;
+ 		sdl->sdl_family = AF_LINK;
+ 		sdl->sdl_index = ifp->if_index;
+ 		sdl->sdl_type = IFT_ETHER;
+ 		sdl->sdl_nlen = 0;
+ 		sdl->sdl_alen = ETHER_ADDR_LEN;
+ 		sdl->sdl_slen = 0;
+ 		e_addr = LLADDR(sdl);
+ 		bcopy((char *)&sa->sa_data, (char *)e_addr, ETHER_ADDR_LEN);
+ 		*llsa = (struct sockaddr *)sdl;
+ 		return 0;
  	case AF_LINK:
  		/* 
  		 * No mapping needed. Just check that it's a valid MC address.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199901312255.RAA01895>