Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F139424811
D53694.id167039.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
60 KB
Referenced Files
None
Subscribers
None
D53694.id167039.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D53694: [ipfw] Add support for masked ip-address lookups
Attached
Detach File
Event Timeline
Log In to Comment