* Fix issue with links that are ip addresses in numeric form in surbl * On Darwin use BSD style sendfile definition * Reorganize platform specific knobs in CMakeLists * Use gettimeofday on systems that have not clock_getres * Use ftime for dns trans id generation on systems without clock_getrestags/0.3.1
INCLUDE(CheckCCompilerFlag) | INCLUDE(CheckCCompilerFlag) | ||||
INCLUDE(FindPerl) | INCLUDE(FindPerl) | ||||
# Initial set | |||||
SET(CMAKE_REQUIRED_LIBRARIES m) | |||||
SET(CMAKE_REQUIRED_INCLUDES sys/mman.h stdlib.h stdio.h unistd.h time.h sched.h) | |||||
# Platform specific routines | |||||
IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") | |||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE -DFREEBSD") | |||||
CONFIGURE_FILE(freebsd/rspamd.sh.in freebsd/rspamd.sh @ONLY) | |||||
IF(ENABLE_REDIRECTOR MATCHES "ON") | |||||
CONFIGURE_FILE(freebsd/redirector.sh.in freebsd/redirector.sh @ONLY) | |||||
ENDIF(ENABLE_REDIRECTOR MATCHES "ON") | |||||
IF(NOT ETC_PREFIX) | |||||
SET(ETC_PREFIX /usr/local/etc) | |||||
SET(PREFIX /usr/local) | |||||
ENDIF(NOT ETC_PREFIX) | |||||
LIST(APPEND CMAKE_REQUIRED_LIBRARIES intl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") | |||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Darwin") | |||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE -DDARWIN") | |||||
IF(NOT ETC_PREFIX) | |||||
SET(ETC_PREFIX /usr/local/etc) | |||||
SET(PREFIX /usr/local) | |||||
ENDIF(NOT ETC_PREFIX) | |||||
LIST(APPEND CMAKE_REQUIRED_LIBRARIES intl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin") | |||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE -DLINUX") | |||||
IF(NOT ETC_PREFIX) | |||||
SET(ETC_PREFIX /etc) | |||||
SET(PREFIX /usr) | |||||
ENDIF(NOT ETC_PREFIX) | |||||
LIST(APPEND CMAKE_REQUIRED_LIBRARIES rt) | |||||
LIST(APPEND CMAKE_REQUIRED_LIBRARIES dl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
IF(ENABLE_PERL MATCHES "ON") | IF(ENABLE_PERL MATCHES "ON") | ||||
IF(NOT PERL_EXECUTABLE) | IF(NOT PERL_EXECUTABLE) | ||||
INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) | INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS}) | ||||
LINK_DIRECTORIES(${GLIB2_LIBRARY_DIRS}) | LINK_DIRECTORIES(${GLIB2_LIBRARY_DIRS}) | ||||
SET(CMAKE_REQUIRED_LIBRARIES m) | |||||
SET(CMAKE_REQUIRED_INCLUDES sys/mman.h stdlib.h stdio.h unistd.h time.h sched.h) | |||||
# Check for libevent | # Check for libevent | ||||
IF(HAVE_SYS_WAIT_H) | IF(HAVE_SYS_WAIT_H) | ||||
LIST(APPEND CMAKE_REQUIRED_INCLUDES sys/wait.h) | LIST(APPEND CMAKE_REQUIRED_INCLUDES sys/wait.h) | ||||
ENDIF(HAVE_SYS_WAIT_H) | ENDIF(HAVE_SYS_WAIT_H) | ||||
IF(HAVE_TIME_H) | |||||
LIST(APPEND CMAKE_REQUIRED_INCLUDES time.h) | |||||
ENDIF(HAVE_TIME_H) | |||||
CHECK_FUNCTION_EXISTS(setproctitle HAVE_SETPROCTITLE) | CHECK_FUNCTION_EXISTS(setproctitle HAVE_SETPROCTITLE) | ||||
CHECK_FUNCTION_EXISTS(getpagesize HAVE_GETPAGESIZE) | CHECK_FUNCTION_EXISTS(getpagesize HAVE_GETPAGESIZE) | ||||
CHECK_FUNCTION_EXISTS(tanhl HAVE_TANHL) | CHECK_FUNCTION_EXISTS(tanhl HAVE_TANHL) | ||||
CHECK_FUNCTION_EXISTS(sendfile HAVE_SENDFILE) | CHECK_FUNCTION_EXISTS(sendfile HAVE_SENDFILE) | ||||
CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP) | CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP) | ||||
CHECK_FUNCTION_EXISTS(clock_gettime HAVE_CLOCK_GETTIME) | |||||
CHECK_SYMBOL_EXISTS(PATH_MAX limits.h HAVE_PATH_MAX) | CHECK_SYMBOL_EXISTS(PATH_MAX limits.h HAVE_PATH_MAX) | ||||
CHECK_SYMBOL_EXISTS(MAXPATHLEN sys/param.h HAVE_MAXPATHLEN) | CHECK_SYMBOL_EXISTS(MAXPATHLEN sys/param.h HAVE_MAXPATHLEN) | ||||
CHECK_SYMBOL_EXISTS(MAP_ANON sys/mman.h HAVE_MMAP_ANON) | CHECK_SYMBOL_EXISTS(MAP_ANON sys/mman.h HAVE_MMAP_ANON) | ||||
CHECK_SYMBOL_EXISTS(MAP_NOCORE sys/mman.h HAVE_MMAP_NOCORE) | CHECK_SYMBOL_EXISTS(MAP_NOCORE sys/mman.h HAVE_MMAP_NOCORE) | ||||
CHECK_SYMBOL_EXISTS(_SC_NPROCESSORS_ONLN unistd.h HAVE_SC_NPROCESSORS_ONLN) | CHECK_SYMBOL_EXISTS(_SC_NPROCESSORS_ONLN unistd.h HAVE_SC_NPROCESSORS_ONLN) | ||||
CHECK_SYMBOL_EXISTS(CLOCK_PROCESS_CPUTIME_ID time.h HAVE_CLOCK_PROCESS_CPUTIME_ID) | |||||
CHECK_SYMBOL_EXISTS(SA_SIGINFO signal.h HAVE_SA_SIGINFO) | CHECK_SYMBOL_EXISTS(SA_SIGINFO signal.h HAVE_SA_SIGINFO) | ||||
CHECK_SYMBOL_EXISTS(CLOCK_VIRTUAL time.h HAVE_CLOCK_VIRTUAL) | |||||
IF(HAVE_CLOCK_GETTIME) | |||||
CHECK_SYMBOL_EXISTS(CLOCK_PROCESS_CPUTIME_ID time.h HAVE_CLOCK_PROCESS_CPUTIME_ID) | |||||
CHECK_SYMBOL_EXISTS(CLOCK_VIRTUAL time.h HAVE_CLOCK_VIRTUAL) | |||||
ELSE(HAVE_CLOCK_GETTIME) | |||||
CHECK_INCLUDE_FILES(sys/timeb.h HAVE_SYS_TIMEDB_H) | |||||
ENDIF(HAVE_CLOCK_GETTIME) | |||||
CHECK_C_SOURCE_COMPILES ("#include <sys/types.h> | CHECK_C_SOURCE_COMPILES ("#include <sys/types.h> | ||||
int main (int argc, char **argv) { | int main (int argc, char **argv) { | ||||
SET(CMAKE_C_FLAGS "${CMAKE_C_OPT_FLAGS} ${CMAKE_C_FLAGS} ${CMAKE_C_WARN_FLAGS}") | SET(CMAKE_C_FLAGS "${CMAKE_C_OPT_FLAGS} ${CMAKE_C_FLAGS} ${CMAKE_C_WARN_FLAGS}") | ||||
# Platform specific routines | |||||
IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") | |||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_BSD_SOURCE -DFREEBSD") | |||||
CONFIGURE_FILE(freebsd/rspamd.sh.in freebsd/rspamd.sh @ONLY) | |||||
IF(ENABLE_REDIRECTOR MATCHES "ON") | |||||
CONFIGURE_FILE(freebsd/redirector.sh.in freebsd/redirector.sh @ONLY) | |||||
ENDIF(ENABLE_REDIRECTOR MATCHES "ON") | |||||
IF(NOT ETC_PREFIX) | |||||
SET(ETC_PREFIX /usr/local/etc) | |||||
SET(PREFIX /usr/local) | |||||
ENDIF(NOT ETC_PREFIX) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") | |||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE -DLINUX") | |||||
IF(NOT ETC_PREFIX) | |||||
SET(ETC_PREFIX /etc) | |||||
SET(PREFIX /usr) | |||||
ENDIF(NOT ETC_PREFIX) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
IF(ENABLE_REDIRECTOR MATCHES "ON") | IF(ENABLE_REDIRECTOR MATCHES "ON") | ||||
CONFIGURE_FILE(utils/redirector.pl.in utils/redirector.pl @ONLY) | CONFIGURE_FILE(utils/redirector.pl.in utils/redirector.pl @ONLY) | ||||
TARGET_LINK_LIBRARIES(rspamd rspamd_lua) | TARGET_LINK_LIBRARIES(rspamd rspamd_lua) | ||||
TARGET_LINK_LIBRARIES(rspamd "${LUA_LIBRARY}") | TARGET_LINK_LIBRARIES(rspamd "${LUA_LIBRARY}") | ||||
TARGET_LINK_LIBRARIES(rspamd m) | |||||
IF(LIBUTIL_LIBRARY) | |||||
TARGET_LINK_LIBRARIES(rspamd util) | |||||
ENDIF(LIBUTIL_LIBRARY) | |||||
IF(LIBJUDY_LIBRARY) | IF(LIBJUDY_LIBRARY) | ||||
TARGET_LINK_LIBRARIES(rspamd Judy) | TARGET_LINK_LIBRARIES(rspamd Judy) | ||||
ENDIF(LIBJUDY_LIBRARY) | ENDIF(LIBJUDY_LIBRARY) | ||||
IF(ENABLE_STATIC MATCHES "ON") | IF(ENABLE_STATIC MATCHES "ON") | ||||
TARGET_LINK_LIBRARIES(rspamd ${PCRE_LIBRARIES}) | TARGET_LINK_LIBRARIES(rspamd ${PCRE_LIBRARIES}) | ||||
ENDIF(ENABLE_STATIC MATCHES "ON") | ENDIF(ENABLE_STATIC MATCHES "ON") | ||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(rspamd rt) | |||||
TARGET_LINK_LIBRARIES(rspamd dl) | |||||
ELSE(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(rspamd intl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
IF(ENABLE_GPERF_TOOLS MATCHES "ON") | IF(ENABLE_GPERF_TOOLS MATCHES "ON") | ||||
TARGET_LINK_LIBRARIES(rspamd profiler) | TARGET_LINK_LIBRARIES(rspamd profiler) | ||||
ADD_EXECUTABLE(test/rspamd-test ${TESTDEPENDS} ${CONTRIBSRC} ${TESTSRC}) | ADD_EXECUTABLE(test/rspamd-test ${TESTDEPENDS} ${CONTRIBSRC} ${TESTSRC}) | ||||
SET_TARGET_PROPERTIES(test/rspamd-test PROPERTIES LINKER_LANGUAGE C) | SET_TARGET_PROPERTIES(test/rspamd-test PROPERTIES LINKER_LANGUAGE C) | ||||
TARGET_LINK_LIBRARIES(test/rspamd-test m) | |||||
IF(LIBUTIL_LIBRARY) | |||||
TARGET_LINK_LIBRARIES(test/rspamd-test util) | |||||
ENDIF(LIBUTIL_LIBRARY) | |||||
TARGET_LINK_LIBRARIES(test/rspamd-test event) | TARGET_LINK_LIBRARIES(test/rspamd-test event) | ||||
TARGET_LINK_LIBRARIES(test/rspamd-test ${GLIB2_LIBRARIES}) | TARGET_LINK_LIBRARIES(test/rspamd-test ${GLIB2_LIBRARIES}) | ||||
IF(GMIME2_FOUND) | IF(GMIME2_FOUND) | ||||
IF(ENABLE_STATIC MATCHES "ON") | IF(ENABLE_STATIC MATCHES "ON") | ||||
TARGET_LINK_LIBRARIES(test/rspamd-test ${PCRE_LIBRARIES}) | TARGET_LINK_LIBRARIES(test/rspamd-test ${PCRE_LIBRARIES}) | ||||
ENDIF(ENABLE_STATIC MATCHES "ON") | ENDIF(ENABLE_STATIC MATCHES "ON") | ||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(test/rspamd-test rt) | |||||
ELSE(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(test/rspamd-test intl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
ADD_EXECUTABLE(utils/url-extracter ${UTILSDEPENDS} ${CONTRIBSRC} ${UTILSSRC}) | ADD_EXECUTABLE(utils/url-extracter ${UTILSDEPENDS} ${CONTRIBSRC} ${UTILSSRC}) | ||||
SET_TARGET_PROPERTIES(utils/url-extracter PROPERTIES LINKER_LANGUAGE C) | SET_TARGET_PROPERTIES(utils/url-extracter PROPERTIES LINKER_LANGUAGE C) | ||||
TARGET_LINK_LIBRARIES(utils/url-extracter m) | |||||
IF(LIBUTIL_LIBRARY) | |||||
TARGET_LINK_LIBRARIES(utils/url-extracter util) | |||||
ENDIF(LIBUTIL_LIBRARY) | |||||
TARGET_LINK_LIBRARIES(utils/url-extracter ${GLIB2_LIBRARIES}) | TARGET_LINK_LIBRARIES(utils/url-extracter ${GLIB2_LIBRARIES}) | ||||
IF(GMIME2_FOUND) | IF(GMIME2_FOUND) | ||||
TARGET_LINK_LIBRARIES(utils/url-extracter ${GMIME2_LIBRARIES}) | TARGET_LINK_LIBRARIES(utils/url-extracter ${GMIME2_LIBRARIES}) | ||||
IF(ENABLE_STATIC MATCHES "ON") | IF(ENABLE_STATIC MATCHES "ON") | ||||
TARGET_LINK_LIBRARIES(utils/url-extracter ${PCRE_LIBRARIES}) | TARGET_LINK_LIBRARIES(utils/url-extracter ${PCRE_LIBRARIES}) | ||||
ENDIF(ENABLE_STATIC MATCHES "ON") | ENDIF(ENABLE_STATIC MATCHES "ON") | ||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(utils/url-extracter rt) | |||||
ELSE(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(utils/url-extracter intl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
ADD_EXECUTABLE(utils/expression-parser ${UTILSDEPENDS} ${CONTRIBSRC} ${EXPRSRC}) | ADD_EXECUTABLE(utils/expression-parser ${UTILSDEPENDS} ${CONTRIBSRC} ${EXPRSRC}) | ||||
SET_TARGET_PROPERTIES(utils/expression-parser PROPERTIES LINKER_LANGUAGE C) | SET_TARGET_PROPERTIES(utils/expression-parser PROPERTIES LINKER_LANGUAGE C) | ||||
IF(ENABLE_STATIC MATCHES "ON") | IF(ENABLE_STATIC MATCHES "ON") | ||||
TARGET_LINK_LIBRARIES(utils/expression-parser ${PCRE_LIBRARIES}) | TARGET_LINK_LIBRARIES(utils/expression-parser ${PCRE_LIBRARIES}) | ||||
ENDIF(ENABLE_STATIC MATCHES "ON") | ENDIF(ENABLE_STATIC MATCHES "ON") | ||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(utils/expression-parser rt) | |||||
ELSE(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
TARGET_LINK_LIBRARIES(utils/expression-parser intl) | |||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||||
##################### INSTALLATION ########################################## | ##################### INSTALLATION ########################################## | ||||
#cmakedefine HAVE_SYS_PARAM_H 1 | #cmakedefine HAVE_SYS_PARAM_H 1 | ||||
#cmakedefine HAVE_SYS_FILE_H 1 | #cmakedefine HAVE_SYS_FILE_H 1 | ||||
#cmakedefine HAVE_SYS_RESOURCE_H 1 | #cmakedefine HAVE_SYS_RESOURCE_H 1 | ||||
#cmakedefine HAVE_SYS_TIMEDB_H 1 | |||||
#cmakedefine HAVE_PIDFILE 1 | #cmakedefine HAVE_PIDFILE 1 | ||||
#cmakedefine BUILD_STATIC 1 | #cmakedefine BUILD_STATIC 1 | ||||
#cmakedefine HAVE_SENDFILE 1 | #cmakedefine HAVE_SENDFILE 1 | ||||
#cmakedefine HAVE_MKSTEMP 1 | |||||
#cmakedefine HAVE_SYS_SENDFILE_H 1 | #cmakedefine HAVE_SYS_SENDFILE_H 1 | ||||
#cmakedefine HAVE_MKSTEMP 1 | |||||
#cmakedefine HAVE_CLOCK_GETTIME 1 | |||||
#define RVERSION "${RSPAMD_VERSION}" | #define RVERSION "${RSPAMD_VERSION}" | ||||
#define RSPAMD_MASTER_SITE_URL "${RSPAMD_MASTER_SITE_URL}" | #define RSPAMD_MASTER_SITE_URL "${RSPAMD_MASTER_SITE_URL}" | ||||
#include <time.h> | #include <time.h> | ||||
#endif | #endif | ||||
/* timedb */ | |||||
#ifdef HAVE_SYS_TIMEDB_H | |||||
#include <sys/timedb.h> | |||||
#endif | |||||
/* sysexits */ | /* sysexits */ | ||||
#ifdef HAVE_SYSEXITS_H | #ifdef HAVE_SYSEXITS_H | ||||
#include <sysexits.h> | #include <sysexits.h> |
GError *err; | GError *err; | ||||
#ifdef HAVE_SENDFILE | #ifdef HAVE_SENDFILE | ||||
#if defined(FREEBSD) | |||||
#if defined(FREEBSD) || defined(DARWIN) | |||||
off_t off = 0; | off_t off = 0; | ||||
/* FreeBSD version */ | /* FreeBSD version */ | ||||
if (sendfile (d->sendfile_fd, d->fd, d->offset, 0, 0, &off, 0) != 0) { | if (sendfile (d->sendfile_fd, d->fd, d->offset, 0, 0, &off, 0) != 0) { | ||||
GError *err; | GError *err; | ||||
f_str_t res; | f_str_t res; | ||||
char *c, *b; | char *c, *b; | ||||
char **pos; | |||||
size_t *len; | |||||
char *end; | |||||
size_t len; | |||||
enum io_policy saved_policy; | enum io_policy saved_policy; | ||||
if (d->wanna_die) { | if (d->wanna_die) { | ||||
d->in_buf->pos = d->in_buf->data->begin; | d->in_buf->pos = d->in_buf->data->begin; | ||||
} | } | ||||
pos = &d->in_buf->pos; | |||||
len = &d->in_buf->data->len; | |||||
end = d->in_buf->pos; | |||||
len = d->in_buf->data->len; | |||||
if (BUFREMAIN (d->in_buf) == 0) { | if (BUFREMAIN (d->in_buf) == 0) { | ||||
/* Buffer is full, try to call callback with overflow error */ | /* Buffer is full, try to call callback with overflow error */ | ||||
} | } | ||||
else if (!skip_read) { | else if (!skip_read) { | ||||
/* Try to read the whole buffer */ | /* Try to read the whole buffer */ | ||||
r = read (fd, *pos, BUFREMAIN (d->in_buf)); | |||||
r = read (fd, end, BUFREMAIN (d->in_buf)); | |||||
if (r == -1 && errno != EAGAIN) { | if (r == -1 && errno != EAGAIN) { | ||||
if (d->err_callback) { | if (d->err_callback) { | ||||
err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); | err = g_error_new (G_DISPATCHER_ERROR, errno, "%s", strerror (errno)); | ||||
return; | return; | ||||
} | } | ||||
else { | else { | ||||
*pos += r; | |||||
*len += r; | |||||
/* Set current position in buffer */ | |||||
d->in_buf->pos += r; | |||||
d->in_buf->data->len += r; | |||||
} | } | ||||
debug_ip (d->peer_addr, "read %z characters, policy is %s, watermark is: %z", r, | debug_ip (d->peer_addr, "read %z characters, policy is %s, watermark is: %z", r, | ||||
d->policy == BUFFER_LINE ? "LINE" : "CHARACTER", d->nchars); | d->policy == BUFFER_LINE ? "LINE" : "CHARACTER", d->nchars); | ||||
saved_policy = d->policy; | saved_policy = d->policy; | ||||
c = d->in_buf->data->begin; | c = d->in_buf->data->begin; | ||||
end = d->in_buf->pos; | |||||
len = d->in_buf->data->len; | |||||
b = c; | b = c; | ||||
r = 0; | r = 0; | ||||
* c - pointer to current position (buffer->begin + r) | * c - pointer to current position (buffer->begin + r) | ||||
* res - result string | * res - result string | ||||
*/ | */ | ||||
while (r < *len) { | |||||
while (r < len) { | |||||
if (*c == '\n') { | if (*c == '\n') { | ||||
res.begin = b; | res.begin = b; | ||||
res.len = c - b; | res.len = c - b; | ||||
} | } | ||||
if (d->policy != saved_policy) { | if (d->policy != saved_policy) { | ||||
/* Drain buffer as policy is changed */ | /* Drain buffer as policy is changed */ | ||||
len = &d->in_buf->data->len; | |||||
pos = &d->in_buf->pos; | |||||
if (c != *pos) { | |||||
memmove (d->in_buf->data->begin, c + 1, *len - r - 1); | |||||
*len = *len -r - 1; | |||||
*pos = d->in_buf->data->begin + *len; | |||||
/* Note that d->in_buffer is other pointer now, so we need to reinit all pointers */ | |||||
/* First detect how much symbols do we have */ | |||||
if (end == c) { | |||||
/* In fact we read the whole buffer and change input policy, so just set current pos to begin of buffer */ | |||||
d->in_buf->pos = d->in_buf->data->begin; | |||||
d->in_buf->data->len = 0; | |||||
} | } | ||||
else { | else { | ||||
*len = 0; | |||||
*pos = d->in_buf->data->begin; | |||||
/* Otherwise we need to move buffer */ | |||||
/* Reinit pointers */ | |||||
len = d->in_buf->data->len - r - 1; | |||||
end = d->in_buf->data->begin + r + 1; | |||||
memmove (d->in_buf->data->begin, end, len); | |||||
d->in_buf->data->len = len; | |||||
d->in_buf->pos = d->in_buf->data->begin + len; | |||||
/* Process remaining buffer */ | |||||
read_buffers (fd, d, TRUE); | |||||
} | } | ||||
debug_ip (d->peer_addr, "policy changed during callback, restart buffer's processing"); | |||||
read_buffers (fd, d, TRUE); | |||||
return; | return; | ||||
} | } | ||||
} | } | ||||
r++; | r++; | ||||
c++; | c++; | ||||
} | } | ||||
/* Now drain buffer */ | |||||
len = &d->in_buf->data->len; | |||||
pos = &d->in_buf->pos; | |||||
/* Now drain remaining characters in buffer */ | |||||
memmove (d->in_buf->data->begin, b, c - b); | memmove (d->in_buf->data->begin, b, c - b); | ||||
*len = c - b; | |||||
*pos = d->in_buf->data->begin + *len; | |||||
d->in_buf->data->len = c - b; | |||||
d->in_buf->pos = d->in_buf->data->begin + (c - b); | |||||
break; | break; | ||||
case BUFFER_CHARACTER: | case BUFFER_CHARACTER: | ||||
r = d->nchars; | r = d->nchars; | ||||
if (*len >= r) { | |||||
if (len >= r) { | |||||
res.begin = b; | res.begin = b; | ||||
res.len = r; | res.len = r; | ||||
c = b + r; | c = b + r; | ||||
return; | return; | ||||
} | } | ||||
/* Move remaining string to begin of buffer (draining) */ | /* Move remaining string to begin of buffer (draining) */ | ||||
len = &d->in_buf->data->len; | |||||
pos = &d->in_buf->pos; | |||||
memmove (d->in_buf->data->begin, c, *len - r); | |||||
b = d->in_buf->data->begin; | |||||
c = b; | |||||
*len -= r; | |||||
*pos = b + *len; | |||||
if (d->policy != saved_policy) { | |||||
if (len > r) { | |||||
len -= r; | |||||
memmove (d->in_buf->data->begin, c, len); | |||||
d->in_buf->data->len = len; | |||||
d->in_buf->pos = d->in_buf->data->begin + len; | |||||
b = d->in_buf->data->begin; | |||||
c = b; | |||||
} | |||||
if (d->policy != saved_policy && len != r) { | |||||
debug_ip (d->peer_addr, "policy changed during callback, restart buffer's processing"); | debug_ip (d->peer_addr, "policy changed during callback, restart buffer's processing"); | ||||
read_buffers (fd, d, TRUE); | read_buffers (fd, d, TRUE); | ||||
return; | return; | ||||
break; | break; | ||||
case BUFFER_ANY: | case BUFFER_ANY: | ||||
res.begin = d->in_buf->data->begin; | res.begin = d->in_buf->data->begin; | ||||
res.len = *len; | |||||
res.len = len; | |||||
if (d->read_callback) { | if (d->read_callback) { | ||||
if (!d->read_callback (&res, d->user_data)) { | if (!d->read_callback (&res, d->user_data)) { | ||||
return; | return; |
void | void | ||||
post_load_config (struct config_file *cfg) | post_load_config (struct config_file *cfg) | ||||
{ | { | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
struct timespec ts; | struct timespec ts; | ||||
#endif | |||||
struct metric *def_metric; | struct metric *def_metric; | ||||
g_hash_table_foreach (cfg->variables, substitute_all_variables, cfg); | g_hash_table_foreach (cfg->variables, substitute_all_variables, cfg); | ||||
parse_filters_str (cfg, cfg->filters_str); | parse_filters_str (cfg, cfg->filters_str); | ||||
fill_cfg_params (cfg); | fill_cfg_params (cfg); | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | #ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | ||||
clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts); | clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts); | ||||
#elif defined(HAVE_CLOCK_VIRTUAL) | |||||
# elif defined(HAVE_CLOCK_VIRTUAL) | |||||
clock_getres (CLOCK_VIRTUAL, &ts); | clock_getres (CLOCK_VIRTUAL, &ts); | ||||
#else | |||||
# else | |||||
clock_getres (CLOCK_REALTIME, &ts); | clock_getres (CLOCK_REALTIME, &ts); | ||||
#endif | |||||
# endif | |||||
cfg->clock_res = (int)log10 (1000000 / ts.tv_nsec); | cfg->clock_res = (int)log10 (1000000 / ts.tv_nsec); | ||||
if (cfg->clock_res < 0) { | if (cfg->clock_res < 0) { | ||||
cfg->clock_res = 0; | cfg->clock_res = 0; | ||||
if (cfg->clock_res > 3) { | if (cfg->clock_res > 3) { | ||||
cfg->clock_res = 3; | cfg->clock_res = 3; | ||||
} | } | ||||
#else | |||||
/* For gettimeofday */ | |||||
cfg->clock_res = 1; | |||||
#endif | |||||
if ((def_metric = g_hash_table_lookup (cfg->metrics, DEFAULT_METRIC)) == NULL) { | if ((def_metric = g_hash_table_lookup (cfg->metrics, DEFAULT_METRIC)) == NULL) { | ||||
def_metric = check_metric_conf (cfg, NULL); | def_metric = check_metric_conf (cfg, NULL); |
default_transaction_id_fn(void) | default_transaction_id_fn(void) | ||||
{ | { | ||||
u16 trans_id; | u16 trans_id; | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
struct timespec ts; | struct timespec ts; | ||||
static int clkid = -1; | static int clkid = -1; | ||||
if (clkid == -1) { | if (clkid == -1) { | ||||
} | } | ||||
clock_gettime(clkid, &ts); | clock_gettime(clkid, &ts); | ||||
trans_id = ts.tv_nsec & 0xffff; | trans_id = ts.tv_nsec & 0xffff; | ||||
#elif defined(HAVE_SYS_TIMEDB_H) | |||||
struct timeb tb; | |||||
ftime(&tb); | |||||
trans_id = tb.millitm & 0xffff; | |||||
#else | |||||
# error Cannot find way to generate dns transaction id | |||||
#endif | |||||
return trans_id; | return trans_id; | ||||
} | } |
char *last_error; /**< last error */ | char *last_error; /**< last error */ | ||||
int error_code; /**< code of last error */ | int error_code; /**< code of last error */ | ||||
memory_pool_t *task_pool; /**< memory pool for task */ | memory_pool_t *task_pool; /**< memory pool for task */ | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
struct timespec ts; /**< time of connection */ | struct timespec ts; /**< time of connection */ | ||||
#else | |||||
struct timeval tv; /**< time of connection */ | |||||
#endif | |||||
struct rspamd_view *view; /**< matching view */ | struct rspamd_view *view; /**< matching view */ | ||||
gboolean view_checked; | gboolean view_checked; | ||||
gboolean pass_all_filters; /**< pass task throught every rule */ | gboolean pass_all_filters; /**< pass task throught every rule */ |
} | } | ||||
/* Get upstream */ | /* Get upstream */ | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num, | selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num, | ||||
sizeof (struct storage_server), task->ts.tv_sec, | sizeof (struct storage_server), task->ts.tv_sec, | ||||
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); | DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); | ||||
#else | |||||
selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num, | |||||
sizeof (struct storage_server), task->tv.tv_sec, | |||||
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); | |||||
#endif | |||||
if (selected) { | if (selected) { | ||||
if ((sock = make_udp_socket (&selected->addr, selected->port, FALSE, TRUE)) == -1) { | if ((sock = make_udp_socket (&selected->addr, selected->port, FALSE, TRUE)) == -1) { | ||||
msg_warn ("cannot connect to %s, %d, %s", selected->name, errno, strerror (errno)); | msg_warn ("cannot connect to %s, %d, %s", selected->name, errno, strerror (errno)); | ||||
continue; | continue; | ||||
} | } | ||||
/* Get upstream */ | /* Get upstream */ | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num, | selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num, | ||||
sizeof (struct storage_server), task->ts.tv_sec, | sizeof (struct storage_server), task->ts.tv_sec, | ||||
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); | DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); | ||||
#else | |||||
selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num, | |||||
sizeof (struct storage_server), task->tv.tv_sec, | |||||
DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe)); | |||||
#endif | |||||
if (selected) { | if (selected) { | ||||
/* Create UDP socket */ | /* Create UDP socket */ | ||||
if ((sock = make_udp_socket (&selected->addr, selected->port, FALSE, TRUE)) == -1) { | if ((sock = make_udp_socket (&selected->addr, selected->port, FALSE, TRUE)) == -1) { |
r = snprintf (result, len, "%*s.%*s.%*s.%*s", | r = snprintf (result, len, "%*s.%*s.%*s.%*s", | ||||
(int)(hostname->len - (dots[2] - hostname->begin + 1)), | (int)(hostname->len - (dots[2] - hostname->begin + 1)), | ||||
dots[2] + 1, | dots[2] + 1, | ||||
(int)(dots[2] - (dots[1] - hostname->begin + 1)), | |||||
(int)(dots[2] - dots[1] - 1), | |||||
dots[1], | dots[1], | ||||
(int)(dots[1] - (dots[0] - hostname->begin + 1)), | |||||
(int)(dots[1] - dots[0] - 1), | |||||
dots[0], | dots[0], | ||||
(int)(dots[0] - (hostname->begin + 1)), | |||||
(int)(dots[0] - hostname->begin), | |||||
hostname->begin); | hostname->begin); | ||||
} | } | ||||
else if (is_numeric && dots_num == 0) { | else if (is_numeric && dots_num == 0) { |
show_metric_symbols (metric_res, cd); | show_metric_symbols (metric_res, cd); | ||||
} | } | ||||
} | } | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %ld, time: %sms", | cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %ld, time: %sms", | ||||
(long int)task->msg->len, calculate_check_time (&task->ts, task->cfg->clock_res)); | (long int)task->msg->len, calculate_check_time (&task->ts, task->cfg->clock_res)); | ||||
#else | |||||
cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %ld, time: %sms", | |||||
(long int)task->msg->len, calculate_check_time (&task->tv, task->cfg->clock_res)); | |||||
#endif | |||||
} | } | ||||
static void | static void |
case SMTP_COMMAND_NOOP: | case SMTP_COMMAND_NOOP: | ||||
break; | break; | ||||
case SMTP_COMMAND_MAIL: | case SMTP_COMMAND_MAIL: | ||||
if ((session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO && !session->ctx->helo_required) | |||||
if (((session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) && !session->ctx->helo_required) | |||||
|| session->state == SMTP_STATE_FROM) { | || session->state == SMTP_STATE_FROM) { | ||||
if (parse_smtp_from (session, cmd)) { | if (parse_smtp_from (session, cmd)) { | ||||
session->state = SMTP_STATE_RCPT; | session->state = SMTP_STATE_RCPT; | ||||
cur = g_list_next (cur); | cur = g_list_next (cur); | ||||
} | } | ||||
g_list_free (symbols); | g_list_free (symbols); | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
r += snprintf (logbuf + r, sizeof (logbuf) - r, "]), len: %ld, time: %sms", | r += snprintf (logbuf + r, sizeof (logbuf) - r, "]), len: %ld, time: %sms", | ||||
(long int)session->task->msg->len, calculate_check_time (&session->task->ts, session->cfg->clock_res)); | (long int)session->task->msg->len, calculate_check_time (&session->task->ts, session->cfg->clock_res)); | ||||
#else | |||||
r += snprintf (logbuf + r, sizeof (logbuf) - r, "]), len: %ld, time: %sms", | |||||
(long int)session->task->msg->len, calculate_check_time (&session->task->tv, session->cfg->clock_res)); | |||||
#endif | |||||
msg_info ("%s", logbuf); | msg_info ("%s", logbuf); | ||||
if (is_spam) { | if (is_spam) { |
gboolean | gboolean | ||||
call_symbol_callback (struct worker_task * task, struct symbols_cache * cache, gpointer *save) | call_symbol_callback (struct worker_task * task, struct symbols_cache * cache, gpointer *save) | ||||
{ | { | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
struct timespec ts1, ts2; | struct timespec ts1, ts2; | ||||
#else | |||||
struct timeval tv1, tv2; | |||||
#endif | |||||
uint64_t diff; | uint64_t diff; | ||||
struct cache_item *item = NULL; | struct cache_item *item = NULL; | ||||
struct symbol_callback_data *s = *save; | struct symbol_callback_data *s = *save; | ||||
return FALSE; | return FALSE; | ||||
} | } | ||||
if (check_view (task->cfg->views, item->s->symbol, task)) { | if (check_view (task->cfg->views, item->s->symbol, task)) { | ||||
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | |||||
#ifdef HAVE_CLOCK_GETTIME | |||||
# ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | |||||
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts1); | clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts1); | ||||
#elif defined(HAVE_CLOCK_VIRTUAL) | |||||
# elif defined(HAVE_CLOCK_VIRTUAL) | |||||
clock_gettime (CLOCK_VIRTUAL, &ts1); | clock_gettime (CLOCK_VIRTUAL, &ts1); | ||||
#else | |||||
# else | |||||
clock_gettime (CLOCK_REALTIME, &ts1); | clock_gettime (CLOCK_REALTIME, &ts1); | ||||
# endif | |||||
#else | |||||
if (gettimeofday (&tv1, NULL) == -1) { | |||||
msg_warn ("gettimeofday failed: %s", strerror (errno)); | |||||
} | |||||
#endif | #endif | ||||
item->func (task, item->user_data); | item->func (task, item->user_data); | ||||
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | |||||
#ifdef HAVE_CLOCK_GETTIME | |||||
# ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | |||||
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts2); | clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts2); | ||||
#elif defined(HAVE_CLOCK_VIRTUAL) | |||||
# elif defined(HAVE_CLOCK_VIRTUAL) | |||||
clock_gettime (CLOCK_VIRTUAL, &ts2); | clock_gettime (CLOCK_VIRTUAL, &ts2); | ||||
#else | |||||
# else | |||||
clock_gettime (CLOCK_REALTIME, &ts2); | clock_gettime (CLOCK_REALTIME, &ts2); | ||||
# endif | |||||
#else | |||||
if (gettimeofday (&tv2, NULL) == -1) { | |||||
msg_warn ("gettimeofday failed: %s", strerror (errno)); | |||||
} | |||||
#endif | #endif | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
diff = (ts2.tv_sec - ts1.tv_sec) * 1000000 + (ts2.tv_nsec - ts1.tv_nsec) / 1000; | diff = (ts2.tv_sec - ts1.tv_sec) * 1000000 + (ts2.tv_nsec - ts1.tv_nsec) / 1000; | ||||
#else | |||||
diff = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec); | |||||
#endif | |||||
item->s->avg_time = set_counter (item->s->symbol, diff); | item->s->avg_time = set_counter (item->s->symbol, diff); | ||||
} | } | ||||
return new; | return new; | ||||
} | } | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
const char * | const char * | ||||
calculate_check_time (struct timespec *begin, int resolution) | calculate_check_time (struct timespec *begin, int resolution) | ||||
#else | |||||
const char * | |||||
calculate_check_time (struct timeval *begin, int resolution) | |||||
#endif | |||||
{ | { | ||||
struct timespec ts; | |||||
double diff; | double diff; | ||||
static char res[sizeof ("100000.000")]; | static char res[sizeof ("100000.000")]; | ||||
static char fmt[sizeof ("%.10f")]; | static char fmt[sizeof ("%.10f")]; | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
struct timespec ts; | |||||
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | #ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | ||||
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts); | clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts); | ||||
diff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ | diff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ | ||||
(ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */ | (ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */ | ||||
#else | |||||
struct timeval tv; | |||||
if (gettimeofday (&tv, NULL) == -1) { | |||||
msg_warn ("gettimeofday failed: %s", strerror (errno)); | |||||
} | |||||
diff = (tv.tv_sec - begin->tv_sec) * 1000. + /* Seconds */ | |||||
(tv.tv_usec - begin->tv_usec) / 1000.; /* Microseconds */ | |||||
#endif | |||||
sprintf (fmt, "%%.%df", resolution); | sprintf (fmt, "%%.%df", resolution); | ||||
snprintf (res, sizeof (res), fmt, diff); | snprintf (res, sizeof (res), fmt, diff); | ||||
/* Replace %r with rcpt value and %f with from value, new string is allocated in pool */ | /* Replace %r with rcpt value and %f with from value, new string is allocated in pool */ | ||||
char* resolve_stat_filename (memory_pool_t *pool, char *pattern, char *rcpt, char *from); | char* resolve_stat_filename (memory_pool_t *pool, char *pattern, char *rcpt, char *from); | ||||
#ifdef HAVE_CLOCK_GETTIME | |||||
const char* calculate_check_time (struct timespec *begin, int resolution); | const char* calculate_check_time (struct timespec *begin, int resolution); | ||||
#else | |||||
const char* calculate_check_time (struct timeval *begin, int resolution); | |||||
#endif | |||||
double set_counter (const char *name, long int value); | double set_counter (const char *name, long int value); | ||||
new_task->cfg = worker->srv->cfg; | new_task->cfg = worker->srv->cfg; | ||||
new_task->from_addr.s_addr = INADDR_NONE; | new_task->from_addr.s_addr = INADDR_NONE; | ||||
new_task->view_checked = FALSE; | new_task->view_checked = FALSE; | ||||
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | |||||
#ifdef HAVE_CLOCK_GETTIME | |||||
# ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID | |||||
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &new_task->ts); | clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &new_task->ts); | ||||
#elif defined(HAVE_CLOCK_VIRTUAL) | |||||
# elif defined(HAVE_CLOCK_VIRTUAL) | |||||
clock_gettime (CLOCK_VIRTUAL, &new_task->ts); | clock_gettime (CLOCK_VIRTUAL, &new_task->ts); | ||||
#else | |||||
# else | |||||
clock_gettime (CLOCK_REALTIME, &new_task->ts); | clock_gettime (CLOCK_REALTIME, &new_task->ts); | ||||
# endif | |||||
#else | |||||
if (gettimeofday (&new_task->tv, NULL) == -1) { | |||||
msg_warn ("gettimeofday failed: %s", strerror (errno)); | |||||
} | |||||
#endif | #endif | ||||
io_tv.tv_sec = WORKER_IO_TIMEOUT; | io_tv.tv_sec = WORKER_IO_TIMEOUT; | ||||
io_tv.tv_usec = 0; | io_tv.tv_usec = 0; |