| 2026 | } |
| 2027 | |
| 2028 | static void |
| 2029 | print_proto(struct buf_pr *bp, struct format_opts *fo, |
| 2030 | struct show_state *state) |
| 2031 | { |
| 2032 | ipfw_insn *cmd; |
| 2033 | int l, proto, ip4, ip6; |
| 2034 | |
| 2035 | /* Count all O_PROTO, O_IP4, O_IP6 instructions. */ |
| 2036 | proto = ip4 = ip6 = 0; |
| 2037 | for (l = state->rule->act_ofs, cmd = state->rule->cmd; |
| 2038 | l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) { |
| 2039 | switch (cmd->opcode) { |
| 2040 | case O_PROTO: |
| 2041 | proto++; |
| 2042 | break; |
| 2043 | case O_IP4: |
| 2044 | ip4 = 1; |
| 2045 | if (cmd->len & F_OR) |
| 2046 | ip4++; |
| 2047 | break; |
| 2048 | case O_IP6: |
| 2049 | ip6 = 1; |
| 2050 | if (cmd->len & F_OR) |
| 2051 | ip6++; |
| 2052 | break; |
| 2053 | default: |
| 2054 | continue; |
| 2055 | } |
| 2056 | } |
| 2057 | if (proto == 0 && ip4 == 0 && ip6 == 0) { |
| 2058 | state->proto = IPPROTO_IP; |
| 2059 | state->flags |= HAVE_PROTO; |
| 2060 | bprintf(bp, " ip"); |
| 2061 | return; |
| 2062 | } |
| 2063 | /* To handle the case { ip4 or ip6 }, print opcode with F_OR first */ |
| 2064 | cmd = NULL; |
| 2065 | if (ip4 || ip6) |
| 2066 | cmd = print_opcode(bp, fo, state, ip4 > ip6 ? O_IP4: O_IP6); |
| 2067 | if (cmd != NULL && (cmd->len & F_OR)) |
| 2068 | cmd = print_opcode(bp, fo, state, ip4 > ip6 ? O_IP6: O_IP4); |
| 2069 | if (cmd == NULL || (cmd->len & F_OR)) |
| 2070 | for (l = proto; l > 0; l--) { |
| 2071 | cmd = print_opcode(bp, fo, state, O_PROTO); |
| 2072 | if (cmd == NULL || (cmd->len & F_OR) == 0) |
| 2073 | break; |
| 2074 | } |
| 2075 | /* Initialize proto, it is used by print_newports() */ |
| 2076 | state->flags |= HAVE_PROTO; |
| 2077 | if (state->proto == 0 && ip6 != 0) |
| 2078 | state->proto = IPPROTO_IPV6; |
| 2079 | } |
| 2080 | |
| 2081 | static int |
| 2082 | match_opcode(int opcode, const int opcodes[], size_t nops) |
no test coverage detected