summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2008-07-22 12:13:43 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2008-07-22 12:13:43 +0200
commit77b1fdb824eb45213df4f57224e8e799fed43ded (patch)
tree282a395e7ab2d8fe8cfe12f34e6d09535d067101
parent2de606c2458067c48e72058a31af384574cf9c70 (diff)
downloadconntrack-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.conf54
-rw-r--r--doc/sync/alarm/node1/conntrackd.conf65
-rw-r--r--doc/sync/alarm/node2/conntrackd.conf65
-rw-r--r--doc/sync/ftfw/node1/conntrackd.conf65
-rw-r--r--doc/sync/ftfw/node2/conntrackd.conf65
-rw-r--r--doc/sync/notrack/node1/conntrackd.conf65
-rw-r--r--doc/sync/notrack/node2/conntrackd.conf65
-rw-r--r--include/Makefile.am4
-rw-r--r--include/bitops.h36
-rw-r--r--include/conntrackd.h4
-rw-r--r--include/filter.h31
-rw-r--r--include/ignore.h18
-rw-r--r--include/state_helper.h22
-rw-r--r--src/Makefile.am3
-rw-r--r--src/filter.c250
-rw-r--r--src/ignore_pool.c155
-rw-r--r--src/netlink.c16
-rw-r--r--src/read_config_lex.l14
-rw-r--r--src/read_config_yy.y255
-rw-r--r--src/run.c4
-rw-r--r--src/state_helper.c44
-rw-r--r--src/state_helper_tcp.c35
-rw-r--r--src/sync-mode.c4
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;
diff --git a/src/run.c b/src/run.c
index cadcb4d..cf570d8 100644
--- a/src/run.c
+++ b/src/run.c
@@ -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);