Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1e00b39 authored by Jozsef Kadlecsik's avatar Jozsef Kadlecsik Committed by Patrick McHardy
Browse files

netfilter: ipset: set type support with multiple revisions added



A set type may have multiple revisions, for example when syntax is
extended. Support continuous revision ranges in set types.

Signed-off-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 3d14b171
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -282,8 +282,8 @@ struct ip_set_type {
	u8 dimension;
	/* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
	u8 family;
	/* Type revision */
	u8 revision;
	/* Type revisions */
	u8 revision_min, revision_max;

	/* Create set */
	int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
@@ -314,6 +314,8 @@ struct ip_set {
	const struct ip_set_type_variant *variant;
	/* The actual INET family of the set */
	u8 family;
	/* The type revision */
	u8 revision;
	/* The type specific data */
	void *data;
};
+2 −1
Original line number Diff line number Diff line
@@ -551,7 +551,8 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
	.features	= IPSET_TYPE_IP,
	.dimension	= IPSET_DIM_ONE,
	.family		= AF_INET,
	.revision	= 0,
	.revision_min	= 0,
	.revision_max	= 0,
	.create		= bitmap_ip_create,
	.create_policy	= {
		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+2 −1
Original line number Diff line number Diff line
@@ -623,7 +623,8 @@ static struct ip_set_type bitmap_ipmac_type = {
	.features	= IPSET_TYPE_IP | IPSET_TYPE_MAC,
	.dimension	= IPSET_DIM_TWO,
	.family		= AF_INET,
	.revision	= 0,
	.revision_min	= 0,
	.revision_max	= 0,
	.create		= bitmap_ipmac_create,
	.create_policy	= {
		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+2 −1
Original line number Diff line number Diff line
@@ -483,7 +483,8 @@ static struct ip_set_type bitmap_port_type = {
	.features	= IPSET_TYPE_PORT,
	.dimension	= IPSET_DIM_ONE,
	.family		= AF_UNSPEC,
	.revision	= 0,
	.revision_min	= 0,
	.revision_max	= 0,
	.create		= bitmap_port_create,
	.create_policy	= {
		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+25 −20
Original line number Diff line number Diff line
@@ -70,7 +70,8 @@ find_set_type(const char *name, u8 family, u8 revision)
	list_for_each_entry_rcu(type, &ip_set_type_list, list)
		if (STREQ(type->name, name) &&
		    (type->family == family || type->family == AF_UNSPEC) &&
		    type->revision == revision)
		    revision >= type->revision_min &&
		    revision <= type->revision_max)
			return type;
	return NULL;
}
@@ -135,10 +136,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
		if (STREQ(type->name, name) &&
		    (type->family == family || type->family == AF_UNSPEC)) {
			found = true;
			if (type->revision < *min)
				*min = type->revision;
			if (type->revision > *max)
				*max = type->revision;
			if (type->revision_min < *min)
				*min = type->revision_min;
			if (type->revision_max > *max)
				*max = type->revision_max;
		}
	rcu_read_unlock();
	if (found)
@@ -159,25 +160,27 @@ ip_set_type_register(struct ip_set_type *type)
	int ret = 0;

	if (type->protocol != IPSET_PROTOCOL) {
		pr_warning("ip_set type %s, family %s, revision %u uses "
		pr_warning("ip_set type %s, family %s, revision %u:%u uses "
			   "wrong protocol version %u (want %u)\n",
			   type->name, family_name(type->family),
			   type->revision, type->protocol, IPSET_PROTOCOL);
			   type->revision_min, type->revision_max,
			   type->protocol, IPSET_PROTOCOL);
		return -EINVAL;
	}

	ip_set_type_lock();
	if (find_set_type(type->name, type->family, type->revision)) {
	if (find_set_type(type->name, type->family, type->revision_min)) {
		/* Duplicate! */
		pr_warning("ip_set type %s, family %s, revision %u "
		pr_warning("ip_set type %s, family %s with revision min %u "
			   "already registered!\n", type->name,
			   family_name(type->family), type->revision);
			   family_name(type->family), type->revision_min);
		ret = -EINVAL;
		goto unlock;
	}
	list_add_rcu(&type->list, &ip_set_type_list);
	pr_debug("type %s, family %s, revision %u registered.\n",
		 type->name, family_name(type->family), type->revision);
	pr_debug("type %s, family %s, revision %u:%u registered.\n",
		 type->name, family_name(type->family),
		 type->revision_min, type->revision_max);
unlock:
	ip_set_type_unlock();
	return ret;
@@ -189,15 +192,15 @@ void
ip_set_type_unregister(struct ip_set_type *type)
{
	ip_set_type_lock();
	if (!find_set_type(type->name, type->family, type->revision)) {
		pr_warning("ip_set type %s, family %s, revision %u "
	if (!find_set_type(type->name, type->family, type->revision_min)) {
		pr_warning("ip_set type %s, family %s with revision min %u "
			   "not registered\n", type->name,
			   family_name(type->family), type->revision);
			   family_name(type->family), type->revision_min);
		goto unlock;
	}
	list_del_rcu(&type->list);
	pr_debug("type %s, family %s, revision %u unregistered.\n",
		 type->name, family_name(type->family), type->revision);
	pr_debug("type %s, family %s with revision min %u unregistered.\n",
		 type->name, family_name(type->family), type->revision_min);
unlock:
	ip_set_type_unlock();

@@ -656,6 +659,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
	rwlock_init(&set->lock);
	strlcpy(set->name, name, IPSET_MAXNAMELEN);
	set->family = family;
	set->revision = revision;

	/*
	 * Next, check that we know the type, and take
@@ -696,7 +700,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
		    (flags & IPSET_FLAG_EXIST) &&
		    STREQ(set->type->name, clash->type->name) &&
		    set->type->family == clash->type->family &&
		    set->type->revision == clash->type->revision &&
		    set->type->revision_min == clash->type->revision_min &&
		    set->type->revision_max == clash->type->revision_max &&
		    set->variant->same_set(set, clash))
			ret = 0;
		goto cleanup;
@@ -1080,7 +1085,7 @@ dump_last:
			NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
				   set->family);
			NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
				   set->type->revision);
				   set->revision);
			ret = set->variant->head(set, skb);
			if (ret < 0)
				goto release_refcount;
@@ -1385,7 +1390,7 @@ ip_set_header(struct sock *ctnl, struct sk_buff *skb,
	NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
	NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
	NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision);
	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->revision);
	nlmsg_end(skb2, nlh2);

	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
Loading