Example #1
0
static int
addrinfo_from_pkt(struct asr_query *as, char *pkt, size_t pktlen)
{
	struct asr_unpack	 p;
	struct asr_dns_header	 h;
	struct asr_dns_query	 q;
	struct asr_dns_rr	 rr;
	int			 i;
	union {
		struct sockaddr		sa;
		struct sockaddr_in	sain;
		struct sockaddr_in6	sain6;
	} u;
	char		 buf[MAXDNAME], *c;

	asr_unpack_init(&p, pkt, pktlen);
	asr_unpack_header(&p, &h);
	for (; h.qdcount; h.qdcount--)
		asr_unpack_query(&p, &q);

	for (i = 0; i < h.ancount; i++) {
		asr_unpack_rr(&p, &rr);
		if (rr.rr_type != q.q_type ||
		    rr.rr_class != q.q_class)
			continue;

		memset(&u, 0, sizeof u);
		if (rr.rr_type == T_A) {
			u.sain.sin_len = sizeof u.sain;
			u.sain.sin_family = AF_INET;
			u.sain.sin_addr = rr.rr.in_a.addr;
			u.sain.sin_port = 0;
		} else if (rr.rr_type == T_AAAA) {
			u.sain6.sin6_len = sizeof u.sain6;
			u.sain6.sin6_family = AF_INET6;
			u.sain6.sin6_addr = rr.rr.in_aaaa.addr6;
			u.sain6.sin6_port = 0;
		} else
			continue;

		if (as->as.ai.hints.ai_flags & AI_CANONNAME) {
			asr_strdname(rr.rr_dname, buf, sizeof buf);
			buf[strlen(buf) - 1] = '\0';
			c = res_hnok(buf) ? buf : NULL;
		} else if (as->as.ai.hints.ai_flags & AI_FQDN)
			c = as->as.ai.fqdn;
		else
			c = NULL;

		if (addrinfo_add(as, &u.sa, c))
			return (-1); /* errno set */
	}
	return (0);
}
Example #2
0
/*
 * Fill the hostent from the given DNS packet.
 */
static struct hostent_ext *
hostent_from_packet(int reqtype, int family, char *pkt, size_t pktlen)
{
	struct hostent_ext *h;
	struct unpack	 p;
	struct header	 hdr;
	struct query	 q;
	struct rr	 rr;
	char		 dname[MAXDNAME];

	if ((h = hostent_alloc(family)) == NULL)
		return (NULL);

	asr_unpack_init(&p, pkt, pktlen);
	asr_unpack_header(&p, &hdr);
	for (; hdr.qdcount; hdr.qdcount--)
		asr_unpack_query(&p, &q);
	strlcpy(dname, q.q_dname, sizeof(dname));

	for (; hdr.ancount; hdr.ancount--) {
		asr_unpack_rr(&p, &rr);
		if (rr.rr_class != C_IN)
			continue;
		switch (rr.rr_type) {

		case T_CNAME:
			if (reqtype == ASR_GETHOSTBYNAME) {
				if (hostent_add_alias(h, rr.rr_dname, 1) == -1)
					goto fail;
			} else {
				if (strcasecmp(rr.rr_dname, dname) == 0)
					strlcpy(dname, rr.rr.cname.cname,
					    sizeof(dname));
			}
			break;

		case T_PTR:
			if (reqtype != ASR_GETHOSTBYADDR)
				break;
			if (strcasecmp(rr.rr_dname, dname) != 0)
				continue;
			if (hostent_set_cname(h, rr.rr.ptr.ptrname, 1) == -1)
				goto fail;
			/* XXX See if we need MULTI_PTRS_ARE_ALIASES */
			break;

		case T_A:
			if (reqtype != ASR_GETHOSTBYNAME)
				break;
			if (family != AF_INET)
				break;
			if (hostent_set_cname(h, rr.rr_dname, 1) == -1)
				;
			if (hostent_add_addr(h, &rr.rr.in_a.addr, 4) == -1)
				goto fail;
			break;

		case T_AAAA:
			if (reqtype != ASR_GETHOSTBYNAME)
				break;
			if (family != AF_INET6)
				break;
			if (hostent_set_cname(h, rr.rr_dname, 1) == -1)
				;
			if (hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16) == -1)
				goto fail;
			break;
		}
	}

	return (h);
fail:
	free(h);
	return (NULL);
}