Esempio n. 1
0
si_item_t *
si_addrinfo_v4_mapped(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr *addr, uint16_t iface, const char *cname)
{
	socket_data_t sockdata;
	struct sockaddr_in6 *sa;
	int32_t len;
	uint32_t unused;

	unused = 0;
	len = sizeof(struct sockaddr_in6);
	memset(&sockdata, 0, sizeof(socket_data_t));
	sa = (struct sockaddr_in6 *)&sockdata;
#ifndef ANDROID
	sa->sin6_len = len;
#endif
	sa->sin6_family = AF_INET6;
	sa->sin6_port = htons(port);
	memset(&(sa->sin6_addr.__u6_addr.__u6_addr8[10]), 0xff, 2);
	memcpy(&(sa->sin6_addr.__u6_addr.__u6_addr8[12]), addr, sizeof(struct in_addr));

	/* sin6_scope_id is in host byte order */
	sa->sin6_scope_id = iface;

	return (si_item_t *)LI_ils_create("L444444444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET6, sock, proto, len, sockdata, cname);
}
Esempio n. 2
0
si_item_t *
si_addrinfo_v6(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr *addr, uint16_t iface, const char *cname)
{
	socket_data_t sockdata;
	struct sockaddr_in6 *sa;
	int32_t len;
	uint32_t unused;

	unused = 0;
	len = sizeof(struct sockaddr_in6);
	memset(&sockdata, 0, sizeof(socket_data_t));
	sa = (struct sockaddr_in6 *)&sockdata;
#ifndef ANDROID
	sa->sin6_len = len;
#endif
	sa->sin6_family = AF_INET6;
	sa->sin6_port = htons(port);
	memcpy(&sa->sin6_addr, addr, sizeof(sa->sin6_addr));

	/* sin6_scope_id is in host byte order */
	sa->sin6_scope_id = iface;

	if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
	{
		/* check for embedded scopeid */
		uint16_t esid = ntohs(sa->sin6_addr.__u6_addr.__u6_addr16[1]);
		if (esid != 0)
		{
			sa->sin6_addr.__u6_addr.__u6_addr16[1] = 0;
			if (iface == 0) sa->sin6_scope_id = esid;
		}
	}

	return (si_item_t *)LI_ils_create("L444444444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET6, sock, proto, len, sockdata, cname);
}
Esempio n. 3
0
static si_item_t *
make_hostent6(si_mod_t *si, const char *name, struct in6_addr addr)
{
	char *addrs[2];
	char *aliases[1];
	uint32_t unused;

	if (name == NULL) return NULL;

	unused = 0;

	addrs[0] = (char *)&(addr.__u6_addr.__u6_addr32[0]);
	addrs[1] = NULL;
	aliases[0] = NULL;

	return (si_item_t *)LI_ils_create("L4444s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, name, aliases, AF_INET6, IPV6_ADDR_LEN, addrs);
}
static si_item_t *
make_hostent(si_mod_t *si, const char *name, struct in_addr addr)
{
	char *addrs[2];
	char *aliases[1];
	uint64_t unused;

	if (name == NULL) return NULL;

	unused = 0;

	addrs[0] = (char *)&(addr.s_addr);
	addrs[1] = NULL;
	aliases[0] = NULL;

	return (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, unused, unused, name, aliases, AF_INET, IPV4_ADDR_LEN, addrs);
}
Esempio n. 5
0
si_item_t *
si_addrinfo_v4(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr *addr, uint16_t iface, const char *cname)
{
	socket_data_t sockdata;
	struct sockaddr_in *sa;
	int32_t len, v32;
	uint32_t unused;

	unused = 0;
	len = sizeof(struct sockaddr_in);
	memset(&sockdata, 0, sizeof(socket_data_t));
	sa = (struct sockaddr_in *)&sockdata;

	sa->sin_len = len;
	sa->sin_family = AF_INET;
	sa->sin_port = htons(port);
	memcpy(&sa->sin_addr, addr, sizeof(sa->sin_addr));

	/* Kludge: Jam the interface number into sin_zero (4 bytes). */
	v32 = iface;
	memmove(sa->sin_zero, &v32, sizeof(uint32_t));

	return (si_item_t *)LI_ils_create("L444444444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET, sock, proto, len, sockdata, cname);
}
Esempio n. 6
0
/*
 * getnameinfo
 *
 * We handle some "trival" cases locally.  If the caller passes
 * NI_NUMERICHOST (only), then this call turns into a getservbyport
 * to get the service name + inet_pton() to create a host string.
 * If the caller passes NI_NUMERICSERV (only), then we zero out the port
 * number, complete the getnameinfo, and use printf() to create a service
 * string.  If the caller specifies both NI_NUMERICHOST and NI_NUMERICSERV,
 * we inet_ntop() and printf() and return the results.
 */
si_item_t *
si_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, const char *interface, uint32_t *err)
{
	si_item_t *out = NULL;
	const struct sockaddr *lookup_sa;
	struct sockaddr_in s4;
	struct in_addr a4;
	struct in6_addr a6;
	const uint32_t unused = 0;
	void *addr = NULL;
	char *host = NULL;
	char *serv = NULL;
	uint32_t ifnum = 0;
	uint16_t port = 0;

	int do_host_lookup = ((flags & NI_NUMERICHOST) == 0);
	int do_serv_lookup = ((flags & NI_NUMERICSERV) == 0);

	/* check input */
	if ((si == NULL) || (sa == NULL))
	{
		if (err != NULL) *err = SI_STATUS_EAI_FAIL;
		return NULL;
	}

	if (err != NULL) *err = SI_STATUS_NO_ERROR;

	lookup_sa = sa;

	if (sa->sa_family == AF_INET)
	{
		struct sockaddr_in *s4 = (struct sockaddr_in *)sa;
		memcpy(&a4, &s4->sin_addr, sizeof(a4));
		port = s4->sin_port;
		addr = &a4;
	}
	else if (sa->sa_family == AF_INET6)
	{
		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)sa;
		memcpy(&a6, &s6->sin6_addr, sizeof(a6));
		port = s6->sin6_port;

		/* Look for scope id in IPv6 Link Local, Multicast Node Local, and Multicast Link Local */
		if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&s6->sin6_addr))
		{
			ifnum = ntohs(a6.__u6_addr.__u6_addr16[1]);
			if (ifnum == 0)
			{
				ifnum = s6->sin6_scope_id;
				a6.__u6_addr.__u6_addr16[1] = htons(ifnum);
			}

			if ((ifnum != s6->sin6_scope_id) && (s6->sin6_scope_id != 0))
			{
				if (err != NULL) *err = SI_STATUS_EAI_FAIL;
				return NULL;
			}
		}

		/* v4 mapped and compat addresses are converted to plain v4 */
		if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr))
		{
			memcpy(&a4, &s6->sin6_addr.s6_addr[12], sizeof(a4));
			addr = &a4;
			memset(&s4, 0, sizeof(s4));
			s4.sin_len = sizeof(s4);
			s4.sin_family = AF_INET;
			s4.sin_port = port;
			memcpy(&s4.sin_addr, &a4, sizeof(s4.sin_addr));
			lookup_sa = (const struct sockaddr *)&s4;
		}
		else
		{
			addr = &a6;
		}
	}
	else
	{
		if (err != NULL) *err = SI_STATUS_EAI_FAMILY;
		return NULL;
	}

	if (do_host_lookup == 1)
	{
		si_item_t *item = si_host_byaddr(si, addr, lookup_sa->sa_family, interface, NULL);
		if (item != NULL)
		{
			struct hostent *h;
			h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
			host = strdup(h->h_name);
			si_item_release(item);
			if (host == NULL)
			{
				if (err != NULL) *err = SI_STATUS_EAI_MEMORY;
				return NULL;
			}
		}
	}

	if ((do_serv_lookup == 1) && (port != 0))
	{
		si_item_t *item = si_service_byport(si, port, NULL);
		if (item != NULL)
		{
			struct servent *s;
			s = (struct servent *)((uintptr_t)item + sizeof(si_item_t));
			serv = strdup(s->s_name);
			si_item_release(item);
			if (serv == NULL)
			{
				free(host);
				if (err != NULL) *err = SI_STATUS_EAI_MEMORY;
				return NULL;
			}
		}
	}

	/*
	 * Return numeric host name for NI_NUMERICHOST or if lookup failed, but not
	 * if NI_NAMEREQD is specified (so that we later fail with EAI_NONAME).
	 */
	if ((host == NULL) && ((flags & NI_NAMEREQD) == 0))
	{
		char tmp[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1];
		tmp[0] = '\0';
		if (sa->sa_family == AF_INET)
		{
			char buf[INET_ADDRSTRLEN];
			if (inet_ntop(AF_INET, &a4, buf, sizeof(buf)) != 0)
			{
				host = strdup(buf);
			}
		}
		else if (sa->sa_family == AF_INET6)
		{
			char buf[INET6_ADDRSTRLEN];

			/* zero the embedded scope ID */
			if (ifnum != 0)
			{
				a6.__u6_addr.__u6_addr16[1] = 0;
			}

			if (inet_ntop(AF_INET6, &a6, buf, sizeof(buf)) != 0)
			{
				if (ifnum != 0)
				{
					char ifname[IF_NAMESIZE];
					if (if_indextoname(ifnum, ifname) != NULL)
					{
						asprintf(&host, "%s%%%s", buf, ifname);
					}
					else
					{
						/* ENXIO */
						if (err != NULL) *err = SI_STATUS_EAI_FAIL;
						return NULL;
					}
				}
				else
				{
					host = strdup(buf);
				}
			}
		}
	}

	/* Return numeric service name for NI_NUMERICSERV or if lookup failed. */
	if (serv == NULL)
	{
		asprintf(&serv, "%hu", ntohs(port));
	}

	if ((host == NULL) || (serv == NULL))
	{
		if (err != NULL)
		{
			if ((flags & NI_NAMEREQD) != 0)
			{
				*err = SI_STATUS_EAI_NONAME;
			}
			else
			{
				*err = SI_STATUS_EAI_MEMORY;
			}
		}
	}
	else
	{
		out = (si_item_t *)LI_ils_create("L4444ss", (unsigned long)si, CATEGORY_NAMEINFO, 1, unused, unused, host, serv);
	}

	free(host);
	free(serv);
	return out;
}
Esempio n. 7
0
si_item_t *
si_ipnode_byname(si_mod_t *si, const char *name, int family, int flags, const char *interface, uint32_t *err)
{
	int i, status, want;
	uint32_t if4, if6;
	struct in_addr addr4;
	struct in6_addr addr6;
	si_item_t *item4, *item6;
	build_hostent_t *out;
	struct hostent *h;
	uint32_t unused;

	memset(&addr4, 0, sizeof(struct in_addr));
	memset(&addr6, 0, sizeof(struct in6_addr));

	if (err != NULL) *err = 0;

	if (family == AF_INET)
	{
		status = inet_aton(name, &addr4);
		if (status == 1)
		{
			/* create a host entry */
			item4 = make_hostent(si, name, addr4);
			if (item4 == NULL)
			{
				if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
				return NULL;
			}

			return item4;
		}
	}
	else if (family == AF_INET6)
	{
		status = inet_pton(family, name, &addr6);
		if (status == 1)
		{
			/* create a host entry */
			item6 = make_hostent6(si, name, addr6);
			if (item6 == NULL)
			{
				if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
				return NULL;
			}

			return item6;
		}

		status = inet_aton(name, &addr4);
		if (status == 1)
		{
			if (!(flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)))
			{
				if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
				return NULL;
			}

			addr6.__u6_addr.__u6_addr32[0] = 0x00000000;
			addr6.__u6_addr.__u6_addr32[1] = 0x00000000;
			addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
			memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr4.s_addr), IPV4_ADDR_LEN);

			/* create a host entry */
			item6 = make_hostent6(si, name, addr6);
			if (item6 == NULL)
			{
				if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
				return NULL;
			}

			return item6;
		}
	}
	else
	{
		if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
		return NULL;
	}

	/*
	 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
	 */

	if4 = 0;
	if6 = 0;

	if (flags & AI_ADDRCONFIG)
	{
		if (si_inet_config(&if4, &if6) < 0)
		{
			if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
			return NULL;
		}

		/* Bail out if there are no interfaces */
		if ((if4 == 0) && (if6 == 0))
		{
			if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
			return NULL;
		}
	}

	/*
	 * Figure out what we want.
	 * If user asked for AF_INET, we only want V4 addresses.
	 */
	want = WANT_A4_ONLY;

	if (family == AF_INET)
	{
		if ((flags & AI_ADDRCONFIG) && (if4 == 0))
		{
			if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
			return NULL;
		}
	}
	else if (family == AF_INET6)
	{
		/* family == AF_INET6 */
		want = WANT_A6_ONLY;

		if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG))
		{
			if (flags & AI_ALL)
			{
				want = WANT_A6_PLUS_MAPPED_A4;
			}
			else
			{
				want = WANT_A6_OR_MAPPED_A4_IF_NO_A6;
			}
		}
		else
		{
			if ((flags & AI_ADDRCONFIG) && (if6 == 0)) 
			{
				if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
				return NULL;
			}
		}
	}
	else
	{
		if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
		return NULL;
	}

	item6 = NULL;
	item4 = NULL;

	/* fetch IPv6 data if required */
	if ((want == WANT_A6_ONLY) || (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) || (want == WANT_A6_PLUS_MAPPED_A4))
	{
		item6 = si_host_byname(si, name, AF_INET6, interface, (uint32_t *)err);
	}

	/* fetch IPv4 data if required */
	if ((want == WANT_A4_ONLY) || (want == WANT_A6_PLUS_MAPPED_A4) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (item6 == NULL)))
	{
		item4 = si_host_byname(si, name, AF_INET, interface, (uint32_t *)err);
	}

	if (want == WANT_A4_ONLY)
	{
		si_item_release(item6);
		if ((item4 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
		return item4;
	}

	if (want == WANT_A6_ONLY)
	{
		si_item_release(item4);
		if ((item6 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
		return item6;
	}

	if ((item6 == NULL) && (item4 == NULL))
	{
		if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
		return NULL;
	}

	/* output item will have IPv6 + mapped IPv4 addresses */

	out = (build_hostent_t *)calloc(1, sizeof(build_hostent_t));
	if (out == NULL)
	{
		si_item_release(item4);
		si_item_release(item6);
		if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
		return NULL;
	}

	if (item4 != NULL)
	{
		h = (struct hostent *)((uintptr_t)item4 + sizeof(si_item_t));

		out->host.h_name = lower_case(h->h_name);

		if (h->h_aliases != NULL)
		{
			for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out);
		}

		for (i = 0; h->h_addr_list[i] != 0; i++)
		{
			addr6.__u6_addr.__u6_addr32[0] = 0x00000000;
			addr6.__u6_addr.__u6_addr32[1] = 0x00000000;
			addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
			memmove(&(addr6.__u6_addr.__u6_addr32[3]), h->h_addr_list[i], IPV4_ADDR_LEN);
			append_addr((const char *)&addr6, IPV6_ADDR_LEN, out);
		}
	}

	if (item6 != NULL)
	{
		h = (struct hostent *)((uintptr_t)item6 + sizeof(si_item_t));

		if (out->host.h_name == NULL) out->host.h_name = lower_case(h->h_name);

		if (h->h_aliases != NULL)
		{
			for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out);
		}

		for (i = 0; h->h_addr_list[i] != 0; i++) append_addr(h->h_addr_list[i], IPV6_ADDR_LEN, out);
	}

	si_item_release(item4);
	si_item_release(item6);

	unused = 0;

	item6 = (si_item_t *)LI_ils_create("L4444s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, out->host.h_name, out->host.h_aliases, AF_INET6, IPV6_ADDR_LEN, out->host.h_addr_list);

	free_build_hostent(out);

	return item6;
}