/*
 * Fill the hostent from the given DNS packet.
 */
static int
hostent_from_packet(struct hostent *h, int action, char *pkt, size_t pktlen)
{
	struct packed	 p;
	struct header	 hdr;
	struct query	 q;
	struct rr	 rr;
	int		 r;

	packed_init(&p, pkt, pktlen);
	unpack_header(&p, &hdr);
	for(; hdr.qdcount; hdr.qdcount--)
		unpack_query(&p, &q);
	for(; hdr.ancount; hdr.ancount--) {
		unpack_rr(&p, &rr);
		if (rr.rr_class != C_IN)
			continue;
		switch (rr.rr_type) {

		case T_CNAME:
			if (action == ASR_GETHOSTBYNAME)
				r = hostent_add_alias(h, rr.rr_dname, 1);
			else
				r = hostent_set_cname(h, rr.rr_dname, 1);
			break;

		case T_PTR:
			if (action != ASR_GETHOSTBYADDR)
				continue;
			r = hostent_set_cname(h, rr.rr.ptr.ptrname, 1);
			/* XXX See if we need MULTI_PTRS_ARE_ALIASES */
			break;

		case T_A:
			if (h->h_addrtype != AF_INET)
				break;
			r = hostent_set_cname(h, rr.rr_dname, 1);
			r = hostent_add_addr(h, &rr.rr.in_a.addr, 4);
			break;

		case T_AAAA:
			if (h->h_addrtype != AF_INET6)
				break;
			r = hostent_set_cname(h, rr.rr_dname, 1);
			r = hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16);
			break;
		}
	}

	return (0);
}
Example #2
0
static void
dns_dispatch_mx_preference(struct asr_result *ar, void *arg)
{
	struct dns_session	*s = arg;
	struct unpack		 pack;
	struct dns_header	 h;
	struct dns_query	 q;
	struct dns_rr		 rr;
	char			 buf[512];
	int			 error;

	if (ar->ar_h_errno) {
		if (ar->ar_rcode == NXDOMAIN)
			error = DNS_ENONAME;
		else if (ar->ar_h_errno == NO_RECOVERY
		    || ar->ar_h_errno == NO_DATA)
			error = DNS_EINVAL;
		else
			error = DNS_RETRY;
	}
	else {
		error = DNS_ENOTFOUND;
		unpack_init(&pack, ar->ar_data, ar->ar_datalen);
		if (unpack_header(&pack, &h) != -1 &&
		    unpack_query(&pack, &q) != -1) {
			for (; h.ancount; h.ancount--) {
				if (unpack_rr(&pack, &rr) == -1)
					break;
				if (rr.rr_type != T_MX)
					continue;
				print_dname(rr.rr.mx.exchange, buf, sizeof(buf));
				buf[strlen(buf) - 1] = '\0';
				if (!strcasecmp(s->name, buf)) {
					error = DNS_OK;
					break;
				}
			}
		}
	}

	free(ar->ar_data);

	m_create(s->p, IMSG_MTA_DNS_MX_PREFERENCE, 0, 0, -1);
	m_add_id(s->p, s->reqid);
	m_add_int(s->p, error);
	if (error == DNS_OK)
		m_add_int(s->p, rr.rr.mx.preference);
	m_close(s->p);
	free(s);
}
Example #3
0
static void
dns_dispatch_mx(struct asr_result *ar, void *arg)
{
	struct dns_session	*s = arg;
	struct unpack		 pack;
	struct dns_header	 h;
	struct dns_query	 q;
	struct dns_rr		 rr;
	char			 buf[512];
	size_t			 found;

	if (ar->ar_h_errno && ar->ar_h_errno != NO_DATA) {

		m_create(s->p,  IMSG_MTA_DNS_HOST_END, 0, 0, -1);
		m_add_id(s->p, s->reqid);
		if (ar->ar_rcode == NXDOMAIN)
			m_add_int(s->p, DNS_ENONAME);
		else if (ar->ar_h_errno == NO_RECOVERY)
			m_add_int(s->p, DNS_EINVAL);
		else
			m_add_int(s->p, DNS_RETRY);
		m_close(s->p);
		free(s);
		free(ar->ar_data);
		return;
	}

	found = 0;

	unpack_init(&pack, ar->ar_data, ar->ar_datalen);
	if (unpack_header(&pack, &h) == -1 || unpack_query(&pack, &q) == -1)
		return;

	for (; h.ancount; h.ancount--) {
		if (unpack_rr(&pack, &rr) == -1)
			break;
		if (rr.rr_type != T_MX)
			continue;
		print_dname(rr.rr.mx.exchange, buf, sizeof(buf));
		buf[strlen(buf) - 1] = '\0';
		dns_lookup_host(s, buf, rr.rr.mx.preference);
		found++;
	}
	free(ar->ar_data);

	/* fallback to host if no MX is found. */
	if (found == 0)
		dns_lookup_host(s, s->name, 0);
}
Example #4
0
/*
 * Fill the hostent from the given DNS packet.
 */
static struct hostent *
hostent_from_packet(int reqtype, int family, char *pkt, size_t pktlen)
{
	struct hostent	*h;
	struct packed	 p;
	struct header	 hdr;
	struct query	 q;
	struct rr	 rr;

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

	packed_init(&p, pkt, pktlen);
	unpack_header(&p, &hdr);
	for(; hdr.qdcount; hdr.qdcount--)
		unpack_query(&p, &q);
	for(; hdr.ancount; hdr.ancount--) {
		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 (hostent_set_cname(h, rr.rr_dname, 1) == -1)
					goto fail;
			}
			break;

		case T_PTR:
			if (reqtype != ASR_GETHOSTBYADDR)
				break;
			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)
				goto fail;
			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)
				goto fail;
			if (hostent_add_addr(h, &rr.rr.in_aaaa.addr6, 16) == -1)
				goto fail;
			break;
		}
	}

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