aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2012-09-21 16:02:36 -0400
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2012-09-22 16:44:34 -0400
commit3e0304a583d72c747caa8afac76b8d514aa293f5 (patch)
tree134fd8cc48ed72be16a7ca2f90b169de103bec2e
parent3ace95c0ac125a042cfb682d0a9bbdbf1e5a2c65 (diff)
netfilter: ipset: Support to match elements marked with "nomatch"
Exceptions can now be matched and we can branch according to the possible cases: a. match in the set if the element is not flagged as "nomatch" b. match in the set if the element is flagged with "nomatch" c. no match i.e. iptables ... -m set --match-set ... -j ... iptables ... -m set --match-set ... --nomatch-entries -j ... ... Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
-rw-r--r--include/linux/netfilter/ipset/ip_set.h4
-rw-r--r--net/netfilter/ipset/ip_set_core.c6
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c11
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c10
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c11
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c10
-rw-r--r--net/netfilter/xt_set.c22
7 files changed, 54 insertions, 20 deletions
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index 0c1e97b3acfb..528697b3c152 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -190,6 +190,7 @@ enum ip_set_dim {
190 * If changed, new revision of iptables match/target is required. 190 * If changed, new revision of iptables match/target is required.
191 */ 191 */
192 IPSET_DIM_MAX = 6, 192 IPSET_DIM_MAX = 6,
193 IPSET_BIT_RETURN_NOMATCH = 7,
193}; 194};
194 195
195/* Option flags for kernel operations */ 196/* Option flags for kernel operations */
@@ -198,6 +199,7 @@ enum ip_set_kopt {
198 IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), 199 IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
199 IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), 200 IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
200 IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), 201 IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
202 IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
201}; 203};
202 204
203#ifdef __KERNEL__ 205#ifdef __KERNEL__
@@ -229,6 +231,8 @@ enum ip_set_feature {
229 IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG), 231 IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
230 IPSET_TYPE_IFACE_FLAG = 5, 232 IPSET_TYPE_IFACE_FLAG = 5,
231 IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG), 233 IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
234 IPSET_TYPE_NOMATCH_FLAG = 6,
235 IPSET_TYPE_NOMATCH = (1 << IPSET_TYPE_NOMATCH_FLAG),
232 /* Strictly speaking not a feature, but a flag for dumping: 236 /* Strictly speaking not a feature, but a flag for dumping:
233 * this settype must be dumped last */ 237 * this settype must be dumped last */
234 IPSET_DUMP_LAST_FLAG = 7, 238 IPSET_DUMP_LAST_FLAG = 7,
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 72e9bf0ef90d..778465f217fa 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -370,6 +370,12 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
370 set->variant->kadt(set, skb, par, IPSET_ADD, opt); 370 set->variant->kadt(set, skb, par, IPSET_ADD, opt);
371 write_unlock_bh(&set->lock); 371 write_unlock_bh(&set->lock);
372 ret = 1; 372 ret = 1;
373 } else {
374 /* --return-nomatch: invert matched element */
375 if ((opt->flags & IPSET_RETURN_NOMATCH) &&
376 (set->type->features & IPSET_TYPE_NOMATCH) &&
377 (ret > 0 || ret == -ENOTEMPTY))
378 ret = -ret;
373 } 379 }
374 380
375 /* Convert error codes to nomatch */ 381 /* Convert error codes to nomatch */
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 8ee916875a23..cb71f9a774e7 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -104,10 +104,10 @@ hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
105} 105}
106 106
107static inline bool 107static inline int
108hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem) 108hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
109{ 109{
110 return !elem->nomatch; 110 return elem->nomatch ? -ENOTEMPTY : 1;
111} 111}
112 112
113static inline void 113static inline void
@@ -411,10 +411,10 @@ hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
411 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 411 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
412} 412}
413 413
414static inline bool 414static inline int
415hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem) 415hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
416{ 416{
417 return !elem->nomatch; 417 return elem->nomatch ? -ENOTEMPTY : 1;
418} 418}
419 419
420static inline void 420static inline void
@@ -697,7 +697,8 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
697static struct ip_set_type hash_ipportnet_type __read_mostly = { 697static struct ip_set_type hash_ipportnet_type __read_mostly = {
698 .name = "hash:ip,port,net", 698 .name = "hash:ip,port,net",
699 .protocol = IPSET_PROTOCOL, 699 .protocol = IPSET_PROTOCOL,
700 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, 700 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 |
701 IPSET_TYPE_NOMATCH,
701 .dimension = IPSET_DIM_THREE, 702 .dimension = IPSET_DIM_THREE,
702 .family = NFPROTO_UNSPEC, 703 .family = NFPROTO_UNSPEC,
703 .revision_min = REVISION_MIN, 704 .revision_min = REVISION_MIN,
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 014ff7272f7b..29e94b981f3f 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -90,10 +90,10 @@ hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags)
90 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 90 dst->nomatch = flags & IPSET_FLAG_NOMATCH;
91} 91}
92 92
93static inline bool 93static inline int
94hash_net4_data_match(const struct hash_net4_elem *elem) 94hash_net4_data_match(const struct hash_net4_elem *elem)
95{ 95{
96 return !elem->nomatch; 96 return elem->nomatch ? -ENOTEMPTY : 1;
97} 97}
98 98
99static inline void 99static inline void
@@ -311,10 +311,10 @@ hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
311 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 311 dst->nomatch = flags & IPSET_FLAG_NOMATCH;
312} 312}
313 313
314static inline bool 314static inline int
315hash_net6_data_match(const struct hash_net6_elem *elem) 315hash_net6_data_match(const struct hash_net6_elem *elem)
316{ 316{
317 return !elem->nomatch; 317 return elem->nomatch ? -ENOTEMPTY : 1;
318} 318}
319 319
320static inline void 320static inline void
@@ -536,7 +536,7 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
536static struct ip_set_type hash_net_type __read_mostly = { 536static struct ip_set_type hash_net_type __read_mostly = {
537 .name = "hash:net", 537 .name = "hash:net",
538 .protocol = IPSET_PROTOCOL, 538 .protocol = IPSET_PROTOCOL,
539 .features = IPSET_TYPE_IP, 539 .features = IPSET_TYPE_IP | IPSET_TYPE_NOMATCH,
540 .dimension = IPSET_DIM_ONE, 540 .dimension = IPSET_DIM_ONE,
541 .family = NFPROTO_UNSPEC, 541 .family = NFPROTO_UNSPEC,
542 .revision_min = REVISION_MIN, 542 .revision_min = REVISION_MIN,
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index a5c8491d265e..b9a63381e349 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -201,10 +201,10 @@ hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
201 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 201 dst->nomatch = flags & IPSET_FLAG_NOMATCH;
202} 202}
203 203
204static inline bool 204static inline int
205hash_netiface4_data_match(const struct hash_netiface4_elem *elem) 205hash_netiface4_data_match(const struct hash_netiface4_elem *elem)
206{ 206{
207 return !elem->nomatch; 207 return elem->nomatch ? -ENOTEMPTY : 1;
208} 208}
209 209
210static inline void 210static inline void
@@ -497,10 +497,10 @@ hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
497 dst->nomatch = flags & IPSET_FLAG_NOMATCH; 497 dst->nomatch = flags & IPSET_FLAG_NOMATCH;
498} 498}
499 499
500static inline bool 500static inline int
501hash_netiface6_data_match(const struct hash_netiface6_elem *elem) 501hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
502{ 502{
503 return !elem->nomatch; 503 return elem->nomatch ? -ENOTEMPTY : 1;
504} 504}
505 505
506static inline void 506static inline void
@@ -774,7 +774,8 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
774static struct ip_set_type hash_netiface_type __read_mostly = { 774static struct ip_set_type hash_netiface_type __read_mostly = {
775 .name = "hash:net,iface", 775 .name = "hash:net,iface",
776 .protocol = IPSET_PROTOCOL, 776 .protocol = IPSET_PROTOCOL,
777 .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE, 777 .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE |
778 IPSET_TYPE_NOMATCH,
778 .dimension = IPSET_DIM_TWO, 779 .dimension = IPSET_DIM_TWO,
779 .family = NFPROTO_UNSPEC, 780 .family = NFPROTO_UNSPEC,
780 .revision_min = REVISION_MIN, 781 .revision_min = REVISION_MIN,
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index 7ca357a62b1c..7ef700de596c 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -104,10 +104,10 @@ hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags)
104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
105} 105}
106 106
107static inline bool 107static inline int
108hash_netport4_data_match(const struct hash_netport4_elem *elem) 108hash_netport4_data_match(const struct hash_netport4_elem *elem)
109{ 109{
110 return !elem->nomatch; 110 return elem->nomatch ? -ENOTEMPTY : 1;
111} 111}
112 112
113static inline void 113static inline void
@@ -375,10 +375,10 @@ hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags)
375 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 375 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
376} 376}
377 377
378static inline bool 378static inline int
379hash_netport6_data_match(const struct hash_netport6_elem *elem) 379hash_netport6_data_match(const struct hash_netport6_elem *elem)
380{ 380{
381 return !elem->nomatch; 381 return elem->nomatch ? -ENOTEMPTY : 1;
382} 382}
383 383
384static inline void 384static inline void
@@ -650,7 +650,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
650static struct ip_set_type hash_netport_type __read_mostly = { 650static struct ip_set_type hash_netport_type __read_mostly = {
651 .name = "hash:net,port", 651 .name = "hash:net,port",
652 .protocol = IPSET_PROTOCOL, 652 .protocol = IPSET_PROTOCOL,
653 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, 653 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_NOMATCH,
654 .dimension = IPSET_DIM_TWO, 654 .dimension = IPSET_DIM_TWO,
655 .family = NFPROTO_UNSPEC, 655 .family = NFPROTO_UNSPEC,
656 .revision_min = REVISION_MIN, 656 .revision_min = REVISION_MIN,
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index c6f7db720d84..865a9e54f3ad 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -356,6 +356,27 @@ static struct xt_match set_matches[] __read_mostly = {
356 .destroy = set_match_v1_destroy, 356 .destroy = set_match_v1_destroy,
357 .me = THIS_MODULE 357 .me = THIS_MODULE
358 }, 358 },
359 /* --return-nomatch flag support */
360 {
361 .name = "set",
362 .family = NFPROTO_IPV4,
363 .revision = 2,
364 .match = set_match_v1,
365 .matchsize = sizeof(struct xt_set_info_match_v1),
366 .checkentry = set_match_v1_checkentry,
367 .destroy = set_match_v1_destroy,
368 .me = THIS_MODULE
369 },
370 {
371 .name = "set",
372 .family = NFPROTO_IPV6,
373 .revision = 2,
374 .match = set_match_v1,
375 .matchsize = sizeof(struct xt_set_info_match_v1),
376 .checkentry = set_match_v1_checkentry,
377 .destroy = set_match_v1_destroy,
378 .me = THIS_MODULE
379 },
359}; 380};
360 381
361static struct xt_target set_targets[] __read_mostly = { 382static struct xt_target set_targets[] __read_mostly = {
@@ -389,6 +410,7 @@ static struct xt_target set_targets[] __read_mostly = {
389 .destroy = set_target_v1_destroy, 410 .destroy = set_target_v1_destroy,
390 .me = THIS_MODULE 411 .me = THIS_MODULE
391 }, 412 },
413 /* --timeout and --exist flags support */
392 { 414 {
393 .name = "SET", 415 .name = "SET",
394 .revision = 2, 416 .revision = 2,