FreeBSD Bugzilla – Attachment 191779 Details for
Bug 222705
ipfw "proto udp" parsing problem
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed patch
ipfw.diff (text/plain), 22.60 KB, created by
Andrey V. Elsukov
on 2018-03-24 10:35:56 UTC
(
hide
)
Description:
Proposed patch
Filename:
MIME Type:
Creator:
Andrey V. Elsukov
Created:
2018-03-24 10:35:56 UTC
Size:
22.60 KB
patch
obsolete
>Index: sbin/ipfw/ipfw2.c >=================================================================== >--- sbin/ipfw/ipfw2.c (revision 331095) >+++ sbin/ipfw/ipfw2.c (working copy) >@@ -1277,7 +1277,7 @@ print_ip(struct buf_pr *bp, struct format_opts *fo > * prints a MAC address/mask pair > */ > static void >-print_mac(struct buf_pr *bp, uint8_t *addr, uint8_t *mask) >+format_mac(struct buf_pr *bp, uint8_t *addr, uint8_t *mask) > { > int l = contigmask(mask, 48); > >@@ -1296,6 +1296,15 @@ static void > } > > static void >+print_mac(struct buf_pr *bp, ipfw_insn_mac *mac) >+{ >+ >+ bprintf(bp, " MAC"); >+ format_mac(bp, mac->addr, mac->mask); >+ format_mac(bp, mac->addr + 6, mac->mask + 6); >+} >+ >+static void > fill_icmptypes(ipfw_insn_u32 *cmd, char *av) > { > uint8_t type; >@@ -1405,7 +1414,806 @@ show_prerequisites(struct buf_pr *bp, int *flags, > *flags |= want; > } > >+#define insntod(cmd, type) ((ipfw_insn_ ## type *)(cmd)) >+#define IPFW_MAX_CMDS 1000 >+struct show_state { >+ struct ip_fw_rule *rule; >+ const ipfw_insn *printed[IPFW_MAX_CMDS]; >+ const ipfw_insn *eaction; >+ int pcnt; /* number of printed[] instructions */ >+ int flags; >+ int proto; >+ int or_block; >+}; >+ > static void >+init_state(struct show_state *state, struct ip_fw_rule *rule) >+{ >+ >+ state->rule = rule; >+ state->eaction = NULL; >+ state->pcnt = 0; >+ state->flags = 0; >+ state->proto = 0; >+ state->or_block = 0; >+} >+ >+static int >+is_printed_opcode(struct show_state *state, const ipfw_insn *cmd) >+{ >+ int i; >+ >+ for (i = 0; i < state->pcnt; i++) >+ if (state->printed[i] == cmd) >+ return (1); >+ return (0); >+} >+ >+static void >+mark_printed(struct show_state *state, const ipfw_insn *cmd) >+{ >+ >+ if (state->pcnt < nitems(state->printed) - 1) >+ state->printed[state->pcnt++] = cmd; >+} >+ >+static void >+print_limit(struct buf_pr *bp, const ipfw_insn_limit *limit) >+{ >+ struct _s_x *p = limit_masks; >+ char const *comma = " "; >+ uint8_t x; >+ >+ bprintf(bp, " limit"); >+ for (x = limit->limit_mask; p->x != 0; p++) { >+ if ((x & p->x) == p->x) { >+ x &= ~p->x; >+ bprintf(bp, "%s%s", comma, p->s); >+ comma = ","; >+ } >+ } >+ bprint_uint_arg(bp, " ", limit->conn_limit); >+} >+ >+static ipfw_insn * >+print_opcode(struct buf_pr *bp, struct format_opts *fo, >+ struct show_state *state, uint8_t opcode) >+{ >+ struct protoent *pe; >+ struct passwd *pwd; >+ struct group *grp; >+ ipfw_insn *cmd; >+ char const *s; >+ double d; >+ int l; >+ >+ for (l = state->rule->act_ofs, cmd = state->rule->cmd; >+ l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { >+ /* We use zero opcode to print the rest of options */ >+ if (opcode != 0 && cmd->opcode != opcode) >+ continue; >+ if (is_printed_opcode(state, cmd)) >+ continue; >+ if ((cmd->len & F_OR) != 0 && state->or_block == 0) >+ bprintf(bp, " {"); >+ if (cmd->opcode != O_IN && (cmd->len & F_NOT) != 0) >+ bprintf(bp, " not"); >+ switch (cmd->opcode) { >+ case O_PROB: >+ d = 1.0 * insntod(cmd, u32)->d[0] / 0x7fffffff; >+ bprintf(bp, "prob %f ", d); >+ break; >+ case O_PROBE_STATE: /* no need to print anything here */ >+ break; >+ case O_IP_SRC: >+ case O_IP_SRC_LOOKUP: >+ case O_IP_SRC_MASK: >+ case O_IP_SRC_ME: >+ case O_IP_SRC_SET: >+ case O_IP_DST: >+ case O_IP_DST_LOOKUP: >+ case O_IP_DST_MASK: >+ case O_IP_DST_ME: >+ case O_IP_DST_SET: >+ print_ip(bp, fo, insntod(cmd, ip), ""); >+ break; >+ case O_IP6_SRC: >+ case O_IP6_SRC_MASK: >+ case O_IP6_SRC_ME: >+ case O_IP6_DST: >+ case O_IP6_DST_MASK: >+ case O_IP6_DST_ME: >+ print_ip6(bp, insntod(cmd, ip6), ""); >+ break; >+ case O_FLOW6ID: >+ print_flow6id(bp, insntod(cmd, u32)); >+ break; >+ case O_IP_DSTPORT: >+ case O_IP_SRCPORT: >+ print_newports(bp, insntod(cmd, u16), state->proto, >+ (state->flags & (HAVE_SRCIP | HAVE_DSTIP)) == >+ (HAVE_SRCIP | HAVE_DSTIP) ? cmd->opcode: 0); >+ break; >+ case O_PROTO: >+ pe = getprotobynumber(cmd->arg1); >+ if (state->flags & HAVE_PROTO) >+ bprintf(bp, " proto"); >+ if (pe != NULL) >+ bprintf(bp, " %s", pe->p_name); >+ else >+ bprintf(bp, " %u", cmd->arg1); >+ break; >+ case O_MACADDR2: >+ print_mac(bp, insntod(cmd, mac)); >+ break; >+ case O_MAC_TYPE: >+ print_newports(bp, insntod(cmd, u16), >+ IPPROTO_ETHERTYPE, cmd->opcode); >+ break; >+ case O_FRAG: >+ bprintf(bp, " frag"); >+ break; >+ case O_FIB: >+ bprintf(bp, " fib %u", cmd->arg1); >+ break; >+ case O_SOCKARG: >+ bprintf(bp, " sockarg"); >+ break; >+ case O_IN: >+ bprintf(bp, cmd->len & F_NOT ? " out" : " in"); >+ break; >+ case O_DIVERTED: >+ switch (cmd->arg1) { >+ case 3: >+ bprintf(bp, " diverted"); >+ break; >+ case 2: >+ bprintf(bp, " diverted-output"); >+ break; >+ case 1: >+ bprintf(bp, " diverted-loopback"); >+ break; >+ default: >+ bprintf(bp, " diverted-?<%u>", cmd->arg1); >+ break; >+ } >+ break; >+ case O_LAYER2: >+ bprintf(bp, " layer2"); >+ break; >+ case O_XMIT: >+ case O_RECV: >+ case O_VIA: >+ if (cmd->opcode == O_XMIT) >+ s = "xmit"; >+ else if (cmd->opcode == O_RECV) >+ s = "recv"; >+ else /* if (cmd->opcode == O_VIA) */ >+ s = "via"; >+ switch (insntod(cmd, if)->name[0]) { >+ case '\0': >+ bprintf(bp, " %s %s", s, >+ inet_ntoa(insntod(cmd, if)->p.ip)); >+ break; >+ case '\1': >+ bprintf(bp, " %s table(%s)", s, >+ table_search_ctlv(fo->tstate, >+ insntod(cmd, if)->p.kidx)); >+ break; >+ default: >+ bprintf(bp, " %s %s", s, >+ insntod(cmd, if)->name); >+ } >+ break; >+ case O_IP_FLOW_LOOKUP: >+ s = table_search_ctlv(fo->tstate, cmd->arg1); >+ bprintf(bp, " flow table(%s", s); >+ if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32)) >+ bprintf(bp, ",%u", insntod(cmd, u32)->d[0]); >+ bprintf(bp, ")"); >+ break; >+ case O_IPID: >+ case O_IPTTL: >+ case O_IPLEN: >+ case O_TCPDATALEN: >+ case O_TCPWIN: >+ if (F_LEN(cmd) == 1) { >+ switch (cmd->opcode) { >+ case O_IPID: >+ s = "ipid"; >+ break; >+ case O_IPTTL: >+ s = "ipttl"; >+ break; >+ case O_IPLEN: >+ s = "iplen"; >+ break; >+ case O_TCPDATALEN: >+ s = "tcpdatalen"; >+ break; >+ case O_TCPWIN: >+ s = "tcpwin"; >+ break; >+ } >+ bprintf(bp, " %s %u", s, cmd->arg1); >+ } else >+ print_newports(bp, insntod(cmd, u16), 0, >+ cmd->opcode); >+ break; >+ case O_IPVER: >+ bprintf(bp, " ipver %u", cmd->arg1); >+ break; >+ case O_IPPRECEDENCE: >+ bprintf(bp, " ipprecedence %u", cmd->arg1 >> 5); >+ break; >+ case O_DSCP: >+ print_dscp(bp, insntod(cmd, u32)); >+ break; >+ case O_IPOPT: >+ print_flags(bp, "ipoptions", cmd, f_ipopts); >+ break; >+ case O_IPTOS: >+ print_flags(bp, "iptos", cmd, f_iptos); >+ break; >+ case O_ICMPTYPE: >+ print_icmptypes(bp, insntod(cmd, u32)); >+ break; >+ case O_ESTAB: >+ bprintf(bp, " established"); >+ break; >+ case O_TCPFLAGS: >+ print_flags(bp, "tcpflags", cmd, f_tcpflags); >+ break; >+ case O_TCPOPTS: >+ print_flags(bp, "tcpoptions", cmd, f_tcpopts); >+ break; >+ case O_TCPACK: >+ bprintf(bp, " tcpack %d", >+ ntohl(insntod(cmd, u32)->d[0])); >+ break; >+ case O_TCPSEQ: >+ bprintf(bp, " tcpseq %d", >+ ntohl(insntod(cmd, u32)->d[0])); >+ break; >+ case O_UID: >+ pwd = getpwuid(insntod(cmd, u32)->d[0]); >+ if (pwd != NULL) >+ bprintf(bp, " uid %s", pwd->pw_name); >+ else >+ bprintf(bp, " uid %u", >+ insntod(cmd, u32)->d[0]); >+ break; >+ case O_GID: >+ grp = getgrgid(insntod(cmd, u32)->d[0]); >+ if (grp != NULL) >+ bprintf(bp, " gid %s", grp->gr_name); >+ else >+ bprintf(bp, " gid %u", >+ insntod(cmd, u32)->d[0]); >+ break; >+ case O_JAIL: >+ bprintf(bp, " jail %d", insntod(cmd, u32)->d[0]); >+ break; >+ case O_VERREVPATH: >+ bprintf(bp, " verrevpath"); >+ break; >+ case O_VERSRCREACH: >+ bprintf(bp, " versrcreach"); >+ break; >+ case O_ANTISPOOF: >+ bprintf(bp, " antispoof"); >+ break; >+ case O_IPSEC: >+ bprintf(bp, " ipsec"); >+ break; >+ case O_NOP: >+ /* >+ * Skip O_NOP, when we printing the rest >+ * of options, it will be handled separately. >+ */ >+ if (opcode != cmd->opcode) >+ return (NULL); >+ bprintf(bp, " // %s", (char *)(cmd + 1)); >+ break; >+ case O_KEEP_STATE: >+ bprintf(bp, " keep-state"); >+ bprintf(bp, " :%s", >+ object_search_ctlv(fo->tstate, cmd->arg1, >+ IPFW_TLV_STATE_NAME)); >+ break; >+ case O_LIMIT: >+ print_limit(bp, insntod(cmd, limit)); >+ bprintf(bp, " :%s", >+ object_search_ctlv(fo->tstate, cmd->arg1, >+ IPFW_TLV_STATE_NAME)); >+ break; >+ case O_IP6: >+ bprintf(bp, " ip6"); >+ break; >+ case O_IP4: >+ bprintf(bp, " ip4"); >+ break; >+ case O_ICMP6TYPE: >+ print_icmp6types(bp, insntod(cmd, u32)); >+ break; >+ case O_EXT_HDR: >+ print_ext6hdr(bp, cmd); >+ break; >+ case O_TAGGED: >+ if (F_LEN(cmd) == 1) >+ bprint_uint_arg(bp, " tagged ", cmd->arg1); >+ else >+ print_newports(bp, insntod(cmd, u16), >+ 0, O_TAGGED); >+ break; >+ default: >+ bprintf(bp, " [opcode %d len %d]", cmd->opcode, >+ cmd->len); >+ } >+ if (cmd->len & F_OR) { >+ bprintf(bp, " or"); >+ state->or_block = 1; >+ } else if (state->or_block != 0) { >+ bprintf(bp, " }"); >+ state->or_block = 0; >+ } >+ mark_printed(state, cmd); >+ return (cmd); >+ } >+ return (NULL); >+} >+ >+static void >+print_fwd(struct buf_pr *bp, ipfw_insn *cmd) >+{ >+ char buf[INET6_ADDRSTRLEN + IF_NAMESIZE + 2]; >+ ipfw_insn_sa6 *sa6; >+ ipfw_insn_sa *sa; >+ uint16_t port; >+ >+ if (cmd->opcode == O_FORWARD_IP) { >+ sa = insntod(cmd, sa); >+ port = sa->sa.sin_port; >+ if (sa->sa.sin_addr.s_addr == INADDR_ANY) >+ bprintf(bp, "fwd tablearg"); >+ else >+ bprintf(bp, "fwd %s", inet_ntoa(sa->sa.sin_addr)); >+ } else { >+ sa6 = insntod(cmd, sa6); >+ port = sa6->sa.sin6_port; >+ bprintf(bp, "fwd "); >+ if (getnameinfo((const struct sockaddr *)&sa6->sa, >+ sizeof(struct sockaddr_in6), buf, sizeof(buf), NULL, 0, >+ NI_NUMERICHOST) == 0) >+ bprintf(bp, "%s", buf); >+ } >+ if (port != 0) >+ bprintf(bp, ",%u", port); >+} >+ >+static ipfw_insn * >+print_action(struct buf_pr *bp, struct format_opts *fo, >+ struct show_state *state, uint8_t opcode) >+{ >+ ipfw_insn *cmd; >+ char const *s; >+ int l; >+ >+ for (l = state->rule->cmd_len - state->rule->act_ofs, >+ cmd = ACTION_PTR(state->rule); l > 0; >+ l -= F_LEN(cmd), cmd += F_LEN(cmd)) { >+ if (cmd->opcode != opcode) >+ continue; >+ if (is_printed_opcode(state, cmd)) >+ continue; >+ switch (opcode) { >+ case O_CHECK_STATE: >+ bprintf(bp, "check-state"); >+ if (cmd->arg1 != 0) >+ s = object_search_ctlv(fo->tstate, cmd->arg1, >+ IPFW_TLV_STATE_NAME); >+ else >+ s = NULL; >+ bprintf(bp, " :%s", s ? s: "any"); >+ break; >+ case O_ACCEPT: >+ bprintf(bp, "allow"); >+ break; >+ case O_COUNT: >+ bprintf(bp, "count"); >+ break; >+ case O_DENY: >+ bprintf(bp, "deny"); >+ break; >+ case O_REJECT: >+ if (cmd->arg1 == ICMP_REJECT_RST) >+ bprintf(bp, "reset"); >+ else if (cmd->arg1 == ICMP_REJECT_ABORT) >+ bprintf(bp, "abort"); >+ else if (cmd->arg1 == ICMP_UNREACH_HOST) >+ bprintf(bp, "reject"); >+ else >+ print_reject_code(bp, cmd->arg1); >+ break; >+ case O_UNREACH6: >+ if (cmd->arg1 == ICMP6_UNREACH_RST) >+ bprintf(bp, "reset6"); >+ else if (cmd->arg1 == ICMP6_UNREACH_ABORT) >+ bprintf(bp, "abort6"); >+ else >+ print_unreach6_code(bp, cmd->arg1); >+ break; >+ case O_SKIPTO: >+ bprint_uint_arg(bp, "skipto ", cmd->arg1); >+ break; >+ case O_PIPE: >+ bprint_uint_arg(bp, "pipe ", cmd->arg1); >+ break; >+ case O_QUEUE: >+ bprint_uint_arg(bp, "queue ", cmd->arg1); >+ break; >+ case O_DIVERT: >+ bprint_uint_arg(bp, "divert ", cmd->arg1); >+ break; >+ case O_TEE: >+ bprint_uint_arg(bp, "tee ", cmd->arg1); >+ break; >+ case O_NETGRAPH: >+ bprint_uint_arg(bp, "netgraph ", cmd->arg1); >+ break; >+ case O_NGTEE: >+ bprint_uint_arg(bp, "ngtee ", cmd->arg1); >+ break; >+ case O_FORWARD_IP: >+ case O_FORWARD_IP6: >+ print_fwd(bp, cmd); >+ break; >+ case O_LOG: >+ if (insntod(cmd, log)->max_log > 0) >+ bprintf(bp, " log logamount %d", >+ insntod(cmd, log)->max_log); >+ else >+ bprintf(bp, " log"); >+ break; >+ case O_ALTQ: >+#ifndef NO_ALTQ >+ print_altq_cmd(bp, insntod(cmd, altq)); >+#endif >+ break; >+ case O_TAG: >+ bprint_uint_arg(bp, cmd->len & F_NOT ? " untag ": >+ " tag ", cmd->arg1); >+ break; >+ case O_NAT: >+ if (cmd->arg1 != IP_FW_NAT44_GLOBAL) >+ bprint_uint_arg(bp, "nat ", cmd->arg1); >+ else >+ bprintf(bp, "nat global"); >+ break; >+ case O_SETFIB: >+ if (cmd->arg1 == IP_FW_TARG) >+ bprint_uint_arg(bp, "setfib ", cmd->arg1); >+ else >+ bprintf(bp, "setfib %u", cmd->arg1 & 0x7FFF); >+ break; >+ case O_EXTERNAL_ACTION: >+ /* >+ * The external action can consists of two following >+ * each other opcodes - O_EXTERNAL_ACTION and >+ * O_EXTERNAL_INSTANCE. The first contains the ID of >+ * name of external action. The second contains the ID >+ * of name of external action instance. >+ * NOTE: in case when external action has no named >+ * instances support, the second opcode isn't needed. >+ */ >+ state->eaction = cmd; >+ s = object_search_ctlv(fo->tstate, cmd->arg1, >+ IPFW_TLV_EACTION); >+ if (match_token(rule_eactions, s) != -1) >+ bprintf(bp, "%s", s); >+ else >+ bprintf(bp, "eaction %s", s); >+ break; >+ case O_EXTERNAL_INSTANCE: >+ if (state->eaction == NULL) >+ break; >+ /* >+ * XXX: we need to teach ipfw(9) to rewrite opcodes >+ * in the user buffer on rule addition. When we add >+ * the rule, we specify zero TLV type for >+ * O_EXTERNAL_INSTANCE object. To show correct >+ * rule after `ipfw add` we need to search instance >+ * name with zero type. But when we do `ipfw show` >+ * we calculate TLV type using IPFW_TLV_EACTION_NAME() >+ * macro. >+ */ >+ s = object_search_ctlv(fo->tstate, cmd->arg1, 0); >+ if (s == NULL) >+ s = object_search_ctlv(fo->tstate, >+ cmd->arg1, IPFW_TLV_EACTION_NAME( >+ state->eaction->arg1)); >+ bprintf(bp, " %s", s); >+ break; >+ case O_EXTERNAL_DATA: >+ if (state->eaction == NULL) >+ break; >+ /* >+ * Currently we support data formatting only for >+ * external data with datalen u16. For unknown data >+ * print its size in bytes. >+ */ >+ if (cmd->len == F_INSN_SIZE(ipfw_insn)) >+ bprintf(bp, " %u", cmd->arg1); >+ else >+ bprintf(bp, " %ubytes", >+ cmd->len * sizeof(uint32_t)); >+ break; >+ case O_SETDSCP: >+ if (cmd->arg1 == IP_FW_TARG) { >+ bprintf(bp, "setdscp tablearg"); >+ break; >+ } >+ s = match_value(f_ipdscp, cmd->arg1 & 0x3F); >+ if (s != NULL) >+ bprintf(bp, "setdscp %s", s); >+ else >+ bprintf(bp, "setdscp %s", cmd->arg1 & 0x3F); >+ break; >+ case O_REASS: >+ bprintf(bp, "reass"); >+ break; >+ case O_CALLRETURN: >+ if (cmd->len & F_NOT) >+ bprintf(bp, "return"); >+ else >+ bprint_uint_arg(bp, "call ", cmd->arg1); >+ break; >+ default: >+ bprintf(bp, "** unrecognized action %d len %d ", >+ cmd->opcode, cmd->len); >+ } >+ mark_printed(state, cmd); >+ return (cmd); >+ } >+ return (NULL); >+} >+ >+static void >+print_proto(struct buf_pr *bp, struct format_opts *fo, >+ struct show_state *state) >+{ >+ ipfw_insn *cmd; >+ int l, proto, ip4, ip6, tmp; >+ >+ /* Count all O_PROTO, O_IP4, O_IP6 instructions. */ >+ proto = tmp = ip4 = ip6 = 0; >+ for (l = state->rule->act_ofs, cmd = state->rule->cmd; >+ l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { >+ switch (cmd->opcode) { >+ case O_PROTO: >+ proto++; >+ break; >+ case O_IP4: >+ ip4 = 1; >+ if (cmd->len & F_OR) >+ ip4++; >+ break; >+ case O_IP6: >+ ip6 = 1; >+ if (cmd->len & F_OR) >+ ip6++; >+ break; >+ default: >+ continue; >+ } >+ } >+ if (proto == 0 && ip4 == 0 && ip6 == 0) { >+ state->proto = IPPROTO_IP; >+ state->flags |= HAVE_PROTO; >+ bprintf(bp, " ip"); >+ return; >+ } >+ /* To handle the case { ip4 or ip6 }, print opcode with F_OR first */ >+ if (ip4 || ip6) >+ cmd = print_opcode(bp, fo, state, ip4 > ip6 ? O_IP4: O_IP6); >+ if (cmd != NULL && (cmd->len & F_OR)) >+ cmd = print_opcode(bp, fo, state, ip4 > ip6 ? O_IP6: O_IP4); >+ if (cmd == NULL || (cmd->len & F_OR)) >+ for (l = proto; l > 0; l--) { >+ cmd = print_opcode(bp, fo, state, O_PROTO); >+ if (cmd != NULL && (cmd->len & F_OR) == 0) >+ break; >+ tmp = cmd->arg1; >+ } >+ /* Initialize proto, it is used by print_newports() */ >+ if (tmp != 0) >+ state->proto = tmp; >+ else if (ip6 != 0) >+ state->proto = IPPROTO_IPV6; >+ else >+ state->proto = IPPROTO_IP; >+ state->flags |= HAVE_PROTO; >+} >+ >+static int >+match_opcode(int opcode, const int opcodes[], size_t nops) >+{ >+ int i; >+ >+ for (i = 0; i < nops; i++) >+ if (opcode == opcodes[i]) >+ return (1); >+ return (0); >+} >+ >+static void >+print_address(struct buf_pr *bp, struct format_opts *fo, >+ struct show_state *state, const int opcodes[], size_t nops, int portop, >+ int flag) >+{ >+ ipfw_insn *cmd; >+ int count, l, portcnt; >+ >+ count = portcnt = 0; >+ for (l = state->rule->act_ofs, cmd = state->rule->cmd; >+ l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { >+ if (match_opcode(cmd->opcode, opcodes, nops)) >+ count++; >+ else if (cmd->opcode == portop) >+ portcnt++; >+ } >+ if (count == 0) >+ bprintf(bp, " any"); >+ for (l = state->rule->act_ofs, cmd = state->rule->cmd; >+ l > 0 && count > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { >+ if (!match_opcode(cmd->opcode, opcodes, nops)) >+ continue; >+ cmd = print_opcode(bp, fo, state, cmd->opcode); >+ if (cmd != NULL && (cmd->len & F_OR) == 0) >+ break; >+ count--; >+ } >+ /* Print ports */ >+ state->flags |= flag; >+ for (l = state->rule->act_ofs, cmd = state->rule->cmd; >+ l > 0 && portcnt > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { >+ if (cmd->opcode != portop) >+ continue; >+ cmd = print_opcode(bp, fo, state, cmd->opcode); >+ if (cmd != NULL && (cmd->len & F_OR) == 0) >+ break; >+ portcnt--; >+ } >+} >+ >+static const int action_opcodes[] = { >+ O_CHECK_STATE, O_ACCEPT, O_COUNT, O_DENY, O_REJECT, O_UNREACH6, >+ O_SKIPTO, O_PIPE, O_QUEUE, O_DIVERT, O_TEE, O_NETGRAPH, O_NGTEE, >+ O_FORWARD_IP, O_FORWARD_IP6, O_NAT, O_SETFIB, O_SETDSCP, O_REASS, >+ O_CALLRETURN, O_EXTERNAL_ACTION, O_EXTERNAL_INSTANCE, O_EXTERNAL_DATA >+}; >+ >+static const int modifier_opcodes[] = { >+ O_LOG, O_ALTQ, O_TAG >+}; >+ >+static const int src_opcodes[] = { >+ O_IP_SRC, O_IP_SRC_LOOKUP, O_IP_SRC_MASK, O_IP_SRC_ME, >+ O_IP_SRC_SET, O_IP6_SRC, O_IP6_SRC_MASK, O_IP6_SRC_ME >+}; >+ >+static const int dst_opcodes[] = { >+ 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 >+}; >+ >+static void >+show_static_rule2(struct cmdline_opts *co, struct format_opts *fo, >+ struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr) >+{ >+ struct show_state state; >+ ipfw_insn *cmd; >+ static int twidth = 0; >+ int i; >+ >+ /* Print # DISABLED or skip the rule */ >+ if ((fo->set_mask & (1 << rule->set)) == 0) { >+ /* disabled mask */ >+ if (!co->show_sets) >+ return; >+ else >+ bprintf(bp, "# DISABLED "); >+ } >+ bprintf(bp, "%05u ", rule->rulenum); >+ >+ /* Print counters if enabled */ >+ if (fo->pcwidth > 0 || fo->bcwidth > 0) { >+ pr_u64(bp, &cntr->pcnt, fo->pcwidth); >+ pr_u64(bp, &cntr->bcnt, fo->bcwidth); >+ } >+ >+ /* Print timestamp */ >+ if (co->do_time == TIMESTAMP_NUMERIC) >+ bprintf(bp, "%10u ", cntr->timestamp); >+ else if (co->do_time == TIMESTAMP_STRING) { >+ char timestr[30]; >+ time_t t = (time_t)0; >+ >+ if (twidth == 0) { >+ strcpy(timestr, ctime(&t)); >+ *strchr(timestr, '\n') = '\0'; >+ twidth = strlen(timestr); >+ } >+ if (cntr->timestamp > 0) { >+ t = _long_to_time(cntr->timestamp); >+ >+ strcpy(timestr, ctime(&t)); >+ *strchr(timestr, '\n') = '\0'; >+ bprintf(bp, "%s ", timestr); >+ } else { >+ bprintf(bp, "%*s", twidth, " "); >+ } >+ } >+ >+ /* Print set number */ >+ if (co->show_sets) >+ bprintf(bp, "set %d ", rule->set); >+ >+ init_state(&state, rule); >+ /* Print the optional "match probability" */ >+ cmd = print_opcode(bp, fo, &state, O_PROB); >+ /* Print rule action */ >+ for (i = 0; i < nitems(action_opcodes); i++) { >+ cmd = print_action(bp, fo, &state, action_opcodes[i]); >+ if (cmd == NULL) >+ continue; >+ /* Handle special cases */ >+ switch (cmd->opcode) { >+ case O_CHECK_STATE: >+ goto end; >+ case O_EXTERNAL_ACTION: >+ case O_EXTERNAL_INSTANCE: >+ /* External action can have several instructions */ >+ continue; >+ } >+ break; >+ } >+ /* Print rule modifiers */ >+ for (i = 0; i < nitems(modifier_opcodes); i++) >+ print_action(bp, fo, &state, modifier_opcodes[i]); >+ /* >+ * Print rule body >+ */ >+ if (co->comment_only != 0) >+ goto end; >+ print_proto(bp, fo, &state); >+ if (rule->flags & IPFW_RULE_NOOPT) { /* empty rules before options */ >+ if (co->do_compact == 0) >+ bprintf(bp, " from any to any"); >+ } else >+ bprintf(bp, " from"); >+ >+ /* Print source */ >+ print_address(bp, fo, &state, src_opcodes, nitems(src_opcodes), >+ O_IP_SRCPORT, HAVE_SRCIP); >+ >+ /* Print destination */ >+ bprintf(bp, " to"); >+ print_address(bp, fo, &state, dst_opcodes, nitems(dst_opcodes), >+ O_IP_DSTPORT, HAVE_DSTIP); >+ >+ /* Print the rest of options */ >+ while (print_opcode(bp, fo, &state, 0)) >+ ; >+end: >+ /* Print comment at the end */ >+ cmd = print_opcode(bp, fo, &state, O_NOP); >+ if (co->comment_only != 0 && cmd == NULL) >+ bprintf(bp, " // ..."); >+ bprintf(bp, "\n"); >+} >+ >+static void > 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) > { >@@ -1881,13 +2689,8 @@ show_static_rule(struct cmdline_opts *co, struct f > if (cmd->len & F_NOT && cmd->opcode != O_IN) > bprintf(bp, " not"); > switch(cmd->opcode) { >- case O_MACADDR2: { >- ipfw_insn_mac *m = (ipfw_insn_mac *)cmd; >- >- bprintf(bp, " MAC"); >- print_mac(bp, m->addr, m->mask); >- print_mac(bp, m->addr + 6, m->mask + 6); >- } >+ case O_MACADDR2: >+ print_mac(bp, (ipfw_insn_mac *)cmd); > break; > > case O_MAC_TYPE: >@@ -2537,7 +3340,7 @@ list_static_range(struct cmdline_opts *co, struct > if (co->use_set && r->set != co->use_set - 1) > continue; > if (r->rulenum >= fo->first && r->rulenum <= fo->last) { >- show_static_rule(co, fo, bp, r, cntr); >+ show_static_rule2(co, fo, bp, r, cntr); > printf("%s", bp->buf); > c += rtlv->length; > bp_flush(bp); >@@ -5152,7 +5955,7 @@ ipfw_add(char *av[]) > sfo.tstate = tstate; > sfo.set_mask = (uint32_t)(-1); > bp_alloc(&bp, 4096); >- show_static_rule(&co, &sfo, &bp, rule, NULL); >+ show_static_rule2(&co, &sfo, &bp, rule, NULL); > printf("%s", bp.buf); > bp_free(&bp); > } >Index: sbin/ipfw/ipfw2.h >=================================================================== >--- sbin/ipfw/ipfw2.h (revision 331095) >+++ sbin/ipfw/ipfw2.h (working copy) >@@ -56,6 +56,12 @@ struct cmdline_opts { > > }; > >+enum { >+ TIMESTAMP_NONE = 0, >+ TIMESTAMP_STRING, >+ TIMESTAMP_NUMERIC, >+}; >+ > extern struct cmdline_opts co; > > /* >Index: sbin/ipfw/main.c >=================================================================== >--- sbin/ipfw/main.c (revision 331095) >+++ sbin/ipfw/main.c (working copy) >@@ -324,11 +324,11 @@ ipfw_main(int oldac, char **oldav) > break; > > case 't': >- co.do_time = 1; >+ co.do_time = TIMESTAMP_STRING; > break; > > case 'T': >- co.do_time = 2; /* numeric timestamp */ >+ co.do_time = TIMESTAMP_NUMERIC; > break; > > case 'v': /* verbose */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 222705
:
187264
|
191775
| 191779