diff options
Diffstat (limited to 'wiretap/bpf.c')
-rw-r--r-- | wiretap/bpf.c | 373 |
1 files changed, 0 insertions, 373 deletions
diff --git a/wiretap/bpf.c b/wiretap/bpf.c deleted file mode 100644 index 3f02859d13..0000000000 --- a/wiretap/bpf.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * bpf.c - * ----- - * Creates and handles the BPF code produced by wiretap. - * - * Gilbert Ramirez - */ - -#ifndef __G_LIB_H__ -#include <glib.h> -#endif - -#include <sys/types.h> -#include <netinet/in.h> - -#include "wtap.h" -#include "rt-compile.h" -#include "rt-global.h" -#include "bpf-engine.h" -#include "bpf.h" - - -static GList *bpf_code_just_parsed = NULL; -static struct bpf_instruction *bpf_record = NULL; - -static int -bpf_clean_jump(GList *L, int i_this, int jmp, int num_bpf_instructions, - int i_ret_success, int i_ret_failure); -static void -bpf_pass1(GList *L); - -static GList* -bpf_mk_bytecmp(int ftype, int rel_opcode, guint8 *bytes); - -static void -bpf_optimize(GList *L); - -static int -bpf_attach(wtap *wth); - -static void -bpf_attach_record(gpointer bpf_code, gpointer junk); - -static int -offline_attach(wtap *wth); - - -/* sets function pointers in rt-grammar.y to point to the BPF-related - * functions */ -void -wtap_filter_bpf_init(void) -{ - mk_bytecmp = bpf_mk_bytecmp; - mk_optimize = bpf_optimize; - mk_attach = bpf_attach; -} - -/* almost the same as bpf_init... */ -void -wtap_filter_offline_init(wtap *wth) -{ - int fi; /* filter index */ - - mk_bytecmp = bpf_mk_bytecmp; - mk_optimize = bpf_optimize; - mk_attach = offline_attach; - - wtap_filter_offline_clear(wth); - - /* make the offline filter array */ - wth->filter.offline = g_malloc(sizeof(int*) * WTAP_NUM_ENCAP_TYPES); - wth->filter_type = WTAP_FILTER_OFFLINE; - wth->offline_filter_lengths = g_malloc(sizeof(int) * WTAP_NUM_ENCAP_TYPES); - - for (fi = 0; fi < WTAP_NUM_ENCAP_TYPES; fi++) { - wth->filter.offline[fi] = NULL; - } -} - -/* Removes an offline filter from a wtap struct, and frees memory used - * by that filter */ -void -wtap_filter_offline_clear(wtap *wth) -{ - int fi; /* filter index */ - - if (wth->filter.offline) { - for (fi = 0; fi < WTAP_NUM_ENCAP_TYPES; fi++) { - if (wth->filter.offline[fi]) - g_free(wth->filter.offline[fi]); - } - g_free(wth->filter.offline); - g_free(wth->offline_filter_lengths); - } - wth->filter_type = WTAP_FILTER_NONE; -} - -/* Allocate a new bpf_code_unit structure and initialize the BPF instruction - * codes to the values passed by the caller. */ -static struct bpf_code_unit * -bpf_code_unit_alloc(guint8 label, guint16 code, guint8 jt, guint8 jf, guint32 k) -{ - struct bpf_code_unit *bpf; - - bpf = g_malloc(sizeof(struct bpf_code_unit)); - bpf->line_label = label; - bpf->bpf.code = code; - bpf->bpf.jt = jt; - bpf->bpf.jf = jf; - bpf->bpf.k = k; - - /*g_print("{ %d { 0x%02x, %d, %d, 0x%08x }},\n", - label, code, jt, jf, k);*/ - return bpf; -} - - -/* Finds ftype in the bytecmp_table, the relation, and the n-string -byte array, and creates BPF that will check those bytes */ -static GList* -bpf_mk_bytecmp(int ftype, int rel_opcode, guint8 *bytes) -{ - GList *L; - struct bpf_code_unit *bpf; - int len_to_cmp, offset, endpoint, label; - bytecmp_info *b; - - L = g_list_alloc(); - - /* find the field in the table */ - b = lookup_bytecmp(ftype); - - /* How many bytes do we have to compare, and where? */ - len_to_cmp = b->length; - offset = b->offset; - endpoint = len_to_cmp + offset; - /*g_print("len_to_cmp=%d, offset=%d, endpoint=%d\n", - len_to_cmp, offset, endpoint); - g_print("bytes: (%d) %02X:%02X:%02X\n", - bytes[0], bytes[1], bytes[2], bytes[3]);*/ - - label = NEXT_BLOCK; - /* loop until we have written instructions to compare - all bytes */ - while (len_to_cmp) { - - if (len_to_cmp >= 4) { - bpf = bpf_code_unit_alloc(label, - BPF_LD|BPF_W|BPF_ABS, - 0, 0, endpoint - 4); - g_list_append(L, bpf); - label = NO_LABEL; - - endpoint -= 4; - bpf = bpf_code_unit_alloc(NO_LABEL, - BPF_JMP|BPF_JEQ, - (len_to_cmp == 4 ? END_OF_PROGRAM_SUCCESS : 0), - NEXT_BLOCK, - phtonl(&bytes[len_to_cmp-3])); - g_list_append(L, bpf); - - len_to_cmp -= 4; - } - else if (len_to_cmp == 3) { - bpf = bpf_code_unit_alloc(label, - BPF_LD|BPF_W|BPF_ABS, - 0, 0, endpoint - 3); - g_list_append(L, bpf); - label = NO_LABEL; - endpoint -= 3; - - bpf = bpf_code_unit_alloc(NO_LABEL, - BPF_ALU|BPF_AND, - 0, 0, 0xffffff); - /*htonl(0xffffff));*/ - g_list_append(L, bpf); - - bpf = bpf_code_unit_alloc(NO_LABEL, - BPF_JMP|BPF_JEQ, - (len_to_cmp == 3 ? END_OF_PROGRAM_SUCCESS : 0), - NEXT_BLOCK, - phtonl(&bytes[len_to_cmp-2]) & 0xffffff00); - g_list_append(L, bpf); - - len_to_cmp -= 3; - } - else if (len_to_cmp == 2) { - bpf = bpf_code_unit_alloc(label, - BPF_LD|BPF_H|BPF_ABS, - 0, 0, endpoint - 2); - g_list_append(L, bpf); - label = NO_LABEL; - - endpoint -= 2; - bpf = bpf_code_unit_alloc(NO_LABEL, - BPF_JMP|BPF_JEQ, - (len_to_cmp == 2 ? END_OF_PROGRAM_SUCCESS : 0), - NEXT_BLOCK, - (guint32)phtons(&bytes[len_to_cmp-1])); - g_list_append(L, bpf); - - len_to_cmp -= 2; - } - else if (len_to_cmp == 1) { - bpf = bpf_code_unit_alloc(label, - BPF_LD|BPF_B|BPF_ABS, - 0, 0, endpoint - 1); - g_list_append(L, bpf); - label = NO_LABEL; - - endpoint--; - bpf = bpf_code_unit_alloc(NO_LABEL, - BPF_JMP|BPF_JEQ, - END_OF_PROGRAM_SUCCESS, NEXT_BLOCK, - bytes[len_to_cmp]); - g_list_append(L, bpf); - len_to_cmp--; - } - } - - - L = g_list_remove(L, 0); - return L; -} - - -static void -bpf_optimize(GList *L) -{ - bpf_pass1(L); - bpf_code_just_parsed = L; -} - -/* after the BPF code is constructed from the parser, this step is run. During - * pass1 we: - * - * 1. Clean up the jump variables - */ -static void -bpf_pass1(GList *L) -{ - struct bpf_code_unit *bpf; - int num_bpf_instructions; - int i_ret_success; - int i_ret_failure; - int i; - - /* Attach a SUCCESS return to the end of the BPF code */ - bpf = bpf_code_unit_alloc(END_OF_PROGRAM_SUCCESS, BPF_RET, 0, 0, 0xffff); - g_list_append(L, bpf); - - /* Attach a FAILURE return to the end of the BPF code */ - bpf = bpf_code_unit_alloc(END_OF_PROGRAM_FAILURE, BPF_RET, 0, 0, 0); - g_list_append(L, bpf); - - num_bpf_instructions = g_list_length(L); - i_ret_success = num_bpf_instructions - 2; - i_ret_failure = num_bpf_instructions - 1; - - for(i = 0; i < num_bpf_instructions; i++) { - bpf = (struct bpf_code_unit*) g_list_nth_data(L, i); - if (!bpf) - continue; - - /* Check for Jump to end failure/success */ - if (bpf->bpf.code & BPF_JMP) { - - bpf->bpf.jt = bpf_clean_jump(L, i, bpf->bpf.jt, num_bpf_instructions, - i_ret_success, i_ret_failure); - - bpf->bpf.jf = bpf_clean_jump(L, i, bpf->bpf.jf, num_bpf_instructions, - i_ret_success, i_ret_failure); - } - } -} - -static int -bpf_clean_jump(GList *L, int i_this, int jmp, int num_bpf_instructions, - int i_ret_success, int i_ret_failure) -{ - int i; - struct bpf_code_unit *bpf; - - switch(jmp) { - case END_OF_PROGRAM_SUCCESS: - return i_ret_success - i_this - 1; - - case END_OF_PROGRAM_FAILURE: - return i_ret_failure - i_this - 1; - - case NEXT_BLOCK: - for (i = i_this + 1; i < num_bpf_instructions; i++) { - bpf = (struct bpf_code_unit*) g_list_nth_data(L, i); - if (!bpf) - continue; - if (bpf->line_label == NEXT_BLOCK) { - return i - i_this - 1; - } - } - /* failed to find NEXT_BLOCK.... chose FAILURE */ - return i_ret_failure - i_this - 1; - - /* default: nothing */ - } - return jmp; -} - - - -/* Takes code from bpf_code_just_parsed and attaches it to wth - * returns 1 if sucessfull, 0 if not */ -static int bpf_attach(wtap *wth) -{ - if (wth->filter.bpf) - g_free(wth->filter.bpf); - - /* filter_length will be number of bpf_block records */ - wth->filter_length = g_list_length(bpf_code_just_parsed) - 1; - - wth->filter.bpf = g_malloc(wth->filter_length * - sizeof(struct bpf_instruction)); - wth->filter_type = WTAP_FILTER_BPF; - - bpf_record = wth->filter.bpf; - - g_list_foreach(bpf_code_just_parsed, bpf_attach_record, NULL); - - if (bpf_chk_filter(wth->filter.bpf, wth->filter_length) == 0) - return 1; - else - return 0; - -} - -void bpf_attach_record(gpointer bpf_code, gpointer junk) -{ - struct bpf_code_unit *bpf_c = (struct bpf_code_unit*) bpf_code; - - struct bpf_instruction *bpf_i; - - if (!bpf_c) - return; - - bpf_i = &(bpf_c->bpf); - memcpy(bpf_record, bpf_i, sizeof(struct bpf_instruction)); - bpf_record++; -} - - -/* Takes code from bpf_code_just_parsed and attachs it to wth. - * returns 1 if sucessfull, 0 if not */ -static int offline_attach(wtap *wth) -{ - /* filter_length will be number of bpf_instruction records */ - wth->offline_filter_lengths[comp_encap_type] = - g_list_length(bpf_code_just_parsed); - - /* Make space for this filter */ - wth->filter.offline[comp_encap_type] = - g_malloc(wth->offline_filter_lengths[comp_encap_type] - * sizeof(struct bpf_instruction)); - - bpf_record = wth->filter.offline[comp_encap_type]; - - g_list_foreach(bpf_code_just_parsed, bpf_attach_record, NULL); - - if (bpf_chk_filter(wth->filter.offline[comp_encap_type], - wth->offline_filter_lengths[comp_encap_type]) == 0) - return 1; - else - return 0; -} - |