aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dns.c154
-rw-r--r--lib/dns.h43
-rw-r--r--lib/libmf.h4
-rw-r--r--src/builtin/dns.bi43
-rw-r--r--src/callout.c12
-rw-r--r--src/mailfromd.h3
-rw-r--r--src/prog.c10
-rw-r--r--src/spf.c10
8 files changed, 105 insertions, 174 deletions
diff --git a/lib/dns.c b/lib/dns.c
index 5d428e50..a8fdf32a 100644
--- a/lib/dns.c
+++ b/lib/dns.c
@@ -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;
}
diff --git a/lib/dns.h b/lib/dns.h
index 0b5ca8ec..bc30418c 100644
--- a/lib/dns.h
+++ b/lib/dns.h
@@ -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;
diff --git a/src/prog.c b/src/prog.c
index 3e90472f..932efd25 100644
--- a/src/prog.c
+++ b/src/prog.c
@@ -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),
diff --git a/src/spf.c b/src/spf.c
index 05fbd538..0b570a04 100644
--- a/src/spf.c
+++ b/src/spf.c
@@ -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;
}

Return to:

Send suggestions and report system problems to the System administrator.