diff options
Diffstat (limited to 'sysdeps/mach/hurd/if_index.c')
-rw-r--r-- | sysdeps/mach/hurd/if_index.c | 240 |
1 files changed, 131 insertions, 109 deletions
diff --git a/sysdeps/mach/hurd/if_index.c b/sysdeps/mach/hurd/if_index.c index 9870e44715..ca3e2d93a6 100644 --- a/sysdeps/mach/hurd/if_index.c +++ b/sysdeps/mach/hurd/if_index.c @@ -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 @@ -17,143 +17,165 @@ 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 |