Changeset View
Changeset View
Standalone View
Standalone View
sbin/ipfw/ipfw2.c
Context not available. | |||||
{ "jail", TOK_JAIL }, | { "jail", TOK_JAIL }, | ||||
{ "in", TOK_IN }, | { "in", TOK_IN }, | ||||
{ "limit", TOK_LIMIT }, | { "limit", TOK_LIMIT }, | ||||
{ "set-limit", TOK_SETLIMIT }, | |||||
{ "keep-state", TOK_KEEPSTATE }, | { "keep-state", TOK_KEEPSTATE }, | ||||
{ "record-state", TOK_RECORDSTATE }, | |||||
{ "bridged", TOK_LAYER2 }, | { "bridged", TOK_LAYER2 }, | ||||
{ "layer2", TOK_LAYER2 }, | { "layer2", TOK_LAYER2 }, | ||||
{ "out", TOK_OUT }, | { "out", TOK_OUT }, | ||||
Context not available. | |||||
{ "src-ip6", TOK_SRCIP6}, | { "src-ip6", TOK_SRCIP6}, | ||||
{ "lookup", TOK_LOOKUP}, | { "lookup", TOK_LOOKUP}, | ||||
{ "flow", TOK_FLOW}, | { "flow", TOK_FLOW}, | ||||
{ "defer-action", TOK_SKIPACTION }, | |||||
{ "defer-immediate-action", TOK_SKIPACTION }, | |||||
{ "//", TOK_COMMENT }, | { "//", TOK_COMMENT }, | ||||
{ "not", TOK_NOT }, /* pseudo option */ | { "not", TOK_NOT }, /* pseudo option */ | ||||
Context not available. | |||||
ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */ | ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */ | ||||
int or_block = 0; /* we are in an or block */ | int or_block = 0; /* we are in an or block */ | ||||
uint32_t uval; | uint32_t uval; | ||||
int have_probe_state = 0; | |||||
if ((fo->set_mask & (1 << rule->set)) == 0) { | if ((fo->set_mask & (1 << rule->set)) == 0) { | ||||
/* disabled mask */ | /* disabled mask */ | ||||
Context not available. | |||||
break; /* done already */ | break; /* done already */ | ||||
case O_PROBE_STATE: | case O_PROBE_STATE: | ||||
have_probe_state = 1; | |||||
break; /* no need to print anything here */ | break; /* no need to print anything here */ | ||||
case O_IP_SRC: | case O_IP_SRC: | ||||
Context not available. | |||||
break; | break; | ||||
case O_KEEP_STATE: | case O_KEEP_STATE: | ||||
bprintf(bp, " keep-state"); | if (have_probe_state) | ||||
bprintf(bp, " keep-state"); | |||||
else | |||||
bprintf(bp, " record-state"); | |||||
bprintf(bp, " %s", | bprintf(bp, " %s", | ||||
object_search_ctlv(fo->tstate, cmd->arg1, | object_search_ctlv(fo->tstate, cmd->arg1, | ||||
IPFW_TLV_STATE_NAME)); | IPFW_TLV_STATE_NAME)); | ||||
Context not available. | |||||
uint8_t x = c->limit_mask; | uint8_t x = c->limit_mask; | ||||
char const *comma = " "; | char const *comma = " "; | ||||
bprintf(bp, " limit"); | if (have_probe_state) | ||||
bprintf(bp, " limit"); | |||||
else | |||||
bprintf(bp, " set-limit"); | |||||
for (; p->x != 0 ; p++) | for (; p->x != 0 ; p++) | ||||
if ((x & p->x) == p->x) { | if ((x & p->x) == p->x) { | ||||
x &= ~p->x; | x &= ~p->x; | ||||
Context not available. | |||||
0, O_TAGGED); | 0, O_TAGGED); | ||||
break; | break; | ||||
case O_SKIP_ACTION: | |||||
bprintf(bp, " defer-immediate-action"); | |||||
break; | |||||
default: | default: | ||||
bprintf(bp, " [opcode %d len %d]", | bprintf(bp, " [opcode %d len %d]", | ||||
cmd->opcode, cmd->len); | cmd->opcode, cmd->len); | ||||
Context not available. | |||||
/* | /* | ||||
* 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; /* any state-related option */ | ||||
int have_rstate = 0; | |||||
ipfw_insn *have_log = NULL, *have_altq = NULL, *have_tag = NULL; | ipfw_insn *have_log = NULL, *have_altq = NULL, *have_tag = NULL; | ||||
ipfw_insn *have_skipcmd = NULL; | |||||
size_t len; | size_t len; | ||||
int i; | int i; | ||||
Context not available. | |||||
av++; | av++; | ||||
break; | break; | ||||
case TOK_KEEPSTATE: { | case TOK_KEEPSTATE: | ||||
case TOK_RECORDSTATE: { | |||||
uint16_t uidx; | uint16_t uidx; | ||||
if (open_par) | if (open_par) | ||||
errx(EX_USAGE, "keep-state cannot be part " | errx(EX_USAGE, "keep-state or record-state cannot be part " | ||||
"of an or block"); | "of an or block"); | ||||
if (have_state) | if (have_state) | ||||
errx(EX_USAGE, "only one of keep-state " | errx(EX_USAGE, "only one of keep-state, record-state, " | ||||
"and limit is allowed"); | " limit and set-limit is allowed"); | ||||
if (*av == NULL || | if (*av == NULL || | ||||
match_token(rule_options, *av) != -1) { | match_token(rule_options, *av) != -1) { | ||||
if (*av != NULL) | if (*av != NULL) | ||||
Context not available. | |||||
av++; | av++; | ||||
} | } | ||||
have_state = cmd; | have_state = cmd; | ||||
have_rstate = i == TOK_RECORDSTATE; | |||||
fill_cmd(cmd, O_KEEP_STATE, 0, uidx); | fill_cmd(cmd, O_KEEP_STATE, 0, uidx); | ||||
break; | break; | ||||
} | } | ||||
case TOK_LIMIT: { | case TOK_LIMIT: | ||||
case TOK_SETLIMIT: { | |||||
ipfw_insn_limit *c = (ipfw_insn_limit *)cmd; | ipfw_insn_limit *c = (ipfw_insn_limit *)cmd; | ||||
int val; | int val; | ||||
if (open_par) | if (open_par) | ||||
errx(EX_USAGE, | errx(EX_USAGE, | ||||
"limit cannot be part of an or block"); | "limit or set-limit cannot be part of an or block"); | ||||
if (have_state) | if (have_state) | ||||
errx(EX_USAGE, "only one of keep-state and " | errx(EX_USAGE, "only one of keep-state, record-state, " | ||||
"limit is allowed"); | " limit and set-limit is allowed"); | ||||
have_state = cmd; | have_state = cmd; | ||||
have_rstate = i == TOK_SETLIMIT; | |||||
cmd->len = F_INSN_SIZE(ipfw_insn_limit); | cmd->len = F_INSN_SIZE(ipfw_insn_limit); | ||||
CHECK_CMDLEN; | CHECK_CMDLEN; | ||||
Context not available. | |||||
av++; | av++; | ||||
} | } | ||||
break; | break; | ||||
case TOK_FLOW: | case TOK_FLOW: | ||||
NEED1("missing table name"); | NEED1("missing table name"); | ||||
if (strncmp(*av, "table(", 6) != 0) | if (strncmp(*av, "table(", 6) != 0) | ||||
Context not available. | |||||
av++; | av++; | ||||
break; | break; | ||||
case TOK_SKIPACTION: | |||||
if (have_skipcmd) | |||||
errx(EX_USAGE, "only one defer-action " | |||||
"is allowed"); | |||||
have_skipcmd = cmd; | |||||
fill_cmd(cmd, O_SKIP_ACTION, 0, 0); | |||||
break; | |||||
default: | default: | ||||
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s); | errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s); | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
done: | done: | ||||
if (!have_state && have_skipcmd) | |||||
warnx("Rule contains \"defer-immediate-action\" " | |||||
"and doesn't contain any state-related options."); | |||||
/* | /* | ||||
* Now copy stuff into the rule. | * Now copy stuff into the rule. | ||||
* If we have a keep-state option, the first instruction | * If we have a keep-state option, the first instruction | ||||
Context not available. | |||||
/* | /* | ||||
* generate O_PROBE_STATE if necessary | * generate O_PROBE_STATE if necessary | ||||
*/ | */ | ||||
if (have_state && have_state->opcode != O_CHECK_STATE) { | if (have_state && have_state->opcode != O_CHECK_STATE && !have_rstate) { | ||||
fill_cmd(dst, O_PROBE_STATE, 0, have_state->arg1); | fill_cmd(dst, O_PROBE_STATE, 0, have_state->arg1); | ||||
dst = next_cmd(dst, &rblen); | dst = next_cmd(dst, &rblen); | ||||
} | } | ||||
/* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ, O_TAG */ | /* | ||||
* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ, O_TAG, | |||||
* O_SKIP_ACTION | |||||
*/ | |||||
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); | ||||
CHECK_RBUFLEN(i); | CHECK_RBUFLEN(i); | ||||
Context not available. | |||||
case O_LIMIT: | case O_LIMIT: | ||||
case O_ALTQ: | case O_ALTQ: | ||||
case O_TAG: | case O_TAG: | ||||
case O_SKIP_ACTION: | |||||
break; | break; | ||||
default: | default: | ||||
bcopy(src, dst, i * sizeof(uint32_t)); | bcopy(src, dst, i * sizeof(uint32_t)); | ||||
Context not available. | |||||
bcopy(have_state, dst, i * sizeof(uint32_t)); | bcopy(have_state, dst, i * sizeof(uint32_t)); | ||||
dst += i; | dst += i; | ||||
} | } | ||||
/* | /* | ||||
* put back the have_skipcmd command as very last opcode | |||||
*/ | |||||
if (have_skipcmd) { | |||||
i = F_LEN(have_skipcmd); | |||||
CHECK_RBUFLEN(i); | |||||
bcopy(have_skipcmd, dst, i * sizeof(uint32_t)); | |||||
dst += i; | |||||
} | |||||
/* | |||||
* start action section | * start action section | ||||
*/ | */ | ||||
rule->act_ofs = dst - rule->cmd; | rule->act_ofs = dst - rule->cmd; | ||||
Context not available. | |||||
free(olh); | free(olh); | ||||
} | } | ||||
Context not available. |