2004-06-29 04:09:13

by Ulrich Drepper

[permalink] [raw]
Subject: inconsistency between SIOCGIFCONF and SIOCGIFNAME

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.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖


2004-06-29 08:26:18

by David Miller

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

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_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.

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 =====
--- 1.29/net/ipv4/devinet.c 2004-05-30 11:56:05 -07:00
+++ edited/net/ipv4/devinet.c 2004-06-29 01:17:42 -07:00
@@ -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) {

2004-06-29 16:25:13

by Ulrich Drepper

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

David S. Miller wrote:

> 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.


> 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,

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

2004-06-29 16:32:43

by Stephen Hemminger

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

On Mon, 28 Jun 2004 21:06:25 -0700
Ulrich Drepper <[email protected]> wrote:

> 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.
>

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.

--
Stephen Hemminger mailto:[email protected]
Open Source Development Lab http://developer.osdl.org/shemminger

2004-06-29 19:13:05

by Ulrich Drepper

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

David S. Miller wrote:

> I enclose a potential implementation for the ipv4 instance.
> Please at least make sure it does what you want.

Seems to work nicely.


> 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.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

2004-06-29 19:15:32

by Ulrich Drepper

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

Stephen Hemminger wrote:

> 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.

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.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

2004-06-29 21:19:36

by David Miller

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME


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.

2004-06-30 04:50:46

by Ulrich Drepper

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

David S. Miller wrote:
> 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.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

2004-06-30 05:09:46

by YOSHIFUJI Hideaki

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

In article <[email protected]> (at Tue, 29 Jun 2004 21:45:39 -0700), Ulrich Drepper <[email protected]> says:

> David S. Miller wrote:
> > 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

2004-06-30 05:14:14

by David Miller

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

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.

2004-06-30 07:55:33

by Ulrich Drepper

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

David S. Miller wrote:

> 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.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

2004-06-30 20:03:10

by David Miller

[permalink] [raw]
Subject: Re: inconsistency between SIOCGIFCONF and SIOCGIFNAME

On Wed, 30 Jun 2004 00:51:31 -0700
Ulrich Drepper <[email protected]> wrote:

> David S. Miller wrote:
>
> > 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.