Re: ioctl SIOCGIFADDR bug

Bob (bob@cavu.com)
Thu, 5 Aug 1999 19:32:46 -0400


Zachary wrote:

> It's not a bug. bzero() the ifreq struct before calling the kernel. The
> kernel does it for you on error, hence it works the second time.

If you take another look at the code, you'll notice that my ifreq structure
is declared static. This means that it is initialized to zeros when the
program is loaded. However, you gave me an idea.

Through trial and error I determined that if the 18'th byte of the structure
is set to 1 (with all other bytes 0) then it works the first time. If it is
zeroed out before each call then neither call works. The new program that
causes this to work is appended.

This still strikes me as a bug as it is not documented (that I know of) and
this behavior is not present for the related SIOCGIF* calls.

> Zachary Amsden
> ZAmsden@engr.sgi.com

> Bob wrote:

> > I have observed a possible bug in the kernel (or device drivers) when using
> > ioctl with the SIOCGIFADDR command to get the address of one's network
> > interface, typically "eth0".
> >
> > The bug is that the ioctl() must be called twice as the first time it
> > returns garbage. The other SSIOCGIF* commands (such as NETMASK and BROADCAST)
> > do not suffer from this even though their code paths in the kernel are in
> > common. The ifconfig program seems to not suffer from this problem because
> > it invokes the ioctl() with other SIOCGIF* commands prior to invoking the
> > SIOCGIFADDR command.
> >
> > I have observed this both on Red Hat 5.1 with kernel 2.0.34 on a generic
> > i586 tower and on Slackware 3.4 with kernel 2.0.30 running on a Toshiba
> > T4700CT laptop.
> >
> > Please include email to me (bob@cavu.com) in any replies as I do not
> > normally follow the kernel mailing list.
> >
> > I enclose a demonstration program and its output for your consideration.
> >
> > ------------------------------- addr.c -----------------------------
> > #include <string.h>
> > #include <sys/socket.h>
> > #include <asm/ioctls.h>
> > #ifndef SIOCGIFADDR
> > #include <ioctls.h>
> > #endif
> > #include <net/if.h>
> > #include <stdio.h>
> >
> > main()
> > {
> > zzz();
> > zzz();
> > exit(0);
> > }
> >
> > zzz()
> > {
> > int inet_sock;
> > int i;
> > static
> > struct ifreq ifr;
> > static
> > int n;
> >
> > inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
> > strcpy(ifr.ifr_name, "eth0");
> > if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)
> > perror("zzz: ioctl");
> > printf("zzz%d: &ifr.ifr_addr=0x%X SIOCGIFADDR=0x%X dev=%s\n",
> > n, &ifr.ifr_addr, SIOCGIFADDR, "eth0");
> > printf("zzz%d: dump:\n", n);
> > for (i=0; i<sizeof ifr; i++)
> > printf("%3d ", ((unsigned char *) &ifr)[i]);
> > printf("\n");
> > printf("==============================\n");
> > n++;
> > }
> > ------------------------------- output of ./addr -----------------------------
> > zzz0: &ifr.ifr_addr=0x8049810 SIOCGIFADDR=0x8915 dev=eth0
> > zzz0: dump:
> > 101 116 104 48 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 96
> > 8 137 123 90 0 0 0 0 0 0 0 0
> > ^^^^^^^^^^^^^^^^ bogus inet addr
> > ==============================
> > zzz1: &ifr.ifr_addr=0x8049810 SIOCGIFADDR=0x8915 dev=eth0
> > zzz1: dump:
> > 101 116 104 48 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0
> > 139 162 250 186 0 0 0 0 0 0 0 0
> > ^^^^^^^^^^^^^^^^ correct inet addr
> > ==============================
> > ------------------------------ output of "ifconfig eth0" --------------------------
> > eth0 Link encap:Ethernet HWaddr 00:60:08:89:7B:5A
> > inet addr:139.162.250.186 Bcast:139.162.250.255 Mask:255.255.255.0
> > ^^^^^^^^^^^^^^^ correct inet addr from ifconfig
> > UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
> > RX packets:490829 errors:165 dropped:165 overruns:1584997 frame:165
> > TX packets:1970214 errors:0 dropped:0 overruns:0 carrier:4755428 coll:
> > 1584858
> > Interrupt:3 Base address:0x300
> > ----------------------------------------------------------------------
> > Thanks,
> > Bob
> > bob@cavu.com
> > -
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.rutgers.edu
> > Please read the FAQ at http://www.tux.org/lkml/

------------------------------------------ start of new addr.c ---------
#include <string.h>
#include <sys/socket.h>
#include <asm/ioctls.h>
#ifndef SIOCGIFADDR
#include <ioctls.h>
#endif
#include <net/if.h>
#include <stdio.h>

main()
{
zzz();
zzz();
}

zzz()
{
int inet_sock;
int i;
static
struct ifreq ifr;
static
int n;
bzero(&ifr, sizeof ifr);
((unsigned char *) &ifr)[17] = 1;

inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
strcpy(ifr.ifr_name, "eth0");
if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)
perror("zzz: ioctl");
printf("zzz%d: &ifr.ifr_addr=0x%X SIOCGIFADDR=0x%X dev=%s\n",
n, &ifr.ifr_addr, SIOCGIFADDR, "eth0");
printf("zzz%d: dump:\n", n);
for (i=0; i<sizeof ifr; i++)
printf("%3d ", ((unsigned char *) &ifr)[i]);
printf("\n");
printf("==============================\n");
n++;
}
------------------------------------------ end of new addr.c ---------

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/