if_nametoindex.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* Copyright (C) 1997,98,99,2000,02 Free Software Foundation, Inc.
  2. * This file is part of the GNU C Library.
  3. *
  4. * The GNU C Library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * The GNU C Library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with the GNU C Library; if not, write to the Free
  16. * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  17. * 02111-1307 USA.
  18. *
  19. * Reworked Dec 2002 by Erik Andersen <andersen@codepoet.org>
  20. */
  21. #define __FORCE_GLIBC
  22. #include <features.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <net/if.h>
  26. #include <sys/ioctl.h>
  27. #include <unistd.h>
  28. #include <stdlib.h>
  29. static int __opensock(void)
  30. {
  31. int fd;
  32. #ifdef __UCLIBC_HAS_IPV6__
  33. fd=socket(AF_INET6,SOCK_DGRAM,0);
  34. if (fd<0)
  35. #endif /* __UCLIBC_HAS_IPV6__ */
  36. fd=socket(AF_INET,SOCK_DGRAM,0);
  37. return(fd);
  38. }
  39. unsigned int if_nametoindex(const char* ifname)
  40. {
  41. #ifndef SIOCGIFINDEX
  42. __set_errno (ENOSYS);
  43. return 0;
  44. #else
  45. int fd;
  46. struct ifreq ifr;
  47. fd = __opensock();
  48. if (fd < 0)
  49. return 0;
  50. strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
  51. if (ioctl(fd,SIOCGIFINDEX,&ifr) < 0) {
  52. int saved_errno = errno;
  53. close(fd);
  54. if (saved_errno == EINVAL)
  55. __set_errno(ENOSYS);
  56. return 0;
  57. }
  58. close(fd);
  59. return ifr.ifr_ifindex;
  60. #endif /* SIOCGIFINDEX */
  61. }
  62. void if_freenameindex (struct if_nameindex *ifn)
  63. {
  64. struct if_nameindex *ptr = ifn;
  65. while (ptr->if_name || ptr->if_index) {
  66. if (ptr->if_name) {
  67. free (ptr->if_name);
  68. }
  69. ++ptr;
  70. }
  71. free (ifn);
  72. }
  73. struct if_nameindex * if_nameindex (void)
  74. {
  75. #ifndef SIOCGIFINDEX
  76. __set_errno (ENOSYS);
  77. return NULL;
  78. #else
  79. int fd;
  80. struct ifconf ifc;
  81. unsigned int nifs, i;
  82. int rq_len;
  83. struct if_nameindex *idx = NULL;
  84. # define RQ_IFS 4
  85. fd = __opensock();
  86. if (fd < 0)
  87. return 0;
  88. ifc.ifc_buf = NULL;
  89. /* Guess on the correct buffer size... */
  90. rq_len = RQ_IFS * sizeof (struct ifreq);
  91. /* Read all the interfaces out of the kernel. */
  92. do {
  93. ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len = rq_len);
  94. if (ifc.ifc_buf == NULL || ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
  95. close(fd);
  96. return NULL;
  97. }
  98. rq_len *= 2;
  99. } while (ifc.ifc_len == rq_len);
  100. nifs = ifc.ifc_len / sizeof(struct ifreq);
  101. idx = malloc ((nifs + 1) * sizeof(struct if_nameindex));
  102. if (idx == NULL) {
  103. close(fd);
  104. __set_errno(ENOBUFS);
  105. return NULL;
  106. }
  107. for (i = 0; i < nifs; ++i) {
  108. struct ifreq *ifr = &ifc.ifc_req[i];
  109. idx[i].if_name = strdup (ifr->ifr_name);
  110. if (idx[i].if_name == NULL || ioctl(fd,SIOCGIFINDEX,ifr) < 0) {
  111. int saved_errno = errno;
  112. unsigned int j;
  113. for (j = 0; j < i; ++j)
  114. free (idx[j].if_name);
  115. free(idx);
  116. close(fd);
  117. if (saved_errno == EINVAL)
  118. saved_errno = ENOSYS;
  119. else if (saved_errno == ENOMEM)
  120. saved_errno = ENOBUFS;
  121. __set_errno (saved_errno);
  122. return NULL;
  123. }
  124. idx[i].if_index = ifr->ifr_ifindex;
  125. }
  126. idx[i].if_index = 0;
  127. idx[i].if_name = NULL;
  128. close(fd);
  129. return idx;
  130. #endif
  131. }
  132. char * if_indextoname (unsigned int ifindex, char *ifname)
  133. {
  134. #ifdef SIOCGIFNAME
  135. /* Use ioctl to avoid searching the list. */
  136. struct ifreq ifr;
  137. int fd, saved_errno;
  138. fd = __opensock ();
  139. if (fd < 0)
  140. return NULL;
  141. ifr.ifr_ifindex = ifindex;
  142. if (ioctl (fd, SIOCGIFNAME, &ifr) < 0) {
  143. saved_errno = errno;
  144. close (fd);
  145. __set_errno (saved_errno);
  146. return NULL;
  147. }
  148. close (fd);
  149. return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
  150. #else
  151. struct if_nameindex *idx;
  152. struct if_nameindex *p;
  153. char *result = NULL;
  154. idx = if_nameindex();
  155. if (idx != NULL) {
  156. for (p = idx; p->if_index || p->if_name; ++p) {
  157. if (p->if_index == ifindex) {
  158. result = strncpy (ifname, p->if_name, IFNAMSIZ);
  159. break;
  160. }
  161. }
  162. if_freenameindex (idx);
  163. }
  164. return result;
  165. #endif
  166. }