]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
* sysdeps/mach/hurd/if_index.c: Redone to use new interfaces in the Hurd pfinet serve...
authorMark Kettenis <kettenis@gnu.org>
Sun, 1 Jul 2001 12:06:11 +0000 (12:06 +0000)
committerMark Kettenis <kettenis@gnu.org>
Sun, 1 Jul 2001 12:06:11 +0000 (12:06 +0000)
2001-07-01  Mark Kettenis  <kettenis@gnu.org>

* sysdeps/mach/hurd/if_index.c: Redone to use new interfaces in
the Hurd pfinet server, using equivalent code from the Linux
version in sysdeps/unix/sysv/linux/if_index.c. In detail:
Include <unistd.h>, <error.h>, <sys/ioctl.h>, <hurd/ioctl.h> and
<hurd/pfinet.h>.  Don't include <sys/mman.h> and <hurd/fsys.h>
anymore.
(if_nametoindex): New implementation using SIOCGIFINDEX.
(if_freenameindex): Straight copy of the Linux version.
(if_nameindex): New implementation based on pfinet_siocgifconf and
SIOCGIFINDEX.
(if_indextoname): New implementation using SIOCGIFNAME.
(map_interfaces): Function removed.
From Marcus Brinkmann <marcus@gnu.org>.

ChangeLog
sysdeps/mach/hurd/if_index.c

index 884a20f3ece0894620d8f6f9a4b93d432c822612..f7d756e2e57a97722826fad08668070af4ee70b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2001-07-01  Mark Kettenis  <kettenis@gnu.org>
+
+       * sysdeps/mach/hurd/if_index.c: Redone to use new interfaces in
+       the Hurd pfinet server, using equivalent code from the Linux
+       version in sysdeps/unix/sysv/linux/if_index.c. In detail:
+       Include <unistd.h>, <error.h>, <sys/ioctl.h>, <hurd/ioctl.h> and
+       <hurd/pfinet.h>.  Don't include <sys/mman.h> and <hurd/fsys.h>
+       anymore.
+       (if_nametoindex): New implementation using SIOCGIFINDEX.
+       (if_freenameindex): Straight copy of the Linux version.
+       (if_nameindex): New implementation based on pfinet_siocgifconf and
+       SIOCGIFINDEX.
+       (if_indextoname): New implementation using SIOCGIFNAME.
+       (map_interfaces): Function removed.
+       From Marcus Brinkmann <marcus@gnu.org>.
+
 2001-06-30  Jakub Jelinek  <jakub@redhat.com>
 
        * sysdeps/powerpc/dl-machine.c (__elf_preferred_address): Prefer
index 9870e44715f48b1be65baf11fad2afb87af898cd..ca3e2d93a661584f71bf48112ebbd5c7945fed13 100644 (file)
@@ -1,5 +1,5 @@
 /* Find network interface names and index numbers.  Hurd version.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <error.h>
 #include <net/if.h>
-#include <hurd.h>
-#include <hurd/fsys.h>
 #include <string.h>
-#include <sys/mman.h>
-
-static int
-map_interfaces (int domain,
-               unsigned int *idxp,
-               int (*counted_initializer) (unsigned int count,
-                                           size_t nameslen),
-               int (*iterator) (const char *))
-{
-  static const char ifopt[] = "--interface=";
-  file_t server;
-  char optsbuf[512], *opts = optsbuf, *p;
-  size_t optslen = sizeof optsbuf;
-  error_t err;
+#include <sys/ioctl.h>
+#include <unistd.h>
 
-  /* Find the socket server for DOMAIN.  */
-  server = _hurd_socket_server (domain, 0);
-  if (server == MACH_PORT_NULL)
-    return 0;
-
-  err = __file_get_fs_options (server, &opts, &optslen);
-  if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
-    {
-      /* On the first use of the socket server during the operation,
-        allow for the old server port dying.  */
-      server = _hurd_socket_server (domain, 1);
-      if (server == MACH_PORT_NULL)
-       return -1;
-      err = __file_get_fs_options (server, &opts, &optslen);
-    }
-  if (err)
-    return __hurd_fail (err), 0;
+#include <hurd.h>
+#include <hurd/ioctl.h>
+#include <hurd/pfinet.h>
 
-  if (counted_initializer)
-    {
-      unsigned int count = 0;
-      size_t nameslen = 0;
-      p = memchr (opts, '\0', optslen);
-      while (p != 0)
-       {
-         char *end = memchr (p + 1, '\0', optslen - (p - opts));
-         if (end == 0)
-           break;
-         if (optslen - (p - opts) >= sizeof ifopt
-             && !memcmp (p + 1, ifopt, sizeof ifopt - 1))
-           {
-             size_t len = end + 1 - (p + sizeof ifopt);
-             nameslen += len > IFNAMSIZ+1 ? IFNAMSIZ+1 : len;
-             ++count;
-           }
-         p = end;
-       }
+/* Return the interface index corresponding to interface IFNAME.
+   On error, return 0.  */
+unsigned int
+if_nametoindex (const char *ifname)
+{
+  struct ifreq ifr;
+  int fd = __opensock ();
 
-      if ((*counted_initializer) (count, nameslen))
-       return 0;
-    }
+  if (fd < 0)
+    return 0;
 
-  *idxp = 0;
-  for (p = memchr (opts, '\0', optslen); p != 0;
-       p = memchr (p + 1, '\0', optslen - (p - opts)))
+  strncpy (ifr.ifr_name, ifname, IFNAMSIZ);
+  if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
     {
-      ++*idxp;
-      if (optslen - (p - opts) >= sizeof ifopt
-         && !memcmp (p + 1, ifopt, sizeof ifopt - 1)
-         && (*iterator) (p + sizeof ifopt))
-       break;
+      int saved_errno = errno;
+      __close (fd);
+      if (saved_errno == EINVAL || saved_errno == ENOTTY)
+        __set_errno (ENOSYS);
+      return 0;
     }
-
-  if (opts != optsbuf)
-    __munmap (opts, optslen);
-
-  return 1;
+  __close (fd);
+  return ifr.ifr_ifindex;
 }
 
-unsigned int
-if_nametoindex (const char *ifname)
+/* Free the structure IFN returned by if_nameindex.  */
+void
+if_freenameindex (struct if_nameindex *ifn)
 {
-  unsigned int idx;
-  int find_name (const char *name)
+  struct if_nameindex *ptr = ifn;
+  while (ptr->if_name || ptr->if_index)
     {
-      return !strcmp (name, ifname);
+      if (ptr->if_name)
+        free (ptr->if_name);
+      ++ptr;
     }
-  return map_interfaces (PF_INET, &idx, 0, &find_name) ? idx : 0;
+  free (ifn);
 }
 
-char *
-if_indextoname (unsigned int ifindex, char *ifname)
+/* Return an array of if_nameindex structures, one for each network
+   interface present, plus one indicating the end of the array.  On
+   error, return NULL.  */
+struct if_nameindex *
+if_nameindex (void)
 {
-  unsigned int idx;
-  int find_idx (const char *name)
+  error_t err = 0;
+  char data[2048];
+  file_t server;
+  int fd = __opensock ();
+  struct ifconf ifc;
+  unsigned int nifs, i;
+  struct if_nameindex *idx = NULL;
+
+  ifc.ifc_buf = data;
+  ifc.ifc_len = sizeof (data);
+
+  if (fd < 0)
+    return NULL;
+
+  server = _hurd_socket_server (PF_INET, 0);
+  if (server == MACH_PORT_NULL)
+    nifs = 0;
+  else
     {
-      if (idx == ifindex)
+      err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf,
+                                 &ifc.ifc_len);
+      if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
        {
-         strncpy (ifname, name, IFNAMSIZ);
-         return 1;
+         /* On the first use of the socket server during the operation,
+            allow for the old server port dying.  */
+         server = _hurd_socket_server (PF_INET, 1);
+         if (server == MACH_PORT_NULL)
+           goto out;
+         err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf,
+                                     &ifc.ifc_len);
        }
-      return 0;
-    }
-  return map_interfaces (PF_INET, &idx, 0, &find_idx) ? ifname : NULL;
-}
+      if (err)
+       goto out;
 
+      nifs = ifc.ifc_len / sizeof (struct ifreq);
+    }
 
-struct if_nameindex *
-if_nameindex (void)
-{
-  unsigned int idx;
-  struct if_nameindex *buf;
-  char *namep;
-  int alloc (unsigned int count, size_t nameslen)
+  idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
+  if (idx == NULL)
     {
-      buf = malloc ((sizeof buf[0] * (count + 1)) + nameslen);
-      if (buf == 0)
-       return 1;
-      buf[count].if_index = 0;
-      buf[count].if_name = NULL;
-      namep = (char *) &buf[count + 1];
-      return 0;
+      err = ENOBUFS;
+      goto out;
     }
-  int fill (const char *name)
+
+  for (i = 0; i < nifs; ++i)
     {
-      buf[idx - 1].if_index = idx;
-      buf[idx - 1].if_name = namep;
-      namep = __memccpy (namep, name, '\0', IFNAMSIZ+1) ?: &namep[IFNAMSIZ+1];
-      return 0;
+      struct ifreq *ifr = &ifc.ifc_req[i];
+      idx[i].if_name = __strdup (ifr->ifr_name);
+      if (idx[i].if_name == NULL
+          || __ioctl (fd, SIOCGIFINDEX, ifr) < 0)
+        {
+          unsigned int j;
+          err = errno;
+
+          for (j =  0; j < i; ++j)
+            free (idx[j].if_name);
+          free (idx);
+         idx = NULL;
+
+          if (err == EINVAL)
+            err = ENOSYS;
+          else if (err == ENOMEM)
+            err = ENOBUFS;
+          goto out;
+        }
+      idx[i].if_index = ifr->ifr_ifindex;
     }
 
-  return map_interfaces (PF_INET, &idx, &alloc, &fill) ? buf : NULL;
+  idx[i].if_index = 0;
+  idx[i].if_name = NULL;
+
+ out:
+  __close (fd);
+  if (data != ifc.ifc_buf)
+    __vm_deallocate (__mach_task_self (), (vm_address_t) ifc.ifc_buf,
+                    ifc.ifc_len);
+  __set_errno (err);
+  return idx;
 }
 
-void
-if_freenameindex (struct if_nameindex *ifn)
+/* Store the name of the interface corresponding to index IFINDEX in
+   IFNAME (which has space for at least IFNAMSIZ characters).  Return
+   IFNAME, or NULL on error.  */
+char *
+if_indextoname (unsigned int ifindex, char *ifname)
 {
-  free (ifn);
+  struct ifreq ifr;
+  int fd = __opensock ();
+
+  if (fd < 0)
+    return NULL;
+
+  ifr.ifr_ifindex = ifindex;
+  if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0)
+    {
+      int saved_errno = errno;
+      __close (fd);
+      if (saved_errno == EINVAL || saved_errno == ENOTTY)
+        __set_errno (ENOSYS);
+      else if (saved_errno == ENODEV)
+       __set_errno (ENXIO);
+      return NULL;
+    }
+  __close (fd);
+  return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
 }
 
 #if 0