summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
author/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org>2006-01-26 09:28:47 +0000
committer/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org>2006-01-26 09:28:47 +0000
commit8f076cfcad17e3590302c8831f83b216fb255ec6 (patch)
treefe82f93407ea0bb7a5e9f0f9c775ea74c132e4ce /src
parent0455f4ffb3557036089d1f71bb013297ddcb9286 (diff)
fix logic for using one socket for multiple subsystems to be compatible with
multiple nfnetlink sockets per process (pid overlap)
Diffstat (limited to 'src')
-rw-r--r--src/libnfnetlink.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/src/libnfnetlink.c b/src/libnfnetlink.c
index def45fb..5765072 100644
--- a/src/libnfnetlink.c
+++ b/src/libnfnetlink.c
@@ -33,8 +33,19 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <linux/netlink.h>
+
#include <libnfnetlink/libnfnetlink.h>
+#ifndef NETLINK_ADD_MEMBERSHIP
+#define NETLINK_ADD_MEMBERSHIP 1
+#endif
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+
#define nfnl_error(format, args...) \
fprintf(stderr, "%s: " format "\n", __FUNCTION__, ## args)
@@ -95,25 +106,23 @@ int nfnl_fd(struct nfnl_handle *h)
static int recalc_rebind_subscriptions(struct nfnl_handle *nfnlh)
{
- int i;
- u_int32_t new_subscriptions = 0;
+ int i, err;
+ u_int32_t new_subscriptions = nfnlh->subscriptions;
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;
+ 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;
}
@@ -156,10 +165,23 @@ struct nfnl_handle *nfnl_open(void)
goto err_close;
}
nfnlh->seq = time(NULL);
- /*
- * nfnl_talk checks: h->nlmsg_pid != nfnlh->local.nl_pid
- */
- nfnlh->local.nl_pid = getpid();
+
+ /* don't set pid here, only first socket of process has real pid !!!
+ * binding to pid '0' will default */
+
+ /* let us do the initial bind */
+ if (recalc_rebind_subscriptions(nfnlh) < 0)
+ goto err_close;
+
+ /* use getsockname to get the netlink pid that the kernel assigned us */
+ 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));
+ goto err_close;
+ }
return nfnlh;
@@ -206,6 +228,8 @@ nfnl_subsys_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
ssh->subscriptions = subscriptions;
ssh->subsys_id = subsys_id;
+ /* FIXME: reimplement this based on
+ * setsockopt(nfnlh->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,,) */
if (recalc_rebind_subscriptions(nfnlh) < 0) {
free(ssh->cb);
ssh->cb = NULL;