/*
* Minimal BPF debugger
*
* Minimal BPF debugger that mimics the kernel's engine (w/o extensions)
* and allows for single stepping through selected packets from a pcap
* with a provided user filter in order to facilitate verification of a
* BPF program. Besides others, this is useful to verify BPF programs
* before attaching to a live system, and can be used in socket filters,
* cls_bpf, xt_bpf, team driver and e.g. PTP code; in particular when a
* single more complex BPF program is being used. Reasons for a more
* complex BPF program are likely primarily to optimize execution time
* for making a verdict when multiple simple BPF programs are combined
* into one in order to prevent parsing same headers multiple times.
*
* More on how to debug BPF opcodes see Documentation/networking/filter.txt
* which is the main document on BPF. Mini howto for getting started:
*
* 1) `./bpf_dbg` to enter the shell (shell cmds denoted with '>'):
* 2) > load bpf 6,40 0 0 12,21 0 3 20... (output from `bpf_asm` or
* `tcpdump -iem1 -ddd port 22 | tr '\n' ','` to load as filter)
* 3) > load pcap foo.pcap
* 4) > run <n>/disassemble/dump/quit (self-explanatory)
* 5) > breakpoint 2 (sets bp at loaded BPF insns 2, do `run` then;
* multiple bps can be set, of course, a call to `breakpoint`
* w/o args shows currently loaded bps, `breakpoint reset` for
* resetting all breakpoints)
* 6) > select 3 (`run` etc will start from the 3rd packet in the pcap)
* 7) > step [-<n>, +<n>] (performs single stepping through the BPF)
*
* Copyright 2013 Daniel Borkmann <borkmann@redhat.com>
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdarg.h>
#include <setjmp.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#define TCPDUMP_MAGIC 0xa1b2c3d4
#define BPF_LDX_B (BPF_LDX | BPF_B)
#define BPF_LDX_W (BPF_LDX | BPF_W)
#define BPF_JMP_JA (BPF_JMP | BPF_JA)
#define BPF_JMP_JEQ (BPF_JMP | BPF_JEQ)
#define BPF_JMP_JGT (BPF_JMP | BPF_JGT)
#define BPF_JMP_JGE (BPF_JMP | BPF_JGE)
#define BPF_JMP_JSET (BPF_JMP | BPF_JSET)
#define BPF_ALU_ADD (BPF_ALU | BPF_ADD)
#define BPF_ALU_SUB (BPF_ALU | BPF_SUB)
#define BPF_ALU_MUL (BPF_ALU | BPF_MUL)
#define BPF_ALU_DIV (BPF_ALU | BPF_DIV)
#define BPF_ALU_MOD (BPF_ALU | BPF_MOD)
#define BPF_ALU_NEG (BPF_ALU | BPF_NEG)
#define BPF_ALU_AND (BPF_ALU | BPF_AND)
#define BPF_ALU_OR (BPF_ALU | BPF_OR)
#define BPF_ALU_XOR (BPF_ALU | BPF_XOR)
#define BPF_ALU_LSH (BPF_ALU | BPF_LSH)
#define BPF_ALU_RSH (BPF_ALU | BPF_RSH)
#define BPF_MISC_TAX (BPF_MISC | BPF_TAX)
#define BPF_MISC_TXA (BPF_MISC | BPF_TXA)
#define BPF_LD_B (BPF_LD | BPF_B)
#define BPF_LD_H (BPF_LD | BPF_H)
#define BPF_LD_W (BPF_LD | BPF_W)
#ifndef array_size
# define array_size(x) (sizeof(x) / sizeof((x)[0]))
#endif
#ifndef __check_format_printf
# define __check_format_printf(pos_fmtstr, pos_fmtargs) \
__attribute__ ((format (printf, (pos_fmtstr), (pos_fmtargs))))
#endif
#define CMD(_name, _func) { .name = _name, .func = _func, }
#define OP(_op, _name) [_op] = _name
enum {
CMD_OK,
CMD_ERR,
CMD_EX,
};
struct shell_cmd {
const char *name;
int (*func)(char *args);
};
struct pcap_filehdr {
uint32_t magic;
uint16_t version_major;
uint16_t version_minor;
int32_t thiszone;
<