summaryrefslogtreecommitdiffstats
path: root/input
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2010-01-11 17:38:22 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2010-01-17 22:23:16 +0100
commit1f50a6a2d5a4ede3505f9298b25fc3e081cbc443 (patch)
tree334adcffa9ff4029056baac4129d9e35bba66816 /input
parentdf78c5c6863c7f68ef7a089e26dab22540f3f015 (diff)
NFCT: change `pollinterval' behaviour
This patch adds support for poll-based logging. Basically, ulogd polls from the kernel periodically to log entries. You can use the `pollinterval' option in the configuration file to set the polling period. This patch changes the current behaviour of `pollinterval' that allowed to mix both the event-driven logging with polling periodically from the kernel. I have tried to look for anyone in google (and asking Eric Leblond) using this feature but I found noone. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'input')
-rw-r--r--input/flow/ulogd_inpflow_NFCT.c128
1 files changed, 120 insertions, 8 deletions
diff --git a/input/flow/ulogd_inpflow_NFCT.c b/input/flow/ulogd_inpflow_NFCT.c
index 5f42523..095a8fb 100644
--- a/input/flow/ulogd_inpflow_NFCT.c
+++ b/input/flow/ulogd_inpflow_NFCT.c
@@ -567,7 +567,6 @@ do_propagate_ct(struct ulogd_pluginstance *upi,
propagate_ct(upi, ct, type, ts);
}
-/* XXX: pollinterval needs a different handler */
static int event_handler(enum nf_conntrack_msg_type type,
struct nf_conntrack *ct,
void *data)
@@ -646,6 +645,40 @@ static int event_handler(enum nf_conntrack_msg_type type,
return NFCT_CB_CONTINUE;
}
+static int
+polling_handler(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct, void *data)
+{
+ struct ulogd_pluginstance *upi = data;
+ struct nfct_pluginstance *cpi =
+ (struct nfct_pluginstance *) upi->private;
+ struct ct_timestamp *ts = NULL;
+ struct ct_timestamp tmp = {
+ .ct = ct,
+ };
+
+ switch(type) {
+ case NFCT_T_UPDATE:
+ ts = hashtable_get(cpi->ct_active, &tmp);
+ if (ts)
+ nfct_copy(ts->ct, ct, NFCT_CP_META);
+ else {
+ ts = hashtable_add(cpi->ct_active, &tmp);
+ if (ts == NULL)
+ return NFCT_CB_CONTINUE;
+
+ gettimeofday(&ts->time[START], NULL);
+ return NFCT_CB_STOLEN;
+ }
+ break;
+ default:
+ ulogd_log(ULOGD_NOTICE, "unknown netlink message type\n");
+ break;
+ }
+
+ return NFCT_CB_CONTINUE;
+}
+
static int setnlbufsiz(struct ulogd_pluginstance *upi, int size)
{
struct nfct_pluginstance *cpi =
@@ -804,13 +837,15 @@ static int get_ctr_zero(struct ulogd_pluginstance *upi)
return nfct_query(cpi->cth, NFCT_Q_DUMP_RESET, &family);
}
-static void getctr_timer_cb(struct ulogd_timer *t, void *data)
+static void polling_timer_cb(struct ulogd_timer *t, void *data)
{
struct ulogd_pluginstance *upi = data;
struct nfct_pluginstance *cpi =
(struct nfct_pluginstance *)upi->private;
+ int family = AF_UNSPEC;
- get_ctr_zero(upi);
+ nfct_query(cpi->pgh, NFCT_Q_DUMP, &family);
+ hashtable_iterate(cpi->ct_active, upi, do_purge);
ulogd_add_timer(&cpi->timer, pollint_ce(upi->config_kset).u.value);
}
@@ -825,7 +860,7 @@ static int configure_nfct(struct ulogd_pluginstance *upi,
if (ret < 0)
return ret;
- ulogd_init_timer(&cpi->timer, upi, getctr_timer_cb);
+ ulogd_init_timer(&cpi->timer, upi, polling_timer_cb);
if (pollint_ce(upi->config_kset).u.value != 0)
ulogd_add_timer(&cpi->timer,
pollint_ce(upi->config_kset).u.value);
@@ -843,7 +878,7 @@ static void overrun_timeout(struct ulogd_timer *a, void *data)
nfct_send(cpi->ovh, NFCT_Q_DUMP, &family);
}
-static int constructor_nfct(struct ulogd_pluginstance *upi)
+static int constructor_nfct_events(struct ulogd_pluginstance *upi)
{
struct nfct_pluginstance *cpi =
(struct nfct_pluginstance *)upi->private;
@@ -927,6 +962,7 @@ static int constructor_nfct(struct ulogd_pluginstance *upi)
}
}
+ ulogd_log(ULOGD_NOTICE, "NFCT plugin working in event mode\n");
return 0;
err_pgh:
@@ -941,9 +977,61 @@ err_cth:
return -1;
}
-static int destructor_nfct(struct ulogd_pluginstance *pi)
+static int constructor_nfct_polling(struct ulogd_pluginstance *upi)
{
- struct nfct_pluginstance *cpi = (void *) pi->private;
+ struct nfct_pluginstance *cpi =
+ (struct nfct_pluginstance *)upi->private;
+
+ if (usehash_ce(upi->config_kset).u.value == 0) {
+ ulogd_log(ULOGD_FATAL, "NFCT polling mode requires "
+ "the hashtable\n");
+ goto err;
+ }
+
+ cpi->pgh = nfct_open(NFNL_SUBSYS_CTNETLINK, 0);
+ if (!cpi->pgh) {
+ ulogd_log(ULOGD_FATAL, "error opening ctnetlink\n");
+ goto err;
+ }
+ nfct_callback_register(cpi->pgh, NFCT_T_ALL, &polling_handler, upi);
+
+ cpi->ct_active =
+ hashtable_create(buckets_ce(upi->config_kset).u.value,
+ maxentries_ce(upi->config_kset).u.value,
+ sizeof(struct ct_timestamp),
+ hash,
+ compare);
+ if (!cpi->ct_active) {
+ ulogd_log(ULOGD_FATAL, "error allocating hash\n");
+ goto err_hashtable;
+ }
+
+ ulogd_log(ULOGD_NOTICE, "NFCT working in polling mode\n");
+ return 0;
+
+err_hashtable:
+ nfct_close(cpi->pgh);
+err:
+ return -1;
+}
+
+static int constructor_nfct(struct ulogd_pluginstance *upi)
+{
+ if (pollint_ce(upi->config_kset).u.value == 0) {
+ /* listen to ctnetlink events. */
+ return constructor_nfct_events(upi);
+ } else {
+ /* poll from ctnetlink periodically. */
+ return constructor_nfct_polling(upi);
+ }
+ /* should not ever happen. */
+ ulogd_log(ULOGD_FATAL, "invalid NFCT configuration\n");
+ return -1;
+}
+
+static int destructor_nfct_events(struct ulogd_pluginstance *upi)
+{
+ struct nfct_pluginstance *cpi = (void *) upi->private;
int rc;
ulogd_unregister_fd(&cpi->nfct_fd);
@@ -953,7 +1041,7 @@ static int destructor_nfct(struct ulogd_pluginstance *pi)
return rc;
- if (usehash_ce(pi->config_kset).u.value != 0) {
+ if (usehash_ce(upi->config_kset).u.value != 0) {
ulogd_del_timer(&cpi->ov_timer);
ulogd_unregister_fd(&cpi->nfct_ov);
@@ -971,6 +1059,30 @@ static int destructor_nfct(struct ulogd_pluginstance *pi)
return 0;
}
+static int destructor_nfct_polling(struct ulogd_pluginstance *upi)
+{
+ int rc;
+ struct nfct_pluginstance *cpi = (void *)upi->private;
+
+ rc = nfct_close(cpi->pgh);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int destructor_nfct(struct ulogd_pluginstance *upi)
+{
+ if (pollint_ce(upi->config_kset).u.value == 0) {
+ return destructor_nfct_events(upi);
+ } else {
+ return destructor_nfct_polling(upi);
+ }
+ /* should not ever happen. */
+ ulogd_log(ULOGD_FATAL, "invalid NFCT configuration\n");
+ return -1;
+}
+
static void signal_nfct(struct ulogd_pluginstance *pi, int signal)
{
switch (signal) {