summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-07-23 16:51:39 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-07-23 16:51:39 +0200
commit167a57cb822eb6ce3759f5de3a11c59849b494e4 (patch)
tree77b93103a50e66fabcfe51302c9c46ac746c9e91 /src
parent77b1fdb824eb45213df4f57224e8e799fed43ded (diff)
add support for kernel-space filtering via BSF
This patch adds support for kernel-space filtering via BSF by means of the libnetfilter_conntrack's BSF high-level API. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/netlink.c14
-rw-r--r--src/read_config_yy.y90
2 files changed, 104 insertions, 0 deletions
diff --git a/src/netlink.c b/src/netlink.c
index 1823280..1287454 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -85,6 +85,20 @@ int nl_init_event_handler(void)
if (!STATE(event))
return -1;
+ if (STATE(filter)) {
+ if (nfct_filter_attach(nfct_fd(STATE(event)),
+ STATE(filter)) == -1) {
+ dlog(LOG_NOTICE, "cannot set netlink kernel-space "
+ "event filtering, defaulting to "
+ "user-space. We suggest you to "
+ "upgrade your Linux kernel to "
+ ">= 2.6.26. Operation returns: %s",
+ strerror(errno));
+ /* don't fail here, old kernels don't support this */
+ }
+ nfct_filter_destroy(STATE(filter));
+ }
+
fcntl(nfct_fd(STATE(event)), F_SETFL, O_NONBLOCK);
/* set up socket buffer size */
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 2a1c88c..33a435c 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -27,12 +27,16 @@
#include "conntrackd.h"
#include "bitops.h"
#include <syslog.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
extern char *yytext;
extern int yylineno;
struct ct_conf conf;
+
+static void __kernel_filter_start(void);
+static void __kernel_filter_add_state(int value);
%}
%union {
@@ -558,54 +562,72 @@ tcp_state: T_SYN_SENT
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_SYN_SENT);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_SYN_SENT);
};
tcp_state: T_SYN_RECV
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_SYN_RECV);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_SYN_RECV);
};
tcp_state: T_ESTABLISHED
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_ESTABLISHED);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_ESTABLISHED);
};
tcp_state: T_FIN_WAIT
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_FIN_WAIT);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_FIN_WAIT);
};
tcp_state: T_CLOSE_WAIT
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_CLOSE_WAIT);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_CLOSE_WAIT);
};
tcp_state: T_LAST_ACK
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_LAST_ACK);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_LAST_ACK);
};
tcp_state: T_TIME_WAIT
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_TIME_WAIT);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_TIME_WAIT);
};
tcp_state: T_CLOSE
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_CLOSE);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_CLOSE);
};
tcp_state: T_LISTEN
{
ct_filter_add_state(STATE(us_filter),
IPPROTO_TCP,
TCP_CONNTRACK_LISTEN);
+
+ __kernel_filter_add_state(TCP_CONNTRACK_LISTEN);
};
cache_writethrough: T_WRITE_THROUGH T_ON
@@ -666,6 +688,8 @@ filter_item : T_PROTOCOL T_ACCEPT '{' filter_protocol_list '}'
ct_filter_set_logic(STATE(us_filter),
CT_FILTER_L4PROTO,
CT_FILTER_POSITIVE);
+
+ __kernel_filter_start();
};
filter_item : T_PROTOCOL T_IGNORE '{' filter_protocol_list '}'
@@ -673,6 +697,12 @@ filter_item : T_PROTOCOL T_IGNORE '{' filter_protocol_list '}'
ct_filter_set_logic(STATE(us_filter),
CT_FILTER_L4PROTO,
CT_FILTER_NEGATIVE);
+
+ __kernel_filter_start();
+
+ nfct_filter_set_logic(STATE(filter),
+ NFCT_FILTER_L4PROTO,
+ NFCT_FILTER_LOGIC_NEGATIVE);
};
filter_protocol_list :
@@ -689,6 +719,12 @@ filter_protocol_item : T_STRING
break;
}
ct_filter_add_proto(STATE(us_filter), pent->p_proto);
+
+ __kernel_filter_start();
+
+ nfct_filter_add_attr_u32(STATE(filter),
+ NFCT_FILTER_L4PROTO,
+ pent->p_proto);
};
filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}'
@@ -696,6 +732,8 @@ filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}'
ct_filter_set_logic(STATE(us_filter),
CT_FILTER_ADDRESS,
CT_FILTER_POSITIVE);
+
+ __kernel_filter_start();
};
filter_item : T_ADDRESS T_IGNORE '{' filter_address_list '}'
@@ -703,6 +741,15 @@ filter_item : T_ADDRESS T_IGNORE '{' filter_address_list '}'
ct_filter_set_logic(STATE(us_filter),
CT_FILTER_ADDRESS,
CT_FILTER_NEGATIVE);
+
+ __kernel_filter_start();
+
+ nfct_filter_set_logic(STATE(filter),
+ NFCT_FILTER_SRC_IPV4,
+ NFCT_FILTER_LOGIC_NEGATIVE);
+ nfct_filter_set_logic(STATE(filter),
+ NFCT_FILTER_DST_IPV4,
+ NFCT_FILTER_LOGIC_NEGATIVE);
};
filter_address_list :
@@ -726,6 +773,16 @@ filter_address_item : T_IPV4_ADDR T_IP
if (errno == ENOSPC)
fprintf(stderr, "Too many IP in the ignore pool!\n");
}
+
+ __kernel_filter_start();
+
+ struct nfct_filter_ipv4 filter_ipv4 = {
+ .addr = htonl(ip.ipv4),
+ .mask = 0xffffffff,
+ };
+
+ nfct_filter_add_attr(STATE(filter), NFCT_FILTER_SRC_IPV4, &filter_ipv4);
+ nfct_filter_add_attr(STATE(filter), NFCT_FILTER_DST_IPV4, &filter_ipv4);
};
filter_address_item : T_IPV6_ADDR T_IP
@@ -758,6 +815,8 @@ filter_item : T_STATE T_ACCEPT '{' filter_state_list '}'
ct_filter_set_logic(STATE(us_filter),
CT_FILTER_STATE,
CT_FILTER_POSITIVE);
+
+ __kernel_filter_start();
};
filter_item : T_STATE T_IGNORE '{' filter_state_list '}'
@@ -765,6 +824,13 @@ filter_item : T_STATE T_IGNORE '{' filter_state_list '}'
ct_filter_set_logic(STATE(us_filter),
CT_FILTER_STATE,
CT_FILTER_NEGATIVE);
+
+
+ __kernel_filter_start();
+
+ nfct_filter_set_logic(STATE(filter),
+ NFCT_FILTER_L4PROTO_STATE,
+ NFCT_FILTER_LOGIC_NEGATIVE);
};
filter_state_list :
@@ -864,6 +930,30 @@ yyerror(char *msg)
exit(EXIT_FAILURE);
}
+static void __kernel_filter_start(void)
+{
+ if (!STATE(filter)) {
+ STATE(filter) = nfct_filter_create();
+ if (!STATE(filter)) {
+ fprintf(stderr, "Can't create ignore pool!\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+static void __kernel_filter_add_state(int value)
+{
+ __kernel_filter_start();
+
+ struct nfct_filter_proto filter_proto = {
+ .proto = IPPROTO_TCP,
+ .state = value
+ };
+ nfct_filter_add_attr(STATE(filter),
+ NFCT_FILTER_L4PROTO_STATE,
+ &filter_proto);
+}
+
int
init_config(char *filename)
{