static char *dumpsoa(struct rfc1035_reply *r, struct rfc1035_rr *rr)
{
char	name1[RFC1035_MAXNAMESIZE+1], name2[RFC1035_MAXNAMESIZE+1];
char	*p;
char	timebuf[RFC1035_MAXTIMEBUFSIZE+1];

	rfc1035_replyhostname(r, rr->rr.soa.rname_label, name1);
	rfc1035_replyhostname(r, rr->rr.soa.mname_label, name2);

	p=(char *)malloc(strlen(name1)+strlen(name2)+500);
	if (!p)	return (0);

	strcat(strcat(strcat(strcpy(p, name2), ". "), name1), ". (\n\t\t\t\t");
	sprintf(p+strlen(p), "%lu ; serial\n", 
			(unsigned long)rr->rr.soa.serial);
	sprintf(p+strlen(p), "\t\t\t\t%s  ; refresh\n", 
			rfc1035_fmttime( rr->rr.soa.refresh, timebuf));
	sprintf(p+strlen(p), "\t\t\t\t%s  ; retry\n", 
			rfc1035_fmttime( rr->rr.soa.retry, timebuf));
	sprintf(p+strlen(p), "\t\t\t\t%s  ; expire\n", 
			rfc1035_fmttime( rr->rr.soa.expire, timebuf));
	sprintf(p+strlen(p), "\t\t\t\t%s) ; minimum", 
			rfc1035_fmttime( rr->rr.soa.minimum, timebuf));
	return (p);
}
Beispiel #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);
}
char *rfc1035_dumprrdata(struct rfc1035_reply *r, struct rfc1035_rr *rr)
{
	if (rr->rrclass != RFC1035_CLASS_IN)	return (0);
	switch (rr->rrtype)	{
	case RFC1035_TYPE_A:
		{
		char	ipbuf[RFC1035_NTOABUFSIZE];

			rfc1035_ntoa_ipv4(&rr->rr.inaddr, ipbuf);
			return (strdup(ipbuf));
		}
#if	RFC1035_IPV6
	case RFC1035_TYPE_AAAA:
		{
		char	ipbuf[INET6_ADDRSTRLEN];

			if (inet_ntop(AF_INET6, &rr->rr.in6addr,
				ipbuf, sizeof(ipbuf)) == 0)
				ipbuf[0]=0;
			return (strdup(ipbuf));
		}
#endif
	case RFC1035_TYPE_TXT:
		return (dumptxt(r, rr));
	case RFC1035_TYPE_CNAME:
	case RFC1035_TYPE_MB:
	case RFC1035_TYPE_MG:
	case RFC1035_TYPE_MR:
	case RFC1035_TYPE_MD:
	case RFC1035_TYPE_MF:
	case RFC1035_TYPE_NS:
	case RFC1035_TYPE_PTR:
		{
		char	p[RFC1035_MAXNAMESIZE+1], *q;

			rfc1035_replyhostname(r, rr->rr.domainname, p);

			if ((q=(char *)malloc(strlen(p)+2)) != 0)
				strcat(strcpy(q, p), ".");
			return (q);
		}

	case RFC1035_TYPE_SOA:
		return (dumpsoa(r, rr));
		break;
	case RFC1035_TYPE_MX:

		{
		char	p[RFC1035_MAXNAMESIZE+1], *q;

			rfc1035_replyhostname(r, rr->rr.mx.mx_label, p);

			if ((q=(char *)malloc(strlen(p)+40)) != 0)
			{
				sprintf(q, "%d %s.",
					(int)rr->rr.mx.preference, p);
			}
			return (q);
		}

	case RFC1035_TYPE_HINFO:
		{
		char *p=malloc( (int)(unsigned char)*rr->rr.hinfo.hinfo_str+
				(int)(unsigned char)*rr->rr.hinfo.os_str+10);

			if (p)
			{
			const char *q=rr->rr.hinfo.hinfo_str;

				*p=0;
				str_cat(p, &q);
				strcat(p, ", ");
				q=rr->rr.hinfo.os_str;
				str_cat(p, &q);
			}
			return (p);
		}
	case RFC1035_TYPE_MINFO:
		{
		char	p[RFC1035_MAXNAMESIZE+1], t[RFC1035_MAXNAMESIZE+1], *q;

			rfc1035_replyhostname(r, rr->rr.minfo.rmailbx_label, p);
			rfc1035_replyhostname(r, rr->rr.minfo.emailbx_label, t);

			if ((q=(char *)malloc(strlen(p)+strlen(t)+4)) == 0)
				return (0);
			strcat(strcat(strcat(strcpy(q, p), ". "), t), ".");
			return (q);
		}

	case RFC1035_TYPE_RRSIG:
		{
			time_t now=time(NULL);

			size_t n=fmt_rrsig(r, rr, now, NULL);
			char *p;

			if ((p=malloc(n+1)) == 0)
				return (0);

			fmt_rrsig(r, rr, now, p);

			p[n]=0;
			return p;
		}
	}
	return (0);
}
static size_t fmt_rrsig(struct rfc1035_reply *r,
			struct rfc1035_rr *rr, time_t now, char *buf)
{
	char	p[RFC1035_MAXNAMESIZE+1];

	char	timebuf[RFC1035_MAXTIMEBUFSIZE+1];

	time_t signature_inception, signature_expiration;

	struct libmail_encode_info lei;

	struct fmt_rrsig_info fri;

	fri.buf=buf;
	fri.n=0;

	rfc1035_type_itostr(rr->rr.rrsig.type_covered, tostr_callback, &fri);

	append_str(&fri, " ", 1);

	append_int32(&fri, rr->rr.rrsig.algorithm);

	append_str(&fri, " ", 1);

	append_int32(&fri, rr->rr.rrsig.labels);

	append_str(&fri, " ", 1);

	rfc1035_fmttime(rr->rr.rrsig.original_ttl, timebuf);

	append_str(&fri, timebuf, strlen(timebuf));

	append_str(&fri, " ", 1);

	if (sizeof(time_t) == 4)
	{
		signature_inception=rr->rr.rrsig.signature_inception;
		signature_expiration=rr->rr.rrsig.signature_expiration;
	}
	else
	{
		time_t now_epoch=(now & ~0xFFFFFFFFLL);

		time_t cur_epoch=now_epoch | rr->rr.rrsig.signature_inception;

		time_t prev_epoch=cur_epoch - 0xFFFFFFFF-1;
		time_t next_epoch=cur_epoch + 0xFFFFFFFF+1;


#define time2diff(a,b) ((a) < (b) ? (b)-(a):(a)-(b))

#define closest2now(now,time1,time2)					\
		(time2diff((now), (time1)) < time2diff((now), (time2))	\
		 ? (time1):(time2))

		signature_inception =
			closest2now(now, closest2now(now,
						     prev_epoch,
						     cur_epoch),
				    next_epoch);

		signature_expiration =
			signature_inception +
			((rr->rr.rrsig.signature_expiration -
			  rr->rr.rrsig.signature_inception)
			 & 0x7FFFFFFF);
	}

	append_time_t(&fri, signature_inception);

	append_str(&fri, " ", 1);

	append_time_t(&fri, signature_expiration);

	append_str(&fri, " ", 1);

	append_int32(&fri, rr->rr.rrsig.key_tag);

	append_str(&fri, " ", 1);

	rfc1035_replyhostname(r, rr->rr.rrsig.signer_name, p);

	append_str(&fri, p, strlen(p));

	append_str(&fri, ". ", 2);

	libmail_encode_start(&lei, "base64", encode_callback_func, &fri);

	libmail_encode(&lei, rr->rr.rrsig.signature,
		       rr->rr.rrsig.signature_len);
	libmail_encode_end(&lei);

	return fri.n;
}