aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-06-29 02:15:22 -0400
committerDavid S. Miller <davem@davemloft.net>2012-06-29 19:46:06 -0400
commit03292745b02d1166e2a215504407e096b8427be5 (patch)
tree2251b4bed9969a6c8a02a322927a74621b29155c /net
parenta31f2d17b331db970259e875b7223d3aba7e3821 (diff)
netlink: add nlk->netlink_bind hook for module auto-loading
This patch adds a hook in the binding path of netlink. This is used by ctnetlink to allow module autoloading for the case in which one user executes: conntrack -E So far, this resulted in nfnetlink loaded, but not nf_conntrack_netlink. I have received in the past many complains on this behaviour. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nfnetlink.c29
-rw-r--r--net/netlink/af_netlink.c19
2 files changed, 48 insertions, 0 deletions
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 700e4616a098..5a2132b97fe9 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -39,6 +39,15 @@ static char __initdata nfversion[] = "0.30";
39static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT]; 39static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT];
40static DEFINE_MUTEX(nfnl_mutex); 40static DEFINE_MUTEX(nfnl_mutex);
41 41
42static const int nfnl_group2type[NFNLGRP_MAX+1] = {
43 [NFNLGRP_CONNTRACK_NEW] = NFNL_SUBSYS_CTNETLINK,
44 [NFNLGRP_CONNTRACK_UPDATE] = NFNL_SUBSYS_CTNETLINK,
45 [NFNLGRP_CONNTRACK_DESTROY] = NFNL_SUBSYS_CTNETLINK,
46 [NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP,
47 [NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP,
48 [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
49};
50
42void nfnl_lock(void) 51void nfnl_lock(void)
43{ 52{
44 mutex_lock(&nfnl_mutex); 53 mutex_lock(&nfnl_mutex);
@@ -200,12 +209,32 @@ static void nfnetlink_rcv(struct sk_buff *skb)
200 netlink_rcv_skb(skb, &nfnetlink_rcv_msg); 209 netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
201} 210}
202 211
212#ifdef CONFIG_MODULES
213static void nfnetlink_bind(int group)
214{
215 const struct nfnetlink_subsystem *ss;
216 int type = nfnl_group2type[group];
217
218 rcu_read_lock();
219 ss = nfnetlink_get_subsys(type);
220 if (!ss) {
221 rcu_read_unlock();
222 request_module("nfnetlink-subsys-%d", type);
223 return;
224 }
225 rcu_read_unlock();
226}
227#endif
228
203static int __net_init nfnetlink_net_init(struct net *net) 229static int __net_init nfnetlink_net_init(struct net *net)
204{ 230{
205 struct sock *nfnl; 231 struct sock *nfnl;
206 struct netlink_kernel_cfg cfg = { 232 struct netlink_kernel_cfg cfg = {
207 .groups = NFNLGRP_MAX, 233 .groups = NFNLGRP_MAX,
208 .input = nfnetlink_rcv, 234 .input = nfnetlink_rcv,
235#ifdef CONFIG_MODULES
236 .bind = nfnetlink_bind,
237#endif
209 }; 238 };
210 239
211 nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, THIS_MODULE, &cfg); 240 nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, THIS_MODULE, &cfg);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 43a124feaad8..5463969da45b 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -80,6 +80,7 @@ struct netlink_sock {
80 struct mutex *cb_mutex; 80 struct mutex *cb_mutex;
81 struct mutex cb_def_mutex; 81 struct mutex cb_def_mutex;
82 void (*netlink_rcv)(struct sk_buff *skb); 82 void (*netlink_rcv)(struct sk_buff *skb);
83 void (*netlink_bind)(int group);
83 struct module *module; 84 struct module *module;
84}; 85};
85 86
@@ -124,6 +125,7 @@ struct netlink_table {
124 unsigned int groups; 125 unsigned int groups;
125 struct mutex *cb_mutex; 126 struct mutex *cb_mutex;
126 struct module *module; 127 struct module *module;
128 void (*bind)(int group);
127 int registered; 129 int registered;
128}; 130};
129 131
@@ -444,6 +446,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
444 struct module *module = NULL; 446 struct module *module = NULL;
445 struct mutex *cb_mutex; 447 struct mutex *cb_mutex;
446 struct netlink_sock *nlk; 448 struct netlink_sock *nlk;
449 void (*bind)(int group);
447 int err = 0; 450 int err = 0;
448 451
449 sock->state = SS_UNCONNECTED; 452 sock->state = SS_UNCONNECTED;
@@ -468,6 +471,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
468 else 471 else
469 err = -EPROTONOSUPPORT; 472 err = -EPROTONOSUPPORT;
470 cb_mutex = nl_table[protocol].cb_mutex; 473 cb_mutex = nl_table[protocol].cb_mutex;
474 bind = nl_table[protocol].bind;
471 netlink_unlock_table(); 475 netlink_unlock_table();
472 476
473 if (err < 0) 477 if (err < 0)
@@ -483,6 +487,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
483 487
484 nlk = nlk_sk(sock->sk); 488 nlk = nlk_sk(sock->sk);
485 nlk->module = module; 489 nlk->module = module;
490 nlk->netlink_bind = bind;
486out: 491out:
487 return err; 492 return err;
488 493
@@ -683,6 +688,15 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
683 netlink_update_listeners(sk); 688 netlink_update_listeners(sk);
684 netlink_table_ungrab(); 689 netlink_table_ungrab();
685 690
691 if (nlk->netlink_bind && nlk->groups[0]) {
692 int i;
693
694 for (i=0; i<nlk->ngroups; i++) {
695 if (test_bit(i, nlk->groups))
696 nlk->netlink_bind(i);
697 }
698 }
699
686 return 0; 700 return 0;
687} 701}
688 702
@@ -1239,6 +1253,10 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
1239 netlink_update_socket_mc(nlk, val, 1253 netlink_update_socket_mc(nlk, val,
1240 optname == NETLINK_ADD_MEMBERSHIP); 1254 optname == NETLINK_ADD_MEMBERSHIP);
1241 netlink_table_ungrab(); 1255 netlink_table_ungrab();
1256
1257 if (nlk->netlink_bind)
1258 nlk->netlink_bind(val);
1259
1242 err = 0; 1260 err = 0;
1243 break; 1261 break;
1244 } 1262 }
@@ -1559,6 +1577,7 @@ netlink_kernel_create(struct net *net, int unit,
1559 rcu_assign_pointer(nl_table[unit].listeners, listeners); 1577 rcu_assign_pointer(nl_table[unit].listeners, listeners);
1560 nl_table[unit].cb_mutex = cb_mutex; 1578 nl_table[unit].cb_mutex = cb_mutex;
1561 nl_table[unit].module = module; 1579 nl_table[unit].module = module;
1580 nl_table[unit].bind = cfg ? cfg->bind : NULL;
1562 nl_table[unit].registered = 1; 1581 nl_table[unit].registered = 1;
1563 } else { 1582 } else {
1564 kfree(listeners); 1583 kfree(listeners);