1 /* wtap_opttypes.c
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 2001 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 #include "config.h"
10 
11 #include <glib.h>
12 #include <string.h>
13 
14 #include "wtap.h"
15 #include "wtap_opttypes.h"
16 #include "wtap-int.h"
17 #include "pcapng_module.h"
18 #include <wsutil/ws_assert.h>
19 
20 #include <wsutil/glib-compat.h>
21 #include <wsutil/inet_ipv6.h>
22 
23 #if 0
24 #define wtap_debug(...) g_warning(__VA_ARGS__)
25 #define DEBUG_COUNT_REFS
26 #else
27 #define wtap_debug(...)
28 #endif
29 
30 #define ROUND_TO_4BYTE(len) (((len) + 3) & ~3)
31 
32 /*
33  * Structure describing a type of block.
34  */
35 typedef struct {
36     wtap_block_type_t block_type;    /**< internal type code for block */
37     const char *name;                /**< name of block */
38     const char *description;         /**< human-readable description of block */
39     wtap_block_create_func create;
40     wtap_mand_free_func free_mand;
41     wtap_mand_copy_func copy_mand;
42     GHashTable *options;             /**< hash table of known options */
43 } wtap_blocktype_t;
44 
45 #define GET_OPTION_TYPE(options, option_id) \
46     (const wtap_opttype_t *)g_hash_table_lookup((options), GUINT_TO_POINTER(option_id))
47 
48 /*
49  * Structure describing a type of option.
50  */
51 typedef struct {
52     const char *name;                            /**< name of option */
53     const char *description;                     /**< human-readable description of option */
54     wtap_opttype_e data_type;                    /**< data type of that option */
55     guint flags;                                 /**< flags for the option */
56 } wtap_opttype_t;
57 
58 /* Flags */
59 #define WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED 0x00000001 /* multiple instances allowed */
60 
61 /* Debugging reference counting */
62 #ifdef DEBUG_COUNT_REFS
63 static guint block_count = 0;
64 static guint8 blocks_active[sizeof(guint)/8];
65 
rc_set(guint refnum)66 static void rc_set(guint refnum)
67 {
68     guint cellno = refnum / 8;
69     guint bitno = refnum % 8;
70     blocks_active[cellno] |= (guint8)(1 << bitno);
71 }
72 
rc_clear(guint refnum)73 static void rc_clear(guint refnum)
74 {
75     guint cellno = refnum / 8;
76     guint bitno = refnum % 8;
77     blocks_active[cellno] &= (guint8)~(1 << bitno);
78 }
79 
80 #endif /* DEBUG_COUNT_REFS */
81 
82 struct wtap_block
83 {
84     wtap_blocktype_t* info;
85     void* mandatory_data;
86     GArray* options;
87     gint ref_count;
88 #ifdef DEBUG_COUNT_REFS
89     guint id;
90 #endif
91 };
92 
93 /* Keep track of wtap_blocktype_t's via their id number */
94 static wtap_blocktype_t* blocktype_list[MAX_WTAP_BLOCK_TYPE_VALUE];
95 
if_filter_dup(if_filter_opt_t * filter_src)96 static if_filter_opt_t if_filter_dup(if_filter_opt_t* filter_src)
97 {
98     if_filter_opt_t filter_dest;
99 
100     memset(&filter_dest, 0, sizeof(filter_dest));
101 
102     /* Deep copy. */
103     filter_dest.type = filter_src->type;
104     switch (filter_src->type) {
105 
106     case if_filter_pcap:
107         /* pcap filter string */
108         filter_dest.data.filter_str =
109             g_strdup(filter_src->data.filter_str);
110         break;
111 
112     case if_filter_bpf:
113         /* BPF program */
114         filter_dest.data.bpf_prog.bpf_prog_len =
115             filter_src->data.bpf_prog.bpf_prog_len;
116         filter_dest.data.bpf_prog.bpf_prog =
117             (wtap_bpf_insn_t *)g_memdup2(filter_src->data.bpf_prog.bpf_prog,
118                                         filter_src->data.bpf_prog.bpf_prog_len * sizeof (wtap_bpf_insn_t));
119         break;
120 
121     default:
122         break;
123     }
124     return filter_dest;
125 }
126 
if_filter_free(if_filter_opt_t * filter_src)127 static void if_filter_free(if_filter_opt_t* filter_src)
128 {
129     switch (filter_src->type) {
130 
131     case if_filter_pcap:
132         /* pcap filter string */
133         g_free(filter_src->data.filter_str);
134         break;
135 
136     case if_filter_bpf:
137         /* BPF program */
138         g_free(filter_src->data.bpf_prog.bpf_prog);
139         break;
140 
141     default:
142         break;
143     }
144 }
145 
146 static packet_verdict_opt_t
packet_verdict_dup(packet_verdict_opt_t * verdict_src)147 packet_verdict_dup(packet_verdict_opt_t* verdict_src)
148 {
149     packet_verdict_opt_t verdict_dest;
150 
151     memset(&verdict_dest, 0, sizeof(verdict_dest));
152 
153     /* Deep copy. */
154     verdict_dest.type = verdict_src->type;
155     switch (verdict_src->type) {
156 
157     case packet_verdict_hardware:
158         /* array of octets */
159         verdict_dest.data.verdict_bytes =
160             g_byte_array_new_take((guint8 *)g_memdup2(verdict_src->data.verdict_bytes->data,
161                                                       verdict_src->data.verdict_bytes->len),
162                                   verdict_src->data.verdict_bytes->len);
163         break;
164 
165     case packet_verdict_linux_ebpf_tc:
166         /* eBPF TC_ACT_ value */
167         verdict_dest.data.verdict_linux_ebpf_tc =
168             verdict_src->data.verdict_linux_ebpf_tc;
169         break;
170 
171     case packet_verdict_linux_ebpf_xdp:
172         /* xdp_action value */
173         verdict_dest.data.verdict_linux_ebpf_xdp =
174             verdict_src->data.verdict_linux_ebpf_xdp;
175         break;
176 
177     default:
178         break;
179     }
180     return verdict_dest;
181 }
182 
wtap_packet_verdict_free(packet_verdict_opt_t * verdict)183 void wtap_packet_verdict_free(packet_verdict_opt_t* verdict)
184 {
185     switch (verdict->type) {
186 
187     case packet_verdict_hardware:
188         /* array of bytes */
189         g_byte_array_free(verdict->data.verdict_bytes, TRUE);
190         break;
191 
192     default:
193         break;
194     }
195 }
196 
wtap_opttype_block_register(wtap_blocktype_t * blocktype)197 static void wtap_opttype_block_register(wtap_blocktype_t *blocktype)
198 {
199     wtap_block_type_t block_type;
200     static const wtap_opttype_t opt_comment = {
201         "opt_comment",
202         "Comment",
203         WTAP_OPTTYPE_STRING,
204         WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
205     };
206     static const wtap_opttype_t opt_custom = {
207         "opt_custom",
208         "Custom Option",
209         WTAP_OPTTYPE_CUSTOM,
210         WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
211     };
212 
213     block_type = blocktype->block_type;
214 
215     /* Check input */
216     ws_assert(block_type < MAX_WTAP_BLOCK_TYPE_VALUE);
217 
218     /* Don't re-register. */
219     ws_assert(blocktype_list[block_type] == NULL);
220 
221     /* Sanity check */
222     ws_assert(blocktype->name);
223     ws_assert(blocktype->description);
224     ws_assert(blocktype->create);
225 
226     /*
227      * Initialize the set of supported options.
228      * All blocks that support options at all support
229      * OPT_COMMENT and OPT_CUSTOM.
230      *
231      * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
232      * so we use "g_direct_hash()" and "g_direct_equal()".
233      */
234     blocktype->options = g_hash_table_new(g_direct_hash, g_direct_equal);
235     g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_COMMENT),
236                         (gpointer)&opt_comment);
237     g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_STR_COPY),
238                         (gpointer)&opt_custom);
239     g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_BIN_COPY),
240                         (gpointer)&opt_custom);
241     g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_STR_NO_COPY),
242                         (gpointer)&opt_custom);
243     g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(OPT_CUSTOM_BIN_NO_COPY),
244                         (gpointer)&opt_custom);
245 
246     blocktype_list[block_type] = blocktype;
247 }
248 
wtap_opttype_option_register(wtap_blocktype_t * blocktype,guint opttype,const wtap_opttype_t * option)249 static void wtap_opttype_option_register(wtap_blocktype_t *blocktype, guint opttype, const wtap_opttype_t *option)
250 {
251     g_hash_table_insert(blocktype->options, GUINT_TO_POINTER(opttype),
252                         (gpointer) option);
253 }
254 
wtap_block_get_type(wtap_block_t block)255 wtap_block_type_t wtap_block_get_type(wtap_block_t block)
256 {
257     return block->info->block_type;
258 }
259 
wtap_block_get_mandatory_data(wtap_block_t block)260 void* wtap_block_get_mandatory_data(wtap_block_t block)
261 {
262     return block->mandatory_data;
263 }
264 
265 static wtap_optval_t *
wtap_block_get_option(wtap_block_t block,guint option_id)266 wtap_block_get_option(wtap_block_t block, guint option_id)
267 {
268     guint i;
269     wtap_option_t *opt;
270 
271     if (block == NULL) {
272         return NULL;
273     }
274 
275     for (i = 0; i < block->options->len; i++) {
276         opt = &g_array_index(block->options, wtap_option_t, i);
277         if (opt->option_id == option_id)
278             return &opt->value;
279     }
280 
281     return NULL;
282 }
283 
284 static wtap_optval_t *
wtap_block_get_nth_option(wtap_block_t block,guint option_id,guint idx)285 wtap_block_get_nth_option(wtap_block_t block, guint option_id, guint idx)
286 {
287     guint i;
288     wtap_option_t *opt;
289     guint opt_idx;
290 
291     if (block == NULL) {
292         return NULL;
293     }
294 
295     opt_idx = 0;
296     for (i = 0; i < block->options->len; i++) {
297         opt = &g_array_index(block->options, wtap_option_t, i);
298         if (opt->option_id == option_id) {
299             if (opt_idx == idx)
300                 return &opt->value;
301             opt_idx++;
302         }
303     }
304 
305     return NULL;
306 }
307 
wtap_block_create(wtap_block_type_t block_type)308 wtap_block_t wtap_block_create(wtap_block_type_t block_type)
309 {
310     wtap_block_t block;
311 
312     if (block_type >= MAX_WTAP_BLOCK_TYPE_VALUE)
313         return NULL;
314 
315     block = g_new(struct wtap_block, 1);
316     block->info = blocktype_list[block_type];
317     block->options = g_array_new(FALSE, FALSE, sizeof(wtap_option_t));
318     block->info->create(block);
319     block->ref_count = 1;
320 #ifdef DEBUG_COUNT_REFS
321     block->id = block_count++;
322     rc_set(block->id);
323     wtap_debug("Created #%d %s", block->id, block->info->name);
324 #endif /* DEBUG_COUNT_REFS */
325 
326     return block;
327 }
328 
wtap_block_free_option(wtap_block_t block,wtap_option_t * opt)329 static void wtap_block_free_option(wtap_block_t block, wtap_option_t *opt)
330 {
331     const wtap_opttype_t *opttype;
332 
333     if (block == NULL) {
334         return;
335     }
336 
337     opttype = GET_OPTION_TYPE(block->info->options, opt->option_id);
338     switch (opttype->data_type) {
339 
340     case WTAP_OPTTYPE_STRING:
341         g_free(opt->value.stringval);
342         break;
343 
344     case WTAP_OPTTYPE_BYTES:
345         g_bytes_unref(opt->value.byteval);
346         break;
347 
348     case WTAP_OPTTYPE_CUSTOM:
349         switch (opt->value.custom_opt.pen) {
350         case PEN_NFLX:
351             g_free(opt->value.custom_opt.data.nflx_data.custom_data);
352             break;
353         default:
354             g_free(opt->value.custom_opt.data.generic_data.custom_data);
355             break;
356         }
357         break;
358 
359     case WTAP_OPTTYPE_IF_FILTER:
360         if_filter_free(&opt->value.if_filterval);
361         break;
362 
363     case WTAP_OPTTYPE_PACKET_VERDICT:
364         wtap_packet_verdict_free(&opt->value.packet_verdictval);
365         break;
366 
367     default:
368         break;
369     }
370 }
371 
wtap_block_free_options(wtap_block_t block)372 static void wtap_block_free_options(wtap_block_t block)
373 {
374     guint i;
375     wtap_option_t *opt;
376 
377     if (block == NULL || block->options == NULL) {
378         return;
379     }
380 
381     for (i = 0; i < block->options->len; i++) {
382         opt = &g_array_index(block->options, wtap_option_t, i);
383         wtap_block_free_option(block, opt);
384     }
385     g_array_remove_range(block->options, 0, block->options->len);
386 }
387 
wtap_block_ref(wtap_block_t block)388 wtap_block_t wtap_block_ref(wtap_block_t block)
389 {
390     if (block == NULL) {
391         return NULL;
392     }
393 
394     g_atomic_int_inc(&block->ref_count);
395 #ifdef DEBUG_COUNT_REFS
396         wtap_debug("Ref     #%d %s", block->id, block->info->name);
397 #endif /* DEBUG_COUNT_REFS */
398     return block;
399 }
400 
wtap_block_unref(wtap_block_t block)401 void wtap_block_unref(wtap_block_t block)
402 {
403     if (block != NULL)
404     {
405         if (g_atomic_int_dec_and_test(&block->ref_count)) {
406 #ifdef DEBUG_COUNT_REFS
407             wtap_debug("Destroy #%d %s", block->id, block->info->name);
408             rc_clear(block->id);
409 #endif /* DEBUG_COUNT_REFS */
410             if (block->info->free_mand != NULL)
411                 block->info->free_mand(block);
412 
413             g_free(block->mandatory_data);
414             wtap_block_free_options(block);
415             g_array_free(block->options, TRUE);
416             g_free(block);
417         }
418 #ifdef DEBUG_COUNT_REFS
419         else {
420             wtap_debug("Unref   #%d %s", block->id, block->info->name);
421         }
422 #endif /* DEBUG_COUNT_REFS */
423     }
424 }
425 
wtap_block_array_free(GArray * block_array)426 void wtap_block_array_free(GArray* block_array)
427 {
428     guint block;
429 
430     if (block_array == NULL)
431         return;
432 
433     for (block = 0; block < block_array->len; block++) {
434         wtap_block_unref(g_array_index(block_array, wtap_block_t, block));
435     }
436     g_array_free(block_array, TRUE);
437 }
438 
439 /*
440  * Make a copy of a block.
441  */
442 void
wtap_block_copy(wtap_block_t dest_block,wtap_block_t src_block)443 wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block)
444 {
445     guint i;
446     wtap_option_t *src_opt;
447     const wtap_opttype_t *opttype;
448 
449     /*
450      * Copy the mandatory data.
451      */
452     if (dest_block->info->copy_mand != NULL)
453         dest_block->info->copy_mand(dest_block, src_block);
454 
455     /* Copy the options.  For now, don't remove any options that are in destination
456      * but not source.
457      */
458     for (i = 0; i < src_block->options->len; i++)
459     {
460         src_opt = &g_array_index(src_block->options, wtap_option_t, i);
461         opttype = GET_OPTION_TYPE(src_block->info->options, src_opt->option_id);
462 
463         switch(opttype->data_type) {
464 
465         case WTAP_OPTTYPE_UINT8:
466             wtap_block_add_uint8_option(dest_block, src_opt->option_id, src_opt->value.uint8val);
467             break;
468 
469         case WTAP_OPTTYPE_UINT32:
470             wtap_block_add_uint32_option(dest_block, src_opt->option_id, src_opt->value.uint32val);
471             break;
472 
473         case WTAP_OPTTYPE_UINT64:
474             wtap_block_add_uint64_option(dest_block, src_opt->option_id, src_opt->value.uint64val);
475             break;
476 
477         case WTAP_OPTTYPE_IPv4:
478             wtap_block_add_ipv4_option(dest_block, src_opt->option_id, src_opt->value.ipv4val);
479             break;
480 
481         case WTAP_OPTTYPE_IPv6:
482             wtap_block_add_ipv6_option(dest_block, src_opt->option_id, &src_opt->value.ipv6val);
483             break;
484 
485         case WTAP_OPTTYPE_STRING:
486             wtap_block_add_string_option(dest_block, src_opt->option_id, src_opt->value.stringval, strlen(src_opt->value.stringval));
487             break;
488 
489         case WTAP_OPTTYPE_BYTES:
490             wtap_block_add_bytes_option_borrow(dest_block, src_opt->option_id, src_opt->value.byteval);
491             break;
492 
493         case WTAP_OPTTYPE_CUSTOM:
494             switch (src_opt->value.custom_opt.pen) {
495             case PEN_NFLX:
496                 wtap_block_add_nflx_custom_option(dest_block, src_opt->value.custom_opt.data.nflx_data.type, src_opt->value.custom_opt.data.nflx_data.custom_data, src_opt->value.custom_opt.data.nflx_data.custom_data_len);
497                 break;
498             default:
499                 wtap_block_add_custom_option(dest_block, src_opt->option_id, src_opt->value.custom_opt.pen, src_opt->value.custom_opt.data.generic_data.custom_data, src_opt->value.custom_opt.data.generic_data.custom_data_len);
500                 break;
501             }
502             break;
503 
504         case WTAP_OPTTYPE_IF_FILTER:
505             wtap_block_add_if_filter_option(dest_block, src_opt->option_id, &src_opt->value.if_filterval);
506             break;
507 
508         case WTAP_OPTTYPE_PACKET_VERDICT:
509             wtap_block_add_packet_verdict_option(dest_block, src_opt->option_id, &src_opt->value.packet_verdictval);
510             break;
511         }
512     }
513 }
514 
wtap_block_make_copy(wtap_block_t block)515 wtap_block_t wtap_block_make_copy(wtap_block_t block)
516 {
517     wtap_block_t block_copy;
518 
519     block_copy = wtap_block_create(block->info->block_type);
520     wtap_block_copy(block_copy, block);
521     return block_copy;
522 }
523 
524 guint
wtap_block_count_option(wtap_block_t block,guint option_id)525 wtap_block_count_option(wtap_block_t block, guint option_id)
526 {
527     guint i;
528     guint ret_val = 0;
529     wtap_option_t *opt;
530 
531     if (block == NULL) {
532         return 0;
533     }
534 
535     for (i = 0; i < block->options->len; i++) {
536         opt = &g_array_index(block->options, wtap_option_t, i);
537         if (opt->option_id == option_id)
538             ret_val++;
539     }
540 
541     return ret_val;
542 }
543 
544 
wtap_block_foreach_option(wtap_block_t block,wtap_block_foreach_func func,void * user_data)545 gboolean wtap_block_foreach_option(wtap_block_t block, wtap_block_foreach_func func, void* user_data)
546 {
547     guint i;
548     wtap_option_t *opt;
549     const wtap_opttype_t *opttype;
550 
551     if (block == NULL) {
552         return TRUE;
553     }
554 
555     for (i = 0; i < block->options->len; i++) {
556         opt = &g_array_index(block->options, wtap_option_t, i);
557         opttype = GET_OPTION_TYPE(block->info->options, opt->option_id);
558         if (!func(block, opt->option_id, opttype->data_type, &opt->value, user_data))
559             return FALSE;
560     }
561     return TRUE;
562 }
563 
564 static wtap_opttype_return_val
wtap_block_add_option_common(wtap_block_t block,guint option_id,wtap_opttype_e type,wtap_option_t ** optp)565 wtap_block_add_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, wtap_option_t **optp)
566 {
567     wtap_option_t *opt;
568     const wtap_opttype_t *opttype;
569     guint i;
570 
571     if (block == NULL) {
572         return WTAP_OPTTYPE_BAD_BLOCK;
573     }
574 
575     opttype = GET_OPTION_TYPE(block->info->options, option_id);
576     if (opttype == NULL) {
577         /* There's no option for this block with that option ID */
578         return WTAP_OPTTYPE_NO_SUCH_OPTION;
579     }
580 
581     /*
582      * Is this an option of the specified data type?
583      */
584     if (opttype->data_type != type) {
585         /*
586          * No.
587          */
588         return WTAP_OPTTYPE_TYPE_MISMATCH;
589     }
590 
591     /*
592      * Can there be more than one instance of this option?
593      */
594     if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
595         /*
596          * No. Is there already an instance of this option?
597          */
598         if (wtap_block_get_option(block, option_id) != NULL) {
599             /*
600              * Yes. Fail.
601              */
602             return WTAP_OPTTYPE_ALREADY_EXISTS;
603         }
604     }
605 
606     /*
607      * Add an instance.
608      */
609     i = block->options->len;
610     g_array_set_size(block->options, i + 1);
611     opt = &g_array_index(block->options, wtap_option_t, i);
612     opt->option_id = option_id;
613     *optp = opt;
614     return WTAP_OPTTYPE_SUCCESS;
615 }
616 
617 static wtap_opttype_return_val
wtap_block_get_option_common(wtap_block_t block,guint option_id,wtap_opttype_e type,wtap_optval_t ** optvalp)618 wtap_block_get_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, wtap_optval_t **optvalp)
619 {
620     const wtap_opttype_t *opttype;
621     wtap_optval_t *optval;
622 
623     if (block == NULL) {
624         return WTAP_OPTTYPE_BAD_BLOCK;
625     }
626 
627     opttype = GET_OPTION_TYPE(block->info->options, option_id);
628     if (opttype == NULL) {
629         /* There's no option for this block with that option ID */
630         return WTAP_OPTTYPE_NO_SUCH_OPTION;
631     }
632 
633     /*
634      * Is this an option of the specified data type?
635      */
636     if (opttype->data_type != type) {
637         /*
638          * No.
639          */
640         return WTAP_OPTTYPE_TYPE_MISMATCH;
641     }
642 
643     /*
644      * Can there be more than one instance of this option?
645      */
646     if (opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED) {
647         /*
648          * Yes.  You can't ask for "the" value.
649          */
650         return WTAP_OPTTYPE_NUMBER_MISMATCH;
651     }
652 
653     optval = wtap_block_get_option(block, option_id);
654     if (optval == NULL) {
655         /* Didn't find the option */
656         return WTAP_OPTTYPE_NOT_FOUND;
657     }
658 
659     *optvalp = optval;
660     return WTAP_OPTTYPE_SUCCESS;
661 }
662 
663 static wtap_opttype_return_val
wtap_block_get_nth_option_common(wtap_block_t block,guint option_id,wtap_opttype_e type,guint idx,wtap_optval_t ** optvalp)664 wtap_block_get_nth_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, guint idx, wtap_optval_t **optvalp)
665 {
666     const wtap_opttype_t *opttype;
667     wtap_optval_t *optval;
668 
669     if (block == NULL) {
670         return WTAP_OPTTYPE_BAD_BLOCK;
671     }
672 
673     opttype = GET_OPTION_TYPE(block->info->options, option_id);
674     if (opttype == NULL) {
675         /* There's no option for this block with that option ID */
676         return WTAP_OPTTYPE_NO_SUCH_OPTION;
677     }
678 
679     /*
680      * Is this an option of the specified data type?
681      */
682     if (opttype->data_type != type) {
683         /*
684          * No.
685          */
686         return WTAP_OPTTYPE_TYPE_MISMATCH;
687     }
688 
689     /*
690      * Can there be more than one instance of this option?
691      */
692     if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
693         /*
694          * No.
695          */
696         return WTAP_OPTTYPE_NUMBER_MISMATCH;
697     }
698 
699     optval = wtap_block_get_nth_option(block, option_id, idx);
700     if (optval == NULL) {
701         /* Didn't find the option */
702         return WTAP_OPTTYPE_NOT_FOUND;
703     }
704 
705     *optvalp = optval;
706     return WTAP_OPTTYPE_SUCCESS;
707 }
708 
709 wtap_opttype_return_val
wtap_block_add_uint8_option(wtap_block_t block,guint option_id,guint8 value)710 wtap_block_add_uint8_option(wtap_block_t block, guint option_id, guint8 value)
711 {
712     wtap_opttype_return_val ret;
713     wtap_option_t *opt;
714 
715     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &opt);
716     if (ret != WTAP_OPTTYPE_SUCCESS)
717         return ret;
718     opt->value.uint8val = value;
719     return WTAP_OPTTYPE_SUCCESS;
720 }
721 
722 wtap_opttype_return_val
wtap_block_set_uint8_option_value(wtap_block_t block,guint option_id,guint8 value)723 wtap_block_set_uint8_option_value(wtap_block_t block, guint option_id, guint8 value)
724 {
725     wtap_opttype_return_val ret;
726     wtap_optval_t *optval;
727 
728     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &optval);
729     if (ret != WTAP_OPTTYPE_SUCCESS)
730         return ret;
731     optval->uint8val = value;
732     return WTAP_OPTTYPE_SUCCESS;
733 }
734 
735 wtap_opttype_return_val
wtap_block_get_uint8_option_value(wtap_block_t block,guint option_id,guint8 * value)736 wtap_block_get_uint8_option_value(wtap_block_t block, guint option_id, guint8* value)
737 {
738     wtap_opttype_return_val ret;
739     wtap_optval_t *optval;
740 
741     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &optval);
742     if (ret != WTAP_OPTTYPE_SUCCESS)
743         return ret;
744     *value = optval->uint8val;
745     return WTAP_OPTTYPE_SUCCESS;
746 }
747 
748 wtap_opttype_return_val
wtap_block_add_uint32_option(wtap_block_t block,guint option_id,guint32 value)749 wtap_block_add_uint32_option(wtap_block_t block, guint option_id, guint32 value)
750 {
751     wtap_opttype_return_val ret;
752     wtap_option_t *opt;
753 
754     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT32, &opt);
755     if (ret != WTAP_OPTTYPE_SUCCESS)
756         return ret;
757     opt->value.uint32val = value;
758     return WTAP_OPTTYPE_SUCCESS;
759 }
760 
761 wtap_opttype_return_val
wtap_block_set_uint32_option_value(wtap_block_t block,guint option_id,guint32 value)762 wtap_block_set_uint32_option_value(wtap_block_t block, guint option_id, guint32 value)
763 {
764     wtap_opttype_return_val ret;
765     wtap_optval_t *optval;
766 
767     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT32, &optval);
768     if (ret != WTAP_OPTTYPE_SUCCESS)
769         return ret;
770     optval->uint32val = value;
771     return WTAP_OPTTYPE_SUCCESS;
772 }
773 
774 wtap_opttype_return_val
wtap_block_get_uint32_option_value(wtap_block_t block,guint option_id,guint32 * value)775 wtap_block_get_uint32_option_value(wtap_block_t block, guint option_id, guint32* value)
776 {
777     wtap_opttype_return_val ret;
778     wtap_optval_t *optval;
779 
780     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT32, &optval);
781     if (ret != WTAP_OPTTYPE_SUCCESS)
782         return ret;
783     *value = optval->uint32val;
784     return WTAP_OPTTYPE_SUCCESS;
785 }
786 
787 wtap_opttype_return_val
wtap_block_add_uint64_option(wtap_block_t block,guint option_id,guint64 value)788 wtap_block_add_uint64_option(wtap_block_t block, guint option_id, guint64 value)
789 {
790     wtap_opttype_return_val ret;
791     wtap_option_t *opt;
792 
793     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &opt);
794     if (ret != WTAP_OPTTYPE_SUCCESS)
795         return ret;
796     opt->value.uint64val = value;
797     return WTAP_OPTTYPE_SUCCESS;
798 }
799 
800 wtap_opttype_return_val
wtap_block_set_uint64_option_value(wtap_block_t block,guint option_id,guint64 value)801 wtap_block_set_uint64_option_value(wtap_block_t block, guint option_id, guint64 value)
802 {
803     wtap_opttype_return_val ret;
804     wtap_optval_t *optval;
805 
806     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &optval);
807     if (ret != WTAP_OPTTYPE_SUCCESS)
808         return ret;
809     optval->uint64val = value;
810     return WTAP_OPTTYPE_SUCCESS;
811 }
812 
813 wtap_opttype_return_val
wtap_block_get_uint64_option_value(wtap_block_t block,guint option_id,guint64 * value)814 wtap_block_get_uint64_option_value(wtap_block_t block, guint option_id, guint64 *value)
815 {
816     wtap_opttype_return_val ret;
817     wtap_optval_t *optval;
818 
819     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &optval);
820     if (ret != WTAP_OPTTYPE_SUCCESS)
821         return ret;
822     *value = optval->uint64val;
823     return WTAP_OPTTYPE_SUCCESS;
824 }
825 
826 wtap_opttype_return_val
wtap_block_add_ipv4_option(wtap_block_t block,guint option_id,guint32 value)827 wtap_block_add_ipv4_option(wtap_block_t block, guint option_id, guint32 value)
828 {
829     wtap_opttype_return_val ret;
830     wtap_option_t *opt;
831 
832     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &opt);
833     if (ret != WTAP_OPTTYPE_SUCCESS)
834         return ret;
835     opt->value.ipv4val = value;
836     return WTAP_OPTTYPE_SUCCESS;
837 }
838 
839 wtap_opttype_return_val
wtap_block_set_ipv4_option_value(wtap_block_t block,guint option_id,guint32 value)840 wtap_block_set_ipv4_option_value(wtap_block_t block, guint option_id, guint32 value)
841 {
842     wtap_opttype_return_val ret;
843     wtap_optval_t *optval;
844 
845     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
846     if (ret != WTAP_OPTTYPE_SUCCESS)
847         return ret;
848     optval->ipv4val = value;
849     return WTAP_OPTTYPE_SUCCESS;
850 }
851 
852 wtap_opttype_return_val
wtap_block_get_ipv4_option_value(wtap_block_t block,guint option_id,guint32 * value)853 wtap_block_get_ipv4_option_value(wtap_block_t block, guint option_id, guint32* value)
854 {
855     wtap_opttype_return_val ret;
856     wtap_optval_t *optval;
857 
858     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
859     if (ret != WTAP_OPTTYPE_SUCCESS)
860         return ret;
861     *value = optval->ipv4val;
862     return WTAP_OPTTYPE_SUCCESS;
863 }
864 
865 wtap_opttype_return_val
wtap_block_add_ipv6_option(wtap_block_t block,guint option_id,ws_in6_addr * value)866 wtap_block_add_ipv6_option(wtap_block_t block, guint option_id, ws_in6_addr *value)
867 {
868     wtap_opttype_return_val ret;
869     wtap_option_t *opt;
870 
871     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &opt);
872     if (ret != WTAP_OPTTYPE_SUCCESS)
873         return ret;
874     opt->value.ipv6val = *value;
875     return WTAP_OPTTYPE_SUCCESS;
876 }
877 
878 wtap_opttype_return_val
wtap_block_set_ipv6_option_value(wtap_block_t block,guint option_id,ws_in6_addr * value)879 wtap_block_set_ipv6_option_value(wtap_block_t block, guint option_id, ws_in6_addr *value)
880 {
881     wtap_opttype_return_val ret;
882     wtap_optval_t *optval;
883 
884     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &optval);
885     if (ret != WTAP_OPTTYPE_SUCCESS)
886         return ret;
887     optval->ipv6val = *value;
888     return WTAP_OPTTYPE_SUCCESS;
889 }
890 
891 wtap_opttype_return_val
wtap_block_get_ipv6_option_value(wtap_block_t block,guint option_id,ws_in6_addr * value)892 wtap_block_get_ipv6_option_value(wtap_block_t block, guint option_id, ws_in6_addr* value)
893 {
894     wtap_opttype_return_val ret;
895     wtap_optval_t *optval;
896 
897     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &optval);
898     if (ret != WTAP_OPTTYPE_SUCCESS)
899         return ret;
900     *value = optval->ipv6val;
901     return WTAP_OPTTYPE_SUCCESS;
902 }
903 
904 wtap_opttype_return_val
wtap_block_add_string_option(wtap_block_t block,guint option_id,const char * value,gsize value_length)905 wtap_block_add_string_option(wtap_block_t block, guint option_id, const char *value, gsize value_length)
906 {
907     wtap_opttype_return_val ret;
908     wtap_option_t *opt;
909 
910     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
911     if (ret != WTAP_OPTTYPE_SUCCESS)
912         return ret;
913     opt->value.stringval = g_strndup(value, value_length);
914     return WTAP_OPTTYPE_SUCCESS;
915 }
916 
917 static wtap_opttype_return_val
wtap_block_add_string_option_vformat(wtap_block_t block,guint option_id,const char * format,va_list va)918 wtap_block_add_string_option_vformat(wtap_block_t block, guint option_id, const char *format, va_list va)
919 {
920     wtap_opttype_return_val ret;
921     wtap_option_t *opt;
922 
923     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
924     if (ret != WTAP_OPTTYPE_SUCCESS)
925         return ret;
926     opt->value.stringval = g_strdup_vprintf(format, va);
927     return WTAP_OPTTYPE_SUCCESS;
928 }
929 
930 wtap_opttype_return_val
wtap_block_add_string_option_format(wtap_block_t block,guint option_id,const char * format,...)931 wtap_block_add_string_option_format(wtap_block_t block, guint option_id, const char *format, ...)
932 {
933     wtap_opttype_return_val ret;
934     wtap_option_t *opt;
935     va_list va;
936 
937     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
938     if (ret != WTAP_OPTTYPE_SUCCESS)
939         return ret;
940     va_start(va, format);
941     opt->value.stringval = g_strdup_vprintf(format, va);
942     va_end(va);
943     return WTAP_OPTTYPE_SUCCESS;
944 }
945 
946 wtap_opttype_return_val
wtap_block_set_string_option_value(wtap_block_t block,guint option_id,const char * value,size_t value_length)947 wtap_block_set_string_option_value(wtap_block_t block, guint option_id, const char *value, size_t value_length)
948 {
949     wtap_opttype_return_val ret;
950     wtap_optval_t *optval;
951 
952     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
953     if (ret != WTAP_OPTTYPE_SUCCESS) {
954         if (ret == WTAP_OPTTYPE_NOT_FOUND) {
955             /*
956              * There's no instance to set, so just try to create a new one
957              * with the value.
958              */
959             return wtap_block_add_string_option(block, option_id, value, value_length);
960         }
961         /* Otherwise fail. */
962         return ret;
963     }
964     g_free(optval->stringval);
965     optval->stringval = g_strndup(value, value_length);
966     return WTAP_OPTTYPE_SUCCESS;
967 }
968 
969 wtap_opttype_return_val
wtap_block_set_nth_string_option_value(wtap_block_t block,guint option_id,guint idx,const char * value,size_t value_length)970 wtap_block_set_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, const char *value, size_t value_length)
971 {
972     wtap_opttype_return_val ret;
973     wtap_optval_t *optval;
974 
975     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
976     if (ret != WTAP_OPTTYPE_SUCCESS)
977         return ret;
978     g_free(optval->stringval);
979     optval->stringval = g_strndup(value, value_length);
980     return WTAP_OPTTYPE_SUCCESS;
981 }
982 
983 wtap_opttype_return_val
wtap_block_set_string_option_value_format(wtap_block_t block,guint option_id,const char * format,...)984 wtap_block_set_string_option_value_format(wtap_block_t block, guint option_id, const char *format, ...)
985 {
986     wtap_opttype_return_val ret;
987     wtap_optval_t *optval;
988     va_list va;
989 
990     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
991     if (ret != WTAP_OPTTYPE_SUCCESS) {
992         if (ret == WTAP_OPTTYPE_NOT_FOUND) {
993             /*
994              * There's no instance to set, so just try to create a new one
995              * with the formatted string.
996              */
997             va_start(va, format);
998             ret = wtap_block_add_string_option_vformat(block, option_id, format, va);
999             va_end(va);
1000             return ret;
1001         }
1002         /* Otherwise fail. */
1003         return ret;
1004     }
1005     g_free(optval->stringval);
1006     va_start(va, format);
1007     optval->stringval = g_strdup_vprintf(format, va);
1008     va_end(va);
1009     return WTAP_OPTTYPE_SUCCESS;
1010 }
1011 
1012 wtap_opttype_return_val
wtap_block_set_nth_string_option_value_format(wtap_block_t block,guint option_id,guint idx,const char * format,...)1013 wtap_block_set_nth_string_option_value_format(wtap_block_t block, guint option_id, guint idx, const char *format, ...)
1014 {
1015     wtap_opttype_return_val ret;
1016     wtap_optval_t *optval;
1017     va_list va;
1018 
1019     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
1020     if (ret != WTAP_OPTTYPE_SUCCESS)
1021         return ret;
1022     g_free(optval->stringval);
1023     va_start(va, format);
1024     optval->stringval = g_strdup_vprintf(format, va);
1025     va_end(va);
1026     return WTAP_OPTTYPE_SUCCESS;
1027 }
1028 
1029 wtap_opttype_return_val
wtap_block_get_string_option_value(wtap_block_t block,guint option_id,char ** value)1030 wtap_block_get_string_option_value(wtap_block_t block, guint option_id, char** value)
1031 {
1032     wtap_opttype_return_val ret;
1033     wtap_optval_t *optval;
1034 
1035     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
1036     if (ret != WTAP_OPTTYPE_SUCCESS)
1037         return ret;
1038     *value = optval->stringval;
1039     return WTAP_OPTTYPE_SUCCESS;
1040 }
1041 
1042 wtap_opttype_return_val
wtap_block_get_nth_string_option_value(wtap_block_t block,guint option_id,guint idx,char ** value)1043 wtap_block_get_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, char** value)
1044 {
1045     wtap_opttype_return_val ret;
1046     wtap_optval_t *optval;
1047 
1048     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
1049     if (ret != WTAP_OPTTYPE_SUCCESS)
1050         return ret;
1051     *value = optval->stringval;
1052     return WTAP_OPTTYPE_SUCCESS;
1053 }
1054 
1055 wtap_opttype_return_val
wtap_block_add_bytes_option(wtap_block_t block,guint option_id,const guint8 * value,gsize value_length)1056 wtap_block_add_bytes_option(wtap_block_t block, guint option_id, const guint8 *value, gsize value_length)
1057 {
1058     wtap_opttype_return_val ret;
1059     wtap_option_t *opt;
1060 
1061     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_BYTES, &opt);
1062     if (ret != WTAP_OPTTYPE_SUCCESS)
1063         return ret;
1064     opt->value.byteval = g_bytes_new(value, value_length);
1065     return WTAP_OPTTYPE_SUCCESS;
1066 }
1067 
1068 wtap_opttype_return_val
wtap_block_add_bytes_option_borrow(wtap_block_t block,guint option_id,GBytes * value)1069 wtap_block_add_bytes_option_borrow(wtap_block_t block, guint option_id, GBytes *value)
1070 {
1071     wtap_opttype_return_val ret;
1072     wtap_option_t *opt;
1073 
1074     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_BYTES, &opt);
1075     if (ret != WTAP_OPTTYPE_SUCCESS)
1076         return ret;
1077     opt->value.byteval = g_bytes_ref(value);
1078     return WTAP_OPTTYPE_SUCCESS;
1079 }
1080 
1081 wtap_opttype_return_val
wtap_block_set_bytes_option_value(wtap_block_t block,guint option_id,const guint8 * value,size_t value_length)1082 wtap_block_set_bytes_option_value(wtap_block_t block, guint option_id, const guint8 *value, size_t value_length)
1083 {
1084     wtap_opttype_return_val ret;
1085     wtap_optval_t *optval;
1086 
1087     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_BYTES, &optval);
1088     if (ret != WTAP_OPTTYPE_SUCCESS) {
1089         if (ret == WTAP_OPTTYPE_NOT_FOUND) {
1090             /*
1091              * There's no instance to set, so just try to create a new one
1092              * with the value.
1093              */
1094             return wtap_block_add_bytes_option(block, option_id, value, value_length);
1095         }
1096         /* Otherwise fail. */
1097         return ret;
1098     }
1099     g_bytes_unref(optval->byteval);
1100     optval->byteval = g_bytes_new(value, value_length);
1101     return WTAP_OPTTYPE_SUCCESS;
1102 }
1103 
1104 wtap_opttype_return_val
wtap_block_set_nth_bytes_option_value(wtap_block_t block,guint option_id,guint idx,GBytes * value)1105 wtap_block_set_nth_bytes_option_value(wtap_block_t block, guint option_id, guint idx, GBytes *value)
1106 {
1107     wtap_opttype_return_val ret;
1108     wtap_optval_t *optval;
1109 
1110     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_BYTES, idx, &optval);
1111     if (ret != WTAP_OPTTYPE_SUCCESS)
1112         return ret;
1113     g_bytes_unref(optval->byteval);
1114     optval->byteval = g_bytes_ref(value);
1115     return WTAP_OPTTYPE_SUCCESS;
1116 }
1117 
1118 wtap_opttype_return_val
wtap_block_get_bytes_option_value(wtap_block_t block,guint option_id,GBytes ** value)1119 wtap_block_get_bytes_option_value(wtap_block_t block, guint option_id, GBytes** value)
1120 {
1121     wtap_opttype_return_val ret;
1122     wtap_optval_t *optval;
1123 
1124     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_BYTES, &optval);
1125     if (ret != WTAP_OPTTYPE_SUCCESS)
1126         return ret;
1127     *value = optval->byteval;
1128     return WTAP_OPTTYPE_SUCCESS;
1129 }
1130 
1131 wtap_opttype_return_val
wtap_block_get_nth_bytes_option_value(wtap_block_t block,guint option_id,guint idx,GBytes ** value)1132 wtap_block_get_nth_bytes_option_value(wtap_block_t block, guint option_id, guint idx, GBytes** value)
1133 {
1134     wtap_opttype_return_val ret;
1135     wtap_optval_t *optval;
1136 
1137     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_BYTES, idx, &optval);
1138     if (ret != WTAP_OPTTYPE_SUCCESS)
1139         return ret;
1140     *value = optval->byteval;
1141     return WTAP_OPTTYPE_SUCCESS;
1142 }
1143 
1144 wtap_opttype_return_val
wtap_block_add_nflx_custom_option(wtap_block_t block,guint32 type,const char * custom_data,gsize custom_data_len)1145 wtap_block_add_nflx_custom_option(wtap_block_t block, guint32 type, const char *custom_data, gsize custom_data_len)
1146 {
1147     wtap_opttype_return_val ret;
1148     wtap_option_t *opt;
1149 
1150     ret = wtap_block_add_option_common(block, OPT_CUSTOM_BIN_COPY, WTAP_OPTTYPE_CUSTOM, &opt);
1151     if (ret != WTAP_OPTTYPE_SUCCESS)
1152         return ret;
1153     opt->value.custom_opt.pen = PEN_NFLX;
1154     opt->value.custom_opt.data.nflx_data.type = type;
1155     opt->value.custom_opt.data.nflx_data.custom_data_len = custom_data_len;
1156     opt->value.custom_opt.data.nflx_data.custom_data = g_memdup2(custom_data, custom_data_len);
1157     opt->value.custom_opt.data.nflx_data.use_little_endian = (block->info->block_type == WTAP_BLOCK_CUSTOM);
1158     return WTAP_OPTTYPE_SUCCESS;
1159 }
1160 
1161 wtap_opttype_return_val
wtap_block_get_nflx_custom_option(wtap_block_t block,guint32 nflx_type,char * nflx_custom_data _U_,gsize nflx_custom_data_len)1162 wtap_block_get_nflx_custom_option(wtap_block_t block, guint32 nflx_type, char *nflx_custom_data _U_, gsize nflx_custom_data_len)
1163 {
1164     const wtap_opttype_t *opttype;
1165     wtap_option_t *opt;
1166     guint i;
1167 
1168     if (block == NULL) {
1169         return WTAP_OPTTYPE_BAD_BLOCK;
1170     }
1171     opttype = GET_OPTION_TYPE(block->info->options, OPT_CUSTOM_BIN_COPY);
1172     if (opttype == NULL) {
1173         return WTAP_OPTTYPE_NO_SUCH_OPTION;
1174     }
1175     if (opttype->data_type != WTAP_OPTTYPE_CUSTOM) {
1176         return WTAP_OPTTYPE_TYPE_MISMATCH;
1177     }
1178 
1179     for (i = 0; i < block->options->len; i++) {
1180         opt = &g_array_index(block->options, wtap_option_t, i);
1181         if ((opt->option_id == OPT_CUSTOM_BIN_COPY) &&
1182             (opt->value.custom_opt.pen == PEN_NFLX) &&
1183             (opt->value.custom_opt.data.nflx_data.type == nflx_type)) {
1184             break;
1185         }
1186     }
1187     if (i == block->options->len) {
1188         return WTAP_OPTTYPE_NOT_FOUND;
1189     }
1190     if (nflx_custom_data_len < opt->value.custom_opt.data.nflx_data.custom_data_len) {
1191         return WTAP_OPTTYPE_TYPE_MISMATCH;
1192     }
1193     switch (nflx_type) {
1194     case NFLX_OPT_TYPE_VERSION: {
1195         guint32 *src, *dst;
1196 
1197         ws_assert(nflx_custom_data_len == sizeof(guint32));
1198         src = (guint32 *)opt->value.custom_opt.data.nflx_data.custom_data;
1199         dst = (guint32 *)nflx_custom_data;
1200         *dst = GUINT32_FROM_LE(*src);
1201         break;
1202     }
1203     case NFLX_OPT_TYPE_TCPINFO: {
1204         struct nflx_tcpinfo *src, *dst;
1205 
1206         ws_assert(nflx_custom_data_len == sizeof(struct nflx_tcpinfo));
1207         src = (struct nflx_tcpinfo *)opt->value.custom_opt.data.nflx_data.custom_data;
1208         dst = (struct nflx_tcpinfo *)nflx_custom_data;
1209         dst->tlb_tv_sec = GUINT64_FROM_LE(src->tlb_tv_sec);
1210         dst->tlb_tv_usec = GUINT64_FROM_LE(src->tlb_tv_usec);
1211         dst->tlb_ticks = GUINT32_FROM_LE(src->tlb_ticks);
1212         dst->tlb_sn = GUINT32_FROM_LE(src->tlb_sn);
1213         dst->tlb_stackid = src->tlb_stackid;
1214         dst->tlb_eventid = src->tlb_eventid;
1215         dst->tlb_eventflags = GUINT16_FROM_LE(src->tlb_eventflags);
1216         dst->tlb_errno = GINT32_FROM_LE(src->tlb_errno);
1217         dst->tlb_rxbuf_tls_sb_acc = GUINT32_FROM_LE(src->tlb_rxbuf_tls_sb_acc);
1218         dst->tlb_rxbuf_tls_sb_ccc = GUINT32_FROM_LE(src->tlb_rxbuf_tls_sb_ccc);
1219         dst->tlb_rxbuf_tls_sb_spare = GUINT32_FROM_LE(src->tlb_rxbuf_tls_sb_spare);
1220         dst->tlb_txbuf_tls_sb_acc = GUINT32_FROM_LE(src->tlb_txbuf_tls_sb_acc);
1221         dst->tlb_txbuf_tls_sb_ccc = GUINT32_FROM_LE(src->tlb_txbuf_tls_sb_ccc);
1222         dst->tlb_txbuf_tls_sb_spare = GUINT32_FROM_LE(src->tlb_txbuf_tls_sb_spare);
1223         dst->tlb_state = GINT32_FROM_LE(src->tlb_state);
1224         dst->tlb_starttime = GUINT32_FROM_LE(src->tlb_starttime);
1225         dst->tlb_iss = GUINT32_FROM_LE(src->tlb_iss);
1226         dst->tlb_flags = GUINT32_FROM_LE(src->tlb_flags);
1227         dst->tlb_snd_una = GUINT32_FROM_LE(src->tlb_snd_una);
1228         dst->tlb_snd_max = GUINT32_FROM_LE(src->tlb_snd_max);
1229         dst->tlb_snd_cwnd = GUINT32_FROM_LE(src->tlb_snd_cwnd);
1230         dst->tlb_snd_nxt = GUINT32_FROM_LE(src->tlb_snd_nxt);
1231         dst->tlb_snd_recover = GUINT32_FROM_LE(src->tlb_snd_recover);
1232         dst->tlb_snd_wnd = GUINT32_FROM_LE(src->tlb_snd_wnd);
1233         dst->tlb_snd_ssthresh = GUINT32_FROM_LE(src->tlb_snd_ssthresh);
1234         dst->tlb_srtt = GUINT32_FROM_LE(src->tlb_srtt);
1235         dst->tlb_rttvar = GUINT32_FROM_LE(src->tlb_rttvar);
1236         dst->tlb_rcv_up = GUINT32_FROM_LE(src->tlb_rcv_up);
1237         dst->tlb_rcv_adv = GUINT32_FROM_LE(src->tlb_rcv_adv);
1238         dst->tlb_flags2 = GUINT32_FROM_LE(src->tlb_flags2);
1239         dst->tlb_rcv_nxt = GUINT32_FROM_LE(src->tlb_rcv_nxt);
1240         dst->tlb_rcv_wnd = GUINT32_FROM_LE(src->tlb_rcv_wnd);
1241         dst->tlb_dupacks = GUINT32_FROM_LE(src->tlb_dupacks);
1242         dst->tlb_segqlen = GINT32_FROM_LE(src->tlb_segqlen);
1243         dst->tlb_snd_numholes = GINT32_FROM_LE(src->tlb_snd_numholes);
1244         dst->tlb_flex1 = GUINT32_FROM_LE(src->tlb_flex1);
1245         dst->tlb_flex2 = GUINT32_FROM_LE(src->tlb_flex2);
1246         dst->tlb_fbyte_in = GUINT32_FROM_LE(src->tlb_fbyte_in);
1247         dst->tlb_fbyte_out = GUINT32_FROM_LE(src->tlb_fbyte_out);
1248         dst->tlb_snd_scale = src->tlb_snd_scale;
1249         dst->tlb_rcv_scale = src->tlb_rcv_scale;
1250         for (i = 0; i < 3; i++) {
1251             dst->_pad[i] = src->_pad[i];
1252         }
1253         dst->tlb_stackinfo_bbr_cur_del_rate = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_cur_del_rate);
1254         dst->tlb_stackinfo_bbr_delRate = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_delRate);
1255         dst->tlb_stackinfo_bbr_rttProp = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_rttProp);
1256         dst->tlb_stackinfo_bbr_bw_inuse = GUINT64_FROM_LE(src->tlb_stackinfo_bbr_bw_inuse);
1257         dst->tlb_stackinfo_bbr_inflight = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_inflight);
1258         dst->tlb_stackinfo_bbr_applimited = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_applimited);
1259         dst->tlb_stackinfo_bbr_delivered = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_delivered);
1260         dst->tlb_stackinfo_bbr_timeStamp = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_timeStamp);
1261         dst->tlb_stackinfo_bbr_epoch = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_epoch);
1262         dst->tlb_stackinfo_bbr_lt_epoch = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_lt_epoch);
1263         dst->tlb_stackinfo_bbr_pkts_out = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_pkts_out);
1264         dst->tlb_stackinfo_bbr_flex1 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex1);
1265         dst->tlb_stackinfo_bbr_flex2 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex2);
1266         dst->tlb_stackinfo_bbr_flex3 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex3);
1267         dst->tlb_stackinfo_bbr_flex4 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex4);
1268         dst->tlb_stackinfo_bbr_flex5 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex5);
1269         dst->tlb_stackinfo_bbr_flex6 = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_flex6);
1270         dst->tlb_stackinfo_bbr_lost = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_lost);
1271         dst->tlb_stackinfo_bbr_pacing_gain = GUINT16_FROM_LE(src->tlb_stackinfo_bbr_lost);
1272         dst->tlb_stackinfo_bbr_cwnd_gain = GUINT16_FROM_LE(src->tlb_stackinfo_bbr_lost);
1273         dst->tlb_stackinfo_bbr_flex7 = GUINT16_FROM_LE(src->tlb_stackinfo_bbr_flex7);
1274         dst->tlb_stackinfo_bbr_bbr_state = src->tlb_stackinfo_bbr_bbr_state;
1275         dst->tlb_stackinfo_bbr_bbr_substate = src->tlb_stackinfo_bbr_bbr_substate;
1276         dst->tlb_stackinfo_bbr_inhpts = src->tlb_stackinfo_bbr_inhpts;
1277         dst->tlb_stackinfo_bbr_ininput = src->tlb_stackinfo_bbr_ininput;
1278         dst->tlb_stackinfo_bbr_use_lt_bw = src->tlb_stackinfo_bbr_use_lt_bw;
1279         dst->tlb_stackinfo_bbr_flex8 = src->tlb_stackinfo_bbr_flex8;
1280         dst->tlb_stackinfo_bbr_pkt_epoch = GUINT32_FROM_LE(src->tlb_stackinfo_bbr_pkt_epoch);
1281         dst->tlb_len = GUINT32_FROM_LE(src->tlb_len);
1282         break;
1283     }
1284     case NFLX_OPT_TYPE_DUMPINFO: {
1285         struct nflx_dumpinfo *src, *dst;
1286 
1287         ws_assert(nflx_custom_data_len == sizeof(struct nflx_dumpinfo));
1288         src = (struct nflx_dumpinfo *)opt->value.custom_opt.data.nflx_data.custom_data;
1289         dst = (struct nflx_dumpinfo *)nflx_custom_data;
1290         dst->tlh_version = GUINT32_FROM_LE(src->tlh_version);
1291         dst->tlh_type = GUINT32_FROM_LE(src->tlh_type);
1292         dst->tlh_length = GUINT64_FROM_LE(src->tlh_length);
1293         dst->tlh_ie_fport = src->tlh_ie_fport;
1294         dst->tlh_ie_lport = src->tlh_ie_lport;
1295         for (i = 0; i < 4; i++) {
1296             dst->tlh_ie_faddr_addr32[i] = src->tlh_ie_faddr_addr32[i];
1297             dst->tlh_ie_laddr_addr32[i] = src->tlh_ie_laddr_addr32[i];
1298         }
1299         dst->tlh_ie_zoneid = src->tlh_ie_zoneid;
1300         dst->tlh_offset_tv_sec = GUINT64_FROM_LE(src->tlh_offset_tv_sec);
1301         dst->tlh_offset_tv_usec = GUINT64_FROM_LE(src->tlh_offset_tv_usec);
1302         memcpy(dst->tlh_id, src->tlh_id, 64);
1303         memcpy(dst->tlh_reason, src->tlh_reason, 32);
1304         memcpy(dst->tlh_tag, src->tlh_tag, 32);
1305         dst->tlh_af = src->tlh_af;
1306         memcpy(dst->_pad, src->_pad, 7);
1307         break;
1308     }
1309     case NFLX_OPT_TYPE_DUMPTIME: {
1310         guint64 *src, *dst;
1311 
1312         ws_assert(nflx_custom_data_len == sizeof(guint64));
1313         src = (guint64 *)opt->value.custom_opt.data.nflx_data.custom_data;
1314         dst = (guint64 *)nflx_custom_data;
1315         *dst = GUINT64_FROM_LE(*src);
1316         break;
1317     }
1318     case NFLX_OPT_TYPE_STACKNAME:
1319         ws_assert(nflx_custom_data_len >= 2);
1320         memcpy(nflx_custom_data, opt->value.custom_opt.data.nflx_data.custom_data, nflx_custom_data_len);
1321         break;
1322     default:
1323         return WTAP_OPTTYPE_NOT_FOUND;
1324     }
1325     return WTAP_OPTTYPE_SUCCESS;
1326 }
1327 
1328 wtap_opttype_return_val
wtap_block_add_custom_option(wtap_block_t block,guint option_id,guint32 pen,const char * custom_data,gsize custom_data_len)1329 wtap_block_add_custom_option(wtap_block_t block, guint option_id, guint32 pen, const char *custom_data, gsize custom_data_len)
1330 {
1331     wtap_opttype_return_val ret;
1332     wtap_option_t *opt;
1333 
1334     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &opt);
1335     if (ret != WTAP_OPTTYPE_SUCCESS)
1336         return ret;
1337     opt->value.custom_opt.pen = pen;
1338     opt->value.custom_opt.data.generic_data.custom_data_len = custom_data_len;
1339     opt->value.custom_opt.data.generic_data.custom_data = g_memdup2(custom_data, custom_data_len);
1340     return WTAP_OPTTYPE_SUCCESS;
1341 }
1342 
1343 wtap_opttype_return_val
wtap_block_add_if_filter_option(wtap_block_t block,guint option_id,if_filter_opt_t * value)1344 wtap_block_add_if_filter_option(wtap_block_t block, guint option_id, if_filter_opt_t* value)
1345 {
1346     wtap_opttype_return_val ret;
1347     wtap_option_t *opt;
1348 
1349     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IF_FILTER, &opt);
1350     if (ret != WTAP_OPTTYPE_SUCCESS)
1351         return ret;
1352     opt->value.if_filterval = if_filter_dup(value);
1353     return WTAP_OPTTYPE_SUCCESS;
1354 }
1355 
1356 wtap_opttype_return_val
wtap_block_set_if_filter_option_value(wtap_block_t block,guint option_id,if_filter_opt_t * value)1357 wtap_block_set_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value)
1358 {
1359     wtap_opttype_return_val ret;
1360     wtap_optval_t *optval;
1361     if_filter_opt_t prev_value;
1362 
1363     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IF_FILTER, &optval);
1364     if (ret != WTAP_OPTTYPE_SUCCESS)
1365         return ret;
1366     prev_value = optval->if_filterval;
1367     optval->if_filterval = if_filter_dup(value);
1368     /* Free after memory is duplicated in case structure was manipulated with a "get then set" */
1369     if_filter_free(&prev_value);
1370 
1371     return WTAP_OPTTYPE_SUCCESS;
1372 }
1373 
1374 wtap_opttype_return_val
wtap_block_get_if_filter_option_value(wtap_block_t block,guint option_id,if_filter_opt_t * value)1375 wtap_block_get_if_filter_option_value(wtap_block_t block, guint option_id, if_filter_opt_t* value)
1376 {
1377     wtap_opttype_return_val ret;
1378     wtap_optval_t *optval;
1379 
1380     ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IF_FILTER, &optval);
1381     if (ret != WTAP_OPTTYPE_SUCCESS)
1382         return ret;
1383     *value = optval->if_filterval;
1384     return WTAP_OPTTYPE_SUCCESS;
1385 }
1386 
1387 wtap_opttype_return_val
wtap_block_add_packet_verdict_option(wtap_block_t block,guint option_id,packet_verdict_opt_t * value)1388 wtap_block_add_packet_verdict_option(wtap_block_t block, guint option_id, packet_verdict_opt_t* value)
1389 {
1390     wtap_opttype_return_val ret;
1391     wtap_option_t *opt;
1392 
1393     ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_PACKET_VERDICT, &opt);
1394     if (ret != WTAP_OPTTYPE_SUCCESS)
1395         return ret;
1396     opt->value.packet_verdictval = packet_verdict_dup(value);
1397     return WTAP_OPTTYPE_SUCCESS;
1398 }
1399 
1400 wtap_opttype_return_val
wtap_block_set_nth_packet_verdict_option_value(wtap_block_t block,guint option_id,guint idx,packet_verdict_opt_t * value)1401 wtap_block_set_nth_packet_verdict_option_value(wtap_block_t block, guint option_id, guint idx, packet_verdict_opt_t* value)
1402 {
1403     wtap_opttype_return_val ret;
1404     wtap_optval_t *optval;
1405     packet_verdict_opt_t prev_value;
1406 
1407     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_PACKET_VERDICT, idx, &optval);
1408     if (ret != WTAP_OPTTYPE_SUCCESS)
1409         return ret;
1410     prev_value = optval->packet_verdictval;
1411     optval->packet_verdictval = packet_verdict_dup(value);
1412     /* Free after memory is duplicated in case structure was manipulated with a "get then set" */
1413     wtap_packet_verdict_free(&prev_value);
1414 
1415     return WTAP_OPTTYPE_SUCCESS;
1416 }
1417 
1418 wtap_opttype_return_val
wtap_block_get_nth_packet_verdict_option_value(wtap_block_t block,guint option_id,guint idx,packet_verdict_opt_t * value)1419 wtap_block_get_nth_packet_verdict_option_value(wtap_block_t block, guint option_id, guint idx, packet_verdict_opt_t* value)
1420 {
1421     wtap_opttype_return_val ret;
1422     wtap_optval_t *optval;
1423 
1424     ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
1425     if (ret != WTAP_OPTTYPE_SUCCESS)
1426         return ret;
1427     *value = optval->packet_verdictval;
1428     return WTAP_OPTTYPE_SUCCESS;
1429 }
1430 
1431 wtap_opttype_return_val
wtap_block_remove_option(wtap_block_t block,guint option_id)1432 wtap_block_remove_option(wtap_block_t block, guint option_id)
1433 {
1434     const wtap_opttype_t *opttype;
1435     guint i;
1436     wtap_option_t *opt;
1437 
1438     if (block == NULL) {
1439         return WTAP_OPTTYPE_BAD_BLOCK;
1440     }
1441 
1442     opttype = GET_OPTION_TYPE(block->info->options, option_id);
1443     if (opttype == NULL) {
1444         /* There's no option for this block with that option ID */
1445         return WTAP_OPTTYPE_NO_SUCH_OPTION;
1446     }
1447 
1448     /*
1449      * Can there be more than one instance of this option?
1450      */
1451     if (opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED) {
1452         /*
1453          * Yes.  You can't remove "the" value.
1454          */
1455         return WTAP_OPTTYPE_NUMBER_MISMATCH;
1456     }
1457 
1458     for (i = 0; i < block->options->len; i++) {
1459         opt = &g_array_index(block->options, wtap_option_t, i);
1460         if (opt->option_id == option_id) {
1461             /* Found it - free up the value */
1462             wtap_block_free_option(block, opt);
1463             /* Remove the option from the array of options */
1464             g_array_remove_index(block->options, i);
1465             return WTAP_OPTTYPE_SUCCESS;
1466         }
1467     }
1468 
1469     /* Didn't find the option */
1470     return WTAP_OPTTYPE_NOT_FOUND;
1471 }
1472 
1473 wtap_opttype_return_val
wtap_block_remove_nth_option_instance(wtap_block_t block,guint option_id,guint idx)1474 wtap_block_remove_nth_option_instance(wtap_block_t block, guint option_id,
1475                                       guint idx)
1476 {
1477     const wtap_opttype_t *opttype;
1478     guint i;
1479     wtap_option_t *opt;
1480     guint opt_idx;
1481 
1482     if (block == NULL) {
1483         return WTAP_OPTTYPE_BAD_BLOCK;
1484     }
1485 
1486     opttype = GET_OPTION_TYPE(block->info->options, option_id);
1487     if (opttype == NULL) {
1488         /* There's no option for this block with that option ID */
1489         return WTAP_OPTTYPE_NO_SUCH_OPTION;
1490     }
1491 
1492     /*
1493      * Can there be more than one instance of this option?
1494      */
1495     if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
1496         /*
1497          * No.
1498          */
1499         return WTAP_OPTTYPE_NUMBER_MISMATCH;
1500     }
1501 
1502     opt_idx = 0;
1503     for (i = 0; i < block->options->len; i++) {
1504         opt = &g_array_index(block->options, wtap_option_t, i);
1505         if (opt->option_id == option_id) {
1506             if (opt_idx == idx) {
1507                 /* Found it - free up the value */
1508                 wtap_block_free_option(block, opt);
1509                 /* Remove the option from the array of options */
1510                 g_array_remove_index(block->options, i);
1511                 return WTAP_OPTTYPE_SUCCESS;
1512             }
1513             opt_idx++;
1514         }
1515     }
1516 
1517     /* Didn't find the option */
1518     return WTAP_OPTTYPE_NOT_FOUND;
1519 }
1520 
shb_create(wtap_block_t block)1521 static void shb_create(wtap_block_t block)
1522 {
1523     wtapng_section_mandatory_t* section_mand = g_new(wtapng_section_mandatory_t, 1);
1524 
1525     section_mand->section_length = -1;
1526 
1527     block->mandatory_data = section_mand;
1528 }
1529 
shb_copy_mand(wtap_block_t dest_block,wtap_block_t src_block)1530 static void shb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
1531 {
1532     memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_section_mandatory_t));
1533 }
1534 
nrb_create(wtap_block_t block)1535 static void nrb_create(wtap_block_t block)
1536 {
1537     block->mandatory_data = NULL;
1538 }
1539 
isb_create(wtap_block_t block)1540 static void isb_create(wtap_block_t block)
1541 {
1542     block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1);
1543 }
1544 
isb_copy_mand(wtap_block_t dest_block,wtap_block_t src_block)1545 static void isb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
1546 {
1547     memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t));
1548 }
1549 
idb_create(wtap_block_t block)1550 static void idb_create(wtap_block_t block)
1551 {
1552     block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1);
1553 }
1554 
idb_free_mand(wtap_block_t block)1555 static void idb_free_mand(wtap_block_t block)
1556 {
1557     guint j;
1558     wtap_block_t if_stats;
1559     wtapng_if_descr_mandatory_t* mand = (wtapng_if_descr_mandatory_t*)block->mandatory_data;
1560 
1561     for(j = 0; j < mand->num_stat_entries; j++) {
1562         if_stats = g_array_index(mand->interface_statistics, wtap_block_t, j);
1563         wtap_block_unref(if_stats);
1564     }
1565 
1566     if (mand->interface_statistics)
1567         g_array_free(mand->interface_statistics, TRUE);
1568 }
1569 
idb_copy_mand(wtap_block_t dest_block,wtap_block_t src_block)1570 static void idb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
1571 {
1572     guint j;
1573     wtap_block_t src_if_stats, dest_if_stats;
1574     wtapng_if_descr_mandatory_t *src_mand = (wtapng_if_descr_mandatory_t*)src_block->mandatory_data,
1575                                 *dest_mand = (wtapng_if_descr_mandatory_t*)dest_block->mandatory_data;
1576 
1577     /* Need special consideration for copying of the interface_statistics member */
1578     if (dest_mand->num_stat_entries != 0)
1579         g_array_free(dest_mand->interface_statistics, TRUE);
1580 
1581     memcpy(dest_mand, src_mand, sizeof(wtapng_if_descr_mandatory_t));
1582     if (src_mand->num_stat_entries != 0)
1583     {
1584         dest_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
1585         for (j = 0; j < src_mand->num_stat_entries; j++)
1586         {
1587             src_if_stats = g_array_index(src_mand->interface_statistics, wtap_block_t, j);
1588             dest_if_stats = wtap_block_make_copy(src_if_stats);
1589             dest_mand->interface_statistics = g_array_append_val(dest_mand->interface_statistics, dest_if_stats);
1590         }
1591     }
1592 }
1593 
dsb_create(wtap_block_t block)1594 static void dsb_create(wtap_block_t block)
1595 {
1596     block->mandatory_data = g_new0(wtapng_dsb_mandatory_t, 1);
1597 }
1598 
dsb_free_mand(wtap_block_t block)1599 static void dsb_free_mand(wtap_block_t block)
1600 {
1601     wtapng_dsb_mandatory_t *mand = (wtapng_dsb_mandatory_t *)block->mandatory_data;
1602     g_free(mand->secrets_data);
1603 }
1604 
dsb_copy_mand(wtap_block_t dest_block,wtap_block_t src_block)1605 static void dsb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
1606 {
1607     wtapng_dsb_mandatory_t *src = (wtapng_dsb_mandatory_t *)src_block->mandatory_data;
1608     wtapng_dsb_mandatory_t *dst = (wtapng_dsb_mandatory_t *)dest_block->mandatory_data;
1609     dst->secrets_type = src->secrets_type;
1610     dst->secrets_len = src->secrets_len;
1611     g_free(dst->secrets_data);
1612     dst->secrets_data = (guint8 *)g_memdup2(src->secrets_data, src->secrets_len);
1613 }
1614 
pkt_create(wtap_block_t block)1615 static void pkt_create(wtap_block_t block)
1616 {
1617     /* Commented out for now, there's no mandatory data that isn't handled by
1618      * Wireshark in other ways.
1619      */
1620     //block->mandatory_data = g_new0(wtapng_packet_mandatory_t, 1);
1621 
1622     /* Ensure this is null, so when g_free is called on it, it simply returns */
1623     block->mandatory_data = NULL;
1624 }
1625 
cb_create(wtap_block_t block)1626 static void cb_create(wtap_block_t block)
1627 {
1628     /* Ensure this is null, so when g_free is called on it, it simply returns */
1629     block->mandatory_data = NULL;
1630 }
1631 
wtap_opttypes_initialize(void)1632 void wtap_opttypes_initialize(void)
1633 {
1634     static wtap_blocktype_t shb_block = {
1635         WTAP_BLOCK_SECTION,     /* block_type */
1636         "SHB",                  /* name */
1637         "Section Header Block", /* description */
1638         shb_create,             /* create */
1639         NULL,                   /* free_mand */
1640         shb_copy_mand,          /* copy_mand */
1641         NULL                    /* options */
1642     };
1643     static const wtap_opttype_t shb_hardware = {
1644         "hardware",
1645         "SHB Hardware",
1646         WTAP_OPTTYPE_STRING,
1647         0
1648     };
1649     static const wtap_opttype_t shb_os = {
1650         "os",
1651         "SHB Operating System",
1652         WTAP_OPTTYPE_STRING,
1653         0
1654     };
1655     static const wtap_opttype_t shb_userappl = {
1656         "user_appl",
1657         "SHB User Application",
1658         WTAP_OPTTYPE_STRING,
1659         0
1660     };
1661 
1662     static wtap_blocktype_t idb_block = {
1663         WTAP_BLOCK_IF_ID_AND_INFO,     /* block_type */
1664         "IDB",                         /* name */
1665         "Interface Description Block", /* description */
1666         idb_create,                    /* create */
1667         idb_free_mand,                 /* free_mand */
1668         idb_copy_mand,                 /* copy_mand */
1669         NULL                           /* options */
1670     };
1671     static const wtap_opttype_t if_name = {
1672         "name",
1673         "IDB Name",
1674         WTAP_OPTTYPE_STRING,
1675         0
1676     };
1677     static const wtap_opttype_t if_description = {
1678         "description",
1679         "IDB Description",
1680         WTAP_OPTTYPE_STRING,
1681         0
1682     };
1683     static const wtap_opttype_t if_speed = {
1684         "speed",
1685         "IDB Speed",
1686         WTAP_OPTTYPE_UINT64,
1687         0
1688     };
1689     static const wtap_opttype_t if_tsresol = {
1690         "tsresol",
1691         "IDB Time Stamp Resolution",
1692         WTAP_OPTTYPE_UINT8, /* XXX - signed? */
1693         0
1694     };
1695     static const wtap_opttype_t if_filter = {
1696         "filter",
1697         "IDB Filter",
1698         WTAP_OPTTYPE_IF_FILTER,
1699         0
1700     };
1701     static const wtap_opttype_t if_os = {
1702         "os",
1703         "IDB Operating System",
1704         WTAP_OPTTYPE_STRING,
1705         0
1706     };
1707     static const wtap_opttype_t if_fcslen = {
1708         "fcslen",
1709         "IDB FCS Length",
1710         WTAP_OPTTYPE_UINT8,
1711         0
1712     };
1713     static const wtap_opttype_t if_hardware = {
1714         "hardware",
1715         "IDB Hardware",
1716         WTAP_OPTTYPE_STRING,
1717         0
1718     };
1719 
1720     static wtap_blocktype_t dsb_block = {
1721         WTAP_BLOCK_DECRYPTION_SECRETS,
1722         "DSB",
1723         "Decryption Secrets Block",
1724         dsb_create,
1725         dsb_free_mand,
1726         dsb_copy_mand,
1727         NULL
1728     };
1729 
1730     static wtap_blocktype_t nrb_block = {
1731         WTAP_BLOCK_NAME_RESOLUTION, /* block_type */
1732         "NRB",                      /* name */
1733         "Name Resolution Block",    /* description */
1734         nrb_create,                 /* create */
1735         NULL,                       /* free_mand */
1736         NULL,                       /* copy_mand */
1737         NULL                        /* options */
1738     };
1739     static const wtap_opttype_t ns_dnsname = {
1740         "dnsname",
1741         "NRB DNS server name",
1742         WTAP_OPTTYPE_STRING,
1743         0
1744     };
1745     static const wtap_opttype_t ns_dnsIP4addr = {
1746         "dnsIP4addr",
1747         "NRB DNS server IPv4 address",
1748         WTAP_OPTTYPE_IPv4,
1749         0
1750     };
1751     static const wtap_opttype_t ns_dnsIP6addr = {
1752         "dnsIP6addr",
1753         "NRB DNS server IPv6 address",
1754         WTAP_OPTTYPE_IPv6,
1755         0
1756     };
1757 
1758     static wtap_blocktype_t isb_block = {
1759         WTAP_BLOCK_IF_STATISTICS,     /* block_type */
1760         "ISB",                        /* name */
1761         "Interface Statistics Block", /* description */
1762         isb_create,                   /* create */
1763         NULL,                         /* free_mand */
1764         isb_copy_mand,                /* copy_mand */
1765         NULL                          /* options */
1766     };
1767     static const wtap_opttype_t isb_starttime = {
1768         "starttime",
1769         "ISB Start Time",
1770         WTAP_OPTTYPE_UINT64,
1771         0
1772     };
1773     static const wtap_opttype_t isb_endtime = {
1774         "endtime",
1775         "ISB End Time",
1776         WTAP_OPTTYPE_UINT64,
1777         0
1778     };
1779     static const wtap_opttype_t isb_ifrecv = {
1780         "ifrecv",
1781         "ISB Received Packets",
1782         WTAP_OPTTYPE_UINT64,
1783         0
1784     };
1785     static const wtap_opttype_t isb_ifdrop = {
1786         "ifdrop",
1787         "ISB Dropped Packets",
1788         WTAP_OPTTYPE_UINT64,
1789         0
1790     };
1791     static const wtap_opttype_t isb_filteraccept = {
1792         "filteraccept",
1793         "ISB Packets Accepted By Filter",
1794         WTAP_OPTTYPE_UINT64,
1795         0
1796     };
1797     static const wtap_opttype_t isb_osdrop = {
1798         "osdrop",
1799         "ISB Packets Dropped By The OS",
1800         WTAP_OPTTYPE_UINT64,
1801         0
1802     };
1803     static const wtap_opttype_t isb_usrdeliv = {
1804         "usrdeliv",
1805         "ISB Packets Delivered To The User",
1806         WTAP_OPTTYPE_UINT64,
1807         0
1808     };
1809 
1810     static wtap_blocktype_t pkt_block = {
1811         WTAP_BLOCK_PACKET,            /* block_type */
1812         "EPB/SPB/PB",                 /* name */
1813         "Packet Block",               /* description */
1814         pkt_create,                   /* create */
1815         NULL,                         /* free_mand */
1816         NULL,                         /* copy_mand */
1817         NULL                          /* options */
1818     };
1819     static const wtap_opttype_t pkt_flags = {
1820         "flags",
1821         "Link-layer flags",
1822         WTAP_OPTTYPE_UINT32,
1823         0
1824     };
1825     static const wtap_opttype_t pkt_dropcount = {
1826         "dropcount",
1827         "Packets Dropped since last packet",
1828         WTAP_OPTTYPE_UINT64,
1829         0
1830     };
1831     static const wtap_opttype_t pkt_id = {
1832         "packetid",
1833         "Unique Packet Identifier",
1834         WTAP_OPTTYPE_UINT64,
1835         0
1836     };
1837     static const wtap_opttype_t pkt_queue = {
1838         "queue",
1839         "Queue ID in which packet was received",
1840         WTAP_OPTTYPE_UINT32,
1841         0
1842     };
1843     static const wtap_opttype_t pkt_hash = {
1844         "hash",
1845         "Hash of packet data",
1846         WTAP_OPTTYPE_BYTES,  // TODO: replace with a pkt_hash_opt_t
1847         WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
1848     };
1849     static const wtap_opttype_t pkt_verdict = {
1850         "verdict",
1851         "Packet Verdict",
1852         WTAP_OPTTYPE_PACKET_VERDICT,
1853         WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED
1854     };
1855 
1856     static wtap_blocktype_t cb_block = {
1857         WTAP_BLOCK_CUSTOM,            /* block_type */
1858         "CB",                         /* name */
1859         "Packet Block",               /* description */
1860         cb_create,                    /* create */
1861         NULL,                         /* free_mand */
1862         NULL,                         /* copy_mand */
1863         NULL                          /* options */
1864     };
1865 
1866     /*
1867      * Register the SHB and the options that can appear in it.
1868      */
1869     wtap_opttype_block_register(&shb_block);
1870     wtap_opttype_option_register(&shb_block, OPT_SHB_HARDWARE, &shb_hardware);
1871     wtap_opttype_option_register(&shb_block, OPT_SHB_OS, &shb_os);
1872     wtap_opttype_option_register(&shb_block, OPT_SHB_USERAPPL, &shb_userappl);
1873 
1874     /*
1875      * Register the IDB and the options that can appear in it.
1876      */
1877     wtap_opttype_block_register(&idb_block);
1878     wtap_opttype_option_register(&idb_block, OPT_IDB_NAME, &if_name);
1879     wtap_opttype_option_register(&idb_block, OPT_IDB_DESCRIPTION, &if_description);
1880     wtap_opttype_option_register(&idb_block, OPT_IDB_SPEED, &if_speed);
1881     wtap_opttype_option_register(&idb_block, OPT_IDB_TSRESOL, &if_tsresol);
1882     wtap_opttype_option_register(&idb_block, OPT_IDB_FILTER, &if_filter);
1883     wtap_opttype_option_register(&idb_block, OPT_IDB_OS, &if_os);
1884     wtap_opttype_option_register(&idb_block, OPT_IDB_FCSLEN, &if_fcslen);
1885     wtap_opttype_option_register(&idb_block, OPT_IDB_HARDWARE, &if_hardware);
1886 
1887     /*
1888      * Register the NRB and the options that can appear in it.
1889      */
1890     wtap_opttype_block_register(&nrb_block);
1891     wtap_opttype_option_register(&nrb_block, OPT_NS_DNSNAME, &ns_dnsname);
1892     wtap_opttype_option_register(&nrb_block, OPT_NS_DNSIP4ADDR, &ns_dnsIP4addr);
1893     wtap_opttype_option_register(&nrb_block, OPT_NS_DNSIP6ADDR, &ns_dnsIP6addr);
1894 
1895     /*
1896      * Register the ISB and the options that can appear in it.
1897      */
1898     wtap_opttype_block_register(&isb_block);
1899     wtap_opttype_option_register(&isb_block, OPT_ISB_STARTTIME, &isb_starttime);
1900     wtap_opttype_option_register(&isb_block, OPT_ISB_ENDTIME, &isb_endtime);
1901     wtap_opttype_option_register(&isb_block, OPT_ISB_IFRECV, &isb_ifrecv);
1902     wtap_opttype_option_register(&isb_block, OPT_ISB_IFDROP, &isb_ifdrop);
1903     wtap_opttype_option_register(&isb_block, OPT_ISB_FILTERACCEPT, &isb_filteraccept);
1904     wtap_opttype_option_register(&isb_block, OPT_ISB_OSDROP, &isb_osdrop);
1905     wtap_opttype_option_register(&isb_block, OPT_ISB_USRDELIV, &isb_usrdeliv);
1906 
1907     /*
1908      * Register the DSB, currently no options are defined.
1909      */
1910     wtap_opttype_block_register(&dsb_block);
1911 
1912     /*
1913      * Register EPB/SPB/PB and the options that can appear in it/them.
1914      * NB: Simple Packet Blocks have no options.
1915      * NB: obsolete Packet Blocks have dropcount as a mandatory member instead
1916      * of an option.
1917      */
1918     wtap_opttype_block_register(&pkt_block);
1919     wtap_opttype_option_register(&pkt_block, OPT_PKT_FLAGS, &pkt_flags);
1920     wtap_opttype_option_register(&pkt_block, OPT_PKT_DROPCOUNT, &pkt_dropcount);
1921     wtap_opttype_option_register(&pkt_block, OPT_PKT_PACKETID, &pkt_id);
1922     wtap_opttype_option_register(&pkt_block, OPT_PKT_QUEUE, &pkt_queue);
1923     wtap_opttype_option_register(&pkt_block, OPT_PKT_HASH, &pkt_hash);
1924     wtap_opttype_option_register(&pkt_block, OPT_PKT_VERDICT, &pkt_verdict);
1925 
1926     /*
1927      * Register the CB and the options that can appear in it.
1928      */
1929     wtap_opttype_block_register(&cb_block);
1930 
1931 #ifdef DEBUG_COUNT_REFS
1932     memset(blocks_active, 0, sizeof(blocks_active));
1933 #endif
1934 }
1935 
wtap_opttypes_cleanup(void)1936 void wtap_opttypes_cleanup(void)
1937 {
1938     guint block_type;
1939 #ifdef DEBUG_COUNT_REFS
1940     guint i;
1941     guint cellno;
1942     guint bitno;
1943     guint8 mask;
1944 #endif /* DEBUG_COUNT_REFS */
1945 
1946     for (block_type = (guint)WTAP_BLOCK_SECTION;
1947          block_type < (guint)MAX_WTAP_BLOCK_TYPE_VALUE; block_type++) {
1948         if (blocktype_list[block_type]) {
1949             if (blocktype_list[block_type]->options)
1950                 g_hash_table_destroy(blocktype_list[block_type]->options);
1951             blocktype_list[block_type] = NULL;
1952         }
1953     }
1954 
1955 #ifdef DEBUG_COUNT_REFS
1956     for (i = 0 ; i < block_count; i++) {
1957         cellno = i / 8;
1958         bitno = i % 8;
1959         mask = 1 << bitno;
1960 
1961         if ((blocks_active[cellno] & mask) == mask) {
1962             wtap_debug("wtap_opttypes_cleanup: orphaned block #%d", i);
1963         }
1964     }
1965 #endif /* DEBUG_COUNT_REFS */
1966 }
1967