Remove Makefile.common files
[metze/wireshark/wip.git] / wiretap / wtap_opttypes.c
1 /* wtap_opttypes.c
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 2001 Gerald Combs
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 #include "config.h"
22
23 #include <glib.h>
24 #include <string.h>
25
26 #include "wtap.h"
27 #include "wtap_opttypes.h"
28 #include "wtap-int.h"
29 #include "pcapng.h"
30 #include "pcapng_module.h"
31
32 #if 0
33 #define wtap_debug(...) g_warning(__VA_ARGS__)
34 #else
35 #define wtap_debug(...)
36 #endif
37
38 typedef struct wtap_opt_register
39 {
40     const char *name;                /**< name of block */
41     const char *description;         /**< human-readable description of block */
42     wtap_block_create_func create;
43     wtap_mand_free_func free_mand;
44     wtap_mand_copy_func copy_mand;
45 } wtap_opt_register_t;
46
47 typedef struct wtap_optblock_internal {
48     const char *name;                /**< name of option */
49     const char *description;         /**< human-readable description of option */
50     guint number;                    /**< Option index */
51     wtap_opttype_e type;             /**< type of that option */
52 } wtap_optblock_internal_t;
53
54 typedef struct wtap_optblock_value {
55     wtap_optblock_internal_t* info;
56     wtap_option_type option;         /**< pointer to variable storing the value */
57     wtap_option_type default_val;    /**< the default value of the option */
58 } wtap_optblock_value_t;
59
60 struct wtap_optionblock
61 {
62     wtap_opt_register_t* info;
63     void* mandatory_data;
64     GArray* option_infos; /* Only want to keep 1 copy of "static" option information */
65     GArray* option_values;
66 };
67
68 #define MAX_WTAP_OPTION_BLOCK_CUSTOM    10
69 #define MAX_WTAP_OPTION_BLOCK_TYPE_VALUE (WTAP_OPTION_BLOCK_END_OF_LIST+MAX_WTAP_OPTION_BLOCK_CUSTOM)
70
71 /* Keep track of wtap_opt_register_t's via their id number */
72 static wtap_opt_register_t* block_list[MAX_WTAP_OPTION_BLOCK_TYPE_VALUE];
73 static guint num_custom_blocks;
74 static wtap_opt_register_t custom_block_list[MAX_WTAP_OPTION_BLOCK_CUSTOM];
75
76 static void wtap_opttype_block_register(int block_type, wtap_opt_register_t *block)
77 {
78     /* Check input */
79     g_assert(block_type < WTAP_OPTION_BLOCK_END_OF_LIST);
80
81     /* Don't re-register. */
82     g_assert(block_list[block_type] == NULL);
83
84     /* Sanity check */
85     g_assert(block->name);
86     g_assert(block->description);
87     g_assert(block->create);
88
89     block_list[block_type] = block;
90 }
91
92 int wtap_opttype_register_custom_block_type(const char* name, const char* description, wtap_block_create_func create,
93                                                 wtap_mand_free_func free_mand, wtap_mand_copy_func copy_mand)
94 {
95     int block_type;
96
97     /* Ensure valid data/functions for required fields */
98     g_assert(name);
99     g_assert(description);
100     g_assert(create);
101
102     /* This shouldn't happen, so flag it for fixing */
103     g_assert(num_custom_blocks < MAX_WTAP_OPTION_BLOCK_CUSTOM);
104
105     block_type = WTAP_OPTION_BLOCK_END_OF_LIST+num_custom_blocks;
106
107     custom_block_list[num_custom_blocks].name = name;
108     custom_block_list[num_custom_blocks].description = description;
109     custom_block_list[num_custom_blocks].create = create;
110     custom_block_list[num_custom_blocks].free_mand = free_mand;
111     custom_block_list[num_custom_blocks].copy_mand = copy_mand;
112     block_list[block_type] = &custom_block_list[num_custom_blocks];
113
114     num_custom_blocks++;
115     return block_type;
116 }
117
118 void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block)
119 {
120     return block->mandatory_data;
121 }
122
123 static wtap_optblock_value_t* wtap_optionblock_get_option(wtap_optionblock_t block, guint option_id)
124 {
125     guint i;
126     wtap_optblock_value_t* opttype = NULL;
127
128     for (i = 0; i < block->option_values->len; i++)
129     {
130         opttype = g_array_index(block->option_values, wtap_optblock_value_t*, i);
131         if (opttype->info->number == option_id)
132             return opttype;
133     }
134
135     return NULL;
136 }
137
138 wtap_optionblock_t wtap_optionblock_create(int block_type)
139 {
140     wtap_optionblock_t block;
141
142     if (block_type >= (int)(WTAP_OPTION_BLOCK_END_OF_LIST+num_custom_blocks))
143         return NULL;
144
145     block = g_new(struct wtap_optionblock, 1);
146     block->info = block_list[block_type];
147     block->option_infos = g_array_new(FALSE, FALSE, sizeof(wtap_optblock_internal_t*));
148     block->option_values = g_array_new(FALSE, FALSE, sizeof(wtap_optblock_value_t*));
149     block->info->create(block);
150
151     return block;
152 }
153
154 static void wtap_optionblock_free_options(wtap_optionblock_t block)
155 {
156     guint i;
157     wtap_optblock_value_t* opttype = NULL;
158
159     for (i = 0; i < block->option_values->len; i++) {
160         opttype = g_array_index(block->option_values, wtap_optblock_value_t*, i);
161         switch(opttype->info->type)
162         {
163         case WTAP_OPTTYPE_STRING:
164             g_free(opttype->option.stringval);
165             break;
166         case WTAP_OPTTYPE_CUSTOM:
167             opttype->option.customval.free_func(opttype->option.customval.data);
168             g_free(opttype->option.customval.data);
169             opttype->default_val.customval.free_func(opttype->default_val.customval.data);
170             g_free(opttype->default_val.customval.data);
171             break;
172         default:
173             break;
174         }
175         g_free(opttype);
176     }
177 }
178
179 void wtap_optionblock_free(wtap_optionblock_t block)
180 {
181     unsigned i;
182     if (block != NULL)
183     {
184         if (block->info->free_mand != NULL)
185             block->info->free_mand(block);
186
187         g_free(block->mandatory_data);
188         wtap_optionblock_free_options(block);
189         for (i = 0; i < block->option_infos->len; i++)
190             g_free(g_array_index(block->option_infos, wtap_optblock_internal_t*, i));
191         if (block->option_infos != NULL)
192             g_array_free(block->option_infos, TRUE);
193         if (block->option_values != NULL)
194             g_array_free(block->option_values, TRUE);
195         g_free(block);
196     }
197 }
198
199 void wtap_optionblock_array_free(GArray* block_array)
200 {
201     guint block;
202     if (block_array == NULL)
203         return;
204
205     for (block = 0; block < block_array->len; block++) {
206         wtap_optionblock_free(g_array_index(block_array, wtap_optionblock_t, block));
207     }
208     g_array_free(block_array, TRUE);
209 }
210
211 void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
212 {
213     guint i;
214     wtap_optblock_internal_t *src_internal;
215     wtap_optblock_value_t *dest_value, *src_value;
216
217     if (dest_block->info->copy_mand != NULL)
218         dest_block->info->copy_mand(dest_block, src_block);
219
220     /* Copy the options.  For now, don't remove any options that are in destination
221      * but not source.
222      */
223     for (i = 0; i < src_block->option_values->len; i++)
224     {
225         src_internal = g_array_index(src_block->option_infos, wtap_optblock_internal_t*, i);
226         src_value = g_array_index(src_block->option_values, wtap_optblock_value_t*, i);
227         dest_value = wtap_optionblock_get_option(dest_block, src_internal->number);
228         if (dest_value == NULL)
229         {
230             wtap_optblock_reg_t reg_optblock;
231
232             reg_optblock.name = src_internal->name;
233             reg_optblock.description = src_internal->description;
234             reg_optblock.type = src_internal->type;
235             reg_optblock.option = src_value->option;
236             reg_optblock.default_val = src_value->default_val;
237
238             wtap_optionblock_add_option(dest_block, src_internal->number, &reg_optblock);
239         }
240         else
241         {
242             /* Option exists, replace it */
243             switch(src_internal->type)
244             {
245             case WTAP_OPTTYPE_UINT8:
246                 dest_value->option.uint8val = src_value->option.uint8val;
247                 break;
248             case WTAP_OPTTYPE_UINT64:
249                 dest_value->option.uint64val = src_value->option.uint64val;
250                 break;
251             case WTAP_OPTTYPE_STRING:
252                 g_free(dest_value->option.stringval);
253                 dest_value->option.stringval = g_strdup(src_value->option.stringval);
254                 break;
255             case WTAP_OPTTYPE_CUSTOM:
256                 dest_value->option.customval.free_func(dest_value->option.customval.data);
257                 g_free(dest_value->option.customval.data);
258                 dest_value->option.customval.data = g_memdup(src_value->option.customval.data, src_value->option.customval.size);
259                 break;
260             }
261         }
262     }
263 }
264
265 void wtap_optionblock_foreach_option(wtap_optionblock_t block, wtap_optionblock_foreach_func func, void* user_data)
266 {
267     guint i;
268     wtap_optblock_internal_t *internal_data;
269     wtap_optblock_value_t *value;
270
271     for (i = 0; i < block->option_values->len; i++)
272     {
273         internal_data = g_array_index(block->option_infos, wtap_optblock_internal_t*, i);
274         value = g_array_index(block->option_values, wtap_optblock_value_t*, i);
275         func(block, internal_data->number, value->info->type, &value->option, user_data);
276     }
277 }
278
279 wtap_opttype_return_val wtap_optionblock_add_option(wtap_optionblock_t block, guint option_id, wtap_optblock_reg_t* option)
280 {
281     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
282     wtap_optblock_internal_t *opt_internal;
283
284     /* Option already exists */
285     if (opt_value != NULL)
286         return WTAP_OPTTYPE_ALREADY_EXISTS;
287
288     opt_value = g_new0(wtap_optblock_value_t, 1);
289     opt_internal = g_new(wtap_optblock_internal_t, 1);
290
291     opt_internal->name = option->name;
292     opt_internal->description = option->description;
293     opt_internal->number = option_id;
294     opt_internal->type = option->type;
295
296     opt_value->info = opt_internal;
297
298     switch(option->type)
299     {
300     case WTAP_OPTTYPE_UINT8:
301         opt_value->option.uint8val = option->option.uint8val;
302         opt_value->default_val.uint8val = option->default_val.uint8val;
303         break;
304     case WTAP_OPTTYPE_UINT64:
305         opt_value->option.uint64val = option->option.uint64val;
306         opt_value->default_val.uint64val = option->default_val.uint64val;
307         break;
308     case WTAP_OPTTYPE_STRING:
309         opt_value->option.stringval = g_strdup(option->option.stringval);
310         opt_value->default_val.stringval = option->default_val.stringval;
311         break;
312     case WTAP_OPTTYPE_CUSTOM:
313         opt_value->option.customval.size = option->option.customval.size;
314         opt_value->option.customval.data = g_memdup(option->option.customval.data, option->option.customval.size);
315         opt_value->option.customval.free_func = option->option.customval.free_func;
316         opt_value->default_val.customval.size = option->default_val.customval.size;
317         opt_value->default_val.customval.data = g_memdup(option->default_val.customval.data, option->default_val.customval.size);
318         opt_value->default_val.customval.free_func = option->default_val.customval.free_func;
319         break;
320     }
321
322     g_array_append_val(block->option_infos, opt_internal);
323     g_array_append_val(block->option_values, opt_value);
324     return WTAP_OPTTYPE_SUCCESS;
325 }
326
327 wtap_opttype_return_val wtap_optionblock_set_option_string(wtap_optionblock_t block, guint option_id, char* value, gsize value_length)
328 {
329     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
330
331     /* Didn't find the option */
332     if (opt_value == NULL)
333         return WTAP_OPTTYPE_NOT_FOUND;
334
335     if (opt_value->info->type != WTAP_OPTTYPE_STRING)
336         return WTAP_OPTTYPE_TYPE_MISMATCH;
337
338     g_free(opt_value->option.stringval);
339     opt_value->option.stringval = g_strndup(value, value_length);
340     return WTAP_OPTTYPE_SUCCESS;
341 }
342
343 wtap_opttype_return_val wtap_optionblock_set_option_string_format(wtap_optionblock_t block, guint option_id, const char *format, ...)
344 {
345     va_list va;
346     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
347
348     /* Didn't find the option */
349     if (opt_value == NULL)
350         return WTAP_OPTTYPE_NOT_FOUND;
351
352     if (opt_value->info->type != WTAP_OPTTYPE_STRING)
353         return WTAP_OPTTYPE_TYPE_MISMATCH;
354
355     g_free(opt_value->option.stringval);
356     va_start(va, format);
357     opt_value->option.stringval = g_strdup_vprintf(format, va);
358     va_end(va);
359     return WTAP_OPTTYPE_SUCCESS;
360 }
361
362 wtap_opttype_return_val wtap_optionblock_get_option_string(wtap_optionblock_t block, guint option_id, char** value)
363 {
364     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
365
366     /* Didn't find the option */
367     if (opt_value == NULL)
368         return WTAP_OPTTYPE_NOT_FOUND;
369
370     if (opt_value->info->type != WTAP_OPTTYPE_STRING)
371         return WTAP_OPTTYPE_TYPE_MISMATCH;
372
373     *value = opt_value->option.stringval;
374     return WTAP_OPTTYPE_SUCCESS;
375 }
376
377 wtap_opttype_return_val wtap_optionblock_get_string_options(wtap_optionblock_t block, guint option_id, GArray **value)
378 {
379     guint n_options;
380     guint i;
381     wtap_optblock_value_t* opt_value;
382     GArray *opt_values;
383
384     n_options = 0;
385     for (i = 0; i < block->option_values->len; i++)
386     {
387         opt_value = g_array_index(block->option_values, wtap_optblock_value_t*, i);
388         if (opt_value->info->number == option_id) {
389             if (opt_value->info->type != WTAP_OPTTYPE_STRING)
390                 return WTAP_OPTTYPE_TYPE_MISMATCH;
391             n_options++;
392         }
393     }
394
395     opt_values = g_array_sized_new(FALSE, FALSE, sizeof (char *), n_options);
396     for (i = 0; i < block->option_values->len; i++)
397     {
398         opt_value = g_array_index(block->option_values, wtap_optblock_value_t*, i);
399         if (opt_value->info->number == option_id)
400             g_array_append_val(opt_values, opt_value->option.stringval);
401     }
402
403     *value = opt_values;
404     return WTAP_OPTTYPE_SUCCESS;
405 }
406
407 wtap_opttype_return_val wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, guint64 value)
408 {
409     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
410
411     /* Didn't find the option */
412     if (opt_value == NULL)
413         return WTAP_OPTTYPE_NOT_FOUND;
414
415     if (opt_value->info->type != WTAP_OPTTYPE_UINT64)
416         return WTAP_OPTTYPE_TYPE_MISMATCH;
417
418     opt_value->option.uint64val = value;
419     return WTAP_OPTTYPE_SUCCESS;
420 }
421
422 wtap_opttype_return_val wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, guint64* value)
423 {
424     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
425
426     /* Didn't find the option */
427     if (opt_value == NULL)
428         return WTAP_OPTTYPE_NOT_FOUND;
429
430     if (opt_value->info->type != WTAP_OPTTYPE_UINT64)
431         return WTAP_OPTTYPE_TYPE_MISMATCH;
432
433     *value = opt_value->option.uint64val;
434     return WTAP_OPTTYPE_SUCCESS;
435 }
436
437
438 wtap_opttype_return_val wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, guint8 value)
439 {
440     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
441
442     /* Didn't find the option */
443     if (opt_value == NULL)
444         return WTAP_OPTTYPE_NOT_FOUND;
445
446     if (opt_value->info->type != WTAP_OPTTYPE_UINT8)
447         return WTAP_OPTTYPE_TYPE_MISMATCH;
448
449     opt_value->option.uint8val = value;
450     return WTAP_OPTTYPE_SUCCESS;
451 }
452
453 wtap_opttype_return_val wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, guint8* value)
454 {
455     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
456
457     /* Didn't find the option */
458     if (opt_value == NULL)
459         return WTAP_OPTTYPE_NOT_FOUND;
460
461     if (opt_value->info->type != WTAP_OPTTYPE_UINT8)
462         return WTAP_OPTTYPE_TYPE_MISMATCH;
463
464     *value = opt_value->option.uint8val;
465     return WTAP_OPTTYPE_SUCCESS;
466 }
467
468 wtap_opttype_return_val wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, void* value)
469 {
470     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
471     void* prev_value;
472
473     /* Didn't find the option */
474     if (opt_value == NULL)
475         return WTAP_OPTTYPE_NOT_FOUND;
476
477     if (opt_value->info->type != WTAP_OPTTYPE_CUSTOM)
478         return WTAP_OPTTYPE_TYPE_MISMATCH;
479
480     prev_value = opt_value->option.customval.data;
481     opt_value->option.customval.data = g_memdup(value, opt_value->option.customval.size);
482     /* Free after memory is duplicated in case structure was manipulated with a "get then set" */
483     g_free(prev_value);
484     return WTAP_OPTTYPE_SUCCESS;
485 }
486
487 wtap_opttype_return_val wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, void** value)
488 {
489     wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
490
491     /* Didn't find the option */
492     if (opt_value == NULL)
493         return WTAP_OPTTYPE_NOT_FOUND;
494
495     if (opt_value->info->type != WTAP_OPTTYPE_CUSTOM)
496         return WTAP_OPTTYPE_TYPE_MISMATCH;
497
498     *value = opt_value->option.customval.data;
499     return WTAP_OPTTYPE_SUCCESS;
500 }
501
502 static void shb_create(wtap_optionblock_t block)
503 {
504     static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
505     static wtap_optblock_reg_t hardware_option = {"hardware", "SBH Hardware", WTAP_OPTTYPE_STRING, {0}, {0}};
506     static wtap_optblock_reg_t os_option = {"os", "SBH Operating System", WTAP_OPTTYPE_STRING, {0}, {0}};
507     static wtap_optblock_reg_t user_appl_option = {"user_appl", "SBH User Application", WTAP_OPTTYPE_STRING, {0}, {0}};
508
509     wtapng_mandatory_section_t* section_mand = g_new(wtapng_mandatory_section_t, 1);
510
511     /* Set proper values for the union */
512     comment_option.option.stringval = NULL;
513     comment_option.default_val.stringval = NULL;
514     hardware_option.option.stringval = NULL;
515     hardware_option.default_val.stringval = NULL;
516     os_option.option.stringval = NULL;
517     os_option.default_val.stringval = NULL;
518     user_appl_option.option.stringval = NULL;
519     user_appl_option.default_val.stringval = NULL;
520
521     section_mand->section_length = -1;
522
523     block->mandatory_data = section_mand;
524
525     wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
526     wtap_optionblock_add_option(block, OPT_SHB_HARDWARE, &hardware_option);
527     wtap_optionblock_add_option(block, OPT_SHB_OS, &os_option);
528     wtap_optionblock_add_option(block, OPT_SHB_USERAPPL, &user_appl_option);
529 }
530
531 static void shb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
532 {
533     memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t));
534 }
535
536 static void nrb_create(wtap_optionblock_t block)
537 {
538     static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
539
540     /* Set proper values for the union */
541     comment_option.option.stringval = NULL;
542     comment_option.default_val.stringval = NULL;
543
544     block->mandatory_data = NULL;
545
546     wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
547 }
548
549 static void isb_create(wtap_optionblock_t block)
550 {
551     static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
552     static wtap_optblock_reg_t starttime_option = {"start_time", "Start Time", WTAP_OPTTYPE_UINT64, {0}, {0}};
553     static wtap_optblock_reg_t endtime_option = {"end_time", "End Time", WTAP_OPTTYPE_UINT64, {0}, {0}};
554     static wtap_optblock_reg_t rcv_pkt_option = {"recv", "Receive Packets", WTAP_OPTTYPE_UINT64, {0}, {0}};
555     static wtap_optblock_reg_t drop_pkt_option = {"drop", "Dropped Packets", WTAP_OPTTYPE_UINT64, {0}, {0}};
556     static wtap_optblock_reg_t filteraccept_option = {"filter_accept", "Filter Accept", WTAP_OPTTYPE_UINT64, {0}, {0}};
557     static wtap_optblock_reg_t os_drop_option = {"os_drop", "OS Dropped Packets", WTAP_OPTTYPE_UINT64, {0}, {0}};
558     static wtap_optblock_reg_t user_deliv_option = {"user_deliv", "User Delivery", WTAP_OPTTYPE_UINT64, {0}, {0}};
559
560     block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1);
561
562     /* Set proper values for the union */
563     comment_option.option.stringval = NULL;
564     comment_option.default_val.stringval = NULL;
565     starttime_option.option.uint64val = 0;
566     starttime_option.default_val.uint64val = 0;
567     endtime_option.option.uint64val = 0;
568     endtime_option.default_val.uint64val = 0;
569     rcv_pkt_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
570     rcv_pkt_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
571     drop_pkt_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
572     drop_pkt_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
573     filteraccept_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
574     filteraccept_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
575     os_drop_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
576     os_drop_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
577     user_deliv_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
578     user_deliv_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
579
580     wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
581     wtap_optionblock_add_option(block, OPT_ISB_STARTTIME, &starttime_option);
582     wtap_optionblock_add_option(block, OPT_ISB_ENDTIME, &endtime_option);
583     wtap_optionblock_add_option(block, OPT_ISB_IFRECV, &rcv_pkt_option);
584     wtap_optionblock_add_option(block, OPT_ISB_IFDROP, &drop_pkt_option);
585     wtap_optionblock_add_option(block, OPT_ISB_FILTERACCEPT, &filteraccept_option);
586     wtap_optionblock_add_option(block, OPT_ISB_OSDROP, &os_drop_option);
587     wtap_optionblock_add_option(block, OPT_ISB_USRDELIV, &user_deliv_option);
588 }
589
590 static void isb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
591 {
592     memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t));
593 }
594
595 static void idb_filter_free(void* data)
596 {
597     wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)data;
598     g_free(filter->if_filter_str);
599     g_free(filter->if_filter_bpf_bytes);
600 }
601
602 static void idb_create(wtap_optionblock_t block)
603 {
604     static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
605     static wtap_optblock_reg_t name_option = {"name", "Device name", WTAP_OPTTYPE_STRING, {0}, {0}};
606     static wtap_optblock_reg_t description_option = {"description", "Device description", WTAP_OPTTYPE_STRING, {0}, {0}};
607     static wtap_optblock_reg_t speed_option = {"speed", "Interface speed (in bps)", WTAP_OPTTYPE_UINT64, {0}, {0}};
608     static wtap_optblock_reg_t tsresol_option = {"ts_resolution", "Resolution of timestamps", WTAP_OPTTYPE_UINT8, {0}, {0}};
609     static wtap_optblock_reg_t filter_option = {"filter", "Filter string", WTAP_OPTTYPE_CUSTOM, {0}, {0}};
610     static wtap_optblock_reg_t os_option = {"os", "Operating System", WTAP_OPTTYPE_STRING, {0}, {0}};
611     static wtap_optblock_reg_t fcslen_option = {"fcslen", "FCS Length", WTAP_OPTTYPE_UINT8, {0}, {0}};
612
613     static wtapng_if_descr_filter_t default_filter;
614
615     block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1);
616
617     /* Set proper values for the union */
618     comment_option.option.stringval = NULL;
619     comment_option.default_val.stringval = NULL;
620     name_option.option.stringval = NULL;
621     name_option.default_val.stringval = NULL;
622     description_option.option.stringval = NULL;
623     description_option.default_val.stringval = NULL;
624     speed_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
625     speed_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
626     tsresol_option.option.uint8val = 6;
627     tsresol_option.default_val.uint8val = 6;
628     filter_option.option.customval.size = sizeof(wtapng_if_descr_filter_t);
629     filter_option.option.customval.data = &default_filter;
630     filter_option.option.customval.free_func = idb_filter_free;
631     filter_option.default_val.customval.size = sizeof(wtapng_if_descr_filter_t);
632     filter_option.default_val.customval.data = &default_filter;
633     filter_option.default_val.customval.free_func = idb_filter_free;
634     os_option.option.stringval = NULL;
635     os_option.default_val.stringval = NULL;
636     fcslen_option.option.uint8val = -1;
637     fcslen_option.default_val.uint8val = -1;
638
639     wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
640     wtap_optionblock_add_option(block, OPT_IDB_NAME, &name_option);
641     wtap_optionblock_add_option(block, OPT_IDB_DESCR, &description_option);
642     wtap_optionblock_add_option(block, OPT_IDB_SPEED, &speed_option);
643     wtap_optionblock_add_option(block, OPT_IDB_TSRESOL, &tsresol_option);
644     wtap_optionblock_add_option(block, OPT_IDB_FILTER, &filter_option);
645     wtap_optionblock_add_option(block, OPT_IDB_OS, &os_option);
646     wtap_optionblock_add_option(block, OPT_IDB_FCSLEN, &fcslen_option);
647 }
648
649 static void idb_free_mand(wtap_optionblock_t block)
650 {
651     guint j;
652     wtap_optionblock_t if_stats;
653     wtapng_if_descr_mandatory_t* mand = (wtapng_if_descr_mandatory_t*)block->mandatory_data;
654
655     for(j = 0; j < mand->num_stat_entries; j++) {
656         if_stats = g_array_index(mand->interface_statistics, wtap_optionblock_t, j);
657         wtap_optionblock_free(if_stats);
658     }
659
660     if (mand->interface_statistics)
661         g_array_free(mand->interface_statistics, TRUE);
662 }
663
664 static void idb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
665 {
666     guint j;
667     wtap_optionblock_t src_if_stats, dest_if_stats;
668     wtapng_if_descr_mandatory_t *src_mand = (wtapng_if_descr_mandatory_t*)src_block->mandatory_data,
669                                 *dest_mand = (wtapng_if_descr_mandatory_t*)dest_block->mandatory_data;
670
671     /* Need special consideration for copying of the interface_statistics member */
672     if (dest_mand->num_stat_entries != 0)
673         g_array_free(dest_mand->interface_statistics, TRUE);
674
675     memcpy(dest_mand, src_mand, sizeof(wtapng_if_descr_mandatory_t));
676     if (src_mand->num_stat_entries != 0)
677     {
678         dest_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
679         for (j = 0; j < src_mand->num_stat_entries; j++)
680         {
681             src_if_stats = g_array_index(src_mand->interface_statistics, wtap_optionblock_t, j);
682             dest_if_stats = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_STATS);
683             wtap_optionblock_copy_options(dest_if_stats, src_if_stats);
684             dest_mand->interface_statistics = g_array_append_val(dest_mand->interface_statistics, dest_if_stats);
685         }
686     }
687 }
688
689 void wtap_opttypes_initialize(void)
690 {
691     static wtap_opt_register_t shb_block = {
692         "SHB",              /* name */
693         "Section Header Block",  /* description */
694         shb_create,         /* create */
695         NULL,               /* free_mand */
696         shb_copy_mand,      /* copy_mand */
697     };
698
699     static wtap_opt_register_t nrb_block = {
700         "NRB",              /* name */
701         "Name Resolution Block",  /* description */
702         nrb_create,         /* create */
703         NULL,               /* free_mand */
704         NULL,               /* copy_mand */
705     };
706
707     static wtap_opt_register_t isb_block = {
708         "ISB",              /* name */
709         "Interface Statistics Block",  /* description */
710         isb_create,         /* create */
711         NULL,               /* free_mand */
712         isb_copy_mand,      /* copy_mand */
713     };
714
715     static wtap_opt_register_t idb_block = {
716         "IDB",              /* name */
717         "Interface Description Block",  /* description */
718         idb_create,         /* create */
719         idb_free_mand,      /* free_mand */
720         idb_copy_mand,      /* copy_mand */
721     };
722
723     /* Initialize the custom block array.  This is for future proofing
724        "outside registered" block types (for NULL checking) */
725     memset(block_list, 0, MAX_WTAP_OPTION_BLOCK_TYPE_VALUE*sizeof(wtap_opt_register_t*));
726     num_custom_blocks = 0;
727
728     wtap_opttype_block_register(WTAP_OPTION_BLOCK_NG_SECTION, &shb_block );
729     wtap_opttype_block_register(WTAP_OPTION_BLOCK_NG_NRB, &nrb_block );
730     wtap_opttype_block_register(WTAP_OPTION_BLOCK_IF_STATS, &isb_block );
731     wtap_opttype_block_register(WTAP_OPTION_BLOCK_IF_DESCR, &idb_block );
732 }