diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2014-10-13 13:49:28 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2014-10-13 13:49:28 +0000 |
commit | 2930362fb17c172dd1cadc923badbb65f4851241 (patch) | |
tree | 60f19b7ca48a294aa7225d13b772accbdcede02e /sys | |
parent | 9bfafa105547b490aab3f0cf465485024184e989 (diff) | |
download | src-2930362fb17c172dd1cadc923badbb65f4851241.tar.gz src-2930362fb17c172dd1cadc923badbb65f4851241.zip |
Fix matching default rule on clear/show commands.
Found by: Oleg Ginzburg
Notes
Notes:
svn path=/head/; revision=273035
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_fw.h | 5 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_sockopt.c | 15 |
2 files changed, 15 insertions, 5 deletions
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index ed61b4fe5fe1..ab9ec63e626a 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -886,6 +886,11 @@ typedef struct _ipfw_range_tlv { #define IPFW_RCFLAG_RANGE 0x01 /* rule range is set */ #define IPFW_RCFLAG_ALL 0x02 /* match ALL rules */ #define IPFW_RCFLAG_SET 0x04 /* match rules in given set */ +/* User-settable flags */ +#define IPFW_RCFLAG_USER (IPFW_RCFLAG_RANGE | IPFW_RCFLAG_ALL | \ + IPFW_RCFLAG_SET) +/* Internally used flags */ +#define IPFW_RCFLAG_DEFAULT 0x0100 /* Do not skip defaul rule */ typedef struct _ipfw_ta_tinfo { uint32_t flags; /* Format flags */ diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 048ad933c6a5..0c0d022dd8b1 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -833,8 +833,9 @@ int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt) { - /* Don't match default rule regardless of query */ - if (rule->rulenum == IPFW_DEFAULT_RULE) + /* Don't match default rule for modification queries */ + if (rule->rulenum == IPFW_DEFAULT_RULE && + (rt->flags & IPFW_RCFLAG_DEFAULT) == 0) return (0); /* Don't match rules in reserved set for flush requests */ @@ -965,7 +966,7 @@ move_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt) } /* XXX: We have to do swap holding WLOCK */ - for (i = 0; i < chain->n_rules - 1; i++) { + for (i = 0; i < chain->n_rules; i++) { rule = chain->map[i]; if (ipfw_match_range(rule, rt) == 0) continue; @@ -1006,9 +1007,10 @@ clear_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int log_only) int i; num = 0; + rt->flags |= IPFW_RCFLAG_DEFAULT; IPFW_UH_WLOCK(chain); /* arbitrate writers */ - for (i = 0; i < chain->n_rules - 1; i++) { + for (i = 0; i < chain->n_rules; i++) { rule = chain->map[i]; if (ipfw_match_range(rule, rt) == 0) continue; @@ -1031,6 +1033,9 @@ check_range_tlv(ipfw_range_tlv *rt) if (rt->set >= IPFW_MAX_SETS || rt->new_set >= IPFW_MAX_SETS) return (1); + if ((rt->flags & IPFW_RCFLAG_USER) != rt->flags) + return (1); + return (0); } @@ -2012,7 +2017,7 @@ dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3, da.b = ipfw_find_rule(chain, rnum, 0); rnum = hdr->end_rule; rnum = (rnum < IPFW_DEFAULT_RULE) ? rnum+1 : IPFW_DEFAULT_RULE; - da.e = ipfw_find_rule(chain, rnum, 0); + da.e = ipfw_find_rule(chain, rnum, 0) + 1; } if (hdr->flags & IPFW_CFG_GET_STATIC) { |