From 8f076cfcad17e3590302c8831f83b216fb255ec6 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Thu, 26 Jan 2006 09:28:47 +0000 Subject: fix logic for using one socket for multiple subsystems to be compatible with multiple nfnetlink sockets per process (pid overlap) --- src/libnfnetlink.c | 56 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'src/libnfnetlink.c') 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 #include +#include + #include +#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; -- cgit v1.2.3