diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | inet/test-ifaddrs.c | 7 | ||||
-rw-r--r-- | sysdeps/generic/ifreq.h | 32 | ||||
-rw-r--r-- | sysdeps/gnu/ifaddrs.c | 30 |
4 files changed, 64 insertions, 20 deletions
@@ -7,6 +7,21 @@ 2002-11-25 Roland McGrath <roland@redhat.com> + * inet/test-ifaddrs.c (main: addr_string): Handle null SA. + Grok AF_LINK if defined. + From Momchil Velikov <velco@fadata.bg>. + + * sysdeps/gnu/ifaddrs.c (getifaddrs): If ioctl fails for netmask, + brdaddr, or dstaddr, just set those pointers to null and don't fail. + Reported by Momchil Velikov <velco@fadata.bg>. + + * sysdeps/generic/ifreq.h (__if_nextreq) [_HAVE_SA_LEN]: If sa_len + is > sizeof IFR->ifa_addr, advance past the whole longer length. + (__ifreq): Count up NIFS that way too. + Reported by Momchil Velikov <velco@fadata.bg>. + + * sysdeps/mach/hurd/lchmod.c: Include <fcntl.h>. + * sysdeps/mach/hurd/i386/init-first.c: Include <ldsodefs.h> and <fpu_control.h>. diff --git a/inet/test-ifaddrs.c b/inet/test-ifaddrs.c index 42fb7e75bf..52cda73508 100644 --- a/inet/test-ifaddrs.c +++ b/inet/test-ifaddrs.c @@ -50,6 +50,9 @@ Name Flags Address Netmask Broadcast/Destination"); char abuf[64], mbuf[64], dbuf[64]; inline const char *addr_string (struct sockaddr *sa, char *buf) { + if (sa == NULL) + return "<none>"; + switch (sa->sa_family) { case AF_INET: @@ -60,6 +63,10 @@ Name Flags Address Netmask Broadcast/Destination"); return inet_ntop (AF_INET6, &((struct sockaddr_in6 *) sa)->sin6_addr, buf, sizeof abuf); +#ifdef AF_LINK + case AF_LINK: + return "<link>"; +#endif case AF_UNSPEC: return "---"; default: diff --git a/sysdeps/generic/ifreq.h b/sysdeps/generic/ifreq.h index 0d975be61c..4871c8d1d8 100644 --- a/sysdeps/generic/ifreq.h +++ b/sysdeps/generic/ifreq.h @@ -24,6 +24,15 @@ #include <sys/socket.h> #include <sys/ioctl.h> +static inline struct ifreq * +__if_nextreq (struct ifreq *ifr) +{ +#ifdef _HAVE_SA_LEN + if (ifr->ifa_addr > sizeof ifr->ifa_addr) + return (struct ifreq *) ((char *) &ifr->ifa_addr + ifr->ifa_addr.sa_len); +#endif + return ifr + 1; +} static inline void __ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd) @@ -63,23 +72,28 @@ __ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd) } while (rq_len < sizeof (struct ifreq) + ifc.ifc_len); - nifs = ifc.ifc_len / sizeof (struct ifreq); - if (fd != sockfd) __close (fd); +#ifdef _HAVE_SA_LEN + struct ifreq *ifr = ifreqs; + nifs = 0; + while ((char *) ifr < ifc.ifc_buf + ifc.ifc_len) + { + ++nifs; + ifr = __if_nextreq (ifr); + if (ifr == NULL) + break; + } +#else + nifs = ifc.ifc_len / sizeof (struct ifreq); +#endif + *num_ifs = nifs; *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq)); } -static inline struct ifreq * -__if_nextreq (struct ifreq *ifr) -{ - return ifr + 1; -} - - static inline void __if_freereq (struct ifreq *ifreqs, int num_ifs) { diff --git a/sysdeps/gnu/ifaddrs.c b/sysdeps/gnu/ifaddrs.c index 0c1ae5bf05..6ecc457e50 100644 --- a/sysdeps/gnu/ifaddrs.c +++ b/sysdeps/gnu/ifaddrs.c @@ -79,11 +79,9 @@ getifaddrs (struct ifaddrs **ifap) ifr = ifreqs; do { - /* Fill in all pointers to the storage we've already allocated. */ + /* Fill in pointers to the storage we've already allocated. */ storage[i].ia.ifa_next = &storage[i + 1].ia; storage[i].ia.ifa_addr = &storage[i].addr; - storage[i].ia.ifa_netmask = &storage[i].netmask; - storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; /* & dstaddr */ /* Now copy the information we already have from SIOCGIFCONF. */ storage[i].ia.ifa_name = strncpy (storage[i].name, ifr->ifr_name, @@ -100,26 +98,36 @@ getifaddrs (struct ifaddrs **ifap) ifr->ifr_addr = storage[i].addr; if (__ioctl (fd, SIOCGIFNETMASK, ifr) < 0) - break; - storage[i].netmask = ifr->ifr_netmask; + storage[i].ia.ifa_netmask = NULL; + else + { + storage[i].ia.ifa_netmask = &storage[i].netmask; + storage[i].netmask = ifr->ifr_netmask; + } if (ifr->ifr_flags & IFF_BROADCAST) { ifr->ifr_addr = storage[i].addr; if (__ioctl (fd, SIOCGIFBRDADDR, ifr) < 0) - break; - storage[i].broadaddr = ifr->ifr_broadaddr; + storage[i].ia.ifa_broadaddr = NULL; + { + storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; + storage[i].broadaddr = ifr->ifr_broadaddr; + } } else if (ifr->ifr_flags & IFF_POINTOPOINT) { ifr->ifr_addr = storage[i].addr; if (__ioctl (fd, SIOCGIFDSTADDR, ifr) < 0) - break; - storage[i].broadaddr = ifr->ifr_dstaddr; + storage[i].ia.ifa_broadaddr = NULL; + else + { + storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; + storage[i].broadaddr = ifr->ifr_dstaddr; + } } else - /* Just 'cause. */ - memset (&storage[i].broadaddr, 0, sizeof storage[i].broadaddr); + storage[i].ia.ifa_broadaddr = NULL; storage[i].ia.ifa_data = NULL; /* Nothing here for now. */ |