예제 #1
0
void
isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
	isc_interfaceiter_t *iter;

	REQUIRE(iterp != NULL);
	iter = *iterp;
	REQUIRE(VALID_IFITER(iter));
	REQUIRE(use_GAA_determined);

	if (use_GAA) {
		REQUIRE(NULL == iter->buf4);
		REQUIRE(NULL == iter->buf4);
		if (iter->ipaa != NULL)
			isc_mem_put(iter->mctx, iter->ipaa, iter->ipaasize);
	} else {
		REQUIRE(NULL == iter->ipaa);
		if (iter->buf4 != NULL)
			isc_mem_put(iter->mctx, iter->buf4, iter->buf4size);
		if (iter->buf6 != NULL)
			isc_mem_put(iter->mctx, iter->buf6, iter->buf6size);
	}

	iter->magic = 0;
	isc_mem_put(iter->mctx, iter, sizeof(*iter));
	*iterp = NULL;
}
예제 #2
0
isc_result_t
isc_interfaceiter_next(isc_interfaceiter_t *iter) {
	isc_result_t result;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE(iter->result == ISC_R_SUCCESS);

	for (;;) {
		result = internal_next(iter);
		if (result == ISC_R_NOMORE) {
			result = internal_next6(iter);
			if (result != ISC_R_SUCCESS)
				break;
			result = internal_current6(iter);
			if (result != ISC_R_IGNORE)
				break;
		} else if (result != ISC_R_SUCCESS)
			break;
		result = internal_current(iter);
		if (result != ISC_R_IGNORE)
			break;
	}
	iter->result = result;
	return (result);
}
예제 #3
0
static isc_result_t
internal_current6(isc_interfaceiter_t *iter) {
	BOOL ifNamed = FALSE;
	int i;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE(iter->pos6 >= 0);
	REQUIRE(iter->buf6 != 0);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = AF_INET6;

	get_addr(AF_INET6, &iter->current.address,
		 iter->buf6->Address[iter->pos6].lpSockaddr);

	/*
	 * Get interface flags.
	 */

	iter->current.flags = INTERFACE_F_UP;

	if (ifNamed == FALSE)
		sprintf(iter->current.name,
			"TCP/IPv6 Interface %d", iter->pos6 + 1);

	for (i = 0; i< 16; i++)
		iter->current.netmask.type.in6.s6_addr[i] = 0xff;
	iter->current.netmask.family = AF_INET6;
	return (ISC_R_SUCCESS);
}
예제 #4
0
static isc_result_t
internal_current(isc_interfaceiter_t *iter) {
	BOOL ifNamed = FALSE;
	unsigned long flags;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE(iter->numIF >= 0);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = AF_INET;

	get_addr(AF_INET, &iter->current.address,
		 (struct sockaddr *)&(iter->IFData.iiAddress));

	/*
	 * Get interface flags.
	 */

	iter->current.flags = 0;
	flags = iter->IFData.iiFlags;

	if ((flags & IFF_UP) != 0)
		iter->current.flags |= INTERFACE_F_UP;

	if ((flags & IFF_POINTTOPOINT) != 0) {
		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
		sprintf(iter->current.name, "PPP Interface %d", iter->numIF);
		ifNamed = TRUE;
	}

	if ((flags & IFF_LOOPBACK) != 0) {
		iter->current.flags |= INTERFACE_F_LOOPBACK;
		sprintf(iter->current.name, "Loopback Interface %d",
			iter->numIF);
		ifNamed = TRUE;
	}

	/*
	 * If the interface is point-to-point, get the destination address.
	 */
	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
		get_addr(AF_INET, &iter->current.dstaddress,
		(struct sockaddr *)&(iter->IFData.iiBroadcastAddress));
	}

	if (ifNamed == FALSE)
		sprintf(iter->current.name,
			"TCP/IP Interface %d", iter->numIF);

	/*
	 * Get the network mask.
	 */
	get_addr(AF_INET, &iter->current.netmask,
		 (struct sockaddr *)&(iter->IFData.iiNetmask));

	return (ISC_R_SUCCESS);
}
예제 #5
0
isc_result_t
isc_interfaceiter_first(isc_interfaceiter_t *iter) {

	REQUIRE(VALID_IFITER(iter));

	if (iter->buf6 != NULL)
		iter->pos6 = iter->buf6->iAddressCount;
	iter->result = ISC_R_SUCCESS;
	return (isc_interfaceiter_next(iter));
}
예제 #6
0
static isc_result_t
internal_current(isc_interfaceiter_t *iter) {
	struct ifaddrs *ifa;
	int family;
	unsigned int namelen;

	REQUIRE(VALID_IFITER(iter));

	ifa = iter->pos;

	INSIST(ifa != NULL);
	INSIST(ifa->ifa_name != NULL);

	if (ifa->ifa_addr == NULL)
		return (ISC_R_IGNORE);

	family = ifa->ifa_addr->sa_family;
	if (family != AF_INET && family != AF_INET6)
		return (ISC_R_IGNORE);

	memset(&iter->current, 0, sizeof(iter->current));

	namelen = strlen(ifa->ifa_name);
	if (namelen > sizeof(iter->current.name) - 1)
		namelen = sizeof(iter->current.name) - 1;

	memset(iter->current.name, 0, sizeof(iter->current.name));
	memcpy(iter->current.name, ifa->ifa_name, namelen);

	iter->current.flags = 0;

	if ((ifa->ifa_flags & IFF_UP) != 0)
		iter->current.flags |= INTERFACE_F_UP;

	if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
		iter->current.flags |= INTERFACE_F_POINTTOPOINT;

	if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
		iter->current.flags |= INTERFACE_F_LOOPBACK;

	iter->current.af = family;

	get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);

	if (ifa->ifa_netmask != NULL)
		get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
			 ifa->ifa_name);

	if (ifa->ifa_dstaddr != NULL &&
	    (iter->current.flags & IFF_POINTOPOINT) != 0)
		get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
			 ifa->ifa_name);

	return (ISC_R_SUCCESS);
}
예제 #7
0
void
isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
	isc_interfaceiter_t *iter;
	REQUIRE(iterp != NULL);
	iter = *iterp;
	REQUIRE(VALID_IFITER(iter));

	isc_mem_put(iter->mctx, iter->buf, iter->bufsize);

	iter->magic = 0;
	isc_mem_put(iter->mctx, iter, sizeof(*iter));
	*iterp = NULL;
}
예제 #8
0
isc_result_t
isc_interfaceiter_first(isc_interfaceiter_t *iter) {
	isc_result_t result;

	REQUIRE(VALID_IFITER(iter));

	iter->numIF = 0;
	for (;;) {
		result = internal_next(iter);
		if (result != ISC_R_SUCCESS)
			break;
		result = internal_current(iter, AF_INET);
		if (result != ISC_R_IGNORE)
			break;
	}
	iter->result = result;
	return (result);
}
예제 #9
0
isc_result_t
isc_interfaceiter_first(isc_interfaceiter_t *iter) {

	REQUIRE(VALID_IFITER(iter));

	/*
	 * SIO_ADDRESS_LIST_QUERY (used to query IPv6 addresses)
	 * intentionally omits localhost addresses ::1 and ::fe80 in
	 * some cases.  ntpd depends on enumerating ::1 to listen on
	 * it, and ntpq and ntpdc default to "localhost" as the target,
	 * so they will attempt to talk to [::1]:123 and fail. This
	 * means we need to synthesize ::1, which we will do first,
	 * hence + 1.
	 */
	if (iter->buf6 != NULL)
		iter->pos6 = iter->buf6->iAddressCount + 1;

	iter->result = ISC_R_SUCCESS;
	return (isc_interfaceiter_next(iter));
}
예제 #10
0
isc_result_t
isc_interfaceiter_first(isc_interfaceiter_t *iter) {
	REQUIRE(VALID_IFITER(iter));
	REQUIRE(use_GAA_determined);
	/*
	 * SIO_ADDRESS_LIST_QUERY (used to query IPv6 addresses)
	 * intentionally omits localhost addresses [::1] and [::fe80] in
	 * some cases.  ntpd depends on enumerating [::1] to listen on
	 * it, and ntpq and ntpdc default to "localhost" as the target,
	 * so they will attempt to talk to [::1]:123 and fail. This
	 * means we need to synthesize ::1, which we will do first,
	 * hence iAddressCount + 1.  internal_next6() will decrement
	 * it before the first use as an index, and internal_current6()
	 * will treat pos6 == iAddressCount as a sign to synthesize
	 * [::1] if needed.
	 */
	if (!use_GAA && iter->buf6 != NULL)
		iter->pos6 = iter->buf6->iAddressCount + 1;
	iter->result = ISC_R_SUCCESS;
	return (isc_interfaceiter_next(iter));
}
예제 #11
0
isc_result_t
isc_interfaceiter_next(isc_interfaceiter_t *iter) {
	isc_result_t result;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE(iter->result == ISC_R_SUCCESS);
	REQUIRE(use_GAA_determined);

	if (use_GAA) {
		do {
			result = internal_next_GAA(iter);
			if (ISC_R_NOMORE == result)
				goto set_result;
			result = internal_current_GAA(iter);
		} while (ISC_R_IGNORE == result);
		goto set_result;
	}

	for (;;) {
		result = internal_next(iter);
		if (result == ISC_R_NOMORE) {
			result = internal_next6(iter);
			if (result != ISC_R_SUCCESS)
				break;
			result = internal_current6(iter);
			if (result != ISC_R_IGNORE)
				break;
		} else if (result != ISC_R_SUCCESS)
			break;
		result = internal_current(iter);
		if (result != ISC_R_IGNORE)
			break;
	}
 set_result:
	iter->result = result;
	return (result);
}
예제 #12
0
static isc_result_t
internal_current(isc_interfaceiter_t *iter) {
	struct ifa_msghdr *ifam, *ifam_end;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE (iter->pos < (unsigned int) iter->bufused);

	ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
	ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);

	// Skip wrong RTM version headers
	if (ifam->ifam_version != RTM_VERSION)
		return (ISC_R_IGNORE);

	if (ifam->ifam_type == RTM_IFINFO) {
		struct if_msghdr *ifm = (struct if_msghdr *) ifam;
		struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
		unsigned int namelen;

		memset(&iter->current, 0, sizeof(iter->current));

		iter->current.ifindex = sdl->sdl_index;
		namelen = sdl->sdl_nlen;
		if (namelen > sizeof(iter->current.name) - 1)
			namelen = sizeof(iter->current.name) - 1;

		memset(iter->current.name, 0, sizeof(iter->current.name));
		memcpy(iter->current.name, sdl->sdl_data, namelen);

		iter->current.flags = 0;

		if ((ifam->ifam_flags & IFF_UP) != 0)
			iter->current.flags |= INTERFACE_F_UP;

		if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0)
			iter->current.flags |= INTERFACE_F_POINTTOPOINT;

		if ((ifam->ifam_flags & IFF_LOOPBACK) != 0)
			iter->current.flags |= INTERFACE_F_LOOPBACK;

		if ((ifam->ifam_flags & IFF_BROADCAST) != 0)
			iter->current.flags |= INTERFACE_F_BROADCAST;

#ifdef IFF_MULTICAST
		if ((ifam->ifam_flags & IFF_MULTICAST) != 0)
			iter->current.flags |= INTERFACE_F_MULTICAST;
#endif

		/*
		 * This is not an interface address.
		 * Force another iteration.
		 */
		return (ISC_R_IGNORE);
	} else if (ifam->ifam_type == RTM_NEWADDR) {
		int i;
		int family;
		struct sockaddr *mask_sa = NULL;
		struct sockaddr *addr_sa = NULL;
		struct sockaddr *dst_sa = NULL;

		struct sockaddr *sa = (struct sockaddr *)(ifam + 1);
		family = sa->sa_family;

		for (i = 0; i < RTAX_MAX; i++)
		{
			if ((ifam->ifam_addrs & (1 << i)) == 0)
				continue;

			INSIST(sa < (struct sockaddr *) ifam_end);

			switch (i) {
			case RTAX_NETMASK: /* Netmask */
				mask_sa = sa;
				break;
			case RTAX_IFA: /* Interface address */
				addr_sa = sa;
				break;
			case RTAX_BRD: /* Broadcast or destination address */
				dst_sa = sa;
				break;
			}
#ifdef ISC_PLATFORM_HAVESALEN
			sa = (struct sockaddr *)((char*)(sa)
					 + ROUNDUP(sa->sa_len));
#else
			/* XXX untested. */
			sa = (struct sockaddr *)((char*)(sa)
					 + ROUNDUP(sizeof(struct sockaddr)));
#endif
		}

		if (addr_sa == NULL)
			return (ISC_R_IGNORE);

		family = addr_sa->sa_family;
		if (family != AF_INET && family != AF_INET6)
			return (ISC_R_IGNORE);

		iter->current.af = family;

		get_addr(family, &iter->current.address, addr_sa,
			 iter->current.name);

		if (mask_sa != NULL)
			get_addr(family, &iter->current.netmask, mask_sa,
				 iter->current.name);

		if (dst_sa != NULL &&
		    (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
			get_addr(family, &iter->current.dstaddress, dst_sa,
				 iter->current.name);

		if (dst_sa != NULL &&
		    (iter->current.flags & INTERFACE_F_BROADCAST) != 0)
			get_addr(family, &iter->current.broadcast, dst_sa,
				 iter->current.name);

		return (ISC_R_SUCCESS);
	} else {
		printf("warning: unexpected interface list message type\n");
		return (ISC_R_IGNORE);
	}
}
예제 #13
0
static isc_result_t
internal_current6(isc_interfaceiter_t *iter) {
	struct LIFREQ *ifrp;
	struct LIFREQ lifreq;
	int family;
	char strbuf[ISC_STRERRORSIZE];
	int fd;

	REQUIRE(VALID_IFITER(iter));
	if (iter->result6 != ISC_R_SUCCESS)
		return (iter->result6);
	REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);

	ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);

	memset(&lifreq, 0, sizeof(lifreq));
	memmove(&lifreq, ifrp, sizeof(lifreq));

	family = lifreq.lifr_addr.ss_family;
#ifdef ISC_PLATFORM_HAVEIPV6
	if (family != AF_INET && family != AF_INET6)
#else
	if (family != AF_INET)
#endif
		return (ISC_R_IGNORE);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = family;

	INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
	memset(iter->current.name, 0, sizeof(iter->current.name));
	memmove(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));

	get_addr(family, &iter->current.address,
		 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);

	/*
	 * If the interface does not have a address ignore it.
	 */
	switch (family) {
	case AF_INET:
		if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
			return (ISC_R_IGNORE);
		break;
	case AF_INET6:
		if (memcmp(&iter->current.address.type.in6, &in6addr_any,
			   sizeof(in6addr_any)) == 0)
			return (ISC_R_IGNORE);
		break;
	}

	/*
	 * Get interface flags.
	 */

	iter->current.flags = 0;

	if (family == AF_INET6)
		fd = iter->socket6;
	else
		fd = iter->socket;

	/*
	 * Ignore the HP/UX warning about "integer overflow during
	 * conversion.  It comes from its own macro definition,
	 * and is really hard to shut up.
	 */
	if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "%s: getting interface flags: %s",
				 lifreq.lifr_name, strbuf);
		return (ISC_R_IGNORE);
	}

	if ((lifreq.lifr_flags & IFF_UP) != 0)
		iter->current.flags |= INTERFACE_F_UP;

#ifdef IFF_POINTOPOINT
	if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
#endif

	if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
		iter->current.flags |= INTERFACE_F_LOOPBACK;

#ifdef IFF_POINTOPOINT
	/*
	 * If the interface is point-to-point, get the destination address.
	 */
	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion.  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
		    < 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
				isc_msgcat_get(isc_msgcat,
					       ISC_MSGSET_IFITERIOCTL,
					       ISC_MSG_GETDESTADDR,
					       "%s: getting "
					       "destination address: %s"),
					 lifreq.lifr_name, strbuf);
			return (ISC_R_IGNORE);
		}
		get_addr(family, &iter->current.dstaddress,
			 (struct sockaddr *)&lifreq.lifr_dstaddr,
			 lifreq.lifr_name);
	}
#endif

	/*
	 * Get the network mask.  Netmask already zeroed.
	 */
	memset(&lifreq, 0, sizeof(lifreq));
	memmove(&lifreq, ifrp, sizeof(lifreq));

#ifdef lifr_addrlen
	/*
	 * Special case: if the system provides lifr_addrlen member, the
	 * netmask of an IPv6 address can be derived from the length, since
	 * an IPv6 address always has a contiguous mask.
	 */
	if (family == AF_INET6) {
		int i, bits;

		iter->current.netmask.family = family;
		for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
			bits = lifreq.lifr_addrlen - i;
			bits = (bits < 8) ? (8 - bits) : 0;
			iter->current.netmask.type.in6.s6_addr[i / 8] =
				(~0 << bits) & 0xff;
		}

		return (ISC_R_SUCCESS);
	}
#endif

	/*
	 * Ignore the HP/UX warning about "integer overflow during
	 * conversion.  It comes from its own macro definition,
	 * and is really hard to shut up.
	 */
	if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 isc_msgcat_get(isc_msgcat,
						ISC_MSGSET_IFITERIOCTL,
						ISC_MSG_GETNETMASK,
						"%s: getting netmask: %s"),
				 lifreq.lifr_name, strbuf);
		return (ISC_R_IGNORE);
	}
	get_addr(family, &iter->current.netmask,
		 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);

	return (ISC_R_SUCCESS);
}
예제 #14
0
static isc_result_t
internal_current4(isc_interfaceiter_t *iter) {
	struct ifreq *ifrp;
	struct ifreq ifreq;
	int family;
	char strbuf[ISC_STRERRORSIZE];
#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
	struct lifreq lifreq;
#else
	char sabuf[256];
#endif
	int i, bits, prefixlen;

	REQUIRE(VALID_IFITER(iter));

	if (iter->ifc.ifc_len == 0 ||
	    iter->pos == (unsigned int)iter->ifc.ifc_len) {
#ifdef __linux
		return (linux_if_inet6_current(iter));
#else
		return (ISC_R_NOMORE);
#endif
	}

	INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);

	ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);

	memset(&ifreq, 0, sizeof(ifreq));
	memmove(&ifreq, ifrp, sizeof(ifreq));

	family = ifreq.ifr_addr.sa_family;
#if defined(ISC_PLATFORM_HAVEIPV6)
	if (family != AF_INET && family != AF_INET6)
#else
	if (family != AF_INET)
#endif
		return (ISC_R_IGNORE);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = family;

	INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
	memset(iter->current.name, 0, sizeof(iter->current.name));
	memmove(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));

	get_addr(family, &iter->current.address,
		 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);

	/*
	 * If the interface does not have a address ignore it.
	 */
	switch (family) {
	case AF_INET:
		if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
			return (ISC_R_IGNORE);
		break;
	case AF_INET6:
		if (memcmp(&iter->current.address.type.in6, &in6addr_any,
			   sizeof(in6addr_any)) == 0)
			return (ISC_R_IGNORE);
		break;
	}

	/*
	 * Get interface flags.
	 */

	iter->current.flags = 0;

	/*
	 * Ignore the HP/UX warning about "integer overflow during
	 * conversion.  It comes from its own macro definition,
	 * and is really hard to shut up.
	 */
	if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "%s: getting interface flags: %s",
				 ifreq.ifr_name, strbuf);
		return (ISC_R_IGNORE);
	}

	if ((ifreq.ifr_flags & IFF_UP) != 0)
		iter->current.flags |= INTERFACE_F_UP;

#ifdef IFF_POINTOPOINT
	if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
#endif

	if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
		iter->current.flags |= INTERFACE_F_LOOPBACK;

	if (family == AF_INET)
		goto inet;

#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
	memset(&lifreq, 0, sizeof(lifreq));
	memmove(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
	memmove(&lifreq.lifr_addr, &iter->current.address.type.in6,
	       sizeof(iter->current.address.type.in6));

	if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "%s: getting interface address: %s",
				 ifreq.ifr_name, strbuf);
		return (ISC_R_IGNORE);
	}
	prefixlen = lifreq.lifr_addrlen;
#else
	isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
	isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
		      ISC_LOGMODULE_INTERFACE,
		      ISC_LOG_INFO,
		      isc_msgcat_get(isc_msgcat,
				     ISC_MSGSET_IFITERIOCTL,
				     ISC_MSG_GETIFCONFIG,
				     "prefix length for %s is unknown "
				     "(assume 128)"), sabuf);
	prefixlen = 128;
#endif

	/*
	 * Netmask already zeroed.
	 */
	iter->current.netmask.family = family;
	for (i = 0; i < 16; i++) {
		if (prefixlen > 8) {
			bits = 0;
			prefixlen -= 8;
		} else {
			bits = 8 - prefixlen;
			prefixlen = 0;
		}
		iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
	}
	return (ISC_R_SUCCESS);

 inet:
	if (family != AF_INET)
		return (ISC_R_IGNORE);
#ifdef IFF_POINTOPOINT
	/*
	 * If the interface is point-to-point, get the destination address.
	 */
	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion.  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
		    < 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
				isc_msgcat_get(isc_msgcat,
					       ISC_MSGSET_IFITERIOCTL,
					       ISC_MSG_GETDESTADDR,
					       "%s: getting "
					       "destination address: %s"),
					 ifreq.ifr_name, strbuf);
			return (ISC_R_IGNORE);
		}
		get_addr(family, &iter->current.dstaddress,
			 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
	}
#endif

	/*
	 * Get the network mask.
	 */
	memset(&ifreq, 0, sizeof(ifreq));
	memmove(&ifreq, ifrp, sizeof(ifreq));
	/*
	 * Ignore the HP/UX warning about "integer overflow during
	 * conversion.  It comes from its own macro definition,
	 * and is really hard to shut up.
	 */
	if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
			isc_msgcat_get(isc_msgcat,
				       ISC_MSGSET_IFITERIOCTL,
				       ISC_MSG_GETNETMASK,
				       "%s: getting netmask: %s"),
				       ifreq.ifr_name, strbuf);
		return (ISC_R_IGNORE);
	}
	get_addr(family, &iter->current.netmask,
		 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
	return (ISC_R_SUCCESS);
}
예제 #15
0
static isc_result_t
internal_current6(isc_interfaceiter_t *iter) {
	BOOL ifNamed = FALSE;
	struct sockaddr_in6 *psa6;
	BOOL localhostSeen;
	int i;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE(iter->pos6 >= 0);
	REQUIRE(iter->buf6 != 0);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = AF_INET6;

	/*
	 * synthesize localhost ::1 before returning the rest, if ::1
	 * is not on the list.
	 */
	if (iter->pos6 >= (unsigned)iter->buf6->iAddressCount) {
		localhostSeen = FALSE;
		for (i = 0; i < iter->buf6->iAddressCount; i++) {
			psa6 = (struct sockaddr_in6 *)
			       iter->buf6->Address[i].lpSockaddr;
			if (!memcmp(&iter->loop__1, &psa6->sin6_addr,
				    sizeof(iter->loop__1))) {
				localhostSeen = TRUE;
				break;
			}
		}
		if (localhostSeen)
			iter->pos6 = iter->buf6->iAddressCount - 1;
	}

	if (iter->pos6 < (unsigned)iter->buf6->iAddressCount) {
		isc_netaddr_fromsockaddr(&iter->current.address,
		    (isc_sockaddr_t *)iter->buf6->Address[iter->pos6].lpSockaddr);
	} else {
		iter->current.address.family = AF_INET6;
		memcpy(&iter->current.address.type.in6, &iter->loop__1,
		       sizeof(iter->current.address.type.in6));
	}

	/*
	 * Get interface flags.
	 */

	iter->current.flags = INTERFACE_F_UP | INTERFACE_F_MULTICAST;

	if (!memcmp(&iter->current.address.type.in6, &iter->loop__1,
		    sizeof(iter->current.address.type.in6)) ||
	    !memcmp(&iter->current.address.type.in6, &iter->loopfe80__1,
	            sizeof(iter->current.address.type.in6))) {

		iter->current.flags |= INTERFACE_F_LOOPBACK;
		snprintf(iter->current.name, sizeof(iter->current.name),
			 "v6loop %d",
			 iter->buf6->iAddressCount - iter->pos6);
		ifNamed = TRUE;
	}

	if (ifNamed == FALSE)
		snprintf(iter->current.name, sizeof(iter->current.name),
			 "IPv6 %d",
			 iter->buf6->iAddressCount - iter->pos6);

	memset(iter->current.netmask.type.in6.s6_addr, 0xff,
	       sizeof(iter->current.netmask.type.in6.s6_addr));
	iter->current.netmask.family = AF_INET6;
	return (ISC_R_SUCCESS);
}
예제 #16
0
static isc_result_t
internal_current(isc_interfaceiter_t *iter) {
	BOOL ifNamed = FALSE;
	unsigned long flags;

	REQUIRE(VALID_IFITER(iter));
	REQUIRE(iter->numIF >= 0);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = AF_INET;

	isc_netaddr_fromsockaddr(&iter->current.address,
	    (isc_sockaddr_t *)&(iter->IFData.iiAddress));

	/*
	 * Get interface flags.
	 */

	iter->current.flags = 0;
	flags = iter->IFData.iiFlags;

	if ((flags & IFF_UP) != 0)
		iter->current.flags |= INTERFACE_F_UP;

	if ((flags & IFF_BROADCAST) != 0)
		iter->current.flags |= INTERFACE_F_BROADCAST;

	if ((flags & IFF_MULTICAST) != 0)
		iter->current.flags |= INTERFACE_F_MULTICAST;

	if ((flags & IFF_POINTTOPOINT) != 0) {
		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
		snprintf(iter->current.name, sizeof(iter->current.name),
			 "PPP %d", iter->numIF);
		ifNamed = TRUE;
	}

	if ((flags & IFF_LOOPBACK) != 0) {
		iter->current.flags |= INTERFACE_F_LOOPBACK;
		snprintf(iter->current.name, sizeof(iter->current.name),
			"v4loop %d", iter->numIF);
		ifNamed = TRUE;
	}

	/*
	 * If the interface is point-to-point, get the destination address.
	 */
	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
		isc_netaddr_fromsockaddr(&iter->current.dstaddress,
		    (isc_sockaddr_t *)&(iter->IFData.iiBroadcastAddress));

	/*
	 * Get the network mask.
	 */
	isc_netaddr_fromsockaddr(&iter->current.netmask,
	    (isc_sockaddr_t *)&(iter->IFData.iiNetmask));

	/*
	 * If the interface is broadcast, get the broadcast address,
	 * based on the unicast address and network mask.
	 */
	if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0)
		get_broadcastaddr(&iter->current.broadcast,
				  &iter->current.address,
				  &iter->current.netmask);

	if (ifNamed == FALSE)
		snprintf(iter->current.name, sizeof(iter->current.name),
			"IPv4 %d", iter->numIF);

	return (ISC_R_SUCCESS);
}