Subject: Re: dhcpd
To: Hisashi T Fujinaka <htodd@twofifty.com>
From: Greg Troxel <gdt@ir.bbn.com>
List: tech-net
Date: 09/12/2007 19:48:02
[dhclient fails with sys/net/if.c 1.200]
I am also seeing trouble with dhclient. The SIOCGIFCONF interface is
tricky, and it may be that moving to struct sockaddr_storage results in
different interpretations of what the API should be. racoon works fine
with the new version.
It's not surprising both dhclient and dhcpd fail; they use the same
support code.
Can anyone run them under gdb and see how they cope with parsing the
results of SIOCGIFCONF?
But, I can see the problem; dhclient checks the size of the sockaddr in
ifreq against struct sockaddr, not against sizeof(ifreq).
There's also another bug, in that the 'was the buffer big enough check'
is unreliable. But that's not what's causing trouble now for most
people.
So, this comes down to whether the API for struct ifreq was
size is determined by sa_len if size is > struct sockaddr
or
size is determined by sa_len if size is > (union in ifreq for
sockaddrs, and hence the sockaddr actually needs to extend beyond
ifreq)
racoon assumed the latter. The former is crazy - it means that an IPv4
address results in ifreq spacing of struct ifreq (144 bytes), because
sockaddr_in fits in sockaddr. But sockaddr_dl or sockaddr_in6 is
bigger, and would result in *smaller* struct ifreq, exactly being big
enough.
The real problem is that SIOCGIFCONF never had a real API definition.
I think the right fix is to change dhcp to use sizeof (ifreq.ifr_ifru)
instead of sockaddr for deciding if more space is needed. This declares
that we follow the 2nd choice of what the API used to be.