/* Find network interface names and index numbers.  Hurd version.
   Copyright (C) 2000-2014 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, see
   <http://www.gnu.org/licenses/>.  */

#include <error.h>
#include <net/if.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <hurd.h>
#include <hurd/ioctl.h>
#include <hurd/pfinet.h>

/* 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 (fd < 0)
    return 0;

  strncpy (ifr.ifr_name, ifname, IFNAMSIZ);
  if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0)
    {
      int saved_errno = errno;
      __close (fd);
      if (saved_errno == EINVAL || saved_errno == ENOTTY)
        __set_errno (ENOSYS);
      return 0;
    }
  __close (fd);
  return ifr.ifr_ifindex;
}
libc_hidden_def (if_nametoindex)

/* Free the structure IFN returned by if_nameindex.  */
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);
}

/* 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)
{
  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;

  if (fd < 0)
    return NULL;

  server = _hurd_socket_server (PF_INET, 0);
  if (server == MACH_PORT_NULL)
    nifs = 0;
  else
    {
      size_t len = sizeof data;
      err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len);
      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 (PF_INET, 1);
	  if (server == MACH_PORT_NULL)
	    goto out;
	  err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len);
	}
      if (err)
	goto out;

      ifc.ifc_len = len;
      nifs = len / sizeof (struct ifreq);
    }

  idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
  if (idx == NULL)
    {
      err = ENOBUFS;
      goto out;
    }

  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)
        {
          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;
    }

  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;
}

/* 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)
{
  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);
}
libc_hidden_def (if_indextoname)

#if 0
void
internal_function
__protocol_available (int *have_inet, int *have_inet6)
{
  *have_inet = _hurd_socket_server (PF_INET, 0) != MACH_PORT_NULL;
  *have_inet6 = _hurd_socket_server (PF_INET6, 0) != MACH_PORT_NULL;
}
#endif
