static int __init crypto_user_init(void)
 {
+       struct netlink_kernel_cfg cfg = {
+               .input  = crypto_netlink_rcv,
+       };
+
        crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
-                                           0, crypto_netlink_rcv,
-                                           NULL, THIS_MODULE);
+                                           THIS_MODULE, &cfg);
        if (!crypto_nlsk)
                return -ENOMEM;
 
 
        .release = single_release
 };
 
+static struct cn_dev cdev = {
+       .input   = cn_rx_skb,
+};
+
 static int __devinit cn_init(void)
 {
        struct cn_dev *dev = &cdev;
-
-       dev->input = cn_rx_skb;
+       struct netlink_kernel_cfg cfg = {
+               .groups = CN_NETLINK_USERS + 0xf,
+               .input  = dev->input,
+       };
 
        dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
-                                        CN_NETLINK_USERS + 0xf,
-                                        dev->input, NULL, THIS_MODULE);
+                                        THIS_MODULE, &cfg);
        if (!dev->nls)
                return -EIO;
 
 
 
 int __init ibnl_init(void)
 {
-       nls = netlink_kernel_create(&init_net, NETLINK_RDMA, 0, ibnl_rcv,
-                                   NULL, THIS_MODULE);
+       struct netlink_kernel_cfg cfg = {
+               .input  = ibnl_rcv,
+       };
+
+       nls = netlink_kernel_create(&init_net, NETLINK_RDMA, THIS_MODULE, &cfg);
        if (!nls) {
                pr_warn("Failed to create netlink socket\n");
                return -ENOMEM;
 
 scsi_netlink_init(void)
 {
        int error;
+       struct netlink_kernel_cfg cfg = {
+               .input  = scsi_nl_rcv_msg,
+               .groups = SCSI_NL_GRP_CNT,
+       };
 
        INIT_LIST_HEAD(&scsi_nl_drivers);
 
        }
 
        scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
-                               SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL,
-                               THIS_MODULE);
+                                            THIS_MODULE, &cfg);
        if (!scsi_nl_sock) {
                printk(KERN_ERR "%s: register of receive handler failed\n",
                                __func__);
 
 static __init int iscsi_transport_init(void)
 {
        int err;
-
+       struct netlink_kernel_cfg cfg = {
+               .groups = 1,
+               .input  = iscsi_if_rx,
+       };
        printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
                ISCSI_TRANSPORT_VERSION);
 
        if (err)
                goto unregister_conn_class;
 
-       nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
-                                   NULL, THIS_MODULE);
+       nls = netlink_kernel_create(&init_net, NETLINK_ISCSI,
+                                   THIS_MODULE, &cfg);
        if (!nls) {
                err = -ENOBUFS;
                goto unregister_session_class;
 
                                                void *msg, int len))
 {
        struct sock *sock;
+       struct netlink_kernel_cfg cfg = {
+               .input  = netlink_rcv,
+       };
 
 #if !defined(DEFINE_MUTEX)
        init_MUTEX(&netlink_mutex);
 #endif
 
-       sock = netlink_kernel_create(&init_net, unit, 0, netlink_rcv, NULL,
-                                       THIS_MODULE);
+       sock = netlink_kernel_create(&init_net, unit, THIS_MODULE, &cfg);
 
        if (sock)
                rcv_cb = cb;
 
 extern void netlink_table_grab(void);
 extern void netlink_table_ungrab(void);
 
-extern struct sock *netlink_kernel_create(struct net *net,
-                                         int unit,unsigned int groups,
-                                         void (*input)(struct sk_buff *skb),
-                                         struct mutex *cb_mutex,
-                                         struct module *module);
+/* optional Netlink kernel configuration parameters */
+struct netlink_kernel_cfg {
+       unsigned int    groups;
+       void            (*input)(struct sk_buff *skb);
+       struct mutex    *cb_mutex;
+};
+
+extern struct sock *netlink_kernel_create(struct net *net, int unit,
+                                         struct module *module,
+                                         struct netlink_kernel_cfg *cfg);
 extern void netlink_kernel_release(struct sock *sk);
 extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups);
 extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
 
 static int __init audit_init(void)
 {
        int i;
+       struct netlink_kernel_cfg cfg = {
+               .input  = audit_receive,
+       };
 
        if (audit_initialized == AUDIT_DISABLED)
                return 0;
 
        printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
               audit_default ? "enabled" : "disabled");
-       audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,
-                                          audit_receive, NULL, THIS_MODULE);
+       audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT,
+                                          THIS_MODULE, &cfg);
        if (!audit_sock)
                audit_panic("cannot initialize netlink socket");
        else
 
 static int uevent_net_init(struct net *net)
 {
        struct uevent_sock *ue_sk;
+       struct netlink_kernel_cfg cfg = {
+               .groups = 1,
+       };
 
        ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
        if (!ue_sk)
                return -ENOMEM;
 
        ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
-                                         1, NULL, NULL, THIS_MODULE);
+                                         THIS_MODULE, &cfg);
        if (!ue_sk->sk) {
                printk(KERN_ERR
                       "kobject_uevent: unable to create netlink socket!\n");
 
 {
        int ret;
        int i;
+       struct netlink_kernel_cfg cfg = {
+               .groups = EBT_ULOG_MAXNLGROUPS,
+       };
 
        if (nlbufsiz >= 128*1024) {
                pr_warning("Netlink buffer has to be <= 128kB,"
        }
 
        ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
-                                         EBT_ULOG_MAXNLGROUPS, NULL, NULL,
-                                         THIS_MODULE);
+                                         THIS_MODULE, &cfg);
        if (!ebtulognl)
                ret = -ENOMEM;
        else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0)
 
 static int __net_init rtnetlink_net_init(struct net *net)
 {
        struct sock *sk;
-       sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX,
-                                  rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
+       struct netlink_kernel_cfg cfg = {
+               .groups         = RTNLGRP_MAX,
+               .input          = rtnetlink_rcv,
+               .cb_mutex       = &rtnl_mutex,
+       };
+
+       sk = netlink_kernel_create(net, NETLINK_ROUTE, THIS_MODULE, &cfg);
        if (!sk)
                return -ENOMEM;
        net->rtnl = sk;
 
 
 static int __init sock_diag_init(void)
 {
-       sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 0,
-                                       sock_diag_rcv, NULL, THIS_MODULE);
+       struct netlink_kernel_cfg cfg = {
+               .input  = sock_diag_rcv,
+       };
+
+       sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG,
+                                              THIS_MODULE, &cfg);
        return sock_diag_nlsk == NULL ? -ENOMEM : 0;
 }
 
 
 static int __init dn_rtmsg_init(void)
 {
        int rv = 0;
+       struct netlink_kernel_cfg cfg = {
+               .groups = DNRNG_NLGRP_MAX,
+               .input  = dnrmg_receive_user_skb,
+       };
 
        dnrmg = netlink_kernel_create(&init_net,
-                                     NETLINK_DNRTMSG, DNRNG_NLGRP_MAX,
-                                     dnrmg_receive_user_skb,
-                                     NULL, THIS_MODULE);
+                                     NETLINK_DNRTMSG, THIS_MODULE, &cfg);
        if (dnrmg == NULL) {
                printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
                return -ENOMEM;
 
 static int __net_init nl_fib_lookup_init(struct net *net)
 {
        struct sock *sk;
-       sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0,
-                                  nl_fib_input, NULL, THIS_MODULE);
+       struct netlink_kernel_cfg cfg = {
+               .input  = nl_fib_input,
+       };
+
+       sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, THIS_MODULE, &cfg);
        if (sk == NULL)
                return -EAFNOSUPPORT;
        net->ipv4.fibnl = sk;
 
 static int __init ulog_tg_init(void)
 {
        int ret, i;
+       struct netlink_kernel_cfg cfg = {
+               .groups = ULOG_MAXNLGROUPS,
+       };
 
        pr_debug("init module\n");
 
        for (i = 0; i < ULOG_MAXNLGROUPS; i++)
                setup_timer(&ulog_buffers[i].timer, ulog_timer, i);
 
-       nflognl = netlink_kernel_create(&init_net,
-                                       NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
-                                       NULL, THIS_MODULE);
+       nflognl = netlink_kernel_create(&init_net, NETLINK_NFLOG,
+                                       THIS_MODULE, &cfg);
        if (!nflognl)
                return -ENOMEM;
 
 
 static int __net_init nfnetlink_net_init(struct net *net)
 {
        struct sock *nfnl;
+       struct netlink_kernel_cfg cfg = {
+               .groups = NFNLGRP_MAX,
+               .input  = nfnetlink_rcv,
+       };
 
-       nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX,
-                                    nfnetlink_rcv, NULL, THIS_MODULE);
+       nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, THIS_MODULE, &cfg);
        if (!nfnl)
                return -ENOMEM;
        net->nfnl_stash = nfnl;
 
  */
 
 struct sock *
-netlink_kernel_create(struct net *net, int unit, unsigned int groups,
-                     void (*input)(struct sk_buff *skb),
-                     struct mutex *cb_mutex, struct module *module)
+netlink_kernel_create(struct net *net, int unit,
+                     struct module *module,
+                     struct netlink_kernel_cfg *cfg)
 {
        struct socket *sock;
        struct sock *sk;
        struct netlink_sock *nlk;
        struct listeners *listeners = NULL;
+       struct mutex *cb_mutex = cfg ? cfg->cb_mutex : NULL;
+       unsigned int groups;
 
        BUG_ON(!nl_table);
 
        sk = sock->sk;
        sk_change_net(sk, net);
 
-       if (groups < 32)
+       if (!cfg || cfg->groups < 32)
                groups = 32;
+       else
+               groups = cfg->groups;
 
        listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL);
        if (!listeners)
                goto out_sock_release;
 
        sk->sk_data_ready = netlink_data_ready;
-       if (input)
-               nlk_sk(sk)->netlink_rcv = input;
+       if (cfg && cfg->input)
+               nlk_sk(sk)->netlink_rcv = cfg->input;
 
        if (netlink_insert(sk, net, 0))
                goto out_sock_release;
 
 
 static int __net_init genl_pernet_init(struct net *net)
 {
+       struct netlink_kernel_cfg cfg = {
+               .input          = genl_rcv,
+               .cb_mutex       = &genl_mutex,
+       };
+
        /* we'll bump the group number right afterwards */
-       net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0,
-                                              genl_rcv, &genl_mutex,
-                                              THIS_MODULE);
+       net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC,
+                                              THIS_MODULE, &cfg);
 
        if (!net->genl_sock && net_eq(net, &init_net))
                panic("GENL: Cannot initialize generic netlink\n");
 
 static int __net_init xfrm_user_net_init(struct net *net)
 {
        struct sock *nlsk;
+       struct netlink_kernel_cfg cfg = {
+               .groups = XFRMNLGRP_MAX,
+               .input  = xfrm_netlink_rcv,
+       };
 
-       nlsk = netlink_kernel_create(net, NETLINK_XFRM, XFRMNLGRP_MAX,
-                                    xfrm_netlink_rcv, NULL, THIS_MODULE);
+       nlsk = netlink_kernel_create(net, NETLINK_XFRM, THIS_MODULE, &cfg);
        if (nlsk == NULL)
                return -ENOMEM;
        net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */
 
 
 static int __init selnl_init(void)
 {
+       struct netlink_kernel_cfg cfg = {
+               .groups = SELNLGRP_MAX,
+       };
+
        selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX,
-                                     SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
+                                     THIS_MODULE, &cfg);
        if (selnl == NULL)
                panic("SELinux:  Cannot create netlink socket.");
        netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);