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]

getifaddrs


Functions ``__ifreq'' and ``getifaddrs'' were changed to support
``struct sockaddr'' structures of arbitrary size.

The fields ``ifa_netmask'' and ``ifa_broadaddr'' are set to NULL, if
the coresponding ``ioctl'' fails, per BSD manual pages.

On NetBSD these ioctls fail for the large number of down interfaces,
as a result no information can be obtained for up interfaces.

~velco
diff -rudpN libc/tags/initial/inet/test-ifaddrs.c libc/trunk/inet/test-ifaddrs.c
--- libc/tags/initial/inet/test-ifaddrs.c	Sun Nov 24 23:51:38 2002
+++ libc/trunk/inet/test-ifaddrs.c	Sun Nov 24 23:40:53 2002
@@ -50,6 +50,9 @@ Name           Flags   Address         N
       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         N
 	      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 -rudpN libc/tags/initial/sysdeps/gnu/ifaddrs.c libc/trunk/sysdeps/gnu/ifaddrs.c
--- libc/tags/initial/sysdeps/gnu/ifaddrs.c	Sun Nov 24 23:46:45 2002
+++ libc/trunk/sysdeps/gnu/ifaddrs.c	Sun Nov 24 23:36:20 2002
@@ -31,13 +31,14 @@
 
 /* Create a linked list of `struct ifaddrs' structures, one for each
    network interface on the host machine.  If successful, store the
-   list in *IFAP and return 0.  On errors, return -1 and set `errno'.  */
+   list in *IFAP and return 0.  On errors, return -1 and set
+   `errno'.  */
 int
 getifaddrs (struct ifaddrs **ifap)
 {
-  /* This implementation handles only IPv4 interfaces.
-     The various ioctls below will only work on an AF_INET socket.
-     Some different mechanism entirely must be used for IPv6.  */
+  /* This implementation handles only IPv4 interfaces.  The various
+     ioctls below will only work on an AF_INET socket.  Some different
+     mechanism entirely must be used for IPv6.  */
   int fd = __socket (AF_INET, SOCK_DGRAM, 0);
   struct ifreq *ifreqs;
   int nifs;
@@ -46,14 +47,15 @@ getifaddrs (struct ifaddrs **ifap)
     return -1;
 
   __ifreq (&ifreqs, &nifs, fd);
-  if (ifreqs == NULL)		/* XXX doesn't distinguish error vs none */
+  if (ifreqs == NULL) /* XXX doesn't distinguish error vs none */
     {
       __close (fd);
       return -1;
     }
 
-  /* Now we have the list of interfaces and each one's address.
-     Put it into the expected format and fill in the remaining details.  */
+  /* Now we have the list of interfaces and each one's address.  Put
+     it into the expected format and fill in the remaining
+     details.  */
   if (nifs == 0)
     *ifap = NULL;
   else
@@ -61,10 +63,12 @@ getifaddrs (struct ifaddrs **ifap)
       struct
       {
 	struct ifaddrs ia;
-	struct sockaddr addr, netmask, broadaddr;
+	struct sockaddr_storage addr;
+	struct sockaddr_storage netmask;
+	struct sockaddr_storage broadaddr;
 	char name[IF_NAMESIZE];
       } *storage;
-      struct ifreq *ifr;
+      struct ifreq *ifr, *next;
       int i;
 
       storage = malloc (nifs * sizeof storage[0]);
@@ -79,51 +83,69 @@ getifaddrs (struct ifaddrs **ifap)
       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;
-	  storage[i].ia.ifa_netmask = &storage[i].netmask;
-	  storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; /* & dstaddr */
+	  next = __if_nextreq (ifr);
 
-	  /* Now copy the information we already have from SIOCGIFCONF.  */
-	  storage[i].ia.ifa_name = strncpy (storage[i].name, ifr->ifr_name,
-					    sizeof storage[i].name);
-	  storage[i].addr = ifr->ifr_addr;
+	  /* 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 = (struct sockaddr *) &storage [i].addr;
+	  storage[i].ia.ifa_netmask =
+	    (struct sockaddr *) &storage [i].netmask;
+	  storage[i].ia.ifa_broadaddr =
+	    (struct scokaddr *) &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,
+		     sizeof storage [i].name);
+
+	  memcpy (&storage [i].addr, &ifr->ifr_addr,
+		  ifr->ifr_addr.sa_len);
 
 	  /* The SIOCGIFCONF call filled in only the name and address.
-	     Now we must also ask for the other information we need.  */
+	     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;
-
+	  memcpy (&ifr->ifr_addr, storage [i].ia.ifa_addr,
+		  storage [i].ia.ifa_addr->sa_len);
+	  
 	  if (__ioctl (fd, SIOCGIFNETMASK, ifr) < 0)
-	    break;
-	  storage[i].netmask = ifr->ifr_netmask;
-
+	    storage [i].ia.ifa_netmask = NULL;
+	  else
+	    memcpy (&storage [i].netmask, &ifr->ifr_netmask,
+		    ifr->ifr_netmask.sa_len);
+	  
 	  if (ifr->ifr_flags & IFF_BROADCAST)
 	    {
-	      ifr->ifr_addr = storage[i].addr;
+	      memcpy (&ifr->ifr_addr, storage [i].ia.ifa_addr,
+		      storage [i].ia.ifa_addr->sa_len);
+	      
 	      if (__ioctl (fd, SIOCGIFBRDADDR, ifr) < 0)
-		break;
-	      storage[i].broadaddr = ifr->ifr_broadaddr;
+		storage [i].ia.ifa_broadaddr = NULL;
+	      else
+		memcpy (&storage [i].broadaddr, &ifr->ifr_broadaddr,
+			ifr->ifr_broadaddr.sa_len);
 	    }
 	  else if (ifr->ifr_flags & IFF_POINTOPOINT)
 	    {
-	      ifr->ifr_addr = storage[i].addr;
+	      memcpy (&ifr->ifr_addr, storage [i].ia.ifa_addr,
+		      storage [i].ia.ifa_addr->sa_len);
+
 	      if (__ioctl (fd, SIOCGIFDSTADDR, ifr) < 0)
-		break;
-	      storage[i].broadaddr = ifr->ifr_dstaddr;
+		storage [i].ia.ifa_broadaddr = NULL;
+	      else
+		memcpy (&storage [i].broadaddr, &ifr->ifr_dstaddr,
+			ifr->ifr_dstaddr.sa_len);
 	    }
-	  else
-	    /* Just 'cause.  */
-	    memset (&storage[i].broadaddr, 0, sizeof storage[i].broadaddr);
 
 	  storage[i].ia.ifa_data = NULL; /* Nothing here for now.  */
 
-	  ifr = __if_nextreq (ifr);
+	  ifr = next;
 	} while (++i < nifs);
       if (i < nifs)		/* Broke out early on error.  */
 	{
diff -rudpN libc/tags/initial/sysdeps/generic/ifreq.h libc/trunk/sysdeps/generic/ifreq.h
--- libc/tags/initial/sysdeps/generic/ifreq.h	Sun Nov 24 23:49:30 2002
+++ libc/trunk/sysdeps/generic/ifreq.h	Sun Nov 24 23:39:00 2002
@@ -24,12 +24,22 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 
+static inline struct ifreq *
+__if_nextreq (struct ifreq *ifr)
+{
+  return (struct ifreq *)
+    ((char *) ifr + IFNAMSIZ
+     + (__builtin_expect (ifr->ifr_addr.sa_len <= sizeof (struct sockaddr), 1)
+	? sizeof (struct sockaddr)
+	: ifr->ifr_addr.sa_len));
+}
 
 static inline void
 __ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
 {
   int fd = sockfd;
   struct ifconf ifc;
+  struct ifreq *ifr, *fence;
   int rq_len;
   int nifs;
 # define RQ_IFS	4
@@ -63,22 +73,17 @@ __ifreq (struct ifreq **ifreqs, int *num
     }
   while (rq_len < sizeof (struct ifreq) + ifc.ifc_len);
 
-  nifs = ifc.ifc_len / sizeof (struct ifreq);
+  nifs = 0;
+  fence = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+  for (ifr = (struct ifreq *) ifc.ifc_buf; ifr < fence; nifs++)
+    ifr = __if_nextreq (ifr);
 
   if (fd != sockfd)
     __close (fd);
 
   *num_ifs = nifs;
-  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
-}
-
-
-static inline struct ifreq *
-__if_nextreq (struct ifreq *ifr)
-{
-  return ifr + 1;
+  *ifreqs = realloc (ifc.ifc_buf, ifc.ifc_len);
 }
-
 
 static inline void
 __if_freereq (struct ifreq *ifreqs, int num_ifs)

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