diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-07-22 12:13:43 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-07-22 12:13:43 +0200 |
commit | 77b1fdb824eb45213df4f57224e8e799fed43ded (patch) | |
tree | 282a395e7ab2d8fe8cfe12f34e6d09535d067101 | |
parent | 2de606c2458067c48e72058a31af384574cf9c70 (diff) | |
download | conntrack-tools-77b1fdb824eb45213df4f57224e8e799fed43ded.tar.gz conntrack-tools-77b1fdb824eb45213df4f57224e8e799fed43ded.zip |
Major rework of the user-space event filtering
This patch reworks the user-space filtering. Although we have
kernel-space filtering since Linux kernel >= 2.6.26, we keep userspace
filtering to ensure backward compatibility. Moreover, this patch
prepares the implementation of the kernel-space filtering via
libnetfilter_conntrack's high-level berkeley socket filter API.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | doc/stats/conntrackd.conf | 54 | ||||
-rw-r--r-- | doc/sync/alarm/node1/conntrackd.conf | 65 | ||||
-rw-r--r-- | doc/sync/alarm/node2/conntrackd.conf | 65 | ||||
-rw-r--r-- | doc/sync/ftfw/node1/conntrackd.conf | 65 | ||||
-rw-r--r-- | doc/sync/ftfw/node2/conntrackd.conf | 65 | ||||
-rw-r--r-- | doc/sync/notrack/node1/conntrackd.conf | 65 | ||||
-rw-r--r-- | doc/sync/notrack/node2/conntrackd.conf | 65 | ||||
-rw-r--r-- | include/Makefile.am | 4 | ||||
-rw-r--r-- | include/bitops.h | 36 | ||||
-rw-r--r-- | include/conntrackd.h | 4 | ||||
-rw-r--r-- | include/filter.h | 31 | ||||
-rw-r--r-- | include/ignore.h | 18 | ||||
-rw-r--r-- | include/state_helper.h | 22 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/filter.c | 250 | ||||
-rw-r--r-- | src/ignore_pool.c | 155 | ||||
-rw-r--r-- | src/netlink.c | 16 | ||||
-rw-r--r-- | src/read_config_lex.l | 14 | ||||
-rw-r--r-- | src/read_config_yy.y | 255 | ||||
-rw-r--r-- | src/run.c | 4 | ||||
-rw-r--r-- | src/state_helper.c | 44 | ||||
-rw-r--r-- | src/state_helper_tcp.c | 35 | ||||
-rw-r--r-- | src/sync-mode.c | 4 |
23 files changed, 807 insertions, 532 deletions
diff --git a/doc/stats/conntrackd.conf b/doc/stats/conntrackd.conf index 4bc5642..b63c2c3 100644 --- a/doc/stats/conntrackd.conf +++ b/doc/stats/conntrackd.conf @@ -47,6 +47,39 @@ General { # Increase the socket buffer up to maximun if required # SocketBufferSizeMaxGrown 655355 + + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to log the + # state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } + + # + # Ignore traffic for a certain set of IP's. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + } + + # + # Uncomment this line below if you want to filter by flow state. + # The existing TCP states are: SYN_SENT, SYN_RECV, ESTABLISHED, + # FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } Stats { @@ -66,24 +99,3 @@ Stats { # #Syslog on } - -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback -} - -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP -# ICMP -# IGMP -# VRRP - # numeric numbers also valid -} diff --git a/doc/sync/alarm/node1/conntrackd.conf b/doc/sync/alarm/node1/conntrackd.conf index 56bef0c..c3c4da4 100644 --- a/doc/sync/alarm/node1/conntrackd.conf +++ b/doc/sync/alarm/node1/conntrackd.conf @@ -133,30 +133,47 @@ General { # Increase the socket buffer up to maximum if required # SocketBufferSizeMaxGrown 655355 -} -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to replicate + # the state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid + # + # Ignore traffic for a certain set of IP's: Usually all the + # IP assigned to the firewall since local traffic must be + # ignored, only forwarded connections are worth to replicate. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 + } + + # + # Uncomment this line below if you want to filter by flow state. + # This option introduces a trade-off in the replication: it + # reduces CPU consumption at the cost of having lazy backup + # firewall replicas. The existing TCP states are: SYN_SENT, + # SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK, + # TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } diff --git a/doc/sync/alarm/node2/conntrackd.conf b/doc/sync/alarm/node2/conntrackd.conf index e0cb375..e61e76a 100644 --- a/doc/sync/alarm/node2/conntrackd.conf +++ b/doc/sync/alarm/node2/conntrackd.conf @@ -133,30 +133,47 @@ General { # Increase the socket buffer up to maximum if required # SocketBufferSizeMaxGrown 655355 -} -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to replicate + # the state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid + # + # Ignore traffic for a certain set of IP's: Usually all the + # IP assigned to the firewall since local traffic must be + # ignored, only forwarded connections are worth to replicate. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 + } + + # + # Uncomment this line below if you want to filter by flow state. + # This option introduces a trade-off in the replication: it + # reduces CPU consumption at the cost of having lazy backup + # firewall replicas. The existing TCP states are: SYN_SENT, + # SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK, + # TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } diff --git a/doc/sync/ftfw/node1/conntrackd.conf b/doc/sync/ftfw/node1/conntrackd.conf index f3211db..98ad581 100644 --- a/doc/sync/ftfw/node1/conntrackd.conf +++ b/doc/sync/ftfw/node1/conntrackd.conf @@ -128,30 +128,47 @@ General { # Increase the socket buffer up to maximum if required # SocketBufferSizeMaxGrown 655355 -} -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to replicate + # the state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid + # + # Ignore traffic for a certain set of IP's: Usually all the + # IP assigned to the firewall since local traffic must be + # ignored, only forwarded connections are worth to replicate. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 + } + + # + # Uncomment this line below if you want to filter by flow state. + # This option introduces a trade-off in the replication: it + # reduces CPU consumption at the cost of having lazy backup + # firewall replicas. The existing TCP states are: SYN_SENT, + # SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK, + # TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } diff --git a/doc/sync/ftfw/node2/conntrackd.conf b/doc/sync/ftfw/node2/conntrackd.conf index 9c26ff5..2fab830 100644 --- a/doc/sync/ftfw/node2/conntrackd.conf +++ b/doc/sync/ftfw/node2/conntrackd.conf @@ -127,30 +127,47 @@ General { # Increase the socket buffer up to maximum if required # SocketBufferSizeMaxGrown 655355 -} -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to replicate + # the state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid + # + # Ignore traffic for a certain set of IP's: Usually all the + # IP assigned to the firewall since local traffic must be + # ignored, only forwarded connections are worth to replicate. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 + } + + # + # Uncomment this line below if you want to filter by flow state. + # This option introduces a trade-off in the replication: it + # reduces CPU consumption at the cost of having lazy backup + # firewall replicas. The existing TCP states are: SYN_SENT, + # SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK, + # TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } diff --git a/doc/sync/notrack/node1/conntrackd.conf b/doc/sync/notrack/node1/conntrackd.conf index 1185351..724183a 100644 --- a/doc/sync/notrack/node1/conntrackd.conf +++ b/doc/sync/notrack/node1/conntrackd.conf @@ -121,30 +121,47 @@ General { # Increase the socket buffer up to maximum if required # SocketBufferSizeMaxGrown 655355 -} -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.1 - IPv4_address 192.168.1.1 - IPv4_address 192.168.100.100 # dedicated link ip - IPv4_address 192.168.0.100 # virtual IP 1 - IPv4_address 192.168.1.100 # virtual IP 2 -} + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to replicate + # the state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid + # + # Ignore traffic for a certain set of IP's: Usually all the + # IP assigned to the firewall since local traffic must be + # ignored, only forwarded connections are worth to replicate. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.1 + IPv4_address 192.168.1.1 + IPv4_address 192.168.100.100 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 + } + + # + # Uncomment this line below if you want to filter by flow state. + # This option introduces a trade-off in the replication: it + # reduces CPU consumption at the cost of having lazy backup + # firewall replicas. The existing TCP states are: SYN_SENT, + # SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK, + # TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } diff --git a/doc/sync/notrack/node2/conntrackd.conf b/doc/sync/notrack/node2/conntrackd.conf index 7881d46..cbf5cee 100644 --- a/doc/sync/notrack/node2/conntrackd.conf +++ b/doc/sync/notrack/node2/conntrackd.conf @@ -120,30 +120,47 @@ General { # Increase the socket buffer up to maximum if required # SocketBufferSizeMaxGrown 655355 -} -# -# Ignore traffic for a certain set of IP's: Usually -# all the IP assigned to the firewall since local -# traffic must be ignored, just forwarded connections -# are worth to replicate -# -IgnoreTrafficFor { - IPv4_address 127.0.0.1 # loopback - IPv4_address 192.168.0.2 - IPv4_address 192.168.1.2 - IPv4_address 192.168.100.200 # dedicated link ip - IPv4_address 192.168.0.200 # virtual IP 1 - IPv4_address 192.168.1.200 # virtual IP 2 -} + # + # Event filtering: This clause allows you to filter certain traffic, + # There are currently three filter-sets: Protocol, Address and + # State. The filter is attached to an action that can be: Accept or + # Ignore. Thus, you can define the event filtering policy of the + # filter-sets in positive or negative logic depending on your needs. + # + Filter { + # + # Accept only certain protocols: You may want to replicate + # the state of flows depending on their layer 4 protocol. + # + Protocol Accept { + TCP + } -# -# Do not replicate certain protocol traffic -# -IgnoreProtocol { - UDP - ICMP - IGMP - VRRP - # numeric numbers also valid + # + # Ignore traffic for a certain set of IP's: Usually all the + # IP assigned to the firewall since local traffic must be + # ignored, only forwarded connections are worth to replicate. + # + Address Ignore { + IPv4_address 127.0.0.1 # loopback + IPv4_address 192.168.0.2 + IPv4_address 192.168.1.2 + IPv4_address 192.168.100.200 # dedicated link ip + IPv4_address 192.168.0.100 # virtual IP 1 + IPv4_address 192.168.1.100 # virtual IP 2 + } + + # + # Uncomment this line below if you want to filter by flow state. + # This option introduces a trade-off in the replication: it + # reduces CPU consumption at the cost of having lazy backup + # firewall replicas. The existing TCP states are: SYN_SENT, + # SYN_RECV, ESTABLISHED, FIN_WAIT, CLOSE_WAIT, LAST_ACK, + # TIME_WAIT, CLOSED, LISTEN. + # + # State Accept { + # ESTABLISHED CLOSED TIME_WAIT CLOSE_WAIT for TCP + # } + } } diff --git a/include/Makefile.am b/include/Makefile.am index 01be0df..3287a0c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,6 +2,6 @@ noinst_HEADERS = alarm.h jhash.h slist.h cache.h linux_list.h linux_rbtree.h \ sync.h conntrackd.h local.h us-conntrack.h \ debug.h log.h hash.h mcast.h conntrack.h \ - state_helper.h network.h ignore.h queue.h \ - traffic_stats.h netlink.h fds.h event.h + network.h filter.h queue.h \ + traffic_stats.h netlink.h fds.h event.h bitops.h diff --git a/include/bitops.h b/include/bitops.h new file mode 100644 index 0000000..51f4289 --- /dev/null +++ b/include/bitops.h @@ -0,0 +1,36 @@ +#ifndef _BITOPS_H_ +#define _BITOPS_H_ + +#include <stdlib.h> + +static inline void set_bit_u32(int nr, u_int32_t *addr) +{ + addr[nr >> 5] |= (1UL << (nr & 31)); +} + +static inline void unset_bit_u32(int nr, u_int32_t *addr) +{ + addr[nr >> 5] &= ~(1UL << (nr & 31)); +} + +static inline int test_bit_u32(int nr, const u_int32_t *addr) +{ + return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; +} + +static inline void set_bit_u16(int nr, u_int16_t *addr) +{ + addr[nr >> 4] |= (1UL << (nr & 15)); +} + +static inline void unset_bit_u16(int nr, u_int16_t *addr) +{ + addr[nr >> 4] &= ~(1UL << (nr & 15)); +} + +static inline int test_bit_u16(int nr, const u_int16_t *addr) +{ + return ((1UL << (nr & 15)) & (addr[nr >> 4])) != 0; +} + +#endif diff --git a/include/conntrackd.h b/include/conntrackd.h index 8a6e8d2..cd02f1f 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -4,6 +4,7 @@ #include "mcast.h" #include "local.h" #include "alarm.h" +#include "filter.h" #include <stdint.h> #include <stdio.h> @@ -80,7 +81,6 @@ struct ct_conf { int del_timeout; unsigned int netlink_buffer_size; unsigned int netlink_buffer_size_max_grown; - unsigned char ignore_protocol[IPPROTO_MAX]; union inet_address *listen_to; unsigned int listen_to_len; unsigned int flags; @@ -103,7 +103,7 @@ struct ct_general_state { FILE *stats_log; struct local_server local; struct ct_mode *mode; - struct ignore_pool *ignore_pool; + struct ct_filter *us_filter; struct nfct_handle *event; /* event handler */ struct nfct_handle *dump; /* dump handler */ diff --git a/include/filter.h b/include/filter.h new file mode 100644 index 0000000..de0754e --- /dev/null +++ b/include/filter.h @@ -0,0 +1,31 @@ +#ifndef _FILTER_H_ +#define _FILTER_H_ + +#include <stdint.h> + +enum ct_filter_type { + CT_FILTER_L4PROTO, + CT_FILTER_STATE, + CT_FILTER_ADDRESS, + CT_FILTER_MAX +}; + +enum ct_filter_logic { + CT_FILTER_NEGATIVE = 0, + CT_FILTER_POSITIVE = 1, +}; + +struct nf_conntrack; +struct ct_filter; + +struct ct_filter *ct_filter_create(void); +void ct_filter_destroy(struct ct_filter *filter); +int ct_filter_add_ip(struct ct_filter *filter, void *data, uint8_t family); +void ct_filter_add_proto(struct ct_filter *filter, int protonum); +void ct_filter_add_state(struct ct_filter *f, int protonum, int state); +void ct_filter_set_logic(struct ct_filter *f, + enum ct_filter_type type, + enum ct_filter_logic logic); +int ct_filter_check(struct ct_filter *filter, struct nf_conntrack *ct); + +#endif diff --git a/include/ignore.h b/include/ignore.h deleted file mode 100644 index e5e96ff..0000000 --- a/include/ignore.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _IGNORE_H_ -#define _IGNORE_H_ - -#include <stdint.h> - -struct nf_conntrack; - -struct ignore_pool { - struct hashtable *h; - struct hashtable *h6; -}; - -struct ignore_pool *ignore_pool_create(void); -void ignore_pool_destroy(struct ignore_pool *ip); -int ignore_pool_add(struct ignore_pool *ip, void *data, uint8_t family); -int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct); - -#endif diff --git a/include/state_helper.h b/include/state_helper.h deleted file mode 100644 index 1a68b04..0000000 --- a/include/state_helper.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _STATE_HELPER_H_ -#define _STATE_HELPER_H_ - -#include <stdint.h> - -enum { - ST_H_SKIP, - ST_H_REPLICATE -}; - -struct state_replication_helper { - uint8_t proto; - unsigned int state; - - int (*verdict)(const struct state_replication_helper *h, - const struct nf_conntrack *ct); -}; - -int state_helper_verdict(int type, struct nf_conntrack *ct); -void state_helper_register(struct state_replication_helper *h, int h_state); - -#endif diff --git a/src/Makefile.am b/src/Makefile.am index 69ddcfd..805e50d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,13 +12,12 @@ conntrack_LDFLAGS = $(all_libraries) @LIBNETFILTER_CONNTRACK_LIBS@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ local.c log.c mcast.c netlink.c \ - ignore_pool.c fds.c event.c \ + filter.c fds.c event.c \ cache.c cache_iterators.c \ cache_lifetime.c cache_timer.c cache_wt.c \ sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \ traffic_stats.c stats-mode.c \ network.c \ - state_helper.c state_helper_tcp.c \ build.c parse.c \ read_config_yy.y read_config_lex.l diff --git a/src/filter.c b/src/filter.c new file mode 100644 index 0000000..6e4d64a --- /dev/null +++ b/src/filter.c @@ -0,0 +1,250 @@ +/* + * (C) 2006-2008 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "filter.h" +#include "bitops.h" +#include "jhash.h" +#include "hash.h" +#include "conntrackd.h" +#include "log.h" + +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +struct ct_filter { + int logic[CT_FILTER_MAX]; + u_int32_t l4protomap[IPPROTO_MAX/32]; + u_int16_t statemap[IPPROTO_MAX]; + struct hashtable *h; + struct hashtable *h6; +}; + +/* XXX: These should be configurable, better use a rb-tree */ +#define FILTER_POOL_SIZE 128 +#define FILTER_POOL_LIMIT INT_MAX + +static uint32_t hash(const void *data, struct hashtable *table) +{ + const uint32_t *f = data; + + return jhash_1word(*f, 0) % table->hashsize; +} + +static uint32_t hash6(const void *data, struct hashtable *table) +{ + return jhash(data, sizeof(uint32_t)*4, 0) % table->hashsize; +} + +static int compare(const void *data1, const void *data2) +{ + const uint32_t *f1 = data1; + const uint32_t *f2 = data2; + + return *f1 == *f2; +} + +static int compare6(const void *data1, const void *data2) +{ + return memcmp(data1, data2, sizeof(uint32_t)*4) == 0; +} + +struct ct_filter *ct_filter_create(void) +{ + int i; + struct ct_filter *filter; + + filter = calloc(sizeof(struct ct_filter), 1); + if (!filter) + return NULL; + + filter->h = hashtable_create(FILTER_POOL_SIZE, + FILTER_POOL_LIMIT, + sizeof(uint32_t), + hash, + compare); + if (!filter->h) { + free(filter); + return NULL; + } + + filter->h6 = hashtable_create(FILTER_POOL_SIZE, + FILTER_POOL_LIMIT, + sizeof(uint32_t)*4, + hash6, + compare6); + if (!filter->h6) { + free(filter->h); + free(filter); + return NULL; + } + + for (i=0; i<CT_FILTER_MAX; i++) + filter->logic[i] = -1; + + return filter; +} + +void ct_filter_destroy(struct ct_filter *filter) +{ + hashtable_destroy(filter->h); + hashtable_destroy(filter->h6); + free(filter); +} + +/* this is ugly, but it simplifies read_config_yy.y */ +static struct ct_filter *__filter_alloc(struct ct_filter *filter) +{ + if (!STATE(us_filter)) { + STATE(us_filter) = ct_filter_create(); + if (!STATE(us_filter)) { + fprintf(stderr, "Can't create ignore pool!\n"); + exit(EXIT_FAILURE); + } + } + + return STATE(us_filter); +} + +void ct_filter_set_logic(struct ct_filter *filter, + enum ct_filter_type type, + enum ct_filter_logic logic) +{ + filter = __filter_alloc(filter); + filter->logic[type] = logic; +} + +int ct_filter_add_ip(struct ct_filter *filter, void *data, uint8_t family) +{ + filter = __filter_alloc(filter); + + switch(family) { + case AF_INET: + if (!hashtable_add(filter->h, data)) + return 0; + break; + case AF_INET6: + if (!hashtable_add(filter->h6, data)) + return 0; + break; + } + return 1; +} + +void ct_filter_add_proto(struct ct_filter *f, int protonum) +{ + f = __filter_alloc(f); + + set_bit_u32(protonum, f->l4protomap); +} + +void ct_filter_add_state(struct ct_filter *f, int protonum, int val) +{ + f = __filter_alloc(f); + + set_bit_u16(val, &f->statemap[protonum]); +} + +static int +__ct_filter_test_ipv4(struct ct_filter *f, struct nf_conntrack *ct) +{ + if (!f->h) + return 0; + + return (hashtable_test(f->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC)) || + hashtable_test(f->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_DST)) || + hashtable_test(f->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)) || + hashtable_test(f->h, nfct_get_attr(ct, ATTR_REPL_IPV4_DST))); +} + +static int +__ct_filter_test_ipv6(struct ct_filter *f, struct nf_conntrack *ct) +{ + if (!f->h6) + return 0; + + return (hashtable_test(f->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) || + hashtable_test(f->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_DST)) || + hashtable_test(f->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_SRC)) || + hashtable_test(f->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_DST))); +} + +static int __ct_filter_test_state(struct ct_filter *f, struct nf_conntrack *ct) +{ + uint16_t val = 0; + uint8_t protonum = nfct_get_attr_u8(ct, ATTR_L4PROTO); + + switch(protonum) { + case IPPROTO_TCP: + val = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + break; + default: + return -1; + } + + return test_bit_u16(val, &f->statemap[protonum]); +} + +int ct_filter_check(struct ct_filter *f, struct nf_conntrack *ct) +{ + int ret, protonum = nfct_get_attr_u8(ct, ATTR_L4PROTO); + + /* no event filtering at all */ + if (f == NULL) + return 1; + + if (f->logic[CT_FILTER_L4PROTO] != -1) { + ret = test_bit_u32(protonum, f->l4protomap); + if (ret == 0 && f->logic[CT_FILTER_L4PROTO]) + return 0; + else if (ret == 1 && !f->logic[CT_FILTER_L4PROTO]) + return 0; + } + + if (f->logic[CT_FILTER_ADDRESS] != -1) { + switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { + case AF_INET: + ret = __ct_filter_test_ipv4(f, ct); + if (ret == 0 && f->logic[CT_FILTER_ADDRESS]) + return 0; + else if (ret == 1 && !f->logic[CT_FILTER_ADDRESS]) + return 0; + break; + case AF_INET6: + ret = __ct_filter_test_ipv6(f, ct); + if (ret == 0 && f->logic[CT_FILTER_ADDRESS]) + return 0; + else if (ret == 1 && !f->logic[CT_FILTER_ADDRESS]) + return 0; + break; + default: + break; + } + } + + if (f->logic[CT_FILTER_STATE] != -1) { + ret = __ct_filter_test_state(f, ct); + if (ret == 0 && f->logic[CT_FILTER_STATE]) + return 0; + else if (ret == 1 && !f->logic[CT_FILTER_STATE]) + return 0; + } + + return 1; +} diff --git a/src/ignore_pool.c b/src/ignore_pool.c deleted file mode 100644 index 2f951e8..0000000 --- a/src/ignore_pool.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "ignore.h" -#include "jhash.h" -#include "hash.h" -#include "conntrackd.h" -#include "log.h" - -#include <libnetfilter_conntrack/libnetfilter_conntrack.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> - -/* XXX: These should be configurable, better use a rb-tree */ -#define IGNORE_POOL_SIZE 128 -#define IGNORE_POOL_LIMIT INT_MAX - -static uint32_t hash(const void *data, struct hashtable *table) -{ - const uint32_t *ip = data; - - return jhash_1word(*ip, 0) % table->hashsize; -} - -static uint32_t hash6(const void *data, struct hashtable *table) -{ - return jhash(data, sizeof(uint32_t)*4, 0) % table->hashsize; -} - -static int compare(const void *data1, const void *data2) -{ - const uint32_t *ip1 = data1; - const uint32_t *ip2 = data2; - - return *ip1 == *ip2; -} - -static int compare6(const void *data1, const void *data2) -{ - return memcmp(data1, data2, sizeof(uint32_t)*4) == 0; -} - -struct ignore_pool *ignore_pool_create(void) -{ - struct ignore_pool *ip; - - ip = malloc(sizeof(struct ignore_pool)); - if (!ip) - return NULL; - memset(ip, 0, sizeof(struct ignore_pool)); - - ip->h = hashtable_create(IGNORE_POOL_SIZE, - IGNORE_POOL_LIMIT, - sizeof(uint32_t), - hash, - compare); - if (!ip->h) { - free(ip); - return NULL; - } - - ip->h6 = hashtable_create(IGNORE_POOL_SIZE, - IGNORE_POOL_LIMIT, - sizeof(uint32_t)*4, - hash6, - compare6); - if (!ip->h6) { - free(ip->h); - free(ip); - return NULL; - } - - return ip; -} - -void ignore_pool_destroy(struct ignore_pool *ip) -{ - hashtable_destroy(ip->h); - hashtable_destroy(ip->h6); - free(ip); -} - -int ignore_pool_add(struct ignore_pool *ip, void *data, uint8_t family) -{ - switch(family) { - case AF_INET: - if (!hashtable_add(ip->h, data)) - return 0; - break; - case AF_INET6: - if (!hashtable_add(ip->h6, data)) - return 0; - break; - } - return 1; -} - -static int -__ignore_pool_test_ipv4(struct ignore_pool *ip, struct nf_conntrack *ct) -{ - if (!ip->h) - return 0; - - return (hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_ORIG_IPV4_DST)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_SRC)) || - hashtable_test(ip->h, nfct_get_attr(ct, ATTR_REPL_IPV4_DST))); -} - -static int -__ignore_pool_test_ipv6(struct ignore_pool *ip, struct nf_conntrack *ct) -{ - if (!ip->h6) - return 0; - - return (hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC)) || - hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_ORIG_IPV6_DST)) || - hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_SRC)) || - hashtable_test(ip->h6, nfct_get_attr(ct, ATTR_REPL_IPV6_DST))); -} - -int ignore_pool_test(struct ignore_pool *ip, struct nf_conntrack *ct) -{ - int ret = 0; - - switch(nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO)) { - case AF_INET: - ret = __ignore_pool_test_ipv4(ip, ct); - break; - case AF_INET6: - ret = __ignore_pool_test_ipv6(ip, ct); - break; - default: - dlog(LOG_WARNING, "unknown layer 3 protocol?"); - break; - } - - return ret; -} diff --git a/src/netlink.c b/src/netlink.c index 387062d..1823280 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -19,7 +19,7 @@ #include "netlink.h" #include "conntrackd.h" #include "traffic_stats.h" -#include "ignore.h" +#include "filter.h" #include "log.h" #include "debug.h" @@ -28,10 +28,6 @@ int ignore_conntrack(struct nf_conntrack *ct) { - /* ignore a certain protocol */ - if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)]) - return 1; - /* Accept DNAT'ed traffic: not really coming to the local machine */ if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) { debug_ct(ct, "DNAT"); @@ -45,7 +41,7 @@ int ignore_conntrack(struct nf_conntrack *ct) } /* Ignore traffic */ - if (ignore_pool_test(STATE(ignore_pool), ct)) { + if (!ct_filter_check(STATE(us_filter), ct)) { debug_ct(ct, "ignore traffic"); return 1; } @@ -57,10 +53,6 @@ static int event_handler(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - /* - * Ignore this conntrack: it talks about a - * connection that is not interesting for us. - */ if (ignore_conntrack(ct)) return NFCT_CB_STOP; @@ -125,10 +117,6 @@ static int dump_handler(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) { - /* - * Ignore this conntrack: it talks about a - * connection that is not interesting for us. - */ if (ignore_conntrack(ct)) return NFCT_CB_CONTINUE; diff --git a/src/read_config_lex.l b/src/read_config_lex.l index bdde3b6..584a4a3 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -68,11 +68,6 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k] "HashLimit" { return T_HASHLIMIT; } "Path" { return T_PATH; } "IgnoreProtocol" { return T_IGNORE_PROTOCOL; } -"UDP" { return T_UDP; } -"ICMP" { return T_ICMP; } -"VRRP" { return T_VRRP; } -"IGMP" { return T_IGMP; } -"TCP" { return T_TCP; } "IgnoreTrafficFor" { return T_IGNORE_TRAFFIC; } "StripNAT" { return T_STRIP_NAT; } "Backlog" { return T_BACKLOG; } @@ -103,12 +98,19 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k] "CLOSE_WAIT" { return T_CLOSE_WAIT; } "LAST_ACK" { return T_LAST_ACK; } "TIME_WAIT" { return T_TIME_WAIT; } -"CLOSE" { return T_CLOSE; } +"CLOSE" { return T_CLOSE; /* alias of CLOSED */ } +"CLOSED" { return T_CLOSE; } "LISTEN" { return T_LISTEN; } "LogFileBufferSize" { return T_STAT_BUFFER_SIZE; } "DestroyTimeout" { return T_DESTROY_TIMEOUT; } "McastSndSocketBuffer" { return T_MCAST_SNDBUFF; } "McastRcvSocketBuffer" { return T_MCAST_RCVBUFF; } +"Filter" { return T_FILTER; } +"Protocol" { return T_PROTOCOL; } +"Address" { return T_ADDRESS; } +"State" { return T_STATE; } +"Accept" { return T_ACCEPT; } +"Ignore" { return T_IGNORE; } {is_on} { return T_ON; } {is_off} { return T_OFF; } diff --git a/src/read_config_yy.y b/src/read_config_yy.y index b9c53be..2a1c88c 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -22,14 +22,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <netdb.h> #include <errno.h> #include "conntrackd.h" -#include "ignore.h" +#include "bitops.h" #include <syslog.h> #include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h> -extern struct state_replication_helper tcp_state_helper; - extern char *yytext; extern int yylineno; @@ -44,7 +43,7 @@ struct ct_conf conf; %token T_IPV4_ADDR T_IPV4_IFACE T_PORT T_HASHSIZE T_HASHLIMIT T_MULTICAST %token T_PATH T_UNIX T_REFRESH T_IPV6_ADDR T_IPV6_IFACE %token T_IGNORE_UDP T_IGNORE_ICMP T_IGNORE_TRAFFIC T_BACKLOG T_GROUP -%token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_TCP T_IGNORE_PROTOCOL +%token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_IGNORE_PROTOCOL %token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT %token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY %token T_SYNC_MODE T_LISTEN_TO T_FAMILY T_RESEND_BUFFER_SIZE @@ -54,6 +53,7 @@ struct ct_conf conf; %token T_CLOSE_WAIT T_LAST_ACK T_TIME_WAIT T_CLOSE T_LISTEN %token T_SYSLOG T_WRITE_THROUGH T_STAT_BUFFER_SIZE T_DESTROY_TIMEOUT %token T_MCAST_RCVBUFF T_MCAST_SNDBUFF T_NOTRACK +%token T_FILTER T_ADDRESS T_PROTOCOL T_STATE T_ACCEPT T_IGNORE %token <string> T_IP T_PATH_VAL %token <val> T_NUMBER @@ -169,7 +169,15 @@ checksum: T_CHECKSUM T_OFF conf.mcast.checksum = 1; }; -ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}'; +ignore_traffic : T_IGNORE_TRAFFIC '{' ignore_traffic_options '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_ADDRESS, + CT_FILTER_NEGATIVE); + + fprintf(stderr, "WARNING: The clause `IgnoreTrafficFor' is obsolete. " + "Use `Filter' instead.\n"); +}; ignore_traffic_options : | ignore_traffic_options ignore_traffic_option; @@ -185,15 +193,7 @@ ignore_traffic_option : T_IPV4_ADDR T_IP break; } - if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(); - if (!STATE(ignore_pool)) { - fprintf(stderr, "Can't create ignore pool!\n"); - exit(EXIT_FAILURE); - } - } - - if (!ignore_pool_add(STATE(ignore_pool), &ip, AF_INET)) { + if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET)) { if (errno == EEXIST) fprintf(stderr, "IP %s is repeated " "in the ignore pool\n", $2); @@ -218,15 +218,7 @@ ignore_traffic_option : T_IPV6_ADDR T_IP break; #endif - if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(); - if (!STATE(ignore_pool)) { - fprintf(stderr, "Can't create ignore pool!\n"); - exit(EXIT_FAILURE); - } - } - - if (!ignore_pool_add(STATE(ignore_pool), &ip, AF_INET6)) { + if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET6)) { if (errno == EEXIST) fprintf(stderr, "IP %s is repeated " "in the ignore pool\n", $2); @@ -380,7 +372,15 @@ unix_option : T_BACKLOG T_NUMBER conf.local.backlog = $2; }; -ignore_protocol: T_IGNORE_PROTOCOL '{' ignore_proto_list '}'; +ignore_protocol: T_IGNORE_PROTOCOL '{' ignore_proto_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_L4PROTO, + CT_FILTER_NEGATIVE); + + fprintf(stderr, "WARNING: The clause `IgnoreProtocol' is obsolete. " + "Use `Filter' instead.\n"); +}; ignore_proto_list: | ignore_proto_list ignore_proto @@ -389,29 +389,22 @@ ignore_proto_list: ignore_proto: T_NUMBER { if ($1 < IPPROTO_MAX) - conf.ignore_protocol[$1] = 1; + ct_filter_add_proto(STATE(us_filter), $1); else fprintf(stderr, "Protocol number `%d' is freak\n", $1); }; -ignore_proto: T_UDP +ignore_proto: T_STRING { - conf.ignore_protocol[IPPROTO_UDP] = 1; -}; + struct protoent *pent; -ignore_proto: T_ICMP -{ - conf.ignore_protocol[IPPROTO_ICMP] = 1; -}; - -ignore_proto: T_VRRP -{ - conf.ignore_protocol[IPPROTO_VRRP] = 1; -}; - -ignore_proto: T_IGMP -{ - conf.ignore_protocol[IPPROTO_IGMP] = 1; + pent = getprotobyname($1); + if (pent == NULL) { + fprintf(stderr, "getprotobyname() cannot find " + "protocol `%s' in /etc/protocols.\n", $1); + break; + } + ct_filter_add_proto(STATE(us_filter), pent->p_proto); }; sync: T_SYNC '{' sync_list '}' @@ -538,49 +531,81 @@ listen_to: T_LISTEN_TO T_IP } }; -state_replication: T_REPLICATE states T_FOR state_proto; +state_replication: T_REPLICATE states T_FOR state_proto +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_STATE, + CT_FILTER_POSITIVE); + + fprintf(stderr, "WARNING: The clause `Replicate' is obsolete. " + "Use `Filter' instead.\n"); +}; states: | states state; -state_proto: T_TCP; +state_proto: T_STRING +{ + if (strncmp($1, "TCP", strlen("TCP")) != 0) { + fprintf(stderr, "Unsupported protocol `%s' in line %d.\n", + $1, yylineno); + } +}; state: tcp_state; tcp_state: T_SYN_SENT { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_SENT); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_SYN_SENT); }; tcp_state: T_SYN_RECV { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_SYN_RECV); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_SYN_RECV); }; tcp_state: T_ESTABLISHED { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_ESTABLISHED); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_ESTABLISHED); }; tcp_state: T_FIN_WAIT { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_FIN_WAIT); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_FIN_WAIT); }; tcp_state: T_CLOSE_WAIT { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE_WAIT); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_CLOSE_WAIT); }; tcp_state: T_LAST_ACK { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LAST_ACK); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_LAST_ACK); }; tcp_state: T_TIME_WAIT { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_TIME_WAIT); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_TIME_WAIT); }; tcp_state: T_CLOSE { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_CLOSE); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_CLOSE); }; tcp_state: T_LISTEN { - state_helper_register(&tcp_state_helper, TCP_CONNTRACK_LISTEN); + ct_filter_add_state(STATE(us_filter), + IPPROTO_TCP, + TCP_CONNTRACK_LISTEN); }; cache_writethrough: T_WRITE_THROUGH T_ON @@ -610,6 +635,7 @@ general_line: hashsize | netlink_buffer_size | netlink_buffer_size_max_grown | family + | filter ; netlink_buffer_size: T_BUFFER_SIZE T_NUMBER @@ -630,6 +656,122 @@ family : T_FAMILY T_STRING conf.family = AF_INET; }; +filter : T_FILTER '{' filter_list '}'; + +filter_list : + | filter_list filter_item; + +filter_item : T_PROTOCOL T_ACCEPT '{' filter_protocol_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_L4PROTO, + CT_FILTER_POSITIVE); +}; + +filter_item : T_PROTOCOL T_IGNORE '{' filter_protocol_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_L4PROTO, + CT_FILTER_NEGATIVE); +}; + +filter_protocol_list : + | filter_protocol_list filter_protocol_item; + +filter_protocol_item : T_STRING +{ + struct protoent *pent; + + pent = getprotobyname($1); + if (pent == NULL) { + fprintf(stderr, "getprotobyname() cannot find " + "protocol `%s' in /etc/protocols.\n", $1); + break; + } + ct_filter_add_proto(STATE(us_filter), pent->p_proto); +}; + +filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_ADDRESS, + CT_FILTER_POSITIVE); +}; + +filter_item : T_ADDRESS T_IGNORE '{' filter_address_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_ADDRESS, + CT_FILTER_NEGATIVE); +}; + +filter_address_list : + | filter_address_list filter_address_item; + +filter_address_item : T_IPV4_ADDR T_IP +{ + union inet_address ip; + + memset(&ip, 0, sizeof(union inet_address)); + + if (!inet_aton($2, &ip.ipv4)) { + fprintf(stderr, "%s is not a valid IPv4, ignoring", $2); + break; + } + + if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET)) { + if (errno == EEXIST) + fprintf(stderr, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stderr, "Too many IP in the ignore pool!\n"); + } +}; + +filter_address_item : T_IPV6_ADDR T_IP +{ + union inet_address ip; + + memset(&ip, 0, sizeof(union inet_address)); + +#ifdef HAVE_INET_PTON_IPV6 + if (inet_pton(AF_INET6, $2, &ip.ipv6) <= 0) { + fprintf(stderr, "%s is not a valid IPv6, ignoring", $2); + break; + } +#else + fprintf(stderr, "Cannot find inet_pton(), IPv6 unsupported!"); + break; +#endif + + if (!ct_filter_add_ip(STATE(us_filter), &ip, AF_INET6)) { + if (errno == EEXIST) + fprintf(stderr, "IP %s is repeated " + "in the ignore pool\n", $2); + if (errno == ENOSPC) + fprintf(stderr, "Too many IP in the ignore pool!\n"); + } +}; + +filter_item : T_STATE T_ACCEPT '{' filter_state_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_STATE, + CT_FILTER_POSITIVE); +}; + +filter_item : T_STATE T_IGNORE '{' filter_state_list '}' +{ + ct_filter_set_logic(STATE(us_filter), + CT_FILTER_STATE, + CT_FILTER_NEGATIVE); +}; + +filter_state_list : + | filter_state_list filter_state_item; + +filter_state_item : states T_FOR state_proto ; + stats: T_STATS '{' stats_list '}' { if (conf.flags & CTD_SYNC_MODE) { @@ -762,15 +904,6 @@ init_config(char *filename) if (CONFIG(resend_queue_size) == 0) CONFIG(resend_queue_size) = 262144; - /* create empty pool */ - if (!STATE(ignore_pool)) { - STATE(ignore_pool) = ignore_pool_create(); - if (!STATE(ignore_pool)) { - fprintf(stderr, "Can't create ignore pool!\n"); - exit(EXIT_FAILURE); - } - } - /* default to a window size of 20 packets */ if (CONFIG(window_size) == 0) CONFIG(window_size) = 20; @@ -20,7 +20,7 @@ #include "conntrackd.h" #include "netlink.h" -#include "ignore.h" +#include "filter.h" #include "log.h" #include "alarm.h" #include "fds.h" @@ -39,7 +39,7 @@ void killer(int foo) nfct_close(STATE(event)); - ignore_pool_destroy(STATE(ignore_pool)); + ct_filter_destroy(STATE(us_filter)); local_server_destroy(&STATE(local)); STATE(mode)->kill(); diff --git a/src/state_helper.c b/src/state_helper.c deleted file mode 100644 index 9034864..0000000 --- a/src/state_helper.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "conntrackd.h" -#include "state_helper.h" - -static struct state_replication_helper *helper[IPPROTO_MAX]; - -int state_helper_verdict(int type, struct nf_conntrack *ct) -{ - uint8_t l4proto; - - if (type == NFCT_Q_DESTROY) - return ST_H_REPLICATE; - - l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); - if (helper[l4proto]) - return helper[l4proto]->verdict(helper[l4proto], ct); - - return ST_H_REPLICATE; -} - -void state_helper_register(struct state_replication_helper *h, int h_state) -{ - if (helper[h->proto] == NULL) - helper[h->proto] = h; - - helper[h->proto]->state |= (1 << h_state); -} diff --git a/src/state_helper_tcp.c b/src/state_helper_tcp.c deleted file mode 100644 index 88af35e..0000000 --- a/src/state_helper_tcp.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "conntrackd.h" -#include "state_helper.h" - -static int tcp_verdict(const struct state_replication_helper *h, - const struct nf_conntrack *ct) -{ - uint8_t t_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); - if (h->state & (1 << t_state)) - return ST_H_REPLICATE; - - return ST_H_SKIP; -} - -struct state_replication_helper tcp_state_helper = { - .proto = IPPROTO_TCP, - .verdict = tcp_verdict, -}; diff --git a/src/sync-mode.c b/src/sync-mode.c index 4b36935..0f3760e 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -20,7 +20,6 @@ #include "netlink.h" #include "traffic_stats.h" #include "log.h" -#include "state_helper.h" #include "cache.h" #include "conntrackd.h" #include "us-conntrack.h" @@ -390,9 +389,6 @@ static void mcast_send_sync(struct us_conntrack *u, int query) size_t len; struct nethdr *net; - if (!state_helper_verdict(query, u->ct)) - return; - net = BUILD_NETMSG(u->ct, query); len = prepare_send_netmsg(STATE_SYNC(mcast_client), net); |