u8 physdev;
u8 cidr;
u8 nomatch;
- u8 padding;
+ u8 elem;
};
#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
u8 physdev;
u8 cidr;
u8 nomatch;
- u8 padding;
+ u8 elem;
const char *iface;
};
u8 physdev;
u8 cidr;
u8 nomatch;
- u8 padding;
+ u8 elem;
const char *iface;
unsigned long timeout;
};
static inline bool
hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
{
- return elem->cidr == 0;
+ return elem->elem == 0;
}
static inline void
hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
const struct hash_netiface4_elem *src)
{
- dst->ip = src->ip;
- dst->cidr = src->cidr;
- dst->physdev = src->physdev;
- dst->iface = src->iface;
- dst->nomatch = src->nomatch;
+ memcpy(dst, src, sizeof(*dst));
}
static inline void
static inline void
hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
{
- elem->cidr = 0;
+ elem->elem = 0;
}
static bool
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+ .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
+ .elem = 1,
};
int ret;
{
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netiface4_elem data = { .cidr = HOST_MASK };
+ struct hash_netiface4_elem data = { .cidr = HOST_MASK, .elem = 1 };
u32 ip = 0, ip_to, last;
u32 timeout = h->timeout;
char iface[IFNAMSIZ];
if (tb[IPSET_ATTR_CIDR]) {
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr || data.cidr > HOST_MASK)
+ if (data.cidr > HOST_MASK)
return -IPSET_ERR_INVALID_CIDR;
}
if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH))
flags |= (cadt_flags << 16);
}
-
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
ret = adtfn(set, &data, timeout, flags);
u8 physdev;
u8 cidr;
u8 nomatch;
- u8 padding;
+ u8 elem;
};
#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
u8 physdev;
u8 cidr;
u8 nomatch;
- u8 padding;
+ u8 elem;
const char *iface;
};
u8 physdev;
u8 cidr;
u8 nomatch;
- u8 padding;
+ u8 elem;
const char *iface;
unsigned long timeout;
};
static inline bool
hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
{
- return elem->cidr == 0;
+ return elem->elem == 0;
}
static inline void
static inline void
hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
{
- elem->cidr = 0;
+ elem->elem = 0;
}
static inline void
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface6_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+ .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
+ .elem = 1,
};
int ret;
{
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netiface6_elem data = { .cidr = HOST_MASK };
+ struct hash_netiface6_elem data = { .cidr = HOST_MASK, .elem = 1 };
u32 timeout = h->timeout;
char iface[IFNAMSIZ];
int ret;
if (tb[IPSET_ATTR_CIDR])
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr || data.cidr > HOST_MASK)
+ if (data.cidr > HOST_MASK)
return -IPSET_ERR_INVALID_CIDR;
ip6_netmask(&data.ip, data.cidr);
.dimension = IPSET_DIM_TWO,
.family = NFPROTO_UNSPEC,
.revision_min = 0,
- .revision_max = 1, /* nomatch flag support added */
+ /* = 1, nomatch flag support added */
+ .revision_max = 2, /* /0 support added */
.create = hash_netiface_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
.usage = hash_netiface1_usage,
};
+static struct ipset_type ipset_hash_netiface2 = {
+ .name = "hash:net,iface",
+ .alias = { "netifacehash", NULL },
+ .revision = 2,
+ .family = NFPROTO_IPSET_IPV46,
+ .dimension = IPSET_DIM_TWO,
+ .elem = {
+ [IPSET_DIM_ONE - 1] = {
+ .parse = ipset_parse_ip4_net6,
+ .print = ipset_print_ip,
+ .opt = IPSET_OPT_IP
+ },
+ [IPSET_DIM_TWO - 1] = {
+ .parse = ipset_parse_iface,
+ .print = ipset_print_iface,
+ .opt = IPSET_OPT_IFACE
+ },
+ },
+ .args = {
+ [IPSET_CREATE] = hash_netiface_create_args,
+ [IPSET_ADD] = hash_netiface1_add_args,
+ },
+ .mandatory = {
+ [IPSET_CREATE] = 0,
+ [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IFACE),
+ [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IFACE),
+ [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_IFACE),
+ },
+ .full = {
+ [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
+ | IPSET_FLAG(IPSET_OPT_MAXELEM)
+ | IPSET_FLAG(IPSET_OPT_TIMEOUT),
+ [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IFACE)
+ | IPSET_FLAG(IPSET_OPT_PHYSDEV)
+ | IPSET_FLAG(IPSET_OPT_TIMEOUT)
+ | IPSET_FLAG(IPSET_OPT_NOMATCH),
+ [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IFACE)
+ | IPSET_FLAG(IPSET_OPT_PHYSDEV),
+ [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
+ | IPSET_FLAG(IPSET_OPT_CIDR)
+ | IPSET_FLAG(IPSET_OPT_IP_TO)
+ | IPSET_FLAG(IPSET_OPT_IFACE)
+ | IPSET_FLAG(IPSET_OPT_PHYSDEV),
+ },
+
+ .usage = hash_netiface1_usage,
+};
+
void _init(void);
void _init(void)
{
ipset_type_add(&ipset_hash_netiface0);
ipset_type_add(&ipset_hash_netiface1);
+ ipset_type_add(&ipset_hash_netiface2);
}
ipset test foo 192.168.1,80.10.0.0/24
.SS hash:net,iface
The \fBhash:net,iface\fR set type uses a hash to store different sized IP network
-address and interface name pairs. Network address with zero prefix size is not
-accepted.
+address and interface name pairs.
.PP
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
.PP
# Create a set
0 ipset create test hash:net,iface hashsize 128
# Add zero valued element
-1 ipset add test 0.0.0.0/0,eth0
+0 ipset add test 0.0.0.0/0,eth0
# Test zero valued element
-1 ipset test test 0.0.0.0/0,eth0
+0 ipset test test 0.0.0.0/0,eth0
# Delete zero valued element
-1 ipset del test 0.0.0.0/0,eth0
-# Try to add /0
-1 ipset add test 1.1.1.1/0,eth0
+0 ipset del test 0.0.0.0/0,eth0
+# Add 1.1.1.1/0
+0 ipset add test 1.1.1.1/0,eth0
+# Test 1.1.1.1/0
+0 ipset test test 1.1.1.1/0,eth0
+# Delete 1.1.1.1/0
+0 ipset del test 1.1.1.1/0,eth0
# Try to add /32
0 ipset add test 1.1.1.1/32,eth0
# Add almost zero valued element
0 ipset -L test 2>/dev/null > .foo0 && ./sort.sh .foo0
# Check listing
0 diff -u -I 'Size in memory.*' .foo hash:net,iface.t.list2
+# Flush test set
+0 ipset flush test
+# Add 0/0,eth0
+0 ipset add test 0/0,eth0
+# Add 10.0.0.0/16,eth1
+0 ipset add test 10.0.0.0/16,eth1
+# Add 10.0.0.0/24,eth0
+0 ipset add test 10.0.0.0/24,eth0
+# Add 10.0.0.0/16,eth2
+0 ipset add test 10.0.0.0/16,eth2
+# Check 10.0.1.1 with eth1
+0 ipset test test 10.0.1.1,eth1
+# Check 10.0.1.1 with eth2
+0 ipset test test 10.0.1.1,eth2
+# Check 10.0.1.1 with eth0
+1 ipset test test 10.0.1.1,eth0
+# Check 10.0.0.1 with eth1
+1 ipset test test 10.0.0.1,eth1
+# Check 10.0.0.1 with eth2
+1 ipset test test 10.0.0.1,eth2
+# Check 10.0.0.1 with eth0
+0 ipset test test 10.0.0.1,eth0
+# Check 1.0.1.1 with eth1
+1 ipset test test 1.0.1.1,eth1
+# Check 1.0.1.1 with eth2
+1 ipset test test 1.0.1.1,eth2
+# Check 1.0.1.1 with eth0
+0 ipset test test 1.0.1.1,eth0
# Delete test set
0 ipset destroy test
# Create test set