diff options
Diffstat (limited to 'wiretap/wtap_opttypes.c')
-rw-r--r-- | wiretap/wtap_opttypes.c | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c new file mode 100644 index 0000000000..3486ef69a9 --- /dev/null +++ b/wiretap/wtap_opttypes.c @@ -0,0 +1,505 @@ +/* wtap_opttypes.c + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 2001 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "config.h" + +#include <glib.h> +#include <string.h> + +#include "wtap.h" +#include "wtap_opttypes.h" +#include "wtap-int.h" +#include "pcapng.h" + +struct wtap_optionblock +{ + const char *name; /**< name of block */ + const char *description; /**< human-readable description of block */ + wtap_optionblock_type_t type; + void* mandatory_data; + GArray* options; +}; + +void wtap_opttypes_initialize(void) +{ +} + +static void wtap_if_descr_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); +} + +wtap_optionblock_t wtap_optionblock_create(wtap_optionblock_type_t block_type) +{ + wtap_optionblock_t block = NULL; + + switch(block_type) + { + case WTAP_OPTION_BLOCK_NG_SECTION: + { + wtapng_mandatory_section_t* section_mand; + + block = g_new(struct wtap_optionblock, 1); + block->name = "SHB"; + block->description = "Section Header block"; + block->type = WTAP_OPTION_BLOCK_NG_SECTION; + block->mandatory_data = g_new(wtapng_mandatory_section_t, 1); + section_mand = (wtapng_mandatory_section_t*)block->mandatory_data; + section_mand->section_length = -1; + block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*)); + + wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL); + wtap_optionblock_add_option_string(block, OPT_SHB_HARDWARE, "hardware", "SBH Hardware", NULL, NULL); + wtap_optionblock_add_option_string(block, OPT_SHB_OS, "os", "SBH Operating System", NULL, NULL); + wtap_optionblock_add_option_string(block, OPT_SHB_USERAPPL, "user_appl", "SBH User Application", NULL, NULL); + } + break; + case WTAP_OPTION_BLOCK_NG_NRB: + block = g_new(struct wtap_optionblock, 1); + block->name = "NRB"; + block->description = "Name Resolution Block"; + block->type = WTAP_OPTION_BLOCK_NG_NRB; + block->mandatory_data = NULL; + block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*)); + + wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL); + break; + + case WTAP_OPTION_BLOCK_IF_STATS: + block = g_new(struct wtap_optionblock, 1); + block->name = "ISB"; + block->description = "Interface Statistics Block"; + block->type = WTAP_OPTION_BLOCK_IF_STATS; + block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1); + block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*)); + + wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL); + wtap_optionblock_add_option_uint64(block, OPT_ISB_STARTTIME, "start_time", "Start Time", 0, 0); + wtap_optionblock_add_option_uint64(block, OPT_ISB_ENDTIME, "end_time", "End Time", 0, 0); + wtap_optionblock_add_option_uint64(block, OPT_ISB_IFRECV, "recv", "Receive Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)); + wtap_optionblock_add_option_uint64(block, OPT_ISB_IFDROP, "drop", "Dropped Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)); + wtap_optionblock_add_option_uint64(block, OPT_ISB_FILTERACCEPT, "filter_accept", "Filter Accept", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)); + wtap_optionblock_add_option_uint64(block, OPT_ISB_OSDROP, "os_drop", "OS Dropped Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)); + wtap_optionblock_add_option_uint64(block, OPT_ISB_USRDELIV, "user_deliv", "User Delivery", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)); + break; + case WTAP_OPTION_BLOCK_IF_DESCR: + { + wtapng_if_descr_filter_t default_filter; + memset(&default_filter, 0, sizeof(default_filter)); + + block = g_new(struct wtap_optionblock, 1); + block->name = "IDB"; + block->description = "Interface Description Block"; + block->type = WTAP_OPTION_BLOCK_IF_DESCR; + block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1); + block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*)); + + wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL); + wtap_optionblock_add_option_string(block, OPT_IDB_NAME, "name", "Device name", NULL, NULL); + wtap_optionblock_add_option_string(block, OPT_IDB_DESCR, "description", "Device description", NULL, NULL); + wtap_optionblock_add_option_uint64(block, OPT_IDB_SPEED, "speed", "Interface speed (in bps)", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)); + wtap_optionblock_add_option_uint8(block, OPT_IDB_TSRESOL, "ts_resolution", "Resolution of timestamps", 6, 6); + wtap_optionblock_add_option_custom(block, OPT_IDB_FILTER, "filter", "Filter string", &default_filter, &default_filter, sizeof(wtapng_if_descr_filter_t), wtap_if_descr_filter_free); + wtap_optionblock_add_option_string(block, OPT_IDB_OS, "os", "Operating System", NULL, NULL); + wtap_optionblock_add_option_uint8(block, OPT_IDB_FCSLEN, "fcslen", "FCS Length", -1, -1); + } + break; + } + + return block; +} + +static void wtap_optionblock_free_options(wtap_optionblock_t block) +{ + guint i; + wtap_opttype_t* opttype = NULL; + + for (i = 0; i < block->options->len; i++) { + opttype = g_array_index(block->options, wtap_opttype_t*, i); + switch(opttype->type) + { + case WTAP_OPTTYPE_STRING: + g_free(opttype->option.stringval); + break; + case WTAP_OPTTYPE_CUSTOM: + opttype->option.customval.free_func(opttype->option.customval.data); + g_free(opttype->option.customval.data); + opttype->default_val.customval.free_func(opttype->default_val.customval.data); + g_free(opttype->default_val.customval.data); + break; + default: + break; + } + g_free(opttype); + } +} + +void wtap_optionblock_free(wtap_optionblock_t block) +{ + if (block != NULL) + { + /* Need special consideration for freeing of the interface_statistics member */ + if (block->type == WTAP_OPTION_BLOCK_IF_DESCR) + { + wtapng_if_descr_mandatory_t* mand = (wtapng_if_descr_mandatory_t*)block->mandatory_data; + if (mand->num_stat_entries != 0) + { + g_array_free(mand->interface_statistics, TRUE); + } + } + + g_free(block->mandatory_data); + wtap_optionblock_free_options(block); + g_array_free(block->options, FALSE); + g_free(block); + } +} + +void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block) +{ + return block->mandatory_data; +} + +static wtap_opttype_t* wtap_optionblock_get_option(wtap_optionblock_t block, guint option_id) +{ + guint i; + wtap_opttype_t* opttype = NULL; + + for (i = 0; i < block->options->len; i++) + { + opttype = g_array_index(block->options, wtap_opttype_t*, i); + if (opttype->number == option_id) + return opttype; + } + + return NULL; +} + +int wtap_optionblock_add_option_string(wtap_optionblock_t block, guint option_id, + const char *name, const char *description, char* opt_value, char* default_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Option already exists */ + if (opttype != NULL) + return WTAP_OPTTYPE_ALREADY_EXISTS; + + opttype = g_new(wtap_opttype_t, 1); + + opttype->name = name; + opttype->description = description; + opttype->number = option_id; + opttype->type = WTAP_OPTTYPE_STRING; + opttype->option.stringval = g_strdup(opt_value); + opttype->default_val.stringval = default_value; + + g_array_append_val(block->options, opttype); + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_set_option_string(wtap_optionblock_t block, guint option_id, char* opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_STRING) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + g_free(opttype->option.stringval); + opttype->option.stringval = g_strdup(opt_value); + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_get_option_string(wtap_optionblock_t block, guint option_id, char** opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_STRING) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + *opt_value = opttype->option.stringval; + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_add_option_uint64(wtap_optionblock_t block, guint option_id, + const char *name, const char *description, guint64 opt_value, guint64 default_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Option already exists */ + if (opttype != NULL) + return WTAP_OPTTYPE_ALREADY_EXISTS; + + opttype = g_new(wtap_opttype_t, 1); + + opttype->name = name; + opttype->description = description; + opttype->number = option_id; + opttype->type = WTAP_OPTTYPE_UINT64; + opttype->option.uint64val = opt_value; + opttype->default_val.uint64val = default_value; + + g_array_append_val(block->options, opttype); + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, guint64 opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_UINT64) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + opttype->option.uint64val = opt_value; + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, guint64* opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_UINT64) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + *opt_value = opttype->option.uint64val; + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_add_option_uint8(wtap_optionblock_t block, guint option_id, + const char *name, const char *description, guint8 opt_value, guint8 default_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Option already exists */ + if (opttype != NULL) + return WTAP_OPTTYPE_ALREADY_EXISTS; + + opttype = g_new(wtap_opttype_t, 1); + + opttype->name = name; + opttype->description = description; + opttype->number = option_id; + opttype->type = WTAP_OPTTYPE_UINT8; + opttype->option.uint8val = opt_value; + opttype->default_val.uint8val = default_value; + + g_array_append_val(block->options, opttype); + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, guint8 opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_UINT8) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + opttype->option.uint8val = opt_value; + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, guint8* opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_UINT8) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + *opt_value = opttype->option.uint8val; + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_add_option_custom(wtap_optionblock_t block, guint option_id, + const char *name, const char *description, void* opt_value, void* default_value, + guint size, wtap_opttype_free_custom_func free_func) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Option already exists */ + if (opttype != NULL) + return WTAP_OPTTYPE_ALREADY_EXISTS; + + opttype = g_new(wtap_opttype_t, 1); + + opttype->name = name; + opttype->description = description; + opttype->number = option_id; + opttype->type = WTAP_OPTTYPE_CUSTOM; + opttype->option.customval.size = size; + opttype->option.customval.data = g_memdup(opt_value, size); + opttype->option.customval.free_func = free_func; + opttype->default_val.customval.size = size; + opttype->default_val.customval.data = g_memdup(default_value, size); + opttype->default_val.customval.free_func = free_func; + + g_array_append_val(block->options, opttype); + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, void* opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + void* prev_value; + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_CUSTOM) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + prev_value = opttype->option.customval.data; + opttype->option.customval.data = g_memdup(opt_value, opttype->option.customval.size); + /* Free after memory is duplicated in case structure was manipulated with a "get then set" */ + g_free(prev_value); + return WTAP_OPTTYPE_SUCCESS; +} + +int wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, void** opt_value) +{ + wtap_opttype_t* opttype = wtap_optionblock_get_option(block, option_id); + + /* Didn't find the option */ + if (opttype == NULL) + return WTAP_OPTTYPE_NOT_FOUND; + + if (opttype->type != WTAP_OPTTYPE_CUSTOM) + return WTAP_OPTTYPE_TYPE_MISMATCH; + + *opt_value = opttype->option.customval.data; + return WTAP_OPTTYPE_SUCCESS; +} + +void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block) +{ + guint i; + wtap_opttype_t *dest_opttype, *src_opttype; + + switch(src_block->type) + { + case WTAP_OPTION_BLOCK_NG_SECTION: + memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t)); + break; + case WTAP_OPTION_BLOCK_NG_NRB: + /* No mandatory data */ + break; + case WTAP_OPTION_BLOCK_IF_STATS: + memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t)); + break; + case WTAP_OPTION_BLOCK_IF_DESCR: + { + wtapng_if_descr_mandatory_t *src_mand = (wtapng_if_descr_mandatory_t*)src_block->mandatory_data, + *dest_mand = (wtapng_if_descr_mandatory_t*)dest_block->mandatory_data; + /* Need special consideration for copying of the interface_statistics member */ + if (dest_mand->num_stat_entries != 0) + { + g_array_free(dest_mand->interface_statistics, TRUE); + } + + memcpy(dest_mand, src_mand, sizeof(wtapng_if_descr_mandatory_t)); + if (src_mand->num_stat_entries != 0) + { + dest_mand->interface_statistics = NULL; + dest_mand->interface_statistics = g_array_append_vals(dest_mand->interface_statistics, src_mand->interface_statistics->data, src_mand->interface_statistics->len); + } + } + break; + } + + /* Copy the options. For now, don't remove any options that are in destination + * but not source. + */ + for (i = 0; i < src_block->options->len; i++) + { + src_opttype = g_array_index(src_block->options, wtap_opttype_t*, i); + dest_opttype = wtap_optionblock_get_option(dest_block, src_opttype->number); + if (dest_opttype == NULL) + { + /* Option doesn't exist, add it */ + switch(src_opttype->type) + { + case WTAP_OPTTYPE_UINT8: + wtap_optionblock_add_option_uint8(dest_block, src_opttype->number, src_opttype->name, src_opttype->description, + src_opttype->option.uint8val, src_opttype->default_val.uint8val); + break; + case WTAP_OPTTYPE_UINT64: + wtap_optionblock_add_option_uint64(dest_block, src_opttype->number, src_opttype->name, src_opttype->description, + src_opttype->option.uint64val, src_opttype->default_val.uint64val); + break; + case WTAP_OPTTYPE_STRING: + wtap_optionblock_add_option_string(dest_block, src_opttype->number, src_opttype->name, src_opttype->description, + src_opttype->option.stringval, src_opttype->default_val.stringval); + break; + case WTAP_OPTTYPE_CUSTOM: + wtap_optionblock_add_option_custom(dest_block, src_opttype->number, src_opttype->name, src_opttype->description, + src_opttype->option.customval.data, src_opttype->default_val.customval.data, + src_opttype->option.customval.size, src_opttype->option.customval.free_func); + break; + } + } + else + { + /* Option exists, replace it */ + switch(src_opttype->type) + { + case WTAP_OPTTYPE_UINT8: + dest_opttype->option.uint8val = src_opttype->option.uint8val; + break; + case WTAP_OPTTYPE_UINT64: + dest_opttype->option.uint64val = src_opttype->option.uint64val; + break; + case WTAP_OPTTYPE_STRING: + g_free(dest_opttype->option.stringval); + dest_opttype->option.stringval = g_strdup(src_opttype->option.stringval); + break; + case WTAP_OPTTYPE_CUSTOM: + dest_opttype->option.customval.free_func(dest_opttype->option.customval.data); + g_free(dest_opttype->option.customval.data); + dest_opttype->option.customval.data = g_memdup(src_opttype->option.customval.data, src_opttype->option.customval.size); + break; + } + } + } +} |