diff options
| -rw-r--r-- | tools/net/Makefile | 18 | ||||
| -rw-r--r-- | tools/net/bpf_asm.c | 52 | ||||
| -rw-r--r-- | tools/net/bpf_exp.l | 143 | ||||
| -rw-r--r-- | tools/net/bpf_exp.y | 749 |
4 files changed, 960 insertions, 2 deletions
diff --git a/tools/net/Makefile b/tools/net/Makefile index 0f30d923afa0..004cd74734b6 100644 --- a/tools/net/Makefile +++ b/tools/net/Makefile | |||
| @@ -1,8 +1,16 @@ | |||
| 1 | prefix = /usr | 1 | prefix = /usr |
| 2 | 2 | ||
| 3 | CC = gcc | 3 | CC = gcc |
| 4 | LEX = flex | ||
| 5 | YACC = bison | ||
| 4 | 6 | ||
| 5 | all : bpf_jit_disasm bpf_dbg | 7 | %.yacc.c: %.y |
| 8 | $(YACC) -o $@ -d $< | ||
| 9 | |||
| 10 | %.lex.c: %.l | ||
| 11 | $(LEX) -o $@ $< | ||
| 12 | |||
| 13 | all : bpf_jit_disasm bpf_dbg bpf_asm | ||
| 6 | 14 | ||
| 7 | bpf_jit_disasm : CFLAGS = -Wall -O2 | 15 | bpf_jit_disasm : CFLAGS = -Wall -O2 |
| 8 | bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl | 16 | bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl |
| @@ -12,9 +20,15 @@ bpf_dbg : CFLAGS = -Wall -O2 | |||
| 12 | bpf_dbg : LDLIBS = -lreadline | 20 | bpf_dbg : LDLIBS = -lreadline |
| 13 | bpf_dbg : bpf_dbg.o | 21 | bpf_dbg : bpf_dbg.o |
| 14 | 22 | ||
| 23 | bpf_asm : CFLAGS = -Wall -O2 -I. | ||
| 24 | bpf_asm : LDLIBS = | ||
| 25 | bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o | ||
| 26 | bpf_exp.lex.o : bpf_exp.yacc.c | ||
| 27 | |||
| 15 | clean : | 28 | clean : |
| 16 | rm -rf *.o bpf_jit_disasm bpf_dbg | 29 | rm -rf *.o bpf_jit_disasm bpf_dbg bpf_asm bpf_exp.yacc.* bpf_exp.lex.* |
| 17 | 30 | ||
| 18 | install : | 31 | install : |
| 19 | install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm | 32 | install bpf_jit_disasm $(prefix)/bin/bpf_jit_disasm |
| 20 | install bpf_dbg $(prefix)/bin/bpf_dbg | 33 | install bpf_dbg $(prefix)/bin/bpf_dbg |
| 34 | install bpf_asm $(prefix)/bin/bpf_asm | ||
diff --git a/tools/net/bpf_asm.c b/tools/net/bpf_asm.c new file mode 100644 index 000000000000..c15aef097b04 --- /dev/null +++ b/tools/net/bpf_asm.c | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* | ||
| 2 | * Minimal BPF assembler | ||
| 3 | * | ||
| 4 | * Instead of libpcap high-level filter expressions, it can be quite | ||
| 5 | * useful to define filters in low-level BPF assembler (that is kept | ||
| 6 | * close to Steven McCanne and Van Jacobson's original BPF paper). | ||
| 7 | * In particular for BPF JIT implementors, JIT security auditors, or | ||
| 8 | * just for defining BPF expressions that contain extensions which are | ||
| 9 | * not supported by compilers. | ||
| 10 | * | ||
| 11 | * How to get into it: | ||
| 12 | * | ||
| 13 | * 1) read Documentation/networking/filter.txt | ||
| 14 | * 2) Run `bpf_asm [-c] <filter-prog file>` to translate into binary | ||
| 15 | * blob that is loadable with xt_bpf, cls_bpf et al. Note: -c will | ||
| 16 | * pretty print a C-like construct. | ||
| 17 | * | ||
| 18 | * Copyright 2013 Daniel Borkmann <borkmann@redhat.com> | ||
| 19 | * Licensed under the GNU General Public License, version 2.0 (GPLv2) | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <stdbool.h> | ||
| 23 | #include <stdio.h> | ||
| 24 | #include <string.h> | ||
| 25 | |||
| 26 | extern void bpf_asm_compile(FILE *fp, bool cstyle); | ||
| 27 | |||
| 28 | int main(int argc, char **argv) | ||
| 29 | { | ||
| 30 | FILE *fp = stdin; | ||
| 31 | bool cstyle = false; | ||
| 32 | int i; | ||
| 33 | |||
| 34 | for (i = 1; i < argc; i++) { | ||
| 35 | if (!strncmp("-c", argv[i], 2)) { | ||
| 36 | cstyle = true; | ||
| 37 | continue; | ||
| 38 | } | ||
| 39 | |||
| 40 | fp = fopen(argv[i], "r"); | ||
| 41 | if (!fp) { | ||
| 42 | fp = stdin; | ||
| 43 | continue; | ||
| 44 | } | ||
| 45 | |||
| 46 | break; | ||
| 47 | } | ||
| 48 | |||
| 49 | bpf_asm_compile(fp, cstyle); | ||
| 50 | |||
| 51 | return 0; | ||
| 52 | } | ||
diff --git a/tools/net/bpf_exp.l b/tools/net/bpf_exp.l new file mode 100644 index 000000000000..bf7be77ddd62 --- /dev/null +++ b/tools/net/bpf_exp.l | |||
| @@ -0,0 +1,143 @@ | |||
| 1 | /* | ||
| 2 | * BPF asm code lexer | ||
| 3 | * | ||
| 4 | * This program is free software; you can distribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published | ||
| 6 | * by the Free Software Foundation; either version 2 of the License, | ||
| 7 | * or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Syntax kept close to: | ||
| 10 | * | ||
| 11 | * Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new | ||
| 12 | * architecture for user-level packet capture. In Proceedings of the | ||
| 13 | * USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993 | ||
| 14 | * Conference Proceedings (USENIX'93). USENIX Association, Berkeley, | ||
| 15 | * CA, USA, 2-2. | ||
| 16 | * | ||
| 17 | * Copyright 2013 Daniel Borkmann <borkmann@redhat.com> | ||
| 18 | * Licensed under the GNU General Public License, version 2.0 (GPLv2) | ||
| 19 | */ | ||
| 20 | |||
| 21 | %{ | ||
| 22 | |||
| 23 | #include <stdio.h> | ||
| 24 | #include <stdint.h> | ||
| 25 | #include <stdlib.h> | ||
| 26 | |||
| 27 | #include "bpf_exp.yacc.h" | ||
| 28 | |||
| 29 | extern void yyerror(const char *str); | ||
| 30 | |||
| 31 | %} | ||
| 32 | |||
| 33 | %option align | ||
| 34 | %option ecs | ||
| 35 | |||
| 36 | %option nounput | ||
| 37 | %option noreject | ||
| 38 | %option noinput | ||
| 39 | %option noyywrap | ||
| 40 | |||
| 41 | %option 8bit | ||
| 42 | %option caseless | ||
| 43 | %option yylineno | ||
| 44 | |||
| 45 | %% | ||
| 46 | |||
| 47 | "ldb" { return OP_LDB; } | ||
| 48 | "ldh" { return OP_LDH; } | ||
| 49 | "ld" { return OP_LD; } | ||
| 50 | "ldi" { return OP_LDI; } | ||
| 51 | "ldx" { return OP_LDX; } | ||
| 52 | "ldxi" { return OP_LDXI; } | ||
| 53 | "ldxb" { return OP_LDXB; } | ||
| 54 | "st" { return OP_ST; } | ||
| 55 | "stx" { return OP_STX; } | ||
| 56 | "jmp" { return OP_JMP; } | ||
| 57 | "ja" { return OP_JMP; } | ||
| 58 | "jeq" { return OP_JEQ; } | ||
| 59 | "jneq" { return OP_JNEQ; } | ||
| 60 | "jne" { return OP_JNEQ; } | ||
| 61 | "jlt" { return OP_JLT; } | ||
| 62 | "jle" { return OP_JLE; } | ||
| 63 | "jgt" { return OP_JGT; } | ||
| 64 | "jge" { return OP_JGE; } | ||
| 65 | "jset" { return OP_JSET; } | ||
| 66 | "add" { return OP_ADD; } | ||
| 67 | "sub" { return OP_SUB; } | ||
| 68 | "mul" { return OP_MUL; } | ||
| 69 | "div" { return OP_DIV; } | ||
| 70 | "mod" { return OP_MOD; } | ||
| 71 | "neg" { return OP_NEG; } | ||
| 72 | "and" { return OP_AND; } | ||
| 73 | "xor" { return OP_XOR; } | ||
| 74 | "or" { return OP_OR; } | ||
| 75 | "lsh" { return OP_LSH; } | ||
| 76 | "rsh" { return OP_RSH; } | ||
| 77 | "ret" { return OP_RET; } | ||
| 78 | "tax" { return OP_TAX; } | ||
| 79 | "txa" { return OP_TXA; } | ||
| 80 | |||
| 81 | "#"?("len") { return K_PKT_LEN; } | ||
| 82 | "#"?("proto") { return K_PROTO; } | ||
| 83 | "#"?("type") { return K_TYPE; } | ||
| 84 | "#"?("poff") { return K_POFF; } | ||
| 85 | "#"?("ifidx") { return K_IFIDX; } | ||
| 86 | "#"?("nla") { return K_NLATTR; } | ||
| 87 | "#"?("nlan") { return K_NLATTR_NEST; } | ||
| 88 | "#"?("mark") { return K_MARK; } | ||
| 89 | "#"?("queue") { return K_QUEUE; } | ||
| 90 | "#"?("hatype") { return K_HATYPE; } | ||
| 91 | "#"?("rxhash") { return K_RXHASH; } | ||
| 92 | "#"?("cpu") { return K_CPU; } | ||
| 93 | "#"?("vlan_tci") { return K_VLANT; } | ||
| 94 | "#"?("vlan_pr") { return K_VLANP; } | ||
| 95 | |||
| 96 | ":" { return ':'; } | ||
| 97 | "," { return ','; } | ||
| 98 | "#" { return '#'; } | ||
| 99 | "%" { return '%'; } | ||
| 100 | "[" { return '['; } | ||
| 101 | "]" { return ']'; } | ||
| 102 | "(" { return '('; } | ||
| 103 | ")" { return ')'; } | ||
| 104 | "x" { return 'x'; } | ||
| 105 | "a" { return 'a'; } | ||
| 106 | "+" { return '+'; } | ||
| 107 | "M" { return 'M'; } | ||
| 108 | "*" { return '*'; } | ||
| 109 | "&" { return '&'; } | ||
| 110 | |||
| 111 | ([0][x][a-fA-F0-9]+) { | ||
| 112 | yylval.number = strtoul(yytext, NULL, 16); | ||
| 113 | return number; | ||
| 114 | } | ||
| 115 | ([0][b][0-1]+) { | ||
| 116 | yylval.number = strtol(yytext + 2, NULL, 2); | ||
| 117 | return number; | ||
| 118 | } | ||
| 119 | (([0])|([-+]?[1-9][0-9]*)) { | ||
| 120 | yylval.number = strtol(yytext, NULL, 10); | ||
| 121 | return number; | ||
| 122 | } | ||
| 123 | ([0][0-9]+) { | ||
| 124 | yylval.number = strtol(yytext + 1, NULL, 8); | ||
| 125 | return number; | ||
| 126 | } | ||
| 127 | [a-zA-Z_][a-zA-Z0-9_]+ { | ||
| 128 | yylval.label = strdup(yytext); | ||
| 129 | return label; | ||
| 130 | } | ||
| 131 | |||
| 132 | "/*"([^\*]|\*[^/])*"*/" { /* NOP */ } | ||
| 133 | ";"[^\n]* { /* NOP */ } | ||
| 134 | ^#.* { /* NOP */ } | ||
| 135 | [ \t]+ { /* NOP */ } | ||
| 136 | [ \n]+ { /* NOP */ } | ||
| 137 | |||
| 138 | . { | ||
| 139 | printf("unknown character \'%s\'", yytext); | ||
| 140 | yyerror("lex unknown character"); | ||
| 141 | } | ||
| 142 | |||
| 143 | %% | ||
diff --git a/tools/net/bpf_exp.y b/tools/net/bpf_exp.y new file mode 100644 index 000000000000..f524110643bb --- /dev/null +++ b/tools/net/bpf_exp.y | |||
| @@ -0,0 +1,749 @@ | |||
| 1 | /* | ||
| 2 | * BPF asm code parser | ||
| 3 | * | ||
| 4 | * This program is free software; you can distribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published | ||
| 6 | * by the Free Software Foundation; either version 2 of the License, | ||
| 7 | * or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Syntax kept close to: | ||
| 10 | * | ||
| 11 | * Steven McCanne and Van Jacobson. 1993. The BSD packet filter: a new | ||
| 12 | * architecture for user-level packet capture. In Proceedings of the | ||
| 13 | * USENIX Winter 1993 Conference Proceedings on USENIX Winter 1993 | ||
| 14 | * Conference Proceedings (USENIX'93). USENIX Association, Berkeley, | ||
| 15 | * CA, USA, 2-2. | ||
| 16 | * | ||
| 17 | * Copyright 2013 Daniel Borkmann <borkmann@redhat.com> | ||
| 18 | * Licensed under the GNU General Public License, version 2.0 (GPLv2) | ||
| 19 | */ | ||
| 20 | |||
| 21 | %{ | ||
| 22 | |||
| 23 | #include <stdio.h> | ||
| 24 | #include <string.h> | ||
| 25 | #include <stdint.h> | ||
| 26 | #include <stdlib.h> | ||
| 27 | #include <stdbool.h> | ||
| 28 | #include <unistd.h> | ||
| 29 | #include <errno.h> | ||
| 30 | #include <assert.h> | ||
| 31 | #include <linux/filter.h> | ||
| 32 | |||
| 33 | #include "bpf_exp.yacc.h" | ||
| 34 | |||
| 35 | enum jmp_type { JTL, JFL, JKL }; | ||
| 36 | |||
| 37 | extern FILE *yyin; | ||
| 38 | extern int yylex(void); | ||
| 39 | extern void yyerror(const char *str); | ||
| 40 | |||
| 41 | extern void bpf_asm_compile(FILE *fp, bool cstyle); | ||
| 42 | static void bpf_set_curr_instr(uint16_t op, uint8_t jt, uint8_t jf, uint32_t k); | ||
| 43 | static void bpf_set_curr_label(const char *label); | ||
| 44 | static void bpf_set_jmp_label(const char *label, enum jmp_type type); | ||
| 45 | |||
| 46 | %} | ||
| 47 | |||
| 48 | %union { | ||
| 49 | char *label; | ||
| 50 | uint32_t number; | ||
| 51 | } | ||
| 52 | |||
| 53 | %token OP_LDB OP_LDH OP_LD OP_LDX OP_ST OP_STX OP_JMP OP_JEQ OP_JGT OP_JGE | ||
| 54 | %token OP_JSET OP_ADD OP_SUB OP_MUL OP_DIV OP_AND OP_OR OP_XOR OP_LSH OP_RSH | ||
| 55 | %token OP_RET OP_TAX OP_TXA OP_LDXB OP_MOD OP_NEG OP_JNEQ OP_JLT OP_JLE OP_LDI | ||
| 56 | %token OP_LDXI | ||
| 57 | |||
| 58 | %token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE | ||
| 59 | %token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF | ||
| 60 | |||
| 61 | %token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' | ||
| 62 | |||
| 63 | %token number label | ||
| 64 | |||
| 65 | %type <label> label | ||
| 66 | %type <number> number | ||
| 67 | |||
| 68 | %% | ||
| 69 | |||
| 70 | prog | ||
| 71 | : line | ||
| 72 | | prog line | ||
| 73 | ; | ||
| 74 | |||
| 75 | line | ||
| 76 | : instr | ||
| 77 | | labelled_instr | ||
| 78 | ; | ||
| 79 | |||
| 80 | labelled_instr | ||
| 81 | : labelled instr | ||
| 82 | ; | ||
| 83 | |||
| 84 | instr | ||
| 85 | : ldb | ||
| 86 | | ldh | ||
| 87 | | ld | ||
| 88 | | ldi | ||
| 89 | | ldx | ||
| 90 | | ldxi | ||
| 91 | | st | ||
| 92 | | stx | ||
| 93 | | jmp | ||
| 94 | | jeq | ||
| 95 | | jneq | ||
| 96 | | jlt | ||
| 97 | | jle | ||
| 98 | | jgt | ||
| 99 | | jge | ||
| 100 | | jset | ||
| 101 | | add | ||
| 102 | | sub | ||
| 103 | | mul | ||
| 104 | | div | ||
| 105 | | mod | ||
| 106 | | neg | ||
| 107 | | and | ||
| 108 | | or | ||
| 109 | | xor | ||
| 110 | | lsh | ||
| 111 | | rsh | ||
| 112 | | ret | ||
| 113 | | tax | ||
| 114 | | txa | ||
| 115 | ; | ||
| 116 | |||
| 117 | labelled | ||
| 118 | : label ':' { bpf_set_curr_label($1); } | ||
| 119 | ; | ||
| 120 | |||
| 121 | ldb | ||
| 122 | : OP_LDB '[' 'x' '+' number ']' { | ||
| 123 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $5); } | ||
| 124 | | OP_LDB '[' '%' 'x' '+' number ']' { | ||
| 125 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_IND, 0, 0, $6); } | ||
| 126 | | OP_LDB '[' number ']' { | ||
| 127 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, $3); } | ||
| 128 | | OP_LDB K_PROTO { | ||
| 129 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 130 | SKF_AD_OFF + SKF_AD_PROTOCOL); } | ||
| 131 | | OP_LDB K_TYPE { | ||
| 132 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 133 | SKF_AD_OFF + SKF_AD_PKTTYPE); } | ||
| 134 | | OP_LDB K_IFIDX { | ||
| 135 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 136 | SKF_AD_OFF + SKF_AD_IFINDEX); } | ||
| 137 | | OP_LDB K_NLATTR { | ||
| 138 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 139 | SKF_AD_OFF + SKF_AD_NLATTR); } | ||
| 140 | | OP_LDB K_NLATTR_NEST { | ||
| 141 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 142 | SKF_AD_OFF + SKF_AD_NLATTR_NEST); } | ||
| 143 | | OP_LDB K_MARK { | ||
| 144 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 145 | SKF_AD_OFF + SKF_AD_MARK); } | ||
| 146 | | OP_LDB K_QUEUE { | ||
| 147 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 148 | SKF_AD_OFF + SKF_AD_QUEUE); } | ||
| 149 | | OP_LDB K_HATYPE { | ||
| 150 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 151 | SKF_AD_OFF + SKF_AD_HATYPE); } | ||
| 152 | | OP_LDB K_RXHASH { | ||
| 153 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 154 | SKF_AD_OFF + SKF_AD_RXHASH); } | ||
| 155 | | OP_LDB K_CPU { | ||
| 156 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 157 | SKF_AD_OFF + SKF_AD_CPU); } | ||
| 158 | | OP_LDB K_VLANT { | ||
| 159 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 160 | SKF_AD_OFF + SKF_AD_VLAN_TAG); } | ||
| 161 | | OP_LDB K_VLANP { | ||
| 162 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 163 | SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); } | ||
| 164 | | OP_LDB K_POFF { | ||
| 165 | bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, | ||
| 166 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } | ||
| 167 | ; | ||
| 168 | |||
| 169 | ldh | ||
| 170 | : OP_LDH '[' 'x' '+' number ']' { | ||
| 171 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $5); } | ||
| 172 | | OP_LDH '[' '%' 'x' '+' number ']' { | ||
| 173 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_IND, 0, 0, $6); } | ||
| 174 | | OP_LDH '[' number ']' { | ||
| 175 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, $3); } | ||
| 176 | | OP_LDH K_PROTO { | ||
| 177 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 178 | SKF_AD_OFF + SKF_AD_PROTOCOL); } | ||
| 179 | | OP_LDH K_TYPE { | ||
| 180 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 181 | SKF_AD_OFF + SKF_AD_PKTTYPE); } | ||
| 182 | | OP_LDH K_IFIDX { | ||
| 183 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 184 | SKF_AD_OFF + SKF_AD_IFINDEX); } | ||
| 185 | | OP_LDH K_NLATTR { | ||
| 186 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 187 | SKF_AD_OFF + SKF_AD_NLATTR); } | ||
| 188 | | OP_LDH K_NLATTR_NEST { | ||
| 189 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 190 | SKF_AD_OFF + SKF_AD_NLATTR_NEST); } | ||
| 191 | | OP_LDH K_MARK { | ||
| 192 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 193 | SKF_AD_OFF + SKF_AD_MARK); } | ||
| 194 | | OP_LDH K_QUEUE { | ||
| 195 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 196 | SKF_AD_OFF + SKF_AD_QUEUE); } | ||
| 197 | | OP_LDH K_HATYPE { | ||
| 198 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 199 | SKF_AD_OFF + SKF_AD_HATYPE); } | ||
| 200 | | OP_LDH K_RXHASH { | ||
| 201 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 202 | SKF_AD_OFF + SKF_AD_RXHASH); } | ||
| 203 | | OP_LDH K_CPU { | ||
| 204 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 205 | SKF_AD_OFF + SKF_AD_CPU); } | ||
| 206 | | OP_LDH K_VLANT { | ||
| 207 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 208 | SKF_AD_OFF + SKF_AD_VLAN_TAG); } | ||
| 209 | | OP_LDH K_VLANP { | ||
| 210 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 211 | SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); } | ||
| 212 | | OP_LDH K_POFF { | ||
| 213 | bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, | ||
| 214 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } | ||
| 215 | ; | ||
| 216 | |||
| 217 | ldi | ||
| 218 | : OP_LDI '#' number { | ||
| 219 | bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); } | ||
| 220 | | OP_LDI number { | ||
| 221 | bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $2); } | ||
| 222 | ; | ||
| 223 | |||
| 224 | ld | ||
| 225 | : OP_LD '#' number { | ||
| 226 | bpf_set_curr_instr(BPF_LD | BPF_IMM, 0, 0, $3); } | ||
| 227 | | OP_LD K_PKT_LEN { | ||
| 228 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_LEN, 0, 0, 0); } | ||
| 229 | | OP_LD K_PROTO { | ||
| 230 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 231 | SKF_AD_OFF + SKF_AD_PROTOCOL); } | ||
| 232 | | OP_LD K_TYPE { | ||
| 233 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 234 | SKF_AD_OFF + SKF_AD_PKTTYPE); } | ||
| 235 | | OP_LD K_IFIDX { | ||
| 236 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 237 | SKF_AD_OFF + SKF_AD_IFINDEX); } | ||
| 238 | | OP_LD K_NLATTR { | ||
| 239 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 240 | SKF_AD_OFF + SKF_AD_NLATTR); } | ||
| 241 | | OP_LD K_NLATTR_NEST { | ||
| 242 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 243 | SKF_AD_OFF + SKF_AD_NLATTR_NEST); } | ||
| 244 | | OP_LD K_MARK { | ||
| 245 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 246 | SKF_AD_OFF + SKF_AD_MARK); } | ||
| 247 | | OP_LD K_QUEUE { | ||
| 248 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 249 | SKF_AD_OFF + SKF_AD_QUEUE); } | ||
| 250 | | OP_LD K_HATYPE { | ||
| 251 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 252 | SKF_AD_OFF + SKF_AD_HATYPE); } | ||
| 253 | | OP_LD K_RXHASH { | ||
| 254 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 255 | SKF_AD_OFF + SKF_AD_RXHASH); } | ||
| 256 | | OP_LD K_CPU { | ||
| 257 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 258 | SKF_AD_OFF + SKF_AD_CPU); } | ||
| 259 | | OP_LD K_VLANT { | ||
| 260 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 261 | SKF_AD_OFF + SKF_AD_VLAN_TAG); } | ||
| 262 | | OP_LD K_VLANP { | ||
| 263 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 264 | SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); } | ||
| 265 | | OP_LD K_POFF { | ||
| 266 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, | ||
| 267 | SKF_AD_OFF + SKF_AD_PAY_OFFSET); } | ||
| 268 | | OP_LD 'M' '[' number ']' { | ||
| 269 | bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } | ||
| 270 | | OP_LD '[' 'x' '+' number ']' { | ||
| 271 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $5); } | ||
| 272 | | OP_LD '[' '%' 'x' '+' number ']' { | ||
| 273 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_IND, 0, 0, $6); } | ||
| 274 | | OP_LD '[' number ']' { | ||
| 275 | bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, $3); } | ||
| 276 | ; | ||
| 277 | |||
| 278 | ldxi | ||
| 279 | : OP_LDXI '#' number { | ||
| 280 | bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); } | ||
| 281 | | OP_LDXI number { | ||
| 282 | bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $2); } | ||
| 283 | ; | ||
| 284 | |||
| 285 | ldx | ||
| 286 | : OP_LDX '#' number { | ||
| 287 | bpf_set_curr_instr(BPF_LDX | BPF_IMM, 0, 0, $3); } | ||
| 288 | | OP_LDX K_PKT_LEN { | ||
| 289 | bpf_set_curr_instr(BPF_LDX | BPF_W | BPF_LEN, 0, 0, 0); } | ||
| 290 | | OP_LDX 'M' '[' number ']' { | ||
| 291 | bpf_set_curr_instr(BPF_LDX | BPF_MEM, 0, 0, $4); } | ||
| 292 | | OP_LDXB number '*' '(' '[' number ']' '&' number ')' { | ||
| 293 | if ($2 != 4 || $9 != 0xf) { | ||
| 294 | fprintf(stderr, "ldxb offset not supported!\n"); | ||
| 295 | exit(0); | ||
| 296 | } else { | ||
| 297 | bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } } | ||
| 298 | | OP_LDX number '*' '(' '[' number ']' '&' number ')' { | ||
| 299 | if ($2 != 4 || $9 != 0xf) { | ||
| 300 | fprintf(stderr, "ldxb offset not supported!\n"); | ||
| 301 | exit(0); | ||
| 302 | } else { | ||
| 303 | bpf_set_curr_instr(BPF_LDX | BPF_MSH | BPF_B, 0, 0, $6); } } | ||
| 304 | ; | ||
| 305 | |||
| 306 | st | ||
| 307 | : OP_ST 'M' '[' number ']' { | ||
| 308 | bpf_set_curr_instr(BPF_ST, 0, 0, $4); } | ||
| 309 | ; | ||
| 310 | |||
| 311 | stx | ||
| 312 | : OP_STX 'M' '[' number ']' { | ||
| 313 | bpf_set_curr_instr(BPF_STX, 0, 0, $4); } | ||
| 314 | ; | ||
| 315 | |||
| 316 | jmp | ||
| 317 | : OP_JMP label { | ||
| 318 | bpf_set_jmp_label($2, JKL); | ||
| 319 | bpf_set_curr_instr(BPF_JMP | BPF_JA, 0, 0, 0); } | ||
| 320 | ; | ||
| 321 | |||
| 322 | jeq | ||
| 323 | : OP_JEQ '#' number ',' label ',' label { | ||
| 324 | bpf_set_jmp_label($5, JTL); | ||
| 325 | bpf_set_jmp_label($7, JFL); | ||
| 326 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); } | ||
| 327 | | OP_JEQ 'x' ',' label ',' label { | ||
| 328 | bpf_set_jmp_label($4, JTL); | ||
| 329 | bpf_set_jmp_label($6, JFL); | ||
| 330 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); } | ||
| 331 | | OP_JEQ '%' 'x' ',' label ',' label { | ||
| 332 | bpf_set_jmp_label($5, JTL); | ||
| 333 | bpf_set_jmp_label($7, JFL); | ||
| 334 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); } | ||
| 335 | | OP_JEQ '#' number ',' label { | ||
| 336 | bpf_set_jmp_label($5, JTL); | ||
| 337 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); } | ||
| 338 | | OP_JEQ 'x' ',' label { | ||
| 339 | bpf_set_jmp_label($4, JTL); | ||
| 340 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); } | ||
| 341 | | OP_JEQ '%' 'x' ',' label { | ||
| 342 | bpf_set_jmp_label($5, JTL); | ||
| 343 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); } | ||
| 344 | ; | ||
| 345 | |||
| 346 | jneq | ||
| 347 | : OP_JNEQ '#' number ',' label { | ||
| 348 | bpf_set_jmp_label($5, JFL); | ||
| 349 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, $3); } | ||
| 350 | | OP_JNEQ 'x' ',' label { | ||
| 351 | bpf_set_jmp_label($4, JFL); | ||
| 352 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); } | ||
| 353 | | OP_JNEQ '%' 'x' ',' label { | ||
| 354 | bpf_set_jmp_label($5, JFL); | ||
| 355 | bpf_set_curr_instr(BPF_JMP | BPF_JEQ | BPF_X, 0, 0, 0); } | ||
| 356 | ; | ||
| 357 | |||
| 358 | jlt | ||
| 359 | : OP_JLT '#' number ',' label { | ||
| 360 | bpf_set_jmp_label($5, JFL); | ||
| 361 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); } | ||
| 362 | | OP_JLT 'x' ',' label { | ||
| 363 | bpf_set_jmp_label($4, JFL); | ||
| 364 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); } | ||
| 365 | | OP_JLT '%' 'x' ',' label { | ||
| 366 | bpf_set_jmp_label($5, JFL); | ||
| 367 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); } | ||
| 368 | ; | ||
| 369 | |||
| 370 | jle | ||
| 371 | : OP_JLE '#' number ',' label { | ||
| 372 | bpf_set_jmp_label($5, JFL); | ||
| 373 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); } | ||
| 374 | | OP_JLE 'x' ',' label { | ||
| 375 | bpf_set_jmp_label($4, JFL); | ||
| 376 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); } | ||
| 377 | | OP_JLE '%' 'x' ',' label { | ||
| 378 | bpf_set_jmp_label($5, JFL); | ||
| 379 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); } | ||
| 380 | ; | ||
| 381 | |||
| 382 | jgt | ||
| 383 | : OP_JGT '#' number ',' label ',' label { | ||
| 384 | bpf_set_jmp_label($5, JTL); | ||
| 385 | bpf_set_jmp_label($7, JFL); | ||
| 386 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); } | ||
| 387 | | OP_JGT 'x' ',' label ',' label { | ||
| 388 | bpf_set_jmp_label($4, JTL); | ||
| 389 | bpf_set_jmp_label($6, JFL); | ||
| 390 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); } | ||
| 391 | | OP_JGT '%' 'x' ',' label ',' label { | ||
| 392 | bpf_set_jmp_label($5, JTL); | ||
| 393 | bpf_set_jmp_label($7, JFL); | ||
| 394 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); } | ||
| 395 | | OP_JGT '#' number ',' label { | ||
| 396 | bpf_set_jmp_label($5, JTL); | ||
| 397 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_K, 0, 0, $3); } | ||
| 398 | | OP_JGT 'x' ',' label { | ||
| 399 | bpf_set_jmp_label($4, JTL); | ||
| 400 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); } | ||
| 401 | | OP_JGT '%' 'x' ',' label { | ||
| 402 | bpf_set_jmp_label($5, JTL); | ||
| 403 | bpf_set_curr_instr(BPF_JMP | BPF_JGT | BPF_X, 0, 0, 0); } | ||
| 404 | ; | ||
| 405 | |||
| 406 | jge | ||
| 407 | : OP_JGE '#' number ',' label ',' label { | ||
| 408 | bpf_set_jmp_label($5, JTL); | ||
| 409 | bpf_set_jmp_label($7, JFL); | ||
| 410 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); } | ||
| 411 | | OP_JGE 'x' ',' label ',' label { | ||
| 412 | bpf_set_jmp_label($4, JTL); | ||
| 413 | bpf_set_jmp_label($6, JFL); | ||
| 414 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); } | ||
| 415 | | OP_JGE '%' 'x' ',' label ',' label { | ||
| 416 | bpf_set_jmp_label($5, JTL); | ||
| 417 | bpf_set_jmp_label($7, JFL); | ||
| 418 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); } | ||
| 419 | | OP_JGE '#' number ',' label { | ||
| 420 | bpf_set_jmp_label($5, JTL); | ||
| 421 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_K, 0, 0, $3); } | ||
| 422 | | OP_JGE 'x' ',' label { | ||
| 423 | bpf_set_jmp_label($4, JTL); | ||
| 424 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); } | ||
| 425 | | OP_JGE '%' 'x' ',' label { | ||
| 426 | bpf_set_jmp_label($5, JTL); | ||
| 427 | bpf_set_curr_instr(BPF_JMP | BPF_JGE | BPF_X, 0, 0, 0); } | ||
| 428 | ; | ||
| 429 | |||
| 430 | jset | ||
| 431 | : OP_JSET '#' number ',' label ',' label { | ||
| 432 | bpf_set_jmp_label($5, JTL); | ||
| 433 | bpf_set_jmp_label($7, JFL); | ||
| 434 | bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); } | ||
| 435 | | OP_JSET 'x' ',' label ',' label { | ||
| 436 | bpf_set_jmp_label($4, JTL); | ||
| 437 | bpf_set_jmp_label($6, JFL); | ||
| 438 | bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); } | ||
| 439 | | OP_JSET '%' 'x' ',' label ',' label { | ||
| 440 | bpf_set_jmp_label($5, JTL); | ||
| 441 | bpf_set_jmp_label($7, JFL); | ||
| 442 | bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); } | ||
| 443 | | OP_JSET '#' number ',' label { | ||
| 444 | bpf_set_jmp_label($5, JTL); | ||
| 445 | bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_K, 0, 0, $3); } | ||
| 446 | | OP_JSET 'x' ',' label { | ||
| 447 | bpf_set_jmp_label($4, JTL); | ||
| 448 | bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); } | ||
| 449 | | OP_JSET '%' 'x' ',' label { | ||
| 450 | bpf_set_jmp_label($5, JTL); | ||
| 451 | bpf_set_curr_instr(BPF_JMP | BPF_JSET | BPF_X, 0, 0, 0); } | ||
| 452 | ; | ||
| 453 | |||
| 454 | add | ||
| 455 | : OP_ADD '#' number { | ||
| 456 | bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_K, 0, 0, $3); } | ||
| 457 | | OP_ADD 'x' { | ||
| 458 | bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); } | ||
| 459 | | OP_ADD '%' 'x' { | ||
| 460 | bpf_set_curr_instr(BPF_ALU | BPF_ADD | BPF_X, 0, 0, 0); } | ||
| 461 | ; | ||
| 462 | |||
| 463 | sub | ||
| 464 | : OP_SUB '#' number { | ||
| 465 | bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_K, 0, 0, $3); } | ||
| 466 | | OP_SUB 'x' { | ||
| 467 | bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); } | ||
| 468 | | OP_SUB '%' 'x' { | ||
| 469 | bpf_set_curr_instr(BPF_ALU | BPF_SUB | BPF_X, 0, 0, 0); } | ||
| 470 | ; | ||
| 471 | |||
| 472 | mul | ||
| 473 | : OP_MUL '#' number { | ||
| 474 | bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_K, 0, 0, $3); } | ||
| 475 | | OP_MUL 'x' { | ||
| 476 | bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); } | ||
| 477 | | OP_MUL '%' 'x' { | ||
| 478 | bpf_set_curr_instr(BPF_ALU | BPF_MUL | BPF_X, 0, 0, 0); } | ||
| 479 | ; | ||
| 480 | |||
| 481 | div | ||
| 482 | : OP_DIV '#' number { | ||
| 483 | bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_K, 0, 0, $3); } | ||
| 484 | | OP_DIV 'x' { | ||
| 485 | bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); } | ||
| 486 | | OP_DIV '%' 'x' { | ||
| 487 | bpf_set_curr_instr(BPF_ALU | BPF_DIV | BPF_X, 0, 0, 0); } | ||
| 488 | ; | ||
| 489 | |||
| 490 | mod | ||
| 491 | : OP_MOD '#' number { | ||
| 492 | bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_K, 0, 0, $3); } | ||
| 493 | | OP_MOD 'x' { | ||
| 494 | bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); } | ||
| 495 | | OP_MOD '%' 'x' { | ||
| 496 | bpf_set_curr_instr(BPF_ALU | BPF_MOD | BPF_X, 0, 0, 0); } | ||
| 497 | ; | ||
| 498 | |||
| 499 | neg | ||
| 500 | : OP_NEG { | ||
| 501 | bpf_set_curr_instr(BPF_ALU | BPF_NEG, 0, 0, 0); } | ||
| 502 | ; | ||
| 503 | |||
| 504 | and | ||
| 505 | : OP_AND '#' number { | ||
| 506 | bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_K, 0, 0, $3); } | ||
| 507 | | OP_AND 'x' { | ||
| 508 | bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); } | ||
| 509 | | OP_AND '%' 'x' { | ||
| 510 | bpf_set_curr_instr(BPF_ALU | BPF_AND | BPF_X, 0, 0, 0); } | ||
| 511 | ; | ||
| 512 | |||
| 513 | or | ||
| 514 | : OP_OR '#' number { | ||
| 515 | bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_K, 0, 0, $3); } | ||
| 516 | | OP_OR 'x' { | ||
| 517 | bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); } | ||
| 518 | | OP_OR '%' 'x' { | ||
| 519 | bpf_set_curr_instr(BPF_ALU | BPF_OR | BPF_X, 0, 0, 0); } | ||
| 520 | ; | ||
| 521 | |||
| 522 | xor | ||
| 523 | : OP_XOR '#' number { | ||
| 524 | bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_K, 0, 0, $3); } | ||
| 525 | | OP_XOR 'x' { | ||
| 526 | bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); } | ||
| 527 | | OP_XOR '%' 'x' { | ||
| 528 | bpf_set_curr_instr(BPF_ALU | BPF_XOR | BPF_X, 0, 0, 0); } | ||
| 529 | ; | ||
| 530 | |||
| 531 | lsh | ||
| 532 | : OP_LSH '#' number { | ||
| 533 | bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_K, 0, 0, $3); } | ||
| 534 | | OP_LSH 'x' { | ||
| 535 | bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); } | ||
| 536 | | OP_LSH '%' 'x' { | ||
| 537 | bpf_set_curr_instr(BPF_ALU | BPF_LSH | BPF_X, 0, 0, 0); } | ||
| 538 | ; | ||
| 539 | |||
| 540 | rsh | ||
| 541 | : OP_RSH '#' number { | ||
| 542 | bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_K, 0, 0, $3); } | ||
| 543 | | OP_RSH 'x' { | ||
| 544 | bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); } | ||
| 545 | | OP_RSH '%' 'x' { | ||
| 546 | bpf_set_curr_instr(BPF_ALU | BPF_RSH | BPF_X, 0, 0, 0); } | ||
| 547 | ; | ||
| 548 | |||
| 549 | ret | ||
| 550 | : OP_RET 'a' { | ||
| 551 | bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); } | ||
| 552 | | OP_RET '%' 'a' { | ||
| 553 | bpf_set_curr_instr(BPF_RET | BPF_A, 0, 0, 0); } | ||
| 554 | | OP_RET 'x' { | ||
| 555 | bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); } | ||
| 556 | | OP_RET '%' 'x' { | ||
| 557 | bpf_set_curr_instr(BPF_RET | BPF_X, 0, 0, 0); } | ||
| 558 | | OP_RET '#' number { | ||
| 559 | bpf_set_curr_instr(BPF_RET | BPF_K, 0, 0, $3); } | ||
| 560 | ; | ||
| 561 | |||
| 562 | tax | ||
| 563 | : OP_TAX { | ||
| 564 | bpf_set_curr_instr(BPF_MISC | BPF_TAX, 0, 0, 0); } | ||
| 565 | ; | ||
| 566 | |||
| 567 | txa | ||
| 568 | : OP_TXA { | ||
| 569 | bpf_set_curr_instr(BPF_MISC | BPF_TXA, 0, 0, 0); } | ||
| 570 | ; | ||
| 571 | |||
| 572 | %% | ||
| 573 | |||
| 574 | static int curr_instr = 0; | ||
| 575 | static struct sock_filter out[BPF_MAXINSNS]; | ||
| 576 | static const char **labels, **labels_jt, **labels_jf, **labels_k; | ||
| 577 | |||
| 578 | static void bpf_assert_max(void) | ||
| 579 | { | ||
| 580 | if (curr_instr >= BPF_MAXINSNS) { | ||
| 581 | fprintf(stderr, "only max %u insns allowed!\n", BPF_MAXINSNS); | ||
| 582 | exit(0); | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 586 | static void bpf_set_curr_instr(uint16_t code, uint8_t jt, uint8_t jf, | ||
| 587 | uint32_t k) | ||
| 588 | { | ||
| 589 | bpf_assert_max(); | ||
| 590 | out[curr_instr].code = code; | ||
| 591 | out[curr_instr].jt = jt; | ||
| 592 | out[curr_instr].jf = jf; | ||
| 593 | out[curr_instr].k = k; | ||
| 594 | curr_instr++; | ||
| 595 | } | ||
| 596 | |||
| 597 | static void bpf_set_curr_label(const char *label) | ||
| 598 | { | ||
| 599 | bpf_assert_max(); | ||
| 600 | labels[curr_instr] = label; | ||
| 601 | } | ||
| 602 | |||
| 603 | static void bpf_set_jmp_label(const char *label, enum jmp_type type) | ||
| 604 | { | ||
| 605 | bpf_assert_max(); | ||
| 606 | switch (type) { | ||
| 607 | case JTL: | ||
| 608 | labels_jt[curr_instr] = label; | ||
| 609 | break; | ||
| 610 | case JFL: | ||
| 611 | labels_jf[curr_instr] = label; | ||
| 612 | break; | ||
| 613 | case JKL: | ||
| 614 | labels_k[curr_instr] = label; | ||
| 615 | break; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | |||
| 619 | static int bpf_find_insns_offset(const char *label) | ||
| 620 | { | ||
| 621 | int i, max = curr_instr, ret = -ENOENT; | ||
| 622 | |||
| 623 | for (i = 0; i < max; i++) { | ||
| 624 | if (labels[i] && !strcmp(label, labels[i])) { | ||
| 625 | ret = i; | ||
| 626 | break; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | if (ret == -ENOENT) { | ||
| 631 | fprintf(stderr, "no such label \'%s\'!\n", label); | ||
| 632 | exit(0); | ||
| 633 | } | ||
| 634 | |||
| 635 | return ret; | ||
| 636 | } | ||
| 637 | |||
| 638 | static void bpf_stage_1_insert_insns(void) | ||
| 639 | { | ||
| 640 | yyparse(); | ||
| 641 | } | ||
| 642 | |||
| 643 | static void bpf_reduce_k_jumps(void) | ||
| 644 | { | ||
| 645 | int i; | ||
| 646 | |||
| 647 | for (i = 0; i < curr_instr; i++) { | ||
| 648 | if (labels_k[i]) { | ||
| 649 | int off = bpf_find_insns_offset(labels_k[i]); | ||
| 650 | out[i].k = (uint32_t) (off - i - 1); | ||
| 651 | } | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | static void bpf_reduce_jt_jumps(void) | ||
| 656 | { | ||
| 657 | int i; | ||
| 658 | |||
| 659 | for (i = 0; i < curr_instr; i++) { | ||
| 660 | if (labels_jt[i]) { | ||
| 661 | int off = bpf_find_insns_offset(labels_jt[i]); | ||
| 662 | out[i].jt = (uint8_t) (off - i -1); | ||
| 663 | } | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | static void bpf_reduce_jf_jumps(void) | ||
| 668 | { | ||
| 669 | int i; | ||
| 670 | |||
| 671 | for (i = 0; i < curr_instr; i++) { | ||
| 672 | if (labels_jf[i]) { | ||
| 673 | int off = bpf_find_insns_offset(labels_jf[i]); | ||
| 674 | out[i].jf = (uint8_t) (off - i - 1); | ||
| 675 | } | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | static void bpf_stage_2_reduce_labels(void) | ||
| 680 | { | ||
| 681 | bpf_reduce_k_jumps(); | ||
| 682 | bpf_reduce_jt_jumps(); | ||
| 683 | bpf_reduce_jf_jumps(); | ||
| 684 | } | ||
| 685 | |||
| 686 | static void bpf_pretty_print_c(void) | ||
| 687 | { | ||
| 688 | int i; | ||
| 689 | |||
| 690 | for (i = 0; i < curr_instr; i++) | ||
| 691 | printf("{ %#04x, %2u, %2u, %#010x },\n", out[i].code, | ||
| 692 | out[i].jt, out[i].jf, out[i].k); | ||
| 693 | } | ||
| 694 | |||
| 695 | static void bpf_pretty_print(void) | ||
| 696 | { | ||
| 697 | int i; | ||
| 698 | |||
| 699 | printf("%u,", curr_instr); | ||
| 700 | for (i = 0; i < curr_instr; i++) | ||
| 701 | printf("%u %u %u %u,", out[i].code, | ||
| 702 | out[i].jt, out[i].jf, out[i].k); | ||
| 703 | printf("\n"); | ||
| 704 | } | ||
| 705 | |||
| 706 | static void bpf_init(void) | ||
| 707 | { | ||
| 708 | memset(out, 0, sizeof(out)); | ||
| 709 | |||
| 710 | labels = calloc(BPF_MAXINSNS, sizeof(*labels)); | ||
| 711 | assert(labels); | ||
| 712 | labels_jt = calloc(BPF_MAXINSNS, sizeof(*labels_jt)); | ||
| 713 | assert(labels_jt); | ||
| 714 | labels_jf = calloc(BPF_MAXINSNS, sizeof(*labels_jf)); | ||
| 715 | assert(labels_jf); | ||
| 716 | labels_k = calloc(BPF_MAXINSNS, sizeof(*labels_k)); | ||
| 717 | assert(labels_k); | ||
| 718 | } | ||
| 719 | |||
| 720 | static void bpf_destroy(void) | ||
| 721 | { | ||
| 722 | free(labels); | ||
| 723 | free(labels_jt); | ||
| 724 | free(labels_jf); | ||
| 725 | free(labels_k); | ||
| 726 | } | ||
| 727 | |||
| 728 | void bpf_asm_compile(FILE *fp, bool cstyle) | ||
| 729 | { | ||
| 730 | yyin = fp; | ||
| 731 | |||
| 732 | bpf_init(); | ||
| 733 | bpf_stage_1_insert_insns(); | ||
| 734 | bpf_stage_2_reduce_labels(); | ||
| 735 | bpf_destroy(); | ||
| 736 | |||
| 737 | if (cstyle) | ||
| 738 | bpf_pretty_print_c(); | ||
| 739 | else | ||
| 740 | bpf_pretty_print(); | ||
| 741 | |||
| 742 | if (fp != stdin) | ||
| 743 | fclose(yyin); | ||
| 744 | } | ||
| 745 | |||
| 746 | void yyerror(const char *str) | ||
| 747 | { | ||
| 748 | exit(1); | ||
| 749 | } | ||
