diff options
-rw-r--r-- | lib/dns.c | 154 | ||||
-rw-r--r-- | lib/dns.h | 43 | ||||
-rw-r--r-- | lib/libmf.h | 4 | ||||
-rw-r--r-- | src/builtin/dns.bi | 43 | ||||
-rw-r--r-- | src/callout.c | 12 | ||||
-rw-r--r-- | src/mailfromd.h | 3 | ||||
-rw-r--r-- | src/prog.c | 10 | ||||
-rw-r--r-- | src/spf.c | 10 |
8 files changed, 105 insertions, 174 deletions
@@ -145,17 +145,15 @@ adns_to_dns_status(int e) } } -/* Return MX records for the given HOST. If no records were found, recurse - to its parent domains until any record is found or recursion depth reaches - MAXDEPTH */ +/* Return MX records for the given HOST. */ dns_status -dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf) +dns_get_mx_records(const char *host, struct dns_reply *reply) { dns_status status = dns_failure; int rc; adns_answer *ans; int i; - + rc = adns_synchronous(get_state(), host, adns_r_mx, adns_qf_quoteok_cname|adns_qf_cname_loose, &ans); @@ -164,66 +162,30 @@ dns_get_mx_records(const char *host, int maxdepth, struct mxbuf *mxbuf) status = adns_to_dns_status(ans->status); if (status != dns_success) return status; - mxbuf_init(mxbuf, ans->nrrs); + + reply->type = dns_reply_str; + reply->count = ans->nrrs; + reply->data.str = mu_calloc(reply->count, + sizeof(reply->data.str[0])); for (i = 0; i < ans->nrrs; i++) - mxbuf->mx_buf[i] = mu_strdup(ans->rrs.inthostaddr[i].ha.host); - mxbuf->mx_cnt = i; + reply->data.str[i] = mu_strdup(ans->rrs.inthostaddr[i].ha.host); free(ans); return status; } void -mxbuf_init(struct mxbuf *mxbuf, size_t nmx) -{ - if (mxbuf->mx_flags & MXF_REUSE) { - size_t i; - - for (i = 0; i < mxbuf->mx_cnt; i++) { - free(mxbuf->mx_buf[i]); - mxbuf->mx_buf[i] = NULL; - } - if (nmx > mxbuf->mx_max) { - mxbuf->mx_buf = - mu_realloc(mxbuf->mx_buf, - nmx * sizeof(mxbuf->mx_buf[0])); - mxbuf->mx_max = nmx; - } - } else { - mxbuf->mx_buf = mu_calloc(nmx, sizeof(mxbuf->mx_buf[0])); - mxbuf->mx_max = nmx; - mxbuf->mx_flags |= MXF_REUSE; - } - mxbuf->mx_cnt = 0; -} - -void -mxbuf_free(struct mxbuf *mxbuf) -{ - if (mxbuf->mx_flags & MXF_REUSE) { - int i; - - for (i = 0; i < mxbuf->mx_max && mxbuf->mx_buf[i]; i++) - free(mxbuf->mx_buf[i]); - free(mxbuf->mx_buf); - mxbuf->mx_buf = NULL; - mxbuf->mx_flags &= ~MXF_REUSE; - mxbuf->mx_cnt = mxbuf->mx_max = 0; - } -} - -void -dns_reply_free(struct dns_reply *r) +dns_reply_free(struct dns_reply *reply) { int i; - switch (r->type) { + switch (reply->type) { case dns_reply_str: - for (i = 0; i < r->count; i++) - free(r->data.str[i]); - free(r->data.str); + for (i = 0; i < reply->count; i++) + free(reply->data.str[i]); + free(reply->data.str); break; case dns_reply_ip: - free(r->data.ip); + free(reply->data.ip); break; } } @@ -309,7 +271,7 @@ dns_resolve_hostname(const char *host, char **ipbuf) dns_status -a_lookup(const char *host, struct dns_reply *repl) +a_lookup(const char *host, struct dns_reply *reply) { dns_status status = dns_failure; int rc; @@ -323,19 +285,19 @@ a_lookup(const char *host, struct dns_reply *repl) status = adns_to_dns_status(ans->status); if (status == dns_success) { int i; - repl->type = dns_reply_ip; - repl->count = ans->nrrs; - repl->data.ip = mu_calloc(repl->count, - sizeof(repl->data.ip[0])); + reply->type = dns_reply_ip; + reply->count = ans->nrrs; + reply->data.ip = mu_calloc(reply->count, + sizeof(reply->data.ip[0])); for (i = 0; i < ans->nrrs; i++) - repl->data.ip[i] = ans->rrs.inaddr[i].s_addr; + reply->data.ip[i] = ans->rrs.inaddr[i].s_addr; } free(ans); return status; } dns_status -ptr_lookup(struct in_addr ip, struct dns_reply *repl) +ptr_lookup(struct in_addr ip, struct dns_reply *reply) { dns_status status = dns_failure; int rc; @@ -352,19 +314,19 @@ ptr_lookup(struct in_addr ip, struct dns_reply *repl) status = adns_to_dns_status(ans->status); if (status == dns_success) { int i; - repl->type = dns_reply_str; - repl->count = ans->nrrs; - repl->data.str = mu_calloc(repl->count, - sizeof(repl->data.str[0])); + reply->type = dns_reply_str; + reply->count = ans->nrrs; + reply->data.str = mu_calloc(reply->count, + sizeof(reply->data.str[0])); for (i = 0; i < ans->nrrs; i++) - repl->data.str[i] = mu_strdup(ans->rrs.str[i]); + reply->data.str[i] = mu_strdup(ans->rrs.str[i]); } free(ans); return status; } dns_status -txt_lookup(const char *name, struct dns_reply *repl) +txt_lookup(const char *name, struct dns_reply *reply) { dns_status status = dns_failure; int rc; @@ -378,12 +340,12 @@ txt_lookup(const char *name, struct dns_reply *repl) status = adns_to_dns_status(ans->status); if (status == dns_success) { int i; - repl->type = dns_reply_str; - repl->count = ans->nrrs; - repl->data.str = mu_calloc(repl->count, - sizeof(repl->data.str[0])); + reply->type = dns_reply_str; + reply->count = ans->nrrs; + reply->data.str = mu_calloc(reply->count, + sizeof(reply->data.str[0])); for (i = 0; i < ans->nrrs; i++) - repl->data.str[i] = mu_strdup(ans->rrs.manyistr[i]->str); + reply->data.str[i] = mu_strdup(ans->rrs.manyistr[i]->str); } free(ans); return status; @@ -393,24 +355,24 @@ dns_status spf_lookup(const char *domain, char **rec) { dns_status status; - struct dns_reply r; + struct dns_reply reply; - status = txt_lookup(domain, &r); + status = txt_lookup(domain, &reply); if (status == dns_success) { int i; status = dns_not_found; - for (i = 0; i < r.count; i++) { - if (memcmp(r.data.str[i], "v=spf1", 6) == 0 - && (r.data.str[i][6] == 0 - || mu_isspace(r.data.str[i][6]))) { - *rec = mu_strdup(r.data.str[i]); + for (i = 0; i < reply.count; i++) { + if (memcmp(reply.data.str[i], "v=spf1", 6) == 0 + && (reply.data.str[i][6] == 0 + || mu_isspace(reply.data.str[i][6]))) { + *rec = mu_strdup(reply.data.str[i]); status = dns_success; break; } } - dns_reply_free(&r); + dns_reply_free(&reply); } return status; } @@ -422,7 +384,7 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount) struct in_addr ip; size_t i; int status; - struct dns_reply ptr_repl; + struct dns_reply ptr_reply; char **sv = NULL; size_t sc = 0; size_t sn = 0; @@ -430,14 +392,14 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount) if (!inet_aton(ipstr, &ip)) return dns_failure; - status = ptr_lookup(ip, &ptr_repl); + status = ptr_lookup(ip, &ptr_reply); if (status != dns_success) return status; - for (i = 0; i < ptr_repl.count; i++) { + for (i = 0; i < ptr_reply.count; i++) { struct dns_reply r; - status = a_lookup(ptr_repl.data.str[i], &r); + status = a_lookup(ptr_reply.data.str[i], &r); if (status == dns_success) { size_t k; @@ -446,14 +408,14 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount) if (sc == sn) sv = mu_2nrealloc(sv, &sn, sizeof(sv[0])); - sv[sc++] = mu_strdup(ptr_repl.data.str[i]); + sv[sc++] = mu_strdup(ptr_reply.data.str[i]); break; } } dns_reply_free(&r); } } - dns_reply_free(&ptr_repl); + dns_reply_free(&ptr_reply); if (sc == 0) { return dns_not_found; @@ -482,29 +444,29 @@ mf_to_dns_status(mf_status stat) } mf_status -getmx(const char *host, struct mxbuf *mxbuf) +getmx(const char *host, struct dns_reply *reply) { - return dns_to_mf_status(dns_get_mx_records(host, 1, mxbuf)); + return dns_to_mf_status(dns_get_mx_records(host, reply)); } mf_status -getmxip(char *host, GACOPYZ_UINT32_T **pipbuf, size_t *pcount) +getmxip(char *host, struct dns_reply *reply) { - struct mxbuf mxbuf; + struct dns_reply mxnames; mf_status mxstat; GACOPYZ_UINT32_T *ipbuf = NULL; size_t ipcount = 0; size_t ipmax = 0; size_t i; - mxstat = getmx(host, &mxbuf); + mxstat = getmx(host, &mxnames); if (mxstat != mf_success) return mxstat; ipcount = 0; - for (i = 0; i < mxbuf.mx_cnt; i++) { + for (i = 0; i < mxnames.count; i++) { struct dns_reply r; - dns_status stat = a_lookup(mxbuf.mx_buf[i], &r); + dns_status stat = a_lookup(mxnames.data.str[i], &r); if (stat == dns_success) { size_t n; for (n = 0; n < r.count; n++, ipcount++) { @@ -516,10 +478,10 @@ getmxip(char *host, GACOPYZ_UINT32_T **pipbuf, size_t *pcount) dns_reply_free(&r); } } - - mxbuf_free(&mxbuf); - *pipbuf = ipbuf; - *pcount = ipcount; + dns_reply_free(&mxnames); + reply->type = dns_reply_ip; + reply->count = ipcount; + reply->data.ip = ipbuf; return mf_success; } @@ -17,6 +17,8 @@ #ifndef __mfd_dns_h #define __mfd_dns_h +#define NELEMS(a) (sizeof(a) / sizeof((a)[0])) + typedef enum { dns_success, dns_not_found, @@ -24,37 +26,6 @@ typedef enum { dns_temp_failure, } dns_status; -#define NELEMS(c) (sizeof(c)/sizeof((c)[0])) - -/* Libresolv-related defines and DNS functions */ -#ifndef MAXPACKET -# define MAXPACKET 8192 /* max packet size used internally by BIND */ -#endif - -#define MXF_REUSE 0x02 - -struct mxbuf { - int mx_flags; - size_t mx_max; - char **mx_buf; - size_t mx_cnt; -}; - -void mxbuf_init(struct mxbuf *mxbuf, size_t n); -void mxbuf_free(struct mxbuf *mxbuf); - -int dns_str_is_ipv4(const char *addr); -dns_status dns_get_mx_records(const char *host, int maxdepth, - struct mxbuf *mxbuf); - -int dns_reverse_ipstr(const char *ipstr, char *revipstr); - -dns_status dns_resolve_ipstr(const char *ipstr, const char *domain, - char **hbuf); - -dns_status dns_resolve_hostname(const char *host, - char **ipbuf); - typedef enum { dns_reply_ip, dns_reply_str @@ -71,6 +42,16 @@ struct dns_reply { void dns_reply_free(struct dns_reply *r); +int dns_str_is_ipv4(const char *addr); +dns_status dns_get_mx_records(const char *host, struct dns_reply *repl); + +int dns_reverse_ipstr(const char *ipstr, char *revipstr); + +dns_status dns_resolve_ipstr(const char *ipstr, const char *domain, + char **hbuf); + +dns_status dns_resolve_hostname(const char *host, char **ipbuf); + dns_status a_lookup(const char *host, struct dns_reply *repl); dns_status ptr_lookup(struct in_addr ip, struct dns_reply *repl); diff --git a/lib/libmf.h b/lib/libmf.h index 5336b218..cf57e7a4 100644 --- a/lib/libmf.h +++ b/lib/libmf.h @@ -282,8 +282,8 @@ size_t format_time_str(FILE *fp, time_t timestamp); void dnsbase_init(); mf_status dns_to_mf_status(dns_status stat); dns_status mf_to_dns_status(mf_status stat); -mf_status getmx(const char *host, struct mxbuf *mxbuf); -mf_status getmxip(char *host, GACOPYZ_UINT32_T **ipbuf, size_t *pcount); +mf_status getmx(const char *host, struct dns_reply *repl); +mf_status getmxip(char *host, struct dns_reply *reply); mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf); mf_status resolve_ipstr(const char *ipstr, char **phbuf); mf_status resolve_hostname(const char *host, char **pipbuf); diff --git a/src/builtin/dns.bi b/src/builtin/dns.bi index c23aaf31..f63a2361 100644 --- a/src/builtin/dns.bi +++ b/src/builtin/dns.bi @@ -149,17 +149,16 @@ END MF_DEFUN(primitive_hasmx, NUMBER, STRING string) { - struct mxbuf mxbuf; + struct dns_reply repl; mf_status mxstat; - mxbuf.mx_flags = 0; - mxstat = getmx(string, &mxbuf); + mxstat = getmx(string, &repl); MF_ASSERT(mxstat == mf_success || mxstat == mf_not_found, mf_status_to_exception(mxstat), _("cannot get MX records for %s"), string); - mxbuf_free(&mxbuf); + dns_reply_free(&repl); if (mxstat == mf_success) { MF_RETURN(1); } @@ -170,12 +169,10 @@ END MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve) { mf_status mxstat; + struct dns_reply repl; if (MF_OPTVAL(no_resolve)) { - GACOPYZ_UINT32_T *ipbuf; - size_t ipcount; - - mxstat = getmxip(domain, &ipbuf, &ipcount); + mxstat = getmxip(domain, &repl); if (!mf_resolved(mxstat)) { MF_THROW(mf_status_to_exception(mxstat), _("cannot get MX records for %s"), domain); @@ -186,41 +183,37 @@ MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve) int i; MF_OBSTACK_BEGIN(); - for (i = 0; i < ipcount; i++) { + for (i = 0; i < repl.count; i++) { struct in_addr s; - s.s_addr = htonl(ipbuf[i]); + s.s_addr = htonl(repl.data.ip[i]); if (i > 0) MF_OBSTACK_1GROW(' '); MF_OBSTACK_GROW(inet_ntoa(s)); } - free(ipbuf); MF_OBSTACK_1GROW(0); + dns_reply_free(&repl); MF_RETURN_OBSTACK(); } } else { - struct mxbuf mxbuf; - - mxstat = getmx(domain, &mxbuf); + mxstat = getmx(domain, &repl); if (!mf_resolved(mxstat)) { - mxbuf_free(&mxbuf); MF_THROW(mf_status_to_exception(mxstat), _("cannot get MX records for %s"), domain); } if (mxstat == mf_not_found) { - mxbuf_free(&mxbuf); MF_RETURN(""); } else { int i; MF_OBSTACK_BEGIN(); - for (i = 0; i < mxbuf.mx_cnt; i++) { + for (i = 0; i < repl.count; i++) { if (i > 0) MF_OBSTACK_1GROW(' '); - MF_OBSTACK_GROW(mxbuf.mx_buf[i]); + MF_OBSTACK_GROW(repl.data.str[i]); } MF_OBSTACK_1GROW(0); - mxbuf_free(&mxbuf); + dns_reply_free(&repl); MF_RETURN_OBSTACK(); } } @@ -256,8 +249,7 @@ resolve_host(const char *string, unsigned long *ip) MF_DEFUN(primitive_ismx, NUMBER, STRING domain, STRING ipstr) { - GACOPYZ_UINT32_T *ipbuf; - size_t ipcount; + struct dns_reply reply; mf_status mxstat; unsigned long ip; int rc = 0; @@ -267,21 +259,20 @@ MF_DEFUN(primitive_ismx, NUMBER, STRING domain, STRING ipstr) _("cannot resolve host name %s"), ipstr); ip = ntohl(ip); - mxstat = getmxip(domain, &ipbuf, &ipcount); + mxstat = getmxip(domain, &reply); if (mxstat != mf_success) { MF_THROW(mf_status_to_exception(mxstat), _("cannot get MXs for %s"), domain); } - for (i = 0; i < ipcount; i++) { - if (ipbuf[i] == ip) { + for (i = 0; i < reply.count; i++) { + if (reply.data.ip[i] == ip) { rc = 1; break; } } - - free(ipbuf); + dns_reply_free(&reply); MF_RETURN(rc); } END diff --git a/src/callout.c b/src/callout.c index 633a33b7..1d46bc70 100644 --- a/src/callout.c +++ b/src/callout.c @@ -634,10 +634,10 @@ mf_status callout_mx(struct smtp_io_data *iop, const char *hostname, int *pcount) { int i; - struct mxbuf mxbuf; + struct dns_reply reply; mf_status rc, mxstat; - mxstat = getmx(hostname, &mxbuf); + mxstat = getmx(hostname, &reply); if (pcount) *pcount = 0; @@ -646,20 +646,20 @@ callout_mx(struct smtp_io_data *iop, const char *hostname, int *pcount) mu_debug(MF_SOURCE_CALLOUT, MU_DEBUG_TRACE1, ("Checking MX servers for %s", iop->email)); rc = mf_not_found; - for (i = 0; i < mxbuf.mx_cnt; i++) { - rc = callout_host(iop, mxbuf.mx_buf[i]); + for (i = 0; i < reply.count; i++) { + rc = callout_host(iop, reply.data.str[i]); if (mf_resolved(rc)) break; } if (pcount) - *pcount = mxbuf.mx_cnt; + *pcount = reply.count; + dns_reply_free(&reply); break; default: rc = mxstat; break; } - mxbuf_free(&mxbuf); return rc; } diff --git a/src/mailfromd.h b/src/mailfromd.h index 7f21e360..efea11ab 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -75,9 +75,6 @@ mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf); mf_status resolve_hostname(const char *host, char **pipbuf); -mf_status getmx(const char *ipstr, struct mxbuf *mxbuf); -mf_status getmxip(char *host, GACOPYZ_UINT32_T **ipbuf, size_t *pcount); - /* Debugging macros */ extern mu_debug_handle_t mfd_debug_handle; @@ -1594,7 +1594,7 @@ mx_match(eval_environ_t env, char *string, int (*matcher)(const char *name, void *data), void *data) { int rc = 0; - struct mxbuf mxbuf; + struct dns_reply reply; mf_status mxstat; char *p = strchr(string, '@'); @@ -1602,19 +1602,19 @@ mx_match(eval_environ_t env, char *string, p++; else p = string; - mxstat = getmx(p, &mxbuf); + mxstat = getmx(p, &reply); rc = 0; if (mxstat == mf_success) { int i; - for (i = 0; i < mxbuf.mx_cnt; i++) { - if (matcher(mxbuf.mx_buf[i], data)) { + for (i = 0; i < reply.count; i++) { + if (matcher(reply.data.str[i], data)) { rc = 1; break; } } } - mxbuf_free(&mxbuf); + dns_reply_free(&reply); if (!mf_resolved(mxstat)) env_throw(env, mf_status_to_exception(mxstat), @@ -659,7 +659,7 @@ static spf_term_result mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen) { unsigned long netmask = make_netmask(masklen); - struct mxbuf mxbuf; + struct dns_reply reply; size_t i; spf_term_result result = spf_term_nomatch; const char *domain_spec; @@ -673,14 +673,14 @@ mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen) ("MX domain_spec=%s, netmask=%lx", domain_spec, netmask)); - DNS_CATCH(dns_get_mx_records(domain_spec, 1, &mxbuf)); + DNS_CATCH(dns_get_mx_records(domain_spec, &reply)); - for (i = 0; i < mxbuf.mx_cnt; i++) { + for (i = 0; i < reply.count; i++) { spf_term_arg targ; spf_term_result res; targ.type = spf_arg_domain_spec; - targ.v.domain_spec = mxbuf.mx_buf[i]; + targ.v.domain_spec = reply.data.str[i]; res = mech_a(dat, &targ, masklen); if (res == spf_term_match) { result = res; @@ -688,7 +688,7 @@ mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen) } } - mxbuf_free(&mxbuf); + dns_reply_free(&reply); return result; } |