diff options
-rw-r--r-- | debian/libwiretap0.symbols | 6 | ||||
-rw-r--r-- | ui/summary.c | 11 | ||||
-rw-r--r-- | wiretap/erf.c | 36 | ||||
-rw-r--r-- | wiretap/pcapng.c | 186 | ||||
-rw-r--r-- | wiretap/wtap.c | 34 | ||||
-rw-r--r-- | wiretap/wtap.h | 9 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.c | 220 | ||||
-rw-r--r-- | wiretap/wtap_opttypes.h | 52 |
8 files changed, 336 insertions, 218 deletions
diff --git a/debian/libwiretap0.symbols b/debian/libwiretap0.symbols index 72909048b6..4063fae2c9 100644 --- a/debian/libwiretap0.symbols +++ b/debian/libwiretap0.symbols @@ -21,7 +21,7 @@ libwiretap.so.0 libwiretap0 #MINVER# register_pcapng_option_handler@Base 1.99.2 wtap_add_generated_idb@Base 3.3.0 wtap_addrinfo_list_empty@Base 2.5.0 - wtap_block_add_structured_option@Base 3.5.0 + wtap_block_add_if_filter_option@Base 3.5.0 wtap_block_add_ipv4_option@Base 2.1.2 wtap_block_add_ipv6_option@Base 2.1.2 wtap_block_add_string_option@Base 2.1.2 @@ -33,7 +33,7 @@ libwiretap.so.0 libwiretap0 #MINVER# wtap_block_create@Base 2.1.2 wtap_block_foreach_option@Base 2.1.2 wtap_block_free@Base 2.1.2 - wtap_block_get_structured_option_value@Base 3.5.0 + wtap_block_get_if_filter_option_value@Base 3.5.0 wtap_block_get_ipv4_option_value@Base 2.1.2 wtap_block_get_ipv6_option_value@Base 2.1.2 wtap_block_get_mandatory_data@Base 2.1.2 @@ -44,7 +44,7 @@ libwiretap.so.0 libwiretap0 #MINVER# wtap_block_make_copy@Base 3.3.2 wtap_block_remove_nth_option_instance@Base 2.2.0 wtap_block_remove_option@Base 2.2.0 - wtap_block_set_structured_option_value@Base 3.5.0 + wtap_block_set_if_filter_option_value@Base 3.5.0 wtap_block_set_ipv4_option_value@Base 2.1.2 wtap_block_set_ipv6_option_value@Base 2.1.2 wtap_block_set_nth_string_option_value@Base 2.1.2 diff --git a/ui/summary.c b/ui/summary.c index 565bb86307..268f993694 100644 --- a/ui/summary.c +++ b/ui/summary.c @@ -117,7 +117,7 @@ summary_fill_in(capture_file *cf, summary_tally *st) wtap_block_t if_stats; guint64 isb_ifdrop; char* if_string; - wtapng_if_descr_filter_t* if_filter; + if_filter_opt_t if_filter; FILE *fh; char *hash_buf; @@ -171,8 +171,13 @@ summary_fill_in(capture_file *cf, summary_tally *st) for (i = 0; i < idb_info->interface_data->len; i++) { wtapng_if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i); wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wtapng_if_descr); - if (wtap_block_get_structured_option_value(wtapng_if_descr, OPT_IDB_FILTER, (void**)&if_filter) == WTAP_OPTTYPE_SUCCESS) { - iface.cfilter = g_strdup(if_filter->if_filter_str); + if (wtap_block_get_if_filter_option_value(wtapng_if_descr, OPT_IDB_FILTER, &if_filter) == WTAP_OPTTYPE_SUCCESS) { + if (if_filter.type == if_filter_pcap) { + iface.cfilter = g_strdup(if_filter.data.filter_str); + } else { + /* Not a pcap filter string; punt for now */ + iface.cfilter = NULL; + } } else { iface.cfilter = NULL; } diff --git a/wiretap/erf.c b/wiretap/erf.c index 8804f450f8..512a114455 100644 --- a/wiretap/erf.c +++ b/wiretap/erf.c @@ -1107,12 +1107,12 @@ static void erf_write_wtap_option_to_interface_tag(wtap_block_t block _U_, break; case OPT_IDB_FILTER: { - wtapng_if_descr_filter_t *filter; + if_filter_opt_t *filter; + filter = &optval->if_filterval; tag_ptr->type = 0xF800; - filter = (wtapng_if_descr_filter_t*)&optval->structuredval; - if(filter->if_filter_str) { + if(filter->type == if_filter_pcap) { tag_ptr->type = ERF_META_TAG_filter; - tag_ptr->value = (guint8*)g_strdup(filter->if_filter_str); + tag_ptr->value = (guint8*)g_strdup(filter->data.filter_str); tag_ptr->length = (guint16)strlen((char*)tag_ptr->value); } } @@ -2710,7 +2710,7 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo int interface_index = -1; wtap_block_t int_data = NULL; wtapng_if_descr_mandatory_t* int_data_mand = NULL; - wtapng_if_descr_filter_t if_filter = {0}; + if_filter_opt_t if_filter; guint32 if_num = 0; struct erf_if_info* if_info = NULL; @@ -2840,9 +2840,10 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo wtap_block_add_string_option(int_data, OPT_COMMENT, tag.value, tag.length); break; case ERF_META_TAG_filter: - if_filter.if_filter_str = g_strndup((gchar*) tag.value, tag.length); - wtap_block_add_structured_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter); - g_free(if_filter.if_filter_str); + if_filter.type = if_filter_pcap; + if_filter.data.filter_str = g_strndup((gchar*) tag.value, tag.length); + wtap_block_add_if_filter_option(int_data, OPT_IDB_FILTER, &if_filter); + g_free(if_filter.data.filter_str); if_info->set_flags.filter = 1; break; default: @@ -2866,16 +2867,18 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo if (!if_info->set_flags.filter) { if (state->if_map->module_filter_str) { /* Duplicate because might use with multiple interfaces */ - if_filter.if_filter_str = state->if_map->module_filter_str; - wtap_block_add_structured_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter); + if_filter.type = if_filter_pcap; + if_filter.data.filter_str = state->if_map->module_filter_str; + wtap_block_add_if_filter_option(int_data, OPT_IDB_FILTER, &if_filter); /* * Don't set flag because stream is more specific than module. */ } else if (state->if_map->capture_filter_str) { /* TODO: display separately? Note that we could have multiple captures * from multiple hosts in the file */ - if_filter.if_filter_str = state->if_map->capture_filter_str; - wtap_block_add_structured_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter); + if_filter.type = if_filter_pcap; + if_filter.data.filter_str = state->if_map->capture_filter_str; + wtap_block_add_if_filter_option(int_data, OPT_IDB_FILTER, &if_filter); } } @@ -2901,7 +2904,7 @@ static int populate_stream_info(erf_t *erf_priv _U_, wtap *wth, union wtap_pseud int interface_index = -1; wtap_block_t int_data = NULL; wtapng_if_descr_mandatory_t* int_data_mand = NULL; - wtapng_if_descr_filter_t if_filter = {0}; + if_filter_opt_t if_filter; guint32 if_num = 0; gint32 stream_num = -1; guint8 *tag_ptr_tmp; @@ -3011,9 +3014,10 @@ static int populate_stream_info(erf_t *erf_priv _U_, wtap *wth, union wtap_pseud case ERF_META_TAG_filter: /* Override only if not set */ if (!if_info->set_flags.filter) { - if_filter.if_filter_str = g_strndup((gchar*) tag.value, tag.length); - wtap_block_add_structured_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter); - g_free(if_filter.if_filter_str); + if_filter.type = if_filter_pcap; + if_filter.data.filter_str = g_strndup((gchar*) tag.value, tag.length); + wtap_block_add_if_filter_option(int_data, OPT_IDB_FILTER, &if_filter); + g_free(if_filter.data.filter_str); if_info->set_flags.filter = 1; } break; diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 019bf17084..4c78e073aa 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -937,21 +937,55 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh, */ case(OPT_IDB_FILTER): /* if_filter */ if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) { - wtapng_if_descr_filter_t if_filter = {0}; + if_filter_opt_t if_filter; /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, * or BPF bytecode. */ if (option_content[0] == 0) { - if_filter.if_filter_str = g_strndup((char *)option_content+1, oh.option_length-1); - pcapng_debug("pcapng_read_if_descr_block: if_filter_str %s oh.option_length %u", if_filter.if_filter_str, oh.option_length); + if_filter.type = if_filter_pcap; + if_filter.data.filter_str = g_strndup((char *)option_content+1, oh.option_length-1); + pcapng_debug("pcapng_read_if_descr_block: filter_str %s oh.option_length %u", if_filter.filter_str, oh.option_length); } else if (option_content[0] == 1) { - if_filter.bpf_filter_len = oh.option_length-1; - if_filter.if_filter_bpf_bytes = option_content+1; + /* + * XXX - byte-swap the code and k fields + * of each instruction as needed! + * + * XXX - what if oh.option_length-1 is not a + * multiple of the size of a BPF instruction? + */ + guint num_insns; + const guint8 *insn_in; + + if_filter.type = if_filter_bpf; + num_insns = (oh.option_length-1)/8; + insn_in = option_content+1; + if_filter.data.bpf_prog.bpf_prog_len = num_insns; + if_filter.data.bpf_prog.bpf_prog = g_new(wtap_bpf_insn_t, num_insns); + for (guint i = 0; i < num_insns; i++) { + wtap_bpf_insn_t *insn = &if_filter.data.bpf_prog.bpf_prog[i]; + + memcpy(&insn->code, insn_in, 2); + if (section_info->byte_swapped) + insn->code = GUINT16_SWAP_LE_BE(insn->code); + insn_in += 2; + memcpy(&insn->jt, insn_in, 1); + insn_in += 1; + memcpy(&insn->jf, insn_in, 1); + insn_in += 1; + memcpy(&insn->k, insn_in, 4); + if (section_info->byte_swapped) + insn->code = GUINT32_SWAP_LE_BE(insn->code); + insn_in += 4; + } } /* Fails with multiple options; we silently ignore the failure */ - wtap_block_add_structured_option(wblock->block, oh.option_code, &if_filter, sizeof if_filter); - g_free(if_filter.if_filter_str); + wtap_block_add_if_filter_option(wblock->block, oh.option_code, &if_filter); + if (if_filter.type == if_filter_pcap) { + g_free(if_filter.data.filter_str); + } else if (if_filter.type == if_filter_bpf) { + g_free(if_filter.data.bpf_prog.bpf_prog); + } } else { pcapng_debug("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length); } @@ -3294,12 +3328,21 @@ pcapng_write_block_t; static gboolean pcapng_write_option_string(wtap_dumper *wdh, guint option_id, char *str, int *err) { struct pcapng_option_header option_hdr; - guint32 size = (guint32)strlen(str) & 0xffff; + size_t size = strlen(str); const guint32 zero_pad = 0; guint32 pad; if (size == 0) return TRUE; + if (size > 65535) { + /* + * Too big to fit in the option. + * Don't write anything. + * + * XXX - truncate it? Report an error? + */ + return TRUE; + } /* String options don't consider pad bytes part of the length */ option_hdr.type = (guint16)option_id; @@ -4541,18 +4584,22 @@ static void compute_idb_option_size(wtap_block_t block _U_, guint option_id, wta break; case OPT_IDB_FILTER: { - wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)optval->structuredval.data; + if_filter_opt_t* filter = &optval->if_filterval; guint32 pad; - if (filter->if_filter_str != NULL) { - size = (guint32)(strlen(filter->if_filter_str) + 1) & 0xffff; - if ((size % 4)) { - pad = 4 - (size % 4); - } else { - pad = 0; - } - - size += pad; + if (filter->type == if_filter_pcap) { + size = (guint32)(strlen(filter->data.filter_str) + 1) & 0xffff; + } else if (filter->type == if_filter_bpf) { + size = (guint32)((filter->data.bpf_prog.bpf_prog_len * 8) + 1) & 0xffff; + } else { + /* Unknown type; don't write it */ + size = 0; } + if ((size % 4)) { + pad = 4 - (size % 4); + } else { + pad = 0; + } + size += pad; } break; case OPT_IDB_FCSLEN: @@ -4631,47 +4678,98 @@ static void write_wtap_idb_option(wtap_block_t block _U_, guint option_id, wtap_ break; case OPT_IDB_FILTER: { - wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)optval->structuredval.data; + if_filter_opt_t* filter = &optval->if_filterval; guint32 size, pad; - if (filter->if_filter_str != NULL) { - size = (guint32)(strlen(filter->if_filter_str) + 1) & 0xffff; - if ((size % 4)) { - pad = 4 - (size % 4); - } else { - pad = 0; + guint8 filter_type; + size_t filter_data_len; + switch (filter->type) { + + case if_filter_pcap: + filter_type = 0; /* pcap filter string */ + filter_data_len = strlen(filter->data.filter_str); + if (filter_data_len > 65534) { + /* + * Too big to fit in the option. + * Don't write anything. + * + * XXX - truncate it? Report an error? + */ + return; } + break; - option_hdr.type = option_id; - option_hdr.value_length = size; - if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) { - write_block->success = FALSE; + case if_filter_bpf: + filter_type = 1; /* BPF filter program */ + filter_data_len = filter->data.bpf_prog.bpf_prog_len*8; + if (filter_data_len > 65528) { + /* + * Too big to fit in the option. (The filter length + * must be a multiple of 8, as that's the length + * of a BPF instruction.) Don't write anything. + * + * XXX - truncate it? Report an error? + */ return; } - write_block->wdh->bytes_dumped += 4; + break; + + default: + /* Unknown filter type; don't write anything. */ + return; + } + size = (guint32)(filter_data_len + 1); + if ((size % 4)) { + pad = 4 - (size % 4); + } else { + pad = 0; + } + + option_hdr.type = option_id; + option_hdr.value_length = size; + if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) { + write_block->success = FALSE; + return; + } + write_block->wdh->bytes_dumped += 4; + + /* Write the filter type */ + if (!wtap_dump_file_write(write_block->wdh, &filter_type, 1, write_block->err)) { + write_block->success = FALSE; + return; + } + write_block->wdh->bytes_dumped += 1; - /* Write the zero indicating libpcap filter variant */ - if (!wtap_dump_file_write(write_block->wdh, &zero_pad, 1, write_block->err)) { + switch (filter->type) { + + case if_filter_pcap: + /* Write the filter string */ + if (!wtap_dump_file_write(write_block->wdh, filter->data.filter_str, filter_data_len, write_block->err)) { write_block->success = FALSE; return; } - write_block->wdh->bytes_dumped += 1; + write_block->wdh->bytes_dumped += filter_data_len; + break; - /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */ - if (!wtap_dump_file_write(write_block->wdh, filter->if_filter_str, size-1, write_block->err)) { + case if_filter_bpf: + if (!wtap_dump_file_write(write_block->wdh, filter->data.bpf_prog.bpf_prog, filter_data_len, write_block->err)) { write_block->success = FALSE; return; } - write_block->wdh->bytes_dumped += size - 1; + write_block->wdh->bytes_dumped += filter_data_len; + break; - /* write padding (if any) */ - if (pad != 0) { - if (!wtap_dump_file_write(write_block->wdh, &zero_pad, pad, write_block->err)) { - write_block->success = FALSE; - return; - } - write_block->wdh->bytes_dumped += pad; - } + default: + g_assert_not_reached(); + return; + } + /* write padding (if any) */ + if (pad != 0) { + if (!wtap_dump_file_write(write_block->wdh, &zero_pad, pad, write_block->err)) { + write_block->success = FALSE; + return; + } + write_block->wdh->bytes_dumped += pad; } } break; diff --git a/wiretap/wtap.c b/wiretap/wtap.c index ff4479f68a..26615e3d3a 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -295,7 +295,7 @@ wtap_get_debug_if_descr(const wtap_block_t if_descr, guint64 tmp64; gint8 itmp8; guint8 tmp8; - wtapng_if_descr_filter_t* if_filter; + if_filter_opt_t if_filter; g_assert(if_descr); @@ -365,16 +365,30 @@ wtap_get_debug_if_descr(const wtap_block_t if_descr, line_end); } - if (wtap_block_get_structured_option_value(if_descr, OPT_IDB_FILTER, (void**)&if_filter) == WTAP_OPTTYPE_SUCCESS) { - g_string_append_printf(info, - "%*cFilter string = %s%s", indent, ' ', - if_filter->if_filter_str ? if_filter->if_filter_str : "NONE", - line_end); + if (wtap_block_get_if_filter_option_value(if_descr, OPT_IDB_FILTER, &if_filter) == WTAP_OPTTYPE_SUCCESS) { + switch (if_filter.type) { - g_string_append_printf(info, - "%*cBPF filter length = %u%s", indent, ' ', - if_filter->bpf_filter_len, - line_end); + case if_filter_pcap: + g_string_append_printf(info, + "%*cFilter string = %s%s", indent, ' ', + if_filter.data.filter_str, + line_end); + break; + + case if_filter_bpf: + g_string_append_printf(info, + "%*cBPF filter length = %u%s", indent, ' ', + if_filter.data.bpf_prog.bpf_prog_len, + line_end); + break; + + default: + g_string_append_printf(info, + "%*cUnknown filter type %u%s", indent, ' ', + if_filter.type, + line_end); + break; + } } if (wtap_block_get_string_option_value(if_descr, OPT_IDB_OS, &tmp_content) == WTAP_OPTTYPE_SUCCESS) { diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 9005cf3290..9e4b835bd5 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1515,15 +1515,6 @@ typedef struct wtapng_dsb_mandatory_s { guint8 *secrets_data; /** Buffer of secrets (not NUL-terminated) */ } wtapng_dsb_mandatory_t; -/* Interface description data - Option 11 structure */ -typedef struct wtapng_if_descr_filter_s { - gchar *if_filter_str; /**< NULL if not available - * libpcap string. - */ - guint16 bpf_filter_len; /** variant II BPF filter len 0 if not used*/ - guint8 *if_filter_bpf_bytes; /** BPF filter or NULL */ -} wtapng_if_descr_filter_t; - /** * Holds the required data for pcapng Interface Statistics Block (ISB). */ diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c index 29c5f82b46..42439e8fc6 100644 --- a/wiretap/wtap_opttypes.c +++ b/wiretap/wtap_opttypes.c @@ -36,9 +36,6 @@ typedef struct { GArray *options; /**< array of known options */ } wtap_blocktype_t; -typedef void *(*wtap_opttype_dup_structured_func)(void* src); -typedef void (*wtap_opttype_free_structured_func)(void* data); - /* * Structure describing a type of option. */ @@ -47,8 +44,6 @@ typedef struct { const char *description; /**< human-readable description of option */ wtap_opttype_e data_type; /**< data type of that option */ guint flags; /**< flags for the option */ - wtap_opttype_dup_structured_func dup_func; /**< function to duplicate structured option data */ - wtap_opttype_free_structured_func free_func; /**< function to free structured option data */ } wtap_opttype_t; /* Flags */ @@ -75,9 +70,7 @@ static void wtap_opttype_block_register(wtap_block_type_t block_type, wtap_block "opt_comment", "Comment", WTAP_OPTTYPE_STRING, - WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED, - NULL, - NULL + WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED }; /* Check input */ @@ -204,9 +197,21 @@ static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt) g_free(opt->value.stringval); break; - case WTAP_OPTTYPE_STRUCTURED: - opttype->free_func(opt->value.structuredval.data); - g_free(opt->value.structuredval.data); + case WTAP_OPTTYPE_IF_FILTER: + switch (opt->value.if_filterval.type) { + + case if_filter_pcap: + /* pcap filter string */ + g_free(opt->value.if_filterval.data.filter_str); + break; + + case if_filter_bpf: + g_free(opt->value.if_filterval.data.bpf_prog.bpf_prog); + break; + + default: + break; + } break; default: @@ -298,8 +303,8 @@ wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block) wtap_block_add_string_option(dest_block, src_opt->option_id, src_opt->value.stringval, strlen(src_opt->value.stringval)); break; - case WTAP_OPTTYPE_STRUCTURED: - wtap_block_add_structured_option(dest_block, src_opt->option_id, src_opt->value.structuredval.data, src_opt->value.structuredval.size); + case WTAP_OPTTYPE_IF_FILTER: + wtap_block_add_if_filter_option(dest_block, src_opt->option_id, &src_opt->value.if_filterval); break; } } @@ -769,54 +774,95 @@ wtap_block_get_nth_string_option_value(wtap_block_t block, guint option_id, guin return WTAP_OPTTYPE_SUCCESS; } +static if_filter_opt_t if_filter_dup(if_filter_opt_t* filter_src) +{ + if_filter_opt_t filter_dest; + + /* Deep copy. */ + filter_dest.type = filter_src->type; + switch (filter_src->type) { + + case if_filter_pcap: + /* pcap filter string */ + filter_dest.data.filter_str = + g_strdup(filter_src->data.filter_str); + break; + + case if_filter_bpf: + /* BPF program */ + filter_dest.data.bpf_prog.bpf_prog_len = + filter_src->data.bpf_prog.bpf_prog_len; + filter_dest.data.bpf_prog.bpf_prog = + (wtap_bpf_insn_t *)g_memdup(filter_src->data.bpf_prog.bpf_prog, + filter_src->data.bpf_prog.bpf_prog_len * sizeof (wtap_bpf_insn_t)); + break; + + default: + break; + } + return filter_dest; +} + +static void if_filter_free(if_filter_opt_t* filter_src) +{ + switch (filter_src->type) { + + case if_filter_pcap: + /* pcap filter string */ + g_free(filter_src->data.filter_str); + break; + + case if_filter_bpf: + /* BPF program */ + g_free(filter_src->data.bpf_prog.bpf_prog); + break; + + default: + break; + } +} + wtap_opttype_return_val -wtap_block_add_structured_option(wtap_block_t block, guint option_id, void *value, size_t value_size) +wtap_block_add_if_filter_option(wtap_block_t block, guint option_id, if_filter_opt_t* value) { wtap_opttype_return_val ret; wtap_option_t *opt; - wtap_opttype_t *opttype; - ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRUCTURED, &opt); + ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IF_FILTER, &opt); if (ret != WTAP_OPTTYPE_SUCCESS) return ret; - opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id); - opt->value.structuredval.size = (guint)value_size; - opt->value.structuredval.data = opttype->dup_func(value); + opt->value.if_filterval = if_filter_dup(value); return WTAP_OPTTYPE_SUCCESS; } wtap_opttype_return_val -wtap_block_get_structured_option_value(wtap_block_t block, guint option_id, void** value) +wtap_block_set_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value) { wtap_opttype_return_val ret; wtap_optval_t *optval; + if_filter_opt_t prev_value; - ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRUCTURED, &optval); + ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IF_FILTER, &optval); if (ret != WTAP_OPTTYPE_SUCCESS) return ret; - *value = optval->structuredval.data; + prev_value = optval->if_filterval; + optval->if_filterval = if_filter_dup(value); + /* Free after memory is duplicated in case structure was manipulated with a "get then set" */ + if_filter_free(&prev_value); + return WTAP_OPTTYPE_SUCCESS; } wtap_opttype_return_val -wtap_block_set_structured_option_value(wtap_block_t block, guint option_id, void *value) +wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value) { wtap_opttype_return_val ret; wtap_optval_t *optval; - void *prev_value; - ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRUCTURED, &optval); + ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IF_FILTER, &optval); if (ret != WTAP_OPTTYPE_SUCCESS) return ret; - prev_value = optval->structuredval.data; - /* - * XXX - a custom value can be a structure that points to other data, - * but we're doing a shallow copy here. - */ - optval->structuredval.data = g_memdup(value, optval->structuredval.size); - /* Free after memory is duplicated in case structure was manipulated with a "get then set" */ - g_free(prev_value); - + *value = optval->if_filterval; return WTAP_OPTTYPE_SUCCESS; } @@ -933,26 +979,6 @@ static void isb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block) memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t)); } -static void *idb_filter_dup(void* src) -{ - wtapng_if_descr_filter_t* filter_src = (wtapng_if_descr_filter_t*)src; - wtapng_if_descr_filter_t* filter_dest; - - /* Deep copy. */ - filter_dest = g_new(wtapng_if_descr_filter_t, 1); - filter_dest->if_filter_str = g_strdup(filter_src->if_filter_str); - filter_dest->bpf_filter_len = filter_src->bpf_filter_len; - filter_dest->if_filter_bpf_bytes = (guint8 *)g_memdup(filter_src->if_filter_bpf_bytes, filter_src->bpf_filter_len); - return (void *)filter_dest; -} - -static void idb_filter_free(void* data) -{ - wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)data; - g_free(filter->if_filter_str); - g_free(filter->if_filter_bpf_bytes); -} - static void idb_create(wtap_block_t block) { block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1); @@ -1033,25 +1059,19 @@ void wtap_opttypes_initialize(void) "hardware", "SHB Hardware", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t shb_os = { "os", "SHB Operating System", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t shb_userappl = { "user_appl", "SHB User Application", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_blocktype_t idb_block = { @@ -1067,65 +1087,49 @@ void wtap_opttypes_initialize(void) "name", "IDB Name", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t if_description = { "description", "IDB Description", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t if_speed = { "speed", "IDB Speed", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t if_tsresol = { "tsresol", "IDB Time Stamp Resolution", WTAP_OPTTYPE_UINT8, /* XXX - signed? */ - 0, - NULL, - NULL + 0 }; static wtap_opttype_t if_filter = { "filter", "IDB Filter", - WTAP_OPTTYPE_STRUCTURED, - 0, - idb_filter_dup, - idb_filter_free + WTAP_OPTTYPE_IF_FILTER, + 0 }; static wtap_opttype_t if_os = { "os", "IDB Operating System", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t if_fcslen = { "fcslen", "IDB FCS Length", WTAP_OPTTYPE_UINT8, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t if_hardware = { "hardware", "IDB Hardware", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_blocktype_t dsb_block = { @@ -1151,25 +1155,19 @@ void wtap_opttypes_initialize(void) "dnsname", "NRB DNS server name", WTAP_OPTTYPE_STRING, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t ns_dnsIP4addr = { "dnsIP4addr", "NRB DNS server IPv4 address", WTAP_OPTTYPE_IPv4, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t ns_dnsIP6addr = { "dnsIP6addr", "NRB DNS server IPv6 address", WTAP_OPTTYPE_IPv6, - 0, - NULL, - NULL + 0 }; static wtap_blocktype_t isb_block = { @@ -1185,57 +1183,43 @@ void wtap_opttypes_initialize(void) "starttime", "ISB Start Time", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t isb_endtime = { "endtime", "ISB End Time", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t isb_ifrecv = { "ifrecv", "ISB Received Packets", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t isb_ifdrop = { "ifdrop", "ISB Dropped Packets", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t isb_filteraccept = { "filteraccept", "ISB Packets Accepted By Filter", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t isb_osdrop = { "osdrop", "ISB Packets Dropped By The OS", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; static wtap_opttype_t isb_usrdeliv = { "usrdeliv", "ISB Packets Delivered To The User", WTAP_OPTTYPE_UINT64, - 0, - NULL, - NULL + 0 }; /* Initialize the custom block array. This is for future proofing diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h index f9477b56cd..d2e4a39f10 100644 --- a/wiretap/wtap_opttypes.h +++ b/wiretap/wtap_opttypes.h @@ -144,7 +144,7 @@ typedef enum { WTAP_OPTTYPE_STRING, WTAP_OPTTYPE_IPv4, WTAP_OPTTYPE_IPv6, - WTAP_OPTTYPE_STRUCTURED /* option-dependent non-simple format */ + WTAP_OPTTYPE_IF_FILTER } wtap_opttype_e; typedef enum { @@ -156,11 +156,34 @@ typedef enum { WTAP_OPTTYPE_ALREADY_EXISTS = -5 } wtap_opttype_return_val; -struct wtap_opttype_structured -{ - void* data; - guint size; -}; +/* Interface description data - if_filter option structure */ + +/* BPF instruction */ +typedef struct wtap_bpf_insn_s { + guint16 code; + guint8 jt; + guint8 jf; + guint32 k; +} wtap_bpf_insn_t; + +/* + * Type of filter. + */ +typedef enum { + if_filter_pcap = 0, /* pcap filter string */ + if_filter_bpf = 1 /* BPF program */ +} if_filter_type_e; + +typedef struct if_filter_opt_s { + if_filter_type_e type; + union { + gchar *filter_str; /**< pcap filter string */ + struct wtap_bpf_insns { + guint bpf_prog_len; /**< number of BPF instructions */ + wtap_bpf_insn_t *bpf_prog; /**< BPF instructions */ + } bpf_prog; /**< BPF program */ + } data; +} if_filter_opt_t; /* * Structure describing a value of an option. @@ -171,7 +194,7 @@ typedef union { guint32 ipv4val; /* network byte order */ ws_in6_addr ipv6val; char *stringval; - struct wtap_opttype_structured structuredval; + if_filter_opt_t if_filterval; } wtap_optval_t; /* @@ -460,19 +483,18 @@ wtap_block_get_string_option_value(wtap_block_t block, guint option_id, char** v WS_DLL_PUBLIC wtap_opttype_return_val wtap_block_get_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, char** value) G_GNUC_WARN_UNUSED_RESULT; -/** Add a structured option value to a block +/** Add an if_filter option value to a block * * @param[in] block Block to which to add the option * @param[in] option_id Identifier value for option * @param[in] value Value of option - * @param[in] value_size Size of value * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful, * error code otherwise */ WS_DLL_PUBLIC wtap_opttype_return_val -wtap_block_add_structured_option(wtap_block_t block, guint option_id, void* value, size_t value_size); +wtap_block_add_if_filter_option(wtap_block_t block, guint option_id, if_filter_opt_t* value); -/** Set a structured option value in a block +/** Set an if_filter option value in a block * * @param[in] block Block in which to set the option value * @param[in] option_id Identifier value for option @@ -481,18 +503,18 @@ wtap_block_add_structured_option(wtap_block_t block, guint option_id, void* valu * error code otherwise */ WS_DLL_PUBLIC wtap_opttype_return_val -wtap_block_set_structured_option_value(wtap_block_t block, guint option_id, void* value); +wtap_block_set_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value); -/** Get a structured option value from a block +/** Get an if_filter option value from a block * * @param[in] block Block from which to get the option value * @param[in] option_id Identifier value for option - * @param[out] value Returned value of option + * @param[out] value Returned value of option value * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful, * error code otherwise */ WS_DLL_PUBLIC wtap_opttype_return_val -wtap_block_get_structured_option_value(wtap_block_t block, guint option_id, void** value) G_GNUC_WARN_UNUSED_RESULT; +wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value) G_GNUC_WARN_UNUSED_RESULT; /** Remove an option from a block * |