コード例 #1
0
ファイル: if.c プロジェクト: kusumi/DragonFlyBSD
/* get ia6_flags for link-local addr on if.  returns -1 on error. */
static int
get_llflag(const char *name)
{
#ifdef HAVE_GETIFADDRS
	struct ifaddrs *ifap, *ifa;
	struct in6_ifreq ifr6;
	struct sockaddr_in6 *sin6;
	int s;

	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
		    strerror(errno));
		exit(1);
	}
	if (getifaddrs(&ifap) != 0) {
		warnmsg(LOG_ERR, __func__, "etifaddrs: %s",
		    strerror(errno));
		exit(1);
	}

	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
		if (strlen(ifa->ifa_name) != strlen(name)
		 || strncmp(ifa->ifa_name, name, strlen(name)) != 0)
			continue;
		if (ifa->ifa_addr->sa_family != AF_INET6)
			continue;
		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
			continue;

		memset(&ifr6, 0, sizeof(ifr6));
		strcpy(ifr6.ifr_name, name);
		memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
			warnmsg(LOG_ERR, __func__,
			    "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
			exit(1);
		}

		freeifaddrs(ifap);
		close(s);
		return ifr6.ifr_ifru.ifru_flags6;
	}

	freeifaddrs(ifap);
	close(s);
	return -1;
#else
	int s;
	unsigned int maxif;
	struct ifreq *iflist;
	struct ifconf ifconf;
	struct ifreq *ifr, *ifr_end;
	struct sockaddr_in6 *sin6;
	struct in6_ifreq ifr6;

	maxif = if_maxindex() + 1;
	iflist = (struct ifreq *)malloc(maxif * BUFSIZ);	/* XXX */
	if (iflist == NULL) {
		warnmsg(LOG_ERR, __func__, "not enough core");
		exit(1);
	}

	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
		    strerror(errno));
		exit(1);
	}
	memset(&ifconf, 0, sizeof(ifconf));
	ifconf.ifc_req = iflist;
	ifconf.ifc_len = maxif * BUFSIZ;	/* XXX */
	if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
		warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFCONF): %s",
		    strerror(errno));
		exit(1);
	}

	/* Look for this interface in the list */
	ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
	for (ifr = ifconf.ifc_req;
	     ifr < ifr_end;
	     ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
				    + ifr->ifr_addr.sa_len)) {
		if (strlen(ifr->ifr_name) != strlen(name)
		 || strncmp(ifr->ifr_name, name, strlen(name)) != 0)
			continue;
		if (ifr->ifr_addr.sa_family != AF_INET6)
			continue;
		sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr;
		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
			continue;

		memset(&ifr6, 0, sizeof(ifr6));
		strcpy(ifr6.ifr_name, name);
		memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
			warnmsg(LOG_ERR, __func__,
			    "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
			exit(1);
		}

		free(iflist);
		close(s);
		return ifr6.ifr_ifru.ifru_flags6;
	}

	free(iflist);
	close(s);
	return -1;
#endif
}
コード例 #2
0
ファイル: ifaddrlist.c プロジェクト: MarginC/kame
/*
 * 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
}