From 5e458871b31a8657118d88bccccf376d76c150fc Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 9 Jul 2010 18:19:04 +0400 Subject: [PATCH] * Make SURBL module to use rspamd dns module * Several fixes to DNS logic --- src/dns.c | 33 +++++-- src/dns.h | 1 + src/plugins/surbl.c | 19 ++-- src/spf.c | 197 ++++++++++++++++++++--------------------- test/rspamd_dns_test.c | 2 +- 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: -- 2.39.5