@@ -487,7 +487,7 @@ ENDIF(ENABLE_PERL MATCHES "ON") | |||
ADD_SUBDIRECTORY(src/lua) | |||
ADD_SUBDIRECTORY(src/json) | |||
ADD_SUBDIRECTORY(src/evdns) | |||
# ADD_SUBDIRECTORY(src/evdns) | |||
ADD_SUBDIRECTORY(src/plugins/custom) | |||
SET(TOKENIZERSSRC src/tokenizers/tokenizers.c | |||
@@ -594,7 +594,7 @@ TARGET_LINK_LIBRARIES(rspamd "${LUA_LIBRARY}") | |||
IF(LIBJUDY_LIBRARY) | |||
TARGET_LINK_LIBRARIES(rspamd Judy) | |||
ENDIF(LIBJUDY_LIBRARY) | |||
TARGET_LINK_LIBRARIES(rspamd rspamd_evdns) | |||
# TARGET_LINK_LIBRARIES(rspamd rspamd_evdns) | |||
TARGET_LINK_LIBRARIES(rspamd event) | |||
TARGET_LINK_LIBRARIES(rspamd rspamd_json) | |||
TARGET_LINK_LIBRARIES(rspamd ${CMAKE_REQUIRED_LIBRARIES}) |
@@ -560,6 +560,7 @@ dns_fin_cb (gpointer arg) | |||
{ | |||
struct rspamd_dns_request *req = arg; | |||
event_del (&req->timer_event); | |||
g_hash_table_remove (req->resolver->requests, GUINT_TO_POINTER (req->id)); | |||
} | |||
@@ -735,7 +736,6 @@ dns_parse_rr (guint8 *in, union rspamd_reply_element *elt, guint8 **pos, struct | |||
{ | |||
guint8 *p = *pos; | |||
guint16 type, datalen; | |||
guint16 addrcount; | |||
/* Skip the whole name */ | |||
if (! dns_parse_labels (in, NULL, &p, rep, remain, FALSE)) { | |||
@@ -759,10 +759,8 @@ dns_parse_rr (guint8 *in, union rspamd_reply_element *elt, guint8 **pos, struct | |||
} | |||
else { | |||
if (!(datalen & 0x3) && datalen <= *remain) { | |||
addrcount = MIN (elt->a.addrcount + (datalen >> 2), MAX_ADDRS); | |||
memcpy (&elt->a.addr[elt->a.addrcount], p, addrcount * sizeof (struct in_addr)); | |||
memcpy (&elt->a.addr[0], p, sizeof (struct in_addr)); | |||
p += datalen; | |||
elt->a.addrcount += addrcount; | |||
} | |||
else { | |||
msg_info ("corrupted A record"); |
@@ -26,7 +26,7 @@ | |||
#include "lua_common.h" | |||
#include "../message.h" | |||
#include "../expressions.h" | |||
#include "../evdns/evdns.h" | |||
#include "../dns.h" | |||
/* Task methods */ | |||
LUA_FUNCTION_DEF (task, get_message); | |||
@@ -37,6 +37,7 @@ LUA_FUNCTION_DEF (task, get_raw_headers); | |||
LUA_FUNCTION_DEF (task, get_received_headers); | |||
LUA_FUNCTION_DEF (task, resolve_dns_a); | |||
LUA_FUNCTION_DEF (task, resolve_dns_ptr); | |||
LUA_FUNCTION_DEF (task, resolve_dns_txt); | |||
LUA_FUNCTION_DEF (task, call_rspamd_function); | |||
LUA_FUNCTION_DEF (task, get_recipients); | |||
LUA_FUNCTION_DEF (task, get_from); | |||
@@ -54,6 +55,7 @@ static const struct luaL_reg tasklib_m[] = { | |||
LUA_INTERFACE_DEF (task, get_received_headers), | |||
LUA_INTERFACE_DEF (task, resolve_dns_a), | |||
LUA_INTERFACE_DEF (task, resolve_dns_ptr), | |||
LUA_INTERFACE_DEF (task, resolve_dns_txt), | |||
LUA_INTERFACE_DEF (task, call_rspamd_function), | |||
LUA_INTERFACE_DEF (task, get_recipients), | |||
LUA_INTERFACE_DEF (task, get_from), | |||
@@ -238,12 +240,14 @@ struct lua_dns_callback_data { | |||
}; | |||
static void | |||
lua_dns_callback (int result, char type, int count, int ttl, void *addresses, void *arg) | |||
lua_dns_callback (struct rspamd_dns_reply *reply, gpointer arg) | |||
{ | |||
struct lua_dns_callback_data *cd = arg; | |||
int i; | |||
int i = 0; | |||
struct in_addr ina; | |||
struct worker_task **ptask; | |||
union rspamd_reply_element *elt; | |||
GList *cur; | |||
lua_getglobal (cd->L, cd->callback); | |||
ptask = lua_newuserdata (cd->L, sizeof (struct worker_task *)); | |||
@@ -252,25 +256,41 @@ lua_dns_callback (int result, char type, int count, int ttl, void *addresses, vo | |||
*ptask = cd->task; | |||
lua_pushstring (cd->L, cd->to_resolve); | |||
if (result == DNS_ERR_NONE) { | |||
if (type == DNS_IPv4_A) { | |||
if (reply->code == DNS_RC_NOERROR) { | |||
if (reply->type == DNS_REQUEST_A) { | |||
lua_newtable (cd->L); | |||
for (i = 1; i <= count; i++) { | |||
memcpy (&ina.s_addr, ((in_addr_t *) addresses) + i - 1, sizeof (in_addr_t)); | |||
cur = reply->elements; | |||
while (cur) { | |||
elt = cur->data; | |||
memcpy (&ina, elt->a.addr, sizeof (in_addr_t)); | |||
/* Actually this copy memory, so using of inet_ntoa is valid */ | |||
lua_pushstring (cd->L, inet_ntoa (ina)); | |||
lua_rawseti (cd->L, -2, i); | |||
lua_rawseti (cd->L, -2, ++i); | |||
} | |||
lua_pushnil (cd->L); | |||
} | |||
else if (reply->type == DNS_REQUEST_A) { | |||
lua_newtable (cd->L); | |||
cur = reply->elements; | |||
while (cur) { | |||
elt = cur->data; | |||
lua_pushstring (cd->L, elt->ptr.name); | |||
lua_rawseti (cd->L, -2, ++i); | |||
} | |||
lua_pushnil (cd->L); | |||
} | |||
else if (type == DNS_PTR) { | |||
else if (reply->type == DNS_REQUEST_TXT) { | |||
lua_newtable (cd->L); | |||
for (i = 1; i <= count; i++) { | |||
lua_pushstring (cd->L, ((char **)addresses)[i - 1]); | |||
lua_rawseti (cd->L, -2, i); | |||
cur = reply->elements; | |||
while (cur) { | |||
elt = cur->data; | |||
lua_pushstring (cd->L, elt->txt.data); | |||
lua_rawseti (cd->L, -2, ++i); | |||
} | |||
lua_pushnil (cd->L); | |||
} | |||
else { | |||
lua_pushnil (cd->L); | |||
@@ -279,7 +299,7 @@ lua_dns_callback (int result, char type, int count, int ttl, void *addresses, vo | |||
} | |||
else { | |||
lua_pushnil (cd->L); | |||
lua_pushstring (cd->L, evdns_err_to_string (result)); | |||
lua_pushstring (cd->L, dns_strerror (reply->code)); | |||
} | |||
if (lua_pcall (cd->L, 4, 0, 0) != 0) { | |||
@@ -292,8 +312,6 @@ lua_dns_callback (int result, char type, int count, int ttl, void *addresses, vo | |||
cd->task->save.saved = 1; | |||
process_filters (cd->task); | |||
} | |||
remove_forced_event (cd->task->s, (event_finalizer_t) lua_dns_callback); | |||
} | |||
static int | |||
@@ -312,9 +330,31 @@ lua_task_resolve_dns_a (lua_State * L) | |||
msg_info ("invalid parameters passed to function"); | |||
return 0; | |||
} | |||
if (evdns_resolve_ipv4 (cd->to_resolve, DNS_QUERY_NO_SEARCH, lua_dns_callback, (void *)cd) == 0) { | |||
if (make_dns_request (task->resolver, task->s, task->task_pool, lua_dns_callback, (void *)cd, DNS_REQUEST_A, cd->to_resolve)) { | |||
task->save.saved++; | |||
} | |||
} | |||
return 0; | |||
} | |||
static int | |||
lua_task_resolve_dns_txt (lua_State * L) | |||
{ | |||
struct worker_task *task = lua_check_task (L); | |||
struct lua_dns_callback_data *cd; | |||
if (task) { | |||
cd = memory_pool_alloc (task->task_pool, sizeof (struct lua_dns_callback_data)); | |||
cd->task = task; | |||
cd->L = L; | |||
cd->to_resolve = memory_pool_strdup (task->task_pool, luaL_checkstring (L, 2)); | |||
cd->callback = memory_pool_strdup (task->task_pool, luaL_checkstring (L, 3)); | |||
if (!cd->to_resolve || !cd->callback) { | |||
msg_info ("invalid parameters passed to function"); | |||
return 0; | |||
} | |||
if (make_dns_request (task->resolver, task->s, task->task_pool, lua_dns_callback, (void *)cd, DNS_REQUEST_TXT, cd->to_resolve)) { | |||
task->save.saved++; | |||
register_async_event (task->s, (event_finalizer_t) lua_dns_callback, NULL, TRUE); | |||
} | |||
} | |||
return 0; | |||
@@ -338,9 +378,8 @@ lua_task_resolve_dns_ptr (lua_State * L) | |||
msg_info ("invalid parameters passed to function"); | |||
return 0; | |||
} | |||
if (evdns_resolve_reverse (ina, DNS_QUERY_NO_SEARCH, lua_dns_callback, (void *)cd) == 0) { | |||
if (make_dns_request (task->resolver, task->s, task->task_pool, lua_dns_callback, (void *)cd, DNS_REQUEST_PTR, ina)) { | |||
task->save.saved++; | |||
register_async_event (task->s, (event_finalizer_t) lua_dns_callback, NULL, TRUE); | |||
} | |||
} | |||
return 0; |
@@ -39,7 +39,6 @@ | |||
#include "../view.h" | |||
#include "../lua/lua_common.h" | |||
#include "../json/jansson.h" | |||
#include "../evdns/evdns.h" | |||
#define DEFAULT_STATFILE_PREFIX "./" | |||
@@ -31,7 +31,7 @@ | |||
#include "map.h" | |||
#include "message.h" | |||
#include "settings.h" | |||
#include "evdns/evdns.h" | |||
#include "dns.h" | |||
/* Max line size as it is defined in rfc2822 */ | |||
#define OUTBUFSIZ 1000 | |||
@@ -190,7 +190,6 @@ call_stage_filters (struct smtp_session *session, enum rspamd_smtp_stage stage) | |||
static gboolean | |||
read_smtp_command (struct smtp_session *session, f_str_t *line) | |||
{ | |||
/* XXX: write dialog implementation */ | |||
struct smtp_command *cmd; | |||
char outbuf[BUFSIZ]; | |||
int r; | |||
@@ -703,19 +702,21 @@ smtp_make_delay (struct smtp_session *session) | |||
* Handle DNS replies | |||
*/ | |||
static void | |||
smtp_dns_cb (int result, char type, int count, int ttl, void *addresses, void *arg) | |||
smtp_dns_cb (struct rspamd_dns_reply *reply, void *arg) | |||
{ | |||
struct smtp_session *session = arg; | |||
int i, res = 0; | |||
int res = 0; | |||
union rspamd_reply_element *elt; | |||
GList *cur; | |||
remove_forced_event (session->s, (event_finalizer_t)smtp_dns_cb); | |||
switch (session->state) { | |||
case SMTP_STATE_RESOLVE_REVERSE: | |||
/* Parse reverse reply and start resolve of this ip */ | |||
if (result != DNS_ERR_NONE || type != DNS_PTR) { | |||
debug_ip (session->client_addr.s_addr, "DNS error: %s", evdns_err_to_string (result)); | |||
if (reply->code != DNS_RC_NOERROR) { | |||
debug_ip (session->client_addr.s_addr, "DNS error: %s", dns_strerror (reply->code)); | |||
if (result == DNS_ERR_NOTEXIST) { | |||
if (reply->code == DNS_RC_NXDOMAIN) { | |||
session->hostname = memory_pool_strdup (session->pool, "unknown"); | |||
} | |||
else { | |||
@@ -725,19 +726,20 @@ smtp_dns_cb (int result, char type, int count, int ttl, void *addresses, void *a | |||
smtp_make_delay (session); | |||
} | |||
else { | |||
if (addresses) { | |||
session->hostname = memory_pool_strdup (session->pool, * ((const char**)addresses)); | |||
if (reply->elements) { | |||
elt = reply->elements->data; | |||
session->hostname = memory_pool_strdup (session->pool, elt->ptr.name); | |||
session->state = SMTP_STATE_RESOLVE_NORMAL; | |||
evdns_resolve_ipv4 (session->hostname, DNS_QUERY_NO_SEARCH, smtp_dns_cb, (void *)session); | |||
register_async_event (session->s, (event_finalizer_t)smtp_dns_cb, NULL, TRUE); | |||
make_dns_request (session->resolver, session->s, session->pool, smtp_dns_cb, session, DNS_REQUEST_A, session->hostname); | |||
} | |||
} | |||
break; | |||
case SMTP_STATE_RESOLVE_NORMAL: | |||
if (result != DNS_ERR_NONE || type != DNS_IPv4_A) { | |||
debug_ip (session->client_addr.s_addr, "DNS error: %s", evdns_err_to_string (result)); | |||
if (result == DNS_ERR_NOTEXIST) { | |||
if (reply->code != DNS_RC_NOERROR) { | |||
debug_ip (session->client_addr.s_addr, "DNS error: %s", dns_strerror (reply->code)); | |||
if (reply->code == DNS_RC_NXDOMAIN) { | |||
session->hostname = memory_pool_strdup (session->pool, "unknown"); | |||
} | |||
else { | |||
@@ -748,12 +750,15 @@ smtp_dns_cb (int result, char type, int count, int ttl, void *addresses, void *a | |||
} | |||
else { | |||
res = 0; | |||
for (i = 0; i < count; i++) { | |||
if (session->client_addr.s_addr == ((in_addr_t *)addresses)[i]) { | |||
cur = reply->elements; | |||
while (cur) { | |||
elt = cur->data; | |||
if (memcmp (&session->client_addr, &elt->a.addr[0], sizeof (struct in_addr)) == 0) { | |||
res = 1; | |||
session->resolved = TRUE; | |||
break; | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
if (res == 0) { | |||
@@ -786,6 +791,7 @@ accept_socket (int fd, short what, void *arg) | |||
struct rspamd_worker *worker = (struct rspamd_worker *)arg; | |||
union sa_union su; | |||
struct smtp_session *session; | |||
struct smtp_worker_ctx *ctx; | |||
socklen_t addrlen = sizeof (su.ss); | |||
int nfd; | |||
@@ -799,6 +805,7 @@ accept_socket (int fd, short what, void *arg) | |||
return; | |||
} | |||
ctx = worker->ctx; | |||
session = g_malloc0 (sizeof (struct smtp_session)); | |||
session->pool = memory_pool_new (memory_pool_get_size ()); | |||
@@ -814,24 +821,23 @@ accept_socket (int fd, short what, void *arg) | |||
session->sock = nfd; | |||
session->temp_fd = -1; | |||
session->worker = worker; | |||
session->ctx = worker->ctx; | |||
session->ctx = ctx; | |||
session->cfg = worker->srv->cfg; | |||
session->session_time = time (NULL); | |||
session->resolver = ctx->resolver; | |||
worker->srv->stat->connections_count++; | |||
/* Resolve client's addr */ | |||
/* Set up async session */ | |||
session->s = new_async_session (session->pool, free_smtp_session, session); | |||
session->state = SMTP_STATE_RESOLVE_REVERSE; | |||
if (evdns_resolve_reverse (&session->client_addr, DNS_QUERY_NO_SEARCH, smtp_dns_cb, session) != 0) { | |||
if (! make_dns_request (session->resolver, session->s, session->pool, smtp_dns_cb, session, DNS_REQUEST_A, session->client_addr)) { | |||
msg_err ("cannot resolve %s", inet_ntoa (session->client_addr)); | |||
g_free (session); | |||
close (nfd); | |||
return; | |||
} | |||
else { | |||
/* Set up async session */ | |||
session->s = new_async_session (session->pool, free_smtp_session, session); | |||
register_async_event (session->s, (event_finalizer_t)smtp_dns_cb, NULL, TRUE); | |||
/* Set up dispatcher */ | |||
session->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, | |||
smtp_read_socket, smtp_write_socket, smtp_err_socket, &session->ctx->smtp_timeout, session); | |||
session->dispatcher->peer_addr = session->client_addr.s_addr; | |||
@@ -1092,6 +1098,8 @@ config_smtp_worker (struct rspamd_worker *worker) | |||
ctx->reject_message = DEFAULT_REJECT_MESSAGE; | |||
} | |||
ctx->resolver = dns_resolver_init (worker->srv->cfg); | |||
/* Set ctx */ | |||
worker->ctx = ctx; | |||
@@ -1119,7 +1127,6 @@ start_smtp_worker (struct rspamd_worker *worker) | |||
} | |||
event_init (); | |||
evdns_init (); | |||
init_signals (&signals, sig_handler); | |||
sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL); |
@@ -14,6 +14,8 @@ struct smtp_upstream { | |||
gboolean is_unix; | |||
}; | |||
struct rspamd_dns_resolver; | |||
#define MAX_UPSTREAM 128 | |||
#define DEFAULT_MAX_ERRORS 10 | |||
@@ -44,6 +46,7 @@ struct smtp_worker_ctx { | |||
guint max_errors; | |||
char *metric; | |||
GList *smtp_filters[SMTP_STAGE_MAX]; | |||
struct rspamd_dns_resolver *resolver; | |||
}; | |||
enum rspamd_smtp_state { | |||
@@ -102,6 +105,7 @@ struct smtp_session { | |||
gboolean resolved; | |||
gboolean esmtp; | |||
struct rspamd_dns_resolver *resolver; | |||
}; | |||
typedef gboolean (*smtp_filter_t)(struct smtp_session *session, gpointer filter_data); |