diff options
-rw-r--r-- | libc/inet/Makefile.in | 4 | ||||
-rw-r--r-- | libc/inet/if_index.c | 218 | ||||
-rw-r--r-- | libc/inet/if_nametoindex.c | 189 | ||||
-rw-r--r-- | libc/inet/opensock.c | 40 |
4 files changed, 260 insertions, 191 deletions
diff --git a/libc/inet/Makefile.in b/libc/inet/Makefile.in index cb844907b..f4b6d26c5 100644 --- a/libc/inet/Makefile.in +++ b/libc/inet/Makefile.in @@ -9,8 +9,8 @@ include $(top_srcdir)libc/inet/rpc/Makefile.in CSRC:= getservice.c getproto.c hostid.c getnetent.c getnetbynm.c getnetbyad.c \ - inet_net.c ntop.c herror.c if_nametoindex.c gai_strerror.c getaddrinfo.c \ - in6_addr.c ether_addr.c ntohl.c + inet_net.c ntop.c herror.c if_index.c gai_strerror.c getaddrinfo.c \ + in6_addr.c ether_addr.c ntohl.c opensock.c MSRC1:= addr.c MOBJ1:= inet_aton.o inet_addr.o inet_ntoa.o inet_makeaddr.o inet_lnaof.o \ diff --git a/libc/inet/if_index.c b/libc/inet/if_index.c new file mode 100644 index 000000000..5837faa65 --- /dev/null +++ b/libc/inet/if_index.c @@ -0,0 +1,218 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 + 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Reworked Dec 2002 by Erik Andersen <andersen@codepoet.org> + */ + +#define strndup __strndup + +#define __FORCE_GLIBC +#include <features.h> +#define __USE_GNU +#include <string.h> +#include <alloca.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <net/if.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <libc-internal.h> + +extern int __opensock(void) attribute_hidden; + +unsigned int +if_nametoindex(const char* ifname) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return 0; +#else + struct ifreq ifr; + int fd = __opensock(); + + if (fd < 0) + return 0; + + __strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; + __close(fd); + if (saved_errno == EINVAL) + __set_errno(ENOSYS); + return 0; + } + + __close(fd); + return ifr.ifr_ifindex; +#endif +} + +void +if_freenameindex (struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + free (ptr->if_name); + ++ptr; + } + free (ifn); +} + +struct if_nameindex * +if_nameindex (void) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else + int fd = __opensock (); + struct ifconf ifc; + unsigned int nifs, i; + int rq_len; + struct if_nameindex *idx = NULL; +# define RQ_IFS 4 + + if (fd < 0) + return NULL; + + ifc.ifc_buf = NULL; + + /* Guess on the correct buffer size... */ + rq_len = RQ_IFS * sizeof (struct ifreq); + + /* Read all the interfaces out of the kernel. */ + ifc.ifc_buf = alloca (rq_len); + ifc.ifc_len = rq_len; + while (1) + { + if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0) + { + __close (fd); + return NULL; + } + if (ifc.ifc_len < rq_len) + break; + + ifc.ifc_buf = extend_alloca (ifc.ifc_buf, rq_len, 2 * rq_len); + ifc.ifc_len = rq_len; + } + + nifs = ifc.ifc_len / sizeof(struct ifreq); + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + __close(fd); + __set_errno(ENOBUFS); + return NULL; + } + + for (i = 0; i < nifs; ++i) + { + 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) + { + int saved_errno = errno; + unsigned int j; + + for (j = 0; j < i; ++j) + free (idx[j].if_name); + free(idx); + __close(fd); + if (saved_errno == EINVAL) + saved_errno = ENOSYS; + else if (saved_errno == ENOMEM) + saved_errno = ENOBUFS; + __set_errno (saved_errno); + return NULL; + } + idx[i].if_index = ifr->ifr_ifindex; + } + + idx[i].if_index = 0; + idx[i].if_name = NULL; + + __close(fd); + return idx; +#endif +} + +char * +if_indextoname (unsigned int ifindex, char *ifname) +{ +#if !defined SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else +# ifdef SIOCGIFNAME + /* Use ioctl to avoid searching the list. */ + struct ifreq ifr; + int fd; + + fd = __opensock (); + + if (fd < 0) + return NULL; + + ifr.ifr_ifindex = ifindex; + if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0) + { + int serrno = errno; + __close (fd); + if (serrno == ENODEV) + /* POSIX requires ENXIO. */ + serrno = ENXIO; + __set_errno (serrno); + return NULL; + } + __close (fd); + + return __strncpy (ifname, ifr.ifr_name, IFNAMSIZ); +# else + struct if_nameindex *idx; + struct if_nameindex *p; + char *result = NULL; + + idx = if_nameindex(); + + if (idx != NULL) + { + for (p = idx; p->if_index || p->if_name; ++p) + if (p->if_index == ifindex) + { + result = __strncpy (ifname, p->if_name, IFNAMSIZ); + break; + } + + if_freenameindex (idx); + + if (result == NULL) + __set_errno (ENXIO); + } + return result; +# endif +#endif +} + diff --git a/libc/inet/if_nametoindex.c b/libc/inet/if_nametoindex.c deleted file mode 100644 index f3803e56b..000000000 --- a/libc/inet/if_nametoindex.c +++ /dev/null @@ -1,189 +0,0 @@ -/* Copyright (C) 1997,98,99,2000,02 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 - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * The GNU C Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the GNU C Library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA. - * - * Reworked Dec 2002 by Erik Andersen <andersen@codepoet.org> - */ - -#define __FORCE_GLIBC -#include <features.h> -#include <string.h> -#include <errno.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <unistd.h> -#include <stdlib.h> - -static int __opensock(void) -{ - int fd; -#ifdef __UCLIBC_HAS_IPV6__ - fd=__socket(AF_INET6,SOCK_DGRAM,0); - if (fd<0) -#endif /* __UCLIBC_HAS_IPV6__ */ - fd=__socket(AF_INET,SOCK_DGRAM,0); - return(fd); -} - -unsigned int if_nametoindex(const char* ifname) -{ -#ifndef SIOCGIFINDEX - __set_errno (ENOSYS); - return 0; -#else - int fd; - struct ifreq ifr; - - fd = __opensock(); - if (fd < 0) - return 0; - __strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - if (__ioctl(fd,SIOCGIFINDEX,&ifr) < 0) { - int saved_errno = errno; - __close(fd); - if (saved_errno == EINVAL) - __set_errno(ENOSYS); - return 0; - } - __close(fd); - return ifr.ifr_ifindex; - -#endif /* SIOCGIFINDEX */ -} - -void if_freenameindex (struct if_nameindex *ifn) -{ - struct if_nameindex *ptr = ifn; - while (ptr->if_name || ptr->if_index) { - if (ptr->if_name) { - free (ptr->if_name); - } - ++ptr; - } - free (ifn); -} - -struct if_nameindex * if_nameindex (void) -{ -#ifndef SIOCGIFINDEX - __set_errno (ENOSYS); - return NULL; -#else - int fd; - struct ifconf ifc; - unsigned int nifs, i; - int rq_len; - struct if_nameindex *idx = NULL; -# define RQ_IFS 4 - - fd = __opensock(); - if (fd < 0) - return 0; - - ifc.ifc_buf = NULL; - - /* Guess on the correct buffer size... */ - rq_len = RQ_IFS * sizeof (struct ifreq); - - /* Read all the interfaces out of the kernel. */ - do { - ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len = rq_len); - if (ifc.ifc_buf == NULL || __ioctl(fd, SIOCGIFCONF, &ifc) < 0) { - __close(fd); - return NULL; - } - rq_len *= 2; - } while (ifc.ifc_len == rq_len); - - nifs = ifc.ifc_len / sizeof(struct ifreq); - - idx = malloc ((nifs + 1) * sizeof(struct if_nameindex)); - if (idx == NULL) { - __close(fd); - __set_errno(ENOBUFS); - return NULL; - } - - for (i = 0; i < nifs; ++i) { - 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) { - int saved_errno = errno; - unsigned int j; - for (j = 0; j < i; ++j) - free (idx[j].if_name); - free(idx); - __close(fd); - if (saved_errno == EINVAL) - saved_errno = ENOSYS; - else if (saved_errno == ENOMEM) - saved_errno = ENOBUFS; - __set_errno (saved_errno); - return NULL; - } - idx[i].if_index = ifr->ifr_ifindex; - } - - idx[i].if_index = 0; - idx[i].if_name = NULL; - - __close(fd); - return idx; -#endif -} - -char * if_indextoname (unsigned int ifindex, char *ifname) -{ -#ifdef SIOCGIFNAME - /* Use ioctl to avoid searching the list. */ - struct ifreq ifr; - int fd, saved_errno; - - fd = __opensock (); - - if (fd < 0) - return NULL; - - ifr.ifr_ifindex = ifindex; - if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0) { - saved_errno = errno; - __close (fd); - __set_errno (saved_errno); - return NULL; - } - __close (fd); - - return __strncpy (ifname, ifr.ifr_name, IFNAMSIZ); -#else - struct if_nameindex *idx; - struct if_nameindex *p; - char *result = NULL; - - idx = if_nameindex(); - if (idx != NULL) { - for (p = idx; p->if_index || p->if_name; ++p) { - if (p->if_index == ifindex) { - result = __strncpy (ifname, p->if_name, IFNAMSIZ); - break; - } - } - if_freenameindex (idx); - } - return result; -#endif -} - diff --git a/libc/inet/opensock.c b/libc/inet/opensock.c new file mode 100644 index 000000000..a27141a16 --- /dev/null +++ b/libc/inet/opensock.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1999, 2001, 2002 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <features.h> +#include <libc-internal.h> + +/* Return a socket of any type. The socket can be used in subsequent + ioctl calls to talk to the kernel. */ +int attribute_hidden +__opensock (void) +{ + int fd; +#ifdef __UCLIBC_HAS_IPV6__ + fd = __socket(AF_INET6, SOCK_DGRAM, 0); + if (fd<0) +#endif /* __UCLIBC_HAS_IPV6__ */ + fd = __socket(AF_INET, SOCK_DGRAM, 0); + return(fd); +} |