* [PATCH] iftable: make library thread-safe.
2009-04-28 21:45 [RFC] make thread-safe iface resolution in libnfnetlink Eric Leblond
@ 2009-04-28 21:45 ` Eric Leblond
2009-04-29 0:01 ` [RFC] make thread-safe iface resolution in libnfnetlink Pablo Neira Ayuso
1 sibling, 0 replies; 4+ messages in thread
From: Eric Leblond @ 2009-04-28 21:45 UTC (permalink / raw)
To: pablo, kaber; +Cc: netfilter-devel, Eric Leblond
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@inl.fr>
---
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
^ permalink raw reply related [flat|nested] 4+ messages in thread