Exemple #1
0
char *
__if_indextoname (unsigned int ifindex, char *ifname)
{
  /* We may be able to do the conversion directly, rather than searching a
     list.  This ioctl is not present in kernels before version 2.1.50.  */
  struct ifreq ifr;
  int fd;
  int status;

  fd = __opensock ();

  if (fd < 0)
    return NULL;

  ifr.ifr_ifindex = ifindex;
  status = __ioctl (fd, SIOCGIFNAME, &ifr);

  close_not_cancel_no_status (fd);

  if (status  < 0)
    {
      if (errno == ENODEV)
	/* POSIX requires ENXIO.  */
	__set_errno (ENXIO);

      return NULL;
    }
  else
    return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
}
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_not_cancel_no_status (fd);
      if (saved_errno == EINVAL)
	__set_errno (ENOSYS);
      return 0;
    }
  close_not_cancel_no_status (fd);
  return ifr.ifr_ifindex;
#endif
}
Exemple #3
0
void
__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
{
  int fd = sockfd;
  struct ifconf ifc;
  int rq_len;
  int nifs;
# define RQ_IFS	4

  if (fd < 0)
    fd = __opensock ();
  if (fd < 0)
    {
      *num_ifs = 0;
      *ifreqs = NULL;
      return;
    }

  ifc.ifc_buf = NULL;
  rq_len = RQ_IFS * sizeof (struct ifreq) / 2; /* Doubled in the loop.  */
  do
    {
      ifc.ifc_len = rq_len *= 2;
      void *newp = realloc (ifc.ifc_buf, ifc.ifc_len);
      if (newp == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
	{
	  free (ifc.ifc_buf);

	  if (fd != sockfd)
	    __close (fd);
	  *num_ifs = 0;
	  *ifreqs = NULL;
	  return;
	}
      ifc.ifc_buf = newp;
    }
  while (rq_len < sizeof (struct ifreq) + ifc.ifc_len);

  if (fd != sockfd)
    __close (fd);

#ifdef _HAVE_SA_LEN
  struct ifreq *ifr = *ifreqs;
  nifs = 0;
  while ((char *) ifr < ifc.ifc_buf + ifc.ifc_len)
    {
      ++nifs;
      ifr = __if_nextreq (ifr);
      if (ifr == NULL)
	break;
    }
#else
  nifs = ifc.ifc_len / sizeof (struct ifreq);
#endif

  *num_ifs = nifs;
  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
}
Exemple #4
0
void
__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
{
  int fd = sockfd;
  struct ifconf ifc;
  int rq_len;
  int nifs;
# define RQ_IFS	4

  if (fd < 0)
    fd = __opensock ();
  if (fd < 0)
    {
      *num_ifs = 0;
      *ifreqs = NULL;
      return;
    }

  ifc.ifc_buf = NULL;

  /* We may be able to get the needed buffer size directly, rather than
     guessing.  */
  ifc.ifc_buf = NULL;
  ifc.ifc_len = 0;
  if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
    rq_len = RQ_IFS * sizeof (struct ifreq);
  else
    rq_len = ifc.ifc_len;

  /* Read all the interfaces out of the kernel.  */
  ifc.ifc_len = rq_len;
  void *newp = realloc (ifc.ifc_buf, ifc.ifc_len);
  if (newp == NULL
      || (ifc.ifc_buf = newp, __ioctl (fd, SIOCGIFCONF, &ifc)) < 0)
    {
      free (ifc.ifc_buf);

      if (fd != sockfd)
	__close (fd);

      *num_ifs = 0;
      *ifreqs = NULL;
      return;
    }

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

  if (fd != sockfd)
    __close (fd);

  *num_ifs = nifs;
  *ifreqs = realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
}
/* 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;
}
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
}
/* 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);
}
/* 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;
}
static struct if_nameindex *
if_nameindex_ioctl (void)
{
  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;

  /* We may be able to get the needed buffer size directly, rather than
     guessing.  */
  if (! old_siocgifconf)
    {
      ifc.ifc_buf = NULL;
      ifc.ifc_len = 0;
      if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
	{
# if __ASSUME_SIOCGIFNAME == 0
	  old_siocgifconf = 1;
# endif
	  rq_len = RQ_IFS * sizeof (struct ifreq);
	}
      else
	rq_len = ifc.ifc_len;
    }
  else
    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_not_cancel_no_status (fd);
	  return NULL;
	}
      if (ifc.ifc_len < rq_len || ! old_siocgifconf)
	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_not_cancel_no_status (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_not_cancel_no_status (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_not_cancel_no_status (fd);
  return idx;
}
void
internal_function
__protocol_available (int *have_inet, int *have_inet6)
{
  int fd = __opensock ();
  unsigned int nifs;
  int rq_len;
  struct ifconf ifc;
# define RQ_IFS	4

  /* Wirst case assumption.  */
  *have_inet = 0;
  *have_inet6 = 0;

  if (fd < 0)
    /* We cannot open the socket.  No networking at all?  */
    return;

  /* We may be able to get the needed buffer size directly, rather than
     guessing.  */
  if (! old_siocgifconf)
    {
      ifc.ifc_buf = NULL;
      ifc.ifc_len = 0;
      if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
	{
# if __ASSUME_SIOCGIFNAME == 0
	  old_siocgifconf = 1;
# endif
	  rq_len = RQ_IFS * sizeof (struct ifreq);
	}
      else
	rq_len = ifc.ifc_len;
    }
  else
    rq_len = RQ_IFS * sizeof (struct ifreq);

  /* Read all the interfaces out of the kernel.  */
  do
    {
      ifc.ifc_buf = alloca (ifc.ifc_len = rq_len);
      if (__ioctl (fd, SIOCGIFCONF, &ifc) < 0)
	{
	  close_not_cancel_no_status (fd);
	  return;
	}
      rq_len *= 2;
    }
  while (ifc.ifc_len == rq_len && old_siocgifconf);

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

  /* Go through all the interfaces and get the address.  */
  while (nifs-- > 0)
    if (__ioctl (fd, SIOCGIFADDR, &ifc.ifc_req[nifs]) >= 0)
      {
	/* We successfully got information about this interface.  Now
	   test whether it is an IPv4 or IPv6 address.  */
	if (ifc.ifc_req[nifs].ifr_addr.sa_family == AF_INET)
	  *have_inet = 1;
	else if (ifc.ifc_req[nifs].ifr_addr.sa_family == AF_INET6)
	  *have_inet6 = 1;

	/* Note, this is & not &&.  It works since the values are always
	   0 or 1.  */
	if (*have_inet & *have_inet6)
	  /* We can stop early.  */
	  break;
      }

  close_not_cancel_no_status (fd);
}
char *
if_indextoname (unsigned int ifindex, char *ifname)
{
#if !defined SIOCGIFINDEX && __ASSUME_SIOCGIFNAME == 0
  __set_errno (ENOSYS);
  return NULL;
#else
# if __ASSUME_SIOCGIFNAME == 0
  struct if_nameindex *idx;
  struct if_nameindex *p;
  char *result = NULL;
# endif

# if defined SIOCGIFNAME || __ASSUME_SIOCGIFNAME > 0
  /* We may be able to do the conversion directly, rather than searching a
     list.  This ioctl is not present in kernels before version 2.1.50.  */
  struct ifreq ifr;
  int fd;
#  if __ASSUME_SIOCGIFNAME == 0
  static int siocgifname_works_not;

  if (!siocgifname_works_not)
#  endif
    {
#  if __ASSUME_SIOCGIFNAME == 0
      int serrno = errno;
#  endif
      int status;

      fd = __opensock ();

      if (fd < 0)
	return NULL;

      ifr.ifr_ifindex = ifindex;
      status = __ioctl (fd, SIOCGIFNAME, &ifr);

      close_not_cancel_no_status (fd);

      if (status  < 0)
	{
#  if __ASSUME_SIOCGIFNAME == 0
	  if (errno == EINVAL)
	    siocgifname_works_not = 1; /* Don't make the same mistake twice. */
	  else
#  endif
	    {
	      if (errno == ENODEV)
		/* POSIX requires ENXIO.  */
		__set_errno (ENXIO);

	      return NULL;
	    }
	}
      else
	return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);

#  if __ASSUME_SIOCGIFNAME == 0
      __set_errno (serrno);
#  endif
    }
# endif

# if __ASSUME_SIOCGIFNAME == 0
  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
}
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
}
Exemple #13
0
void
__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
{
  int fd = sockfd;
  struct ifconf ifc;
  int rq_len;
  int nifs;
  char *ifstart;
  char *ifend;
  struct ifreq *ifr;
  /* FreeBSD has many interfaces, many of them are usually down.  */
# define RQ_IFS	16
  /* We have to assume all records are of limited size, so that we know
     when we can stop enlarging the buffer.  */
# define RQ_MAXSIZE 256

  if (fd < 0)
    fd = __opensock ();
  if (fd < 0)
    {
      *num_ifs = 0;
      *ifreqs = NULL;
      return;
    }

  ifc.ifc_buf = NULL;
  rq_len = RQ_IFS * sizeof (struct ifreq) + RQ_MAXSIZE;
  for (;;)
    {
      ifc.ifc_len = rq_len;
      ifc.ifc_buf = realloc (ifc.ifc_buf, ifc.ifc_len);
      if (ifc.ifc_buf == NULL || __ioctl (fd, SIOCGIFCONF, &ifc) < 0)
	{
	  if (ifc.ifc_buf)
	    free (ifc.ifc_buf);

	  if (fd != sockfd)
	    __close (fd);
	  *num_ifs = 0;
	  *ifreqs = NULL;
	  return;
	}
      if (ifc.ifc_len + RQ_MAXSIZE <= rq_len)
	break;
      rq_len *= 2;
    }

  nifs = 0;
  ifstart = (char *) ifc.ifc_buf;
  ifend = ifstart + ifc.ifc_len;
  for (ifr = (struct ifreq *) ifstart;
       (char *) ifr < ifend;
       ifr = __if_nextreq (ifr))
    nifs++;

  if (fd != sockfd)
    __close (fd);

  *num_ifs = nifs;
  *ifreqs = realloc (ifc.ifc_buf, ifc.ifc_len);
}