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) --- include/libnfnetlink/linux_nfnetlink.h | 8 +++-- src/libnfnetlink.c | 56 ++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/include/libnfnetlink/linux_nfnetlink.h b/include/libnfnetlink/linux_nfnetlink.h index f08e870..934a247 100644 --- a/include/libnfnetlink/linux_nfnetlink.h +++ b/include/libnfnetlink/linux_nfnetlink.h @@ -112,7 +112,6 @@ struct nfnl_callback { int (*call)(struct sock *nl, struct sk_buff *skb, struct nlmsghdr *nlh, struct nfattr *cda[], int *errp); - kernel_cap_t cap_required; /* capabilities required for this msg */ u_int16_t attr_count; /* number of nfattr's */ }; @@ -146,7 +145,7 @@ extern void nfnl_unlock(void); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); -extern int nfattr_parse(struct nfattr *tb[], int maxattr, +extern void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len); #define nfattr_parse_nested(tb, max, nfa) \ @@ -154,11 +153,14 @@ extern int nfattr_parse(struct nfattr *tb[], int maxattr, #define nfattr_bad_size(tb, max, cta_min) \ ({ int __i, __res = 0; \ - for (__i=0; __i #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