aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dns.c20
-rw-r--r--lib/dns.h2
-rw-r--r--src/builtin/dns.bi20
-rw-r--r--src/spf.c34
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/resolv.c255
7 files changed, 301 insertions, 39 deletions
diff --git a/lib/dns.c b/lib/dns.c
index a8fdf32a..f57eb7a9 100644
--- a/lib/dns.c
+++ b/lib/dns.c
@@ -86,8 +86,7 @@ get_state(void)
dnsbase_real_init();
return state;
}
-
-
+
int
dns_str_is_ipv4(const char *addr)
{
@@ -144,7 +143,7 @@ adns_to_dns_status(int e)
return dns_failure;
}
}
-
+
/* Return MX records for the given HOST. */
dns_status
dns_get_mx_records(const char *host, struct dns_reply *reply)
@@ -304,8 +303,9 @@ ptr_lookup(struct in_addr ip, struct dns_reply *reply)
adns_answer *ans;
char *name;
+ ip.s_addr = ntohl(ip.s_addr);
mu_asprintf(&name, "%s.in-addr.arpa", inet_ntoa(ip));
- rc = adns_synchronous(get_state(), name, adns_r_ptr,
+ rc = adns_synchronous(get_state(), name, adns_r_ptr_raw,
adns_qf_quoteok_cname|adns_qf_cname_loose,
&ans);
free(name);
@@ -379,7 +379,7 @@ spf_lookup(const char *domain, char **rec)
/* rfc4408, chapter 5.5 */
dns_status
-ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount)
+ptr_validate(const char *ipstr, struct dns_reply *reply)
{
struct in_addr ip;
size_t i;
@@ -420,11 +420,11 @@ ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount)
if (sc == 0) {
return dns_not_found;
}
- if (vcount)
- *vcount = sc;
- if (vnptr)
- *vnptr = sv;
- else
+ if (reply) {
+ reply->type = dns_reply_str;
+ reply->count = sc;
+ reply->data.str = sv;
+ } else
mu_argcv_free(sc, sv);
return dns_success;
diff --git a/lib/dns.h b/lib/dns.h
index bc30418c..fc0d4820 100644
--- a/lib/dns.h
+++ b/lib/dns.h
@@ -57,7 +57,7 @@ dns_status a_lookup(const char *host, struct dns_reply *repl);
dns_status ptr_lookup(struct in_addr ip, struct dns_reply *repl);
dns_status txt_lookup(const char *name, struct dns_reply *repl);
-dns_status ptr_validate(const char *ipstr, char ***vnptr, size_t *vcount);
+dns_status ptr_validate(const char *ipstr, struct dns_reply *repl);
dns_status spf_lookup(const char *domain, char **record);
diff --git a/src/builtin/dns.bi b/src/builtin/dns.bi
index f63a2361..4bde9676 100644
--- a/src/builtin/dns.bi
+++ b/src/builtin/dns.bi
@@ -169,10 +169,10 @@ END
MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve)
{
mf_status mxstat;
- struct dns_reply repl;
+ struct dns_reply reply;
if (MF_OPTVAL(no_resolve)) {
- mxstat = getmxip(domain, &repl);
+ mxstat = getmxip(domain, &reply);
if (!mf_resolved(mxstat)) {
MF_THROW(mf_status_to_exception(mxstat),
_("cannot get MX records for %s"), domain);
@@ -183,20 +183,20 @@ MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve)
int i;
MF_OBSTACK_BEGIN();
- for (i = 0; i < repl.count; i++) {
+ for (i = 0; i < reply.count; i++) {
struct in_addr s;
- s.s_addr = htonl(repl.data.ip[i]);
+ s.s_addr = htonl(reply.data.ip[i]);
if (i > 0)
MF_OBSTACK_1GROW(' ');
MF_OBSTACK_GROW(inet_ntoa(s));
}
MF_OBSTACK_1GROW(0);
- dns_reply_free(&repl);
+ dns_reply_free(&reply);
MF_RETURN_OBSTACK();
}
} else {
- mxstat = getmx(domain, &repl);
+ mxstat = getmx(domain, &reply);
if (!mf_resolved(mxstat)) {
MF_THROW(mf_status_to_exception(mxstat),
_("cannot get MX records for %s"), domain);
@@ -207,13 +207,13 @@ MF_DEFUN(getmx, STRING, STRING domain, OPTIONAL, NUMBER no_resolve)
int i;
MF_OBSTACK_BEGIN();
- for (i = 0; i < repl.count; i++) {
+ for (i = 0; i < reply.count; i++) {
if (i > 0)
MF_OBSTACK_1GROW(' ');
- MF_OBSTACK_GROW(repl.data.str[i]);
+ MF_OBSTACK_GROW(reply.data.str[i]);
}
MF_OBSTACK_1GROW(0);
- dns_reply_free(&repl);
+ dns_reply_free(&reply);
MF_RETURN_OBSTACK();
}
}
@@ -286,7 +286,7 @@ END
MF_DEFUN(ptr_validate, NUMBER, STRING s)
{
int rc, res;
- switch (rc = ptr_validate(s, NULL, NULL)) {
+ switch (rc = ptr_validate(s, NULL)) {
case dns_success:
res = 1;
break;
diff --git a/src/spf.c b/src/spf.c
index 0b570a04..87a158a9 100644
--- a/src/spf.c
+++ b/src/spf.c
@@ -334,32 +334,31 @@ spf_expand_do(struct spf_data *dat, int allow_exp, const char **pptr)
int rc;
size_t i;
char *name = NULL;
- char **vnames;
- size_t vcount;
- dns_status status = ptr_validate(dat->q.ipstr,
- &vnames, &vcount);
+ struct dns_reply reply;
+ dns_status status = ptr_validate(dat->q.ipstr, &reply);
if (status != dns_success)
return spf_transform(dat, "unknown", 0, pptr);
- for (i = 0; i < vcount; i++)
- if (strcasecmp(vnames[i], dat->q.domain) == 0) {
- name = vnames[i];
+ for (i = 0; i < reply.count; i++)
+ if (strcasecmp(reply.data.str[i], dat->q.domain) == 0) {
+ name = reply.data.str[i];
break;
}
if (!name) {
- for (i = 0; i < vcount; i++)
- if (domain_match(vnames[i], dat->q.domain)) {
- name = vnames[i];
+ for (i = 0; i < reply.count; i++)
+ if (domain_match(reply.data.str[i],
+ dat->q.domain)) {
+ name = reply.data.str[i];
break;
}
if (!name)
- name = vnames[0];
+ name = reply.data.str[0];
}
rc = spf_transform(dat, name, 0, pptr);
- mu_argcv_free(vcount, vnames);
+ dns_reply_free(&reply);
return rc;
}
@@ -698,8 +697,7 @@ mech_mx(spf_data *dat, spf_term_arg *arg, unsigned long masklen)
static spf_term_result
mech_ptr(spf_data *dat, spf_term_arg *arg, unsigned long masklen)
{
- char **vnames;
- size_t vcount;
+ struct dns_reply reply;
size_t i;
const char *domain_spec;
spf_term_result result = spf_term_nomatch;
@@ -709,14 +707,14 @@ mech_ptr(spf_data *dat, spf_term_arg *arg, unsigned long masklen)
else
domain_spec = dat->q.domain;
- DNS_CATCH(ptr_validate(dat->q.ipstr, &vnames, &vcount));
+ DNS_CATCH(ptr_validate(dat->q.ipstr, &reply));
- for (i = 0; i < vcount; i++)
- if (domain_match(vnames[i], domain_spec)) {
+ for (i = 0; i < reply.count; i++)
+ if (domain_match(reply.data.str[i], domain_spec)) {
result = spf_term_match;
break;
}
- mu_argcv_free(vcount, vnames);
+ dns_reply_free(&reply);
return result;
}
diff --git a/tests/.gitignore b/tests/.gitignore
index 33e4e9a5..fb1cd65c 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -5,3 +5,4 @@ status.mf
testsuite
testsuite.dir
testsuite.log
+resolv
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7def02b3..2f840fc3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -156,6 +156,14 @@ TESTSUITE_AT = \
TESTSUITE = $(srcdir)/testsuite
M4=m4
+noinst_PROGRAMS = \
+ resolv
+
+resolv_CPPFLAGS = -I$(top_srcdir)/lib
+resolv_LDADD = \
+ ../lib/libmf.a \
+ $(MAILUTILS_LIBS)
+
AUTOTEST = $(AUTOM4TE) --language=autotest
$(TESTSUITE): package.m4 $(TESTSUITE_AT)
$(AM_V_GEN)$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
diff --git a/tests/resolv.c b/tests/resolv.c
new file mode 100644
index 00000000..460b14b2
--- /dev/null
+++ b/tests/resolv.c
@@ -0,0 +1,255 @@
+#include <config.h>
+#include <stdio.h>
+#include <stdio.h>
+#include <assert.h>
+#include <mailutils/mailutils.h>
+#include "dns.h"
+
+void
+status_print(dns_status status)
+{
+ switch (status) {
+ case dns_success:
+ printf("OK");
+ break;
+ case dns_not_found:
+ printf("NOTFOUND");
+ break;
+ case dns_failure:
+ printf("FAILURE");
+ break;
+ case dns_temp_failure:
+ printf("TEMPFAIL");
+ break;
+ default:
+ mu_error("%s:%d: unrecognized status", __FILE__, __LINE__);
+ abort();
+ }
+ putchar('\n');
+}
+
+static int
+hostname_cmp(const void *a, const void *b)
+{
+ return strcmp(*(const char**) a, *(const char**) b);
+}
+
+void
+reply_print_str(struct dns_reply *reply)
+{
+ int i;
+
+ qsort(reply->data.str, reply->count, sizeof reply->data.str[0],
+ hostname_cmp);
+ for (i = 0; i < reply->count; i++) {
+ printf("%s\n", reply->data.str[i]);
+ }
+}
+
+static int
+ipaddr_cmp(const void *a, const void *b)
+{
+ GACOPYZ_UINT32_T ipa = ntohl(*(GACOPYZ_UINT32_T*)a);
+ GACOPYZ_UINT32_T ipb = ntohl(*(GACOPYZ_UINT32_T*)b);
+ if (ipa < ipb)
+ return -1;
+ if (ipa > ipb)
+ return 1;
+ return 0;
+}
+
+void
+reply_print_ip(struct dns_reply *reply)
+{
+ int i;
+
+ qsort(reply->data.ip, reply->count, sizeof reply->data.ip[0],
+ ipaddr_cmp);
+ for (i = 0; i < reply->count; i++) {
+ struct in_addr ip;
+ ip.s_addr = reply->data.ip[i];
+ printf("%s\n", inet_ntoa(ip));
+ }
+}
+
+void
+reply_print(struct dns_reply *reply)
+{
+ switch (reply->type) {
+ case dns_reply_str:
+ reply_print_str(reply);
+ break;
+ case dns_reply_ip:
+ reply_print_ip(reply);
+ break;
+ default:
+ mu_error("%s:%d: unrecognized reply type", __FILE__, __LINE__);
+ abort();
+ }
+}
+
+static int
+res_a(int argc, char **argv)
+{
+ dns_status status;
+ struct dns_reply reply;
+
+ assert(argc == 1);
+ status = a_lookup(argv[0], &reply);
+ status_print(status);
+ if (status == dns_success) {
+ reply_print(&reply);
+ dns_reply_free(&reply);
+ }
+ return 0;
+}
+
+static int
+res_ptr(int argc, char **argv)
+{
+ dns_status status;
+ struct dns_reply reply;
+ struct in_addr in;
+
+ assert(argc == 1);
+ if (!inet_aton(argv[0], &in)) {
+ mu_error("%s: can't convert address", argv[0]);
+ return 1;
+ }
+
+ status = ptr_lookup(in, &reply);
+ status_print(status);
+ if (status == dns_success) {
+ reply_print(&reply);
+ dns_reply_free(&reply);
+ }
+ return 0;
+}
+
+static int
+res_ptr_val(int argc, char **argv)
+{
+ dns_status status;
+ struct dns_reply reply;
+
+ assert(argc == 1);
+ status = ptr_validate(argv[0], &reply);
+ status_print(status);
+ if (status == dns_success) {
+ reply_print(&reply);
+ dns_reply_free(&reply);
+ }
+ return 0;
+}
+
+static int
+res_txt(int argc, char **argv)
+{
+ dns_status status;
+ struct dns_reply reply;
+
+ assert(argc == 1);
+ status = txt_lookup(argv[0], &reply);
+ status_print(status);
+ if (status == dns_success) {
+ reply_print(&reply);
+ dns_reply_free(&reply);
+ }
+ return 0;
+}
+
+static int
+res_mx(int argc, char **argv)
+{
+ dns_status status;
+ struct dns_reply reply;
+
+ assert(argc == 1);
+ status = dns_get_mx_records(argv[0], &reply);
+ status_print(status);
+ if (status == dns_success) {
+ reply_print(&reply);
+ dns_reply_free(&reply);
+ }
+ return 0;
+}
+
+static int
+res_spf(int argc, char **argv)
+{
+ dns_status status;
+ char *record;
+
+ status = spf_lookup(argv[0], &record);
+ status_print(status);
+ if (status == dns_success) {
+ printf("%s\n", record);
+ free(record);
+ }
+ return 0;
+}
+
+static int
+res_host(int argc, char **argv)
+{
+ dns_status status;
+ char *str;
+
+ assert(argc == 1 || argc == 2);
+ status = dns_resolve_ipstr(argv[0], argv[1], &str);
+ status_print(status);
+ if (status == dns_success) {
+ printf("%s\n", str);
+ free(str);
+ }
+ return 0;
+}
+
+static int
+res_ip(int argc, char **argv)
+{
+ dns_status status;
+ char *str;
+
+ assert(argc == 1);
+ status = dns_resolve_hostname(argv[0], &str);
+ status_print(status);
+ if (status == dns_success) {
+ printf("%s\n", str);
+ free(str);
+ }
+ return 0;
+}
+
+struct mode {
+ char const *name;
+ int (*func)(int, char **);
+};
+
+struct mode mode[] = {
+ { "host", res_host },
+ { "ip", res_ip },
+ { "a", res_a },
+ { "ptr", res_ptr },
+ { "txt", res_txt },
+ { "mx", res_mx },
+ { "ptr_val", res_ptr_val },
+ { "spf", res_spf },
+ { NULL }
+};
+
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ mu_set_program_name(argv[0]);
+ mu_stdstream_setup(MU_STDSTREAM_RESET_NONE);
+ assert(argc > 2);
+ for (i = 0; mode[i].name; i++) {
+ if (strcmp(mode[i].name, argv[1]) == 0)
+ exit(mode[i].func(argc - 2, argv + 2));
+ }
+ mu_error("%s:%d: unrecognized mode", __FILE__, __LINE__);
+ abort();
+}

Return to:

Send suggestions and report system problems to the System administrator.