Add to IPFW the ability to do ALTQ classification/tagging.
This commit is contained in:
parent
8ceb3dcb60
commit
974dfe3084
@ -4,5 +4,6 @@ PROG= ipfw
|
||||
SRCS= ipfw2.c
|
||||
WARNS?= 0
|
||||
MAN= ipfw.8
|
||||
CFLAGS+= -I${.CURDIR}/../../sys/contrib/pf
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -26,10 +26,10 @@
|
||||
.Op Ar number ...
|
||||
.Nm
|
||||
.Cm enable
|
||||
.Brq Cm firewall | one_pass | debug | verbose | dyn_keepalive
|
||||
.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
|
||||
.Nm
|
||||
.Cm disable
|
||||
.Brq Cm firewall | one_pass | debug | verbose | dyn_keepalive
|
||||
.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
|
||||
.Pp
|
||||
.Nm
|
||||
.Cm set Oo Cm disable Ar number ... Oc Op Cm enable Ar number ...
|
||||
@ -438,6 +438,7 @@ rules is the following:
|
||||
.br
|
||||
.Ar " " action
|
||||
.Op Cm log Op Cm logamount Ar number
|
||||
.Op Cm altq Ar queue
|
||||
.Ar body
|
||||
.Ed
|
||||
.Pp
|
||||
@ -469,6 +470,8 @@ window
|
||||
for ICMP packets
|
||||
.It User/group ID
|
||||
When the packet can be associated with a local socket.
|
||||
.It Divert status
|
||||
Whether a packet came from a divert socket (e.g. natd).
|
||||
.El
|
||||
.Pp
|
||||
Note that some of the above information, e.g.\& source MAC or IP addresses and
|
||||
@ -560,6 +563,41 @@ command.
|
||||
Note: logging is done after all other packet matching conditions
|
||||
have been successfully verified, and before performing the final
|
||||
action (accept, deny, etc.) on the packet.
|
||||
.It Cm altq Ar queue
|
||||
When a packet matches a rule with the
|
||||
.Cm altq
|
||||
keyword, the ALTQ identifier for the given
|
||||
.Ar queue
|
||||
(see
|
||||
.Xr pf.conf 5 )
|
||||
will be attached.
|
||||
Note that this ALTQ tag is only meaningful for packets going "out" of IPFW,
|
||||
and not being rejected or going to divert sockets.
|
||||
Note that if there is insufficient memory at the time the packet is
|
||||
processed, it will not be tagged, so it is wise to make your ALTQ
|
||||
"default" queue policy account for this.
|
||||
If multiple
|
||||
.Cm altq
|
||||
rules match a single packet, subsequent tags are ignored by ALTQ.
|
||||
.Pp
|
||||
You must run
|
||||
.Xr pfctl 8
|
||||
to set up the queues before IPFW will be able to look them up by name,
|
||||
and if the ALTQ disciplines are rearranged, the rules in containing the
|
||||
queue identifiers in the kernel will likely have gone stale and need
|
||||
to be reloaded.
|
||||
Stale queue identifiers will probably misclassify
|
||||
.Pp
|
||||
All system ALTQ processing can be turned on or off via
|
||||
.Nm
|
||||
.Cm enable Ar altq
|
||||
and
|
||||
.Nm
|
||||
.Cm disable Ar altq .
|
||||
The usage of
|
||||
.Em net.inet.ip.fw.one_pass
|
||||
is irrelevant to ALTQ traffic shaping, as the actual rule action is followed
|
||||
always after adding an ALTQ tag.
|
||||
.El
|
||||
.Ss RULE ACTIONS
|
||||
A rule can be associated with one of the following actions, which
|
||||
@ -2275,6 +2313,7 @@ the sleep terminates thus restoring the previous situation.
|
||||
.Xr ip 4 ,
|
||||
.Xr ipfirewall 4 ,
|
||||
.Xr protocols 5 ,
|
||||
.Xr pf.conf 5 ,
|
||||
.Xr services 5 ,
|
||||
.Xr init 8 ,
|
||||
.Xr kldload 8 ,
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
@ -43,8 +44,11 @@
|
||||
#include <timeconv.h> /* XXX do we need this ? */
|
||||
#include <unistd.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
@ -202,6 +206,9 @@ enum tokens {
|
||||
TOK_UNREACH,
|
||||
TOK_CHECKSTATE,
|
||||
|
||||
TOK_ALTQ,
|
||||
TOK_LOG,
|
||||
|
||||
TOK_UID,
|
||||
TOK_GID,
|
||||
TOK_JAIL,
|
||||
@ -302,6 +309,12 @@ struct _s_x rule_actions[] = {
|
||||
{ NULL, 0 } /* terminator */
|
||||
};
|
||||
|
||||
struct _s_x rule_action_params[] = {
|
||||
{ "altq", TOK_ALTQ },
|
||||
{ "log", TOK_LOG },
|
||||
{ NULL, 0 } /* terminator */
|
||||
};
|
||||
|
||||
struct _s_x rule_options[] = {
|
||||
{ "uid", TOK_UID },
|
||||
{ "gid", TOK_GID },
|
||||
@ -562,6 +575,107 @@ strtoport(char *s, char **end, int base, int proto)
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
/*
|
||||
* Map between current altq queue id numbers and names.
|
||||
*/
|
||||
static int altq_fetched = 0;
|
||||
static TAILQ_HEAD(, pf_altq) altq_entries =
|
||||
TAILQ_HEAD_INITIALIZER(altq_entries);
|
||||
|
||||
static void
|
||||
altq_set_enabled(int enabled)
|
||||
{
|
||||
int pffd;
|
||||
|
||||
pffd = open("/dev/pf", O_RDWR);
|
||||
if (pffd == -1)
|
||||
err(EX_UNAVAILABLE,
|
||||
"altq support opening pf(4) control device");
|
||||
if (enabled) {
|
||||
if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST)
|
||||
err(EX_UNAVAILABLE, "enabling altq");
|
||||
} else {
|
||||
if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT)
|
||||
err(EX_UNAVAILABLE, "disabling altq");
|
||||
}
|
||||
close(pffd);
|
||||
}
|
||||
|
||||
static void
|
||||
altq_fetch()
|
||||
{
|
||||
struct pfioc_altq pfioc;
|
||||
struct pf_altq *altq;
|
||||
int pffd, mnr;
|
||||
|
||||
if (altq_fetched)
|
||||
return;
|
||||
altq_fetched = 1;
|
||||
pffd = open("/dev/pf", O_RDONLY);
|
||||
if (pffd == -1) {
|
||||
warn("altq support opening pf(4) control device");
|
||||
return;
|
||||
}
|
||||
bzero(&pfioc, sizeof(pfioc));
|
||||
if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) {
|
||||
warn("altq support getting queue list");
|
||||
close(pffd);
|
||||
return;
|
||||
}
|
||||
mnr = pfioc.nr;
|
||||
for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) {
|
||||
if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) {
|
||||
if (errno == EBUSY)
|
||||
break;
|
||||
warn("altq support getting queue list");
|
||||
close(pffd);
|
||||
return;
|
||||
}
|
||||
if (pfioc.altq.qid == 0)
|
||||
continue;
|
||||
altq = malloc(sizeof(*altq));
|
||||
if (altq == NULL)
|
||||
err(EX_OSERR, "malloc");
|
||||
*altq = pfioc.altq;
|
||||
TAILQ_INSERT_TAIL(&altq_entries, altq, entries);
|
||||
}
|
||||
close(pffd);
|
||||
}
|
||||
|
||||
static u_int32_t
|
||||
altq_name_to_qid(const char *name)
|
||||
{
|
||||
struct pf_altq *altq;
|
||||
|
||||
altq_fetch();
|
||||
TAILQ_FOREACH(altq, &altq_entries, entries)
|
||||
if (strcmp(name, altq->qname) == 0)
|
||||
break;
|
||||
if (altq == NULL)
|
||||
errx(EX_DATAERR, "altq has no queue named `%s'", name);
|
||||
return altq->qid;
|
||||
}
|
||||
|
||||
static const char *
|
||||
altq_qid_to_name(u_int32_t qid)
|
||||
{
|
||||
struct pf_altq *altq;
|
||||
|
||||
altq_fetch();
|
||||
TAILQ_FOREACH(altq, &altq_entries, entries)
|
||||
if (qid == altq->qid)
|
||||
break;
|
||||
if (altq == NULL)
|
||||
return NULL;
|
||||
return altq->qname;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_altq_qid(u_int32_t *qid, const char *av)
|
||||
{
|
||||
*qid = altq_name_to_qid(av);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the body of the command with the list of port ranges.
|
||||
*/
|
||||
@ -908,6 +1022,7 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
int proto = 0; /* default */
|
||||
int flags = 0; /* prerequisites */
|
||||
ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
|
||||
ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */
|
||||
int or_block = 0; /* we are in an or block */
|
||||
uint32_t set_disable;
|
||||
|
||||
@ -1033,8 +1148,12 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
logptr = (ipfw_insn_log *)cmd;
|
||||
break;
|
||||
|
||||
case O_ALTQ: /* O_ALTQ is printed after O_LOG */
|
||||
altqptr = (ipfw_insn_altq *)cmd;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("** unrecognized action %d len %d",
|
||||
printf("** unrecognized action %d len %d ",
|
||||
cmd->opcode, cmd->len);
|
||||
}
|
||||
}
|
||||
@ -1044,6 +1163,15 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
else
|
||||
printf(" log");
|
||||
}
|
||||
if (altqptr) {
|
||||
const char *qname;
|
||||
|
||||
qname = altq_qid_to_name(altqptr->qid);
|
||||
if (qname == NULL)
|
||||
printf(" altq ?<%u>", altqptr->qid);
|
||||
else
|
||||
printf(" altq %s", qname);
|
||||
}
|
||||
|
||||
/*
|
||||
* then print the body.
|
||||
@ -1174,6 +1302,23 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
|
||||
printf(cmd->len & F_NOT ? " out" : " in");
|
||||
break;
|
||||
|
||||
case O_DIVERTED:
|
||||
switch (cmd->arg1) {
|
||||
case 3:
|
||||
printf(" diverted");
|
||||
break;
|
||||
case 1:
|
||||
printf(" diverted-loopback");
|
||||
break;
|
||||
case 2:
|
||||
printf(" diverted-output");
|
||||
break;
|
||||
default:
|
||||
printf(" diverted-?<%u>", cmd->arg1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case O_LAYER2:
|
||||
printf(" layer2");
|
||||
break;
|
||||
@ -1709,6 +1854,8 @@ sysctl_handler(int ac, char *av[], int which)
|
||||
} else if (strncmp(*av, "dyn_keepalive", strlen(*av)) == 0) {
|
||||
sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
|
||||
&which, sizeof(which));
|
||||
} else if (strncmp(*av, "altq", strlen(*av)) == 0) {
|
||||
altq_set_enabled(which);
|
||||
} else {
|
||||
warnx("unrecognize enable/disable keyword: %s\n", *av);
|
||||
}
|
||||
@ -1903,9 +2050,10 @@ help(void)
|
||||
"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
|
||||
"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
|
||||
"\n"
|
||||
"RULE-BODY: check-state [LOG] | ACTION [LOG] ADDR [OPTION_LIST]\n"
|
||||
"RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
|
||||
"ACTION: check-state | allow | count | deny | reject | skipto N |\n"
|
||||
" {divert|tee} PORT | forward ADDR | pipe N | queue N\n"
|
||||
"PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
|
||||
"ADDR: [ MAC dst src ether_type ] \n"
|
||||
" [ from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
|
||||
"IPADDR: [not] { any | me | ip/bits{x,y,z} | table(t[,v]) | IPLIST }\n"
|
||||
@ -2756,11 +2904,11 @@ add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode)
|
||||
* Rules are added into the 'rulebuf' and then copied in the correct order
|
||||
* into the actual rule.
|
||||
*
|
||||
* The syntax for a rule starts with the action, followed by an
|
||||
* optional log action, and the various match patterns.
|
||||
* The syntax for a rule starts with the action, followed by
|
||||
* optional action parameters, and the various match patterns.
|
||||
* In the assembled microcode, the first opcode must be an O_PROBE_STATE
|
||||
* (generated if the rule includes a keep-state option), then the
|
||||
* various match patterns, the "log" action, and the actual action.
|
||||
* various match patterns, log/altq actions, and the actual action.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
@ -2783,6 +2931,7 @@ add(int ac, char *av[])
|
||||
* various flags used to record that we entered some fields.
|
||||
*/
|
||||
ipfw_insn *have_state = NULL; /* check-state or keep-state */
|
||||
ipfw_insn *have_log = NULL, *have_altq = NULL;
|
||||
size_t len;
|
||||
|
||||
int i;
|
||||
@ -2945,32 +3094,63 @@ add(int ac, char *av[])
|
||||
action = next_cmd(action);
|
||||
|
||||
/*
|
||||
* [altq queuename] -- altq tag, optional
|
||||
* [log [logamount N]] -- log, optional
|
||||
*
|
||||
* If exists, it goes first in the cmdbuf, but then it is
|
||||
* If they exist, it go first in the cmdbuf, but then it is
|
||||
* skipped in the copy section to the end of the buffer.
|
||||
*/
|
||||
if (ac && !strncmp(*av, "log", strlen(*av))) {
|
||||
ipfw_insn_log *c = (ipfw_insn_log *)cmd;
|
||||
int l;
|
||||
while (ac != 0 && (i = match_token(rule_action_params, *av)) != -1) {
|
||||
ac--; av++;
|
||||
switch (i) {
|
||||
case TOK_LOG:
|
||||
{
|
||||
ipfw_insn_log *c = (ipfw_insn_log *)cmd;
|
||||
int l;
|
||||
|
||||
cmd->len = F_INSN_SIZE(ipfw_insn_log);
|
||||
cmd->opcode = O_LOG;
|
||||
av++; ac--;
|
||||
if (ac && !strncmp(*av, "logamount", strlen(*av))) {
|
||||
if (have_log)
|
||||
errx(EX_DATAERR,
|
||||
"log cannot be specified more than once");
|
||||
have_log = (ipfw_insn *)c;
|
||||
cmd->len = F_INSN_SIZE(ipfw_insn_log);
|
||||
cmd->opcode = O_LOG;
|
||||
if (ac && !strncmp(*av, "logamount", strlen(*av))) {
|
||||
ac--; av++;
|
||||
NEED1("logamount requires argument");
|
||||
l = atoi(*av);
|
||||
if (l < 0)
|
||||
errx(EX_DATAERR,
|
||||
"logamount must be positive");
|
||||
c->max_log = l;
|
||||
ac--; av++;
|
||||
} else {
|
||||
len = sizeof(c->max_log);
|
||||
if (sysctlbyname("net.inet.ip.fw.verbose_limit",
|
||||
&c->max_log, &len, NULL, 0) == -1)
|
||||
errx(1, "sysctlbyname(\"%s\")",
|
||||
"net.inet.ip.fw.verbose_limit");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_ALTQ:
|
||||
{
|
||||
ipfw_insn_altq *a = (ipfw_insn_altq *)cmd;
|
||||
|
||||
NEED1("missing altq queue name");
|
||||
if (have_altq)
|
||||
errx(EX_DATAERR,
|
||||
"altq cannot be specified more than once");
|
||||
have_altq = (ipfw_insn *)a;
|
||||
cmd->len = F_INSN_SIZE(ipfw_insn_altq);
|
||||
cmd->opcode = O_ALTQ;
|
||||
fill_altq_qid(&a->qid, *av);
|
||||
ac--; av++;
|
||||
NEED1("logamount requires argument");
|
||||
l = atoi(*av);
|
||||
if (l < 0)
|
||||
errx(EX_DATAERR, "logamount must be positive");
|
||||
c->max_log = l;
|
||||
ac--; av++;
|
||||
} else {
|
||||
len = sizeof(c->max_log);
|
||||
if (sysctlbyname("net.inet.ip.fw.verbose_limit",
|
||||
&c->max_log, &len, NULL, 0) == -1)
|
||||
errx(1, "sysctlbyname(\"%s\")",
|
||||
"net.inet.ip.fw.verbose_limit");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
cmd = next_cmd(cmd);
|
||||
}
|
||||
@ -3533,7 +3713,7 @@ add(int ac, char *av[])
|
||||
dst = next_cmd(dst);
|
||||
}
|
||||
/*
|
||||
* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT
|
||||
* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ
|
||||
*/
|
||||
for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
|
||||
i = F_LEN(src);
|
||||
@ -3542,6 +3722,7 @@ add(int ac, char *av[])
|
||||
case O_LOG:
|
||||
case O_KEEP_STATE:
|
||||
case O_LIMIT:
|
||||
case O_ALTQ:
|
||||
break;
|
||||
default:
|
||||
bcopy(src, dst, i * sizeof(uint32_t));
|
||||
@ -3563,12 +3744,16 @@ add(int ac, char *av[])
|
||||
rule->act_ofs = dst - rule->cmd;
|
||||
|
||||
/*
|
||||
* put back O_LOG if necessary
|
||||
* put back O_LOG, O_ALTQ if necessary
|
||||
*/
|
||||
src = (ipfw_insn *)cmdbuf;
|
||||
if (src->opcode == O_LOG) {
|
||||
i = F_LEN(src);
|
||||
bcopy(src, dst, i * sizeof(uint32_t));
|
||||
if (have_log) {
|
||||
i = F_LEN(have_log);
|
||||
bcopy(have_log, dst, i * sizeof(uint32_t));
|
||||
dst += i;
|
||||
}
|
||||
if (have_altq) {
|
||||
i = F_LEN(have_altq);
|
||||
bcopy(have_altq, dst, i * sizeof(uint32_t));
|
||||
dst += i;
|
||||
}
|
||||
/*
|
||||
|
@ -134,6 +134,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
|
||||
O_IP_DST_LOOKUP, /* arg1=table number, u32=value */
|
||||
O_ANTISPOOF, /* none */
|
||||
O_JAIL, /* u32 = id */
|
||||
O_ALTQ, /* u32 = altq classif. qid */
|
||||
|
||||
O_LAST_OPCODE /* not an opcode! */
|
||||
};
|
||||
@ -250,6 +251,14 @@ typedef struct _ipfw_insn_pipe {
|
||||
void *pipe_ptr; /* XXX */
|
||||
} ipfw_insn_pipe;
|
||||
|
||||
/*
|
||||
* This is used for storing an altq queue id number.
|
||||
*/
|
||||
typedef struct _ipfw_insn_altq {
|
||||
ipfw_insn o;
|
||||
u_int32_t qid;
|
||||
} ipfw_insn_altq;
|
||||
|
||||
/*
|
||||
* This is used for limit rules.
|
||||
*/
|
||||
@ -293,6 +302,7 @@ typedef struct _ipfw_insn_log {
|
||||
* first instruction (at r->cmd) MUST BE an O_PROBE_STATE
|
||||
* + if a rule has a "log" option, then the first action
|
||||
* (at ACTION_PTR(r)) MUST be O_LOG
|
||||
* + if a rule has an "altq" option, it comes after "log"
|
||||
*
|
||||
* 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
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include <netinet/tcpip.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#include <altq/if_altq.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
@ -553,6 +554,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ether_header *eh,
|
||||
if (l->log_left == 0)
|
||||
limit_reached = l->max_log;
|
||||
cmd += F_LEN(cmd); /* point to first action */
|
||||
if (cmd->opcode == O_ALTQ) {
|
||||
ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd;
|
||||
|
||||
snprintf(SNPARGS(action2, 0), "Altq %d",
|
||||
altq->qid);
|
||||
cmd += F_LEN(cmd);
|
||||
}
|
||||
if (cmd->opcode == O_PROB)
|
||||
cmd += F_LEN(cmd);
|
||||
|
||||
@ -1324,6 +1332,8 @@ lookup_next_rule(struct ip_fw *me)
|
||||
cmd = ACTION_PTR(me);
|
||||
if (cmd->opcode == O_LOG)
|
||||
cmd += F_LEN(cmd);
|
||||
if (cmd->opcode == O_ALTQ)
|
||||
cmd += F_LEN(cmd);
|
||||
if ( cmd->opcode == O_SKIPTO )
|
||||
for (rule = me->next; rule ; rule = rule->next)
|
||||
if (rule->rulenum >= cmd->arg1)
|
||||
@ -2212,6 +2222,32 @@ ipfw_chk(struct ip_fw_args *args)
|
||||
(TH_RST | TH_ACK | TH_SYN)) != TH_SYN);
|
||||
break;
|
||||
|
||||
case O_ALTQ: {
|
||||
struct altq_tag *at;
|
||||
ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd;
|
||||
|
||||
match = 1;
|
||||
mtag = m_tag_get(PACKET_TAG_PF_QID,
|
||||
sizeof(struct altq_tag),
|
||||
M_NOWAIT);
|
||||
if (mtag == NULL) {
|
||||
/*
|
||||
* Let the packet fall back to the
|
||||
* default ALTQ.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
at = (struct altq_tag *)(mtag+1);
|
||||
at->qid = altq->qid;
|
||||
if (hlen != 0)
|
||||
at->af = AF_INET;
|
||||
else
|
||||
at->af = AF_LINK;
|
||||
at->hdr = ip;
|
||||
m_tag_prepend(m, mtag);
|
||||
break;
|
||||
}
|
||||
|
||||
case O_LOG:
|
||||
if (fw_verbose)
|
||||
ipfw_log(f, hlen, args->eh, m, oif);
|
||||
@ -2275,6 +2311,9 @@ ipfw_chk(struct ip_fw_args *args)
|
||||
* or to the SKIPTO target ('goto again' after
|
||||
* having set f, cmd and l), respectively.
|
||||
*
|
||||
* O_LOG and O_ALTQ action parameters:
|
||||
* perform some action and set match = 1;
|
||||
*
|
||||
* O_LIMIT and O_KEEP_STATE: these opcodes are
|
||||
* not real 'actions', and are stored right
|
||||
* before the 'action' part of the rule.
|
||||
@ -2974,6 +3013,11 @@ check_ipfw_struct(struct ip_fw *rule, int size)
|
||||
goto bad_size;
|
||||
break;
|
||||
|
||||
case O_ALTQ:
|
||||
if (cmdlen != F_INSN_SIZE(ipfw_insn_altq))
|
||||
goto bad_size;
|
||||
break;
|
||||
|
||||
case O_PIPE:
|
||||
case O_QUEUE:
|
||||
if (cmdlen != F_INSN_SIZE(ipfw_insn_pipe))
|
||||
|
Loading…
Reference in New Issue
Block a user