git: 4a77657cbc01 - main - ipfw: migrate ipfw to 32-bit size rule numbers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 03 Mar 2025 19:00:47 UTC
The branch main has been updated by ae:
URL: https://cgit.FreeBSD.org/src/commit/?id=4a77657cbc011ea657ccb079fff6b58b295eccb0
commit 4a77657cbc011ea657ccb079fff6b58b295eccb0
Author: Andrey V. Elsukov <ae@FreeBSD.org>
AuthorDate: 2025-03-03 18:15:17 +0000
Commit: Andrey V. Elsukov <ae@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 ***