summaryrefslogtreecommitdiffstats
path: root/src/map.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map.c')
-rw-r--r--src/map.c439
1 files changed, 218 insertions, 221 deletions
diff --git a/src/map.c b/src/map.c
index 950a154d8..d78ac96e1 100644
--- a/src/map.c
+++ b/src/map.c
@@ -31,30 +31,30 @@
#include "util.h"
#include "mem_pool.h"
-static memory_pool_t *map_pool = NULL;
+static memory_pool_t *map_pool = NULL;
-static GList *maps = NULL;
-static char *hash_fill = "1";
+static GList *maps = NULL;
+static char *hash_fill = "1";
/* Http reply */
struct http_reply {
- int code;
- GHashTable *headers;
- char *cur_header;
+ int code;
+ GHashTable *headers;
+ char *cur_header;
- int parser_state;
+ int parser_state;
};
struct http_callback_data {
- struct event ev;
- struct timeval tv;
- struct rspamd_map *map;
- struct http_map_data *data;
- struct http_reply *reply;
- struct map_cb_data cbdata;
-
- int state;
- int fd;
+ struct event ev;
+ struct timeval tv;
+ struct rspamd_map *map;
+ struct http_map_data *data;
+ struct http_reply *reply;
+ struct map_cb_data cbdata;
+
+ int state;
+ int fd;
};
/* Value in seconds after whitch we would try to do stat on list file */
@@ -66,7 +66,7 @@ struct http_callback_data {
static int
connect_http (struct rspamd_map *map, struct http_map_data *data, gboolean is_async)
{
- int sock;
+ int sock;
if ((sock = make_tcp_socket (&data->addr, data->port, FALSE, is_async)) == -1) {
msg_info ("connect_http: cannot connect to http server %s: %d, %s", data->host, errno, strerror (errno));
@@ -79,13 +79,10 @@ connect_http (struct rspamd_map *map, struct http_map_data *data, gboolean is_as
static void
write_http_request (struct rspamd_map *map, struct http_map_data *data, int sock)
{
- char outbuf[BUFSIZ];
- int r;
+ char outbuf[BUFSIZ];
+ int r;
- r = snprintf (outbuf, sizeof (outbuf), "GET %s%s HTTP/1.1" CRLF
- "Connection: close" CRLF
- "Host: %s" CRLF, (*data->path == '/') ? "" : "/",
- data->path, data->host);
+ r = snprintf (outbuf, sizeof (outbuf), "GET %s%s HTTP/1.1" CRLF "Connection: close" CRLF "Host: %s" CRLF, (*data->path == '/') ? "" : "/", data->path, data->host);
if (data->last_checked != 0) {
r += snprintf (outbuf + r, sizeof (outbuf) - r, "If-Modified-Since: %s" CRLF, asctime (gmtime (&data->last_checked)));
}
@@ -97,88 +94,88 @@ write_http_request (struct rspamd_map *map, struct http_map_data *data, int sock
}
}
-static u_char *
-parse_http_reply (u_char *chunk, size_t len, struct http_reply *reply)
+static u_char *
+parse_http_reply (u_char * chunk, size_t len, struct http_reply *reply)
{
- u_char *s, *p, *err_str, *tmp;
+ u_char *s, *p, *err_str, *tmp;
p = chunk;
s = chunk;
while (p - chunk < len) {
switch (reply->parser_state) {
/* Search status code */
- case 0:
- /* Search for status code */
- if (*p != ' ') {
- p ++;
- }
- else {
- /* Try to parse HTTP reply code */
- reply->code = strtoul (++p, (char **)&err_str, 10);
- if (*err_str != ' ') {
- msg_info ("parse_http_reply: error while reading HTTP status code: %s", p);
- return NULL;
- }
- /* Now skip to end of status string */
- reply->parser_state = 1;
- continue;
+ case 0:
+ /* Search for status code */
+ if (*p != ' ') {
+ p++;
+ }
+ else {
+ /* Try to parse HTTP reply code */
+ reply->code = strtoul (++p, (char **)&err_str, 10);
+ if (*err_str != ' ') {
+ msg_info ("parse_http_reply: error while reading HTTP status code: %s", p);
+ return NULL;
}
- break;
+ /* Now skip to end of status string */
+ reply->parser_state = 1;
+ continue;
+ }
+ break;
/* Skip to end of line */
- case 1:
- if (*p == '\n') {
- /* Switch to read header state */
- reply->parser_state = 2;
- }
- /* Each skipped symbol is proceeded */
- s = ++p;
- break;
+ case 1:
+ if (*p == '\n') {
+ /* Switch to read header state */
+ reply->parser_state = 2;
+ }
+ /* Each skipped symbol is proceeded */
+ s = ++p;
+ break;
/* Read header value */
- case 2:
- if (*p == ':') {
- reply->cur_header = g_malloc (p - s + 1);
- g_strlcpy (reply->cur_header, s, p - s + 1);
- reply->parser_state = 3;
- }
- else if (*p == '\r' && *(p + 1) == '\n') {
- /* Last empty line */
- reply->parser_state = 5;
- }
- p ++;
- break;
+ case 2:
+ if (*p == ':') {
+ reply->cur_header = g_malloc (p - s + 1);
+ g_strlcpy (reply->cur_header, s, p - s + 1);
+ reply->parser_state = 3;
+ }
+ else if (*p == '\r' && *(p + 1) == '\n') {
+ /* Last empty line */
+ reply->parser_state = 5;
+ }
+ p++;
+ break;
/* Skip spaces after header name */
- case 3:
- if (*p != ' ') {
- s = p;
- reply->parser_state = 4;
- }
- else {
- p ++;
- }
- break;
+ case 3:
+ if (*p != ' ') {
+ s = p;
+ reply->parser_state = 4;
+ }
+ else {
+ p++;
+ }
+ break;
/* Read header value */
- case 4:
- if (*p == '\r') {
- if (reply->cur_header != NULL) {
- tmp = g_malloc (p - s + 1);
- g_strlcpy (tmp, s, p - s + 1);
- g_hash_table_insert (reply->headers, reply->cur_header, tmp);
- reply->cur_header = NULL;
- }
- reply->parser_state = 1;
+ case 4:
+ if (*p == '\r') {
+ if (reply->cur_header != NULL) {
+ tmp = g_malloc (p - s + 1);
+ g_strlcpy (tmp, s, p - s + 1);
+ g_hash_table_insert (reply->headers, reply->cur_header, tmp);
+ reply->cur_header = NULL;
}
- p ++;
- break;
- case 5:
- /* Set pointer to begining of HTTP body */
- p ++;
- s = p;
- reply->parser_state = 6;
- break;
- case 6:
- /* Headers parsed, just return */
- return p;
- break;
+ reply->parser_state = 1;
+ }
+ p++;
+ break;
+ case 5:
+ /* Set pointer to begining of HTTP body */
+ p++;
+ s = p;
+ reply->parser_state = 6;
+ break;
+ case 6:
+ /* Headers parsed, just return */
+ return p;
+ break;
}
}
@@ -186,39 +183,39 @@ parse_http_reply (u_char *chunk, size_t len, struct http_reply *reply)
}
static int
-read_chunk_header (u_char *buf, size_t len, struct http_map_data *data)
+read_chunk_header (u_char * buf, size_t len, struct http_map_data *data)
{
- u_char chunkbuf[32], *p, *c;
- int skip = 0;
+ u_char chunkbuf[32], *p, *c;
+ int skip = 0;
p = chunkbuf;
c = buf;
while (g_ascii_isxdigit (*c) && p - chunkbuf < sizeof (chunkbuf) - 1) {
*p++ = *c++;
- skip ++;
+ skip++;
}
*p = '\0';
data->chunk = strtoul (chunkbuf, NULL, 16);
/* Now skip to CRLF */
while (*c != '\n' && c - buf < len) {
- c ++;
- skip ++;
+ c++;
+ skip++;
}
if (*c == '\n') {
- skip ++;
- c ++;
+ skip++;
+ c++;
}
data->chunk_read = 0;
-
+
return skip;
}
-static gboolean
-read_http_chunked (u_char *buf, size_t len, struct rspamd_map *map, struct http_map_data *data, struct map_cb_data *cbdata)
+static gboolean
+read_http_chunked (u_char * buf, size_t len, struct rspamd_map *map, struct http_map_data *data, struct map_cb_data *cbdata)
{
- u_char *p = buf, *remain;
- uint32_t skip = 0, rlen;
-
+ u_char *p = buf, *remain;
+ uint32_t skip = 0, rlen;
+
if (data->chunk == 0) {
/* Read first chunk data */
skip = read_chunk_header (buf, len, data);
@@ -261,17 +258,17 @@ read_http_chunked (u_char *buf, size_t len, struct rspamd_map *map, struct http_
return TRUE;
}
-static gboolean
+static gboolean
read_http_common (struct rspamd_map *map, struct http_map_data *data, struct http_reply *reply, struct map_cb_data *cbdata, int fd)
{
- u_char buf[BUFSIZ], *remain, *pos;
- int rlen;
- ssize_t r;
- char *te;
+ u_char buf[BUFSIZ], *remain, *pos;
+ int rlen;
+ ssize_t r;
+ char *te;
rlen = 0;
if ((r = read (fd, buf + rlen, sizeof (buf) - rlen - 1)) > 0) {
- buf[r ++] = '\0';
+ buf[r++] = '\0';
remain = parse_http_reply (buf, r - 1, reply);
if (remain != NULL && remain != buf) {
/* copy remaining buffer to start of buffer */
@@ -318,9 +315,9 @@ read_http_common (struct rspamd_map *map, struct http_map_data *data, struct htt
static void
read_http_sync (struct rspamd_map *map, struct http_map_data *data)
{
- struct map_cb_data cbdata;
- int fd;
- struct http_reply *repl;
+ struct map_cb_data cbdata;
+ int fd;
+ struct http_reply *repl;
if (map->read_callback == NULL || map->fin_callback == NULL) {
msg_err ("read_map_file: bad callback for reading map file");
@@ -332,7 +329,7 @@ read_http_sync (struct rspamd_map *map, struct http_map_data *data)
return;
}
write_http_request (map, data, fd);
-
+
cbdata.state = 0;
cbdata.prev_data = *map->user_data;
cbdata.cur_data = NULL;
@@ -341,7 +338,7 @@ read_http_sync (struct rspamd_map *map, struct http_map_data *data)
repl->parser_state = 0;
repl->code = 404;
repl->headers = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, g_free);
-
+
while (read_http_common (map, data, repl, &cbdata, fd));
close (fd);
@@ -357,11 +354,11 @@ read_http_sync (struct rspamd_map *map, struct http_map_data *data)
static void
read_map_file (struct rspamd_map *map, struct file_map_data *data)
{
- struct map_cb_data cbdata;
- u_char buf[BUFSIZ], *remain;
- ssize_t r;
- int fd, rlen;
-
+ struct map_cb_data cbdata;
+ u_char buf[BUFSIZ], *remain;
+ ssize_t r;
+ int fd, rlen;
+
if (map->read_callback == NULL || map->fin_callback == NULL) {
msg_err ("read_map_file: bad callback for reading map file");
return;
@@ -375,10 +372,10 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data)
cbdata.state = 0;
cbdata.prev_data = *map->user_data;
cbdata.cur_data = NULL;
-
+
rlen = 0;
while ((r = read (fd, buf + rlen, sizeof (buf) - rlen - 1)) > 0) {
- buf[r ++] = '\0';
+ buf[r++] = '\0';
remain = map->read_callback (map->pool, buf, r - 1, &cbdata);
if (remain != NULL) {
/* copy remaining buffer to start of buffer */
@@ -386,24 +383,24 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data)
memmove (buf, remain, rlen);
}
}
-
+
close (fd);
map->fin_callback (map->pool, &cbdata);
*map->user_data = cbdata.cur_data;
}
-gboolean
+gboolean
add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data)
{
- struct rspamd_map *new_map;
- enum fetch_proto proto;
- const char *def, *p, *hostend;
- struct file_map_data *fdata;
- struct http_map_data *hdata;
- char portbuf[6];
- int i, s, fd;
- struct hostent *hent;
+ struct rspamd_map *new_map;
+ enum fetch_proto proto;
+ const char *def, *p, *hostend;
+ struct file_map_data *fdata;
+ struct http_map_data *hdata;
+ char portbuf[6];
+ int i, s, fd;
+ struct hostent *hent;
/* First of all detect protocol line */
if (strncmp (map_line, "http://", sizeof ("http://") - 1) == 0) {
@@ -427,7 +424,7 @@ add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback
new_map->fin_callback = fin_callback;
new_map->user_data = user_data;
new_map->protocol = proto;
-
+
/* Now check for each proto separately */
if (proto == PROTO_FILE) {
if ((fd = open (def, O_RDONLY)) == -1) {
@@ -445,9 +442,9 @@ add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback
if ((p = strchr (def, ':')) != NULL) {
hostend = p;
i = 0;
- p ++;
+ p++;
while (g_ascii_isdigit (*p) && i < sizeof (portbuf) - 1) {
- portbuf[i ++] = *p ++;
+ portbuf[i++] = *p++;
}
if (*p != '/') {
msg_info ("add_map: bad http map definition: %s", def);
@@ -478,7 +475,7 @@ add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback
return FALSE;
}
else {
- memcpy (&hdata->addr, hent->h_addr, sizeof(struct in_addr));
+ memcpy (&hdata->addr, hent->h_addr, sizeof (struct in_addr));
}
}
/* Now try to connect */
@@ -497,12 +494,12 @@ add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback
return TRUE;
}
-typedef void (*insert_func)(gpointer st, gconstpointer key, gpointer value);
+typedef void (*insert_func) (gpointer st, gconstpointer key, gpointer value);
-static u_char*
-abstract_parse_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data, insert_func func)
+static u_char *
+abstract_parse_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data, insert_func func)
{
- u_char *s, *p, *str, *start;
+ u_char *s, *p, *str, *start;
p = chunk;
start = p;
@@ -513,53 +510,53 @@ abstract_parse_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_
while (p - chunk < len) {
switch (data->state) {
/* READ_SYMBOL */
- case 0:
- if (*p == '#') {
- if (s != str) {
- *s = '\0';
- s = memory_pool_strdup (pool, g_strstrip (str));
- if (strlen (s) > 0) {
- func (data->cur_data, s, hash_fill);
- }
- s = str;
- start = p;
- }
- data->state = 1;
- }
- else if (*p == '\r' || *p == '\n') {
- if (s != str) {
- *s = '\0';
- s = memory_pool_strdup (pool, g_strstrip (str));
- if (strlen (s) > 0) {
- func (data->cur_data, s, hash_fill);
- }
- s = str;
- start = p;
+ case 0:
+ if (*p == '#') {
+ if (s != str) {
+ *s = '\0';
+ s = memory_pool_strdup (pool, g_strstrip (str));
+ if (strlen (s) > 0) {
+ func (data->cur_data, s, hash_fill);
}
- while (*p == '\r' || *p == '\n') {
- p ++;
- }
- }
- else {
- *s = *p;
- s ++;
- p ++;
+ s = str;
+ start = p;
}
- break;
- /* SKIP_COMMENT */
- case 1:
- if (*p == '\r' || *p == '\n') {
- while (*p == '\r' || *p == '\n') {
- p ++;
+ data->state = 1;
+ }
+ else if (*p == '\r' || *p == '\n') {
+ if (s != str) {
+ *s = '\0';
+ s = memory_pool_strdup (pool, g_strstrip (str));
+ if (strlen (s) > 0) {
+ func (data->cur_data, s, hash_fill);
}
s = str;
start = p;
- data->state = 0;
}
- else {
- p ++;
+ while (*p == '\r' || *p == '\n') {
+ p++;
}
- break;
+ }
+ else {
+ *s = *p;
+ s++;
+ p++;
+ }
+ break;
+ /* SKIP_COMMENT */
+ case 1:
+ if (*p == '\r' || *p == '\n') {
+ while (*p == '\r' || *p == '\n') {
+ p++;
+ }
+ s = str;
+ start = p;
+ data->state = 0;
+ }
+ else {
+ p++;
+ }
+ break;
}
}
@@ -571,19 +568,19 @@ abstract_parse_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_
static void
radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value)
{
- radix_tree_t *tree = st;
-
- uint32_t mask = 0xFFFFFFFF;
- uint32_t ip;
- char *token, *ipnet, *err_str, **strv, **cur;
- struct in_addr ina;
- int k;
-
- strv = g_strsplit_set ((char *)key, " ,;", 0);
+ radix_tree_t *tree = st;
+
+ uint32_t mask = 0xFFFFFFFF;
+ uint32_t ip;
+ char *token, *ipnet, *err_str, **strv, **cur;
+ struct in_addr ina;
+ int k;
+
+ strv = g_strsplit_set ((char *)key, " ,;", 0);
cur = strv;
- while (*cur) {
+ while (*cur) {
if (**cur == '\0') {
- cur ++;
+ cur++;
continue;
}
ipnet = *cur;
@@ -609,7 +606,7 @@ radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value)
return;
}
- ip = ntohl ((uint32_t)ina.s_addr);
+ ip = ntohl ((uint32_t) ina.s_addr);
k = radix32tree_insert (tree, ip, mask, 1);
if (k == -1) {
msg_warn ("radix_tree_insert_helper: cannot insert ip to tree: %s, mask %X", inet_ntoa (ina), mask);
@@ -617,40 +614,40 @@ radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value)
else if (k == 1) {
msg_warn ("add_ip_radix: ip %s, mask %X, value already exists", inet_ntoa (ina), mask);
}
- cur ++;
+ cur++;
}
g_strfreev (strv);
}
-u_char *
-read_host_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data)
-{
+u_char *
+read_host_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
+{
if (data->cur_data == NULL) {
data->cur_data = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
}
- return abstract_parse_list (pool, chunk, len, data, (insert_func)g_hash_table_insert);
+ return abstract_parse_list (pool, chunk, len, data, (insert_func) g_hash_table_insert);
}
-void
-fin_host_list (memory_pool_t *pool, struct map_cb_data *data)
+void
+fin_host_list (memory_pool_t * pool, struct map_cb_data *data)
{
if (data->prev_data) {
g_hash_table_destroy (data->prev_data);
}
}
-u_char *
-read_radix_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data)
+u_char *
+read_radix_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
{
if (data->cur_data == NULL) {
data->cur_data = radix_tree_create ();
}
- return abstract_parse_list (pool, chunk, len, data, (insert_func)radix_tree_insert_helper);
+ return abstract_parse_list (pool, chunk, len, data, (insert_func) radix_tree_insert_helper);
}
-void
-fin_radix_list (memory_pool_t *pool, struct map_cb_data *data)
+void
+fin_radix_list (memory_pool_t * pool, struct map_cb_data *data)
{
if (data->prev_data) {
radix_tree_free (data->prev_data);
@@ -660,9 +657,9 @@ fin_radix_list (memory_pool_t *pool, struct map_cb_data *data)
static void
file_callback (int fd, short what, void *ud)
{
- struct rspamd_map *map = ud;
- struct file_map_data *data = map->map_data;
- struct stat st;
+ struct rspamd_map *map = ud;
+ struct file_map_data *data = map->map_data;
+ struct stat st;
/* Plan event again with jitter */
evtimer_del (&map->ev);
@@ -676,7 +673,7 @@ file_callback (int fd, short what, void *ud)
else {
return;
}
-
+
msg_info ("rereading map file %s", data->filename);
read_map_file (map, data);
}
@@ -696,8 +693,8 @@ free_http_cbdata (struct http_callback_data *cbd)
static void
http_async_callback (int fd, short what, void *ud)
{
- struct http_callback_data *cbd = ud;
-
+ struct http_callback_data *cbd = ud;
+
/* Begin of connection */
if (what == EV_WRITE) {
if (cbd->state == 0) {
@@ -745,7 +742,7 @@ http_async_callback (int fd, short what, void *ud)
free_http_cbdata (cbd);
return;
- }
+ }
else if (cbd->state == 1) {
/* Write to log that data is modified */
msg_info ("http_async_callback: rereading map data from %s", cbd->data->host);
@@ -763,10 +760,10 @@ http_async_callback (int fd, short what, void *ud)
static void
http_callback (int fd, short what, void *ud)
{
- struct rspamd_map *map = ud;
- struct http_map_data *data = map->map_data;
- int sock;
- struct http_callback_data *cbd;
+ struct rspamd_map *map = ud;
+ struct http_map_data *data = map->map_data;
+ int sock;
+ struct http_callback_data *cbd;
/* Plan event again with jitter */
evtimer_del (&map->ev);
@@ -794,12 +791,12 @@ http_callback (int fd, short what, void *ud)
}
/* Start watching event for all maps */
-void
+void
start_map_watch (void)
{
- GList *cur = maps;
- struct rspamd_map *map;
-
+ GList *cur = maps;
+ struct rspamd_map *map;
+
/* First of all do synced read of data */
while (cur) {
map = cur->data;