예제 #1
0
/*% Release the memory in resolver context ctx that was allocated to the lwres_gabnresponse_t. */
void
lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp)
{
	lwres_gabnresponse_t *gabn;
	lwres_addr_t *addr;

	REQUIRE(ctx != NULL);
	REQUIRE(structp != NULL && *structp != NULL);

	gabn = *structp;
	*structp = NULL;

	if (gabn->naliases > 0) {
		CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases);
		CTXFREE(gabn->aliaslen,
			sizeof(lwres_uint16_t) * gabn->naliases);
	}
	addr = LWRES_LIST_HEAD(gabn->addrs);
	while (addr != NULL) {
		LWRES_LIST_UNLINK(gabn->addrs, addr, link);
		CTXFREE(addr, sizeof(lwres_addr_t));
		addr = LWRES_LIST_HEAD(gabn->addrs);
	}
	if (gabn->base != NULL)
		CTXFREE(gabn->base, gabn->baselen);
	CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
}
예제 #2
0
static void
test_gabn(const char *target) {
	lwres_gabnresponse_t *res;
	lwres_addr_t *addr;
	int ret;
	unsigned int i;
	char outbuf[64];

	res = NULL;
	ret = lwres_getaddrsbyname(ctx, target,
				   LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6,
				   &res);
	printf("gabn %s ret == %d\n", target, ret);
	if (ret != 0) {
		printf("FAILURE!\n");
		if (res != NULL)
			lwres_gabnresponse_free(ctx, &res);
		return;
	}

	printf("Returned real name: (%u, %s)\n",
	       res->realnamelen, res->realname);
	printf("%u aliases:\n", res->naliases);
	for (i = 0; i < res->naliases; i++)
		printf("\t(%u, %s)\n", res->aliaslen[i], res->aliases[i]);
	printf("%u addresses:\n", res->naddrs);
	addr = LWRES_LIST_HEAD(res->addrs);
	for (i = 0; i < res->naddrs; i++) {
		INSIST(addr != NULL);

		if (addr->family == LWRES_ADDRTYPE_V4)
			(void)inet_ntop(AF_INET, addr->address,
					outbuf, sizeof(outbuf));
		else
			(void)inet_ntop(AF_INET6, addr->address,
					outbuf, sizeof(outbuf));
		printf("\tAddr len %u family %08x %s\n",
		       addr->length, addr->family, outbuf);
		addr = LWRES_LIST_NEXT(addr, link);
	}

	lwres_gabnresponse_free(ctx, &res);
}
예제 #3
0
static struct hostent *
hostfromname(lwres_gabnresponse_t *name, int af) {
	struct hostent *he;
	int i;
	lwres_addr_t *addr;

	he = malloc(sizeof(*he));
	if (he == NULL)
		goto cleanup;
	memset(he, 0, sizeof(*he));

	/*
	 * Set family and length.
	 */
	he->h_addrtype = af;
	switch (af) {
	case AF_INET:
		he->h_length = INADDRSZ;
		break;
	case AF_INET6:
		he->h_length = IN6ADDRSZ;
		break;
	default:
		INSIST(0);
	}

	/*
	 * Copy name.
	 */
	he->h_name = strdup(name->realname);
	if (he->h_name == NULL)
		goto cleanup;

	/*
	 * Copy aliases.
	 */
	he->h_aliases = malloc(sizeof(char *) * (name->naliases + 1));
	for (i = 0; i < name->naliases; i++) {
		he->h_aliases[i] = strdup(name->aliases[i]);
		if (he->h_aliases[i] == NULL)
			goto cleanup;
	}
	he->h_aliases[i] = NULL;

	/*
	 * Copy addresses.
	 */
	he->h_addr_list = malloc(sizeof(char *) * (name->naddrs + 1));
	addr = LWRES_LIST_HEAD(name->addrs);
	i = 0;
	while (addr != NULL) {
		he->h_addr_list[i] = malloc(he->h_length);
		if (he->h_addr_list[i] == NULL)
			goto cleanup;
		memcpy(he->h_addr_list[i], addr->address, he->h_length);
		addr = LWRES_LIST_NEXT(addr, link);
		i++;
	}
	he->h_addr_list[i] = NULL;
	return (he);

 cleanup:
	if (he != NULL && he->h_addr_list != NULL) {
		for (i = 0; he->h_addr_list[i] != NULL; i++)
			free(he->h_addr_list[i]);
		free(he->h_addr_list);
	}
	if (he != NULL && he->h_aliases != NULL) {
		for (i = 0; he->h_aliases[i] != NULL; i++)
			free(he->h_aliases[i]);
		free(he->h_aliases);
	}
	if (he != NULL && he->h_name != NULL)
		free(he->h_name);
	if (he != NULL)
		free(he);
	return (NULL);
}
예제 #4
0
static void
test_gabn(const char *target, lwres_result_t expected, const char *address,
	  lwres_uint32_t af)
{
	lwres_gabnresponse_t *res;
	unsigned char addrbuf[16];
	lwres_addr_t *addr;
	char outbuf[64];
	unsigned int len;
	lwres_result_t ret;

	res = NULL;
	ret = lwres_getaddrsbyname(ctx, target,
				   LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6,
				   &res);
	if (ret != expected) {
		printf("I:gabn(%s) failed: %d\n", target, ret);
		if (res != NULL)
			lwres_gabnresponse_free(ctx, &res);
		fails++;
		return;
	}
	if (ret == LWRES_R_SUCCESS) {
		if (af == LWRES_ADDRTYPE_V4) {
			len = 4;
			ret = inet_pton(AF_INET, address, addrbuf);
			assert(ret == 1);
		} else {
			len = 16;
			ret = inet_pton(AF_INET6, address, addrbuf);
			assert(ret == 1);
		}
		addr = LWRES_LIST_HEAD(res->addrs);
		if (addr == NULL) {
			printf("I:gabn(%s) returned empty list\n", target);
			fails++;
			return;
		}
		while (addr != NULL) {
			if (addr->family != af || addr->length != len ||
			    memcmp(addr->address, addrbuf, len) == 0)
				break;
			addr = LWRES_LIST_NEXT(addr, link);
		}
		if (addr == NULL) {
			addr = LWRES_LIST_HEAD(res->addrs);
			if (addr->family == LWRES_ADDRTYPE_V4)
				(void)inet_ntop(AF_INET, addr->address,
						outbuf, sizeof(outbuf));
			else
				(void)inet_ntop(AF_INET6, addr->address,
						outbuf, sizeof(outbuf));
			printf("I:gabn(%s) returned %s, expected %s\n",
				target, outbuf, address);
			fails++;
			return;
		}
	}
	if (res != NULL)
		lwres_gabnresponse_free(ctx, &res);
}
예제 #5
0
static int
add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
	 int socktype, int port)
{
	struct addrinfo *ai;
	lwres_context_t *lwrctx = NULL;
	lwres_gabnresponse_t *by = NULL;
	lwres_addr_t *addr;
	lwres_result_t lwres;
	int result = 0;

	lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
	if (lwres != LWRES_R_SUCCESS)
		ERR(EAI_FAIL);
	(void) lwres_conf_parse(lwrctx, lwres_resolv_conf);

	if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
		ai = ai_clone(*aip, AF_INET6);
		if (ai == NULL) {
			lwres_freeaddrinfo(*aip);
			ERR(EAI_MEMORY);
		}

		*aip = ai;
		ai->ai_socktype = socktype;
		SIN6(ai->ai_addr)->sin6_port = port;
		memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16);
	} else {
		lwres = lwres_getaddrsbyname(lwrctx, hostname,
					     LWRES_ADDRTYPE_V6, &by);
		if (lwres != LWRES_R_SUCCESS) {
			if (lwres == LWRES_R_NOTFOUND)
				goto cleanup;
			else
				ERR(EAI_FAIL);
		}
		addr = LWRES_LIST_HEAD(by->addrs);
		while (addr != NULL) {
			ai = ai_clone(*aip, AF_INET6);
			if (ai == NULL) {
				lwres_freeaddrinfo(*aip);
				ERR(EAI_MEMORY);
			}
			*aip = ai;
			ai->ai_socktype = socktype;
			SIN6(ai->ai_addr)->sin6_port = port;
			memcpy(&SIN6(ai->ai_addr)->sin6_addr,
			       addr->address, 16);
			if (flags & AI_CANONNAME) {
				ai->ai_canonname = strdup(by->realname);
				if (ai->ai_canonname == NULL)
					ERR(EAI_MEMORY);
			}
			addr = LWRES_LIST_NEXT(addr, link);
		}
	}
 cleanup:
	if (by != NULL)
		lwres_gabnresponse_free(lwrctx, &by);
	if (lwrctx != NULL) {
		lwres_conf_clear(lwrctx);
		lwres_context_destroy(&lwrctx);
	}
	return (result);
}
예제 #6
0
lwres_result_t
lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
			lwres_lwpacket_t *pkt, lwres_gabnresponse_t **structp)
{
	lwres_result_t ret;
	unsigned int x;
	lwres_uint32_t flags;
	lwres_uint16_t naliases;
	lwres_uint16_t naddrs;
	lwres_gabnresponse_t *gabn;
	lwres_addrlist_t addrlist;
	lwres_addr_t *addr;

	REQUIRE(ctx != NULL);
	REQUIRE(pkt != NULL);
	REQUIRE(b != NULL);
	REQUIRE(structp != NULL && *structp == NULL);

	gabn = NULL;

	if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
		return (LWRES_R_FAILURE);

	/*
	 * Pull off the name itself
	 */
	if (!SPACE_REMAINING(b, 4 + 2 + 2))
		return (LWRES_R_UNEXPECTEDEND);
	flags = lwres_buffer_getuint32(b);
	naliases = lwres_buffer_getuint16(b);
	naddrs = lwres_buffer_getuint16(b);

	gabn = CTXMALLOC(sizeof(lwres_gabnresponse_t));
	if (gabn == NULL)
		return (LWRES_R_NOMEMORY);
	gabn->aliases = NULL;
	gabn->aliaslen = NULL;
	LWRES_LIST_INIT(gabn->addrs);
	gabn->base = NULL;

	gabn->flags = flags;
	gabn->naliases = naliases;
	gabn->naddrs = naddrs;

	LWRES_LIST_INIT(addrlist);

	if (naliases > 0) {
		gabn->aliases = CTXMALLOC(sizeof(char *) * naliases);
		if (gabn->aliases == NULL) {
			ret = LWRES_R_NOMEMORY;
			goto out;
		}

		gabn->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
		if (gabn->aliaslen == NULL) {
			ret = LWRES_R_NOMEMORY;
			goto out;
		}
	}

	for (x = 0; x < naddrs; x++) {
		addr = CTXMALLOC(sizeof(lwres_addr_t));
		if (addr == NULL) {
			ret = LWRES_R_NOMEMORY;
			goto out;
		}
		LWRES_LINK_INIT(addr, link);
		LWRES_LIST_APPEND(addrlist, addr, link);
	}

	/*
	 * Now, pull off the real name.
	 */
	ret = lwres_string_parse(b, &gabn->realname, &gabn->realnamelen);
	if (ret != LWRES_R_SUCCESS)
		goto out;

	/*
	 * Parse off the aliases.
	 */
	for (x = 0; x < gabn->naliases; x++) {
		ret = lwres_string_parse(b, &gabn->aliases[x],
					 &gabn->aliaslen[x]);
		if (ret != LWRES_R_SUCCESS)
			goto out;
	}

	/*
	 * Pull off the addresses.  We already strung the linked list
	 * up above.
	 */
	addr = LWRES_LIST_HEAD(addrlist);
	for (x = 0; x < gabn->naddrs; x++) {
		INSIST(addr != NULL);
		ret = lwres_addr_parse(b, addr);
		if (ret != LWRES_R_SUCCESS)
			goto out;
		addr = LWRES_LIST_NEXT(addr, link);
	}

	if (LWRES_BUFFER_REMAINING(b) != 0) {
		ret = LWRES_R_TRAILINGDATA;
		goto out;
	}

	gabn->addrs = addrlist;

	*structp = gabn;
	return (LWRES_R_SUCCESS);

 out:
	if (gabn != NULL) {
		if (gabn->aliases != NULL)
			CTXFREE(gabn->aliases, sizeof(char *) * naliases);
		if (gabn->aliaslen != NULL)
			CTXFREE(gabn->aliaslen,
				sizeof(lwres_uint16_t) * naliases);
		addr = LWRES_LIST_HEAD(addrlist);
		while (addr != NULL) {
			LWRES_LIST_UNLINK(addrlist, addr, link);
			CTXFREE(addr, sizeof(lwres_addr_t));
			addr = LWRES_LIST_HEAD(addrlist);
		}
		CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
	}

	return (ret);
}
예제 #7
0
/*% converts a getaddrbyname response structure lwres_gabnresponse_t to the lightweight resolver's canonical format. */
lwres_result_t
lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req,
			  lwres_lwpacket_t *pkt, lwres_buffer_t *b)
{
	unsigned char *buf;
	size_t buflen;
	int ret;
	size_t payload_length;
	lwres_uint16_t datalen;
	lwres_addr_t *addr;
	int x;

	REQUIRE(ctx != NULL);
	REQUIRE(req != NULL);
	REQUIRE(pkt != NULL);
	REQUIRE(b != NULL);

	/* naliases, naddrs */
	payload_length = 4 + 2 + 2;
	/* real name encoding */
	payload_length += 2 + req->realnamelen + 1;
	/* each alias */
	for (x = 0; x < req->naliases; x++)
		payload_length += 2 + req->aliaslen[x] + 1;
	/* each address */
	x = 0;
	addr = LWRES_LIST_HEAD(req->addrs);
	while (addr != NULL) {
		payload_length += 4 + 2;
		payload_length += addr->length;
		addr = LWRES_LIST_NEXT(addr, link);
		x++;
	}
	INSIST(x == req->naddrs);

	buflen = LWRES_LWPACKET_LENGTH + payload_length;
	buf = CTXMALLOC(buflen);
	if (buf == NULL)
		return (LWRES_R_NOMEMORY);
	lwres_buffer_init(b, buf, (unsigned int)buflen);

	pkt->length = (lwres_uint32_t)buflen;
	pkt->version = LWRES_LWPACKETVERSION_0;
	pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
	pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME;
	pkt->authtype = 0;
	pkt->authlength = 0;

	ret = lwres_lwpacket_renderheader(b, pkt);
	if (ret != LWRES_R_SUCCESS) {
		lwres_buffer_invalidate(b);
		CTXFREE(buf, buflen);
		return (ret);
	}

	/*
	 * Check space needed here.
	 */
	INSIST(SPACE_OK(b, payload_length));

	/* Flags. */
	lwres_buffer_putuint32(b, req->flags);

	/* encode naliases and naddrs */
	lwres_buffer_putuint16(b, req->naliases);
	lwres_buffer_putuint16(b, req->naddrs);

	/* encode the real name */
	datalen = req->realnamelen;
	lwres_buffer_putuint16(b, datalen);
	lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
	lwres_buffer_putuint8(b, 0);

	/* encode the aliases */
	for (x = 0; x < req->naliases; x++) {
		datalen = req->aliaslen[x];
		lwres_buffer_putuint16(b, datalen);
		lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
				    datalen);
		lwres_buffer_putuint8(b, 0);
	}

	/* encode the addresses */
	addr = LWRES_LIST_HEAD(req->addrs);
	while (addr != NULL) {
		lwres_buffer_putuint32(b, addr->family);
		lwres_buffer_putuint16(b, addr->length);
		lwres_buffer_putmem(b, addr->address, addr->length);
		addr = LWRES_LIST_NEXT(addr, link);
	}

	INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
	INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);

	return (LWRES_R_SUCCESS);
}