Re: SIOCADDMULTI doesn't work, proposed fix

1999-02-01 Thread Garrett Wollman
On Mon, 1 Feb 1999 02:02:48 -0500 (EST), Bill Paul 
wp...@skynet.ctr.columbia.edu said:

 to compare 0 bytes worth of data and returns success). In my opinion,
 this is a bug: either the equal() macro should return false, or the
 zero length field should be detected by a sanity check and the function
 should return EINVAL.

OK, I'll agree that this is a bug.

-GAWollman

--
Garrett A. Wollman   | O Siem / We are all family / O Siem / We're all the same
woll...@lcs.mit.edu  | O Siem / The fires of freedom 
Opinions not those of| Dance in the burning flame
MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick

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


SIOCADDMULTI doesn't work, proposed fix

1999-01-31 Thread Bill Paul
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: wp...@ctr.columbia.edu | Center for Telecommunications Research
Home:  wp...@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.cSun 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 majord...@freebsd.org
with unsubscribe freebsd-current in the body of the message


SIOCADDMULTI doesn't work, proposed fix

1999-01-31 Thread Garrett Wollman
On Sun, 31 Jan 1999 17:55:22 -0500 (EST), Bill Paul 
wp...@skynet.ctr.columbia.edu said:

 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.

This is called ``poor man's inheritance''.

I believe it is an error for any code to use AF_UNSPEC for any purpose
other than masks (where it makes sense since the address family is
normally not included in the mask).  A `sockaddr_dl', while by default
longer than a `sockaddr', in this case will fit withing the structure
allotted.

In the future, I fully expect that `sockaddr' will be of maximal
length (we need this for IPv6).

 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.

There are two things which should be done here.

First, the kernel AppleTalk code should be fixed to join the necessary
multicast groups when an interface is first configured for AppleTalk.
(By preference the AARP implementation should be entirely in the
kernel as well, but that's more of a challenge.)  Second, the generic
ether_resolvemulti function should be enhanced to know about AppleTalk
multicast addresses.

-GAWollman

--
Garrett A. Wollman   | O Siem / We are all family / O Siem / We're all the same
woll...@lcs.mit.edu  | O Siem / The fires of freedom 
Opinions not those of| Dance in the burning flame
MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick

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


Re: SIOCADDMULTI doesn't work, proposed fix

1999-01-31 Thread Bill Paul
Of all the gin joints in all the towns in all the world, Garrett Wollman 
had to walk into mine and say:

 On Sun, 31 Jan 1999 17:55:22 -0500 (EST), Bill Paul 
 wp...@skynet.ctr.columbia.edu said:
 
  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.
 
 This is called ``poor man's inheritance''.
 
 I believe it is an error for any code to use AF_UNSPEC for any purpose
 other than masks (where it makes sense since the address family is
 normally not included in the mask).  A `sockaddr_dl', while by default
 longer than a `sockaddr', in this case will fit withing the structure
 allotted.
 
 In the future, I fully expect that `sockaddr' will be of maximal
 length (we need this for IPv6).

There's still one small problem: the code as it stands now can return
success and still not update the multicast filter. If you pass a structure
with AF_LINK as the family but with the length set to 0, if_addmulti()
falsely detects that the entry already matches an existing one and
returns success (it the equal() macro equates to a bcmp(), which tries
to compare 0 bytes worth of data and returns success). In my opinion,
this is a bug: either the equal() macro should return false, or the
zero length field should be detected by a sanity check and the function
should return EINVAL.
 
  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.
 
 There are two things which should be done here.
 
 First, the kernel AppleTalk code should be fixed to join the necessary
 multicast groups when an interface is first configured for AppleTalk.
 (By preference the AARP implementation should be entirely in the
 kernel as well, but that's more of a challenge.)  Second, the generic
 ether_resolvemulti function should be enhanced to know about AppleTalk
 multicast addresses.

The Columbia Appletalk code is not the same as netatalk: it's implemented
entirely in user space and uses BPF as well as manually joining multicast
groups. The existing Columbia Appletalk port, which works on 2.2.x, uses
SIOCADDMULTI with a family of AF_UNSPEC. I rifled through a bunch of
man pages in 3.0-RELEASE trying to find the Right Way To Do This (tm)
but came up empty. If the right way to do this is to cast the struct 
sockaddr to a struct sockaddr_dl and use AF_LINK, then this should be
documented somewhere. (If it is documented and I missed it, feel free
to slap me around and point me in the right direction.)

-Bill

-- 
=
-Bill Paul(212) 854-6020 | System Manager, Master of Unix-Fu
Work: wp...@ctr.columbia.edu | Center for Telecommunications Research
Home:  wp...@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
=

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