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); }
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; }