Back to index

glibc  2.9
if_index.c
Go to the documentation of this file.
00001 /* Find network interface names and index numbers.  Hurd version.
00002    Copyright (C) 2000,01,02 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <error.h>
00021 #include <net/if.h>
00022 #include <string.h>
00023 #include <sys/ioctl.h>
00024 #include <unistd.h>
00025 
00026 #include <hurd.h>
00027 #include <hurd/ioctl.h>
00028 #include <hurd/pfinet.h>
00029 
00030 /* Return the interface index corresponding to interface IFNAME.
00031    On error, return 0.  */
00032 unsigned int
00033 if_nametoindex (const char *ifname)
00034 {
00035   struct ifreq ifr;
00036   int fd = __opensock ();
00037 
00038   if (fd < 0)
00039     return 0;
00040 
00041   strncpy (ifr.ifr_name, ifname, IFNAMSIZ);
00042   if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
00043     {
00044       int saved_errno = errno;
00045       __close (fd);
00046       if (saved_errno == EINVAL || saved_errno == ENOTTY)
00047         __set_errno (ENOSYS);
00048       return 0;
00049     }
00050   __close (fd);
00051   return ifr.ifr_ifindex;
00052 }
00053 libc_hidden_def (if_nametoindex)
00054 
00055 /* Free the structure IFN returned by if_nameindex.  */
00056 void
00057 if_freenameindex (struct if_nameindex *ifn)
00058 {
00059   struct if_nameindex *ptr = ifn;
00060   while (ptr->if_name || ptr->if_index)
00061     {
00062       free (ptr->if_name);
00063       ++ptr;
00064     }
00065   free (ifn);
00066 }
00067 
00068 /* Return an array of if_nameindex structures, one for each network
00069    interface present, plus one indicating the end of the array.  On
00070    error, return NULL.  */
00071 struct if_nameindex *
00072 if_nameindex (void)
00073 {
00074   error_t err = 0;
00075   char data[2048];
00076   file_t server;
00077   int fd = __opensock ();
00078   struct ifconf ifc;
00079   unsigned int nifs, i;
00080   struct if_nameindex *idx = NULL;
00081 
00082   ifc.ifc_buf = data;
00083 
00084   if (fd < 0)
00085     return NULL;
00086 
00087   server = _hurd_socket_server (PF_INET, 0);
00088   if (server == MACH_PORT_NULL)
00089     nifs = 0;
00090   else
00091     {
00092       size_t len = sizeof data;
00093       err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len);
00094       if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
00095        {
00096          /* On the first use of the socket server during the operation,
00097             allow for the old server port dying.  */
00098          server = _hurd_socket_server (PF_INET, 1);
00099          if (server == MACH_PORT_NULL)
00100            goto out;
00101          err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len);
00102        }
00103       if (err)
00104        goto out;
00105 
00106       ifc.ifc_len = len;
00107       nifs = len / sizeof (struct ifreq);
00108     }
00109 
00110   idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
00111   if (idx == NULL)
00112     {
00113       err = ENOBUFS;
00114       goto out;
00115     }
00116 
00117   for (i = 0; i < nifs; ++i)
00118     {
00119       struct ifreq *ifr = &ifc.ifc_req[i];
00120       idx[i].if_name = __strdup (ifr->ifr_name);
00121       if (idx[i].if_name == NULL
00122           || __ioctl (fd, SIOCGIFINDEX, ifr) < 0)
00123         {
00124           unsigned int j;
00125           err = errno;
00126 
00127           for (j =  0; j < i; ++j)
00128             free (idx[j].if_name);
00129           free (idx);
00130          idx = NULL;
00131 
00132           if (err == EINVAL)
00133             err = ENOSYS;
00134           else if (err == ENOMEM)
00135             err = ENOBUFS;
00136           goto out;
00137         }
00138       idx[i].if_index = ifr->ifr_ifindex;
00139     }
00140 
00141   idx[i].if_index = 0;
00142   idx[i].if_name = NULL;
00143 
00144  out:
00145   __close (fd);
00146   if (data != ifc.ifc_buf)
00147     __vm_deallocate (__mach_task_self (), (vm_address_t) ifc.ifc_buf,
00148                    ifc.ifc_len);
00149   __set_errno (err);
00150   return idx;
00151 }
00152 
00153 /* Store the name of the interface corresponding to index IFINDEX in
00154    IFNAME (which has space for at least IFNAMSIZ characters).  Return
00155    IFNAME, or NULL on error.  */
00156 char *
00157 if_indextoname (unsigned int ifindex, char *ifname)
00158 {
00159   struct ifreq ifr;
00160   int fd = __opensock ();
00161 
00162   if (fd < 0)
00163     return NULL;
00164 
00165   ifr.ifr_ifindex = ifindex;
00166   if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0)
00167     {
00168       int saved_errno = errno;
00169       __close (fd);
00170       if (saved_errno == EINVAL || saved_errno == ENOTTY)
00171         __set_errno (ENOSYS);
00172       else if (saved_errno == ENODEV)
00173        __set_errno (ENXIO);
00174       return NULL;
00175     }
00176   __close (fd);
00177   return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
00178 }
00179 libc_hidden_def (if_indextoname)
00180 
00181 #if 0
00182 void
00183 internal_function
00184 __protocol_available (int *have_inet, int *have_inet6)
00185 {
00186   *have_inet = _hurd_socket_server (PF_INET, 0) != MACH_PORT_NULL;
00187   *have_inet6 = _hurd_socket_server (PF_INET6, 0) != MACH_PORT_NULL;
00188 }
00189 #endif