aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2014-10-13 13:49:28 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2014-10-13 13:49:28 +0000
commit2930362fb17c172dd1cadc923badbb65f4851241 (patch)
tree60f19b7ca48a294aa7225d13b772accbdcede02e /sys
parent9bfafa105547b490aab3f0cf465485024184e989 (diff)
downloadsrc-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.h5
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c15
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) {