2007-03-24 19:49:30 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
|
2007-03-25 15:24:47 +02:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
2007-03-24 19:49:30 +01:00
|
|
|
#include <libnfnetlink/libnfnetlink.h>
|
|
|
|
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
|
|
|
|
|
|
|
|
#include "configfile.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "hashtable.h"
|
|
|
|
|
|
|
|
#define DEFAULT_HASHSIZE 127
|
2007-03-25 15:24:47 +02:00
|
|
|
#define DEFAULT_NETMASK "255.255.255.255"
|
2007-03-24 19:49:30 +01:00
|
|
|
|
|
|
|
static pthread_t ct_thread;
|
|
|
|
|
|
|
|
static struct nfct_handle *cth;
|
|
|
|
|
|
|
|
static struct hash_table *table[2];
|
|
|
|
static int hash_select = 0;
|
2007-03-25 15:24:47 +02:00
|
|
|
static struct in_addr netmask;
|
2007-03-24 19:49:30 +01:00
|
|
|
|
|
|
|
static int conntrack_event_cb(void *arg, unsigned int flags, int type, void *privdata)
|
|
|
|
{
|
|
|
|
struct nfct_conntrack *ct = (struct nfct_conntrack *)arg;
|
|
|
|
|
|
|
|
if (ct->tuple[NFCT_DIR_ORIGINAL].l3protonum != AF_INET)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
struct hash_entry *entry = malloc(sizeof(struct hash_entry));
|
|
|
|
if (entry == NULL) {
|
|
|
|
log_print(LOG_WARN, "conntrack_event_cb: out of memory");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-03-25 15:24:47 +02:00
|
|
|
entry->src_ip = (ct->tuple[NFCT_DIR_ORIGINAL].src.v4 & netmask.s_addr);
|
2007-03-24 19:49:30 +01:00
|
|
|
entry->protonum = ct->tuple[NFCT_DIR_ORIGINAL].protonum;
|
|
|
|
entry->dst_port = ct->tuple[NFCT_DIR_ORIGINAL].l4dst.tcp.port;
|
|
|
|
|
|
|
|
entry->src_bytes = ct->counters[NFCT_DIR_ORIGINAL].bytes;
|
|
|
|
entry->dst_bytes = ct->counters[NFCT_DIR_REPLY].bytes;
|
|
|
|
|
|
|
|
hash_add(table[hash_select], entry);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-03-25 15:24:47 +02:00
|
|
|
struct hash_table * conntrack_get_hash(void)
|
2007-03-24 19:49:30 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* switch hashtable
|
|
|
|
* -> conntrack_event_cb will use the empty hash next time, and we dump now the full one
|
|
|
|
* -> if conntrack_event_cb is running *now* (on the full hash), we have to wait a bit
|
|
|
|
* -> but since we are faster than dump intervall, conntrack_event_cb never waits
|
|
|
|
*/
|
|
|
|
int used_hash = hash_select;
|
|
|
|
hash_select ^= 0x01;
|
2007-03-25 15:24:47 +02:00
|
|
|
return table[used_hash];
|
2007-03-24 19:49:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int conntrack_init(void)
|
|
|
|
{
|
2007-03-25 15:24:47 +02:00
|
|
|
char *mask = config_get_string("global", "netmask", DEFAULT_NETMASK);
|
|
|
|
if (inet_aton(mask, &netmask) == 0) {
|
|
|
|
log_print(LOG_ERROR, "conntrack_init: invalid netmask");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-03-24 19:49:30 +01:00
|
|
|
cth = nfct_open(CONNTRACK, NF_NETLINK_CONNTRACK_DESTROY);
|
|
|
|
if (cth == NULL) {
|
|
|
|
log_print(LOG_ERROR, "conntrack_init: nfct_open()");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int size = config_get_int("global", "hashsize", DEFAULT_HASHSIZE);
|
|
|
|
|
|
|
|
table[0] = create_hash(size);
|
|
|
|
if (table[0] == NULL) {
|
|
|
|
log_print(LOG_ERROR, "conntrack_init: create_hash(0)");
|
|
|
|
nfct_close(cth);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
table[1] = create_hash(size);
|
|
|
|
if (table[1] == NULL) {
|
|
|
|
log_print(LOG_ERROR, "conntrack_init: create_hash(1)");
|
|
|
|
destroy_hash(table[0]);
|
|
|
|
nfct_close(cth);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nfct_register_callback(cth, conntrack_event_cb, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int event_thread(void *arg)
|
|
|
|
{
|
|
|
|
nfct_event_conntrack(cth);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int conntrack_start_event_thread(void)
|
|
|
|
{
|
|
|
|
/* startup conntrack event listener */
|
|
|
|
pthread_attr_t attr;
|
|
|
|
|
|
|
|
pthread_attr_init(&attr);
|
|
|
|
pthread_attr_setstacksize(&attr, 65536);
|
|
|
|
pthread_create(&ct_thread, &attr, (void *)&event_thread, NULL);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int conntrack_close(void)
|
|
|
|
{
|
|
|
|
destroy_hash(table[1]);
|
|
|
|
destroy_hash(table[0]);
|
|
|
|
|
|
|
|
nfct_close(cth);
|
|
|
|
return 0;
|
|
|
|
}
|