diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-06-29 02:15:22 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-29 19:46:06 -0400 |
commit | 03292745b02d1166e2a215504407e096b8427be5 (patch) | |
tree | 2251b4bed9969a6c8a02a322927a74621b29155c /net/netlink | |
parent | a31f2d17b331db970259e875b7223d3aba7e3821 (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/netlink')
-rw-r--r-- | net/netlink/af_netlink.c | 19 |
1 files changed, 19 insertions, 0 deletions
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; | ||
486 | out: | 491 | out: |
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); |