Commit a6555365 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso
Browse files

netfilter: nfnetlink: add struct nfnl_info and pass it to callbacks



Add a new structure to reduce callback footprint and to facilite
extensions of the nfnetlink callback interface in the future.

Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent d59d2f82
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -7,11 +7,16 @@
#include <net/netlink.h>
#include <uapi/linux/netfilter/nfnetlink.h>

struct nfnl_info {
	struct net		*net;
	struct sock		*sk;
	const struct nlmsghdr	*nlh;
	struct netlink_ext_ack	*extack;
};

struct nfnl_callback {
	int (*call)(struct net *net, struct sock *nl, struct sk_buff *skb,
		    const struct nlmsghdr *nlh,
		    const struct nlattr * const cda[],
		    struct netlink_ext_ack *extack);
	int (*call)(struct sk_buff *skb, const struct nfnl_info *info,
		    const struct nlattr * const cda[]);
	int (*call_rcu)(struct net *net, struct sock *nl, struct sk_buff *skb,
			const struct nlmsghdr *nlh,
			const struct nlattr * const cda[],
+62 −87
Original line number Diff line number Diff line
@@ -1031,26 +1031,22 @@ find_free_id(struct ip_set_net *inst, const char *name, ip_set_id_t *index,
	return 0;
}

static int ip_set_none(struct net *net, struct sock *ctnl, struct sk_buff *skb,
		       const struct nlmsghdr *nlh,
		       const struct nlattr * const attr[],
		       struct netlink_ext_ack *extack)
static int ip_set_none(struct sk_buff *skb, const struct nfnl_info *info,
		       const struct nlattr * const attr[])
{
	return -EOPNOTSUPP;
}

static int ip_set_create(struct net *net, struct sock *ctnl,
			 struct sk_buff *skb, const struct nlmsghdr *nlh,
			 const struct nlattr * const attr[],
			 struct netlink_ext_ack *extack)
static int ip_set_create(struct sk_buff *skb, const struct nfnl_info *info,
			 const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct ip_set *set, *clash = NULL;
	ip_set_id_t index = IPSET_INVALID_ID;
	struct nlattr *tb[IPSET_ATTR_CREATE_MAX + 1] = {};
	const char *name, *typename;
	u8 family, revision;
	u32 flags = flag_exist(nlh);
	u32 flags = flag_exist(info->nlh);
	int ret = 0;

	if (unlikely(protocol_min_failed(attr) ||
@@ -1101,7 +1097,7 @@ static int ip_set_create(struct net *net, struct sock *ctnl,
	/* Set create flags depending on the type revision */
	set->flags |= set->type->create_flags[revision];

	ret = set->type->create(net, set, tb, flags);
	ret = set->type->create(info->net, set, tb, flags);
	if (ret != 0)
		goto put_out;

@@ -1183,12 +1179,10 @@ ip_set_destroy_set(struct ip_set *set)
	kfree(set);
}

static int ip_set_destroy(struct net *net, struct sock *ctnl,
			  struct sk_buff *skb, const struct nlmsghdr *nlh,
			  const struct nlattr * const attr[],
			  struct netlink_ext_ack *extack)
static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info,
			  const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct ip_set *s;
	ip_set_id_t i;
	int ret = 0;
@@ -1230,7 +1224,7 @@ static int ip_set_destroy(struct net *net, struct sock *ctnl,
		/* Modified by ip_set_destroy() only, which is serialized */
		inst->is_destroyed = false;
	} else {
		u32 flags = flag_exist(nlh);
		u32 flags = flag_exist(info->nlh);
		s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
				    &i);
		if (!s) {
@@ -1264,12 +1258,10 @@ ip_set_flush_set(struct ip_set *set)
	ip_set_unlock(set);
}

static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb,
			const struct nlmsghdr *nlh,
			const struct nlattr * const attr[],
			struct netlink_ext_ack *extack)
static int ip_set_flush(struct sk_buff *skb, const struct nfnl_info *info,
			const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct ip_set *s;
	ip_set_id_t i;

@@ -1304,12 +1296,10 @@ ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
				    .len = IPSET_MAXNAMELEN - 1 },
};

static int ip_set_rename(struct net *net, struct sock *ctnl,
			 struct sk_buff *skb, const struct nlmsghdr *nlh,
			 const struct nlattr * const attr[],
			 struct netlink_ext_ack *extack)
static int ip_set_rename(struct sk_buff *skb, const struct nfnl_info *info,
			 const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct ip_set *set, *s;
	const char *name2;
	ip_set_id_t i;
@@ -1354,12 +1344,10 @@ static int ip_set_rename(struct net *net, struct sock *ctnl,
 * so the ip_set_list always contains valid pointers to the sets.
 */

static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb,
		       const struct nlmsghdr *nlh,
		       const struct nlattr * const attr[],
		       struct netlink_ext_ack *extack)
static int ip_set_swap(struct sk_buff *skb, const struct nfnl_info *info,
		       const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct ip_set *from, *to;
	ip_set_id_t from_id, to_id;
	char from_name[IPSET_MAXNAMELEN];
@@ -1669,10 +1657,8 @@ ip_set_dump_do(struct sk_buff *skb, struct netlink_callback *cb)
	return ret < 0 ? ret : skb->len;
}

static int ip_set_dump(struct net *net, struct sock *ctnl, struct sk_buff *skb,
		       const struct nlmsghdr *nlh,
		       const struct nlattr * const attr[],
		       struct netlink_ext_ack *extack)
static int ip_set_dump(struct sk_buff *skb, const struct nfnl_info *info,
		       const struct nlattr * const attr[])
{
	if (unlikely(protocol_min_failed(attr)))
		return -IPSET_ERR_PROTOCOL;
@@ -1683,7 +1669,7 @@ static int ip_set_dump(struct net *net, struct sock *ctnl, struct sk_buff *skb,
			.dump = ip_set_dump_do,
			.done = ip_set_dump_done,
		};
		return netlink_dump_start(ctnl, skb, nlh, &c);
		return netlink_dump_start(info->sk, skb, info->nlh, &c);
	}
}

@@ -1817,30 +1803,24 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
	return ret;
}

static int ip_set_uadd(struct net *net, struct sock *ctnl,
		       struct sk_buff *skb, const struct nlmsghdr *nlh,
		       const struct nlattr * const attr[],
		       struct netlink_ext_ack *extack)
static int ip_set_uadd(struct sk_buff *skb, const struct nfnl_info *info,
		       const struct nlattr * const attr[])
{
	return ip_set_ad(net, ctnl, skb,
			 IPSET_ADD, nlh, attr, extack);
	return ip_set_ad(info->net, info->sk, skb,
			 IPSET_ADD, info->nlh, attr, info->extack);
}

static int ip_set_udel(struct net *net, struct sock *ctnl,
		       struct sk_buff *skb, const struct nlmsghdr *nlh,
		       const struct nlattr * const attr[],
		       struct netlink_ext_ack *extack)
static int ip_set_udel(struct sk_buff *skb, const struct nfnl_info *info,
		       const struct nlattr * const attr[])
{
	return ip_set_ad(net, ctnl, skb,
			 IPSET_DEL, nlh, attr, extack);
	return ip_set_ad(info->net, info->sk, skb,
			 IPSET_DEL, info->nlh, attr, info->extack);
}

static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
			const struct nlmsghdr *nlh,
			const struct nlattr * const attr[],
			struct netlink_ext_ack *extack)
static int ip_set_utest(struct sk_buff *skb, const struct nfnl_info *info,
			const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct ip_set *set;
	struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
	int ret = 0;
@@ -1872,12 +1852,10 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,

/* Get headed data of a set */

static int ip_set_header(struct net *net, struct sock *ctnl,
			 struct sk_buff *skb, const struct nlmsghdr *nlh,
			 const struct nlattr * const attr[],
			 struct netlink_ext_ack *extack)
static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info,
			 const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	const struct ip_set *set;
	struct sk_buff *skb2;
	struct nlmsghdr *nlh2;
@@ -1895,7 +1873,7 @@ static int ip_set_header(struct net *net, struct sock *ctnl,
	if (!skb2)
		return -ENOMEM;

	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, info->nlh->nlmsg_seq, 0,
			 IPSET_CMD_HEADER);
	if (!nlh2)
		goto nlmsg_failure;
@@ -1907,7 +1885,8 @@ static int ip_set_header(struct net *net, struct sock *ctnl,
		goto nla_put_failure;
	nlmsg_end(skb2, nlh2);

	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (ret < 0)
		return ret;

@@ -1929,10 +1908,8 @@ static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
	[IPSET_ATTR_FAMILY]	= { .type = NLA_U8 },
};

static int ip_set_type(struct net *net, struct sock *ctnl, struct sk_buff *skb,
		       const struct nlmsghdr *nlh,
		       const struct nlattr * const attr[],
		       struct netlink_ext_ack *extack)
static int ip_set_type(struct sk_buff *skb, const struct nfnl_info *info,
		       const struct nlattr * const attr[])
{
	struct sk_buff *skb2;
	struct nlmsghdr *nlh2;
@@ -1955,7 +1932,7 @@ static int ip_set_type(struct net *net, struct sock *ctnl, struct sk_buff *skb,
	if (!skb2)
		return -ENOMEM;

	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, info->nlh->nlmsg_seq, 0,
			 IPSET_CMD_TYPE);
	if (!nlh2)
		goto nlmsg_failure;
@@ -1968,7 +1945,8 @@ static int ip_set_type(struct net *net, struct sock *ctnl, struct sk_buff *skb,
	nlmsg_end(skb2, nlh2);

	pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (ret < 0)
		return ret;

@@ -1988,10 +1966,8 @@ ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
};

static int ip_set_protocol(struct net *net, struct sock *ctnl,
			   struct sk_buff *skb, const struct nlmsghdr *nlh,
			   const struct nlattr * const attr[],
			   struct netlink_ext_ack *extack)
static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info,
			   const struct nlattr * const attr[])
{
	struct sk_buff *skb2;
	struct nlmsghdr *nlh2;
@@ -2004,7 +1980,7 @@ static int ip_set_protocol(struct net *net, struct sock *ctnl,
	if (!skb2)
		return -ENOMEM;

	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, info->nlh->nlmsg_seq, 0,
			 IPSET_CMD_PROTOCOL);
	if (!nlh2)
		goto nlmsg_failure;
@@ -2014,7 +1990,8 @@ static int ip_set_protocol(struct net *net, struct sock *ctnl,
		goto nla_put_failure;
	nlmsg_end(skb2, nlh2);

	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (ret < 0)
		return ret;

@@ -2029,12 +2006,10 @@ static int ip_set_protocol(struct net *net, struct sock *ctnl,

/* Get set by name or index, from userspace */

static int ip_set_byname(struct net *net, struct sock *ctnl,
			 struct sk_buff *skb, const struct nlmsghdr *nlh,
			 const struct nlattr * const attr[],
			 struct netlink_ext_ack *extack)
static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info,
			 const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct sk_buff *skb2;
	struct nlmsghdr *nlh2;
	ip_set_id_t id = IPSET_INVALID_ID;
@@ -2053,7 +2028,7 @@ static int ip_set_byname(struct net *net, struct sock *ctnl,
	if (!skb2)
		return -ENOMEM;

	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, info->nlh->nlmsg_seq, 0,
			 IPSET_CMD_GET_BYNAME);
	if (!nlh2)
		goto nlmsg_failure;
@@ -2063,7 +2038,8 @@ static int ip_set_byname(struct net *net, struct sock *ctnl,
		goto nla_put_failure;
	nlmsg_end(skb2, nlh2);

	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (ret < 0)
		return ret;

@@ -2081,12 +2057,10 @@ static const struct nla_policy ip_set_index_policy[IPSET_ATTR_CMD_MAX + 1] = {
	[IPSET_ATTR_INDEX]	= { .type = NLA_U16 },
};

static int ip_set_byindex(struct net *net, struct sock *ctnl,
			  struct sk_buff *skb, const struct nlmsghdr *nlh,
			  const struct nlattr * const attr[],
			  struct netlink_ext_ack *extack)
static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info,
			  const struct nlattr * const attr[])
{
	struct ip_set_net *inst = ip_set_pernet(net);
	struct ip_set_net *inst = ip_set_pernet(info->net);
	struct sk_buff *skb2;
	struct nlmsghdr *nlh2;
	ip_set_id_t id = IPSET_INVALID_ID;
@@ -2108,7 +2082,7 @@ static int ip_set_byindex(struct net *net, struct sock *ctnl,
	if (!skb2)
		return -ENOMEM;

	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
	nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, info->nlh->nlmsg_seq, 0,
			 IPSET_CMD_GET_BYINDEX);
	if (!nlh2)
		goto nlmsg_failure;
@@ -2117,7 +2091,8 @@ static int ip_set_byindex(struct net *net, struct sock *ctnl,
		goto nla_put_failure;
	nlmsg_end(skb2, nlh2);

	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (ret < 0)
		return ret;

+101 −113
Original line number Diff line number Diff line
@@ -1524,17 +1524,15 @@ static int ctnetlink_flush_conntrack(struct net *net,
	return 0;
}

static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
				   struct sk_buff *skb,
				   const struct nlmsghdr *nlh,
				   const struct nlattr * const cda[],
				   struct netlink_ext_ack *extack)
static int ctnetlink_del_conntrack(struct sk_buff *skb,
				   const struct nfnl_info *info,
				   const struct nlattr * const cda[])
{
	struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
	struct nf_conntrack_tuple_hash *h;
	struct nf_conntrack_tuple tuple;
	struct nf_conn *ct;
	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
	struct nf_conntrack_zone zone;
	struct nf_conn *ct;
	int err;

	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
@@ -1550,15 +1548,15 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
	else {
		u_int8_t u3 = nfmsg->version ? nfmsg->nfgen_family : AF_UNSPEC;

		return ctnetlink_flush_conntrack(net, cda,
		return ctnetlink_flush_conntrack(info->net, cda,
						 NETLINK_CB(skb).portid,
						 nlmsg_report(nlh), u3);
						 nlmsg_report(info->nlh), u3);
	}

	if (err < 0)
		return err;

	h = nf_conntrack_find_get(net, &zone, &tuple);
	h = nf_conntrack_find_get(info->net, &zone, &tuple);
	if (!h)
		return -ENOENT;

@@ -1578,28 +1576,26 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
		}
	}

	nf_ct_delete(ct, NETLINK_CB(skb).portid, nlmsg_report(nlh));
	nf_ct_delete(ct, NETLINK_CB(skb).portid, nlmsg_report(info->nlh));
	nf_ct_put(ct);

	return 0;
}

static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
				   struct sk_buff *skb,
				   const struct nlmsghdr *nlh,
				   const struct nlattr * const cda[],
				   struct netlink_ext_ack *extack)
static int ctnetlink_get_conntrack(struct sk_buff *skb,
				   const struct nfnl_info *info,
				   const struct nlattr * const cda[])
{
	struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_tuple_hash *h;
	struct nf_conntrack_tuple tuple;
	struct nf_conn *ct;
	struct sk_buff *skb2 = NULL;
	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_zone zone;
	struct sk_buff *skb2;
	struct nf_conn *ct;
	int err;

	if (nlh->nlmsg_flags & NLM_F_DUMP) {
	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.start = ctnetlink_start,
			.dump = ctnetlink_dump_table,
@@ -1607,7 +1603,7 @@ static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
			.data = (void *)cda,
		};

		return netlink_dump_start(ctnl, skb, nlh, &c);
		return netlink_dump_start(info->sk, skb, info->nlh, &c);
	}

	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
@@ -1626,7 +1622,7 @@ static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
	if (err < 0)
		return err;

	h = nf_conntrack_find_get(net, &zone, &tuple);
	h = nf_conntrack_find_get(info->net, &zone, &tuple);
	if (!h)
		return -ENOENT;

@@ -1639,13 +1635,16 @@ static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
		return -ENOMEM;
	}

	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
				  NFNL_MSG_TYPE(nlh->nlmsg_type), ct, true, 0);
	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).portid,
				  info->nlh->nlmsg_seq,
				  NFNL_MSG_TYPE(info->nlh->nlmsg_type), ct,
				  true, 0);
	nf_ct_put(ct);
	if (err <= 0)
		goto free;

	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (err < 0)
		goto out;

@@ -1743,18 +1742,16 @@ ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
	return ctnetlink_dump_list(skb, cb, true);
}

static int ctnetlink_get_ct_dying(struct net *net, struct sock *ctnl,
				  struct sk_buff *skb,
				  const struct nlmsghdr *nlh,
				  const struct nlattr * const cda[],
				  struct netlink_ext_ack *extack)
static int ctnetlink_get_ct_dying(struct sk_buff *skb,
				  const struct nfnl_info *info,
				  const struct nlattr * const cda[])
{
	if (nlh->nlmsg_flags & NLM_F_DUMP) {
	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.dump = ctnetlink_dump_dying,
			.done = ctnetlink_done_list,
		};
		return netlink_dump_start(ctnl, skb, nlh, &c);
		return netlink_dump_start(info->sk, skb, info->nlh, &c);
	}

	return -EOPNOTSUPP;
@@ -1766,18 +1763,16 @@ ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
	return ctnetlink_dump_list(skb, cb, false);
}

static int ctnetlink_get_ct_unconfirmed(struct net *net, struct sock *ctnl,
					struct sk_buff *skb,
					const struct nlmsghdr *nlh,
					const struct nlattr * const cda[],
					struct netlink_ext_ack *extack)
static int ctnetlink_get_ct_unconfirmed(struct sk_buff *skb,
					const struct nfnl_info *info,
					const struct nlattr * const cda[])
{
	if (nlh->nlmsg_flags & NLM_F_DUMP) {
	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.dump = ctnetlink_dump_unconfirmed,
			.done = ctnetlink_done_list,
		};
		return netlink_dump_start(ctnl, skb, nlh, &c);
		return netlink_dump_start(info->sk, skb, info->nlh, &c);
	}

	return -EOPNOTSUPP;
@@ -2374,18 +2369,16 @@ ctnetlink_create_conntrack(struct net *net,
	return ERR_PTR(err);
}

static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
				   struct sk_buff *skb,
				   const struct nlmsghdr *nlh,
				   const struct nlattr * const cda[],
				   struct netlink_ext_ack *extack)
static int ctnetlink_new_conntrack(struct sk_buff *skb,
				   const struct nfnl_info *info,
				   const struct nlattr * const cda[])
{
	struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
	struct nf_conntrack_tuple otuple, rtuple;
	struct nf_conntrack_tuple_hash *h = NULL;
	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
	struct nf_conn *ct;
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_zone zone;
	struct nf_conn *ct;
	int err;

	err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
@@ -2407,13 +2400,13 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
	}

	if (cda[CTA_TUPLE_ORIG])
		h = nf_conntrack_find_get(net, &zone, &otuple);
		h = nf_conntrack_find_get(info->net, &zone, &otuple);
	else if (cda[CTA_TUPLE_REPLY])
		h = nf_conntrack_find_get(net, &zone, &rtuple);
		h = nf_conntrack_find_get(info->net, &zone, &rtuple);

	if (h == NULL) {
		err = -ENOENT;
		if (nlh->nlmsg_flags & NLM_F_CREATE) {
		if (info->nlh->nlmsg_flags & NLM_F_CREATE) {
			enum ip_conntrack_events events;

			if (!cda[CTA_TUPLE_ORIG] || !cda[CTA_TUPLE_REPLY])
@@ -2421,8 +2414,8 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
			if (otuple.dst.protonum != rtuple.dst.protonum)
				return -EINVAL;

			ct = ctnetlink_create_conntrack(net, &zone, cda, &otuple,
							&rtuple, u3);
			ct = ctnetlink_create_conntrack(info->net, &zone, cda,
							&otuple, &rtuple, u3);
			if (IS_ERR(ct))
				return PTR_ERR(ct);

@@ -2445,7 +2438,7 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
						      (1 << IPCT_SYNPROXY) |
						      events,
						      ct, NETLINK_CB(skb).portid,
						      nlmsg_report(nlh));
						      nlmsg_report(info->nlh));
			nf_ct_put(ct);
		}

@@ -2455,7 +2448,7 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,

	err = -EEXIST;
	ct = nf_ct_tuplehash_to_ctrack(h);
	if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
	if (!(info->nlh->nlmsg_flags & NLM_F_EXCL)) {
		err = ctnetlink_change_conntrack(ct, cda);
		if (err == 0) {
			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
@@ -2467,7 +2460,7 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
						      (1 << IPCT_MARK) |
						      (1 << IPCT_SYNPROXY),
						      ct, NETLINK_CB(skb).portid,
						      nlmsg_report(nlh));
						      nlmsg_report(info->nlh));
		}
	}

@@ -2539,17 +2532,15 @@ ctnetlink_ct_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
	return skb->len;
}

static int ctnetlink_stat_ct_cpu(struct net *net, struct sock *ctnl,
				 struct sk_buff *skb,
				 const struct nlmsghdr *nlh,
				 const struct nlattr * const cda[],
				 struct netlink_ext_ack *extack)
static int ctnetlink_stat_ct_cpu(struct sk_buff *skb,
				 const struct nfnl_info *info,
				 const struct nlattr * const cda[])
{
	if (nlh->nlmsg_flags & NLM_F_DUMP) {
	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.dump = ctnetlink_ct_stat_cpu_dump,
		};
		return netlink_dump_start(ctnl, skb, nlh, &c);
		return netlink_dump_start(info->sk, skb, info->nlh, &c);
	}

	return 0;
@@ -2585,10 +2576,8 @@ ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
	return -1;
}

static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl,
			     struct sk_buff *skb, const struct nlmsghdr *nlh,
			     const struct nlattr * const cda[],
			     struct netlink_ext_ack *extack)
static int ctnetlink_stat_ct(struct sk_buff *skb, const struct nfnl_info *info,
			     const struct nlattr * const cda[])
{
	struct sk_buff *skb2;
	int err;
@@ -2598,13 +2587,14 @@ static int ctnetlink_stat_ct(struct net *net, struct sock *ctnl,
		return -ENOMEM;

	err = ctnetlink_stat_ct_fill_info(skb2, NETLINK_CB(skb).portid,
					  nlh->nlmsg_seq,
					  NFNL_MSG_TYPE(nlh->nlmsg_type),
					  info->nlh->nlmsg_seq,
					  NFNL_MSG_TYPE(info->nlh->nlmsg_type),
					  sock_net(skb->sk));
	if (err <= 0)
		goto free;

	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (err < 0)
		goto out;

@@ -3284,29 +3274,29 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
	return err;
}

static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
				struct sk_buff *skb, const struct nlmsghdr *nlh,
				const struct nlattr * const cda[],
				struct netlink_ext_ack *extack)
static int ctnetlink_get_expect(struct sk_buff *skb,
				const struct nfnl_info *info,
				const struct nlattr * const cda[])
{
	struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_tuple tuple;
	struct nf_conntrack_expect *exp;
	struct sk_buff *skb2;
	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_zone zone;
	struct sk_buff *skb2;
	int err;

	if (nlh->nlmsg_flags & NLM_F_DUMP) {
	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
		if (cda[CTA_EXPECT_MASTER])
			return ctnetlink_dump_exp_ct(net, ctnl, skb, nlh, cda,
						     extack);
			return ctnetlink_dump_exp_ct(info->net, info->sk, skb,
						     info->nlh, cda,
						     info->extack);
		else {
			struct netlink_dump_control c = {
				.dump = ctnetlink_exp_dump_table,
				.done = ctnetlink_exp_done,
			};
			return netlink_dump_start(ctnl, skb, nlh, &c);
			return netlink_dump_start(info->sk, skb, info->nlh, &c);
		}
	}

@@ -3326,7 +3316,7 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
	if (err < 0)
		return err;

	exp = nf_ct_expect_find_get(net, &zone, &tuple);
	exp = nf_ct_expect_find_get(info->net, &zone, &tuple);
	if (!exp)
		return -ENOENT;

@@ -3348,13 +3338,15 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,

	rcu_read_lock();
	err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).portid,
				      nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, exp);
				      info->nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
				      exp);
	rcu_read_unlock();
	nf_ct_expect_put(exp);
	if (err <= 0)
		goto free;

	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
	err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
			      MSG_DONTWAIT);
	if (err < 0)
		goto out;

@@ -3382,15 +3374,14 @@ static bool expect_iter_all(struct nf_conntrack_expect *exp, void *data)
	return true;
}

static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
				struct sk_buff *skb, const struct nlmsghdr *nlh,
				const struct nlattr * const cda[],
				struct netlink_ext_ack *extack)
static int ctnetlink_del_expect(struct sk_buff *skb,
				const struct nfnl_info *info,
				const struct nlattr * const cda[])
{
	struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_expect *exp;
	struct nf_conntrack_tuple tuple;
	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_zone zone;
	int err;

@@ -3406,7 +3397,7 @@ static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
			return err;

		/* bump usage count to 2 */
		exp = nf_ct_expect_find_get(net, &zone, &tuple);
		exp = nf_ct_expect_find_get(info->net, &zone, &tuple);
		if (!exp)
			return -ENOENT;

@@ -3422,7 +3413,7 @@ static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
		spin_lock_bh(&nf_conntrack_expect_lock);
		if (del_timer(&exp->timeout)) {
			nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid,
						   nlmsg_report(nlh));
						   nlmsg_report(info->nlh));
			nf_ct_expect_put(exp);
		}
		spin_unlock_bh(&nf_conntrack_expect_lock);
@@ -3432,14 +3423,14 @@ static int ctnetlink_del_expect(struct net *net, struct sock *ctnl,
	} else if (cda[CTA_EXPECT_HELP_NAME]) {
		char *name = nla_data(cda[CTA_EXPECT_HELP_NAME]);

		nf_ct_expect_iterate_net(net, expect_iter_name, name,
		nf_ct_expect_iterate_net(info->net, expect_iter_name, name,
					 NETLINK_CB(skb).portid,
					 nlmsg_report(nlh));
					 nlmsg_report(info->nlh));
	} else {
		/* This basically means we have to flush everything*/
		nf_ct_expect_iterate_net(net, expect_iter_all, NULL,
		nf_ct_expect_iterate_net(info->net, expect_iter_all, NULL,
					 NETLINK_CB(skb).portid,
					 nlmsg_report(nlh));
					 nlmsg_report(info->nlh));
	}

	return 0;
@@ -3635,15 +3626,14 @@ ctnetlink_create_expect(struct net *net,
	return err;
}

static int ctnetlink_new_expect(struct net *net, struct sock *ctnl,
				struct sk_buff *skb, const struct nlmsghdr *nlh,
				const struct nlattr * const cda[],
				struct netlink_ext_ack *extack)
static int ctnetlink_new_expect(struct sk_buff *skb,
				const struct nfnl_info *info,
				const struct nlattr * const cda[])
{
	struct nfgenmsg *nfmsg = nlmsg_data(info->nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_tuple tuple;
	struct nf_conntrack_expect *exp;
	struct nfgenmsg *nfmsg = nlmsg_data(nlh);
	u_int8_t u3 = nfmsg->nfgen_family;
	struct nf_conntrack_zone zone;
	int err;

@@ -3662,20 +3652,20 @@ static int ctnetlink_new_expect(struct net *net, struct sock *ctnl,
		return err;

	spin_lock_bh(&nf_conntrack_expect_lock);
	exp = __nf_ct_expect_find(net, &zone, &tuple);
	exp = __nf_ct_expect_find(info->net, &zone, &tuple);
	if (!exp) {
		spin_unlock_bh(&nf_conntrack_expect_lock);
		err = -ENOENT;
		if (nlh->nlmsg_flags & NLM_F_CREATE) {
			err = ctnetlink_create_expect(net, &zone, cda, u3,
		if (info->nlh->nlmsg_flags & NLM_F_CREATE) {
			err = ctnetlink_create_expect(info->net, &zone, cda, u3,
						      NETLINK_CB(skb).portid,
						      nlmsg_report(nlh));
						      nlmsg_report(info->nlh));
		}
		return err;
	}

	err = -EEXIST;
	if (!(nlh->nlmsg_flags & NLM_F_EXCL))
	if (!(info->nlh->nlmsg_flags & NLM_F_EXCL))
		err = ctnetlink_change_expect(exp, cda);
	spin_unlock_bh(&nf_conntrack_expect_lock);

@@ -3736,17 +3726,15 @@ ctnetlink_exp_stat_cpu_dump(struct sk_buff *skb, struct netlink_callback *cb)
	return skb->len;
}

static int ctnetlink_stat_exp_cpu(struct net *net, struct sock *ctnl,
				  struct sk_buff *skb,
				  const struct nlmsghdr *nlh,
				  const struct nlattr * const cda[],
				  struct netlink_ext_ack *extack)
static int ctnetlink_stat_exp_cpu(struct sk_buff *skb,
				  const struct nfnl_info *info,
				  const struct nlattr * const cda[])
{
	if (nlh->nlmsg_flags & NLM_F_DUMP) {
	if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
		struct netlink_dump_control c = {
			.dump = ctnetlink_exp_stat_cpu_dump,
		};
		return netlink_dump_start(ctnl, skb, nlh, &c);
		return netlink_dump_start(info->sk, skb, info->nlh, &c);
	}

	return 0;
+12 −6

File changed.

Preview size limit exceeded, changes collapsed.

+19 −25

File changed.

Preview size limit exceeded, changes collapsed.

Loading