diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2013-03-16 19:04:39 +0100 |
---|---|---|
committer | Daniel Borkmann <dborkman@redhat.com> | 2013-03-16 19:04:39 +0100 |
commit | a7b0ee3852e05dc92bb98971c09e271d4d7f245e (patch) | |
tree | b884f0ea1c70d3befa6634e22b6e2d5adea7f41c | |
parent | 135167da52296dc602e3fe6f1552d30af56ca12c (diff) |
bpfc: support different output formats
Add different bpf opcode pretty printer to support a variety of
output formats for netsniff-ng, xt_bpf, tcpdump, C-like and make
future integration of formats easier.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
-rw-r--r-- | bpf_parser.y | 70 | ||||
-rw-r--r-- | bpfc.c | 32 |
2 files changed, 80 insertions, 22 deletions
diff --git a/bpf_parser.y b/bpf_parser.y index 4c35e07..7f6bcc8 100644 --- a/bpf_parser.y +++ b/bpf_parser.y @@ -25,7 +25,7 @@ #define MAX_INSTRUCTIONS 4096 -int compile_filter(char *file, int verbose, int bypass, int decimal); +int compile_filter(char *file, int verbose, int bypass, int format); static int curr_instr = 0; @@ -597,7 +597,60 @@ static void stage_2_label_reduce(void) } } -int compile_filter(char *file, int verbose, int bypass, int decimal) +static void pretty_printer_c(const struct sock_fprog *prog) +{ + int i; + + for (i = 0; i < prog->len; ++i) { + printf("{ 0x%x, %u, %u, 0x%08x },\n", + prog->filter[i].code, prog->filter[i].jt, + prog->filter[i].jf, prog->filter[i].k); + } +} + +static void pretty_printer_xt_bpf(const struct sock_fprog *prog) +{ + int i; + + printf("%d,", prog->len); + for (i = 0; i < prog->len; ++i) { + printf("%u %u %u %u,", + prog->filter[i].code, prog->filter[i].jt, + prog->filter[i].jf, prog->filter[i].k); + } + + fflush(stdout); +} + +static void pretty_printer_tcpdump(const struct sock_fprog *prog) +{ + int i; + + for (i = 0; i < prog->len; ++i) { + printf("%u %u %u %u\n", + prog->filter[i].code, prog->filter[i].jt, + prog->filter[i].jf, prog->filter[i].k); + } +} + +static void pretty_printer(const struct sock_fprog *prog, int format) +{ + switch (format) { + case 0: + pretty_printer_c(prog); + break; + case 1: + pretty_printer_xt_bpf(prog); + break; + case 2: + pretty_printer_tcpdump(prog); + break; + default: + bug(); + } +} + +int compile_filter(char *file, int verbose, int bypass, int format) { int i; struct sock_fprog res; @@ -645,17 +698,10 @@ int compile_filter(char *file, int verbose, int bypass, int decimal) if (verbose) printf("Result:\n"); - for (i = 0; i < res.len; ++i) { - if (decimal) { - printf("%u %u %u %u\n", - res.filter[i].code, res.filter[i].jt, - res.filter[i].jf, res.filter[i].k); - } else { - printf("{ 0x%x, %u, %u, 0x%08x },\n", - res.filter[i].code, res.filter[i].jt, - res.filter[i].jf, res.filter[i].k); - } + pretty_printer(&res, format); + + for (i = 0; i < res.len; ++i) { free(labels[i]); free(labels_jt[i]); free(labels_jf[i]); @@ -17,11 +17,11 @@ #include "die.h" #include "bpf.h" -static const char *short_options = "vhi:VdbD"; +static const char *short_options = "vhi:Vdbf:"; static const struct option long_options[] = { {"input", required_argument, NULL, 'i'}, + {"format", required_argument, NULL, 'f'}, {"verbose", no_argument, NULL, 'V'}, - {"decimal", no_argument, NULL, 'D'}, {"bypass", no_argument, NULL, 'b'}, {"dump", no_argument, NULL, 'd'}, {"version", no_argument, NULL, 'v'}, @@ -29,7 +29,7 @@ static const struct option long_options[] = { {NULL, 0, NULL, 0} }; -extern int compile_filter(char *file, int verbose, int bypass, int decimal); +extern int compile_filter(char *file, int verbose, int bypass, int format); static void help(void) { @@ -38,15 +38,18 @@ static void help(void) "Usage: bpfc [options] || bpfc <program>\n" "Options:\n" " -i|--input <program/-> Berkeley Packet Filter file/stdin\n" - " -D|--decimal Decimal output, e.g. for xt_bpf\n" - " -V|--verbose Be more verbose\n" + " -f|--format <format> Output format: C|netsniff-ng|xt_bpf|tcpdump\n" " -b|--bypass Bypass filter validation (e.g. for bug testing)\n" + " -V|--verbose Be more verbose\n" " -d|--dump Dump supported instruction table\n" " -v|--version Print version\n" " -h|--help Print this help\n\n" "Examples:\n" " bpfc fubar\n" - " bpfc -Dbi fubar\n" + " bpfc fubar > foo (bpfc -f C -i fubar > foo) --> netsniff-ng -f foo ...\n" + " bpfc -f tcpdump -i fubar > foo --> tcpdump -ddd like ...\n" + " bpfc -f xt_bpf -b -i fubar\n" + " iptables -A INPUT -m bpf --bytecode \"`./bpfc -f xt_bpf -i fubar`\" -j LOG\n" " bpfc - (read from stdin)\n\n" "Please report bugs to <bugs@netsniff-ng.org>\n" "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n" @@ -72,7 +75,7 @@ static void version(void) int main(int argc, char **argv) { - int ret, verbose = 0, c, opt_index, bypass = 0, decimal = 0; + int ret, verbose = 0, c, opt_index, bypass = 0, format = 0; char *file = NULL; setfsuid(getuid()); @@ -93,8 +96,16 @@ int main(int argc, char **argv) case 'V': verbose = 1; break; - case 'D': - decimal = 1; + case 'f': + if (!strncmp(optarg, "C", 1) || + !strncmp(optarg, "netsniff-ng", 11)) + format = 0; + else if (!strncmp(optarg, "xt_bpf", 6)) + format = 1; + else if (!strncmp(optarg, "tcpdump", 7)) + format = 2; + else + help(); break; case 'b': bypass = 1; @@ -108,6 +119,7 @@ int main(int argc, char **argv) case '?': switch (optopt) { case 'i': + case 'f': panic("Option -%c requires an argument!\n", optopt); default: @@ -125,7 +137,7 @@ int main(int argc, char **argv) if (!file) panic("No Berkeley Packet Filter program specified!\n"); - ret = compile_filter(file, verbose, bypass, decimal); + ret = compile_filter(file, verbose, bypass, format); xfree(file); return ret; |