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