This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]