[netfilter-cvslog] r6816 - in trunk/libnetfilter_conntrack: . include include/libnetfilter_conntrack src src/conntrack src/expect utils

pablo at netfilter.org pablo at netfilter.org
Tue May 1 20:30:04 CEST 2007


Author: pablo at netfilter.org
Date: 2007-05-01 20:30:03 +0200 (Tue, 01 May 2007)
New Revision: 6816

Added:
   trunk/libnetfilter_conntrack/src/expect/
   trunk/libnetfilter_conntrack/src/expect/Makefile.am
   trunk/libnetfilter_conntrack/src/expect/api.c
   trunk/libnetfilter_conntrack/src/expect/build.c
   trunk/libnetfilter_conntrack/src/expect/callback.c
   trunk/libnetfilter_conntrack/src/expect/getter.c
   trunk/libnetfilter_conntrack/src/expect/parse.c
   trunk/libnetfilter_conntrack/src/expect/setter.c
   trunk/libnetfilter_conntrack/src/expect/snprintf.c
   trunk/libnetfilter_conntrack/src/expect/snprintf_default.c
   trunk/libnetfilter_conntrack/utils/expect_api_test.c
Modified:
   trunk/libnetfilter_conntrack/configure.in
   trunk/libnetfilter_conntrack/include/internal.h
   trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h
   trunk/libnetfilter_conntrack/src/Makefile.am
   trunk/libnetfilter_conntrack/src/conntrack/parse.c
   trunk/libnetfilter_conntrack/src/conntrack/snprintf_default.c
   trunk/libnetfilter_conntrack/utils/Makefile.am
Log:
introduce the new expectation API



Modified: trunk/libnetfilter_conntrack/configure.in
===================================================================
--- trunk/libnetfilter_conntrack/configure.in	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/configure.in	2007-05-01 18:30:03 UTC (rev 6816)
@@ -70,5 +70,5 @@
 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 libnetfilter_conntrack.pc)
+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)
 

Modified: trunk/libnetfilter_conntrack/include/internal.h
===================================================================
--- trunk/libnetfilter_conntrack/include/internal.h	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/include/internal.h	2007-05-01 18:30:03 UTC (rev 6816)
@@ -50,6 +50,9 @@
 	int(*cb)(enum nf_conntrack_msg_type type, 
 		 struct nf_conntrack *ct,
 		 void *data);
+	int(*expect_cb)(enum nf_conntrack_msg_type type, 
+			struct nf_expect *exp,
+			void *data);
 };
 
 union __nfct_l4 {
@@ -122,6 +125,17 @@
 	u_int32_t set[2];
 };
 
+struct nf_expect {
+	struct nf_conntrack master;
+	struct nf_conntrack expected;
+	struct nf_conntrack mask;
+	u_int32_t timeout;
+	u_int32_t id;
+	u_int16_t expectfn_queue_id;
+
+	u_int32_t set[1];
+};
+
 /* container used to pass data to nfnl callbacks */
 struct __data_container {
 	struct nfct_handle *h;
@@ -145,9 +159,13 @@
 }
 
 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);
+void __build_tuple(struct nfnlhdr *req, size_t size, const struct __nfct_tuple *t, const int type);
 int __parse_message_type(const struct nlmsghdr *nlh);
 void __parse_conntrack(const struct nlmsghdr *nlh, const struct nfattr *cda[], struct nf_conntrack *ct);
+void __parse_tuple(const struct nfattr *attr, struct __nfct_tuple *tuple, int dir, u_int32_t *set);
 int __snprintf_conntrack(char *buf, unsigned int len, const struct nf_conntrack *ct, unsigned int type, unsigned int msg_output, unsigned int flags);
+int __snprintf_address(char *buf, unsigned int len, const struct __nfct_tuple *tuple);
+int __snprintf_protocol(char *buf, unsigned int len, const struct nf_conntrack *ct);
 int __snprintf_conntrack_default(char *buf, unsigned int len, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int flags);
 int __snprintf_conntrack_xml(char *buf, unsigned int len, const struct nf_conntrack *ct, const unsigned int msg_type, const unsigned int flags);
 
@@ -158,4 +176,15 @@
 int __getobjopt(const struct nf_conntrack *ct, unsigned int option);
 int __compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2);
 
+typedef void (*set_exp_attr)(struct nf_expect *exp, const void *value);
+typedef const void *(*get_exp_attr)(const struct nf_expect *exp);
+
+extern set_exp_attr set_exp_attr_array[];
+extern get_exp_attr get_exp_attr_array[];
+
+int __build_expect(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t size, u_int16_t type, u_int16_t flags, const struct nf_expect *exp);
+int __parse_expect_message_type(const struct nlmsghdr *nlh);
+void __parse_expect(const struct nlmsghdr *nlh, const struct nfattr *cda[], struct nf_expect *exp);
+int __expect_callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data);
+
 #endif

Modified: trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h
===================================================================
--- trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2007-05-01 18:30:03 UTC (rev 6816)
@@ -559,6 +559,89 @@
 			    void *req,
 			    unsigned int size);
 
+/* 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);
+
+/* 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);
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/libnetfilter_conntrack/src/Makefile.am
===================================================================
--- trunk/libnetfilter_conntrack/src/Makefile.am	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/src/Makefile.am	2007-05-01 18:30:03 UTC (rev 6816)
@@ -4,14 +4,15 @@
 
 #EXTRA_DIST = $(man_MANS) acinclude.m4
 
-SUBDIRS=conntrack
+SUBDIRS=conntrack expect
 
 AM_CFLAGS = -fPIC -Wall
 LIBS = @LIBNFCONNTRACK_LIBS@
 
 lib_LTLIBRARIES = libnetfilter_conntrack.la 
 
-libnetfilter_conntrack_la_LIBADD = conntrack/libnetfilter_conntrack_new_api.la
+libnetfilter_conntrack_la_LIBADD = conntrack/libnetfilter_conntrack_new_api.la \
+				   expect/libnetfilter_conntrack_expect.la
 libnetfilter_conntrack_la_LDFLAGS = -Wc,-nostartfiles -lnfnetlink -ldl 	\
 				    -version-info $(LIBVERSION)
 libnetfilter_conntrack_la_SOURCES = libnetfilter_conntrack.c 

Modified: trunk/libnetfilter_conntrack/src/conntrack/parse.c
===================================================================
--- trunk/libnetfilter_conntrack/src/conntrack/parse.c	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/src/conntrack/parse.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -133,10 +133,10 @@
 	}
 }
 
-static void __parse_tuple(const struct nfattr *attr,
-			  struct __nfct_tuple *tuple, 
-			  int dir,
-			  u_int32_t *set)
+void __parse_tuple(const struct nfattr *attr,
+		   struct __nfct_tuple *tuple, 
+		   int dir,
+		   u_int32_t *set)
 {
 	struct nfattr *tb[CTA_TUPLE_MAX];
 
@@ -148,15 +148,6 @@
 		__parse_proto(tb[CTA_TUPLE_PROTO-1], tuple, dir, set);
 }
 
-static void __parse_mask(const struct nfattr *attr,
-			 struct __nfct_tuple *tuple,
-			 const u_int8_t l3protonum, 
-			 const u_int16_t protonum,
-			 u_int32_t *set)
-{
-	__parse_tuple(attr, tuple, __DIR_ORIG, set);
-}
-
 static void __parse_protoinfo_tcp(const struct nfattr *attr, 
 				  struct nf_conntrack *ct)
 {

Modified: trunk/libnetfilter_conntrack/src/conntrack/snprintf_default.c
===================================================================
--- trunk/libnetfilter_conntrack/src/conntrack/snprintf_default.c	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/src/conntrack/snprintf_default.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -42,9 +42,9 @@
 		 ct->tuple[__DIR_ORIG].l3protonum));
 }
 
-static int __snprintf_protocol(char *buf,
-			       unsigned int len,
-			       const struct nf_conntrack *ct)
+int __snprintf_protocol(char *buf,
+			unsigned int len,
+			const struct nf_conntrack *ct)
 {
 	return (snprintf(buf, len, "%-8s %u ", 
 		proto2str[ct->tuple[__DIR_ORIG].protonum] == NULL ?

Added: trunk/libnetfilter_conntrack/src/expect/Makefile.am
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/Makefile.am	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/Makefile.am	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,16 @@
+include $(top_srcdir)/Make_global.am
+
+#AUTOMAKE_OPTIONS = no-dependencies foreign
+
+#EXTRA_DIST = $(man_MANS) acinclude.m4
+
+AM_CFLAGS = -fPIC -Wall
+LIBS = @LIBNFCONNTRACK_LIBS@
+
+noinst_LTLIBRARIES = libnetfilter_conntrack_expect.la 
+
+libnetfilter_conntrack_expect_la_SOURCES = api.c callback.c \
+					   getter.c setter.c \
+					   parse.c build.c \
+					   snprintf.c \
+					   snprintf_default.c

Added: trunk/libnetfilter_conntrack/src/expect/api.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/api.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/api.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,545 @@
+/*
+ * (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 <stdlib.h>
+#include <string.h> /* for memset */
+#include <errno.h>
+#include <assert.h>
+
+#include "internal.h"
+
+/**
+ * nfexp_new - allocate a new expectation
+ *
+ * In case of success, this function returns a valid pointer to a memory blob,
+ * otherwise NULL is returned and errno is set appropiately.
+ */
+struct nf_expect *nfexp_new()
+{
+	struct nf_expect *exp;
+
+	exp = malloc(sizeof(struct nf_expect));
+	if (!exp)
+		return NULL;
+
+	memset(exp, 0, sizeof(struct nf_expect));
+
+	return exp;
+}
+
+/**
+ * nfexp_destroy - release an expectation object
+ * @exp: pointer to the expectation object
+ */
+void nfexp_destroy(struct nf_expect *exp)
+{
+	assert(exp != NULL);
+	free(exp);
+	exp = NULL; /* bugtrap */
+}
+
+/**
+ * nfexp_clone - clone a expectation object
+ * @exp: pointer to a valid expectation object
+ *
+ * On error, NULL is returned and errno is appropiately set. Otherwise,
+ * a valid pointer to the clone expect is returned.
+ */
+struct nf_expect *nfexp_clone(const struct nf_expect *exp)
+{
+	struct nf_expect *clone;
+
+	assert(exp != NULL);
+
+	if ((clone = nfexp_new()) == NULL)
+		return NULL;
+	memcpy(clone, exp, sizeof(*exp));
+
+	return clone;
+}
+
+/**
+ * nfexp_callback_register - register a callback
+ * @h: library handler
+ * @cb: callback used to process expect received
+ * @data: data used by the callback, if any.
+ *
+ * This function register a callback to handle the expect received, 
+ * in case of error -1 is returned and errno is set appropiately, otherwise
+ * 0 is returned.
+ *
+ * Note that the data parameter is optional, if you do not want to pass any
+ * data to your callback, then use NULL.
+ */
+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)
+{
+	struct __data_container *container;
+
+	assert(h != NULL);
+
+	container = malloc(sizeof(struct __data_container));
+	if (!container)
+		return -1;
+	memset(container, 0, sizeof(struct __data_container));
+
+	h->expect_cb = cb;
+	container->h = h;
+	container->type = type;
+	container->data = data;
+
+	h->nfnl_cb.call = __expect_callback;
+	h->nfnl_cb.data = container;
+	h->nfnl_cb.attr_count = CTA_EXPECT_MAX;
+
+	nfnl_callback_register(h->nfnlssh_exp, 
+			       IPCTNL_MSG_EXP_NEW,
+			       &h->nfnl_cb);
+
+	nfnl_callback_register(h->nfnlssh_exp,
+			       IPCTNL_MSG_EXP_DELETE,
+			       &h->nfnl_cb);
+
+	return 0;
+}
+
+/**
+ * nfexp_callback_unregister - unregister a callback
+ * @h: library handler
+ */
+void nfexp_callback_unregister(struct nfct_handle *h)
+{
+	assert(h != NULL);
+
+	nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
+	nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
+
+	h->expect_cb = NULL;
+	free(h->nfnl_cb.data);
+
+	h->nfnl_cb.call = NULL;
+	h->nfnl_cb.data = NULL;
+	h->nfnl_cb.attr_count = 0;
+}
+
+/**
+ * nfexp_set_attr - set the value of a certain expect attribute
+ * @exp: pointer to a valid expect 
+ * @type: attribute type
+ * @value: pointer to the attribute value
+ *
+ * Note that certain attributes are unsettable:
+ * 	- ATTR_EXP_USE
+ * 	- ATTR_EXP_ID
+ * 	- ATTR_EXP_*_COUNTER_*
+ * The call of this function for such attributes do nothing.
+ */
+void nfexp_set_attr(struct nf_expect *exp,
+		    const enum nf_expect_attr type, 
+		    const void *value)
+{
+	assert(exp != NULL);
+	assert(value != NULL);
+
+	if (type >= ATTR_EXP_MAX)
+		return;
+
+	if (set_exp_attr_array[type]) {
+		set_exp_attr_array[type](exp, value);
+		set_bit(type, exp->set);
+	}
+}
+
+/**
+ * nfexp_set_attr_u8 - set the value of a certain expect attribute
+ * @exp: pointer to a valid expect 
+ * @type: attribute type
+ * @value: unsigned 8 bits attribute value
+ */
+void nfexp_set_attr_u8(struct nf_expect *exp,
+		       const enum nf_expect_attr type, 
+		       u_int8_t value)
+{
+	nfexp_set_attr(exp, type, &value);
+}
+
+/**
+ * nfexp_set_attr_u16 - set the value of a certain expect attribute
+ * @exp: pointer to a valid expect 
+ * @type: attribute type
+ * @value: unsigned 16 bits attribute value
+ */
+void nfexp_set_attr_u16(struct nf_expect *exp,
+			const enum nf_expect_attr type, 
+			u_int16_t value)
+{
+	nfexp_set_attr(exp, type, &value);
+}
+
+/**
+ * nfexp_set_attr_u32 - set the value of a certain expect attribute
+ * @exp: pointer to a valid expect 
+ * @type: attribute type
+ * @value: unsigned 32 bits attribute value
+ */
+void nfexp_set_attr_u32(struct nf_expect *exp,
+			const enum nf_expect_attr type, 
+			u_int32_t value)
+{
+	nfexp_set_attr(exp, type, &value);
+}
+
+/**
+ * nfexp_get_attr - get an expect attribute
+ * exp: pointer to a valid expect
+ * @type: attribute type
+ *
+ * In case of success a valid pointer to the attribute requested is returned,
+ * on error NULL is returned and errno is set appropiately.
+ */
+const void *nfexp_get_attr(const struct nf_expect *exp,
+			   const enum nf_expect_attr type)
+{
+	assert(exp != NULL);
+
+	if (type >= ATTR_EXP_MAX) {
+		errno = EINVAL;
+		return NULL;
+	}
+
+	if (!test_bit(type, exp->set)) {
+		errno = ENODATA;
+		return NULL;
+	}
+
+	return get_exp_attr_array[type](exp);
+}
+
+/**
+ * nfexp_get_attr_u8 - get attribute of unsigned 8-bits long
+ * @exp: pointer to a valid expectation
+ * @type: attribute type
+ *
+ * Returns the value of the requested attribute, if the attribute is not 
+ * set, 0 is returned. In order to check if the attribute is set or not,
+ * use nfexp_attr_is_set.
+ */
+u_int8_t nfexp_get_attr_u8(const struct nf_expect *exp,
+			   const enum nf_expect_attr type)
+{
+	const int *ret = nfexp_get_attr(exp, type);
+	return ret == NULL ? 0 : *ret;
+}
+
+/**
+ * nfexp_get_attr_u16 - get attribute of unsigned 16-bits long
+ * @exp: pointer to a valid expectation
+ * @type: attribute type
+ *
+ * Returns the value of the requested attribute, if the attribute is not 
+ * set, 0 is returned. In order to check if the attribute is set or not,
+ * use nfexp_attr_is_set.
+ */
+u_int16_t nfexp_get_attr_u16(const struct nf_expect *exp,
+			     const enum nf_expect_attr type)
+{
+	const int *ret = nfexp_get_attr(exp, type);
+	return ret == NULL ? 0 : *ret;
+}
+
+/**
+ * nfexp_get_attr_u32 - get attribute of unsigned 32-bits long
+ * @exp: pointer to a valid expectation
+ * @type: attribute type
+ *
+ * Returns the value of the requested attribute, if the attribute is not 
+ * set, 0 is returned. In order to check if the attribute is set or not,
+ * use nfexp_attr_is_set.
+ */
+u_int32_t nfexp_get_attr_u32(const struct nf_expect *exp,
+			    const enum nf_expect_attr type)
+{
+	const int *ret = nfexp_get_attr(exp, type);
+	return ret == NULL ? 0 : *ret;
+}
+
+/**
+ * nfexp_attr_is_set - check if a certain attribute is set
+ * @exp: pointer to a valid expectation object
+ * @type: attribute type
+ *
+ * On error, -1 is returned and errno is set appropiately, otherwise
+ * the value of the attribute is returned.
+ */
+int nfexp_attr_is_set(const struct nf_expect *exp,
+		      const enum nf_expect_attr type)
+{
+	assert(exp != NULL);
+
+	if (type >= ATTR_EXP_MAX) {
+		errno = EINVAL;
+		return -1;
+	}
+	return test_bit(type, exp->set);
+}
+
+/**
+ * nfexp_attr_unset - unset a certain attribute
+ * @type: attribute type
+ * @exp: pointer to a valid expectation object
+ * 
+ * On error, -1 is returned and errno is set appropiately, otherwise
+ * 0 is returned.
+ */
+int nfexp_attr_unset(struct nf_expect *exp,
+		     const enum nf_expect_attr type)
+{
+	assert(exp != NULL);
+
+	if (type >= ATTR_EXP_MAX) {
+		errno = EINVAL;
+		return -1;
+	}
+	unset_bit(type, exp->set);
+
+	return 0;
+}
+
+/**
+ * nfexp_build_expect - build a netlink message from a conntrack object
+ * @ssh: nfnetlink subsystem handler
+ * @req: buffer used to build the netlink message
+ * @size: size of the buffer passed
+ * @type: netlink message type
+ * @flags: netlink flags
+ * @exp: pointer to a conntrack object
+ *
+ * This is a low level function for those that require to be close to
+ * netlink details via libnfnetlink. If you do want to obviate the netlink
+ * details then we suggest you to use nfexp_query.
+ *
+ * On error, -1 is returned and errno is appropiately set.
+ * On success, 0 is returned.
+ */
+int nfexp_build_expect(struct nfnl_subsys_handle *ssh,
+		       void *req,
+		       size_t size,
+		       u_int16_t type,
+		       u_int16_t flags,
+		       const struct nf_expect *exp)
+{
+	assert(ssh != NULL);
+	assert(req != NULL);
+	assert(exp != NULL);
+
+	return __build_expect(ssh, req, size, type, flags, exp);
+}
+
+/**
+ * nfexp_build_query - build a query in netlink message format for ctnetlink
+ * @ssh: nfnetlink subsystem handler
+ * @qt: query type
+ * @data: data required to build the query
+ * @req: buffer to build the netlink message
+ * @size: size of the buffer passed
+ *
+ * This is a low level function, use it if you want to require to work
+ * with netlink details via libnfnetlink, otherwise we suggest you to
+ * use nfexp_query.
+ *
+ * The pointer to data can be a conntrack object or the protocol family
+ * depending on the request.
+ *
+ * For query types:
+ * 	NFEXP_Q_CREATE
+ * 	NFEXP_Q_DESTROY
+ *
+ * Pass a valid pointer to an expectation object.
+ *
+ * For query types:
+ * 	NFEXP_Q_FLUSH
+ * 	NFEXP_Q_DUMP
+ *
+ * Pass a valid pointer to the protocol family (u_int8_t)
+ *
+ * On success, 0 is returned. On error, -1 is returned and errno is set
+ * appropiately.
+ */
+int nfexp_build_query(struct nfnl_subsys_handle *ssh,
+		      const enum nf_conntrack_query qt,
+		      const void *data,
+		      void *buffer,
+		      unsigned int size)
+{
+	struct nfnlhdr *req = buffer;
+	const u_int8_t *family = data;
+
+	assert(ssh != NULL);
+	assert(data != NULL);
+	assert(req != NULL);
+
+	memset(req, 0, size);
+
+	switch(qt) {
+	case NFCT_Q_CREATE:
+		nfexp_build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
+		break;
+	case NFCT_Q_GET:
+		nfexp_build_expect(ssh, req, size, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK, data);
+		break;
+	case NFCT_Q_DESTROY:
+		nfexp_build_expect(ssh, req, size, IPCTNL_MSG_EXP_DELETE, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK, data);
+		break;
+	case NFCT_Q_FLUSH:
+		nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK);
+		break;
+	case NFCT_Q_DUMP:
+		nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_EXP_GET, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_DUMP);
+		break;
+	default:
+		errno = ENOTSUP;
+		return -1;
+	}
+	return 1;
+}
+
+/**
+ * nfexp_parse_expect - translate a netlink message to a conntrack object
+ * @type: do the translation iif the message type is of a certain type
+ * @nlh: pointer to the netlink message
+ * @exp: pointer to the conntrack object
+ *
+ * This is a low level function, use it in case that you require to work
+ * with netlink details via libnfnetlink. Otherwise, we suggest you to
+ * use the high level API.
+ *
+ * The message types are:
+ *
+ * NFEXP_T_NEW: parse messages with new conntracks
+ * NFEXP_T_UPDATE: parse messages with conntrack updates
+ * NFEXP_T_DESTROY: parse messages with conntrack destroy 
+ * NFEXP_T_ALL: all message types
+ *
+ * The message type is a flag, therefore the can be combined, ie.
+ * NFEXP_T_NEW | NFEXP_T_DESTROY to parse only new and destroy messages
+ *
+ * On error, NFEXP_T_ERROR is returned and errno is set appropiately. If 
+ * the message received is not of the requested type then 0 is returned, 
+ * otherwise this function returns the message type parsed.
+ */
+int nfexp_parse_expect(enum nf_conntrack_msg_type type,
+		       const struct nlmsghdr *nlh,
+		       struct nf_expect *exp)
+{
+	unsigned int flags;
+	int len = nlh->nlmsg_len;
+	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
+	struct nfattr *cda[CTA_EXPECT_MAX];
+
+	assert(nlh != NULL);
+	assert(exp != NULL);
+
+	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+	if (len < 0) {
+		errno = EINVAL;
+		return NFCT_T_ERROR;
+	}
+
+	flags = __parse_expect_message_type(nlh);
+	if (!(flags & type))
+		return 0;
+
+	nfnl_parse_attr(cda, CTA_EXPECT_MAX, NFA_DATA(nfhdr), len);
+
+	__parse_expect(nlh, cda, exp);
+
+	return flags;
+}
+
+/**
+ * nfexp_query - send a query to ctnetlink
+ * @h: library handler
+ * @qt: query type
+ * @data: data required to send the query
+ *
+ * On error, -1 is returned and errno is explicitely set. On success, 0
+ * is returned.
+ */
+int nfexp_query(struct nfct_handle *h,
+	        const enum nf_conntrack_query qt,
+	        const void *data)
+{
+	size_t size = 4096;	/* enough for now */
+	char buffer[4096];
+	struct nfnlhdr *req = (struct nfnlhdr *) buffer;
+
+	assert(h != NULL);
+	assert(data != NULL);
+
+	if (nfexp_build_query(h->nfnlssh_exp, qt, data, req, size) == -1)
+		return -1;
+
+	return nfnl_query(h->nfnlh, &req->nlh);
+}
+
+/**
+ * nfexp_catch - catch events
+ * @h: library handler
+ *
+ * On error, -1 is returned and errno is set appropiately. On success, 
+ * a value greater or equal to 0 is returned indicating the callback
+ * verdiexp: NFEXP_CB_STOP, NFEXP_CB_CONTINUE or NFEXP_CB_STOLEN
+ */
+int nfexp_catch(struct nfct_handle *h)
+{
+	assert(h != NULL);
+
+	return nfnl_catch(h->nfnlh);
+}
+
+/**
+ * nfexp_snprintf - print a conntrack object to a buffer
+ * @buf: buffer used to build the printable conntrack
+ * @size: size of the buffer
+ * @exp: pointer to a valid expectation object
+ * @message_type: print message type (NFEXP_T_UNKNOWN, NFEXP_T_NEW,...)
+ * @output_type: print type (NFEXP_O_DEFAULT, NFEXP_O_XML, ...)
+ * @flags: extra flags for the output type (NFEXP_OF_LAYER3)
+ *
+ * If you are listening to events, probably you want to display the message 
+ * type as well. In that case, set the message type parameter to any of the
+ * known existing types, ie. NFEXP_T_NEW, NFEXP_T_UPDATE, NFEXP_T_DESTROY.
+ * If you pass NFEXP_T_UNKNOWN, the message type will not be output. 
+ *
+ * Currently, the output available are:
+ * 	- NFEXP_O_DEFAULT: default /proc-like output
+ * 	- NFEXP_O_XML: XML output
+ *
+ * The output flags are:
+ * 	- NFEXP_O_LAYER: include layer 3 information in the output, this is
+ * 			*only* required by NFEXP_O_DEFAULT.
+ *
+ * On error, -1 is returned and errno is set appropiately. Otherwise,
+ * 0 is returned.
+ */
+int nfexp_snprintf(char *buf,
+		  unsigned int size,
+		  const struct nf_expect *exp,
+		  unsigned int msg_type,
+		  unsigned int out_type,
+		  unsigned int flags) 
+{
+	assert(buf != NULL);
+	assert(size > 0);
+	assert(exp != NULL);
+
+	return __snprintf_expect(buf, size, exp, msg_type, out_type, flags);
+}

Added: trunk/libnetfilter_conntrack/src/expect/build.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/build.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/build.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,58 @@
+/*
+ * (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"
+
+static void __build_timeout(struct nfnlhdr *req,
+			    size_t size,
+			    const struct nf_expect *exp)
+{
+	nfnl_addattr32(&req->nlh, size, CTA_EXPECT_TIMEOUT,htonl(exp->timeout));
+}
+
+int __build_expect(struct nfnl_subsys_handle *ssh,
+		   struct nfnlhdr *req,
+		   size_t size,
+		   u_int16_t type,
+		   u_int16_t flags,
+		   const struct nf_expect *exp)
+{
+	u_int8_t l3num = exp->master.tuple[NFCT_DIR_ORIGINAL].l3protonum;
+
+	if (!test_bit(ATTR_ORIG_L3PROTO, exp->master.set)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	memset(req, 0, size);
+
+	nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags);
+
+	__build_tuple(req,
+		      size,
+		      &exp->expected.tuple[__DIR_ORIG],
+		      CTA_EXPECT_TUPLE);
+
+	/* get and delete only require the expectation tuple */
+	if (type == IPCTNL_MSG_EXP_GET || type == IPCTNL_MSG_EXP_DELETE)
+		return 0;
+
+	__build_tuple(req,
+		      size,
+		      &exp->master.tuple[__DIR_ORIG],
+		      CTA_EXPECT_MASTER);
+	
+	__build_tuple(req,
+		      size,
+		      &exp->mask.tuple[__DIR_ORIG],
+		      CTA_EXPECT_MASK);
+
+	if (test_bit(ATTR_EXP_TIMEOUT, exp->set))
+		__build_timeout(req, size, exp);
+
+	return 0;
+}

Added: trunk/libnetfilter_conntrack/src/expect/callback.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/callback.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/callback.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,53 @@
+/*
+ * (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"
+
+int __expect_callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data)
+{
+	int ret = NFNL_CB_STOP;
+	unsigned int type;
+	struct nf_expect *exp;
+	int len = nlh->nlmsg_len;
+	struct __data_container *container = data;
+
+	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+	if (len < 0)
+		return NFNL_CB_CONTINUE;
+
+	type = __parse_message_type(nlh);
+	if (!(type & container->type))
+		return NFNL_CB_CONTINUE;
+
+	exp = nfexp_new();
+	if (!exp)
+		return NFNL_CB_CONTINUE;
+
+	__parse_expect(nlh, nfa, exp);
+
+	if (container->h->expect_cb)
+		ret = container->h->expect_cb(type, exp, container->data);
+
+	switch(ret) {
+	case NFCT_CB_FAILURE:
+		free(exp);
+		ret = NFNL_CB_FAILURE;
+		break;
+	case NFCT_CB_STOP:
+		free(exp);
+		ret = NFNL_CB_STOP;
+		break;
+	case NFCT_CB_CONTINUE:
+		free(exp);
+		ret = NFNL_CB_CONTINUE;
+		break;
+	case NFCT_CB_STOLEN:
+		ret = NFNL_CB_CONTINUE;
+		break;
+	}
+	return ret;
+}

Added: trunk/libnetfilter_conntrack/src/expect/getter.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/getter.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/getter.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,35 @@
+/*
+ * (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"
+
+static const void *get_exp_attr_master(const struct nf_expect *exp)
+{
+	return &exp->master;
+}
+
+static const void *get_exp_attr_expected(const struct nf_expect *exp)
+{
+	return &exp->expected;
+}
+
+static const void *get_exp_attr_mask(const struct nf_expect *exp)
+{
+	return &exp->mask;
+}
+
+static const void *get_exp_attr_timeout(const struct nf_expect *exp)
+{
+	return &exp->timeout;
+}
+
+get_exp_attr get_exp_attr_array[] = {
+	[ATTR_EXP_MASTER]		= get_exp_attr_master,
+	[ATTR_EXP_EXPECTED]		= get_exp_attr_expected,
+	[ATTR_EXP_MASK]			= get_exp_attr_mask,
+	[ATTR_EXP_TIMEOUT]		= get_exp_attr_timeout,
+};

Added: trunk/libnetfilter_conntrack/src/expect/parse.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/parse.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/parse.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,57 @@
+/*
+ * (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"
+
+int __parse_expect_message_type(const struct nlmsghdr *nlh)
+{
+	u_int16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
+	u_int16_t flags = nlh->nlmsg_flags;
+	int ret = NFCT_T_UNKNOWN;
+
+	if (type == IPCTNL_MSG_EXP_NEW) {
+		if (flags & (NLM_F_CREATE|NLM_F_EXCL))
+			ret = NFCT_T_NEW;
+		else
+			ret = NFCT_T_UPDATE;
+	} else if (type == IPCTNL_MSG_EXP_DELETE)
+		ret = NFCT_T_DESTROY;
+
+	return ret;
+}
+
+void __parse_expect(const struct nlmsghdr *nlh,
+		    const struct nfattr *cda[],
+		    struct nf_expect *exp)
+{
+	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
+
+	/* XXX: this is ugly, clean it up, please */
+	exp->expected.tuple[__DIR_ORIG].l3protonum = nfhdr->nfgen_family;
+	set_bit(ATTR_ORIG_L3PROTO, exp->expected.set);
+
+	exp->mask.tuple[__DIR_REPL].l3protonum = nfhdr->nfgen_family;
+	set_bit(ATTR_ORIG_L3PROTO, exp->mask.set);
+
+	if (cda[CTA_EXPECT_TUPLE-1])
+		__parse_tuple(cda[CTA_EXPECT_TUPLE-1], 
+			      &exp->expected.tuple[__DIR_ORIG],
+			      __DIR_ORIG,
+			      exp->set);
+
+	if (cda[CTA_EXPECT_MASK-1])
+		__parse_tuple(cda[CTA_EXPECT_MASK-1], 
+			      &exp->mask.tuple[__DIR_ORIG], 
+			      __DIR_ORIG,
+			      exp->set);
+
+	if (cda[CTA_EXPECT_TIMEOUT-1]) {
+		exp->timeout = 
+		      ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_TIMEOUT-1]));
+		set_bit(ATTR_EXP_TIMEOUT, exp->set);
+	}
+}

Added: trunk/libnetfilter_conntrack/src/expect/setter.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/setter.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/setter.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,35 @@
+/*
+ * (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"
+
+static void set_exp_attr_master(struct nf_expect *exp, const void *value)
+{
+	exp->master = *((struct nf_conntrack *) value);
+}
+
+static void set_exp_attr_expected(struct nf_expect *exp, const void *value)
+{
+	exp->expected = *((struct nf_conntrack *) value);
+}
+
+static void set_exp_attr_mask(struct nf_expect *exp, const void *value)
+{
+	exp->mask = *((struct nf_conntrack *) value);
+}
+
+static void set_exp_attr_timeout(struct nf_expect *exp, const void *value)
+{
+	exp->timeout = *((u_int32_t *) value);
+}
+
+set_exp_attr set_exp_attr_array[] = {
+	[ATTR_EXP_MASTER]		= set_exp_attr_master,
+	[ATTR_EXP_EXPECTED]		= set_exp_attr_expected,
+	[ATTR_EXP_MASK]			= set_exp_attr_mask,
+	[ATTR_EXP_TIMEOUT]		= set_exp_attr_timeout,
+};

Added: trunk/libnetfilter_conntrack/src/expect/snprintf.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/snprintf.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/snprintf.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,33 @@
+/*
+ * (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"
+
+int __snprintf_expect(char *buf,
+		      unsigned int len,
+		      const struct nf_expect *exp,
+		      unsigned int type,
+		      unsigned int msg_output,
+		      unsigned int flags)
+{
+	int size;
+
+	switch(msg_output) {
+	case NFCT_O_DEFAULT:
+		size = __snprintf_expect_default(buf, len, exp, type, flags);
+		break;
+	default:
+		errno = ENOENT;
+		return -1;
+	}
+
+	/* NULL terminated string */
+	if (snprintf(buf+size, len-size, "\0") == -1)
+		return -1;
+
+	return size;
+}

Added: trunk/libnetfilter_conntrack/src/expect/snprintf_default.c
===================================================================
--- trunk/libnetfilter_conntrack/src/expect/snprintf_default.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/src/expect/snprintf_default.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,62 @@
+/*
+ * (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"
+
+static int __snprintf_expect_proto(char *buf, 
+				   unsigned int len,
+				   const struct nf_expect *exp)
+{
+	 return(snprintf(buf, len, "%u proto=%d ", 
+	 		 exp->timeout, 
+			 exp->expected.tuple[__DIR_ORIG].protonum));
+}
+
+int __snprintf_expect_default(char *buf, 
+			      unsigned int remain,
+			      const struct nf_expect *exp,
+			      unsigned int msg_type,
+			      unsigned int flags) 
+{
+	int ret = 0, size = 0;
+
+	switch(msg_type) {
+		case NFCT_T_NEW:
+			ret = snprintf(buf, remain, "%9s ", "[NEW]");
+			break;
+		default:
+			break;
+	}
+
+	if (ret == -1)
+		return -1;
+	size += ret;
+	remain -= ret;
+
+	ret = __snprintf_expect_proto(buf+size, remain, exp);
+	if (ret == -1)
+		return -1;
+	size += ret;
+	remain -= ret;
+
+	ret = __snprintf_address(buf+size, remain, &exp->expected.tuple[__DIR_ORIG]);
+	if (ret == -1)
+		return -1;
+	size += ret;
+	remain -= ret;
+
+	ret = __snprintf_proto(buf+size, remain, &exp->expected.tuple[__DIR_ORIG]);
+	if (ret == -1)
+		return -1;
+	size += ret;
+	remain -= ret;
+
+	/* Delete the last blank space */
+	size--;
+
+	return size;
+}

Modified: trunk/libnetfilter_conntrack/utils/Makefile.am
===================================================================
--- trunk/libnetfilter_conntrack/utils/Makefile.am	2007-04-30 00:01:39 UTC (rev 6815)
+++ trunk/libnetfilter_conntrack/utils/Makefile.am	2007-05-01 18:30:03 UTC (rev 6816)
@@ -1,11 +1,15 @@
 include $(top_srcdir)/Make_global.am
 
-bin_PROGRAMS = ctnl_test new_api_test
+bin_PROGRAMS = ctnl_test new_api_test expect_api_test
 
 new_api_test_SOURCES = new_api_test.c
 new_api_test_LDADD = ../src/libnetfilter_conntrack.la
 new_api_test_LDFLAGS = -dynamic -ldl
 
+expect_api_test_SOURCES = expect_api_test.c
+expect_api_test_LDADD = ../src/libnetfilter_conntrack.la
+expect_api_test_LDFLAGS = -dynamic -ldl
+
 ctnl_test_SOURCES = ctnl_test.c
 ctnl_test_LDADD = ../src/libnetfilter_conntrack.la
 ctnl_test_LDFLAGS = -dynamic -ldl

Added: trunk/libnetfilter_conntrack/utils/expect_api_test.c
===================================================================
--- trunk/libnetfilter_conntrack/utils/expect_api_test.c	                        (rev 0)
+++ trunk/libnetfilter_conntrack/utils/expect_api_test.c	2007-05-01 18:30:03 UTC (rev 6816)
@@ -0,0 +1,160 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
+
+static int cb(enum nf_conntrack_msg_type type,
+	      struct nf_expect *exp,
+	      void *data)
+{
+	char buf[1024];
+
+	nfexp_snprintf(buf, 1024, exp, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
+	printf("%s\n", buf);
+
+	return NFCT_CB_CONTINUE;
+}
+
+static int event_cb(enum nf_conntrack_msg_type type,
+		    struct nf_expect *exp,
+		    void *data)
+{
+	static int n = 0;
+	char buf[1024];
+
+	nfexp_snprintf(buf, 1024, exp, type, NFCT_O_DEFAULT, 0);
+	printf("%s\n", buf);
+
+	if (++n == 10)
+		return NFCT_CB_STOP;
+
+	return NFCT_CB_CONTINUE;
+}
+
+int main()
+{
+	int ret;
+	u_int8_t family = AF_INET;
+	struct nfct_handle *h;
+	struct nf_conntrack *master, *expected, *mask;
+	struct nf_expect *exp;
+	char buf[1024];
+
+	printf("Test for NEW expectation libnetfilter_conntrack API\n");
+	printf("===================================================\n");
+
+	master = nfct_new();
+	if (!master) {
+		perror("nfct_new");
+		exit(EXIT_FAILURE);
+	}
+
+	nfct_set_attr_u8(master, ATTR_ORIG_L3PROTO, AF_INET);
+	nfct_set_attr_u32(master, ATTR_ORIG_IPV4_SRC, inet_addr("1.1.1.1"));
+	nfct_set_attr_u32(master, ATTR_ORIG_IPV4_DST, inet_addr("2.2.2.2"));
+
+	nfct_set_attr_u8(master, ATTR_ORIG_L4PROTO, IPPROTO_TCP);
+	nfct_set_attr_u16(master, ATTR_ORIG_PORT_SRC, htons(1025));
+	nfct_set_attr_u16(master, ATTR_ORIG_PORT_DST, htons(21));
+
+	nfct_set_attr_u8(master, ATTR_REPL_L3PROTO, AF_INET);
+	nfct_set_attr_u32(master, ATTR_REPL_IPV4_SRC, inet_addr("2.2.2.2"));
+	nfct_set_attr_u32(master, ATTR_REPL_IPV4_DST, inet_addr("1.1.1.1"));
+
+	nfct_set_attr_u8(master, ATTR_REPL_L4PROTO, IPPROTO_TCP);
+	nfct_set_attr_u16(master, ATTR_REPL_PORT_SRC, htons(21));
+	nfct_set_attr_u16(master, ATTR_REPL_PORT_DST, htons(1025));
+
+	nfct_set_attr_u8(master, ATTR_TCP_STATE, TCP_CONNTRACK_LISTEN);
+	nfct_set_attr_u32(master, ATTR_TIMEOUT, 200);
+
+	h = nfct_open(CONNTRACK, 0);
+	if (!h) {
+		perror("nfct_open");
+		return -1;
+	}
+
+	ret = nfct_query(h, NFCT_Q_CREATE, master);
+
+	printf("TEST 1: create conntrack (%d)(%s)\n", ret, strerror(errno));
+
+	nfct_close(h);
+
+	expected = nfct_new();
+	if (!expected) {
+		perror("nfct_new");
+		exit(EXIT_FAILURE);
+	}
+
+	nfct_set_attr_u8(expected, ATTR_ORIG_L3PROTO, AF_INET);
+	nfct_set_attr_u32(expected, ATTR_ORIG_IPV4_SRC, inet_addr("4.4.4.4"));
+	nfct_set_attr_u32(expected, ATTR_ORIG_IPV4_DST, inet_addr("5.5.5.5"));
+
+	nfct_set_attr_u8(expected, ATTR_ORIG_L4PROTO, IPPROTO_TCP);
+	nfct_set_attr_u16(expected, ATTR_ORIG_PORT_SRC, htons(10240));
+	nfct_set_attr_u16(expected, ATTR_ORIG_PORT_DST, htons(10241));
+
+	mask = nfct_new();
+	if (!mask) {
+		perror("nfct_new");
+		exit(EXIT_FAILURE);
+	}
+
+	nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, AF_INET);
+	nfct_set_attr_u32(mask, ATTR_ORIG_IPV4_SRC, 0xffffffff);
+	nfct_set_attr_u32(mask, ATTR_ORIG_IPV4_DST, 0xffffffff);
+
+	nfct_set_attr_u8(mask, ATTR_ORIG_L4PROTO, IPPROTO_TCP);
+	nfct_set_attr_u16(mask, ATTR_ORIG_PORT_SRC, 0xffff);
+	nfct_set_attr_u16(mask, ATTR_ORIG_PORT_DST, 0xffff);
+	
+	exp = nfexp_new();
+	if (!exp) {
+		perror("nfexp_new");
+		exit(EXIT_FAILURE);
+	}
+
+	nfexp_set_attr(exp, ATTR_EXP_MASTER, master);
+	nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);
+	nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
+	nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, 200);
+
+	h = nfct_open(EXPECT, 0);
+	if (!h) {
+		perror("nfct_open");
+		return -1;
+	}
+
+	ret = nfexp_query(h, NFCT_Q_CREATE, exp);
+
+	printf("TEST 2: create expectation (%d)(%s)\n", ret, strerror(errno));
+
+	nfexp_callback_register(h, NFCT_T_ALL, cb, NULL);
+	ret = nfexp_query(h, NFCT_Q_GET, exp);
+
+	printf("TEST 3: get expectation (%d)(%s)\n", ret, strerror(errno));
+
+	ret = nfexp_query(h, NFCT_Q_DESTROY, exp);
+
+	printf("TEST 4: destroy expectation (%d)(%s)\n", ret, strerror(errno));
+
+	nfct_close(h);
+
+	h = nfct_open(EXPECT, NF_NETLINK_CONNTRACK_EXP_NEW);
+	if (!h) {
+		perror("nfct_open");
+		return -1;
+	}
+
+	nfexp_callback_register(h, NFCT_T_ALL, event_cb, NULL);
+
+	printf("TEST 5: waiting for 10 events...\n");
+
+	ret = nfexp_catch(h);
+
+	printf("TEST 5: OK (%d)(%s)\n", ret, strerror(errno));
+
+	nfct_close(h);
+}




More information about the netfilter-cvslog mailing list