[conntrack-tools] Major rework of the user-space event filtering

Pablo Neira netfilter-cvslog-bounces at lists.netfilter.org
Tue Jul 22 12:14:55 CEST 2008


Gitweb:		http://git.netfilter.org/cgi-bin/gitweb.cgi?p=conntrack-tools.git;a=commit;h=77b1fdb824eb45213df4f57224e8e799fed43ded
commit 77b1fdb824eb45213df4f57224e8e799fed43ded
Author:     Pablo Neira Ayuso <pablo at netfilter.org>
AuthorDate: Tue Jul 22 12:13:43 2008 +0200
Commit:     Pablo Neira Ayuso <pablo at netfilter.org>
CommitDate: Tue Jul 22 12:13:43 2008 +0200

    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 at netfilter.org>
       via  77b1fdb824eb45213df4f57224e8e799fed43ded (commit)
      from  2de606c2458067c48e72058a31af384574cf9c70 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 77b1fdb824eb45213df4f57224e8e799fed43ded
Author: Pablo Neira Ayuso <pablo at netfilter.org>
Date:   Tue Jul 22 12:13:43 2008 +0200

    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 at netfilter.org>

-----------------------------------------------------------------------

 doc/stats/conntrackd.conf              |   54 ++++---
 doc/sync/alarm/node1/conntrackd.conf   |   65 +++++---
 doc/sync/alarm/node2/conntrackd.conf   |   65 +++++---
 doc/sync/ftfw/node1/conntrackd.conf    |   65 +++++---
 doc/sync/ftfw/node2/conntrackd.conf    |   65 +++++---
 doc/sync/notrack/node1/conntrackd.conf |   65 +++++---
 doc/sync/notrack/node2/conntrackd.conf |   65 +++++---
 include/Makefile.am                    |    4 +-
 include/bitops.h                       |   36 +++++
 include/conntrackd.h                   |    4 +-
 include/filter.h                       |   31 ++++
 include/ignore.h                       |   18 ---
 include/state_helper.h                 |   22 ---
 src/Makefile.am                        |    3 +-
 src/filter.c                           |  250 +++++++++++++++++++++++++++++++
 src/ignore_pool.c                      |  155 -------------------
 src/netlink.c                          |   16 +--
 src/read_config_lex.l                  |   14 +-
 src/read_config_yy.y                   |  255 ++++++++++++++++++++++++--------
 src/run.c                              |    4 +-
 src/state_helper.c                     |   44 ------
 src/state_helper_tcp.c                 |   35 -----
 src/sync-mode.c                        |    4 -
 23 files changed, 807 insertions(+), 532 deletions(-)
 create mode 100644 include/bitops.h
 create mode 100644 include/filter.h
 delete mode 100644 include/ignore.h
 delete mode 100644 include/state_helper.h
 create mode 100644 src/filter.c
 delete mode 100644 src/ignore_pool.c
 delete mode 100644 src/state_helper.c
 delete mode 100644 src/state_helper_tcp.c
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 at netfilter.org>

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 at 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 at 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 at 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 at 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);
 



More information about the netfilter-cvslog mailing list