From ae598d17370e141c37e3130fe16123d3e36d5195 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Fri, 15 Jul 2016 17:25:41 -0700 Subject: [PATCH] Add APIs to remove option instances from blocks. That will allow deletion of comments, stripping of options when sanitizing captures, etc.. Change-Id: I9667ba2ccf4e548ff3b7d500796b260a437bcea0 Reviewed-on: https://code.wireshark.org/review/16485 Reviewed-by: Guy Harris --- wiretap/wtap_opttypes.c | 122 ++++++++++++++++++++++++++++++++++------ wiretap/wtap_opttypes.h | 22 ++++++++ 2 files changed, 128 insertions(+), 16 deletions(-) diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c index 0f4da0f936..c3b9f0df29 100644 --- a/wiretap/wtap_opttypes.c +++ b/wiretap/wtap_opttypes.c @@ -205,29 +205,35 @@ wtap_block_t wtap_block_create(wtap_block_type_t block_type) return block; } +static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt) +{ + wtap_opttype_t *opttype; + + opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id); + switch (opttype->data_type) { + + case WTAP_OPTTYPE_STRING: + g_free(opt->value.stringval); + break; + + case WTAP_OPTTYPE_CUSTOM: + opttype->free_func(opt->value.customval.data); + g_free(opt->value.customval.data); + break; + + default: + break; + } +} + static void wtap_block_free_options(wtap_block_t block) { guint i; wtap_option_t *opt; - wtap_opttype_t *opttype; for (i = 0; i < block->options->len; i++) { opt = &g_array_index(block->options, wtap_option_t, i); - opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id); - switch (opttype->data_type) { - - case WTAP_OPTTYPE_STRING: - g_free(opt->value.stringval); - break; - - case WTAP_OPTTYPE_CUSTOM: - opttype->free_func(opt->value.customval.data); - g_free(opt->value.customval.data); - break; - - default: - break; - } + wtap_block_free_option(block, opt); } } @@ -837,6 +843,90 @@ wtap_block_set_custom_option_value(wtap_block_t block, guint option_id, void *va return WTAP_OPTTYPE_SUCCESS; } +wtap_opttype_return_val +wtap_block_remove_option(wtap_block_t block, guint option_id) +{ + wtap_opttype_t *opttype; + guint i; + wtap_option_t *opt; + + if (option_id >= block->info->options->len) { + /* There's no option for this block with that option ID */ + return WTAP_OPTTYPE_NO_SUCH_OPTION; + } + + opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id); + + /* + * Can there be more than one instance of this option? + */ + if (opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED) { + /* + * Yes. You can't remove "the" value. + */ + return WTAP_OPTTYPE_NUMBER_MISMATCH; + } + + for (i = 0; i < block->options->len; i++) { + opt = &g_array_index(block->options, wtap_option_t, i); + if (opt->option_id == option_id) { + /* Found it - free up the value */ + wtap_block_free_option(block, opt); + /* Remove the option from the array of options */ + g_array_remove_index(block->options, i); + return WTAP_OPTTYPE_SUCCESS; + } + } + + /* Didn't find the option */ + return WTAP_OPTTYPE_NOT_FOUND; +} + +wtap_opttype_return_val +wtap_block_remove_nth_option_instance(wtap_block_t block, guint option_id, + guint idx) +{ + wtap_opttype_t *opttype; + guint i; + wtap_option_t *opt; + guint opt_idx; + + if (option_id >= block->info->options->len) { + /* There's no option for this block with that option ID */ + return WTAP_OPTTYPE_NO_SUCH_OPTION; + } + + opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id); + + /* + * Can there be more than one instance of this option? + */ + if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) { + /* + * No. + */ + return WTAP_OPTTYPE_NUMBER_MISMATCH; + } + + opt_idx = 0; + for (i = 0; i < block->options->len; i++) { + opt = &g_array_index(block->options, wtap_option_t, i); + if (opt->option_id == option_id) { + if (opt_idx == idx) { + /* Found it - free up the value */ + wtap_block_free_option(block, opt); + /* Remove the option from the array of options */ + g_array_remove_index(block->options, i); + return WTAP_OPTTYPE_SUCCESS; + } + opt_idx++; + } + } + + /* Didn't find the option */ + return WTAP_OPTTYPE_NOT_FOUND; +} + static void shb_create(wtap_block_t block) { wtapng_mandatory_section_t* section_mand = g_new(wtapng_mandatory_section_t, 1); diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h index a7d2fe8966..f1c4fd3af3 100644 --- a/wiretap/wtap_opttypes.h +++ b/wiretap/wtap_opttypes.h @@ -481,6 +481,28 @@ wtap_block_set_custom_option_value(wtap_block_t block, guint option_id, void* va WS_DLL_PUBLIC wtap_opttype_return_val wtap_block_get_custom_option_value(wtap_block_t block, guint option_id, void** value) G_GNUC_WARN_UNUSED_RESULT; +/** Remove an option from a block + * + * @param[in] block Block from which to remove the option + * @param[in] option_id Identifier value for option + * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful, + * error code otherwise + */ +WS_DLL_PUBLIC wtap_opttype_return_val +wtap_block_remove_option(wtap_block_t block, guint option_id); + +/** Remove the nth instance of an option from a block + * + * @param[in] block Block from which to remove the option instance + * @param[in] option_id Identifier value for option + * @param[in] idx Instance number of option with that ID + * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful, + * error code otherwise + */ +WS_DLL_PUBLIC wtap_opttype_return_val +wtap_block_remove_nth_option_instance(wtap_block_t block, guint option_id, + guint idx); + /** Copy a block to another. * * Any options that are in the destination but not the source are not removed.