Implement internal (i.e. inside kernel) packet tagging using mbuf_tags(9).
Since tags are kept while packet resides in kernelspace, it's possible to use other kernel facilities (like netgraph nodes) for altering those tags. Submitted by: Andrey Elsukov <bu7cher at yandex dot ru> Submitted by: Vadim Goncharov <vadimnuclight at tpu dot ru> Approved by: glebius (mentor) Idea from: OpenBSD PF MFC after: 1 month
This commit is contained in:
parent
16a67f532d
commit
6a7d5cb645
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=158879
@ -1,7 +1,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd May 12, 2006
|
.Dd May 24, 2006
|
||||||
.Dt IPFW 8
|
.Dt IPFW 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -420,6 +420,10 @@ rules is the following:
|
|||||||
.Ar action
|
.Ar action
|
||||||
.Op Cm log Op Cm logamount Ar number
|
.Op Cm log Op Cm logamount Ar number
|
||||||
.Op Cm altq Ar queue
|
.Op Cm altq Ar queue
|
||||||
|
.Oo
|
||||||
|
.Bro Cm tag | untag
|
||||||
|
.Brc Ar number
|
||||||
|
.Oc
|
||||||
.Ar body
|
.Ar body
|
||||||
.Ek
|
.Ek
|
||||||
.Ed
|
.Ed
|
||||||
@ -552,6 +556,53 @@ command.
|
|||||||
Note: logging is done after all other packet matching conditions
|
Note: logging is done after all other packet matching conditions
|
||||||
have been successfully verified, and before performing the final
|
have been successfully verified, and before performing the final
|
||||||
action (accept, deny, etc.) on the packet.
|
action (accept, deny, etc.) on the packet.
|
||||||
|
.It Cm tag Ar number
|
||||||
|
When a packet matches a rule with the
|
||||||
|
.Cm tag
|
||||||
|
keyword, the numeric tag for the given
|
||||||
|
.Ar number
|
||||||
|
in the range 0..65535 will be attached to the packet.
|
||||||
|
The tag acts as an internal marker (it is not sent out over
|
||||||
|
the wire) that can be used to identify these packets later on.
|
||||||
|
This can be used, for example, to provide trust between interfaces
|
||||||
|
and to start doing policy-based filtering.
|
||||||
|
A packet can have mutiple tags at the same time.
|
||||||
|
Tags are "sticky", meaning once a tag is applied to a packet by a
|
||||||
|
matching rule it exists until explicit removal.
|
||||||
|
Tags are kept with the packet everywhere within the kernel, but are
|
||||||
|
lost when packet leaves the kernel, for example, on transmitting
|
||||||
|
packet out to the network or sending packet to a
|
||||||
|
.Xr divert 4
|
||||||
|
socket.
|
||||||
|
.Pp
|
||||||
|
To check for previously applied tags, use the
|
||||||
|
.Cm tagged
|
||||||
|
rule option. To delete previously applied tag, use the
|
||||||
|
.Cm untag
|
||||||
|
keyword.
|
||||||
|
.Pp
|
||||||
|
Note: since tags are kept with the packet everywhere in kernelspace,
|
||||||
|
they can be set and unset anywhere in kernel network subsystem
|
||||||
|
(using
|
||||||
|
.Xr mbuf_tags 9
|
||||||
|
facility), not only by means of
|
||||||
|
.Xr ipfw 4
|
||||||
|
.Cm tag
|
||||||
|
and
|
||||||
|
.Cm untag
|
||||||
|
keywords.
|
||||||
|
For example, there can be a specialized
|
||||||
|
.Xr netgraph 4
|
||||||
|
node doing traffic analyzing and tagging for later inspecting
|
||||||
|
in firewall.
|
||||||
|
.It Cm untag Ar number
|
||||||
|
When a packet matches a rule with the
|
||||||
|
.Cm untag
|
||||||
|
keyword, the tag with the number
|
||||||
|
.Ar number
|
||||||
|
is searched among the tags attached to this packet and,
|
||||||
|
if found, removed from it.
|
||||||
|
Other tags bound to packet, if present, are left untouched.
|
||||||
.It Cm altq Ar queue
|
.It Cm altq Ar queue
|
||||||
When a packet matches a rule with the
|
When a packet matches a rule with the
|
||||||
.Cm altq
|
.Cm altq
|
||||||
@ -1362,6 +1413,15 @@ specified as an argument.
|
|||||||
.It Cm src-port Ar ports
|
.It Cm src-port Ar ports
|
||||||
Matches IP packets whose source port is one of the port(s)
|
Matches IP packets whose source port is one of the port(s)
|
||||||
specified as argument.
|
specified as argument.
|
||||||
|
.It Cm tagged Ar tag-list
|
||||||
|
Matches packets whose tags are included in
|
||||||
|
.Ar tag-list ,
|
||||||
|
which is either a single value or a list of values or ranges
|
||||||
|
specified in the same way as
|
||||||
|
.Ar ports .
|
||||||
|
Tags can be applied to the packet using
|
||||||
|
.Cm tag
|
||||||
|
rule action parameter (see it's description for details on tags).
|
||||||
.It Cm tcpack Ar ack
|
.It Cm tcpack Ar ack
|
||||||
TCP packets only.
|
TCP packets only.
|
||||||
Match if the TCP header acknowledgment number field is set to
|
Match if the TCP header acknowledgment number field is set to
|
||||||
|
@ -82,6 +82,15 @@ int
|
|||||||
*/
|
*/
|
||||||
#define NEED1(msg) {if (!ac) errx(EX_USAGE, msg);}
|
#define NEED1(msg) {if (!ac) errx(EX_USAGE, msg);}
|
||||||
|
|
||||||
|
#define NOT_NUMBER(str, msg) do { \
|
||||||
|
char *c; \
|
||||||
|
for (c = str; *c != '\0'; c++) { \
|
||||||
|
if (isdigit(*c)) \
|
||||||
|
continue; \
|
||||||
|
errx(EX_DATAERR, msg); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _s_x is a structure that stores a string <-> token pairs, used in
|
* _s_x is a structure that stores a string <-> token pairs, used in
|
||||||
* various places in the parser. Entries are stored in arrays,
|
* various places in the parser. Entries are stored in arrays,
|
||||||
@ -212,7 +221,10 @@ enum tokens {
|
|||||||
|
|
||||||
TOK_ALTQ,
|
TOK_ALTQ,
|
||||||
TOK_LOG,
|
TOK_LOG,
|
||||||
|
TOK_TAG,
|
||||||
|
TOK_UNTAG,
|
||||||
|
|
||||||
|
TOK_TAGGED,
|
||||||
TOK_UID,
|
TOK_UID,
|
||||||
TOK_GID,
|
TOK_GID,
|
||||||
TOK_JAIL,
|
TOK_JAIL,
|
||||||
@ -340,10 +352,13 @@ struct _s_x rule_actions[] = {
|
|||||||
struct _s_x rule_action_params[] = {
|
struct _s_x rule_action_params[] = {
|
||||||
{ "altq", TOK_ALTQ },
|
{ "altq", TOK_ALTQ },
|
||||||
{ "log", TOK_LOG },
|
{ "log", TOK_LOG },
|
||||||
|
{ "tag", TOK_TAG },
|
||||||
|
{ "untag", TOK_UNTAG },
|
||||||
{ NULL, 0 } /* terminator */
|
{ NULL, 0 } /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _s_x rule_options[] = {
|
struct _s_x rule_options[] = {
|
||||||
|
{ "tagged", TOK_TAGGED },
|
||||||
{ "uid", TOK_UID },
|
{ "uid", TOK_UID },
|
||||||
{ "gid", TOK_GID },
|
{ "gid", TOK_GID },
|
||||||
{ "jail", TOK_JAIL },
|
{ "jail", TOK_JAIL },
|
||||||
@ -572,6 +587,7 @@ struct _s_x _port_name[] = {
|
|||||||
{"ipttl", O_IPTTL},
|
{"ipttl", O_IPTTL},
|
||||||
{"mac-type", O_MAC_TYPE},
|
{"mac-type", O_MAC_TYPE},
|
||||||
{"tcpdatalen", O_TCPDATALEN},
|
{"tcpdatalen", O_TCPDATALEN},
|
||||||
|
{"tagged", O_TAGGED},
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1358,7 +1374,7 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
{
|
{
|
||||||
static int twidth = 0;
|
static int twidth = 0;
|
||||||
int l;
|
int l;
|
||||||
ipfw_insn *cmd;
|
ipfw_insn *cmd, *tagptr = NULL;
|
||||||
char *comment = NULL; /* ptr to comment if we have one */
|
char *comment = NULL; /* ptr to comment if we have one */
|
||||||
int proto = 0; /* default */
|
int proto = 0; /* default */
|
||||||
int flags = 0; /* prerequisites */
|
int flags = 0; /* prerequisites */
|
||||||
@ -1500,6 +1516,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
altqptr = (ipfw_insn_altq *)cmd;
|
altqptr = (ipfw_insn_altq *)cmd;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case O_TAG:
|
||||||
|
tagptr = cmd;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("** unrecognized action %d len %d ",
|
printf("** unrecognized action %d len %d ",
|
||||||
cmd->opcode, cmd->len);
|
cmd->opcode, cmd->len);
|
||||||
@ -1520,6 +1540,12 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
else
|
else
|
||||||
printf(" altq %s", qname);
|
printf(" altq %s", qname);
|
||||||
}
|
}
|
||||||
|
if (tagptr) {
|
||||||
|
if (tagptr->len & F_NOT)
|
||||||
|
printf(" untag %hu", tagptr->arg1);
|
||||||
|
else
|
||||||
|
printf(" tag %hu", tagptr->arg1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* then print the body.
|
* then print the body.
|
||||||
@ -1906,6 +1932,14 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
|||||||
print_ext6hdr( (ipfw_insn *) cmd );
|
print_ext6hdr( (ipfw_insn *) cmd );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case O_TAGGED:
|
||||||
|
if (F_LEN(cmd) == 1)
|
||||||
|
printf(" tagged %hu", cmd->arg1 );
|
||||||
|
else
|
||||||
|
print_newports((ipfw_insn_u16 *)cmd, 0,
|
||||||
|
O_TAGGED);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf(" [opcode %d len %d]",
|
printf(" [opcode %d len %d]",
|
||||||
cmd->opcode, cmd->len);
|
cmd->opcode, cmd->len);
|
||||||
@ -3775,7 +3809,7 @@ add(int ac, char *av[])
|
|||||||
* various flags used to record that we entered some fields.
|
* various flags used to record that we entered some fields.
|
||||||
*/
|
*/
|
||||||
ipfw_insn *have_state = NULL; /* check-state or keep-state */
|
ipfw_insn *have_state = NULL; /* check-state or keep-state */
|
||||||
ipfw_insn *have_log = NULL, *have_altq = NULL;
|
ipfw_insn *have_log = NULL, *have_altq = NULL, *have_tag = NULL;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
@ -4016,6 +4050,20 @@ add(int ac, char *av[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOK_TAG:
|
||||||
|
case TOK_UNTAG:
|
||||||
|
{
|
||||||
|
if (have_tag)
|
||||||
|
errx(EX_USAGE, "tag and untag cannot be specified more than once");
|
||||||
|
NEED1("missing tag number");
|
||||||
|
NOT_NUMBER(*av, "invalid tag number");
|
||||||
|
have_tag = cmd;
|
||||||
|
fill_cmd(cmd, O_TAG, (i == TOK_TAG) ? 0: F_NOT,
|
||||||
|
strtoul(*av, NULL, 0));
|
||||||
|
ac--; av++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -4605,6 +4653,19 @@ add(int ac, char *av[])
|
|||||||
ac = 0;
|
ac = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOK_TAGGED:
|
||||||
|
NEED1("missing tag number");
|
||||||
|
if (strpbrk(*av, "-,")) {
|
||||||
|
if (!add_ports(cmd, *av, 0, O_TAGGED))
|
||||||
|
errx(EX_DATAERR, "invalid tag %s", *av);
|
||||||
|
} else {
|
||||||
|
NOT_NUMBER(*av, "invalid tag number");
|
||||||
|
fill_cmd(cmd, O_TAGGED, 0,
|
||||||
|
strtoul(*av, NULL, 0));
|
||||||
|
}
|
||||||
|
ac--; av++;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
|
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
|
||||||
}
|
}
|
||||||
@ -4641,9 +4702,8 @@ add(int ac, char *av[])
|
|||||||
fill_cmd(dst, O_PROBE_STATE, 0, 0);
|
fill_cmd(dst, O_PROBE_STATE, 0, 0);
|
||||||
dst = next_cmd(dst);
|
dst = next_cmd(dst);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ
|
/* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ, O_TAG */
|
||||||
*/
|
|
||||||
for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
|
for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
|
||||||
i = F_LEN(src);
|
i = F_LEN(src);
|
||||||
|
|
||||||
@ -4652,6 +4712,7 @@ add(int ac, char *av[])
|
|||||||
case O_KEEP_STATE:
|
case O_KEEP_STATE:
|
||||||
case O_LIMIT:
|
case O_LIMIT:
|
||||||
case O_ALTQ:
|
case O_ALTQ:
|
||||||
|
case O_TAG:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bcopy(src, dst, i * sizeof(uint32_t));
|
bcopy(src, dst, i * sizeof(uint32_t));
|
||||||
@ -4672,9 +4733,7 @@ add(int ac, char *av[])
|
|||||||
*/
|
*/
|
||||||
rule->act_ofs = dst - rule->cmd;
|
rule->act_ofs = dst - rule->cmd;
|
||||||
|
|
||||||
/*
|
/* put back O_LOG, O_ALTQ, O_TAG if necessary */
|
||||||
* put back O_LOG, O_ALTQ if necessary
|
|
||||||
*/
|
|
||||||
if (have_log) {
|
if (have_log) {
|
||||||
i = F_LEN(have_log);
|
i = F_LEN(have_log);
|
||||||
bcopy(have_log, dst, i * sizeof(uint32_t));
|
bcopy(have_log, dst, i * sizeof(uint32_t));
|
||||||
@ -4685,6 +4744,11 @@ add(int ac, char *av[])
|
|||||||
bcopy(have_altq, dst, i * sizeof(uint32_t));
|
bcopy(have_altq, dst, i * sizeof(uint32_t));
|
||||||
dst += i;
|
dst += i;
|
||||||
}
|
}
|
||||||
|
if (have_tag) {
|
||||||
|
i = F_LEN(have_tag);
|
||||||
|
bcopy(have_tag, dst, i * sizeof(uint32_t));
|
||||||
|
dst += i;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* copy all other actions
|
* copy all other actions
|
||||||
*/
|
*/
|
||||||
|
@ -157,6 +157,9 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
|
|||||||
|
|
||||||
O_UNREACH6, /* arg1=icmpv6 code arg (deny) */
|
O_UNREACH6, /* arg1=icmpv6 code arg (deny) */
|
||||||
|
|
||||||
|
O_TAG, /* arg1=tag number */
|
||||||
|
O_TAGGED, /* arg1=tag number */
|
||||||
|
|
||||||
O_LAST_OPCODE /* not an opcode! */
|
O_LAST_OPCODE /* not an opcode! */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -215,6 +218,8 @@ typedef struct _ipfw_insn { /* template for instructions */
|
|||||||
*/
|
*/
|
||||||
#define F_INSN_SIZE(t) ((sizeof (t))/sizeof(u_int32_t))
|
#define F_INSN_SIZE(t) ((sizeof (t))/sizeof(u_int32_t))
|
||||||
|
|
||||||
|
#define MTAG_IPFW 1148380143 /* IPFW-tagged cookie */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used to store an array of 16-bit entries (ports etc.)
|
* This is used to store an array of 16-bit entries (ports etc.)
|
||||||
*/
|
*/
|
||||||
@ -346,6 +351,7 @@ typedef struct _ipfw_insn_icmp6 {
|
|||||||
* + if a rule has a "log" option, then the first action
|
* + if a rule has a "log" option, then the first action
|
||||||
* (at ACTION_PTR(r)) MUST be O_LOG
|
* (at ACTION_PTR(r)) MUST be O_LOG
|
||||||
* + if a rule has an "altq" option, it comes after "log"
|
* + if a rule has an "altq" option, it comes after "log"
|
||||||
|
* + if a rule has an O_TAG option, it comes after "log" and "altq"
|
||||||
*
|
*
|
||||||
* NOTE: we use a simple linked list of rules because we never need
|
* NOTE: we use a simple linked list of rules because we never need
|
||||||
* to delete a rule without scanning the list. We do not use
|
* to delete a rule without scanning the list. We do not use
|
||||||
|
@ -781,6 +781,9 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
|
|||||||
if (cmd->opcode == O_PROB)
|
if (cmd->opcode == O_PROB)
|
||||||
cmd += F_LEN(cmd);
|
cmd += F_LEN(cmd);
|
||||||
|
|
||||||
|
if (cmd->opcode == O_TAG)
|
||||||
|
cmd += F_LEN(cmd);
|
||||||
|
|
||||||
action = action2;
|
action = action2;
|
||||||
switch (cmd->opcode) {
|
switch (cmd->opcode) {
|
||||||
case O_DENY:
|
case O_DENY:
|
||||||
@ -1660,6 +1663,8 @@ lookup_next_rule(struct ip_fw *me)
|
|||||||
cmd += F_LEN(cmd);
|
cmd += F_LEN(cmd);
|
||||||
if (cmd->opcode == O_ALTQ)
|
if (cmd->opcode == O_ALTQ)
|
||||||
cmd += F_LEN(cmd);
|
cmd += F_LEN(cmd);
|
||||||
|
if (cmd->opcode == O_TAG)
|
||||||
|
cmd += F_LEN(cmd);
|
||||||
if ( cmd->opcode == O_SKIPTO )
|
if ( cmd->opcode == O_SKIPTO )
|
||||||
for (rule = me->next; rule ; rule = rule->next)
|
for (rule = me->next; rule ; rule = rule->next)
|
||||||
if (rule->rulenum >= cmd->arg1)
|
if (rule->rulenum >= cmd->arg1)
|
||||||
@ -2886,6 +2891,55 @@ do { \
|
|||||||
match = is_ipv4;
|
match = is_ipv4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case O_TAG:
|
||||||
|
/* Packet is already tagged with this tag? */
|
||||||
|
mtag = m_tag_locate(m, MTAG_IPFW,
|
||||||
|
((ipfw_insn *) cmd)->arg1, NULL);
|
||||||
|
/* We have `untag' action when F_NOT flag is
|
||||||
|
* present. And we must remove this mtag from
|
||||||
|
* mbuf and reset `match' to zero (`match' will
|
||||||
|
* be inversed later).
|
||||||
|
* Otherwise we should allocate new mtag and
|
||||||
|
* push it into mbuf.
|
||||||
|
*/
|
||||||
|
if (cmd->len & F_NOT) { /* `untag' action */
|
||||||
|
if (mtag != NULL)
|
||||||
|
m_tag_delete(m, mtag);
|
||||||
|
} else if (mtag == NULL) {
|
||||||
|
mtag = m_tag_alloc(MTAG_IPFW,
|
||||||
|
((ipfw_insn *) cmd)->arg1, 0, M_NOWAIT);
|
||||||
|
if (mtag != NULL)
|
||||||
|
m_tag_prepend(m, mtag);
|
||||||
|
}
|
||||||
|
match = (cmd->len & F_NOT) ? 0: 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case O_TAGGED:
|
||||||
|
if (cmdlen == 1) {
|
||||||
|
match = (m_tag_locate(m, MTAG_IPFW,
|
||||||
|
((ipfw_insn *) cmd)->arg1, NULL) != NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have ranges */
|
||||||
|
for (mtag = m_tag_first(m);
|
||||||
|
mtag != NULL && !match;
|
||||||
|
mtag = m_tag_next(m, mtag)) {
|
||||||
|
uint16_t *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (mtag->m_tag_cookie != MTAG_IPFW)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p = ((ipfw_insn_u16 *)cmd)->ports;
|
||||||
|
i = cmdlen - 1;
|
||||||
|
for(; !match && i > 0; i--, p += 2)
|
||||||
|
match =
|
||||||
|
mtag->m_tag_id >= p[0] &&
|
||||||
|
mtag->m_tag_id <= p[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The second set of opcodes represents 'actions',
|
* The second set of opcodes represents 'actions',
|
||||||
* i.e. the terminal part of a rule once the packet
|
* i.e. the terminal part of a rule once the packet
|
||||||
@ -2905,7 +2959,7 @@ do { \
|
|||||||
* or to the SKIPTO target ('goto again' after
|
* or to the SKIPTO target ('goto again' after
|
||||||
* having set f, cmd and l), respectively.
|
* having set f, cmd and l), respectively.
|
||||||
*
|
*
|
||||||
* O_LOG and O_ALTQ action parameters:
|
* O_TAG, O_LOG and O_ALTQ action parameters:
|
||||||
* perform some action and set match = 1;
|
* perform some action and set match = 1;
|
||||||
*
|
*
|
||||||
* O_LIMIT and O_KEEP_STATE: these opcodes are
|
* O_LIMIT and O_KEEP_STATE: these opcodes are
|
||||||
@ -3528,6 +3582,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
|||||||
case O_IP6:
|
case O_IP6:
|
||||||
#endif
|
#endif
|
||||||
case O_IP4:
|
case O_IP4:
|
||||||
|
case O_TAG:
|
||||||
if (cmdlen != F_INSN_SIZE(ipfw_insn))
|
if (cmdlen != F_INSN_SIZE(ipfw_insn))
|
||||||
goto bad_size;
|
goto bad_size;
|
||||||
break;
|
break;
|
||||||
@ -3600,6 +3655,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
|||||||
case O_IPTTL:
|
case O_IPTTL:
|
||||||
case O_IPLEN:
|
case O_IPLEN:
|
||||||
case O_TCPDATALEN:
|
case O_TCPDATALEN:
|
||||||
|
case O_TAGGED:
|
||||||
if (cmdlen < 1 || cmdlen > 31)
|
if (cmdlen < 1 || cmdlen > 31)
|
||||||
goto bad_size;
|
goto bad_size;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user