[netfilter-cvslog] r6410 - in trunk: libnetfilter_conntrack libnetfilter_conntrack/include/libnetfilter_conntrack libnetfilter_conntrack/src libnetfilter_log libnetfilter_log/include/libnetfilter_log libnetfilter_log/src libnetfilter_queue libnetfilter_queue/include/libnetfilter_queue libnetfilter_queue/src libnfnetlink libnfnetlink/include/libnfnetlink libnfnetlink/src

laforge at netfilter.org laforge at netfilter.org
Sat Jan 14 20:04:55 CET 2006


Author: laforge at netfilter.org
Date: 2006-01-14 20:04:51 +0100 (Sat, 14 Jan 2006)
New Revision: 6410

Modified:
   trunk/libnetfilter_conntrack/Make_global.am
   trunk/libnetfilter_conntrack/configure.in
   trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h
   trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
   trunk/libnetfilter_conntrack/src/libnetfilter_conntrack.c
   trunk/libnetfilter_log/configure.in
   trunk/libnetfilter_log/include/libnetfilter_log/libnetfilter_log.h
   trunk/libnetfilter_log/src/Makefile.am
   trunk/libnetfilter_log/src/libnetfilter_log.c
   trunk/libnetfilter_queue/configure.in
   trunk/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue.h
   trunk/libnetfilter_queue/src/Makefile.am
   trunk/libnetfilter_queue/src/libnetfilter_queue.c
   trunk/libnfnetlink/configure.in
   trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h
   trunk/libnfnetlink/src/Makefile.am
   trunk/libnfnetlink/src/libnfnetlink.c
Log:
Introduce various API changes throughout the library stack
1) make libnfnetlink dynamically allocate it's handles
2) apply that change throughout libnetfilter_*
3) add {nfq,nflog,nfct}_open_nfnl() functions that open
   the specific subsystem on top of an existing nfnl_handle,
   which is required for upcoming libnetfilter_conntrack_helper

The changes break ABI and API compatibility of libnfnetlink, but don't
break ABI or API compatibility of the libnetfilter_* libraries.


Modified: trunk/libnetfilter_conntrack/Make_global.am
===================================================================
--- trunk/libnetfilter_conntrack/Make_global.am	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_conntrack/Make_global.am	2006-01-14 19:04:51 UTC (rev 6410)
@@ -1,6 +1,6 @@
 # This is _NOT_ the library release version, it's an API version.
 # Please read Chapter 6 "Library interface versions" of the libtool
 # documentation before making any modification
-LIBVERSION=1:0:0
+LIBVERSION=2:0:1
 
 INCLUDES=$(all_includes) -I$(top_srcdir)/include

Modified: trunk/libnetfilter_conntrack/configure.in
===================================================================
--- trunk/libnetfilter_conntrack/configure.in	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_conntrack/configure.in	2006-01-14 19:04:51 UTC (rev 6410)
@@ -4,7 +4,7 @@
 
 AC_CANONICAL_SYSTEM
 
-AM_INIT_AUTOMAKE(libnetfilter_conntrack, 0.0.30)
+AM_INIT_AUTOMAKE(libnetfilter_conntrack, 0.0.31)
 
 AC_PROG_CC
 AM_PROG_LIBTOOL

Modified: trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h
===================================================================
--- trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h	2006-01-14 19:04:51 UTC (rev 6410)
@@ -105,6 +105,7 @@
 	struct nfct_tuple mask;
 	u_int32_t timeout;
 	u_int32_t id;
+	u_int16_t expectfn_queue_id;
 };
 
 struct nfct_conntrack_compare {
@@ -225,6 +226,9 @@
  * [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);

Modified: trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
===================================================================
--- trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_conntrack/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h	2006-01-14 19:04:51 UTC (rev 6410)
@@ -120,6 +120,7 @@
 	CTA_EXPECT_TIMEOUT,
 	CTA_EXPECT_ID,
 	CTA_EXPECT_HELP_NAME,
+	CTA_EXPECT_QUEUENR,
 	__CTA_EXPECT_MAX
 };
 #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
@@ -131,6 +132,4 @@
 };
 #define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
 
-#define CTA_HELP_MAXNAMESIZE	32
-
 #endif /* _IPCONNTRACK_NETLINK_H */

Modified: trunk/libnetfilter_conntrack/src/libnetfilter_conntrack.c
===================================================================
--- trunk/libnetfilter_conntrack/src/libnetfilter_conntrack.c	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_conntrack/src/libnetfilter_conntrack.c	2006-01-14 19:04:51 UTC (rev 6410)
@@ -29,7 +29,9 @@
 
 /* Harald says: "better for encapsulation" ;) */
 struct nfct_handle {
-	struct nfnl_handle nfnlh;
+	struct nfnl_handle *nfnlh;
+	struct nfnl_subsys_handle *nfnlssh_ct;
+	struct nfnl_subsys_handle *nfnlssh_exp;
 	nfct_callback callback;		/* user callback */
 	void *callback_data;		/* user data for callback */
 	nfct_handler handler;		/* netlink handler */
@@ -75,44 +77,81 @@
 	return ret;
 }
 
-struct nfct_handle *nfct_open(u_int8_t subsys_id, unsigned subscriptions)
+struct nfct_handle *nfct_open_nfnl(struct nfnl_handle *nfnlh,
+				   u_int8_t subsys_id,
+				   unsigned int subscriptions)
 {
-	int err;
-	u_int8_t cb_count;
 	struct nfct_handle *cth;
 
-	switch(subsys_id) {
-		case NFNL_SUBSYS_CTNETLINK:
-			cb_count = IPCTNL_MSG_MAX;
-			break;
-		case NFNL_SUBSYS_CTNETLINK_EXP:
-			cb_count = IPCTNL_MSG_EXP_MAX;
-			break;
-		default:
-			return NULL;
-			break;
-	}
-	cth = (struct nfct_handle *)
-		malloc(sizeof(struct nfct_handle));
+	cth = (struct nfct_handle *) malloc(sizeof(struct nfct_handle));
 	if (!cth)
 		return NULL;
 	
 	memset(cth, 0, sizeof(*cth));
+	cth->nfnlh = nfnlh;
 
-	err = nfnl_open(&cth->nfnlh, subsys_id, cb_count, subscriptions);
-	if (err < 0) {
-		free(cth);
-		return NULL;
+	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;
 
-	err = nfnl_close(&cth->nfnlh);
+	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;
+	}
+
+	err = nfnl_close(cth->nfnlh);
 	free(cth);
 
 	return err;
@@ -120,7 +159,7 @@
 
 int nfct_fd(struct nfct_handle *cth)
 {
-	return nfnl_fd(&cth->nfnlh);
+	return nfnl_fd(cth->nfnlh);
 }
 
 void nfct_register_callback(struct nfct_handle *cth, nfct_callback callback,
@@ -889,7 +928,8 @@
 
 	memset(buf, 0, sizeof(buf));
 	
-	nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_CT_NEW,
+	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], 
@@ -911,7 +951,7 @@
 	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);
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
 }
 
 int nfct_update_conntrack(struct nfct_handle *cth, struct nfct_conntrack *ct)
@@ -928,8 +968,8 @@
 	req = (void *) &buf;
 	memset(&buf, 0, sizeof(buf));
 
-	nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_CT_NEW,
-		      NLM_F_REQUEST|NLM_F_ACK);	
+	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);
@@ -954,11 +994,11 @@
 
 	nfct_build_protoinfo(req, sizeof(buf), ct);
 
-	err = nfnl_send(&cth->nfnlh, &req->nlh);
+	err = nfnl_send(cth->nfnlh, &req->nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 int nfct_delete_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, 
@@ -972,7 +1012,7 @@
 	req = (void *) &buf;
 	memset(&buf, 0, sizeof(buf));
 
-	nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, 
+	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);
 
@@ -984,7 +1024,7 @@
 			       sizeof(u_int32_t));
 	}
 
-	return nfnl_talk(&cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(cth->nfnlh, &req->nlh, 0, 0, NULL, NULL, NULL);
 }
 
 int nfct_get_conntrack(struct nfct_handle *cth, struct nfct_tuple *tuple, 
@@ -1001,7 +1041,7 @@
 	memset(&buf, 0, sizeof(buf));
 	req = (void *) &buf;
 
-	nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0,
+	nfnl_fill_hdr(cth->nfnlssh_ct, &req->nlh, 0,
 		      l3num, 0, IPCTNL_MSG_CT_GET,
 		      NLM_F_REQUEST|NLM_F_ACK);
 	
@@ -1013,11 +1053,11 @@
 			       sizeof(u_int32_t));
 	}
 
-	err = nfnl_send(&cth->nfnlh, &req->nlh);
+	err = nfnl_send(cth->nfnlh, &req->nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 static int __nfct_dump_conntrack_table(struct nfct_handle *cth, int zero, 
@@ -1034,14 +1074,14 @@
 	else
 		msg = IPCTNL_MSG_CT_GET;
 
-	nfnl_fill_hdr(&cth->nfnlh, &req.nlh, 0, family, 0,
+	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);
+	err = nfnl_send(cth->nfnlh, &req.nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth); 
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth); 
 }
 
 int nfct_dump_conntrack_table(struct nfct_handle *cth, int family)
@@ -1064,7 +1104,7 @@
 		return -EPERM;
 	
 	cth->handler = nfct_conntrack_netlink_handler;
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 void nfct_register_proto(struct nfct_proto *h)
@@ -1095,14 +1135,14 @@
 	memset(&req, 0, sizeof(req));
 
 	cth->handler = nfct_expect_netlink_handler;
-	nfnl_fill_hdr(&cth->nfnlh, &req.nlh, 0, family, 0,
+	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);
+	err = nfnl_send(cth->nfnlh, &req.nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 int nfct_flush_conntrack_table(struct nfct_handle *cth, int family)
@@ -1111,11 +1151,11 @@
 
 	memset(&req, 0, sizeof(req));
 
-	nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &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);
+	return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL);
 }
 
 int nfct_get_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple,
@@ -1129,7 +1169,8 @@
 	memset(&buf, 0, sizeof(buf));
 	req = (void *) &buf;
 
-	nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_EXP_GET,
+	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;
@@ -1139,11 +1180,11 @@
 		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id,
 			       sizeof(u_int32_t));
 
-	err = nfnl_send(&cth->nfnlh, &req->nlh);
+	err = nfnl_send(cth->nfnlh, &req->nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 struct nfct_expect *
@@ -1161,7 +1202,7 @@
 	exp->master = *master;
 	exp->tuple = *tuple;
 	exp->mask = *mask;
-	exp->timeout = htonl(timeout);
+	exp->timeout = timeout;
 	if (id != NFCT_ANY_ID)
 		exp->id = htonl(id);
 
@@ -1180,27 +1221,36 @@
 	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->nfnlh, &req->nlh, 0, l3num, 0, IPCTNL_MSG_EXP_NEW,
+	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, 
-		       &exp->timeout, sizeof(u_int32_t));
+		       &timeout, sizeof(u_int32_t));
 
-	err = nfnl_send(&cth->nfnlh, &req->nlh);
+	queuenr = htons(exp->expectfn_queue_id);
+	if (queuenr)
+		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_QUEUENR,
+			       &queuenr, sizeof(u_int16_t));
+		 
+	err = nfnl_send(cth->nfnlh, &req->nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
-int nfct_delete_expectation(struct nfct_handle *cth,struct nfct_tuple *tuple,
+int nfct_delete_expectation(struct nfct_handle *cth, struct nfct_tuple *tuple,
 			    u_int32_t id)
 {
 	int err;
@@ -1211,7 +1261,7 @@
 	memset(&buf, 0, sizeof(buf));
 	req = (void *) &buf;
 	
-	nfnl_fill_hdr(&cth->nfnlh, &req->nlh, 0, l3num, 
+	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);
 
@@ -1221,11 +1271,11 @@
 		nfnl_addattr_l(&req->nlh, sizeof(buf), CTA_EXPECT_ID, &id,
 			       sizeof(u_int32_t));
 	
-	err = nfnl_send(&cth->nfnlh, &req->nlh);
+	err = nfnl_send(cth->nfnlh, &req->nlh);
 	if (err < 0)
 		return err;
 
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 int nfct_event_expectation(struct nfct_handle *cth)
@@ -1237,7 +1287,7 @@
 		return -EPERM;
 
 	cth->handler = nfct_expect_netlink_handler;
-	return nfnl_listen(&cth->nfnlh, &callback_handler, cth);
+	return nfnl_listen(cth->nfnlh, &callback_handler, cth);
 }
 
 int nfct_flush_expectation_table(struct nfct_handle *cth, int family)
@@ -1246,9 +1296,9 @@
 
 	memset(&req, 0, sizeof(req));
 	
-	nfnl_fill_hdr(&cth->nfnlh, (struct nlmsghdr *) &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);
+	return nfnl_talk(cth->nfnlh, &req.nlh, 0, 0, NULL, NULL, NULL);
 }

Modified: trunk/libnetfilter_log/configure.in
===================================================================
--- trunk/libnetfilter_log/configure.in	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_log/configure.in	2006-01-14 19:04:51 UTC (rev 6410)
@@ -4,7 +4,7 @@
 
 AC_CANONICAL_SYSTEM
 
-AM_INIT_AUTOMAKE(libnetfilter_log, 0.0.12)
+AM_INIT_AUTOMAKE(libnetfilter_log, 0.0.13)
 
 AC_PROG_CC
 AM_PROG_LIBTOOL

Modified: trunk/libnetfilter_log/include/libnetfilter_log/libnetfilter_log.h
===================================================================
--- trunk/libnetfilter_log/include/libnetfilter_log/libnetfilter_log.h	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_log/include/libnetfilter_log/libnetfilter_log.h	2006-01-14 19:04:51 UTC (rev 6410)
@@ -25,6 +25,7 @@
 
 
 extern struct nflog_handle *nflog_open(void);
+extern struct nflog_handle *nflog_open_nfnl(struct nfnl_handle *nfnlh);
 extern int nflog_close(struct nflog_handle *h);
 
 extern int nflog_bind_pf(struct nflog_handle *h, u_int16_t pf);

Modified: trunk/libnetfilter_log/src/Makefile.am
===================================================================
--- trunk/libnetfilter_log/src/Makefile.am	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_log/src/Makefile.am	2006-01-14 19:04:51 UTC (rev 6410)
@@ -1,6 +1,6 @@
 # This is _NOT_ the library release version, it's an API version.
 # Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
-LIBVERSION=1:0:0
+LIBVERSION=2:0:1
 
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
 AM_CFLAGS=-fPIC -Wall

Modified: trunk/libnetfilter_log/src/libnetfilter_log.c
===================================================================
--- trunk/libnetfilter_log/src/libnetfilter_log.c	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_log/src/libnetfilter_log.c	2006-01-14 19:04:51 UTC (rev 6410)
@@ -33,7 +33,8 @@
 
 struct nflog_handle
 {
-	struct nfnl_handle nfnlh;
+	struct nfnl_handle *nfnlh;
+	struct nfnl_subsys_handle *nfnlssh;
 	struct nflog_g_handle *gh_list;
 };
 
@@ -94,7 +95,7 @@
 static int __nflog_rcv_cmd(struct nlmsghdr *nlh, struct nfattr *nfa[],
 			    void *data)
 {
-	struct nflog_handle *h = data;
+	/* struct nflog_handle *h = data; */
 
 	/* FIXME: implement this */
 	return 0;
@@ -110,13 +111,13 @@
 	struct nfulnl_msg_config_cmd cmd;
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
-	nfnl_fill_hdr(&h->nfnlh, nmh, 0, pf, queuenum,
+	nfnl_fill_hdr(h->nfnlssh, nmh, 0, pf, queuenum,
 		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	cmd.command = command;
 	nfnl_addattr_l(nmh, sizeof(buf), NFULA_CFG_CMD, &cmd, sizeof(cmd));
 
-	return nfnl_talk(&h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 static int __nflog_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
@@ -152,7 +153,7 @@
 
 struct nfnl_handle *nflog_nfnlh(struct nflog_handle *h)
 {
-	return &h->nfnlh;
+	return h->nfnlh;
 }
 
 int nflog_fd(struct nflog_handle *h)
@@ -160,7 +161,7 @@
 	return nfnl_fd(nflog_nfnlh(h));
 }
 
-struct nflog_handle *nflog_open(void)
+struct nflog_handle *nflog_open_nfnl(struct nfnl_handle *nfnlh)
 {
 	struct nflog_handle *h;
 	int err;
@@ -170,21 +171,23 @@
 		return NULL;
 
 	memset(h, 0, sizeof(*h));
+	h->nfnlh = nfnlh;
 
-	err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_ULOG, NFULNL_MSG_MAX, 0);
-	if (err < 0) {
-		nflog_errno = err;
+	h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_ULOG, 
+				      NFULNL_MSG_MAX, 0);
+	if (!h->nfnlssh) {
+		/* FIXME: nflog_errno */
 		goto out_free;
 	}
 
 	cmd_cb.data = h;
-	err = nfnl_callback_register(&h->nfnlh, NFULNL_MSG_CONFIG, &cmd_cb);
+	err = nfnl_callback_register(h->nfnlssh, NFULNL_MSG_CONFIG, &cmd_cb);
 	if (err < 0) {
 		nflog_errno = err;
 		goto out_close;
 	}
 	pkt_cb.data = h;
-	err = nfnl_callback_register(&h->nfnlh, NFULNL_MSG_PACKET, &pkt_cb);
+	err = nfnl_callback_register(h->nfnlssh, NFULNL_MSG_PACKET, &pkt_cb);
 	if (err < 0) {
 		nflog_errno = err;
 		goto out_close;
@@ -192,12 +195,30 @@
 
 	return h;
 out_close:
-	nfnl_close(&h->nfnlh);
+	nfnl_close(h->nfnlh);
 out_free:
 	free(h);
 	return NULL;
 }
 
+struct nflog_handle *nflog_open(void)
+{
+	struct nfnl_handle *nfnlh;
+	struct nflog_handle *lh;
+
+	nfnlh = nfnl_open();
+	if (!nfnlh) {
+		/* FIXME: nflog_errno */
+		return NULL;
+	}
+
+	lh = nflog_open_nfnl(nfnlh);
+	if (!lh)
+		nfnl_close(nfnlh);
+
+	return lh;
+}
+
 int nflog_callback_register(struct nflog_g_handle *gh, nflog_callback *cb,
 			     void *data)
 {
@@ -209,12 +230,12 @@
 
 int nflog_handle_packet(struct nflog_handle *h, char *buf, int len)
 {
-	return nfnl_handle_packet(&h->nfnlh, buf, len);
+	return nfnl_handle_packet(h->nfnlh, buf, len);
 }
 
 int nflog_close(struct nflog_handle *h)
 {
-	return nfnl_close(&h->nfnlh);
+	return nfnl_close(h->nfnlh);
 }
 
 /* bind nf_queue from a specific protocol family */
@@ -275,7 +296,7 @@
 	struct nfulnl_msg_config_mode params;
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
-	nfnl_fill_hdr(&gh->h->nfnlh, nmh, 0, AF_UNSPEC, gh->id,
+	nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id,
 		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	params.copy_range = htonl(range);	/* copy_range is short */
@@ -283,7 +304,7 @@
 	nfnl_addattr_l(nmh, sizeof(buf), NFULA_CFG_MODE, &params,
 		       sizeof(params));
 
-	return nfnl_talk(&gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 int nflog_set_timeout(struct nflog_g_handle *gh, u_int32_t timeout)
@@ -291,12 +312,12 @@
 	char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(u_int32_t))];
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
-	nfnl_fill_hdr(&gh->h->nfnlh, nmh, 0, AF_UNSPEC, gh->id,
+	nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id,
 		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	nfnl_addattr32(nmh, sizeof(buf), NFULA_CFG_TIMEOUT, htonl(timeout));
 
-	return nfnl_talk(&gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 int nflog_set_qthresh(struct nflog_g_handle *gh, u_int32_t qthresh)
@@ -304,12 +325,12 @@
 	char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(u_int32_t))];
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
-	nfnl_fill_hdr(&gh->h->nfnlh, nmh, 0, AF_UNSPEC, gh->id,
+	nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id,
 		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	nfnl_addattr32(nmh, sizeof(buf), NFULA_CFG_QTHRESH, htonl(qthresh));
 
-	return nfnl_talk(&gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 int nflog_set_nlbufsiz(struct nflog_g_handle *gh, u_int32_t nlbufsiz)
@@ -318,16 +339,16 @@
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 	int status;
 
-	nfnl_fill_hdr(&gh->h->nfnlh, nmh, 0, AF_UNSPEC, gh->id,
+	nfnl_fill_hdr(gh->h->nfnlssh, nmh, 0, AF_UNSPEC, gh->id,
 		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	nfnl_addattr32(nmh, sizeof(buf), NFULA_CFG_NLBUFSIZ, htonl(nlbufsiz));
 
-	status = nfnl_talk(&gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	status = nfnl_talk(gh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 
 	/* we try to have space for at least 10 messages in the socket buffer */
 	if (status >= 0)
-		nfnl_rcvbufsiz(&gh->h->nfnlh, 10*nlbufsiz);
+		nfnl_rcvbufsiz(gh->h->nfnlh, 10*nlbufsiz);
 
 	return status;
 }

Modified: trunk/libnetfilter_queue/configure.in
===================================================================
--- trunk/libnetfilter_queue/configure.in	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_queue/configure.in	2006-01-14 19:04:51 UTC (rev 6410)
@@ -3,7 +3,7 @@
 AC_INIT
 AC_CANONICAL_SYSTEM
 
-AM_INIT_AUTOMAKE(libnetfilter_queue, 0.0.11)
+AM_INIT_AUTOMAKE(libnetfilter_queue, 0.0.12)
 
 AC_PROG_CC
 AC_EXEEXT

Modified: trunk/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue.h
===================================================================
--- trunk/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue.h	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue.h	2006-01-14 19:04:51 UTC (rev 6410)
@@ -32,6 +32,7 @@
 
 
 extern struct nfq_handle *nfq_open(void);
+extern struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh);
 extern int nfq_close(struct nfq_handle *h);
 
 extern int nfq_bind_pf(struct nfq_handle *h, u_int16_t pf);

Modified: trunk/libnetfilter_queue/src/Makefile.am
===================================================================
--- trunk/libnetfilter_queue/src/Makefile.am	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_queue/src/Makefile.am	2006-01-14 19:04:51 UTC (rev 6410)
@@ -1,6 +1,6 @@
 # This is _NOT_ the library release version, it's an API version.
 # Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
-LIBVERSION=1:0:0
+LIBVERSION=2:0:1
 
 INCLUDES = $(all_includes) -I$(top_srcdir)/include -I${KERNELDIR}
 AM_CFLAGS=-fPIC -Wall

Modified: trunk/libnetfilter_queue/src/libnetfilter_queue.c
===================================================================
--- trunk/libnetfilter_queue/src/libnetfilter_queue.c	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnetfilter_queue/src/libnetfilter_queue.c	2006-01-14 19:04:51 UTC (rev 6410)
@@ -31,7 +31,8 @@
 
 struct nfq_handle
 {
-	struct nfnl_handle nfnlh;
+	struct nfnl_handle *nfnlh;
+	struct nfnl_subsys_handle *nfnlssh;
 	struct nfq_q_handle *qh_list;
 };
 
@@ -98,14 +99,14 @@
 	struct nfqnl_msg_config_cmd cmd;
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
-	nfnl_fill_hdr(&h->nfnlh, nmh, 0, AF_UNSPEC, queuenum,
+	nfnl_fill_hdr(h->nfnlssh, nmh, 0, AF_UNSPEC, queuenum,
 			NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	cmd.command = command;
 	cmd.pf = htons(pf);
 	nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_CMD, &cmd, sizeof(cmd));
 
-	return nfnl_talk(&h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
@@ -137,7 +138,7 @@
 
 struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h)
 {
-	return &h->nfnlh;
+	return h->nfnlh;
 }
 
 int nfq_fd(struct nfq_handle *h)
@@ -147,6 +148,21 @@
 
 struct nfq_handle *nfq_open(void)
 {
+	struct nfnl_handle *nfnlh = nfnl_open();
+	struct nfq_handle *qh;
+
+	if (!nfnlh)
+		return NULL;
+
+	qh = nfq_open_nfnl(nfnlh);
+	if (!qh)
+		nfnl_close(nfnlh);
+
+	return qh;
+}
+
+struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
+{
 	struct nfq_handle *h;
 	int err;
 
@@ -156,14 +172,15 @@
 
 	memset(h, 0, sizeof(*h));
 
-	err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, NFQNL_MSG_MAX, 0);
-	if (err < 0) {
-		nfq_errno = err;
+	h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE, 
+				      NFQNL_MSG_MAX, 0);
+	if (!h->nfnlssh) {
+		/* FIXME: nfq_errno */
 		goto out_free;
 	}
 
 	pkt_cb.data = h;
-	err = nfnl_callback_register(&h->nfnlh, NFQNL_MSG_PACKET, &pkt_cb);
+	err = nfnl_callback_register(h->nfnlssh, NFQNL_MSG_PACKET, &pkt_cb);
 	if (err < 0) {
 		nfq_errno = err;
 		goto out_close;
@@ -171,7 +188,7 @@
 
 	return h;
 out_close:
-	nfnl_close(&h->nfnlh);
+	nfnl_subsys_close(h->nfnlssh);
 out_free:
 	free(h);
 	return NULL;
@@ -179,7 +196,10 @@
 
 int nfq_close(struct nfq_handle *h)
 {
-	int ret = nfnl_close(&h->nfnlh);
+	int ret;
+	
+	nfnl_subsys_close(h->nfnlssh);
+	ret = nfnl_close(h->nfnlh);
 	if (ret == 0)
 		free(h);
 	return ret;
@@ -242,7 +262,7 @@
 
 int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
 {
-	return nfnl_handle_packet(&h->nfnlh, buf, len);
+	return nfnl_handle_packet(h->nfnlh, buf, len);
 }
 
 int nfq_set_mode(struct nfq_q_handle *qh,
@@ -253,7 +273,7 @@
 	struct nfqnl_msg_config_params params;
 	struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
 
-	nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
+	nfnl_fill_hdr(qh->h->nfnlssh, nmh, 0, AF_UNSPEC, qh->id,
 			NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
 
 	params.copy_range = htonl(range);
@@ -261,7 +281,7 @@
 	nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, &params,
 			sizeof(params));
 
-	return nfnl_talk(&qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+	return nfnl_talk(qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
 }
 
 static int __set_verdict(struct nfq_q_handle *qh, u_int32_t id,
@@ -282,7 +302,7 @@
 	vh.verdict = htonl(verdict);
 	vh.id = htonl(id);
 
-	nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, qh->id,
+	nfnl_fill_hdr(qh->h->nfnlssh, nmh, 0, AF_UNSPEC, qh->id,
 			NFQNL_MSG_VERDICT, NLM_F_REQUEST);
 
 	/* add verdict header */
@@ -303,7 +323,7 @@
 		nvecs += 2;
 	}
 
-	return nfnl_sendiov(&qh->h->nfnlh, iov, nvecs, 0);
+	return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
 }
 
 int nfq_set_verdict(struct nfq_q_handle *qh, u_int32_t id,

Modified: trunk/libnfnetlink/configure.in
===================================================================
--- trunk/libnfnetlink/configure.in	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnfnetlink/configure.in	2006-01-14 19:04:51 UTC (rev 6410)
@@ -4,7 +4,7 @@
 
 AC_CANONICAL_SYSTEM
 
-AM_INIT_AUTOMAKE(libnfnetlink, 0.0.14)
+AM_INIT_AUTOMAKE(libnfnetlink, 0.0.16)
 
 AC_PROG_CC
 AC_EXEEXT

Modified: trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h
===================================================================
--- trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnfnetlink/include/libnfnetlink/libnfnetlink.h	2006-01-14 19:04:51 UTC (rev 6410)
@@ -43,25 +43,20 @@
 	u_int16_t attr_count;
 };
 
-struct nfnl_handle {
-	int			fd;
-	struct sockaddr_nl	local;
-	struct sockaddr_nl	peer;
-	u_int8_t		subsys_id;
-	u_int32_t		seq;
-	u_int32_t		dump;
-	struct nlmsghdr 	*last_nlhdr;
+struct nfnl_handle;
+struct nfnl_subsys_handle;
 
-	u_int8_t		cb_count;
-	struct nfnl_callback 	*cb;	/* array of callbacks */
-};
-
 extern int nfnl_fd(struct nfnl_handle *h);
 
 /* get a new library handle */
-extern int nfnl_open(struct nfnl_handle *, u_int8_t, u_int8_t, unsigned int);
+extern struct nfnl_handle *nfnl_open(void);
 extern int nfnl_close(struct nfnl_handle *);
 
+extern struct nfnl_subsys_handle *nfnl_subsys_open(struct nfnl_handle *, 
+						   u_int8_t, u_int8_t, 
+						   unsigned int);
+extern void nfnl_subsys_close(struct nfnl_subsys_handle *);
+
 /* sending of data */
 extern int nfnl_send(struct nfnl_handle *, struct nlmsghdr *);
 extern int nfnl_sendmsg(const struct nfnl_handle *, const struct msghdr *msg,
@@ -69,7 +64,7 @@
 extern int nfnl_sendiov(const struct nfnl_handle *nfnlh,
 			const struct iovec *iov, unsigned int num,
 			unsigned int flags);
-extern void nfnl_fill_hdr(struct nfnl_handle *, struct nlmsghdr *,
+extern void nfnl_fill_hdr(struct nfnl_subsys_handle *, struct nlmsghdr *,
 			  unsigned int, u_int8_t, u_int16_t, u_int16_t,
 			  u_int16_t);
 extern int nfnl_talk(struct nfnl_handle *, struct nlmsghdr *, pid_t,
@@ -84,9 +79,9 @@
 
 /* receiving */
 extern ssize_t nfnl_recv(const struct nfnl_handle *h, unsigned char *buf, size_t len);
-extern int nfnl_callback_register(struct nfnl_handle *,
+extern int nfnl_callback_register(struct nfnl_subsys_handle *,
 				  u_int8_t type, struct nfnl_callback *cb);
-extern int nfnl_callback_unregister(struct nfnl_handle *, u_int8_t type);
+extern int nfnl_callback_unregister(struct nfnl_subsys_handle *, u_int8_t type);
 extern int nfnl_handle_packet(struct nfnl_handle *, char *buf, int len);
 
 /* parsing */

Modified: trunk/libnfnetlink/src/Makefile.am
===================================================================
--- trunk/libnfnetlink/src/Makefile.am	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnfnetlink/src/Makefile.am	2006-01-14 19:04:51 UTC (rev 6410)
@@ -1,12 +1,13 @@
-#AUTOMAKE_OPTIONS = no-dependencies foreign
+# This is _NOT_ the library release version, it's an API version.
+# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
+LIBVERSION=1:0:0
 
-#EXTRA_DIST = $(man_MANS) acinclude.m4
-
 INCLUDES = $(all_includes) -I$(top_srcdir)/include
 AM_CFLAGS=-fPIC -Wall
 LIBS=
 
 lib_LTLIBRARIES = libnfnetlink.la
 
-libnfnetlink_la_LDFLAGS = -Wc,-nostartfiles
+libnfnetlink_la_LDFLAGS = -Wc,-nostartfiles	\
+			  -version-info $(LIBVERSION)
 libnfnetlink_la_SOURCES = libnfnetlink.c 

Modified: trunk/libnfnetlink/src/libnfnetlink.c
===================================================================
--- trunk/libnfnetlink/src/libnfnetlink.c	2006-01-13 20:54:52 UTC (rev 6409)
+++ trunk/libnfnetlink/src/libnfnetlink.c	2006-01-14 19:04:51 UTC (rev 6410)
@@ -1,8 +1,9 @@
 /* libnfnetlink.c: generic library for communication with netfilter
  *
- * (C) 2001 by Jay Schulist <jschlst at samba.org>
- * (C) 2002-2005 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2002-2006 by Harald Welte <laforge at gnumonks.org>
  *
+ * Based on some original ideas from Jay Schulist <jschlst at samba.org>
+ *
  * Development of this code funded by Astaro AG (http://www.astaro.com)
  *
  * this software may be used and distributed according to the terms
@@ -12,6 +13,9 @@
  * 	Define structure nfnlhdr
  * 	Added __be64_to_cpu function
  *	Use NFA_TYPE macro to get the attribute type
+ *
+ * 2006-01-14 Harald Welte <laforge at netfilter.org>:
+ * 	introduce nfnl_subsys_handle
  */
 
 #include <stdlib.h>
@@ -36,6 +40,26 @@
 #define nfnl_debug_dump_packet(a, b, ...)
 #endif
 
+struct nfnl_subsys_handle {
+	struct nfnl_handle 	*nfnlh;
+	u_int32_t		subscriptions;
+	u_int8_t		subsys_id;
+	u_int8_t		cb_count;
+	struct nfnl_callback 	*cb;	/* array of callbacks */
+};
+
+#define		NFNL_MAX_SUBSYS			16 /* enough for now */
+struct nfnl_handle {
+	int			fd;
+	struct sockaddr_nl	local;
+	struct sockaddr_nl	peer;
+	u_int32_t		subscriptions;
+	u_int32_t		seq;
+	u_int32_t		dump;
+	struct nlmsghdr 	*last_nlhdr;
+	struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1];
+};
+
 void nfnl_dump_packet(struct nlmsghdr *nlh, int received_len, char *desc)
 {
 	void *nlmsg_data = NLMSG_DATA(nlh);
@@ -65,66 +89,134 @@
 	return h->fd;
 }
 
+static int recalc_rebind_subscriptions(struct nfnl_handle *nfnlh)
+{
+	int i;
+	u_int32_t new_subscriptions = 0;
+
+	for (i = 0; i < NFNL_MAX_SUBSYS; i++)
+		new_subscriptions |= nfnlh->subsys[i].subscriptions;
+
+	if (nfnlh->subscriptions != new_subscriptions) {
+		int err;
+
+		nfnlh->local.nl_groups = new_subscriptions;
+		err = bind(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
+			   sizeof(nfnlh->local));
+		if (err < 0) {
+			nfnl_error("bind(netlink): %s", strerror(errno));
+			return err;
+		}
+		nfnlh->subscriptions = new_subscriptions;
+	}
+
+	return 0;
+}
+
 /**
  * nfnl_open - open a netlink socket
  *
  * nfnlh: libnfnetlink handle to be allocated by user
- * subsys_id: which nfnetlink subsystem we are interested in
- * cb_count: number of callbacks that are used maximum.
- * subscriptions: netlink groups we want to be subscribed to
  *
  */
-int nfnl_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id, 
-	      u_int8_t cb_count, u_int32_t subscriptions)
+struct nfnl_handle *nfnl_open(void)
 {
+	struct nfnl_handle *nfnlh;
+	unsigned int addr_len;
 	int err;
-	unsigned int addr_len;
-	struct nfnl_callback *cb;
 
-	cb = malloc(sizeof(*cb) * cb_count);
-	if (!cb)
-		return -ENOMEM;
-	
+	nfnlh = malloc(sizeof(*nfnlh));
+	if (!nfnlh)
+		return NULL;
+
 	memset(nfnlh, 0, sizeof(*nfnlh));
 	nfnlh->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
 	if (nfnlh->fd < 0) {
 		nfnl_error("socket(netlink): %s", strerror(errno));
-		return nfnlh->fd;
+		goto err_free;
 	}
 
 	nfnlh->local.nl_family = AF_NETLINK;
-	nfnlh->local.nl_groups = subscriptions;
-
 	nfnlh->peer.nl_family = AF_NETLINK;
 
-	err = bind(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
-		   sizeof(nfnlh->local));
-	if (err < 0) {
-		nfnl_error("bind(netlink): %s", strerror(errno));
-		return err;
-	}
-
 	addr_len = sizeof(nfnlh->local);
 	err = getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, 
 			  &addr_len);
 	if (addr_len != sizeof(nfnlh->local)) {
 		nfnl_error("Bad address length (%u != %zd)", addr_len,
 			   sizeof(nfnlh->local));
-		return -1;
+		goto err_close;
 	}
 	if (nfnlh->local.nl_family != AF_NETLINK) {
 		nfnl_error("Bad address family %d", nfnlh->local.nl_family);
-		return -1;
+		goto err_close;
 	}
 	nfnlh->seq = time(NULL);
-	nfnlh->subsys_id = subsys_id;
-	nfnlh->cb_count = cb_count;
-	nfnlh->cb = cb;
 
-	return 0;
+	return nfnlh;
+
+err_close:
+	close(nfnlh->fd);
+err_free:
+	free(nfnlh);
+	return NULL;
 }
 
 /**
+ * nfnl_subsys_open - open a netlink subsystem
+ *
+ * nfnlh: libnfnetlink handle
+ * subsys_id: which nfnetlink subsystem we are interested in
+ * cb_count: number of callbacks that are used maximum.
+ * subscriptions: netlink groups we want to be subscribed to
+ */
+struct nfnl_subsys_handle *
+nfnl_subsys_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
+		 u_int8_t cb_count, u_int32_t subscriptions)
+{
+	struct nfnl_subsys_handle *ssh;
+
+	if (subsys_id > NFNL_MAX_SUBSYS) { 
+
+		return NULL;
+	}
+
+	ssh = &nfnlh->subsys[subsys_id];
+	if (ssh->cb) {
+
+		return NULL;
+	}
+
+	ssh->cb = malloc(sizeof(*(ssh->cb)) * cb_count);
+	if (!ssh->cb) {
+		
+		return NULL;
+	}
+
+	ssh->nfnlh = nfnlh;
+	ssh->cb_count = cb_count;
+	ssh->subscriptions = subscriptions;
+
+	if (recalc_rebind_subscriptions(nfnlh) < 0) {
+		free(ssh->cb);
+		ssh->cb = NULL;
+		return NULL;
+	}
+	
+	return ssh;
+}
+
+void nfnl_subsys_close(struct nfnl_subsys_handle *ssh)
+{
+	ssh->subscriptions = 0;
+	ssh->cb_count = 0;
+	if (ssh->cb) {
+		free(ssh->cb);
+		ssh->cb = NULL;
+	}
+}
+
+/**
  * nfnl_close - close netlink socket
  *
  * nfnlh: libnfnetlink handle
@@ -132,8 +224,18 @@
  */
 int nfnl_close(struct nfnl_handle *nfnlh)
 {
-	free(nfnlh->cb);
-	return close(nfnlh->fd);
+	int i, ret;
+
+	for (i = 0; i < NFNL_MAX_SUBSYS; i++)
+		nfnl_subsys_close(&nfnlh->subsys[i]);
+
+	ret = close(nfnlh->fd);
+	if (ret < 0)
+		return ret;
+
+	free(nfnlh);
+
+	return 0;
 }
 
 /**
@@ -187,7 +289,7 @@
  * the size of struct nlmsghdr + struct nfgenmsg
  *
  */
-void nfnl_fill_hdr(struct nfnl_handle *nfnlh,
+void nfnl_fill_hdr(struct nfnl_subsys_handle *ssh,
 		    struct nlmsghdr *nlh, unsigned int len, 
 		    u_int8_t family,
 		    u_int16_t res_id,
@@ -198,10 +300,10 @@
 					((void *)nlh + sizeof(*nlh));
 
 	nlh->nlmsg_len = NLMSG_LENGTH(len+sizeof(*nfg));
-	nlh->nlmsg_type = (nfnlh->subsys_id<<8)|msg_type;
+	nlh->nlmsg_type = (ssh->subsys_id<<8)|msg_type;
 	nlh->nlmsg_flags = msg_flags;
 	nlh->nlmsg_pid = 0;
-	nlh->nlmsg_seq = ++nfnlh->seq;
+	nlh->nlmsg_seq = ++ssh->nfnlh->seq;
 
 	nfg->nfgen_family = family;
 	nfg->version = NFNETLINK_V0;
@@ -693,23 +795,23 @@
 	return nlh;
 }
 
-int nfnl_callback_register(struct nfnl_handle *h,
+int nfnl_callback_register(struct nfnl_subsys_handle *ssh,
 			   u_int8_t type, struct nfnl_callback *cb)
 {
-	if (type >= h->cb_count)
+	if (type >= ssh->cb_count)
 		return -EINVAL;
 
-	memcpy(&h->cb[type], cb, sizeof(*cb));
+	memcpy(&ssh->cb[type], cb, sizeof(*cb));
 
 	return 0;
 }
 
-int nfnl_callback_unregister(struct nfnl_handle *h, u_int8_t type)
+int nfnl_callback_unregister(struct nfnl_subsys_handle *ssh, u_int8_t type)
 {
-	if (type >= h->cb_count)
+	if (type >= ssh->cb_count)
 		return -EINVAL;
 
-	h->cb[type].call = NULL;
+	ssh->cb[type].call = NULL;
 
 	return 0;
 }
@@ -720,12 +822,20 @@
 {
 	int min_len;
 	u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
-	struct nfnl_callback *cb = &h->cb[type];
+	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type);
+	const struct nfnl_subsys_handle *ssh;
+	struct nfnl_callback *cb;
 
+	if (subsys_id > NFNL_MAX_SUBSYS)
+		return -EINVAL;
+
+	ssh = &h->subsys[subsys_id];
+ 	cb = &ssh->cb[type];
+
 #if 1
 	/* checks need to be enabled as soon as this is called from
 	 * somebody else than __nfnl_handle_msg */
-	if (type >= h->cb_count)
+	if (type >= ssh->cb_count)
 		return -EINVAL;
 
 	min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg));
@@ -755,26 +865,30 @@
 static int __nfnl_handle_msg(struct nfnl_handle *h, struct nlmsghdr *nlh,
 			     int len)
 {
+	struct nfnl_subsys_handle *ssh;
 	u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
+	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type);
 	int err = 0;
 
-	if (NFNL_SUBSYS_ID(nlh->nlmsg_type) != h->subsys_id)
+	if (subsys_id > NFNL_MAX_SUBSYS)
 		return -1;
 
+	ssh = &h->subsys[subsys_id];
+
 	if (nlh->nlmsg_len < NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
 		return -1;
 
-	if (type >= h->cb_count)
+	if (type >= ssh->cb_count)
 		return -1;
 
-	if (h->cb[type].attr_count) {
-		struct nfattr *nfa[h->cb[type].attr_count];
+	if (ssh->cb[type].attr_count) {
+		struct nfattr *nfa[ssh->cb[type].attr_count];
 
 		err = nfnl_check_attributes(h, nlh, nfa);
 		if (err < 0)
 			return err;
-		if (h->cb[type].call)
-			return h->cb[type].call(nlh, nfa, h->cb[type].data);
+		if (ssh->cb[type].call)
+			return ssh->cb[type].call(nlh, nfa, ssh->cb[type].data);
 	}
 	return 0;
 }




More information about the netfilter-cvslog mailing list