Commit 50f2db9e authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso
Browse files

netfilter: nfnetlink: consolidate callback types



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

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 7dab8ee3
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -14,15 +14,19 @@ struct nfnl_info {
	struct netlink_ext_ack	*extack;
};

enum nfnl_callback_type {
	NFNL_CB_UNSPEC	= 0,
	NFNL_CB_MUTEX,
	NFNL_CB_RCU,
	NFNL_CB_BATCH,
};

struct nfnl_callback {
	int (*call)(struct sk_buff *skb, const struct nfnl_info *info,
		    const struct nlattr * const cda[]);
	int (*call_rcu)(struct sk_buff *skb, const struct nfnl_info *info,
			const struct nlattr * const cda[]);
	int (*call_batch)(struct sk_buff *skb, const struct nfnl_info *info,
			  const struct nlattr * const cda[]);
	const struct nla_policy *policy;	/* netlink attribute policy */
	const u_int16_t attr_count;		/* number of nlattr's */
	const struct nla_policy	*policy;
	enum nfnl_callback_type	type;
	__u16			attr_count;
};

enum nfnl_abort_action {
+16 −0
Original line number Diff line number Diff line
@@ -2108,80 +2108,96 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info,
static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
	[IPSET_CMD_NONE]	= {
		.call		= ip_set_none,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
	},
	[IPSET_CMD_CREATE]	= {
		.call		= ip_set_create,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_create_policy,
	},
	[IPSET_CMD_DESTROY]	= {
		.call		= ip_set_destroy,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname_policy,
	},
	[IPSET_CMD_FLUSH]	= {
		.call		= ip_set_flush,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname_policy,
	},
	[IPSET_CMD_RENAME]	= {
		.call		= ip_set_rename,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname2_policy,
	},
	[IPSET_CMD_SWAP]	= {
		.call		= ip_set_swap,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname2_policy,
	},
	[IPSET_CMD_LIST]	= {
		.call		= ip_set_dump,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_dump_policy,
	},
	[IPSET_CMD_SAVE]	= {
		.call		= ip_set_dump,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname_policy,
	},
	[IPSET_CMD_ADD]	= {
		.call		= ip_set_uadd,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_adt_policy,
	},
	[IPSET_CMD_DEL]	= {
		.call		= ip_set_udel,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_adt_policy,
	},
	[IPSET_CMD_TEST]	= {
		.call		= ip_set_utest,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_adt_policy,
	},
	[IPSET_CMD_HEADER]	= {
		.call		= ip_set_header,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname_policy,
	},
	[IPSET_CMD_TYPE]	= {
		.call		= ip_set_type,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_type_policy,
	},
	[IPSET_CMD_PROTOCOL]	= {
		.call		= ip_set_protocol,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_protocol_policy,
	},
	[IPSET_CMD_GET_BYNAME]	= {
		.call		= ip_set_byname,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_setname_policy,
	},
	[IPSET_CMD_GET_BYINDEX]	= {
		.call		= ip_set_byindex,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= IPSET_ATTR_CMD_MAX,
		.policy		= ip_set_index_policy,
	},
+62 −26
Original line number Diff line number Diff line
@@ -3751,35 +3751,71 @@ static struct nf_exp_event_notifier ctnl_notifier_exp = {
#endif

static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
	[IPCTNL_MSG_CT_NEW]		= { .call = ctnetlink_new_conntrack,
	[IPCTNL_MSG_CT_NEW]	= {
		.call		= ctnetlink_new_conntrack,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_MAX,
					    .policy = ct_nla_policy },
	[IPCTNL_MSG_CT_GET] 		= { .call = ctnetlink_get_conntrack,
		.policy		= ct_nla_policy
	},
	[IPCTNL_MSG_CT_GET]	= {
		.call		= ctnetlink_get_conntrack,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_MAX,
					    .policy = ct_nla_policy },
	[IPCTNL_MSG_CT_DELETE]  	= { .call = ctnetlink_del_conntrack,
		.policy		= ct_nla_policy
	},
	[IPCTNL_MSG_CT_DELETE]	= {
		.call		= ctnetlink_del_conntrack,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_MAX,
					    .policy = ct_nla_policy },
	[IPCTNL_MSG_CT_GET_CTRZERO] 	= { .call = ctnetlink_get_conntrack,
		.policy		= ct_nla_policy
	},
	[IPCTNL_MSG_CT_GET_CTRZERO] = {
		.call		= ctnetlink_get_conntrack,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_MAX,
					    .policy = ct_nla_policy },
	[IPCTNL_MSG_CT_GET_STATS_CPU]	= { .call = ctnetlink_stat_ct_cpu },
	[IPCTNL_MSG_CT_GET_STATS]	= { .call = ctnetlink_stat_ct },
	[IPCTNL_MSG_CT_GET_DYING]	= { .call = ctnetlink_get_ct_dying },
	[IPCTNL_MSG_CT_GET_UNCONFIRMED]	= { .call = ctnetlink_get_ct_unconfirmed },
		.policy		= ct_nla_policy
	},
	[IPCTNL_MSG_CT_GET_STATS_CPU] = {
		.call		= ctnetlink_stat_ct_cpu,
		.type		= NFNL_CB_MUTEX,
	},
	[IPCTNL_MSG_CT_GET_STATS] = {
		.call		= ctnetlink_stat_ct,
		.type		= NFNL_CB_MUTEX,
	},
	[IPCTNL_MSG_CT_GET_DYING] = {
		.call		= ctnetlink_get_ct_dying,
		.type		= NFNL_CB_MUTEX,
	},
	[IPCTNL_MSG_CT_GET_UNCONFIRMED]	= {
		.call		= ctnetlink_get_ct_unconfirmed,
		.type		= NFNL_CB_MUTEX,
	},
};

static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
	[IPCTNL_MSG_EXP_GET]		= { .call = ctnetlink_get_expect,
	[IPCTNL_MSG_EXP_GET] = {
		.call		= ctnetlink_get_expect,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_EXPECT_MAX,
					    .policy = exp_nla_policy },
	[IPCTNL_MSG_EXP_NEW]		= { .call = ctnetlink_new_expect,
		.policy		= exp_nla_policy
	},
	[IPCTNL_MSG_EXP_NEW] = {
		.call		= ctnetlink_new_expect,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_EXPECT_MAX,
					    .policy = exp_nla_policy },
	[IPCTNL_MSG_EXP_DELETE]		= { .call = ctnetlink_del_expect,
		.policy		= exp_nla_policy
	},
	[IPCTNL_MSG_EXP_DELETE] = {
		.call		= ctnetlink_del_expect,
		.type		= NFNL_CB_MUTEX,
		.attr_count	= CTA_EXPECT_MAX,
					    .policy = exp_nla_policy },
	[IPCTNL_MSG_EXP_GET_STATS_CPU]	= { .call = ctnetlink_stat_exp_cpu },
		.policy		= exp_nla_policy
	},
	[IPCTNL_MSG_EXP_GET_STATS_CPU] = {
		.call		= ctnetlink_stat_exp_cpu,
		.type		= NFNL_CB_MUTEX,
	},
};

static const struct nfnetlink_subsystem ctnl_subsys = {
+46 −23
Original line number Diff line number Diff line
@@ -7554,115 +7554,138 @@ static int nf_tables_getgen(struct sk_buff *skb, const struct nfnl_info *info,

static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
	[NFT_MSG_NEWTABLE] = {
		.call_batch	= nf_tables_newtable,
		.call		= nf_tables_newtable,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_TABLE_MAX,
		.policy		= nft_table_policy,
	},
	[NFT_MSG_GETTABLE] = {
		.call_rcu	= nf_tables_gettable,
		.call		= nf_tables_gettable,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_TABLE_MAX,
		.policy		= nft_table_policy,
	},
	[NFT_MSG_DELTABLE] = {
		.call_batch	= nf_tables_deltable,
		.call		= nf_tables_deltable,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_TABLE_MAX,
		.policy		= nft_table_policy,
	},
	[NFT_MSG_NEWCHAIN] = {
		.call_batch	= nf_tables_newchain,
		.call		= nf_tables_newchain,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_CHAIN_MAX,
		.policy		= nft_chain_policy,
	},
	[NFT_MSG_GETCHAIN] = {
		.call_rcu	= nf_tables_getchain,
		.call		= nf_tables_getchain,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_CHAIN_MAX,
		.policy		= nft_chain_policy,
	},
	[NFT_MSG_DELCHAIN] = {
		.call_batch	= nf_tables_delchain,
		.call		= nf_tables_delchain,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_CHAIN_MAX,
		.policy		= nft_chain_policy,
	},
	[NFT_MSG_NEWRULE] = {
		.call_batch	= nf_tables_newrule,
		.call		= nf_tables_newrule,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_RULE_MAX,
		.policy		= nft_rule_policy,
	},
	[NFT_MSG_GETRULE] = {
		.call_rcu	= nf_tables_getrule,
		.call		= nf_tables_getrule,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_RULE_MAX,
		.policy		= nft_rule_policy,
	},
	[NFT_MSG_DELRULE] = {
		.call_batch	= nf_tables_delrule,
		.call		= nf_tables_delrule,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_RULE_MAX,
		.policy		= nft_rule_policy,
	},
	[NFT_MSG_NEWSET] = {
		.call_batch	= nf_tables_newset,
		.call		= nf_tables_newset,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_SET_MAX,
		.policy		= nft_set_policy,
	},
	[NFT_MSG_GETSET] = {
		.call_rcu	= nf_tables_getset,
		.call		= nf_tables_getset,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_SET_MAX,
		.policy		= nft_set_policy,
	},
	[NFT_MSG_DELSET] = {
		.call_batch	= nf_tables_delset,
		.call		= nf_tables_delset,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_SET_MAX,
		.policy		= nft_set_policy,
	},
	[NFT_MSG_NEWSETELEM] = {
		.call_batch	= nf_tables_newsetelem,
		.call		= nf_tables_newsetelem,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_SET_ELEM_LIST_MAX,
		.policy		= nft_set_elem_list_policy,
	},
	[NFT_MSG_GETSETELEM] = {
		.call_rcu	= nf_tables_getsetelem,
		.call		= nf_tables_getsetelem,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_SET_ELEM_LIST_MAX,
		.policy		= nft_set_elem_list_policy,
	},
	[NFT_MSG_DELSETELEM] = {
		.call_batch	= nf_tables_delsetelem,
		.call		= nf_tables_delsetelem,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_SET_ELEM_LIST_MAX,
		.policy		= nft_set_elem_list_policy,
	},
	[NFT_MSG_GETGEN] = {
		.call_rcu	= nf_tables_getgen,
		.call		= nf_tables_getgen,
		.type		= NFNL_CB_RCU,
	},
	[NFT_MSG_NEWOBJ] = {
		.call_batch	= nf_tables_newobj,
		.call		= nf_tables_newobj,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_OBJ_MAX,
		.policy		= nft_obj_policy,
	},
	[NFT_MSG_GETOBJ] = {
		.call_rcu	= nf_tables_getobj,
		.call		= nf_tables_getobj,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_OBJ_MAX,
		.policy		= nft_obj_policy,
	},
	[NFT_MSG_DELOBJ] = {
		.call_batch	= nf_tables_delobj,
		.call		= nf_tables_delobj,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_OBJ_MAX,
		.policy		= nft_obj_policy,
	},
	[NFT_MSG_GETOBJ_RESET] = {
		.call_rcu	= nf_tables_getobj,
		.call		= nf_tables_getobj,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_OBJ_MAX,
		.policy		= nft_obj_policy,
	},
	[NFT_MSG_NEWFLOWTABLE] = {
		.call_batch	= nf_tables_newflowtable,
		.call		= nf_tables_newflowtable,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_FLOWTABLE_MAX,
		.policy		= nft_flowtable_policy,
	},
	[NFT_MSG_GETFLOWTABLE] = {
		.call_rcu	= nf_tables_getflowtable,
		.call		= nf_tables_getflowtable,
		.type		= NFNL_CB_RCU,
		.attr_count	= NFTA_FLOWTABLE_MAX,
		.policy		= nft_flowtable_policy,
	},
	[NFT_MSG_DELFLOWTABLE] = {
		.call_batch	= nf_tables_delflowtable,
		.call		= nf_tables_delflowtable,
		.type		= NFNL_CB_BATCH,
		.attr_count	= NFTA_FLOWTABLE_MAX,
		.policy		= nft_flowtable_policy,
	},
+23 −14
Original line number Diff line number Diff line
@@ -273,23 +273,30 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
			return err;
		}

		if (nc->call_rcu) {
			err = nc->call_rcu(skb, &info,
					   (const struct nlattr **)cda);
		if (!nc->call) {
			rcu_read_unlock();
		} else {
			return -EINVAL;
		}

		switch (nc->type) {
		case NFNL_CB_RCU:
			err = nc->call(skb, &info, (const struct nlattr **)cda);
			rcu_read_unlock();
			break;
		case NFNL_CB_MUTEX:
			rcu_read_unlock();
			nfnl_lock(subsys_id);
			if (nfnl_dereference_protected(subsys_id) != ss ||
			    nfnetlink_find_client(type, ss) != nc) {
				err = -EAGAIN;
			} else if (nc->call) {
				err = nc->call(skb, &info,
					       (const struct nlattr **)cda);
			} else {
				err = -EINVAL;
				break;
			}
			err = nc->call(skb, &info, (const struct nlattr **)cda);
			nfnl_unlock(subsys_id);
			break;
		default:
			err = -EINVAL;
			break;
		}
		if (err == -EAGAIN)
			goto replay;
@@ -467,12 +474,17 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
			goto ack;
		}

		if (nc->type != NFNL_CB_BATCH) {
			err = -EINVAL;
			goto ack;
		}

		{
			int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
			struct nfnl_net *nfnlnet = nfnl_pernet(net);
			u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
			struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
			struct nlattr *attr = (void *)nlh + min_len;
			u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
			int attrlen = nlh->nlmsg_len - min_len;
			struct nfnl_info info = {
				.net	= net,
@@ -494,10 +506,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
			if (err < 0)
				goto ack;

			if (nc->call_batch) {
				err = nc->call_batch(skb, &info,
						     (const struct nlattr **)cda);
			}
			err = nc->call(skb, &info, (const struct nlattr **)cda);

			/* The lock was released to autoload some module, we
			 * have to abort and start from scratch using the
Loading