aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-08-09 22:40:55 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:35:08 -0400
commit4fdb3bb723db469717c6d38fda667d8b0fa86ebd (patch)
tree43d82e717922e6319cf8a8f9dc5ee902c651b491 /net
parent020b4c12dbe3868d792a01d7c1470cd837abe10f (diff)
[NETLINK]: Add properly module refcounting for kernel netlink sockets.
- Remove bogus code for compiling netlink as module - Add module refcounting support for modules implementing a netlink protocol - Add support for autoloading modules that implement a netlink protocol as soon as someone opens a socket for that protocol Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/netfilter/ebt_ulog.c2
-rw-r--r--net/core/rtnetlink.c2
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c4
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/netfilter/ip_queue.c3
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c3
-rw-r--r--net/ipv4/tcp_diag.c3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/netfilter/nfnetlink.c5
-rw-r--r--net/netlink/af_netlink.c108
-rw-r--r--net/xfrm/xfrm_user.c4
11 files changed, 107 insertions, 31 deletions
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 01af4fcef26d..561d75c8ed5a 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -258,7 +258,7 @@ static int __init init(void)
258 spin_lock_init(&ulog_buffers[i].lock); 258 spin_lock_init(&ulog_buffers[i].lock);
259 } 259 }
260 260
261 ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL); 261 ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL, THIS_MODULE);
262 if (!ebtulognl) 262 if (!ebtulognl)
263 ret = -ENOMEM; 263 ret = -ENOMEM;
264 else if ((ret = ebt_register_watcher(&ulog))) 264 else if ((ret = ebt_register_watcher(&ulog)))
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4b1bb30e6381..9b3c61f1a37d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -708,7 +708,7 @@ void __init rtnetlink_init(void)
708 if (!rta_buf) 708 if (!rta_buf)
709 panic("rtnetlink_init: cannot allocate rta_buf\n"); 709 panic("rtnetlink_init: cannot allocate rta_buf\n");
710 710
711 rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv); 711 rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv, THIS_MODULE);
712 if (rtnl == NULL) 712 if (rtnl == NULL)
713 panic("rtnetlink_init: cannot initialize rtnetlink\n"); 713 panic("rtnetlink_init: cannot initialize rtnetlink\n");
714 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); 714 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 284a9998e53d..3068fddb2da3 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -138,7 +138,8 @@ static int __init init(void)
138{ 138{
139 int rv = 0; 139 int rv = 0;
140 140
141 dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk); 141 dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk,
142 THIS_MODULE);
142 if (dnrmg == NULL) { 143 if (dnrmg == NULL) {
143 printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); 144 printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
144 return -ENOMEM; 145 return -ENOMEM;
@@ -162,6 +163,7 @@ static void __exit fini(void)
162MODULE_DESCRIPTION("DECnet Routing Message Grabulator"); 163MODULE_DESCRIPTION("DECnet Routing Message Grabulator");
163MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>"); 164MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>");
164MODULE_LICENSE("GPL"); 165MODULE_LICENSE("GPL");
166MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
165 167
166module_init(init); 168module_init(init);
167module_exit(fini); 169module_exit(fini);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index e5722084239b..b5e2f1550c91 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -567,7 +567,7 @@ static void nl_fib_input(struct sock *sk, int len)
567 567
568static void nl_fib_lookup_init(void) 568static void nl_fib_lookup_init(void)
569{ 569{
570 netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input); 570 netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input, THIS_MODULE);
571} 571}
572 572
573static void fib_disable_ip(struct net_device *dev, int force) 573static void fib_disable_ip(struct net_device *dev, int force)
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index ae975ac59c6a..b237f7fcad92 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -692,7 +692,8 @@ init_or_cleanup(int init)
692 goto cleanup; 692 goto cleanup;
693 693
694 netlink_register_notifier(&ipq_nl_notifier); 694 netlink_register_notifier(&ipq_nl_notifier);
695 ipqnl = netlink_kernel_create(NETLINK_FIREWALL, ipq_rcv_sk); 695 ipqnl = netlink_kernel_create(NETLINK_FIREWALL, ipq_rcv_sk,
696 THIS_MODULE);
696 if (ipqnl == NULL) { 697 if (ipqnl == NULL) {
697 printk(KERN_ERR "ip_queue: failed to create netlink socket\n"); 698 printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
698 goto cleanup_netlink_notifier; 699 goto cleanup_netlink_notifier;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 52a0076302a7..4ea8371ab270 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -62,6 +62,7 @@
62MODULE_LICENSE("GPL"); 62MODULE_LICENSE("GPL");
63MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 63MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
64MODULE_DESCRIPTION("iptables userspace logging module"); 64MODULE_DESCRIPTION("iptables userspace logging module");
65MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
65 66
66#define ULOG_NL_EVENT 111 /* Harald's favorite number */ 67#define ULOG_NL_EVENT 111 /* Harald's favorite number */
67#define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ 68#define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */
@@ -372,7 +373,7 @@ static int __init init(void)
372 ulog_buffers[i].timer.data = i; 373 ulog_buffers[i].timer.data = i;
373 } 374 }
374 375
375 nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL); 376 nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL, THIS_MODULE);
376 if (!nflognl) 377 if (!nflognl)
377 return -ENOMEM; 378 return -ENOMEM;
378 379
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index f66945cb158f..f79bd11a4701 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -774,7 +774,8 @@ static void tcpdiag_rcv(struct sock *sk, int len)
774 774
775static int __init tcpdiag_init(void) 775static int __init tcpdiag_init(void)
776{ 776{
777 tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv); 777 tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv,
778 THIS_MODULE);
778 if (tcpnl == NULL) 779 if (tcpnl == NULL)
779 return -ENOMEM; 780 return -ENOMEM;
780 return 0; 781 return 0;
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 7130603a32c5..1c3d247a22cc 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -685,7 +685,7 @@ init_or_cleanup(int init)
685 goto cleanup; 685 goto cleanup;
686 686
687 netlink_register_notifier(&ipq_nl_notifier); 687 netlink_register_notifier(&ipq_nl_notifier);
688 ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk); 688 ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk, THIS_MODULE);
689 if (ipqnl == NULL) { 689 if (ipqnl == NULL) {
690 printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); 690 printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
691 goto cleanup_netlink_notifier; 691 goto cleanup_netlink_notifier;
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index b0ed57981847..6210ca42166c 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -38,6 +38,8 @@
38#include <linux/netfilter/nfnetlink.h> 38#include <linux/netfilter/nfnetlink.h>
39 39
40MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
41MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
42MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
41 43
42static char __initdata nfversion[] = "0.30"; 44static char __initdata nfversion[] = "0.30";
43 45
@@ -324,7 +326,8 @@ int __init nfnetlink_init(void)
324{ 326{
325 printk("Netfilter messages via NETLINK v%s.\n", nfversion); 327 printk("Netfilter messages via NETLINK v%s.\n", nfversion);
326 328
327 nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv); 329 nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv,
330 THIS_MODULE);
328 if (!nfnl) { 331 if (!nfnl) {
329 printk(KERN_ERR "cannot initialize nfnetlink!\n"); 332 printk(KERN_ERR "cannot initialize nfnetlink!\n");
330 return -1; 333 return -1;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index ff774a06c89d..5d487cd69c8c 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -13,7 +13,12 @@
13 * added netlink_proto_exit 13 * added netlink_proto_exit
14 * Tue Jan 22 18:32:44 BRST 2002 Arnaldo C. de Melo <acme@conectiva.com.br> 14 * Tue Jan 22 18:32:44 BRST 2002 Arnaldo C. de Melo <acme@conectiva.com.br>
15 * use nlk_sk, as sk->protinfo is on a diet 8) 15 * use nlk_sk, as sk->protinfo is on a diet 8)
16 * 16 * Fri Jul 22 19:51:12 MEST 2005 Harald Welte <laforge@gnumonks.org>
17 * - inc module use count of module that owns
18 * the kernel socket in case userspace opens
19 * socket of same protocol
20 * - remove all module support, since netlink is
21 * mandatory if CONFIG_NET=y these days
17 */ 22 */
18 23
19#include <linux/config.h> 24#include <linux/config.h>
@@ -92,6 +97,7 @@ struct netlink_table {
92 struct nl_pid_hash hash; 97 struct nl_pid_hash hash;
93 struct hlist_head mc_list; 98 struct hlist_head mc_list;
94 unsigned int nl_nonroot; 99 unsigned int nl_nonroot;
100 struct proto_ops *p_ops;
95}; 101};
96 102
97static struct netlink_table *nl_table; 103static struct netlink_table *nl_table;
@@ -341,7 +347,21 @@ static int netlink_create(struct socket *sock, int protocol)
341 if (protocol<0 || protocol >= MAX_LINKS) 347 if (protocol<0 || protocol >= MAX_LINKS)
342 return -EPROTONOSUPPORT; 348 return -EPROTONOSUPPORT;
343 349
344 sock->ops = &netlink_ops; 350 netlink_table_grab();
351 if (!nl_table[protocol].hash.entries) {
352#ifdef CONFIG_KMOD
353 /* We do 'best effort'. If we find a matching module,
354 * it is loaded. If not, we don't return an error to
355 * allow pure userspace<->userspace communication. -HW
356 */
357 netlink_table_ungrab();
358 request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
359 netlink_table_grab();
360#endif
361 }
362 netlink_table_ungrab();
363
364 sock->ops = nl_table[protocol].p_ops;
345 365
346 sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1); 366 sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
347 if (!sk) 367 if (!sk)
@@ -394,6 +414,22 @@ static int netlink_release(struct socket *sock)
394 }; 414 };
395 notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n); 415 notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
396 } 416 }
417
418 /* When this is a kernel socket, we need to remove the owner pointer,
419 * since we don't know whether the module will be dying at any given
420 * point - HW
421 */
422 if (!nlk->pid) {
423 struct proto_ops *p_tmp;
424
425 netlink_table_grab();
426 p_tmp = nl_table[sk->sk_protocol].p_ops;
427 if (p_tmp != &netlink_ops) {
428 nl_table[sk->sk_protocol].p_ops = &netlink_ops;
429 kfree(p_tmp);
430 }
431 netlink_table_ungrab();
432 }
397 433
398 sock_put(sk); 434 sock_put(sk);
399 return 0; 435 return 0;
@@ -1023,8 +1059,9 @@ static void netlink_data_ready(struct sock *sk, int len)
1023 */ 1059 */
1024 1060
1025struct sock * 1061struct sock *
1026netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len)) 1062netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct module *module)
1027{ 1063{
1064 struct proto_ops *p_ops;
1028 struct socket *sock; 1065 struct socket *sock;
1029 struct sock *sk; 1066 struct sock *sk;
1030 1067
@@ -1034,22 +1071,63 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
1034 if (unit<0 || unit>=MAX_LINKS) 1071 if (unit<0 || unit>=MAX_LINKS)
1035 return NULL; 1072 return NULL;
1036 1073
1074 /* Do a quick check, to make us not go down to netlink_insert()
1075 * if protocol already has kernel socket.
1076 */
1077 sk = netlink_lookup(unit, 0);
1078 if (unlikely(sk)) {
1079 sock_put(sk);
1080 return NULL;
1081 }
1082
1037 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) 1083 if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
1038 return NULL; 1084 return NULL;
1039 1085
1086 sk = NULL;
1087 if (module) {
1088 /* Every registering protocol implemented in a module needs
1089 * it's own p_ops, since the socket code cannot deal with
1090 * module refcounting otherwise. -HW
1091 */
1092 p_ops = kmalloc(sizeof(*p_ops), GFP_KERNEL);
1093 if (!p_ops)
1094 goto out_sock_release;
1095
1096 memcpy(p_ops, &netlink_ops, sizeof(*p_ops));
1097 p_ops->owner = module;
1098 } else
1099 p_ops = &netlink_ops;
1100
1101 netlink_table_grab();
1102 nl_table[unit].p_ops = p_ops;
1103 netlink_table_ungrab();
1104
1040 if (netlink_create(sock, unit) < 0) { 1105 if (netlink_create(sock, unit) < 0) {
1041 sock_release(sock); 1106 sk = NULL;
1042 return NULL; 1107 goto out_kfree_p_ops;
1043 } 1108 }
1109
1044 sk = sock->sk; 1110 sk = sock->sk;
1045 sk->sk_data_ready = netlink_data_ready; 1111 sk->sk_data_ready = netlink_data_ready;
1046 if (input) 1112 if (input)
1047 nlk_sk(sk)->data_ready = input; 1113 nlk_sk(sk)->data_ready = input;
1048 1114
1049 if (netlink_insert(sk, 0)) { 1115 if (netlink_insert(sk, 0)) {
1050 sock_release(sock); 1116 sk = NULL;
1051 return NULL; 1117 goto out_kfree_p_ops;
1118 }
1119
1120 return sk;
1121
1122out_kfree_p_ops:
1123 netlink_table_grab();
1124 if (nl_table[unit].p_ops != &netlink_ops) {
1125 kfree(nl_table[unit].p_ops);
1126 nl_table[unit].p_ops = &netlink_ops;
1052 } 1127 }
1128 netlink_table_ungrab();
1129out_sock_release:
1130 sock_release(sock);
1053 return sk; 1131 return sk;
1054} 1132}
1055 1133
@@ -1413,6 +1491,8 @@ enomem:
1413 for (i = 0; i < MAX_LINKS; i++) { 1491 for (i = 0; i < MAX_LINKS; i++) {
1414 struct nl_pid_hash *hash = &nl_table[i].hash; 1492 struct nl_pid_hash *hash = &nl_table[i].hash;
1415 1493
1494 nl_table[i].p_ops = &netlink_ops;
1495
1416 hash->table = nl_pid_hash_alloc(1 * sizeof(*hash->table)); 1496 hash->table = nl_pid_hash_alloc(1 * sizeof(*hash->table));
1417 if (!hash->table) { 1497 if (!hash->table) {
1418 while (i-- > 0) 1498 while (i-- > 0)
@@ -1438,21 +1518,7 @@ out:
1438 return err; 1518 return err;
1439} 1519}
1440 1520
1441static void __exit netlink_proto_exit(void)
1442{
1443 sock_unregister(PF_NETLINK);
1444 proc_net_remove("netlink");
1445 kfree(nl_table);
1446 nl_table = NULL;
1447 proto_unregister(&netlink_proto);
1448}
1449
1450core_initcall(netlink_proto_init); 1521core_initcall(netlink_proto_init);
1451module_exit(netlink_proto_exit);
1452
1453MODULE_LICENSE("GPL");
1454
1455MODULE_ALIAS_NETPROTO(PF_NETLINK);
1456 1522
1457EXPORT_SYMBOL(netlink_ack); 1523EXPORT_SYMBOL(netlink_ack);
1458EXPORT_SYMBOL(netlink_broadcast); 1524EXPORT_SYMBOL(netlink_broadcast);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 8da3e25b2c4c..33ceeea783b1 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1519,7 +1519,8 @@ static int __init xfrm_user_init(void)
1519{ 1519{
1520 printk(KERN_INFO "Initializing IPsec netlink socket\n"); 1520 printk(KERN_INFO "Initializing IPsec netlink socket\n");
1521 1521
1522 xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv); 1522 xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv,
1523 THIS_MODULE);
1523 if (xfrm_nl == NULL) 1524 if (xfrm_nl == NULL)
1524 return -ENOMEM; 1525 return -ENOMEM;
1525 1526
@@ -1537,3 +1538,4 @@ static void __exit xfrm_user_exit(void)
1537module_init(xfrm_user_init); 1538module_init(xfrm_user_init);
1538module_exit(xfrm_user_exit); 1539module_exit(xfrm_user_exit);
1539MODULE_LICENSE("GPL"); 1540MODULE_LICENSE("GPL");
1541MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);