The branch main has been updated by ae:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4a77657cbc011ea657ccb079fff6b58b295eccb0

commit 4a77657cbc011ea657ccb079fff6b58b295eccb0
Author:     Andrey V. Elsukov <a...@freebsd.org>
AuthorDate: 2025-03-03 18:15:17 +0000
Commit:     Andrey V. Elsukov <a...@freebsd.org>
CommitDate: 2025-03-03 18:15:17 +0000

    ipfw: migrate ipfw to 32-bit size rule numbers
    
    This changes ABI due to the changed opcodes and includes the
    following:
     * rule numbers and named object indexes converted to 32-bits
     * all hardcoded maximum rule number was replaced with
       IPFW_DEFAULT_RULE macro
     * now it is possible to grow maximum numbers or rules in
       build time
     * several opcodes converted to ipfw_insn_u32 to keep rulenum:
       O_CALL, O_SKIPTO
     * call stack modified to keep u32 rulenum. The behaviour of
       O_CALL opcode was changed to avoid possible packets looping.
       Now when call stack is overflowed or mbuf tag allocation
       failed, a packet will be dropped instead of skipping to next
       rule.
     * 'return' action now have two modes to specify return point:
       'next-rulenum' and 'next-rule'
     * new lookup key added for O_IP_DST_LOOKUP opcode 'lookup rulenum'
     * several opcodes converted to keep u32 named object indexes
       in special structure ipfw_insn_kidx
     * tables related opcodes modified to use two structures:
       ipfw_insn_kidx and ipfw_insn_table
     * added ability for table value matching for specific value type
       in 'table(name,valtype=value)' opcode
     * dynamic states and eaction code converted to use u32 rulenum
       and named objects indexes
     * added insntod() and insntoc() macros to cast to specific
       ipfw instruction type
     * default sockopt version was changed to IP_FW3_OPVER=1
     * FreeBSD 7-11 rule format support was removed
     * added ability to generate special rtsock messages via log opcode
     * added IP_FW_SKIPTO_CACHE sockopt to enable/disable skipto cache.
       It helps to reduce overhead when many rules are modified in batch.
     * added ability to keep NAT64LSN states during sets swapping
    
    Obtained from:  Yandex LLC
    Relnotes:       yes
    Sponsored by:   Yandex LLC
    Differential Revision:  https://reviews.freebsd.org/D46183
---
 sbin/ipfw/ipfw.8                           |   18 +-
 sbin/ipfw/ipfw2.c                          |  593 +++++---
 sbin/ipfw/ipfw2.h                          |    4 +-
 sbin/ipfw/nat64lsn.c                       |   16 +
 sbin/ipfw/tables.c                         |    2 +-
 sbin/route/route.c                         |    1 +
 sys/net/route.h                            |    1 +
 sys/netinet/ip_fw.h                        |  227 ++-
 sys/netinet6/ip_fw_nat64.h                 |   10 +-
 sys/netpfil/ipfw/ip_fw2.c                  |  471 +++---
 sys/netpfil/ipfw/ip_fw_compat.c            |  714 +++++++++
 sys/netpfil/ipfw/ip_fw_dynamic.c           |  257 ++--
 sys/netpfil/ipfw/ip_fw_eaction.c           |   71 +-
 sys/netpfil/ipfw/ip_fw_iface.c             |   10 +-
 sys/netpfil/ipfw/ip_fw_log.c               |  315 +++-
 sys/netpfil/ipfw/ip_fw_nat.c               |   10 +-
 sys/netpfil/ipfw/ip_fw_private.h           |  136 +-
 sys/netpfil/ipfw/ip_fw_sockopt.c           | 2171 ++++++++--------------------
 sys/netpfil/ipfw/ip_fw_table.c             |  483 ++-----
 sys/netpfil/ipfw/ip_fw_table.h             |   16 +-
 sys/netpfil/ipfw/ip_fw_table_algo.c        |   11 +-
 sys/netpfil/ipfw/ip_fw_table_value.c       |   52 +-
 sys/netpfil/ipfw/nat64/ip_fw_nat64.h       |   48 +
 sys/netpfil/ipfw/nat64/nat64clat.c         |    8 +-
 sys/netpfil/ipfw/nat64/nat64clat.h         |    2 +-
 sys/netpfil/ipfw/nat64/nat64clat_control.c |   80 +-
 sys/netpfil/ipfw/nat64/nat64lsn.c          |  390 +++--
 sys/netpfil/ipfw/nat64/nat64lsn.h          |   68 +-
 sys/netpfil/ipfw/nat64/nat64lsn_control.c  |  285 ++--
 sys/netpfil/ipfw/nat64/nat64stl.c          |   10 +-
 sys/netpfil/ipfw/nat64/nat64stl.h          |    6 +-
 sys/netpfil/ipfw/nat64/nat64stl_control.c  |   76 +-
 sys/netpfil/ipfw/nptv6/nptv6.c             |   49 +-
 sys/netpfil/ipfw/pmod/tcpmod.c             |    6 +-
 sys/sys/socket.h                           |    4 +-
 35 files changed, 3389 insertions(+), 3232 deletions(-)

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index bc78ae1c655b..348e9a58f2ce 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,5 +1,5 @@
 .\"
-.Dd December 6, 2024
+.Dd March 3, 2025
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -40,10 +40,10 @@ in-kernel NAT.
 .Ss SYSCTL SHORTCUTS
 .Nm
 .Cm enable
-.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
+.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive | 
skipto_cache
 .Nm
 .Cm disable
-.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
+.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive | 
skipto_cache
 .Ss LOOKUP TABLES
 .Nm
 .Oo Cm set Ar N Oc Cm table Ar name Cm create Ar create-options
@@ -1395,6 +1395,16 @@ Matches any IPv4 or IPv6 address for which an entry 
exists in the lookup table
 If an optional 32-bit unsigned
 .Ar value
 is also specified, an entry will match only if it has this value.
+If
+.Ar value
+is specified in form
+.Ar valtype=value ,
+then specified value type field will be checked.
+It can be
+.Ar skipto, pipe, fib, nat, dscp, tag, divert, netgraph, limit, nh4
+and
+.Ar mark.
+
 See the
 .Sx LOOKUP TABLES
 section below for more information on lookup tables.
@@ -1865,7 +1875,7 @@ One or more
 of source and destination addresses and ports can be
 specified.
 .It Cm lookup Bro Cm dst-ip | dst-port | dst-mac | src-ip | src-port | src-mac 
| uid |
-.Cm jail | dscp | mark Brc Ar name
+.Cm jail | dscp | mark | rulenum Brc Ar name
 Search an entry in lookup table
 .Ar name
 that matches the field specified as argument.
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index cc0970207749..be796808380f 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -290,6 +290,12 @@ static struct _s_x rule_actions[] = {
        { NULL, 0 }     /* terminator */
 };
 
+static struct _s_x return_types[] = {
+       { "next-rulenum",       RETURN_NEXT_RULENUM },
+       { "next-rule",          RETURN_NEXT_RULE },
+       { NULL, 0 }     /* terminator */
+};
+
 static struct _s_x rule_action_params[] = {
        { "altq",               TOK_ALTQ },
        { "log",                TOK_LOG },
@@ -300,7 +306,7 @@ static struct _s_x rule_action_params[] = {
 
 /*
  * The 'lookup' instruction accepts one of the following arguments.
- * Arguments are passed as v[1] in O_DST_LOOKUP options.
+ * Arguments are passed as o.arg1 and o->value in O_DST_LOOKUP option.
  */
 static struct _s_x lookup_keys[] = {
        { "dst-ip",             LOOKUP_DST_IP },
@@ -313,9 +319,29 @@ static struct _s_x lookup_keys[] = {
        { "jail",               LOOKUP_JAIL },
        { "dscp",               LOOKUP_DSCP },
        { "mark",               LOOKUP_MARK },
+       { "rulenum",            LOOKUP_RULENUM },
        { NULL,                 0 },
 };
 
+/*
+ * table(name,valuename=value) instruction accepts one of the
+ * following arguments as valuename.
+ */
+static struct _s_x tvalue_names[] = {
+       { "tag",                TVALUE_TAG },
+       { "pipe",               TVALUE_PIPE },
+       { "divert",             TVALUE_DIVERT },
+       { "skipto",             TVALUE_SKIPTO },
+       { "netgraph",           TVALUE_NETGRAPH },
+       { "fib",                TVALUE_FIB },
+       { "nat",                TVALUE_NAT },
+       { "nh4",                TVALUE_NH4 },
+       { "dscp",               TVALUE_DSCP },
+       { "limit",              TVALUE_LIMIT },
+       { "mark",               TVALUE_MARK },
+       { NULL,                 0 }
+};
+
 static struct _s_x rule_options[] = {
        { "tagged",             TOK_TAGGED },
        { "uid",                TOK_UID },
@@ -415,12 +441,12 @@ static int ipfw_show_config(struct cmdline_opts *co, 
struct format_opts *fo,
 static void ipfw_list_tifaces(void);
 
 struct tidx;
-static uint16_t pack_object(struct tidx *tstate, const char *name, int otype);
-static uint16_t pack_table(struct tidx *tstate, const char *name);
+static uint32_t pack_object(struct tidx *tstate, const char *name, int otype);
+static uint32_t pack_table(struct tidx *tstate, const char *name);
 
-static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx);
+static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx);
 static void object_sort_ctlv(ipfw_obj_ctlv *ctlv);
-static char *object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx,
+static char *object_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx,
     uint16_t type);
 
 int
@@ -650,6 +676,7 @@ do_set3(int optname, ip_fw3_opheader *op3, size_t optlen)
 {
 
        op3->opcode = optname;
+       op3->version = IP_FW3_OPVER; /* use last version */
 
        if (g_co.debug_only) {
                struct debug_header dbg = {
@@ -690,6 +717,7 @@ do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen)
        socklen_t len;
 
        op3->opcode = optname;
+       op3->version = IP_FW3_OPVER; /* use last version */
 
        if (g_co.debug_only) {
                struct debug_header dbg = {
@@ -1284,6 +1312,15 @@ print_flags(struct buf_pr *bp, char const *name, const 
ipfw_insn *cmd,
        }
 }
 
+static void
+print_tvalue(struct buf_pr *bp, const ipfw_insn_table *cmd)
+{
+       const char *name;
+
+       name = match_value(tvalue_names, IPFW_TVALUE_TYPE(&cmd->o));
+       bprintf(bp, ",%s=%u", name != NULL ? name: "<invalid>", cmd->value);
+}
+
 
 /*
  * Print the ip address contained in a command.
@@ -1295,33 +1332,46 @@ print_ip(struct buf_pr *bp, const struct format_opts 
*fo,
        struct hostent *he = NULL;
        const struct in_addr *ia;
        const uint32_t *a = ((const ipfw_insn_u32 *)cmd)->d;
-       uint32_t len = F_LEN((const ipfw_insn *)cmd);
+       uint32_t len = F_LEN(&cmd->o);
        char *t;
 
        bprintf(bp, " ");
-       if (cmd->o.opcode == O_IP_DST_LOOKUP && len > 
F_INSN_SIZE(ipfw_insn_u32)) {
-               const char *arg;
-
-               arg = match_value(lookup_keys, a[1]);
-               t = table_search_ctlv(fo->tstate,
-                   ((const ipfw_insn *)cmd)->arg1);
-               bprintf(bp, "lookup %s %s", arg, t);
-               return;
-       }
-       if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) {
+       switch (cmd->o.opcode) {
+       case O_IP_SRC_ME:
+       case O_IP_DST_ME:
                bprintf(bp, "me");
                return;
-       }
-       if (cmd->o.opcode == O_IP_SRC_LOOKUP ||
-           cmd->o.opcode == O_IP_DST_LOOKUP) {
+
+       case O_IP_DST_LOOKUP:
+               if ((len == F_INSN_SIZE(ipfw_insn_kidx) ||
+                   len == F_INSN_SIZE(ipfw_insn_table)) &&
+                   IPFW_LOOKUP_TYPE(&cmd->o) != LOOKUP_NONE) {
+                       const char *key;
+
+                       key = match_value(lookup_keys,
+                           IPFW_LOOKUP_TYPE(&cmd->o));
+                       t = table_search_ctlv(fo->tstate,
+                           insntoc(&cmd->o, kidx)->kidx);
+                       if (len == F_INSN_SIZE(ipfw_insn_table)) {
+                               bprintf(bp, "lookup %s:%#x %s",
+                                   (key != NULL ? key : "<invalid>"),
+                                   insntoc(&cmd->o, table)->value, t);
+                       } else
+                               bprintf(bp, "lookup %s %s", key != NULL ? key:
+                                   "<invalid>", t);
+                       return;
+               }
+               /* FALLTHROUGH */
+       case O_IP_SRC_LOOKUP:
                t = table_search_ctlv(fo->tstate,
-                   ((const ipfw_insn *)cmd)->arg1);
+                   insntoc(&cmd->o, kidx)->kidx);
                bprintf(bp, "table(%s", t);
-               if (len == F_INSN_SIZE(ipfw_insn_u32))
-                       bprintf(bp, ",%u", *a);
+               if (len == F_INSN_SIZE(ipfw_insn_table))
+                       print_tvalue(bp, insntoc(&cmd->o, table));
                bprintf(bp, ")");
                return;
        }
+
        if (cmd->o.opcode == O_IP_SRC_SET || cmd->o.opcode == O_IP_DST_SET) {
                const uint32_t *map = (const uint32_t *)&cmd->mask;
                struct in_addr addr;
@@ -1427,10 +1477,10 @@ print_mac_lookup(struct buf_pr *bp, const struct 
format_opts *fo,
 
        bprintf(bp, " ");
 
-       t = table_search_ctlv(fo->tstate, cmd->arg1);
+       t = table_search_ctlv(fo->tstate, insntoc(cmd, kidx)->kidx);
        bprintf(bp, "table(%s", t);
-       if (len == F_INSN_SIZE(ipfw_insn_u32))
-               bprintf(bp, ",%u", ((const ipfw_insn_u32 *)cmd)->d[0]);
+       if (len == F_INSN_SIZE(ipfw_insn_table))
+               print_tvalue(bp, insntoc(cmd, table));
        bprintf(bp, ")");
 }
 
@@ -1497,10 +1547,9 @@ print_dscp(struct buf_pr *bp, const ipfw_insn_u32 *cmd)
        }
 }
 
-#define        insntod(cmd, type)      ((const ipfw_insn_ ## type *)(cmd))
 struct show_state {
        struct ip_fw_rule       *rule;
-       const ipfw_insn         *eaction;
+       const ipfw_insn_kidx    *eaction;
        uint8_t                 *printed;
        int                     flags;
 #define        HAVE_PROTO              0x0001
@@ -1583,7 +1632,7 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
 
        switch (cmd->opcode) {
        case O_PROB:
-               d = 1.0 * insntod(cmd, u32)->d[0] / 0x7fffffff;
+               d = 1.0 * insntoc(cmd, u32)->d[0] / 0x7fffffff;
                bprintf(bp, "prob %f ", d);
                break;
        case O_PROBE_STATE: /* no need to print anything here */
@@ -1596,30 +1645,36 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
        case O_IP_SRC_SET:
                if (state->flags & HAVE_SRCIP)
                        bprintf(bp, " src-ip");
-               print_ip(bp, fo, insntod(cmd, ip));
+               print_ip(bp, fo, insntoc(cmd, ip));
                break;
        case O_IP_DST:
-       case O_IP_DST_LOOKUP:
        case O_IP_DST_MASK:
        case O_IP_DST_ME:
        case O_IP_DST_SET:
-               if (state->flags & HAVE_DSTIP)
+       case O_IP_DST_LOOKUP:
+               /*
+                * Special handling for O_IP_DST_LOOKUP when
+                * lookup type is not LOOKUP_NONE.
+                */
+               if ((state->flags & HAVE_DSTIP) != 0 && (
+                   cmd->opcode != O_IP_DST_LOOKUP ||
+                   IPFW_LOOKUP_TYPE(cmd) == LOOKUP_NONE))
                        bprintf(bp, " dst-ip");
-               print_ip(bp, fo, insntod(cmd, ip));
+               print_ip(bp, fo, insntoc(cmd, ip));
                break;
        case O_IP6_SRC:
        case O_IP6_SRC_MASK:
        case O_IP6_SRC_ME:
                if (state->flags & HAVE_SRCIP)
                        bprintf(bp, " src-ip6");
-               print_ip6(bp, insntod(cmd, ip6));
+               print_ip6(bp, insntoc(cmd, ip6));
                break;
        case O_IP6_DST:
        case O_IP6_DST_MASK:
        case O_IP6_DST_ME:
                if (state->flags & HAVE_DSTIP)
                        bprintf(bp, " dst-ip6");
-               print_ip6(bp, insntod(cmd, ip6));
+               print_ip6(bp, insntoc(cmd, ip6));
                break;
        case O_MAC_SRC_LOOKUP:
                bprintf(bp, " src-mac");
@@ -1630,11 +1685,11 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                print_mac_lookup(bp, fo, cmd);
                break;
        case O_FLOW6ID:
-               print_flow6id(bp, insntod(cmd, u32));
+               print_flow6id(bp, insntoc(cmd, u32));
                break;
        case O_IP_DSTPORT:
        case O_IP_SRCPORT:
-               print_newports(bp, insntod(cmd, u16), state->proto,
+               print_newports(bp, insntoc(cmd, u16), state->proto,
                    (state->flags & (HAVE_SRCIP | HAVE_DSTIP)) ==
                    (HAVE_SRCIP | HAVE_DSTIP) ?  cmd->opcode: 0);
                break;
@@ -1649,10 +1704,10 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                state->proto = cmd->arg1;
                break;
        case O_MACADDR2:
-               print_mac(bp, insntod(cmd, mac));
+               print_mac(bp, insntoc(cmd, mac));
                break;
        case O_MAC_TYPE:
-               print_newports(bp, insntod(cmd, u16),
+               print_newports(bp, insntoc(cmd, u16),
                    IPPROTO_ETHERTYPE, cmd->opcode);
                break;
        case O_FRAG:
@@ -1695,26 +1750,27 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                        s = "recv";
                else /* if (cmd->opcode == O_VIA) */
                        s = "via";
-               switch (insntod(cmd, if)->name[0]) {
+               switch (insntoc(cmd, if)->name[0]) {
                case '\0':
                        bprintf(bp, " %s %s", s,
-                           inet_ntoa(insntod(cmd, if)->p.ip));
+                           inet_ntoa(insntoc(cmd, if)->p.ip));
                        break;
                case '\1':
                        bprintf(bp, " %s table(%s)", s,
                            table_search_ctlv(fo->tstate,
-                           insntod(cmd, if)->p.kidx));
+                           insntoc(cmd, if)->p.kidx));
                        break;
                default:
                        bprintf(bp, " %s %s", s,
-                           insntod(cmd, if)->name);
+                           insntoc(cmd, if)->name);
                }
                break;
        case O_IP_FLOW_LOOKUP:
-               s = table_search_ctlv(fo->tstate, cmd->arg1);
+               s = table_search_ctlv(fo->tstate,
+                   insntoc(cmd, kidx)->kidx);
                bprintf(bp, " flow table(%s", s);
-               if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))
-                       bprintf(bp, ",%u", insntod(cmd, u32)->d[0]);
+               if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_table))
+                       print_tvalue(bp, insntoc(cmd, table));
                bprintf(bp, ")");
                break;
        case O_IPID:
@@ -1749,7 +1805,7 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                        }
                        bprintf(bp, " %s %u", s, cmd->arg1);
                } else
-                       print_newports(bp, insntod(cmd, u16), 0,
+                       print_newports(bp, insntoc(cmd, u16), 0,
                            cmd->opcode);
                break;
        case O_IPVER:
@@ -1759,7 +1815,7 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                bprintf(bp, " ipprecedence %u", cmd->arg1 >> 5);
                break;
        case O_DSCP:
-               print_dscp(bp, insntod(cmd, u32));
+               print_dscp(bp, insntoc(cmd, u32));
                break;
        case O_IPOPT:
                print_flags(bp, "ipoptions", cmd, f_ipopts);
@@ -1768,7 +1824,7 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                print_flags(bp, "iptos", cmd, f_iptos);
                break;
        case O_ICMPTYPE:
-               print_icmptypes(bp, insntod(cmd, u32));
+               print_icmptypes(bp, insntoc(cmd, u32));
                break;
        case O_ESTAB:
                bprintf(bp, " established");
@@ -1781,30 +1837,30 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                break;
        case O_TCPACK:
                bprintf(bp, " tcpack %d",
-                   ntohl(insntod(cmd, u32)->d[0]));
+                   ntohl(insntoc(cmd, u32)->d[0]));
                break;
        case O_TCPSEQ:
                bprintf(bp, " tcpseq %d",
-                   ntohl(insntod(cmd, u32)->d[0]));
+                   ntohl(insntoc(cmd, u32)->d[0]));
                break;
        case O_UID:
-               pwd = getpwuid(insntod(cmd, u32)->d[0]);
+               pwd = getpwuid(insntoc(cmd, u32)->d[0]);
                if (pwd != NULL)
                        bprintf(bp, " uid %s", pwd->pw_name);
                else
                        bprintf(bp, " uid %u",
-                           insntod(cmd, u32)->d[0]);
+                           insntoc(cmd, u32)->d[0]);
                break;
        case O_GID:
-               grp = getgrgid(insntod(cmd, u32)->d[0]);
+               grp = getgrgid(insntoc(cmd, u32)->d[0]);
                if (grp != NULL)
                        bprintf(bp, " gid %s", grp->gr_name);
                else
                        bprintf(bp, " gid %u",
-                           insntod(cmd, u32)->d[0]);
+                           insntoc(cmd, u32)->d[0]);
                break;
        case O_JAIL:
-               bprintf(bp, " jail %d", insntod(cmd, u32)->d[0]);
+               bprintf(bp, " jail %d", insntoc(cmd, u32)->d[0]);
                break;
        case O_VERREVPATH:
                bprintf(bp, " verrevpath");
@@ -1827,7 +1883,8 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                else
                        bprintf(bp, " record-state");
                bprintf(bp, " :%s",
-                   object_search_ctlv(fo->tstate, cmd->arg1,
+                   object_search_ctlv(fo->tstate,
+                   insntoc(cmd, kidx)->kidx,
                    IPFW_TLV_STATE_NAME));
                break;
        case O_LIMIT:
@@ -1835,9 +1892,10 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                        bprintf(bp, " limit");
                else
                        bprintf(bp, " set-limit");
-               print_limit_mask(bp, insntod(cmd, limit));
+               print_limit_mask(bp, insntoc(cmd, limit));
                bprintf(bp, " :%s",
-                   object_search_ctlv(fo->tstate, cmd->arg1,
+                   object_search_ctlv(fo->tstate,
+                   insntoc(cmd, kidx)->kidx,
                    IPFW_TLV_STATE_NAME));
                break;
        case O_IP6:
@@ -1851,7 +1909,7 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                bprintf(bp, " ip4");
                break;
        case O_ICMP6TYPE:
-               print_icmp6types(bp, insntod(cmd, u32));
+               print_icmp6types(bp, insntoc(cmd, u32));
                break;
        case O_EXT_HDR:
                print_ext6hdr(bp, cmd);
@@ -1860,7 +1918,7 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                if (F_LEN(cmd) == 1)
                        bprint_uint_arg(bp, " tagged ", cmd->arg1);
                else
-                       print_newports(bp, insntod(cmd, u16),
+                       print_newports(bp, insntoc(cmd, u16),
                                    0, O_TAGGED);
                break;
        case O_SKIP_ACTION:
@@ -1871,12 +1929,10 @@ print_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                if (cmd->arg1 == IP_FW_TARG)
                        bprintf(bp, " tablearg");
                else
-                       bprintf(bp, " %#x",
-                           ((const ipfw_insn_u32 *)cmd)->d[0]);
+                       bprintf(bp, " %#x", insntoc(cmd, u32)->d[0]);
 
-               if (((const ipfw_insn_u32 *)cmd)->d[1] != 0xFFFFFFFF)
-                       bprintf(bp, ":%#x",
-                           ((const ipfw_insn_u32 *)cmd)->d[1]);
+               if (insntoc(cmd, u32)->d[1] != 0xFFFFFFFF)
+                       bprintf(bp, ":%#x", insntoc(cmd, u32)->d[1]);
                break;
 
        default:
@@ -1929,14 +1985,14 @@ print_fwd(struct buf_pr *bp, const ipfw_insn *cmd)
        uint16_t port;
 
        if (cmd->opcode == O_FORWARD_IP) {
-               sa = insntod(cmd, sa);
+               sa = insntoc(cmd, sa);
                port = sa->sa.sin_port;
                if (sa->sa.sin_addr.s_addr == INADDR_ANY)
                        bprintf(bp, "fwd tablearg");
                else
                        bprintf(bp, "fwd %s", inet_ntoa(sa->sa.sin_addr));
        } else {
-               sa6 = insntod(cmd, sa6);
+               sa6 = insntoc(cmd, sa6);
                port = sa6->sa.sin6_port;
                bprintf(bp, "fwd ");
                if (getnameinfo((const struct sockaddr *)&sa6->sa,
@@ -1948,6 +2004,26 @@ print_fwd(struct buf_pr *bp, const ipfw_insn *cmd)
                bprintf(bp, ",%u", port);
 }
 
+static void
+print_logdst(struct buf_pr *bp, uint16_t arg1)
+{
+       char const *comma = "";
+
+       bprintf(bp, " logdst ", arg1);
+       if (arg1 & IPFW_LOG_SYSLOG) {
+               bprintf(bp, "%ssyslog", comma);
+               comma = ",";
+       }
+       if (arg1 & IPFW_LOG_IPFW0) {
+               bprintf(bp, "%sipfw0", comma);
+               comma = ",";
+       }
+       if (arg1 & IPFW_LOG_RTSOCK) {
+               bprintf(bp, "%srtsock", comma);
+               comma = ",";
+       }
+}
+
 static int
 print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
     struct show_state *state, const ipfw_insn *cmd)
@@ -1959,8 +2035,9 @@ print_action_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
        switch (cmd->opcode) {
        case O_CHECK_STATE:
                bprintf(bp, "check-state");
-               if (cmd->arg1 != 0)
-                       s = object_search_ctlv(fo->tstate, cmd->arg1,
+               if (insntoc(cmd, kidx)->kidx != 0)
+                       s = object_search_ctlv(fo->tstate,
+                           insntoc(cmd, kidx)->kidx,
                            IPFW_TLV_STATE_NAME);
                else
                        s = NULL;
@@ -1985,7 +2062,7 @@ print_action_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                else if (cmd->arg1 == ICMP_UNREACH_NEEDFRAG &&
                    cmd->len == F_INSN_SIZE(ipfw_insn_u16))
                        bprintf(bp, "needfrag %u",
-                           ((const ipfw_insn_u16 *)cmd)->ports[0]);
+                           insntoc(cmd, u16)->ports[0]);
                else
                        print_reject_code(bp, cmd->arg1);
                break;
@@ -1998,7 +2075,7 @@ print_action_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                        print_unreach6_code(bp, cmd->arg1);
                break;
        case O_SKIPTO:
-               bprint_uint_arg(bp, "skipto ", cmd->arg1);
+               bprint_uint_arg(bp, "skipto ", insntoc(cmd, u32)->d[0]);
                break;
        case O_PIPE:
                bprint_uint_arg(bp, "pipe ", cmd->arg1);
@@ -2023,15 +2100,16 @@ print_action_instruction(struct buf_pr *bp, const 
struct format_opts *fo,
                print_fwd(bp, cmd);
                break;
        case O_LOG:
-               if (insntod(cmd, log)->max_log > 0)
-                       bprintf(bp, " log logamount %d",
-                           insntod(cmd, log)->max_log);
-               else
-                       bprintf(bp, " log");
+               bprintf(bp, " log");
+               if (insntoc(cmd, log)->max_log > 0)
+                       bprintf(bp, " logamount %d",
+                           insntoc(cmd, log)->max_log);
+               if (cmd->arg1 != IPFW_LOG_DEFAULT)
+                       print_logdst(bp, cmd->arg1);
                break;
        case O_ALTQ:
 #ifndef NO_ALTQ
-               print_altq_cmd(bp, insntod(cmd, altq));
+               print_altq_cmd(bp, insntoc(cmd, altq));
 #endif
                break;
        case O_TAG:
@@ -2060,8 +2138,9 @@ print_action_instruction(struct buf_pr *bp, const struct 
format_opts *fo,
                 * NOTE: in case when external action has no named
                 * instances support, the second opcode isn't needed.
                 */
-               state->eaction = cmd;
-               s = object_search_ctlv(fo->tstate, cmd->arg1,
+               state->eaction = insntoc(cmd, kidx);
+               s = object_search_ctlv(fo->tstate,
+                   state->eaction->kidx,
                    IPFW_TLV_EACTION);
                if (match_token(rule_eactions, s) != -1)
                        bprintf(bp, "%s", s);
@@ -2081,11 +2160,12 @@ print_action_instruction(struct buf_pr *bp, const 
struct format_opts *fo,
                 * we calculate TLV type using IPFW_TLV_EACTION_NAME()
                 * macro.
                 */
-               s = object_search_ctlv(fo->tstate, cmd->arg1, 0);
+               s = object_search_ctlv(fo->tstate,
+                   insntoc(cmd, kidx)->kidx, 0);
                if (s == NULL)
                        s = object_search_ctlv(fo->tstate,
-                           cmd->arg1, IPFW_TLV_EACTION_NAME(
-                           state->eaction->arg1));
+                           insntoc(cmd, kidx)->kidx, IPFW_TLV_EACTION_NAME(
+                           state->eaction->kidx));
                bprintf(bp, " %s", s);
                break;
        case O_EXTERNAL_DATA:
@@ -2117,17 +2197,18 @@ print_action_instruction(struct buf_pr *bp, const 
struct format_opts *fo,
                bprintf(bp, "reass");
                break;
        case O_CALLRETURN:
-               if (cmd->len & F_NOT)
-                       bprintf(bp, "return");
-               else
-                       bprint_uint_arg(bp, "call ", cmd->arg1);
+               if (cmd->len & F_NOT) {
+                       s = match_value(return_types, cmd->arg1);
+                       bprintf(bp, "return %s", s ? s: "<invalid>");
+               } else
+                       bprint_uint_arg(bp, "call ", insntoc(cmd, u32)->d[0]);
                break;
        case O_SETMARK:
                if (cmd->arg1 == IP_FW_TARG) {
                        bprintf(bp, "setmark tablearg");
                        break;
                }
-               bprintf(bp, "setmark %#x", ((const ipfw_insn_u32 *)cmd)->d[0]);
+               bprintf(bp, "setmark %#x", insntoc(cmd, u32)->d[0]);
                break;
        default:
                bprintf(bp, "** unrecognized action %d len %d ",
@@ -2233,9 +2314,16 @@ print_address(struct buf_pr *bp, struct format_opts *fo,
        count = portcnt = 0;
        for (l = state->rule->act_ofs, cmd = state->rule->cmd;
            l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
-               if (match_opcode(cmd->opcode, opcodes, nops))
+               if (match_opcode(cmd->opcode, opcodes, nops)) {
+                       /*
+                        * Special handling for O_IP_DST_LOOKUP when
+                        * lookup type is not LOOKUP_NONE.
+                        */
+                       if (cmd->opcode == O_IP_DST_LOOKUP &&
+                           IPFW_LOOKUP_TYPE(cmd) != LOOKUP_NONE)
+                               continue;
                        count++;
-               else if (cmd->opcode == portop)
+               } else if (cmd->opcode == portop)
                        portcnt++;
        }
        if (count == 0)
@@ -2292,6 +2380,12 @@ static const int dst_opcodes[] = {
        O_IP_DST_SET, O_IP6_DST, O_IP6_DST_MASK, O_IP6_DST_ME
 };
 
+#if IPFW_DEFAULT_RULE > 65535
+#define        RULENUM_FORMAT  "%06d"
+#else
+#define        RULENUM_FORMAT  "%05d"
+#endif
+
 static void
 show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
     struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr)
@@ -2313,7 +2407,8 @@ show_static_rule(struct cmdline_opts *co, struct 
format_opts *fo,
                warn("init_show_state() failed");
                return;
        }
-       bprintf(bp, "%05u ", rule->rulenum);
+
+       bprintf(bp, RULENUM_FORMAT " ", rule->rulenum);
 
        /* only if counters are available */
        if (cntr != NULL) {
@@ -2423,23 +2518,21 @@ show_dyn_state(struct cmdline_opts *co, struct 
format_opts *fo,
 {
        struct protoent *pe;
        struct in_addr a;
-       uint16_t rulenum;
        char buf[INET6_ADDRSTRLEN];
 
-       if (d->expire == 0 && d->dyn_type != O_LIMIT_PARENT)
+       if (!d->expire && !(d->type == O_LIMIT_PARENT))
                return;
 
-       bcopy(&d->rule, &rulenum, sizeof(rulenum));
-       bprintf(bp, "%05d", rulenum);
+       bprintf(bp, RULENUM_FORMAT, d->rulenum);
        if (fo->pcwidth > 0 || fo->bcwidth > 0) {
                bprintf(bp, " ");
                pr_u64(bp, &d->pcnt, fo->pcwidth);
                pr_u64(bp, &d->bcnt, fo->bcwidth);
                bprintf(bp, "(%ds)", d->expire);
        }
-       switch (d->dyn_type) {
+       switch (d->type) {
        case O_LIMIT_PARENT:
-               bprintf(bp, " PARENT %d", d->count);
+               bprintf(bp, " PARENT %u", d->count);
                break;
        case O_LIMIT:
                bprintf(bp, " LIMIT");
@@ -2531,9 +2624,8 @@ ipfw_sets_handler(char *av[])
        ipfw_range_tlv rt;
        const char *msg;
        size_t size;
-       uint32_t masks[2];
+       uint32_t masks[2], rulenum;
        int i;
-       uint16_t rulenum;
        uint8_t cmd;
 
        av++;
@@ -2584,7 +2676,7 @@ ipfw_sets_handler(char *av[])
                if (av[0] == NULL || av[1] == NULL || av[2] == NULL ||
                                av[3] != NULL ||  _substrcmp(av[1], "to") != 0)
                        errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
-               rulenum = atoi(av[0]);
+               rulenum = (uint32_t)strtoul(av[0], NULL, 10);
                rt.new_set = atoi(av[2]);
                if (cmd == IP_FW_XMOVE) {
                        rt.start_rule = rulenum;
@@ -2637,6 +2729,18 @@ ipfw_sets_handler(char *av[])
                errx(EX_USAGE, "invalid set command %s\n", *av);
 }
 
+static void
+manage_skipto_cache(int op)
+{
+       ipfw_cmd_header req;
+
+       memset(&req, 0, sizeof(req));
+       req.size = sizeof(req);
+       req.cmd = op ? SKIPTO_CACHE_ENABLE : SKIPTO_CACHE_DISABLE;
+
+       do_set3(IP_FW_SKIPTO_CACHE, &req.opheader, sizeof(req));
+}
+
 void
 ipfw_sysctl_handler(char *av[], int which)
 {
@@ -2661,6 +2765,8 @@ ipfw_sysctl_handler(char *av[], int which)
        } else if (_substrcmp(*av, "dyn_keepalive") == 0) {
                sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
                    &which, sizeof(which));
+       } else if (_substrcmp(*av, "skipto_cache") == 0) {
+               manage_skipto_cache(which);
 #ifndef NO_ALTQ
        } else if (_substrcmp(*av, "altq") == 0) {
                altq_set_enabled(which);
@@ -2679,7 +2785,6 @@ prepare_format_dyn(struct cmdline_opts *co, struct 
format_opts *fo,
 {
        ipfw_dyn_rule *d;
        int width;
-       uint8_t set;
 
        d = (ipfw_dyn_rule *)_state;
        /* Count _ALL_ states */
@@ -2688,13 +2793,9 @@ prepare_format_dyn(struct cmdline_opts *co, struct 
format_opts *fo,
        if (fo->show_counters == 0)
                return;
 
-       if (co->use_set) {
-               /* skip states from another set */
-               bcopy((char *)&d->rule + sizeof(uint16_t), &set,
-                   sizeof(uint8_t));
-               if (set != co->use_set - 1)
-                       return;
-       }
+       /* skip states from another set */
+       if (co->use_set != 0 && d->set != co->use_set - 1)
+               return;
 
        width = pr_u64(NULL, &d->pcnt, 0);
        if (width > fo->pcwidth)
@@ -2822,24 +2923,17 @@ static void
 list_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
     void *_arg, void *_state)
 {
-       uint16_t rulenum;
-       uint8_t set;
        ipfw_dyn_rule *d;
        struct buf_pr *bp;
 
        d = (ipfw_dyn_rule *)_state;
        bp = (struct buf_pr *)_arg;
 
-       bcopy(&d->rule, &rulenum, sizeof(rulenum));
-       if (rulenum > fo->last)
+       if (d->rulenum > fo->last)
                return;
-       if (co->use_set) {
-               bcopy((char *)&d->rule + sizeof(uint16_t),
-                     &set, sizeof(uint8_t));
-               if (set != co->use_set - 1)
-                       return;
-       }
-       if (rulenum >= fo->first) {
+       if (co->use_set != 0 && d->set != co->use_set - 1)
+               return;
+       if (d->rulenum >= fo->first) {
                show_dyn_state(co, fo, bp, d);
                printf("%s\n", bp->buf);
                bp_flush(bp);
@@ -3165,7 +3259,7 @@ eaction_check_name(const char *name)
        return (0);
 }
 
-static uint16_t
+static uint32_t
 pack_object(struct tidx *tstate, const char *name, int otype)
 {
        ipfw_obj_ntlv *ntlv;
@@ -3202,7 +3296,7 @@ pack_object(struct tidx *tstate, const char *name, int 
otype)
        return (ntlv->idx);
 }
 
-static uint16_t
+static uint32_t
 pack_table(struct tidx *tstate, const char *name)
 {
 
@@ -3212,12 +3306,32 @@ pack_table(struct tidx *tstate, const char *name)
        return (pack_object(tstate, name, IPFW_TLV_TBL_NAME));
 }
 
+static void
+fill_table_value(ipfw_insn *cmd, char *s)
+{
+       char *p;
+       int i;
+
+       p = strchr(s, '=');
+       if (p != NULL) {
+               *p++ = '\0';
+               i = match_token(tvalue_names, s);
+               if (i == -1)
+                       errx(EX_USAGE,
+                           "format: unknown table value name %s", s);
+       } else {
+               i = TVALUE_TAG;
+               p = s;
+       }
+
+       IPFW_SET_TVALUE_TYPE(cmd, i);
+       insntod(cmd, table)->value = strtoul(p, NULL, 0);
+}
+
 void
-fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode,
-    struct tidx *tstate)
+fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
 {
-       uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
-       uint16_t uidx;
+       ipfw_insn_kidx *c = insntod(cmd, kidx);
        char *p;
 
        if ((p = strchr(av + 6, ')')) == NULL)
@@ -3227,19 +3341,19 @@ fill_table(struct _ipfw_insn *cmd, char *av, uint8_t 
opcode,
        if (p)
                *p++ = '\0';
 
-       if ((uidx = pack_table(tstate, av + 6)) == 0)
+       if ((c->kidx = pack_table(tstate, av + 6)) == 0)
                errx(EX_DATAERR, "Invalid table name: %s", av + 6);
 
        cmd->opcode = opcode;
-       cmd->arg1 = uidx;
        if (p) {
-               cmd->len |= F_INSN_SIZE(ipfw_insn_u32);
-               d[0] = strtoul(p, NULL, 0);
-       } else
-               cmd->len |= F_INSN_SIZE(ipfw_insn);
+               cmd->len |= F_INSN_SIZE(ipfw_insn_table);
+               fill_table_value(cmd, p);
+       } else {
+               IPFW_SET_LOOKUP_TYPE(cmd, LOOKUP_NONE);
+               cmd->len |= F_INSN_SIZE(ipfw_insn_kidx);
+       }
 }
 
-
 /*
  * fills the addr and mask fields in the instruction as appropriate from av.
  * Update length as appropriate.
@@ -3470,7 +3584,7 @@ ipfw_delete(char *av[])
 {
        ipfw_range_tlv rt;
        char *sep;
-       int i, j;
+       uint32_t i, j;
        int exitval = EX_OK;
        int do_set = 0;
 
@@ -3503,8 +3617,8 @@ ipfw_delete(char *av[])
                                rt.set = i & 31;
                                rt.flags = IPFW_RCFLAG_SET;
                        } else {
-                               rt.start_rule = i & 0xffff;
*** 9719 LINES SKIPPED ***


Reply via email to