On Wed, 20 Dec 2000, Nicholas Dronen wrote: [...] > $ strace -e trace=ioctl ifconfig eth0:1 >/dev/null More correctly, we need to look at happens when an interface's parameters are set (the above cause a bunch of SIOG*, i.e. getting parameter values): ----------------------------------------------------------------------- gull:~# ifconfig dummy0 down gull:~# strace -e trace=ioctl ifconfig dummy0 10.42.42.0 netmask 255.255.0.0 ioctl(4, SIOCSIFADDR, 0xbffffc6c) = 0 ioctl(4, SIOCGIFFLAGS, 0xbffffbbc) = 0 ioctl(4, SIOCSIFFLAGS, 0xbffffbbc) = 0 ioctl(4, SIOCSIFNETMASK, 0xbffffc6c) = 0 gull:~# ifconfig dummy0 dummy0 Link encap:Ethernet HWaddr 00:00:00:00:00:00 inet addr:10.42.42.0 Bcast:10.255.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING NOARP MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 ----------------------------------------------------------------------- [...] > I believe the problem is *not* with the kernel, which should > provide mechanism, not policy. Rather, ifconfig needs to > pass more appropriate values in the struct ifreq when issuing > the SIOCSIFBRDADDR ioctl. That argument is not without merit, but I remain unconvinced. The counter-argument is that currently the kernel is, having been supplied with an address and mask, conjuring up an incorrect broadcast address based on a classful view of things. IMHO, an address and mask are sufficient data from which to derive the correct broadcast. > Regarding where in the kernel this is handled, see: [snip] > net/ipv4/devinet.c:devinet_ioctl() # where the real work is done This is the one that interests me right now. I was trying to make some sense of it (on the train home!) and might be getting somewhere. In devinet_ioctl there is a big "switch(cmd)". In that we see that setting the address also causes setting both ifa_prefixlen by classful logic and ifa_mask from ifa_prefixlen; then the broadcast address is set as ifa_address|~ifa_mask - i.e. along classful lines. Mmm... does this imply that changing the IP address of an interface will reset its mask to the classful default? This suggests that, except for classful masks, we must always follow any setting of IP address by a setting of the mask (even if the mask remained constant when the address was changed). That being the case, it's not unreasonable to consider always setting the broadcast address when the mask is set. Untested diff attached. This is from net/ipv4/devinet.c 1.28.2.4 from kernel 2.2.18. Regards, Neale.
--- devinet.c Mon Dec 11 11:49:44 2000 +++ devinet.c.nb0 Wed Dec 20 22:21:43 2000 @@ -590,6 +590,16 @@ inet_del_ifa(in_dev, ifap, 0); ifa->ifa_mask = sin->sin_addr.s_addr; ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); + /* + * In a CIDR-world, it's probably a Good Idea + * to update the Broadcast address when the + * netmask is changed. Note that this could + * surprise someone who has set the broadcast + * non-standard and then sets the netmask. + * Neale Banks <neale@lowendale.com.au> + * Wed, 20 Dec 2000 19:56:54 +1100 + * / + ifa->ifa_broadcast = ifa->ifa_address|~ifa->ifa_mask; inet_set_ifa(dev, ifa); } break;