Index: include/cache.h
===================================================================
--- include/cache.h	(revisión: 13)
+++ include/cache.h	(copia de trabajo)
@@ -61,14 +61,14 @@
 	unsigned int flush;
 };
 
-struct nfct_conntrack;
+struct nf_conntrack;
 
-struct cache *cache_create(char *name, unsigned int features);
+struct cache *cache_create(char *name, unsigned int features, u_int8_t proto);
 void cache_destroy(struct cache *e);
 
-int cache_add_entry(struct cache *c, struct nfct_conntrack *ct);
-int cache_update_entry(struct cache *c, struct nfct_conntrack *ct, u_int32_t flags);
-int cache_del_entry(struct cache *c, struct nfct_conntrack *ct);
+int cache_add_entry(struct cache *c, struct nf_conntrack *ct);
+int cache_update_entry(struct cache *c, struct nf_conntrack *ct);
+int cache_del_entry(struct cache *c, struct nf_conntrack *ct);
 
 void cache_dump(struct cache *c, int fd);
 void cache_commit(struct cache *c);
Index: include/conntrackd.h
===================================================================
--- include/conntrackd.h	(revisión: 20)
+++ include/conntrackd.h	(copia de trabajo)
@@ -76,6 +76,7 @@
 	union inet_address *listen_to;
 	unsigned int listen_to_len;
 	unsigned int flags;
+	int family;			/* protocol family */
 };
 
 #define STATE(x) st.x
@@ -139,14 +140,10 @@
 	void (*step)(fd_set *readfds);
 	void (*local)(int fd, int type, void *data);
 	void (*kill)(void);
-	void (*dump)(struct nfct_conntrack *ct, struct nlmsghdr *nlh,
-		     unsigned int flags);
-	void (*event_new)(struct nfct_conntrack *ct, struct nlmsghdr *nlh,
-			  unsigned int flags);
-	void (*event_upd)(struct nfct_conntrack *ct, struct nlmsghdr *nlh,
-			  unsigned int flags);
-	int (*event_dst)(struct nfct_conntrack *ct, struct nlmsghdr *nlh,
-			  unsigned int flags);
+	void (*dump)(struct nf_conntrack *ct, struct nlmsghdr *nlh);
+	void (*event_new)(struct nf_conntrack *ct, struct nlmsghdr *nlh);
+	void (*event_upd)(struct nf_conntrack *ct, struct nlmsghdr *nlh);
+	int (*event_dst)(struct nf_conntrack *ct, struct nlmsghdr *nlh);
 };
 
 /* conntrackd modes */
Index: include/debug.h
===================================================================
--- include/debug.h	(revisión: 2)
+++ include/debug.h	(copia de trabajo)
@@ -7,26 +7,47 @@
 #define debug
 #endif
 
+#include <string.h>
+#include <netinet/in.h>
 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
 
-static inline void dump_tuple(struct nfct_tuple *tp)
+static inline void debug_ct(struct nf_conntrack *ct, char *msg)
 {
-	struct in_addr src = { .s_addr = tp->src.v4 };
-	struct in_addr dst = { .s_addr = tp->dst.v4 };
+	struct in_addr addr, addr2, addr3, addr4;
 
-	debug("tuple %p: %u %s:%hu -> ", tp, tp->protonum,
-					 inet_ntoa(src),
-					 ntohs(tp->l4src.all));
-	debug("%s:%hu\n", inet_ntoa(dst), ntohs(tp->l4dst.all));
-}
+	debug("----%s (%p) ----\n", msg, ct);
+	memcpy(&addr, 
+	       nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), 
+	       sizeof(u_int32_t));
+	memcpy(&addr2, 
+	       nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), 
+	       sizeof(u_int32_t));
+	memcpy(&addr3, 
+	       nfct_get_attr(ct, ATTR_REPL_IPV4_SRC), 
+	       sizeof(u_int32_t));
+	memcpy(&addr4, 
+	       nfct_get_attr(ct, ATTR_REPL_IPV4_DST), 
+	       sizeof(u_int32_t));
 
-static inline void debug_info(struct nfct_conntrack *ct, char *msg)
-{
-        debug("-------- %s --------\n", msg);
-        debug("status: %x\n", ct->status);
-        dump_tuple(&ct->tuple[NFCT_DIR_ORIGINAL]);
-        dump_tuple(&ct->tuple[NFCT_DIR_REPLY]);
-        debug("-------------------------\n");
+	debug("status: %x\n", nfct_get_attr_u32(ct, ATTR_STATUS));
+	debug("l3:%d l4:%d ",
+			nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO),
+			nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO));
+	debug("%s:%hu ->", inet_ntoa(addr),
+			   ntohs(nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)));
+	debug("%s:%hu\n",
+			inet_ntoa(addr2),
+			ntohs(nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)));
+	debug("l3:%d l4:%d ",
+			nfct_get_attr_u8(ct, ATTR_REPL_L3PROTO),
+			nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO));
+	debug("%s:%hu ->",
+			inet_ntoa(addr3),
+			ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)));
+	debug("%s:%hu\n",
+			inet_ntoa(addr4),
+			ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)));
+	debug("-------------------------\n");
 }
 
 #endif
Index: include/us-conntrack.h
===================================================================
--- include/us-conntrack.h	(revisión: 8)
+++ include/us-conntrack.h	(copia de trabajo)
@@ -5,7 +5,7 @@
 
 /* be careful, do not modify the layout */
 struct us_conntrack {
-	struct 	nfct_conntrack ct;
+	struct 	nf_conntrack *ct;
 	struct  cache *cache;          /* add new attributes here */
 	char 	data[0];
 };
Index: src/sync-mode.c
===================================================================
--- src/sync-mode.c	(revisión: 20)
+++ src/sync-mode.c	(copia de trabajo)
@@ -30,13 +30,14 @@
 static void mcast_handler()
 {
 	int ret;
-	char buf[8192];
+	char buf[4096], tmp[256];
 	struct mcast_sock *m = STATE_SYNC(mcast_server);
-	struct nfct_conntrack ct, *tmp;
-	unsigned int flags;
 	unsigned int type;
 	struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
+	struct nf_conntrack *ct = (struct nf_conntrack *) tmp;
 
+	memset(tmp, 0, sizeof(tmp));
+
 	ret = mcast_recv_netlink(m, nlh, sizeof(buf));
 	if (ret <= 0)
 		return;
@@ -56,43 +57,43 @@
 	 */
 	mcast_track_netlink_seq(nlh->nlmsg_seq);
 
-	if (nl_parse_network_message(&ct, nlh, &type, &flags) < 0) {
+	if ((type = nl_parse_network_message(ct, nlh)) == NFCT_T_ERROR) {
 		dlog(STATE(log), "mcast_handler says: bad netlink msg!");
 		return;
 	}
 
-	/* 
-	 * Set a reduced timeout for candidate-to-be-committed
-	 * conntracks that live in the external cache
-	 */
-	if (ct.timeout > CONFIG(commit_timeout))
-		ct.timeout = CONFIG(commit_timeout);
+	/* This is required by kernels < 2.6.20 */
+	nfct_attr_unset(ct, ATTR_TIMEOUT);
+	nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
+	nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
+	nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES);
+	nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
 
 	switch(type) {
-	case NFCT_MSG_NEW:
+	case NFCT_T_NEW:
 retry:		
-		if (cache_add_entry(STATE_SYNC(external), &ct))
-			debug_info(&ct, "external new");
+		if (cache_add_entry(STATE_SYNC(external), ct))
+			debug_ct(ct, "external new");
 		else {
 			if (errno == EEXIST) {
-				cache_del_entry(STATE_SYNC(external), &ct);
+				cache_del_entry(STATE_SYNC(external), ct);
 				goto retry;
 			}
 
-			debug_info(&ct, "can't add");
+			debug_ct(ct, "can't add");
 		}
 		break;
-	case NFCT_MSG_UPDATE:
-		if (cache_update_force(STATE_SYNC(external), &ct, flags))
-			debug_info(&ct, "external update");
+	case NFCT_T_UPDATE:
+		if (cache_update_force(STATE_SYNC(external), ct))
+			debug_ct(ct, "external update");
 		else
-			debug_info(&ct, "can't update");
+			debug_ct(ct, "can't update");
 		break;
-	case NFCT_MSG_DESTROY:
-		if (cache_del_entry(STATE_SYNC(external), &ct))
-			debug_info(&ct, "external destroy");
+	case NFCT_T_DESTROY:
+		if (cache_del_entry(STATE_SYNC(external), ct))
+			debug_ct(ct, "external destroy");
 		else
-			debug_info(&ct, "can't destroy");
+			debug_ct(ct, "can't destroy");
 		break;
 	default:
 		debug("unknown type %d\n", type);
@@ -111,7 +112,9 @@
 	}
 	memset(state.sync, 0, sizeof(struct ct_sync_state));
 
-	STATE_SYNC(internal) = cache_create("internal", PERSISTENCE | LIFETIME);
+	STATE_SYNC(internal) = cache_create("internal", 
+					    PERSISTENCE | LIFETIME,
+					    CONFIG(family));
 	if (!STATE_SYNC(internal)) {
 		dlog(STATE(log), "[FAIL] can't allocate memory for "
 				 "the internal cache");
@@ -120,7 +123,9 @@
 
 	dlog(STATE(log), "[OK] internal cache created");
 
-	STATE_SYNC(external) = cache_create("external", TIMER | LIFETIME);
+	STATE_SYNC(external) = cache_create("external",
+					    TIMER | LIFETIME,
+					    CONFIG(family));
 	if (!STATE_SYNC(external)) {
 		dlog(STATE(log), "[FAIL] can't allocate memory for the "
 				 "external cache");
@@ -240,30 +245,33 @@
 	}
 }
 
-static void dump_sync(struct nfct_conntrack *ct,
-		      struct nlmsghdr *nlh,
-		      unsigned int flags)
+static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
-	if (cache_update_force(STATE_SYNC(internal), ct, flags))
-		debug_info(ct, "resync entry");
+	nfct_attr_unset(ct, ATTR_TIMEOUT);
+	nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES);
+	nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS);
+	nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES);
+	nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS);
+
+	if (cache_update_force(STATE_SYNC(internal), ct))
+		debug_ct(ct, "resync");
 }
 
-static void event_new_sync(struct nfct_conntrack *ct,
-			   struct nlmsghdr *nlh,
-			   unsigned int flags)
+static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
+	nfct_attr_unset(ct, ATTR_TIMEOUT);
 retry:
 	if (cache_add_entry(STATE_SYNC(internal), ct)) {
 		mcast_send_netlink(STATE_SYNC(mcast_client), nlh);
-		debug_info(ct, "internal new");
+		debug_ct(ct, "internal new");
 	} else {
 		if (errno == EEXIST) {
 			char buf[4096];
 			struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
 
-			int ret = nl_build_network_message(NFCT_MSG_DESTROY,
+			int ret = nl_build_network_message(NFCT_Q_DESTROY,
 							   STATE(subsys_event),
-							   &ct,
+							   ct,
 							   buf,
 							   sizeof(buf));
 			if (ret == -1)
@@ -275,15 +283,15 @@
 		}
 		dlog(STATE(log), "can't add to internal cache: "
 				      "%s\n", strerror(errno));
-		debug_info(ct, "can't add");
+		debug_ct(ct, "can't add");
 	}
 }
 
-static void event_update_sync(struct nfct_conntrack *ct,
-			      struct nlmsghdr *nlh,
-			      unsigned int flags)
+static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
-	if (!cache_update_entry(STATE_SYNC(internal), ct, flags)) {
+	nfct_attr_unset(ct, ATTR_TIMEOUT);
+
+	if (!cache_update_entry(STATE_SYNC(internal), ct)) {
 		/*
 		 * Perhaps we are losing events. If we are working 
 		 * in relax mode then add a new entry to the cache.
@@ -292,38 +300,37 @@
 		 */
 		if ((CONFIG(flags) & RELAX_TRANSITIONS)
 		    && cache_add_entry(STATE_SYNC(internal), ct)) {
-			debug_info(ct, "forcing internal update");
+			debug_ct(ct, "forcing internal update");
 		} else {
-			debug_info(ct, "can't update");
+			debug_ct(ct, "can't update");
 			return;
 		}
 	}
-	debug_info(ct, "update");
+	debug_ct(ct, "internal update");
 	mcast_send_netlink(STATE_SYNC(mcast_client), nlh);
 }
 
-static int event_destroy_sync(struct nfct_conntrack *ct,
-			      struct nlmsghdr *nlh,
-			      unsigned int flags)
+static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
+	nfct_attr_unset(ct, ATTR_TIMEOUT);
+
 	if (CONFIG(flags) & DELAY_DESTROY_MSG) {
 
-		flags |= NFCT_STATUS;
-		ct->status |= IPS_DYING;
+		nfct_set_attr_u32(ct, ATTR_STATUS, IPS_DYING);
 
-		if (cache_update_entry(STATE_SYNC(internal), ct, flags)) {
-			debug_info(ct, "internal destroy");
+		if (cache_update_entry(STATE_SYNC(internal), ct)) {
+			debug_ct(ct, "delay internal destroy");
 			return 1;
 		} else {
-			debug_info(ct, "can't destroy!");
+			debug_ct(ct, "can't delay destroy!");
 			return 0;
 		}
 	} else {
 		if (cache_del_entry(STATE_SYNC(internal), ct)) {
 			mcast_send_netlink(STATE_SYNC(mcast_client), nlh);
-			debug_info(ct, "internal destroy");
+			debug_ct(ct, "internal destroy");
 		} else
-			debug_info(ct, "can't destroy");
+			debug_ct(ct, "can't destroy");
 	}
 }
 
Index: src/cache.c
===================================================================
--- src/cache.c	(revisión: 19)
+++ src/cache.c	(copia de trabajo)
@@ -29,34 +29,91 @@
 {
 	unsigned int a, b;
 	struct us_conntrack *u = data;
-	struct nfct_tuple *tuple = &u->ct.tuple[NFCT_DIR_ORIGINAL];
+	struct nf_conntrack *ct = u->ct;
 
-	a = jhash((void *)tuple->src.v6, sizeof(tuple->src.v6),
-		  ((tuple->l3protonum) << 16) | tuple->protonum);
-	b = jhash((void *)tuple->dst.v6, sizeof(tuple->dst.v6),
-		  (tuple->l4src.all << 16) | tuple->l4dst.all);
+	a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), sizeof(u_int32_t),
+		  ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) |
+		   (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO))));
 
+	b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), sizeof(u_int32_t),
+		  ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) |
+		   (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST))));
+
 	return jhash_2words(a, b, 0) % table->hashsize;
 }
 
+static u_int32_t hash6(void *data, struct hashtable *table)
+{
+	unsigned int a, b;
+	struct us_conntrack *u = data;
+	struct nf_conntrack *ct = u->ct;
+
+	a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC), sizeof(u_int32_t),
+		  ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) |
+		   (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO))));
+
+	b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(u_int32_t),
+		  ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) |
+		   (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST))));
+
+	return jhash_2words(a, b, 0) % table->hashsize;
+}
+
+static int __compare(struct nf_conntrack *ct1, struct nf_conntrack *ct2)
+{
+	return ((nfct_get_attr_u8(ct1, ATTR_ORIG_L3PROTO) ==
+	  	 nfct_get_attr_u8(ct2, ATTR_ORIG_L3PROTO)) &&
+		(nfct_get_attr_u8(ct1, ATTR_ORIG_L4PROTO) ==
+		 nfct_get_attr_u8(ct2, ATTR_ORIG_L4PROTO)) && 
+		(nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_SRC) ==
+		 nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_SRC)) &&
+		(nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_DST) ==
+	 	 nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_DST)) &&
+		(nfct_get_attr_u16(ct1, ATTR_REPL_PORT_SRC) ==
+	 	 nfct_get_attr_u16(ct2, ATTR_REPL_PORT_SRC)) &&
+		(nfct_get_attr_u16(ct1, ATTR_REPL_PORT_DST) ==
+	 	 nfct_get_attr_u16(ct2, ATTR_REPL_PORT_DST)));
+}
+
 static int compare(void *data1, void *data2)
 {
-	struct us_conntrack *u = data1;
-	struct nfct_conntrack *ct = data2;
+	struct us_conntrack *u1 = data1;
+	struct us_conntrack *u2 = data2;
 
-	return nfct_tuple_equal(&u->ct.tuple[NFCT_DIR_ORIGINAL], 
-				&ct->tuple[NFCT_DIR_ORIGINAL]) &&
-	       nfct_tuple_equal(&u->ct.tuple[NFCT_DIR_REPLY],
-			        &ct->tuple[NFCT_DIR_REPLY]);
+	return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_SRC) ==
+	         nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_SRC)) &&
+	 	(nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_DST) ==
+		 nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_DST)) &&
+		(nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV4_SRC) ==
+		 nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV4_SRC)) &&
+		(nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV4_DST) ==
+		 nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV4_DST)) &&
+		 __compare(u1->ct, u2->ct));
 }
 
+static int compare6(void *data1, void *data2)
+{
+	struct us_conntrack *u1 = data1;
+	struct us_conntrack *u2 = data2;
+
+	return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV6_SRC) ==
+	         nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV6_SRC)) &&
+	 	(nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV6_DST) ==
+		 nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV6_DST)) &&
+		(nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV6_SRC) ==
+		 nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV6_SRC)) &&
+		(nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV6_DST) ==
+		 nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV6_DST)) &&
+		 __compare(u1->ct, u2->ct));
+}
+
 struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = {
 	[TIMER_BIT]		= &timer_feature,
 	[PERSISTENCE_BIT] 	= &persistence_feature,
 	[LIFETIME_BIT]		= &lifetime_feature,
 };
 
-struct cache *cache_create(char *name, unsigned int features)
+struct cache *cache_create(char *name, unsigned int features, u_int8_t proto)
 {
 	size_t size = sizeof(struct us_conntrack);
 	int i, j = 0;
@@ -85,11 +142,23 @@
 	memcpy(c->features, feature_array, sizeof(struct cache_feature) * j);
 	c->num_features = j;
 
-	c->h = hashtable_create(CONFIG(hashsize),
-				CONFIG(limit),
-				size,
-				hash,
-				compare);
+	switch(proto) {
+	case AF_INET:
+		c->h = hashtable_create(CONFIG(hashsize),
+					CONFIG(limit),
+					size,
+					hash,
+					compare);
+		break;
+	case AF_INET6:
+		c->h = hashtable_create(CONFIG(hashsize),
+					CONFIG(limit),
+					size,
+					hash6,
+					compare6);
+		break;
+	}
+
 	if (!c->h) {
 		free(c->features);
 		free(c);
@@ -108,19 +177,27 @@
 	free(c);
 }
 
-int __cache_add_entry(struct cache *c, struct nfct_conntrack *ct)
+int __cache_add_entry(struct cache *c, struct nf_conntrack *ct)
 {
-	char buf[sizeof(struct us_conntrack) + c->h->datasize];
+	int i;
+	size_t size = sizeof(struct us_conntrack) + c->h->datasize;
+	char buf[size];
 	struct us_conntrack *u = (struct us_conntrack *) buf;
-	size_t size;
-	int i;
 
+	memset(u, 0, size);
+
 	u->cache = c;
-	memcpy(&u->ct, ct, sizeof(struct nfct_conntrack));
+	if ((u->ct = nfct_new()) == NULL) {
+		errno = ENOMEM;
+		c->add_fail++;
+		return 0;
+	}
+	memcpy(u->ct, ct, nfct_sizeof(ct));
 
 	u = hashtable_add(c->h, u);
 	if (u) {
 		void *data = u->data;
+
         	for (i = 0; i < c->num_features; i++) {
 			c->features[i]->add(u, data);
 			data += c->features[i]->size;
@@ -142,7 +219,7 @@
 	c->add_fail++;
 	return 0;
 }
-int cache_add_entry(struct cache *c, struct nfct_conntrack *ct)
+int cache_add_entry(struct cache *c, struct nf_conntrack *ct)
 {
 	int ret;
 
@@ -153,13 +230,15 @@
 	return ret;
 }
 
-static int __cache_update_entry(struct cache *c,
-				struct nfct_conntrack *ct, 
-				u_int32_t flags)
+static int __cache_update_entry(struct cache *c, struct nf_conntrack *ct)
 {
-	struct us_conntrack *u;
+        size_t size = sizeof(struct us_conntrack) + c->h->datasize;
+	char buf[size];
+	struct us_conntrack *u = (struct us_conntrack *) buf;
 
-	u = (struct us_conntrack *) hashtable_test(c->h, ct);
+	u->ct = ct;
+
+	u = (struct us_conntrack *) hashtable_test(c->h, u);
 	if (u) {
 		int i;
 		void *data = u->data;
@@ -169,26 +248,25 @@
 			data += c->features[i]->size;
 		}
 
-		if (flags & NFCT_STATUS)
-			u->ct.status |= ct->status;
-		if (flags & NFCT_PROTOINFO)
-			memcpy(&u->ct.protoinfo,
-			       &ct->protoinfo,
-			       sizeof(union nfct_protoinfo));
-		if (flags & NFCT_TIMEOUT)
-			u->ct.timeout = ct->timeout;
+		if (nfct_attr_is_set(ct, ATTR_STATUS))
+		    	nfct_set_attr_u32(u->ct, ATTR_STATUS,
+					  nfct_get_attr_u32(ct, ATTR_STATUS));
+		if (nfct_attr_is_set(ct, ATTR_TCP_STATE))
+			nfct_set_attr_u8(u->ct, ATTR_TCP_STATE,
+					 nfct_get_attr_u8(ct, ATTR_TCP_STATE));
+		if (nfct_attr_is_set(ct, ATTR_TIMEOUT))
+			nfct_set_attr_u32(u->ct, ATTR_TIMEOUT,
+					  nfct_get_attr_u32(ct, ATTR_TIMEOUT));
 
 		return 1;
 	} 
 	return 0;
 }
 
-int cache_update_entry(struct cache *c,
-		       struct nfct_conntrack *ct, 
-		       u_int32_t flags)
+int cache_update_entry(struct cache *c, struct nf_conntrack *ct)
 {
 	lock();
-	if (__cache_update_entry(c, ct, flags)) {
+	if (__cache_update_entry(c, ct)) {
 		c->upd_ok++;
 		unlock();
 		return 1;
@@ -198,12 +276,10 @@
 	return 0;
 }
 
-int cache_update_force(struct cache *c,
-		       struct nfct_conntrack *ct,
-		       u_int32_t flags)
+int cache_update_force(struct cache *c, struct nf_conntrack *ct)
 {
 	lock();
-	if (__cache_update_entry(c, ct, flags)) {
+	if (__cache_update_entry(c, ct)) {
 		c->upd_ok++;
 		unlock();
 		return 1;
@@ -218,21 +294,27 @@
 	return 0;
 }
 
-int __cache_del_entry(struct cache *c, struct nfct_conntrack *ct)
+int __cache_del_entry(struct cache *c, struct nf_conntrack *ct)
 {
-	struct us_conntrack *u;
+	size_t size = sizeof(struct us_conntrack) + c->h->datasize;
+	char buf[size];
+	struct us_conntrack *u = (struct us_conntrack *) buf;
 
-	u = (struct us_conntrack *) hashtable_test(c->h, ct);
+	u->ct = ct;
+
+	u = (struct us_conntrack *) hashtable_test(c->h, u);
 	if (u) {
 		int i;
 		void *data = u->data;
+		struct nf_conntrack *p = u->ct;
 
 		for (i = 0; i < c->num_features; i++) {
 			c->features[i]->destroy(u, data);
 			data += c->features[i]->size;
 		}
 
-		hashtable_del(c->h, ct);
+		hashtable_del(c->h, u);
+		free(p);
 		c->del_ok++;
 		return 1;
 	}
@@ -240,7 +322,7 @@
 	return 0;
 }
 
-int cache_del_entry(struct cache *c, struct nfct_conntrack *ct)
+int cache_del_entry(struct cache *c, struct nf_conntrack *ct)
 {
 	int ret;
 
@@ -255,14 +337,19 @@
 {
 	char buf[1024];
 	int size;
-	unsigned flags = NFCT_PROTOINFO | NFCT_MARK | NFCT_STATUS;
 	int *fd = data1;
 	struct us_conntrack *u = data2;
 	void *data = u->data;
 	int i;
 
 	memset(buf, 0, sizeof(buf));
-	size = nfct_sprintf_conntrack(buf, &u->ct, flags);
+	size = nfct_snprintf(buf, 
+			     sizeof(buf), 
+			     u->ct, 
+			     NFCT_T_UNKNOWN, 
+			     NFCT_O_DEFAULT,
+			     0);
+
 	for (i = 0; i < u->cache->num_features; i++) {
 		if (u->cache->features[i]->dump) {
 			size += u->cache->features[i]->dump(u, data, buf+size);
@@ -289,21 +376,42 @@
 {
 	int ret;
 	struct cache *c = data1;
-	struct nfct_conntrack *ct = data2;
-	struct nfct_conntrack strip_ct;
+	struct us_conntrack *u = data2;
+	struct nf_conntrack *ct;
 	char buf[4096];
 	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
 
-	nfct_conntrack_strip_nat(ct, &strip_ct);
-	ret = nfct_build_netlink_message(NFCT_MSG_NEW,
-					 STATE(subsys_sync),
-					 &strip_ct,
-					 buf,
-					 sizeof(buf));
+	ct = nfct_clone(u->ct);
+	if (ct == NULL)
+		return 0;
+
+	if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT))
+		nfct_setobjopt(ct, NFCT_SOPT_UNDO_SNAT);
+	if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT))
+		nfct_setobjopt(ct, NFCT_SOPT_UNDO_DNAT);
+	if (nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT))
+		nfct_setobjopt(ct, NFCT_SOPT_UNDO_SPAT);
+	if (nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT))
+		nfct_setobjopt(ct, NFCT_SOPT_UNDO_DPAT);
+
+        /* 
+	 * Set a reduced timeout for candidate-to-be-committed
+	 * conntracks that live in the external cache
+	 */
+	nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout));
+
+        ret = nfct_build_query(STATE(subsys_sync),
+			       NFCT_Q_CREATE,
+			       ct,
+			       nlh,
+			       sizeof(buf));
+
+	free(ct);
+
 	if (ret == -1) {
 		/* XXX: Please cleanup this debug crap, default in logfile */
 		debug("--- failed to build: %s --- \n", strerror(errno));
-		goto err;
+		return 0;
 	}
 
 	ret = nfnl_query(STATE(sync), nlh);
@@ -322,12 +430,6 @@
 		debug("----- commit -----\n");
 	}
 
-err:
-	debug("status: %x\n", strip_ct.status);
-	dump_tuple(&strip_ct.tuple[NFCT_DIR_ORIGINAL]);
-	dump_tuple(&strip_ct.tuple[NFCT_DIR_REPLY]);
-	debug("------------------\n");
-
 	/* keep iterating even if we have found errors */
 	return 0;
 }
@@ -384,22 +486,17 @@
 static int iterate_bulk(void *data1, void *data2)
 {
 	int ret;
-	struct nfct_conntrack *ct = data2;
+	struct us_conntrack *u = data2;
 	char buf[4096];
 	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
 
-	ret = nfct_build_netlink_message(NFCT_MSG_UPDATE,
-					 STATE(subsys_sync),
-					 ct,
-					 buf,
-					 sizeof(buf));
-	if (ret == -1) {
-		debug("--- failed to build: %s --- \n", strerror(errno));
-		debug("status: %x\n", ct->status);
-		dump_tuple(&ct->tuple[NFCT_DIR_ORIGINAL]);
-		dump_tuple(&ct->tuple[NFCT_DIR_REPLY]);
-		debug("------------------\n");
-	}
+	ret = nfct_build_query(STATE(subsys_sync),
+			       NFCT_T_UPDATE,
+			       u->ct, 
+			       buf,
+			       sizeof(buf));
+	if (ret == -1)
+		debug_ct(u->ct, "failed to build");
 
 	mcast_send_netlink(STATE_SYNC(mcast_client), nlh);
 
Index: src/cache_timer.c
===================================================================
--- src/cache_timer.c	(revisión: 19)
+++ src/cache_timer.c	(copia de trabajo)
@@ -26,8 +26,8 @@
 {
 	struct us_conntrack *u = data;
 
-	debug_info(&u->ct, "expired timeout");
-	__cache_del_entry(u->cache, &u->ct);
+	debug_ct(u->ct, "expired timeout");
+	__cache_del_entry(u->cache, u->ct);
 }
 
 static void timer_add(struct us_conntrack *u, void *data)
Index: src/netlink.c
===================================================================
--- src/netlink.c	(revisión: 20)
+++ src/netlink.c	(copia de trabajo)
@@ -18,6 +18,7 @@
 
 #include "conntrackd.h"
 #include <libnfnetlink/libnfnetlink.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
 #include <errno.h>
 #include "us-conntrack.h"
 #include <signal.h>
@@ -27,51 +28,19 @@
  * sent via network contain the whole conntrack state */
 int nl_build_network_message(const int msg_type,
 			     struct nfnl_subsys_handle *ssh, 
-			     struct nfct_conntrack *ct,
+			     struct nf_conntrack *ct,
 			     void *buffer,
 			     unsigned int size)
 {
-	struct nfnlhdr *req = buffer;
-	u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
+	u_int8_t l3num = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO);
 	unsigned type, flags;
-	
-	memset(req, 0, size);
 
-	switch(msg_type) {
-	case NFCT_MSG_NEW:
-		type = IPCTNL_MSG_CT_NEW;
-		flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL;
-		break;
-	case NFCT_MSG_UPDATE:
-		type = IPCTNL_MSG_CT_NEW;
-		flags = NLM_F_REQUEST|NLM_F_ACK;
-		break;
-	case NFCT_MSG_DESTROY:
-		type = IPCTNL_MSG_CT_DELETE;
-		flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK;
-		break;
-	default:
-		return -1;
-	}
-	
-	nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags);
+	memset(buffer, 0, size);
 
-	nfct_build_tuple(req, size, &ct->tuple[NFCT_DIR_ORIGINAL], 
-			 CTA_TUPLE_ORIG);
-	nfct_build_tuple(req, size, &ct->tuple[NFCT_DIR_REPLY],
-			 CTA_TUPLE_REPLY);
-
-	nfct_build_status(req, size, ct);
-	nfct_build_timeout(req, size, ct);
-	nfct_build_mark(req, size, ct);
-	nfct_build_protoinfo(req, size, ct);
-	nfct_build_snat(req, size, ct);
-	nfct_build_dnat(req, size, ct);
-
-	return req->nlh.nlmsg_len;
+	return nfct_build_query(ssh, msg_type, ct, buffer, size);
 }
 
-int nl_parse_network_message(struct nfct_conntrack *ct,
+int nl_parse_network_message(struct nf_conntrack *ct,
 			     struct nlmsghdr *nlh,
 			     unsigned int *type,
 			     unsigned int *flags)
@@ -84,38 +53,34 @@
 	 *
 	 * Yup, this is a hack 8)
 	 */
-	return nfct_parse_netlink_message(ct, nlh, type, flags);
+	return nfct_parse_conntrack(NFCT_T_ALL, nlh, ct);
 }
 
-static int ignore_conntrack(struct nfct_conntrack *ct)
+static int ignore_conntrack(struct nf_conntrack *ct)
 {
 	/* ignore a certain protocol */
-	if (CONFIG(ignore_protocol)[ct->tuple[NFCT_DIR_ORIGINAL].protonum] == 1)
+	if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)])
 		return 1;
 
 	/* Accept DNAT'ed traffic: not really coming to the local machine */
-	if ((CONFIG(flags) & STRIP_NAT) && nfct_conntrack_is_dnatted(ct)) {
-		debug_info(ct, "DNAT");
+	if ((CONFIG(flags) & STRIP_NAT) && 
+	    nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) {
+		debug_ct(ct, "DNAT");
 		return 0;
 	}
 
         /* Accept SNAT'ed traffic: not really coming to the local machine */
-	if ((CONFIG(flags) & STRIP_NAT) && nfct_conntrack_is_snatted(ct)) {
-		debug_info(ct, "SNAT");
+	if ((CONFIG(flags) & STRIP_NAT) && 
+	    nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) {
+		debug_ct(ct, "SNAT");
 		return 0;
 	}
 
 	/* Ignore traffic */
-	if (hashtable_test(STATE(ignoreip),
-			   &ct->tuple[NFCT_DIR_ORIGINAL].src.v6)) {
-		debug_info(ct, "ignore traffic (source)");
+	if (hashtable_test(STATE(ignoreip), ct)) {
+		debug_ct(ct, "ignore traffic");
 		return 1;
 	}
-	if (hashtable_test(STATE(ignoreip),
-			   &ct->tuple[NFCT_DIR_ORIGINAL].dst.v6)) {
-		debug_info(ct, "ignore traffic (destination)");
-		return 1;
-	}
 
 	return 0;
 }
@@ -124,36 +89,37 @@
 			    struct nfattr *nfa[],
 			    void *data)
 {
-	struct nfct_conntrack ct;
-	unsigned int flags;
-	unsigned int type;
+	char tmp[1024];
+	struct nf_conntrack *ct = (struct nf_conntrack *) tmp;
+	int type;
 
-	if (nfct_parse_netlink_message(&ct, nlh, &type, &flags) < 0)
-		return 0;
+	if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR)
+		return NFCT_CB_STOP;
 
 	/* 
 	 * Ignore this conntrack: it talks about a
 	 * connection that is not interesting for us.
 	 */
-	if (ignore_conntrack(&ct))
-		return 0;
+	if (ignore_conntrack(ct))
+		return NFCT_CB_STOP;
 
 	switch(type) {
-	case NFCT_MSG_NEW:
-		STATE(mode)->event_new(&ct, nlh, flags);
+	case NFCT_T_NEW:
+		STATE(mode)->event_new(ct, nlh);
 		break;
-	case NFCT_MSG_UPDATE:
-		STATE(mode)->event_upd(&ct, nlh, flags);
+	case NFCT_T_UPDATE:
+		STATE(mode)->event_upd(ct, nlh);
 		break;
-	case NFCT_MSG_DESTROY:
-		if (STATE(mode)->event_dst(&ct, nlh, flags))
-			update_traffic_stats(&ct);
+	case NFCT_T_DESTROY:
+		if (STATE(mode)->event_dst(ct, nlh))
+			update_traffic_stats(ct);
 		break;
 	default:
 		dlog(STATE(log), "received unknown msg from ctnetlink\n");
 		break;
 	}
-	return 0;
+
+	return NFCT_CB_STOP;
 }
 
 int nl_init_event_handler(void)
@@ -212,29 +178,28 @@
 			   struct nfattr *nfa[],
 			   void *data)
 {
-	struct nfct_conntrack ct;
-	unsigned int flags;
-	unsigned int type;
+	char buf[1024];
+	struct nf_conntrack *ct = (struct nf_conntrack *) buf;
+	int type;
 
-	if (nfct_parse_netlink_message(&ct, nlh, &type, &flags) < 0)
-		return 1;
+	if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR)
+		return NFCT_CB_CONTINUE;
 
 	/* 
 	 * Ignore this conntrack: it talks about a
 	 * connection that is not interesting for us.
 	 */
-	if (ignore_conntrack(&ct))
-		return 1;
+	if (ignore_conntrack(ct))
+		return NFCT_CB_CONTINUE;
 
 	switch(type) {
-	case NFCT_MSG_UPDATE:
-		STATE(mode)->dump(&ct, nlh, flags);
+	case NFCT_T_UPDATE:
+		STATE(mode)->dump(ct, nlh);
 		break;
 	default:
 		dlog(STATE(log), "received unknown msg from ctnetlink");
 		break;
 	}
-	return 1;
 }
 
 int nl_init_dump_handler(void)
Index: src/cache_persistence.c
===================================================================
--- src/cache_persistence.c	(revisión: 19)
+++ src/cache_persistence.c	(copia de trabajo)
@@ -28,25 +28,25 @@
 	char buf[8192];
 	int size;
 
-	if (u->ct.status & IPS_DYING) {
+	if (nfct_get_attr_u32(u->ct, ATTR_STATUS) & IPS_DYING) {
 		
-		debug_info(&u->ct, "persistence destroy");
+		debug_ct(u->ct, "persistence destroy");
 
-		size = nl_build_network_message(NFCT_MSG_DESTROY,
+		size = nl_build_network_message(NFCT_Q_DESTROY,
 						STATE(subsys_event),
-						&u->ct,
+						u->ct,
 						buf,
 						sizeof(buf));
-		__cache_del_entry(u->cache, &u->ct);
+		__cache_del_entry(u->cache, u->ct);
 		mcast_send_netlink(STATE_SYNC(mcast_client), buf);
 	} else {
 		
-		debug_info(&u->ct, "persistence update");
+		debug_ct(u->ct, "persistence update");
 
 		a->expires = random() % CONFIG(refresh) + 1;
-		size = nl_build_network_message(NFCT_MSG_UPDATE,
+		size = nl_build_network_message(NFCT_Q_UPDATE,
 						STATE(subsys_event),
-						&u->ct,
+						u->ct,
 						buf, 
 						sizeof(buf));
 		mcast_send_netlink(STATE_SYNC(mcast_client), buf);
Index: src/read_config_yy.y
===================================================================
--- src/read_config_yy.y	(revisión: 19)
+++ src/read_config_yy.y	(copia de trabajo)
@@ -42,7 +42,7 @@
 %token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_IGNORE_PROTOCOL
 %token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT
 %token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY
-%token T_SYNC_MODE T_LISTEN_TO
+%token T_SYNC_MODE T_LISTEN_TO T_FAMILY
 
 %token <string> T_IP T_PATH_VAL
 %token <val> T_NUMBER
@@ -358,6 +358,7 @@
 	    | unix_line
 	    | netlink_buffer_size
 	    | netlink_buffer_size_max_grown
+	    | family
 	    ;
 
 netlink_buffer_size: T_BUFFER_SIZE T_NUMBER
@@ -370,6 +371,14 @@
 	conf.netlink_buffer_size_max_grown = $2;
 };
 
+family : T_FAMILY T_STRING
+{
+	if (strncmp($2, "IPv6", strlen("IPv6")) == 0)
+		conf.family = AF_INET6;
+	else
+		conf.family = AF_INET;
+};
+
 stats: T_SYNC '{' stats_list '}';
 
 stats_list:
@@ -403,6 +412,10 @@
 	yyparse();
 	fclose(fp);
 
+	/* default to IPv4 */
+	if (CONFIG(family) == 0)
+		CONFIG(family) = AF_INET;
+
 	/* set to default is not specified */
 	if (strcmp(CONFIG(lockfile), "") == 0)
 		strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN);
Index: src/stats-mode.c
===================================================================
--- src/stats-mode.c	(revisión: 19)
+++ src/stats-mode.c	(copia de trabajo)
@@ -37,7 +37,7 @@
 	}
 	memset(state.stats, 0, sizeof(struct ct_stats_state));
 
-	STATE_STATS(cache) = cache_create("stats", LIFETIME); 
+	STATE_STATS(cache) = cache_create("stats", LIFETIME, CONFIG(family)); 
 	if (!STATE_STATS(cache)) {
 		dlog(STATE(log), "[FAIL] can't allocate memory for the "
 				 "external cache");
@@ -80,32 +80,29 @@
 	}
 }
 
-static void dump_stats(struct nfct_conntrack *ct,
-		       struct nlmsghdr *nlh,
-		       unsigned int flags)
+static void dump_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
-	if (cache_update_force(STATE_STATS(cache), ct, flags))
-		debug_info(ct, "resync entry");
+	if (cache_update_force(STATE_STATS(cache), ct))
+		debug_ct(ct, "resync entry");
 }
 
-static void event_new_stats(struct nfct_conntrack *ct,
-			    struct nlmsghdr *nlh,
-			    unsigned int flags)
+static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
+	debug_ct(ct, "debug event");
 	if (cache_add_entry(STATE_STATS(cache), ct)) {
-		debug_info(ct, "cache new");
+		debug_ct(ct, "cache new");
 	} else {
 		dlog(STATE(log), "can't add to cache cache: "
 				      "%s\n", strerror(errno));
-		debug_info(ct, "can't add");
+		debug_ct(ct, "can't add");
 	}
 }
 
-static void event_update_stats(struct nfct_conntrack *ct,
-			       struct nlmsghdr *nlh,
-			       unsigned int flags)
+static void event_update_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
-	if (!cache_update_entry(STATE_STATS(cache), ct, flags)) {
+	debug_ct(ct, "update");
+
+	if (!cache_update_entry(STATE_STATS(cache), ct)) {
 		/*
 		 * Perhaps we are losing events. If we are working 
 		 * in relax mode then add a new entry to the cache.
@@ -114,24 +111,22 @@
 		 */
 		if ((CONFIG(flags) & RELAX_TRANSITIONS)
 		    && cache_add_entry(STATE_STATS(cache), ct)) {
-			debug_info(ct, "forcing cache update");
+			debug_ct(ct, "forcing cache update");
 		} else {
-			debug_info(ct, "can't update");
+			debug_ct(ct, "can't update");
 			return;
 		}
 	}
-	debug_info(ct, "update");
+	debug_ct(ct, "update");
 }
 
-static int event_destroy_stats(struct nfct_conntrack *ct,
-			       struct nlmsghdr *nlh,
-			       unsigned int flags)
+static int event_destroy_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh)
 {
 	if (cache_del_entry(STATE_STATS(cache), ct)) {
-		debug_info(ct, "cache destroy");
+		debug_ct(ct, "cache destroy");
 		return 1;
 	} else {
-		debug_info(ct, "can't destroy!");
+		debug_ct(ct, "can't destroy!");
 		return 0;
 	}
 }
Index: src/read_config_lex.l
===================================================================
--- src/read_config_lex.l	(revisión: 19)
+++ src/read_config_lex.l	(copia de trabajo)
@@ -79,6 +79,7 @@
 "SocketBufferSizeMaxGrowth"	{ return T_BUFFER_SIZE_MAX_GROWN; }
 "Mode"				{ return T_SYNC_MODE; }
 "ListenTo"			{ return T_LISTEN_TO; }
+"Family"			{ return T_FAMILY; }
 
 {integer}		{ yylval.val = atoi(yytext); return T_NUMBER; }
 {ip4}			{ yylval.string = strdup(yytext); return T_IP; }
Index: src/traffic_stats.c
===================================================================
--- src/traffic_stats.c	(revisión: 19)
+++ src/traffic_stats.c	(copia de trabajo)
@@ -25,16 +25,16 @@
 #include "us-conntrack.h"
 #include <signal.h>
 
-void update_traffic_stats(struct nfct_conntrack *ct)
+void update_traffic_stats(struct nf_conntrack *ct)
 {
 	STATE(bytes)[NFCT_DIR_ORIGINAL] +=
-		ct->counters[NFCT_DIR_ORIGINAL].bytes;
+		nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_BYTES);
 	STATE(bytes)[NFCT_DIR_REPLY] +=
-		ct->counters[NFCT_DIR_REPLY].bytes;
+		nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_BYTES);
 	STATE(packets)[NFCT_DIR_ORIGINAL] += 
-		ct->counters[NFCT_DIR_ORIGINAL].packets;
+		nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_PACKETS);
 	STATE(packets)[NFCT_DIR_REPLY] +=
-		ct->counters[NFCT_DIR_REPLY].packets;
+		nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_PACKETS);
 }
 
 void dump_traffic_stats(int fd)
