[Toybox] [CLEANUP] Ifconfig commit 919

Rob Landley rob at landley.net
Sun Jun 2 19:12:17 PDT 2013


Commit 919:

   http://landley.net/hg/toybox/rev/919

Starting with a couple of side items, I inlined the last instance of  
set_flags(), and
refactored bits of get_device_info(). (Reordered a couple of lines but  
no significant
code changes there.)

I made readconf() use xsocket(), cleaned up the size finding loop, and  
removed a NOP
errno assignment. I also removed hasaddr, and instead just checked if  
the address
field has any nonzero bits. (You can't assign 0.0.0.0 to an interface,  
it's a
broadcast address.)

And then the big todo item this patch: in ifconfig_main(), introduce  
IFREQ_OFFSZ()
and poke(), and use them it to move another ~dozen command line option  
handlers
into the table.

Most of the collated option handlers just set one field in ifre and call
an ioctl. The SIOCSIFMAP ones need a corresponding SIOCGIFMAP call first
(S for set, G for get), and two of them are actually NOPs (so both  
fields
are 0).

For the 'set one field, call an ioctl' ones, we need four pieces of
information:

   1) A way to indicate of this new category of action
   2) Offset of field in ifre.
   3) Size of field in ifre.
   4) ioctl to call

We already hijacked "off" to store #4 in commit 906, but the first 3  
have
to be packed into "on". Let's look more closely at #1:

The original action was setting flags via an  
ioctl(SIOCGIFFLAGS/SIOCSIFFLAGS)
sandwich with ifre.ifr_flags twiddling in between.

Then we overloaded the "off" field to indicate a different ioctl to  
call,
eating the next command line argument (*argv++) as a network address  
assigned
to ifre.ifr_flags. This was indicated by "(off & 0xFFFFFF00) == 0x8900"  
which
is never a valid flag combination. (All the ioctl macros we're using  
start
with 0x89, because the old _IO(type,nr) macros had 0x89 as the type for
"socket" ioctls. See "man 2 ioctl_list" for details.)

The new action consumes *argv as an unsigned long and assigns it
to an arbitrary field of ifre, then calls the ioctl. We can indicate  
this
by putting a negative value in "on", because there's no IFF_FLAG macro
that sets the top bit so no combination of flags will give a negative  
value.

As for the other 2 pieces of information, the offset's never going to be
bigger than 64k and the size is at most 8, so we can bit shift them  
together
then negate the result.

The IFREQ_OFFSZ() macro combines a field's offset and size into the  
same int
(size << 16 + offset), and then negates it to signal how to handle it.  
(There
isn't an IFF_FLAG for 0x80000000 so no combiantion of flags can be  
negative.)

The new table entries have IFREQ_OFFSZ() in "on" and the IOCTL to call  
in "off".
If "on" is less than zero, we convert the next argument to an unsigned  
long
(I.E. strtoul(*argv)). Then we use the size and offset with the "poke()"
function, which writes a value to a location at a power of two size.
(In theory you could memcpy it, but for big endian machines memcpy
2 bytes from the start of an int into a short will give you the wrong  
bytes.)

This brings us down under 700 lines (688).


More information about the Toybox mailing list