^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Minimal BPF debugger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Minimal BPF debugger that mimics the kernel's engine (w/o extensions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * and allows for single stepping through selected packets from a pcap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * with a provided user filter in order to facilitate verification of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * BPF program. Besides others, this is useful to verify BPF programs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * before attaching to a live system, and can be used in socket filters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * cls_bpf, xt_bpf, team driver and e.g. PTP code; in particular when a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * single more complex BPF program is being used. Reasons for a more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * complex BPF program are likely primarily to optimize execution time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * for making a verdict when multiple simple BPF programs are combined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * into one in order to prevent parsing same headers multiple times.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * More on how to debug BPF opcodes see Documentation/networking/filter.rst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * which is the main document on BPF. Mini howto for getting started:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * 1) `./bpf_dbg` to enter the shell (shell cmds denoted with '>'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 2) > load bpf 6,40 0 0 12,21 0 3 20... (output from `bpf_asm` or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * `tcpdump -iem1 -ddd port 22 | tr '\n' ','` to load as filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * 3) > load pcap foo.pcap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 4) > run <n>/disassemble/dump/quit (self-explanatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 5) > breakpoint 2 (sets bp at loaded BPF insns 2, do `run` then;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * multiple bps can be set, of course, a call to `breakpoint`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * w/o args shows currently loaded bps, `breakpoint reset` for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * resetting all breakpoints)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 6) > select 3 (`run` etc will start from the 3rd packet in the pcap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 7) > step [-<n>, +<n>] (performs single stepping through the BPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <setjmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/filter.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/if_packet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <readline/readline.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <readline/history.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <sys/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <arpa/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <net/ethernet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define TCPDUMP_MAGIC 0xa1b2c3d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define BPF_LDX_B (BPF_LDX | BPF_B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define BPF_LDX_W (BPF_LDX | BPF_W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define BPF_JMP_JA (BPF_JMP | BPF_JA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define BPF_JMP_JEQ (BPF_JMP | BPF_JEQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define BPF_JMP_JGT (BPF_JMP | BPF_JGT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define BPF_JMP_JGE (BPF_JMP | BPF_JGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define BPF_JMP_JSET (BPF_JMP | BPF_JSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define BPF_ALU_ADD (BPF_ALU | BPF_ADD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define BPF_ALU_SUB (BPF_ALU | BPF_SUB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define BPF_ALU_MUL (BPF_ALU | BPF_MUL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define BPF_ALU_DIV (BPF_ALU | BPF_DIV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define BPF_ALU_MOD (BPF_ALU | BPF_MOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define BPF_ALU_NEG (BPF_ALU | BPF_NEG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define BPF_ALU_AND (BPF_ALU | BPF_AND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define BPF_ALU_OR (BPF_ALU | BPF_OR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define BPF_ALU_XOR (BPF_ALU | BPF_XOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define BPF_ALU_LSH (BPF_ALU | BPF_LSH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define BPF_ALU_RSH (BPF_ALU | BPF_RSH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define BPF_MISC_TAX (BPF_MISC | BPF_TAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define BPF_MISC_TXA (BPF_MISC | BPF_TXA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define BPF_LD_B (BPF_LD | BPF_B)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define BPF_LD_H (BPF_LD | BPF_H)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define BPF_LD_W (BPF_LD | BPF_W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #ifndef array_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) # define array_size(x) (sizeof(x) / sizeof((x)[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #ifndef __check_format_printf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) # define __check_format_printf(pos_fmtstr, pos_fmtargs) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) __attribute__ ((format (printf, (pos_fmtstr), (pos_fmtargs))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) CMD_OK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) CMD_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) CMD_EX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct shell_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int (*func)(char *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct pcap_filehdr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) uint32_t magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) uint16_t version_major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) uint16_t version_minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int32_t thiszone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) uint32_t sigfigs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) uint32_t snaplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) uint32_t linktype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct pcap_timeval {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int32_t tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int32_t tv_usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct pcap_pkthdr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct pcap_timeval ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) uint32_t caplen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) uint32_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct bpf_regs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) uint32_t A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) uint32_t X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) uint32_t M[BPF_MEMWORDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) uint32_t R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bool Rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) uint16_t Pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static struct sock_filter bpf_image[BPF_MAXINSNS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static unsigned int bpf_prog_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int bpf_breakpoints[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static struct bpf_regs bpf_regs[BPF_MAXINSNS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static struct bpf_regs bpf_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static unsigned int bpf_regs_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int pcap_fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static unsigned int pcap_packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static size_t pcap_map_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static char *pcap_ptr_va_start, *pcap_ptr_va_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const char * const op_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) [BPF_ST] = "st",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) [BPF_STX] = "stx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) [BPF_LD_B] = "ldb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) [BPF_LD_H] = "ldh",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) [BPF_LD_W] = "ld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) [BPF_LDX] = "ldx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) [BPF_LDX_B] = "ldxb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) [BPF_JMP_JA] = "ja",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) [BPF_JMP_JEQ] = "jeq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) [BPF_JMP_JGT] = "jgt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) [BPF_JMP_JGE] = "jge",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) [BPF_JMP_JSET] = "jset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) [BPF_ALU_ADD] = "add",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) [BPF_ALU_SUB] = "sub",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) [BPF_ALU_MUL] = "mul",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) [BPF_ALU_DIV] = "div",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) [BPF_ALU_MOD] = "mod",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) [BPF_ALU_NEG] = "neg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) [BPF_ALU_AND] = "and",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) [BPF_ALU_OR] = "or",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) [BPF_ALU_XOR] = "xor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) [BPF_ALU_LSH] = "lsh",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) [BPF_ALU_RSH] = "rsh",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) [BPF_MISC_TAX] = "tax",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) [BPF_MISC_TXA] = "txa",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) [BPF_RET] = "ret",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static __check_format_printf(1, 2) int rl_printf(const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) va_list vl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) va_start(vl, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ret = vfprintf(rl_outstream, fmt, vl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) va_end(vl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int matches(const char *cmd, const char *pattern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int len = strlen(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (len > strlen(pattern))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return memcmp(pattern, cmd, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void hex_dump(const uint8_t *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) rl_printf("%3u: ", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (i && !(i % 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) rl_printf("\n%3u: ", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) rl_printf("%02x ", buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) rl_printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static bool bpf_prog_loaded(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (bpf_prog_len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) rl_printf("no bpf program loaded!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return bpf_prog_len > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void bpf_disasm(const struct sock_filter f, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) const char *op, *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int val = f.k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) char buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) switch (f.code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) case BPF_RET | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) op = op_table[BPF_RET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case BPF_RET | BPF_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) op = op_table[BPF_RET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) fmt = "a";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case BPF_RET | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) op = op_table[BPF_RET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case BPF_MISC_TAX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) op = op_table[BPF_MISC_TAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) fmt = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case BPF_MISC_TXA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) op = op_table[BPF_MISC_TXA];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) fmt = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case BPF_ST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) op = op_table[BPF_ST];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) fmt = "M[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case BPF_STX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) op = op_table[BPF_STX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) fmt = "M[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case BPF_LD_W | BPF_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) op = op_table[BPF_LD_W];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) fmt = "[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case BPF_LD_H | BPF_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) op = op_table[BPF_LD_H];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) fmt = "[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case BPF_LD_B | BPF_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) op = op_table[BPF_LD_B];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) fmt = "[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) case BPF_LD_W | BPF_LEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) op = op_table[BPF_LD_W];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) fmt = "#len";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case BPF_LD_W | BPF_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) op = op_table[BPF_LD_W];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) fmt = "[x+%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case BPF_LD_H | BPF_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) op = op_table[BPF_LD_H];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) fmt = "[x+%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) case BPF_LD_B | BPF_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) op = op_table[BPF_LD_B];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) fmt = "[x+%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case BPF_LD | BPF_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) op = op_table[BPF_LD_W];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case BPF_LDX | BPF_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) op = op_table[BPF_LDX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case BPF_LDX_B | BPF_MSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) op = op_table[BPF_LDX_B];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) fmt = "4*([%d]&0xf)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case BPF_LD | BPF_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) op = op_table[BPF_LD_W];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) fmt = "M[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case BPF_LDX | BPF_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) op = op_table[BPF_LDX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) fmt = "M[%d]";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case BPF_JMP_JA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) op = op_table[BPF_JMP_JA];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) fmt = "%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) val = i + 1 + f.k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case BPF_JMP_JGT | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) op = op_table[BPF_JMP_JGT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case BPF_JMP_JGT | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) op = op_table[BPF_JMP_JGT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case BPF_JMP_JGE | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) op = op_table[BPF_JMP_JGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case BPF_JMP_JGE | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) op = op_table[BPF_JMP_JGE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case BPF_JMP_JEQ | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) op = op_table[BPF_JMP_JEQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case BPF_JMP_JEQ | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) op = op_table[BPF_JMP_JEQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case BPF_JMP_JSET | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) op = op_table[BPF_JMP_JSET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case BPF_JMP_JSET | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) op = op_table[BPF_JMP_JSET];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case BPF_ALU_NEG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) op = op_table[BPF_ALU_NEG];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) fmt = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case BPF_ALU_LSH | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) op = op_table[BPF_ALU_LSH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case BPF_ALU_LSH | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) op = op_table[BPF_ALU_LSH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case BPF_ALU_RSH | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) op = op_table[BPF_ALU_RSH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) case BPF_ALU_RSH | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) op = op_table[BPF_ALU_RSH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case BPF_ALU_ADD | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) op = op_table[BPF_ALU_ADD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case BPF_ALU_ADD | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) op = op_table[BPF_ALU_ADD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) case BPF_ALU_SUB | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) op = op_table[BPF_ALU_SUB];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case BPF_ALU_SUB | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) op = op_table[BPF_ALU_SUB];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case BPF_ALU_MUL | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) op = op_table[BPF_ALU_MUL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case BPF_ALU_MUL | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) op = op_table[BPF_ALU_MUL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case BPF_ALU_DIV | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) op = op_table[BPF_ALU_DIV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case BPF_ALU_DIV | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) op = op_table[BPF_ALU_DIV];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case BPF_ALU_MOD | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) op = op_table[BPF_ALU_MOD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) case BPF_ALU_MOD | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) op = op_table[BPF_ALU_MOD];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) fmt = "#%d";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case BPF_ALU_AND | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) op = op_table[BPF_ALU_AND];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) case BPF_ALU_AND | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) op = op_table[BPF_ALU_AND];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case BPF_ALU_OR | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) op = op_table[BPF_ALU_OR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) case BPF_ALU_OR | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) op = op_table[BPF_ALU_OR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) case BPF_ALU_XOR | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) op = op_table[BPF_ALU_XOR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) fmt = "x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) case BPF_ALU_XOR | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) op = op_table[BPF_ALU_XOR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) fmt = "#%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) op = "nosup";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) fmt = "%#x";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) val = f.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) memset(buf, 0, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) snprintf(buf, sizeof(buf), fmt, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) buf[sizeof(buf) - 1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if ((BPF_CLASS(f.code) == BPF_JMP && BPF_OP(f.code) != BPF_JA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) rl_printf("l%d:\t%s %s, l%d, l%d\n", i, op, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) i + 1 + f.jt, i + 1 + f.jf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) rl_printf("l%d:\t%s %s\n", i, op, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static void bpf_dump_curr(struct bpf_regs *r, struct sock_filter *f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int i, m = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) rl_printf("pc: [%u]\n", r->Pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) rl_printf("code: [%u] jt[%u] jf[%u] k[%u]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) f->code, f->jt, f->jf, f->k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) rl_printf("curr: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) bpf_disasm(*f, r->Pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (f->jt || f->jf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) rl_printf("jt: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) bpf_disasm(*(f + f->jt + 1), r->Pc + f->jt + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) rl_printf("jf: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) bpf_disasm(*(f + f->jf + 1), r->Pc + f->jf + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) rl_printf("A: [%#08x][%u]\n", r->A, r->A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) rl_printf("X: [%#08x][%u]\n", r->X, r->X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (r->Rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) rl_printf("ret: [%#08x][%u]!\n", r->R, r->R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) for (i = 0; i < BPF_MEMWORDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (r->M[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) m++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) rl_printf("M[%d]: [%#08x][%u]\n", i, r->M[i], r->M[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (m == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) rl_printf("M[0,%d]: [%#08x][%u]\n", BPF_MEMWORDS - 1, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static void bpf_dump_pkt(uint8_t *pkt, uint32_t pkt_caplen, uint32_t pkt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (pkt_caplen != pkt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) rl_printf("cap: %u, len: %u\n", pkt_caplen, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rl_printf("len: %u\n", pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) hex_dump(pkt, pkt_caplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static void bpf_disasm_all(const struct sock_filter *f, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) bpf_disasm(f[i], i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static void bpf_dump_all(const struct sock_filter *f, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) rl_printf("/* { op, jt, jf, k }, */\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) rl_printf("{ %#04x, %2u, %2u, %#010x },\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) f[i].code, f[i].jt, f[i].jf, f[i].k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static bool bpf_runnable(struct sock_filter *f, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) int sock, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct sock_fprog bpf = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .filter = f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .len = len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) sock = socket(AF_INET, SOCK_DGRAM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (sock < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) rl_printf("cannot open socket!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) close(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) rl_printf("program not allowed to run by kernel!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (BPF_CLASS(f[i].code) == BPF_LD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) f[i].k > SKF_AD_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) rl_printf("extensions currently not supported!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static void bpf_reset_breakpoints(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) for (i = 0; i < array_size(bpf_breakpoints); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) bpf_breakpoints[i] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static void bpf_set_breakpoints(unsigned int where)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) bool set = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) for (i = 0; i < array_size(bpf_breakpoints); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (bpf_breakpoints[i] == (int) where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) rl_printf("breakpoint already set!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (bpf_breakpoints[i] == -1 && set == false) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) bpf_breakpoints[i] = where;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (!set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) rl_printf("too many breakpoints set, reset first!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static void bpf_dump_breakpoints(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) rl_printf("breakpoints: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) for (i = 0; i < array_size(bpf_breakpoints); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (bpf_breakpoints[i] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) rl_printf("%d ", bpf_breakpoints[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) rl_printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static void bpf_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) bpf_regs_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) memset(bpf_regs, 0, sizeof(bpf_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) memset(&bpf_curr, 0, sizeof(bpf_curr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static void bpf_safe_regs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) memcpy(&bpf_regs[bpf_regs_len++], &bpf_curr, sizeof(bpf_curr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static bool bpf_restore_regs(int off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) unsigned int index = bpf_regs_len - 1 + off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (index == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) bpf_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) } else if (index < bpf_regs_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) memcpy(&bpf_curr, &bpf_regs[index], sizeof(bpf_curr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) bpf_regs_len = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) rl_printf("reached bottom of register history stack!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static uint32_t extract_u32(uint8_t *pkt, uint32_t off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) uint32_t r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) memcpy(&r, &pkt[off], sizeof(r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return ntohl(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static uint16_t extract_u16(uint8_t *pkt, uint32_t off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) uint16_t r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) memcpy(&r, &pkt[off], sizeof(r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return ntohs(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static uint8_t extract_u8(uint8_t *pkt, uint32_t off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return pkt[off];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static void set_return(struct bpf_regs *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) r->R = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) r->Rs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) static void bpf_single_step(struct bpf_regs *r, struct sock_filter *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) uint8_t *pkt, uint32_t pkt_caplen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) uint32_t pkt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) uint32_t K = f->k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) switch (f->code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) case BPF_RET | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) r->R = K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) r->Rs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case BPF_RET | BPF_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) r->R = r->A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) r->Rs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case BPF_RET | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) r->R = r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) r->Rs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) case BPF_MISC_TAX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) r->X = r->A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case BPF_MISC_TXA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) r->A = r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) case BPF_ST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) r->M[K] = r->A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case BPF_STX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) r->M[K] = r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) case BPF_LD_W | BPF_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) d = pkt_caplen - K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (d >= sizeof(uint32_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) r->A = extract_u32(pkt, K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) case BPF_LD_H | BPF_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) d = pkt_caplen - K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (d >= sizeof(uint16_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) r->A = extract_u16(pkt, K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) case BPF_LD_B | BPF_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) d = pkt_caplen - K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (d >= sizeof(uint8_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) r->A = extract_u8(pkt, K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case BPF_LD_W | BPF_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) d = pkt_caplen - (r->X + K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (d >= sizeof(uint32_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) r->A = extract_u32(pkt, r->X + K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) case BPF_LD_H | BPF_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) d = pkt_caplen - (r->X + K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (d >= sizeof(uint16_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) r->A = extract_u16(pkt, r->X + K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) case BPF_LD_B | BPF_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) d = pkt_caplen - (r->X + K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (d >= sizeof(uint8_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) r->A = extract_u8(pkt, r->X + K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) case BPF_LDX_B | BPF_MSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) d = pkt_caplen - K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (d >= sizeof(uint8_t)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) r->X = extract_u8(pkt, K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) r->X = (r->X & 0xf) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) case BPF_LD_W | BPF_LEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) r->A = pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) case BPF_LDX_W | BPF_LEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) r->A = pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) case BPF_LD | BPF_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) r->A = K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) case BPF_LDX | BPF_IMM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) r->X = K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) case BPF_LD | BPF_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) r->A = r->M[K];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case BPF_LDX | BPF_MEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) r->X = r->M[K];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) case BPF_JMP_JA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) r->Pc += K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) case BPF_JMP_JGT | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) r->Pc += r->A > r->X ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) case BPF_JMP_JGT | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) r->Pc += r->A > K ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case BPF_JMP_JGE | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) r->Pc += r->A >= r->X ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case BPF_JMP_JGE | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) r->Pc += r->A >= K ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) case BPF_JMP_JEQ | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) r->Pc += r->A == r->X ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) case BPF_JMP_JEQ | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) r->Pc += r->A == K ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) case BPF_JMP_JSET | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) r->Pc += r->A & r->X ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case BPF_JMP_JSET | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) r->Pc += r->A & K ? f->jt : f->jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) case BPF_ALU_NEG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) r->A = -r->A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case BPF_ALU_LSH | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) r->A <<= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) case BPF_ALU_LSH | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) r->A <<= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) case BPF_ALU_RSH | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) r->A >>= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) case BPF_ALU_RSH | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) r->A >>= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case BPF_ALU_ADD | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) r->A += r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case BPF_ALU_ADD | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) r->A += K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) case BPF_ALU_SUB | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) r->A -= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) case BPF_ALU_SUB | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) r->A -= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) case BPF_ALU_MUL | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) r->A *= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) case BPF_ALU_MUL | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) r->A *= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) case BPF_ALU_DIV | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) case BPF_ALU_MOD | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (r->X == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) goto do_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) case BPF_ALU_DIV | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) case BPF_ALU_MOD | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (K == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) set_return(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) do_div:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) switch (f->code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case BPF_ALU_DIV | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) r->A /= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) case BPF_ALU_DIV | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) r->A /= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) case BPF_ALU_MOD | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) r->A %= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) case BPF_ALU_MOD | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) r->A %= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) case BPF_ALU_AND | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) r->A &= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) case BPF_ALU_AND | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) r->A &= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) case BPF_ALU_OR | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) r->A |= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) case BPF_ALU_OR | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) r->A |= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case BPF_ALU_XOR | BPF_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) r->A ^= r->X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) case BPF_ALU_XOR | BPF_K:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) r->A ^= K;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) static bool bpf_pc_has_breakpoint(uint16_t pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) for (i = 0; i < array_size(bpf_breakpoints); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (bpf_breakpoints[i] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) if (bpf_breakpoints[i] == pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static bool bpf_handle_breakpoint(struct bpf_regs *r, struct sock_filter *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) uint8_t *pkt, uint32_t pkt_caplen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) uint32_t pkt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) rl_printf("-- register dump --\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) bpf_dump_curr(r, &f[r->Pc]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) rl_printf("-- packet dump --\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) bpf_dump_pkt(pkt, pkt_caplen, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) rl_printf("(breakpoint)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static int bpf_run_all(struct sock_filter *f, uint16_t bpf_len, uint8_t *pkt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) uint32_t pkt_caplen, uint32_t pkt_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) bool stop = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) while (bpf_curr.Rs == false && stop == false) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) bpf_safe_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (bpf_pc_has_breakpoint(bpf_curr.Pc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) stop = bpf_handle_breakpoint(&bpf_curr, f, pkt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) pkt_caplen, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) bpf_single_step(&bpf_curr, &f[bpf_curr.Pc], pkt, pkt_caplen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) bpf_curr.Pc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return stop ? -1 : bpf_curr.R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static int bpf_run_stepping(struct sock_filter *f, uint16_t bpf_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) uint8_t *pkt, uint32_t pkt_caplen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) uint32_t pkt_len, int next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) bool stop = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) int i = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) while (bpf_curr.Rs == false && stop == false) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) bpf_safe_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (i++ == next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) stop = bpf_handle_breakpoint(&bpf_curr, f, pkt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) pkt_caplen, pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) bpf_single_step(&bpf_curr, &f[bpf_curr.Pc], pkt, pkt_caplen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) pkt_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) bpf_curr.Pc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return stop ? -1 : bpf_curr.R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static bool pcap_loaded(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (pcap_fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) rl_printf("no pcap file loaded!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return pcap_fd >= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static struct pcap_pkthdr *pcap_curr_pkt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) return (void *) pcap_ptr_va_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static bool pcap_next_pkt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct pcap_pkthdr *hdr = pcap_curr_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (pcap_ptr_va_curr + sizeof(*hdr) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) pcap_ptr_va_start >= pcap_map_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (hdr->caplen == 0 || hdr->len == 0 || hdr->caplen > hdr->len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (pcap_ptr_va_curr + sizeof(*hdr) + hdr->caplen -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) pcap_ptr_va_start >= pcap_map_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) pcap_ptr_va_curr += (sizeof(*hdr) + hdr->caplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static void pcap_reset_pkt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) pcap_ptr_va_curr = pcap_ptr_va_start + sizeof(struct pcap_filehdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static int try_load_pcap(const char *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct pcap_filehdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct stat sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) pcap_fd = open(file, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (pcap_fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) rl_printf("cannot open pcap [%s]!\n", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) ret = fstat(pcap_fd, &sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) rl_printf("cannot fstat pcap file!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (!S_ISREG(sb.st_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) rl_printf("not a regular pcap file, duh!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) pcap_map_size = sb.st_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (pcap_map_size <= sizeof(struct pcap_filehdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) rl_printf("pcap file too small!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pcap_ptr_va_start = mmap(NULL, pcap_map_size, PROT_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) MAP_SHARED | MAP_LOCKED, pcap_fd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (pcap_ptr_va_start == MAP_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) rl_printf("mmap of file failed!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) hdr = (void *) pcap_ptr_va_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (hdr->magic != TCPDUMP_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) rl_printf("wrong pcap magic!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) pcap_reset_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static void try_close_pcap(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (pcap_fd >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) munmap(pcap_ptr_va_start, pcap_map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) close(pcap_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) pcap_ptr_va_start = pcap_ptr_va_curr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) pcap_map_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) pcap_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) pcap_fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) static int cmd_load_bpf(char *bpf_string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) char sp, *token, separator = ',';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) unsigned short bpf_len, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct sock_filter tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) bpf_prog_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) memset(bpf_image, 0, sizeof(bpf_image));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (sscanf(bpf_string, "%hu%c", &bpf_len, &sp) != 2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) sp != separator || bpf_len > BPF_MAXINSNS || bpf_len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) rl_printf("syntax error in head length encoding!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) token = bpf_string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) while ((token = strchr(token, separator)) && (++token)[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (i >= bpf_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) rl_printf("program exceeds encoded length!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (sscanf(token, "%hu %hhu %hhu %u,",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) &tmp.code, &tmp.jt, &tmp.jf, &tmp.k) != 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) rl_printf("syntax error at instruction %d!\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) bpf_image[i].code = tmp.code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) bpf_image[i].jt = tmp.jt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) bpf_image[i].jf = tmp.jf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) bpf_image[i].k = tmp.k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (i != bpf_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) rl_printf("syntax error exceeding encoded length!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) bpf_prog_len = bpf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!bpf_runnable(bpf_image, bpf_prog_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) bpf_prog_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) static int cmd_load_pcap(char *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) char *file_trim, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) file_trim = strtok_r(file, " ", &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (file_trim == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) try_close_pcap();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return try_load_pcap(file_trim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int cmd_load(char *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) char *subcmd, *cont = NULL, *tmp = strdup(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int ret = CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) subcmd = strtok_r(tmp, " ", &cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (subcmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (matches(subcmd, "bpf") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) bpf_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) bpf_reset_breakpoints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!cont)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ret = CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ret = cmd_load_bpf(cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) } else if (matches(subcmd, "pcap") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) ret = cmd_load_pcap(cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) rl_printf("bpf <code>: load bpf code\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) rl_printf("pcap <file>: load pcap file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) ret = CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) static int cmd_step(char *num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct pcap_pkthdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) int steps, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (!bpf_prog_loaded() || !pcap_loaded())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) steps = strtol(num, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (steps == 0 || strlen(num) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) steps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (steps < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!bpf_restore_regs(steps))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) steps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) hdr = pcap_curr_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) ret = bpf_run_stepping(bpf_image, bpf_prog_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) (uint8_t *) hdr + sizeof(*hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) hdr->caplen, hdr->len, steps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (ret >= 0 || bpf_curr.Rs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) bpf_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (!pcap_next_pkt()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) rl_printf("(going back to first packet)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) pcap_reset_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) rl_printf("(next packet)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static int cmd_select(char *num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) unsigned int which, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) bool have_next = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!pcap_loaded() || strlen(num) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) which = strtoul(num, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (which == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) rl_printf("packet count starts with 1, clamping!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) which = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) pcap_reset_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) bpf_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) for (i = 0; i < which && (have_next = pcap_next_pkt()); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* noop */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (!have_next || pcap_curr_pkt() == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) rl_printf("no packet #%u available!\n", which);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) pcap_reset_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static int cmd_breakpoint(char *subcmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (!bpf_prog_loaded())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (strlen(subcmd) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) bpf_dump_breakpoints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) else if (matches(subcmd, "reset") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) bpf_reset_breakpoints();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) unsigned int where = strtoul(subcmd, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (where < bpf_prog_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) bpf_set_breakpoints(where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) rl_printf("breakpoint at: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) bpf_disasm(bpf_image[where], where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static int cmd_run(char *num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) static uint32_t pass, fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) bool has_limit = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) int pkts = 0, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (!bpf_prog_loaded() || !pcap_loaded())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) pkts = strtol(num, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (pkts == 0 || strlen(num) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) has_limit = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct pcap_pkthdr *hdr = pcap_curr_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) int ret = bpf_run_all(bpf_image, bpf_prog_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) (uint8_t *) hdr + sizeof(*hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) hdr->caplen, hdr->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) pass++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) else if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) fail++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) bpf_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) } while (pcap_next_pkt() && (!has_limit || (has_limit && ++i < pkts)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) rl_printf("bpf passes:%u fails:%u\n", pass, fail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) pcap_reset_pkt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) bpf_reset();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) pass = fail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static int cmd_disassemble(char *line_string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) bool single_line = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) unsigned long line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (!bpf_prog_loaded())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (strlen(line_string) > 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) (line = strtoul(line_string, NULL, 10)) < bpf_prog_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) single_line = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (single_line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) bpf_disasm(bpf_image[line], line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) bpf_disasm_all(bpf_image, bpf_prog_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) static int cmd_dump(char *dontcare)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (!bpf_prog_loaded())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return CMD_ERR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) bpf_dump_all(bpf_image, bpf_prog_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return CMD_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) static int cmd_quit(char *dontcare)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return CMD_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static const struct shell_cmd cmds[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) { .name = "load", .func = cmd_load },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) { .name = "select", .func = cmd_select },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) { .name = "step", .func = cmd_step },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) { .name = "run", .func = cmd_run },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) { .name = "breakpoint", .func = cmd_breakpoint },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) { .name = "disassemble", .func = cmd_disassemble },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) { .name = "dump", .func = cmd_dump },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) { .name = "quit", .func = cmd_quit },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) static int execf(char *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) char *cmd, *cont, *tmp = strdup(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) int i, ret = 0, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) cmd = strtok_r(tmp, " ", &cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) len = strlen(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) for (i = 0; i < array_size(cmds); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (len != strlen(cmds[i].name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (strncmp(cmds[i].name, cmd, len) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) ret = cmds[i].func(cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) static char *shell_comp_gen(const char *buf, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static int list_index, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (!state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) list_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) len = strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) for (; list_index < array_size(cmds); ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) const char *name = cmds[list_index].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) list_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (strncmp(name, buf, len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return strdup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static char **shell_completion(const char *buf, int start, int end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) char **matches = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (start == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) matches = rl_completion_matches(buf, shell_comp_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) return matches;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) static void intr_shell(int sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (rl_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) rl_kill_line(-1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) rl_crlf();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) rl_refresh_line(0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) rl_free_line_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static void init_shell(FILE *fin, FILE *fout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) char file[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) snprintf(file, sizeof(file), "%s/.bpf_dbg_history", getenv("HOME"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) read_history(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) rl_instream = fin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) rl_outstream = fout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) rl_readline_name = "bpf_dbg";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) rl_terminal_name = getenv("TERM");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) rl_catch_signals = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) rl_catch_sigwinch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) rl_attempted_completion_function = shell_completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) rl_bind_key('\t', rl_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) rl_bind_key_in_map('\t', rl_complete, emacs_meta_keymap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) rl_bind_key_in_map('\033', rl_complete, emacs_meta_keymap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) snprintf(file, sizeof(file), "%s/.bpf_dbg_init", getenv("HOME"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) rl_read_init_file(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) rl_prep_terminal(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) rl_set_signals();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) signal(SIGINT, intr_shell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) static void exit_shell(FILE *fin, FILE *fout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) char file[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) snprintf(file, sizeof(file), "%s/.bpf_dbg_history", getenv("HOME"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) write_history(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) clear_history();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) rl_deprep_terminal();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) try_close_pcap();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (fin != stdin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) fclose(fin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (fout != stdout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) fclose(fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) static int run_shell_loop(FILE *fin, FILE *fout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) init_shell(fin, fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) while ((buf = readline("> ")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) int ret = execf(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (ret == CMD_EX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (ret == CMD_OK && strlen(buf) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) add_history(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) free(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) exit_shell(fin, fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) FILE *fin = NULL, *fout = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (argc >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) fin = fopen(argv[1], "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (argc >= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) fout = fopen(argv[2], "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) return run_shell_loop(fin ? : stdin, fout ? : stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) }