Page MenuHomeFreeBSD

D1776.id5113.diff
No OneTemporary

D1776.id5113.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 these matched by the rule) but
+.Cm record-state
+and
+.Cm set-limit
+have no 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,35 @@
.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.
+However, this option doesn't imply an implicit
+.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 like
+.Cm limit
+but does not have an implicit
+.Cm check-state
+attached to it.
+.It Cm skip-immediate-action | skip-action
+A 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 the dynamic rule, created but ignored on match, will work
+as intended.
+Rules with both
+.Cm record-state
+and
+.Cm skip-immediate-action
+create a dynamic rule and continue with the next rule without actually
+performing the action part of this rule. When the rule is later activated
+via the state table, the action is performed as usual.
.It Cm layer2
Matches only layer2 packets, i.e., those passed to
.Nm
@@ -2166,16 +2214,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
@@ -292,7 +292,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 },
@@ -355,6 +357,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 */
@@ -1392,6 +1396,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 */
@@ -1664,6 +1669,7 @@
break; /* done already */
case O_PROBE_STATE:
+ have_probe_state = 1;
break; /* no need to print anything here */
case O_IP_SRC:
@@ -2001,7 +2007,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: {
@@ -2010,7 +2019,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;
@@ -2046,6 +2059,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);
@@ -3507,8 +3524,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;
@@ -4356,27 +4375,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;
@@ -4560,6 +4583,7 @@
av++;
}
break;
+
case TOK_FLOW:
NEED1("missing table name");
if (strncmp(*av, "table(", 6) != 0)
@@ -4569,6 +4593,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);
}
@@ -4579,6 +4611,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
@@ -4601,12 +4638,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);
@@ -4617,6 +4657,7 @@
case O_LIMIT:
case O_ALTQ:
case O_TAG:
+ case O_SKIP_ACTION:
break;
default:
bcopy(src, dst, i * sizeof(uint32_t));
@@ -4633,7 +4674,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;
@@ -5079,7 +5131,3 @@
free(olh);
}
-
-
-
-
Index: sys/netinet/ip_fw.h
===================================================================
--- sys/netinet/ip_fw.h
+++ sys/netinet/ip_fw.h
@@ -254,6 +254,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 a real 'action'
+ * either, and is stored right before the 'action'
+ * part of the rule, right after the O_KEEP_STATE
+ * opcode. It causes match failure so the real
+ * 'action' could be executed only if the rule
+ * is checked via dynamic rule from the state
+ * table, as in such case execution starts
+ * from the 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 */
@@ -2572,7 +2590,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
@@ -186,8 +186,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
@@ -1476,6 +1476,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
Wed, May 20, 5:46 AM (11 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33338142
Default Alt Text
D1776.id5113.diff (12 KB)

Event Timeline