aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dns.c33
-rw-r--r--src/dns.h1
-rw-r--r--src/plugins/surbl.c19
-rw-r--r--src/spf.c197
-rw-r--r--test/rspamd_dns_test.c2
5 files changed, 130 insertions, 122 deletions
diff --git a/src/dns.c b/src/dns.c
index dcbde4afe..e9f057b5e 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -409,8 +409,8 @@ format_dns_name (struct rspamd_dns_request *req, const char *name, guint namelen
}
}
/* Termination label */
- *(++pos) = '\0';
- req->pos += pos - (req->packet + req->pos);
+ *pos = '\0';
+ req->pos += pos - (req->packet + req->pos) + 1;
if (table != NULL) {
g_list_free (table);
}
@@ -601,6 +601,7 @@ dns_request_reply_cmp (struct rspamd_dns_request *req, guint8 *in, int len)
}
/* This may be compressed, so we need to decompress it */
if (len1 & DNS_COMPRESSION_BITS) {
+ memcpy (&len1, p, sizeof (guint16));
l1 = decompress_label (in, &len1);
decompressed ++;
l1 ++;
@@ -611,6 +612,7 @@ dns_request_reply_cmp (struct rspamd_dns_request *req, guint8 *in, int len)
p += len1;
}
if (len2 & DNS_COMPRESSION_BITS) {
+ memcpy (&len2, p, sizeof (guint16));
l2 = decompress_label (req->packet, &len2);
decompressed ++;
l2 ++;
@@ -796,8 +798,8 @@ dns_parse_rr (guint8 *in, union rspamd_reply_element *elt, guint8 **pos, struct
p += datalen;
}
else {
- elt->txt.data = memory_pool_alloc (rep->request->pool, datalen + 1);
- memcpy (elt->txt.data, p, datalen);
+ elt->txt.data = memory_pool_alloc (rep->request->pool, datalen);
+ memcpy (elt->txt.data, p + 1, datalen - 1);
*(elt->txt.data + datalen) = '\0';
}
break;
@@ -806,8 +808,8 @@ dns_parse_rr (guint8 *in, union rspamd_reply_element *elt, guint8 **pos, struct
p += datalen;
}
else {
- elt->spf.data = memory_pool_alloc (rep->request->pool, datalen + 1);
- memcpy (elt->spf.data, p, datalen);
+ elt->spf.data = memory_pool_alloc (rep->request->pool, datalen);
+ memcpy (elt->spf.data, p + 1, datalen - 1);
*(elt->spf.data + datalen) = '\0';
}
break;
@@ -924,7 +926,7 @@ dns_timer_cb (int fd, short what, void *arg)
/* Retransmit dns request */
req->retransmits ++;
if (req->retransmits >= req->resolver->max_retransmits) {
- msg_err ("maximum number of retransmits expired");
+ msg_err ("maximum number of retransmits expired for resolving %s of type %s", req->requested_name, dns_strtype (req->type));
event_del (&req->timer_event);
rep = memory_pool_alloc0 (req->pool, sizeof (struct rspamd_dns_reply));
rep->request = req;
@@ -985,7 +987,7 @@ dns_retransmit_handler (int fd, short what, void *arg)
/* Retransmit dns request */
req->retransmits ++;
if (req->retransmits >= req->resolver->max_retransmits) {
- msg_err ("maximum number of retransmits expired");
+ msg_err ("maximum number of retransmits expired for %s", req->requested_name);
event_del (&req->io_event);
rep = memory_pool_alloc0 (req->pool, sizeof (struct rspamd_dns_reply));
rep->request = req;
@@ -1258,3 +1260,18 @@ dns_strerror (enum dns_rcode rcode)
}
return dns_rcodes[rcode];
}
+
+static char dns_types[6][16] = {
+ [DNS_REQUEST_A] = "A request",
+ [DNS_REQUEST_PTR] = "PTR request",
+ [DNS_REQUEST_MX] = "MX request",
+ [DNS_REQUEST_TXT] = "TXT request",
+ [DNS_REQUEST_SRV] = "SRV request",
+ [DNS_REQUEST_SPF] = "SPF request"
+};
+
+const char *
+dns_strtype (enum rspamd_request_type type)
+{
+ return dns_types[type];
+}
diff --git a/src/dns.h b/src/dns.h
index 338daf033..c0a79a6b0 100644
--- a/src/dns.h
+++ b/src/dns.h
@@ -226,5 +226,6 @@ gboolean make_dns_request (struct rspamd_dns_resolver *resolver,
struct rspamd_async_session *session, memory_pool_t *pool, dns_callback_type cb,
gpointer ud, enum rspamd_request_type type, ...);
const char *dns_strerror (enum dns_rcode rcode);
+const char *dns_strtype (enum rspamd_request_type type);
#endif
diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c
index f50bd8976..09c382b7f 100644
--- a/src/plugins/surbl.c
+++ b/src/plugins/surbl.c
@@ -46,7 +46,7 @@
#include "../message.h"
#include "../view.h"
#include "../map.h"
-#include "../evdns/evdns.h"
+#include "../dns.h"
#include "surbl.h"
@@ -54,7 +54,7 @@ static struct surbl_ctx *surbl_module_ctx = NULL;
static int surbl_filter (struct worker_task *task);
static void surbl_test_url (struct worker_task *task, void *user_data);
-static void dns_callback (int result, char type, int count, int ttl, void *addresses, void *data);
+static void dns_callback (struct rspamd_dns_reply *reply, gpointer arg);
static void process_dns_results (struct worker_task *task, struct suffix_item *suffix, char *url, uint32_t addr);
static int urls_command_handler (struct worker_task *task);
@@ -449,9 +449,8 @@ make_surbl_requests (struct uri *url, struct worker_task *task, GTree * tree, st
param->suffix = suffix;
param->host_resolve = memory_pool_strdup (task->task_pool, surbl_req);
debug_task ("send surbl dns request %s", surbl_req);
- if (evdns_resolve_ipv4 (surbl_req, DNS_QUERY_NO_SEARCH, dns_callback, (void *)param) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, dns_callback, (void *)param, DNS_REQUEST_A, surbl_req)) {
param->task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) dns_callback, NULL, TRUE);
}
}
else {
@@ -508,16 +507,18 @@ process_dns_results (struct worker_task *task, struct suffix_item *suffix, char
}
static void
-dns_callback (int result, char type, int count, int ttl, void *addresses, void *data)
+dns_callback (struct rspamd_dns_reply *reply, gpointer arg)
{
- struct dns_param *param = (struct dns_param *)data;
+ struct dns_param *param = (struct dns_param *)arg;
struct worker_task *task = param->task;
+ union rspamd_reply_element *elt;
debug_task ("in surbl request callback");
/* If we have result from DNS server, this url exists in SURBL, so increase score */
- if (result == DNS_ERR_NONE && type == DNS_IPv4_A) {
+ if (reply->code == DNS_RC_NOERROR && reply->elements) {
msg_info ("<%s> domain [%s] is in surbl %s", param->task->message_id, param->host_resolve, param->suffix->suffix);
- process_dns_results (param->task, param->suffix, param->host_resolve, (uint32_t) (((in_addr_t *) addresses)[0]));
+ elt = reply->elements->data;
+ process_dns_results (param->task, param->suffix, param->host_resolve, (uint32_t)elt->a.addr[0].s_addr);
}
else {
debug_task ("<%s> domain [%s] is not in surbl %s", param->task->message_id, param->host_resolve, param->suffix->suffix);
@@ -529,8 +530,6 @@ dns_callback (int result, char type, int count, int ttl, void *addresses, void *
param->task->save.saved = 1;
process_filters (param->task);
}
- remove_forced_event (param->task->s, (event_finalizer_t) dns_callback);
-
}
static void
diff --git a/src/spf.c b/src/spf.c
index 0cc1bf53e..3f735457a 100644
--- a/src/spf.c
+++ b/src/spf.c
@@ -23,7 +23,7 @@
*/
#include "config.h"
-#include "evdns/evdns.h"
+#include "dns.h"
#include "spf.h"
#include "main.h"
#include "message.h"
@@ -228,101 +228,103 @@ parse_spf_hostmask (struct worker_task *task, const char *begin, struct spf_addr
}
static void
-spf_record_dns_callback (int result, char type, int count, int ttl, void *addresses, void *data)
+spf_record_dns_callback (struct rspamd_dns_reply *reply, gpointer arg)
{
- struct spf_dns_cb *cb = data;
+ struct spf_dns_cb *cb = arg;
char *begin;
- struct evdns_mx *mx;
- GList *tmp = NULL, *elt, *last;
+ union rspamd_reply_element *elt_data;
+ GList *tmp = NULL, *tmp1, *elt, *last;
+ struct worker_task *task;
- if (result == DNS_ERR_NONE) {
- if (addresses != NULL) {
+ task = cb->rec->task;
+
+ if (reply->code == DNS_RC_NOERROR) {
+ if (reply->elements != NULL) {
/* Add all logic for all DNS states here */
- switch (cb->cur_action) {
+ elt = reply->elements;
+ while (elt) {
+ elt_data = elt->data;
+ switch (cb->cur_action) {
case SPF_RESOLVE_MX:
- if (type == DNS_MX) {
- mx = (struct evdns_mx *)addresses;
+ if (reply->type == DNS_REQUEST_MX) {
/* Now resolve A record for this MX */
- if (evdns_resolve_ipv4 (mx->host, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
- return;
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_A, elt_data->mx.name)) {
+ task->save.saved++;
}
}
- else if (type == DNS_IPv4_A) {
+ else if (reply->type == DNS_REQUEST_A) {
/* XXX: process only one record */
- cb->addr->addr = ntohl (*((uint32_t *)addresses));
+ cb->addr->addr = ntohl (elt_data->a.addr[0].s_addr);
}
break;
case SPF_RESOLVE_A:
- if (type == DNS_IPv4_A) {
+ if (reply->type == DNS_REQUEST_A) {
/* XXX: process only one record */
- cb->addr->addr = ntohl (*((uint32_t *)addresses));
+ cb->addr->addr = ntohl (elt_data->a.addr[0].s_addr);
}
break;
case SPF_RESOLVE_PTR:
break;
case SPF_RESOLVE_REDIRECT:
- if (type == DNS_TXT) {
- if (addresses != NULL) {
- begin = *(char **)addresses;
+ if (reply->type == DNS_REQUEST_TXT) {
+ begin = elt_data->txt.data;
- if (!cb->in_include && cb->rec->addrs) {
- g_list_free (cb->rec->addrs);
- cb->rec->addrs = NULL;
- }
- start_spf_parse (cb->rec, begin);
+ if (!cb->in_include && cb->rec->addrs) {
+ g_list_free (cb->rec->addrs);
+ cb->rec->addrs = NULL;
}
+ start_spf_parse (cb->rec, begin);
+
}
break;
case SPF_RESOLVE_INCLUDE:
- if (type == DNS_TXT) {
- if (addresses != NULL) {
- begin = *(char **)addresses;
- if (cb->rec->addrs) {
- tmp = cb->rec->addrs;
- cb->rec->addrs = NULL;
- }
- cb->rec->in_include = TRUE;
- start_spf_parse (cb->rec, begin);
- cb->rec->in_include = FALSE;
-
- if (tmp) {
- elt = g_list_find (tmp, cb->addr);
- if (elt) {
- /* Insert new list in place of include element */
- last = g_list_last (cb->rec->addrs);
+ if (reply->type == DNS_REQUEST_TXT) {
+ begin = elt_data->txt.data;
+ if (cb->rec->addrs) {
+ tmp = cb->rec->addrs;
+ cb->rec->addrs = NULL;
+ }
+ cb->rec->in_include = TRUE;
+ start_spf_parse (cb->rec, begin);
+ cb->rec->in_include = FALSE;
+
+ if (tmp) {
+ tmp1 = g_list_find (tmp, cb->addr);
+ if (tmp1) {
+ /* Insert new list in place of include element */
+ last = g_list_last (cb->rec->addrs);
+
+ if (tmp1->prev == NULL && tmp1->next == NULL) {
+ g_list_free1 (tmp1);
+ }
+ else {
- if (elt->prev == NULL && elt->next == NULL) {
- g_list_free1 (elt);
+ if (tmp1->prev) {
+ tmp1->prev->next = cb->rec->addrs;
}
else {
-
- if (elt->prev) {
- elt->prev->next = cb->rec->addrs;
- }
- else {
- /* Elt is the first element, so we need to shift temporary list */
- tmp = elt->next;
- tmp->prev = NULL;
- }
- if (elt->next) {
- elt->next->prev = last;
- if (last != NULL) {
- last->next = elt->next;
- }
- }
-
- if (cb->rec->addrs != NULL) {
- cb->rec->addrs->prev = elt->prev;
+ /* Elt is the first element, so we need to shift temporary list */
+ tmp = tmp1->next;
+ tmp->prev = NULL;
+ }
+ if (tmp1->next) {
+ tmp1->next->prev = last;
+ if (last != NULL) {
+ last->next = tmp1->next;
}
+ }
- /* Shift temporary list */
- while (tmp->prev) {
- tmp = tmp->prev;
- }
+ if (cb->rec->addrs != NULL) {
+ cb->rec->addrs->prev = tmp1->prev;
+ }
- cb->rec->addrs = tmp;
- g_list_free1 (elt);
+ /* Shift temporary list */
+ while (tmp->prev) {
+ tmp = tmp->prev;
}
+
+ cb->rec->addrs = tmp;
+ g_list_free1 (tmp1);
}
}
}
@@ -331,29 +333,31 @@ spf_record_dns_callback (int result, char type, int count, int ttl, void *addres
case SPF_RESOLVE_EXP:
break;
case SPF_RESOLVE_EXISTS:
- if (type == DNS_IPv4_A) {
+ if (reply->type == DNS_REQUEST_A) {
/* If specified address resolves, we can accept connection from every IP */
cb->addr->addr = ntohl (INADDR_ANY);
cb->addr->mask = 0;
}
break;
+ }
+ elt = g_list_next (elt);
}
}
}
- else if (result == DNS_ERR_NOTEXIST) {
+ else if (reply->code == DNS_RC_NXDOMAIN) {
switch (cb->cur_action) {
case SPF_RESOLVE_MX:
- if (type == DNS_MX) {
+ if (reply->type == DNS_REQUEST_MX) {
msg_info ("cannot find MX record for %s", cb->rec->cur_domain);
cb->addr->addr = ntohl (INADDR_NONE);
}
- else if (type == DNS_IPv4_A) {
+ else if (reply->type != DNS_REQUEST_MX) {
msg_info ("cannot resolve MX record for %s", cb->rec->cur_domain);
cb->addr->addr = ntohl (INADDR_NONE);
}
break;
case SPF_RESOLVE_A:
- if (type == DNS_IPv4_A) {
+ if (reply->type == DNS_REQUEST_A) {
/* XXX: process only one record */
cb->addr->addr = ntohl (INADDR_NONE);
}
@@ -382,8 +386,6 @@ spf_record_dns_callback (int result, char type, int count, int ttl, void *addres
cb->rec->addrs = NULL;
}
}
- remove_forced_event (cb->rec->task->s, (event_finalizer_t) spf_record_dns_callback);
-
}
static gboolean
@@ -411,10 +413,8 @@ parse_spf_a (struct worker_task *task, const char *begin, struct spf_record *rec
cb->addr = addr;
cb->cur_action = SPF_RESOLVE_A;
cb->in_include = rec->in_include;
-
- if (evdns_resolve_ipv4 (host, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_A, host)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_record_dns_callback, NULL, TRUE);
return TRUE;
}
@@ -459,10 +459,8 @@ parse_spf_mx (struct worker_task *task, const char *begin, struct spf_record *re
cb->addr = addr;
cb->cur_action = SPF_RESOLVE_MX;
cb->in_include = rec->in_include;
-
- if (evdns_resolve_mx (host, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_MX, host)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_record_dns_callback, NULL, TRUE);
return TRUE;
}
@@ -516,14 +514,13 @@ parse_spf_include (struct worker_task *task, const char *begin, struct spf_recor
cb->cur_action = SPF_RESOLVE_INCLUDE;
cb->in_include = rec->in_include;
domain = memory_pool_strdup (task->task_pool, begin);
-
- if (evdns_resolve_txt (domain, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_TXT, domain)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_record_dns_callback, NULL, TRUE);
return TRUE;
}
+
return FALSE;
}
@@ -556,10 +553,8 @@ parse_spf_redirect (struct worker_task *task, const char *begin, struct spf_reco
cb->cur_action = SPF_RESOLVE_REDIRECT;
cb->in_include = rec->in_include;
domain = memory_pool_strdup (task->task_pool, begin);
-
- if (evdns_resolve_txt (domain, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_TXT, domain)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_record_dns_callback, NULL, TRUE);
return TRUE;
}
@@ -589,9 +584,8 @@ parse_spf_exists (struct worker_task *task, const char *begin, struct spf_record
cb->in_include = rec->in_include;
host = memory_pool_strdup (task->task_pool, begin);
- if (evdns_resolve_ipv4 (host, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_A, host)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_record_dns_callback, NULL, TRUE);
return TRUE;
}
@@ -1062,15 +1056,18 @@ start_spf_parse (struct spf_record *rec, char *begin)
}
static void
-spf_dns_callback (int result, char type, int count, int ttl, void *addresses, void *data)
+spf_dns_callback (struct rspamd_dns_reply *reply, gpointer arg)
{
- struct spf_record *rec = data;
- char *begin;
-
- if (result == DNS_ERR_NONE && type == DNS_TXT) {
- if (addresses != NULL) {
- begin = *(char **)addresses;
- start_spf_parse (rec, begin);
+ struct spf_record *rec = arg;
+ union rspamd_reply_element *elt;
+ GList *cur;
+
+ if (reply->code == DNS_RC_NOERROR) {
+ cur = reply->elements;
+ while (cur) {
+ elt = cur->data;
+ start_spf_parse (rec, elt->txt.data);
+ cur = g_list_next (cur);
}
}
@@ -1078,8 +1075,6 @@ spf_dns_callback (int result, char type, int count, int ttl, void *addresses, vo
if (rec->task->save.saved == 0 && rec->callback) {
rec->callback (rec, rec->task);
}
- remove_forced_event (rec->task->s, (event_finalizer_t) spf_dns_callback);
-
}
@@ -1108,10 +1103,8 @@ resolve_spf (struct worker_task *task, spf_cb_t callback)
}
rec->sender_domain = rec->cur_domain;
- if (evdns_resolve_txt (rec->cur_domain, DNS_QUERY_NO_SEARCH, spf_dns_callback, (void *)rec) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_dns_callback, (void *)rec, DNS_REQUEST_TXT, rec->cur_domain)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_dns_callback, NULL, TRUE);
-
return TRUE;
}
}
@@ -1138,10 +1131,8 @@ resolve_spf (struct worker_task *task, spf_cb_t callback)
*domain = '\0';
}
rec->sender_domain = rec->cur_domain;
- if (evdns_resolve_txt (rec->cur_domain, DNS_QUERY_NO_SEARCH, spf_dns_callback, (void *)rec) == 0) {
+ if (make_dns_request (task->resolver, task->s, task->task_pool, spf_dns_callback, (void *)rec, DNS_REQUEST_TXT, rec->cur_domain)) {
task->save.saved++;
- register_async_event (task->s, (event_finalizer_t) spf_dns_callback, NULL, TRUE);
-
return TRUE;
}
}
diff --git a/test/rspamd_dns_test.c b/test/rspamd_dns_test.c
index a6ffcc79a..13d276313 100644
--- a/test/rspamd_dns_test.c
+++ b/test/rspamd_dns_test.c
@@ -33,7 +33,7 @@ test_dns_cb (struct rspamd_dns_reply *reply, gpointer arg)
msg_debug ("got spf %s", elt->spf.data);
break;
case DNS_REQUEST_SRV:
- msg_debug ("got srv pri:%d, weight:%d, port: %d, target: %s", elt->srv.weight,
+ msg_debug ("got srv pri: %d, weight: %d, port: %d, target: %s", elt->srv.weight,
elt->srv.priority, elt->srv.port, elt->srv.target);
break;
case DNS_REQUEST_MX: