Changeset View
Changeset View
Standalone View
Standalone View
sbin/ipfw/ipfw2.c
| Show First 20 Lines • Show All 284 Lines • ▼ Show 20 Lines | static struct _s_x rule_actions[] = { | ||||
| { "call", TOK_CALL }, | { "call", TOK_CALL }, | ||||
| { "return", TOK_RETURN }, | { "return", TOK_RETURN }, | ||||
| { "eaction", TOK_EACTION }, | { "eaction", TOK_EACTION }, | ||||
| { "tcp-setmss", TOK_TCPSETMSS }, | { "tcp-setmss", TOK_TCPSETMSS }, | ||||
| { "setmark", TOK_SETMARK }, | { "setmark", TOK_SETMARK }, | ||||
| { NULL, 0 } /* terminator */ | { NULL, 0 } /* terminator */ | ||||
| }; | }; | ||||
| static struct _s_x return_types[] = { | |||||
| { "next-rulenum", RETURN_NEXT_RULENUM }, | |||||
| { "next-rule", RETURN_NEXT_RULE }, | |||||
| { NULL, 0 } /* terminator */ | |||||
| }; | |||||
| static struct _s_x rule_action_params[] = { | static struct _s_x rule_action_params[] = { | ||||
| { "altq", TOK_ALTQ }, | { "altq", TOK_ALTQ }, | ||||
| { "log", TOK_LOG }, | { "log", TOK_LOG }, | ||||
| { "tag", TOK_TAG }, | { "tag", TOK_TAG }, | ||||
| { "untag", TOK_UNTAG }, | { "untag", TOK_UNTAG }, | ||||
| { NULL, 0 } /* terminator */ | { NULL, 0 } /* terminator */ | ||||
| }; | }; | ||||
| /* | /* | ||||
| * The 'lookup' instruction accepts one of the following arguments. | * The 'lookup' instruction accepts one of the following arguments. | ||||
| * Arguments are passed as v[1] in O_DST_LOOKUP options. | * Arguments are passed as o.arg1 and o->value in O_DST_LOOKUP option. | ||||
| */ | */ | ||||
| static struct _s_x lookup_keys[] = { | static struct _s_x lookup_keys[] = { | ||||
| { "dst-ip", LOOKUP_DST_IP }, | { "dst-ip", LOOKUP_DST_IP }, | ||||
| { "src-ip", LOOKUP_SRC_IP }, | { "src-ip", LOOKUP_SRC_IP }, | ||||
| { "dst-port", LOOKUP_DST_PORT }, | { "dst-port", LOOKUP_DST_PORT }, | ||||
| { "src-port", LOOKUP_SRC_PORT }, | { "src-port", LOOKUP_SRC_PORT }, | ||||
| { "dst-mac", LOOKUP_DST_MAC }, | { "dst-mac", LOOKUP_DST_MAC }, | ||||
| { "src-mac", LOOKUP_SRC_MAC }, | { "src-mac", LOOKUP_SRC_MAC }, | ||||
| { "uid", LOOKUP_UID }, | { "uid", LOOKUP_UID }, | ||||
| { "jail", LOOKUP_JAIL }, | { "jail", LOOKUP_JAIL }, | ||||
| { "dscp", LOOKUP_DSCP }, | { "dscp", LOOKUP_DSCP }, | ||||
| { "mark", LOOKUP_MARK }, | { "mark", LOOKUP_MARK }, | ||||
| { "rulenum", LOOKUP_RULENUM }, | |||||
| { NULL, 0 }, | { NULL, 0 }, | ||||
| }; | }; | ||||
| /* | |||||
| * table(name,valuename=value) instruction accepts one of the | |||||
| * following arguments as valuename. | |||||
| */ | |||||
| static struct _s_x tvalue_names[] = { | |||||
| { "tag", TVALUE_TAG }, | |||||
| { "pipe", TVALUE_PIPE }, | |||||
| { "divert", TVALUE_DIVERT }, | |||||
| { "skipto", TVALUE_SKIPTO }, | |||||
| { "netgraph", TVALUE_NETGRAPH }, | |||||
| { "fib", TVALUE_FIB }, | |||||
| { "nat", TVALUE_NAT }, | |||||
| { "nh4", TVALUE_NH4 }, | |||||
| { "dscp", TVALUE_DSCP }, | |||||
| { "limit", TVALUE_LIMIT }, | |||||
| { "mark", TVALUE_MARK }, | |||||
| { NULL, 0 } | |||||
| }; | |||||
| static struct _s_x rule_options[] = { | static struct _s_x rule_options[] = { | ||||
| { "tagged", TOK_TAGGED }, | { "tagged", TOK_TAGGED }, | ||||
| { "uid", TOK_UID }, | { "uid", TOK_UID }, | ||||
| { "gid", TOK_GID }, | { "gid", TOK_GID }, | ||||
| { "jail", TOK_JAIL }, | { "jail", TOK_JAIL }, | ||||
| { "in", TOK_IN }, | { "in", TOK_IN }, | ||||
| { "limit", TOK_LIMIT }, | { "limit", TOK_LIMIT }, | ||||
| { "set-limit", TOK_SETLIMIT }, | { "set-limit", TOK_SETLIMIT }, | ||||
| ▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
| void bprint_uint_arg(struct buf_pr *bp, const char *str, uint32_t arg); | void bprint_uint_arg(struct buf_pr *bp, const char *str, uint32_t arg); | ||||
| static int ipfw_get_config(struct cmdline_opts *co, struct format_opts *fo, | static int ipfw_get_config(struct cmdline_opts *co, struct format_opts *fo, | ||||
| ipfw_cfg_lheader **pcfg, size_t *psize); | ipfw_cfg_lheader **pcfg, size_t *psize); | ||||
| static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo, | static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo, | ||||
| ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av); | ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av); | ||||
| static void ipfw_list_tifaces(void); | static void ipfw_list_tifaces(void); | ||||
| struct tidx; | struct tidx; | ||||
| static uint16_t pack_object(struct tidx *tstate, const char *name, int otype); | static uint32_t pack_object(struct tidx *tstate, const char *name, int otype); | ||||
| static uint16_t pack_table(struct tidx *tstate, const char *name); | static uint32_t pack_table(struct tidx *tstate, const char *name); | ||||
| static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx); | static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx); | ||||
| static void object_sort_ctlv(ipfw_obj_ctlv *ctlv); | static void object_sort_ctlv(ipfw_obj_ctlv *ctlv); | ||||
| static char *object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx, | static char *object_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx, | ||||
| uint16_t type); | uint16_t type); | ||||
| int | int | ||||
| is_ipfw(void) | is_ipfw(void) | ||||
| { | { | ||||
| return (g_co.prog == cmdline_prog_ipfw); | return (g_co.prog == cmdline_prog_ipfw); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | |||||
| * Calls setsockopt() with IP_FW3 as kernel-visible opcode. | * Calls setsockopt() with IP_FW3 as kernel-visible opcode. | ||||
| * Returns 0 on success or errno otherwise. | * Returns 0 on success or errno otherwise. | ||||
| */ | */ | ||||
| int | int | ||||
| do_set3(int optname, ip_fw3_opheader *op3, size_t optlen) | do_set3(int optname, ip_fw3_opheader *op3, size_t optlen) | ||||
| { | { | ||||
| op3->opcode = optname; | op3->opcode = optname; | ||||
| op3->version = IP_FW3_OPVER; /* use last version */ | |||||
| if (g_co.debug_only) { | if (g_co.debug_only) { | ||||
| struct debug_header dbg = { | struct debug_header dbg = { | ||||
| .cmd_type = 2, | .cmd_type = 2, | ||||
| .opt_name = optname, | .opt_name = optname, | ||||
| .total_len = optlen, sizeof(struct debug_header), | .total_len = optlen, sizeof(struct debug_header), | ||||
| }; | }; | ||||
| write(1, &dbg, sizeof(dbg)); | write(1, &dbg, sizeof(dbg)); | ||||
| Show All 24 Lines | |||||
| */ | */ | ||||
| int | int | ||||
| do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen) | do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen) | ||||
| { | { | ||||
| int error; | int error; | ||||
| socklen_t len; | socklen_t len; | ||||
| op3->opcode = optname; | op3->opcode = optname; | ||||
| op3->version = IP_FW3_OPVER; /* use last version */ | |||||
| if (g_co.debug_only) { | if (g_co.debug_only) { | ||||
| struct debug_header dbg = { | struct debug_header dbg = { | ||||
| .cmd_type = 3, | .cmd_type = 3, | ||||
| .opt_name = optname, | .opt_name = optname, | ||||
| .total_len = *optlen + sizeof(struct debug_header), | .total_len = *optlen + sizeof(struct debug_header), | ||||
| }; | }; | ||||
| write(1, &dbg, sizeof(dbg)); | write(1, &dbg, sizeof(dbg)); | ||||
| ▲ Show 20 Lines • Show All 578 Lines • ▼ Show 20 Lines | for (i=0; list[i].x != 0; i++) { | ||||
| if (clear & list[i].x) { | if (clear & list[i].x) { | ||||
| clear &= ~list[i].x; | clear &= ~list[i].x; | ||||
| bprintf(bp, "%s!%s", comma, list[i].s); | bprintf(bp, "%s!%s", comma, list[i].s); | ||||
| comma = ","; | comma = ","; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void | |||||
| print_tvalue(struct buf_pr *bp, const ipfw_insn_table *cmd) | |||||
| { | |||||
| const char *name; | |||||
| name = match_value(tvalue_names, IPFW_TVALUE_TYPE(&cmd->o)); | |||||
| bprintf(bp, ",%s=%u", name != NULL ? name: "<invalid>", cmd->value); | |||||
| } | |||||
| /* | /* | ||||
| * Print the ip address contained in a command. | * Print the ip address contained in a command. | ||||
| */ | */ | ||||
| static void | static void | ||||
| print_ip(struct buf_pr *bp, const struct format_opts *fo, | print_ip(struct buf_pr *bp, const struct format_opts *fo, | ||||
| const ipfw_insn_ip *cmd) | const ipfw_insn_ip *cmd) | ||||
| { | { | ||||
| struct hostent *he = NULL; | struct hostent *he = NULL; | ||||
| const struct in_addr *ia; | const struct in_addr *ia; | ||||
| const uint32_t *a = ((const ipfw_insn_u32 *)cmd)->d; | const uint32_t *a = ((const ipfw_insn_u32 *)cmd)->d; | ||||
| uint32_t len = F_LEN((const ipfw_insn *)cmd); | uint32_t len = F_LEN(&cmd->o); | ||||
| char *t; | char *t; | ||||
| bprintf(bp, " "); | bprintf(bp, " "); | ||||
| if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) { | switch (cmd->o.opcode) { | ||||
| const char *arg; | case O_IP_SRC_ME: | ||||
| case O_IP_DST_ME: | |||||
| bprintf(bp, "me"); | |||||
| return; | |||||
| arg = match_value(lookup_keys, a[1]); | 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, | t = table_search_ctlv(fo->tstate, | ||||
| ((const ipfw_insn *)cmd)->arg1); | insntoc(&cmd->o, kidx)->kidx); | ||||
| bprintf(bp, "lookup %s %s", arg, t); | 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); | |||||
| return; | return; | ||||
| } | } | ||||
| if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) { | /* FALLTHROUGH */ | ||||
| bprintf(bp, "me"); | case O_IP_SRC_LOOKUP: | ||||
| return; | |||||
| } | |||||
| if (cmd->o.opcode == O_IP_SRC_LOOKUP || | |||||
| cmd->o.opcode == O_IP_DST_LOOKUP) { | |||||
| t = table_search_ctlv(fo->tstate, | t = table_search_ctlv(fo->tstate, | ||||
| ((const ipfw_insn *)cmd)->arg1); | insntoc(&cmd->o, kidx)->kidx); | ||||
| bprintf(bp, "table(%s", t); | bprintf(bp, "table(%s", t); | ||||
| if (len == F_INSN_SIZE(ipfw_insn_u32)) | if (len == F_INSN_SIZE(ipfw_insn_table)) | ||||
| bprintf(bp, ",%u", *a); | print_tvalue(bp, insntoc(&cmd->o, table)); | ||||
| bprintf(bp, ")"); | bprintf(bp, ")"); | ||||
| return; | return; | ||||
| } | } | ||||
| if (cmd->o.opcode == O_IP_SRC_SET || cmd->o.opcode == O_IP_DST_SET) { | if (cmd->o.opcode == O_IP_SRC_SET || cmd->o.opcode == O_IP_DST_SET) { | ||||
| const uint32_t *map = (const uint32_t *)&cmd->mask; | const uint32_t *map = (const uint32_t *)&cmd->mask; | ||||
| struct in_addr addr; | struct in_addr addr; | ||||
| uint32_t x; | uint32_t x; | ||||
| int i, j; | int i, j; | ||||
| char comma = '{'; | char comma = '{'; | ||||
| x = cmd->o.arg1 - 1; | x = cmd->o.arg1 - 1; | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
| print_mac_lookup(struct buf_pr *bp, const struct format_opts *fo, | print_mac_lookup(struct buf_pr *bp, const struct format_opts *fo, | ||||
| const ipfw_insn *cmd) | const ipfw_insn *cmd) | ||||
| { | { | ||||
| uint32_t len = F_LEN(cmd); | uint32_t len = F_LEN(cmd); | ||||
| char *t; | char *t; | ||||
| bprintf(bp, " "); | bprintf(bp, " "); | ||||
| t = table_search_ctlv(fo->tstate, cmd->arg1); | t = table_search_ctlv(fo->tstate, insntoc(cmd, kidx)->kidx); | ||||
| bprintf(bp, "table(%s", t); | bprintf(bp, "table(%s", t); | ||||
| if (len == F_INSN_SIZE(ipfw_insn_u32)) | if (len == F_INSN_SIZE(ipfw_insn_table)) | ||||
| bprintf(bp, ",%u", ((const ipfw_insn_u32 *)cmd)->d[0]); | print_tvalue(bp, insntoc(cmd, table)); | ||||
| bprintf(bp, ")"); | bprintf(bp, ")"); | ||||
| } | } | ||||
| static void | static void | ||||
| fill_icmptypes(ipfw_insn_u32 *cmd, char *av) | fill_icmptypes(ipfw_insn_u32 *cmd, char *av) | ||||
| { | { | ||||
| uint8_t type; | uint8_t type; | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (*v & (1 << i)) { | ||||
| sep = ','; | sep = ','; | ||||
| } | } | ||||
| if ((++i % 32) == 0) | if ((++i % 32) == 0) | ||||
| v++; | v++; | ||||
| } | } | ||||
| } | } | ||||
| #define insntod(cmd, type) ((const ipfw_insn_ ## type *)(cmd)) | |||||
| struct show_state { | struct show_state { | ||||
| struct ip_fw_rule *rule; | struct ip_fw_rule *rule; | ||||
| const ipfw_insn *eaction; | const ipfw_insn_kidx *eaction; | ||||
| uint8_t *printed; | uint8_t *printed; | ||||
| int flags; | int flags; | ||||
| #define HAVE_PROTO 0x0001 | #define HAVE_PROTO 0x0001 | ||||
| #define HAVE_SRCIP 0x0002 | #define HAVE_SRCIP 0x0002 | ||||
| #define HAVE_DSTIP 0x0004 | #define HAVE_DSTIP 0x0004 | ||||
| #define HAVE_PROBE_STATE 0x0008 | #define HAVE_PROBE_STATE 0x0008 | ||||
| int proto; | int proto; | ||||
| int or_block; | int or_block; | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | if (is_printed_opcode(state, cmd)) | ||||
| return (0); | return (0); | ||||
| if ((cmd->len & F_OR) != 0 && state->or_block == 0) | if ((cmd->len & F_OR) != 0 && state->or_block == 0) | ||||
| bprintf(bp, " {"); | bprintf(bp, " {"); | ||||
| if (cmd->opcode != O_IN && (cmd->len & F_NOT) != 0) | if (cmd->opcode != O_IN && (cmd->len & F_NOT) != 0) | ||||
| bprintf(bp, " not"); | bprintf(bp, " not"); | ||||
| switch (cmd->opcode) { | switch (cmd->opcode) { | ||||
| case O_PROB: | case O_PROB: | ||||
| d = 1.0 * insntod(cmd, u32)->d[0] / 0x7fffffff; | d = 1.0 * insntoc(cmd, u32)->d[0] / 0x7fffffff; | ||||
| bprintf(bp, "prob %f ", d); | bprintf(bp, "prob %f ", d); | ||||
| break; | break; | ||||
| case O_PROBE_STATE: /* no need to print anything here */ | case O_PROBE_STATE: /* no need to print anything here */ | ||||
| state->flags |= HAVE_PROBE_STATE; | state->flags |= HAVE_PROBE_STATE; | ||||
| break; | break; | ||||
| case O_IP_SRC: | case O_IP_SRC: | ||||
| case O_IP_SRC_LOOKUP: | case O_IP_SRC_LOOKUP: | ||||
| case O_IP_SRC_MASK: | case O_IP_SRC_MASK: | ||||
| case O_IP_SRC_ME: | case O_IP_SRC_ME: | ||||
| case O_IP_SRC_SET: | case O_IP_SRC_SET: | ||||
| if (state->flags & HAVE_SRCIP) | if (state->flags & HAVE_SRCIP) | ||||
| bprintf(bp, " src-ip"); | bprintf(bp, " src-ip"); | ||||
| print_ip(bp, fo, insntod(cmd, ip)); | print_ip(bp, fo, insntoc(cmd, ip)); | ||||
| break; | break; | ||||
| case O_IP_DST: | case O_IP_DST: | ||||
| case O_IP_DST_LOOKUP: | |||||
| case O_IP_DST_MASK: | case O_IP_DST_MASK: | ||||
| case O_IP_DST_ME: | case O_IP_DST_ME: | ||||
| case O_IP_DST_SET: | case O_IP_DST_SET: | ||||
| if (state->flags & HAVE_DSTIP) | case O_IP_DST_LOOKUP: | ||||
| /* | |||||
| * Special handling for O_IP_DST_LOOKUP when | |||||
| * lookup type is not LOOKUP_NONE. | |||||
| */ | |||||
| if ((state->flags & HAVE_DSTIP) != 0 && ( | |||||
| cmd->opcode != O_IP_DST_LOOKUP || | |||||
| IPFW_LOOKUP_TYPE(cmd) == LOOKUP_NONE)) | |||||
| bprintf(bp, " dst-ip"); | bprintf(bp, " dst-ip"); | ||||
| print_ip(bp, fo, insntod(cmd, ip)); | print_ip(bp, fo, insntoc(cmd, ip)); | ||||
| break; | break; | ||||
| case O_IP6_SRC: | case O_IP6_SRC: | ||||
| case O_IP6_SRC_MASK: | case O_IP6_SRC_MASK: | ||||
| case O_IP6_SRC_ME: | case O_IP6_SRC_ME: | ||||
| if (state->flags & HAVE_SRCIP) | if (state->flags & HAVE_SRCIP) | ||||
| bprintf(bp, " src-ip6"); | bprintf(bp, " src-ip6"); | ||||
| print_ip6(bp, insntod(cmd, ip6)); | print_ip6(bp, insntoc(cmd, ip6)); | ||||
| break; | break; | ||||
| case O_IP6_DST: | case O_IP6_DST: | ||||
| case O_IP6_DST_MASK: | case O_IP6_DST_MASK: | ||||
| case O_IP6_DST_ME: | case O_IP6_DST_ME: | ||||
| if (state->flags & HAVE_DSTIP) | if (state->flags & HAVE_DSTIP) | ||||
| bprintf(bp, " dst-ip6"); | bprintf(bp, " dst-ip6"); | ||||
| print_ip6(bp, insntod(cmd, ip6)); | print_ip6(bp, insntoc(cmd, ip6)); | ||||
| break; | break; | ||||
| case O_MAC_SRC_LOOKUP: | case O_MAC_SRC_LOOKUP: | ||||
| bprintf(bp, " src-mac"); | bprintf(bp, " src-mac"); | ||||
| print_mac_lookup(bp, fo, cmd); | print_mac_lookup(bp, fo, cmd); | ||||
| break; | break; | ||||
| case O_MAC_DST_LOOKUP: | case O_MAC_DST_LOOKUP: | ||||
| bprintf(bp, " dst-mac"); | bprintf(bp, " dst-mac"); | ||||
| print_mac_lookup(bp, fo, cmd); | print_mac_lookup(bp, fo, cmd); | ||||
| break; | break; | ||||
| case O_FLOW6ID: | case O_FLOW6ID: | ||||
| print_flow6id(bp, insntod(cmd, u32)); | print_flow6id(bp, insntoc(cmd, u32)); | ||||
| break; | break; | ||||
| case O_IP_DSTPORT: | case O_IP_DSTPORT: | ||||
| case O_IP_SRCPORT: | case O_IP_SRCPORT: | ||||
| print_newports(bp, insntod(cmd, u16), state->proto, | print_newports(bp, insntoc(cmd, u16), state->proto, | ||||
| (state->flags & (HAVE_SRCIP | HAVE_DSTIP)) == | (state->flags & (HAVE_SRCIP | HAVE_DSTIP)) == | ||||
| (HAVE_SRCIP | HAVE_DSTIP) ? cmd->opcode: 0); | (HAVE_SRCIP | HAVE_DSTIP) ? cmd->opcode: 0); | ||||
| break; | break; | ||||
| case O_PROTO: | case O_PROTO: | ||||
| pe = getprotobynumber(cmd->arg1); | pe = getprotobynumber(cmd->arg1); | ||||
| if (state->flags & HAVE_PROTO) | if (state->flags & HAVE_PROTO) | ||||
| bprintf(bp, " proto"); | bprintf(bp, " proto"); | ||||
| if (pe != NULL) | if (pe != NULL) | ||||
| bprintf(bp, " %s", pe->p_name); | bprintf(bp, " %s", pe->p_name); | ||||
| else | else | ||||
| bprintf(bp, " %u", cmd->arg1); | bprintf(bp, " %u", cmd->arg1); | ||||
| state->proto = cmd->arg1; | state->proto = cmd->arg1; | ||||
| break; | break; | ||||
| case O_MACADDR2: | case O_MACADDR2: | ||||
| print_mac(bp, insntod(cmd, mac)); | print_mac(bp, insntoc(cmd, mac)); | ||||
| break; | break; | ||||
| case O_MAC_TYPE: | case O_MAC_TYPE: | ||||
| print_newports(bp, insntod(cmd, u16), | print_newports(bp, insntoc(cmd, u16), | ||||
| IPPROTO_ETHERTYPE, cmd->opcode); | IPPROTO_ETHERTYPE, cmd->opcode); | ||||
| break; | break; | ||||
| case O_FRAG: | case O_FRAG: | ||||
| print_flags(bp, "frag", cmd, f_ipoff); | print_flags(bp, "frag", cmd, f_ipoff); | ||||
| break; | break; | ||||
| case O_FIB: | case O_FIB: | ||||
| bprintf(bp, " fib %u", cmd->arg1); | bprintf(bp, " fib %u", cmd->arg1); | ||||
| break; | break; | ||||
| Show All 26 Lines | print_instruction(struct buf_pr *bp, const struct format_opts *fo, | ||||
| case O_RECV: | case O_RECV: | ||||
| case O_VIA: | case O_VIA: | ||||
| if (cmd->opcode == O_XMIT) | if (cmd->opcode == O_XMIT) | ||||
| s = "xmit"; | s = "xmit"; | ||||
| else if (cmd->opcode == O_RECV) | else if (cmd->opcode == O_RECV) | ||||
| s = "recv"; | s = "recv"; | ||||
| else /* if (cmd->opcode == O_VIA) */ | else /* if (cmd->opcode == O_VIA) */ | ||||
| s = "via"; | s = "via"; | ||||
| switch (insntod(cmd, if)->name[0]) { | switch (insntoc(cmd, if)->name[0]) { | ||||
| case '\0': | case '\0': | ||||
| bprintf(bp, " %s %s", s, | bprintf(bp, " %s %s", s, | ||||
| inet_ntoa(insntod(cmd, if)->p.ip)); | inet_ntoa(insntoc(cmd, if)->p.ip)); | ||||
| break; | break; | ||||
| case '\1': | case '\1': | ||||
| bprintf(bp, " %s table(%s)", s, | bprintf(bp, " %s table(%s)", s, | ||||
| table_search_ctlv(fo->tstate, | table_search_ctlv(fo->tstate, | ||||
| insntod(cmd, if)->p.kidx)); | insntoc(cmd, if)->p.kidx)); | ||||
| break; | break; | ||||
| default: | default: | ||||
| bprintf(bp, " %s %s", s, | bprintf(bp, " %s %s", s, | ||||
| insntod(cmd, if)->name); | insntoc(cmd, if)->name); | ||||
| } | } | ||||
| break; | break; | ||||
| case O_IP_FLOW_LOOKUP: | case O_IP_FLOW_LOOKUP: | ||||
| s = table_search_ctlv(fo->tstate, cmd->arg1); | s = table_search_ctlv(fo->tstate, | ||||
| insntoc(cmd, kidx)->kidx); | |||||
| bprintf(bp, " flow table(%s", s); | bprintf(bp, " flow table(%s", s); | ||||
| if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) | if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_table)) | ||||
| bprintf(bp, ",%u", insntod(cmd, u32)->d[0]); | print_tvalue(bp, insntoc(cmd, table)); | ||||
| bprintf(bp, ")"); | bprintf(bp, ")"); | ||||
| break; | break; | ||||
| case O_IPID: | case O_IPID: | ||||
| case O_IPTTL: | case O_IPTTL: | ||||
| case O_IPLEN: | case O_IPLEN: | ||||
| case O_TCPDATALEN: | case O_TCPDATALEN: | ||||
| case O_TCPMSS: | case O_TCPMSS: | ||||
| case O_TCPWIN: | case O_TCPWIN: | ||||
| Show All 18 Lines | if (F_LEN(cmd) == 1) { | ||||
| s = "tcpwin"; | s = "tcpwin"; | ||||
| break; | break; | ||||
| default: | default: | ||||
| s = "<unknown>"; | s = "<unknown>"; | ||||
| break; | break; | ||||
| } | } | ||||
| bprintf(bp, " %s %u", s, cmd->arg1); | bprintf(bp, " %s %u", s, cmd->arg1); | ||||
| } else | } else | ||||
| print_newports(bp, insntod(cmd, u16), 0, | print_newports(bp, insntoc(cmd, u16), 0, | ||||
| cmd->opcode); | cmd->opcode); | ||||
| break; | break; | ||||
| case O_IPVER: | case O_IPVER: | ||||
| bprintf(bp, " ipver %u", cmd->arg1); | bprintf(bp, " ipver %u", cmd->arg1); | ||||
| break; | break; | ||||
| case O_IPPRECEDENCE: | case O_IPPRECEDENCE: | ||||
| bprintf(bp, " ipprecedence %u", cmd->arg1 >> 5); | bprintf(bp, " ipprecedence %u", cmd->arg1 >> 5); | ||||
| break; | break; | ||||
| case O_DSCP: | case O_DSCP: | ||||
| print_dscp(bp, insntod(cmd, u32)); | print_dscp(bp, insntoc(cmd, u32)); | ||||
| break; | break; | ||||
| case O_IPOPT: | case O_IPOPT: | ||||
| print_flags(bp, "ipoptions", cmd, f_ipopts); | print_flags(bp, "ipoptions", cmd, f_ipopts); | ||||
| break; | break; | ||||
| case O_IPTOS: | case O_IPTOS: | ||||
| print_flags(bp, "iptos", cmd, f_iptos); | print_flags(bp, "iptos", cmd, f_iptos); | ||||
| break; | break; | ||||
| case O_ICMPTYPE: | case O_ICMPTYPE: | ||||
| print_icmptypes(bp, insntod(cmd, u32)); | print_icmptypes(bp, insntoc(cmd, u32)); | ||||
| break; | break; | ||||
| case O_ESTAB: | case O_ESTAB: | ||||
| bprintf(bp, " established"); | bprintf(bp, " established"); | ||||
| break; | break; | ||||
| case O_TCPFLAGS: | case O_TCPFLAGS: | ||||
| print_flags(bp, "tcpflags", cmd, f_tcpflags); | print_flags(bp, "tcpflags", cmd, f_tcpflags); | ||||
| break; | break; | ||||
| case O_TCPOPTS: | case O_TCPOPTS: | ||||
| print_flags(bp, "tcpoptions", cmd, f_tcpopts); | print_flags(bp, "tcpoptions", cmd, f_tcpopts); | ||||
| break; | break; | ||||
| case O_TCPACK: | case O_TCPACK: | ||||
| bprintf(bp, " tcpack %d", | bprintf(bp, " tcpack %d", | ||||
| ntohl(insntod(cmd, u32)->d[0])); | ntohl(insntoc(cmd, u32)->d[0])); | ||||
| break; | break; | ||||
| case O_TCPSEQ: | case O_TCPSEQ: | ||||
| bprintf(bp, " tcpseq %d", | bprintf(bp, " tcpseq %d", | ||||
| ntohl(insntod(cmd, u32)->d[0])); | ntohl(insntoc(cmd, u32)->d[0])); | ||||
| break; | break; | ||||
| case O_UID: | case O_UID: | ||||
| pwd = getpwuid(insntod(cmd, u32)->d[0]); | pwd = getpwuid(insntoc(cmd, u32)->d[0]); | ||||
| if (pwd != NULL) | if (pwd != NULL) | ||||
| bprintf(bp, " uid %s", pwd->pw_name); | bprintf(bp, " uid %s", pwd->pw_name); | ||||
| else | else | ||||
| bprintf(bp, " uid %u", | bprintf(bp, " uid %u", | ||||
| insntod(cmd, u32)->d[0]); | insntoc(cmd, u32)->d[0]); | ||||
| break; | break; | ||||
| case O_GID: | case O_GID: | ||||
| grp = getgrgid(insntod(cmd, u32)->d[0]); | grp = getgrgid(insntoc(cmd, u32)->d[0]); | ||||
| if (grp != NULL) | if (grp != NULL) | ||||
| bprintf(bp, " gid %s", grp->gr_name); | bprintf(bp, " gid %s", grp->gr_name); | ||||
| else | else | ||||
| bprintf(bp, " gid %u", | bprintf(bp, " gid %u", | ||||
| insntod(cmd, u32)->d[0]); | insntoc(cmd, u32)->d[0]); | ||||
| break; | break; | ||||
| case O_JAIL: | case O_JAIL: | ||||
| bprintf(bp, " jail %d", insntod(cmd, u32)->d[0]); | bprintf(bp, " jail %d", insntoc(cmd, u32)->d[0]); | ||||
| break; | break; | ||||
| case O_VERREVPATH: | case O_VERREVPATH: | ||||
| bprintf(bp, " verrevpath"); | bprintf(bp, " verrevpath"); | ||||
| break; | break; | ||||
| case O_VERSRCREACH: | case O_VERSRCREACH: | ||||
| bprintf(bp, " versrcreach"); | bprintf(bp, " versrcreach"); | ||||
| break; | break; | ||||
| case O_ANTISPOOF: | case O_ANTISPOOF: | ||||
| bprintf(bp, " antispoof"); | bprintf(bp, " antispoof"); | ||||
| break; | break; | ||||
| case O_IPSEC: | case O_IPSEC: | ||||
| bprintf(bp, " ipsec"); | bprintf(bp, " ipsec"); | ||||
| break; | break; | ||||
| case O_NOP: | case O_NOP: | ||||
| bprintf(bp, " // %s", (const char *)(cmd + 1)); | bprintf(bp, " // %s", (const char *)(cmd + 1)); | ||||
| break; | break; | ||||
| case O_KEEP_STATE: | case O_KEEP_STATE: | ||||
| if (state->flags & HAVE_PROBE_STATE) | if (state->flags & HAVE_PROBE_STATE) | ||||
| bprintf(bp, " keep-state"); | bprintf(bp, " keep-state"); | ||||
| else | else | ||||
| bprintf(bp, " record-state"); | bprintf(bp, " record-state"); | ||||
| bprintf(bp, " :%s", | bprintf(bp, " :%s", | ||||
| object_search_ctlv(fo->tstate, cmd->arg1, | object_search_ctlv(fo->tstate, | ||||
| insntoc(cmd, kidx)->kidx, | |||||
| IPFW_TLV_STATE_NAME)); | IPFW_TLV_STATE_NAME)); | ||||
| break; | break; | ||||
| case O_LIMIT: | case O_LIMIT: | ||||
| if (state->flags & HAVE_PROBE_STATE) | if (state->flags & HAVE_PROBE_STATE) | ||||
| bprintf(bp, " limit"); | bprintf(bp, " limit"); | ||||
| else | else | ||||
| bprintf(bp, " set-limit"); | bprintf(bp, " set-limit"); | ||||
| print_limit_mask(bp, insntod(cmd, limit)); | print_limit_mask(bp, insntoc(cmd, limit)); | ||||
| bprintf(bp, " :%s", | bprintf(bp, " :%s", | ||||
| object_search_ctlv(fo->tstate, cmd->arg1, | object_search_ctlv(fo->tstate, | ||||
| insntoc(cmd, kidx)->kidx, | |||||
| IPFW_TLV_STATE_NAME)); | IPFW_TLV_STATE_NAME)); | ||||
| break; | break; | ||||
| case O_IP6: | case O_IP6: | ||||
| if (state->flags & HAVE_PROTO) | if (state->flags & HAVE_PROTO) | ||||
| bprintf(bp, " proto"); | bprintf(bp, " proto"); | ||||
| bprintf(bp, " ip6"); | bprintf(bp, " ip6"); | ||||
| break; | break; | ||||
| case O_IP4: | case O_IP4: | ||||
| if (state->flags & HAVE_PROTO) | if (state->flags & HAVE_PROTO) | ||||
| bprintf(bp, " proto"); | bprintf(bp, " proto"); | ||||
| bprintf(bp, " ip4"); | bprintf(bp, " ip4"); | ||||
| break; | break; | ||||
| case O_ICMP6TYPE: | case O_ICMP6TYPE: | ||||
| print_icmp6types(bp, insntod(cmd, u32)); | print_icmp6types(bp, insntoc(cmd, u32)); | ||||
| break; | break; | ||||
| case O_EXT_HDR: | case O_EXT_HDR: | ||||
| print_ext6hdr(bp, cmd); | print_ext6hdr(bp, cmd); | ||||
| break; | break; | ||||
| case O_TAGGED: | case O_TAGGED: | ||||
| if (F_LEN(cmd) == 1) | if (F_LEN(cmd) == 1) | ||||
| bprint_uint_arg(bp, " tagged ", cmd->arg1); | bprint_uint_arg(bp, " tagged ", cmd->arg1); | ||||
| else | else | ||||
| print_newports(bp, insntod(cmd, u16), | print_newports(bp, insntoc(cmd, u16), | ||||
| 0, O_TAGGED); | 0, O_TAGGED); | ||||
| break; | break; | ||||
| case O_SKIP_ACTION: | case O_SKIP_ACTION: | ||||
| bprintf(bp, " defer-immediate-action"); | bprintf(bp, " defer-immediate-action"); | ||||
| break; | break; | ||||
| case O_MARK: | case O_MARK: | ||||
| bprintf(bp, " mark"); | bprintf(bp, " mark"); | ||||
| if (cmd->arg1 == IP_FW_TARG) | if (cmd->arg1 == IP_FW_TARG) | ||||
| bprintf(bp, " tablearg"); | bprintf(bp, " tablearg"); | ||||
| else | else | ||||
| bprintf(bp, " %#x", | bprintf(bp, " %#x", insntoc(cmd, u32)->d[0]); | ||||
| ((const ipfw_insn_u32 *)cmd)->d[0]); | |||||
| if (((const ipfw_insn_u32 *)cmd)->d[1] != 0xFFFFFFFF) | if (insntoc(cmd, u32)->d[1] != 0xFFFFFFFF) | ||||
| bprintf(bp, ":%#x", | bprintf(bp, ":%#x", insntoc(cmd, u32)->d[1]); | ||||
| ((const ipfw_insn_u32 *)cmd)->d[1]); | |||||
| break; | break; | ||||
| default: | default: | ||||
| bprintf(bp, " [opcode %d len %d]", cmd->opcode, | bprintf(bp, " [opcode %d len %d]", cmd->opcode, | ||||
| cmd->len); | cmd->len); | ||||
| } | } | ||||
| if (cmd->len & F_OR) { | if (cmd->len & F_OR) { | ||||
| bprintf(bp, " or"); | bprintf(bp, " or"); | ||||
| Show All 36 Lines | |||||
| print_fwd(struct buf_pr *bp, const ipfw_insn *cmd) | print_fwd(struct buf_pr *bp, const ipfw_insn *cmd) | ||||
| { | { | ||||
| char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2]; | char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2]; | ||||
| const ipfw_insn_sa6 *sa6; | const ipfw_insn_sa6 *sa6; | ||||
| const ipfw_insn_sa *sa; | const ipfw_insn_sa *sa; | ||||
| uint16_t port; | uint16_t port; | ||||
| if (cmd->opcode == O_FORWARD_IP) { | if (cmd->opcode == O_FORWARD_IP) { | ||||
| sa = insntod(cmd, sa); | sa = insntoc(cmd, sa); | ||||
| port = sa->sa.sin_port; | port = sa->sa.sin_port; | ||||
| if (sa->sa.sin_addr.s_addr == INADDR_ANY) | if (sa->sa.sin_addr.s_addr == INADDR_ANY) | ||||
| bprintf(bp, "fwd tablearg"); | bprintf(bp, "fwd tablearg"); | ||||
| else | else | ||||
| bprintf(bp, "fwd %s", inet_ntoa(sa->sa.sin_addr)); | bprintf(bp, "fwd %s", inet_ntoa(sa->sa.sin_addr)); | ||||
| } else { | } else { | ||||
| sa6 = insntod(cmd, sa6); | sa6 = insntoc(cmd, sa6); | ||||
| port = sa6->sa.sin6_port; | port = sa6->sa.sin6_port; | ||||
| bprintf(bp, "fwd "); | bprintf(bp, "fwd "); | ||||
| if (getnameinfo((const struct sockaddr *)&sa6->sa, | if (getnameinfo((const struct sockaddr *)&sa6->sa, | ||||
| sizeof(struct sockaddr_in6), buf, sizeof(buf), NULL, 0, | sizeof(struct sockaddr_in6), buf, sizeof(buf), NULL, 0, | ||||
| NI_NUMERICHOST) == 0) | NI_NUMERICHOST) == 0) | ||||
| bprintf(bp, "%s", buf); | bprintf(bp, "%s", buf); | ||||
| } | } | ||||
| if (port != 0) | if (port != 0) | ||||
| bprintf(bp, ",%u", port); | bprintf(bp, ",%u", port); | ||||
| } | } | ||||
| static void | |||||
| print_logdst(struct buf_pr *bp, uint16_t arg1) | |||||
| { | |||||
| char const *comma = ""; | |||||
| bprintf(bp, " logdst ", arg1); | |||||
| if (arg1 & IPFW_LOG_SYSLOG) { | |||||
| bprintf(bp, "%ssyslog", comma); | |||||
| comma = ","; | |||||
| } | |||||
| if (arg1 & IPFW_LOG_IPFW0) { | |||||
| bprintf(bp, "%sipfw0", comma); | |||||
| comma = ","; | |||||
| } | |||||
| if (arg1 & IPFW_LOG_RTSOCK) { | |||||
| bprintf(bp, "%srtsock", comma); | |||||
| comma = ","; | |||||
| } | |||||
| } | |||||
| static int | static int | ||||
| print_action_instruction(struct buf_pr *bp, const struct format_opts *fo, | print_action_instruction(struct buf_pr *bp, const struct format_opts *fo, | ||||
| struct show_state *state, const ipfw_insn *cmd) | struct show_state *state, const ipfw_insn *cmd) | ||||
| { | { | ||||
| const char *s; | const char *s; | ||||
| if (is_printed_opcode(state, cmd)) | if (is_printed_opcode(state, cmd)) | ||||
| return (0); | return (0); | ||||
| 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) | if (insntoc(cmd, kidx)->kidx != 0) | ||||
| s = object_search_ctlv(fo->tstate, cmd->arg1, | s = object_search_ctlv(fo->tstate, | ||||
| insntoc(cmd, kidx)->kidx, | |||||
| IPFW_TLV_STATE_NAME); | IPFW_TLV_STATE_NAME); | ||||
| else | else | ||||
| s = NULL; | s = NULL; | ||||
| bprintf(bp, " :%s", s ? s: "any"); | bprintf(bp, " :%s", s ? s: "any"); | ||||
| break; | break; | ||||
| case O_ACCEPT: | case O_ACCEPT: | ||||
| bprintf(bp, "allow"); | bprintf(bp, "allow"); | ||||
| break; | break; | ||||
| case O_COUNT: | case O_COUNT: | ||||
| bprintf(bp, "count"); | bprintf(bp, "count"); | ||||
| break; | break; | ||||
| case O_DENY: | case O_DENY: | ||||
| bprintf(bp, "deny"); | bprintf(bp, "deny"); | ||||
| break; | break; | ||||
| case O_REJECT: | case O_REJECT: | ||||
| if (cmd->arg1 == ICMP_REJECT_RST) | if (cmd->arg1 == ICMP_REJECT_RST) | ||||
| bprintf(bp, "reset"); | bprintf(bp, "reset"); | ||||
| else if (cmd->arg1 == ICMP_REJECT_ABORT) | else if (cmd->arg1 == ICMP_REJECT_ABORT) | ||||
| bprintf(bp, "abort"); | bprintf(bp, "abort"); | ||||
| else if (cmd->arg1 == ICMP_UNREACH_HOST) | else if (cmd->arg1 == ICMP_UNREACH_HOST) | ||||
| bprintf(bp, "reject"); | bprintf(bp, "reject"); | ||||
| else if (cmd->arg1 == ICMP_UNREACH_NEEDFRAG && | else if (cmd->arg1 == ICMP_UNREACH_NEEDFRAG && | ||||
| cmd->len == F_INSN_SIZE(ipfw_insn_u16)) | cmd->len == F_INSN_SIZE(ipfw_insn_u16)) | ||||
| bprintf(bp, "needfrag %u", | bprintf(bp, "needfrag %u", | ||||
| ((const ipfw_insn_u16 *)cmd)->ports[0]); | insntoc(cmd, u16)->ports[0]); | ||||
| else | else | ||||
| print_reject_code(bp, cmd->arg1); | print_reject_code(bp, cmd->arg1); | ||||
| break; | break; | ||||
| case O_UNREACH6: | case O_UNREACH6: | ||||
| if (cmd->arg1 == ICMP6_UNREACH_RST) | if (cmd->arg1 == ICMP6_UNREACH_RST) | ||||
| bprintf(bp, "reset6"); | bprintf(bp, "reset6"); | ||||
| else if (cmd->arg1 == ICMP6_UNREACH_ABORT) | else if (cmd->arg1 == ICMP6_UNREACH_ABORT) | ||||
| bprintf(bp, "abort6"); | bprintf(bp, "abort6"); | ||||
| else | else | ||||
| print_unreach6_code(bp, cmd->arg1); | print_unreach6_code(bp, cmd->arg1); | ||||
| break; | break; | ||||
| case O_SKIPTO: | case O_SKIPTO: | ||||
| bprint_uint_arg(bp, "skipto ", cmd->arg1); | bprint_uint_arg(bp, "skipto ", insntoc(cmd, u32)->d[0]); | ||||
| break; | break; | ||||
| case O_PIPE: | case O_PIPE: | ||||
| bprint_uint_arg(bp, "pipe ", cmd->arg1); | bprint_uint_arg(bp, "pipe ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_QUEUE: | case O_QUEUE: | ||||
| bprint_uint_arg(bp, "queue ", cmd->arg1); | bprint_uint_arg(bp, "queue ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_DIVERT: | case O_DIVERT: | ||||
| bprint_uint_arg(bp, "divert ", cmd->arg1); | bprint_uint_arg(bp, "divert ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_TEE: | case O_TEE: | ||||
| bprint_uint_arg(bp, "tee ", cmd->arg1); | bprint_uint_arg(bp, "tee ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_NETGRAPH: | case O_NETGRAPH: | ||||
| bprint_uint_arg(bp, "netgraph ", cmd->arg1); | bprint_uint_arg(bp, "netgraph ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_NGTEE: | case O_NGTEE: | ||||
| bprint_uint_arg(bp, "ngtee ", cmd->arg1); | bprint_uint_arg(bp, "ngtee ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_FORWARD_IP: | case O_FORWARD_IP: | ||||
| case O_FORWARD_IP6: | case O_FORWARD_IP6: | ||||
| print_fwd(bp, cmd); | print_fwd(bp, cmd); | ||||
| break; | break; | ||||
| case O_LOG: | case O_LOG: | ||||
| if (insntod(cmd, log)->max_log > 0) | |||||
| bprintf(bp, " log logamount %d", | |||||
| insntod(cmd, log)->max_log); | |||||
| else | |||||
| bprintf(bp, " log"); | bprintf(bp, " log"); | ||||
| if (insntoc(cmd, log)->max_log > 0) | |||||
| bprintf(bp, " logamount %d", | |||||
| insntoc(cmd, log)->max_log); | |||||
| if (cmd->arg1 != IPFW_LOG_DEFAULT) | |||||
| print_logdst(bp, cmd->arg1); | |||||
| break; | break; | ||||
| case O_ALTQ: | case O_ALTQ: | ||||
| #ifndef NO_ALTQ | #ifndef NO_ALTQ | ||||
| print_altq_cmd(bp, insntod(cmd, altq)); | print_altq_cmd(bp, insntoc(cmd, altq)); | ||||
| #endif | #endif | ||||
| break; | break; | ||||
| case O_TAG: | case O_TAG: | ||||
| bprint_uint_arg(bp, cmd->len & F_NOT ? " untag ": | bprint_uint_arg(bp, cmd->len & F_NOT ? " untag ": | ||||
| " tag ", cmd->arg1); | " tag ", cmd->arg1); | ||||
| break; | break; | ||||
| case O_NAT: | case O_NAT: | ||||
| if (cmd->arg1 != IP_FW_NAT44_GLOBAL) | if (cmd->arg1 != IP_FW_NAT44_GLOBAL) | ||||
| Show All 12 Lines | case O_EXTERNAL_ACTION: | ||||
| * 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. | ||||
| */ | */ | ||||
| state->eaction = cmd; | state->eaction = insntoc(cmd, kidx); | ||||
| s = object_search_ctlv(fo->tstate, cmd->arg1, | s = object_search_ctlv(fo->tstate, | ||||
| state->eaction->kidx, | |||||
| IPFW_TLV_EACTION); | IPFW_TLV_EACTION); | ||||
| if (match_token(rule_eactions, s) != -1) | if (match_token(rule_eactions, s) != -1) | ||||
| bprintf(bp, "%s", s); | bprintf(bp, "%s", s); | ||||
| else | else | ||||
| bprintf(bp, "eaction %s", s); | bprintf(bp, "eaction %s", s); | ||||
| break; | break; | ||||
| case O_EXTERNAL_INSTANCE: | case O_EXTERNAL_INSTANCE: | ||||
| if (state->eaction == NULL) | if (state->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 | ||||
| * name with zero type. But when we do `ipfw show` | * name with zero type. But when we do `ipfw show` | ||||
| * we calculate TLV type using IPFW_TLV_EACTION_NAME() | * we calculate TLV type using IPFW_TLV_EACTION_NAME() | ||||
| * macro. | * macro. | ||||
| */ | */ | ||||
| s = object_search_ctlv(fo->tstate, cmd->arg1, 0); | s = object_search_ctlv(fo->tstate, | ||||
| insntoc(cmd, kidx)->kidx, 0); | |||||
| if (s == NULL) | if (s == NULL) | ||||
| s = object_search_ctlv(fo->tstate, | s = object_search_ctlv(fo->tstate, | ||||
| cmd->arg1, IPFW_TLV_EACTION_NAME( | insntoc(cmd, kidx)->kidx, IPFW_TLV_EACTION_NAME( | ||||
| state->eaction->arg1)); | state->eaction->kidx)); | ||||
| bprintf(bp, " %s", s); | bprintf(bp, " %s", s); | ||||
| break; | break; | ||||
| case O_EXTERNAL_DATA: | case O_EXTERNAL_DATA: | ||||
| if (state->eaction == NULL) | if (state->eaction == NULL) | ||||
| break; | break; | ||||
| /* | /* | ||||
| * Currently we support data formatting only for | * Currently we support data formatting only for | ||||
| * external data with datalen u16. For unknown data | * external data with datalen u16. For unknown data | ||||
| Show All 15 Lines | if (s != NULL) | ||||
| bprintf(bp, "setdscp %s", s); | bprintf(bp, "setdscp %s", s); | ||||
| else | else | ||||
| bprintf(bp, "setdscp %u", cmd->arg1 & 0x3F); | bprintf(bp, "setdscp %u", cmd->arg1 & 0x3F); | ||||
| break; | break; | ||||
| case O_REASS: | case O_REASS: | ||||
| bprintf(bp, "reass"); | bprintf(bp, "reass"); | ||||
| break; | break; | ||||
| case O_CALLRETURN: | case O_CALLRETURN: | ||||
| if (cmd->len & F_NOT) | if (cmd->len & F_NOT) { | ||||
| bprintf(bp, "return"); | s = match_value(return_types, cmd->arg1); | ||||
| else | bprintf(bp, "return %s", s ? s: "<invalid>"); | ||||
| bprint_uint_arg(bp, "call ", cmd->arg1); | } else | ||||
| bprint_uint_arg(bp, "call ", insntoc(cmd, u32)->d[0]); | |||||
| break; | break; | ||||
| case O_SETMARK: | case O_SETMARK: | ||||
| if (cmd->arg1 == IP_FW_TARG) { | if (cmd->arg1 == IP_FW_TARG) { | ||||
| bprintf(bp, "setmark tablearg"); | bprintf(bp, "setmark tablearg"); | ||||
| break; | break; | ||||
| } | } | ||||
| bprintf(bp, "setmark %#x", ((const ipfw_insn_u32 *)cmd)->d[0]); | bprintf(bp, "setmark %#x", insntoc(cmd, u32)->d[0]); | ||||
| break; | break; | ||||
| default: | default: | ||||
| bprintf(bp, "** unrecognized action %d len %d ", | bprintf(bp, "** unrecognized action %d len %d ", | ||||
| cmd->opcode, cmd->len); | cmd->opcode, cmd->len); | ||||
| } | } | ||||
| mark_printed(state, cmd); | mark_printed(state, cmd); | ||||
| return (1); | return (1); | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | print_address(struct buf_pr *bp, struct format_opts *fo, | ||||
| int flag) | int flag) | ||||
| { | { | ||||
| ipfw_insn *cmd; | ipfw_insn *cmd; | ||||
| int count, l, portcnt, pf; | int count, l, portcnt, pf; | ||||
| count = portcnt = 0; | count = portcnt = 0; | ||||
| for (l = state->rule->act_ofs, cmd = state->rule->cmd; | for (l = state->rule->act_ofs, cmd = state->rule->cmd; | ||||
| l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { | l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { | ||||
| if (match_opcode(cmd->opcode, opcodes, nops)) | if (match_opcode(cmd->opcode, opcodes, nops)) { | ||||
| /* | |||||
| * Special handling for O_IP_DST_LOOKUP when | |||||
| * lookup type is not LOOKUP_NONE. | |||||
| */ | |||||
| if (cmd->opcode == O_IP_DST_LOOKUP && | |||||
| IPFW_LOOKUP_TYPE(cmd) != LOOKUP_NONE) | |||||
| continue; | |||||
| count++; | count++; | ||||
| else if (cmd->opcode == portop) | } else if (cmd->opcode == portop) | ||||
| portcnt++; | portcnt++; | ||||
| } | } | ||||
| if (count == 0) | if (count == 0) | ||||
| bprintf(bp, " any"); | bprintf(bp, " any"); | ||||
| for (l = state->rule->act_ofs, cmd = state->rule->cmd; | for (l = state->rule->act_ofs, cmd = state->rule->cmd; | ||||
| l > 0 && count > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { | l > 0 && count > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { | ||||
| if (!match_opcode(cmd->opcode, opcodes, nops)) | if (!match_opcode(cmd->opcode, opcodes, nops)) | ||||
| continue; | continue; | ||||
| Show All 40 Lines | static const int src_opcodes[] = { | ||||
| O_IP_SRC_SET, O_IP6_SRC, O_IP6_SRC_MASK, O_IP6_SRC_ME | O_IP_SRC_SET, O_IP6_SRC, O_IP6_SRC_MASK, O_IP6_SRC_ME | ||||
| }; | }; | ||||
| static const int dst_opcodes[] = { | static const int dst_opcodes[] = { | ||||
| O_IP_DST, O_IP_DST_LOOKUP, O_IP_DST_MASK, O_IP_DST_ME, | O_IP_DST, O_IP_DST_LOOKUP, O_IP_DST_MASK, O_IP_DST_ME, | ||||
| O_IP_DST_SET, O_IP6_DST, O_IP6_DST_MASK, O_IP6_DST_ME | O_IP_DST_SET, O_IP6_DST, O_IP6_DST_MASK, O_IP6_DST_ME | ||||
| }; | }; | ||||
| #if IPFW_DEFAULT_RULE > 65535 | |||||
| #define RULENUM_FORMAT "%06d" | |||||
| #else | |||||
| #define RULENUM_FORMAT "%05d" | |||||
| #endif | |||||
| 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; | ||||
| struct show_state state; | struct show_state state; | ||||
| ipfw_insn *cmd; | ipfw_insn *cmd; | ||||
| size_t i; | size_t i; | ||||
| /* Print # DISABLED or skip the rule */ | /* Print # DISABLED or skip the rule */ | ||||
| if ((fo->set_mask & (1 << rule->set)) == 0) { | if ((fo->set_mask & (1 << rule->set)) == 0) { | ||||
| /* disabled mask */ | /* disabled mask */ | ||||
| if (!co->show_sets) | if (!co->show_sets) | ||||
| return; | return; | ||||
| else | else | ||||
| bprintf(bp, "# DISABLED "); | bprintf(bp, "# DISABLED "); | ||||
| } | } | ||||
| if (init_show_state(&state, rule) != 0) { | if (init_show_state(&state, rule) != 0) { | ||||
| warn("init_show_state() failed"); | warn("init_show_state() failed"); | ||||
| return; | return; | ||||
| } | } | ||||
| bprintf(bp, "%05u ", rule->rulenum); | |||||
| bprintf(bp, RULENUM_FORMAT " ", rule->rulenum); | |||||
| /* only if counters are available */ | /* only if counters are available */ | ||||
| if (cntr != NULL) { | if (cntr != NULL) { | ||||
| /* Print counters if enabled */ | /* Print counters if enabled */ | ||||
| if (fo->pcwidth > 0 || fo->bcwidth > 0) { | if (fo->pcwidth > 0 || fo->bcwidth > 0) { | ||||
| pr_u64(bp, &cntr->pcnt, fo->pcwidth); | pr_u64(bp, &cntr->pcnt, fo->pcwidth); | ||||
| pr_u64(bp, &cntr->bcnt, fo->bcwidth); | pr_u64(bp, &cntr->bcnt, fo->bcwidth); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| static void | static void | ||||
| show_dyn_state(struct cmdline_opts *co, struct format_opts *fo, | show_dyn_state(struct cmdline_opts *co, struct format_opts *fo, | ||||
| struct buf_pr *bp, ipfw_dyn_rule *d) | struct buf_pr *bp, ipfw_dyn_rule *d) | ||||
| { | { | ||||
| struct protoent *pe; | struct protoent *pe; | ||||
| struct in_addr a; | struct in_addr a; | ||||
| uint16_t rulenum; | |||||
| char buf[INET6_ADDRSTRLEN]; | char buf[INET6_ADDRSTRLEN]; | ||||
| if (d->expire == 0 && d->dyn_type != O_LIMIT_PARENT) | if (!d->expire && !(d->type == O_LIMIT_PARENT)) | ||||
| return; | return; | ||||
| bcopy(&d->rule, &rulenum, sizeof(rulenum)); | bprintf(bp, RULENUM_FORMAT, d->rulenum); | ||||
| bprintf(bp, "%05d", rulenum); | |||||
| if (fo->pcwidth > 0 || fo->bcwidth > 0) { | if (fo->pcwidth > 0 || fo->bcwidth > 0) { | ||||
| bprintf(bp, " "); | bprintf(bp, " "); | ||||
| pr_u64(bp, &d->pcnt, fo->pcwidth); | pr_u64(bp, &d->pcnt, fo->pcwidth); | ||||
| pr_u64(bp, &d->bcnt, fo->bcwidth); | pr_u64(bp, &d->bcnt, fo->bcwidth); | ||||
| bprintf(bp, "(%ds)", d->expire); | bprintf(bp, "(%ds)", d->expire); | ||||
| } | } | ||||
| switch (d->dyn_type) { | switch (d->type) { | ||||
| case O_LIMIT_PARENT: | case O_LIMIT_PARENT: | ||||
| bprintf(bp, " PARENT %d", d->count); | bprintf(bp, " PARENT %u", d->count); | ||||
| break; | break; | ||||
| case O_LIMIT: | case O_LIMIT: | ||||
| bprintf(bp, " LIMIT"); | bprintf(bp, " LIMIT"); | ||||
| break; | break; | ||||
| case O_KEEP_STATE: /* bidir, no mask */ | case O_KEEP_STATE: /* bidir, no mask */ | ||||
| bprintf(bp, " STATE"); | bprintf(bp, " STATE"); | ||||
| break; | break; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
| * ipfw set move rule X to Y | * ipfw set move rule X to Y | ||||
| */ | */ | ||||
| void | void | ||||
| ipfw_sets_handler(char *av[]) | ipfw_sets_handler(char *av[]) | ||||
| { | { | ||||
| ipfw_range_tlv rt; | ipfw_range_tlv rt; | ||||
| const char *msg; | const char *msg; | ||||
| size_t size; | size_t size; | ||||
| uint32_t masks[2]; | uint32_t masks[2], rulenum; | ||||
| int i; | int i; | ||||
| uint16_t rulenum; | |||||
| uint8_t cmd; | uint8_t cmd; | ||||
| av++; | av++; | ||||
| memset(&rt, 0, sizeof(rt)); | memset(&rt, 0, sizeof(rt)); | ||||
| if (av[0] == NULL) | if (av[0] == NULL) | ||||
| errx(EX_USAGE, "set needs command"); | errx(EX_USAGE, "set needs command"); | ||||
| if (_substrcmp(*av, "show") == 0) { | if (_substrcmp(*av, "show") == 0) { | ||||
| Show All 34 Lines | if (av[0] && _substrcmp(*av, "rule") == 0) { | ||||
| rt.flags = IPFW_RCFLAG_RANGE; /* move rules to new set */ | rt.flags = IPFW_RCFLAG_RANGE; /* move rules to new set */ | ||||
| cmd = IP_FW_XMOVE; | cmd = IP_FW_XMOVE; | ||||
| av++; | av++; | ||||
| } else | } else | ||||
| cmd = IP_FW_SET_MOVE; /* Move set to new one */ | cmd = IP_FW_SET_MOVE; /* Move set to new one */ | ||||
| if (av[0] == NULL || av[1] == NULL || av[2] == NULL || | if (av[0] == NULL || av[1] == NULL || av[2] == NULL || | ||||
| av[3] != NULL || _substrcmp(av[1], "to") != 0) | av[3] != NULL || _substrcmp(av[1], "to") != 0) | ||||
| errx(EX_USAGE, "syntax: set move [rule] X to Y\n"); | errx(EX_USAGE, "syntax: set move [rule] X to Y\n"); | ||||
| rulenum = atoi(av[0]); | rulenum = (uint32_t)strtoul(av[0], NULL, 10); | ||||
| rt.new_set = atoi(av[2]); | rt.new_set = atoi(av[2]); | ||||
| if (cmd == IP_FW_XMOVE) { | if (cmd == IP_FW_XMOVE) { | ||||
| rt.start_rule = rulenum; | rt.start_rule = rulenum; | ||||
| rt.end_rule = rulenum; | rt.end_rule = rulenum; | ||||
| } else | } else | ||||
| rt.set = rulenum; | rt.set = rulenum; | ||||
| rt.new_set = atoi(av[2]); | rt.new_set = atoi(av[2]); | ||||
| if (!isdigit(*(av[0])) || (cmd == 3 && rt.set > RESVD_SET) || | if (!isdigit(*(av[0])) || (cmd == 3 && rt.set > RESVD_SET) || | ||||
| Show All 36 Lines | if (_substrcmp(*av, "show") == 0) { | ||||
| rt.new_set = masks[1]; | rt.new_set = masks[1]; | ||||
| i = do_range_cmd(IP_FW_SET_ENABLE, &rt); | i = do_range_cmd(IP_FW_SET_ENABLE, &rt); | ||||
| if (i) | if (i) | ||||
| warn("set enable/disable: setsockopt(IP_FW_SET_ENABLE)"); | warn("set enable/disable: setsockopt(IP_FW_SET_ENABLE)"); | ||||
| } else | } else | ||||
| errx(EX_USAGE, "invalid set command %s\n", *av); | errx(EX_USAGE, "invalid set command %s\n", *av); | ||||
| } | } | ||||
| static void | |||||
| manage_skipto_cache(int op) | |||||
| { | |||||
| ipfw_cmd_header req; | |||||
| memset(&req, 0, sizeof(req)); | |||||
| req.size = sizeof(req); | |||||
| req.cmd = op ? SKIPTO_CACHE_ENABLE : SKIPTO_CACHE_DISABLE; | |||||
| do_set3(IP_FW_SKIPTO_CACHE, &req.opheader, sizeof(req)); | |||||
| } | |||||
| void | void | ||||
| ipfw_sysctl_handler(char *av[], int which) | ipfw_sysctl_handler(char *av[], int which) | ||||
| { | { | ||||
| av++; | av++; | ||||
| if (av[0] == NULL) { | if (av[0] == NULL) { | ||||
| warnx("missing keyword to enable/disable\n"); | warnx("missing keyword to enable/disable\n"); | ||||
| } else if (_substrcmp(*av, "firewall") == 0) { | } else if (_substrcmp(*av, "firewall") == 0) { | ||||
| sysctlbyname("net.inet.ip.fw.enable", NULL, 0, | sysctlbyname("net.inet.ip.fw.enable", NULL, 0, | ||||
| &which, sizeof(which)); | &which, sizeof(which)); | ||||
| sysctlbyname("net.inet6.ip6.fw.enable", NULL, 0, | sysctlbyname("net.inet6.ip6.fw.enable", NULL, 0, | ||||
| &which, sizeof(which)); | &which, sizeof(which)); | ||||
| } else if (_substrcmp(*av, "one_pass") == 0) { | } else if (_substrcmp(*av, "one_pass") == 0) { | ||||
| sysctlbyname("net.inet.ip.fw.one_pass", NULL, 0, | sysctlbyname("net.inet.ip.fw.one_pass", NULL, 0, | ||||
| &which, sizeof(which)); | &which, sizeof(which)); | ||||
| } else if (_substrcmp(*av, "debug") == 0) { | } else if (_substrcmp(*av, "debug") == 0) { | ||||
| sysctlbyname("net.inet.ip.fw.debug", NULL, 0, | sysctlbyname("net.inet.ip.fw.debug", NULL, 0, | ||||
| &which, sizeof(which)); | &which, sizeof(which)); | ||||
| } else if (_substrcmp(*av, "verbose") == 0) { | } else if (_substrcmp(*av, "verbose") == 0) { | ||||
| sysctlbyname("net.inet.ip.fw.verbose", NULL, 0, | sysctlbyname("net.inet.ip.fw.verbose", NULL, 0, | ||||
| &which, sizeof(which)); | &which, sizeof(which)); | ||||
| } else if (_substrcmp(*av, "dyn_keepalive") == 0) { | } else if (_substrcmp(*av, "dyn_keepalive") == 0) { | ||||
| sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0, | sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0, | ||||
| &which, sizeof(which)); | &which, sizeof(which)); | ||||
| } else if (_substrcmp(*av, "skipto_cache") == 0) { | |||||
| manage_skipto_cache(which); | |||||
| #ifndef NO_ALTQ | #ifndef NO_ALTQ | ||||
| } else if (_substrcmp(*av, "altq") == 0) { | } else if (_substrcmp(*av, "altq") == 0) { | ||||
| altq_set_enabled(which); | altq_set_enabled(which); | ||||
| #endif | #endif | ||||
| } else { | } else { | ||||
| warnx("unrecognize enable/disable keyword: %s\n", *av); | warnx("unrecognize enable/disable keyword: %s\n", *av); | ||||
| } | } | ||||
| } | } | ||||
| typedef void state_cb(struct cmdline_opts *co, struct format_opts *fo, | typedef void state_cb(struct cmdline_opts *co, struct format_opts *fo, | ||||
| void *arg, void *state); | void *arg, void *state); | ||||
| static void | static void | ||||
| prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo, | prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo, | ||||
| void *arg __unused, void *_state) | void *arg __unused, void *_state) | ||||
| { | { | ||||
| ipfw_dyn_rule *d; | ipfw_dyn_rule *d; | ||||
| int width; | int width; | ||||
| uint8_t set; | |||||
| d = (ipfw_dyn_rule *)_state; | d = (ipfw_dyn_rule *)_state; | ||||
| /* Count _ALL_ states */ | /* Count _ALL_ states */ | ||||
| fo->dcnt++; | fo->dcnt++; | ||||
| if (fo->show_counters == 0) | if (fo->show_counters == 0) | ||||
| return; | return; | ||||
| if (co->use_set) { | |||||
| /* skip states from another set */ | /* skip states from another set */ | ||||
| bcopy((char *)&d->rule + sizeof(uint16_t), &set, | if (co->use_set != 0 && d->set != co->use_set - 1) | ||||
| sizeof(uint8_t)); | |||||
| if (set != co->use_set - 1) | |||||
| return; | return; | ||||
| } | |||||
| width = pr_u64(NULL, &d->pcnt, 0); | width = pr_u64(NULL, &d->pcnt, 0); | ||||
| if (width > fo->pcwidth) | if (width > fo->pcwidth) | ||||
| fo->pcwidth = width; | fo->pcwidth = width; | ||||
| width = pr_u64(NULL, &d->bcnt, 0); | width = pr_u64(NULL, &d->bcnt, 0); | ||||
| if (width > fo->bcwidth) | if (width > fo->bcwidth) | ||||
| fo->bcwidth = width; | fo->bcwidth = width; | ||||
| ▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | list_static_range(struct cmdline_opts *co, struct format_opts *fo, | ||||
| return (seen); | return (seen); | ||||
| } | } | ||||
| static void | static void | ||||
| list_dyn_state(struct cmdline_opts *co, struct format_opts *fo, | list_dyn_state(struct cmdline_opts *co, struct format_opts *fo, | ||||
| void *_arg, void *_state) | void *_arg, void *_state) | ||||
| { | { | ||||
| uint16_t rulenum; | |||||
| uint8_t set; | |||||
| ipfw_dyn_rule *d; | ipfw_dyn_rule *d; | ||||
| struct buf_pr *bp; | struct buf_pr *bp; | ||||
| d = (ipfw_dyn_rule *)_state; | d = (ipfw_dyn_rule *)_state; | ||||
| bp = (struct buf_pr *)_arg; | bp = (struct buf_pr *)_arg; | ||||
| bcopy(&d->rule, &rulenum, sizeof(rulenum)); | if (d->rulenum > fo->last) | ||||
| if (rulenum > fo->last) | |||||
| return; | return; | ||||
| if (co->use_set) { | if (co->use_set != 0 && d->set != co->use_set - 1) | ||||
| bcopy((char *)&d->rule + sizeof(uint16_t), | |||||
| &set, sizeof(uint8_t)); | |||||
| if (set != co->use_set - 1) | |||||
| return; | return; | ||||
| } | if (d->rulenum >= fo->first) { | ||||
| if (rulenum >= fo->first) { | |||||
| show_dyn_state(co, fo, bp, d); | show_dyn_state(co, fo, bp, d); | ||||
| printf("%s\n", bp->buf); | printf("%s\n", bp->buf); | ||||
| bp_flush(bp); | bp_flush(bp); | ||||
| } | } | ||||
| } | } | ||||
| static int | static int | ||||
| list_dyn_range(struct cmdline_opts *co, struct format_opts *fo, | list_dyn_range(struct cmdline_opts *co, struct format_opts *fo, | ||||
| ▲ Show 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | 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) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static uint16_t | static uint32_t | ||||
| pack_object(struct tidx *tstate, const char *name, int otype) | pack_object(struct tidx *tstate, const char *name, int otype) | ||||
| { | { | ||||
| ipfw_obj_ntlv *ntlv; | ipfw_obj_ntlv *ntlv; | ||||
| uint32_t i; | uint32_t i; | ||||
| for (i = 0; i < tstate->count; i++) { | for (i = 0; i < tstate->count; i++) { | ||||
| if (strcmp(tstate->idx[i].name, name) != 0) | if (strcmp(tstate->idx[i].name, name) != 0) | ||||
| continue; | continue; | ||||
| Show All 20 Lines | pack_object(struct tidx *tstate, const char *name, int otype) | ||||
| ntlv->head.length = sizeof(ipfw_obj_ntlv); | ntlv->head.length = sizeof(ipfw_obj_ntlv); | ||||
| ntlv->set = tstate->set; | ntlv->set = tstate->set; | ||||
| ntlv->idx = ++tstate->counter; | ntlv->idx = ++tstate->counter; | ||||
| tstate->count++; | tstate->count++; | ||||
| return (ntlv->idx); | return (ntlv->idx); | ||||
| } | } | ||||
| static uint16_t | static uint32_t | ||||
| pack_table(struct tidx *tstate, const char *name) | pack_table(struct tidx *tstate, const char *name) | ||||
| { | { | ||||
| if (table_check_name(name) != 0) | if (table_check_name(name) != 0) | ||||
| return (0); | return (0); | ||||
| return (pack_object(tstate, name, IPFW_TLV_TBL_NAME)); | return (pack_object(tstate, name, IPFW_TLV_TBL_NAME)); | ||||
| } | } | ||||
| static void | |||||
| fill_table_value(ipfw_insn *cmd, char *s) | |||||
| { | |||||
| char *p; | |||||
| int i; | |||||
| p = strchr(s, '='); | |||||
| if (p != NULL) { | |||||
| *p++ = '\0'; | |||||
| i = match_token(tvalue_names, s); | |||||
| if (i == -1) | |||||
| errx(EX_USAGE, | |||||
| "format: unknown table value name %s", s); | |||||
| } else { | |||||
| i = TVALUE_TAG; | |||||
| p = s; | |||||
| } | |||||
| IPFW_SET_TVALUE_TYPE(cmd, i); | |||||
| insntod(cmd, table)->value = strtoul(p, NULL, 0); | |||||
| } | |||||
| void | void | ||||
| fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode, | fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate) | ||||
| struct tidx *tstate) | |||||
| { | { | ||||
| uint32_t *d = ((ipfw_insn_u32 *)cmd)->d; | ipfw_insn_kidx *c = insntod(cmd, kidx); | ||||
| uint16_t uidx; | |||||
| char *p; | char *p; | ||||
| if ((p = strchr(av + 6, ')')) == NULL) | if ((p = strchr(av + 6, ')')) == NULL) | ||||
| errx(EX_DATAERR, "forgotten parenthesis: '%s'", av); | errx(EX_DATAERR, "forgotten parenthesis: '%s'", av); | ||||
| *p = '\0'; | *p = '\0'; | ||||
| p = strchr(av + 6, ','); | p = strchr(av + 6, ','); | ||||
| if (p) | if (p) | ||||
| *p++ = '\0'; | *p++ = '\0'; | ||||
| if ((uidx = pack_table(tstate, av + 6)) == 0) | if ((c->kidx = pack_table(tstate, av + 6)) == 0) | ||||
| errx(EX_DATAERR, "Invalid table name: %s", av + 6); | errx(EX_DATAERR, "Invalid table name: %s", av + 6); | ||||
| cmd->opcode = opcode; | cmd->opcode = opcode; | ||||
| cmd->arg1 = uidx; | |||||
| if (p) { | if (p) { | ||||
| cmd->len |= F_INSN_SIZE(ipfw_insn_u32); | cmd->len |= F_INSN_SIZE(ipfw_insn_table); | ||||
| d[0] = strtoul(p, NULL, 0); | fill_table_value(cmd, p); | ||||
| } else | } else { | ||||
| cmd->len |= F_INSN_SIZE(ipfw_insn); | IPFW_SET_LOOKUP_TYPE(cmd, LOOKUP_NONE); | ||||
| cmd->len |= F_INSN_SIZE(ipfw_insn_kidx); | |||||
| } | } | ||||
| } | |||||
| /* | /* | ||||
| * fills the addr and mask fields in the instruction as appropriate from av. | * fills the addr and mask fields in the instruction as appropriate from av. | ||||
| * Update length as appropriate. | * Update length as appropriate. | ||||
| * The following formats are allowed: | * The following formats are allowed: | ||||
| * me returns O_IP_*_ME | * me returns O_IP_*_ME | ||||
| * 1.2.3.4 single IP address | * 1.2.3.4 single IP address | ||||
| * 1.2.3.4:5.6.7.8 address:mask | * 1.2.3.4:5.6.7.8 address:mask | ||||
| * 1.2.3.4/24 address/mask | * 1.2.3.4/24 address/mask | ||||
| ▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void | void | ||||
| ipfw_delete(char *av[]) | ipfw_delete(char *av[]) | ||||
| { | { | ||||
| ipfw_range_tlv rt; | ipfw_range_tlv rt; | ||||
| char *sep; | char *sep; | ||||
| int i, j; | uint32_t i, j; | ||||
| int exitval = EX_OK; | int exitval = EX_OK; | ||||
| int do_set = 0; | int do_set = 0; | ||||
| av++; | av++; | ||||
| NEED1("missing rule specification"); | NEED1("missing rule specification"); | ||||
| if ( *av && _substrcmp(*av, "set") == 0) { | if ( *av && _substrcmp(*av, "set") == 0) { | ||||
| /* Do not allow using the following syntax: | /* Do not allow using the following syntax: | ||||
| * ipfw set N delete set M | * ipfw set N delete set M | ||||
| Show All 16 Lines | while (*av && isdigit(**av)) { | ||||
| } else if (g_co.do_pipe) { | } else if (g_co.do_pipe) { | ||||
| exitval = ipfw_delete_pipe(g_co.do_pipe, i); | exitval = ipfw_delete_pipe(g_co.do_pipe, i); | ||||
| } else { | } else { | ||||
| memset(&rt, 0, sizeof(rt)); | memset(&rt, 0, sizeof(rt)); | ||||
| if (do_set != 0) { | if (do_set != 0) { | ||||
| rt.set = i & 31; | rt.set = i & 31; | ||||
| rt.flags = IPFW_RCFLAG_SET; | rt.flags = IPFW_RCFLAG_SET; | ||||
| } else { | } else { | ||||
| rt.start_rule = i & 0xffff; | rt.start_rule = i; | ||||
| rt.end_rule = j & 0xffff; | rt.end_rule = j; | ||||
| if (rt.start_rule == 0 && rt.end_rule == 0) | if (rt.start_rule == 0 && rt.end_rule == 0) | ||||
| rt.flags |= IPFW_RCFLAG_ALL; | rt.flags |= IPFW_RCFLAG_ALL; | ||||
| else | else | ||||
| rt.flags |= IPFW_RCFLAG_RANGE; | rt.flags |= IPFW_RCFLAG_RANGE; | ||||
| if (g_co.use_set != 0) { | if (g_co.use_set != 0) { | ||||
| rt.set = g_co.use_set - 1; | rt.set = g_co.use_set - 1; | ||||
| rt.flags |= IPFW_RCFLAG_SET; | rt.flags |= IPFW_RCFLAG_SET; | ||||
| } | } | ||||
| Show All 20 Lines | if (g_co.do_nat) { | ||||
| rt.start_rule); | rt.start_rule); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (exitval != EX_OK && g_co.do_force == 0) | if (exitval != EX_OK && g_co.do_force == 0) | ||||
| exit(exitval); | exit(exitval); | ||||
| } | } | ||||
| /* | /* | ||||
| * fill the interface structure. We do not check the name as we can | * fill the interface structure. We do not check the name as we can | ||||
| * create interfaces dynamically, so checking them at insert time | * create interfaces dynamically, so checking them at insert time | ||||
| * makes relatively little sense. | * makes relatively little sense. | ||||
| * Interface names containing '*', '?', or '[' are assumed to be shell | * Interface names containing '*', '?', or '[' are assumed to be shell | ||||
| * patterns which match interfaces. | * patterns which match interfaces. | ||||
| */ | */ | ||||
| static void | static void | ||||
| fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate) | fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate) | ||||
| { | { | ||||
| char *p; | char *p; | ||||
| uint16_t uidx; | uint32_t uidx; | ||||
| cmd->name[0] = '\0'; | cmd->name[0] = '\0'; | ||||
| cmd->o.len |= F_INSN_SIZE(ipfw_insn_if); | cmd->o.len |= F_INSN_SIZE(ipfw_insn_if); | ||||
| CHECK_CMDLEN; | CHECK_CMDLEN; | ||||
| /* Parse the interface or address */ | /* Parse the interface or address */ | ||||
| if (strcmp(arg, "any") == 0) | if (strcmp(arg, "any") == 0) | ||||
| ▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | static struct _s_x f_reserved_keywords[] = { | ||||
| { "icmptypes", TOK_OR }, | { "icmptypes", TOK_OR }, | ||||
| { "in", TOK_OR }, | { "in", TOK_OR }, | ||||
| { "out", TOK_OR }, | { "out", TOK_OR }, | ||||
| { "ip6", TOK_OR }, | { "ip6", TOK_OR }, | ||||
| { "any", TOK_OR }, | { "any", TOK_OR }, | ||||
| { "to", TOK_OR }, | { "to", TOK_OR }, | ||||
| { "via", TOK_OR }, | { "via", TOK_OR }, | ||||
| { "{", TOK_OR }, | { "{", TOK_OR }, | ||||
| { "lookup", TOK_OR }, | |||||
| { "tagged", TOK_OR }, | |||||
| { NULL, 0 } /* terminator */ | { NULL, 0 } /* terminator */ | ||||
| }; | }; | ||||
| static ipfw_insn * | static ipfw_insn * | ||||
| add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode, int cblen) | add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode, int cblen) | ||||
| { | { | ||||
| if (match_token(f_reserved_keywords, av) != -1) | if (match_token(f_reserved_keywords, av) != -1) | ||||
| ▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || | ||||
| inet_pton(AF_INET6, host, &a) != 1)) | inet_pton(AF_INET6, host, &a) != 1)) | ||||
| ret = add_dstip(cmd, av, cblen, tstate); | ret = add_dstip(cmd, av, cblen, tstate); | ||||
| if (ret == NULL && strcmp(av, "any") != 0) | if (ret == NULL && strcmp(av, "any") != 0) | ||||
| ret = cmd; | ret = cmd; | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| static inline int | static uint16_t | ||||
| parse_logdst(char *logdst_iter) | |||||
| { | |||||
| char *token; | |||||
| uint16_t ret; | |||||
| ret = IPFW_LOG_DEFAULT; | |||||
| while ((token = strsep(&logdst_iter, ",")) != NULL) { | |||||
| if (_substrcmp(token, "syslog") == 0) { | |||||
| ret |= IPFW_LOG_SYSLOG; | |||||
| continue; | |||||
| } | |||||
| if (_substrcmp(token, "ipfw0") == 0) { | |||||
| /* XXX add multiple ipfw* */ | |||||
| ret |= IPFW_LOG_IPFW0; | |||||
| continue; | |||||
| } | |||||
| if (_substrcmp(token, "rtsock") == 0) { | |||||
| ret |= IPFW_LOG_RTSOCK; | |||||
| continue; | |||||
| } | |||||
| errx(EX_DATAERR, | |||||
| "unsupported logdst token"); | |||||
| } | |||||
| return (ret); | |||||
| } | |||||
| static inline uint32_t | |||||
| arg_or_targ_relaxed(const char *arg, const char *action) | arg_or_targ_relaxed(const char *arg, const char *action) | ||||
| { | { | ||||
| uint32_t arg1 = (uint32_t)(-1); | uint32_t arg1 = (uint32_t)(-1); | ||||
| if (arg == NULL) | if (arg == NULL) | ||||
| errx(EX_USAGE, "missing argument for %s", action); | errx(EX_USAGE, "missing argument for %s", action); | ||||
| if (isdigit(arg[0])) { | if (isdigit(arg[0])) { | ||||
| arg1 = strtoul(arg, NULL, 10); | arg1 = strtoul(arg, NULL, 10); | ||||
| if (arg1 <= 0 || arg1 >= IP_FW_TABLEARG) | if (arg1 <= 0 || arg1 >= IP_FW_TABLEARG) | ||||
| errx(EX_DATAERR, "illegal argument %s(%u) for %s", | errx(EX_DATAERR, "illegal argument %s(%u) for %s", | ||||
| arg, arg1, action); | arg, arg1, action); | ||||
| } else if (_substrcmp(arg, "tablearg") == 0) | } else if (_substrcmp(arg, "tablearg") == 0) | ||||
| arg1 = IP_FW_TARG; | arg1 = IP_FW_TARG; | ||||
| return (arg1); | return (arg1); | ||||
| } | } | ||||
| static inline uint16_t | static inline uint32_t | ||||
| arg_or_targ(const char *arg, const char *action) | arg_or_targ(const char *arg, const char *action) | ||||
| { | { | ||||
| uint32_t arg1 = arg_or_targ_relaxed(arg, action); | uint32_t arg1 = arg_or_targ_relaxed(arg, action); | ||||
| if (arg1 == (uint32_t)(-1)) | if (arg1 == (uint32_t)(-1)) | ||||
| errx(EX_DATAERR, "illegal argument %s(%u) for %s", | errx(EX_DATAERR, "illegal argument %s(%u) for %s", | ||||
| arg, arg1, action); | arg, arg1, action); | ||||
| return (arg1); | return (arg1); | ||||
| ▲ Show 20 Lines • Show All 111 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; | ||||
| action->len = F_INSN_SIZE(ipfw_insn_kidx); | |||||
| CHECK_ACTLEN; | |||||
| if (*av == NULL || | if (*av == NULL || | ||||
| match_token(rule_options, *av) == TOK_COMMENT) { | match_token(rule_options, *av) == TOK_COMMENT) { | ||||
| action->arg1 = pack_object(tstate, | insntod(have_state, kidx)->kidx = pack_object(tstate, | ||||
| default_state_name, IPFW_TLV_STATE_NAME); | default_state_name, IPFW_TLV_STATE_NAME); | ||||
| break; | break; | ||||
| } | } | ||||
| if (*av[0] == ':') { | if (*av[0] == ':') { | ||||
| if (strcmp(*av + 1, "any") == 0) | if (strcmp(*av + 1, "any") == 0) | ||||
| action->arg1 = 0; | insntod(have_state, kidx)->kidx = 0; | ||||
| else if (state_check_name(*av + 1) == 0) | else if (state_check_name(*av + 1) == 0) | ||||
| action->arg1 = pack_object(tstate, *av + 1, | insntod(have_state, kidx)->kidx = pack_object( | ||||
| IPFW_TLV_STATE_NAME); | tstate, *av + 1, IPFW_TLV_STATE_NAME); | ||||
| else | else | ||||
| errx(EX_DATAERR, "Invalid state name %s", | errx(EX_DATAERR, "Invalid state name %s", | ||||
| *av); | *av); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| } | } | ||||
| errx(EX_DATAERR, "Invalid state name %s", *av); | errx(EX_DATAERR, "Invalid state name %s", *av); | ||||
| break; | break; | ||||
| Show All 40 Lines | case TOK_UNREACH: | ||||
| if (action->arg1 == ICMP_UNREACH_NEEDFRAG && isdigit(**av)) { | if (action->arg1 == ICMP_UNREACH_NEEDFRAG && isdigit(**av)) { | ||||
| uint16_t mtu; | uint16_t mtu; | ||||
| mtu = strtoul(*av, NULL, 10); | mtu = strtoul(*av, NULL, 10); | ||||
| if (mtu < 68 || mtu >= IP_MAXPACKET) | if (mtu < 68 || mtu >= IP_MAXPACKET) | ||||
| errx(EX_DATAERR, "illegal argument for %s", | errx(EX_DATAERR, "illegal argument for %s", | ||||
| *(av - 1)); | *(av - 1)); | ||||
| action->len = F_INSN_SIZE(ipfw_insn_u16); | action->len = F_INSN_SIZE(ipfw_insn_u16); | ||||
| ((ipfw_insn_u16 *)action)->ports[0] = mtu; | insntod(action, u16)->ports[0] = mtu; | ||||
| av++; | av++; | ||||
| } | } | ||||
| break; | break; | ||||
| case TOK_UNREACH6: | case TOK_UNREACH6: | ||||
| action->opcode = O_UNREACH6; | action->opcode = O_UNREACH6; | ||||
| NEED1("missing unreach code"); | NEED1("missing unreach code"); | ||||
| action->arg1 = get_unreach6_code(*av); | action->arg1 = get_unreach6_code(*av); | ||||
| Show All 21 Lines | case TOK_QUEUE: | ||||
| break; | break; | ||||
| case TOK_PIPE: | case TOK_PIPE: | ||||
| action->opcode = O_PIPE; | action->opcode = O_PIPE; | ||||
| action->arg1 = arg_or_targ(av[0], *(av - 1)); | action->arg1 = arg_or_targ(av[0], *(av - 1)); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_SKIPTO: | case TOK_SKIPTO: | ||||
| action->opcode = O_SKIPTO; | action->opcode = O_SKIPTO; | ||||
| action->arg1 = arg_or_targ(av[0], *(av - 1)); | action->len = F_INSN_SIZE(ipfw_insn_u32); | ||||
| CHECK_ACTLEN; | |||||
| insntod(action, u32)->d[0] = arg_or_targ(av[0], *(av - 1)); | |||||
| if (insntod(action, u32)->d[0] < IPFW_ARG_MIN || | |||||
| insntod(action, u32)->d[0] > IPFW_DEFAULT_RULE) | |||||
| errx(EX_DATAERR, "illegal argument for %s", *(av - 1)); | |||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_NETGRAPH: | case TOK_NETGRAPH: | ||||
| action->opcode = O_NETGRAPH; | action->opcode = O_NETGRAPH; | ||||
| action->arg1 = arg_or_targ(av[0], *(av - 1)); | action->arg1 = arg_or_targ(av[0], *(av - 1)); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_NGTEE: | case TOK_NGTEE: | ||||
| action->opcode = O_NGTEE; | action->opcode = O_NGTEE; | ||||
| action->arg1 = arg_or_targ(av[0], *(av - 1)); | action->arg1 = arg_or_targ(av[0], *(av - 1)); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_DIVERT: | case TOK_DIVERT: | ||||
| action->opcode = O_DIVERT; | action->opcode = O_DIVERT; | ||||
| action->arg1 = get_divert_port(av[0], *(av - 1)); | action->arg1 = get_divert_port(av[0], *(av - 1)); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_TEE: | case TOK_TEE: | ||||
| action->opcode = O_TEE; | action->opcode = O_TEE; | ||||
| action->arg1 = get_divert_port(av[0], *(av - 1)); | action->arg1 = get_divert_port(av[0], *(av - 1)); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_CALL: | case TOK_CALL: | ||||
| action->opcode = O_CALLRETURN; | action->opcode = O_CALLRETURN; | ||||
| action->arg1 = arg_or_targ(av[0], *(av - 1)); | action->len = F_INSN_SIZE(ipfw_insn_u32); | ||||
| insntod(action, u32)->d[0] = arg_or_targ(av[0], *(av - 1)); | |||||
| if (insntod(action, u32)->d[0] < IPFW_ARG_MIN || | |||||
| insntod(action, u32)->d[0] > IPFW_DEFAULT_RULE) | |||||
| errx(EX_DATAERR, "illegal argument for %s", *(av - 1)); | |||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_FORWARD: { | case TOK_FORWARD: { | ||||
| /* | /* | ||||
| * Locate the address-port separator (':' or ','). | * Locate the address-port separator (':' or ','). | ||||
| * Could be one of the following: | * Could be one of the following: | ||||
| * hostname:port | * hostname:port | ||||
| ▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | if (_substrcmp(*av, "tablearg") == 0) { | ||||
| */ | */ | ||||
| action->arg1 |= 0x8000; | action->arg1 |= 0x8000; | ||||
| } | } | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| } | } | ||||
| case TOK_REASS: | case TOK_REASS: | ||||
| action->opcode = O_REASS; | action->opcode = O_CALLRETURN; | ||||
| action->len = F_INSN_SIZE(ipfw_insn_u32) | F_NOT; | |||||
| if (*av != NULL) { | |||||
| /* | |||||
| * Return type is optional. | |||||
| * By default we use RETURN_NEXT_RULENUM. | |||||
| */ | |||||
| i = match_token(return_types, *av); | |||||
| if (i >= 0) { | |||||
| action->arg1 = i; | |||||
| av++; | |||||
| } else | |||||
| action->arg1 = RETURN_NEXT_RULENUM; | |||||
| } | |||||
| CHECK_ACTLEN; | |||||
| break; | break; | ||||
| case TOK_RETURN: | case TOK_RETURN: | ||||
| fill_cmd(action, O_CALLRETURN, F_NOT, 0); | fill_cmd(action, O_CALLRETURN, F_NOT, 0); | ||||
| break; | break; | ||||
| case TOK_SETMARK: { | case TOK_SETMARK: { | ||||
| action->opcode = O_SETMARK; | action->opcode = O_SETMARK; | ||||
| action->len = F_INSN_SIZE(ipfw_insn_u32); | action->len = F_INSN_SIZE(ipfw_insn_u32); | ||||
| NEED1("missing mark"); | NEED1("missing mark"); | ||||
| if (strcmp(*av, "tablearg") == 0) { | if (strcmp(*av, "tablearg") == 0) { | ||||
| action->arg1 = IP_FW_TARG; | action->arg1 = IP_FW_TARG; | ||||
| } else { | } else { | ||||
| ((ipfw_insn_u32 *)action)->d[0] = | insntod(action, u32)->d[0] = strtoul(*av, NULL, 0); | ||||
| strtoul(*av, NULL, 0); | |||||
| /* This is not a tablearg */ | /* This is not a tablearg */ | ||||
| action->arg1 |= 0x8000; | action->arg1 |= 0x8000; | ||||
| } | } | ||||
| av++; | av++; | ||||
| CHECK_CMDLEN; | CHECK_CMDLEN; | ||||
| break; | break; | ||||
| } | } | ||||
| case TOK_TCPSETMSS: { | case TOK_TCPSETMSS: { | ||||
| u_long mss; | u_long mss; | ||||
| uint16_t idx; | uint32_t idx; | ||||
| idx = pack_object(tstate, "tcp-setmss", IPFW_TLV_EACTION); | idx = pack_object(tstate, "tcp-setmss", IPFW_TLV_EACTION); | ||||
| if (idx == 0) | if (idx == 0) | ||||
| errx(EX_DATAERR, "pack_object failed"); | errx(EX_DATAERR, "pack_object failed"); | ||||
| fill_cmd(action, O_EXTERNAL_ACTION, 0, idx); | action->opcode = O_EXTERNAL_ACTION; | ||||
| action->len = F_INSN_SIZE(ipfw_insn_kidx); | |||||
| CHECK_ACTLEN; | |||||
| insntod(action, kidx)->kidx = idx; | |||||
| NEED1("Missing MSS value"); | NEED1("Missing MSS value"); | ||||
| action = next_cmd(action, &ablen); | action = next_cmd(action, &ablen); | ||||
| action->len = 1; | action->len = 1; | ||||
| CHECK_ACTLEN; | CHECK_ACTLEN; | ||||
| mss = strtoul(*av, NULL, 10); | mss = strtoul(*av, NULL, 10); | ||||
| if (mss == 0 || mss > UINT16_MAX) | if (mss == 0 || mss > UINT16_MAX) | ||||
| errx(EX_USAGE, "invalid MSS value %s", *av); | errx(EX_USAGE, "invalid MSS value %s", *av); | ||||
| fill_cmd(action, O_EXTERNAL_DATA, 0, (uint16_t)mss); | fill_cmd(action, O_EXTERNAL_DATA, 0, (uint16_t)mss); | ||||
| Show All 17 Lines | case TOK_EACTION: { | ||||
| uint16_t idx; | uint16_t idx; | ||||
| NEED1("Missing eaction name"); | NEED1("Missing eaction name"); | ||||
| if (eaction_check_name(*av) != 0) | if (eaction_check_name(*av) != 0) | ||||
| errx(EX_DATAERR, "Invalid eaction name %s", *av); | errx(EX_DATAERR, "Invalid eaction name %s", *av); | ||||
| idx = pack_object(tstate, *av, IPFW_TLV_EACTION); | idx = pack_object(tstate, *av, IPFW_TLV_EACTION); | ||||
| if (idx == 0) | if (idx == 0) | ||||
| errx(EX_DATAERR, "pack_object failed"); | errx(EX_DATAERR, "pack_object failed"); | ||||
| fill_cmd(action, O_EXTERNAL_ACTION, 0, idx); | action->opcode = O_EXTERNAL_ACTION; | ||||
| action->len = F_INSN_SIZE(ipfw_insn_kidx); | |||||
| CHECK_ACTLEN; | |||||
| insntod(action, kidx)->kidx = idx; | |||||
| av++; | av++; | ||||
| NEED1("Missing eaction instance name"); | NEED1("Missing eaction instance name"); | ||||
| action = next_cmd(action, &ablen); | |||||
| action->len = 1; | |||||
| CHECK_ACTLEN; | |||||
| if (eaction_check_name(*av) != 0) | if (eaction_check_name(*av) != 0) | ||||
| errx(EX_DATAERR, "Invalid eaction instance name %s", | errx(EX_DATAERR, "Invalid eaction instance name %s", | ||||
| *av); | *av); | ||||
| /* | /* | ||||
| * External action instance object has TLV type depended | * External action instance object has TLV type depended | ||||
| * from the external action name object index. Since we | * from the external action name object index. Since we | ||||
| * currently don't know this index, use zero as TLV type. | * currently don't know this index, use zero as TLV type. | ||||
| */ | */ | ||||
| idx = pack_object(tstate, *av, 0); | idx = pack_object(tstate, *av, 0); | ||||
| if (idx == 0) | if (idx == 0) | ||||
| errx(EX_DATAERR, "pack_object failed"); | errx(EX_DATAERR, "pack_object failed"); | ||||
| fill_cmd(action, O_EXTERNAL_INSTANCE, 0, idx); | action = next_cmd(action, &ablen); | ||||
| action->opcode = O_EXTERNAL_INSTANCE; | |||||
| action->len = F_INSN_SIZE(ipfw_insn_kidx); | |||||
| CHECK_ACTLEN; | |||||
| insntod(action, kidx)->kidx = idx; | |||||
| av++; | av++; | ||||
| } | } | ||||
| } | } | ||||
| action = next_cmd(action, &ablen); | action = next_cmd(action, &ablen); | ||||
| /* | /* | ||||
| * [altq queuename] -- altq tag, optional | * [altq queuename] -- altq tag, optional | ||||
| * [log [logamount N]] -- log, optional | * [log [logamount N]] -- log, optional | ||||
| Show All 11 Lines | case TOK_LOG: | ||||
| if (have_log) | if (have_log) | ||||
| errx(EX_DATAERR, | errx(EX_DATAERR, | ||||
| "log cannot be specified more than once"); | "log cannot be specified more than once"); | ||||
| have_log = (ipfw_insn *)c; | have_log = (ipfw_insn *)c; | ||||
| cmd->len = F_INSN_SIZE(ipfw_insn_log); | cmd->len = F_INSN_SIZE(ipfw_insn_log); | ||||
| CHECK_CMDLEN; | CHECK_CMDLEN; | ||||
| cmd->opcode = O_LOG; | cmd->opcode = O_LOG; | ||||
| cmd->arg1 = IPFW_LOG_DEFAULT; | |||||
| /* logdst before logamount */ | |||||
| if (av[0] && _substrcmp(*av, "logdst") == 0) { | |||||
| av++; | |||||
| NEED1("logdst requires argument"); | |||||
| cmd->arg1 = parse_logdst(*av); | |||||
| av++; | |||||
| } | |||||
| if (av[0] && _substrcmp(*av, "logamount") == 0) { | if (av[0] && _substrcmp(*av, "logamount") == 0) { | ||||
| av++; | av++; | ||||
| NEED1("logamount requires argument"); | NEED1("logamount requires argument"); | ||||
| l = atoi(*av); | l = atoi(*av); | ||||
| if (l < 0) | if (l < 0) | ||||
| errx(EX_DATAERR, | errx(EX_DATAERR, | ||||
| "logamount must be positive"); | "logamount must be positive"); | ||||
| c->max_log = l; | c->max_log = l; | ||||
| av++; | av++; | ||||
| } else { | } else { | ||||
| len = sizeof(c->max_log); | len = sizeof(c->max_log); | ||||
| if (sysctlbyname("net.inet.ip.fw.verbose_limit", | if (sysctlbyname("net.inet.ip.fw.verbose_limit", | ||||
| &c->max_log, &len, NULL, 0) == -1) { | &c->max_log, &len, NULL, 0) == -1) { | ||||
| if (g_co.test_only) { | if (g_co.test_only) { | ||||
| c->max_log = 0; | c->max_log = 0; | ||||
| break; | break; | ||||
| } | } | ||||
| errx(1, "sysctlbyname(\"%s\")", | errx(1, "sysctlbyname(\"%s\")", | ||||
| "net.inet.ip.fw.verbose_limit"); | "net.inet.ip.fw.verbose_limit"); | ||||
| } | } | ||||
| } | } | ||||
| /* logdst after logamount */ | |||||
| if (av[0] && _substrcmp(*av, "logdst") == 0) { | |||||
| av++; | |||||
| NEED1("logdst requires argument"); | |||||
| cmd->arg1 = parse_logdst(*av); | |||||
| av++; | |||||
| } | } | ||||
| } | |||||
| break; | break; | ||||
| #ifndef NO_ALTQ | #ifndef NO_ALTQ | ||||
| case TOK_ALTQ: | case TOK_ALTQ: | ||||
| { | { | ||||
| ipfw_insn_altq *a = (ipfw_insn_altq *)cmd; | ipfw_insn_altq *a = (ipfw_insn_altq *)cmd; | ||||
| NEED1("missing altq queue name"); | NEED1("missing altq queue name"); | ||||
| ▲ Show 20 Lines • Show All 295 Lines • ▼ Show 20 Lines | case TOK_LAYER2: | ||||
| fill_cmd(cmd, O_LAYER2, 0, 0); | fill_cmd(cmd, O_LAYER2, 0, 0); | ||||
| break; | break; | ||||
| case TOK_XMIT: | case TOK_XMIT: | ||||
| case TOK_RECV: | case TOK_RECV: | ||||
| case TOK_VIA: | case TOK_VIA: | ||||
| NEED1("recv, xmit, via require interface name" | NEED1("recv, xmit, via require interface name" | ||||
| " or address"); | " or address"); | ||||
| fill_iface((ipfw_insn_if *)cmd, av[0], cblen, tstate); | fill_iface(insntod(cmd, if), av[0], cblen, tstate); | ||||
| av++; | av++; | ||||
| if (F_LEN(cmd) == 0) /* not a valid address */ | if (F_LEN(cmd) == 0) /* not a valid address */ | ||||
| break; | break; | ||||
| if (i == TOK_XMIT) | if (i == TOK_XMIT) | ||||
| cmd->opcode = O_XMIT; | cmd->opcode = O_XMIT; | ||||
| else if (i == TOK_RECV) | else if (i == TOK_RECV) | ||||
| cmd->opcode = O_RECV; | cmd->opcode = O_RECV; | ||||
| else if (i == TOK_VIA) | else if (i == TOK_VIA) | ||||
| ▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | 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: | ||||
| case TOK_RECORDSTATE: { | case TOK_RECORDSTATE: { | ||||
| uint16_t uidx; | uint32_t uidx; | ||||
| if (open_par) | if (open_par) | ||||
| errx(EX_USAGE, "keep-state or record-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, record-state, " | errx(EX_USAGE, "only one of keep-state, record-state, " | ||||
| " limit and set-limit is allowed"); | " limit and set-limit is allowed"); | ||||
| if (*av != NULL && *av[0] == ':') { | if (*av != NULL && *av[0] == ':') { | ||||
| if (state_check_name(*av + 1) != 0) | if (state_check_name(*av + 1) != 0) | ||||
| errx(EX_DATAERR, | errx(EX_DATAERR, | ||||
| "Invalid state name %s", *av); | "Invalid state name %s", *av); | ||||
| uidx = pack_object(tstate, *av + 1, | uidx = pack_object(tstate, *av + 1, | ||||
| IPFW_TLV_STATE_NAME); | IPFW_TLV_STATE_NAME); | ||||
| av++; | av++; | ||||
| } else | } else | ||||
| uidx = pack_object(tstate, default_state_name, | uidx = pack_object(tstate, default_state_name, | ||||
| IPFW_TLV_STATE_NAME); | IPFW_TLV_STATE_NAME); | ||||
| have_state = cmd; | have_state = cmd; | ||||
| have_rstate = i == TOK_RECORDSTATE; | have_rstate = i == TOK_RECORDSTATE; | ||||
| fill_cmd(cmd, O_KEEP_STATE, 0, uidx); | cmd->opcode = O_KEEP_STATE; | ||||
| cmd->len = F_INSN_SIZE(ipfw_insn_kidx); | |||||
| CHECK_CMDLEN; | |||||
| insntod(have_state, kidx)->kidx = uidx; | |||||
| break; | break; | ||||
| } | } | ||||
| case TOK_LIMIT: | case TOK_LIMIT: | ||||
| case TOK_SETLIMIT: { | case TOK_SETLIMIT: { | ||||
| ipfw_insn_limit *c = (ipfw_insn_limit *)cmd; | ipfw_insn_limit *c = insntod(cmd, limit); | ||||
| int val; | int val; | ||||
| if (open_par) | if (open_par) | ||||
| errx(EX_USAGE, | errx(EX_USAGE, | ||||
| "limit or set-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, record-state, " | errx(EX_USAGE, "only one of keep-state, record-state, " | ||||
| " limit and set-limit is allowed"); | " limit and set-limit is allowed"); | ||||
| have_state = cmd; | have_state = cmd; | ||||
| have_rstate = i == TOK_SETLIMIT; | have_rstate = i == TOK_SETLIMIT; | ||||
| cmd->opcode = O_LIMIT; | |||||
| cmd->len = F_INSN_SIZE(ipfw_insn_limit); | cmd->len = F_INSN_SIZE(ipfw_insn_limit); | ||||
| CHECK_CMDLEN; | CHECK_CMDLEN; | ||||
| cmd->opcode = O_LIMIT; | c->limit_mask = c->conn_limit = c->kidx = 0; | ||||
| c->limit_mask = c->conn_limit = 0; | |||||
| while ( av[0] != NULL ) { | while ( av[0] != NULL ) { | ||||
| if ((val = match_token(limit_masks, *av)) <= 0) | if ((val = match_token(limit_masks, *av)) <= 0) | ||||
| break; | break; | ||||
| c->limit_mask |= val; | c->limit_mask |= val; | ||||
| 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++; | av++; | ||||
| if (*av != NULL && *av[0] == ':') { | if (*av != NULL && *av[0] == ':') { | ||||
| if (state_check_name(*av + 1) != 0) | if (state_check_name(*av + 1) != 0) | ||||
| errx(EX_DATAERR, | errx(EX_DATAERR, | ||||
| "Invalid state name %s", *av); | "Invalid state name %s", *av); | ||||
| cmd->arg1 = pack_object(tstate, *av + 1, | c->kidx = pack_object(tstate, *av + 1, | ||||
| IPFW_TLV_STATE_NAME); | IPFW_TLV_STATE_NAME); | ||||
| av++; | av++; | ||||
| } else | } else | ||||
| cmd->arg1 = pack_object(tstate, | c->kidx = pack_object(tstate, | ||||
| default_state_name, IPFW_TLV_STATE_NAME); | default_state_name, IPFW_TLV_STATE_NAME); | ||||
| 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++; | ||||
| ▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | case TOK_FIB: | ||||
| fill_cmd(cmd, O_FIB, 0, strtoul(*av, NULL, 0)); | fill_cmd(cmd, O_FIB, 0, strtoul(*av, NULL, 0)); | ||||
| av++; | av++; | ||||
| break; | break; | ||||
| case TOK_SOCKARG: | case TOK_SOCKARG: | ||||
| fill_cmd(cmd, O_SOCKARG, 0, 0); | fill_cmd(cmd, O_SOCKARG, 0, 0); | ||||
| break; | break; | ||||
| case TOK_LOOKUP: { | case TOK_LOOKUP: { | ||||
| ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd; | /* optional mask for some LOOKUP types */ | ||||
| ipfw_insn_table *c = insntod(cmd, table); | |||||
| char *lkey; | |||||
| if (!av[0] || !av[1]) | if (!av[0] || !av[1]) | ||||
| errx(EX_USAGE, "format: lookup argument tablenum"); | errx(EX_USAGE, | ||||
| "format: lookup argument tablenum"); | |||||
| cmd->opcode = O_IP_DST_LOOKUP; | cmd->opcode = O_IP_DST_LOOKUP; | ||||
| cmd->len |= F_INSN_SIZE(ipfw_insn) + 2; | |||||
| i = match_token(lookup_keys, *av); | lkey = strsep(av, ":"); | ||||
| i = match_token(lookup_keys, lkey); | |||||
| if (i == -1) | if (i == -1) | ||||
| errx(EX_USAGE, "format: cannot lookup on %s", *av); | errx(EX_USAGE, | ||||
| __PAST_END(c->d, 1) = i; | "format: cannot lookup on %s", lkey); | ||||
| av++; | /* masked lookup key */ | ||||
| if (*av != NULL) { | |||||
| switch (i) { | |||||
| case LOOKUP_DST_PORT: | |||||
| case LOOKUP_SRC_PORT: | |||||
| case LOOKUP_UID: | |||||
| case LOOKUP_JAIL: | |||||
| case LOOKUP_DSCP: | |||||
| case LOOKUP_MARK: | |||||
| case LOOKUP_RULENUM: | |||||
| 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"); | |||||
| } else { | |||||
| cmd->len |= F_INSN_SIZE(ipfw_insn_kidx); | |||||
| } | |||||
| CHECK_CMDLEN; | |||||
| if ((i = pack_table(tstate, *av)) == 0) | IPFW_SET_LOOKUP_TYPE(cmd, i); | ||||
| errx(EX_DATAERR, "Invalid table name: %s", *av); | |||||
| cmd->arg1 = i; | |||||
| av++; | av++; | ||||
| c->kidx = pack_table(tstate, *av); | |||||
| if (c->kidx == 0) | |||||
| errx(EX_DATAERR, | |||||
| "Invalid table name: %s", *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) | ||||
| errx(EX_DATAERR, | errx(EX_DATAERR, | ||||
| "enclose table name into \"table()\""); | "enclose table name into \"table()\""); | ||||
| fill_table(cmd, *av, O_IP_FLOW_LOOKUP, tstate); | fill_table(cmd, *av, O_IP_FLOW_LOOKUP, tstate); | ||||
| av++; | av++; | ||||
| ▲ Show 20 Lines • Show All 46 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 && !have_rstate) { | if (have_state && have_state->opcode != O_CHECK_STATE && !have_rstate) { | ||||
| fill_cmd(dst, O_PROBE_STATE, 0, have_state->arg1); | dst->opcode = O_PROBE_STATE; | ||||
| dst->len = F_INSN_SIZE(ipfw_insn_kidx); | |||||
| insntod(dst, kidx)->kidx = insntod(have_state, kidx)->kidx; | |||||
| 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 | * O_SKIP_ACTION | ||||
| */ | */ | ||||
| for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) { | for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) { | ||||
| ▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
| static void | static void | ||||
| object_sort_ctlv(ipfw_obj_ctlv *ctlv) | object_sort_ctlv(ipfw_obj_ctlv *ctlv) | ||||
| { | { | ||||
| qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv); | qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv); | ||||
| } | } | ||||
| struct object_kt { | struct object_kt { | ||||
| uint16_t uidx; | uint32_t uidx; | ||||
| uint16_t type; | uint16_t type; | ||||
| }; | }; | ||||
| static int | static int | ||||
| compare_object_kntlv(const void *k, const void *v) | compare_object_kntlv(const void *k, const void *v) | ||||
| { | { | ||||
| const ipfw_obj_ntlv *ntlv; | const ipfw_obj_ntlv *ntlv; | ||||
| struct object_kt key; | struct object_kt key; | ||||
| Show All 17 Lines | |||||
| * Finds object name in @ctlv by @idx and @type. | * Finds object name in @ctlv by @idx and @type. | ||||
| * Uses the following facts: | * Uses the following facts: | ||||
| * 1) All TLVs are the same size | * 1) All TLVs are the same size | ||||
| * 2) Kernel implementation provides already sorted list. | * 2) Kernel implementation provides already sorted list. | ||||
| * | * | ||||
| * Returns table name or NULL. | * Returns table name or NULL. | ||||
| */ | */ | ||||
| static char * | static char * | ||||
| object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx, uint16_t type) | object_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx, uint16_t type) | ||||
| { | { | ||||
| ipfw_obj_ntlv *ntlv; | ipfw_obj_ntlv *ntlv; | ||||
| struct object_kt key; | struct object_kt key; | ||||
| key.uidx = idx; | key.uidx = idx; | ||||
| key.type = type; | key.type = type; | ||||
| ntlv = bsearch(&key, (ctlv + 1), ctlv->count, ctlv->objsize, | ntlv = bsearch(&key, (ctlv + 1), ctlv->count, ctlv->objsize, | ||||
| compare_object_kntlv); | compare_object_kntlv); | ||||
| if (ntlv != NULL) | if (ntlv != NULL) | ||||
| return (ntlv->name); | return (ntlv->name); | ||||
| return (NULL); | return (NULL); | ||||
| } | } | ||||
| static char * | static char * | ||||
| table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx) | table_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx) | ||||
| { | { | ||||
| return (object_search_ctlv(ctlv, idx, IPFW_TLV_TBL_NAME)); | return (object_search_ctlv(ctlv, idx, IPFW_TLV_TBL_NAME)); | ||||
| } | } | ||||
| /* | /* | ||||
| * Adds one or more rules to ipfw chain. | * Adds one or more rules to ipfw chain. | ||||
| * Data layout: | * Data layout: | ||||
| ▲ Show 20 Lines • Show All 384 Lines • Show Last 20 Lines | |||||