3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 2001 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "wtap_opttypes.h"
18 #include "pcapng_module.h"
21 #define wtap_debug(...) g_warning(__VA_ARGS__)
23 #define wtap_debug(...)
27 * Structure describing a type of block.
30 wtap_block_type_t block_type; /**< internal type code for block */
31 const char *name; /**< name of block */
32 const char *description; /**< human-readable description of block */
33 wtap_block_create_func create;
34 wtap_mand_free_func free_mand;
35 wtap_mand_copy_func copy_mand;
36 GArray *options; /**< array of known options */
39 typedef void *(*wtap_opttype_dup_custom_func)(void* src);
40 typedef void (*wtap_opttype_free_custom_func)(void* data);
43 * Structure describing a type of option.
46 const char *name; /**< name of option */
47 const char *description; /**< human-readable description of option */
48 wtap_opttype_e data_type; /**< data type of that option */
49 guint flags; /**< flags for the option */
50 wtap_opttype_dup_custom_func dup_func; /**< function to duplicate custom option data */
51 wtap_opttype_free_custom_func free_func; /**< function to free custom option data */
55 #define WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED 0x00000001 /* multiple instances allowed */
59 wtap_blocktype_t* info;
64 #define MAX_WTAP_BLOCK_CUSTOM 10
65 #define MAX_WTAP_BLOCK_TYPE_VALUE (WTAP_BLOCK_END_OF_LIST+MAX_WTAP_BLOCK_CUSTOM)
67 /* Keep track of wtap_blocktype_t's via their id number */
68 static wtap_blocktype_t* blocktype_list[MAX_WTAP_BLOCK_TYPE_VALUE];
69 static guint num_custom_blocks;
70 static wtap_blocktype_t custom_blocktype_list[MAX_WTAP_BLOCK_CUSTOM];
72 static void wtap_opttype_block_register(wtap_block_type_t block_type, wtap_blocktype_t *blocktype)
74 static const wtap_opttype_t opt_comment = {
78 WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED,
84 g_assert(block_type < WTAP_BLOCK_END_OF_LIST);
86 /* Don't re-register. */
87 g_assert(blocktype_list[block_type] == NULL);
90 g_assert(blocktype->name);
91 g_assert(blocktype->description);
92 g_assert(blocktype->create);
94 blocktype->block_type = block_type;
97 * Initialize the set of supported options.
98 * All blocks that support options at all support OPT_COMMENT.
100 blocktype->options = g_array_sized_new(FALSE, TRUE, sizeof (wtap_opttype_t), OPT_COMMENT + 1);
101 if (OPT_COMMENT + 1 > blocktype->options->len)
102 g_array_set_size(blocktype->options, OPT_COMMENT + 1);
103 g_array_insert_val(blocktype->options, OPT_COMMENT, opt_comment);
105 blocktype_list[block_type] = blocktype;
108 int wtap_opttype_register_custom_block_type(const char* name, const char* description, wtap_block_create_func create,
109 wtap_mand_free_func free_mand, wtap_mand_copy_func copy_mand)
113 /* Ensure valid data/functions for required fields */
115 g_assert(description);
118 /* This shouldn't happen, so flag it for fixing */
119 g_assert(num_custom_blocks < MAX_WTAP_BLOCK_CUSTOM);
121 block_type = (wtap_block_type_t)(WTAP_BLOCK_END_OF_LIST+num_custom_blocks);
123 custom_blocktype_list[num_custom_blocks].name = name;
124 custom_blocktype_list[num_custom_blocks].description = description;
125 custom_blocktype_list[num_custom_blocks].create = create;
126 custom_blocktype_list[num_custom_blocks].free_mand = free_mand;
127 custom_blocktype_list[num_custom_blocks].copy_mand = copy_mand;
128 blocktype_list[block_type] = &custom_blocktype_list[num_custom_blocks];
134 static void wtap_opttype_option_register(wtap_blocktype_t *blocktype, int opttype, wtap_opttype_t *option)
136 if ((guint)opttype + 1 > blocktype->options->len)
137 g_array_set_size(blocktype->options, opttype + 1);
138 g_array_insert_val(blocktype->options, opttype, *option);
141 void* wtap_block_get_mandatory_data(wtap_block_t block)
143 return block->mandatory_data;
146 static wtap_optval_t *
147 wtap_block_get_option(wtap_block_t block, guint option_id)
152 for (i = 0; i < block->options->len; i++) {
153 opt = &g_array_index(block->options, wtap_option_t, i);
154 if (opt->option_id == option_id)
161 static wtap_optval_t *
162 wtap_block_get_nth_option(wtap_block_t block, guint option_id, guint idx)
169 for (i = 0; i < block->options->len; i++) {
170 opt = &g_array_index(block->options, wtap_option_t, i);
171 if (opt->option_id == option_id) {
181 wtap_block_t wtap_block_create(wtap_block_type_t block_type)
185 if (block_type >= (wtap_block_type_t)(WTAP_BLOCK_END_OF_LIST+num_custom_blocks))
188 block = g_new(struct wtap_block, 1);
189 block->info = blocktype_list[block_type];
190 block->options = g_array_new(FALSE, FALSE, sizeof(wtap_option_t));
191 block->info->create(block);
196 static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt)
198 wtap_opttype_t *opttype;
200 opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id);
201 switch (opttype->data_type) {
203 case WTAP_OPTTYPE_STRING:
204 g_free(opt->value.stringval);
207 case WTAP_OPTTYPE_CUSTOM:
208 opttype->free_func(opt->value.customval.data);
209 g_free(opt->value.customval.data);
217 static void wtap_block_free_options(wtap_block_t block)
222 for (i = 0; i < block->options->len; i++) {
223 opt = &g_array_index(block->options, wtap_option_t, i);
224 wtap_block_free_option(block, opt);
228 void wtap_block_free(wtap_block_t block)
232 if (block->info->free_mand != NULL)
233 block->info->free_mand(block);
235 g_free(block->mandatory_data);
236 wtap_block_free_options(block);
237 g_array_free(block->options, TRUE);
242 void wtap_block_array_free(GArray* block_array)
246 if (block_array == NULL)
249 for (block = 0; block < block_array->len; block++) {
250 wtap_block_free(g_array_index(block_array, wtap_block_t, block));
252 g_array_free(block_array, TRUE);
256 * Make a copy of a block.
259 wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block)
262 wtap_option_t *src_opt;
263 wtap_opttype_t *opttype;
266 * Copy the mandatory data.
268 if (dest_block->info->copy_mand != NULL)
269 dest_block->info->copy_mand(dest_block, src_block);
271 /* Copy the options. For now, don't remove any options that are in destination
274 for (i = 0; i < src_block->options->len; i++)
276 src_opt = &g_array_index(src_block->options, wtap_option_t, i);
277 opttype = &g_array_index(src_block->info->options, wtap_opttype_t, src_opt->option_id);
279 switch(opttype->data_type) {
281 case WTAP_OPTTYPE_UINT8:
282 wtap_block_add_uint8_option(dest_block, src_opt->option_id, src_opt->value.uint8val);
285 case WTAP_OPTTYPE_UINT64:
286 wtap_block_add_uint64_option(dest_block, src_opt->option_id, src_opt->value.uint64val);
289 case WTAP_OPTTYPE_IPv4:
290 wtap_block_add_ipv4_option(dest_block, src_opt->option_id, src_opt->value.ipv4val);
293 case WTAP_OPTTYPE_IPv6:
294 wtap_block_add_ipv6_option(dest_block, src_opt->option_id, &src_opt->value.ipv6val);
297 case WTAP_OPTTYPE_STRING:
298 wtap_block_add_string_option(dest_block, src_opt->option_id, src_opt->value.stringval, strlen(src_opt->value.stringval));
301 case WTAP_OPTTYPE_CUSTOM:
302 wtap_block_add_custom_option(dest_block, src_opt->option_id, src_opt->value.customval.data, src_opt->value.customval.size);
308 void wtap_block_foreach_option(wtap_block_t block, wtap_block_foreach_func func, void* user_data)
312 wtap_opttype_t *opttype;
314 for (i = 0; i < block->options->len; i++) {
315 opt = &g_array_index(block->options, wtap_option_t, i);
316 opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id);
317 func(block, opt->option_id, opttype->data_type, &opt->value, user_data);
321 static wtap_opttype_return_val
322 wtap_block_add_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, wtap_option_t **optp)
325 wtap_opttype_t *opttype;
328 if (option_id >= block->info->options->len) {
329 /* There's no option for this block with that option ID */
330 return WTAP_OPTTYPE_NO_SUCH_OPTION;
332 opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
335 * Is this an option of the specified data type?
337 if (opttype->data_type != type) {
341 return WTAP_OPTTYPE_TYPE_MISMATCH;
345 * Can there be more than one instance of this option?
347 if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
349 * No. Is there already an instance of this option?
351 if (wtap_block_get_option(block, option_id) != NULL) {
355 return WTAP_OPTTYPE_ALREADY_EXISTS;
362 i = block->options->len;
363 g_array_set_size(block->options, i + 1);
364 opt = &g_array_index(block->options, wtap_option_t, i);
365 opt->option_id = option_id;
367 return WTAP_OPTTYPE_SUCCESS;
370 static wtap_opttype_return_val
371 wtap_block_get_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, wtap_optval_t **optvalp)
373 wtap_opttype_t *opttype;
374 wtap_optval_t *optval;
376 if (option_id >= block->info->options->len) {
377 /* There's no option for this block with that option ID */
378 return WTAP_OPTTYPE_NO_SUCH_OPTION;
381 opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
384 * Is this an option of the specified data type?
386 if (opttype->data_type != type) {
390 return WTAP_OPTTYPE_TYPE_MISMATCH;
394 * Can there be more than one instance of this option?
396 if (opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED) {
398 * Yes. You can't ask for "the" value.
400 return WTAP_OPTTYPE_NUMBER_MISMATCH;
403 optval = wtap_block_get_option(block, option_id);
404 if (optval == NULL) {
405 /* Didn't find the option */
406 return WTAP_OPTTYPE_NOT_FOUND;
410 return WTAP_OPTTYPE_SUCCESS;
413 static wtap_opttype_return_val
414 wtap_block_get_nth_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, guint idx, wtap_optval_t **optvalp)
416 wtap_opttype_t *opttype;
417 wtap_optval_t *optval;
419 if (option_id >= block->info->options->len) {
420 /* There's no option for this block with that option ID */
421 return WTAP_OPTTYPE_NO_SUCH_OPTION;
424 opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
427 * Is this an option of the specified data type?
429 if (opttype->data_type != type) {
433 return WTAP_OPTTYPE_TYPE_MISMATCH;
437 * Can there be more than one instance of this option?
439 if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
443 return WTAP_OPTTYPE_NUMBER_MISMATCH;
446 optval = wtap_block_get_nth_option(block, option_id, idx);
447 if (optval == NULL) {
448 /* Didn't find the option */
449 return WTAP_OPTTYPE_NOT_FOUND;
453 return WTAP_OPTTYPE_SUCCESS;
456 wtap_opttype_return_val
457 wtap_block_add_uint8_option(wtap_block_t block, guint option_id, guint8 value)
459 wtap_opttype_return_val ret;
462 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &opt);
463 if (ret != WTAP_OPTTYPE_SUCCESS)
465 opt->value.uint8val = value;
466 return WTAP_OPTTYPE_SUCCESS;
469 wtap_opttype_return_val
470 wtap_block_set_uint8_option_value(wtap_block_t block, guint option_id, guint8 value)
472 wtap_opttype_return_val ret;
473 wtap_optval_t *optval;
475 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &optval);
476 if (ret != WTAP_OPTTYPE_SUCCESS)
478 optval->uint8val = value;
479 return WTAP_OPTTYPE_SUCCESS;
482 wtap_opttype_return_val
483 wtap_block_get_uint8_option_value(wtap_block_t block, guint option_id, guint8* value)
485 wtap_opttype_return_val ret;
486 wtap_optval_t *optval;
488 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &optval);
489 if (ret != WTAP_OPTTYPE_SUCCESS)
491 *value = optval->uint8val;
492 return WTAP_OPTTYPE_SUCCESS;
495 wtap_opttype_return_val
496 wtap_block_add_uint64_option(wtap_block_t block, guint option_id, guint64 value)
498 wtap_opttype_return_val ret;
501 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &opt);
502 if (ret != WTAP_OPTTYPE_SUCCESS)
504 opt->value.uint64val = value;
505 return WTAP_OPTTYPE_SUCCESS;
508 wtap_opttype_return_val
509 wtap_block_set_uint64_option_value(wtap_block_t block, guint option_id, guint64 value)
511 wtap_opttype_return_val ret;
512 wtap_optval_t *optval;
514 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &optval);
515 if (ret != WTAP_OPTTYPE_SUCCESS)
517 optval->uint64val = value;
518 return WTAP_OPTTYPE_SUCCESS;
521 wtap_opttype_return_val
522 wtap_block_get_uint64_option_value(wtap_block_t block, guint option_id, guint64 *value)
524 wtap_opttype_return_val ret;
525 wtap_optval_t *optval;
527 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &optval);
528 if (ret != WTAP_OPTTYPE_SUCCESS)
530 *value = optval->uint64val;
531 return WTAP_OPTTYPE_SUCCESS;
534 wtap_opttype_return_val
535 wtap_block_add_ipv4_option(wtap_block_t block, guint option_id, guint32 value)
537 wtap_opttype_return_val ret;
540 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &opt);
541 if (ret != WTAP_OPTTYPE_SUCCESS)
543 opt->value.ipv4val = value;
544 return WTAP_OPTTYPE_SUCCESS;
547 wtap_opttype_return_val
548 wtap_block_set_ipv4_option_value(wtap_block_t block, guint option_id, guint32 value)
550 wtap_opttype_return_val ret;
551 wtap_optval_t *optval;
553 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
554 if (ret != WTAP_OPTTYPE_SUCCESS)
556 optval->ipv4val = value;
557 return WTAP_OPTTYPE_SUCCESS;
560 wtap_opttype_return_val
561 wtap_block_get_ipv4_option_value(wtap_block_t block, guint option_id, guint32* value)
563 wtap_opttype_return_val ret;
564 wtap_optval_t *optval;
566 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
567 if (ret != WTAP_OPTTYPE_SUCCESS)
569 *value = optval->ipv4val;
570 return WTAP_OPTTYPE_SUCCESS;
573 wtap_opttype_return_val
574 wtap_block_add_ipv6_option(wtap_block_t block, guint option_id, ws_in6_addr *value)
576 wtap_opttype_return_val ret;
579 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &opt);
580 if (ret != WTAP_OPTTYPE_SUCCESS)
582 opt->value.ipv6val = *value;
583 return WTAP_OPTTYPE_SUCCESS;
586 wtap_opttype_return_val
587 wtap_block_set_ipv6_option_value(wtap_block_t block, guint option_id, ws_in6_addr *value)
589 wtap_opttype_return_val ret;
590 wtap_optval_t *optval;
592 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &optval);
593 if (ret != WTAP_OPTTYPE_SUCCESS)
595 optval->ipv6val = *value;
596 return WTAP_OPTTYPE_SUCCESS;
599 wtap_opttype_return_val
600 wtap_block_get_ipv6_option_value(wtap_block_t block, guint option_id, ws_in6_addr* value)
602 wtap_opttype_return_val ret;
603 wtap_optval_t *optval;
605 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
606 if (ret != WTAP_OPTTYPE_SUCCESS)
608 *value = optval->ipv6val;
609 return WTAP_OPTTYPE_SUCCESS;
612 wtap_opttype_return_val
613 wtap_block_add_string_option(wtap_block_t block, guint option_id, const char *value, gsize value_length)
615 wtap_opttype_return_val ret;
618 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
619 if (ret != WTAP_OPTTYPE_SUCCESS)
621 opt->value.stringval = g_strndup(value, value_length);
622 return WTAP_OPTTYPE_SUCCESS;
625 static wtap_opttype_return_val
626 wtap_block_add_string_option_vformat(wtap_block_t block, guint option_id, const char *format, va_list va)
628 wtap_opttype_return_val ret;
631 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
632 if (ret != WTAP_OPTTYPE_SUCCESS)
634 opt->value.stringval = g_strdup_vprintf(format, va);
635 return WTAP_OPTTYPE_SUCCESS;
638 wtap_opttype_return_val
639 wtap_block_add_string_option_format(wtap_block_t block, guint option_id, const char *format, ...)
641 wtap_opttype_return_val ret;
645 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
646 if (ret != WTAP_OPTTYPE_SUCCESS)
648 va_start(va, format);
649 opt->value.stringval = g_strdup_vprintf(format, va);
651 return WTAP_OPTTYPE_SUCCESS;
654 wtap_opttype_return_val
655 wtap_block_set_string_option_value(wtap_block_t block, guint option_id, const char *value, size_t value_length)
657 wtap_opttype_return_val ret;
658 wtap_optval_t *optval;
660 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
661 if (ret != WTAP_OPTTYPE_SUCCESS) {
662 if (ret == WTAP_OPTTYPE_NOT_FOUND) {
664 * There's no instance to set, so just try to create a new one
667 return wtap_block_add_string_option(block, option_id, value, value_length);
669 /* Otherwise fail. */
672 g_free(optval->stringval);
673 optval->stringval = g_strndup(value, value_length);
674 return WTAP_OPTTYPE_SUCCESS;
677 wtap_opttype_return_val
678 wtap_block_set_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, const char *value, size_t value_length)
680 wtap_opttype_return_val ret;
681 wtap_optval_t *optval;
683 ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
684 if (ret != WTAP_OPTTYPE_SUCCESS)
686 g_free(optval->stringval);
687 optval->stringval = g_strndup(value, value_length);
688 return WTAP_OPTTYPE_SUCCESS;
691 wtap_opttype_return_val
692 wtap_block_set_string_option_value_format(wtap_block_t block, guint option_id, const char *format, ...)
694 wtap_opttype_return_val ret;
695 wtap_optval_t *optval;
698 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
699 if (ret != WTAP_OPTTYPE_SUCCESS) {
700 if (ret == WTAP_OPTTYPE_NOT_FOUND) {
702 * There's no instance to set, so just try to create a new one
703 * with the formatted string.
705 va_start(va, format);
706 ret = wtap_block_add_string_option_vformat(block, option_id, format, va);
710 /* Otherwise fail. */
713 g_free(optval->stringval);
714 va_start(va, format);
715 optval->stringval = g_strdup_vprintf(format, va);
717 return WTAP_OPTTYPE_SUCCESS;
720 wtap_opttype_return_val
721 wtap_block_get_string_option_value(wtap_block_t block, guint option_id, char** value)
723 wtap_opttype_return_val ret;
724 wtap_optval_t *optval;
726 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
727 if (ret != WTAP_OPTTYPE_SUCCESS)
729 *value = optval->stringval;
730 return WTAP_OPTTYPE_SUCCESS;
733 wtap_opttype_return_val
734 wtap_block_get_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, char** value)
736 wtap_opttype_return_val ret;
737 wtap_optval_t *optval;
739 ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
740 if (ret != WTAP_OPTTYPE_SUCCESS)
742 *value = optval->stringval;
743 return WTAP_OPTTYPE_SUCCESS;
746 wtap_opttype_return_val
747 wtap_block_add_custom_option(wtap_block_t block, guint option_id, void *value, size_t value_size)
749 wtap_opttype_return_val ret;
751 wtap_opttype_t *opttype;
753 ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &opt);
754 if (ret != WTAP_OPTTYPE_SUCCESS)
756 opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id);
757 opt->value.customval.size = (guint)value_size;
758 opt->value.customval.data = opttype->dup_func(value);
759 return WTAP_OPTTYPE_SUCCESS;
762 wtap_opttype_return_val
763 wtap_block_get_custom_option_value(wtap_block_t block, guint option_id, void** value)
765 wtap_opttype_return_val ret;
766 wtap_optval_t *optval;
768 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &optval);
769 if (ret != WTAP_OPTTYPE_SUCCESS)
771 *value = optval->customval.data;
772 return WTAP_OPTTYPE_SUCCESS;
775 wtap_opttype_return_val
776 wtap_block_set_custom_option_value(wtap_block_t block, guint option_id, void *value)
778 wtap_opttype_return_val ret;
779 wtap_optval_t *optval;
782 ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &optval);
783 if (ret != WTAP_OPTTYPE_SUCCESS)
785 prev_value = optval->customval.data;
787 * XXX - a custom value can be a structure that points to other data,
788 * but we're doing a shallow copy here.
790 optval->customval.data = g_memdup(value, optval->customval.size);
791 /* Free after memory is duplicated in case structure was manipulated with a "get then set" */
794 return WTAP_OPTTYPE_SUCCESS;
797 wtap_opttype_return_val
798 wtap_block_remove_option(wtap_block_t block, guint option_id)
800 wtap_opttype_t *opttype;
804 if (option_id >= block->info->options->len) {
805 /* There's no option for this block with that option ID */
806 return WTAP_OPTTYPE_NO_SUCH_OPTION;
809 opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
812 * Can there be more than one instance of this option?
814 if (opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED) {
816 * Yes. You can't remove "the" value.
818 return WTAP_OPTTYPE_NUMBER_MISMATCH;
821 for (i = 0; i < block->options->len; i++) {
822 opt = &g_array_index(block->options, wtap_option_t, i);
823 if (opt->option_id == option_id) {
824 /* Found it - free up the value */
825 wtap_block_free_option(block, opt);
826 /* Remove the option from the array of options */
827 g_array_remove_index(block->options, i);
828 return WTAP_OPTTYPE_SUCCESS;
832 /* Didn't find the option */
833 return WTAP_OPTTYPE_NOT_FOUND;
836 wtap_opttype_return_val
837 wtap_block_remove_nth_option_instance(wtap_block_t block, guint option_id,
840 wtap_opttype_t *opttype;
845 if (option_id >= block->info->options->len) {
846 /* There's no option for this block with that option ID */
847 return WTAP_OPTTYPE_NO_SUCH_OPTION;
850 opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
853 * Can there be more than one instance of this option?
855 if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
859 return WTAP_OPTTYPE_NUMBER_MISMATCH;
863 for (i = 0; i < block->options->len; i++) {
864 opt = &g_array_index(block->options, wtap_option_t, i);
865 if (opt->option_id == option_id) {
866 if (opt_idx == idx) {
867 /* Found it - free up the value */
868 wtap_block_free_option(block, opt);
869 /* Remove the option from the array of options */
870 g_array_remove_index(block->options, i);
871 return WTAP_OPTTYPE_SUCCESS;
877 /* Didn't find the option */
878 return WTAP_OPTTYPE_NOT_FOUND;
881 static void shb_create(wtap_block_t block)
883 wtapng_mandatory_section_t* section_mand = g_new(wtapng_mandatory_section_t, 1);
885 section_mand->section_length = -1;
887 block->mandatory_data = section_mand;
890 static void shb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
892 memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t));
895 static void nrb_create(wtap_block_t block)
897 block->mandatory_data = NULL;
900 static void isb_create(wtap_block_t block)
902 block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1);
905 static void isb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
907 memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t));
910 static void *idb_filter_dup(void* src)
912 wtapng_if_descr_filter_t* filter_src = (wtapng_if_descr_filter_t*)src;
913 wtapng_if_descr_filter_t* filter_dest;
916 filter_dest = g_new(wtapng_if_descr_filter_t, 1);
917 filter_dest->if_filter_str = g_strdup(filter_src->if_filter_str);
918 filter_dest->bpf_filter_len = filter_src->bpf_filter_len;
919 filter_dest->if_filter_bpf_bytes = (guint8 *)g_memdup(filter_src->if_filter_bpf_bytes, filter_src->bpf_filter_len);
920 return (void *)filter_dest;
923 static void idb_filter_free(void* data)
925 wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)data;
926 g_free(filter->if_filter_str);
927 g_free(filter->if_filter_bpf_bytes);
930 static void idb_create(wtap_block_t block)
932 block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1);
935 static void idb_free_mand(wtap_block_t block)
938 wtap_block_t if_stats;
939 wtapng_if_descr_mandatory_t* mand = (wtapng_if_descr_mandatory_t*)block->mandatory_data;
941 for(j = 0; j < mand->num_stat_entries; j++) {
942 if_stats = g_array_index(mand->interface_statistics, wtap_block_t, j);
943 wtap_block_free(if_stats);
946 if (mand->interface_statistics)
947 g_array_free(mand->interface_statistics, TRUE);
950 static void idb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
953 wtap_block_t src_if_stats, dest_if_stats;
954 wtapng_if_descr_mandatory_t *src_mand = (wtapng_if_descr_mandatory_t*)src_block->mandatory_data,
955 *dest_mand = (wtapng_if_descr_mandatory_t*)dest_block->mandatory_data;
957 /* Need special consideration for copying of the interface_statistics member */
958 if (dest_mand->num_stat_entries != 0)
959 g_array_free(dest_mand->interface_statistics, TRUE);
961 memcpy(dest_mand, src_mand, sizeof(wtapng_if_descr_mandatory_t));
962 if (src_mand->num_stat_entries != 0)
964 dest_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
965 for (j = 0; j < src_mand->num_stat_entries; j++)
967 src_if_stats = g_array_index(src_mand->interface_statistics, wtap_block_t, j);
968 dest_if_stats = wtap_block_create(WTAP_BLOCK_IF_STATS);
969 wtap_block_copy(dest_if_stats, src_if_stats);
970 dest_mand->interface_statistics = g_array_append_val(dest_mand->interface_statistics, dest_if_stats);
975 void wtap_opttypes_initialize(void)
977 static wtap_blocktype_t shb_block = {
978 WTAP_BLOCK_NG_SECTION, /* block_type */
980 "Section Header Block", /* description */
981 shb_create, /* create */
982 NULL, /* free_mand */
983 shb_copy_mand, /* copy_mand */
986 static wtap_opttype_t shb_hardware = {
994 static wtap_opttype_t shb_os = {
996 "SHB Operating System",
1002 static wtap_opttype_t shb_userappl = {
1004 "SHB User Application",
1005 WTAP_OPTTYPE_STRING,
1011 static wtap_blocktype_t idb_block = {
1012 WTAP_BLOCK_IF_DESCR, /* block_type */
1014 "Interface Description Block", /* description */
1015 idb_create, /* create */
1016 idb_free_mand, /* free_mand */
1017 idb_copy_mand, /* copy_mand */
1020 static wtap_opttype_t if_name = {
1023 WTAP_OPTTYPE_STRING,
1028 static wtap_opttype_t if_description = {
1031 WTAP_OPTTYPE_STRING,
1036 static wtap_opttype_t if_speed = {
1039 WTAP_OPTTYPE_UINT64,
1044 static wtap_opttype_t if_tsresol = {
1046 "IDB Time Stamp Resolution",
1047 WTAP_OPTTYPE_UINT8, /* XXX - signed? */
1052 static wtap_opttype_t if_filter = {
1055 WTAP_OPTTYPE_CUSTOM,
1060 static wtap_opttype_t if_os = {
1062 "IDB Operating System",
1063 WTAP_OPTTYPE_STRING,
1068 static wtap_opttype_t if_fcslen = {
1076 static wtap_opttype_t if_hardware = {
1079 WTAP_OPTTYPE_STRING,
1085 static wtap_blocktype_t nrb_block = {
1086 WTAP_BLOCK_NG_NRB, /* block_type */
1088 "Name Resolution Block", /* description */
1089 nrb_create, /* create */
1090 NULL, /* free_mand */
1091 NULL, /* copy_mand */
1094 static wtap_opttype_t ns_dnsname = {
1096 "NRB DNS server name",
1097 WTAP_OPTTYPE_STRING,
1102 static wtap_opttype_t ns_dnsIP4addr = {
1104 "NRB DNS server IPv4 address",
1110 static wtap_opttype_t ns_dnsIP6addr = {
1112 "NRB DNS server IPv6 address",
1119 static wtap_blocktype_t isb_block = {
1120 WTAP_BLOCK_IF_STATS, /* block_type */
1122 "Interface Statistics Block", /* description */
1123 isb_create, /* create */
1124 NULL, /* free_mand */
1125 isb_copy_mand, /* copy_mand */
1128 static wtap_opttype_t isb_starttime = {
1131 WTAP_OPTTYPE_UINT64,
1136 static wtap_opttype_t isb_endtime = {
1139 WTAP_OPTTYPE_UINT64,
1144 static wtap_opttype_t isb_ifrecv = {
1146 "ISB Received Packets",
1147 WTAP_OPTTYPE_UINT64,
1152 static wtap_opttype_t isb_ifdrop = {
1154 "ISB Dropped Packets",
1155 WTAP_OPTTYPE_UINT64,
1160 static wtap_opttype_t isb_filteraccept = {
1162 "ISB Packets Accepted By Filter",
1163 WTAP_OPTTYPE_UINT64,
1168 static wtap_opttype_t isb_osdrop = {
1170 "ISB Packets Dropped By The OS",
1171 WTAP_OPTTYPE_UINT64,
1176 static wtap_opttype_t isb_usrdeliv = {
1178 "ISB Packets Delivered To The User",
1179 WTAP_OPTTYPE_UINT64,
1185 /* Initialize the custom block array. This is for future proofing
1186 "outside registered" block types (for NULL checking) */
1187 memset(blocktype_list, 0, MAX_WTAP_BLOCK_TYPE_VALUE*sizeof(wtap_blocktype_t*));
1188 num_custom_blocks = 0;
1191 * Register the SHB and the options that can appear in it.
1193 wtap_opttype_block_register(WTAP_BLOCK_NG_SECTION, &shb_block);
1194 wtap_opttype_option_register(&shb_block, OPT_SHB_HARDWARE, &shb_hardware);
1195 wtap_opttype_option_register(&shb_block, OPT_SHB_OS, &shb_os);
1196 wtap_opttype_option_register(&shb_block, OPT_SHB_USERAPPL, &shb_userappl);
1199 * Register the IDB and the options that can appear in it.
1201 wtap_opttype_block_register(WTAP_BLOCK_IF_DESCR, &idb_block);
1202 wtap_opttype_option_register(&idb_block, OPT_IDB_NAME, &if_name);
1203 wtap_opttype_option_register(&idb_block, OPT_IDB_DESCR, &if_description);
1204 wtap_opttype_option_register(&idb_block, OPT_IDB_SPEED, &if_speed);
1205 wtap_opttype_option_register(&idb_block, OPT_IDB_TSRESOL, &if_tsresol);
1206 wtap_opttype_option_register(&idb_block, OPT_IDB_FILTER, &if_filter);
1207 wtap_opttype_option_register(&idb_block, OPT_IDB_OS, &if_os);
1208 wtap_opttype_option_register(&idb_block, OPT_IDB_FCSLEN, &if_fcslen);
1209 wtap_opttype_option_register(&idb_block, OPT_IDB_HARDWARE, &if_hardware);
1212 * Register the NRB and the options that can appear in it.
1214 wtap_opttype_block_register(WTAP_BLOCK_NG_NRB, &nrb_block);
1215 wtap_opttype_option_register(&nrb_block, OPT_NS_DNSNAME, &ns_dnsname);
1216 wtap_opttype_option_register(&nrb_block, OPT_NS_DNSIP4ADDR, &ns_dnsIP4addr);
1217 wtap_opttype_option_register(&nrb_block, OPT_NS_DNSIP6ADDR, &ns_dnsIP6addr);
1220 * Register the ISB and the options that can appear in it.
1222 wtap_opttype_block_register(WTAP_BLOCK_IF_STATS, &isb_block);
1223 wtap_opttype_option_register(&isb_block, OPT_ISB_STARTTIME, &isb_starttime);
1224 wtap_opttype_option_register(&isb_block, OPT_ISB_ENDTIME, &isb_endtime);
1225 wtap_opttype_option_register(&isb_block, OPT_ISB_IFRECV, &isb_ifrecv);
1226 wtap_opttype_option_register(&isb_block, OPT_ISB_IFDROP, &isb_ifdrop);
1227 wtap_opttype_option_register(&isb_block, OPT_ISB_FILTERACCEPT, &isb_filteraccept);
1228 wtap_opttype_option_register(&isb_block, OPT_ISB_OSDROP, &isb_osdrop);
1229 wtap_opttype_option_register(&isb_block, OPT_ISB_USRDELIV, &isb_usrdeliv);
1232 void wtap_opttypes_cleanup(void)
1236 for (block_type = 0; block_type < (WTAP_BLOCK_END_OF_LIST+num_custom_blocks); block_type++) {
1237 if (blocktype_list[block_type]) {
1238 if (blocktype_list[block_type]->options)
1239 g_array_free(blocktype_list[block_type]->options, TRUE);
1240 blocktype_list[block_type] = NULL;