Subject: Re: Updating arp(8) to use getifaddrs (cf. bin/8566)
To: Luke Mewburn <lukem@netbsd.org>
From: Andrew Brown <atatat@atatdot.net>
List: tech-net
Date: 11/07/2002 09:17:35
>The problem with SIOCGIFCONF as used by most programs is that it
>doesn't cater for when the number of interfaces * sizeof(struct ifreq)
>(== 32) exceeds the buffer size passed in, so you might get truncated
>results.  There is a way to detect and work around this, except non
>of the programs in usr.sbin/* that use SIOCGIFCONF do this, and won't
>work correctly if the buffer size is exceeded.
>(I checked various programs in usr.sbin which use SIOCGIFCONF, and
>they support between 10, 16, 32, 256 (or 1 case, 512) addresses.)

they're done incredibly wrong then.  my understanding of the
"canonical" way to use SIOCGIFCONF was to call it once with an empty
struct ifconf (ie, ifc_buf is null and ifc_len is zero), and then
malloc a buffer of the size returned in ifc_len.  probably with a pad
so that any *new* addresses that show up in between your first a
second calls are also covered.  it's simple to check that you didn't
"get back" more data than you expected if you save the value of
ifc_len between the first and second calls.

>IIRC, SIOCGIFCONF also can't support sockaddr_in6 addresses, or any
>other sockaddr > 16 bytes long...

from a program i wrote a while back for a reason i don't remember...

	% ./printifaddrs 
	lo0: fam=LINK len=20 addr=[lo0 -]
		(index=1 type=(LOOPBACK) nlen=3 alen=0 slen=0)
	lo0: fam=INET len=16 addr=127.0.0.1
		(port=0)
	lo0: fam=INET6 len=28 addr=::1
		(port=0 flow=0 scope=0)
	lo0: fam=INET6 len=28 addr=fe80:1::1
		(port=0 flow=0 scope=0)
	...
	ep0: fam=LINK len=20 addr=[ep0 00:10:4b:9f:ab:87]
		(index=8 type=IEEE802 nlen=3 alen=6 slen=0)
	ep0: fam=INET len=16 addr=206.223.36.134
		(port=0)
	ep0: fam=INET6 len=28 addr=fe80:8::210:4bff:fe9f:ab87
		(port=0 flow=0 scope=0)

it just calls SIOCGIFCONF (twice) and prints what it gets back.  the
INET and INET6 cases are the only special ones.  the LINK address is
printed by the default case.  SIOCGIFCONF can clearly handle stuff
larger than 16 bytes.  :-P

i also once wrote a program that printed the moral equivalent of the
output of ifconfig -a, but which was portable across many operating
systems (linux, netbsd, solaris, hpux, pyramid nile) since i was
discovering some that didn't *have* anything like that and i needed
it.  hmm...i wonder where that went...

using SIOCGIFCONF is like implementing des.  sure it's tedious (with
all those one and two bit rotates, and the "random" bit swapping) but
you can do it, and once you've done it, you can do it again easily.

-- 
|-----< "CODE WARRIOR" >-----|
codewarrior@daemon.org             * "ah!  i see you have the internet
twofsonet@graffiti.com (Andrew Brown)                that goes *ping*!"
werdna@squooshy.com       * "information is power -- share the wealth."