Page MenuHomeFreeBSD

D1776.id3634.diff
No OneTemporary

D1776.id3634.diff

Index: sbin/ipfw/ipfw.8
===================================================================
--- sbin/ipfw/ipfw.8
+++ sbin/ipfw/ipfw.8
@@ -166,9 +166,11 @@
depending on how the kernel is configured.
.Pp
If the ruleset includes one or more rules with the
-.Cm keep-state
+.Cm keep-state ,
+.Cm record-state ,
+.Cm limit
or
-.Cm limit
+.Cm set-limit
option,
the firewall will have a
.Em stateful
@@ -185,6 +187,18 @@
.Cm limit
rule, and are typically used to open the firewall on-demand to
legitimate traffic only.
+Please, note, that
+.Cm keep-state
+amd
+.Cm limit
+imply implicit
+.Cm check-state
+for all packets (not only matched by rule) but
+.Cm record-state
+and
+.Cm set-limit
+have not implicit
+.Cm check-state .
See the
.Sx STATEFUL FIREWALL
and
@@ -582,7 +596,12 @@
packet delivery.
.Pp
Note: this condition is checked before any other condition, including
-ones such as keep-state or check-state which might have side effects.
+ones such as
+.Cm keep-state
+or
+.Cm check-state
+which might have
+side effects.
.It Cm log Op Cm logamount Ar number
Packets matching a rule with the
.Cm log
@@ -1583,6 +1602,34 @@
.Xr sysctl 8
variables), and the lifetime is refreshed every time a matching
packet is found.
+.It Cm record-state
+Upon a match, the firewall will create a dynamic rule as if
+.Cm keep-state
+was specified.
+This option doesn't act as
+.Cm check-state
+in contrast to
+.Cm keep-state .
+.It Cm set-limit Bro Cm src-addr | src-port | dst-addr | dst-port Brc Ar N
+Works exactly like
+.Cm limit
+but rule with this option doesn't have implicit
+.Cm check-state
+attached to it.
+.It Cm skip-immediate-action | skip-action
+Rule with this option will not perform normal action
+upon a match. This option is intended to be used with
+.Cm record-state
+or
+.Cm keep-state
+as dynamic rule, created on match, will work
+as intended.
+Rule with both
+.Cm record-state
+and
+.Cm skip-immediate-action
+creates dynamic rule and continues with next rule, but
+when dynamic rule is matched, action is executed as usual.
.It Cm layer2
Matches only layer2 packets, i.e., those passed to
.Nm
@@ -2164,16 +2211,18 @@
match a given pattern are detected.
Support for stateful
operation comes through the
-.Cm check-state , keep-state
+.Cm check-state , keep-state , record-state , limit
and
-.Cm limit
+.Cm set-limit
options of
.Nm rules .
.Pp
Dynamic rules are created when a packet matches a
-.Cm keep-state
+.Cm keep-state ,
+.Cm record-state ,
+.Cm limit
or
-.Cm limit
+.Cm set-limit
rule, causing the creation of a
.Em dynamic
rule which will match all and only packets with
Index: sbin/ipfw/ipfw2.h
===================================================================
--- sbin/ipfw/ipfw2.h
+++ sbin/ipfw/ipfw2.h
@@ -115,7 +115,9 @@
TOK_JAIL,
TOK_IN,
TOK_LIMIT,
+ TOK_SETLIMIT,
TOK_KEEPSTATE,
+ TOK_RECORDSTATE,
TOK_LAYER2,
TOK_OUT,
TOK_DIVERTED,
@@ -227,6 +229,7 @@
TOK_LOCK,
TOK_UNLOCK,
TOK_VLIST,
+ TOK_SKIPACTION,
};
/*
Index: sbin/ipfw/ipfw2.c
===================================================================
--- sbin/ipfw/ipfw2.c
+++ sbin/ipfw/ipfw2.c
@@ -291,7 +291,9 @@
{ "jail", TOK_JAIL },
{ "in", TOK_IN },
{ "limit", TOK_LIMIT },
+ { "set-limit", TOK_SETLIMIT },
{ "keep-state", TOK_KEEPSTATE },
+ { "record-state", TOK_RECORDSTATE },
{ "bridged", TOK_LAYER2 },
{ "layer2", TOK_LAYER2 },
{ "out", TOK_OUT },
@@ -354,6 +356,8 @@
{ "src-ip6", TOK_SRCIP6},
{ "lookup", TOK_LOOKUP},
{ "flow", TOK_FLOW},
+ { "skip-action", TOK_SKIPACTION },
+ { "skip-immediate-action", TOK_SKIPACTION },
{ "//", TOK_COMMENT },
{ "not", TOK_NOT }, /* pseudo option */
@@ -1384,6 +1388,7 @@
ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */
int or_block = 0; /* we are in an or block */
uint32_t uval;
+ int have_probe_state = 0;
if ((fo->set_mask & (1 << rule->set)) == 0) {
/* disabled mask */
@@ -1653,6 +1658,7 @@
break; /* done already */
case O_PROBE_STATE:
+ have_probe_state = 1;
break; /* no need to print anything here */
case O_IP_SRC:
@@ -1990,7 +1996,10 @@
break;
case O_KEEP_STATE:
- bprintf(bp, " keep-state");
+ if (have_probe_state)
+ bprintf(bp, " keep-state");
+ else
+ bprintf(bp, " record-state");
break;
case O_LIMIT: {
@@ -1999,7 +2008,11 @@
uint8_t x = c->limit_mask;
char const *comma = " ";
- bprintf(bp, " limit");
+ if (have_probe_state)
+ bprintf(bp, " limit");
+ else
+ bprintf(bp, " set-limit");
+
for (; p->x != 0 ; p++)
if ((x & p->x) == p->x) {
x &= ~p->x;
@@ -2035,6 +2048,10 @@
0, O_TAGGED);
break;
+ case O_SKIP_ACTION:
+ bprintf(bp, " skip-immediate-action");
+ break;
+
default:
bprintf(bp, " [opcode %d len %d]",
cmd->opcode, cmd->len);
@@ -3485,8 +3502,10 @@
/*
* various flags used to record that we entered some fields.
*/
- ipfw_insn *have_state = NULL; /* check-state or keep-state */
+ ipfw_insn *have_state = NULL; /* any state-related option */
+ int have_rstate = 0;
ipfw_insn *have_log = NULL, *have_altq = NULL, *have_tag = NULL;
+ ipfw_insn *have_skipcmd = NULL;
size_t len;
int i;
@@ -4335,27 +4354,31 @@
break;
case TOK_KEEPSTATE:
+ case TOK_RECORDSTATE:
if (open_par)
- errx(EX_USAGE, "keep-state cannot be part "
+ errx(EX_USAGE, "keep-state or record-state cannot be part "
"of an or block");
if (have_state)
- errx(EX_USAGE, "only one of keep-state "
- "and limit is allowed");
+ errx(EX_USAGE, "only one of keep-state, record-state, "
+ " limit and set-limit is allowed");
have_state = cmd;
+ have_rstate = i == TOK_RECORDSTATE;
fill_cmd(cmd, O_KEEP_STATE, 0, 0);
break;
- case TOK_LIMIT: {
+ case TOK_LIMIT:
+ case TOK_SETLIMIT: {
ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
int val;
if (open_par)
errx(EX_USAGE,
- "limit cannot be part of an or block");
+ "limit or set-limit cannot be part of an or block");
if (have_state)
- errx(EX_USAGE, "only one of keep-state and "
- "limit is allowed");
+ errx(EX_USAGE, "only one of keep-state, record-state, "
+ " limit and set-limit is allowed");
have_state = cmd;
+ have_rstate = i == TOK_SETLIMIT;
cmd->len = F_INSN_SIZE(ipfw_insn_limit);
CHECK_CMDLEN;
@@ -4539,6 +4562,7 @@
av++;
}
break;
+
case TOK_FLOW:
NEED1("missing table name");
if (strncmp(*av, "table(", 6) != 0)
@@ -4548,6 +4572,14 @@
av++;
break;
+ case TOK_SKIPACTION:
+ if (have_skipcmd)
+ errx(EX_USAGE, "only one skip-action "
+ "is allowed");
+ have_skipcmd = cmd;
+ fill_cmd(cmd, O_SKIP_ACTION, 0, 0);
+ break;
+
default:
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
}
@@ -4558,6 +4590,11 @@
}
done:
+
+ if (!have_state && have_skipcmd)
+ warnx("Rule contains \"skip-immediate-action\" "
+ "and doesn't contain any state-related options.");
+
/*
* Now copy stuff into the rule.
* If we have a keep-state option, the first instruction
@@ -4580,12 +4617,15 @@
/*
* generate O_PROBE_STATE if necessary
*/
- if (have_state && have_state->opcode != O_CHECK_STATE) {
+ if (have_state && have_state->opcode != O_CHECK_STATE && !have_rstate) {
fill_cmd(dst, O_PROBE_STATE, 0, 0);
dst = next_cmd(dst, &rblen);
}
- /* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ, O_TAG */
+ /*
+ * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ, O_TAG,
+ * O_SKIP_ACTION
+ */
for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
i = F_LEN(src);
CHECK_RBUFLEN(i);
@@ -4596,6 +4636,7 @@
case O_LIMIT:
case O_ALTQ:
case O_TAG:
+ case O_SKIP_ACTION:
break;
default:
bcopy(src, dst, i * sizeof(uint32_t));
@@ -4612,7 +4653,18 @@
bcopy(have_state, dst, i * sizeof(uint32_t));
dst += i;
}
+
/*
+ * put back the have_skipcmd command as very last opcode
+ */
+ if (have_skipcmd) {
+ i = F_LEN(have_skipcmd);
+ CHECK_RBUFLEN(i);
+ bcopy(have_skipcmd, dst, i * sizeof(uint32_t));
+ dst += i;
+ }
+
+ /*
* start action section
*/
rule->act_ofs = dst - rule->cmd;
@@ -4963,7 +5015,3 @@
free(olh);
}
-
-
-
-
Index: sys/netinet/ip_fw.h
===================================================================
--- sys/netinet/ip_fw.h
+++ sys/netinet/ip_fw.h
@@ -252,6 +252,8 @@
O_DSCP, /* 2 u32 = DSCP mask */
O_SETDSCP, /* arg1=DSCP value */
O_IP_FLOW_LOOKUP, /* arg1=table number, u32=value */
+
+ O_SKIP_ACTION, /* none */
O_LAST_OPCODE /* not an opcode! */
};
Index: sys/netpfil/ipfw/ip_fw2.c
===================================================================
--- sys/netpfil/ipfw/ip_fw2.c
+++ sys/netpfil/ipfw/ip_fw2.c
@@ -2109,7 +2109,9 @@
*
* O_LIMIT and O_KEEP_STATE: these opcodes are
* not real 'actions', and are stored right
- * before the 'action' part of the rule.
+ * before the 'action' part of the rule (one
+ * exception is O_SKIP_ACTION which could be
+ * between these opcodes and 'action' one).
* These opcodes try to install an entry in the
* state tables; if successful, we continue with
* the next opcode (match=1; break;), otherwise
@@ -2126,11 +2128,22 @@
* further instances of these opcodes become NOPs.
* The jump to the next rule is done by setting
* l=0, cmdlen=0.
+ *
+ * O_SKIP_ACTION: this opcode is not real 'action'
+ * too, and is stored right before the 'action'
+ * part of the rule, right after O_KEEP_STATE
+ * opcode. It causes match failure so real
+ * 'action' could be executed only if rule
+ * is checked via dynamic rule from state
+ * table, as in such case execution starts
+ * from true 'action' opcode directly.
+ *
*/
case O_LIMIT:
case O_KEEP_STATE:
- if (ipfw_install_state(chain, f,
- (ipfw_insn_limit *)cmd, args, tablearg)) {
+ if (ipfw_install_or_update_state(chain, f,
+ (ipfw_insn_limit *)cmd, args, tablearg,
+ proto == IPPROTO_TCP ? TCP(ulp) : NULL)) {
/* error or limit violation */
retval = IP_FW_DENY;
l = 0; /* exit inner loop */
@@ -2187,6 +2200,11 @@
match = 1;
break;
+ case O_SKIP_ACTION:
+ match = 0; /* skip to the next rule */
+ l = 0; /* exit inner loop */
+ break;
+
case O_ACCEPT:
retval = 0; /* accept */
l = 0; /* exit inner loop */
@@ -2537,7 +2555,7 @@
done = 1; /* exit outer loop */
break;
}
-
+
default:
panic("-- unknown opcode %d\n", cmd->opcode);
} /* end of switch() on opcodes */
Index: sys/netpfil/ipfw/ip_fw_dynamic.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_dynamic.c
+++ sys/netpfil/ipfw/ip_fw_dynamic.c
@@ -669,13 +669,15 @@
/**
* Install dynamic state for rule type cmd->o.opcode
+ * If rule exists, update it state.
*
* Returns 1 (failure) if state is not installed because of errors or because
* session limitations are enforced.
*/
int
-ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
- ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg)
+ipfw_install_or_update_state(struct ip_fw_chain *chain, struct ip_fw *rule,
+ ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg,
+ struct tcphdr *tcp)
{
ipfw_dyn_rule *q;
int i;
@@ -686,9 +688,9 @@
IPFW_BUCK_LOCK(i);
- q = lookup_dyn_rule_locked(&args->f_id, i, NULL, NULL);
+ q = lookup_dyn_rule_locked(&args->f_id, i, NULL, tcp);
- if (q != NULL) { /* should never occur */
+ if (q != NULL) { /* could occur in case of "record-state" */
DEB(
if (last_log != time_uptime) {
last_log = time_uptime;
Index: sys/netpfil/ipfw/ip_fw_private.h
===================================================================
--- sys/netpfil/ipfw/ip_fw_private.h
+++ sys/netpfil/ipfw/ip_fw_private.h
@@ -183,8 +183,9 @@
struct tcphdr;
struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *,
u_int32_t, u_int32_t, int);
-int ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
- ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg);
+int ipfw_install_or_update_state(struct ip_fw_chain *chain, struct ip_fw *rule,
+ ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg,
+ struct tcphdr *tcp);
ipfw_dyn_rule *ipfw_lookup_dyn_rule(struct ipfw_flow_id *pkt,
int *match_direction, struct tcphdr *tcp);
void ipfw_remove_dyn_children(struct ip_fw *rule);
Index: sys/netpfil/ipfw/ip_fw_sockopt.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_sockopt.c
+++ sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1460,6 +1460,7 @@
#endif
case O_IP4:
case O_TAG:
+ case O_SKIP_ACTION:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;
break;

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 10, 4:46 AM (10 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31200123
Default Alt Text
D1776.id3634.diff (12 KB)

Event Timeline