[PATCH] iftable: make library thread-safe.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds some locking on the interface hash to make libnfnetlink
thread-safe. The interface hash could be accessed via nlif_index2name()
function and modified simultaneously via event treatment.

This introduces a depedencies on libpthread. Thus, the compilation
tools have been modified.

Signed-off-by: Eric Leblond <eric@xxxxxx>
---
 configure.in                        |    2 ++
 include/libnfnetlink/libnfnetlink.h |    2 +-
 src/Makefile.am                     |    2 +-
 src/iftable.c                       |   26 ++++++++++++++++++++++++--
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/configure.in b/configure.in
index f760cd0..9febde0 100644
--- a/configure.in
+++ b/configure.in
@@ -11,6 +11,8 @@ AC_EXEEXT
 AM_PROG_LIBTOOL
 AC_SUBST(LIBTOOL_DEPS)
 
+AC_CHECK_LIB([pthread], [pthread_mutex_init])
+
 case $target in 
 *-*-linux*) ;;
 *) AC_MSG_ERROR([Linux only, dude!]);;
diff --git a/include/libnfnetlink/libnfnetlink.h b/include/libnfnetlink/libnfnetlink.h
index f689ab0..7984c08 100644
--- a/include/libnfnetlink/libnfnetlink.h
+++ b/include/libnfnetlink/libnfnetlink.h
@@ -209,7 +209,7 @@ int nlif_catch(struct nlif_handle *nlif_handle);
 int nlif_index2name(struct nlif_handle *nlif_handle, 
 		    unsigned int if_index, 
 		    char *name);
-int nlif_get_ifflags(const struct nlif_handle *h,
+int nlif_get_ifflags(struct nlif_handle *h,
 		     unsigned int index,
 		     unsigned int *flags);
 
diff --git a/src/Makefile.am b/src/Makefile.am
index cc400b9..68301af 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,7 +6,7 @@ LIBS=
 lib_LTLIBRARIES = libnfnetlink.la
 
 libnfnetlink_la_LDFLAGS = -Wc,-nostartfiles	\
-			  -version-info $(LIBVERSION)
+			  -version-info $(LIBVERSION) -lpthread
 libnfnetlink_la_SOURCES = libnfnetlink.c iftable.c rtnl.c
 
 noinst_HEADERS = iftable.h rtnl.h
diff --git a/src/iftable.c b/src/iftable.c
index f316217..7dc5d27 100644
--- a/src/iftable.c
+++ b/src/iftable.c
@@ -17,6 +17,7 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <assert.h>
+#include <pthread.h>
 
 #include <linux/netdevice.h>
 
@@ -40,6 +41,7 @@ struct nlif_handle {
 	struct rtnl_handle *rtnl_handle;
 	struct rtnl_handler ifadd_handler;
 	struct rtnl_handler ifdel_handler;
+	pthread_mutex_t mutex;
 };
 
 /* iftable_add - Add/Update an entry to/in the interface table
@@ -69,6 +71,7 @@ static int iftable_add(struct nlmsghdr *n, void *arg)
 		return -1;
 
 	hash = ifi_msg->ifi_index & 0xF;
+	pthread_mutex_lock(&(h->mutex));
 	list_for_each_entry(this, &h->ifindex_hash[hash], head) {
 		if (this->index == ifi_msg->ifi_index) {
 			found = 1;
@@ -78,8 +81,10 @@ static int iftable_add(struct nlmsghdr *n, void *arg)
 
 	if (!found) {
 		this = malloc(sizeof(*this));
-		if (!this)
+		if (!this) {
+			pthread_mutex_unlock(&(h->mutex));
 			return -1;
+		}
 
 		this->index = ifi_msg->ifi_index;
 	}
@@ -101,6 +106,8 @@ static int iftable_add(struct nlmsghdr *n, void *arg)
 	if (!found)
 		list_add(&this->head, &h->ifindex_hash[hash]);
 
+	pthread_mutex_unlock(&(h->mutex));
+
 	return 1;
 }
 
@@ -128,13 +135,16 @@ static int iftable_del(struct nlmsghdr *n, void *arg)
 	rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
 
 	hash = ifi_msg->ifi_index & 0xF;
+	pthread_mutex_lock(&(h->mutex));
 	list_for_each_entry_safe(this, tmp, &h->ifindex_hash[hash], head) {
 		if (this->index == ifi_msg->ifi_index) {
 			list_del(&this->head);
 			free(this);
+			pthread_mutex_unlock(&(h->mutex));
 			return 1;
 		}
 	}
+	pthread_mutex_unlock(&(h->mutex));
 
 	return 0;
 }
@@ -162,12 +172,15 @@ int nlif_index2name(struct nlif_handle *h,
 	}
 
 	hash = index & 0xF;
+	pthread_mutex_lock(&(h->mutex));
 	list_for_each_entry(this, &h->ifindex_hash[hash], head) {
 		if (this->index == index) {
 			strcpy(name, this->name);
+			pthread_mutex_unlock(&(h->mutex));
 			return 1;
 		}
 	}
+	pthread_mutex_unlock(&(h->mutex));
 
 	errno = ENOENT;
 	return -1;
@@ -180,7 +193,7 @@ int nlif_index2name(struct nlif_handle *h,
  * \param flags pointer to variable used to store the interface flags
  * \return -1 on error, 1 on success 
  */
-int nlif_get_ifflags(const struct nlif_handle *h,
+int nlif_get_ifflags(struct nlif_handle *h,
 		     unsigned int index,
 		     unsigned int *flags)
 {
@@ -196,12 +209,15 @@ int nlif_get_ifflags(const struct nlif_handle *h,
 	}
 
 	hash = index & 0xF;
+	pthread_mutex_lock(&(h->mutex));
 	list_for_each_entry(this, &h->ifindex_hash[hash], head) {
 		if (this->index == index) {
 			*flags = this->flags;
+			pthread_mutex_unlock(&(h->mutex));
 			return 1;
 		}
 	}
+	pthread_mutex_unlock(&(h->mutex));
 	errno = ENOENT;
 	return -1;
 }
@@ -232,6 +248,8 @@ struct nlif_handle *nlif_open(void)
 	h->ifdel_handler.handlefn = iftable_del;
 	h->ifdel_handler.arg = h;
 
+	pthread_mutex_init(&(h->mutex), NULL);
+
 	h->rtnl_handle = rtnl_open();
 	if (h->rtnl_handle == NULL)
 		goto err;
@@ -269,12 +287,16 @@ void nlif_close(struct nlif_handle *h)
 	rtnl_handler_unregister(h->rtnl_handle, &h->ifdel_handler);
 	rtnl_close(h->rtnl_handle);
 
+	pthread_mutex_lock(&(h->mutex));
 	for (i=0; i<16; i++) {
 		list_for_each_entry_safe(this, tmp, &h->ifindex_hash[i], head) {
 			list_del(&this->head);
 			free(this);
 		}
 	}
+	pthread_mutex_unlock(&(h->mutex));
+
+	pthread_mutex_destroy(&(h->mutex));
 
 	free(h);
 	h = NULL; /* bugtrap */
-- 
1.6.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux