[Toybox] Entering the home stretch on ifconfig...

Rob Landley rob at landley.net
Mon Jun 10 11:10:41 PDT 2013


On 06/10/2013 01:31:36 AM, idunham at lavabit.com wrote:
> On Sat, Jun 08, 2013 at 02:40:04PM -0500, Rob Landley wrote:
> > On 06/07/2013 01:11:50 AM, Bastian Bittorf wrote:
> > >* Rob Landley <rob at landley.net> [07.06.2013 07:57]:
> > >> It looks like show_iface() enumerates /proc/net/dev and then  
> calls
> > >> readconf() to do ioctl() based enumeration. The /proc one gives
> > >us RX
> > >> bytes and such, the ioctl gives us a "virtual interface" (ala  
> lo:0 I
> > >
> > >dont use the deprecated one, but /sys/class/net/
> > >or even "better" via netlink.
> >
> > I didn't write this code, I'm just cleaning it up. Patches welcome.
> >
> > Where is it deprecated? Documentation/filesystems/proc.txt currently
> > says (line 1029):
> >
> >  dev           network devices with statistics
> >
> > Line 1056 then provides an example. No warnings about using it.
> 
> I don't know for sure, but he may mean the interface referred to in  
> this
> line in the linux.die.net version of the manpage:

Last time I checked that was a random assortment of BSD, Solaris, and  
obsolete Linux man pages. But it's been a while...

> "Ifconfig uses obsolete kernel interface. It uses the ioctl access  
> method
> to get the full address information, which limits hardware addresses  
> to 8
> bytes. Since an Infiniband address is 20 bytes, only the first 8  
> bytes of
> Infiniband address are displayed."

I don't have any infiniband hardware to test on, but I note that the  
set codepath handles 20 bytes of infiniband data around line 586.

The display side has an infiniband case on line 257, but the actual  
hardware address display only triggers for ARPHRD_ETHER so it doesn't  
look like it displays an infiniband address at all. As for fetch, yes  
it does ioctl(TT.sockfd, SIOCGIFHWADDR, &ifre) and the field it fills  
out is struct sockaddr, and according to linux/socket.h _K_SS_MAXSIZE  
is 128 so if the ioctl can't fit 20 bytes of hardware address in there  
something is wrong.

Let's see what the kernel actually does with SIOCGIFHWADDR? Well, in  
net/core/dev_ioctl.c dev_ioctl() calls dev_ifsioc_locked(), and _that_  
has:

     memcpy(ifr->ifr_hwaddr.sa_data, dev->dev_addr,
         min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len));

And ifr_hwaddr.sa_data is "struct sock", and in include/linux/socket.h:

   /*
    *      1003.1g requires sa_family_t and that sa_data is char.
    */

   struct sockaddr {
           sa_family_t     sa_family;      /* address family,  
AF_xxx       */
           char            sa_data[14];    /* 14 bytes of protocol  
address */
   };

Great. So the uapi one is 128 bytes, but the kernel internal one is 16,  
only 14 of which are left for payload after the family. So the die.net  
man page has the size wrong, but the limit is still under 20.

(Sigh. I see why infiniband has a CONFIG symbol to chop it out  
everywhere, the implementation is really crappy.)

So what method are you supposed to use to fetch an infiniband address?  
Some variant of "cat /sys/class/net/$IFACE/address" and just output  
that verbatim?

The problem remains: I don't have an inifiniband test system. I can  
just chop infiniband support out completely, but when it comes to  
extending it I haven't got a test environment. (If somebody _else_  
wants to test it...)

> Of course, /sys/ carries all sorts of dire warnings about not being
> intended as a public interface...although it's really the nicest one  
> to
> use.

Yeah, I have history with those guys.

   http://landley.net/notes-2008.html#05-05-2008

Rob


More information about the Toybox mailing list