Changeset View
Changeset View
Standalone View
Standalone View
head/sbin/ipfw/ipfw2.c
Show First 20 Lines • Show All 1,398 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
show_static_rule(struct cmdline_opts *co, struct format_opts *fo, | show_static_rule(struct cmdline_opts *co, struct format_opts *fo, | ||||
struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr) | struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr) | ||||
{ | { | ||||
static int twidth = 0; | static int twidth = 0; | ||||
int l; | int l; | ||||
ipfw_insn *cmd, *has_eaction = NULL, *tagptr = NULL; | ipfw_insn *cmd, *has_eaction = NULL, *tagptr = NULL; | ||||
const char *comment = NULL; /* ptr to comment if we have one */ | const char *comment = NULL; /* ptr to comment if we have one */ | ||||
const char *ename; | |||||
int proto = 0; /* default */ | int proto = 0; /* default */ | ||||
int flags = 0; /* prerequisites */ | int flags = 0; /* prerequisites */ | ||||
ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */ | ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */ | ||||
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; | ||||
if ((fo->set_mask & (1 << rule->set)) == 0) { | if ((fo->set_mask & (1 << rule->set)) == 0) { | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | show_static_rule(struct cmdline_opts *co, struct format_opts *fo, | ||||
/* | /* | ||||
* first print actions | * first print actions | ||||
*/ | */ | ||||
for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule); | for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule); | ||||
l > 0 ; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { | l > 0 ; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { | ||||
switch(cmd->opcode) { | switch(cmd->opcode) { | ||||
case O_CHECK_STATE: | case O_CHECK_STATE: | ||||
bprintf(bp, "check-state"); | bprintf(bp, "check-state"); | ||||
if (cmd->arg1 != 0) | |||||
ename = object_search_ctlv(fo->tstate, | |||||
cmd->arg1, IPFW_TLV_STATE_NAME); | |||||
else | |||||
ename = NULL; | |||||
bprintf(bp, " %s", ename ? ename: "any"); | |||||
/* avoid printing anything else */ | /* avoid printing anything else */ | ||||
flags = HAVE_PROTO | HAVE_SRCIP | | flags = HAVE_PROTO | HAVE_SRCIP | | ||||
HAVE_DSTIP | HAVE_IP; | HAVE_DSTIP | HAVE_IP; | ||||
break; | break; | ||||
case O_ACCEPT: | case O_ACCEPT: | ||||
bprintf(bp, "allow"); | bprintf(bp, "allow"); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | case O_NAT: | ||||
bprintf(bp, "nat global"); | bprintf(bp, "nat global"); | ||||
break; | break; | ||||
case O_SETFIB: | case O_SETFIB: | ||||
bprint_uint_arg(bp, "setfib ", cmd->arg1 & 0x7FFF); | bprint_uint_arg(bp, "setfib ", cmd->arg1 & 0x7FFF); | ||||
break; | break; | ||||
case O_EXTERNAL_ACTION: { | case O_EXTERNAL_ACTION: { | ||||
const char *ename; | |||||
/* | /* | ||||
* The external action can consists of two following | * The external action can consists of two following | ||||
* each other opcodes - O_EXTERNAL_ACTION and | * each other opcodes - O_EXTERNAL_ACTION and | ||||
* O_EXTERNAL_INSTANCE. The first contains the ID of | * O_EXTERNAL_INSTANCE. The first contains the ID of | ||||
* name of external action. The second contains the ID | * name of external action. The second contains the ID | ||||
* of name of external action instance. | * of name of external action instance. | ||||
* NOTE: in case when external action has no named | * NOTE: in case when external action has no named | ||||
* instances support, the second opcode isn't needed. | * instances support, the second opcode isn't needed. | ||||
*/ | */ | ||||
has_eaction = cmd; | has_eaction = cmd; | ||||
ename = object_search_ctlv(fo->tstate, cmd->arg1, | ename = object_search_ctlv(fo->tstate, cmd->arg1, | ||||
IPFW_TLV_EACTION); | IPFW_TLV_EACTION); | ||||
if (match_token(rule_eactions, ename) != -1) | if (match_token(rule_eactions, ename) != -1) | ||||
bprintf(bp, "%s", ename); | bprintf(bp, "%s", ename); | ||||
else | else | ||||
bprintf(bp, "eaction %s", ename); | bprintf(bp, "eaction %s", ename); | ||||
break; | break; | ||||
} | } | ||||
case O_EXTERNAL_INSTANCE: { | case O_EXTERNAL_INSTANCE: { | ||||
const char *ename; | |||||
if (has_eaction == NULL) | if (has_eaction == NULL) | ||||
break; | break; | ||||
/* | /* | ||||
* XXX: we need to teach ipfw(9) to rewrite opcodes | * XXX: we need to teach ipfw(9) to rewrite opcodes | ||||
* in the user buffer on rule addition. When we add | * in the user buffer on rule addition. When we add | ||||
* the rule, we specify zero TLV type for | * the rule, we specify zero TLV type for | ||||
* O_EXTERNAL_INSTANCE object. To show correct | * O_EXTERNAL_INSTANCE object. To show correct | ||||
* rule after `ipfw add` we need to search instance | * rule after `ipfw add` we need to search instance | ||||
▲ Show 20 Lines • Show All 439 Lines • ▼ Show 20 Lines | default: /*options ... */ | ||||
break; | break; | ||||
case O_NOP: | case O_NOP: | ||||
comment = (char *)(cmd + 1); | comment = (char *)(cmd + 1); | ||||
break; | break; | ||||
case O_KEEP_STATE: | case O_KEEP_STATE: | ||||
bprintf(bp, " keep-state"); | bprintf(bp, " keep-state"); | ||||
bprintf(bp, " %s", | |||||
object_search_ctlv(fo->tstate, cmd->arg1, | |||||
IPFW_TLV_STATE_NAME)); | |||||
break; | break; | ||||
case O_LIMIT: { | case O_LIMIT: { | ||||
struct _s_x *p = limit_masks; | struct _s_x *p = limit_masks; | ||||
ipfw_insn_limit *c = (ipfw_insn_limit *)cmd; | ipfw_insn_limit *c = (ipfw_insn_limit *)cmd; | ||||
uint8_t x = c->limit_mask; | uint8_t x = c->limit_mask; | ||||
char const *comma = " "; | char const *comma = " "; | ||||
bprintf(bp, " limit"); | bprintf(bp, " 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; | ||||
bprintf(bp, "%s%s", comma,p->s); | bprintf(bp, "%s%s", comma,p->s); | ||||
comma = ","; | comma = ","; | ||||
} | } | ||||
bprint_uint_arg(bp, " ", c->conn_limit); | bprint_uint_arg(bp, " ", c->conn_limit); | ||||
bprintf(bp, " %s", | |||||
object_search_ctlv(fo->tstate, cmd->arg1, | |||||
IPFW_TLV_STATE_NAME)); | |||||
break; | break; | ||||
} | } | ||||
case O_IP6: | case O_IP6: | ||||
bprintf(bp, " ip6"); | bprintf(bp, " ip6"); | ||||
break; | break; | ||||
case O_IP4: | case O_IP4: | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | if (d->id.addr_type == 4) { | ||||
a.s_addr = htonl(d->id.dst_ip); | a.s_addr = htonl(d->id.dst_ip); | ||||
bprintf(bp, " <-> %s %d", inet_ntoa(a), d->id.dst_port); | bprintf(bp, " <-> %s %d", inet_ntoa(a), d->id.dst_port); | ||||
} else if (d->id.addr_type == 6) { | } else if (d->id.addr_type == 6) { | ||||
bprintf(bp, " %s %d", inet_ntop(AF_INET6, &d->id.src_ip6, buf, | bprintf(bp, " %s %d", inet_ntop(AF_INET6, &d->id.src_ip6, buf, | ||||
sizeof(buf)), d->id.src_port); | sizeof(buf)), d->id.src_port); | ||||
bprintf(bp, " <-> %s %d", inet_ntop(AF_INET6, &d->id.dst_ip6, | bprintf(bp, " <-> %s %d", inet_ntop(AF_INET6, &d->id.dst_ip6, | ||||
buf, sizeof(buf)), d->id.dst_port); | buf, sizeof(buf)), d->id.dst_port); | ||||
} else | } else | ||||
bprintf(bp, " UNKNOWN <-> UNKNOWN\n"); | bprintf(bp, " UNKNOWN <-> UNKNOWN"); | ||||
if (d->kidx != 0) | |||||
bprintf(bp, " %s", object_search_ctlv(fo->tstate, | |||||
d->kidx, IPFW_TLV_STATE_NAME)); | |||||
} | } | ||||
static int | static int | ||||
do_range_cmd(int cmd, ipfw_range_tlv *rt) | do_range_cmd(int cmd, ipfw_range_tlv *rt) | ||||
{ | { | ||||
ipfw_range_header rh; | ipfw_range_header rh; | ||||
size_t sz; | size_t sz; | ||||
▲ Show 20 Lines • Show All 624 Lines • ▼ Show 20 Lines | for (i = 0; i < l; i++) { | ||||
if (isalpha(c) || isdigit(c) || c == '_' || | if (isalpha(c) || isdigit(c) || c == '_' || | ||||
c == '-' || c == '.') | c == '-' || c == '.') | ||||
continue; | continue; | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static char *default_state_name = "default"; | |||||
static int | static int | ||||
state_check_name(const char *name) | |||||
{ | |||||
if (ipfw_check_object_name(name) != 0) | |||||
return (EINVAL); | |||||
if (strcmp(name, "any") == 0) | |||||
return (EINVAL); | |||||
return (0); | |||||
} | |||||
static int | |||||
eaction_check_name(const char *name) | eaction_check_name(const char *name) | ||||
{ | { | ||||
if (ipfw_check_object_name(name) != 0) | if (ipfw_check_object_name(name) != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* Restrict some 'special' names */ | /* Restrict some 'special' names */ | ||||
if (match_token(rule_actions, name) != -1 && | if (match_token(rule_actions, name) != -1 && | ||||
match_token(rule_action_params, name) != -1) | match_token(rule_action_params, name) != -1) | ||||
▲ Show 20 Lines • Show All 844 Lines • ▼ Show 20 Lines | #define CHECK_ACTLEN CHECK_LENGTH(ablen, action->len) | ||||
i = match_token(rule_actions, *av); | i = match_token(rule_actions, *av); | ||||
av++; | av++; | ||||
action->len = 1; /* default */ | action->len = 1; /* default */ | ||||
CHECK_ACTLEN; | CHECK_ACTLEN; | ||||
switch(i) { | switch(i) { | ||||
case TOK_CHECKSTATE: | case TOK_CHECKSTATE: | ||||
have_state = action; | have_state = action; | ||||
action->opcode = O_CHECK_STATE; | action->opcode = O_CHECK_STATE; | ||||
if (*av == NULL) { | |||||
action->arg1 = pack_object(tstate, | |||||
default_state_name, IPFW_TLV_STATE_NAME); | |||||
break; | break; | ||||
} | |||||
if (strcmp(*av, "any") == 0) | |||||
action->arg1 = 0; | |||||
else if (match_token(rule_options, *av) != -1) { | |||||
action->arg1 = pack_object(tstate, | |||||
default_state_name, IPFW_TLV_STATE_NAME); | |||||
warn("Ambiguous state name '%s', '%s' used instead.\n", | |||||
*av, default_state_name); | |||||
} else if (state_check_name(*av) == 0) | |||||
action->arg1 = pack_object(tstate, *av, | |||||
IPFW_TLV_STATE_NAME); | |||||
else | |||||
errx(EX_DATAERR, "Invalid state name %s", *av); | |||||
av++; | |||||
break; | |||||
case TOK_ACCEPT: | case TOK_ACCEPT: | ||||
action->opcode = O_ACCEPT; | action->opcode = O_ACCEPT; | ||||
break; | break; | ||||
case TOK_DENY: | case TOK_DENY: | ||||
action->opcode = O_DENY; | action->opcode = O_DENY; | ||||
action->arg1 = 0; | action->arg1 = 0; | ||||
▲ Show 20 Lines • Show All 803 Lines • ▼ Show 20 Lines | while ( av[0] != NULL ) { | ||||
case TOK_TCPFLAGS: | case TOK_TCPFLAGS: | ||||
NEED1("missing argument for tcpflags"); | NEED1("missing argument for tcpflags"); | ||||
cmd->opcode = O_TCPFLAGS; | cmd->opcode = O_TCPFLAGS; | ||||
fill_flags_cmd(cmd, O_TCPFLAGS, f_tcpflags, *av); | fill_flags_cmd(cmd, O_TCPFLAGS, f_tcpflags, *av); | ||||
av++; | av++; | ||||
break; | break; | ||||
case TOK_KEEPSTATE: | case TOK_KEEPSTATE: { | ||||
uint16_t uidx; | |||||
if (open_par) | if (open_par) | ||||
errx(EX_USAGE, "keep-state cannot be part " | errx(EX_USAGE, "keep-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 " | ||||
"and limit is allowed"); | "and limit is allowed"); | ||||
if (*av == NULL || | |||||
match_token(rule_options, *av) != -1) { | |||||
if (*av != NULL) | |||||
warn("Ambiguous state name '%s'," | |||||
" '%s' used instead.\n", *av, | |||||
default_state_name); | |||||
uidx = pack_object(tstate, default_state_name, | |||||
IPFW_TLV_STATE_NAME); | |||||
} else { | |||||
if (state_check_name(*av) != 0) | |||||
errx(EX_DATAERR, | |||||
"Invalid state name %s", *av); | |||||
uidx = pack_object(tstate, *av, | |||||
IPFW_TLV_STATE_NAME); | |||||
av++; | |||||
} | |||||
have_state = cmd; | have_state = cmd; | ||||
fill_cmd(cmd, O_KEEP_STATE, 0, 0); | fill_cmd(cmd, O_KEEP_STATE, 0, uidx); | ||||
break; | break; | ||||
} | |||||
case TOK_LIMIT: { | case TOK_LIMIT: { | ||||
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 cannot be part of an or block"); | ||||
Show All 14 Lines | case TOK_LIMIT: { | ||||
av++; | av++; | ||||
} | } | ||||
if (c->limit_mask == 0) | if (c->limit_mask == 0) | ||||
errx(EX_USAGE, "limit: missing limit mask"); | errx(EX_USAGE, "limit: missing limit mask"); | ||||
GET_UINT_ARG(c->conn_limit, IPFW_ARG_MIN, IPFW_ARG_MAX, | GET_UINT_ARG(c->conn_limit, IPFW_ARG_MIN, IPFW_ARG_MAX, | ||||
TOK_LIMIT, rule_options); | TOK_LIMIT, rule_options); | ||||
av++; | |||||
if (*av == NULL || | |||||
match_token(rule_options, *av) != -1) { | |||||
if (*av != NULL) | |||||
warn("Ambiguous state name '%s'," | |||||
" '%s' used instead.\n", *av, | |||||
default_state_name); | |||||
cmd->arg1 = pack_object(tstate, | |||||
default_state_name, IPFW_TLV_STATE_NAME); | |||||
} else { | |||||
if (state_check_name(*av) != 0) | |||||
errx(EX_DATAERR, | |||||
"Invalid state name %s", *av); | |||||
cmd->arg1 = pack_object(tstate, *av, | |||||
IPFW_TLV_STATE_NAME); | |||||
av++; | av++; | ||||
} | |||||
break; | break; | ||||
} | } | ||||
case TOK_PROTO: | case TOK_PROTO: | ||||
NEED1("missing protocol"); | NEED1("missing protocol"); | ||||
if (add_proto(cmd, *av, &proto)) { | if (add_proto(cmd, *av, &proto)) { | ||||
av++; | av++; | ||||
} else | } else | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | if (match_prob != 1) { /* 1 means always match */ | ||||
*((int32_t *)(dst+1)) = (int32_t)(match_prob * 0x7fffffff); | *((int32_t *)(dst+1)) = (int32_t)(match_prob * 0x7fffffff); | ||||
dst += dst->len; | dst += dst->len; | ||||
} | } | ||||
/* | /* | ||||
* 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) { | ||||
fill_cmd(dst, O_PROBE_STATE, 0, 0); | 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 */ | ||||
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); | ||||
▲ Show 20 Lines • Show All 368 Lines • ▼ Show 20 Lines | static struct _s_x intcmds[] = { | ||||
{ "iflist", TOK_IFLIST }, | { "iflist", TOK_IFLIST }, | ||||
{ "olist", TOK_OLIST }, | { "olist", TOK_OLIST }, | ||||
{ "vlist", TOK_VLIST }, | { "vlist", TOK_VLIST }, | ||||
{ NULL, 0 } | { NULL, 0 } | ||||
}; | }; | ||||
static struct _s_x otypes[] = { | static struct _s_x otypes[] = { | ||||
{ "EACTION", IPFW_TLV_EACTION }, | { "EACTION", IPFW_TLV_EACTION }, | ||||
{ "DYNSTATE", IPFW_TLV_STATE_NAME }, | |||||
{ NULL, 0 } | { NULL, 0 } | ||||
}; | }; | ||||
static const char* | static const char* | ||||
lookup_eaction_name(ipfw_obj_ntlv *ntlv, int cnt, uint16_t type) | lookup_eaction_name(ipfw_obj_ntlv *ntlv, int cnt, uint16_t type) | ||||
{ | { | ||||
const char *name; | const char *name; | ||||
int i; | int i; | ||||
▲ Show 20 Lines • Show All 162 Lines • Show Last 20 Lines |