-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

On 03.02.2015 19:13, Lev Serebryakov wrote:

> Ok, "allow-state"/"deny-state" was very limited idea. Here is more
> universal mechanism: new "keep-state-only" (aliased as 
> "record-only") option, which works exactly as "keep-state" BUT
> cancel match of rule after state creation. It allows to write
> stateful + nat firewall as easy as:
 To work as expected, "keep-state-only" should not imply "check-state"
in opposite to "keep-state".

- -- 
// Lev Serebryakov
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)

iQJ8BAEBCgBmBQJU0P2bXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w
ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXRGOTZEMUNBMEI1RjQzMThCNjc0QjMzMEFF
QUIwM0M1OEJGREM0NzhGAAoJEOqwPFi/3EePkkoQAJHlybB+Hmcae64Bu5CyimWy
FJsicjr/DkNLhzAVJAglslBqgEkSrN2CiYTaASMMTmg6bj8RL6LLHWm0v/bAYQQR
lMGqCCcz+NvKjrB2D4egRYkA4NHGQ60Lj4O4YfsNOc9Jrsyn7RAqVc9vwMXT/GvN
GmDgVqsgA+IWSNZ4flE/MbnkZ8tq/jztuxaQneeKq6qmT9HaiNN8QeNrecO0kghz
GXZCXTGVgoguv4K/SDTkqcKapL7vP1mzRuR34FQcN/Mmj4lJ9Mdk2JNzIg0YHBZ+
HzvRvoNBHJfgw1G5ydORGOeIBgd5XCzlYTws2dboksLrd3taF4emDGjpvzn+Qwzd
X7B2hRnSOByM5j8LfctO2E7Zj7zPDtVtlZ3YsCpKvWzCdtSthzQAlvB/iE9CBOis
JAXbINONngevwwrWqCsZCxgXCGSrp9scGHY7Es02M2Pov6GSzXtPq1349SmFrH5I
J/ijTfV8e0kNnwBHfy/jf5wpXNQSV93IqRwDNp5jG+0qtDL2ZZNhMamELauWhbhB
nTJ+Og2TsPeOSp88/Jb6bW+pIsDQ7XIxdBNFC0j9lU/jFwNIfAK5xkvc239IsqeC
ylQGghwiGl9E4P3yIhLa2OAUdCy9J+dw8ZlyBkS3pN27j/RIoyMvkAA5l8i6dVRR
AEfyn36tKaR/BEUkGN5g
=9avV
-----END PGP SIGNATURE-----
Index: sbin/ipfw/ipfw.8
===================================================================
--- sbin/ipfw/ipfw.8    (revision 278151)
+++ sbin/ipfw/ipfw.8    (working copy)
@@ -166,7 +166,8 @@
 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 keep-state-only
 or
 .Cm limit
 option,
@@ -582,7 +583,8 @@
 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 keep-state, keep-stat-only or 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 +1585,18 @@
 .Xr sysctl 8
 variables), and the lifetime is refreshed every time a matching
 packet is found.
+.It Cm keep-state-only | record-only
+Upon a match, the firewall will create a dynamic rule as if
+.Cm keep-state
+was specified, but after that match is cancelled and the search
+continues with the next rule.
+On dynamic rule match action, specified in this rule,
+performed as if rule contains
+.Cm keep-state .
+This option doesn't act as
+.Cm check-state
+in contrast to
+.Cm keep-state .
 .It Cm layer2
 Matches only layer2 packets, i.e., those passed to
 .Nm
Index: sbin/ipfw/ipfw2.c
===================================================================
--- sbin/ipfw/ipfw2.c   (revision 278151)
+++ sbin/ipfw/ipfw2.c   (working copy)
@@ -292,6 +292,8 @@
        { "in",                 TOK_IN },
        { "limit",              TOK_LIMIT },
        { "keep-state",         TOK_KEEPSTATE },
+       { "record-state",       TOK_STATE_ONLY },
+       { "keep-state-only",    TOK_STATE_ONLY },
        { "bridged",            TOK_LAYER2 },
        { "layer2",             TOK_LAYER2 },
        { "out",                TOK_OUT },
@@ -1993,6 +1995,10 @@
                                bprintf(bp, " keep-state");
                                break;
 
+                       case O_STATE_ONLY:
+                               bprintf(bp, " keep-state-only");
+                               break;
+
                        case O_LIMIT: {
                                struct _s_x *p = limit_masks;
                                ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
@@ -4335,14 +4341,16 @@
                        break;
 
                case TOK_KEEPSTATE:
+               case TOK_STATE_ONLY:
                        if (open_par)
-                               errx(EX_USAGE, "keep-state cannot be part "
+                               errx(EX_USAGE, "keep-state or keep-state-only 
cannot be part "
                                    "of an or block");
                        if (have_state)
                                errx(EX_USAGE, "only one of keep-state "
                                        "and limit is allowed");
                        have_state = cmd;
-                       fill_cmd(cmd, O_KEEP_STATE, 0, 0);
+                       fill_cmd(cmd, i == TOK_KEEPSTATE ?
+                               O_KEEP_STATE : O_STATE_ONLY, 0, 0);
                        break;
 
                case TOK_LIMIT: {
@@ -4580,12 +4588,13 @@
        /*
         * 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_state->opcode != O_STATE_ONLY) {
                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_STATE_ONLY, O_LIMIT, 
O_ALTQ, O_TAG */
        for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
                i = F_LEN(src);
                CHECK_RBUFLEN(i);
@@ -4593,6 +4602,7 @@
                switch (src->opcode) {
                case O_LOG:
                case O_KEEP_STATE:
+               case O_STATE_ONLY:
                case O_LIMIT:
                case O_ALTQ:
                case O_TAG:
Index: sbin/ipfw/ipfw2.h
===================================================================
--- sbin/ipfw/ipfw2.h   (revision 278151)
+++ sbin/ipfw/ipfw2.h   (working copy)
@@ -227,6 +227,7 @@
        TOK_LOCK,
        TOK_UNLOCK,
        TOK_VLIST,
+       TOK_STATE_ONLY,
 };
 
 /*
Index: sys/netinet/ip_fw.h
===================================================================
--- sys/netinet/ip_fw.h (revision 278151)
+++ sys/netinet/ip_fw.h (working copy)
@@ -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_STATE_ONLY,           /* none                         */
 
        O_LAST_OPCODE           /* not an opcode!               */
 };
Index: sys/netpfil/ipfw/ip_fw2.c
===================================================================
--- sys/netpfil/ipfw/ip_fw2.c   (revision 278151)
+++ sys/netpfil/ipfw/ip_fw2.c   (working copy)
@@ -2107,9 +2107,9 @@
                         * O_TAG, O_LOG and O_ALTQ action parameters:
                         *   perform some action and set match = 1;
                         *
-                        * O_LIMIT and O_KEEP_STATE: these opcodes are
-                        *   not real 'actions', and are stored right
-                        *   before the 'action' part of the rule.
+                        * O_LIMIT, O_KEEP_STATE and O_STATE_ONLY: these
+                        *   opcodes are not real 'actions', and are stored
+                        *   right before the 'action' part of the rule.
                         *   These opcodes try to install an entry in the
                         *   state tables; if successful, we continue with
                         *   the next opcode (match=1; break;), otherwise
@@ -2126,9 +2126,20 @@
                         *   further instances of these opcodes become NOPs.
                         *   The jump to the next rule is done by setting
                         *   l=0, cmdlen=0.
+                        *
+                        * O_STATE_ONLY: 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:
+                       case O_STATE_ONLY:
                                if (ipfw_install_state(chain, f,
                                    (ipfw_insn_limit *)cmd, args, tablearg)) {
                                        /* error or limit violation */
@@ -2136,7 +2147,11 @@
                                        l = 0;  /* exit inner loop */
                                        done = 1; /* exit outer loop */
                                }
-                               match = 1;
+                               if (cmd->opcode == O_STATE_ONLY) {
+                                       l = 0;  /* exit inner loop */
+                                       match = 0;
+                               } else
+                                       match = 1;
                                break;
 
                        case O_PROBE_STATE:
@@ -2188,6 +2203,7 @@
                                break;
 
                        case O_ACCEPT:
+
                                retval = 0;     /* accept */
                                l = 0;          /* exit inner loop */
                                done = 1;       /* exit outer loop */
@@ -2537,7 +2553,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    (revision 278151)
+++ sys/netpfil/ipfw/ip_fw_dynamic.c    (working copy)
@@ -708,6 +708,7 @@
 
        switch (cmd->o.opcode) {
        case O_KEEP_STATE:      /* bidir rule */
+       case O_STATE_ONLY:
                q = add_dyn_rule(&args->f_id, i, O_KEEP_STATE, rule);
                break;
 
@@ -1357,6 +1358,7 @@
                switch (cmd->opcode) {
                case O_LIMIT:
                case O_KEEP_STATE:
+               case O_STATE_ONLY:
                case O_PROBE_STATE:
                case O_CHECK_STATE:
                        return (1);
Index: sys/netpfil/ipfw/ip_fw_sockopt.c
===================================================================
--- sys/netpfil/ipfw/ip_fw_sockopt.c    (revision 278151)
+++ sys/netpfil/ipfw/ip_fw_sockopt.c    (working copy)
@@ -1433,6 +1433,7 @@
                switch (cmd->opcode) {
                case O_PROBE_STATE:
                case O_KEEP_STATE:
+               case O_STATE_ONLY:
                case O_PROTO:
                case O_IP_SRC_ME:
                case O_IP_DST_ME:

Attachment: ipfw-state-only-v2.diff.sig
Description: Binary data

_______________________________________________
freebsd-ipfw@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
To unsubscribe, send any mail to "freebsd-ipfw-unsubscr...@freebsd.org"

Reply via email to