Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nfnetlink: consolidate callback types

Add enum nfnl_callback_type to identify the callback type to provide one
single callback.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+271 -124
+10 -6
include/linux/netfilter/nfnetlink.h
··· 14 14 struct netlink_ext_ack *extack; 15 15 }; 16 16 17 + enum nfnl_callback_type { 18 + NFNL_CB_UNSPEC = 0, 19 + NFNL_CB_MUTEX, 20 + NFNL_CB_RCU, 21 + NFNL_CB_BATCH, 22 + }; 23 + 17 24 struct nfnl_callback { 18 25 int (*call)(struct sk_buff *skb, const struct nfnl_info *info, 19 26 const struct nlattr * const cda[]); 20 - int (*call_rcu)(struct sk_buff *skb, const struct nfnl_info *info, 21 - const struct nlattr * const cda[]); 22 - int (*call_batch)(struct sk_buff *skb, const struct nfnl_info *info, 23 - const struct nlattr * const cda[]); 24 - const struct nla_policy *policy; /* netlink attribute policy */ 25 - const u_int16_t attr_count; /* number of nlattr's */ 27 + const struct nla_policy *policy; 28 + enum nfnl_callback_type type; 29 + __u16 attr_count; 26 30 }; 27 31 28 32 enum nfnl_abort_action {
+16
net/netfilter/ipset/ip_set_core.c
··· 2108 2108 static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = { 2109 2109 [IPSET_CMD_NONE] = { 2110 2110 .call = ip_set_none, 2111 + .type = NFNL_CB_MUTEX, 2111 2112 .attr_count = IPSET_ATTR_CMD_MAX, 2112 2113 }, 2113 2114 [IPSET_CMD_CREATE] = { 2114 2115 .call = ip_set_create, 2116 + .type = NFNL_CB_MUTEX, 2115 2117 .attr_count = IPSET_ATTR_CMD_MAX, 2116 2118 .policy = ip_set_create_policy, 2117 2119 }, 2118 2120 [IPSET_CMD_DESTROY] = { 2119 2121 .call = ip_set_destroy, 2122 + .type = NFNL_CB_MUTEX, 2120 2123 .attr_count = IPSET_ATTR_CMD_MAX, 2121 2124 .policy = ip_set_setname_policy, 2122 2125 }, 2123 2126 [IPSET_CMD_FLUSH] = { 2124 2127 .call = ip_set_flush, 2128 + .type = NFNL_CB_MUTEX, 2125 2129 .attr_count = IPSET_ATTR_CMD_MAX, 2126 2130 .policy = ip_set_setname_policy, 2127 2131 }, 2128 2132 [IPSET_CMD_RENAME] = { 2129 2133 .call = ip_set_rename, 2134 + .type = NFNL_CB_MUTEX, 2130 2135 .attr_count = IPSET_ATTR_CMD_MAX, 2131 2136 .policy = ip_set_setname2_policy, 2132 2137 }, 2133 2138 [IPSET_CMD_SWAP] = { 2134 2139 .call = ip_set_swap, 2140 + .type = NFNL_CB_MUTEX, 2135 2141 .attr_count = IPSET_ATTR_CMD_MAX, 2136 2142 .policy = ip_set_setname2_policy, 2137 2143 }, 2138 2144 [IPSET_CMD_LIST] = { 2139 2145 .call = ip_set_dump, 2146 + .type = NFNL_CB_MUTEX, 2140 2147 .attr_count = IPSET_ATTR_CMD_MAX, 2141 2148 .policy = ip_set_dump_policy, 2142 2149 }, 2143 2150 [IPSET_CMD_SAVE] = { 2144 2151 .call = ip_set_dump, 2152 + .type = NFNL_CB_MUTEX, 2145 2153 .attr_count = IPSET_ATTR_CMD_MAX, 2146 2154 .policy = ip_set_setname_policy, 2147 2155 }, 2148 2156 [IPSET_CMD_ADD] = { 2149 2157 .call = ip_set_uadd, 2158 + .type = NFNL_CB_MUTEX, 2150 2159 .attr_count = IPSET_ATTR_CMD_MAX, 2151 2160 .policy = ip_set_adt_policy, 2152 2161 }, 2153 2162 [IPSET_CMD_DEL] = { 2154 2163 .call = ip_set_udel, 2164 + .type = NFNL_CB_MUTEX, 2155 2165 .attr_count = IPSET_ATTR_CMD_MAX, 2156 2166 .policy = ip_set_adt_policy, 2157 2167 }, 2158 2168 [IPSET_CMD_TEST] = { 2159 2169 .call = ip_set_utest, 2170 + .type = NFNL_CB_MUTEX, 2160 2171 .attr_count = IPSET_ATTR_CMD_MAX, 2161 2172 .policy = ip_set_adt_policy, 2162 2173 }, 2163 2174 [IPSET_CMD_HEADER] = { 2164 2175 .call = ip_set_header, 2176 + .type = NFNL_CB_MUTEX, 2165 2177 .attr_count = IPSET_ATTR_CMD_MAX, 2166 2178 .policy = ip_set_setname_policy, 2167 2179 }, 2168 2180 [IPSET_CMD_TYPE] = { 2169 2181 .call = ip_set_type, 2182 + .type = NFNL_CB_MUTEX, 2170 2183 .attr_count = IPSET_ATTR_CMD_MAX, 2171 2184 .policy = ip_set_type_policy, 2172 2185 }, 2173 2186 [IPSET_CMD_PROTOCOL] = { 2174 2187 .call = ip_set_protocol, 2188 + .type = NFNL_CB_MUTEX, 2175 2189 .attr_count = IPSET_ATTR_CMD_MAX, 2176 2190 .policy = ip_set_protocol_policy, 2177 2191 }, 2178 2192 [IPSET_CMD_GET_BYNAME] = { 2179 2193 .call = ip_set_byname, 2194 + .type = NFNL_CB_MUTEX, 2180 2195 .attr_count = IPSET_ATTR_CMD_MAX, 2181 2196 .policy = ip_set_setname_policy, 2182 2197 }, 2183 2198 [IPSET_CMD_GET_BYINDEX] = { 2184 2199 .call = ip_set_byindex, 2200 + .type = NFNL_CB_MUTEX, 2185 2201 .attr_count = IPSET_ATTR_CMD_MAX, 2186 2202 .policy = ip_set_index_policy, 2187 2203 },
+62 -26
net/netfilter/nf_conntrack_netlink.c
··· 3751 3751 #endif 3752 3752 3753 3753 static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { 3754 - [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack, 3755 - .attr_count = CTA_MAX, 3756 - .policy = ct_nla_policy }, 3757 - [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack, 3758 - .attr_count = CTA_MAX, 3759 - .policy = ct_nla_policy }, 3760 - [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack, 3761 - .attr_count = CTA_MAX, 3762 - .policy = ct_nla_policy }, 3763 - [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, 3764 - .attr_count = CTA_MAX, 3765 - .policy = ct_nla_policy }, 3766 - [IPCTNL_MSG_CT_GET_STATS_CPU] = { .call = ctnetlink_stat_ct_cpu }, 3767 - [IPCTNL_MSG_CT_GET_STATS] = { .call = ctnetlink_stat_ct }, 3768 - [IPCTNL_MSG_CT_GET_DYING] = { .call = ctnetlink_get_ct_dying }, 3769 - [IPCTNL_MSG_CT_GET_UNCONFIRMED] = { .call = ctnetlink_get_ct_unconfirmed }, 3754 + [IPCTNL_MSG_CT_NEW] = { 3755 + .call = ctnetlink_new_conntrack, 3756 + .type = NFNL_CB_MUTEX, 3757 + .attr_count = CTA_MAX, 3758 + .policy = ct_nla_policy 3759 + }, 3760 + [IPCTNL_MSG_CT_GET] = { 3761 + .call = ctnetlink_get_conntrack, 3762 + .type = NFNL_CB_MUTEX, 3763 + .attr_count = CTA_MAX, 3764 + .policy = ct_nla_policy 3765 + }, 3766 + [IPCTNL_MSG_CT_DELETE] = { 3767 + .call = ctnetlink_del_conntrack, 3768 + .type = NFNL_CB_MUTEX, 3769 + .attr_count = CTA_MAX, 3770 + .policy = ct_nla_policy 3771 + }, 3772 + [IPCTNL_MSG_CT_GET_CTRZERO] = { 3773 + .call = ctnetlink_get_conntrack, 3774 + .type = NFNL_CB_MUTEX, 3775 + .attr_count = CTA_MAX, 3776 + .policy = ct_nla_policy 3777 + }, 3778 + [IPCTNL_MSG_CT_GET_STATS_CPU] = { 3779 + .call = ctnetlink_stat_ct_cpu, 3780 + .type = NFNL_CB_MUTEX, 3781 + }, 3782 + [IPCTNL_MSG_CT_GET_STATS] = { 3783 + .call = ctnetlink_stat_ct, 3784 + .type = NFNL_CB_MUTEX, 3785 + }, 3786 + [IPCTNL_MSG_CT_GET_DYING] = { 3787 + .call = ctnetlink_get_ct_dying, 3788 + .type = NFNL_CB_MUTEX, 3789 + }, 3790 + [IPCTNL_MSG_CT_GET_UNCONFIRMED] = { 3791 + .call = ctnetlink_get_ct_unconfirmed, 3792 + .type = NFNL_CB_MUTEX, 3793 + }, 3770 3794 }; 3771 3795 3772 3796 static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = { 3773 - [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect, 3774 - .attr_count = CTA_EXPECT_MAX, 3775 - .policy = exp_nla_policy }, 3776 - [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect, 3777 - .attr_count = CTA_EXPECT_MAX, 3778 - .policy = exp_nla_policy }, 3779 - [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, 3780 - .attr_count = CTA_EXPECT_MAX, 3781 - .policy = exp_nla_policy }, 3782 - [IPCTNL_MSG_EXP_GET_STATS_CPU] = { .call = ctnetlink_stat_exp_cpu }, 3797 + [IPCTNL_MSG_EXP_GET] = { 3798 + .call = ctnetlink_get_expect, 3799 + .type = NFNL_CB_MUTEX, 3800 + .attr_count = CTA_EXPECT_MAX, 3801 + .policy = exp_nla_policy 3802 + }, 3803 + [IPCTNL_MSG_EXP_NEW] = { 3804 + .call = ctnetlink_new_expect, 3805 + .type = NFNL_CB_MUTEX, 3806 + .attr_count = CTA_EXPECT_MAX, 3807 + .policy = exp_nla_policy 3808 + }, 3809 + [IPCTNL_MSG_EXP_DELETE] = { 3810 + .call = ctnetlink_del_expect, 3811 + .type = NFNL_CB_MUTEX, 3812 + .attr_count = CTA_EXPECT_MAX, 3813 + .policy = exp_nla_policy 3814 + }, 3815 + [IPCTNL_MSG_EXP_GET_STATS_CPU] = { 3816 + .call = ctnetlink_stat_exp_cpu, 3817 + .type = NFNL_CB_MUTEX, 3818 + }, 3783 3819 }; 3784 3820 3785 3821 static const struct nfnetlink_subsystem ctnl_subsys = {
+46 -23
net/netfilter/nf_tables_api.c
··· 7554 7554 7555 7555 static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { 7556 7556 [NFT_MSG_NEWTABLE] = { 7557 - .call_batch = nf_tables_newtable, 7557 + .call = nf_tables_newtable, 7558 + .type = NFNL_CB_BATCH, 7558 7559 .attr_count = NFTA_TABLE_MAX, 7559 7560 .policy = nft_table_policy, 7560 7561 }, 7561 7562 [NFT_MSG_GETTABLE] = { 7562 - .call_rcu = nf_tables_gettable, 7563 + .call = nf_tables_gettable, 7564 + .type = NFNL_CB_RCU, 7563 7565 .attr_count = NFTA_TABLE_MAX, 7564 7566 .policy = nft_table_policy, 7565 7567 }, 7566 7568 [NFT_MSG_DELTABLE] = { 7567 - .call_batch = nf_tables_deltable, 7569 + .call = nf_tables_deltable, 7570 + .type = NFNL_CB_BATCH, 7568 7571 .attr_count = NFTA_TABLE_MAX, 7569 7572 .policy = nft_table_policy, 7570 7573 }, 7571 7574 [NFT_MSG_NEWCHAIN] = { 7572 - .call_batch = nf_tables_newchain, 7575 + .call = nf_tables_newchain, 7576 + .type = NFNL_CB_BATCH, 7573 7577 .attr_count = NFTA_CHAIN_MAX, 7574 7578 .policy = nft_chain_policy, 7575 7579 }, 7576 7580 [NFT_MSG_GETCHAIN] = { 7577 - .call_rcu = nf_tables_getchain, 7581 + .call = nf_tables_getchain, 7582 + .type = NFNL_CB_RCU, 7578 7583 .attr_count = NFTA_CHAIN_MAX, 7579 7584 .policy = nft_chain_policy, 7580 7585 }, 7581 7586 [NFT_MSG_DELCHAIN] = { 7582 - .call_batch = nf_tables_delchain, 7587 + .call = nf_tables_delchain, 7588 + .type = NFNL_CB_BATCH, 7583 7589 .attr_count = NFTA_CHAIN_MAX, 7584 7590 .policy = nft_chain_policy, 7585 7591 }, 7586 7592 [NFT_MSG_NEWRULE] = { 7587 - .call_batch = nf_tables_newrule, 7593 + .call = nf_tables_newrule, 7594 + .type = NFNL_CB_BATCH, 7588 7595 .attr_count = NFTA_RULE_MAX, 7589 7596 .policy = nft_rule_policy, 7590 7597 }, 7591 7598 [NFT_MSG_GETRULE] = { 7592 - .call_rcu = nf_tables_getrule, 7599 + .call = nf_tables_getrule, 7600 + .type = NFNL_CB_RCU, 7593 7601 .attr_count = NFTA_RULE_MAX, 7594 7602 .policy = nft_rule_policy, 7595 7603 }, 7596 7604 [NFT_MSG_DELRULE] = { 7597 - .call_batch = nf_tables_delrule, 7605 + .call = nf_tables_delrule, 7606 + .type = NFNL_CB_BATCH, 7598 7607 .attr_count = NFTA_RULE_MAX, 7599 7608 .policy = nft_rule_policy, 7600 7609 }, 7601 7610 [NFT_MSG_NEWSET] = { 7602 - .call_batch = nf_tables_newset, 7611 + .call = nf_tables_newset, 7612 + .type = NFNL_CB_BATCH, 7603 7613 .attr_count = NFTA_SET_MAX, 7604 7614 .policy = nft_set_policy, 7605 7615 }, 7606 7616 [NFT_MSG_GETSET] = { 7607 - .call_rcu = nf_tables_getset, 7617 + .call = nf_tables_getset, 7618 + .type = NFNL_CB_RCU, 7608 7619 .attr_count = NFTA_SET_MAX, 7609 7620 .policy = nft_set_policy, 7610 7621 }, 7611 7622 [NFT_MSG_DELSET] = { 7612 - .call_batch = nf_tables_delset, 7623 + .call = nf_tables_delset, 7624 + .type = NFNL_CB_BATCH, 7613 7625 .attr_count = NFTA_SET_MAX, 7614 7626 .policy = nft_set_policy, 7615 7627 }, 7616 7628 [NFT_MSG_NEWSETELEM] = { 7617 - .call_batch = nf_tables_newsetelem, 7629 + .call = nf_tables_newsetelem, 7630 + .type = NFNL_CB_BATCH, 7618 7631 .attr_count = NFTA_SET_ELEM_LIST_MAX, 7619 7632 .policy = nft_set_elem_list_policy, 7620 7633 }, 7621 7634 [NFT_MSG_GETSETELEM] = { 7622 - .call_rcu = nf_tables_getsetelem, 7635 + .call = nf_tables_getsetelem, 7636 + .type = NFNL_CB_RCU, 7623 7637 .attr_count = NFTA_SET_ELEM_LIST_MAX, 7624 7638 .policy = nft_set_elem_list_policy, 7625 7639 }, 7626 7640 [NFT_MSG_DELSETELEM] = { 7627 - .call_batch = nf_tables_delsetelem, 7641 + .call = nf_tables_delsetelem, 7642 + .type = NFNL_CB_BATCH, 7628 7643 .attr_count = NFTA_SET_ELEM_LIST_MAX, 7629 7644 .policy = nft_set_elem_list_policy, 7630 7645 }, 7631 7646 [NFT_MSG_GETGEN] = { 7632 - .call_rcu = nf_tables_getgen, 7647 + .call = nf_tables_getgen, 7648 + .type = NFNL_CB_RCU, 7633 7649 }, 7634 7650 [NFT_MSG_NEWOBJ] = { 7635 - .call_batch = nf_tables_newobj, 7651 + .call = nf_tables_newobj, 7652 + .type = NFNL_CB_BATCH, 7636 7653 .attr_count = NFTA_OBJ_MAX, 7637 7654 .policy = nft_obj_policy, 7638 7655 }, 7639 7656 [NFT_MSG_GETOBJ] = { 7640 - .call_rcu = nf_tables_getobj, 7657 + .call = nf_tables_getobj, 7658 + .type = NFNL_CB_RCU, 7641 7659 .attr_count = NFTA_OBJ_MAX, 7642 7660 .policy = nft_obj_policy, 7643 7661 }, 7644 7662 [NFT_MSG_DELOBJ] = { 7645 - .call_batch = nf_tables_delobj, 7663 + .call = nf_tables_delobj, 7664 + .type = NFNL_CB_BATCH, 7646 7665 .attr_count = NFTA_OBJ_MAX, 7647 7666 .policy = nft_obj_policy, 7648 7667 }, 7649 7668 [NFT_MSG_GETOBJ_RESET] = { 7650 - .call_rcu = nf_tables_getobj, 7669 + .call = nf_tables_getobj, 7670 + .type = NFNL_CB_RCU, 7651 7671 .attr_count = NFTA_OBJ_MAX, 7652 7672 .policy = nft_obj_policy, 7653 7673 }, 7654 7674 [NFT_MSG_NEWFLOWTABLE] = { 7655 - .call_batch = nf_tables_newflowtable, 7675 + .call = nf_tables_newflowtable, 7676 + .type = NFNL_CB_BATCH, 7656 7677 .attr_count = NFTA_FLOWTABLE_MAX, 7657 7678 .policy = nft_flowtable_policy, 7658 7679 }, 7659 7680 [NFT_MSG_GETFLOWTABLE] = { 7660 - .call_rcu = nf_tables_getflowtable, 7681 + .call = nf_tables_getflowtable, 7682 + .type = NFNL_CB_RCU, 7661 7683 .attr_count = NFTA_FLOWTABLE_MAX, 7662 7684 .policy = nft_flowtable_policy, 7663 7685 }, 7664 7686 [NFT_MSG_DELFLOWTABLE] = { 7665 - .call_batch = nf_tables_delflowtable, 7687 + .call = nf_tables_delflowtable, 7688 + .type = NFNL_CB_BATCH, 7666 7689 .attr_count = NFTA_FLOWTABLE_MAX, 7667 7690 .policy = nft_flowtable_policy, 7668 7691 },
+23 -14
net/netfilter/nfnetlink.c
··· 273 273 return err; 274 274 } 275 275 276 - if (nc->call_rcu) { 277 - err = nc->call_rcu(skb, &info, 278 - (const struct nlattr **)cda); 276 + if (!nc->call) { 279 277 rcu_read_unlock(); 280 - } else { 278 + return -EINVAL; 279 + } 280 + 281 + switch (nc->type) { 282 + case NFNL_CB_RCU: 283 + err = nc->call(skb, &info, (const struct nlattr **)cda); 284 + rcu_read_unlock(); 285 + break; 286 + case NFNL_CB_MUTEX: 281 287 rcu_read_unlock(); 282 288 nfnl_lock(subsys_id); 283 289 if (nfnl_dereference_protected(subsys_id) != ss || 284 290 nfnetlink_find_client(type, ss) != nc) { 285 291 err = -EAGAIN; 286 - } else if (nc->call) { 287 - err = nc->call(skb, &info, 288 - (const struct nlattr **)cda); 289 - } else { 290 - err = -EINVAL; 292 + break; 291 293 } 294 + err = nc->call(skb, &info, (const struct nlattr **)cda); 292 295 nfnl_unlock(subsys_id); 296 + break; 297 + default: 298 + err = -EINVAL; 299 + break; 293 300 } 294 301 if (err == -EAGAIN) 295 302 goto replay; ··· 474 467 goto ack; 475 468 } 476 469 470 + if (nc->type != NFNL_CB_BATCH) { 471 + err = -EINVAL; 472 + goto ack; 473 + } 474 + 477 475 { 478 476 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); 479 477 struct nfnl_net *nfnlnet = nfnl_pernet(net); 480 - u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); 481 478 struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1]; 482 479 struct nlattr *attr = (void *)nlh + min_len; 480 + u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); 483 481 int attrlen = nlh->nlmsg_len - min_len; 484 482 struct nfnl_info info = { 485 483 .net = net, ··· 506 494 if (err < 0) 507 495 goto ack; 508 496 509 - if (nc->call_batch) { 510 - err = nc->call_batch(skb, &info, 511 - (const struct nlattr **)cda); 512 - } 497 + err = nc->call(skb, &info, (const struct nlattr **)cda); 513 498 514 499 /* The lock was released to autoload some module, we 515 500 * have to abort and start from scratch using the
+6 -3
net/netfilter/nft_compat.c
··· 698 698 }; 699 699 700 700 static const struct nfnl_callback nfnl_nft_compat_cb[NFNL_MSG_COMPAT_MAX] = { 701 - [NFNL_MSG_COMPAT_GET] = { .call_rcu = nfnl_compat_get_rcu, 702 - .attr_count = NFTA_COMPAT_MAX, 703 - .policy = nfnl_compat_policy_get }, 701 + [NFNL_MSG_COMPAT_GET] = { 702 + .call = nfnl_compat_get_rcu, 703 + .type = NFNL_CB_RCU, 704 + .attr_count = NFTA_COMPAT_MAX, 705 + .policy = nfnl_compat_policy_get 706 + }, 704 707 }; 705 708 706 709 static const struct nfnetlink_subsystem nfnl_compat_subsys = {