Beispiel #1
0
int
add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
    u_int flags, const char *description, char *errbuf)
{
	pcap_t *p;
	pcap_if_t *curdev, *prevdev, *nextdev;
	int this_instance;
	char open_errbuf[PCAP_ERRBUF_SIZE];

	/*
	 * Is there already an entry in the list for this interface?
	 */
	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
		if (strcmp(name, curdev->name) == 0)
			break;	/* yes, we found it */
	}

	if (curdev == NULL) {
		/*
		 * No, we didn't find it.
		 *
		 * Can we open this interface for live capture?
		 *
		 * We do this check so that interfaces that are
		 * supplied by the interface enumeration mechanism
		 * we're using but that don't support packet capture
		 * aren't included in the list.  Loopback interfaces
		 * on Solaris are an example of this; we don't just
		 * omit loopback interfaces on all platforms because
		 * you *can* capture on loopback interfaces on some
		 * OSes.
		 *
		 * On OS X, we don't do this check if the device
		 * name begins with "wlt"; at least some versions
		 * of OS X offer monitor mode capturing by having
		 * a separate "monitor mode" device for each wireless
		 * adapter, rather than by implementing the ioctls
		 * that {Free,Net,Open,DragonFly}BSD provide.
		 * Opening that device puts the adapter into monitor
		 * mode, which, at least for some adapters, causes
		 * them to deassociate from the network with which
		 * they're associated.
		 *
		 * Instead, we try to open the corresponding "en"
		 * device (so that we don't end up with, for users
		 * without sufficient privilege to open capture
		 * devices, a list of adapters that only includes
		 * the wlt devices).
		 */
#ifdef __APPLE__
		if (strncmp(name, "wlt", 3) == 0) {
			char *en_name;
			size_t en_name_len;

			/*
			 * Try to allocate a buffer for the "en"
			 * device's name.
			 */
			en_name_len = strlen(name) - 1;
			en_name = malloc(en_name_len + 1);
			if (en_name == NULL) {
				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
				    "malloc: %s", pcap_strerror(errno));
				return (-1);
			}
			strcpy(en_name, "en");
			strcat(en_name, name + 3);
			p = pcap_open_live(en_name, 68, 0, 0, open_errbuf);
			free(en_name);
		} else
#endif /* __APPLE */
		p = pcap_open_live(name, 68, 0, 0, open_errbuf);
		if (p == NULL) {
			/*
			 * No.  Don't bother including it.
			 * Don't treat this as an error, though.
			 */
			*curdev_ret = NULL;
			return (0);
		}
		pcap_close(p);

		/*
		 * Yes, we can open it.
		 * Allocate a new entry.
		 */
		curdev = malloc(sizeof(pcap_if_t));
		if (curdev == NULL) {
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
			    "malloc: %s", pcap_strerror(errno));
			return (-1);
		}

		/*
		 * Fill in the entry.
		 */
		curdev->next = NULL;
		curdev->name = strdup(name);
		if (curdev->name == NULL) {
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
			    "malloc: %s", pcap_strerror(errno));
			free(curdev);
			return (-1);
		}
		if (description != NULL) {
			/*
			 * We have a description for this interface.
			 */
			curdev->description = strdup(description);
			if (curdev->description == NULL) {
				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
				    "malloc: %s", pcap_strerror(errno));
				free(curdev->name);
				free(curdev);
				return (-1);
			}
		} else {
			/*
			 * We don't.
			 */
			curdev->description = NULL;
		}
		curdev->addresses = NULL;	/* list starts out as empty */
		curdev->flags = 0;
		if (ISLOOPBACK(name, flags))
			curdev->flags |= PCAP_IF_LOOPBACK;

		/*
		 * Add it to the list, in the appropriate location.
		 * First, get the instance number of this interface.
		 */
		this_instance = get_instance(name);

		/*
		 * Now look for the last interface with an instance number
		 * less than or equal to the new interface's instance
		 * number - except that non-loopback interfaces are
		 * arbitrarily treated as having interface numbers less
		 * than those of loopback interfaces, so the loopback
		 * interfaces are put at the end of the list.
		 *
		 * We start with "prevdev" being NULL, meaning we're before
		 * the first element in the list.
		 */
		prevdev = NULL;
		for (;;) {
			/*
			 * Get the interface after this one.
			 */
			if (prevdev == NULL) {
				/*
				 * The next element is the first element.
				 */
				nextdev = *alldevs;
			} else
				nextdev = prevdev->next;

			/*
			 * Are we at the end of the list?
			 */
			if (nextdev == NULL) {
				/*
				 * Yes - we have to put the new entry
				 * after "prevdev".
				 */
				break;
			}

			/*
			 * Is the new interface a non-loopback interface
			 * and the next interface a loopback interface?
			 */
			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
				/*
				 * Yes, we should put the new entry
				 * before "nextdev", i.e. after "prevdev".
				 */
				break;
			}

			/*
			 * Is the new interface's instance number less
			 * than the next interface's instance number,
			 * and is it the case that the new interface is a
			 * non-loopback interface or the next interface is
			 * a loopback interface?
			 *
			 * (The goal of both loopback tests is to make
			 * sure that we never put a loopback interface
			 * before any non-loopback interface and that we
			 * always put a non-loopback interface before all
			 * loopback interfaces.)
			 */
			if (this_instance < get_instance(nextdev->name) &&
			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
				/*
				 * Yes - we should put the new entry
				 * before "nextdev", i.e. after "prevdev".
				 */
				break;
			}

			prevdev = nextdev;
		}

		/*
		 * Insert before "nextdev".
		 */
		curdev->next = nextdev;

		/*
		 * Insert after "prevdev" - unless "prevdev" is null,
		 * in which case this is the first interface.
		 */
		if (prevdev == NULL) {
			/*
			 * This is the first interface.  Pass back a
			 * pointer to it, and put "curdev" before
			 * "nextdev".
			 */
			*alldevs = curdev;
		} else
			prevdev->next = curdev;
	}

	*curdev_ret = curdev;
	return (0);
}
Beispiel #2
0
/*
 * Look for a given device in the specified list of devices.
 *
 * If we find it, return 0 and set *curdev_ret to point to it.
 *
 * If we don't find it, check whether we can open it:
 *
 *     If that fails with PCAP_ERROR_NO_SUCH_DEVICE or
 *     PCAP_ERROR_IFACE_NOT_UP, don't attempt to add an entry for
 *     it, as that probably means it exists but doesn't support
 *     packet capture.
 *
 *     Otherwise, attempt to add an entry for it, with the specified
 *     ifnet flags and description, and, if that succeeds, return 0
 *     and set *curdev_ret to point to the new entry, otherwise
 *     return PCAP_ERROR and set errbuf to an error message.
 */
int
add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
    u_int flags, const char *description, char *errbuf)
{
	pcap_t *p;
	pcap_if_t *curdev, *prevdev, *nextdev;
	u_int this_figure_of_merit, nextdev_figure_of_merit;
	char open_errbuf[PCAP_ERRBUF_SIZE];
	int ret;

	/*
	 * Is there already an entry in the list for this interface?
	 */
	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
		if (strcmp(name, curdev->name) == 0)
			break;	/* yes, we found it */
	}

	if (curdev == NULL) {
		/*
		 * No, we didn't find it.
		 *
		 * Can we open this interface for live capture?
		 *
		 * We do this check so that interfaces that are
		 * supplied by the interface enumeration mechanism
		 * we're using but that don't support packet capture
		 * aren't included in the list.  Loopback interfaces
		 * on Solaris are an example of this; we don't just
		 * omit loopback interfaces on all platforms because
		 * you *can* capture on loopback interfaces on some
		 * OSes.
		 *
		 * On OS X, we don't do this check if the device
		 * name begins with "wlt"; at least some versions
		 * of OS X offer monitor mode capturing by having
		 * a separate "monitor mode" device for each wireless
		 * adapter, rather than by implementing the ioctls
		 * that {Free,Net,Open,DragonFly}BSD provide.
		 * Opening that device puts the adapter into monitor
		 * mode, which, at least for some adapters, causes
		 * them to deassociate from the network with which
		 * they're associated.
		 *
		 * Instead, we try to open the corresponding "en"
		 * device (so that we don't end up with, for users
		 * without sufficient privilege to open capture
		 * devices, a list of adapters that only includes
		 * the wlt devices).
		 */
#ifdef __APPLE__
		if (strncmp(name, "wlt", 3) == 0) {
			char *en_name;
			size_t en_name_len;

			/*
			 * Try to allocate a buffer for the "en"
			 * device's name.
			 */
			en_name_len = strlen(name) - 1;
			en_name = malloc(en_name_len + 1);
			if (en_name == NULL) {
				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
				    "malloc: %s", pcap_strerror(errno));
				return (-1);
			}
			strcpy(en_name, "en");
			strcat(en_name, name + 3);
			p = pcap_create(en_name, open_errbuf);
			free(en_name);
		} else
#endif /* __APPLE */
		p = pcap_create(name, open_errbuf);
		if (p == NULL) {
			/*
			 * The attempt to create the pcap_t failed;
			 * that's probably an indication that we're
			 * out of memory.
			 *
			 * Don't bother including this interface,
			 * but don't treat it as an error.
			 */
			*curdev_ret = NULL;
			return (0);
		}
		/* Small snaplen, so we don't try to allocate much memory. */
		pcap_set_snaplen(p, 68);
		ret = pcap_activate(p);
		pcap_close(p);
		switch (ret) {

		case PCAP_ERROR_NO_SUCH_DEVICE:
		case PCAP_ERROR_IFACE_NOT_UP:
			/*
			 * We expect these two errors - they're the
			 * reason we try to open the device.
			 *
			 * PCAP_ERROR_NO_SUCH_DEVICE typically means
			 * "there's no such device *known to the
			 * OS's capture mechanism*", so, even though
			 * it might be a valid network interface, you
			 * can't capture on it (e.g., the loopback
			 * device in Solaris up to Solaris 10, or
			 * the vmnet devices in OS X with VMware
			 * Fusion).  We don't include those devices
			 * in our list of devices, as there's no
			 * point in doing so - they're not available
			 * for capture.
			 *
			 * PCAP_ERROR_IFACE_NOT_UP means that the
			 * OS's capture mechanism doesn't work on
			 * interfaces not marked as up; some capture
			 * mechanisms *do* support that, so we no
			 * longer reject those interfaces out of hand,
			 * but we *do* want to reject them if they
			 * can't be opened for capture.
			 */
			*curdev_ret = NULL;
			return (0);
		}

		/*
		 * Yes, we can open it, or we can't, for some other
		 * reason.
		 *
		 * If we can open it, we want to offer it for
		 * capture, as you can capture on it.  If we can't,
		 * we want to offer it for capture, so that, if
		 * the user tries to capture on it, they'll get
		 * an error and they'll know why they can't
		 * capture on it (e.g., insufficient permissions)
		 * or they'll report it as a problem (and then
		 * have the error message to provide as information).
		 *
		 * Allocate a new entry.
		 */
		curdev = malloc(sizeof(pcap_if_t));
		if (curdev == NULL) {
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
			    "malloc: %s", pcap_strerror(errno));
			return (-1);
		}

		/*
		 * Fill in the entry.
		 */
		curdev->next = NULL;
		curdev->name = strdup(name);
		if (curdev->name == NULL) {
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
			    "malloc: %s", pcap_strerror(errno));
			free(curdev);
			return (-1);
		}
		if (description != NULL) {
			/*
			 * We have a description for this interface.
			 */
			curdev->description = strdup(description);
			if (curdev->description == NULL) {
				(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
				    "malloc: %s", pcap_strerror(errno));
				free(curdev->name);
				free(curdev);
				return (-1);
			}
		} else {
			/*
			 * We don't.
			 */
			curdev->description = NULL;
		}
		curdev->addresses = NULL;	/* list starts out as empty */
		curdev->flags = 0;
		if (ISLOOPBACK(name, flags))
			curdev->flags |= PCAP_IF_LOOPBACK;
		if (ISUP(flags))
			curdev->flags |= PCAP_IF_UP;
		if (ISRUNNING(flags))
			curdev->flags |= PCAP_IF_RUNNING;

		/*
		 * Add it to the list, in the appropriate location.
		 * First, get the "figure of merit" for this
		 * interface.
		 */
		this_figure_of_merit = get_figure_of_merit(curdev);

		/*
		 * Now look for the last interface with an figure of merit
		 * less than or equal to the new interface's figure of
		 * merit.
		 *
		 * We start with "prevdev" being NULL, meaning we're before
		 * the first element in the list.
		 */
		prevdev = NULL;
		for (;;) {
			/*
			 * Get the interface after this one.
			 */
			if (prevdev == NULL) {
				/*
				 * The next element is the first element.
				 */
				nextdev = *alldevs;
			} else
				nextdev = prevdev->next;

			/*
			 * Are we at the end of the list?
			 */
			if (nextdev == NULL) {
				/*
				 * Yes - we have to put the new entry
				 * after "prevdev".
				 */
				break;
			}

			/*
			 * Is the new interface's figure of merit less
			 * than the next interface's figure of merit,
			 * meaning that the new interface is better
			 * than the next interface?
			 */
			nextdev_figure_of_merit = get_figure_of_merit(nextdev);
			if (this_figure_of_merit < nextdev_figure_of_merit) {
				/*
				 * Yes - we should put the new entry
				 * before "nextdev", i.e. after "prevdev".
				 */
				break;
			}

			prevdev = nextdev;
		}

		/*
		 * Insert before "nextdev".
		 */
		curdev->next = nextdev;

		/*
		 * Insert after "prevdev" - unless "prevdev" is null,
		 * in which case this is the first interface.
		 */
		if (prevdev == NULL) {
			/*
			 * This is the first interface.  Pass back a
			 * pointer to it, and put "curdev" before
			 * "nextdev".
			 */
			*alldevs = curdev;
		} else
			prevdev->next = curdev;
	}

	*curdev_ret = curdev;
	return (0);
}
Beispiel #3
0
static int
add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, char *name,
    u_int flags, const char *description, char *errbuf)
{
	pcap_t *p;
	pcap_if_t *curdev, *prevdev, *nextdev;
	int this_instance;

	/*
	 * Can we open this interface for live capture?
	 */
	p = pcap_open_live(name, 68, 0, 0, errbuf);
	if (p == NULL) {
		/*
		 * No.  Don't bother including it.
		 * Don't treat this as an error, though.
		 */
		*curdev_ret = NULL;
		return (0);
	}
	pcap_close(p);

	/*
	 * Is there already an entry in the list for this interface?
	 */
	for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
		if (strcmp(name, curdev->name) == 0)
			break;	/* yes, we found it */
	}
	if (curdev == NULL) {
		/*
		 * No, we didn't find it.
		 * Allocate a new entry.
		 */
		curdev = malloc(sizeof(pcap_if_t));
		if (curdev == NULL) {
			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
			    "malloc: %s", pcap_strerror(errno));
			return (-1);
		}
		
		/*
		 * Fill in the entry.
		 */
		curdev->next = NULL;
		curdev->name = malloc(strlen(name) + 1);
		strcpy(curdev->name, name);
		if (description != NULL) {
			/*
			 * We have a description for this interface.
			 */
			curdev->description = malloc(strlen(description) + 1);
			strcpy(curdev->description, description);
		} else {
			/*
			 * We don't.
			 */
			curdev->description = NULL;
		}
		curdev->addresses = NULL;	/* list starts out as empty */
		curdev->flags = 0;
		if (ISLOOPBACK(name, flags))
			curdev->flags |= PCAP_IF_LOOPBACK;

		/*
		 * Add it to the list, in the appropriate location.
		 * First, get the instance number of this interface.
		 */
		this_instance = get_instance(name);

		/*
		 * Now look for the last interface with an instance number
		 * less than or equal to the new interface's instance
		 * number - except that non-loopback interfaces are
		 * arbitrarily treated as having interface numbers less
		 * than those of loopback interfaces, so the loopback
		 * interfaces are put at the end of the list.
		 *
		 * We start with "prevdev" being NULL, meaning we're before
		 * the first element in the list.
		 */
		prevdev = NULL;
		for (;;) {
			/*
			 * Get the interface after this one.
			 */
			if (prevdev == NULL) {
				/*
				 * The next element is the first element.
				 */
				nextdev = *alldevs;
			} else
				nextdev = prevdev->next;

			/*
			 * Are we at the end of the list?
			 */
			if (nextdev == NULL) {
				/*
				 * Yes - we have to put the new entry
				 * after "prevdev".
				 */
				break;
			}

			/*
			 * Is the new interface a non-loopback interface
			 * and the next interface a loopback interface?
			 */
			if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
			    (nextdev->flags & PCAP_IF_LOOPBACK)) {
				/*
				 * Yes, we should put the new entry
				 * before "nextdev", i.e. after "prevdev".
				 */
				break;
			}

			/*
			 * Is the new interface's instance number less
			 * than the next interface's instance number,
			 * and is it the case that the new interface is a
			 * non-loopback interface or the next interface is
			 * a loopback interface?
			 *
			 * (The goal of both loopback tests is to make
			 * sure that we never put a loopback interface
			 * before any non-loopback interface and that we
			 * always put a non-loopback interface before all
			 * loopback interfaces.)
			 */
			if (this_instance < get_instance(nextdev->name) &&
			    (!(curdev->flags & PCAP_IF_LOOPBACK) ||
			       (nextdev->flags & PCAP_IF_LOOPBACK))) {
				/*
				 * Yes - we should put the new entry
				 * before "nextdev", i.e. after "prevdev".
				 */
				break;
			}

			prevdev = nextdev;
		}

		/*
		 * Insert before "nextdev".
		 */
		curdev->next = nextdev;

		/*
		 * Insert after "prevdev" - unless "prevdev" is null,
		 * in which case this is the first interface.
		 */
		if (prevdev == NULL) {
			/*
			 * This is the first interface.  Pass back a
			 * pointer to it, and put "curdev" before
			 * "nextdev".
			 */
			*alldevs = curdev;
		} else
			prevdev->next = curdev;
	}
	
	*curdev_ret = curdev;
	return (0);
}
Beispiel #4
0
/*
 * Return the interface list
 */
int
ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf, size_t l)
{
#ifdef HAVE_GETIFADDRS
	struct ifaddrs *ifap, *ifa;
	int nipaddr;
	struct ifaddrlist *al;
	struct ifaddrlist *ifaddrlist;
	unsigned int maxif;
	struct sockaddr_in *sin;

#if 1
	maxif = if_maxindex() * 3; /* 3 is a magic number... */
#else
	maxif = 64;
#endif

	ifaddrlist = (struct ifaddrlist *)malloc(maxif *
		sizeof(struct ifaddrlist));
	if (ifaddrlist == NULL)
		return -1;

	if (getifaddrs(&ifap) != 0)
		return -1;

	al = ifaddrlist;
	nipaddr = 0;
	for (ifa = ifap; ifa && nipaddr < maxif; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr->sa_family != AF_INET)
			continue;
		if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr ==
		    htonl(INADDR_ANY))
			continue;
		if ((ifa->ifa_flags & IFF_UP) == 0)
			continue;
#ifdef IFF_LOOPBACK
		if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
			continue;
#else
		if (strcmp(ifa->ifa_name, "lo0") == 0)
			continue;
#endif

		sin = (struct sockaddr_in *)ifa->ifa_addr;
		al->addr = sin->sin_addr.s_addr;
		al->device = strdup(ifa->ifa_name);
		++al;
		++nipaddr;
	}

	*ipaddrp = ifaddrlist;
#ifdef HAVE_FREEIFADDRS
	freeifaddrs(ifap);
#else
	free(ifap);
#endif
	return nipaddr;
#else
	register int fd, nipaddr;
#ifdef HAVE_SOCKADDR_SA_LEN
	register int n;
#endif
	register struct ifreq *ifrp, *ifend, *ifnext, *mp;
	register struct sockaddr_in *sin;
	register struct ifaddrlist *al;
	struct ifconf ifc;
	struct ifreq *ibuf, ifr;
	char device[sizeof(ifr.ifr_name) + 1];
	struct ifaddrlist *ifaddrlist;
	unsigned int maxif;

#if 1
	maxif = if_maxindex() * 3; /* 3 is a magic number... */
#else
	maxif = 64;
#endif
	ifaddrlist = (struct ifaddrlist *)malloc(maxif *
		sizeof(struct ifaddrlist));
	if (ifaddrlist == NULL)
		return -1;
	ibuf = (struct ifreq *)malloc(maxif * sizeof(struct ifreq));
	if (ibuf == NULL) {
		free(ifaddrlist);
		return -1;
	}

	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0) {
		(void)snprintf(errbuf, l, "socket: %s", strerror(errno));
		free(ifaddrlist);
		free(ibuf);
		return (-1);
	}
	ifc.ifc_len = maxif * sizeof(struct ifreq);
	ifc.ifc_buf = (caddr_t)ibuf;

	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
	    ifc.ifc_len < sizeof(struct ifreq)) {
		(void)snprintf(errbuf, l, "SIOCGIFCONF: %s", strerror(errno));
		(void)close(fd);
		free(ifaddrlist);
		free(ibuf);
		return (-1);
	}
	ifrp = ibuf;
	ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);

	al = ifaddrlist;
	mp = NULL;
	nipaddr = 0;
	for (; ifrp < ifend; ifrp = ifnext) {
#ifdef HAVE_SOCKADDR_SA_LEN
		n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
		if (n < sizeof(*ifrp))
			ifnext = ifrp + 1;
		else
			ifnext = (struct ifreq *)((char *)ifrp + n);
		if (ifrp->ifr_addr.sa_family != AF_INET)
			continue;
#else
		ifnext = ifrp + 1;
#endif

		if (((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr ==
		    htonl(INADDR_ANY))
			continue;
		/*
		 * Need a template to preserve address info that is
		 * used below to locate the next entry.  (Otherwise,
		 * SIOCGIFFLAGS stomps over it because the requests
		 * are returned in a union.)
		 */
		strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifrp->ifr_name));
		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
			if (errno == ENXIO)
				continue;
			(void)snprintf(errbuf, l, "SIOCGIFFLAGS: %.*s: %s",
			    (int)sizeof(ifr.ifr_name), ifr.ifr_name,
			    strerror(errno));
			(void)close(fd);
			free(ifaddrlist);
			free(ibuf);
			return (-1);
		}

		/* Must be up and not the loopback */
		if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
			continue;

		(void)strncpy(device, ifr.ifr_name, sizeof(ifr.ifr_name));
		device[sizeof(device) - 1] = '\0';
		if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
			(void)snprintf(errbuf, l, "SIOCGIFADDR: %s: %s",
			    device, strerror(errno));
			(void)close(fd);
			free(ifaddrlist);
			free(ibuf);
			return (-1);
		}

		sin = (struct sockaddr_in *)&ifr.ifr_addr;
		al->addr = sin->sin_addr.s_addr;
		al->device = strdup(device);
		++al;
		++nipaddr;
	}
	(void)close(fd);

	*ipaddrp = ifaddrlist;
	free(ibuf);
	return (nipaddr);
#endif
}