lkml.org 
[lkml]   [1999]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: ioctl SIOCGIFADDR bug
Bob wrote:

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

Yes, I forgot you have to set the socket address family:

bzero(&ifr,sizeof(struct ifreq));
ifr.ifru_addr.sa_family = AF_INET;

The reason is because interfaces were designed to allow multiple protocols to run on
them, (at least in theory), thus requiring different address families.

Setting byte 18 to 1 sets sa_family to AF_UNIX, so the fact that your code worked is
somewhat strange. But this is definitely not a kernel bug. BTW, the result you got back
for the "bogus" IP
address were the last 4 octets of the MAC address.

Zachary Amsden
ZAmsden@engr.sgi.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/

\
 
 \ /
  Last update: 2005-03-22 13:53    [W:0.032 / U:2.672 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site