Difference in behaviour between getifaddrs() and ioctl(SIOCGIFCONF)
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
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
More information about the Cygwin