Messages in this thread | | | Date | Thu, 05 Aug 1999 17:09:38 -0700 | From | Zachary Amsden <> | Subject | Re: 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/
| |