This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
FreeBSD port (55): getifaddrs, iteration through list of interfaces
- From: Bruno Haible <bruno at clisp dot org>
- To: libc-alpha at sources dot redhat dot com
- Date: Fri, 20 Sep 2002 16:23:56 +0200 (CEST)
- Subject: FreeBSD port (55): getifaddrs, iteration through list of interfaces
The SIOCGIFCONF ioctl on FreeBSD differs from the one on Linux in two ways:
- The list it returns consists of entries of varying length.
- Not all entries refer to enabled interfaces.
Here is a patch to enhance the portability of getifaddrs. Stepping through
a list of interfaces now consists of repeated application of __if_nextreq.
2002-09-17 Bruno Haible <bruno@clisp.org>
* sysdeps/generic/ifreq.h (__if_nextreq): New function.
* sysdeps/unix/sysv/linux/ifreq.h (__if_nextreq): New function.
* sysdeps/mach/hurd/ifreq.h (__if_nextreq): New function.
* resolv/res_hconf.c (_res_hconf_reorder_addrs): Use __if_nextreq
for iterating through the list of interfaces.
* sysdeps/gnu/ifaddrs.c (getifaddrs): Likewise. When encountering an
interface with unavailable netmask, skip it but don't abort the loop.
diff -r -c3 glibc-20020910.bak/sysdeps/generic/ifreq.h glibc-20020910/sysdeps/generic/ifreq.h
*** glibc-20020910.bak/sysdeps/generic/ifreq.h Thu Jul 25 13:18:17 2002
--- glibc-20020910/sysdeps/generic/ifreq.h Tue Sep 17 02:22:05 2002
***************
*** 74,79 ****
--- 75,87 ----
}
+ static inline struct ifreq *
+ __if_nextreq (struct ifreq *ifr)
+ {
+ return ifr + 1;
+ }
+
+
static inline void
__if_freereq (struct ifreq *ifreqs, int num_ifs)
{
diff -r -c3 glibc-20020910.bak/sysdeps/unix/sysv/linux/ifreq.h glibc-20020910/sysdeps/unix/sysv/linux/ifreq.h
*** glibc-20020910.bak/sysdeps/unix/sysv/linux/ifreq.h Thu Jul 25 13:18:34 2002
--- glibc-20020910/sysdeps/unix/sysv/linux/ifreq.h Tue Sep 17 02:22:07 2002
***************
*** 102,107 ****
--- 103,114 ----
*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 -r -c3 glibc-20020910.bak/sysdeps/mach/hurd/ifreq.h glibc-20020910/sysdeps/mach/hurd/ifreq.h
*** glibc-20020910.bak/sysdeps/mach/hurd/ifreq.h Tue Aug 27 13:39:00 2002
--- glibc-20020910/sysdeps/mach/hurd/ifreq.h Tue Sep 17 02:22:06 2002
***************
*** 66,71 ****
--- 66,78 ----
}
+ static inline struct ifreq *
+ __if_nextreq (struct ifreq *ifr)
+ {
+ return ifr + 1;
+ }
+
+
static inline void
__if_freereq (struct ifreq *ifreqs, int num_ifs)
{
diff -r -c3 glibc-20020910.bak/resolv/res_hconf.c glibc-20020910/resolv/res_hconf.c
*** glibc-20020910.bak/resolv/res_hconf.c Thu Jul 25 13:18:08 2002
--- glibc-20020910/resolv/res_hconf.c Tue Sep 17 02:22:05 2002
***************
*** 556,562 ****
goto cleanup1;
/* Copy usable interfaces in ifaddrs structure. */
! for (cur_ifr = ifr, i = 0; i < num; ++cur_ifr, ++i)
{
if (cur_ifr->ifr_addr.sa_family != AF_INET)
continue;
--- 556,562 ----
goto cleanup1;
/* Copy usable interfaces in ifaddrs structure. */
! for (cur_ifr = ifr, i = 0; i < num; cur_ifr = __if_nextreq (cur_ifr), ++i)
{
if (cur_ifr->ifr_addr.sa_family != AF_INET)
continue;
diff -r -c3 glibc-20020910.bak/sysdeps/gnu/ifaddrs.c glibc-20020910/sysdeps/gnu/ifaddrs.c
*** glibc-20020910.bak/sysdeps/gnu/ifaddrs.c Thu Jul 25 00:56:04 2002
--- glibc-20020910/sysdeps/gnu/ifaddrs.c Tue Sep 17 02:22:06 2002
***************
*** 40,46 ****
Some different mechanism entirely must be used for IPv6. */
int fd = __socket (AF_INET, SOCK_DGRAM, 0);
struct ifreq *ifreqs;
! int nifs, i;
if (fd < 0)
return -1;
--- 40,46 ----
Some different mechanism entirely must be used for IPv6. */
int fd = __socket (AF_INET, SOCK_DGRAM, 0);
struct ifreq *ifreqs;
! int nifs;
if (fd < 0)
return -1;
***************
*** 64,69 ****
--- 64,71 ----
struct sockaddr addr, netmask, broadaddr;
char name[IF_NAMESIZE];
} *storage;
+ struct ifreq *ifr;
+ int i, j;
storage = malloc (nifs * sizeof storage[0]);
if (storage == NULL)
***************
*** 74,83 ****
}
i = 0;
do
{
- struct ifreq *const ifr = &ifreqs[i];
-
/* Fill in all 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;
--- 76,85 ----
}
i = 0;
+ j = 0;
+ ifr = ifreqs;
do
{
/* Fill in all 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;
***************
*** 92,134 ****
/* The SIOCGIFCONF call filled in only the name and address.
Now we must also ask for the other information we need. */
! if (__ioctl (fd, SIOCGIFFLAGS, ifr) < 0)
! break;
! storage[i].ia.ifa_flags = ifr->ifr_flags;
!
! ifr->ifr_addr = storage[i].addr;
! if (__ioctl (fd, SIOCGIFNETMASK, ifr) < 0)
! break;
! 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;
! }
! 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;
! }
! else
! /* Just 'cause. */
! memset (&storage[i].broadaddr, 0, sizeof storage[i].broadaddr);
! storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
! } while (++i < nifs);
! if (i < nifs) /* Broke out early on error. */
{
__close (fd);
free (storage);
__if_freereq (ifreqs, nifs);
return -1;
}
storage[i - 1].ia.ifa_next = NULL;
*ifap = &storage[0].ia;
--- 94,143 ----
/* The SIOCGIFCONF call filled in only the name and address.
Now we must also ask for the other information we need. */
! if (__ioctl (fd, SIOCGIFFLAGS, ifr) >= 0)
{
+ storage[i].ia.ifa_flags = ifr->ifr_flags;
+
ifr->ifr_addr = storage[i].addr;
! if (__ioctl (fd, SIOCGIFNETMASK, ifr) >= 0)
! {
! 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;
! }
! 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;
! }
! else
! /* Just 'cause. */
! memset (&storage[i].broadaddr, 0,
! sizeof storage[i].broadaddr);
! storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
! ++i;
! }
! }
! ++j;
! ifr = __if_nextreq (ifr);
! } while (j < nifs);
! if (j < nifs || i == 0) /* Broke out early on error. */
{
__close (fd);
free (storage);
__if_freereq (ifreqs, nifs);
return -1;
}
+
storage[i - 1].ia.ifa_next = NULL;
*ifap = &storage[0].ia;