[netfilter-cvslog] r3629 - trunk/iptables/libiptc

laforge at netfilter.org laforge at netfilter.org
Tue Feb 1 14:28:15 CET 2005


Author: laforge at netfilter.org
Date: 2005-02-01 14:28:14 +0100 (Tue, 01 Feb 2005)
New Revision: 3629

Modified:
   trunk/iptables/libiptc/libiptc.c
Log:
- Sets the 'iptc_fn' global variable to the pointer to the current functions in all major TC_* functions. This is necessary because in certain cases, an error return from a function that doesn't set 'iptc_fn' will conflict with a function-specific error return from one that does, causing TC_STRERROR() to return the wrong error string. This ensures that the right one will be returned.
- Implements a simple reference counter for the netlink socket global variable 'sockfd'; this is necessary for IPTables::IPv4, where multiple tables (filter, nat, mangle, untracked) may be opened at one time. The way libiptc does it in the official version causes previously-opened tables to break such that attempts to commit changes will fail.
- Adds a couple of memset() invocations in TC_COMMIT, based on past analysis with valgrind. It claimed that allocated structure were not being fully initialized, and adding the memset()s corrected this warning.       
(Derrik Pates <demon at devrandom.net>)


Modified: trunk/iptables/libiptc/libiptc.c
===================================================================
--- trunk/iptables/libiptc/libiptc.c	2005-02-01 13:23:01 UTC (rev 3628)
+++ trunk/iptables/libiptc/libiptc.c	2005-02-01 13:28:14 UTC (rev 3629)
@@ -45,6 +45,7 @@
 #endif
 
 static int sockfd = -1;
+static int sockfd_use = 0;
 static void *iptc_fn = NULL;
 
 static const char *hooknames[]
@@ -788,33 +789,38 @@
 
 	iptc_fn = TC_INIT;
 
-	if (sockfd != -1) {
-		close(sockfd);
-		sockfd = -1;
-	}
-
 	if (strlen(tablename) >= TABLE_MAXNAMELEN) {
 		errno = EINVAL;
 		return NULL;
 	}
 	
-	sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
-	if (sockfd < 0)
-		return NULL;
+	if (sockfd_use == 0) {
+		sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
+		if (sockfd < 0)
+			return NULL;
+	}
+	sockfd_use++;
 
 	s = sizeof(info);
 
 	strcpy(info.name, tablename);
-	if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0)
+	if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) {
+		if (--sockfd_use == 0) {
+			close(sockfd);
+			sockfd = -1;
+		}
 		return NULL;
+	}
 
 	DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n",
 		info.valid_hooks, info.num_entries, info.size);
 
 	if ((h = alloc_handle(info.name, info.size, info.num_entries))
 	    == NULL) {
-		close(sockfd);
-		sockfd = -1;
+		if (--sockfd_use == 0) {
+			close(sockfd);
+			sockfd = -1;
+		}
 		return NULL;
 	}
 
@@ -846,6 +852,10 @@
 	CHECK(h);
 	return h;
 error:
+	if (--sockfd_use == 0) {
+		close(sockfd);
+		sockfd = -1;
+	}
 	TC_FREE(&h);
 	return NULL;
 }
@@ -855,8 +865,11 @@
 {
 	struct chain_head *c, *tmp;
 
-	close(sockfd);
-	sockfd = -1;
+	iptc_fn = TC_FREE;
+	if (--sockfd_use == 0) {
+		close(sockfd);
+		sockfd = -1;
+	}
 
 	list_for_each_entry_safe(c, tmp, &(*h)->chains, list) {
 		struct rule_head *r, *rtmp;
@@ -886,6 +899,7 @@
 void
 TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
 {
+	iptc_fn = TC_DUMP_ENTRIES;
 	CHECK(handle);
 #if 0
 	printf("libiptc v%s. %u bytes.\n",
@@ -912,6 +926,7 @@
 /* Does this chain exist? */
 int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle)
 {
+	iptc_fn = TC_IS_CHAIN;
 	return iptcc_find_label(chain, handle) != NULL;
 }
 
@@ -1003,6 +1018,7 @@
 {
 	struct rule_head *r;
 
+	iptc_fn = TC_NEXT_RULE;
 	DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur);
 
 	if (!(*handle)->rule_iterator_cur) {
@@ -1576,6 +1592,7 @@
 		STRUCT_ENTRY *entry,
 		TC_HANDLE_T *handle)
 {
+	iptc_fn = TC_CHECK_PACKET;
 	errno = ENOSYS;
 	return NULL;
 }
@@ -1611,6 +1628,7 @@
 	struct chain_head *c;
 	struct rule_head *r;
 
+	iptc_fn = TC_ZERO_ENTRIES;
 	if (!(c = iptcc_find_label(chain, *handle))) {
 		errno = ENOENT;
 		return 0;
@@ -1763,6 +1781,7 @@
 {
 	struct chain_head *c;
 
+	iptc_fn = TC_GET_REFERENCES;
 	if (!(c = iptcc_find_label(chain, *handle))) {
 		errno = ENOENT;
 		return 0;
@@ -1991,6 +2010,7 @@
 	int new_number;
 	unsigned int new_size;
 
+	iptc_fn = TC_COMMIT;
 	CHECK(*handle);
 
 	/* Don't commit if nothing changed. */
@@ -2016,6 +2036,7 @@
 
 	counterlen = sizeof(STRUCT_COUNTERS_INFO)
 			+ sizeof(STRUCT_COUNTERS) * new_number;
+	memset(repl, 0, sizeof(*repl) + (*handle)->entries->size);
 
 	/* These are the old counters we will get from kernel */
 	repl->counters = malloc(sizeof(STRUCT_COUNTERS)
@@ -2025,6 +2046,8 @@
 		errno = ENOMEM;
 		return 0;
 	}
+	memset(repl->counters, 0, sizeof(STRUCT_COUNTERS)
+			* (*handle)->info.num_entries);
 	/* These are the counters we're going to put back, later. */
 	newcounters = malloc(counterlen);
 	if (!newcounters) {




More information about the netfilter-cvslog mailing list