Esempio n. 1
0
static int harvest_records(struct rfc1035_res *res,
	struct rfc1035_mxlist **list,
	struct rfc1035_reply *mxreply,
	int mxpreference,
	char *mxname,
	int q_type, int *found,
	int flags, int port)
{
struct rfc1035_reply *areply=0;
int index;
#if	RFC1035_IPV6
struct in6_addr in;
#else
struct in_addr in;
#endif

	index= -1;

	if (!mxreply || (
		((index=rfc1035_replysearch_all( res, mxreply, mxname,
					q_type,
					RFC1035_CLASS_IN,
					0)) < 0 ||
			mxreply->allrrs[index]->rrtype != q_type)
		&& (flags & HARVEST_AUTOQUERY))
		)
	{
		index=rfc1035_resolve_cname(res,
			RFC1035_RESOLVE_RECURSIVE, mxname,
			q_type,
			RFC1035_CLASS_IN, &areply, RFC1035_X_RANDOMIZE);
		if (index < 0)
		{
			if (!areply)
			{
				if (index == RFC1035_ERR_CNAME_RECURSIVE)
					return (RFC1035_MX_BADDNS);
				return (RFC1035_MX_INTERNAL);
			}

			if (areply->rcode == RFC1035_RCODE_NXDOMAIN ||
				areply->rcode == RFC1035_RCODE_NOERROR)
			{
				rfc1035_replyfree(areply);
				return (RFC1035_MX_OK);
			}
			rfc1035_replyfree(areply);
			return (RFC1035_MX_SOFTERR);
		}
		mxreply=areply;
	}

	for ( ; index >= 0 ;
			index=rfc1035_replysearch_all( res, mxreply, mxname,
					q_type,
					RFC1035_CLASS_IN,
					index+1))
	{
		if (mxreply->allrrs[index]->rrtype != q_type)
			continue;

#if RFC1035_IPV6
		if (q_type == RFC1035_TYPE_A)
		{
		struct rfc1035_mxlist *q;

			/* Map it to an IPv4 address */

			rfc1035_ipv4to6(&in,
				&mxreply->allrrs[index]->rr.inaddr);

			/* See if it's already here */

			for (q= *list; q; q=q->next)
			{
			struct sockaddr_in6 sin6;

				if (q->protocol != PF_INET6)
					continue;
				memcpy(&sin6, &q->address, sizeof(sin6));

				if (memcmp(&sin6.sin6_addr, &in, sizeof(in))
					== 0 && q->priority == mxpreference)
					break;
			}
			if ((flags & HARVEST_NODUPE) && q)	continue;
		}
		else
			in=mxreply->allrrs[index]->rr.in6addr;
#else
		in.s_addr=mxreply->allrrs[index]->rr.inaddr.s_addr;
#endif
		*found=1;
		if (addrecord(list, mxname, mxpreference, &in, port))
		{
			if (areply)
				rfc1035_replyfree(areply);
			return (RFC1035_MX_INTERNAL);
		}
	}
	if (areply)
		rfc1035_replyfree(areply);

	return (RFC1035_MX_OK);
}
Esempio n. 2
0
static int domxlistcreate(struct rfc1035_res *res,
			  const char *q_name, int opts,
			  struct rfc1035_mxlist **list, int port)
{
char	namebuf[RFC1035_MAXNAMESIZE+1];
struct	rfc1035_reply *replyp;
int	index;
RFC1035_ADDR	in;
int seen_softerr=0;
int seen_good=0;

	*list=0;
	if (rfc1035_aton(q_name, &in) == 0)
		return (RFC1035_MX_HARDERR);	/* Don't gimme an IP address */

	namebuf[0]=0;
	strncat(namebuf, q_name, RFC1035_MAXNAMESIZE);
	if (namebuf[0] == '[')
	{
	char	*q=strchr(namebuf, ']');

		if (!q || q[1])	return (RFC1035_MX_HARDERR);	/* Bad addr */
		*q=0;
		if (rfc1035_aton(namebuf+1, &in))
			return (RFC1035_MX_HARDERR);

		if (addrecord(list, q_name, -1, &in, port))
			return (RFC1035_MX_INTERNAL);
		return (RFC1035_MX_OK);
	}

	index=rfc1035_resolve_cname(res,
		RFC1035_RESOLVE_RECURSIVE, namebuf,
		RFC1035_TYPE_MX,
		RFC1035_CLASS_IN, &replyp, RFC1035_X_RANDOMIZE);

	if (index < 0)
	{
		if (!replyp)
		{
			if (index == RFC1035_ERR_CNAME_RECURSIVE)
				return (RFC1035_MX_BADDNS);
			return (RFC1035_MX_INTERNAL);
		}

		if (replyp->rcode == RFC1035_RCODE_NXDOMAIN ||
			replyp->rcode == RFC1035_RCODE_NOERROR)
		{
			rfc1035_replyfree(replyp);
			strcpy(namebuf, q_name);

			if (opts & RFC1035_MX_AFALLBACK)
				return (add_arecords(res, list, 0, -1,
						     namebuf, port));
			return RFC1035_MX_HARDERR;
		}

		rfc1035_replyfree(replyp);
		return (RFC1035_MX_SOFTERR);
	}

	for ( ; index >= 0;
			index=rfc1035_replysearch_all( res, replyp, namebuf,
					RFC1035_TYPE_MX,
					RFC1035_CLASS_IN,
					index+1))
	{
	char	mxname[RFC1035_MAXNAMESIZE+1];

		if (replyp->allrrs[index]->rrtype != RFC1035_TYPE_MX)
			continue;

		if (rfc1035_replyhostname(replyp,
			replyp->allrrs[index]->rr.mx.mx_label, mxname) == 0)
			continue;

		switch (add_arecords(res, list, replyp,
			replyp->allrrs[index]->rr.mx.preference, mxname,
			port)) {
		case	RFC1035_MX_SOFTERR:
			seen_softerr=1;
			continue;
		case	RFC1035_MX_INTERNAL:
			rfc1035_replyfree(replyp);
			return (RFC1035_MX_INTERNAL);
		case	RFC1035_MX_BADDNS:
			rfc1035_replyfree(replyp);
			return (RFC1035_MX_BADDNS);
		default:
			seen_good=1;
			continue;
		}
	}

	rfc1035_replyfree(replyp);

	if (seen_good && (opts & RFC1035_MX_IGNORESOFTERR))
		seen_softerr=0;
		/* At least some A records were probably fetched */

	if (seen_softerr)
		return (RFC1035_MX_SOFTERR);

	if (*list)	return (RFC1035_MX_OK);
	return (RFC1035_MX_HARDERR);
}
Esempio n. 3
0
static char *sts_getid(const char *domain)
{
	struct rfc1035_res res;
	struct rfc1035_reply *replyp;
	int n;
	char lookup_domain[RFC1035_MAXNAMESIZE];
	char txtbuf[256];
	char *id_str=NULL;

	/* Domain cannot be too long */

	if (strlen(domain) >= RFC1035_MAXNAMESIZE-10)
		return 0;

	strcat(strcpy(lookup_domain, "_mta-sts."), domain);

	rfc1035_init_resolv(&res);

	(void)rfc1035_resolve_cname(&res,
				    lookup_domain,
				    RFC1035_TYPE_TXT,
				    RFC1035_CLASS_IN, &replyp, 0);

	if (!replyp)
	{
		rfc1035_destroy_resolv(&res);
		return 0;
	}

	for (n=0; (n=rfc1035_replysearch_an(&res,
					    replyp,
					    lookup_domain, RFC1035_TYPE_TXT,
					    RFC1035_CLASS_IN, n)) >= 0; ++n)
	{
		char *p;

		rfc1035_rr_gettxt(replyp->allrrs[n], 0, txtbuf);

		p=strtok(txtbuf, "; ");

		if (!p || strcmp(p, "v=STSv1"))
			continue;

		if (id_str)
		{
			/* RFC 8461 prohibits two or more. */

			free(id_str);
			id_str=NULL;
			break;
		}

		id_str=sts_getid1();

		if (!id_str)
			break;
	}

	rfc1035_replyfree(replyp);
	rfc1035_destroy_resolv(&res);

	return id_str;
}