}
 
 /* called with rcu_read_lock held */
-static int nf_tables_gettable(struct net *net, struct sock *nlsk,
-                             struct sk_buff *skb, const struct nlmsghdr *nlh,
-                             const struct nlattr * const nla[],
-                             struct netlink_ext_ack *extack)
+static int nf_tables_gettable(struct sk_buff *skb, const struct nfnl_info *info,
+                             const struct nlattr * const nla[])
 {
-       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       u8 genmask = nft_genmask_cur(net);
+       const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_cur(info->net);
+       int family = nfmsg->nfgen_family;
        const struct nft_table *table;
+       struct net *net = info->net;
        struct sk_buff *skb2;
-       int family = nfmsg->nfgen_family;
        int err;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .dump = nf_tables_dump_tables,
                        .module = THIS_MODULE,
                };
 
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        table = nft_table_lookup(net, nla[NFTA_TABLE_NAME], family, genmask, 0);
                return -ENOMEM;
 
        err = nf_tables_fill_table_info(skb2, net, NETLINK_CB(skb).portid,
-                                       nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
-                                       family, table);
+                                       info->nlh->nlmsg_seq, NFT_MSG_NEWTABLE,
+                                       0, family, table);
        if (err < 0)
                goto err_fill_table_info;
 
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getchain(struct net *net, struct sock *nlsk,
-                             struct sk_buff *skb, const struct nlmsghdr *nlh,
-                             const struct nlattr * const nla[],
-                             struct netlink_ext_ack *extack)
+static int nf_tables_getchain(struct sk_buff *skb, const struct nfnl_info *info,
+                             const struct nlattr * const nla[])
 {
-       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       u8 genmask = nft_genmask_cur(net);
+       const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_cur(info->net);
+       int family = nfmsg->nfgen_family;
        const struct nft_chain *chain;
+       struct net *net = info->net;
        struct nft_table *table;
        struct sk_buff *skb2;
-       int family = nfmsg->nfgen_family;
        int err;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .dump = nf_tables_dump_chains,
                        .module = THIS_MODULE,
                };
 
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask, 0);
                return -ENOMEM;
 
        err = nf_tables_fill_chain_info(skb2, net, NETLINK_CB(skb).portid,
-                                       nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
-                                       family, table, chain);
+                                       info->nlh->nlmsg_seq, NFT_MSG_NEWCHAIN,
+                                       0, family, table, chain);
        if (err < 0)
                goto err_fill_chain_info;
 
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getrule(struct net *net, struct sock *nlsk,
-                            struct sk_buff *skb, const struct nlmsghdr *nlh,
-                            const struct nlattr * const nla[],
-                            struct netlink_ext_ack *extack)
+static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
+                            const struct nlattr * const nla[])
 {
-       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       u8 genmask = nft_genmask_cur(net);
+       const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_cur(info->net);
+       int family = nfmsg->nfgen_family;
        const struct nft_chain *chain;
        const struct nft_rule *rule;
+       struct net *net = info->net;
        struct nft_table *table;
        struct sk_buff *skb2;
-       int family = nfmsg->nfgen_family;
        int err;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .start= nf_tables_dump_rules_start,
                        .dump = nf_tables_dump_rules,
                        .data = (void *)nla,
                };
 
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask, 0);
                return -ENOMEM;
 
        err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
-                                      nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
+                                      info->nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
                                       family, table, chain, rule, NULL);
        if (err < 0)
                goto err_fill_rule_info;
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getset(struct net *net, struct sock *nlsk,
-                           struct sk_buff *skb, const struct nlmsghdr *nlh,
-                           const struct nlattr * const nla[],
-                           struct netlink_ext_ack *extack)
+static int nf_tables_getset(struct sk_buff *skb, const struct nfnl_info *info,
+                           const struct nlattr * const nla[])
 {
-       u8 genmask = nft_genmask_cur(net);
+       const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_cur(info->net);
+       struct net *net = info->net;
        const struct nft_set *set;
-       struct nft_ctx ctx;
        struct sk_buff *skb2;
-       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       struct nft_ctx ctx;
        int err;
 
        /* Verify existence before starting dump */
-       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack,
+       err = nft_ctx_init_from_setattr(&ctx, net, skb, info->nlh, nla, extack,
                                        genmask, 0);
        if (err < 0)
                return err;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .start = nf_tables_dump_sets_start,
                        .dump = nf_tables_dump_sets,
                        .module = THIS_MODULE,
                };
 
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        /* Only accept unspec with dump */
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
-                               struct sk_buff *skb, const struct nlmsghdr *nlh,
-                               const struct nlattr * const nla[],
-                               struct netlink_ext_ack *extack)
+static int nf_tables_getsetelem(struct sk_buff *skb,
+                               const struct nfnl_info *info,
+                               const struct nlattr * const nla[])
 {
-       u8 genmask = nft_genmask_cur(net);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_cur(info->net);
+       struct net *net = info->net;
        struct nft_set *set;
        struct nlattr *attr;
        struct nft_ctx ctx;
        int rem, err = 0;
 
-       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, info->nlh, nla, extack,
                                         genmask, NETLINK_CB(skb).portid);
        if (err < 0)
                return err;
        if (IS_ERR(set))
                return PTR_ERR(set);
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .start = nf_tables_dump_set_start,
                        .dump = nf_tables_dump_set,
                };
 
                c.data = &dump_ctx;
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getobj(struct net *net, struct sock *nlsk,
-                           struct sk_buff *skb, const struct nlmsghdr *nlh,
-                           const struct nlattr * const nla[],
-                           struct netlink_ext_ack *extack)
+static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
+                           const struct nlattr * const nla[])
 {
-       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       u8 genmask = nft_genmask_cur(net);
+       const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_cur(info->net);
        int family = nfmsg->nfgen_family;
        const struct nft_table *table;
+       struct net *net = info->net;
        struct nft_object *obj;
        struct sk_buff *skb2;
        bool reset = false;
        u32 objtype;
        int err;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .start = nf_tables_dump_obj_start,
                        .dump = nf_tables_dump_obj,
                        .data = (void *)nla,
                };
 
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        if (!nla[NFTA_OBJ_NAME] ||
        if (!skb2)
                return -ENOMEM;
 
-       if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
+       if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
                reset = true;
 
        if (reset) {
        }
 
        err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
-                                     nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
+                                     info->nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
                                      family, table, obj, reset);
        if (err < 0)
                goto err_fill_obj_info;
 }
 
 /* called with rcu_read_lock held */
-static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
-                                 struct sk_buff *skb,
-                                 const struct nlmsghdr *nlh,
-                                 const struct nlattr * const nla[],
-                                 struct netlink_ext_ack *extack)
+static int nf_tables_getflowtable(struct sk_buff *skb,
+                                 const struct nfnl_info *info,
+                                 const struct nlattr * const nla[])
 {
-       const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
-       u8 genmask = nft_genmask_cur(net);
+       const struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       u8 genmask = nft_genmask_cur(info->net);
        int family = nfmsg->nfgen_family;
        struct nft_flowtable *flowtable;
        const struct nft_table *table;
+       struct net *net = info->net;
        struct sk_buff *skb2;
        int err;
 
-       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+       if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .start = nf_tables_dump_flowtable_start,
                        .dump = nf_tables_dump_flowtable,
                        .data = (void *)nla,
                };
 
-               return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
+               return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
        }
 
        if (!nla[NFTA_FLOWTABLE_NAME])
                return -ENOMEM;
 
        err = nf_tables_fill_flowtable_info(skb2, net, NETLINK_CB(skb).portid,
-                                           nlh->nlmsg_seq,
+                                           info->nlh->nlmsg_seq,
                                            NFT_MSG_NEWFLOWTABLE, 0, family,
                                            flowtable, &flowtable->hook_list);
        if (err < 0)
                          -ENOBUFS);
 }
 
-static int nf_tables_getgen(struct net *net, struct sock *nlsk,
-                           struct sk_buff *skb, const struct nlmsghdr *nlh,
-                           const struct nlattr * const nla[],
-                           struct netlink_ext_ack *extack)
+static int nf_tables_getgen(struct sk_buff *skb, const struct nfnl_info *info,
+                           const struct nlattr * const nla[])
 {
        struct sk_buff *skb2;
        int err;
        if (skb2 == NULL)
                return -ENOMEM;
 
-       err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
-                                     nlh->nlmsg_seq);
+       err = nf_tables_fill_gen_info(skb2, info->net, NETLINK_CB(skb).portid,
+                                     info->nlh->nlmsg_seq);
        if (err < 0)
                goto err_fill_gen_info;
 
-       return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
+       return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
 
 err_fill_gen_info:
        kfree_skb(skb2);
 
        return (int)(id - max) > 0;
 }
 
-static int nfqnl_recv_verdict_batch(struct net *net, struct sock *ctnl,
-                                   struct sk_buff *skb,
-                                   const struct nlmsghdr *nlh,
-                                   const struct nlattr * const nfqa[],
-                                   struct netlink_ext_ack *extack)
+static int nfqnl_recv_verdict_batch(struct sk_buff *skb,
+                                   const struct nfnl_info *info,
+                                   const struct nlattr * const nfqa[])
 {
-       struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       struct nfnl_queue_net *q = nfnl_queue_pernet(info->net);
+       struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
+       u16 queue_num = ntohs(nfmsg->res_id);
        struct nf_queue_entry *entry, *tmp;
-       unsigned int verdict, maxid;
        struct nfqnl_msg_verdict_hdr *vhdr;
        struct nfqnl_instance *queue;
+       unsigned int verdict, maxid;
        LIST_HEAD(batch_list);
-       u16 queue_num = ntohs(nfmsg->res_id);
-       struct nfnl_queue_net *q = nfnl_queue_pernet(net);
 
        queue = verdict_instance_lookup(q, queue_num,
                                        NETLINK_CB(skb).portid);
        return 0;
 }
 
-static int nfqnl_recv_verdict(struct net *net, struct sock *ctnl,
-                             struct sk_buff *skb,
-                             const struct nlmsghdr *nlh,
-                             const struct nlattr * const nfqa[],
-                             struct netlink_ext_ack *extack)
+static int nfqnl_recv_verdict(struct sk_buff *skb, const struct nfnl_info *info,
+                             const struct nlattr * const nfqa[])
 {
-       struct nfgenmsg *nfmsg = nlmsg_data(nlh);
+       struct nfnl_queue_net *q = nfnl_queue_pernet(info->net);
+       struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
        u_int16_t queue_num = ntohs(nfmsg->res_id);
        struct nfqnl_msg_verdict_hdr *vhdr;
+       enum ip_conntrack_info ctinfo;
        struct nfqnl_instance *queue;
-       unsigned int verdict;
        struct nf_queue_entry *entry;
-       enum ip_conntrack_info ctinfo;
        struct nfnl_ct_hook *nfnl_ct;
        struct nf_conn *ct = NULL;
-       struct nfnl_queue_net *q = nfnl_queue_pernet(net);
+       unsigned int verdict;
        int err;
 
        queue = verdict_instance_lookup(q, queue_num,
 
        if (nfqa[NFQA_CT]) {
                if (nfnl_ct != NULL)
-                       ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo);
+                       ct = nfqnl_ct_parse(nfnl_ct, info->nlh, nfqa, entry,
+                                           &ctinfo);
        }
 
        if (entry->state.pf == PF_BRIDGE) {
        return 0;
 }
 
-static int nfqnl_recv_unsupp(struct net *net, struct sock *ctnl,
-                            struct sk_buff *skb, const struct nlmsghdr *nlh,
-                            const struct nlattr * const nfqa[],
-                            struct netlink_ext_ack *extack)
+static int nfqnl_recv_unsupp(struct sk_buff *skb, const struct nfnl_info *info,
+                            const struct nlattr * const cda[])
 {
        return -ENOTSUPP;
 }