inconsistency between SIOCGIFCONF and SIOCGIFNAME
Subsystems (2)
POSIX does not specify the if_indextoname and if_nameindex functions, they are only vaguely specified in an RFC. So there is some room for interpretation but still I think it is an issue.
If SIOCGIFCONF to query the system's interfaces only active interfaces are returned. But SIOCGIFNAME (and SIOCGIFINDEX) allow querying interfaces which are down and not fully initialized.
RFC 3493 says if_nameindex should return *all* interfaces. This means that neither if_indextoname or if_nametoindex (defined in the same rfc) should define more interfaces.
With the current kernels all I could do is to make if_indextoname and if_nametoindex slower by always calling if_nameindex implicitly to see whether the interface is defined at all. It would be much better if the kernel could do the right thing. I.e., do one of the following:
~ if the SIOCGIFCONF, return all interfaces SIOCGIFNAME also knows
about.
~ do not allow SIOCGIFNAME and SIOCGIFINDEX) to return values if
SIOCGIFCONF, would not return any.
Signature · 1 line
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Quoted 10 lines · On Mon, 28 Jun 2004 21:06:25 -0700 Ulrich Drepper <[email protected]> wrote:
With the current kernels all I could do is to make
if_indextonameandif_nametoindexslower by always callingif_nameindeximplicitly to see whether the interface is defined at all. It would be much better if the kernel could do the right thing. I.e., do one of the following:~ if the SIOCGIFCONF, return all interfaces SIOCGIFNAME also knows
about.~ do not allow SIOCGIFNAME and SIOCGIFINDEX) to return values if
SIOCGIFCONF, would not return any.
Indeed the if_* routines are specified as you describe, yet the BSD ioctl interfaces discussed here are defined by BSD and therefore I'm hesitant to change how they behave. But I've actually discovered that we diverge from BSD, see below.
What I can recommend is that you obtain the interface information using NETLINK sockets. Specifically via the RTM_GETLINK message. I believe it provides the functionality you desire, and also because I believe you are using netlink for some other implementations in glibc you can make this if_* code share some of that code.
It is one idea, the other is to make us match BSD. At least my best understanding of what BSD does based upon reading the description in Steven's Volume 2.
The exact check we make during ipv4 gifconf processing is that we do not report the interface if either of the following is true:
1) No ipv4 private area has been allocated and attached to the device. This is created the first time an ipv4 address is assigned to a device.
2) No ipv4 addresses are presently assigned to the device.
So it is possible for the device to be UP yet not get reported by SIOCGIFCONF. This occurs when no ipv4 addresses are assigned to it. BSD reports all interfaces, as best as I can tell.
Anyways, I guess we could do your suggestion. SIOCGIFCONF is actually implemented using per-protocol handlers. So, for example there is an ipv4 handler, an ipv6 one, etc. We'd need to make the change for all of them.
I enclose a potential implementation for the ipv4 instance. Please at least make sure it does what you want.
I really really hope there is not some application out there that assumes that devices reported by SIOCGIFCONF are all up. That works now, and we'd break things by making the suggested change. So this is what I'm most concerned about.
===== net/ipv4/devinet.c 1.29 vs edited =====
net/ipv4/devinet.c +11 -1
@@ -720,8 +720,18 @@struct ifreq ifr;int done =0 ; -if (!in_dev || (ifa = in_dev->ifa_list) ==NULL ) +if (!in_dev || (ifa = in_dev->ifa_list) ==NULL ) { +if (!buf) +return sizeof (struct ifreq ); +if (len >= (int )sizeof (ifr)) { +memset (&ifr,0 ,sizeof (struct ifreq )); +strcpy (ifr.ifr_name, dev->name); +if (copy_to_user (buf, &ifr,sizeof (struct ifreq ))) +return -EFAULT ; + done +=sizeof (struct ifreq ); + } goto out; + }for (; ifa; ifa = ifa->ifa_next) {if (!buf) {
Quoted 4 lines · David S. Miller
Anyways, I guess we could do your suggestion. SIOCGIFCONF is actually implemented using per-protocol handlers. So, for example there is an ipv4 handler, an ipv6 one, etc. We'd need to make the change for all of them.
I might not look for the right thing, but there are only two places where register_gifconf is used: in net/ipv4/devinet.c and net/decnet/dn_dev.c. There is no support for IPv6-only interfaces and interfaces for other protocols. So in addition to your change only the DECnet stuff needs changing.
Quoted 2 lines
I enclose a potential implementation for the ipv4 instance. Please at least make sure it does what you want.
I'll try the patch asap. Thanks,
Signature · 1 line
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Quoted 2 lines · David S. Miller
I enclose a potential implementation for the ipv4 instance. Please at least make sure it does what you want.
Seems to work nicely.
Quoted 4 lines
I really really hope there is not some application out there that assumes that devices reported by SIOCGIFCONF are all up. That works now, and we'd break things by making the suggested change. So this is what I'm most concerned about.
The worst that could happen is that some more interfaces are reported. Since the information provided by SIOCGIFCONF isn't really enough to do anything meaningful other calls are needed at which point those interfaces can be weeded out, if this is wanted. Also, the address family reported for those interfaces is AF_UNSPEC which should be a hint strong enough to recognize them.
Signature · 1 line
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Ulrich, is there a major reason why you can't use RTNETLINK for your implementation? It behaves as you desire and gives you all of the link information you are after, in place of SIOCGIFCONF.
I've done some more thinking and I really don't want to put this SIOCGIFCONF hack into the tree.
Quoted 3 lines · David S. Miller
Ulrich, is there a major reason why you can't use RTNETLINK for your implementation? It behaves as you desire and gives you all of the link information you are after, in place of SIOCGIFCONF.
When was the netlink interface introduced? The ioctl() code is most probably older and therefore we would still get wrong results on old kernels. I don't know the reason why you hesitate, but the patch seems really harmless and, as you pointed out, more compatible with the BSD version.
Signature · 1 line
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
In article <[email protected]> (at Tue, 29 Jun 2004 21:45:39 -0700), Ulrich Drepper <[email protected]> says:
Quoted 10 lines
Quoted 3 lines · David S. Miller
Ulrich, is there a major reason why you can't use RTNETLINK for your implementation? It behaves as you desire and gives you all of the link information you are after, in place of SIOCGIFCONF.
When was the netlink interface introduced? The
ioctl()code is most probably older and therefore we would still get wrong results on old kernels. I don't know the reason why you hesitate, but the patch seems really harmless and, as you pointed out, more compatible with the BSD version.
2.2.x or later have (modern) netlink support.
--yoshfuji
Quoted 5 lines · On Tue, 29 Jun 2004 21:45:39 -0700 Ulrich Drepper <[email protected]> wrote:
When was the netlink interface introduced? The
ioctl()code is most probably older and therefore we would still get wrong results on old kernels. I don't know the reason why you hesitate, but the patch seems really harmless and, as you pointed out, more compatible with the BSD version.
RTNETLINK interfaces to get link information has existed since at least 2.0.x or something :-) In fact, the first RTNETLINK codes are the ones to obtain and set link information.
All of these BSD ioctls are deprecated interfaces, back compatability hacks if you real, and the recommended interface to change link and route information is RTNETLINK.
I really hesitate to change the ioctl() code, because basically my suggested change puts effectively an AF_UNSPEC address there (this is what you get with a zero'd out sockaddr_t). Who knows what that means. Sure most apps will ignore it but I absolutely do not want to take the chance.
This is especially unnecessary since rtnetlink does exactly what you want already, so we don't need to add a new interface nor change the semantics of an old one.
Quoted 3 lines · David S. Miller
This is especially unnecessary since rtnetlink does exactly what you want already, so we don't need to add a new interface nor change the semantics of an old one.
I do have code using netlink in cvs now. We'll see whether people complain.
Signature · 1 line
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Quoted 7 lines · On Wed, 30 Jun 2004 00:51:31 -0700 Ulrich Drepper <[email protected]> wrote:
Quoted 3 lines · David S. Miller
This is especially unnecessary since rtnetlink does exactly what you want already, so we don't need to add a new interface nor change the semantics of an old one.
I do have code using netlink in cvs now. We'll see whether people complain.
Let me know, if you can't make it work I'm more than willing to reconsider the SIOCGIFCONF change.
Quoted 4 lines · On Mon, 28 Jun 2004 21:06:25 -0700 Ulrich Drepper <[email protected]> wrote:
POSIX does not specify the
if_indextonameandif_nameindexfunctions, they are only vaguely specified in an RFC. So there is some room for interpretation but still I think it is an issue.
Quoted 8 lines
If SIOCGIFCONF to query the system's interfaces only active interfaces are returned. But SIOCGIFNAME (and SIOCGIFINDEX) allow querying interfaces which are down and not fully initialized.
RFC 3493 says
if_nameindexshould return *all* interfaces. This means that neitherif_indextonameorif_nametoindex(defined in the same rfc) should define more interfaces.
The bridge utilities depends on being able to do if_indextoname and if_nametoindex for interfaces that aren't active to IP. Other non-IP usage probably does as well.
Signature · 2 lines
Stephen Hemminger mailto:[email protected] Open Source Development Lab http://developer.osdl.org/shemminger
Quoted 3 lines · Stephen Hemminger
The bridge utilities depends on being able to do
if_indextonameandif_nametoindexfor interfaces that aren't active to IP. Other non-IP usage probably does as well.
This is not changed by DaveM's patch. All the patch does is to cause SIOCGIFCONF to report all interfaces SIOCGIFINDEX knows about as well. So now if_indextoname() succeeds only if_indexname() also returns the interface name, making the three interfaces consistent.
Signature · 1 line
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖