Difference in behaviour between getifaddrs() and ioctl(SIOCGIFCONF)

Jason Curl jcurlnews@arcor.de
Thu Dec 2 20:04:00 GMT 2010

On 02/12/2010 18:59, Corinna Vinschen wrote:
> On Dec  2 14:23, Jason Curl wrote:
>> One of my use cases is to test a particular interface if it has an IP address
>> or not (due to DHCP, AutoIP, etc.). Then on definition of an address, I can
>> trigger a process. This assumes that the interface names remains constant. So a
>> dynamically changing interface name is something I'd like to NOT see.
> Huh?  My proposal does exactly that.  It would always return unique
> interface names.

Maybe I don't understand your proposal. You want to assign an index name 
based on the IPv4 address. The "UUID:Index" is the complete interface 
name. It's unique for that IPv4 address, but as soon as its IP changes, 
so does the interface name.

Then I think ioctl(SIOCGIFCONF) would also need to follow this 
behaviour. ioctl(SIOCGIFxxx) would also need to accept the interface 
names given. Then there will be maximum compatibility in my source with 
how other OSes work. getifaddrs() returns a name, this same name can be 
used with ioctl(). (note 1)

I have an embedded device that I connect to my PC via Ethernet. When I 
physically connect it, I want to start a process. That process should be 
started, when a specified interface receives an IPv4 address, is IFF_UP 
and has a IFF_LINK. So I need to poll this interface.

With Linux, QNX, FBSD, Solaris, I don't even need to use getifaddrs() or 
ioctl(SIOCGIFCONF), I can poll it directly with ioctl(SIOCGIFADDR) as 
normally the interfaces don't have an alias. With Cygwin 1.7.7 I can 
obtain a complete list once, use SIOCGIFFRNDLYNAM to find the interface 
name and then poll (only with SIOCGIFCONF, not with getifaddrs(), my 
original problem). Cygwin 1.5.x was problematic, except if I had 
precisely only one interface, but generally the names were static, so in 
practice it worked.

Now with the proposal, I need to obtain a complete list of all 
interfaces every time I poll, perform a check against SIOCGIFFRNDLYNAM, 
because the name of the interfaces themselves change.

(note 1) I would not like to make assumptions about the format of the 
Cygwin interface name to get the ioctl() value from getifaddrs(). This 
places an unnecessary burden on Cygwin developers that this format 
remains the same always. Cygwin 1.9 might have a better idea yet, 
breaking my code. Thus my suggestion that ioctl() from Cygwin support 
this ":index" format, which it currently doesn't, also in 1.7.7.

>> The solution that I do prefer, is one similar to QNX. QNX behaves differently
>> to Linux, but could be the simplest implementation for Cygwin. If an interface
>> has aliases, it simply has multiple records in getifaddrs(). The ioctl()
>> interface returns the main/preferred address. Cygwin could return the first
>> AF_INET record in this case.
> Here's the problem.  Windows does not mark an IPv4 address as preferred
> address, nor does it always return the addresses in the order you'd expect.
> Actually, it appears as if the addresses of an interface are always returned
> in ascending order (on W7, at least).
> So, following your proposal, if you add an address which is numerically
> lower than the other addresses, the next call to ioctl(SIOCGIFADDR) would
> return the new address.  If you remove the address again it would return
> the old address again.  From my POV this is as much surprising as the
> current behaviour.  Hence my proposal.

That's why it is now a good time to move to getifaddrs() as recommended 
in general for systems that support it. The programmer can remove this 
issue because they get a complete list. Even on Linux, QNX, FreeBSD, 
Solaris, ioctl() can't guarantee atomicity. With ioctl() interface may 
change sometime between queries. getifaddrs() offers the potential for 
atomicity. And they all provide getifaddrs().

This issue will also only be apparent if the user has multiple IPv4 
addresses assigned to a single interface.

I'm also assuming, that IP address orders will only change if there is a 
change in the system configuration. So such a surprise won't occur too 
often. But importantly, interface names are known in advance with 
ioctl() without having to use SIOCGIFCONF.

And it provides for the minimalistic amount of change to Cygwin, remains 
compatible with other OSes and mappings continue to work with names 
returned by getifaddrs() and ioctl() - always.


Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

More information about the Cygwin mailing list