[netfilter-cvslog] r6963 - in tags/libnetfilter_conntrack: . libnetfilter_conntrack-0.0.81 libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack libnetfilter_conntrack-0.0.81/src libnetfilter_conntrack-0.0.81/src/conntrack

pablo at netfilter.org pablo at netfilter.org
Sat Jul 28 14:31:57 CEST 2007


Author: pablo at netfilter.org
Date: 2007-07-28 14:31:57 +0200 (Sat, 28 Jul 2007)
New Revision: 6963

Added:
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c
Removed:
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c
   tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c
Log:
libnetfilter_conntrack 0.0.81 release tag


Copied: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81 (from rev 6889, trunk/libnetfilter_conntrack)

Deleted: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in
===================================================================
--- trunk/libnetfilter_conntrack/configure.in	2007-06-25 14:55:18 UTC (rev 6889)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in	2007-07-28 12:31:57 UTC (rev 6963)
@@ -1,74 +0,0 @@
-dnl Process this file with autoconf to create configure.
-
-AC_INIT
-
-AC_CANONICAL_SYSTEM
-
-AM_INIT_AUTOMAKE(libnetfilter_conntrack, 0.0.80)
-
-AC_PROG_CC
-AM_PROG_LIBTOOL
-AC_PROG_INSTALL
-AC_PROG_LN_S
-
-AC_SUBST(LIBTOOL_DEPS)
-
-case $target in 
-*-*-linux*) ;;
-*) AC_MSG_ERROR([Linux only, dude!]);;
-esac
-
-dnl Dependencies
-LIBNFNETLINK_REQUIRED=0.0.25
-
-PKG_CHECK_MODULES(LIBNFNETLINK, libnfnetlink >= $LIBNFNETLINK_REQUIRED,,
-	AC_MSG_ERROR(Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED))
-
-AC_CHECK_HEADERS(arpa/inet.h)
-dnl Check for inet_ntop
-AC_CHECK_FUNCS(inet_ntop)
-dnl Again, some systems have it, but not IPv6
-if test "$ac_cv_func_inet_ntop" = "yes" ; then
-AC_MSG_CHECKING(if inet_ntop supports IPv6)
-AC_TRY_RUN(
-   [
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#include <errno.h>
-int main()
-  {
-     struct in6_addr addr6;
-     char buf[128];
-     if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT)
-        exit(1);
-     else
-        exit(0);
-  }
-  ], [ AC_MSG_RESULT(yes)
-       AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6, 1, [Define to 1 if inet_ntop supports IPv6.])
-     ], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
-fi
-
-if test ! -z "$libdir"; then
-	MODULE_DIR="\\\"$libdir/libnetfilter_conntrack/\\\""
-	CFLAGS="$CFLAGS -DLIBNETFILTER_CONNTRACK_DIR=$MODULE_DIR"
-fi
-
-CFLAGS="$CFLAGS $LIBNFNETLINK_CFLAGS"
-LIBNFCONNTRACK_LIBS="$LIBNFNETLINK_LIBS"
-
-AC_SUBST(LIBNFCONNTRACK_LIBS)
-
-dnl Output the makefile
-AC_OUTPUT(Makefile src/Makefile include/Makefile utils/Makefile include/libnetfilter_conntrack/Makefile l3extensions/Makefile extensions/Makefile src/conntrack/Makefile src/expect/Makefile libnetfilter_conntrack.pc)
-

Copied: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in (from rev 6902, trunk/libnetfilter_conntrack/configure.in)
===================================================================
--- tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in	                        (rev 0)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/configure.in	2007-07-28 12:31:57 UTC (rev 6963)
@@ -0,0 +1,74 @@
+dnl Process this file with autoconf to create configure.
+
+AC_INIT
+
+AC_CANONICAL_SYSTEM
+
+AM_INIT_AUTOMAKE(libnetfilter_conntrack, 0.0.81)
+
+AC_PROG_CC
+AM_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_PROG_LN_S
+
+AC_SUBST(LIBTOOL_DEPS)
+
+case $target in 
+*-*-linux*) ;;
+*) AC_MSG_ERROR([Linux only, dude!]);;
+esac
+
+dnl Dependencies
+LIBNFNETLINK_REQUIRED=0.0.25
+
+PKG_CHECK_MODULES(LIBNFNETLINK, libnfnetlink >= $LIBNFNETLINK_REQUIRED,,
+	AC_MSG_ERROR(Cannot find libnfnetlink >= $LIBNFNETLINK_REQUIRED))
+
+AC_CHECK_HEADERS(arpa/inet.h)
+dnl Check for inet_ntop
+AC_CHECK_FUNCS(inet_ntop)
+dnl Again, some systems have it, but not IPv6
+if test "$ac_cv_func_inet_ntop" = "yes" ; then
+AC_MSG_CHECKING(if inet_ntop supports IPv6)
+AC_TRY_RUN(
+   [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#include <errno.h>
+int main()
+  {
+     struct in6_addr addr6;
+     char buf[128];
+     if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT)
+        exit(1);
+     else
+        exit(0);
+  }
+  ], [ AC_MSG_RESULT(yes)
+       AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6, 1, [Define to 1 if inet_ntop supports IPv6.])
+     ], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
+fi
+
+if test ! -z "$libdir"; then
+	MODULE_DIR="\\\"$libdir/libnetfilter_conntrack/\\\""
+	CFLAGS="$CFLAGS -DLIBNETFILTER_CONNTRACK_DIR=$MODULE_DIR"
+fi
+
+CFLAGS="$CFLAGS $LIBNFNETLINK_CFLAGS"
+LIBNFCONNTRACK_LIBS="$LIBNFNETLINK_LIBS"
+
+AC_SUBST(LIBNFCONNTRACK_LIBS)
+
+dnl Output the makefile
+AC_OUTPUT(Makefile src/Makefile include/Makefile utils/Makefile include/libnetfilter_conntrack/Makefile l3extensions/Makefile extensions/Makefile src/conntrack/Makefile src/expect/Makefile libnetfilter_conntrack.pc)
+

Deleted: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h
===================================================================
--- trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2007-06-25 14:55:18 UTC (rev 6889)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2007-07-28 12:31:57 UTC (rev 6963)
@@ -1,675 +0,0 @@
-/*
- * (C) 2005-2007 by Pablo Neira Ayuso <pablo at netfilter.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef _LIBNETFILTER_CONNTRACK_H_
-#define _LIBNETFILTER_CONNTRACK_H_
-
-#include <netinet/in.h>
-#include <libnfnetlink/linux_nfnetlink.h>
-#include <libnfnetlink/libnfnetlink.h>
-#include <libnetfilter_conntrack/linux_nfnetlink_conntrack.h> 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
-	CONNTRACK = NFNL_SUBSYS_CTNETLINK,
-	EXPECT = NFNL_SUBSYS_CTNETLINK_EXP
-};
-
-/*
- * Subscribe to all possible conntrack event groups. Use this 
- * flag in case that you want to catch up all the possible 
- * events. Do not use this flag for dumping or any other
- * similar operation.
- */
-#define NFCT_ALL_CT_GROUPS (NF_NETLINK_CONNTRACK_NEW|NF_NETLINK_CONNTRACK_UPDATE|NF_NETLINK_CONNTRACK_DESTROY)
-
-struct nfct_handle;
-
-/*
- * [Open|close] a conntrack handler
- */
-extern struct nfct_handle *nfct_open(u_int8_t, unsigned);
-extern struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh,
-					  u_int8_t subsys_id,
-					  unsigned int subscriptions);
-extern int nfct_close(struct nfct_handle *cth);
-
-extern int nfct_fd(struct nfct_handle *cth);
-
-/* 
- * NEW libnetfilter_conntrack API 
- */
-
-/* high level API */
-
-#include <sys/types.h>
-
-/* conntrack object */
-struct nf_conntrack;
-
-/* conntrack attributes */
-enum nf_conntrack_attr {
-	ATTR_ORIG_IPV4_SRC = 0,			/* u32 bits */
-	ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC,	/* alias */
-	ATTR_ORIG_IPV4_DST,			/* u32 bits */
-	ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST,	/* alias */
-	ATTR_REPL_IPV4_SRC,			/* u32 bits */
-	ATTR_REPL_IPV4_DST,			/* u32 bits */
-	ATTR_ORIG_IPV6_SRC = 4,			/* u128 bits */
-	ATTR_IPV6_SRC = ATTR_ORIG_IPV6_SRC,	/* alias */
-	ATTR_ORIG_IPV6_DST,			/* u128 bits */
-	ATTR_IPV6_DST = ATTR_ORIG_IPV6_DST,	/* alias */
-	ATTR_REPL_IPV6_SRC,			/* u128 bits */
-	ATTR_REPL_IPV6_DST,			/* u128 bits */
-	ATTR_ORIG_PORT_SRC = 8,			/* u16 bits */
-	ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC,	/* alias */
-	ATTR_ORIG_PORT_DST,			/* u16 bits */
-	ATTR_PORT_DST = ATTR_ORIG_PORT_DST,	/* alias */
-	ATTR_REPL_PORT_SRC,			/* u16 bits */
-	ATTR_REPL_PORT_DST,			/* u16 bits */
-	ATTR_ICMP_TYPE = 12,			/* u8 bits */
-	ATTR_ICMP_CODE,				/* u8 bits */
-	ATTR_ICMP_ID,				/* u16 bits */
-	ATTR_ORIG_L3PROTO,			/* u8 bits */
-	ATTR_L3PROTO = ATTR_ORIG_L3PROTO,	/* alias */
-	ATTR_REPL_L3PROTO = 16,			/* u8 bits */
-	ATTR_ORIG_L4PROTO,			/* u8 bits */
-	ATTR_L4PROTO = ATTR_ORIG_L4PROTO,	/* alias */
-	ATTR_REPL_L4PROTO,			/* u8 bits */
-	ATTR_TCP_STATE,				/* u8 bits */
-	ATTR_SNAT_IPV4 = 20,			/* u32 bits */
-	ATTR_DNAT_IPV4,				/* u32 bits */
-	ATTR_SNAT_PORT,				/* u16 bits */
-	ATTR_DNAT_PORT,				/* u16 bits */
-	ATTR_TIMEOUT = 24,			/* u32 bits */
-	ATTR_MARK,				/* u32 bits */
-	ATTR_ORIG_COUNTER_PACKETS,		/* u32 bits */
-	ATTR_REPL_COUNTER_PACKETS,		/* u32 bits */
-	ATTR_ORIG_COUNTER_BYTES = 28,		/* u32 bits */
-	ATTR_REPL_COUNTER_BYTES,		/* u32 bits */
-	ATTR_USE,				/* u32 bits */
-	ATTR_ID,				/* u32 bits */
-	ATTR_STATUS = 32,			/* u32 bits  */
-	ATTR_MAX
-};
-
-/* message type */
-enum nf_conntrack_msg_type {
-	NFCT_T_UNKNOWN = 0,
-
-	NFCT_T_NEW_BIT = 0,
-	NFCT_T_NEW = (1 << NFCT_T_NEW_BIT),
-
-	NFCT_T_UPDATE_BIT = 1,
-	NFCT_T_UPDATE = (1 << NFCT_T_UPDATE_BIT),
-
-	NFCT_T_DESTROY_BIT = 2,
-	NFCT_T_DESTROY = (1 << NFCT_T_DESTROY_BIT),
-
-	NFCT_T_ALL = NFCT_T_NEW | NFCT_T_UPDATE | NFCT_T_DESTROY,
-
-	NFCT_T_ERROR_BIT = 31,
-	NFCT_T_ERROR = (1 << NFCT_T_ERROR_BIT),
-};
-
-/* constructor / destructor */
-extern struct nf_conntrack *nfct_new(void);
-extern void nfct_destroy(struct nf_conntrack *ct);
-
-/* clone */
-struct nf_conntrack *nfct_clone(const struct nf_conntrack *ct);
-
-/* object size */
-extern size_t nfct_sizeof(const struct nf_conntrack *ct);
-
-/* maximum object size */
-extern size_t nfct_maxsize(void);
-
-/* set option */
-enum {
-	NFCT_SOPT_UNDO_SNAT,
-	NFCT_SOPT_UNDO_DNAT,
-	NFCT_SOPT_UNDO_SPAT,
-	NFCT_SOPT_UNDO_DPAT,
-	NFCT_SOPT_SETUP_ORIGINAL,
-	NFCT_SOPT_SETUP_REPLY,
-	__NFCT_SOPT_MAX,
-};
-#define NFCT_SOPT_MAX (__NFCT_SOPT_MAX - 1)
-
-/* get option */
-enum {
-	NFCT_GOPT_IS_SNAT,
-	NFCT_GOPT_IS_DNAT,
-	NFCT_GOPT_IS_SPAT,
-	NFCT_GOPT_IS_DPAT,
-	__NFCT_GOPT_MAX,
-};
-#define NFCT_GOPT_MAX (__NFCT_GOPT_MAX - 1)
-
-extern int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option);
-extern int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option);
-
-/* register / unregister callback */
-
-extern int nfct_callback_register(struct nfct_handle *h,
-				  enum nf_conntrack_msg_type type,
-				  int (*cb)(enum nf_conntrack_msg_type type,
-				  	    struct nf_conntrack *ct,
-					    void *data),
-				  void *data);
-
-extern void nfct_callback_unregister(struct nfct_handle *h);
-
-/* callback verdict */
-enum {
-	NFCT_CB_FAILURE = -1,   /* failure */
-	NFCT_CB_STOP = 0,       /* stop the query */
-	NFCT_CB_CONTINUE = 1,   /* keep iterating through data */
-	NFCT_CB_STOLEN = 2,     /* like continue, but ct is not freed */
-};
-
-/* setter */
-extern void nfct_set_attr(struct nf_conntrack *ct,
-			  const enum nf_conntrack_attr type,
-			  const void *value);
-
-extern void nfct_set_attr_u8(struct nf_conntrack *ct,
-			     const enum nf_conntrack_attr type,
-			     u_int8_t value);
-
-extern void nfct_set_attr_u16(struct nf_conntrack *ct,
-			      const enum nf_conntrack_attr type,
-			      u_int16_t value);
-
-extern void nfct_set_attr_u32(struct nf_conntrack *ct,
-			      const enum nf_conntrack_attr type,
-			      u_int32_t value);
-
-/* getter */
-extern const void *nfct_get_attr(const struct nf_conntrack *ct,
-				 const enum nf_conntrack_attr type);
-
-extern u_int8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
-				 const enum nf_conntrack_attr type);
-
-extern u_int16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
-				   const enum nf_conntrack_attr type);
-
-extern u_int32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
-				   const enum nf_conntrack_attr type);
-
-/* checker */
-extern int nfct_attr_is_set(const struct nf_conntrack *ct,
-			    const enum nf_conntrack_attr type);
-
-/* unsetter */
-extern int nfct_attr_unset(struct nf_conntrack *ct,
-			   const enum nf_conntrack_attr type);
-
-/* print */
-
-/* output type */
-enum {
-	NFCT_O_PLAIN,
-	NFCT_O_DEFAULT = NFCT_O_PLAIN,
-	NFCT_O_XML,
-	NFCT_O_MAX
-};
-
-/* output flags */
-enum {
-	NFCT_OF_SHOW_LAYER3_BIT = 0,
-	NFCT_OF_SHOW_LAYER3 = (1 << NFCT_OF_SHOW_LAYER3_BIT),
-};
-
-extern int nfct_snprintf(char *buf, 
-			 unsigned int size,
-			 const struct nf_conntrack *ct,
-			 const unsigned int msg_type,
-			 const unsigned int out_type,
-			 const unsigned int out_flags);
-
-extern int nfct_compare(const struct nf_conntrack *ct1,
-			const struct nf_conntrack *ct2);
-
-/* query */
-enum nf_conntrack_query {
-	NFCT_Q_CREATE,
-	NFCT_Q_UPDATE,
-	NFCT_Q_DESTROY,
-	NFCT_Q_GET,
-	NFCT_Q_FLUSH,
-	NFCT_Q_DUMP,
-	NFCT_Q_DUMP_RESET,
-	NFCT_Q_CREATE_UPDATE,
-};
-
-extern int nfct_query(struct nfct_handle *h,
-		      const enum nf_conntrack_query query,
-		      const void *data);
-
-extern int nfct_catch(struct nfct_handle *h);
-
-/* low level API: netlink functions */
-
-extern int nfct_build_conntrack(struct nfnl_subsys_handle *ssh,
-				void *req,
-				size_t size,
-				u_int16_t type,
-				u_int16_t flags,
-				const struct nf_conntrack *ct);
-
-extern int nfct_parse_conntrack(enum nf_conntrack_msg_type msg,
-				const struct nlmsghdr *nlh, 
-				struct nf_conntrack *ct);
-
-extern int nfct_build_query(struct nfnl_subsys_handle *ssh,
-			    const enum nf_conntrack_query query,
-			    const void *data,
-			    void *req,
-			    unsigned int size);
-
-/*
- * NEW expectation API
- */
-
-/* expectation object */
-struct nf_expect;
-
-/* expect attributes */
-enum nf_expect_attr {
-	ATTR_EXP_MASTER = 0,	/* pointer to conntrack object */
-	ATTR_EXP_EXPECTED,	/* pointer to conntrack object */
-	ATTR_EXP_MASK,		/* pointer to conntrack object */
-	ATTR_EXP_TIMEOUT,	/* u32 bits */
-	ATTR_EXP_MAX
-};
-
-/* constructor / destructor */
-extern struct nf_expect *nfexp_new(void);
-extern void nfexp_destroy(struct nf_expect *exp);
-
-/* clone */
-extern struct nf_expect *nfexp_clone(const struct nf_expect *exp);
-
-/* object size */
-extern size_t nfexp_sizeof(const struct nf_expect *exp);
-
-/* maximum object size */
-extern size_t nfexp_maxsize(void);
-
-/* register / unregister callback */
-
-extern int nfexp_callback_register(struct nfct_handle *h,
-				   enum nf_conntrack_msg_type type,
-				   int (*cb)(enum nf_conntrack_msg_type type,
-				  	     struct nf_expect *exp,
-					     void *data),
-				   void *data);
-
-extern void nfexp_callback_unregister(struct nfct_handle *h);
-
-/* setter */
-extern void nfexp_set_attr(struct nf_expect *exp,
-			   const enum nf_expect_attr type,
-			   const void *value);
-
-extern void nfexp_set_attr_u8(struct nf_expect *exp,
-			      const enum nf_expect_attr type,
-			      u_int8_t value);
-
-extern void nfexp_set_attr_u16(struct nf_expect *exp,
-			       const enum nf_expect_attr type,
-			       u_int16_t value);
-
-extern void nfexp_set_attr_u32(struct nf_expect *exp,
-			       const enum nf_expect_attr type,
-			       u_int32_t value);
-
-/* getter */
-extern const void *nfexp_get_attr(const struct nf_expect *exp,
-				  const enum nf_expect_attr type);
-
-extern u_int8_t nfexp_get_attr_u8(const struct nf_expect *exp,
-				  const enum nf_expect_attr type);
-
-extern u_int16_t nfexp_get_attr_u16(const struct nf_expect *exp,
-				    const enum nf_expect_attr type);
-
-extern u_int32_t nfexp_get_attr_u32(const struct nf_expect *exp,
-				    const enum nf_expect_attr type);
-
-/* checker */
-extern int nfexp_attr_is_set(const struct nf_expect *exp,
-			     const enum nf_expect_attr type);
-
-/* unsetter */
-extern int nfexp_attr_unset(struct nf_expect *exp,
-			    const enum nf_expect_attr type);
-
-/* query */
-extern int nfexp_query(struct nfct_handle *h,
-		       const enum nf_conntrack_query qt,
-		       const void *data);
-
-/* print */
-extern int nfexp_snprintf(char *buf, 
-			  unsigned int size,
-			  const struct nf_expect *exp,
-			  const unsigned int msg_type,
-			  const unsigned int out_type,
-			  const unsigned int out_flags);
-
-extern int nfexp_catch(struct nfct_handle *h);
-
-/* Bitset representing status of connection. Taken from ip_conntrack.h
- * 
- * Note: For backward compatibility this shouldn't ever change
- * 	 in kernel space.
- */
-enum ip_conntrack_status {
-	/* It's an expected connection: bit 0 set.  This bit never changed */
-	IPS_EXPECTED_BIT = 0,
-	IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
-
-	/* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
-	IPS_SEEN_REPLY_BIT = 1,
-	IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
-
-	/* Conntrack should never be early-expired. */
-	IPS_ASSURED_BIT = 2,
-	IPS_ASSURED = (1 << IPS_ASSURED_BIT),
-
-	/* Connection is confirmed: originating packet has left box */
-	IPS_CONFIRMED_BIT = 3,
-	IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
-
-	/* Connection needs src nat in orig dir.  This bit never changed. */
-	IPS_SRC_NAT_BIT = 4,
-	IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
-
-	/* Connection needs dst nat in orig dir.  This bit never changed. */
-	IPS_DST_NAT_BIT = 5,
-	IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
-
-	/* Both together. */
-	IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
-
-	/* Connection needs TCP sequence adjusted. */
-	IPS_SEQ_ADJUST_BIT = 6,
-	IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
-
-	/* NAT initialization bits. */
-	IPS_SRC_NAT_DONE_BIT = 7,
-	IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
-
-	IPS_DST_NAT_DONE_BIT = 8,
-	IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
-
-	/* Both together */
-	IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
-
-	/* Connection is dying (removed from lists), can not be unset. */
-	IPS_DYING_BIT = 9,
-	IPS_DYING = (1 << IPS_DYING_BIT),
-
-    /* Connection has fixed timeout. */
-	IPS_FIXED_TIMEOUT_BIT = 10,
-	IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
-};
-
-/* 
- * Old deprecated API, its use for new applications is *strongly discouraged* 
- */
-
-/*
- * In case that the user doesn't want to do some kind
- * of action against a conntrack based on its ID 
- */
-#define NFCT_ANY_ID 0
-
-union nfct_l4 {
-	/* Add other protocols here. */
-	u_int16_t all;
-	struct {
-		u_int16_t port;
-	} tcp;
-	struct {
-		u_int16_t port;
-	} udp;
-	struct {
-		u_int8_t type, code;
-		u_int16_t id;
-	} icmp;
-	struct {
-		u_int16_t port;
-	} sctp;
-};
-
-union nfct_address {
-	u_int32_t v4;
-	u_int32_t v6[4];
-};
-
-struct nfct_tuple {
-	union nfct_address src;
-	union nfct_address dst;
-
-	u_int8_t l3protonum;
-	u_int8_t protonum;
-	union nfct_l4 l4src;
-	union nfct_l4 l4dst;
-};
-
-union nfct_protoinfo {
-	struct {
-		u_int8_t state;
-	} tcp;
-};
-
-struct nfct_counters {
-	u_int64_t packets;
-	u_int64_t bytes;
-};
-
-struct nfct_nat {
-	u_int32_t min_ip, max_ip;
-	union nfct_l4 l4min, l4max;
-};
-
-#define NFCT_DIR_ORIGINAL 0
-#define NFCT_DIR_REPLY 1
-#define NFCT_DIR_MAX NFCT_DIR_REPLY+1
-
-struct nfct_conntrack {
-	struct nfct_tuple tuple[NFCT_DIR_MAX];
-	
-	u_int32_t 	timeout;
-	u_int32_t	mark;
-	u_int32_t 	status;
-	u_int32_t	use;
-	u_int32_t	id;
-
-	union nfct_protoinfo protoinfo;
-	struct nfct_counters counters[NFCT_DIR_MAX];
-	struct nfct_nat nat;
-};
-
-struct nfct_expect {
-	struct nfct_tuple master;
-	struct nfct_tuple tuple;
-	struct nfct_tuple mask;
-	u_int32_t timeout;
-	u_int32_t id;
-	u_int16_t expectfn_queue_id;
-};
-
-struct nfct_conntrack_compare {
-	struct nfct_conntrack *ct;
-	unsigned int flags;
-	unsigned int l3flags;
-	unsigned int l4flags;
-};
-
-enum {
-	NFCT_STATUS_BIT = 0,
-	NFCT_STATUS = (1 << NFCT_STATUS_BIT),
-	
-	NFCT_PROTOINFO_BIT = 1,
-	NFCT_PROTOINFO = (1 << NFCT_PROTOINFO_BIT),
-
-	NFCT_TIMEOUT_BIT = 2,
-	NFCT_TIMEOUT = (1 << NFCT_TIMEOUT_BIT),
-
-	NFCT_MARK_BIT = 3,
-	NFCT_MARK = (1 << NFCT_MARK_BIT),
-
-	NFCT_COUNTERS_ORIG_BIT = 4,
-	NFCT_COUNTERS_ORIG = (1 << NFCT_COUNTERS_ORIG_BIT),
-
-	NFCT_COUNTERS_RPLY_BIT = 5,
-	NFCT_COUNTERS_RPLY = (1 << NFCT_COUNTERS_RPLY_BIT),
-
-	NFCT_USE_BIT = 6,
-	NFCT_USE = (1 << NFCT_USE_BIT),
-
-	NFCT_ID_BIT = 7,
-	NFCT_ID = (1 << NFCT_ID_BIT)
-};
-
-enum {
-	NFCT_MSG_UNKNOWN,
-	NFCT_MSG_NEW,
-	NFCT_MSG_UPDATE,
-	NFCT_MSG_DESTROY
-};
-
-typedef int (*nfct_callback)(void *arg, unsigned int flags, int, void *data);
-
-/*
- * [Allocate|free] a conntrack
- */
-extern struct nfct_conntrack *
-nfct_conntrack_alloc(struct nfct_tuple *orig, struct nfct_tuple *reply,
-		     u_int32_t timeout, union nfct_protoinfo *proto,
-		     u_int32_t status, u_int32_t mark,
-		     u_int32_t id, struct nfct_nat *range);
-extern void nfct_conntrack_free(struct nfct_conntrack *ct);
-
-/*
- * [Allocate|free] an expectation
- */
-extern struct nfct_expect *
-nfct_expect_alloc(struct nfct_tuple *master, struct nfct_tuple *tuple,
-		  struct nfct_tuple *mask, u_int32_t timeout, 
-		  u_int32_t id);
-extern void nfct_expect_free(struct nfct_expect *exp);
-
-
-/*
- * [Register|unregister] callbacks
- */
-extern void nfct_register_callback(struct nfct_handle *cth,
-				   nfct_callback callback, void *data);
-extern void nfct_unregister_callback(struct nfct_handle *cth);
-
-/*
- * callback displayers
- */
-extern int nfct_default_conntrack_display(void *, unsigned int, int, void *); 
-extern int nfct_default_conntrack_display_id(void *, unsigned int, int, void *);
-extern int nfct_default_expect_display(void *, unsigned int, int, void *);
-extern int nfct_default_expect_display_id(void *, unsigned int, int, void *);
-extern int nfct_default_conntrack_event_display(void *, unsigned int, int, 
-						void *);
-
-/*
- * [Create|update|get|destroy] conntracks
- */
-extern int nfct_create_conntrack(struct nfct_handle *cth, 
-				 struct nfct_conntrack *ct);
-extern int nfct_update_conntrack(struct nfct_handle *cth,
-				 struct nfct_conntrack *ct);
-extern int nfct_delete_conntrack(struct nfct_handle *cth, 
-				 struct nfct_tuple *tuple, int dir, 
-				 u_int32_t id);
-extern int nfct_get_conntrack(struct nfct_handle *cth, 
-			      struct nfct_tuple *tuple, int dir,
-			      u_int32_t id); 
-/*
- * Conntrack table dumping & zeroing
- */
-extern int nfct_dump_conntrack_table(struct nfct_handle *cth, int family);
-extern int nfct_dump_conntrack_table_reset_counters(struct nfct_handle *cth, 
-						    int family);
-
-/*
- * Conntrack event notification
- */
-extern int nfct_event_conntrack(struct nfct_handle *cth); 
-
-/*
- * Conntrack printing functions
- */
-extern int nfct_sprintf_conntrack(char *buf, struct nfct_conntrack *ct, 
-				  unsigned int flags);
-extern int nfct_sprintf_conntrack_id(char *buf, struct nfct_conntrack *ct,
-				     unsigned int flags);
-extern int nfct_sprintf_address(char *buf, struct nfct_tuple *t);
-extern int nfct_sprintf_proto(char *buf, struct nfct_tuple *t);
-extern int nfct_sprintf_protoinfo(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_timeout(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_protocol(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_status_assured(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_status_seen_reply(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_counters(char *buf, struct nfct_conntrack *ct, int dir);
-extern int nfct_sprintf_mark(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_use(char *buf, struct nfct_conntrack *ct);
-extern int nfct_sprintf_id(char *buf, u_int32_t id);
-
-/*
- * Conntrack comparison
- */
-extern int nfct_conntrack_compare(struct nfct_conntrack *ct1, 
-				  struct nfct_conntrack *ct2,
-				  struct nfct_conntrack_compare *cmp);
-
-/* 
- * Expectations
- */
-extern int nfct_dump_expect_list(struct nfct_handle *cth, int family);
-extern int nfct_flush_conntrack_table(struct nfct_handle *cth, int family);
-extern int nfct_get_expectation(struct nfct_handle *cth, 
-				struct nfct_tuple *tuple,
-				u_int32_t id);
-extern int nfct_create_expectation(struct nfct_handle *cth, struct nfct_expect *);
-extern int nfct_delete_expectation(struct nfct_handle *cth,
-				   struct nfct_tuple *tuple, u_int32_t id);
-extern int nfct_event_expectation(struct nfct_handle *cth);
-extern int nfct_flush_expectation_table(struct nfct_handle *cth, int family);
-
-/*
- * expectation printing functions
- */
-extern int nfct_sprintf_expect(char *buf, struct nfct_expect *exp);
-extern int nfct_sprintf_expect_id(char *buf, struct nfct_expect *exp);
-
-/*
- * low-level functions for libnetfilter_cthelper
- */
-extern void nfct_build_tuple(struct nfnlhdr *req, int size, 
-			     struct nfct_tuple *t, int type);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _LIBNETFILTER_CONNTRACK_H_ */

Copied: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h (from rev 6902, trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h)
===================================================================
--- tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h	                        (rev 0)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2007-07-28 12:31:57 UTC (rev 6963)
@@ -0,0 +1,676 @@
+/*
+ * (C) 2005-2007 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#ifndef _LIBNETFILTER_CONNTRACK_H_
+#define _LIBNETFILTER_CONNTRACK_H_
+
+#include <netinet/in.h>
+#include <libnfnetlink/linux_nfnetlink.h>
+#include <libnfnetlink/libnfnetlink.h>
+#include <libnetfilter_conntrack/linux_nfnetlink_conntrack.h> 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+	CONNTRACK = NFNL_SUBSYS_CTNETLINK,
+	EXPECT = NFNL_SUBSYS_CTNETLINK_EXP
+};
+
+/*
+ * Subscribe to all possible conntrack event groups. Use this 
+ * flag in case that you want to catch up all the possible 
+ * events. Do not use this flag for dumping or any other
+ * similar operation.
+ */
+#define NFCT_ALL_CT_GROUPS (NF_NETLINK_CONNTRACK_NEW|NF_NETLINK_CONNTRACK_UPDATE|NF_NETLINK_CONNTRACK_DESTROY)
+
+struct nfct_handle;
+
+/*
+ * [Open|close] a conntrack handler
+ */
+extern struct nfct_handle *nfct_open(u_int8_t, unsigned);
+extern struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh,
+					  u_int8_t subsys_id,
+					  unsigned int subscriptions);
+extern int nfct_close(struct nfct_handle *cth);
+
+extern int nfct_fd(struct nfct_handle *cth);
+extern const struct nfnl_handle *nfct_nfnlh(struct nfct_handle *cth);
+
+/* 
+ * NEW libnetfilter_conntrack API 
+ */
+
+/* high level API */
+
+#include <sys/types.h>
+
+/* conntrack object */
+struct nf_conntrack;
+
+/* conntrack attributes */
+enum nf_conntrack_attr {
+	ATTR_ORIG_IPV4_SRC = 0,			/* u32 bits */
+	ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC,	/* alias */
+	ATTR_ORIG_IPV4_DST,			/* u32 bits */
+	ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST,	/* alias */
+	ATTR_REPL_IPV4_SRC,			/* u32 bits */
+	ATTR_REPL_IPV4_DST,			/* u32 bits */
+	ATTR_ORIG_IPV6_SRC = 4,			/* u128 bits */
+	ATTR_IPV6_SRC = ATTR_ORIG_IPV6_SRC,	/* alias */
+	ATTR_ORIG_IPV6_DST,			/* u128 bits */
+	ATTR_IPV6_DST = ATTR_ORIG_IPV6_DST,	/* alias */
+	ATTR_REPL_IPV6_SRC,			/* u128 bits */
+	ATTR_REPL_IPV6_DST,			/* u128 bits */
+	ATTR_ORIG_PORT_SRC = 8,			/* u16 bits */
+	ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC,	/* alias */
+	ATTR_ORIG_PORT_DST,			/* u16 bits */
+	ATTR_PORT_DST = ATTR_ORIG_PORT_DST,	/* alias */
+	ATTR_REPL_PORT_SRC,			/* u16 bits */
+	ATTR_REPL_PORT_DST,			/* u16 bits */
+	ATTR_ICMP_TYPE = 12,			/* u8 bits */
+	ATTR_ICMP_CODE,				/* u8 bits */
+	ATTR_ICMP_ID,				/* u16 bits */
+	ATTR_ORIG_L3PROTO,			/* u8 bits */
+	ATTR_L3PROTO = ATTR_ORIG_L3PROTO,	/* alias */
+	ATTR_REPL_L3PROTO = 16,			/* u8 bits */
+	ATTR_ORIG_L4PROTO,			/* u8 bits */
+	ATTR_L4PROTO = ATTR_ORIG_L4PROTO,	/* alias */
+	ATTR_REPL_L4PROTO,			/* u8 bits */
+	ATTR_TCP_STATE,				/* u8 bits */
+	ATTR_SNAT_IPV4 = 20,			/* u32 bits */
+	ATTR_DNAT_IPV4,				/* u32 bits */
+	ATTR_SNAT_PORT,				/* u16 bits */
+	ATTR_DNAT_PORT,				/* u16 bits */
+	ATTR_TIMEOUT = 24,			/* u32 bits */
+	ATTR_MARK,				/* u32 bits */
+	ATTR_ORIG_COUNTER_PACKETS,		/* u32 bits */
+	ATTR_REPL_COUNTER_PACKETS,		/* u32 bits */
+	ATTR_ORIG_COUNTER_BYTES = 28,		/* u32 bits */
+	ATTR_REPL_COUNTER_BYTES,		/* u32 bits */
+	ATTR_USE,				/* u32 bits */
+	ATTR_ID,				/* u32 bits */
+	ATTR_STATUS = 32,			/* u32 bits  */
+	ATTR_MAX
+};
+
+/* message type */
+enum nf_conntrack_msg_type {
+	NFCT_T_UNKNOWN = 0,
+
+	NFCT_T_NEW_BIT = 0,
+	NFCT_T_NEW = (1 << NFCT_T_NEW_BIT),
+
+	NFCT_T_UPDATE_BIT = 1,
+	NFCT_T_UPDATE = (1 << NFCT_T_UPDATE_BIT),
+
+	NFCT_T_DESTROY_BIT = 2,
+	NFCT_T_DESTROY = (1 << NFCT_T_DESTROY_BIT),
+
+	NFCT_T_ALL = NFCT_T_NEW | NFCT_T_UPDATE | NFCT_T_DESTROY,
+
+	NFCT_T_ERROR_BIT = 31,
+	NFCT_T_ERROR = (1 << NFCT_T_ERROR_BIT),
+};
+
+/* constructor / destructor */
+extern struct nf_conntrack *nfct_new(void);
+extern void nfct_destroy(struct nf_conntrack *ct);
+
+/* clone */
+struct nf_conntrack *nfct_clone(const struct nf_conntrack *ct);
+
+/* object size */
+extern size_t nfct_sizeof(const struct nf_conntrack *ct);
+
+/* maximum object size */
+extern size_t nfct_maxsize(void);
+
+/* set option */
+enum {
+	NFCT_SOPT_UNDO_SNAT,
+	NFCT_SOPT_UNDO_DNAT,
+	NFCT_SOPT_UNDO_SPAT,
+	NFCT_SOPT_UNDO_DPAT,
+	NFCT_SOPT_SETUP_ORIGINAL,
+	NFCT_SOPT_SETUP_REPLY,
+	__NFCT_SOPT_MAX,
+};
+#define NFCT_SOPT_MAX (__NFCT_SOPT_MAX - 1)
+
+/* get option */
+enum {
+	NFCT_GOPT_IS_SNAT,
+	NFCT_GOPT_IS_DNAT,
+	NFCT_GOPT_IS_SPAT,
+	NFCT_GOPT_IS_DPAT,
+	__NFCT_GOPT_MAX,
+};
+#define NFCT_GOPT_MAX (__NFCT_GOPT_MAX - 1)
+
+extern int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option);
+extern int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option);
+
+/* register / unregister callback */
+
+extern int nfct_callback_register(struct nfct_handle *h,
+				  enum nf_conntrack_msg_type type,
+				  int (*cb)(enum nf_conntrack_msg_type type,
+				  	    struct nf_conntrack *ct,
+					    void *data),
+				  void *data);
+
+extern void nfct_callback_unregister(struct nfct_handle *h);
+
+/* callback verdict */
+enum {
+	NFCT_CB_FAILURE = -1,   /* failure */
+	NFCT_CB_STOP = 0,       /* stop the query */
+	NFCT_CB_CONTINUE = 1,   /* keep iterating through data */
+	NFCT_CB_STOLEN = 2,     /* like continue, but ct is not freed */
+};
+
+/* setter */
+extern void nfct_set_attr(struct nf_conntrack *ct,
+			  const enum nf_conntrack_attr type,
+			  const void *value);
+
+extern void nfct_set_attr_u8(struct nf_conntrack *ct,
+			     const enum nf_conntrack_attr type,
+			     u_int8_t value);
+
+extern void nfct_set_attr_u16(struct nf_conntrack *ct,
+			      const enum nf_conntrack_attr type,
+			      u_int16_t value);
+
+extern void nfct_set_attr_u32(struct nf_conntrack *ct,
+			      const enum nf_conntrack_attr type,
+			      u_int32_t value);
+
+/* getter */
+extern const void *nfct_get_attr(const struct nf_conntrack *ct,
+				 const enum nf_conntrack_attr type);
+
+extern u_int8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
+				 const enum nf_conntrack_attr type);
+
+extern u_int16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
+				   const enum nf_conntrack_attr type);
+
+extern u_int32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
+				   const enum nf_conntrack_attr type);
+
+/* checker */
+extern int nfct_attr_is_set(const struct nf_conntrack *ct,
+			    const enum nf_conntrack_attr type);
+
+/* unsetter */
+extern int nfct_attr_unset(struct nf_conntrack *ct,
+			   const enum nf_conntrack_attr type);
+
+/* print */
+
+/* output type */
+enum {
+	NFCT_O_PLAIN,
+	NFCT_O_DEFAULT = NFCT_O_PLAIN,
+	NFCT_O_XML,
+	NFCT_O_MAX
+};
+
+/* output flags */
+enum {
+	NFCT_OF_SHOW_LAYER3_BIT = 0,
+	NFCT_OF_SHOW_LAYER3 = (1 << NFCT_OF_SHOW_LAYER3_BIT),
+};
+
+extern int nfct_snprintf(char *buf, 
+			 unsigned int size,
+			 const struct nf_conntrack *ct,
+			 const unsigned int msg_type,
+			 const unsigned int out_type,
+			 const unsigned int out_flags);
+
+extern int nfct_compare(const struct nf_conntrack *ct1,
+			const struct nf_conntrack *ct2);
+
+/* query */
+enum nf_conntrack_query {
+	NFCT_Q_CREATE,
+	NFCT_Q_UPDATE,
+	NFCT_Q_DESTROY,
+	NFCT_Q_GET,
+	NFCT_Q_FLUSH,
+	NFCT_Q_DUMP,
+	NFCT_Q_DUMP_RESET,
+	NFCT_Q_CREATE_UPDATE,
+};
+
+extern int nfct_query(struct nfct_handle *h,
+		      const enum nf_conntrack_query query,
+		      const void *data);
+
+extern int nfct_catch(struct nfct_handle *h);
+
+/* low level API: netlink functions */
+
+extern int nfct_build_conntrack(struct nfnl_subsys_handle *ssh,
+				void *req,
+				size_t size,
+				u_int16_t type,
+				u_int16_t flags,
+				const struct nf_conntrack *ct);
+
+extern int nfct_parse_conntrack(enum nf_conntrack_msg_type msg,
+				const struct nlmsghdr *nlh, 
+				struct nf_conntrack *ct);
+
+extern int nfct_build_query(struct nfnl_subsys_handle *ssh,
+			    const enum nf_conntrack_query query,
+			    const void *data,
+			    void *req,
+			    unsigned int size);
+
+/*
+ * NEW expectation API
+ */
+
+/* expectation object */
+struct nf_expect;
+
+/* expect attributes */
+enum nf_expect_attr {
+	ATTR_EXP_MASTER = 0,	/* pointer to conntrack object */
+	ATTR_EXP_EXPECTED,	/* pointer to conntrack object */
+	ATTR_EXP_MASK,		/* pointer to conntrack object */
+	ATTR_EXP_TIMEOUT,	/* u32 bits */
+	ATTR_EXP_MAX
+};
+
+/* constructor / destructor */
+extern struct nf_expect *nfexp_new(void);
+extern void nfexp_destroy(struct nf_expect *exp);
+
+/* clone */
+extern struct nf_expect *nfexp_clone(const struct nf_expect *exp);
+
+/* object size */
+extern size_t nfexp_sizeof(const struct nf_expect *exp);
+
+/* maximum object size */
+extern size_t nfexp_maxsize(void);
+
+/* register / unregister callback */
+
+extern int nfexp_callback_register(struct nfct_handle *h,
+				   enum nf_conntrack_msg_type type,
+				   int (*cb)(enum nf_conntrack_msg_type type,
+				  	     struct nf_expect *exp,
+					     void *data),
+				   void *data);
+
+extern void nfexp_callback_unregister(struct nfct_handle *h);
+
+/* setter */
+extern void nfexp_set_attr(struct nf_expect *exp,
+			   const enum nf_expect_attr type,
+			   const void *value);
+
+extern void nfexp_set_attr_u8(struct nf_expect *exp,
+			      const enum nf_expect_attr type,
+			      u_int8_t value);
+
+extern void nfexp_set_attr_u16(struct nf_expect *exp,
+			       const enum nf_expect_attr type,
+			       u_int16_t value);
+
+extern void nfexp_set_attr_u32(struct nf_expect *exp,
+			       const enum nf_expect_attr type,
+			       u_int32_t value);
+
+/* getter */
+extern const void *nfexp_get_attr(const struct nf_expect *exp,
+				  const enum nf_expect_attr type);
+
+extern u_int8_t nfexp_get_attr_u8(const struct nf_expect *exp,
+				  const enum nf_expect_attr type);
+
+extern u_int16_t nfexp_get_attr_u16(const struct nf_expect *exp,
+				    const enum nf_expect_attr type);
+
+extern u_int32_t nfexp_get_attr_u32(const struct nf_expect *exp,
+				    const enum nf_expect_attr type);
+
+/* checker */
+extern int nfexp_attr_is_set(const struct nf_expect *exp,
+			     const enum nf_expect_attr type);
+
+/* unsetter */
+extern int nfexp_attr_unset(struct nf_expect *exp,
+			    const enum nf_expect_attr type);
+
+/* query */
+extern int nfexp_query(struct nfct_handle *h,
+		       const enum nf_conntrack_query qt,
+		       const void *data);
+
+/* print */
+extern int nfexp_snprintf(char *buf, 
+			  unsigned int size,
+			  const struct nf_expect *exp,
+			  const unsigned int msg_type,
+			  const unsigned int out_type,
+			  const unsigned int out_flags);
+
+extern int nfexp_catch(struct nfct_handle *h);
+
+/* Bitset representing status of connection. Taken from ip_conntrack.h
+ * 
+ * Note: For backward compatibility this shouldn't ever change
+ * 	 in kernel space.
+ */
+enum ip_conntrack_status {
+	/* It's an expected connection: bit 0 set.  This bit never changed */
+	IPS_EXPECTED_BIT = 0,
+	IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
+
+	/* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
+	IPS_SEEN_REPLY_BIT = 1,
+	IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
+
+	/* Conntrack should never be early-expired. */
+	IPS_ASSURED_BIT = 2,
+	IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+	/* Connection is confirmed: originating packet has left box */
+	IPS_CONFIRMED_BIT = 3,
+	IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
+
+	/* Connection needs src nat in orig dir.  This bit never changed. */
+	IPS_SRC_NAT_BIT = 4,
+	IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
+
+	/* Connection needs dst nat in orig dir.  This bit never changed. */
+	IPS_DST_NAT_BIT = 5,
+	IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
+
+	/* Both together. */
+	IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
+
+	/* Connection needs TCP sequence adjusted. */
+	IPS_SEQ_ADJUST_BIT = 6,
+	IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
+
+	/* NAT initialization bits. */
+	IPS_SRC_NAT_DONE_BIT = 7,
+	IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
+
+	IPS_DST_NAT_DONE_BIT = 8,
+	IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
+
+	/* Both together */
+	IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
+
+	/* Connection is dying (removed from lists), can not be unset. */
+	IPS_DYING_BIT = 9,
+	IPS_DYING = (1 << IPS_DYING_BIT),
+
+    /* Connection has fixed timeout. */
+	IPS_FIXED_TIMEOUT_BIT = 10,
+	IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+};
+
+/* 
+ * Old deprecated API, its use for new applications is *strongly discouraged* 
+ */
+
+/*
+ * In case that the user doesn't want to do some kind
+ * of action against a conntrack based on its ID 
+ */
+#define NFCT_ANY_ID 0
+
+union nfct_l4 {
+	/* Add other protocols here. */
+	u_int16_t all;
+	struct {
+		u_int16_t port;
+	} tcp;
+	struct {
+		u_int16_t port;
+	} udp;
+	struct {
+		u_int8_t type, code;
+		u_int16_t id;
+	} icmp;
+	struct {
+		u_int16_t port;
+	} sctp;
+};
+
+union nfct_address {
+	u_int32_t v4;
+	u_int32_t v6[4];
+};
+
+struct nfct_tuple {
+	union nfct_address src;
+	union nfct_address dst;
+
+	u_int8_t l3protonum;
+	u_int8_t protonum;
+	union nfct_l4 l4src;
+	union nfct_l4 l4dst;
+};
+
+union nfct_protoinfo {
+	struct {
+		u_int8_t state;
+	} tcp;
+};
+
+struct nfct_counters {
+	u_int64_t packets;
+	u_int64_t bytes;
+};
+
+struct nfct_nat {
+	u_int32_t min_ip, max_ip;
+	union nfct_l4 l4min, l4max;
+};
+
+#define NFCT_DIR_ORIGINAL 0
+#define NFCT_DIR_REPLY 1
+#define NFCT_DIR_MAX NFCT_DIR_REPLY+1
+
+struct nfct_conntrack {
+	struct nfct_tuple tuple[NFCT_DIR_MAX];
+	
+	u_int32_t 	timeout;
+	u_int32_t	mark;
+	u_int32_t 	status;
+	u_int32_t	use;
+	u_int32_t	id;
+
+	union nfct_protoinfo protoinfo;
+	struct nfct_counters counters[NFCT_DIR_MAX];
+	struct nfct_nat nat;
+};
+
+struct nfct_expect {
+	struct nfct_tuple master;
+	struct nfct_tuple tuple;
+	struct nfct_tuple mask;
+	u_int32_t timeout;
+	u_int32_t id;
+	u_int16_t expectfn_queue_id;
+};
+
+struct nfct_conntrack_compare {
+	struct nfct_conntrack *ct;
+	unsigned int flags;
+	unsigned int l3flags;
+	unsigned int l4flags;
+};
+
+enum {
+	NFCT_STATUS_BIT = 0,
+	NFCT_STATUS = (1 << NFCT_STATUS_BIT),
+	
+	NFCT_PROTOINFO_BIT = 1,
+	NFCT_PROTOINFO = (1 << NFCT_PROTOINFO_BIT),
+
+	NFCT_TIMEOUT_BIT = 2,
+	NFCT_TIMEOUT = (1 << NFCT_TIMEOUT_BIT),
+
+	NFCT_MARK_BIT = 3,
+	NFCT_MARK = (1 << NFCT_MARK_BIT),
+
+	NFCT_COUNTERS_ORIG_BIT = 4,
+	NFCT_COUNTERS_ORIG = (1 << NFCT_COUNTERS_ORIG_BIT),
+
+	NFCT_COUNTERS_RPLY_BIT = 5,
+	NFCT_COUNTERS_RPLY = (1 << NFCT_COUNTERS_RPLY_BIT),
+
+	NFCT_USE_BIT = 6,
+	NFCT_USE = (1 << NFCT_USE_BIT),
+
+	NFCT_ID_BIT = 7,
+	NFCT_ID = (1 << NFCT_ID_BIT)
+};
+
+enum {
+	NFCT_MSG_UNKNOWN,
+	NFCT_MSG_NEW,
+	NFCT_MSG_UPDATE,
+	NFCT_MSG_DESTROY
+};
+
+typedef int (*nfct_callback)(void *arg, unsigned int flags, int, void *data);
+
+/*
+ * [Allocate|free] a conntrack
+ */
+extern struct nfct_conntrack *
+nfct_conntrack_alloc(struct nfct_tuple *orig, struct nfct_tuple *reply,
+		     u_int32_t timeout, union nfct_protoinfo *proto,
+		     u_int32_t status, u_int32_t mark,
+		     u_int32_t id, struct nfct_nat *range);
+extern void nfct_conntrack_free(struct nfct_conntrack *ct);
+
+/*
+ * [Allocate|free] an expectation
+ */
+extern struct nfct_expect *
+nfct_expect_alloc(struct nfct_tuple *master, struct nfct_tuple *tuple,
+		  struct nfct_tuple *mask, u_int32_t timeout, 
+		  u_int32_t id);
+extern void nfct_expect_free(struct nfct_expect *exp);
+
+
+/*
+ * [Register|unregister] callbacks
+ */
+extern void nfct_register_callback(struct nfct_handle *cth,
+				   nfct_callback callback, void *data);
+extern void nfct_unregister_callback(struct nfct_handle *cth);
+
+/*
+ * callback displayers
+ */
+extern int nfct_default_conntrack_display(void *, unsigned int, int, void *); 
+extern int nfct_default_conntrack_display_id(void *, unsigned int, int, void *);
+extern int nfct_default_expect_display(void *, unsigned int, int, void *);
+extern int nfct_default_expect_display_id(void *, unsigned int, int, void *);
+extern int nfct_default_conntrack_event_display(void *, unsigned int, int, 
+						void *);
+
+/*
+ * [Create|update|get|destroy] conntracks
+ */
+extern int nfct_create_conntrack(struct nfct_handle *cth, 
+				 struct nfct_conntrack *ct);
+extern int nfct_update_conntrack(struct nfct_handle *cth,
+				 struct nfct_conntrack *ct);
+extern int nfct_delete_conntrack(struct nfct_handle *cth, 
+				 struct nfct_tuple *tuple, int dir, 
+				 u_int32_t id);
+extern int nfct_get_conntrack(struct nfct_handle *cth, 
+			      struct nfct_tuple *tuple, int dir,
+			      u_int32_t id); 
+/*
+ * Conntrack table dumping & zeroing
+ */
+extern int nfct_dump_conntrack_table(struct nfct_handle *cth, int family);
+extern int nfct_dump_conntrack_table_reset_counters(struct nfct_handle *cth, 
+						    int family);
+
+/*
+ * Conntrack event notification
+ */
+extern int nfct_event_conntrack(struct nfct_handle *cth); 
+
+/*
+ * Conntrack printing functions
+ */
+extern int nfct_sprintf_conntrack(char *buf, struct nfct_conntrack *ct, 
+				  unsigned int flags);
+extern int nfct_sprintf_conntrack_id(char *buf, struct nfct_conntrack *ct,
+				     unsigned int flags);
+extern int nfct_sprintf_address(char *buf, struct nfct_tuple *t);
+extern int nfct_sprintf_proto(char *buf, struct nfct_tuple *t);
+extern int nfct_sprintf_protoinfo(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_timeout(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_protocol(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_status_assured(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_status_seen_reply(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_counters(char *buf, struct nfct_conntrack *ct, int dir);
+extern int nfct_sprintf_mark(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_use(char *buf, struct nfct_conntrack *ct);
+extern int nfct_sprintf_id(char *buf, u_int32_t id);
+
+/*
+ * Conntrack comparison
+ */
+extern int nfct_conntrack_compare(struct nfct_conntrack *ct1, 
+				  struct nfct_conntrack *ct2,
+				  struct nfct_conntrack_compare *cmp);
+
+/* 
+ * Expectations
+ */
+extern int nfct_dump_expect_list(struct nfct_handle *cth, int family);
+extern int nfct_flush_conntrack_table(struct nfct_handle *cth, int family);
+extern int nfct_get_expectation(struct nfct_handle *cth, 
+				struct nfct_tuple *tuple,
+				u_int32_t id);
+extern int nfct_create_expectation(struct nfct_handle *cth, struct nfct_expect *);
+extern int nfct_delete_expectation(struct nfct_handle *cth,
+				   struct nfct_tuple *tuple, u_int32_t id);
+extern int nfct_event_expectation(struct nfct_handle *cth);
+extern int nfct_flush_expectation_table(struct nfct_handle *cth, int family);
+
+/*
+ * expectation printing functions
+ */
+extern int nfct_sprintf_expect(char *buf, struct nfct_expect *exp);
+extern int nfct_sprintf_expect_id(char *buf, struct nfct_expect *exp);
+
+/*
+ * low-level functions for libnetfilter_cthelper
+ */
+extern void nfct_build_tuple(struct nfnlhdr *req, int size, 
+			     struct nfct_tuple *t, int type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _LIBNETFILTER_CONNTRACK_H_ */

Deleted: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c
===================================================================
--- trunk/libnetfilter_conntrack/src/conntrack/build.c	2007-06-25 14:55:18 UTC (rev 6889)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c	2007-07-28 12:31:57 UTC (rev 6963)
@@ -1,289 +0,0 @@
-/*
- * (C) 2006 by Pablo Neira Ayuso <pablo at netfilter.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#include "internal.h"
-
-void __build_tuple_ip(struct nfnlhdr *req, 
-		      size_t size,
-		      const struct __nfct_tuple *t)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_IP);
-
-	switch(t->l3protonum) {
-	case AF_INET:
-	        nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_SRC, &t->src.v4,
-			       sizeof(u_int32_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_DST, &t->dst.v4,
-			       sizeof(u_int32_t));
-		break;
-	case AF_INET6:
-		nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_SRC, &t->src.v6,
-			       sizeof(struct in6_addr));
-		nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_DST, &t->dst.v6,
-			       sizeof(struct in6_addr));
-		break;
-	default:
-		break;
-	}
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_tuple_proto(struct nfnlhdr *req,
-			 size_t size,
-			 const struct __nfct_tuple *t)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);
-
-	nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
-		       sizeof(u_int8_t));
-
-	switch(t->protonum) {
-	case IPPROTO_UDP:
-	case IPPROTO_TCP:
-	case IPPROTO_SCTP:
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
-			       &t->l4src.tcp.port, sizeof(u_int16_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
-			       &t->l4dst.tcp.port, sizeof(u_int16_t));
-		break;
-	case IPPROTO_ICMP:
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_CODE,
-			       &t->l4dst.icmp.code, sizeof(u_int8_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_TYPE,
-			       &t->l4dst.icmp.type, sizeof(u_int8_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_ID,
-			       &t->l4src.icmp.id, sizeof(u_int16_t));
-		break;
-	default:
-		break;
-	}
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_tuple(struct nfnlhdr *req, 
-		   size_t size, 
-		   const struct __nfct_tuple *t, 
-		   const int type)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, type);
-
-	__build_tuple_ip(req, size, t);
-	__build_tuple_proto(req, size, t);
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_protoinfo(struct nfnlhdr *req,
-		       size_t size,
-		       const struct nf_conntrack *ct)
-{
-	struct nfattr *nest, *nest_proto;
-
-	switch(ct->tuple[__DIR_ORIG].protonum) {
-	case IPPROTO_TCP:
-		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
-		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTOINFO_TCP_STATE,
-			       &ct->protoinfo.tcp.state, sizeof(u_int8_t));
-		nfnl_nest_end(&req->nlh, nest_proto);
-		nfnl_nest_end(&req->nlh, nest);
-		break;
-	default:
-		break;
-	}
-}
-
-void __build_protonat(struct nfnlhdr *req,
-		      size_t size,
-		      const struct nf_conntrack *ct,
-		      const struct __nfct_nat *nat)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_PROTO);
-
-	switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
-	case IPPROTO_TCP:
-	case IPPROTO_UDP:
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_PORT_MIN,
-			       &nat->l4min.tcp.port, sizeof(u_int16_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_PORT_MAX,
-			       &nat->l4max.tcp.port, sizeof(u_int16_t));
-		break;
-	}
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_nat(struct nfnlhdr *req,
-		 size_t size,
-		 const struct __nfct_nat *nat)
-{
-	nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
-		       &nat->min_ip, sizeof(u_int32_t));
-}
-
-void __build_snat(struct nfnlhdr *req,
-		  size_t size,
-		  const struct nf_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
-	__build_nat(req, size, &ct->snat);
-	__build_protonat(req, size, ct, &ct->snat);
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_snat_ipv4(struct nfnlhdr *req,
-		       size_t size,
-		       const struct nf_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
-	__build_nat(req, size, &ct->snat);
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_snat_port(struct nfnlhdr *req,
-		       size_t size,
-		       const struct nf_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
-	__build_protonat(req, size, ct, &ct->snat);
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_dnat(struct nfnlhdr *req,
-		  size_t size, 
-		  const struct nf_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
-	__build_nat(req, size, &ct->dnat);
-	__build_protonat(req, size, ct, &ct->dnat);
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_dnat_ipv4(struct nfnlhdr *req,
-		       size_t size, 
-		       const struct nf_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
-	__build_nat(req, size, &ct->dnat);
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_dnat_port(struct nfnlhdr *req,
-		       size_t size, 
-		       const struct nf_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
-        __build_protonat(req, size, ct, &ct->dnat);
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void __build_status(struct nfnlhdr *req,
-		    size_t size,
-		    const struct nf_conntrack *ct)
-{
-	nfnl_addattr32(&req->nlh, size, CTA_STATUS,
-		       htonl(ct->status | IPS_CONFIRMED));
-}
-
-void __build_timeout(struct nfnlhdr *req,
-			size_t size,
-			const struct nf_conntrack *ct)
-{
-	nfnl_addattr32(&req->nlh, size, CTA_TIMEOUT, htonl(ct->timeout));
-}
-
-void __build_mark(struct nfnlhdr *req,
-		  size_t size,
-		  const struct nf_conntrack *ct)
-{
-	nfnl_addattr32(&req->nlh, size, CTA_MARK, htonl(ct->mark));
-}
-
-void __build_id(struct nfnlhdr *req,
-		size_t size,
-		const const struct nf_conntrack *ct)
-{
-	nfnl_addattr32(&req->nlh, size, CTA_ID, htonl(ct->id));
-}
-
-int __build_conntrack(struct nfnl_subsys_handle *ssh,
-		      struct nfnlhdr *req,
-		      size_t size,
-		      u_int16_t type,
-		      u_int16_t flags,
-		      const struct nf_conntrack *ct)
-{
-	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
-
-	if (!test_bit(ATTR_ORIG_L3PROTO, ct->set)) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	memset(req, 0, size);
-
-	nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags);
-
-	__build_tuple(req, size, &ct->tuple[__DIR_ORIG], CTA_TUPLE_ORIG);
-	__build_tuple(req, size, &ct->tuple[__DIR_REPL], CTA_TUPLE_REPLY);
-
-	if (test_bit(ATTR_STATUS, ct->set))
-		__build_status(req, size, ct);
-	else {
-		/* build IPS_CONFIRMED if we're creating a new conntrack */
-		if (type == IPCTNL_MSG_CT_NEW && flags & NLM_F_CREATE)
-			__build_status(req, size, ct);
-	}
-
-	if (test_bit(ATTR_TIMEOUT, ct->set))
-		__build_timeout(req, size, ct);
-
-	if (test_bit(ATTR_MARK, ct->set))
-		__build_mark(req, size, ct);
-
-	if (test_bit(ATTR_TCP_STATE, ct->set))
-		__build_protoinfo(req, size, ct);
-
-	if (test_bit(ATTR_SNAT_IPV4, ct->set) && 
-	    test_bit(ATTR_SNAT_PORT, ct->set))
-		__build_snat(req, size, ct);
-	else if (test_bit(ATTR_SNAT_IPV4, ct->set))
-		__build_snat_ipv4(req, size, ct);
-	else if (test_bit(ATTR_SNAT_PORT, ct->set))
-		__build_snat_port(req, size, ct);
-
-	if (test_bit(ATTR_DNAT_IPV4, ct->set) &&
-	    test_bit(ATTR_DNAT_PORT, ct->set))
-		__build_dnat(req, size, ct);
-	else if (test_bit(ATTR_DNAT_IPV4, ct->set))
-		__build_dnat_ipv4(req, size, ct);
-	else if (test_bit(ATTR_DNAT_PORT, ct->set))
-		__build_dnat_port(req, size, ct);
-
-	return 0;
-}

Copied: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c (from rev 6902, trunk/libnetfilter_conntrack/src/conntrack/build.c)
===================================================================
--- tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c	                        (rev 0)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/build.c	2007-07-28 12:31:57 UTC (rev 6963)
@@ -0,0 +1,282 @@
+/*
+ * (C) 2006-2007 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+void __build_tuple_ip(struct nfnlhdr *req, 
+		      size_t size,
+		      const struct __nfct_tuple *t)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_IP);
+
+	switch(t->l3protonum) {
+	case AF_INET:
+	        nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_SRC, &t->src.v4,
+			       sizeof(u_int32_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_DST, &t->dst.v4,
+			       sizeof(u_int32_t));
+		break;
+	case AF_INET6:
+		nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_SRC, &t->src.v6,
+			       sizeof(struct in6_addr));
+		nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_DST, &t->dst.v6,
+			       sizeof(struct in6_addr));
+		break;
+	default:
+		break;
+	}
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_tuple_proto(struct nfnlhdr *req,
+			 size_t size,
+			 const struct __nfct_tuple *t)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);
+
+	nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
+		       sizeof(u_int8_t));
+
+	switch(t->protonum) {
+	case IPPROTO_UDP:
+	case IPPROTO_TCP:
+	case IPPROTO_SCTP:
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
+			       &t->l4src.tcp.port, sizeof(u_int16_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
+			       &t->l4dst.tcp.port, sizeof(u_int16_t));
+		break;
+	case IPPROTO_ICMP:
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_CODE,
+			       &t->l4dst.icmp.code, sizeof(u_int8_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_TYPE,
+			       &t->l4dst.icmp.type, sizeof(u_int8_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_ID,
+			       &t->l4src.icmp.id, sizeof(u_int16_t));
+		break;
+	default:
+		break;
+	}
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_tuple(struct nfnlhdr *req, 
+		   size_t size, 
+		   const struct __nfct_tuple *t, 
+		   const int type)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, type);
+
+	__build_tuple_ip(req, size, t);
+	__build_tuple_proto(req, size, t);
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_protoinfo(struct nfnlhdr *req,
+		       size_t size,
+		       const struct nf_conntrack *ct)
+{
+	struct nfattr *nest, *nest_proto;
+
+	switch(ct->tuple[__DIR_ORIG].protonum) {
+	case IPPROTO_TCP:
+		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
+		nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTOINFO_TCP_STATE,
+			       &ct->protoinfo.tcp.state, sizeof(u_int8_t));
+		nfnl_nest_end(&req->nlh, nest_proto);
+		nfnl_nest_end(&req->nlh, nest);
+		break;
+	default:
+		break;
+	}
+}
+
+void __build_protonat(struct nfnlhdr *req,
+		      size_t size,
+		      const struct nf_conntrack *ct,
+		      const struct __nfct_nat *nat)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_PROTO);
+
+	switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_PORT_MIN,
+			       &nat->l4min.tcp.port, sizeof(u_int16_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_PORT_MAX,
+			       &nat->l4max.tcp.port, sizeof(u_int16_t));
+		break;
+	}
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_nat(struct nfnlhdr *req,
+		 size_t size,
+		 const struct __nfct_nat *nat)
+{
+	nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
+		       &nat->min_ip, sizeof(u_int32_t));
+}
+
+void __build_snat(struct nfnlhdr *req,
+		  size_t size,
+		  const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+	__build_nat(req, size, &ct->snat);
+	__build_protonat(req, size, ct, &ct->snat);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_snat_ipv4(struct nfnlhdr *req,
+		       size_t size,
+		       const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+	__build_nat(req, size, &ct->snat);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_snat_port(struct nfnlhdr *req,
+		       size_t size,
+		       const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+	__build_protonat(req, size, ct, &ct->snat);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_dnat(struct nfnlhdr *req,
+		  size_t size, 
+		  const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
+	__build_nat(req, size, &ct->dnat);
+	__build_protonat(req, size, ct, &ct->dnat);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_dnat_ipv4(struct nfnlhdr *req,
+		       size_t size, 
+		       const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
+	__build_nat(req, size, &ct->dnat);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_dnat_port(struct nfnlhdr *req,
+		       size_t size, 
+		       const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_DST);
+        __build_protonat(req, size, ct, &ct->dnat);
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_status(struct nfnlhdr *req,
+		    size_t size,
+		    const struct nf_conntrack *ct)
+{
+	nfnl_addattr32(&req->nlh, size, CTA_STATUS,
+		       htonl(ct->status | IPS_CONFIRMED));
+}
+
+void __build_timeout(struct nfnlhdr *req,
+			size_t size,
+			const struct nf_conntrack *ct)
+{
+	nfnl_addattr32(&req->nlh, size, CTA_TIMEOUT, htonl(ct->timeout));
+}
+
+void __build_mark(struct nfnlhdr *req,
+		  size_t size,
+		  const struct nf_conntrack *ct)
+{
+	nfnl_addattr32(&req->nlh, size, CTA_MARK, htonl(ct->mark));
+}
+
+int __build_conntrack(struct nfnl_subsys_handle *ssh,
+		      struct nfnlhdr *req,
+		      size_t size,
+		      u_int16_t type,
+		      u_int16_t flags,
+		      const struct nf_conntrack *ct)
+{
+	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
+
+	if (!test_bit(ATTR_ORIG_L3PROTO, ct->set)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	memset(req, 0, size);
+
+	nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags);
+
+	__build_tuple(req, size, &ct->tuple[__DIR_ORIG], CTA_TUPLE_ORIG);
+	__build_tuple(req, size, &ct->tuple[__DIR_REPL], CTA_TUPLE_REPLY);
+
+	if (test_bit(ATTR_STATUS, ct->set))
+		__build_status(req, size, ct);
+	else {
+		/* build IPS_CONFIRMED if we're creating a new conntrack */
+		if (type == IPCTNL_MSG_CT_NEW && flags & NLM_F_CREATE)
+			__build_status(req, size, ct);
+	}
+
+	if (test_bit(ATTR_TIMEOUT, ct->set))
+		__build_timeout(req, size, ct);
+
+	if (test_bit(ATTR_MARK, ct->set))
+		__build_mark(req, size, ct);
+
+	if (test_bit(ATTR_TCP_STATE, ct->set))
+		__build_protoinfo(req, size, ct);
+
+	if (test_bit(ATTR_SNAT_IPV4, ct->set) && 
+	    test_bit(ATTR_SNAT_PORT, ct->set))
+		__build_snat(req, size, ct);
+	else if (test_bit(ATTR_SNAT_IPV4, ct->set))
+		__build_snat_ipv4(req, size, ct);
+	else if (test_bit(ATTR_SNAT_PORT, ct->set))
+		__build_snat_port(req, size, ct);
+
+	if (test_bit(ATTR_DNAT_IPV4, ct->set) &&
+	    test_bit(ATTR_DNAT_PORT, ct->set))
+		__build_dnat(req, size, ct);
+	else if (test_bit(ATTR_DNAT_IPV4, ct->set))
+		__build_dnat_ipv4(req, size, ct);
+	else if (test_bit(ATTR_DNAT_PORT, ct->set))
+		__build_dnat_port(req, size, ct);
+
+	return 0;
+}

Deleted: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c
===================================================================
--- trunk/libnetfilter_conntrack/src/conntrack/compare.c	2007-06-25 14:55:18 UTC (rev 6889)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c	2007-07-28 12:31:57 UTC (rev 6963)
@@ -1,102 +0,0 @@
-/*
- * (C) 2007 by Pablo Neira Ayuso <pablo at netfilter.org>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#include "internal.h"
-
-int __compare(const struct nf_conntrack *ct1,
-	      const struct nf_conntrack *ct2)
-{
-	if (test_bit(ATTR_MARK, ct1->set) && 
-	    test_bit(ATTR_MARK, ct2->set) &&
-	    ct1->mark != ct2->mark)
-	    	return 0;
-
-	if (test_bit(ATTR_TIMEOUT, ct1->set) &&
-	    test_bit(ATTR_TIMEOUT, ct2->set) &&
-	    ct1->timeout != ct2->timeout)
-	    	return 0;
-
-	if (test_bit(ATTR_STATUS, ct1->set) &&
-	    test_bit(ATTR_STATUS, ct2->set) &&
-	    ct1->status == ct2->status)
-	    	return 0;
-
-	if (test_bit(ATTR_TCP_STATE, ct1->set) &&
-	    test_bit(ATTR_TCP_STATE, ct2->set) &&
-	    ct1->protoinfo.tcp.state != ct2->protoinfo.tcp.state)
-	    	return 0;
-
-	if (test_bit(ATTR_ORIG_L3PROTO, ct1->set) &&
-	    test_bit(ATTR_ORIG_L3PROTO, ct2->set) &&
-	    ct1->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC && 
-	    ct2->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC &&
-	    ct1->tuple[__DIR_ORIG].l3protonum !=
-	    ct2->tuple[__DIR_ORIG].l3protonum)
-	    	return 0;
-
-	if (test_bit(ATTR_REPL_L3PROTO, ct1->set) &&
-	    test_bit(ATTR_REPL_L3PROTO, ct2->set) &&
-	    ct1->tuple[__DIR_REPL].l3protonum != AF_UNSPEC && 
-	    ct2->tuple[__DIR_REPL].l3protonum != AF_UNSPEC &&
-	    ct1->tuple[__DIR_REPL].l3protonum !=
-	    ct2->tuple[__DIR_REPL].l3protonum)
-		return 0;
-
-	if (test_bit(ATTR_ORIG_IPV4_SRC, ct1->set) &&
-	    test_bit(ATTR_ORIG_IPV4_SRC, ct2->set) &&
-	    ct1->tuple[__DIR_ORIG].src.v4 !=
-	    ct2->tuple[__DIR_ORIG].src.v4)
-		return 0;
-
-	if (test_bit(ATTR_ORIG_IPV4_DST, ct1->set) &&
-	    test_bit(ATTR_ORIG_IPV4_DST, ct2->set) &&
-	    ct1->tuple[__DIR_ORIG].dst.v4 !=
-	    ct2->tuple[__DIR_ORIG].dst.v4)
-		return 0;
-
-	if (test_bit(ATTR_REPL_IPV4_SRC, ct1->set) &&
-	    test_bit(ATTR_REPL_IPV4_SRC, ct2->set) &&
-	    ct1->tuple[__DIR_REPL].src.v4 !=
-	    ct2->tuple[__DIR_REPL].src.v4)
-		return 0;
-
-	if (test_bit(ATTR_REPL_IPV4_DST, ct1->set) && 
-	    test_bit(ATTR_REPL_IPV4_DST, ct2->set) &&
-	    ct1->tuple[__DIR_REPL].dst.v4 !=
-	    ct2->tuple[__DIR_REPL].dst.v4)
-		return 0;
-
-	if (test_bit(ATTR_ORIG_IPV6_SRC, ct1->set) &&
-	    test_bit(ATTR_ORIG_IPV6_SRC, ct2->set) &&
-	    memcmp(&ct1->tuple[__DIR_ORIG].src.v6,
-	    	   &ct2->tuple[__DIR_ORIG].src.v6,
-		   sizeof(u_int32_t)*4) == 0)
-		return 0;
-
-	if (test_bit(ATTR_ORIG_IPV6_DST, ct1->set) &&
-	    test_bit(ATTR_ORIG_IPV6_DST, ct2->set) &&
-	    memcmp(&ct1->tuple[__DIR_ORIG].dst.v6,
-	    	   &ct2->tuple[__DIR_ORIG].dst.v6,
-		   sizeof(u_int32_t)*4) == 0)
-		return 0;
-
-	if (test_bit(ATTR_REPL_IPV6_SRC, ct1->set) &&
-	    test_bit(ATTR_REPL_IPV6_SRC, ct2->set) &&
-	    memcmp(&ct1->tuple[__DIR_REPL].src.v6,
-	    	   &ct2->tuple[__DIR_REPL].src.v6,
-		   sizeof(u_int32_t)*4) == 0)
-		return 0;
-
-	if (test_bit(ATTR_REPL_IPV6_DST, ct1->set) &&
-	    test_bit(ATTR_REPL_IPV6_DST, ct2->set) &&
-	    memcmp(&ct1->tuple[__DIR_REPL].dst.v6,
-	    	   &ct2->tuple[__DIR_REPL].dst.v6,
-		   sizeof(u_int32_t)*4) == 0)
-		return 0;
-
-	return 1;
-}

Copied: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c (from rev 6911, trunk/libnetfilter_conntrack/src/conntrack/compare.c)
===================================================================
--- tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c	                        (rev 0)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/conntrack/compare.c	2007-07-28 12:31:57 UTC (rev 6963)
@@ -0,0 +1,114 @@
+/*
+ * (C) 2007 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+int __compare(const struct nf_conntrack *ct1,
+	      const struct nf_conntrack *ct2)
+{
+	if (test_bit(ATTR_MARK, ct1->set) && 
+	    test_bit(ATTR_MARK, ct2->set) &&
+	    ct1->mark != ct2->mark)
+	    	return 0;
+
+	if (test_bit(ATTR_TIMEOUT, ct1->set) &&
+	    test_bit(ATTR_TIMEOUT, ct2->set) &&
+	    ct1->timeout != ct2->timeout)
+	    	return 0;
+
+	if (test_bit(ATTR_STATUS, ct1->set) &&
+	    test_bit(ATTR_STATUS, ct2->set) &&
+	    ct1->status == ct2->status)
+	    	return 0;
+
+	if (test_bit(ATTR_TCP_STATE, ct1->set) &&
+	    test_bit(ATTR_TCP_STATE, ct2->set) &&
+	    ct1->protoinfo.tcp.state != ct2->protoinfo.tcp.state)
+	    	return 0;
+
+	if (test_bit(ATTR_ORIG_L3PROTO, ct1->set) &&
+	    test_bit(ATTR_ORIG_L3PROTO, ct2->set) &&
+	    ct1->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC && 
+	    ct2->tuple[__DIR_ORIG].l3protonum != AF_UNSPEC &&
+	    ct1->tuple[__DIR_ORIG].l3protonum !=
+	    ct2->tuple[__DIR_ORIG].l3protonum)
+	    	return 0;
+
+	if (test_bit(ATTR_REPL_L3PROTO, ct1->set) &&
+	    test_bit(ATTR_REPL_L3PROTO, ct2->set) &&
+	    ct1->tuple[__DIR_REPL].l3protonum != AF_UNSPEC && 
+	    ct2->tuple[__DIR_REPL].l3protonum != AF_UNSPEC &&
+	    ct1->tuple[__DIR_REPL].l3protonum !=
+	    ct2->tuple[__DIR_REPL].l3protonum)
+		return 0;
+
+	if (test_bit(ATTR_ORIG_L4PROTO, ct1->set) &&
+	    test_bit(ATTR_ORIG_L4PROTO, ct2->set) &&
+	    ct1->tuple[__DIR_ORIG].protonum !=
+	    ct2->tuple[__DIR_ORIG].protonum)
+		return 0;
+
+	if (test_bit(ATTR_REPL_L4PROTO, ct1->set) &&
+	    test_bit(ATTR_REPL_L4PROTO, ct2->set) &&
+	    ct1->tuple[__DIR_REPL].protonum !=
+	    ct2->tuple[__DIR_REPL].protonum)
+		return 0;
+
+	if (test_bit(ATTR_ORIG_IPV4_SRC, ct1->set) &&
+	    test_bit(ATTR_ORIG_IPV4_SRC, ct2->set) &&
+	    ct1->tuple[__DIR_ORIG].src.v4 !=
+	    ct2->tuple[__DIR_ORIG].src.v4)
+		return 0;
+
+	if (test_bit(ATTR_ORIG_IPV4_DST, ct1->set) &&
+	    test_bit(ATTR_ORIG_IPV4_DST, ct2->set) &&
+	    ct1->tuple[__DIR_ORIG].dst.v4 !=
+	    ct2->tuple[__DIR_ORIG].dst.v4)
+		return 0;
+
+	if (test_bit(ATTR_REPL_IPV4_SRC, ct1->set) &&
+	    test_bit(ATTR_REPL_IPV4_SRC, ct2->set) &&
+	    ct1->tuple[__DIR_REPL].src.v4 !=
+	    ct2->tuple[__DIR_REPL].src.v4)
+		return 0;
+
+	if (test_bit(ATTR_REPL_IPV4_DST, ct1->set) && 
+	    test_bit(ATTR_REPL_IPV4_DST, ct2->set) &&
+	    ct1->tuple[__DIR_REPL].dst.v4 !=
+	    ct2->tuple[__DIR_REPL].dst.v4)
+		return 0;
+
+	if (test_bit(ATTR_ORIG_IPV6_SRC, ct1->set) &&
+	    test_bit(ATTR_ORIG_IPV6_SRC, ct2->set) &&
+	    memcmp(&ct1->tuple[__DIR_ORIG].src.v6,
+	    	   &ct2->tuple[__DIR_ORIG].src.v6,
+		   sizeof(u_int32_t)*4) == 0)
+		return 0;
+
+	if (test_bit(ATTR_ORIG_IPV6_DST, ct1->set) &&
+	    test_bit(ATTR_ORIG_IPV6_DST, ct2->set) &&
+	    memcmp(&ct1->tuple[__DIR_ORIG].dst.v6,
+	    	   &ct2->tuple[__DIR_ORIG].dst.v6,
+		   sizeof(u_int32_t)*4) == 0)
+		return 0;
+
+	if (test_bit(ATTR_REPL_IPV6_SRC, ct1->set) &&
+	    test_bit(ATTR_REPL_IPV6_SRC, ct2->set) &&
+	    memcmp(&ct1->tuple[__DIR_REPL].src.v6,
+	    	   &ct2->tuple[__DIR_REPL].src.v6,
+		   sizeof(u_int32_t)*4) == 0)
+		return 0;
+
+	if (test_bit(ATTR_REPL_IPV6_DST, ct1->set) &&
+	    test_bit(ATTR_REPL_IPV6_DST, ct2->set) &&
+	    memcmp(&ct1->tuple[__DIR_REPL].dst.v6,
+	    	   &ct2->tuple[__DIR_REPL].dst.v6,
+		   sizeof(u_int32_t)*4) == 0)
+		return 0;
+
+	return 1;
+}

Deleted: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c
===================================================================
--- trunk/libnetfilter_conntrack/src/libnetfilter_conntrack.c	2007-06-25 14:55:18 UTC (rev 6889)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c	2007-07-28 12:31:57 UTC (rev 6963)
@@ -1,1307 +0,0 @@
-/*
- * (C) 2005-2006 by Pablo Neira Ayuso <pablo at netfilter.org>
- *                  Harald Welte <laforge 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.
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include "linux_list.h"
-#include <libnfnetlink/libnfnetlink.h>
-#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
-#include <libnetfilter_conntrack/libnetfilter_conntrack_l3extensions.h>
-#include <libnetfilter_conntrack/libnetfilter_conntrack_extensions.h>
-
-#include "internal.h"
-
-#define NFCT_BUFSIZE 4096
-
-static char *lib_dir = LIBNETFILTER_CONNTRACK_DIR;
-static LIST_HEAD(proto_list);
-static LIST_HEAD(l3proto_list);
-static char *proto2str[IPPROTO_MAX] = {
-	[IPPROTO_TCP] = "tcp",
-        [IPPROTO_UDP] = "udp",
-        [IPPROTO_ICMP] = "icmp",
-        [IPPROTO_SCTP] = "sctp"
-};
-static char *l3proto2str[AF_MAX] = {
-	[AF_INET] = "ipv4",
-	[AF_INET6] = "ipv6"
-};
-static struct nfct_proto *findproto(char *name);
-static struct nfct_l3proto *findl3proto(char *name);
-
-/* handler used for nfnl_listen */
-static int callback_handler(struct sockaddr_nl *nladdr,
-			    struct nlmsghdr *n, void *arg)
-{
-	struct nfct_handle *cth = (struct nfct_handle *) arg;
-	int ret;
-
-	if (NFNL_SUBSYS_ID(n->nlmsg_type) != NFNL_SUBSYS_CTNETLINK &&
-	    NFNL_SUBSYS_ID(n->nlmsg_type) != NFNL_SUBSYS_CTNETLINK_EXP) {
-		nfnl_dump_packet(n, n->nlmsg_len, "callback_handler");
-		return 0;
-	}
-
-	if (!cth)
-		return -ENODEV;
-
-	if (!cth->handler)
-		return -ENODEV;
-
-	ret = cth->handler(cth, n, NULL);
-
-	return ret;
-}
-
-struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh,
-				   u_int8_t subsys_id,
-				   unsigned int subscriptions)
-{
-	struct nfct_handle *cth;
-
-	cth = (struct nfct_handle *) malloc(sizeof(struct nfct_handle));
-	if (!cth)
-		return NULL;
-	
-	memset(cth, 0, sizeof(*cth));
-	cth->nfnlh = nfnlh;
-
-	if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK) {
-		cth->nfnlssh_ct = nfnl_subsys_open(cth->nfnlh, 
-						   NFNL_SUBSYS_CTNETLINK, 
-						   IPCTNL_MSG_MAX,
-						   subscriptions);
-		if (!cth->nfnlssh_ct)
-			goto out_free;
-	}
-
-	if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK_EXP) {
-		cth->nfnlssh_exp = nfnl_subsys_open(cth->nfnlh,
-						    NFNL_SUBSYS_CTNETLINK_EXP,
-						    IPCTNL_MSG_EXP_MAX,
-						    subscriptions);
-		if (!cth->nfnlssh_exp)
-			goto out_free;
-	}
-
-	return cth;
-
-out_free:
-	if (cth->nfnlssh_exp) {
-		nfnl_subsys_close(cth->nfnlssh_exp);
-		cth->nfnlssh_exp = NULL;
-	}
-	if (cth->nfnlssh_ct) {
-		nfnl_subsys_close(cth->nfnlssh_ct);
-		cth->nfnlssh_ct = NULL;
-	}
-	free(cth);
-	return NULL;
-}
-
-struct nfct_handle *nfct_open(u_int8_t subsys_id, unsigned subscriptions)
-{
-	struct nfnl_handle *nfnlh = nfnl_open();
-	struct nfct_handle *nfcth;
-
-	if (!nfnlh)
-		return NULL;
-
-	nfcth = nfct_open_nfnl(nfnlh, subsys_id, subscriptions);
-	if (!nfcth)
-		nfnl_close(nfnlh);
-
-	return nfcth;
-}
-
-int nfct_close(struct nfct_handle *cth)
-{
-	int err;
-
-	if (cth->nfnlssh_exp) {
-		nfnl_subsys_close(cth->nfnlssh_exp);
-		cth->nfnlssh_exp = NULL;
-	}
-	if (cth->nfnlssh_ct) {
-		nfnl_subsys_close(cth->nfnlssh_ct);
-		cth->nfnlssh_ct = NULL;
-	}
-
-	/* required by the new API */
-	cth->cb = NULL;
-	free(cth->nfnl_cb.data);
-
-	cth->nfnl_cb.call = NULL; 
-	cth->nfnl_cb.data = NULL;
-	cth->nfnl_cb.attr_count = 0;
-
-	err = nfnl_close(cth->nfnlh);
-	free(cth);
-
-	return err;
-}
-
-int nfct_fd(struct nfct_handle *cth)
-{
-	return nfnl_fd(cth->nfnlh);
-}
-
-void nfct_register_callback(struct nfct_handle *cth, nfct_callback callback,
-			    void *data)
-{
-	cth->callback = callback;
-	cth->callback_data = data;
-}
-
-void nfct_unregister_callback(struct nfct_handle *cth)
-{
-	cth->callback = NULL;
-	cth->callback_data = NULL;
-}
-
-static void nfct_build_tuple_ip(struct nfnlhdr *req, int size, 
-				struct nfct_tuple *t)
-{
-	struct nfattr *nest;
-	struct nfct_l3proto *h;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_IP);
-
-	h = findl3proto(l3proto2str[t->l3protonum]);
-	if (h && h->build_tuple_proto)
-		h->build_tuple_proto(req, size, t);
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-static void nfct_build_tuple_proto(struct nfnlhdr *req, int size,
-				   struct nfct_tuple *t)
-{
-	struct nfct_proto *h;
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);
-
-	nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
-		       sizeof(u_int8_t));
-
-	h = findproto(proto2str[t->protonum]);
-
-	if (h && h->build_tuple_proto)
-		h->build_tuple_proto(req, size, t);
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void nfct_build_tuple(struct nfnlhdr *req, int size, 
-		      struct nfct_tuple *t, int type)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, type);
-
-	nfct_build_tuple_ip(req, size, t);
-	nfct_build_tuple_proto(req, size, t);
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-static void nfct_build_protoinfo(struct nfnlhdr *req, int size,
-				 struct nfct_conntrack *ct)
-{
-	struct nfattr *nest;
-	struct nfct_proto *h;
-
-	h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
-	if (h && h->build_protoinfo) {
-		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
-		h->build_protoinfo(req, size, ct);
-		nfnl_nest_end(&req->nlh, nest);
-	}
-}
-
-static void nfct_build_protonat(struct nfnlhdr *req, int size,
-				struct nfct_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT_PROTO);
-
-	switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
-#if 0
-	case IPPROTO_TCP:
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_TCP_MIN,
-			       &ct->nat.l4min.tcp.port, sizeof(u_int16_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_TCP_MAX,
-			       &ct->nat.l4max.tcp.port, sizeof(u_int16_t));
-		break;
-	case IPPROTO_UDP:
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_UDP_MIN,
-			       &ct->nat.l4min.udp.port, sizeof(u_int16_t));
-		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_UDP_MAX,
-			       &ct->nat.l4max.udp.port, sizeof(u_int16_t));
-		break;
-#endif
-	}
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-static void nfct_build_nat(struct nfnlhdr *req, int size,
-			   struct nfct_conntrack *ct)
-{
-	struct nfattr *nest;
-
-	nest = nfnl_nest(&req->nlh, size, CTA_NAT);
-
-	nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
-		       &ct->nat.min_ip, sizeof(u_int32_t));
-	
-	if (ct->nat.min_ip != ct->nat.max_ip)
-		nfnl_addattr_l(&req->nlh, size, CTA_NAT_MAXIP,
-			       &ct->nat.max_ip, sizeof(u_int32_t));
-
-	if (ct->nat.l4min.all != ct->nat.l4max.all)
-		nfct_build_protonat(req, size, ct);
-
-	nfnl_nest_end(&req->nlh, nest);
-}
-
-void nfct_dump_tuple(struct nfct_tuple *tp)
-{
-	struct in_addr src = { .s_addr = tp->src.v4 };
-	struct in_addr dst = { .s_addr = tp->dst.v4 };
-	
-	fprintf(stdout, "tuple %p: %u %s:%hu -> ", tp, tp->protonum,
-						   inet_ntoa(src),
-						   ntohs(tp->l4src.all));
-
-	fprintf(stdout, "%s:%hu\n", inet_ntoa(dst), ntohs(tp->l4dst.all));
-}
-
-static struct nfct_proto *findproto(char *name)
-{
-	struct list_head *i;
-	struct nfct_proto *cur = NULL, *handler = NULL;
-
-	if (!name) 
-		return handler;
-
-	lib_dir = getenv("LIBNETFILTER_CONNTRACK_DIR");
-	if (!lib_dir)
-		lib_dir = LIBNETFILTER_CONNTRACK_DIR;
-
-	list_for_each(i, &proto_list) {
-		cur = (struct nfct_proto *) i;
-		if (strcmp(cur->name, name) == 0) {
-			handler = cur;
-			break;
-		}
-	}
-
-	if (!handler) {
-		char path[sizeof("nfct_proto_.so") + strlen(VERSION)
-			 + strlen(name) + strlen(lib_dir)];
-                sprintf(path, "%s/nfct_proto_%s-%s.so", lib_dir, name, VERSION);
-		if (dlopen(path, RTLD_NOW))
-			handler = findproto(name);
-		else
-			fprintf(stderr, "%s\n", dlerror());
-	}
-
-	return handler;
-}
-
-static struct nfct_l3proto *findl3proto(char *name)
-{
-	struct list_head *i;
-	struct nfct_l3proto *cur = NULL, *handler = NULL;
-
-	if (!name) 
-		return handler;
-
-	lib_dir = getenv("LIBNETFILTER_CONNTRACK_DIR");
-	if (!lib_dir)
-		lib_dir = LIBNETFILTER_CONNTRACK_DIR;
-
-	list_for_each(i, &l3proto_list) {
-		cur = (struct nfct_l3proto *) i;
-		if (strcmp(cur->name, name) == 0) {
-			handler = cur;
-			break;
-		}
-	}
-
-	if (!handler) {
-		char path[sizeof("nfct_l3proto_.so") + strlen(VERSION)
-			 + strlen(name) + strlen(lib_dir)];
-                sprintf(path, "%s/nfct_l3proto_%s-%s.so",lib_dir,name,VERSION);
-		if (dlopen(path, RTLD_NOW))
-			handler = findl3proto(name);
-		else
-			fprintf(stderr, "%s\n", dlerror());
-	}
-
-	return handler;
-}
-
-int nfct_sprintf_status_assured(char *buf, struct nfct_conntrack *ct)
-{
-	int size = 0;
-	
-	if (ct->status & IPS_ASSURED)
-		size = sprintf(buf, "[ASSURED] ");
-
-	return size;
-}
-
-int nfct_sprintf_status_seen_reply(char *buf, struct nfct_conntrack *ct)
-{
-	int size = 0;
-	
-        if (!(ct->status & IPS_SEEN_REPLY))
-                size = sprintf(buf, "[UNREPLIED] ");
-
-	return size;
-}
-
-static void parse_ip(struct nfattr *attr, struct nfct_tuple *tuple)
-{
-	struct nfattr *tb[CTA_IP_MAX];
-	struct nfct_l3proto *h;
-
-        nfnl_parse_nested(tb, CTA_IP_MAX, attr);
-	h = findl3proto(l3proto2str[tuple->l3protonum]);
-	if (h && h->parse_proto)
-		h->parse_proto(tb, tuple);
-}
-
-static void parse_proto(struct nfattr *attr, struct nfct_tuple *tuple)
-{
-	struct nfattr *tb[CTA_PROTO_MAX];
-	struct nfct_proto *h;
-
-	nfnl_parse_nested(tb, CTA_PROTO_MAX, attr);
-	if (tb[CTA_PROTO_NUM-1])
-		tuple->protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
-	
-	h = findproto(proto2str[tuple->protonum]);
-	if (h && h->parse_proto)
-		h->parse_proto(tb, tuple);
-}
-
-static void parse_tuple(struct nfattr *attr, struct nfct_tuple *tuple)
-{
-	struct nfattr *tb[CTA_TUPLE_MAX];
-
-	nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr);
-
-	if (tb[CTA_TUPLE_IP-1])
-		parse_ip(tb[CTA_TUPLE_IP-1], tuple);
-	if (tb[CTA_TUPLE_PROTO-1])
-		parse_proto(tb[CTA_TUPLE_PROTO-1], tuple);
-}
-
-static void parse_mask(struct nfattr *attr, struct nfct_tuple *tuple,
-		       u_int8_t l3protonum, u_int16_t protonum)
-{
-	struct nfattr *cda[CTA_TUPLE_MAX];
-
-	nfnl_parse_nested(cda, CTA_TUPLE_MAX, attr);
-
-	if (cda[CTA_TUPLE_IP-1]) {
-		struct nfattr *tb[CTA_IP_MAX];
-		struct nfct_l3proto *h;
-
-		nfnl_parse_nested(tb, CTA_IP_MAX, cda[CTA_TUPLE_IP-1]);
-		h = findl3proto(l3proto2str[l3protonum]);
-		if (h && h->parse_proto)
-			h->parse_proto(tb, tuple);
-	}
-	if (cda[CTA_TUPLE_PROTO-1]) {
-		struct nfattr *tb[CTA_PROTO_MAX];
-		struct nfct_proto *h;
-
-		nfnl_parse_nested(tb, CTA_PROTO_MAX, cda[CTA_TUPLE_PROTO-1]);
-		if (tb[CTA_PROTO_NUM-1])
-			tuple->protonum = 
-				*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
-
-		h = findproto(proto2str[protonum]);
-		if (h && h->parse_proto)
-			h->parse_proto(tb, tuple);
-	}
-}
-
-static void parse_protoinfo(struct nfattr *attr, struct nfct_conntrack *ct)
-{
-	struct nfattr *tb[CTA_PROTOINFO_MAX];
-	struct nfct_proto *h;
-
-	nfnl_parse_nested(tb,CTA_PROTOINFO_MAX, attr);
-
-	h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
-        if (h && h->parse_protoinfo)
-		h->parse_protoinfo(tb, ct);
-}
-
-static void nfct_parse_counters(struct nfattr *attr,
-					struct nfct_conntrack *ct,
-					enum ctattr_type parent)
-{
-	struct nfattr *tb[CTA_COUNTERS_MAX];
-	int dir = (parent == CTA_COUNTERS_ORIG ? NFCT_DIR_REPLY 
-					       : NFCT_DIR_ORIGINAL);
-
-	nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr);
-	if (tb[CTA_COUNTERS_PACKETS-1])
-		ct->counters[dir].packets
-			= __be64_to_cpu(*(u_int64_t *)
-					NFA_DATA(tb[CTA_COUNTERS_PACKETS-1]));
-	if (tb[CTA_COUNTERS_BYTES-1])
-		ct->counters[dir].bytes
-			= __be64_to_cpu(*(u_int64_t *)
-					NFA_DATA(tb[CTA_COUNTERS_BYTES-1]));
-	if (tb[CTA_COUNTERS32_PACKETS-1])
-		ct->counters[dir].packets
-			= ntohl(*(u_int32_t *)
-				NFA_DATA(tb[CTA_COUNTERS32_PACKETS-1]));
-	if (tb[CTA_COUNTERS32_BYTES-1])
-		ct->counters[dir].bytes
-			= ntohl(*(u_int32_t *)
-				NFA_DATA(tb[CTA_COUNTERS32_BYTES-1]));
-}
-
-static char *msgtype[] = {"[UNKNOWN]", "[NEW]", "[UPDATE]", "[DESTROY]"};
-
-static int typemsg2enum(u_int16_t type, u_int16_t flags)
-{
-	int ret = NFCT_MSG_UNKNOWN;
-
-	if (type == IPCTNL_MSG_CT_NEW) {
-		if (flags & (NLM_F_CREATE|NLM_F_EXCL))
-			ret = NFCT_MSG_NEW;
-		else
-			ret = NFCT_MSG_UPDATE;
-	} else if (type == IPCTNL_MSG_CT_DELETE)
-		ret = NFCT_MSG_DESTROY;
-
-	return ret;
-}
-
-static int nfct_conntrack_netlink_handler(struct nfct_handle *cth, 
-					  struct nlmsghdr *nlh, void *arg)
-{
-	struct nfct_conntrack ct;
-	unsigned int flags = 0;
-	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
-	int type = NFNL_MSG_TYPE(nlh->nlmsg_type), ret = 0;
-	int len = nlh->nlmsg_len;
-	struct nfattr *cda[CTA_MAX];
-
-	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
-	if (len < 0)
-		return -EINVAL;
-
-	memset(&ct, 0, sizeof(struct nfct_conntrack));
-
-	ct.tuple[NFCT_DIR_ORIGINAL].l3protonum = nfhdr->nfgen_family;
-	ct.tuple[NFCT_DIR_REPLY].l3protonum = nfhdr->nfgen_family;
-
-	nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
-
-	if (cda[CTA_TUPLE_ORIG-1])
-		parse_tuple(cda[CTA_TUPLE_ORIG-1], 
-			    &ct.tuple[NFCT_DIR_ORIGINAL]);
-	
-	if (cda[CTA_TUPLE_REPLY-1])
-		parse_tuple(cda[CTA_TUPLE_REPLY-1], 
-			    &ct.tuple[NFCT_DIR_REPLY]);
-	
-	if (cda[CTA_STATUS-1]) {
-		ct.status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
-		flags |= NFCT_STATUS;
-	}
-
-	if (cda[CTA_PROTOINFO-1]) {
-		parse_protoinfo(cda[CTA_PROTOINFO-1], &ct);
-		flags |= NFCT_PROTOINFO;
-	}
-
-	if (cda[CTA_TIMEOUT-1]) {
-		ct.timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
-		flags |= NFCT_TIMEOUT;
-	}
-	
-	if (cda[CTA_MARK-1]) {
-		ct.mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
-		flags |= NFCT_MARK;
-	}
-	
-	if (cda[CTA_COUNTERS_ORIG-1]) {
-		nfct_parse_counters(cda[CTA_COUNTERS_ORIG-1], &ct, 
-				    NFA_TYPE(cda[CTA_COUNTERS_ORIG-1])-1);
-		flags |= NFCT_COUNTERS_ORIG;
-	}
-
-	if (cda[CTA_COUNTERS_REPLY-1]) {
-		nfct_parse_counters(cda[CTA_COUNTERS_REPLY-1], &ct, 
-				    NFA_TYPE(cda[CTA_COUNTERS_REPLY-1])-1);
-		flags |= NFCT_COUNTERS_RPLY;
-	}
-
-	if (cda[CTA_USE-1]) {
-		ct.use = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_USE-1]));
-		flags |= NFCT_USE;
-	}
-
-	if (cda[CTA_ID-1]) {
-		ct.id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
-		flags |= NFCT_ID;
-	}
-
-	if (cth->callback)
-		ret = cth->callback((void *) &ct, flags,
-				    typemsg2enum(type, nlh->nlmsg_flags),
-				    cth->callback_data);
-
-	return ret;
-}
-
-int nfct_sprintf_protocol(char *buf, struct nfct_conntrack *ct)
-{
-	return (sprintf(buf, "%-8s %u ", 
-		proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum] == NULL ?
-		"unknown" : proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum], 
-		 ct->tuple[NFCT_DIR_ORIGINAL].protonum));
-}
-
-int nfct_sprintf_timeout(char *buf, struct nfct_conntrack *ct)
-{
-	return sprintf(buf, "%u ", ct->timeout);
-}
-
-int nfct_sprintf_protoinfo(char *buf, struct nfct_conntrack *ct)
-{
-	int size = 0;
-	struct nfct_proto *h = NULL;
-	
-	h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
-	if (h && h->print_protoinfo)
-		size += h->print_protoinfo(buf+size, &ct->protoinfo);
-	
-	return size;
-}
-
-int nfct_sprintf_address(char *buf, struct nfct_tuple *t)
-{
-	int size = 0;
-	struct nfct_l3proto *h;
-
-	h = findl3proto(l3proto2str[t->l3protonum]);
-	if (h && h->print_proto)
-		size += h->print_proto(buf, t);
-
-	return size;
-}
-
-int nfct_sprintf_proto(char *buf, struct nfct_tuple *t)
-{
-	int size = 0;
-	struct nfct_proto *h = NULL;
-
-	h = findproto(proto2str[t->protonum]);
-	if (h && h->print_proto)
-		size += h->print_proto(buf, t);
-
-	return size;
-}
-
-int nfct_sprintf_counters(char *buf, struct nfct_conntrack *ct, int dir)
-{
-	return (sprintf(buf, "packets=%llu bytes=%llu ",
-			(unsigned long long) ct->counters[dir].packets,
-			(unsigned long long) ct->counters[dir].bytes));
-}
-
-int nfct_sprintf_mark(char *buf, struct nfct_conntrack *ct)
-{
-	return (sprintf(buf, "mark=%u ", ct->mark));
-}
-
-int nfct_sprintf_use(char *buf, struct nfct_conntrack *ct)
-{
-	return (sprintf(buf, "use=%u ", ct->use));
-}
-
-int nfct_sprintf_id(char *buf, u_int32_t id)
-{
-	return (sprintf(buf, "id=%u ", id));
-}
-
-int nfct_sprintf_conntrack(char *buf, struct nfct_conntrack *ct, 
-			  unsigned int flags)
-{
-	int size = 0;
-
-	size += nfct_sprintf_protocol(buf, ct);
-
-	if (flags & NFCT_TIMEOUT)
-		size += nfct_sprintf_timeout(buf+size, ct);
-
-        if (flags & NFCT_PROTOINFO)
-		size += nfct_sprintf_protoinfo(buf+size, ct);
-
-	size += nfct_sprintf_address(buf+size, &ct->tuple[NFCT_DIR_ORIGINAL]);
-	size += nfct_sprintf_proto(buf+size, &ct->tuple[NFCT_DIR_ORIGINAL]);
-
-	if (flags & NFCT_COUNTERS_ORIG)
-		size += nfct_sprintf_counters(buf+size, ct, NFCT_DIR_ORIGINAL);
-
-	if (flags & NFCT_STATUS)
-		size += nfct_sprintf_status_seen_reply(buf+size, ct);
-
-	size += nfct_sprintf_address(buf+size, &ct->tuple[NFCT_DIR_REPLY]);
-	size += nfct_sprintf_proto(buf+size, &ct->tuple[NFCT_DIR_REPLY]);
-
-	if (flags & NFCT_COUNTERS_RPLY)
-		size += nfct_sprintf_counters(buf+size, ct, NFCT_DIR_REPLY);
-	
-	if (flags & NFCT_STATUS)
-		size += nfct_sprintf_status_assured(buf+size, ct);
-
-	if (flags & NFCT_MARK)
-		size += nfct_sprintf_mark(buf+size, ct);
-
-	if (flags & NFCT_USE)
-		size += nfct_sprintf_use(buf+size, ct);
-
-	/* Delete the last blank space */
-	size--;
-
-	return size;
-}
-
-int nfct_sprintf_conntrack_id(char *buf, struct nfct_conntrack *ct, 
-			     unsigned int flags)
-{
-	int size;
-	
-	/* add a blank space, that's why the add 1 to the size */
-	size = nfct_sprintf_conntrack(buf, ct, flags) + 1;
-	if (flags & NFCT_ID)
-		size += nfct_sprintf_id(buf+size, ct->id);
-
-	/* Delete the last blank space */
-	return --size;
-}
-
-int nfct_default_conntrack_display(void *arg, unsigned int flags, int type,
-				   void *data)
-{
-	char buf[512];
-	int size;
-	struct nfct_conntrack_compare *cmp = data;
-
-	if (cmp && !nfct_conntrack_compare(cmp->ct, arg, cmp))
-		return 0;
-
-	memset(buf, 0, sizeof(buf));
-	size = nfct_sprintf_conntrack(buf, arg, flags);
-	sprintf(buf+size, "\n");
-	fprintf(stdout, buf);
-
-	return 0;
-}
-
-int nfct_default_conntrack_display_id(void *arg, unsigned int flags, int type,
-				      void *data)
-{
-	char buf[512];
-	int size;
-        struct nfct_conntrack_compare *cmp = data;
-
-	if (cmp && !nfct_conntrack_compare(cmp->ct, arg, cmp))
-		return 0;
-
-	memset(buf, 0, sizeof(buf));
-	size = nfct_sprintf_conntrack_id(buf, arg, flags);
-	sprintf(buf+size, "\n");
-	fprintf(stdout, buf);
-
-	return 0;
-}
-
-int nfct_default_conntrack_event_display(void *arg, unsigned int flags, 
-					 int type, void *data)
-{
-	char buf[512];
-	int size;
-	struct nfct_conntrack_compare *cmp = data;
-
-	if (cmp && !nfct_conntrack_compare(cmp->ct, arg, cmp))
-		return 0;
-
-	memset(buf, 0, sizeof(buf));
-	size = sprintf(buf, "%9s ", msgtype[type]);
-	size += nfct_sprintf_conntrack_id(buf + size, arg, flags);
-	sprintf(buf+size, "\n");
-	fprintf(stdout, buf);
-	fflush(stdout);
-
-	return 0;
-}
-
-int nfct_sprintf_expect_proto(char *buf, struct nfct_expect *exp)
-{
-	 return(sprintf(buf, "%u proto=%d ", exp->timeout, 
-					     exp->tuple.protonum));
-}
-
-int nfct_sprintf_expect(char *buf, struct nfct_expect *exp)
-{
-	int size = 0;
-	
-	size = nfct_sprintf_expect_proto(buf, exp);
-	size += nfct_sprintf_address(buf+size, &exp->tuple);
-	size += nfct_sprintf_proto(buf+size, &exp->tuple);
-
-	/* remove last blank space */
-	return --size;
-}
-
-int nfct_sprintf_expect_id(char *buf, struct nfct_expect *exp)
-{
-	int size = 0;
-
-	/* add a blank space, that's why the add 1 to the size */
-	size = nfct_sprintf_expect(buf, exp) + 1;
-	size += nfct_sprintf_id(buf+size, exp->id);
-
-	/* remove last blank space */
-	return --size;
-}
-
-int nfct_default_expect_display(void *arg, unsigned int flags, int type,
-				void *data)
-{
-	char buf[256];
-	int size = 0;
-
-	memset(buf, 0, sizeof(buf));
-	size = nfct_sprintf_expect(buf, arg);
-	sprintf(buf+size, "\n");
-	fprintf(stdout, buf);
-
-	return 0;
-}
-
-int nfct_default_expect_display_id(void *arg, unsigned int flags, int type,
-				   void *data)
-{
-	char buf[256];
-	int size = 0;
-
-	size = nfct_sprintf_expect_id(buf, arg);
-	sprintf(buf+size, "\n");
-	fprintf(stdout, buf);
-
-	return 0;
-}
-
-static int nfct_expect_netlink_handler(struct nfct_handle *cth, 
-				       struct nlmsghdr *nlh, void *arg)
-{
-	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
-	struct nfct_expect exp;
-	int type = NFNL_MSG_TYPE(nlh->nlmsg_type), ret = 0;
-	int len = nlh->nlmsg_len;
-	struct nfattr *cda[CTA_EXPECT_MAX];
-
-	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
-	if (len < 0)
-		return -EINVAL;
-	
-	memset(&exp, 0, sizeof(struct nfct_expect));
-
-	exp.tuple.l3protonum = nfhdr->nfgen_family;
-
-	nfnl_parse_attr(cda, CTA_EXPECT_MAX, NFA_DATA(nfhdr), len);
-
-	if (cda[CTA_EXPECT_TUPLE-1])
-		parse_tuple(cda[CTA_EXPECT_TUPLE-1], &exp.tuple);
-
-	if (cda[CTA_EXPECT_MASK-1])
-		parse_mask(cda[CTA_EXPECT_MASK-1], &exp.mask, 
-			   exp.tuple.l3protonum, exp.tuple.protonum);
-
-	if (cda[CTA_EXPECT_TIMEOUT-1])
-		exp.timeout = ntohl(*(u_int32_t *)
-				NFA_DATA(cda[CTA_EXPECT_TIMEOUT-1]));
-
-	if (cda[CTA_EXPECT_ID-1])
-		exp.id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]));
-
-	if (cth->callback)
-		ret = cth->callback((void *)&exp, 0, 
-				    typemsg2enum(type, nlh->nlmsg_flags),
-				    cth->callback_data);
-
-	return 0;
-}
-
-struct nfct_conntrack *
-nfct_conntrack_alloc(struct nfct_tuple *orig, struct nfct_tuple *reply,
-		     u_int32_t timeout, union nfct_protoinfo *proto,
-		     u_int32_t status, u_int32_t mark, 
-		     u_int32_t id, struct nfct_nat *range)
-{
-	struct nfct_conntrack *ct;
-
-	ct = malloc(sizeof(struct nfct_conntrack));
-	if (!ct)
-		return NULL;
-	memset(ct, 0, sizeof(struct nfct_conntrack));
-
-	ct->tuple[NFCT_DIR_ORIGINAL] = *orig;
-	ct->tuple[NFCT_DIR_REPLY] = *reply;
-	ct->timeout = timeout;
-	ct->status = status;
-	ct->protoinfo = *proto;
-	ct->mark = mark;
-	if (id != NFCT_ANY_ID)
-		ct->id = id;
-	if (range)
-		ct->nat = *range;
-
-	return ct;
-}
-
-void nfct_conntrack_free(struct nfct_conntrack *ct)
-{
-	free(ct);
-}
-
-#define L3PROTONUM(ct) ct->tuple[NFCT_DIR_ORIGINAL].l3protonum
-#define L4PROTONUM(ct) ct->tuple[NFCT_DIR_ORIGINAL].protonum
-
-int nfct_conntrack_compare(struct nfct_conntrack *ct1,
-			   struct nfct_conntrack *ct2,
-			   struct nfct_conntrack_compare *cmp)
-{
-	struct nfct_l3proto *l3proto;
-	struct nfct_proto *proto;
-	unsigned int l3flags = cmp->l3flags;
-	unsigned int l4flags = cmp->l4flags;
-	unsigned int flags = cmp->flags;
-
-	if ((flags & NFCT_MARK) && (ct1->mark != ct2->mark))
-		return 0;
-
-	if (l3flags) {
-		if (ct1->tuple[NFCT_DIR_ORIGINAL].l3protonum != AF_UNSPEC && 
-		    ct2->tuple[NFCT_DIR_ORIGINAL].l3protonum != AF_UNSPEC &&
-		    ct1->tuple[NFCT_DIR_ORIGINAL].l3protonum !=
-		    ct2->tuple[NFCT_DIR_ORIGINAL].l3protonum)
-				return 0;
-		if (ct1->tuple[NFCT_DIR_REPLY].l3protonum != AF_UNSPEC && 
-		    ct2->tuple[NFCT_DIR_REPLY].l3protonum != AF_UNSPEC &&
-		    ct1->tuple[NFCT_DIR_REPLY].l3protonum !=
-		    ct2->tuple[NFCT_DIR_REPLY].l3protonum)
-				return 0;
-		l3proto = findl3proto(l3proto2str[L3PROTONUM(ct1)]);
-		if (l3proto && !l3proto->compare(ct1, ct2, l3flags))
-			return 0;
-	}
-
-	if (l4flags) {
-		if (ct1->tuple[NFCT_DIR_ORIGINAL].protonum != 0 && 
-		    ct2->tuple[NFCT_DIR_ORIGINAL].protonum != 0 &&
-		    ct1->tuple[NFCT_DIR_ORIGINAL].protonum !=
-		    ct2->tuple[NFCT_DIR_ORIGINAL].protonum)
-				return 0;
-		if (ct1->tuple[NFCT_DIR_REPLY].protonum != 0 && 
-		    ct2->tuple[NFCT_DIR_REPLY].protonum != 0 &&
-		    ct1->tuple[NFCT_DIR_REPLY].protonum !=
-		    ct2->tuple[NFCT_DIR_REPLY].protonum)
-				return 0;
-		proto = findproto(proto2str[L4PROTONUM(ct1)]);
-		if (proto && !proto->compare(ct1, ct2, l4flags))
-			return 0;
-	}
-
-	return 1;
-}
-
-int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct)
-{
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	u_int32_t status = htonl(ct->status | IPS_CONFIRMED);
-	u_int32_t timeout = htonl(ct->timeout);
-	u_int32_t mark = htonl(ct->mark);
-	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
-
-	req = (void *) buf;
-
-	memset(buf, 0, sizeof(buf));
-	
-	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, 
-		      IPCTNL_MSG_CT_NEW,
-		      NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL);
-
-	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_ORIGINAL], 
-				 CTA_TUPLE_ORIG);
-	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_REPLY],
-				 CTA_TUPLE_REPLY);
-
-	nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_STATUS, &status, 
-		       sizeof(u_int32_t));
-
-	nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_TIMEOUT, &timeout, 
-		       sizeof(u_int32_t));
-	
-	if (ct->mark != 0)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_MARK, &mark,
-			       sizeof(u_int32_t));
-
-	nfct_build_protoinfo(req, sizeof(buf), ct);
-	if (ct->nat.min_ip != 0)
-		nfct_build_nat(req, sizeof(buf), ct);
-
-	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
-}
-
-int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct)
-{
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	u_int32_t status = htonl(ct->status | IPS_CONFIRMED);
-	u_int32_t timeout = htonl(ct->timeout);
-	u_int32_t id = htonl(ct->id);
-	u_int32_t mark = htonl(ct->mark);
-	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
-
-	req = (void *) &buf;
-	memset(&buf, 0, sizeof(buf));
-
-	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, 
-		      IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK);	
-
-	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_ORIGINAL], 
-				 CTA_TUPLE_ORIG);
-	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_REPLY],
-				 CTA_TUPLE_REPLY);
-
-	if (ct->status != 0)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_STATUS, &status, 
-			       sizeof(u_int32_t));
-
-	if (ct->timeout != 0)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_TIMEOUT, &timeout, 
-			       sizeof(u_int32_t));
-	
-	if (ct->mark != 0)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_MARK, &mark,
-			       sizeof(u_int32_t));
-
-	if (ct->id != NFCT_ANY_ID)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id, 
-			       sizeof(u_int32_t));
-
-	nfct_build_protoinfo(req, sizeof(buf), ct);
-
-	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
-}
-
-int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, 
-			  int dir, u_int32_t id)
-{
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	int type = dir ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG;
-	 u_int8_t l3num = tuple->l3protonum;
-
-	req = (void *) &buf;
-	memset(&buf, 0, sizeof(buf));
-
-	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, 
-		      l3num, 0, IPCTNL_MSG_CT_DELETE, 
-		      NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK);
-
-	nfct_build_tuple(req, sizeof(buf), tuple, type);
-
-	if (id != NFCT_ANY_ID) {
-		id = htonl(id); /* to network byte order */
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id, 
-			       sizeof(u_int32_t));
-	}
-
-	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
-}
-
-int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, 
-		       int dir, u_int32_t id)
-{
-	int err;
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	int type = dir ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG;
-	u_int8_t l3num = tuple->l3protonum;
-
-	cth->handler = nfct_conntrack_netlink_handler;
-	
-	memset(&buf, 0, sizeof(buf));
-	req = (void *) &buf;
-
-	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0,
-		      l3num, 0, IPCTNL_MSG_CT_GET,
-		      NLM_F_REQUEST|NLM_F_ACK);
-	
-	nfct_build_tuple(req, sizeof(buf), tuple, type);
-
-        if (id != NFCT_ANY_ID) {
-		id = htonl(id); /* to network byte order */
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id,
-			       sizeof(u_int32_t));
-	}
-
-	err = nfnl_send(cth->nfnlh, &req->nlh);
-	if (err < 0)
-		return err;
-
-	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
-}
-
-static int __nfct_dump_conntrack_table(struct nfct_handle *cth, int zero, 
-				       int family)
-{
-	int err, msg;
-	struct nfnlhdr req;
-
-	memset(&req, 0, sizeof(req));
-	cth->handler = nfct_conntrack_netlink_handler;
-
-	if (zero)
-		msg = IPCTNL_MSG_CT_GET_CTRZERO;
-	else
-		msg = IPCTNL_MSG_CT_GET;
-
-	nfnl_fill_hdr(cth->nfnlssh_ct, &req.nlh, 0, family, 0,
-		      msg, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_DUMP);
-
-	err = nfnl_send(cth->nfnlh, &req.nlh);
-	if (err < 0)
-		return err;
-
-	return nfnl_listen(cth->nfnlh, &callback_handler, cth); 
-}
-
-int nfct_dump_conntrack_table(struct nfct_handle *cth, int family)
-{
-	return(__nfct_dump_conntrack_table(cth, 0, family));
-}
-
-int nfct_dump_conntrack_table_reset_counters(struct nfct_handle *cth,
-					     int family)
-{
-	return(__nfct_dump_conntrack_table(cth, 1, family));
-}
-
-int nfct_event_conntrack(struct nfct_handle *cth)
-{
-	cth->handler = nfct_conntrack_netlink_handler;
-	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
-}
-
-void nfct_register_proto(struct nfct_proto *h)
-{
-	if (strcmp(h->version, VERSION) != 0) {
-		fprintf(stderr, "plugin `%s': version %s (I'm %s)\n",
-			h->name, h->version, VERSION);
-		exit(1);
-	}
-	list_add(&h->head, &proto_list);
-}
-
-void nfct_register_l3proto(struct nfct_l3proto *h)
-{
-	if (strcmp(h->version, VERSION) != 0) {
-		fprintf(stderr, "plugin `%s': version %s (I'm %s)\n",
-			h->name, h->version, VERSION);
-		exit(1);
-	}
-	list_add(&h->head, &l3proto_list);
-}
-
-int nfct_dump_expect_list(struct nfct_handle *cth, int family)
-{
-	int err;
-	struct nfnlhdr req;
-
-	memset(&req, 0, sizeof(req));
-
-	cth->handler = nfct_expect_netlink_handler;
-	nfnl_fill_hdr(cth->nfnlssh_exp, &req.nlh, 0, family, 0,
-		      IPCTNL_MSG_EXP_GET, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST);
-
-	err = nfnl_send(cth->nfnlh, &req.nlh);
-	if (err < 0)
-		return err;
-
-	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
-}
-
-int nfct_flush_conntrack_table(struct nfct_handle *cth, int family)
-{
-	struct nfnlhdr req;
-
-	memset(&req, 0, sizeof(req));
-
-	nfnl_fill_hdr(cth->nfnlssh_ct, (struct nlmsghdr *) &req,
-			0, family, 0, IPCTNL_MSG_CT_DELETE,
-			NLM_F_REQUEST|NLM_F_ACK);
-
-	return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL);
-}
-
-int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple,
-			 u_int32_t id)
-{
-	int err;
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	u_int8_t l3num = tuple->l3protonum;
-
-	memset(&buf, 0, sizeof(buf));
-	req = (void *) &buf;
-
-	nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0,
-		      IPCTNL_MSG_EXP_GET,
-		      NLM_F_REQUEST|NLM_F_ACK);
-
-	cth->handler = nfct_expect_netlink_handler;
-	nfct_build_tuple(req, sizeof(buf), tuple, CTA_EXPECT_MASTER);
-
-	if (id != NFCT_ANY_ID)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id,
-			       sizeof(u_int32_t));
-
-	err = nfnl_send(cth->nfnlh, &req->nlh);
-	if (err < 0)
-		return err;
-
-	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
-}
-
-struct nfct_expect *
-nfct_expect_alloc(struct nfct_tuple *master, struct nfct_tuple *tuple,
-		  struct nfct_tuple *mask, u_int32_t timeout, 
-		  u_int32_t id)
-{
-	struct nfct_expect *exp;
-
-	exp = malloc(sizeof(struct nfct_expect));
-	if (!exp)
-		return NULL;
-	memset(exp, 0, sizeof(struct nfct_expect));
-
-	exp->master = *master;
-	exp->tuple = *tuple;
-	exp->mask = *mask;
-	exp->timeout = timeout;
-	if (id != NFCT_ANY_ID)
-		exp->id = htonl(id);
-
-	return exp;
-}
-
-void nfct_expect_free(struct nfct_expect *exp)
-{
-	free(exp);
-}
-
-int nfct_create_expectation(struct nfct_handle *cth, struct nfct_expect *exp)
-{
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	req = (void *) &buf;
-	u_int8_t l3num = exp->tuple.l3protonum;
-	u_int32_t timeout;
-	u_int16_t queuenr;
-
-	memset(&buf, 0, sizeof(buf));
-
-	nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0,
-		      IPCTNL_MSG_EXP_NEW,
-		      NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK);
-
-	nfct_build_tuple(req, sizeof(buf), &exp->master, CTA_EXPECT_MASTER);
-	nfct_build_tuple(req, sizeof(buf), &exp->tuple, CTA_EXPECT_TUPLE);
-	nfct_build_tuple(req, sizeof(buf), &exp->mask, CTA_EXPECT_MASK);
-	
-	timeout = htonl(exp->timeout);
-	nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_TIMEOUT, 
-		       &timeout, sizeof(u_int32_t));
-
-	queuenr = htons(exp->expectfn_queue_id);
-	if (queuenr)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_QUEUENR,
-			       &queuenr, sizeof(u_int16_t));
-
-	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
-}
-
-int nfct_delete_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple,
-			    u_int32_t id)
-{
-	struct nfnlhdr *req;
-	char buf[NFCT_BUFSIZE];
-	u_int8_t l3num = tuple->l3protonum;
-
-	memset(&buf, 0, sizeof(buf));
-	req = (void *) &buf;
-	
-	nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 
-		      0, IPCTNL_MSG_EXP_DELETE,
-		      NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK);
-
-	nfct_build_tuple(req, sizeof(buf), tuple, CTA_EXPECT_MASTER);
-
-	if (id != NFCT_ANY_ID)
-		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id,
-			       sizeof(u_int32_t));
-
-	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
-}
-
-int nfct_event_expectation(struct nfct_handle *cth)
-{
-	cth->handler = nfct_expect_netlink_handler;
-	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
-}
-
-int nfct_flush_expectation_table(struct nfct_handle *cth, int family)
-{
-	struct nfnlhdr req;
-
-	memset(&req, 0, sizeof(req));
-	
-	nfnl_fill_hdr(cth->nfnlssh_exp, (struct nlmsghdr *) &req,
-		      0, family, 0, IPCTNL_MSG_EXP_DELETE,
-		      NLM_F_REQUEST|NLM_F_ACK);
-
-	return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL);
-}

Copied: tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c (from rev 6902, trunk/libnetfilter_conntrack/src/libnetfilter_conntrack.c)
===================================================================
--- tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c	                        (rev 0)
+++ tags/libnetfilter_conntrack/libnetfilter_conntrack-0.0.81/src/libnetfilter_conntrack.c	2007-07-28 12:31:57 UTC (rev 6963)
@@ -0,0 +1,1312 @@
+/*
+ * (C) 2005-2006 by Pablo Neira Ayuso <pablo at netfilter.org>
+ *                  Harald Welte <laforge 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.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include "linux_list.h"
+#include <libnfnetlink/libnfnetlink.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack_l3extensions.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack_extensions.h>
+
+#include "internal.h"
+
+#define NFCT_BUFSIZE 4096
+
+static char *lib_dir = LIBNETFILTER_CONNTRACK_DIR;
+static LIST_HEAD(proto_list);
+static LIST_HEAD(l3proto_list);
+static char *proto2str[IPPROTO_MAX] = {
+	[IPPROTO_TCP] = "tcp",
+        [IPPROTO_UDP] = "udp",
+        [IPPROTO_ICMP] = "icmp",
+        [IPPROTO_SCTP] = "sctp"
+};
+static char *l3proto2str[AF_MAX] = {
+	[AF_INET] = "ipv4",
+	[AF_INET6] = "ipv6"
+};
+static struct nfct_proto *findproto(char *name);
+static struct nfct_l3proto *findl3proto(char *name);
+
+/* handler used for nfnl_listen */
+static int callback_handler(struct sockaddr_nl *nladdr,
+			    struct nlmsghdr *n, void *arg)
+{
+	struct nfct_handle *cth = (struct nfct_handle *) arg;
+	int ret;
+
+	if (NFNL_SUBSYS_ID(n->nlmsg_type) != NFNL_SUBSYS_CTNETLINK &&
+	    NFNL_SUBSYS_ID(n->nlmsg_type) != NFNL_SUBSYS_CTNETLINK_EXP) {
+		nfnl_dump_packet(n, n->nlmsg_len, "callback_handler");
+		return 0;
+	}
+
+	if (!cth)
+		return -ENODEV;
+
+	if (!cth->handler)
+		return -ENODEV;
+
+	ret = cth->handler(cth, n, NULL);
+
+	return ret;
+}
+
+struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh,
+				   u_int8_t subsys_id,
+				   unsigned int subscriptions)
+{
+	struct nfct_handle *cth;
+
+	cth = (struct nfct_handle *) malloc(sizeof(struct nfct_handle));
+	if (!cth)
+		return NULL;
+	
+	memset(cth, 0, sizeof(*cth));
+	cth->nfnlh = nfnlh;
+
+	if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK) {
+		cth->nfnlssh_ct = nfnl_subsys_open(cth->nfnlh, 
+						   NFNL_SUBSYS_CTNETLINK, 
+						   IPCTNL_MSG_MAX,
+						   subscriptions);
+		if (!cth->nfnlssh_ct)
+			goto out_free;
+	}
+
+	if (subsys_id == 0 || subsys_id == NFNL_SUBSYS_CTNETLINK_EXP) {
+		cth->nfnlssh_exp = nfnl_subsys_open(cth->nfnlh,
+						    NFNL_SUBSYS_CTNETLINK_EXP,
+						    IPCTNL_MSG_EXP_MAX,
+						    subscriptions);
+		if (!cth->nfnlssh_exp)
+			goto out_free;
+	}
+
+	return cth;
+
+out_free:
+	if (cth->nfnlssh_exp) {
+		nfnl_subsys_close(cth->nfnlssh_exp);
+		cth->nfnlssh_exp = NULL;
+	}
+	if (cth->nfnlssh_ct) {
+		nfnl_subsys_close(cth->nfnlssh_ct);
+		cth->nfnlssh_ct = NULL;
+	}
+	free(cth);
+	return NULL;
+}
+
+struct nfct_handle *nfct_open(u_int8_t subsys_id, unsigned subscriptions)
+{
+	struct nfnl_handle *nfnlh = nfnl_open();
+	struct nfct_handle *nfcth;
+
+	if (!nfnlh)
+		return NULL;
+
+	nfcth = nfct_open_nfnl(nfnlh, subsys_id, subscriptions);
+	if (!nfcth)
+		nfnl_close(nfnlh);
+
+	return nfcth;
+}
+
+int nfct_close(struct nfct_handle *cth)
+{
+	int err;
+
+	if (cth->nfnlssh_exp) {
+		nfnl_subsys_close(cth->nfnlssh_exp);
+		cth->nfnlssh_exp = NULL;
+	}
+	if (cth->nfnlssh_ct) {
+		nfnl_subsys_close(cth->nfnlssh_ct);
+		cth->nfnlssh_ct = NULL;
+	}
+
+	/* required by the new API */
+	cth->cb = NULL;
+	free(cth->nfnl_cb.data);
+
+	cth->nfnl_cb.call = NULL; 
+	cth->nfnl_cb.data = NULL;
+	cth->nfnl_cb.attr_count = 0;
+
+	err = nfnl_close(cth->nfnlh);
+	free(cth);
+
+	return err;
+}
+
+int nfct_fd(struct nfct_handle *cth)
+{
+	return nfnl_fd(cth->nfnlh);
+}
+
+const struct nfnl_handle *nfct_nfnlh(struct nfct_handle *cth)
+{
+	return cth->nfnlh;
+}
+
+void nfct_register_callback(struct nfct_handle *cth, nfct_callback callback,
+			    void *data)
+{
+	cth->callback = callback;
+	cth->callback_data = data;
+}
+
+void nfct_unregister_callback(struct nfct_handle *cth)
+{
+	cth->callback = NULL;
+	cth->callback_data = NULL;
+}
+
+static void nfct_build_tuple_ip(struct nfnlhdr *req, int size, 
+				struct nfct_tuple *t)
+{
+	struct nfattr *nest;
+	struct nfct_l3proto *h;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_IP);
+
+	h = findl3proto(l3proto2str[t->l3protonum]);
+	if (h && h->build_tuple_proto)
+		h->build_tuple_proto(req, size, t);
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+static void nfct_build_tuple_proto(struct nfnlhdr *req, int size,
+				   struct nfct_tuple *t)
+{
+	struct nfct_proto *h;
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);
+
+	nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
+		       sizeof(u_int8_t));
+
+	h = findproto(proto2str[t->protonum]);
+
+	if (h && h->build_tuple_proto)
+		h->build_tuple_proto(req, size, t);
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void nfct_build_tuple(struct nfnlhdr *req, int size, 
+		      struct nfct_tuple *t, int type)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, type);
+
+	nfct_build_tuple_ip(req, size, t);
+	nfct_build_tuple_proto(req, size, t);
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+static void nfct_build_protoinfo(struct nfnlhdr *req, int size,
+				 struct nfct_conntrack *ct)
+{
+	struct nfattr *nest;
+	struct nfct_proto *h;
+
+	h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
+	if (h && h->build_protoinfo) {
+		nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
+		h->build_protoinfo(req, size, ct);
+		nfnl_nest_end(&req->nlh, nest);
+	}
+}
+
+static void nfct_build_protonat(struct nfnlhdr *req, int size,
+				struct nfct_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT_PROTO);
+
+	switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
+#if 0
+	case IPPROTO_TCP:
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_TCP_MIN,
+			       &ct->nat.l4min.tcp.port, sizeof(u_int16_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_TCP_MAX,
+			       &ct->nat.l4max.tcp.port, sizeof(u_int16_t));
+		break;
+	case IPPROTO_UDP:
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_UDP_MIN,
+			       &ct->nat.l4min.udp.port, sizeof(u_int16_t));
+		nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_UDP_MAX,
+			       &ct->nat.l4max.udp.port, sizeof(u_int16_t));
+		break;
+#endif
+	}
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+static void nfct_build_nat(struct nfnlhdr *req, int size,
+			   struct nfct_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_NAT);
+
+	nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
+		       &ct->nat.min_ip, sizeof(u_int32_t));
+	
+	if (ct->nat.min_ip != ct->nat.max_ip)
+		nfnl_addattr_l(&req->nlh, size, CTA_NAT_MAXIP,
+			       &ct->nat.max_ip, sizeof(u_int32_t));
+
+	if (ct->nat.l4min.all != ct->nat.l4max.all)
+		nfct_build_protonat(req, size, ct);
+
+	nfnl_nest_end(&req->nlh, nest);
+}
+
+void nfct_dump_tuple(struct nfct_tuple *tp)
+{
+	struct in_addr src = { .s_addr = tp->src.v4 };
+	struct in_addr dst = { .s_addr = tp->dst.v4 };
+	
+	fprintf(stdout, "tuple %p: %u %s:%hu -> ", tp, tp->protonum,
+						   inet_ntoa(src),
+						   ntohs(tp->l4src.all));
+
+	fprintf(stdout, "%s:%hu\n", inet_ntoa(dst), ntohs(tp->l4dst.all));
+}
+
+static struct nfct_proto *findproto(char *name)
+{
+	struct list_head *i;
+	struct nfct_proto *cur = NULL, *handler = NULL;
+
+	if (!name) 
+		return handler;
+
+	lib_dir = getenv("LIBNETFILTER_CONNTRACK_DIR");
+	if (!lib_dir)
+		lib_dir = LIBNETFILTER_CONNTRACK_DIR;
+
+	list_for_each(i, &proto_list) {
+		cur = (struct nfct_proto *) i;
+		if (strcmp(cur->name, name) == 0) {
+			handler = cur;
+			break;
+		}
+	}
+
+	if (!handler) {
+		char path[sizeof("nfct_proto_.so") + strlen(VERSION)
+			 + strlen(name) + strlen(lib_dir)];
+                sprintf(path, "%s/nfct_proto_%s-%s.so", lib_dir, name, VERSION);
+		if (dlopen(path, RTLD_NOW))
+			handler = findproto(name);
+		else
+			fprintf(stderr, "%s\n", dlerror());
+	}
+
+	return handler;
+}
+
+static struct nfct_l3proto *findl3proto(char *name)
+{
+	struct list_head *i;
+	struct nfct_l3proto *cur = NULL, *handler = NULL;
+
+	if (!name) 
+		return handler;
+
+	lib_dir = getenv("LIBNETFILTER_CONNTRACK_DIR");
+	if (!lib_dir)
+		lib_dir = LIBNETFILTER_CONNTRACK_DIR;
+
+	list_for_each(i, &l3proto_list) {
+		cur = (struct nfct_l3proto *) i;
+		if (strcmp(cur->name, name) == 0) {
+			handler = cur;
+			break;
+		}
+	}
+
+	if (!handler) {
+		char path[sizeof("nfct_l3proto_.so") + strlen(VERSION)
+			 + strlen(name) + strlen(lib_dir)];
+                sprintf(path, "%s/nfct_l3proto_%s-%s.so",lib_dir,name,VERSION);
+		if (dlopen(path, RTLD_NOW))
+			handler = findl3proto(name);
+		else
+			fprintf(stderr, "%s\n", dlerror());
+	}
+
+	return handler;
+}
+
+int nfct_sprintf_status_assured(char *buf, struct nfct_conntrack *ct)
+{
+	int size = 0;
+	
+	if (ct->status & IPS_ASSURED)
+		size = sprintf(buf, "[ASSURED] ");
+
+	return size;
+}
+
+int nfct_sprintf_status_seen_reply(char *buf, struct nfct_conntrack *ct)
+{
+	int size = 0;
+	
+        if (!(ct->status & IPS_SEEN_REPLY))
+                size = sprintf(buf, "[UNREPLIED] ");
+
+	return size;
+}
+
+static void parse_ip(struct nfattr *attr, struct nfct_tuple *tuple)
+{
+	struct nfattr *tb[CTA_IP_MAX];
+	struct nfct_l3proto *h;
+
+        nfnl_parse_nested(tb, CTA_IP_MAX, attr);
+	h = findl3proto(l3proto2str[tuple->l3protonum]);
+	if (h && h->parse_proto)
+		h->parse_proto(tb, tuple);
+}
+
+static void parse_proto(struct nfattr *attr, struct nfct_tuple *tuple)
+{
+	struct nfattr *tb[CTA_PROTO_MAX];
+	struct nfct_proto *h;
+
+	nfnl_parse_nested(tb, CTA_PROTO_MAX, attr);
+	if (tb[CTA_PROTO_NUM-1])
+		tuple->protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
+	
+	h = findproto(proto2str[tuple->protonum]);
+	if (h && h->parse_proto)
+		h->parse_proto(tb, tuple);
+}
+
+static void parse_tuple(struct nfattr *attr, struct nfct_tuple *tuple)
+{
+	struct nfattr *tb[CTA_TUPLE_MAX];
+
+	nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr);
+
+	if (tb[CTA_TUPLE_IP-1])
+		parse_ip(tb[CTA_TUPLE_IP-1], tuple);
+	if (tb[CTA_TUPLE_PROTO-1])
+		parse_proto(tb[CTA_TUPLE_PROTO-1], tuple);
+}
+
+static void parse_mask(struct nfattr *attr, struct nfct_tuple *tuple,
+		       u_int8_t l3protonum, u_int16_t protonum)
+{
+	struct nfattr *cda[CTA_TUPLE_MAX];
+
+	nfnl_parse_nested(cda, CTA_TUPLE_MAX, attr);
+
+	if (cda[CTA_TUPLE_IP-1]) {
+		struct nfattr *tb[CTA_IP_MAX];
+		struct nfct_l3proto *h;
+
+		nfnl_parse_nested(tb, CTA_IP_MAX, cda[CTA_TUPLE_IP-1]);
+		h = findl3proto(l3proto2str[l3protonum]);
+		if (h && h->parse_proto)
+			h->parse_proto(tb, tuple);
+	}
+	if (cda[CTA_TUPLE_PROTO-1]) {
+		struct nfattr *tb[CTA_PROTO_MAX];
+		struct nfct_proto *h;
+
+		nfnl_parse_nested(tb, CTA_PROTO_MAX, cda[CTA_TUPLE_PROTO-1]);
+		if (tb[CTA_PROTO_NUM-1])
+			tuple->protonum = 
+				*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
+
+		h = findproto(proto2str[protonum]);
+		if (h && h->parse_proto)
+			h->parse_proto(tb, tuple);
+	}
+}
+
+static void parse_protoinfo(struct nfattr *attr, struct nfct_conntrack *ct)
+{
+	struct nfattr *tb[CTA_PROTOINFO_MAX];
+	struct nfct_proto *h;
+
+	nfnl_parse_nested(tb,CTA_PROTOINFO_MAX, attr);
+
+	h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
+        if (h && h->parse_protoinfo)
+		h->parse_protoinfo(tb, ct);
+}
+
+static void nfct_parse_counters(struct nfattr *attr,
+					struct nfct_conntrack *ct,
+					enum ctattr_type parent)
+{
+	struct nfattr *tb[CTA_COUNTERS_MAX];
+	int dir = (parent == CTA_COUNTERS_ORIG ? NFCT_DIR_REPLY 
+					       : NFCT_DIR_ORIGINAL);
+
+	nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr);
+	if (tb[CTA_COUNTERS_PACKETS-1])
+		ct->counters[dir].packets
+			= __be64_to_cpu(*(u_int64_t *)
+					NFA_DATA(tb[CTA_COUNTERS_PACKETS-1]));
+	if (tb[CTA_COUNTERS_BYTES-1])
+		ct->counters[dir].bytes
+			= __be64_to_cpu(*(u_int64_t *)
+					NFA_DATA(tb[CTA_COUNTERS_BYTES-1]));
+	if (tb[CTA_COUNTERS32_PACKETS-1])
+		ct->counters[dir].packets
+			= ntohl(*(u_int32_t *)
+				NFA_DATA(tb[CTA_COUNTERS32_PACKETS-1]));
+	if (tb[CTA_COUNTERS32_BYTES-1])
+		ct->counters[dir].bytes
+			= ntohl(*(u_int32_t *)
+				NFA_DATA(tb[CTA_COUNTERS32_BYTES-1]));
+}
+
+static char *msgtype[] = {"[UNKNOWN]", "[NEW]", "[UPDATE]", "[DESTROY]"};
+
+static int typemsg2enum(u_int16_t type, u_int16_t flags)
+{
+	int ret = NFCT_MSG_UNKNOWN;
+
+	if (type == IPCTNL_MSG_CT_NEW) {
+		if (flags & (NLM_F_CREATE|NLM_F_EXCL))
+			ret = NFCT_MSG_NEW;
+		else
+			ret = NFCT_MSG_UPDATE;
+	} else if (type == IPCTNL_MSG_CT_DELETE)
+		ret = NFCT_MSG_DESTROY;
+
+	return ret;
+}
+
+static int nfct_conntrack_netlink_handler(struct nfct_handle *cth, 
+					  struct nlmsghdr *nlh, void *arg)
+{
+	struct nfct_conntrack ct;
+	unsigned int flags = 0;
+	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
+	int type = NFNL_MSG_TYPE(nlh->nlmsg_type), ret = 0;
+	int len = nlh->nlmsg_len;
+	struct nfattr *cda[CTA_MAX];
+
+	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+	if (len < 0)
+		return -EINVAL;
+
+	memset(&ct, 0, sizeof(struct nfct_conntrack));
+
+	ct.tuple[NFCT_DIR_ORIGINAL].l3protonum = nfhdr->nfgen_family;
+	ct.tuple[NFCT_DIR_REPLY].l3protonum = nfhdr->nfgen_family;
+
+	nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
+
+	if (cda[CTA_TUPLE_ORIG-1])
+		parse_tuple(cda[CTA_TUPLE_ORIG-1], 
+			    &ct.tuple[NFCT_DIR_ORIGINAL]);
+	
+	if (cda[CTA_TUPLE_REPLY-1])
+		parse_tuple(cda[CTA_TUPLE_REPLY-1], 
+			    &ct.tuple[NFCT_DIR_REPLY]);
+	
+	if (cda[CTA_STATUS-1]) {
+		ct.status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
+		flags |= NFCT_STATUS;
+	}
+
+	if (cda[CTA_PROTOINFO-1]) {
+		parse_protoinfo(cda[CTA_PROTOINFO-1], &ct);
+		flags |= NFCT_PROTOINFO;
+	}
+
+	if (cda[CTA_TIMEOUT-1]) {
+		ct.timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+		flags |= NFCT_TIMEOUT;
+	}
+	
+	if (cda[CTA_MARK-1]) {
+		ct.mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+		flags |= NFCT_MARK;
+	}
+	
+	if (cda[CTA_COUNTERS_ORIG-1]) {
+		nfct_parse_counters(cda[CTA_COUNTERS_ORIG-1], &ct, 
+				    NFA_TYPE(cda[CTA_COUNTERS_ORIG-1])-1);
+		flags |= NFCT_COUNTERS_ORIG;
+	}
+
+	if (cda[CTA_COUNTERS_REPLY-1]) {
+		nfct_parse_counters(cda[CTA_COUNTERS_REPLY-1], &ct, 
+				    NFA_TYPE(cda[CTA_COUNTERS_REPLY-1])-1);
+		flags |= NFCT_COUNTERS_RPLY;
+	}
+
+	if (cda[CTA_USE-1]) {
+		ct.use = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_USE-1]));
+		flags |= NFCT_USE;
+	}
+
+	if (cda[CTA_ID-1]) {
+		ct.id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+		flags |= NFCT_ID;
+	}
+
+	if (cth->callback)
+		ret = cth->callback((void *) &ct, flags,
+				    typemsg2enum(type, nlh->nlmsg_flags),
+				    cth->callback_data);
+
+	return ret;
+}
+
+int nfct_sprintf_protocol(char *buf, struct nfct_conntrack *ct)
+{
+	return (sprintf(buf, "%-8s %u ", 
+		proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum] == NULL ?
+		"unknown" : proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum], 
+		 ct->tuple[NFCT_DIR_ORIGINAL].protonum));
+}
+
+int nfct_sprintf_timeout(char *buf, struct nfct_conntrack *ct)
+{
+	return sprintf(buf, "%u ", ct->timeout);
+}
+
+int nfct_sprintf_protoinfo(char *buf, struct nfct_conntrack *ct)
+{
+	int size = 0;
+	struct nfct_proto *h = NULL;
+	
+	h = findproto(proto2str[ct->tuple[NFCT_DIR_ORIGINAL].protonum]);
+	if (h && h->print_protoinfo)
+		size += h->print_protoinfo(buf+size, &ct->protoinfo);
+	
+	return size;
+}
+
+int nfct_sprintf_address(char *buf, struct nfct_tuple *t)
+{
+	int size = 0;
+	struct nfct_l3proto *h;
+
+	h = findl3proto(l3proto2str[t->l3protonum]);
+	if (h && h->print_proto)
+		size += h->print_proto(buf, t);
+
+	return size;
+}
+
+int nfct_sprintf_proto(char *buf, struct nfct_tuple *t)
+{
+	int size = 0;
+	struct nfct_proto *h = NULL;
+
+	h = findproto(proto2str[t->protonum]);
+	if (h && h->print_proto)
+		size += h->print_proto(buf, t);
+
+	return size;
+}
+
+int nfct_sprintf_counters(char *buf, struct nfct_conntrack *ct, int dir)
+{
+	return (sprintf(buf, "packets=%llu bytes=%llu ",
+			(unsigned long long) ct->counters[dir].packets,
+			(unsigned long long) ct->counters[dir].bytes));
+}
+
+int nfct_sprintf_mark(char *buf, struct nfct_conntrack *ct)
+{
+	return (sprintf(buf, "mark=%u ", ct->mark));
+}
+
+int nfct_sprintf_use(char *buf, struct nfct_conntrack *ct)
+{
+	return (sprintf(buf, "use=%u ", ct->use));
+}
+
+int nfct_sprintf_id(char *buf, u_int32_t id)
+{
+	return (sprintf(buf, "id=%u ", id));
+}
+
+int nfct_sprintf_conntrack(char *buf, struct nfct_conntrack *ct, 
+			  unsigned int flags)
+{
+	int size = 0;
+
+	size += nfct_sprintf_protocol(buf, ct);
+
+	if (flags & NFCT_TIMEOUT)
+		size += nfct_sprintf_timeout(buf+size, ct);
+
+        if (flags & NFCT_PROTOINFO)
+		size += nfct_sprintf_protoinfo(buf+size, ct);
+
+	size += nfct_sprintf_address(buf+size, &ct->tuple[NFCT_DIR_ORIGINAL]);
+	size += nfct_sprintf_proto(buf+size, &ct->tuple[NFCT_DIR_ORIGINAL]);
+
+	if (flags & NFCT_COUNTERS_ORIG)
+		size += nfct_sprintf_counters(buf+size, ct, NFCT_DIR_ORIGINAL);
+
+	if (flags & NFCT_STATUS)
+		size += nfct_sprintf_status_seen_reply(buf+size, ct);
+
+	size += nfct_sprintf_address(buf+size, &ct->tuple[NFCT_DIR_REPLY]);
+	size += nfct_sprintf_proto(buf+size, &ct->tuple[NFCT_DIR_REPLY]);
+
+	if (flags & NFCT_COUNTERS_RPLY)
+		size += nfct_sprintf_counters(buf+size, ct, NFCT_DIR_REPLY);
+	
+	if (flags & NFCT_STATUS)
+		size += nfct_sprintf_status_assured(buf+size, ct);
+
+	if (flags & NFCT_MARK)
+		size += nfct_sprintf_mark(buf+size, ct);
+
+	if (flags & NFCT_USE)
+		size += nfct_sprintf_use(buf+size, ct);
+
+	/* Delete the last blank space */
+	size--;
+
+	return size;
+}
+
+int nfct_sprintf_conntrack_id(char *buf, struct nfct_conntrack *ct, 
+			     unsigned int flags)
+{
+	int size;
+	
+	/* add a blank space, that's why the add 1 to the size */
+	size = nfct_sprintf_conntrack(buf, ct, flags) + 1;
+	if (flags & NFCT_ID)
+		size += nfct_sprintf_id(buf+size, ct->id);
+
+	/* Delete the last blank space */
+	return --size;
+}
+
+int nfct_default_conntrack_display(void *arg, unsigned int flags, int type,
+				   void *data)
+{
+	char buf[512];
+	int size;
+	struct nfct_conntrack_compare *cmp = data;
+
+	if (cmp && !nfct_conntrack_compare(cmp->ct, arg, cmp))
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	size = nfct_sprintf_conntrack(buf, arg, flags);
+	sprintf(buf+size, "\n");
+	fprintf(stdout, buf);
+
+	return 0;
+}
+
+int nfct_default_conntrack_display_id(void *arg, unsigned int flags, int type,
+				      void *data)
+{
+	char buf[512];
+	int size;
+        struct nfct_conntrack_compare *cmp = data;
+
+	if (cmp && !nfct_conntrack_compare(cmp->ct, arg, cmp))
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	size = nfct_sprintf_conntrack_id(buf, arg, flags);
+	sprintf(buf+size, "\n");
+	fprintf(stdout, buf);
+
+	return 0;
+}
+
+int nfct_default_conntrack_event_display(void *arg, unsigned int flags, 
+					 int type, void *data)
+{
+	char buf[512];
+	int size;
+	struct nfct_conntrack_compare *cmp = data;
+
+	if (cmp && !nfct_conntrack_compare(cmp->ct, arg, cmp))
+		return 0;
+
+	memset(buf, 0, sizeof(buf));
+	size = sprintf(buf, "%9s ", msgtype[type]);
+	size += nfct_sprintf_conntrack_id(buf + size, arg, flags);
+	sprintf(buf+size, "\n");
+	fprintf(stdout, buf);
+	fflush(stdout);
+
+	return 0;
+}
+
+int nfct_sprintf_expect_proto(char *buf, struct nfct_expect *exp)
+{
+	 return(sprintf(buf, "%u proto=%d ", exp->timeout, 
+					     exp->tuple.protonum));
+}
+
+int nfct_sprintf_expect(char *buf, struct nfct_expect *exp)
+{
+	int size = 0;
+	
+	size = nfct_sprintf_expect_proto(buf, exp);
+	size += nfct_sprintf_address(buf+size, &exp->tuple);
+	size += nfct_sprintf_proto(buf+size, &exp->tuple);
+
+	/* remove last blank space */
+	return --size;
+}
+
+int nfct_sprintf_expect_id(char *buf, struct nfct_expect *exp)
+{
+	int size = 0;
+
+	/* add a blank space, that's why the add 1 to the size */
+	size = nfct_sprintf_expect(buf, exp) + 1;
+	size += nfct_sprintf_id(buf+size, exp->id);
+
+	/* remove last blank space */
+	return --size;
+}
+
+int nfct_default_expect_display(void *arg, unsigned int flags, int type,
+				void *data)
+{
+	char buf[256];
+	int size = 0;
+
+	memset(buf, 0, sizeof(buf));
+	size = nfct_sprintf_expect(buf, arg);
+	sprintf(buf+size, "\n");
+	fprintf(stdout, buf);
+
+	return 0;
+}
+
+int nfct_default_expect_display_id(void *arg, unsigned int flags, int type,
+				   void *data)
+{
+	char buf[256];
+	int size = 0;
+
+	size = nfct_sprintf_expect_id(buf, arg);
+	sprintf(buf+size, "\n");
+	fprintf(stdout, buf);
+
+	return 0;
+}
+
+static int nfct_expect_netlink_handler(struct nfct_handle *cth, 
+				       struct nlmsghdr *nlh, void *arg)
+{
+	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
+	struct nfct_expect exp;
+	int type = NFNL_MSG_TYPE(nlh->nlmsg_type), ret = 0;
+	int len = nlh->nlmsg_len;
+	struct nfattr *cda[CTA_EXPECT_MAX];
+
+	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+	if (len < 0)
+		return -EINVAL;
+	
+	memset(&exp, 0, sizeof(struct nfct_expect));
+
+	exp.tuple.l3protonum = nfhdr->nfgen_family;
+
+	nfnl_parse_attr(cda, CTA_EXPECT_MAX, NFA_DATA(nfhdr), len);
+
+	if (cda[CTA_EXPECT_TUPLE-1])
+		parse_tuple(cda[CTA_EXPECT_TUPLE-1], &exp.tuple);
+
+	if (cda[CTA_EXPECT_MASK-1])
+		parse_mask(cda[CTA_EXPECT_MASK-1], &exp.mask, 
+			   exp.tuple.l3protonum, exp.tuple.protonum);
+
+	if (cda[CTA_EXPECT_TIMEOUT-1])
+		exp.timeout = ntohl(*(u_int32_t *)
+				NFA_DATA(cda[CTA_EXPECT_TIMEOUT-1]));
+
+	if (cda[CTA_EXPECT_ID-1])
+		exp.id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]));
+
+	if (cth->callback)
+		ret = cth->callback((void *)&exp, 0, 
+				    typemsg2enum(type, nlh->nlmsg_flags),
+				    cth->callback_data);
+
+	return 0;
+}
+
+struct nfct_conntrack *
+nfct_conntrack_alloc(struct nfct_tuple *orig, struct nfct_tuple *reply,
+		     u_int32_t timeout, union nfct_protoinfo *proto,
+		     u_int32_t status, u_int32_t mark, 
+		     u_int32_t id, struct nfct_nat *range)
+{
+	struct nfct_conntrack *ct;
+
+	ct = malloc(sizeof(struct nfct_conntrack));
+	if (!ct)
+		return NULL;
+	memset(ct, 0, sizeof(struct nfct_conntrack));
+
+	ct->tuple[NFCT_DIR_ORIGINAL] = *orig;
+	ct->tuple[NFCT_DIR_REPLY] = *reply;
+	ct->timeout = timeout;
+	ct->status = status;
+	ct->protoinfo = *proto;
+	ct->mark = mark;
+	if (id != NFCT_ANY_ID)
+		ct->id = id;
+	if (range)
+		ct->nat = *range;
+
+	return ct;
+}
+
+void nfct_conntrack_free(struct nfct_conntrack *ct)
+{
+	free(ct);
+}
+
+#define L3PROTONUM(ct) ct->tuple[NFCT_DIR_ORIGINAL].l3protonum
+#define L4PROTONUM(ct) ct->tuple[NFCT_DIR_ORIGINAL].protonum
+
+int nfct_conntrack_compare(struct nfct_conntrack *ct1,
+			   struct nfct_conntrack *ct2,
+			   struct nfct_conntrack_compare *cmp)
+{
+	struct nfct_l3proto *l3proto;
+	struct nfct_proto *proto;
+	unsigned int l3flags = cmp->l3flags;
+	unsigned int l4flags = cmp->l4flags;
+	unsigned int flags = cmp->flags;
+
+	if ((flags & NFCT_MARK) && (ct1->mark != ct2->mark))
+		return 0;
+
+	if (l3flags) {
+		if (ct1->tuple[NFCT_DIR_ORIGINAL].l3protonum != AF_UNSPEC && 
+		    ct2->tuple[NFCT_DIR_ORIGINAL].l3protonum != AF_UNSPEC &&
+		    ct1->tuple[NFCT_DIR_ORIGINAL].l3protonum !=
+		    ct2->tuple[NFCT_DIR_ORIGINAL].l3protonum)
+				return 0;
+		if (ct1->tuple[NFCT_DIR_REPLY].l3protonum != AF_UNSPEC && 
+		    ct2->tuple[NFCT_DIR_REPLY].l3protonum != AF_UNSPEC &&
+		    ct1->tuple[NFCT_DIR_REPLY].l3protonum !=
+		    ct2->tuple[NFCT_DIR_REPLY].l3protonum)
+				return 0;
+		l3proto = findl3proto(l3proto2str[L3PROTONUM(ct1)]);
+		if (l3proto && !l3proto->compare(ct1, ct2, l3flags))
+			return 0;
+	}
+
+	if (l4flags) {
+		if (ct1->tuple[NFCT_DIR_ORIGINAL].protonum != 0 && 
+		    ct2->tuple[NFCT_DIR_ORIGINAL].protonum != 0 &&
+		    ct1->tuple[NFCT_DIR_ORIGINAL].protonum !=
+		    ct2->tuple[NFCT_DIR_ORIGINAL].protonum)
+				return 0;
+		if (ct1->tuple[NFCT_DIR_REPLY].protonum != 0 && 
+		    ct2->tuple[NFCT_DIR_REPLY].protonum != 0 &&
+		    ct1->tuple[NFCT_DIR_REPLY].protonum !=
+		    ct2->tuple[NFCT_DIR_REPLY].protonum)
+				return 0;
+		proto = findproto(proto2str[L4PROTONUM(ct1)]);
+		if (proto && !proto->compare(ct1, ct2, l4flags))
+			return 0;
+	}
+
+	return 1;
+}
+
+int nfct_create_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct)
+{
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	u_int32_t status = htonl(ct->status | IPS_CONFIRMED);
+	u_int32_t timeout = htonl(ct->timeout);
+	u_int32_t mark = htonl(ct->mark);
+	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
+
+	req = (void *) buf;
+
+	memset(buf, 0, sizeof(buf));
+	
+	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, 
+		      IPCTNL_MSG_CT_NEW,
+		      NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL);
+
+	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_ORIGINAL], 
+				 CTA_TUPLE_ORIG);
+	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_REPLY],
+				 CTA_TUPLE_REPLY);
+
+	nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_STATUS, &status, 
+		       sizeof(u_int32_t));
+
+	nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_TIMEOUT, &timeout, 
+		       sizeof(u_int32_t));
+	
+	if (ct->mark != 0)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_MARK, &mark,
+			       sizeof(u_int32_t));
+
+	nfct_build_protoinfo(req, sizeof(buf), ct);
+	if (ct->nat.min_ip != 0)
+		nfct_build_nat(req, sizeof(buf), ct);
+
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct)
+{
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	u_int32_t status = htonl(ct->status | IPS_CONFIRMED);
+	u_int32_t timeout = htonl(ct->timeout);
+	u_int32_t id = htonl(ct->id);
+	u_int32_t mark = htonl(ct->mark);
+	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
+
+	req = (void *) &buf;
+	memset(&buf, 0, sizeof(buf));
+
+	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, l3num, 0, 
+		      IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK);	
+
+	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_ORIGINAL], 
+				 CTA_TUPLE_ORIG);
+	nfct_build_tuple(req, sizeof(buf), &ct->tuple[NFCT_DIR_REPLY],
+				 CTA_TUPLE_REPLY);
+
+	if (ct->status != 0)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_STATUS, &status, 
+			       sizeof(u_int32_t));
+
+	if (ct->timeout != 0)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_TIMEOUT, &timeout, 
+			       sizeof(u_int32_t));
+	
+	if (ct->mark != 0)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_MARK, &mark,
+			       sizeof(u_int32_t));
+
+	if (ct->id != NFCT_ANY_ID)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id, 
+			       sizeof(u_int32_t));
+
+	nfct_build_protoinfo(req, sizeof(buf), ct);
+
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, 
+			  int dir, u_int32_t id)
+{
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	int type = dir ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG;
+	 u_int8_t l3num = tuple->l3protonum;
+
+	req = (void *) &buf;
+	memset(&buf, 0, sizeof(buf));
+
+	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0, 
+		      l3num, 0, IPCTNL_MSG_CT_DELETE, 
+		      NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK);
+
+	nfct_build_tuple(req, sizeof(buf), tuple, type);
+
+	if (id != NFCT_ANY_ID) {
+		id = htonl(id); /* to network byte order */
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id, 
+			       sizeof(u_int32_t));
+	}
+
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, 
+		       int dir, u_int32_t id)
+{
+	int err;
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	int type = dir ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG;
+	u_int8_t l3num = tuple->l3protonum;
+
+	cth->handler = nfct_conntrack_netlink_handler;
+	
+	memset(&buf, 0, sizeof(buf));
+	req = (void *) &buf;
+
+	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0,
+		      l3num, 0, IPCTNL_MSG_CT_GET,
+		      NLM_F_REQUEST|NLM_F_ACK);
+	
+	nfct_build_tuple(req, sizeof(buf), tuple, type);
+
+        if (id != NFCT_ANY_ID) {
+		id = htonl(id); /* to network byte order */
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_ID, &id,
+			       sizeof(u_int32_t));
+	}
+
+	err = nfnl_send(cth->nfnlh, &req->nlh);
+	if (err < 0)
+		return err;
+
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
+}
+
+static int __nfct_dump_conntrack_table(struct nfct_handle *cth, int zero, 
+				       int family)
+{
+	int err, msg;
+	struct nfnlhdr req;
+
+	memset(&req, 0, sizeof(req));
+	cth->handler = nfct_conntrack_netlink_handler;
+
+	if (zero)
+		msg = IPCTNL_MSG_CT_GET_CTRZERO;
+	else
+		msg = IPCTNL_MSG_CT_GET;
+
+	nfnl_fill_hdr(cth->nfnlssh_ct, &req.nlh, 0, family, 0,
+		      msg, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_DUMP);
+
+	err = nfnl_send(cth->nfnlh, &req.nlh);
+	if (err < 0)
+		return err;
+
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth); 
+}
+
+int nfct_dump_conntrack_table(struct nfct_handle *cth, int family)
+{
+	return(__nfct_dump_conntrack_table(cth, 0, family));
+}
+
+int nfct_dump_conntrack_table_reset_counters(struct nfct_handle *cth,
+					     int family)
+{
+	return(__nfct_dump_conntrack_table(cth, 1, family));
+}
+
+int nfct_event_conntrack(struct nfct_handle *cth)
+{
+	cth->handler = nfct_conntrack_netlink_handler;
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
+}
+
+void nfct_register_proto(struct nfct_proto *h)
+{
+	if (strcmp(h->version, VERSION) != 0) {
+		fprintf(stderr, "plugin `%s': version %s (I'm %s)\n",
+			h->name, h->version, VERSION);
+		exit(1);
+	}
+	list_add(&h->head, &proto_list);
+}
+
+void nfct_register_l3proto(struct nfct_l3proto *h)
+{
+	if (strcmp(h->version, VERSION) != 0) {
+		fprintf(stderr, "plugin `%s': version %s (I'm %s)\n",
+			h->name, h->version, VERSION);
+		exit(1);
+	}
+	list_add(&h->head, &l3proto_list);
+}
+
+int nfct_dump_expect_list(struct nfct_handle *cth, int family)
+{
+	int err;
+	struct nfnlhdr req;
+
+	memset(&req, 0, sizeof(req));
+
+	cth->handler = nfct_expect_netlink_handler;
+	nfnl_fill_hdr(cth->nfnlssh_exp, &req.nlh, 0, family, 0,
+		      IPCTNL_MSG_EXP_GET, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST);
+
+	err = nfnl_send(cth->nfnlh, &req.nlh);
+	if (err < 0)
+		return err;
+
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
+}
+
+int nfct_flush_conntrack_table(struct nfct_handle *cth, int family)
+{
+	struct nfnlhdr req;
+
+	memset(&req, 0, sizeof(req));
+
+	nfnl_fill_hdr(cth->nfnlssh_ct, (struct nlmsghdr *) &req,
+			0, family, 0, IPCTNL_MSG_CT_DELETE,
+			NLM_F_REQUEST|NLM_F_ACK);
+
+	return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple,
+			 u_int32_t id)
+{
+	int err;
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	u_int8_t l3num = tuple->l3protonum;
+
+	memset(&buf, 0, sizeof(buf));
+	req = (void *) &buf;
+
+	nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0,
+		      IPCTNL_MSG_EXP_GET,
+		      NLM_F_REQUEST|NLM_F_ACK);
+
+	cth->handler = nfct_expect_netlink_handler;
+	nfct_build_tuple(req, sizeof(buf), tuple, CTA_EXPECT_MASTER);
+
+	if (id != NFCT_ANY_ID)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id,
+			       sizeof(u_int32_t));
+
+	err = nfnl_send(cth->nfnlh, &req->nlh);
+	if (err < 0)
+		return err;
+
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
+}
+
+struct nfct_expect *
+nfct_expect_alloc(struct nfct_tuple *master, struct nfct_tuple *tuple,
+		  struct nfct_tuple *mask, u_int32_t timeout, 
+		  u_int32_t id)
+{
+	struct nfct_expect *exp;
+
+	exp = malloc(sizeof(struct nfct_expect));
+	if (!exp)
+		return NULL;
+	memset(exp, 0, sizeof(struct nfct_expect));
+
+	exp->master = *master;
+	exp->tuple = *tuple;
+	exp->mask = *mask;
+	exp->timeout = timeout;
+	if (id != NFCT_ANY_ID)
+		exp->id = htonl(id);
+
+	return exp;
+}
+
+void nfct_expect_free(struct nfct_expect *exp)
+{
+	free(exp);
+}
+
+int nfct_create_expectation(struct nfct_handle *cth, struct nfct_expect *exp)
+{
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	req = (void *) &buf;
+	u_int8_t l3num = exp->tuple.l3protonum;
+	u_int32_t timeout;
+	u_int16_t queuenr;
+
+	memset(&buf, 0, sizeof(buf));
+
+	nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 0,
+		      IPCTNL_MSG_EXP_NEW,
+		      NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK);
+
+	nfct_build_tuple(req, sizeof(buf), &exp->master, CTA_EXPECT_MASTER);
+	nfct_build_tuple(req, sizeof(buf), &exp->tuple, CTA_EXPECT_TUPLE);
+	nfct_build_tuple(req, sizeof(buf), &exp->mask, CTA_EXPECT_MASK);
+	
+	timeout = htonl(exp->timeout);
+	nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_TIMEOUT, 
+		       &timeout, sizeof(u_int32_t));
+
+	queuenr = htons(exp->expectfn_queue_id);
+	if (queuenr)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_QUEUENR,
+			       &queuenr, sizeof(u_int16_t));
+
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_delete_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple,
+			    u_int32_t id)
+{
+	struct nfnlhdr *req;
+	char buf[NFCT_BUFSIZE];
+	u_int8_t l3num = tuple->l3protonum;
+
+	memset(&buf, 0, sizeof(buf));
+	req = (void *) &buf;
+	
+	nfnl_fill_hdr(cth->nfnlssh_exp, &req->nlh, 0, l3num, 
+		      0, IPCTNL_MSG_EXP_DELETE,
+		      NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK);
+
+	nfct_build_tuple(req, sizeof(buf), tuple, CTA_EXPECT_MASTER);
+
+	if (id != NFCT_ANY_ID)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id,
+			       sizeof(u_int32_t));
+
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_event_expectation(struct nfct_handle *cth)
+{
+	cth->handler = nfct_expect_netlink_handler;
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
+}
+
+int nfct_flush_expectation_table(struct nfct_handle *cth, int family)
+{
+	struct nfnlhdr req;
+
+	memset(&req, 0, sizeof(req));
+	
+	nfnl_fill_hdr(cth->nfnlssh_exp, (struct nlmsghdr *) &req,
+		      0, family, 0, IPCTNL_MSG_EXP_DELETE,
+		      NLM_F_REQUEST|NLM_F_ACK);
+
+	return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL);
+}




More information about the netfilter-cvslog mailing list