dev->groups = 23;
dev->seq = 1;
- dev->nls = netlink_kernel_create(NETLINK_W1, NULL);
+ dev->nls = netlink_kernel_create(NETLINK_W1, NULL, THIS_MODULE);
if (!dev->nls) {
printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
NETLINK_NFLOG, dev->dev.bus_id);
EXPORT_SYMBOL(w1_add_master_device);
EXPORT_SYMBOL(w1_remove_master_device);
+
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_W1);
#define MODULE_ALIAS_NETPROTO(proto) \
MODULE_ALIAS("net-pf-" __stringify(proto))
+#define MODULE_ALIAS_NET_PF_PROTO(pf, proto) \
+ MODULE_ALIAS("net-pf-" __stringify(pf) "-proto-" __stringify(proto))
+
#endif /* __KERNEL__ */
#endif /* _LINUX_NET_H */
#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
-extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
+extern struct sock *netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct module *module);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
{
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
audit_default ? "enabled" : "disabled");
- audit_sock = netlink_kernel_create(NETLINK_AUDIT, audit_receive);
+ audit_sock = netlink_kernel_create(NETLINK_AUDIT, audit_receive,
+ THIS_MODULE);
if (!audit_sock)
audit_panic("cannot initialize netlink socket");
static int __init kobject_uevent_init(void)
{
- uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, NULL);
+ uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, NULL,
+ THIS_MODULE);
if (!uevent_sock) {
printk(KERN_ERR
spin_lock_init(&ulog_buffers[i].lock);
}
- ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
+ ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL, THIS_MODULE);
if (!ebtulognl)
ret = -ENOMEM;
else if ((ret = ebt_register_watcher(&ulog)))
if (!rta_buf)
panic("rtnetlink_init: cannot allocate rta_buf\n");
- rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
+ rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv, THIS_MODULE);
if (rtnl == NULL)
panic("rtnetlink_init: cannot initialize rtnetlink\n");
netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
{
int rv = 0;
- dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk);
+ dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk,
+ THIS_MODULE);
if (dnrmg == NULL) {
printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
return -ENOMEM;
MODULE_DESCRIPTION("DECnet Routing Message Grabulator");
MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
module_init(init);
module_exit(fini);
static void nl_fib_lookup_init(void)
{
- netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
+ netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input, THIS_MODULE);
}
static void fib_disable_ip(struct net_device *dev, int force)
goto cleanup;
netlink_register_notifier(&ipq_nl_notifier);
- ipqnl = netlink_kernel_create(NETLINK_FIREWALL, ipq_rcv_sk);
+ ipqnl = netlink_kernel_create(NETLINK_FIREWALL, ipq_rcv_sk,
+ THIS_MODULE);
if (ipqnl == NULL) {
printk(KERN_ERR "ip_queue: failed to create netlink socket\n");
goto cleanup_netlink_notifier;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("iptables userspace logging module");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
#define ULOG_NL_EVENT 111 /* Harald's favorite number */
#define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */
ulog_buffers[i].timer.data = i;
}
- nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
+ nflognl = netlink_kernel_create(NETLINK_NFLOG, NULL, THIS_MODULE);
if (!nflognl)
return -ENOMEM;
static int __init tcpdiag_init(void)
{
- tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv);
+ tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv,
+ THIS_MODULE);
if (tcpnl == NULL)
return -ENOMEM;
return 0;
goto cleanup;
netlink_register_notifier(&ipq_nl_notifier);
- ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk);
+ ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk, THIS_MODULE);
if (ipqnl == NULL) {
printk(KERN_ERR "ip6_queue: failed to create netlink socket\n");
goto cleanup_netlink_notifier;
#include <linux/netfilter/nfnetlink.h>
MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
static char __initdata nfversion[] = "0.30";
{
printk("Netfilter messages via NETLINK v%s.\n", nfversion);
- nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv);
+ nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv,
+ THIS_MODULE);
if (!nfnl) {
printk(KERN_ERR "cannot initialize nfnetlink!\n");
return -1;
* added netlink_proto_exit
* Tue Jan 22 18:32:44 BRST 2002 Arnaldo C. de Melo <acme@conectiva.com.br>
* use nlk_sk, as sk->protinfo is on a diet 8)
- *
+ * Fri Jul 22 19:51:12 MEST 2005 Harald Welte <laforge@gnumonks.org>
+ * - inc module use count of module that owns
+ * the kernel socket in case userspace opens
+ * socket of same protocol
+ * - remove all module support, since netlink is
+ * mandatory if CONFIG_NET=y these days
*/
#include <linux/config.h>
struct nl_pid_hash hash;
struct hlist_head mc_list;
unsigned int nl_nonroot;
+ struct proto_ops *p_ops;
};
static struct netlink_table *nl_table;
if (protocol<0 || protocol >= MAX_LINKS)
return -EPROTONOSUPPORT;
- sock->ops = &netlink_ops;
+ netlink_table_grab();
+ if (!nl_table[protocol].hash.entries) {
+#ifdef CONFIG_KMOD
+ /* We do 'best effort'. If we find a matching module,
+ * it is loaded. If not, we don't return an error to
+ * allow pure userspace<->userspace communication. -HW
+ */
+ netlink_table_ungrab();
+ request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
+ netlink_table_grab();
+#endif
+ }
+ netlink_table_ungrab();
+
+ sock->ops = nl_table[protocol].p_ops;
sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
if (!sk)
};
notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
}
+
+ /* When this is a kernel socket, we need to remove the owner pointer,
+ * since we don't know whether the module will be dying at any given
+ * point - HW
+ */
+ if (!nlk->pid) {
+ struct proto_ops *p_tmp;
+
+ netlink_table_grab();
+ p_tmp = nl_table[sk->sk_protocol].p_ops;
+ if (p_tmp != &netlink_ops) {
+ nl_table[sk->sk_protocol].p_ops = &netlink_ops;
+ kfree(p_tmp);
+ }
+ netlink_table_ungrab();
+ }
sock_put(sk);
return 0;
*/
struct sock *
-netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
+netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len), struct module *module)
{
+ struct proto_ops *p_ops;
struct socket *sock;
struct sock *sk;
if (unit<0 || unit>=MAX_LINKS)
return NULL;
+ /* Do a quick check, to make us not go down to netlink_insert()
+ * if protocol already has kernel socket.
+ */
+ sk = netlink_lookup(unit, 0);
+ if (unlikely(sk)) {
+ sock_put(sk);
+ return NULL;
+ }
+
if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
return NULL;
+ sk = NULL;
+ if (module) {
+ /* Every registering protocol implemented in a module needs
+ * it's own p_ops, since the socket code cannot deal with
+ * module refcounting otherwise. -HW
+ */
+ p_ops = kmalloc(sizeof(*p_ops), GFP_KERNEL);
+ if (!p_ops)
+ goto out_sock_release;
+
+ memcpy(p_ops, &netlink_ops, sizeof(*p_ops));
+ p_ops->owner = module;
+ } else
+ p_ops = &netlink_ops;
+
+ netlink_table_grab();
+ nl_table[unit].p_ops = p_ops;
+ netlink_table_ungrab();
+
if (netlink_create(sock, unit) < 0) {
- sock_release(sock);
- return NULL;
+ sk = NULL;
+ goto out_kfree_p_ops;
}
+
sk = sock->sk;
sk->sk_data_ready = netlink_data_ready;
if (input)
nlk_sk(sk)->data_ready = input;
if (netlink_insert(sk, 0)) {
- sock_release(sock);
- return NULL;
+ sk = NULL;
+ goto out_kfree_p_ops;
+ }
+
+ return sk;
+
+out_kfree_p_ops:
+ netlink_table_grab();
+ if (nl_table[unit].p_ops != &netlink_ops) {
+ kfree(nl_table[unit].p_ops);
+ nl_table[unit].p_ops = &netlink_ops;
}
+ netlink_table_ungrab();
+out_sock_release:
+ sock_release(sock);
return sk;
}
for (i = 0; i < MAX_LINKS; i++) {
struct nl_pid_hash *hash = &nl_table[i].hash;
+ nl_table[i].p_ops = &netlink_ops;
+
hash->table = nl_pid_hash_alloc(1 * sizeof(*hash->table));
if (!hash->table) {
while (i-- > 0)
return err;
}
-static void __exit netlink_proto_exit(void)
-{
- sock_unregister(PF_NETLINK);
- proc_net_remove("netlink");
- kfree(nl_table);
- nl_table = NULL;
- proto_unregister(&netlink_proto);
-}
-
core_initcall(netlink_proto_init);
-module_exit(netlink_proto_exit);
-
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS_NETPROTO(PF_NETLINK);
EXPORT_SYMBOL(netlink_ack);
EXPORT_SYMBOL(netlink_broadcast);
{
printk(KERN_INFO "Initializing IPsec netlink socket\n");
- xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv);
+ xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv,
+ THIS_MODULE);
if (xfrm_nl == NULL)
return -ENOMEM;
module_init(xfrm_user_init);
module_exit(xfrm_user_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
static int __init selnl_init(void)
{
- selnl = netlink_kernel_create(NETLINK_SELINUX, NULL);
+ selnl = netlink_kernel_create(NETLINK_SELINUX, NULL, THIS_MODULE);
if (selnl == NULL)
panic("SELinux: Cannot create netlink socket.");
netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);