Page MenuHomeFreeBSD

D53694.id167039.diff
No OneTemporary

D53694.id167039.diff

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1421,8 +1421,7 @@
with multiple addresses) is provided for convenience only and
its use is discouraged.
.It Ar addr : Oo Cm not Oc Bro
-.Cm any | me | me6 |
-.Cm table Ns Pq Ar name Ns Op , Ns Ar value
+.Cm any | me | me6 | Ar table-ref
.Ar | addr-list | addr-set
.Brc
.Bl -tag -width indent
@@ -1434,16 +1433,32 @@
Matches any IPv6 address configured on an interface in the system.
The address list is evaluated at the time the packet is
analysed.
-.It Cm table Ns Pq Ar name Ns Op , Ns Ar value
+.El
+.It Ar table-ref :
+A table lookup can be specified in one of the following ways:
+.Bl -tag -width indent
+.It table Ns Pq Ar name Ns
Matches any IPv4 or IPv6 address for which an entry exists in the lookup table
.Ar number .
-If an optional 32-bit unsigned
+.It table Ns Pq Ar name , Ns Ar value
+Matches any IPv4 or IPv6 address for which an entry exists in the lookup table
+.Ar number
+and 32-bit unsigned
+.Ar value
+specified matchess entry value.
+.It table Ns Pq Ar name , Ns Ar value-type Ns = Ns Ar value
+Matches any IPv4 or IPv6 address for which an entry exists in the lookup table
+.Ar number
+and 32-bit unsigned
.Ar value
-is also specified, an entry will match only if it has this value.
+specified matches corresponding
+.Ar value-type
+field for the record found.
+.El
+.Pp
See the
.Sx LOOKUP TABLES
section below for more information on lookup tables.
-.El
.It Ar addr-list : ip-addr Ns Op , Ns Ar addr-list
.It Ar ip-addr :
A host or subnet address specified in one of the following ways:
@@ -1664,9 +1679,9 @@
.It Cm fib Ar fibnum
Matches a packet that has been tagged to use
the given FIB (routing table) number.
-.It Cm flow Ar table Ns Pq Ar name Ns Op , Ns Ar value
-Search for the flow entry in lookup table
-.Ar name .
+.It Cm flow Ar table-ref
+Search for the flow entry in lookup table specified by
+.Ar table-ref .
If not found, the match fails.
Otherwise, the match succeeds and
.Cm tablearg
@@ -1682,16 +1697,16 @@
.Ar labels .
.Ar labels
is a comma separated list of numeric flow labels.
-.It Cm dst-mac Ar table Ns Pq Ar name Ns Op , Ns Ar value
-Search for the destination MAC address entry in lookup table
-.Ar name .
+.It Cm dst-mac Ar table-ref
+Search for the destination MAC address entry in lookup table specified by
+.Ar table-ref .
If not found, the match fails.
Otherwise, the match succeeds and
.Cm tablearg
is set to the value extracted from the table.
-.It Cm src-mac Ar table Ns Pq Ar name Ns Op , Ns Ar value
-Search for the source MAC address entry in lookup table
-.Ar name .
+.It Cm src-mac Ar table-ref
+Search for the source MAC address entry in lookup table specified by
+.Ar table-ref .
If not found, the match fails.
Otherwise, the match succeeds and
.Cm tablearg
@@ -1909,8 +1924,9 @@
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
+.It Cm lookup Bro Cm dst-ip | dst-ip4 | dst-ip6 | dst-port | dst-mac | src-ip |
+.Cm src-ip4 | src-ip6 | src-port | src-mac | uid | jail | dscp | mark
+.Brc Ns Oo : Ns Ar bitmask Oc Ar name
Search an entry in lookup table
.Ar name
that matches the field specified as argument.
@@ -1919,8 +1935,56 @@
.Cm tablearg
is set to the value extracted from the table.
.Pp
+If an optional
+.Ar bitmask
+is specified, value of the field is altered by bitwize AND with
+.Ar bitmask
+and resulting value is being searched instead of the original one.
+The
+.Ar bitmask
+is accepted in the following formats:
+.Bl -enum -width indent
+.It
+In a dotted-quad form, e.g. 127.88.34.0.
+This form can be used for IPv4 lookups as well as for all numeric lookup
+types.
+.It
+As a 32-bit number, e.g. 0xf00baa1 or 255.
+This form can be used for IPv4 lookups as well as for all numeric lookup
+types.
+.It
+As an IPv6 address when specified alongwith
+.Cm dst-ip6
+or
+.Cm src-ip6
+field.
+If used, the rule will match IPv6 packets only.
+Example: src-ip6:afff:ff00:ffff:ffff:0:0:0:0f0f.
+.It
+As a Ethernet mac address when specified alongwith
+.Cm dst-mac
+or
+.Cm src-mac
+field. E.g. 00:11:22:33:44:55.
+.El
+.Pp
+The
+.Ar bitmask
+can not be specified for
+.Cm dst-ip
+or
+.Cm src-ip
+as these field specifiers lookup both IPv4 and IPv6 addresses.
+.Pp
This option can be useful to quickly dispatch traffic based on
certain packet fields.
+The
+.Ar bitmask
+allows to implement wildcard lookups by inserting into table masked prefix and
+appying
+.Ar bitmask
+upon each lookup.
+.Pp
See the
.Sx LOOKUP TABLES
section below for more information on lookup tables.
@@ -1983,7 +2047,7 @@
.Cm check-state
in contrast to
.Cm keep-state .
-.It Cm recv | xmit | via Brq Ar ifX | Ar ifmask | Ar table Ns Po Ar name Ns Oo , Ns Ar value Oc Pc | Ar ipno | Ar any
+.It Cm recv | xmit | via Brq Ar ifX | Ar ifmask | Ar table-ref | Ar ipno | Ar any
Matches packets received, transmitted or going through,
respectively, the interface specified by exact name
.Po Ar ifX Pc ,
@@ -2001,8 +2065,8 @@
.Sx EXAMPLES
section.
.Pp
-Table
-.Ar name
+A lookup table specified by
+.Ar table-ref
may be used to match interface by its kernel ifindex.
See the
.Sx LOOKUP TABLES
@@ -4309,7 +4373,8 @@
.Xr route 4
socket, that were logged using rules with
.Cm log Cm logdst Ar rtsock
-opcode. Optional
+opcode.
+Optional
.Ar filter-comment
can be specified to show only those messages, that were logged
by rules with specific rule comment.
@@ -4664,10 +4729,41 @@
The following example illustrate usage of flow tables:
.Pp
.Dl "ipfw table fl create type flow:src-ip,proto,dst-ip,dst-port"
-.Dl "ipfw table fl add 2a02:6b8:77::88,tcp,2a02:6b8:77::99,80 11"
+.Dl "ipfw table fl add 2001:db8:77::88,tcp,2001:db8:77::99,80 11"
.Dl "ipfw table fl add 10.0.0.1,udp,10.0.0.2,53 12"
.Dl ".."
.Dl "ipfw add 100 allow ip from any to any flow 'table(fl,11)' recv ix0"
+.Pp
+The following example illustrate masked table lookups to aid uniform client
+distribution among multiple NAT instances:
+.Bd -literal -offset indent
+# Configure NAT instances
+ipfw nat 10 config ip 192.0.2.0
+ipfw nat 11 config ip 192.0.2.1
+ipfw nat 12 config ip 192.0.2.2
+ipfw nat 13 config ip 192.0.2.3
+
+ipfw table mynats create type addr valtype nat
+# Map external NAT address to NAT instance
+ipfw table mynats add 192.0.2.0 10
+ipfw table mynats add 192.0.2.1 11
+ipfw table mynats add 192.0.2.2 12
+ipfw table mynats add 192.0.2.3 13
+
+# Map last 2 bits of client's IP address to NAT instance
+ipfw table mynats add 0.0.0.0 10
+ipfw table mynats add 0.0.0.1 11
+ipfw table mynats add 0.0.0.2 12
+ipfw table mynats add 0.0.0.3 13
+
+# In -> Out NAT, zero out all bits in a client's IP exept
+# 2 least significant prior to table lookup
+ipfw add nat tablearg ip from 10.0.0.0/24 to any
+ lookup src-ip4:0.0.0.3 mynats
+# Out -> In NAT
+ipfw add nat tablearg ip from any to 192.0.2.0/30
+ lookup dst-ip mynats
+.Ed
.Ss SETS OF RULES
To add a set of rules atomically, e.g.\& set 18:
.Pp
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -317,6 +317,10 @@
static struct _s_x lookup_keys[] = {
{ "dst-ip", LOOKUP_DST_IP },
{ "src-ip", LOOKUP_SRC_IP },
+ { "dst-ip6", LOOKUP_DST_IP6 },
+ { "src-ip6", LOOKUP_SRC_IP6 },
+ { "dst-ip4", LOOKUP_DST_IP4 },
+ { "src-ip4", LOOKUP_SRC_IP4 },
{ "dst-port", LOOKUP_DST_PORT },
{ "src-port", LOOKUP_SRC_PORT },
{ "dst-mac", LOOKUP_DST_MAC },
@@ -342,6 +346,7 @@
{ "fib", TVALUE_FIB },
{ "nat", TVALUE_NAT },
{ "nh4", TVALUE_NH4 },
+ { "nh6", TVALUE_NH6 },
{ "dscp", TVALUE_DSCP },
{ "limit", TVALUE_LIMIT },
{ "mark", TVALUE_MARK },
@@ -1319,12 +1324,27 @@
}
static void
-print_tvalue(struct buf_pr *bp, const ipfw_insn_table *cmd)
+print_tvalue(struct buf_pr *bp, const ipfw_insn_lookup *cmd)
{
+ char maskbuf[INET6_ADDRSTRLEN];
const char *name;
name = match_value(tvalue_names, IPFW_TVALUE_TYPE(&cmd->o));
- bprintf(bp, ",%s=%u", name != NULL ? name: "<invalid>", cmd->value);
+ switch(IPFW_TVALUE_TYPE(&cmd->o)) {
+ case TVALUE_NH6:
+ if (inet_ntop(AF_INET6, &insntoc(&cmd->o, lookup)->ip6,
+ maskbuf, sizeof(maskbuf)) == NULL)
+ strcpy(maskbuf, "<invalid>");
+ bprintf(bp, ",%s=%s", name != NULL ? name: "<invalid>",
+ maskbuf);
+ return;
+ case TVALUE_NH4:
+ bprintf(bp, ",%s=%s", name != NULL ? name: "<invalid>",
+ inet_ntoa(cmd->ip4));
+ return;
+ }
+ bprintf(bp, ",%s=%u", name != NULL ? name: "<invalid>",
+ cmd->u32);
}
@@ -1335,11 +1355,14 @@
print_ip(struct buf_pr *bp, const struct format_opts *fo,
const ipfw_insn_ip *cmd)
{
+ char maskbuf[INET6_ADDRSTRLEN];
+ const uint32_t *a = insntoc(cmd, u32)->d;
struct hostent *he = NULL;
const struct in_addr *ia;
- const uint32_t *a = ((const ipfw_insn_u32 *)cmd)->d;
- uint32_t len = F_LEN(&cmd->o);
+ const ipfw_insn_lookup *l = insntoc(cmd, lookup);
+ const char *key;
char *t;
+ uint32_t len = F_LEN(&cmd->o);
bprintf(bp, " ");
switch (cmd->o.opcode) {
@@ -1348,32 +1371,65 @@
bprintf(bp, "me");
return;
- 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);
+ case O_TABLE_LOOKUP: {
+ key = match_value(lookup_keys,
+ IPFW_LOOKUP_TYPE(&cmd->o));
+ t = table_search_ctlv(fo->tstate,
+ insntoc(&cmd->o, kidx)->kidx);
+ if (IPFW_LOOKUP_MASKING(&cmd->o) == 0 ||
+ len != F_INSN_SIZE(ipfw_insn_lookup)) {
+ bprintf(bp, "lookup %s %s",
+ (key != NULL ? key : "<invalid>"), t);
return;
}
- /* FALLTHROUGH */
+ switch (IPFW_LOOKUP_TYPE(&cmd->o)) {
+ case LOOKUP_DST_IP6:
+ case LOOKUP_SRC_IP6:
+ if (inet_ntop(AF_INET6, &l->ip6,
+ maskbuf, sizeof(maskbuf)) == NULL)
+ strcpy(maskbuf, "<invalid>");
+ bprintf(bp, "lookup %s:%s %s", key, maskbuf, t);
+ break;
+ case LOOKUP_DST_IP:
+ case LOOKUP_SRC_IP:
+ case LOOKUP_DST_IP4:
+ case LOOKUP_SRC_IP4:
+ bprintf(bp, "lookup %s:%s %s", key,
+ inet_ntoa(l->ip4), t);
+ break;
+ case LOOKUP_DST_MAC:
+ case LOOKUP_SRC_MAC:
+ bprintf(bp, "lookup %s:%s %s", key,
+ ether_ntoa((const struct ether_addr *)&l->mac), t);
+ break;
+ default:
+ bprintf(bp, "lookup %s:%#x %s",
+ (key != NULL ? key : "<invalid>"),
+ l->u32, t);
+ }
+ return;
+ }
+ case O_IP_DST_LOOKUP:
case O_IP_SRC_LOOKUP:
t = table_search_ctlv(fo->tstate,
insntoc(&cmd->o, kidx)->kidx);
+ /*
+ * D53694 compatibility layer, to be removed.
+ * Properly show rules loaded into new kernel modules by
+ * an old ipfw binary.
+ */
+ if (IPFW_LOOKUP_MASKING(&cmd->o) != 0 &&
+ len == F_INSN_SIZE(ipfw_insn_table)) {
+ key = match_value(lookup_keys,
+ IPFW_LOOKUP_TYPE(&cmd->o));
+ bprintf(bp, "lookup %s:%#x %s",
+ (key != NULL ? key : "<invalid>"),
+ insntoc(&cmd->o, table)->value, t);
+ return;
+ }
bprintf(bp, "table(%s", t);
- if (len == F_INSN_SIZE(ipfw_insn_table))
- print_tvalue(bp, insntoc(&cmd->o, table));
+ if (IPFW_LOOKUP_MATCH_TVALUE(&cmd->o) != 0)
+ print_tvalue(bp, l);
bprintf(bp, ")");
return;
}
@@ -1478,15 +1534,14 @@
print_mac_lookup(struct buf_pr *bp, const struct format_opts *fo,
const ipfw_insn *cmd)
{
- uint32_t len = F_LEN(cmd);
char *t;
bprintf(bp, " ");
t = table_search_ctlv(fo->tstate, insntoc(cmd, kidx)->kidx);
bprintf(bp, "table(%s", t);
- if (len == F_INSN_SIZE(ipfw_insn_table))
- print_tvalue(bp, insntoc(cmd, table));
+ if (IPFW_LOOKUP_MATCH_TVALUE(cmd) != 0)
+ print_tvalue(bp, insntoc(cmd, lookup));
bprintf(bp, ")");
}
@@ -1651,6 +1706,8 @@
case O_IP_SRC_SET:
if (state->flags & HAVE_SRCIP)
bprintf(bp, " src-ip");
+ /* FALLTHROUGH */
+ case O_TABLE_LOOKUP:
print_ip(bp, fo, insntoc(cmd, ip));
break;
case O_IP_DST:
@@ -1775,8 +1832,8 @@
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_table))
- print_tvalue(bp, insntoc(cmd, table));
+ if (IPFW_LOOKUP_MATCH_TVALUE(cmd) != 0)
+ print_tvalue(bp, insntoc(cmd, lookup));
bprintf(bp, ")");
break;
case O_IPID:
@@ -3312,8 +3369,11 @@
return (pack_object(tstate, name, IPFW_TLV_TBL_NAME));
}
+/*
+ * Parse table(NAME, value) and table(NAME,key=value)
+ */
static void
-fill_table_value(ipfw_insn *cmd, char *s)
+fill_table_value(ipfw_insn_lookup *cmd, char *s)
{
char *p;
int i;
@@ -3330,8 +3390,20 @@
p = s;
}
- IPFW_SET_TVALUE_TYPE(cmd, i);
- insntod(cmd, table)->value = strtoul(p, NULL, 0);
+ IPFW_SET_TVALUE_TYPE(&cmd->o, i);
+
+ if (i == TVALUE_NH6) {
+ if (inet_pton(AF_INET6, p, &cmd->ip6) != 1)
+ errx(EX_USAGE, "invalid IPv6 address provided");
+ /* mask in a dotted-quad notation */
+ } else if (strchr(p, '.') != NULL) {
+ if (inet_aton(p, &cmd->ip4) != 1)
+ errx(EX_USAGE, "invalid IPv4 address provided");
+ if (i == TVALUE_NH4)
+ return;
+ cmd->u32 = ntohl(cmd->u32);
+ } else
+ cmd->u32 = strtoul(p, NULL, 0);
}
void
@@ -3352,9 +3424,11 @@
cmd->opcode = opcode;
if (p) {
- cmd->len |= F_INSN_SIZE(ipfw_insn_table);
- fill_table_value(cmd, p);
+ cmd->len |= F_INSN_SIZE(ipfw_insn_lookup);
+ IPFW_SET_LOOKUP_MATCH_TVALUE(cmd, 1);
+ fill_table_value(insntod(cmd, lookup), p);
} else {
+ /* table(NAME) */
IPFW_SET_LOOKUP_TYPE(cmd, LOOKUP_NONE);
cmd->len |= F_INSN_SIZE(ipfw_insn_kidx);
}
@@ -4133,6 +4207,38 @@
return (ntohs(s->s_port));
}
+static void
+get_lookup_bitmask(int opcode, ipfw_insn_lookup *cmd, const char *src)
+{
+ struct ether_addr *mac;
+ const char *macset = "0123456789abcdefABCDEF:";
+
+ if (opcode == LOOKUP_SRC_IP6 || opcode == LOOKUP_DST_IP6) {
+ if (inet_pton(AF_INET6, src, &cmd->ip6) != 1)
+ errx(EX_USAGE, "invalid IPv6 mask provided");
+ return;
+ } else if (opcode == LOOKUP_SRC_MAC || opcode == LOOKUP_DST_MAC) {
+ if (strspn(src, macset) != strlen(src) ||
+ (mac = ether_aton(src)) == NULL)
+ errx(EX_DATAERR, "Incorrect MAC address");
+
+ bcopy(mac, cmd->mac, ETHER_ADDR_LEN);
+ return;
+ /* mask in a dotted-quad notation */
+ } else if (strchr(src, '.') != NULL) {
+ if (inet_aton(src, &cmd->ip4) != 1)
+ errx(EX_USAGE, "invalid dotted-quad mask provided");
+ switch (opcode) {
+ case LOOKUP_SRC_IP4:
+ case LOOKUP_DST_IP4:
+ return;
+ }
+ cmd->u32 = ntohl(cmd->u32);
+ return;
+ }
+ cmd->u32 = strtoul(src, NULL, 0);
+}
+
/*
* Parse arguments and assemble the microinstructions which make up a rule.
* Rules are added into the 'rulebuf' and then copied in the correct order
@@ -5469,13 +5575,13 @@
case TOK_LOOKUP: {
/* optional mask for some LOOKUP types */
- ipfw_insn_table *c = insntod(cmd, table);
+ ipfw_insn_lookup *c = insntod(cmd, lookup);
char *lkey;
if (!av[0] || !av[1])
errx(EX_USAGE,
"format: lookup argument tablenum");
- cmd->opcode = O_IP_DST_LOOKUP;
+ cmd->opcode = O_TABLE_LOOKUP;
lkey = strsep(av, ":");
i = match_token(lookup_keys, lkey);
@@ -5492,18 +5598,21 @@
case LOOKUP_DSCP:
case LOOKUP_MARK:
case LOOKUP_RULENUM:
+ case LOOKUP_SRC_MAC:
+ case LOOKUP_DST_MAC:
+ case LOOKUP_SRC_IP6:
+ case LOOKUP_DST_IP6:
+ case LOOKUP_SRC_IP4:
+ case LOOKUP_DST_IP4:
break;
default:
errx(EX_USAGE,
"masked lookup is not supported "
"for %s", lkey);
}
- cmd->len |= F_INSN_SIZE(ipfw_insn_table);
- c->value = strtoul(*av, NULL, 0);
- if (c->value == 0)
- errx(EX_USAGE,
- "all-zeroes bitmask for lookup "
- "is meaningless");
+ cmd->len |= F_INSN_SIZE(ipfw_insn_lookup);
+ IPFW_SET_LOOKUP_MASKING(cmd, 1);
+ get_lookup_bitmask(i, c, *av);
} else {
cmd->len |= F_INSN_SIZE(ipfw_insn_kidx);
}
diff --git a/sbin/ipfw/tests/test_add_rule.py b/sbin/ipfw/tests/test_add_rule.py
--- a/sbin/ipfw/tests/test_add_rule.py
+++ b/sbin/ipfw/tests/test_add_rule.py
@@ -37,7 +37,11 @@
from atf_python.sys.netpfil.ipfw.insns import InsnReject
from atf_python.sys.netpfil.ipfw.insns import InsnTable
from atf_python.sys.netpfil.ipfw.insns import InsnU32
+from atf_python.sys.netpfil.ipfw.insns import InsnKidx
+from atf_python.sys.netpfil.ipfw.insns import InsnLookup
from atf_python.sys.netpfil.ipfw.insns import IpFwOpcode
+from atf_python.sys.netpfil.ipfw.insn_headers import IpFwTableLookupType
+from atf_python.sys.netpfil.ipfw.insn_headers import IpFwTableValueType
from atf_python.sys.netpfil.ipfw.ioctl import CTlv
from atf_python.sys.netpfil.ipfw.ioctl import CTlvRule
from atf_python.sys.netpfil.ipfw.ioctl import IpFwTlvType
@@ -153,14 +157,226 @@
NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
],
"insns": [
- InsnU32(IpFwOpcode.O_IP_SRC_LOOKUP, u32=1),
- InsnU32(IpFwOpcode.O_IP_DST_LOOKUP, u32=2),
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnKidx(IpFwOpcode.O_IP_DST_LOOKUP, kidx=2),
InsnEmpty(IpFwOpcode.O_ACCEPT),
],
},
},
id="test_tables",
),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup dst-ip BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_DST_IP),
+ ),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_no_mask",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup mark:0xf00baa1 BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_MARK, bitmask=True),
+ bitmask=0xf00baa1),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_u32_mask",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup src-mac:1a:2b:3c:4d:5e:6f BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_SRC_MAC, bitmask=True),
+ bitmask="1a:2b:3c:4d:5e:6f"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_mac_mask",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup dst-ip4:1715004 BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_DST_IP4, bitmask=True),
+ bitmask="60.43.26.0"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_dst_ip4_numeric",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup src-ip4:0.0.0.255 BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_SRC_IP4, bitmask=True),
+ bitmask="0.0.0.255"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_src_ip4_addr",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup jail:0.0.252.128 BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_JAIL, bitmask=True),
+ bitmask=64640),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_jail_addr",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to any lookup dst-ip6:ffff:ffff:f00:baaa:b00c:: BBB",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnKidx(IpFwOpcode.O_IP_SRC_LOOKUP, kidx=1),
+ InsnLookup(IpFwOpcode.O_TABLE_LOOKUP,
+ kidx=2,
+ arg1=InsnLookup.compile_arg1(lookup_type=IpFwTableLookupType.LOOKUP_DST_IP6, bitmask=True),
+ bitmask="ffff:ffff:f00:baaa:b00c::"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_lookup_dst_ip6",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA,16777215) to any",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ ],
+ "insns": [
+ InsnLookup(IpFwOpcode.O_IP_SRC_LOOKUP,
+ kidx=1,
+ arg1=InsnLookup.compile_arg1(value_type=IpFwTableValueType.TVALUE_TAG),
+ value=16777215),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_check_value_legacy",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA,nat=1231) to any",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ ],
+ "insns": [
+ InsnLookup(IpFwOpcode.O_IP_SRC_LOOKUP,
+ kidx=1,
+ arg1=InsnLookup.compile_arg1(value_type=IpFwTableValueType.TVALUE_NAT),
+ value=1231),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_check_value_nat",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA,nh4=10.20.30.40) to any",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ ],
+ "insns": [
+ InsnLookup(IpFwOpcode.O_IP_SRC_LOOKUP,
+ kidx=1,
+ arg1=InsnLookup.compile_arg1(value_type=IpFwTableValueType.TVALUE_NH4),
+ value="10.20.30.40"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_check_value_nh4",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA,nh6=ff02:1234:b00c::abcd) to any",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ ],
+ "insns": [
+ InsnLookup(IpFwOpcode.O_IP_SRC_LOOKUP,
+ kidx=1,
+ arg1=InsnLookup.compile_arg1(value_type=IpFwTableValueType.TVALUE_NH6),
+ value="ff02:1234:b00c::abcd"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables_check_value_nh6",
+ ),
pytest.param(
{
"in": "add allow ip from any to 1.2.3.4 // test comment",
@@ -183,7 +399,7 @@
],
"insns": [
InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"),
- InsnU32(IpFwOpcode.O_EXTERNAL_ACTION, u32=1),
+ InsnKidx(IpFwOpcode.O_EXTERNAL_ACTION, kidx=1),
Insn(IpFwOpcode.O_EXTERNAL_DATA, arg1=123),
],
},
@@ -192,20 +408,20 @@
),
pytest.param(
{
- "in": "add eaction ntpv6 AAA ip from any to 1.2.3.4",
+ "in": "add eaction nptv6 AAA ip from any to 1.2.3.4",
"out": {
"objs": [
- NTlv(IpFwTlvType.IPFW_TLV_EACTION, idx=1, name="ntpv6"),
+ NTlv(IpFwTlvType.IPFW_TLV_EACTION, idx=1, name="nptv6"),
NTlv(0, idx=2, name="AAA"),
],
"insns": [
InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"),
- InsnU32(IpFwOpcode.O_EXTERNAL_ACTION, u32=1),
- InsnU32(IpFwOpcode.O_EXTERNAL_INSTANCE, u32=2),
+ InsnKidx(IpFwOpcode.O_EXTERNAL_ACTION, kidx=1),
+ InsnKidx(IpFwOpcode.O_EXTERNAL_INSTANCE, kidx=2),
],
},
},
- id="test_eaction_ntp",
+ id="test_eaction_nptv6",
),
pytest.param(
{
@@ -228,7 +444,7 @@
],
"insns": [
InsnComment(comment="test comment"),
- InsnU32(IpFwOpcode.O_CHECK_STATE, u32=1),
+ InsnKidx(IpFwOpcode.O_CHECK_STATE, kidx=1),
],
},
},
@@ -242,9 +458,9 @@
NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="OUT"),
],
"insns": [
- InsnU32(IpFwOpcode.O_PROBE_STATE, u32=1),
+ InsnKidx(IpFwOpcode.O_PROBE_STATE, kidx=1),
Insn(IpFwOpcode.O_PROTO, arg1=6),
- InsnU32(IpFwOpcode.O_KEEP_STATE, u32=1),
+ InsnKidx(IpFwOpcode.O_KEEP_STATE, kidx=1),
InsnEmpty(IpFwOpcode.O_ACCEPT),
],
},
@@ -260,7 +476,7 @@
],
"insns": [
Insn(IpFwOpcode.O_PROTO, arg1=6),
- InsnU32(IpFwOpcode.O_KEEP_STATE, u32=1),
+ InsnKidx(IpFwOpcode.O_KEEP_STATE, kidx=1),
InsnEmpty(IpFwOpcode.O_ACCEPT),
],
},
@@ -373,6 +589,9 @@
pytest.param(
("skipto 42", InsnU32(IpFwOpcode.O_SKIPTO, u32=42)), id="skipto_42"
),
+ pytest.param(
+ ("skipto 4200", InsnU32(IpFwOpcode.O_SKIPTO, u32=4200)), id="skipto_4200"
+ ),
pytest.param(
("netgraph 42", Insn(IpFwOpcode.O_NETGRAPH, arg1=42)), id="netgraph_42"
),
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -235,7 +235,7 @@
O_REJECT = 47, /* arg1=icmp arg (same as deny) */
O_COUNT = 48, /* none */
O_SKIPTO = 49, /* v0:arg1=next rule number */
- /* v1:kidx= next rule number */
+ /* v1:u32= next rule number */
O_PIPE = 50, /* arg1=pipe number */
O_QUEUE = 51, /* arg1=queue number */
O_DIVERT = 52, /* arg1=port number */
@@ -250,9 +250,11 @@
*/
O_IPSEC = 58, /* has ipsec history */
O_IP_SRC_LOOKUP = 59, /* v0:arg1=table number, u32=value */
- /* v1:kidx=name, u32=value, arg1=key */
+ /* v1:lookup: kidx=name, arg1=key and */
+ /* flags, bitmask */
O_IP_DST_LOOKUP = 60, /* arg1=table number, u32=value */
- /* v1:kidx=name, u32=value, arg1=key */
+ /* v1:lookup: kidx=name, arg1=key and */
+ /* flags, bitmask */
O_ANTISPOOF = 61, /* none */
O_JAIL = 62, /* u32 = id */
O_ALTQ = 63, /* u32 = altq classif. qid */
@@ -288,14 +290,15 @@
O_SOCKARG = 84, /* socket argument */
O_CALLRETURN = 85, /* v0:arg1=called rule number */
- /* v1:kidx=called rule number */
+ /* v1:u32=called rule number */
O_FORWARD_IP6 = 86, /* fwd sockaddr_in6 */
O_DSCP = 87, /* 2 u32 = DSCP mask */
O_SETDSCP = 88, /* arg1=DSCP value */
O_IP_FLOW_LOOKUP = 89, /* v0:arg1=table number, u32=value */
- /* v1:kidx=name, u32=value */
+ /* v1:lookup: kidx=name, arg1=key and */
+ /* flags, bitmask */
O_EXTERNAL_ACTION = 90, /* v0:arg1=id of external action handler */
/* v1:kidx=id of external action handler */
@@ -306,12 +309,20 @@
O_SKIP_ACTION = 93, /* none */
O_TCPMSS = 94, /* arg1=MSS value */
- O_MAC_SRC_LOOKUP = 95, /* kidx=name, u32=value, arg1=key */
- O_MAC_DST_LOOKUP = 96, /* kidx=name, u32=value, arg1=key */
+ O_MAC_SRC_LOOKUP = 95, /* kidx=name */
+ /* v1:lookup: kidx=name, arg1=key and */
+ /* flags, bitmask */
+ O_MAC_DST_LOOKUP = 96, /* kidx=name */
+ /* v1:lookup: kidx=name, arg1=key and */
+ /* flags, bitmask */
O_SETMARK = 97, /* u32 = value */
O_MARK = 98, /* 2 u32 = value, bitmask */
+ O_TABLE_LOOKUP = 99, /* kidx=name */
+ /* v1:lookup: kidx=name, arg1=key and */
+ /* flags, bitmask */
+
O_LAST_OPCODE /* not an opcode! */
};
@@ -409,12 +420,32 @@
uint32_t value; /* table value */
} ipfw_insn_table;
-#define IPFW_LOOKUP_TYPE_MASK 0x00FF
+typedef struct _ipfw_insn_lookup {
+ ipfw_insn o; /* arg1 is flags and lookup key */
+ uint32_t kidx; /* table name index */
+ union { /* lookup mask */
+ uint64_t __mask64[2];
+ struct in6_addr ip6;
+ struct in_addr ip4;
+ char mac[6];
+ uint32_t u32;
+ };
+} ipfw_insn_lookup;
+
+#define IPFW_LOOKUP_TYPE_MASK 0x007F
#define IPFW_LOOKUP_TYPE(insn) ((insn)->arg1 & IPFW_LOOKUP_TYPE_MASK)
#define IPFW_SET_LOOKUP_TYPE(insn, type) do { \
(insn)->arg1 &= ~IPFW_LOOKUP_TYPE_MASK; \
(insn)->arg1 |= (type) & IPFW_LOOKUP_TYPE_MASK; \
} while (0)
+#define IPFW_LOOKUP_F_MASKING 0x0080
+#define IPFW_LOOKUP_MASKING(insn) ((insn)->arg1 & IPFW_LOOKUP_F_MASKING)
+#define IPFW_SET_LOOKUP_MASKING(insn, value) do { \
+ if (value) \
+ (insn)->arg1 |= IPFW_LOOKUP_F_MASKING; \
+ else \
+ (insn)->arg1 &= ~IPFW_LOOKUP_F_MASKING; \
+} while (0)
/*
* Defines key types used by lookup instruction
@@ -432,6 +463,10 @@
LOOKUP_SRC_MAC,
LOOKUP_MARK,
LOOKUP_RULENUM,
+ LOOKUP_DST_IP4,
+ LOOKUP_SRC_IP4,
+ LOOKUP_DST_IP6,
+ LOOKUP_SRC_IP6,
};
enum ipfw_return_type {
@@ -941,12 +976,20 @@
} a;
};
-#define IPFW_TVALUE_TYPE_MASK 0xFF00
+#define IPFW_TVALUE_TYPE_MASK 0x7F00
#define IPFW_TVALUE_TYPE(insn) (((insn)->arg1 & IPFW_TVALUE_TYPE_MASK) >> 8)
#define IPFW_SET_TVALUE_TYPE(insn, type) do { \
(insn)->arg1 &= ~IPFW_TVALUE_TYPE_MASK; \
(insn)->arg1 |= ((type) << 8) & IPFW_TVALUE_TYPE_MASK; \
} while (0)
+#define IPFW_LOOKUP_F_MATCH_TVALUE 0x8000
+#define IPFW_LOOKUP_MATCH_TVALUE(insn) ((insn)->arg1 & IPFW_LOOKUP_F_MATCH_TVALUE)
+#define IPFW_SET_LOOKUP_MATCH_TVALUE(insn, value) do { \
+ if (value) \
+ (insn)->arg1 |= IPFW_LOOKUP_F_MATCH_TVALUE; \
+ else \
+ (insn)->arg1 &= ~IPFW_LOOKUP_F_MATCH_TVALUE; \
+} while (0)
enum ipfw_table_value_type {
TVALUE_TAG = 0,
@@ -960,6 +1003,7 @@
TVALUE_DSCP,
TVALUE_LIMIT,
TVALUE_MARK,
+ TVALUE_NH6,
};
/* 64-byte structure representing multi-field table value */
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -1317,7 +1317,7 @@
#define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f)
static inline int
-tvalue_match(struct ip_fw_chain *ch, const ipfw_insn_table *cmd,
+tvalue_match(struct ip_fw_chain *ch, const ipfw_insn_lookup *cmd,
uint32_t tablearg)
{
uint32_t tvalue;
@@ -1344,6 +1344,11 @@
case TVALUE_NH4:
tvalue = TARG_VAL(ch, tablearg, nh4);
break;
+ case TVALUE_NH6:
+ if (F_LEN(&cmd->o) != F_INSN_SIZE(ipfw_insn_lookup))
+ return (0);
+ return (0 == memcmp(&TARG_VAL(ch, tablearg, nh6),
+ &cmd->ip6, sizeof(struct in6_addr)));
case TVALUE_DSCP:
tvalue = TARG_VAL(ch, tablearg, dscp);
break;
@@ -1358,7 +1363,13 @@
tvalue = TARG_VAL(ch, tablearg, tag);
break;
}
- return (tvalue == cmd->value);
+ /*
+ * D53694 compatibility layer, to be removed.
+ * Match u32 values specified as ipfw_insn_table structure.
+ */
+ if (F_LEN(&cmd->o) == F_INSN_SIZE(ipfw_insn_table))
+ return (tvalue == insntoc(cmd, table)->value);
+ return (tvalue == cmd->u32);
}
/*
@@ -2102,45 +2113,101 @@
break;
case O_IP_DST_LOOKUP:
- if (IPFW_LOOKUP_TYPE(cmd) != LOOKUP_NONE) {
- void *pkey = NULL;
- uint32_t key, vidx;
- uint16_t keylen = 0; /* zero if can't match the packet */
- uint8_t lookup_type;
+ case O_IP_SRC_LOOKUP:
+ /*
+ * D53694 compatibility layer, to be removed.
+ * The following if and subsequent fallthrough
+ * are here for backward opcode compatibility
+ * used for lookup opcode until O_TABLE_LOOKUP
+ * appeared.
+ */
+ if (IPFW_LOOKUP_TYPE(cmd) == LOOKUP_NONE) {
+ void *pkey;
+ uint32_t vidx;
+ uint16_t keylen;
+
+ if (is_ipv4) {
+ keylen = sizeof(in_addr_t);
+ if (cmd->opcode == O_IP_DST_LOOKUP)
+ pkey = &dst_ip;
+ else
+ pkey = &src_ip;
+ } else if (is_ipv6) {
+ keylen = sizeof(struct in6_addr);
+ if (cmd->opcode == O_IP_DST_LOOKUP)
+ pkey = &args->f_id.dst_ip6;
+ else
+ pkey = &args->f_id.src_ip6;
+ } else
+ break;
+ match = ipfw_lookup_table(chain,
+ insntod(cmd, kidx)->kidx,
+ keylen, pkey, &vidx);
+ if (!match)
+ break;
+ if (IPFW_LOOKUP_MATCH_TVALUE(cmd) != 0) {
+ match = tvalue_match(chain,
+ insntod(cmd, lookup), vidx);
+ if (!match)
+ break;
+ }
+ tablearg = vidx;
+ break;
+ }
+ /* FALLTHROUGH */
+ case O_TABLE_LOOKUP:
+ {
+ ipfw_insn_lookup key;
+ uint32_t vidx;
+ uint16_t keylen = 0; /* zero if can't match the packet */
+ uint8_t lookup_type;
lookup_type = IPFW_LOOKUP_TYPE(cmd);
switch (lookup_type) {
case LOOKUP_DST_IP:
+ case LOOKUP_DST_IP4:
+ if (is_ipv4) {
+ keylen = sizeof(in_addr_t);
+ key.ip4 = dst_ip;
+ break;
+ }
+ if (lookup_type == LOOKUP_DST_IP4)
+ break;
+ /* FALLTHOUGH */
+ case LOOKUP_DST_IP6:
+ if (is_ipv6 == 0)
+ break;
+ keylen = sizeof(struct in6_addr);
+ key.ip6 = args->f_id.dst_ip6;
+ break;
case LOOKUP_SRC_IP:
+ case LOOKUP_SRC_IP4:
if (is_ipv4) {
keylen = sizeof(in_addr_t);
- if (lookup_type == LOOKUP_DST_IP)
- pkey = &dst_ip;
- else
- pkey = &src_ip;
- } else if (is_ipv6) {
- keylen = sizeof(struct in6_addr);
- if (lookup_type == LOOKUP_DST_IP)
- pkey = &args->f_id.dst_ip6;
- else
- pkey = &args->f_id.src_ip6;
+ key.ip4 = src_ip;
+ break;
}
+ if (lookup_type == LOOKUP_SRC_IP4)
+ break;
+ /* FALLTHOUGH */
+ case LOOKUP_SRC_IP6:
+ if (is_ipv6 == 0)
+ break;
+ keylen = sizeof(struct in6_addr);
+ key.ip6 = args->f_id.src_ip6;
break;
case LOOKUP_DSCP:
if (is_ipv4)
- key = ip->ip_tos >> 2;
+ key.u32 = ip->ip_tos >> 2;
else if (is_ipv6)
- key = IPV6_DSCP(
+ key.u32 = IPV6_DSCP(
(struct ip6_hdr *)ip) >> 2;
else
break; /* only for L3 */
- key &= 0x3f;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table))
- key &= insntod(cmd, table)->value;
- pkey = &key;
- keylen = sizeof(key);
+ keylen = sizeof(key.u32);
+ key.u32 &= 0x3f;
break;
case LOOKUP_DST_PORT:
case LOOKUP_SRC_PORT:
@@ -2159,23 +2226,26 @@
proto != IPPROTO_SCTP)
break;
if (lookup_type == LOOKUP_DST_PORT)
- key = dst_port;
+ key.u32 = dst_port;
else
- key = src_port;
- pkey = &key;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table))
- key &= insntod(cmd, table)->value;
- keylen = sizeof(key);
+ key.u32 = src_port;
+ keylen = sizeof(key.u32);
break;
case LOOKUP_DST_MAC:
+ /* only for L2 */
+ if ((args->flags & IPFW_ARGS_ETHER) == 0)
+ break;
+ keylen = ETHER_ADDR_LEN;
+ memcpy(key.mac, eh->ether_dhost,
+ sizeof(key.mac));
+ break;
case LOOKUP_SRC_MAC:
/* only for L2 */
if ((args->flags & IPFW_ARGS_ETHER) == 0)
break;
-
- pkey = lookup_type == LOOKUP_DST_MAC ?
- eh->ether_dhost : eh->ether_shost;
keylen = ETHER_ADDR_LEN;
+ memcpy(key.mac, eh->ether_shost,
+ sizeof(key.mac));
break;
#ifndef USERSPACE
case LOOKUP_UID:
@@ -2185,84 +2255,61 @@
#ifdef __FreeBSD__
&ucred_cache);
if (lookup_type == LOOKUP_UID)
- key = ucred_cache->cr_uid;
+ key.u32 = ucred_cache->cr_uid;
else if (lookup_type == LOOKUP_JAIL)
- key = ucred_cache->cr_prison->pr_id;
+ key.u32 = ucred_cache->cr_prison->pr_id;
#else /* !__FreeBSD__ */
(void *)&ucred_cache);
if (lookup_type == LOOKUP_UID)
- key = ucred_cache.uid;
+ key.u32 = ucred_cache.uid;
else if (lookup_type == LOOKUP_JAIL)
- key = ucred_cache.xid;
+ key.u32 = ucred_cache.xid;
#endif /* !__FreeBSD__ */
- pkey = &key;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table))
- key &= insntod(cmd, table)->value;
- keylen = sizeof(key);
+ keylen = sizeof(key.u32);
break;
#endif /* !USERSPACE */
case LOOKUP_MARK:
- key = args->rule.pkt_mark;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table))
- key &= insntod(cmd, table)->value;
- pkey = &key;
- keylen = sizeof(key);
+ key.u32 = args->rule.pkt_mark;
+ keylen = sizeof(key.u32);
break;
case LOOKUP_RULENUM:
- key = f->rulenum;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table))
- key &= insntod(cmd, table)->value;
- pkey = &key;
- keylen = sizeof(key);
+ key.u32 = f->rulenum;
+ keylen = sizeof(key.u32);
break;
}
/* unknown key type */
if (keylen == 0)
break;
- match = ipfw_lookup_table(chain,
- insntod(cmd, kidx)->kidx, keylen,
- pkey, &vidx);
- if (match)
- tablearg = vidx;
- break;
- }
- /* LOOKUP_NONE */
- /* FALLTHROUGH */
- case O_IP_SRC_LOOKUP:
- {
- void *pkey;
- uint32_t vidx;
- uint16_t keylen;
+ if (IPFW_LOOKUP_MASKING(cmd) == 0) {
+ /* no masking needed */
+ } else if (cmdlen ==
+ F_INSN_SIZE(ipfw_insn_table)) {
+ /*
+ * D53694 compatibility layer,
+ * to be removed.
+ */
+ key.u32 &= insntod(cmd, table)->value;
+ } else {
+ key.__mask64[0] &=
+ insntod(cmd, lookup)->__mask64[0];
+ key.__mask64[1] &=
+ insntod(cmd, lookup)->__mask64[1];
+ }
- if (is_ipv4) {
- keylen = sizeof(in_addr_t);
- if (cmd->opcode == O_IP_DST_LOOKUP)
- pkey = &dst_ip;
- else
- pkey = &src_ip;
- } else if (is_ipv6) {
- keylen = sizeof(struct in6_addr);
- if (cmd->opcode == O_IP_DST_LOOKUP)
- pkey = &args->f_id.dst_ip6;
- else
- pkey = &args->f_id.src_ip6;
- } else
- break;
match = ipfw_lookup_table(chain,
- insntod(cmd, kidx)->kidx,
- keylen, pkey, &vidx);
+ insntod(cmd, kidx)->kidx, keylen,
+ key.__mask64, &vidx);
+
if (!match)
break;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table)) {
- match = tvalue_match(chain,
- insntod(cmd, table), vidx);
- if (!match)
- break;
- }
+ /*
+ * XXX should we support check for value
+ * simultaneously with masked lookup?
+ */
tablearg = vidx;
break;
- }
+ } /* O_TABLE_LOOKUP */
case O_MAC_SRC_LOOKUP:
case O_MAC_DST_LOOKUP:
@@ -2285,9 +2332,9 @@
keylen, pkey, &vidx);
if (!match)
break;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table)) {
+ if (IPFW_LOOKUP_MATCH_TVALUE(cmd) != 0) {
match = tvalue_match(chain,
- insntod(cmd, table), vidx);
+ insntod(cmd, lookup), vidx);
if (!match)
break;
}
@@ -2304,9 +2351,9 @@
&args->f_id, &vidx);
if (!match)
break;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_table))
+ if (IPFW_LOOKUP_MATCH_TVALUE(cmd) != 0)
match = tvalue_match(chain,
- insntod(cmd, table), vidx);
+ insntod(cmd, lookup), vidx);
if (match)
tablearg = vidx;
break;
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1469,6 +1469,7 @@
case O_MAC_SRC_LOOKUP:
case O_MAC_DST_LOOKUP:
if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx) &&
+ cmdlen != F_INSN_SIZE(ipfw_insn_lookup) &&
cmdlen != F_INSN_SIZE(ipfw_insn_table))
return (BAD_SIZE);
if (insntod(cmd, kidx)->kidx >= V_fw_tables_max) {
@@ -1477,6 +1478,37 @@
return (FAILED);
}
ci->object_opcodes++;
+ /*
+ * D53694 compatibility layer, to be removed.
+
+ * ipfw_insn_table was used to match table value for u32
+ * values and cmdlen was used to detect such intention.
+ * A special flag is now used for that in module so
+ * adopt legacy sbin/ipfw behavior and set it for all
+ * lookup instructions with ipfw_insn_table opcode.
+ *
+ * Lookup type different from LOOKUP_NONE was used for
+ * 32-bit bitmasking prior to lookup.
+ * Table value matching was expected otherwise.
+ */
+ if (cmdlen != F_INSN_SIZE(ipfw_insn_table))
+ break;
+
+ if (IPFW_LOOKUP_TYPE(cmd) != LOOKUP_NONE)
+ IPFW_SET_LOOKUP_MASKING(cmd, 1);
+ else
+ IPFW_SET_LOOKUP_MATCH_TVALUE(cmd, 1);
+ break;
+ case O_TABLE_LOOKUP:
+ if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx) &&
+ cmdlen != F_INSN_SIZE(ipfw_insn_lookup))
+ return (BAD_SIZE);
+ if (insntod(cmd, kidx)->kidx >= V_fw_tables_max) {
+ printf("ipfw: invalid table index %u\n",
+ insntod(cmd, kidx)->kidx);
+ return (FAILED);
+ }
+ ci->object_opcodes++;
break;
case O_MACADDR2:
if (cmdlen != F_INSN_SIZE(ipfw_insn_mac))
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c
--- a/sys/netpfil/ipfw/ip_fw_table.c
+++ b/sys/netpfil/ipfw/ip_fw_table.c
@@ -2422,14 +2422,18 @@
static int
classify_srcdst(ipfw_insn *cmd0, uint32_t *puidx, uint8_t *ptype)
{
- ipfw_insn_table *cmd;
+ ipfw_insn_lookup *cmd;
/* Basic IPv4/IPv6 or u32 lookups */
- cmd = insntod(cmd0, table);
+ cmd = insntod(cmd0, lookup);
*puidx = cmd->kidx;
- switch(cmd0->arg1) {
+ switch(IPFW_LOOKUP_TYPE(cmd0)) {
case LOOKUP_DST_IP:
case LOOKUP_SRC_IP:
+ case LOOKUP_DST_IP4:
+ case LOOKUP_SRC_IP4:
+ case LOOKUP_DST_IP6:
+ case LOOKUP_SRC_IP6:
default:
/* IPv4 src/dst */
*ptype = IPFW_TABLE_ADDR;
@@ -2469,7 +2473,7 @@
static int
classify_flow(ipfw_insn *cmd0, uint32_t *puidx, uint8_t *ptype)
{
- *puidx = insntod(cmd0, table)->kidx;
+ *puidx = insntod(cmd0, kidx)->kidx;
*ptype = IPFW_TABLE_FLOW;
return (0);
}
@@ -2477,7 +2481,7 @@
static int
classify_mac_lookup(ipfw_insn *cmd0, uint32_t *puidx, uint8_t *ptype)
{
- *puidx = insntod(cmd0, table)->kidx;
+ *puidx = insntod(cmd0, kidx)->kidx;
*ptype = IPFW_TABLE_MAC;
return (0);
}
@@ -2485,7 +2489,7 @@
static void
update_kidx(ipfw_insn *cmd0, uint32_t idx)
{
- insntod(cmd0, table)->kidx = idx;
+ insntod(cmd0, kidx)->kidx = idx;
}
static void
@@ -2618,6 +2622,16 @@
.create_object = create_table_compat,
.manage_sets = table_manage_sets,
},
+ {
+ .opcode = O_TABLE_LOOKUP,
+ .etlv = IPFW_TLV_TBL_NAME,
+ .classifier = classify_srcdst,
+ .update = update_kidx,
+ .find_byname = table_findbyname,
+ .find_bykidx = table_findbykidx,
+ .create_object = create_table_compat,
+ .manage_sets = table_manage_sets,
+ },
{
.opcode = O_IP_FLOW_LOOKUP,
.etlv = IPFW_TLV_TBL_NAME,
diff --git a/tests/atf_python/sys/netpfil/ipfw/insn_headers.py b/tests/atf_python/sys/netpfil/ipfw/insn_headers.py
--- a/tests/atf_python/sys/netpfil/ipfw/insn_headers.py
+++ b/tests/atf_python/sys/netpfil/ipfw/insn_headers.py
@@ -101,7 +101,8 @@
O_MAC_DST_LOOKUP = 96
O_SETMARK = 97
O_MARK = 98
- O_LAST_OPCODE = 99
+ O_TABLE_LOOKUP = 99
+ O_LAST_OPCODE = 100
class Op3CmdType(Enum):
@@ -196,3 +197,37 @@
ICMP6_DST_UNREACH_SRCROUTE = 7
ICMP6_UNREACH_RST = 256
ICMP6_UNREACH_ABORT = 257
+
+
+class IpFwTableLookupType(Enum):
+ LOOKUP_NONE = 0
+ LOOKUP_DST_IP = 1
+ LOOKUP_SRC_IP = 2
+ LOOKUP_DST_PORT = 3
+ LOOKUP_SRC_PORT = 4
+ LOOKUP_UID = 5
+ LOOKUP_JAIL = 6
+ LOOKUP_DSCP = 7
+ LOOKUP_DST_MAC = 8
+ LOOKUP_SRC_MAC = 9
+ LOOKUP_MARK = 10
+ LOOKUP_RULENUM = 11
+ LOOKUP_DST_IP4 = 12
+ LOOKUP_SRC_IP4 = 13
+ LOOKUP_DST_IP6 = 14
+ LOOKUP_SRC_IP6 = 15
+
+
+class IpFwTableValueType(Enum):
+ TVALUE_TAG = 0
+ TVALUE_PIPE = 1
+ TVALUE_DIVERT = 2
+ TVALUE_SKIPTO = 3
+ TVALUE_NETGRAPH = 4
+ TVALUE_FIB = 5
+ TVALUE_NAT = 6
+ TVALUE_NH4 = 7
+ TVALUE_DSCP = 8
+ TVALUE_LIMIT = 9
+ TVALUE_MARK = 10
+ TVALUE_NH6 = 11
diff --git a/tests/atf_python/sys/netpfil/ipfw/insns.py b/tests/atf_python/sys/netpfil/ipfw/insns.py
--- a/tests/atf_python/sys/netpfil/ipfw/insns.py
+++ b/tests/atf_python/sys/netpfil/ipfw/insns.py
@@ -25,6 +25,8 @@
from atf_python.sys.netpfil.ipfw.insn_headers import IpFwOpcode
from atf_python.sys.netpfil.ipfw.insn_headers import IcmpRejectCode
from atf_python.sys.netpfil.ipfw.insn_headers import Icmp6RejectCode
+from atf_python.sys.netpfil.ipfw.insn_headers import IpFwTableLookupType
+from atf_python.sys.netpfil.ipfw.insn_headers import IpFwTableValueType
from atf_python.sys.netpfil.ipfw.utils import AttrDescr
from atf_python.sys.netpfil.ipfw.utils import enum_or_int
from atf_python.sys.netpfil.ipfw.utils import enum_from_int
@@ -165,7 +167,7 @@
hdr = IpFwInsn.from_buffer_copy(data[off : off + sizeof(IpFwInsn)])
insn_len = (hdr.length & 0x3F) * 4
if off + insn_len > len(data):
- raise ValueError("wrng length")
+ raise ValueError("wrong length")
# print("GET insn type {} len {}".format(hdr.opcode, insn_len))
attr = attr_map.get(hdr.opcode, None)
if attr is None:
@@ -309,6 +311,22 @@
return " arg1={} u32={}".format(self.arg1, self.u32)
+class InsnKidx(InsnU32):
+ def __init__(self, opcode, is_or=False, is_not=False, arg1=0, kidx=0):
+ super().__init__(opcode, is_or=is_or, is_not=is_not, arg1=arg1, u32=kidx)
+
+ @property
+ def kidx(self):
+ return self.u32
+
+ @kidx.setter
+ def kidx(self, kidx):
+ self.u32 = kidx
+
+ def _print_obj_value(self):
+ return " arg1={}, kidx={}".format(self.arg1, self.kidx)
+
+
class InsnProb(InsnU32):
def __init__(
self,
@@ -353,18 +371,23 @@
return " ip={}".format(self.ip)
-class InsnTable(Insn):
+class InsnTable(InsnKidx):
+ def __init__(self, opcode, is_or=False, is_not=False, arg1=0, kidx=0, value=None):
+ super().__init__(opcode, is_or=is_or, is_not=is_not, arg1=arg1, kidx=kidx)
+ self.val = value
+
@classmethod
def _validate(cls, data):
- cls._validate_len(data, [4, 8])
+ cls._validate_len(data, [8, 12])
@classmethod
def _parse(cls, data):
self = super()._parse(data)
- if len(data) == 8:
- (self.val,) = struct.unpack("@I", data[4:8])
- self.ilen = 2
+ (self.kidx,) = struct.unpack("@I", data[4:8])
+ if len(data) == 12:
+ (self.val,) = struct.unpack("@I", data[8:12])
+ self.ilen = 3
else:
self.val = None
return self
@@ -377,9 +400,128 @@
def _print_obj_value(self):
if getattr(self, "val", None) is not None:
- return " table={} value={}".format(self.arg1, self.val)
+ return " table={} value={}".format(self.kidx, self.val)
else:
- return " table={}".format(self.arg1)
+ return " table={}".format(self.kidx)
+
+
+class InsnLookup(InsnKidx):
+ def __init__(self, opcode, is_or=False, is_not=False, arg1=0, kidx=0, value=None, bitmask=None):
+ super().__init__(opcode, is_or=is_or, is_not=is_not, arg1=arg1, kidx=kidx)
+ self.val = value
+ self.bm = bitmask
+ self.decompile_arg1()
+
+ @classmethod
+ def _validate(cls, data):
+ cls._validate_len(data, [8, 24])
+
+ @classmethod
+ def _parse(cls, data):
+ self = super()._parse(data)
+
+ if len(data) == 24:
+ self.decompile_arg1()
+ self.ilen = 8
+ if self.do_masking != 0:
+ if self.lookup_type in [IpFwTableLookupType.LOOKUP_DST_IP4, IpFwTableLookupType.LOOKUP_SRC_IP4]:
+ self.bm = socket.inet_ntop(socket.AF_INET, data[8:12])
+ elif self.lookup_type in [IpFwTableLookupType.LOOKUP_DST_IP6, IpFwTableLookupType.LOOKUP_SRC_IP6]:
+ self.bm = socket.inet_ntop(socket.AF_INET6, data[8:24])
+ elif self.lookup_type in [IpFwTableLookupType.LOOKUP_DST_MAC, IpFwTableLookupType.LOOKUP_SRC_MAC]:
+ self.bm = ':'.join(f'{b:02x}' for b in struct.unpack('!6B', data[8:14]))
+ elif self.lookup_type in [IpFwTableLookupType.LOOKUP_DST_IP, IpFwTableLookupType.LOOKUP_SRC_IP]:
+ raise ValueError(f"maksing LOOKUP_SRC/DST_IP is invalid")
+ else:
+ (self.bm,) = struct.unpack("@I", data[8:12])
+ elif self.do_matching != 0:
+ match self.tvalue_type:
+ case IpFwTableValueType.TVALUE_NH4:
+ self.val = socket.inet_ntop(socket.AF_INET, data[8:12])
+ case IpFwTableValueType.TVALUE_NH6:
+ self.val = socket.inet_ntop(socket.AF_INET6, data[8:24])
+ case _:
+ (self.val,) = struct.unpack("@I", data[8:12])
+ else:
+ raise ValueError(f"insn_lookup is used but neither masking or matching are set")
+
+ return self
+
+ @classmethod
+ def compile_arg1(cls, value_type=None, value=None, lookup_type=None, bitmask=None):
+ arg1 = 0
+ if value_type is not None:
+ arg1 |= value_type.value << 8
+ arg1 |= 0x8000
+ if lookup_type is not None:
+ arg1 |= lookup_type.value
+ if bitmask is not None:
+ arg1 |= 0x0080
+ return arg1
+
+
+ def decompile_arg1(self):
+ self.do_masking = ((self.arg1 & 0x0080) != 0)
+ self.do_matching = ((self.arg1 & 0x8000) != 0)
+ self.lookup_int_type = self.arg1 & 0x007F
+ self.tvalue_int_type = (self.arg1 & 0x7F00) >> 8
+ self.lookup_type = enum_from_int(IpFwTableLookupType, self.lookup_int_type)
+ self.tvalue_type = enum_from_int(IpFwTableValueType, self.tvalue_int_type)
+
+ if self.do_matching != 0 and self.do_masking != 0:
+ raise ValueError(f"masking and matching can not be combined")
+ elif self.do_matching == 0 and self.do_masking == 0:
+ return
+ self.ilen = 8
+
+ def _validate_arg1(self, value, bitmask):
+ if self.do_matching == 0 and value is not None:
+ raise ValueError(f"matching bit is NOT set yet value is set to {value}")
+ elif self.do_matching != 0 and value is None:
+ raise ValueError("matching bit is set yet value is None")
+ elif self.do_matching != 0 and self.tvalue_type is None:
+ raise ValueError(f"matching bit is set but unknown table value ({self.tvalue_type}) is set")
+
+ if self.do_masking == 0 and bitmask is not None:
+ raise ValueError(f"masking bit is NOT set yet bitmask is set to {bitmask}")
+ elif self.do_masking != 0 and bitmask is None:
+ raise ValueError("masking bit is set yet bitmask is None")
+ elif self.do_masking != 0 and self.lookup_type is None:
+ raise ValueError(f"masking bit is set but unknown lookup type ({self.lookup_int_type}) is set")
+ elif self.do_masking != 0 and self.lookup_type == IpFwTableLookupType.LOOKUP_NONE:
+ raise ValueError(f"masking bit is set but LOOKUP_NONE lookup type is set")
+
+ def __bytes__(self):
+ ret = super().__bytes__()
+ if self.do_masking != 0:
+ if (isinstance(self.bm, str) and
+ self.lookup_type in [IpFwTableLookupType.LOOKUP_DST_IP4, IpFwTableLookupType.LOOKUP_SRC_IP4]):
+ ret += socket.inet_pton(socket.AF_INET, self.bm)
+ elif self.lookup_type in [IpFwTableLookupType.LOOKUP_DST_IP6, IpFwTableLookupType.LOOKUP_SRC_IP6]:
+ ret += socket.inet_pton(socket.AF_INET6, self.bm)
+ elif self.lookup_type in [IpFwTableLookupType.LOOKUP_SRC_MAC, IpFwTableLookupType.LOOKUP_SRC_MAC]:
+ ret += struct.pack('!6B10x', *(int(b, 16) for b in self.bm.split(':')))
+ else:
+ ret += struct.pack("@I12x", self.bm)
+ elif self.do_matching != 0:
+ match self.tvalue_type:
+ case IpFwTableValueType.TVALUE_NH4:
+ ret += socket.inet_pton(socket.AF_INET, self.val)
+ case IpFwTableValueType.TVALUE_NH6:
+ ret += socket.inet_pton(socket.AF_INET6, self.val)
+ case _:
+ ret += struct.pack("@I12x", self.val)
+ return ret
+
+ def _print_obj_value(self):
+ if self.do_matching != 0:
+ return " arg1={}, lookup_type={}, tvalue_type={}, kidx={}, value={}".format(
+ self.arg1, self.lookup_type, self.tvalue_type, self.kidx, self.val)
+ elif self.do_masking != 0:
+ return " arg1={}, lookup_type{}, tvalue_type={}, kidx={}, bitmask={}".format(
+ self.arg1, self.lookup_type, self.tvalue_type, self.kidx, self.bm)
+ else:
+ return " arg1={}, kidx={}".format(self.arg1, self.kidx)
class InsnReject(Insn):
@@ -510,7 +652,7 @@
insn_attrs = prepare_attrs_map(
[
- AttrDescr(IpFwOpcode.O_CHECK_STATE, InsnU32),
+ AttrDescr(IpFwOpcode.O_CHECK_STATE, InsnKidx),
AttrDescr(IpFwOpcode.O_ACCEPT, InsnEmpty),
AttrDescr(IpFwOpcode.O_COUNT, InsnEmpty),
@@ -530,10 +672,9 @@
AttrDescr(IpFwOpcode.O_SETFIB, Insn),
AttrDescr(IpFwOpcode.O_SETDSCP, Insn),
AttrDescr(IpFwOpcode.O_REASS, InsnEmpty),
- AttrDescr(IpFwOpcode.O_SETMARK, InsnU32),
-
- AttrDescr(IpFwOpcode.O_EXTERNAL_ACTION, InsnU32),
- AttrDescr(IpFwOpcode.O_EXTERNAL_INSTANCE, InsnU32),
+ AttrDescr(IpFwOpcode.O_SETMARK, Insn),
+ AttrDescr(IpFwOpcode.O_EXTERNAL_ACTION, InsnKidx),
+ AttrDescr(IpFwOpcode.O_EXTERNAL_INSTANCE, InsnKidx),
@@ -548,11 +689,12 @@
AttrDescr(IpFwOpcode.O_IP_DST, InsnIp),
AttrDescr(IpFwOpcode.O_IP6_DST, InsnIp6),
AttrDescr(IpFwOpcode.O_IP6_SRC, InsnIp6),
- AttrDescr(IpFwOpcode.O_IP_SRC_LOOKUP, InsnU32),
- AttrDescr(IpFwOpcode.O_IP_DST_LOOKUP, InsnU32),
+ AttrDescr(IpFwOpcode.O_IP_SRC_LOOKUP, InsnLookup),
+ AttrDescr(IpFwOpcode.O_IP_DST_LOOKUP, InsnLookup),
AttrDescr(IpFwOpcode.O_IP_SRCPORT, InsnPorts),
AttrDescr(IpFwOpcode.O_IP_DSTPORT, InsnPorts),
- AttrDescr(IpFwOpcode.O_PROBE_STATE, InsnU32),
- AttrDescr(IpFwOpcode.O_KEEP_STATE, InsnU32),
+ AttrDescr(IpFwOpcode.O_PROBE_STATE, InsnKidx),
+ AttrDescr(IpFwOpcode.O_KEEP_STATE, InsnKidx),
+ AttrDescr(IpFwOpcode.O_TABLE_LOOKUP, InsnLookup),
]
)
diff --git a/tests/atf_python/sys/netpfil/ipfw/ioctl.py b/tests/atf_python/sys/netpfil/ipfw/ioctl.py
--- a/tests/atf_python/sys/netpfil/ipfw/ioctl.py
+++ b/tests/atf_python/sys/netpfil/ipfw/ioctl.py
@@ -26,6 +26,7 @@
from atf_python.sys.netpfil.ipfw.insns import BaseInsn
from atf_python.sys.netpfil.ipfw.insns import insn_attrs
from atf_python.sys.netpfil.ipfw.ioctl_headers import IpFwTableLookupType
+from atf_python.sys.netpfil.ipfw.ioctl_headers import IpFwTableValueType
from atf_python.sys.netpfil.ipfw.ioctl_headers import IpFwTlvType
from atf_python.sys.netpfil.ipfw.ioctl_headers import Op3CmdType
from atf_python.sys.netpfil.ipfw.utils import align8
diff --git a/tests/atf_python/sys/netpfil/ipfw/ioctl_headers.py b/tests/atf_python/sys/netpfil/ipfw/ioctl_headers.py
--- a/tests/atf_python/sys/netpfil/ipfw/ioctl_headers.py
+++ b/tests/atf_python/sys/netpfil/ipfw/ioctl_headers.py
@@ -61,16 +61,37 @@
class IpFwTableLookupType(Enum):
- LOOKUP_DST_IP = 0
- LOOKUP_SRC_IP = 1
- LOOKUP_DST_PORT = 2
- LOOKUP_SRC_PORT = 3
- LOOKUP_UID = 4
- LOOKUP_JAIL = 5
- LOOKUP_DSCP = 6
- LOOKUP_DST_MAC = 7
- LOOKUP_SRC_MAC = 8
- LOOKUP_MARK = 9
+ LOOKUP_NONE = 0
+ LOOKUP_DST_IP = 1
+ LOOKUP_SRC_IP = 2
+ LOOKUP_DST_PORT = 3
+ LOOKUP_SRC_PORT = 4
+ LOOKUP_UID = 5
+ LOOKUP_JAIL = 6
+ LOOKUP_DSCP = 7
+ LOOKUP_DST_MAC = 8
+ LOOKUP_SRC_MAC = 9
+ LOOKUP_MARK = 10
+ LOOKUP_RULENUM = 11
+ LOOKUP_DST_IP4 = 12
+ LOOKUP_SRC_IP4 = 13
+ LOOKUP_DST_IP6 = 14
+ LOOKUP_SRC_IP6 = 15
+
+
+class IpFwTableValueType(Enum):
+ TVALUE_TAG = 0
+ TVALUE_PIPE = 1
+ TVALUE_DIVERT = 2
+ TVALUE_SKIPTO = 3
+ TVALUE_NETGRAPH = 4
+ TVALUE_FIB = 5
+ TVALUE_NAT = 6
+ TVALUE_NH4 = 8
+ TVALUE_DSCP = 9
+ TVALUE_LIMIT = 10
+ TVALUE_MARK = 11
+ TVALUE_NH6 = 12
class IpFwTlvType(Enum):

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 12, 10:42 PM (6 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26912344
Default Alt Text
D53694.id167039.diff (60 KB)

Event Timeline