}
}
/* 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);
}
}
/* 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 ++;
p += len1;
}
if (len2 & DNS_COMPRESSION_BITS) {
+ memcpy (&len2, p, sizeof (guint16));
l2 = decompress_label (req->packet, &len2);
decompressed ++;
l2 ++;
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;
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;
/* 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;
/* 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;
}
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];
+}
#include "../message.h"
#include "../view.h"
#include "../map.h"
-#include "../evdns/evdns.h"
+#include "../dns.h"
#include "surbl.h"
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);
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 {
}
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);
param->task->save.saved = 1;
process_filters (param->task);
}
- remove_forced_event (param->task->s, (event_finalizer_t) dns_callback);
-
}
static void
*/
#include "config.h"
-#include "evdns/evdns.h"
+#include "dns.h"
#include "spf.h"
#include "main.h"
#include "message.h"
}
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);
}
}
}
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);
}
cb->rec->addrs = NULL;
}
}
- remove_forced_event (cb->rec->task->s, (event_finalizer_t) spf_record_dns_callback);
-
}
static gboolean
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;
}
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;
}
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;
}
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;
}
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;
}
}
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);
}
}
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);
-
}
}
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;
}
}
*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;
}
}