aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.c
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/netlink/af_netlink.c
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/netlink/af_netlink.c')
-rw-r--r--net/netlink/af_netlink.c108
1 files changed, 87 insertions, 21 deletions
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);