Commit 43c56e59 authored by Jozsef Kadlecsik's avatar Jozsef Kadlecsik Committed by Pablo Neira Ayuso

netfilter: ipset: Make possible to test elements marked with nomatch

Signed-off-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 37fe0660
...@@ -200,6 +200,14 @@ ip_set_eexist(int ret, u32 flags) ...@@ -200,6 +200,14 @@ ip_set_eexist(int ret, u32 flags)
return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST); return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
} }
/* Match elements marked with nomatch */
static inline bool
ip_set_enomatch(int ret, u32 flags, enum ipset_adt adt)
{
return adt == IPSET_TEST &&
ret == -ENOTEMPTY && ((flags >> 16) & IPSET_FLAG_NOMATCH);
}
/* Check the NLA_F_NET_BYTEORDER flag */ /* Check the NLA_F_NET_BYTEORDER flag */
static inline bool static inline bool
ip_set_attr_netorder(struct nlattr *tb[], int type) ip_set_attr_netorder(struct nlattr *tb[], int type)
......
...@@ -279,10 +279,10 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -279,10 +279,10 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
} }
if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_NOMATCH) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
...@@ -292,7 +292,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -292,7 +292,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
data.ip = htonl(ip); data.ip = htonl(ip);
data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1)); data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1));
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
ip_to = ip; ip_to = ip;
...@@ -610,15 +611,16 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -610,15 +611,16 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
} }
if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_NOMATCH) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
port = ntohs(data.port); port = ntohs(data.port);
......
...@@ -225,16 +225,17 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -225,16 +225,17 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
} }
if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_NOMATCH) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
data.ip = htonl(ip & ip_set_hostmask(data.cidr)); data.ip = htonl(ip & ip_set_hostmask(data.cidr));
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
ip_to = ip; ip_to = ip;
...@@ -466,15 +467,16 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -466,15 +467,16 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
} }
if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_NOMATCH) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
/* Create hash:ip type of sets */ /* Create hash:ip type of sets */
......
...@@ -396,13 +396,14 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -396,13 +396,14 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_PHYSDEV) if (cadt_flags & IPSET_FLAG_PHYSDEV)
data.physdev = 1; data.physdev = 1;
if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
data.ip = htonl(ip & ip_set_hostmask(data.cidr)); data.ip = htonl(ip & ip_set_hostmask(data.cidr));
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
if (tb[IPSET_ATTR_IP_TO]) { if (tb[IPSET_ATTR_IP_TO]) {
...@@ -704,13 +705,14 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -704,13 +705,14 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_PHYSDEV) if (cadt_flags & IPSET_FLAG_PHYSDEV)
data.physdev = 1; data.physdev = 1;
if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH)) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
/* Create hash:ip type of sets */ /* Create hash:ip type of sets */
......
...@@ -272,16 +272,17 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -272,16 +272,17 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_NOMATCH) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) { if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
data.ip = htonl(ip & ip_set_hostmask(data.cidr + 1)); data.ip = htonl(ip & ip_set_hostmask(data.cidr + 1));
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
port = port_to = ntohs(data.port); port = port_to = ntohs(data.port);
...@@ -561,15 +562,16 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], ...@@ -561,15 +562,16 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
} }
if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) { if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_NOMATCH) if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (cadt_flags << 16); flags |= (IPSET_FLAG_NOMATCH << 16);
} }
if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
ret = adtfn(set, &data, timeout, flags); ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret; return ip_set_enomatch(ret, flags, adt) ? 1 :
ip_set_eexist(ret, flags) ? 0 : ret;
} }
port = ntohs(data.port); port = ntohs(data.port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment