mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-07 21:25:12 +02:00
ipset: update to ipset-6.2
This commit is contained in:
@@ -216,7 +216,8 @@ enum ip_set_feature {
|
||||
|
||||
struct ip_set;
|
||||
|
||||
typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
|
||||
typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
|
||||
u32 timeout, u32 flags);
|
||||
|
||||
/* Set type, variant-specific part */
|
||||
struct ip_set_type_variant {
|
||||
@@ -295,7 +296,7 @@ struct ip_set {
|
||||
/* Lock protecting the set data */
|
||||
rwlock_t lock;
|
||||
/* References to the set */
|
||||
atomic_t ref;
|
||||
u32 ref;
|
||||
/* The core set type */
|
||||
struct ip_set_type *type;
|
||||
/* The type variant doing the real job */
|
||||
|
@@ -349,7 +349,7 @@ retry:
|
||||
/* Add an element to a hash and update the internal counters when succeeded,
|
||||
* otherwise report the proper error code. */
|
||||
static int
|
||||
type_pf_add(struct ip_set *set, void *value, u32 timeout)
|
||||
type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
struct htable *t;
|
||||
@@ -388,7 +388,7 @@ out:
|
||||
* and free up space if possible.
|
||||
*/
|
||||
static int
|
||||
type_pf_del(struct ip_set *set, void *value, u32 timeout)
|
||||
type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
struct htable *t = h->table;
|
||||
@@ -463,7 +463,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
|
||||
|
||||
/* Test whether the element is added to the set */
|
||||
static int
|
||||
type_pf_test(struct ip_set *set, void *value, u32 timeout)
|
||||
type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
struct htable *t = h->table;
|
||||
@@ -515,8 +515,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
|
||||
if (h->netmask != HOST_MASK)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
|
||||
#endif
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));
|
||||
if (with_timeout(h->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout));
|
||||
@@ -777,7 +776,7 @@ retry:
|
||||
}
|
||||
|
||||
static int
|
||||
type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
struct htable *t = h->table;
|
||||
@@ -785,6 +784,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
struct hbucket *n;
|
||||
struct type_pf_elem *data;
|
||||
int ret = 0, i, j = AHASH_MAX_SIZE + 1;
|
||||
bool flag_exist = flags & IPSET_FLAG_EXIST;
|
||||
u32 key;
|
||||
|
||||
if (h->elements >= h->maxelem)
|
||||
@@ -800,7 +800,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
for (i = 0; i < n->pos; i++) {
|
||||
data = ahash_tdata(n, i);
|
||||
if (type_pf_data_equal(data, d)) {
|
||||
if (type_pf_data_expired(data))
|
||||
if (type_pf_data_expired(data) || flag_exist)
|
||||
j = i;
|
||||
else {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
@@ -834,7 +834,7 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
struct htable *t = h->table;
|
||||
@@ -906,7 +906,7 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
|
||||
#endif
|
||||
|
||||
static int
|
||||
type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct ip_set_hash *h = set->data;
|
||||
struct htable *t = h->table;
|
||||
|
@@ -54,7 +54,7 @@ ip_to_id(const struct bitmap_ip *m, u32 ip)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
@@ -63,7 +63,7 @@ bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
@@ -75,7 +75,7 @@ bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
@@ -131,7 +131,7 @@ nla_put_failure:
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
const unsigned long *members = map->members;
|
||||
@@ -141,13 +141,13 @@ bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
members[id] = ip_set_timeout_set(timeout);
|
||||
@@ -156,7 +156,7 @@ bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
@@ -231,7 +231,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
|
||||
ip = ip_to_id(map, ip);
|
||||
|
||||
return adtfn(set, &ip, map->timeout);
|
||||
return adtfn(set, &ip, map->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -266,7 +266,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (adt == IPSET_TEST) {
|
||||
id = ip_to_id(map, ip);
|
||||
return adtfn(set, &id, timeout);
|
||||
return adtfn(set, &id, timeout, flags);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
@@ -293,7 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id(map, ip);
|
||||
ret = adtfn(set, &id, timeout);;
|
||||
ret = adtfn(set, &id, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -338,8 +338,7 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
if (with_timeout(map->timeout))
|
||||
|
@@ -99,7 +99,7 @@ bitmap_ipmac_exist(const struct ipmac_telem *elem)
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
@@ -117,7 +117,7 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
@@ -146,7 +146,7 @@ bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
@@ -212,7 +212,7 @@ nla_put_failure:
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
@@ -231,15 +231,16 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
bool flag_exist = flags & IPSET_FLAG_EXIST;
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!data->ether)
|
||||
if (!(data->ether || flag_exist))
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address and activate the timer */
|
||||
@@ -251,7 +252,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
elem->timeout = ip_set_timeout_set(timeout);
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
if (!bitmap_expired(map, data->id))
|
||||
if (!(bitmap_expired(map, data->id) || flag_exist))
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fall through */
|
||||
case MAC_EMPTY:
|
||||
@@ -273,7 +274,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
@@ -355,7 +356,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
data.id -= map->first_ip;
|
||||
data.ether = eth_hdr(skb)->h_source;
|
||||
|
||||
return adtfn(set, &data, map->timeout);
|
||||
return adtfn(set, &data, map->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -395,7 +396,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
data.id -= map->first_ip;
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
@@ -434,8 +435,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map)
|
||||
+ (map->last_ip - map->first_ip + 1) * map->dsize));
|
||||
|
@@ -40,7 +40,7 @@ struct bitmap_port {
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
@@ -49,7 +49,7 @@ bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
@@ -61,7 +61,7 @@ bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 id = *(u16 *)value;
|
||||
@@ -119,7 +119,7 @@ nla_put_failure:
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
const unsigned long *members = map->members;
|
||||
@@ -129,13 +129,13 @@ bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
u16 id = *(u16 *)value;
|
||||
|
||||
if (ip_set_timeout_test(members[id]))
|
||||
if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
members[id] = ip_set_timeout_set(timeout);
|
||||
@@ -144,7 +144,7 @@ bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
unsigned long *members = map->members;
|
||||
@@ -225,7 +225,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
return adtfn(set, &port, map->timeout);
|
||||
return adtfn(set, &port, map->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -259,7 +259,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (adt == IPSET_TEST) {
|
||||
id = port - map->first_port;
|
||||
return adtfn(set, &id, timeout);
|
||||
return adtfn(set, &id, timeout, flags);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
@@ -277,7 +277,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adtfn(set, &id, timeout);
|
||||
ret = adtfn(set, &id, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -320,8 +320,7 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
if (with_timeout(map->timeout))
|
||||
|
@@ -28,6 +28,7 @@
|
||||
|
||||
static LIST_HEAD(ip_set_type_list); /* all registered set types */
|
||||
static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
|
||||
static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */
|
||||
|
||||
static struct ip_set **ip_set_list; /* all individual sets */
|
||||
static ip_set_id_t ip_set_max = LCONFIG_IP_SET_MAX; /* max number of sets */
|
||||
@@ -97,16 +98,28 @@ static int
|
||||
find_set_type_get(const char *name, u8 family, u8 revision,
|
||||
struct ip_set_type **found)
|
||||
{
|
||||
struct ip_set_type *type;
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
*found = find_set_type(name, family, revision);
|
||||
if (*found) {
|
||||
int err = !try_module_get((*found)->me);
|
||||
rcu_read_unlock();
|
||||
return err ? -EFAULT : 0;
|
||||
err = !try_module_get((*found)->me) ? -EFAULT : 0;
|
||||
goto unlock;
|
||||
}
|
||||
/* Make sure the type is loaded but we don't support the revision */
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
if (STREQ(type->name, name)) {
|
||||
err = -IPSET_ERR_FIND_TYPE;
|
||||
goto unlock;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return try_to_load_type(name);
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Find a given set type by name and family.
|
||||
@@ -119,7 +132,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
||||
struct ip_set_type *type;
|
||||
bool found = false;
|
||||
|
||||
*min = *max = 0;
|
||||
*min = 255; *max = 0;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
if (STREQ(type->name, name) &&
|
||||
@@ -127,7 +140,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
||||
found = true;
|
||||
if (type->revision < *min)
|
||||
*min = type->revision;
|
||||
else if (type->revision > *max)
|
||||
if (type->revision > *max)
|
||||
*max = type->revision;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@@ -297,13 +310,18 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
|
||||
static inline void
|
||||
__ip_set_get(ip_set_id_t index)
|
||||
{
|
||||
atomic_inc(&ip_set_list[index]->ref);
|
||||
write_lock_bh(&ip_set_ref_lock);
|
||||
ip_set_list[index]->ref++;
|
||||
write_unlock_bh(&ip_set_ref_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
__ip_set_put(ip_set_id_t index)
|
||||
{
|
||||
atomic_dec(&ip_set_list[index]->ref);
|
||||
write_lock_bh(&ip_set_ref_lock);
|
||||
BUG_ON(ip_set_list[index]->ref == 0);
|
||||
ip_set_list[index]->ref--;
|
||||
write_unlock_bh(&ip_set_ref_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -320,7 +338,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
|
||||
struct ip_set *set = ip_set_list[index];
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
|
||||
BUG_ON(set == NULL);
|
||||
pr_debug("set %s, index %u\n", set->name, index);
|
||||
|
||||
if (dim < set->type->dimension ||
|
||||
@@ -352,7 +370,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
|
||||
struct ip_set *set = ip_set_list[index];
|
||||
int ret;
|
||||
|
||||
BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
|
||||
BUG_ON(set == NULL);
|
||||
pr_debug("set %s, index %u\n", set->name, index);
|
||||
|
||||
if (dim < set->type->dimension ||
|
||||
@@ -374,7 +392,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
|
||||
struct ip_set *set = ip_set_list[index];
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
|
||||
BUG_ON(set == NULL);
|
||||
pr_debug("set %s, index %u\n", set->name, index);
|
||||
|
||||
if (dim < set->type->dimension ||
|
||||
@@ -393,7 +411,6 @@ EXPORT_SYMBOL_GPL(ip_set_del);
|
||||
* Find set by name, reference it once. The reference makes sure the
|
||||
* thing pointed to, does not go away under our feet.
|
||||
*
|
||||
* The nfnl mutex must already be activated.
|
||||
*/
|
||||
ip_set_id_t
|
||||
ip_set_get_byname(const char *name, struct ip_set **set)
|
||||
@@ -419,15 +436,12 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname);
|
||||
* reference count by 1. The caller shall not assume the index
|
||||
* to be valid, after calling this function.
|
||||
*
|
||||
* The nfnl mutex must already be activated.
|
||||
*/
|
||||
void
|
||||
ip_set_put_byindex(ip_set_id_t index)
|
||||
{
|
||||
if (ip_set_list[index] != NULL) {
|
||||
BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
|
||||
if (ip_set_list[index] != NULL)
|
||||
__ip_set_put(index);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_put_byindex);
|
||||
|
||||
@@ -437,7 +451,6 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex);
|
||||
* can't be destroyed. The set cannot be renamed due to
|
||||
* the referencing either.
|
||||
*
|
||||
* The nfnl mutex must already be activated.
|
||||
*/
|
||||
const char *
|
||||
ip_set_name_byindex(ip_set_id_t index)
|
||||
@@ -445,7 +458,7 @@ ip_set_name_byindex(ip_set_id_t index)
|
||||
const struct ip_set *set = ip_set_list[index];
|
||||
|
||||
BUG_ON(set == NULL);
|
||||
BUG_ON(atomic_read(&set->ref) == 0);
|
||||
BUG_ON(set->ref == 0);
|
||||
|
||||
/* Referenced, so it's safe */
|
||||
return set->name;
|
||||
@@ -511,10 +524,7 @@ void
|
||||
ip_set_nfnl_put(ip_set_id_t index)
|
||||
{
|
||||
nfnl_lock();
|
||||
if (ip_set_list[index] != NULL) {
|
||||
BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
|
||||
__ip_set_put(index);
|
||||
}
|
||||
ip_set_put_byindex(index);
|
||||
nfnl_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
|
||||
@@ -522,7 +532,7 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
|
||||
/*
|
||||
* Communication protocol with userspace over netlink.
|
||||
*
|
||||
* We already locked by nfnl_lock.
|
||||
* The commands are serialized by the nfnl mutex.
|
||||
*/
|
||||
|
||||
static inline bool
|
||||
@@ -611,8 +621,7 @@ static int
|
||||
ip_set_create(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *const *attr = info->attrs;
|
||||
|
||||
struct ip_set *set, *clash;
|
||||
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;
|
||||
@@ -645,7 +654,6 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
|
||||
return -ENOMEM;
|
||||
rwlock_init(&set->lock);
|
||||
strlcpy(set->name, name, IPSET_MAXNAMELEN);
|
||||
atomic_set(&set->ref, 0);
|
||||
set->family = family;
|
||||
|
||||
/*
|
||||
@@ -678,8 +686,8 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
/*
|
||||
* Here, we have a valid, constructed set and we are protected
|
||||
* by nfnl_lock. Find the first free index in ip_set_list and
|
||||
* check clashing.
|
||||
* by the nfnl mutex. Find the first free index in ip_set_list
|
||||
* and check clashing.
|
||||
*/
|
||||
if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
|
||||
/* If this is the same set and requested, ignore error */
|
||||
@@ -738,31 +746,51 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *const *attr = info->attrs;
|
||||
ip_set_id_t i;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(protocol_failed(attr)))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
/* References are protected by the nfnl mutex */
|
||||
/* Commands are serialized and references are
|
||||
* protected by the ip_set_ref_lock.
|
||||
* External systems (i.e. xt_set) must call
|
||||
* ip_set_put|get_nfnl_* functions, that way we
|
||||
* can safely check references here.
|
||||
*
|
||||
* list:set timer can only decrement the reference
|
||||
* counter, so if it's already zero, we can proceed
|
||||
* without holding the lock.
|
||||
*/
|
||||
read_lock_bh(&ip_set_ref_lock);
|
||||
if (!attr[IPSET_ATTR_SETNAME]) {
|
||||
for (i = 0; i < ip_set_max; i++) {
|
||||
if (ip_set_list[i] != NULL &&
|
||||
(atomic_read(&ip_set_list[i]->ref)))
|
||||
return -IPSET_ERR_BUSY;
|
||||
if (ip_set_list[i] != NULL && ip_set_list[i]->ref) {
|
||||
ret = IPSET_ERR_BUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
read_unlock_bh(&ip_set_ref_lock);
|
||||
for (i = 0; i < ip_set_max; i++) {
|
||||
if (ip_set_list[i] != NULL)
|
||||
ip_set_destroy_set(i);
|
||||
}
|
||||
} else {
|
||||
i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (i == IPSET_INVALID_ID)
|
||||
return -ENOENT;
|
||||
else if (atomic_read(&ip_set_list[i]->ref))
|
||||
return -IPSET_ERR_BUSY;
|
||||
if (i == IPSET_INVALID_ID) {
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
} else if (ip_set_list[i]->ref) {
|
||||
ret = -IPSET_ERR_BUSY;
|
||||
goto out;
|
||||
}
|
||||
read_unlock_bh(&ip_set_ref_lock);
|
||||
|
||||
ip_set_destroy_set(i);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
read_unlock_bh(&ip_set_ref_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Flush sets */
|
||||
@@ -819,6 +847,7 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info)
|
||||
struct ip_set *set;
|
||||
const char *name2;
|
||||
ip_set_id_t i;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(protocol_failed(attr) ||
|
||||
attr[IPSET_ATTR_SETNAME] == NULL ||
|
||||
@@ -828,25 +857,33 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info)
|
||||
set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
|
||||
if (set == NULL)
|
||||
return -ENOENT;
|
||||
if (atomic_read(&set->ref) != 0)
|
||||
return -IPSET_ERR_REFERENCED;
|
||||
|
||||
read_lock_bh(&ip_set_ref_lock);
|
||||
if (set->ref != 0) {
|
||||
ret = -IPSET_ERR_REFERENCED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
|
||||
for (i = 0; i < ip_set_max; i++) {
|
||||
if (ip_set_list[i] != NULL &&
|
||||
STREQ(ip_set_list[i]->name, name2))
|
||||
return -IPSET_ERR_EXIST_SETNAME2;
|
||||
STREQ(ip_set_list[i]->name, name2)) {
|
||||
ret = -IPSET_ERR_EXIST_SETNAME2;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
strncpy(set->name, name2, IPSET_MAXNAMELEN);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
read_unlock_bh(&ip_set_ref_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Swap two sets so that name/index points to the other.
|
||||
* References and set names are also swapped.
|
||||
*
|
||||
* We are protected by the nfnl mutex and references are
|
||||
* manipulated only by holding the mutex. The kernel interfaces
|
||||
* The commands are serialized by the nfnl mutex and references are
|
||||
* protected by the ip_set_ref_lock. The kernel interfaces
|
||||
* do not hold the mutex but the pointer settings are atomic
|
||||
* so the ip_set_list always contains valid pointers to the sets.
|
||||
*/
|
||||
@@ -858,7 +895,6 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info)
|
||||
struct ip_set *from, *to;
|
||||
ip_set_id_t from_id, to_id;
|
||||
char from_name[IPSET_MAXNAMELEN];
|
||||
u32 from_ref;
|
||||
|
||||
if (unlikely(protocol_failed(attr) ||
|
||||
attr[IPSET_ATTR_SETNAME] == NULL ||
|
||||
@@ -883,17 +919,15 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info)
|
||||
from->type->family == to->type->family))
|
||||
return -IPSET_ERR_TYPE_MISMATCH;
|
||||
|
||||
/* No magic here: ref munging protected by the nfnl_lock */
|
||||
strncpy(from_name, from->name, IPSET_MAXNAMELEN);
|
||||
from_ref = atomic_read(&from->ref);
|
||||
|
||||
strncpy(from->name, to->name, IPSET_MAXNAMELEN);
|
||||
atomic_set(&from->ref, atomic_read(&to->ref));
|
||||
strncpy(to->name, from_name, IPSET_MAXNAMELEN);
|
||||
atomic_set(&to->ref, from_ref);
|
||||
|
||||
write_lock_bh(&ip_set_ref_lock);
|
||||
swap(from->ref, to->ref);
|
||||
ip_set_list[from_id] = to;
|
||||
ip_set_list[to_id] = from;
|
||||
write_unlock_bh(&ip_set_ref_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -910,7 +944,7 @@ ip_set_dump_done(struct netlink_callback *cb)
|
||||
{
|
||||
if (cb->args[2]) {
|
||||
pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
|
||||
__ip_set_put((ip_set_id_t) cb->args[1]);
|
||||
ip_set_put_byindex((ip_set_id_t) cb->args[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1053,7 +1087,7 @@ release_refcount:
|
||||
/* If there was an error or set is done, release set */
|
||||
if (ret || !cb->args[2]) {
|
||||
pr_debug("release set %s\n", ip_set_list[index]->name);
|
||||
__ip_set_put(index);
|
||||
ip_set_put_byindex(index);
|
||||
}
|
||||
|
||||
/* If we dump all sets, continue with dumping last ones */
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
@@ -35,7 +36,20 @@ get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
|
||||
*port = src ? th->source : th->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
case IPPROTO_SCTP: {
|
||||
sctp_sctphdr_t _sh;
|
||||
const sctp_sctphdr_t *sh;
|
||||
|
||||
sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh);
|
||||
if (sh == NULL)
|
||||
/* No choice either */
|
||||
return false;
|
||||
|
||||
*port = src ? sh->source : sh->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE: {
|
||||
struct udphdr _udph;
|
||||
const struct udphdr *uh;
|
||||
|
||||
|
@@ -18,4 +18,16 @@ static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
|
||||
extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
|
||||
__be16 *port);
|
||||
|
||||
static inline bool ip_set_proto_with_ports(u8 proto)
|
||||
{
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_SCTP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
||||
|
@@ -121,7 +121,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
if (ip == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return adtfn(set, &ip, h->timeout);
|
||||
return adtfn(set, &ip, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -157,7 +157,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
nip = htonl(ip);
|
||||
if (nip == 0)
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
return adtfn(set, &nip, timeout);
|
||||
return adtfn(set, &nip, timeout, flags);
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
@@ -182,7 +182,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
nip = htonl(ip);
|
||||
if (nip == 0)
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
ret = adtfn(set, &nip, timeout);
|
||||
ret = adtfn(set, &nip, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -294,7 +294,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
if (ipv6_addr_any(&ip.in6))
|
||||
return -EINVAL;
|
||||
|
||||
return adtfn(set, &ip, h->timeout);
|
||||
return adtfn(set, &ip, h->timeout, flags);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
@@ -336,7 +336,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &ip, timeout);
|
||||
ret = adtfn(set, &ip, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
@@ -138,7 +138,7 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -150,6 +150,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_ipport4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
@@ -172,21 +173,15 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -195,10 +190,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -219,19 +213,18 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
}
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -349,7 +342,7 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -361,6 +354,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_ipport6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
@@ -385,21 +379,15 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -407,10 +395,8 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -421,7 +407,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -505,7 +491,7 @@ static struct ip_set_type hash_ipport_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.create = hash_ipport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@@ -142,7 +142,7 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -154,6 +154,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_ipportip4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
@@ -180,21 +181,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -203,10 +198,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -227,19 +221,18 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
}
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -363,7 +356,7 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -375,6 +368,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_ipportip6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
@@ -403,21 +397,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -425,10 +413,8 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -439,7 +425,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -523,7 +509,7 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.create = hash_ipportip_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@@ -162,7 +162,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
|
||||
data.ip2 &= ip_set_netmask(data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -174,6 +174,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
@@ -208,21 +209,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -231,10 +226,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
|
||||
tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -255,19 +249,18 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = port = ntohs(data.port);
|
||||
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
}
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -417,7 +410,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
|
||||
ip6_netmask(&data.ip2, data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -429,6 +422,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
|
||||
@@ -465,21 +459,15 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -487,10 +475,8 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -501,7 +487,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -588,7 +574,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.create = hash_ipportnet_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@@ -141,7 +141,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= ip_set_netmask(data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -179,7 +179,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -344,7 +344,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
@@ -158,7 +158,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= ip_set_netmask(data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -170,6 +170,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_netport4_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
@@ -198,21 +199,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMP))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -220,10 +215,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -234,7 +227,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -378,7 +371,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
return adtfn(set, &data, h->timeout, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -390,6 +383,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
struct hash_netport6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
bool with_ports = false;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!tb[IPSET_ATTR_IP] ||
|
||||
@@ -418,21 +412,15 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
with_ports = ip_set_proto_with_ports(data.proto);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
if (!(with_ports || data.proto == IPPROTO_ICMPV6))
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
@@ -440,10 +428,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST ||
|
||||
!(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
|
||||
!tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
@@ -454,7 +440,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
ret = adtfn(set, &data, timeout, flags);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
@@ -540,7 +526,7 @@ static struct ip_set_type hash_netport_type __read_mostly = {
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.create = hash_netport_create,
|
||||
.create_policy = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
|
@@ -43,14 +43,19 @@ struct list_set {
|
||||
static inline struct set_elem *
|
||||
list_set_elem(const struct list_set *map, u32 id)
|
||||
{
|
||||
return (struct set_elem *)((char *)map->members + id * map->dsize);
|
||||
return (struct set_elem *)((void *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline struct set_telem *
|
||||
list_set_telem(const struct list_set *map, u32 id)
|
||||
{
|
||||
return (struct set_telem *)((void *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
list_set_timeout(const struct list_set *map, u32 id)
|
||||
{
|
||||
const struct set_telem *elem =
|
||||
(const struct set_telem *) list_set_elem(map, id);
|
||||
const struct set_telem *elem = list_set_telem(map, id);
|
||||
|
||||
return ip_set_timeout_test(elem->timeout);
|
||||
}
|
||||
@@ -58,19 +63,11 @@ list_set_timeout(const struct list_set *map, u32 id)
|
||||
static inline bool
|
||||
list_set_expired(const struct list_set *map, u32 id)
|
||||
{
|
||||
const struct set_telem *elem =
|
||||
(const struct set_telem *) list_set_elem(map, id);
|
||||
const struct set_telem *elem = list_set_telem(map, id);
|
||||
|
||||
return ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
list_set_exist(const struct set_telem *elem)
|
||||
{
|
||||
return elem->id != IPSET_INVALID_ID &&
|
||||
!ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
/* Set list without and with timeout */
|
||||
|
||||
static int
|
||||
@@ -112,15 +109,28 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static bool
|
||||
next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
const struct set_elem *elem;
|
||||
|
||||
if (i + 1 < map->size) {
|
||||
elem = list_set_elem(map, i + 1);
|
||||
if (i < map->size) {
|
||||
elem = list_set_elem(map, i);
|
||||
return elem->id == id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
const struct set_elem *elem;
|
||||
|
||||
if (i < map->size) {
|
||||
elem = list_set_elem(map, i);
|
||||
return !!(elem->id == id &&
|
||||
!(with_timeout(map->timeout) &&
|
||||
list_set_expired(map, i + 1)));
|
||||
list_set_expired(map, i)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -146,11 +156,11 @@ list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
struct set_telem *e;
|
||||
|
||||
for (; i < map->size; i++) {
|
||||
e = (struct set_telem *)list_set_elem(map, i);
|
||||
e = list_set_telem(map, i);
|
||||
swap(e->id, id);
|
||||
swap(e->timeout, timeout);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
swap(e->timeout, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +174,7 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
/* Last element replaced: e.g. add new,before,last */
|
||||
ip_set_put_byindex(e->id);
|
||||
if (with_timeout(map->timeout))
|
||||
list_elem_tadd(map, i, id, timeout);
|
||||
list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
|
||||
else
|
||||
list_elem_add(map, i, id);
|
||||
|
||||
@@ -172,11 +182,11 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
|
||||
list_set_del(struct list_set *map, u32 i)
|
||||
{
|
||||
struct set_elem *a = list_set_elem(map, i), *b;
|
||||
|
||||
ip_set_put_byindex(id);
|
||||
ip_set_put_byindex(a->id);
|
||||
|
||||
for (; i < map->size - 1; i++) {
|
||||
b = list_set_elem(map, i + 1);
|
||||
@@ -193,12 +203,26 @@ list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_entries(struct list_set *map)
|
||||
{
|
||||
struct set_telem *e;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
e = list_set_telem(map, i);
|
||||
if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
|
||||
list_set_del(map, i);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
bool with_timeout = with_timeout(map->timeout);
|
||||
bool flag_exist = flags & IPSET_FLAG_EXIST;
|
||||
int before = 0;
|
||||
u32 timeout = map->timeout;
|
||||
ip_set_id_t id, refid = IPSET_INVALID_ID;
|
||||
@@ -251,6 +275,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
}
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
if (with_timeout && adt != IPSET_TEST)
|
||||
cleanup_entries(map);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
@@ -262,22 +288,37 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
else if (with_timeout && list_set_expired(map, i))
|
||||
continue;
|
||||
else if (before > 0 && elem->id == id)
|
||||
ret = next_id_eq(map, i, refid);
|
||||
ret = id_eq_timeout(map, i + 1, refid);
|
||||
else if (before < 0 && elem->id == refid)
|
||||
ret = next_id_eq(map, i, id);
|
||||
ret = id_eq_timeout(map, i + 1, id);
|
||||
else if (before == 0 && elem->id == id)
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case IPSET_ADD:
|
||||
for (i = 0; i < map->size && !ret; i++) {
|
||||
for (i = 0; i < map->size; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == id &&
|
||||
!(with_timeout && list_set_expired(map, i)))
|
||||
if (elem->id != id)
|
||||
continue;
|
||||
if (!(with_timeout && flag_exist)) {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto finish;
|
||||
} else {
|
||||
struct set_telem *e = list_set_telem(map, i);
|
||||
|
||||
if ((before > 1 &&
|
||||
!id_eq(map, i + 1, refid)) ||
|
||||
(before < 0 &&
|
||||
(i == 0 || !id_eq(map, i - 1, refid)))) {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto finish;
|
||||
}
|
||||
e->timeout = ip_set_timeout_set(timeout);
|
||||
ip_set_put_byindex(id);
|
||||
ret = 0;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
if (ret == -IPSET_ERR_EXIST)
|
||||
break;
|
||||
ret = -IPSET_ERR_LIST_FULL;
|
||||
for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
@@ -286,9 +327,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
: list_set_add(map, i, id, timeout);
|
||||
else if (elem->id != refid)
|
||||
continue;
|
||||
else if (with_timeout && list_set_expired(map, i))
|
||||
ret = -IPSET_ERR_REF_EXIST;
|
||||
else if (before)
|
||||
else if (before > 0)
|
||||
ret = list_set_add(map, i, id, timeout);
|
||||
else if (i + 1 < map->size)
|
||||
ret = list_set_add(map, i + 1, id, timeout);
|
||||
@@ -302,17 +341,13 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
ret = before != 0 ? -IPSET_ERR_REF_EXIST
|
||||
: -IPSET_ERR_EXIST;
|
||||
break;
|
||||
} else if (with_timeout && list_set_expired(map, i))
|
||||
continue;
|
||||
else if (elem->id == id &&
|
||||
(before == 0 ||
|
||||
(before > 0 &&
|
||||
next_id_eq(map, i, refid))))
|
||||
ret = list_set_del(map, id, i);
|
||||
else if (before < 0 &&
|
||||
elem->id == refid &&
|
||||
next_id_eq(map, i, id))
|
||||
ret = list_set_del(map, id, i + 1);
|
||||
} else if (elem->id == id &&
|
||||
(before == 0 ||
|
||||
(before > 0 && id_eq(map, i + 1, refid))))
|
||||
ret = list_set_del(map, i);
|
||||
else if (elem->id == refid &&
|
||||
before < 0 && id_eq(map, i + 1, id))
|
||||
ret = list_set_del(map, i + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -369,8 +404,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->size * map->dsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
@@ -458,19 +492,10 @@ list_set_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct list_set *map = set->data;
|
||||
struct set_telem *e;
|
||||
u32 i;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (i = map->size - 1; i >= 0; i--) {
|
||||
e = (struct set_telem *) list_set_elem(map, i);
|
||||
if (e->id != IPSET_INVALID_ID &&
|
||||
list_set_expired(map, i))
|
||||
list_set_del(map, e->id, i);
|
||||
}
|
||||
read_unlock_bh(&set->lock);
|
||||
write_lock_bh(&set->lock);
|
||||
cleanup_entries(map);
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
|
@@ -231,6 +231,8 @@ parameter for the \fBcreate\fR command means the default timeout value (in secon
|
||||
for new entries. If a set is created with timeout support, then the same
|
||||
\fBtimeout\fR option can be used to specify non\-default timeout values
|
||||
when adding entries. Zero timeout value means the entry is added permanent to the set.
|
||||
The timeout value of already added elements can be changed by readding the element
|
||||
using the \fB\-exist\fR option.
|
||||
.SS bitmap:ip
|
||||
The \fBbitmap:ip\fR set type uses a memory range to store either IPv4 host
|
||||
(default) or IPv4 network addresses. A \fBbitmap:ip\fR type of set can store up
|
||||
@@ -330,6 +332,9 @@ Mandatory options to use when creating a \fBbitmap:port\fR type of set:
|
||||
\fBrange\fP \fIfromport\fP\-\fItoport\fR
|
||||
Create the set from the specified inclusive port range.
|
||||
.PP
|
||||
The \fBset\fR match and \fBSET\fR target netfilter kernel modules interpret
|
||||
the stored numbers as TCP or UDP port numbers.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo bitmap:port range 0\-1024
|
||||
@@ -380,9 +385,9 @@ a range or a network:
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:ip netmask 24
|
||||
ipset create foo hash:ip netmask 30
|
||||
.IP
|
||||
ipset add foo 192.168.1.1\-192.168.1.2
|
||||
ipset add foo 192.168.1.0/24
|
||||
.IP
|
||||
ipset test foo 192.168.1.2
|
||||
.SS hash:net
|
||||
@@ -414,8 +419,10 @@ correct value.
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.PP
|
||||
When adding/deleting/testing entries, if the cidr prefix parameter is not specified,
|
||||
then the host prefix value is assumed. When adding/deleting entries, overlapping
|
||||
elements are not checked.
|
||||
then the host prefix value is assumed. When adding/deleting entries, the exact
|
||||
element is added/deleted and overlapping elements are not checked by the kernel.
|
||||
When testing entries, if a host address is tested, then the kernel tries to match
|
||||
the host address in the networks added to the set and reports the result accordingly.
|
||||
.PP
|
||||
From the \fBset\fR netfilter match point of view the searching for a match
|
||||
always starts from the smallest size of netblock (most specific
|
||||
@@ -431,7 +438,7 @@ Examples:
|
||||
.IP
|
||||
ipset create foo hash:net
|
||||
.IP
|
||||
ipset add foo 192.168.0/24
|
||||
ipset add foo 192.168.0.0/24
|
||||
.IP
|
||||
ipset add foo 10.1.0.0/16
|
||||
.IP
|
||||
@@ -481,8 +488,8 @@ TCP port or range of ports expressed in TCP portname identifiers from /etc/servi
|
||||
\fIportnumber[\-portnumber]\fR
|
||||
TCP port or range of ports expressed in TCP port numbers
|
||||
.TP
|
||||
\fBtcp\fR|\fBudp\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR]
|
||||
TCP or UDP port or port range expressed in port name(s) or port number(s)
|
||||
\fBtcp\fR|\fBsctp\fR|\fBudp\fR|\fBudplite\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR]
|
||||
TCP, SCTP, UDP or UDPLITE port or port range expressed in port name(s) or port number(s)
|
||||
.TP
|
||||
\fBicmp\fR:\fIcodename\fR|\fItype\fR/\fIcode\fR
|
||||
ICMP codename or type/code. The supported ICMP codename identifiers can always
|
||||
@@ -508,7 +515,7 @@ ipset add foo 192.168.1.0/24,80\-82
|
||||
.IP
|
||||
ipset add foo 192.168.1.1,udp:53
|
||||
.IP
|
||||
ipset add foo 192.168.1.1,ospf:0
|
||||
ipset add foo 192.168.1.1,vrrp:0
|
||||
.IP
|
||||
ipset test foo 192.168.1.1,80
|
||||
.SS hash:net,port
|
||||
@@ -547,8 +554,10 @@ part of the elements see the description at the
|
||||
\fBhash:ip,port\fR set type.
|
||||
.PP
|
||||
When adding/deleting/testing entries, if the cidr prefix parameter is not specified,
|
||||
then the host prefix value is assumed. When adding/deleting entries, overlapping
|
||||
elements are not checked.
|
||||
then the host prefix value is assumed. When adding/deleting entries, the exact
|
||||
element is added/deleted and overlapping elements are not checked by the kernel.
|
||||
When testing entries, if a host address is tested, then the kernel tries to match
|
||||
the host address in the networks added to the set and reports the result accordingly.
|
||||
.PP
|
||||
From the \fBset\fR netfilter match point of view the searching for a match
|
||||
always starts from the smallest size of netblock (most specific
|
||||
|
@@ -500,10 +500,9 @@ ipset_parse_proto_port(struct ipset_session *session,
|
||||
p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
|
||||
switch (p) {
|
||||
case IPPROTO_TCP:
|
||||
proto = tmp;
|
||||
tmp = a;
|
||||
goto parse_port;
|
||||
case IPPROTO_SCTP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
proto = tmp;
|
||||
tmp = a;
|
||||
goto parse_port;
|
||||
|
@@ -585,7 +585,9 @@ ipset_print_proto_port(char *buf, unsigned int len,
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_SCTP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
return ipset_print_icmp(buf + offset, len, data,
|
||||
|
@@ -198,7 +198,7 @@ create_type_get(struct ipset_session *session)
|
||||
struct ipset_data *data;
|
||||
const char *typename;
|
||||
uint8_t family, tmin = 0, tmax = 0;
|
||||
const uint8_t *kmin, *kmax;
|
||||
uint8_t kmin, kmax;
|
||||
int ret;
|
||||
|
||||
data = ipset_session_data(session);
|
||||
@@ -216,7 +216,7 @@ create_type_get(struct ipset_session *session)
|
||||
&& MATCH_FAMILY(t, family)) {
|
||||
if (match == NULL) {
|
||||
match = t;
|
||||
tmax = t->revision;
|
||||
tmin = tmax = t->revision;
|
||||
} else if (t->family == match->family)
|
||||
tmin = t->revision;
|
||||
}
|
||||
@@ -240,32 +240,31 @@ create_type_get(struct ipset_session *session)
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
|
||||
kmax = ipset_data_get(data, IPSET_OPT_REVISION);
|
||||
kmin = kmax = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION);
|
||||
if (ipset_data_test(data, IPSET_OPT_REVISION_MIN))
|
||||
kmin = ipset_data_get(data, IPSET_OPT_REVISION_MIN);
|
||||
else
|
||||
kmin = kmax;
|
||||
if (MAX(tmin, *kmin) > MIN(tmax, *kmax)) {
|
||||
if (*kmin > tmax)
|
||||
kmin = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION_MIN);
|
||||
|
||||
if (MAX(tmin, kmin) > MIN(tmax, kmax)) {
|
||||
if (kmin > tmax)
|
||||
return ipset_errptr(session,
|
||||
"Kernel supports %s type with family %s "
|
||||
"in minimal revision %u while ipset library "
|
||||
"in maximal revision %u. "
|
||||
"You need to upgrade your ipset library.",
|
||||
"Kernel supports %s type, family %s "
|
||||
"with minimal revision %u while ipset program "
|
||||
"with maximal revision %u.\n"
|
||||
"You need to upgrade your ipset program.",
|
||||
typename,
|
||||
family == AF_INET ? "INET" :
|
||||
family == AF_INET6 ? "INET6" : "UNSPEC",
|
||||
*kmin, tmax);
|
||||
kmin, tmax);
|
||||
else
|
||||
return ipset_errptr(session,
|
||||
"Kernel supports %s type with family %s "
|
||||
"in maximal revision %u while ipset library "
|
||||
"in minimal revision %u. "
|
||||
"Kernel supports %s type, family %s "
|
||||
"with maximal revision %u while ipset program "
|
||||
"with minimal revision %u.\n"
|
||||
"You need to upgrade your kernel.",
|
||||
typename,
|
||||
family == AF_INET ? "INET" :
|
||||
family == AF_INET6 ? "INET6" : "UNSPEC",
|
||||
*kmax, tmin);
|
||||
kmax, tmin);
|
||||
}
|
||||
|
||||
match->kernel_check = IPSET_KERNEL_OK;
|
||||
|
@@ -82,13 +82,13 @@ static const char hash_ipport_usage[] =
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname).\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" is supported for IPv4.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range\n"
|
||||
" is supported both for IPv4 and IPv6.\n";
|
||||
" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
|
||||
" port range is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ipport0 = {
|
||||
.name = "hash:ip,port",
|
||||
.alias = { "ipporthash", NULL },
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.elem = {
|
||||
|
@@ -82,13 +82,13 @@ static const char hash_ipportip_usage[] =
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname).\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" in the first IP component is supported for IPv4.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range\n"
|
||||
" is supported both for IPv4 and IPv6.\n";
|
||||
" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
|
||||
" port range is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ipportip0 = {
|
||||
.name = "hash:ip,port,ip",
|
||||
.alias = { "ipportiphash", NULL },
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.elem = {
|
||||
|
@@ -83,13 +83,13 @@ static const char hash_ipportnet_usage[] =
|
||||
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" in the first IP component is supported for IPv4.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range\n"
|
||||
" is supported both for IPv4 and IPv6.\n";
|
||||
" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
|
||||
" port range is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ipportnet0 = {
|
||||
.name = "hash:ip,port,net",
|
||||
.alias = { "ipportnethash", NULL },
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.elem = {
|
||||
|
@@ -60,12 +60,13 @@ static const char hash_netport_usage[] =
|
||||
"where depending on the INET family\n"
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname),\n"
|
||||
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range supported.\n";
|
||||
" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n"
|
||||
" port range is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_netport0 = {
|
||||
.name = "hash:net,port",
|
||||
.alias = { "netporthash", NULL },
|
||||
.revision = 0,
|
||||
.revision = 1,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.elem = {
|
||||
|
Reference in New Issue
Block a user