Bug Summary

File:builds/wireshark/wireshark/wiretap/pcapng.c
Warning:line 3135, column 9
Value stored to 'handler' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pcapng.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/libxml2 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D wiretap_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -I /builds/wireshark/wireshark/build/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D wiretap_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -I /builds/wireshark/wireshark/build/wiretap -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/libxml2 -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/wiretap/pcapng.c -o /builds/wireshark/wireshark/sbout/2025-06-27-100304-3847-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-06-27-100304-3847-1 -x c /builds/wireshark/wireshark/wiretap/pcapng.c
1/* pcapng.c
2 *
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5 *
6 * File format support for pcapng file format
7 * Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12/* File format specification:
13 * https://github.com/pcapng/pcapng
14 * Related Wiki page:
15 * https://gitlab.com/wireshark/wireshark/-/wikis/Development/PcapNg
16 */
17
18#include "config.h"
19#define WS_LOG_DOMAIN"Wiretap" LOG_DOMAIN_WIRETAP"Wiretap"
20#include "pcapng.h"
21
22#include "wtap_opttypes.h"
23
24#include <stdlib.h>
25#include <string.h>
26#include <errno(*__errno_location ()).h>
27
28#include <wsutil/application_flavor.h>
29#include <wsutil/wslog.h>
30#include <wsutil/strtoi.h>
31#include <wsutil/glib-compat.h>
32#include <wsutil/ws_assert.h>
33#include <wsutil/ws_roundup.h>
34#include <wsutil/ws_padding_to.h>
35#include <wsutil/unicode-utils.h>
36
37#include "wtap-int.h"
38#include "file_wrappers.h"
39#include "required_file_handlers.h"
40#include "pcap-common.h"
41#include "pcap-encap.h"
42#include "pcapng_module.h"
43#include "secrets-types.h"
44
45static bool_Bool
46pcapng_read(wtap *wth, wtap_rec *rec, int *err,
47 char **err_info, int64_t *data_offset);
48static bool_Bool
49pcapng_seek_read(wtap *wth, int64_t seek_off,
50 wtap_rec *rec, int *err, char **err_info);
51static void
52pcapng_close(wtap *wth);
53
54static bool_Bool
55pcapng_encap_is_ft_specific(int encap);
56
57static bool_Bool
58pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_block_t int_data,
59 int *err, char **err_info);
60
61/*
62 * Minimum block size = size of block header + size of block trailer.
63 */
64#define MIN_BLOCK_SIZE((uint32_t)(sizeof(pcapng_block_header_t) + sizeof(uint32_t))
)
((uint32_t)(sizeof(pcapng_block_header_t) + sizeof(uint32_t)))
65
66/*
67 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
68 */
69#define MIN_SHB_SIZE((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_section_header_block_t)))
((uint32_t)(MIN_BLOCK_SIZE((uint32_t)(sizeof(pcapng_block_header_t) + sizeof(uint32_t))
)
+ sizeof(pcapng_section_header_block_t)))
70
71/* pcapng: packet block file encoding (obsolete) */
72typedef struct pcapng_packet_block_s {
73 uint16_t interface_id;
74 uint16_t drops_count;
75 uint32_t timestamp_high;
76 uint32_t timestamp_low;
77 uint32_t captured_len;
78 uint32_t packet_len;
79 /* ... Packet Data ... */
80 /* ... Padding ... */
81 /* ... Options ... */
82} pcapng_packet_block_t;
83
84/* pcapng: enhanced packet block file encoding */
85typedef struct pcapng_enhanced_packet_block_s {
86 uint32_t interface_id;
87 uint32_t timestamp_high;
88 uint32_t timestamp_low;
89 uint32_t captured_len;
90 uint32_t packet_len;
91 /* ... Packet Data ... */
92 /* ... Padding ... */
93 /* ... Options ... */
94} pcapng_enhanced_packet_block_t;
95
96/*
97 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
98 */
99#define MIN_EPB_SIZE((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t)))
((uint32_t)(MIN_BLOCK_SIZE((uint32_t)(sizeof(pcapng_block_header_t) + sizeof(uint32_t))
)
+ sizeof(pcapng_enhanced_packet_block_t)))
100
101/* pcapng: simple packet block file encoding */
102typedef struct pcapng_simple_packet_block_s {
103 uint32_t packet_len;
104 /* ... Packet Data ... */
105 /* ... Padding ... */
106} pcapng_simple_packet_block_t;
107
108/* pcapng: name resolution block file encoding */
109typedef struct pcapng_name_resolution_block_s {
110 uint16_t record_type;
111 uint16_t record_len;
112 /* ... Record ... */
113} pcapng_name_resolution_block_t;
114
115/* pcapng: custom block file encoding */
116typedef struct pcapng_custom_block_s {
117 uint32_t pen;
118 /* Custom data and options */
119} pcapng_custom_block_t;
120
121/*
122 * We require __REALTIME_TIMESTAMP in the Journal Export Format reader in
123 * order to set each packet timestamp. Require it here as well, although
124 * it's not strictly necessary.
125 */
126#define SDJ__REALTIME_TIMESTAMP"__REALTIME_TIMESTAMP=" "__REALTIME_TIMESTAMP="
127#define MIN_SYSTEMD_JOURNAL_EXPORT_ENTRY_SIZE23 23 // "__REALTIME_TIMESTAMP=0\n"
128
129/* pcapng: common option header file encoding for every option type */
130typedef struct pcapng_option_header_s {
131 uint16_t option_code;
132 uint16_t option_length;
133 /* ... x bytes Option Body ... */
134 /* ... Padding ... */
135} pcapng_option_header_t;
136
137struct pcapng_option {
138 uint16_t type;
139 uint16_t value_length;
140};
141
142/* MSBit of option code means "local type" */
143#define OPT_LOCAL_FLAG0x8000 0x8000
144
145/* OPT_EPB_VERDICT sub-types */
146#define OPT_VERDICT_TYPE_HW0 0
147#define OPT_VERDICT_TYPE_TC1 1
148#define OPT_VERDICT_TYPE_XDP2 2
149
150/* OPT_EPB_HASH sub-types */
151#define OPT_HASH_2COMP0 0
152#define OPT_HASH_XOR1 1
153#define OPT_HASH_CRC322 2
154#define OPT_HASH_MD53 3
155#define OPT_HASH_SHA14 4
156#define OPT_HASH_TOEPLITZ5 5
157
158/*
159 * In order to keep from trying to allocate large chunks of memory,
160 * which could either fail or, even if it succeeds, chew up so much
161 * address space or memory+backing store as not to leave room for
162 * anything else, we impose upper limits on the size of blocks we're
163 * willing to handle.
164 *
165 * We pick a limit of an EPB with a maximum-sized D-Bus packet and 128 KiB
166 * worth of options; we use the maximum D-Bus packet size as that's larger
167 * than the maximum packet size for other link-layer types, and the maximum
168 * packet size for other link-layer types is currently small enough that
169 * the resulting block size would be less than the previous 16 MiB limit.
170 */
171#define MAX_BLOCK_SIZE(((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t))) + (128U
*1024U*1024U) + 131072)
(MIN_EPB_SIZE((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t)))
+ WTAP_MAX_PACKET_SIZE_DBUS(128U*1024U*1024U) + 131072)
172
173/* Note: many of the defined structures for block data are defined in wtap.h */
174
175/* Packet data - used for both Enhanced Packet Block and the obsolete Packet Block data */
176typedef struct wtapng_packet_s {
177 /* mandatory */
178 uint32_t ts_high; /* seconds since 1.1.1970 */
179 uint32_t ts_low; /* fraction of seconds, depends on if_tsresol */
180 uint32_t cap_len; /* data length in the file */
181 uint32_t packet_len; /* data length on the wire */
182 uint32_t interface_id; /* identifier of the interface. */
183 uint16_t drops_count; /* drops count, only valid for packet block */
184 /* 0xffff if information no available */
185 /* pack_hash */
186 /* XXX - put the packet data / pseudo_header here as well? */
187} wtapng_packet_t;
188
189/* Simple Packet data */
190typedef struct wtapng_simple_packet_s {
191 /* mandatory */
192 uint32_t cap_len; /* data length in the file */
193 uint32_t packet_len; /* data length on the wire */
194 /* XXX - put the packet data / pseudo_header here as well? */
195} wtapng_simple_packet_t;
196
197/* Interface data in private struct */
198typedef struct interface_info_s {
199 int wtap_encap;
200 uint32_t snap_len;
201 uint64_t time_units_per_second;
202 int tsprecision;
203 int64_t tsoffset;
204 int fcslen;
205} interface_info_t;
206
207typedef struct {
208 unsigned current_section_number; /**< Section number of the current section being read sequentially */
209 GArray *sections; /**< Sections found in the capture file. */
210} pcapng_t;
211
212/*
213 * Table for plugins to handle particular block types.
214 *
215 * A handler has a type, whether its internally handled and "read"
216 * and "write" routines.
217 *
218 * A "read" routine returns a block as a libwiretap record, filling
219 * in the wtap_rec structure with the appropriate record type and
220 * other information, and filling in the structure's Buffer with
221 * data for which there's no place in the wtap_rec structure.
222 *
223 * A "write" routine takes a libwiretap record and out a block.
224 */
225static GHashTable *block_handlers;
226
227void
228register_pcapng_block_type_information(pcapng_block_type_information_t* handler)
229{
230 if (handler == NULL((void*)0)) {
231 ws_warning("Attempt to register NULL plugin block type handler")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/pcapng.c"
, 231, __func__, "Attempt to register NULL plugin block type handler"
); } } while (0)
;
232 return;
233 }
234
235 /* Don't allow duplication of block types */
236 if (g_hash_table_lookup(block_handlers, GUINT_TO_POINTER(handler->type)((gpointer) (gulong) (handler->type))) != NULL((void*)0)) {
237 ws_warning("Attempt to register plugin for an existing block type 0x%08x not allowed",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/pcapng.c"
, 238, __func__, "Attempt to register plugin for an existing block type 0x%08x not allowed"
, handler->type); } } while (0)
238 handler->type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/pcapng.c"
, 238, __func__, "Attempt to register plugin for an existing block type 0x%08x not allowed"
, handler->type); } } while (0)
;
239 return;
240 }
241
242 g_hash_table_insert(block_handlers, GUINT_TO_POINTER(handler->type)((gpointer) (gulong) (handler->type)),
243 handler);
244}
245
246/*
247 * Tables for plugins to handle particular options for particular block
248 * types.
249 *
250 * An option has three handler routines:
251 *
252 * An option parser, used when reading an option from a file:
253 *
254 * The option parser is passed an indication of whether this section
255 * of the file is byte-swapped, the length of the option, the data of
256 * the option, a pointer to an error code, and a pointer to a pointer
257 * variable for an error string.
258 *
259 * It checks whether the length and option are valid, and, if they
260 * aren't, returns false, setting the error code to the appropriate
261 * error (normally WTAP_ERR_BAD_FILE) and the error string to an
262 * appropriate string indicating the problem.
263 *
264 * Otherwise, if this section of the file is byte-swapped, it byte-swaps
265 * multi-byte numerical values, so that it's in the host byte order.
266 *
267 * An option sizer, used when writing an option to a file:
268 *
269 * The option sizer is passed the option identifier for the option
270 * and a wtap_optval_t * that points to the data for the option.
271 *
272 * It calculates how many bytes the option's data requires, not
273 * including any padding bytes, and returns that value.
274 *
275 * An option writer, used when writing an option to a file:
276 *
277 * The option writer is passed a wtap_dumper * to which the
278 * option data should be written, the option identifier for
279 * the option, a wtap_optval_t * that points to the data for
280 * the option, and an int * into which an error code should
281 * be stored if an error occurs when writing the option.
282 *
283 * It returns a bool value of true if the attempt to
284 * write the option succeeds and false if the attempt to
285 * write the option gets an error.
286 */
287
288typedef struct {
289 option_parser parser;
290 option_sizer sizer;
291 option_writer writer;
292} option_handler;
293
294static GHashTable *custom_enterprise_handlers;
295
296/* Return whether this block type is handled interally, or
297 * if it is returned to the caller in pcapng_read().
298 * This is used by pcapng_open() to decide if it can process
299 * the block.
300 * Note that for block types that are registered from plugins,
301 * we don't know the true answer without actually reading the block,
302 * or even if there is a fixed answer for all blocks of that type,
303 * so we err on the side of not processing.
304 */
305static bool_Bool
306get_block_type_internal(unsigned block_type)
307{
308 pcapng_block_type_information_t *handler;
309
310 handler = g_hash_table_lookup(block_handlers, GUINT_TO_POINTER(block_type)((gpointer) (gulong) (block_type)));
311
312 if (handler != NULL((void*)0))
313 return handler->internal;
314 else
315 return true1;
316}
317
318GHashTable *
319pcapng_create_option_handler_table(void)
320{
321 return g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL((void*)0), g_free);
322}
323
324static GHashTable *
325get_option_handlers(unsigned block_type)
326{
327 pcapng_block_type_information_t *block_handler;
328
329 block_handler = g_hash_table_lookup(block_handlers, GUINT_TO_POINTER(block_type)((gpointer) (gulong) (block_type)));
330 if (block_handler == NULL((void*)0)) {
331 /* No such block type. */
332 return NULL((void*)0);
333 }
334
335 if (block_handler->option_handlers == NULL((void*)0)) {
336 /*
337 * This block type doesn't support options other than
338 * those supported by all blocks.
339 */
340 return NULL((void*)0);
341 }
342
343 return block_handler->option_handlers;
344}
345
346void
347register_pcapng_option_handler(unsigned block_type, unsigned option_code,
348 option_parser parser,
349 option_sizer sizer,
350 option_writer writer)
351{
352 GHashTable *option_handlers;
353 option_handler *handler;
354
355 /*
356 * Get the table of option handlers for this block type.
357 */
358 option_handlers = get_option_handlers(block_type);
359
360 /*
361 * If there isn't one, the block only supports the standard options
362 * (if it supports options at all; the SPB doesn't).
363 */
364 if (option_handlers == NULL((void*)0))
365 return;
366
367 /*
368 * Is this combination already registered?
369 */
370 handler = (option_handler *)g_hash_table_lookup(option_handlers,
371 GUINT_TO_POINTER(option_code)((gpointer) (gulong) (option_code)));
372 if (handler != NULL((void*)0)) {
373 if (handler->parser == parser &&
374 handler->sizer == sizer &&
375 handler->writer == writer) {
376 /*
377 * Yes. This might be a case where multiple block types
378 * share the same table, and some code registers the same
379 * option for all of those blocks, which is OK. Just
380 * ignore it.
381 */
382 return;
383 }
384
385 /*
386 * No. XXX - report this.
387 */
388 return;
389 }
390
391 /*
392 * No - register it.
393 */
394 handler = g_new(option_handler, 1)((option_handler *) g_malloc_n ((1), sizeof (option_handler))
)
;
395 handler->parser = parser;
396 handler->sizer = sizer;
397 handler->writer = writer;
398 g_hash_table_insert(option_handlers,
399 GUINT_TO_POINTER(option_code)((gpointer) (gulong) (option_code)), handler);
400}
401
402void
403pcapng_add_cb_section_info_data(section_info_t *section_info,
404 uint32_t pen, void *data)
405{
406 g_hash_table_insert(section_info->custom_block_data,
407 GUINT_TO_POINTER(pen)((gpointer) (gulong) (pen)), data);
408}
409
410void *
411pcapng_get_cb_section_info_data(section_info_t *section_info, uint32_t pen,
412 const section_info_funcs_t *funcs)
413{
414 void *data;
415
416 if (section_info->custom_block_data == NULL((void*)0)) {
417 /*
418 * Create the table of custom block data for this section_info_t.
419 *
420 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
421 * so we use "g_direct_hash()" and "g_direct_equal()".
422 */
423 section_info->custom_block_data = g_hash_table_new_full(g_direct_hash,
424 g_direct_equal,
425 NULL((void*)0),
426 funcs->free);
427
428 /*
429 * The newly-created hash table is empty, so no point in looking
430 * for an element in it.
431 */
432 data = NULL((void*)0);
433 } else {
434 /*
435 * We have the hash table; look for the entry.
436 */
437 data = g_hash_table_lookup(section_info->custom_block_data,
438 GUINT_TO_POINTER(pen)((gpointer) (gulong) (pen)));
439 }
440 if (data == NULL((void*)0)) {
441 /*
442 * No entry found - create a new one, and add it to the
443 * hash table.
444 */
445 data = funcs->new();
446 g_hash_table_insert(section_info->custom_block_data,
447 GUINT_TO_POINTER(pen)((gpointer) (gulong) (pen)), data);
448 }
449 return data;
450}
451
452void *
453pcapng_get_lb_section_info_data(section_info_t *section_info,
454 uint32_t block_type,
455 const section_info_funcs_t *funcs)
456{
457 void *data;
458
459 if (section_info->local_block_data == NULL((void*)0)) {
460 /*
461 * Create the table of local block data for this section_info_t.
462 *
463 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
464 * so we use "g_direct_hash()" and "g_direct_equal()".
465 */
466 section_info->local_block_data = g_hash_table_new_full(g_direct_hash,
467 g_direct_equal,
468 NULL((void*)0),
469 funcs->free);
470
471 /*
472 * The newly-created hash table is empty, so no point in looking
473 * for an element in it.
474 */
475 data = NULL((void*)0);
476 } else {
477 /*
478 * We have the hash table; look for the entry.
479 */
480 data = g_hash_table_lookup(section_info->local_block_data,
481 GUINT_TO_POINTER(block_type)((gpointer) (gulong) (block_type)));
482 }
483 if (data == NULL((void*)0)) {
484 /*
485 * No entry found - create a new one, and add it to the
486 * hash table.
487 */
488 data = funcs->new();
489 g_hash_table_insert(section_info->local_block_data,
490 GUINT_TO_POINTER(block_type)((gpointer) (gulong) (block_type)), data);
491 }
492 return data;
493}
494
495void
496pcapng_process_uint8_option(wtapng_block_t *wblock,
497 uint16_t option_code, uint16_t option_length,
498 const uint8_t *option_content)
499{
500 if (option_length == 1) {
501 /*
502 * If this option can appear only once in a block, this call
503 * will fail on the second and later occurrences of the option;
504 * we silently ignore the failure.
505 */
506 wtap_block_add_uint8_option(wblock->block, option_code, option_content[0]);
507 }
508}
509
510void
511pcapng_process_uint32_option(wtapng_block_t *wblock,
512 section_info_t *section_info,
513 pcapng_opt_byte_order_e byte_order,
514 uint16_t option_code, uint16_t option_length,
515 const uint8_t *option_content)
516{
517 uint32_t uint32;
518
519 if (option_length == 4) {
520 /* Don't cast a uint8_t * into a uint32_t *--the
521 * uint8_t * may not point to something that's
522 * aligned correctly.
523 *
524 * XXX - options are aligned on 32-bit boundaries, so, while
525 * it may be true that 64-bit options aren't guaranteed to be
526 * aligned on 64-bit bounaries, it shouldn't be true that 32-bit
527 * options aren't guaranteed to be aligned on 32-bit boundaries.
528 */
529 memcpy(&uint32, option_content, sizeof(uint32_t));
530 switch (byte_order) {
531
532 case OPT_SECTION_BYTE_ORDER:
533 if (section_info->byte_swapped) {
534 uint32 = GUINT32_SWAP_LE_BE(uint32)(((guint32) ( (((guint32) (uint32) & (guint32) 0x000000ffU
) << 24) | (((guint32) (uint32) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (uint32) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (uint32) & (guint32) 0xff000000U
) >> 24))))
;
535 }
536 break;
537
538 case OPT_BIG_ENDIAN:
539 uint32 = GUINT32_FROM_BE(uint32)(((((guint32) ( (((guint32) (uint32) & (guint32) 0x000000ffU
) << 24) | (((guint32) (uint32) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (uint32) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (uint32) & (guint32) 0xff000000U
) >> 24))))))
;
540 break;
541
542 case OPT_LITTLE_ENDIAN:
543 uint32 = GUINT32_FROM_LE(uint32)(((guint32) (uint32)));
544 break;
545
546 default:
547 /*
548 * This should not happen - this is called by pcapng_process_options(),
549 * which returns an error for an invalid byte_order argument, and
550 * otherwise passes the known-to-be-valid byte_order argument to
551 * us.
552 *
553 * Just ignore the option.
554 */
555 return;
556 }
557
558 /*
559 * If this option can appear only once in a block, this call
560 * will fail on the second and later occurrences of the option;
561 * we silently ignore the failure.
562 */
563 wtap_block_add_uint32_option(wblock->block, option_code, uint32);
564 }
565}
566
567void
568pcapng_process_timestamp_option(wtapng_block_t *wblock,
569 section_info_t *section_info,
570 pcapng_opt_byte_order_e byte_order,
571 uint16_t option_code, uint16_t option_length,
572 const uint8_t *option_content)
573{
574 if (option_length == 8) {
575 uint32_t high, low;
576 uint64_t timestamp;
577
578 /* Don't cast a uint8_t * into a uint32_t *--the
579 * uint8_t * may not point to something that's
580 * aligned correctly.
581 */
582 memcpy(&high, option_content, sizeof(uint32_t));
583 memcpy(&low, option_content + sizeof(uint32_t), sizeof(uint32_t));
584 switch (byte_order) {
585
586 case OPT_SECTION_BYTE_ORDER:
587 if (section_info->byte_swapped) {
588 high = GUINT32_SWAP_LE_BE(high)(((guint32) ( (((guint32) (high) & (guint32) 0x000000ffU)
<< 24) | (((guint32) (high) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (high) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (high) & (guint32) 0xff000000U
) >> 24))))
;
589 low = GUINT32_SWAP_LE_BE(low)(((guint32) ( (((guint32) (low) & (guint32) 0x000000ffU) <<
24) | (((guint32) (low) & (guint32) 0x0000ff00U) <<
8) | (((guint32) (low) & (guint32) 0x00ff0000U) >>
8) | (((guint32) (low) & (guint32) 0xff000000U) >>
24))))
;
590 }
591 break;
592
593 case OPT_BIG_ENDIAN:
594 high = GUINT32_FROM_BE(high)(((((guint32) ( (((guint32) (high) & (guint32) 0x000000ffU
) << 24) | (((guint32) (high) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (high) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (high) & (guint32) 0xff000000U
) >> 24))))))
;
595 low = GUINT32_FROM_BE(low)(((((guint32) ( (((guint32) (low) & (guint32) 0x000000ffU
) << 24) | (((guint32) (low) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (low) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (low) & (guint32) 0xff000000U
) >> 24))))))
;
596 break;
597
598 case OPT_LITTLE_ENDIAN:
599 high = GUINT32_FROM_LE(high)(((guint32) (high)));
600 low = GUINT32_FROM_LE(low)(((guint32) (low)));
601 break;
602
603 default:
604 /*
605 * This should not happen - this is called by pcapng_process_options(),
606 * which returns an error for an invalid byte_order argument, and
607 * otherwise passes the known-to-be-valid byte_order argument to
608 * us.
609 *
610 * Just ignore the option.
611 */
612 return;
613 }
614 timestamp = (uint64_t)high;
615 timestamp <<= 32;
616 timestamp += (uint64_t)low;
617 /*
618 * If this option can appear only once in a block, this call
619 * will fail on the second and later occurrences of the option;
620 * we silently ignore the failure.
621 */
622 wtap_block_add_uint64_option(wblock->block, option_code, timestamp);
623 }
624}
625
626void
627pcapng_process_uint64_option(wtapng_block_t *wblock,
628 section_info_t *section_info,
629 pcapng_opt_byte_order_e byte_order,
630 uint16_t option_code, uint16_t option_length,
631 const uint8_t *option_content)
632{
633 uint64_t uint64;
634
635 if (option_length == 8) {
636 /* Don't cast a uint8_t * into a uint64_t *--the
637 * uint8_t * may not point to something that's
638 * aligned correctly.
639 */
640 memcpy(&uint64, option_content, sizeof(uint64_t));
641 switch (byte_order) {
642
643 case OPT_SECTION_BYTE_ORDER:
644 if (section_info->byte_swapped) {
645 uint64 = GUINT64_SWAP_LE_BE(uint64)(((guint64) ( (((guint64) (uint64) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (uint64) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (uint64) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (uint64) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (uint64) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (uint64) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (uint64) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (uint64) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
646 }
647 break;
648
649 case OPT_BIG_ENDIAN:
650 uint64 = GUINT64_FROM_BE(uint64)(((((guint64) ( (((guint64) (uint64) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (uint64) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (uint64) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (uint64) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (uint64) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (uint64) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (uint64) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (uint64) & (guint64) (0xff00000000000000UL
)) >> 56))))))
;
651 break;
652
653 case OPT_LITTLE_ENDIAN:
654 uint64 = GUINT64_FROM_LE(uint64)(((guint64) (uint64)));
655 break;
656
657 default:
658 /*
659 * This should not happen - this is called by pcapng_process_options(),
660 * which returns an error for an invalid byte_order argument, and
661 * otherwise passes the known-to-be-valid byte_order argument to
662 * us.
663 *
664 * Just ignore the option.
665 */
666 return;
667 }
668
669 /*
670 * If this option can appear only once in a block, this call
671 * will fail on the second and later occurrences of the option;
672 * we silently ignore the failure.
673 */
674 wtap_block_add_uint64_option(wblock->block, option_code, uint64);
675 }
676}
677
678void
679pcapng_process_int64_option(wtapng_block_t *wblock,
680 section_info_t *section_info,
681 pcapng_opt_byte_order_e byte_order,
682 uint16_t option_code, uint16_t option_length,
683 const uint8_t *option_content)
684{
685 int64_t int64;
686
687 if (option_length == 8) {
688 /* Don't cast a int8_t * into a int64_t *--the
689 * uint8_t * may not point to something that's
690 * aligned correctly.
691 */
692 memcpy(&int64, option_content, sizeof(int64_t));
693 switch (byte_order) {
694
695 case OPT_SECTION_BYTE_ORDER:
696 if (section_info->byte_swapped) {
697 int64 = GUINT64_SWAP_LE_BE(int64)(((guint64) ( (((guint64) (int64) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (int64) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (int64) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (int64) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (int64) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (int64) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (int64) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (int64) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
698 }
699 break;
700
701 case OPT_BIG_ENDIAN:
702 int64 = GUINT64_FROM_BE(int64)(((((guint64) ( (((guint64) (int64) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (int64) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (int64) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (int64) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (int64) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (int64) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (int64) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (int64) & (guint64) (0xff00000000000000UL
)) >> 56))))))
;
703 break;
704
705 case OPT_LITTLE_ENDIAN:
706 int64 = GUINT64_FROM_LE(int64)(((guint64) (int64)));
707 break;
708
709 default:
710 /*
711 * This should not happen - this is called by pcapng_process_options(),
712 * which returns an error for an invalid byte_order argument, and
713 * otherwise passes the known-to-be-valid byte_order argument to
714 * us.
715 *
716 * Just ignore the option.
717 */
718 return;
719 }
720
721 /*
722 * If this option can appear only once in a block, this call
723 * will fail on the second and later occurrences of the option;
724 * we silently ignore the failure.
725 */
726 wtap_block_add_int64_option(wblock->block, option_code, int64);
727 }
728}
729
730void
731pcapng_process_string_option(wtapng_block_t *wblock, uint16_t option_code,
732 uint16_t option_length, const uint8_t *option_content)
733{
734 const char *opt = (const char *)option_content;
735 size_t optlen = option_length;
736 char *str;
737
738 /* Validate UTF-8 encoding. */
739 str = ws_utf8_make_valid(NULL((void*)0), opt, optlen);
740
741 wtap_block_add_string_option_owned(wblock->block, option_code, str);
742}
743
744void
745pcapng_process_bytes_option(wtapng_block_t *wblock, uint16_t option_code,
746 uint16_t option_length, const uint8_t *option_content)
747{
748 wtap_block_add_bytes_option(wblock->block, option_code, (const char *)option_content, option_length);
749}
750
751static bool_Bool
752pcapng_process_custom_option_common(section_info_t *section_info,
753 uint16_t option_length,
754 const uint8_t *option_content,
755 pcapng_opt_byte_order_e byte_order,
756 uint32_t *pen,
757 int *err, char **err_info)
758{
759 if (option_length < 4) {
760 *err = WTAP_ERR_BAD_FILE-13;
761 *err_info = ws_strdup_printf("pcapng: option length (%d) too small for custom option",wmem_strdup_printf(((void*)0), "pcapng: option length (%d) too small for custom option"
, option_length)
762 option_length)wmem_strdup_printf(((void*)0), "pcapng: option length (%d) too small for custom option"
, option_length)
;
763 return false0;
764 }
765 memcpy(pen, option_content, sizeof(uint32_t));
766 switch (byte_order) {
767
768 case OPT_SECTION_BYTE_ORDER:
769 if (section_info->byte_swapped) {
770 *pen = GUINT32_SWAP_LE_BE(*pen)(((guint32) ( (((guint32) (*pen) & (guint32) 0x000000ffU)
<< 24) | (((guint32) (*pen) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (*pen) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (*pen) & (guint32) 0xff000000U
) >> 24))))
;
771 }
772 break;
773
774 case OPT_BIG_ENDIAN:
775 *pen = GUINT32_FROM_BE(*pen)(((((guint32) ( (((guint32) (*pen) & (guint32) 0x000000ffU
) << 24) | (((guint32) (*pen) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (*pen) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (*pen) & (guint32) 0xff000000U
) >> 24))))))
;
776 break;
777
778 case OPT_LITTLE_ENDIAN:
779 *pen = GUINT32_FROM_LE(*pen)(((guint32) (*pen)));
780 break;
781
782 default:
783 /*
784 * This should not happen - this is called by pcapng_process_options(),
785 * which returns an error for an invalid byte_order argument, and
786 * otherwise passes the known-to-be-valid byte_order argument to
787 * us.
788 */
789 *err = WTAP_ERR_INTERNAL-21;
790 *err_info = ws_strdup_printf("pcapng: invalid byte order %d passed to pcapng_process_custom_option()",wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_process_custom_option()"
, byte_order)
791 byte_order)wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_process_custom_option()"
, byte_order)
;
792 return false0;
793 }
794 return true1;
795}
796
797static bool_Bool
798pcapng_process_custom_string_option(wtapng_block_t *wblock,
799 section_info_t *section_info,
800 uint16_t option_code,
801 uint16_t option_length,
802 const uint8_t *option_content,
803 pcapng_opt_byte_order_e byte_order,
804 int *err, char **err_info)
805{
806 uint32_t pen;
807 bool_Bool ret;
808
809 if (!pcapng_process_custom_option_common(section_info, option_length,
810 option_content, byte_order,
811 &pen, err, err_info)) {
812 return false0;
813 }
814 ret = wtap_block_add_custom_string_option(wblock->block, option_code, pen, option_content + 4, option_length - 4) == WTAP_OPTTYPE_SUCCESS;
815 ws_debug("returning %d", ret)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 815, __func__, "returning %d", ret); } } while (0)
;
816 return ret;
817}
818
819static bool_Bool
820pcapng_process_custom_binary_option(wtapng_block_t *wblock,
821 section_info_t *section_info,
822 uint16_t option_code,
823 uint16_t option_length,
824 const uint8_t *option_content,
825 pcapng_opt_byte_order_e byte_order,
826 int *err, char **err_info)
827{
828 uint32_t pen;
829 pcapng_custom_block_enterprise_handler_t* pen_handler;
830 bool_Bool ret;
831
832 if (!pcapng_process_custom_option_common(section_info, option_length,
833 option_content, byte_order,
834 &pen, err, err_info)) {
835 return false0;
836 }
837
838 pen_handler = (pcapng_custom_block_enterprise_handler_t*)g_hash_table_lookup(custom_enterprise_handlers, GUINT_TO_POINTER(pen)((gpointer) (gulong) (pen)));
839
840 if (pen_handler != NULL((void*)0))
841 {
842 ret = pen_handler->processor(wblock, section_info, option_code, option_content + 4, option_length - 4);
843 }
844 else
845 {
846 ret = wtap_block_add_custom_binary_option_from_data(wblock->block, option_code, pen, option_content + 4, option_length - 4) == WTAP_OPTTYPE_SUCCESS;
847 ws_debug("Custom option type %u (0x%04x) with unknown pen %u with custom data of length %u", option_code, option_code, pen, option_length - 4)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 847, __func__, "Custom option type %u (0x%04x) with unknown pen %u with custom data of length %u"
, option_code, option_code, pen, option_length - 4); } } while
(0)
;
848 }
849
850 ws_debug("returning %d", ret)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 850, __func__, "returning %d", ret); } } while (0)
;
851 return ret;
852}
853
854#ifdef HAVE_PLUGINS1
855static bool_Bool
856pcapng_process_unhandled_option(wtapng_block_t *wblock,
857 section_info_t *section_info,
858 uint16_t option_code, uint16_t option_length,
859 const uint8_t *option_content,
860 int *err, char **err_info)
861{
862 GHashTable *option_handlers;
863 option_handler *handler;
864
865 /*
866 * Get the table of option handlers for this block type.
867 */
868 option_handlers = get_option_handlers(wblock->type);
869
870 /*
871 * Do we have a handler for this packet block option code?
872 */
873 if (option_handlers != NULL((void*)0) &&
874 (handler = (option_handler *)g_hash_table_lookup(option_handlers,
875 GUINT_TO_POINTER((unsigned)option_code)((gpointer) (gulong) ((unsigned)option_code)))) != NULL((void*)0)) {
876 /* Yes - call the handler. */
877 if (!handler->parser(wblock->block, section_info->byte_swapped,
878 option_length, option_content, err, err_info))
879 /* XXX - free anything? */
880 return false0;
881 }
882 return true1;
883}
884#else
885static bool_Bool
886pcapng_process_unhandled_option(wtapng_block_t *wblock _U___attribute__((unused)),
887 section_info_t *section_info _U___attribute__((unused)),
888 uint16_t option_code _U___attribute__((unused)), uint16_t option_length _U___attribute__((unused)),
889 const uint8_t *option_content _U___attribute__((unused)),
890 int *err _U___attribute__((unused)), char **err_info _U___attribute__((unused)))
891{
892 return true1;
893}
894#endif
895
896bool_Bool
897pcapng_process_options(FILE_T fh, wtapng_block_t *wblock,
898 section_info_t *section_info,
899 unsigned opt_cont_buf_len,
900 bool_Bool (*process_option)(wtapng_block_t *,
901 section_info_t *,
902 uint16_t, uint16_t,
903 const uint8_t *,
904 int *, char **),
905 pcapng_opt_byte_order_e byte_order,
906 int *err, char **err_info)
907{
908 uint8_t *option_content; /* Allocate as large as the options block */
909 unsigned opt_bytes_remaining;
910 const uint8_t *option_ptr;
911 const pcapng_option_header_t *oh;
912 uint16_t option_code, option_length;
913 unsigned rounded_option_length;
914
915 ws_debug("Options %u bytes", opt_cont_buf_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 915, __func__, "Options %u bytes", opt_cont_buf_len); } } while
(0)
;
916 if (opt_cont_buf_len == 0) {
917 /* No options, so nothing to do */
918 return true1;
919 }
920
921 /* Allocate enough memory to hold all options */
922 option_content = (uint8_t *)g_try_malloc(opt_cont_buf_len);
923 if (option_content == NULL((void*)0)) {
924 *err = ENOMEM12; /* we assume we're out of memory */
925 return false0;
926 }
927
928 /* Read all the options into the buffer */
929 if (!wtap_read_bytes(fh, option_content, opt_cont_buf_len, err, err_info)) {
930 ws_debug("failed to read options")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 930, __func__, "failed to read options"); } } while (0)
;
931 g_free(option_content);
932 return false0;
933 }
934
935 /*
936 * Now process them.
937 * option_ptr starts out aligned on at least a 4-byte boundary, as
938 * that's what g_try_malloc() gives us, and each option is padded
939 * to a length that's a multiple of 4 bytes, so it remains aligned.
940 */
941 option_ptr = &option_content[0];
942 opt_bytes_remaining = opt_cont_buf_len;
943 while (opt_bytes_remaining != 0) {
944 /* Get option header. */
945 oh = (const pcapng_option_header_t *)(const void *)option_ptr;
946 /* Sanity check: don't run past the end of the options. */
947 if (sizeof (*oh) > opt_bytes_remaining) {
948 *err = WTAP_ERR_BAD_FILE-13;
949 *err_info = ws_strdup_printf("pcapng: Not enough data for option header")wmem_strdup_printf(((void*)0), "pcapng: Not enough data for option header"
)
;
950 g_free(option_content);
951 return false0;
952 }
953 option_code = oh->option_code;
954 option_length = oh->option_length;
955 switch (byte_order) {
956
957 case OPT_SECTION_BYTE_ORDER:
958 if (section_info->byte_swapped) {
959 option_code = GUINT16_SWAP_LE_BE(option_code)(((guint16) ( (guint16) ((guint16) (option_code) >> 8) |
(guint16) ((guint16) (option_code) << 8))))
;
960 option_length = GUINT16_SWAP_LE_BE(option_length)(((guint16) ( (guint16) ((guint16) (option_length) >> 8
) | (guint16) ((guint16) (option_length) << 8))))
;
961 }
962 break;
963
964 case OPT_BIG_ENDIAN:
965 option_code = GUINT16_FROM_BE(option_code)(((((guint16) ( (guint16) ((guint16) (option_code) >> 8
) | (guint16) ((guint16) (option_code) << 8))))))
;
966 option_length = GUINT16_FROM_BE(option_length)(((((guint16) ( (guint16) ((guint16) (option_length) >>
8) | (guint16) ((guint16) (option_length) << 8))))))
;
967 break;
968
969 case OPT_LITTLE_ENDIAN:
970 option_code = GUINT16_FROM_LE(option_code)(((guint16) (option_code)));
971 option_length = GUINT16_FROM_LE(option_length)(((guint16) (option_length)));
972 break;
973
974 default:
975 /* Don't do that. */
976 *err = WTAP_ERR_INTERNAL-21;
977 *err_info = ws_strdup_printf("pcapng: invalid byte order %d passed to pcapng_process_options()",wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_process_options()"
, byte_order)
978 byte_order)wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_process_options()"
, byte_order)
;
979 return false0;
980 }
981 option_ptr += sizeof (*oh); /* 4 bytes, so it remains aligned */
982 opt_bytes_remaining -= sizeof (*oh);
983
984 /* Round up option length to a multiple of 4. */
985 rounded_option_length = WS_ROUNDUP_4(option_length)(((option_length) + ((unsigned)(4U-1U))) & (~((unsigned)(
4U-1U))))
;
986
987 /* Sanity check: don't run past the end of the options. */
988 if (rounded_option_length > opt_bytes_remaining) {
989 *err = WTAP_ERR_BAD_FILE-13;
990 *err_info = ws_strdup_printf("pcapng: Not enough data to handle option of length %u",wmem_strdup_printf(((void*)0), "pcapng: Not enough data to handle option of length %u"
, option_length)
991 option_length)wmem_strdup_printf(((void*)0), "pcapng: Not enough data to handle option of length %u"
, option_length)
;
992 g_free(option_content);
993 return false0;
994 }
995
996 switch (option_code) {
997 case(OPT_EOFOPT0): /* opt_endofopt */
998 if (opt_bytes_remaining != 0) {
999 ws_debug("%u bytes after opt_endofopt", opt_bytes_remaining)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 999, __func__, "%u bytes after opt_endofopt", opt_bytes_remaining
); } } while (0)
;
1000 }
1001 /* padding should be ok here, just get out of this */
1002 opt_bytes_remaining = rounded_option_length;
1003 break;
1004 case(OPT_COMMENT1):
1005 pcapng_process_string_option(wblock, option_code, option_length,
1006 option_ptr);
1007 break;
1008 case(OPT_CUSTOM_STR_COPY2988):
1009 case(OPT_CUSTOM_STR_NO_COPY19372):
1010 if (!pcapng_process_custom_string_option(wblock, section_info,
1011 option_code,
1012 option_length,
1013 option_ptr,
1014 byte_order,
1015 err, err_info)) {
1016 g_free(option_content);
1017 return false0;
1018 }
1019 break;
1020 case(OPT_CUSTOM_BIN_COPY2989):
1021 case(OPT_CUSTOM_BIN_NO_COPY19373):
1022 if (!pcapng_process_custom_binary_option(wblock, section_info,
1023 option_code,
1024 option_length,
1025 option_ptr,
1026 byte_order,
1027 err, err_info)) {
1028 g_free(option_content);
1029 return false0;
1030 }
1031 break;
1032 default:
1033 if (process_option == NULL((void*)0) ||
1034 !(*process_option)(wblock, section_info, option_code,
1035 option_length, option_ptr,
1036 err, err_info)) {
1037 g_free(option_content);
1038 return false0;
1039 }
1040 break;
1041 }
1042 option_ptr += rounded_option_length; /* multiple of 4 bytes, so it remains aligned */
1043 opt_bytes_remaining -= rounded_option_length;
1044 }
1045 g_free(option_content);
1046 return true1;
1047}
1048
1049typedef enum {
1050 PCAPNG_BLOCK_OK,
1051 PCAPNG_BLOCK_NOT_SHB,
1052 PCAPNG_BLOCK_ERROR
1053} block_return_val;
1054
1055static bool_Bool
1056pcapng_process_section_header_block_option(wtapng_block_t *wblock,
1057 section_info_t *section_info,
1058 uint16_t option_code,
1059 uint16_t option_length,
1060 const uint8_t *option_content,
1061 int *err, char **err_info)
1062{
1063 /*
1064 * Handle option content.
1065 *
1066 * ***DO NOT*** add any items to this table that are not
1067 * standardized option codes in either section 3.5 "Options"
1068 * of the current pcapng spec, at
1069 *
1070 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-options
1071 *
1072 * or in the list of options in section 4.1 "Section Header Block"
1073 * of the current pcapng spec, at
1074 *
1075 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-section-header-block
1076 *
1077 * All option codes in this switch statement here must be listed
1078 * in one of those places as standardized option types.
1079 */
1080 switch (option_code) {
1081 case(OPT_SHB_HARDWARE2):
1082 pcapng_process_string_option(wblock, option_code, option_length,
1083 option_content);
1084 break;
1085 case(OPT_SHB_OS3):
1086 pcapng_process_string_option(wblock, option_code, option_length,
1087 option_content);
1088 break;
1089 case(OPT_SHB_USERAPPL4):
1090 pcapng_process_string_option(wblock, option_code, option_length,
1091 option_content);
1092 break;
1093 default:
1094 if (!pcapng_process_unhandled_option(wblock, section_info,
1095 option_code, option_length,
1096 option_content,
1097 err, err_info))
1098 return false0;
1099 break;
1100 }
1101 return true1;
1102}
1103
1104static block_return_val
1105pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
1106 section_info_t *section_info,
1107 wtapng_block_t *wblock,
1108 int *err, char **err_info)
1109{
1110 bool_Bool byte_swapped;
1111 uint16_t version_major;
1112 uint16_t version_minor;
1113 unsigned opt_cont_buf_len;
1114 pcapng_section_header_block_t shb;
1115 wtapng_section_mandatory_t* section_data;
1116
1117 /* read fixed-length part of the block */
1118 if (!wtap_read_bytes(fh, &shb, sizeof shb, err, err_info)) {
1119 /*
1120 * Even if this is just a short read, report it as an error.
1121 * It *is* a read error except when we're doing an open, in
1122 * which case it's a "this isn't a pcapng file" indication.
1123 * The open code will call us directly, and treat a short
1124 * read error as such an indication.
1125 */
1126 return PCAPNG_BLOCK_ERROR;
1127 }
1128
1129 /* is the magic number one we expect? */
1130 switch (shb.magic) {
1131 case(0x1A2B3C4D):
1132 /* this seems pcapng with correct byte order */
1133 byte_swapped = false0;
1134 version_major = shb.version_major;
1135 version_minor = shb.version_minor;
1136
1137 ws_debug("SHB (our byte order) V%u.%u, len %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1138, __func__, "SHB (our byte order) V%u.%u, len %u", version_major
, version_minor, bh->block_total_length); } } while (0)
1138 version_major, version_minor, bh->block_total_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1138, __func__, "SHB (our byte order) V%u.%u, len %u", version_major
, version_minor, bh->block_total_length); } } while (0)
;
1139 break;
1140 case(0x4D3C2B1A):
1141 /* this seems pcapng with swapped byte order */
1142 byte_swapped = true1;
1143 version_major = GUINT16_SWAP_LE_BE(shb.version_major)(((guint16) ( (guint16) ((guint16) (shb.version_major) >>
8) | (guint16) ((guint16) (shb.version_major) << 8))))
;
1144 version_minor = GUINT16_SWAP_LE_BE(shb.version_minor)(((guint16) ( (guint16) ((guint16) (shb.version_minor) >>
8) | (guint16) ((guint16) (shb.version_minor) << 8))))
;
1145
1146 /* tweak the block length to meet current swapping that we know now */
1147 bh->block_total_length = GUINT32_SWAP_LE_BE(bh->block_total_length)(((guint32) ( (((guint32) (bh->block_total_length) & (
guint32) 0x000000ffU) << 24) | (((guint32) (bh->block_total_length
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (bh->
block_total_length) & (guint32) 0x00ff0000U) >> 8) |
(((guint32) (bh->block_total_length) & (guint32) 0xff000000U
) >> 24))))
;
1148
1149 ws_debug("SHB (byte-swapped) V%u.%u, len %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1150, __func__, "SHB (byte-swapped) V%u.%u, len %u", version_major
, version_minor, bh->block_total_length); } } while (0)
1150 version_major, version_minor, bh->block_total_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1150, __func__, "SHB (byte-swapped) V%u.%u, len %u", version_major
, version_minor, bh->block_total_length); } } while (0)
;
1151 break;
1152 default:
1153 /* Not a "pcapng" magic number we know about. */
1154 *err = WTAP_ERR_BAD_FILE-13;
1155 *err_info = ws_strdup_printf("pcapng: unknown byte-order magic number 0x%08x", shb.magic)wmem_strdup_printf(((void*)0), "pcapng: unknown byte-order magic number 0x%08x"
, shb.magic)
;
1156
1157 /*
1158 * See above comment about PCAPNG_BLOCK_NOT_SHB.
1159 */
1160 return PCAPNG_BLOCK_NOT_SHB;
1161 }
1162
1163 /*
1164 * Add padding bytes to the block total length.
1165 *
1166 * See the comment in pcapng_read_block() for a long discussion
1167 * of this.
1168 */
1169 bh->block_total_length = WS_ROUNDUP_4(bh->block_total_length)(((bh->block_total_length) + ((unsigned)(4U-1U))) & (~
((unsigned)(4U-1U))))
;
1170
1171 /*
1172 * Is this block long enough to be an SHB?
1173 */
1174 if (bh->block_total_length < MIN_SHB_SIZE((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_section_header_block_t)))
) {
1175 /*
1176 * No.
1177 */
1178 *err = WTAP_ERR_BAD_FILE-13;
1179 *err_info = ws_strdup_printf("pcapng: total block length %u of an SHB is less than the minimum SHB size %u",wmem_strdup_printf(((void*)0), "pcapng: total block length %u of an SHB is less than the minimum SHB size %u"
, bh->block_total_length, ((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t
) + sizeof(uint32_t))) + sizeof(pcapng_section_header_block_t
))))
1180 bh->block_total_length, MIN_SHB_SIZE)wmem_strdup_printf(((void*)0), "pcapng: total block length %u of an SHB is less than the minimum SHB size %u"
, bh->block_total_length, ((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t
) + sizeof(uint32_t))) + sizeof(pcapng_section_header_block_t
))))
;
1181 return PCAPNG_BLOCK_ERROR;
1182 }
1183
1184 /* OK, at this point we assume it's a pcapng file.
1185
1186 Don't try to allocate memory for a huge number of options, as
1187 that might fail and, even if it succeeds, it might not leave
1188 any address space or memory+backing store for anything else.
1189
1190 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1191 We check for this *after* checking the SHB for its byte
1192 order magic number, so that non-pcapng files are less
1193 likely to be treated as bad pcapng files. */
1194 if (bh->block_total_length > MAX_BLOCK_SIZE(((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t))) + (128U
*1024U*1024U) + 131072)
) {
1195 *err = WTAP_ERR_BAD_FILE-13;
1196 *err_info = ws_strdup_printf("pcapng: total block length %u is too large (> %u)",wmem_strdup_printf(((void*)0), "pcapng: total block length %u is too large (> %u)"
, bh->block_total_length, (((uint32_t)(((uint32_t)(sizeof(
pcapng_block_header_t) + sizeof(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t
))) + (128U*1024U*1024U) + 131072))
1197 bh->block_total_length, MAX_BLOCK_SIZE)wmem_strdup_printf(((void*)0), "pcapng: total block length %u is too large (> %u)"
, bh->block_total_length, (((uint32_t)(((uint32_t)(sizeof(
pcapng_block_header_t) + sizeof(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t
))) + (128U*1024U*1024U) + 131072))
;
1198 return PCAPNG_BLOCK_ERROR;
1199 }
1200
1201 /* Currently only SHB versions 1.0 and 1.2 are supported;
1202 version 1.2 is treated as being the same as version 1.0.
1203 See the current version of the pcapng specification.
1204
1205 Version 1.2 is written by some programs that write additional
1206 block types (which can be read by any code that handles them,
1207 regarless of whether the minor version if 0 or 2, so that's
1208 not a reason to change the minor version number).
1209
1210 XXX - the pcapng specification says that readers should
1211 just ignore sections with an unsupported version number;
1212 presumably they can also report an error if they skip
1213 all the way to the end of the file without finding
1214 any versions that they support. */
1215 if (!(version_major == 1 &&
1216 (version_minor == 0 || version_minor == 2))) {
1217 *err = WTAP_ERR_UNSUPPORTED-4;
1218 *err_info = ws_strdup_printf("pcapng: unknown SHB version %u.%u",wmem_strdup_printf(((void*)0), "pcapng: unknown SHB version %u.%u"
, version_major, version_minor)
1219 version_major, version_minor)wmem_strdup_printf(((void*)0), "pcapng: unknown SHB version %u.%u"
, version_major, version_minor)
;
1220 return PCAPNG_BLOCK_ERROR;
1221 }
1222
1223 memset(section_info, 0, sizeof(section_info_t));
1224 section_info->byte_swapped = byte_swapped;
1225 section_info->version_major = version_major;
1226 section_info->version_minor = version_minor;
1227
1228 /*
1229 * Set wblock->block to a newly-allocated section header block.
1230 */
1231 wblock->block = wtap_block_create(WTAP_BLOCK_SECTION);
1232
1233 /*
1234 * Set the mandatory values for the block.
1235 */
1236 section_data = (wtapng_section_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
1237 /* 64bit section_length (currently unused) */
1238 if (section_info->byte_swapped) {
1239 section_data->section_length = GUINT64_SWAP_LE_BE(shb.section_length)(((guint64) ( (((guint64) (shb.section_length) & (guint64
) (0x00000000000000ffUL)) << 56) | (((guint64) (shb.section_length
) & (guint64) (0x000000000000ff00UL)) << 40) | (((guint64
) (shb.section_length) & (guint64) (0x0000000000ff0000UL)
) << 24) | (((guint64) (shb.section_length) & (guint64
) (0x00000000ff000000UL)) << 8) | (((guint64) (shb.section_length
) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64
) (shb.section_length) & (guint64) (0x0000ff0000000000UL)
) >> 24) | (((guint64) (shb.section_length) & (guint64
) (0x00ff000000000000UL)) >> 40) | (((guint64) (shb.section_length
) & (guint64) (0xff00000000000000UL)) >> 56))))
;
1240 } else {
1241 section_data->section_length = shb.section_length;
1242 }
1243
1244 /* Options */
1245 opt_cont_buf_len = bh->block_total_length - MIN_SHB_SIZE((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_section_header_block_t)))
;
1246 if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
1247 pcapng_process_section_header_block_option,
1248 OPT_SECTION_BYTE_ORDER, err, err_info))
1249 return PCAPNG_BLOCK_ERROR;
1250
1251 /*
1252 * We don't return these to the caller in pcapng_read().
1253 */
1254 wblock->internal = true1;
1255
1256 return PCAPNG_BLOCK_OK;
1257}
1258
1259static bool_Bool
1260pcapng_process_if_descr_block_option(wtapng_block_t *wblock,
1261 section_info_t *section_info,
1262 uint16_t option_code,
1263 uint16_t option_length,
1264 const uint8_t *option_content,
1265 int *err, char **err_info)
1266{
1267 if_filter_opt_t if_filter;
1268
1269 /*
1270 * Handle option content.
1271 *
1272 * ***DO NOT*** add any items to this table that are not
1273 * standardized option codes in either section 3.5 "Options"
1274 * of the current pcapng spec, at
1275 *
1276 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-options
1277 *
1278 * or in the list of options in section 4.1 "Section Header Block"
1279 * of the current pcapng spec, at
1280 *
1281 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-section-header-block
1282 *
1283 * All option codes in this switch statement here must be listed
1284 * in one of those places as standardized option types.
1285 */
1286 switch (option_code) {
1287 case(OPT_IDB_NAME2): /* if_name */
1288 pcapng_process_string_option(wblock, option_code, option_length,
1289 option_content);
1290 break;
1291 case(OPT_IDB_DESCRIPTION3): /* if_description */
1292 pcapng_process_string_option(wblock, option_code, option_length,
1293 option_content);
1294 break;
1295 case(OPT_IDB_IP4ADDR4):
1296 /*
1297 * Interface network address and netmask. This option can be
1298 * repeated multiple times within the same Interface
1299 * Description Block when multiple IPv4 addresses are assigned
1300 * to the interface. 192 168 1 1 255 255 255 0
1301 */
1302 break;
1303 case(OPT_IDB_IP6ADDR5):
1304 /*
1305 * Interface network address and prefix length (stored in the
1306 * last byte). This option can be repeated multiple times
1307 * within the same Interface Description Block when multiple
1308 * IPv6 addresses are assigned to the interface.
1309 * 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in
1310 * hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44
1311 * 40"
1312 */
1313 break;
1314 case(OPT_IDB_MACADDR6):
1315 /*
1316 * Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
1317 */
1318 break;
1319 case(OPT_IDB_EUIADDR7):
1320 /*
1321 * Interface Hardware EUI address (64 bits), if available.
1322 * 02 34 56 FF FE 78 9A BC
1323 */
1324 break;
1325 case(OPT_IDB_SPEED8): /* if_speed */
1326 pcapng_process_uint64_option(wblock, section_info,
1327 OPT_SECTION_BYTE_ORDER,
1328 option_code, option_length,
1329 option_content);
1330 break;
1331 case(OPT_IDB_TSRESOL9): /* if_tsresol */
1332 pcapng_process_uint8_option(wblock, option_code, option_length,
1333 option_content);
1334 break;
1335 case(OPT_IDB_TZONE10): /* if_tzone */
1336 /*
1337 * Time zone for GMT support. This option has never been
1338 * specified in greater detail and, unless it were to identify
1339 * something such as an IANA time zone database timezone,
1340 * would be insufficient for converting between UTC and local
1341 * time. Therefore, it SHOULD NOT be used; instead, the
1342 * if_iana_tzname option SHOULD be used if time zone
1343 * information is to be specified.
1344 *
1345 * Given that, we don't do anything with it.
1346 */
1347 break;
1348 case(OPT_IDB_FILTER11): /* if_filter */
1349 if (option_length < 1) {
1350 *err = WTAP_ERR_BAD_FILE-13;
1351 *err_info = ws_strdup_printf("pcapng: packet block verdict option length %u is < 1",wmem_strdup_printf(((void*)0), "pcapng: packet block verdict option length %u is < 1"
, option_length)
1352 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block verdict option length %u is < 1"
, option_length)
;
1353 /* XXX - free anything? */
1354 return false0;
1355 }
1356 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
1357 * or BPF bytecode.
1358 */
1359 if (option_content[0] == 0) {
1360 if_filter.type = if_filter_pcap;
1361 if_filter.data.filter_str = g_strndup((char *)option_content+1, option_length-1);
1362 ws_debug("filter_str %s option_length %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1363, __func__, "filter_str %s option_length %u", if_filter
.data.filter_str, option_length); } } while (0)
1363 if_filter.data.filter_str, option_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1363, __func__, "filter_str %s option_length %u", if_filter
.data.filter_str, option_length); } } while (0)
;
1364 /* Fails with multiple options; we silently ignore the failure */
1365 wtap_block_add_if_filter_option(wblock->block, option_code, &if_filter);
1366 g_free(if_filter.data.filter_str);
1367 } else if (option_content[0] == 1) {
1368 /*
1369 * XXX - byte-swap the code and k fields
1370 * of each instruction as needed!
1371 *
1372 * XXX - what if option_length-1 is not a
1373 * multiple of the size of a BPF instruction?
1374 */
1375 unsigned num_insns;
1376 const uint8_t *insn_in;
1377
1378 if_filter.type = if_filter_bpf;
1379 num_insns = (option_length-1)/8;
1380 insn_in = option_content+1;
1381 if_filter.data.bpf_prog.bpf_prog_len = num_insns;
1382 if_filter.data.bpf_prog.bpf_prog = g_new(wtap_bpf_insn_t, num_insns)((wtap_bpf_insn_t *) g_malloc_n ((num_insns), sizeof (wtap_bpf_insn_t
)))
;
1383 for (unsigned i = 0; i < num_insns; i++) {
1384 wtap_bpf_insn_t *insn = &if_filter.data.bpf_prog.bpf_prog[i];
1385
1386 memcpy(&insn->code, insn_in, 2);
1387 if (section_info->byte_swapped)
1388 insn->code = GUINT16_SWAP_LE_BE(insn->code)(((guint16) ( (guint16) ((guint16) (insn->code) >> 8
) | (guint16) ((guint16) (insn->code) << 8))))
;
1389 insn_in += 2;
1390 memcpy(&insn->jt, insn_in, 1);
1391 insn_in += 1;
1392 memcpy(&insn->jf, insn_in, 1);
1393 insn_in += 1;
1394 memcpy(&insn->k, insn_in, 4);
1395 if (section_info->byte_swapped)
1396 insn->k = GUINT32_SWAP_LE_BE(insn->k)(((guint32) ( (((guint32) (insn->k) & (guint32) 0x000000ffU
) << 24) | (((guint32) (insn->k) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (insn->k) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (insn->k) & (guint32) 0xff000000U
) >> 24))))
;
1397 insn_in += 4;
1398 }
1399 /* Fails with multiple options; we silently ignore the failure */
1400 wtap_block_add_if_filter_option(wblock->block, option_code, &if_filter);
1401 g_free(if_filter.data.bpf_prog.bpf_prog);
1402 }
1403 break;
1404 case(OPT_IDB_OS12): /* if_os */
1405 /*
1406 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
1407 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
1408 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
1409 */
1410 pcapng_process_string_option(wblock, option_code, option_length,
1411 option_content);
1412 break;
1413 case(OPT_IDB_FCSLEN13): /* if_fcslen */
1414 pcapng_process_uint8_option(wblock, option_code, option_length,
1415 option_content);
1416 break;
1417 case(OPT_IDB_TSOFFSET14):
1418 /*
1419 * A 64-bit integer value that specifies an offset (in
1420 * seconds) that must be added to the timestamp of each packet
1421 * to obtain the absolute timestamp of a packet. If this optio
1422 * is not present, an offset of 0 is assumed (i.e., timestamps
1423 * in blocks are absolute timestamps.)
1424 */
1425 pcapng_process_int64_option(wblock, section_info,
1426 OPT_SECTION_BYTE_ORDER,
1427 option_code, option_length,
1428 option_content);
1429 break;
1430 case(OPT_IDB_HARDWARE15): /* if_hardware */
1431 pcapng_process_string_option(wblock, option_code, option_length,
1432 option_content);
1433 break;
1434 case(OPT_IDB_TXSPEED16): /* if_txspeed */
1435 pcapng_process_uint64_option(wblock, section_info,
1436 OPT_SECTION_BYTE_ORDER,
1437 option_code, option_length,
1438 option_content);
1439 break;
1440 case(OPT_IDB_RXSPEED17): /* if_rxspeed */
1441 pcapng_process_uint64_option(wblock, section_info,
1442 OPT_SECTION_BYTE_ORDER,
1443 option_code, option_length,
1444 option_content);
1445 break;
1446 case(OPT_IDB_IANA_TZNAME18): /* if_iana_tzname */
1447 pcapng_process_string_option(wblock, option_code, option_length,
1448 option_content);
1449 break;
1450 default:
1451 if (!pcapng_process_unhandled_option(wblock, section_info,
1452 option_code, option_length,
1453 option_content,
1454 err, err_info))
1455 return false0;
1456 break;
1457 }
1458 return true1;
1459}
1460
1461/* "Interface Description Block" */
1462static bool_Bool
1463pcapng_read_if_descr_block(wtap *wth, FILE_T fh, uint32_t block_type _U___attribute__((unused)),
1464 uint32_t block_content_length,
1465 section_info_t *section_info,
1466 wtapng_block_t *wblock, int *err, char **err_info)
1467{
1468 /* Default time stamp resolution is 10^6 */
1469 uint64_t time_units_per_second = 1000000;
1470 int tsprecision = 6;
1471 unsigned opt_cont_buf_len;
1472 pcapng_interface_description_block_t idb;
1473 wtapng_if_descr_mandatory_t* if_descr_mand;
1474 unsigned link_type;
1475 uint8_t if_tsresol;
1476
1477 /*
1478 * Is this block long enough to be an IDB?
1479 */
1480 if (block_content_length < sizeof idb) {
1481 /*
1482 * No.
1483 */
1484 *err = WTAP_ERR_BAD_FILE-13;
1485 *err_info = ws_strdup_printf("pcapng: block content length %u of an IDB is less than the minimum IDB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an IDB is less than the minimum IDB content size %zu"
, block_content_length, sizeof idb)
1486 block_content_length, sizeof idb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an IDB is less than the minimum IDB content size %zu"
, block_content_length, sizeof idb)
;
1487 return false0;
1488 }
1489
1490 /* read block content */
1491 if (!wtap_read_bytes(fh, &idb, sizeof idb, err, err_info)) {
1492 ws_debug("failed to read IDB")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1492, __func__, "failed to read IDB"); } } while (0)
;
1493 return false0;
1494 }
1495
1496 /*
1497 * Set wblock->block to a newly-allocated interface ID and information
1498 * block.
1499 */
1500 wblock->block = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
1501
1502 /*
1503 * Set the mandatory values for the block.
1504 */
1505 if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
1506 if (section_info->byte_swapped) {
1507 link_type = GUINT16_SWAP_LE_BE(idb.linktype)(((guint16) ( (guint16) ((guint16) (idb.linktype) >> 8)
| (guint16) ((guint16) (idb.linktype) << 8))))
;
1508 if_descr_mand->snap_len = GUINT32_SWAP_LE_BE(idb.snaplen)(((guint32) ( (((guint32) (idb.snaplen) & (guint32) 0x000000ffU
) << 24) | (((guint32) (idb.snaplen) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (idb.snaplen) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (idb.snaplen) & (guint32) 0xff000000U
) >> 24))))
;
1509 } else {
1510 link_type = idb.linktype;
1511 if_descr_mand->snap_len = idb.snaplen;
1512 }
1513
1514 if_descr_mand->wtap_encap = wtap_pcap_encap_to_wtap_encap(link_type);
1515
1516 ws_debug("IDB link_type %u (%s), snap %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1519, __func__, "IDB link_type %u (%s), snap %u", link_type
, wtap_encap_description(if_descr_mand->wtap_encap), if_descr_mand
->snap_len); } } while (0)
1517 link_type,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1519, __func__, "IDB link_type %u (%s), snap %u", link_type
, wtap_encap_description(if_descr_mand->wtap_encap), if_descr_mand
->snap_len); } } while (0)
1518 wtap_encap_description(if_descr_mand->wtap_encap),do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1519, __func__, "IDB link_type %u (%s), snap %u", link_type
, wtap_encap_description(if_descr_mand->wtap_encap), if_descr_mand
->snap_len); } } while (0)
1519 if_descr_mand->snap_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1519, __func__, "IDB link_type %u (%s), snap %u", link_type
, wtap_encap_description(if_descr_mand->wtap_encap), if_descr_mand
->snap_len); } } while (0)
;
1520
1521 if (if_descr_mand->snap_len > wtap_max_snaplen_for_encap(if_descr_mand->wtap_encap)) {
1522 /*
1523 * We do not use this value, maybe we should check the
1524 * snap_len of the packets against it. For now, only warn.
1525 */
1526 ws_debug("snapshot length %u unrealistic.",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1527, __func__, "snapshot length %u unrealistic.", if_descr_mand
->snap_len); } } while (0)
1527 if_descr_mand->snap_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1527, __func__, "snapshot length %u unrealistic.", if_descr_mand
->snap_len); } } while (0)
;
1528 /*if_descr_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;*/
1529 }
1530
1531 /* Options */
1532 opt_cont_buf_len = block_content_length - sizeof idb;
1533 if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
1534 pcapng_process_if_descr_block_option,
1535 OPT_SECTION_BYTE_ORDER, err, err_info))
1536 return false0;
1537
1538 /*
1539 * Did we get a time stamp precision option?
1540 */
1541 if (wtap_block_get_uint8_option_value(wblock->block, OPT_IDB_TSRESOL9,
1542 &if_tsresol) == WTAP_OPTTYPE_SUCCESS) {
1543 /*
1544 * Yes. Set time_units_per_second appropriately.
1545 */
1546 uint8_t exponent;
1547
1548 exponent = (uint8_t)(if_tsresol & 0x7f);
1549 if (if_tsresol & 0x80) {
1550 /*
1551 * 2^63 fits in a 64-bit unsigned number; 2^64 does not.
1552 *
1553 * ((2^64-1)/(2^63) is about 1.99, so, in practice, that
1554 * fine a time stamp resolution works only if you start
1555 * capturing at the Unix/POSIX epoch and capture for about
1556 * 1.9 seconds, so the maximum useful power-of-2 exponent
1557 * in a pcapng file is less than 63.)
1558 */
1559 if (exponent > 63) {
1560 /*
1561 * Time units per second won't fit in a 64-bit integer,
1562 * so Wireshark's current code can't read the file.
1563 */
1564 *err = WTAP_ERR_UNSUPPORTED-4;
1565 *err_info = ws_strdup_printf("pcapng: IDB power-of-2 time stamp resolution %u > 63",wmem_strdup_printf(((void*)0), "pcapng: IDB power-of-2 time stamp resolution %u > 63"
, exponent)
1566 exponent)wmem_strdup_printf(((void*)0), "pcapng: IDB power-of-2 time stamp resolution %u > 63"
, exponent)
;
1567 return false0;
1568 }
1569
1570 /* 2^exponent */
1571 time_units_per_second = UINT64_C(1)1UL << exponent;
1572
1573 /*
1574 * Set the display precision to a value large enough to
1575 * show the fractional time units we get, so that we
1576 * don't display more digits than are justified.
1577 *
1578 * (That's also used as the base-10 if_tsresol value we use
1579 * if we write this file as a pcapng file. Yes, that means
1580 * that we won't write out the exact value we read in.
1581 *
1582 * Dealing with base-2 time stamps is a bit of a mess,
1583 * thanks to humans counting with their fingers rather
1584 * than their hands, and it applies to more files than
1585 * pcapng files, e.g. ERF files.)
1586 */
1587 if (time_units_per_second >= 1000000000)
1588 tsprecision = WTAP_TSPREC_NSEC9;
1589 else if (time_units_per_second >= 100000000)
1590 tsprecision = WTAP_TSPREC_10_NSEC8;
1591 else if (time_units_per_second >= 10000000)
1592 tsprecision = WTAP_TSPREC_100_NSEC7;
1593 else if (time_units_per_second >= 1000000)
1594 tsprecision = WTAP_TSPREC_USEC6;
1595 else if (time_units_per_second >= 100000)
1596 tsprecision = WTAP_TSPREC_10_USEC5;
1597 else if (time_units_per_second >= 10000)
1598 tsprecision = WTAP_TSPREC_100_USEC4;
1599 else if (time_units_per_second >= 1000)
1600 tsprecision = WTAP_TSPREC_MSEC3;
1601 else if (time_units_per_second >= 100)
1602 tsprecision = WTAP_TSPREC_10_MSEC2;
1603 else if (time_units_per_second >= 10)
1604 tsprecision = WTAP_TSPREC_100_MSEC1;
1605 else
1606 tsprecision = WTAP_TSPREC_SEC0;
1607 } else {
1608 /*
1609 * 10^19 fits in a 64-bit unsigned number; 10^20 does not.
1610 *
1611 * ((2^64-1)/(10^19) is about 1.84, so, in practice, that
1612 * fine a time stamp resolution works only if you start
1613 * capturing at the Unix/POSIX epoch and capture for about
1614 * 1.8 seconds, so the maximum useful power-of-10 exponent
1615 * in a pcapng file is less than 19.)
1616 */
1617 uint64_t result;
1618
1619 if (exponent > 19) {
1620 /*
1621 * Time units per second won't fit in a 64-bit integer,
1622 * so Wireshark's current code can't read the file.
1623 */
1624 *err = WTAP_ERR_UNSUPPORTED-4;
1625 *err_info = ws_strdup_printf("pcapng: IDB power-of-10 time stamp resolution %u > 19",wmem_strdup_printf(((void*)0), "pcapng: IDB power-of-10 time stamp resolution %u > 19"
, exponent)
1626 exponent)wmem_strdup_printf(((void*)0), "pcapng: IDB power-of-10 time stamp resolution %u > 19"
, exponent)
;
1627 return false0;
1628 }
1629
1630 /* 10^exponent */
1631 result = 1;
1632 for (unsigned i = 0; i < exponent; i++) {
1633 result *= 10U;
1634 }
1635 time_units_per_second = result;
1636
1637 /*
1638 * Set the display precision to min(exponent, WS_TSPREC_MAX),
1639 * so that we don't display more digits than are justified.
1640 * (That's also used as the base-10 if_tsresol value we use
1641 * if we write this file as a pcapng file.)
1642 */
1643 if (exponent <= WS_TSPREC_MAX9) {
1644 tsprecision = exponent;
1645 } else {
1646 tsprecision = WS_TSPREC_MAX9;
1647 }
1648 }
1649 if (time_units_per_second > (((uint64_t)1) << 32)) {
1650 ws_debug("time conversion might be inaccurate")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1650, __func__, "time conversion might be inaccurate"); } }
while (0)
;
1651 }
1652 }
1653
1654 /*
1655 * Set the time units per second for this interface.
1656 */
1657 if_descr_mand->time_units_per_second = time_units_per_second;
1658
1659 /*
1660 * Set the number of digits of precision to display (and the
1661 * number to use for this interface if saving to a pcapng
1662 * file).
1663 */
1664 if_descr_mand->tsprecision = tsprecision;
1665
1666 /*
1667 * If the per-file encapsulation isn't known, set it to this
1668 * interface's encapsulation.
1669 *
1670 * If it *is* known, and it isn't this interface's encapsulation,
1671 * set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
1672 * have a single encapsulation for all interfaces in the file,
1673 * so it probably doesn't have a single encapsulation for all
1674 * packets in the file.
1675 */
1676 if (wth->file_encap == WTAP_ENCAP_NONE-2) {
1677 wth->file_encap = if_descr_mand->wtap_encap;
1678 } else {
1679 if (wth->file_encap != if_descr_mand->wtap_encap) {
1680 wth->file_encap = WTAP_ENCAP_PER_PACKET-1;
1681 }
1682 }
1683
1684 /*
1685 * The same applies to the per-file time stamp resolution.
1686 */
1687 if (wth->file_tsprec == WTAP_TSPREC_UNKNOWN-2) {
1688 wth->file_tsprec = if_descr_mand->tsprecision;
1689 } else {
1690 if (wth->file_tsprec != if_descr_mand->tsprecision) {
1691 wth->file_tsprec = WTAP_TSPREC_PER_PACKET-1;
1692 }
1693 }
1694
1695 /*
1696 * We don't return these to the caller in pcapng_read().
1697 */
1698 wblock->internal = true1;
1699
1700 return true1;
1701}
1702
1703static bool_Bool
1704pcapng_read_decryption_secrets_block(wtap *wth _U___attribute__((unused)), FILE_T fh,
1705 uint32_t block_read _U___attribute__((unused)),
1706 uint32_t block_content_length,
1707 section_info_t *section_info,
1708 wtapng_block_t *wblock,
1709 int *err, char **err_info)
1710{
1711 unsigned to_read;
1712 pcapng_decryption_secrets_block_t dsb;
1713 wtapng_dsb_mandatory_t *dsb_mand;
1714
1715 /*
1716 * Is this block long enough to be an DSB?
1717 */
1718 if (block_content_length < sizeof dsb) {
1719 /*
1720 * No.
1721 */
1722 *err = WTAP_ERR_BAD_FILE-13;
1723 *err_info = ws_strdup_printf("pcapng: block content length %u of an DSB is less than the minimum DSB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an DSB is less than the minimum DSB content size %zu"
, block_content_length, sizeof dsb)
1724 block_content_length, sizeof dsb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an DSB is less than the minimum DSB content size %zu"
, block_content_length, sizeof dsb)
;
1725 return false0;
1726 }
1727
1728 /* read block content */
1729 if (!wtap_read_bytes(fh, &dsb, sizeof dsb, err, err_info)) {
1730 ws_debug("failed to read DSB fixed portion")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1730, __func__, "failed to read DSB fixed portion"); } } while
(0)
;
1731 return false0;
1732 }
1733
1734 /*
1735 * Set wblock->block to a newly-allocated decryption secrets block.
1736 */
1737 wblock->block = wtap_block_create(WTAP_BLOCK_DECRYPTION_SECRETS);
1738
1739 /*
1740 * Set the mandatory values for the block.
1741 */
1742 dsb_mand = (wtapng_dsb_mandatory_t *)wtap_block_get_mandatory_data(wblock->block);
1743 if (section_info->byte_swapped) {
1744 dsb_mand->secrets_type = GUINT32_SWAP_LE_BE(dsb.secrets_type)(((guint32) ( (((guint32) (dsb.secrets_type) & (guint32) 0x000000ffU
) << 24) | (((guint32) (dsb.secrets_type) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (dsb.secrets_type) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (dsb.secrets_type
) & (guint32) 0xff000000U) >> 24))))
;
1745 dsb_mand->secrets_len = GUINT32_SWAP_LE_BE(dsb.secrets_len)(((guint32) ( (((guint32) (dsb.secrets_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (dsb.secrets_len) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (dsb.secrets_len) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (dsb.secrets_len
) & (guint32) 0xff000000U) >> 24))))
;
1746 } else {
1747 dsb_mand->secrets_type = dsb.secrets_type;
1748 dsb_mand->secrets_len = dsb.secrets_len;
1749 }
1750
1751 /*
1752 * Is this block long enough to contain the secrets?
1753 */
1754 if (block_content_length < sizeof dsb + dsb_mand->secrets_len) {
1755 /*
1756 * No.
1757 */
1758 *err = WTAP_ERR_BAD_FILE-13;
1759 *err_info = ws_strdup_printf("pcapng: block content length %u of an DSB is less the size needed for the secrets in the DSB %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an DSB is less the size needed for the secrets in the DSB %zu"
, block_content_length, sizeof dsb + dsb_mand->secrets_len
)
1760 block_content_length,wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an DSB is less the size needed for the secrets in the DSB %zu"
, block_content_length, sizeof dsb + dsb_mand->secrets_len
)
1761 sizeof dsb + dsb_mand->secrets_len)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an DSB is less the size needed for the secrets in the DSB %zu"
, block_content_length, sizeof dsb + dsb_mand->secrets_len
)
;
1762 return false0;
1763 }
1764
1765 /*
1766 * Sanity check: assume the secrets will never need to be larger
1767 * than 1 GiB.
1768 */
1769 if (dsb_mand->secrets_len > 1024 * 1024 * 1024) {
1770 *err = WTAP_ERR_BAD_FILE-13;
1771 *err_info = ws_strdup_printf("pcapng: secrets block is too large: %u", dsb_mand->secrets_len)wmem_strdup_printf(((void*)0), "pcapng: secrets block is too large: %u"
, dsb_mand->secrets_len)
;
1772 return false0;
1773 }
1774
1775 dsb_mand->secrets_data = (uint8_t *)g_malloc0(dsb_mand->secrets_len);
1776 if (!wtap_read_bytes(fh, dsb_mand->secrets_data, dsb_mand->secrets_len, err, err_info)) {
1777 ws_debug("failed to read DSB secrets")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1777, __func__, "failed to read DSB secrets"); } } while (0
)
;
1778 return false0;
1779 }
1780
1781 /* Skip past padding and discard options (not supported yet). */
1782 to_read = block_content_length - sizeof dsb - dsb_mand->secrets_len;
1783 if (!wtap_read_bytes(fh, NULL((void*)0), to_read, err, err_info)) {
1784 ws_debug("failed to read DSB options")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1784, __func__, "failed to read DSB options"); } } while (0
)
;
1785 return false0;
1786 }
1787
1788 /*
1789 * We don't return these to the caller in pcapng_read().
1790 */
1791 wblock->internal = true1;
1792
1793 return true1;
1794}
1795
1796static bool_Bool
1797pcapng_process_packet_block_option(wtapng_block_t *wblock,
1798 section_info_t *section_info,
1799 uint16_t option_code,
1800 uint16_t option_length,
1801 const uint8_t *option_content,
1802 int *err, char **err_info)
1803{
1804 uint64_t tmp64;
1805 packet_verdict_opt_t packet_verdict;
1806 packet_hash_opt_t packet_hash;
1807
1808 /*
1809 * Handle option content.
1810 *
1811 * ***DO NOT*** add any items to this table that are not
1812 * standardized option codes in either section 3.5 "Options"
1813 * of the current pcapng spec, at
1814 *
1815 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-options
1816 *
1817 * or in the list of options in section 4.3 "Enhanced Packet Block"
1818 * of the current pcapng spec, at
1819 *
1820 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-enhanced-packet-block
1821 *
1822 * All option codes in this switch statement here must be listed
1823 * in one of those places as standardized option types.
1824 */
1825 switch (option_code) {
1826 case(OPT_PKT_FLAGS2):
1827 if (option_length != 4) {
1828 *err = WTAP_ERR_BAD_FILE-13;
1829 *err_info = ws_strdup_printf("pcapng: packet block flags option length %u is not 4",wmem_strdup_printf(((void*)0), "pcapng: packet block flags option length %u is not 4"
, option_length)
1830 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block flags option length %u is not 4"
, option_length)
;
1831 /* XXX - free anything? */
1832 return false0;
1833 }
1834 pcapng_process_uint32_option(wblock, section_info,
1835 OPT_SECTION_BYTE_ORDER,
1836 option_code, option_length,
1837 option_content);
1838 break;
1839 case(OPT_PKT_HASH3):
1840 if (option_length < 1) {
1841 *err = WTAP_ERR_BAD_FILE-13;
1842 *err_info = ws_strdup_printf("pcapng: packet block hash option length %u is < 1",wmem_strdup_printf(((void*)0), "pcapng: packet block hash option length %u is < 1"
, option_length)
1843 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block hash option length %u is < 1"
, option_length)
;
1844 /* XXX - free anything? */
1845 return false0;
1846 }
1847 packet_hash.type = option_content[0];
1848 packet_hash.hash_bytes =
1849 g_byte_array_new_take((uint8_t *)g_memdup2(&option_content[1],
1850 option_length - 1),
1851 option_length - 1);
1852 wtap_block_add_packet_hash_option(wblock->block, option_code, &packet_hash);
1853 wtap_packet_hash_free(&packet_hash);
1854 ws_debug("hash type %u, data len %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1855, __func__, "hash type %u, data len %u", option_content
[0], option_length - 1); } } while (0)
1855 option_content[0], option_length - 1)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1855, __func__, "hash type %u, data len %u", option_content
[0], option_length - 1); } } while (0)
;
1856 break;
1857 case(OPT_PKT_DROPCOUNT4):
1858 if (option_length != 8) {
1859 *err = WTAP_ERR_BAD_FILE-13;
1860 *err_info = ws_strdup_printf("pcapng: packet block drop count option length %u is not 8",wmem_strdup_printf(((void*)0), "pcapng: packet block drop count option length %u is not 8"
, option_length)
1861 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block drop count option length %u is not 8"
, option_length)
;
1862 /* XXX - free anything? */
1863 return false0;
1864 }
1865 pcapng_process_uint64_option(wblock, section_info,
1866 OPT_SECTION_BYTE_ORDER,
1867 option_code, option_length,
1868 option_content);
1869 break;
1870 case(OPT_PKT_PACKETID5):
1871 if (option_length != 8) {
1872 *err = WTAP_ERR_BAD_FILE-13;
1873 *err_info = ws_strdup_printf("pcapng: packet block packet id option length %u is not 8",wmem_strdup_printf(((void*)0), "pcapng: packet block packet id option length %u is not 8"
, option_length)
1874 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block packet id option length %u is not 8"
, option_length)
;
1875 /* XXX - free anything? */
1876 return false0;
1877 }
1878 pcapng_process_uint64_option(wblock, section_info,
1879 OPT_SECTION_BYTE_ORDER,
1880 option_code, option_length,
1881 option_content);
1882 break;
1883 case(OPT_PKT_QUEUE6):
1884 if (option_length != 4) {
1885 *err = WTAP_ERR_BAD_FILE-13;
1886 *err_info = ws_strdup_printf("pcapng: packet block queue option length %u is not 4",wmem_strdup_printf(((void*)0), "pcapng: packet block queue option length %u is not 4"
, option_length)
1887 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block queue option length %u is not 4"
, option_length)
;
1888 /* XXX - free anything? */
1889 return false0;
1890 }
1891 pcapng_process_uint32_option(wblock, section_info,
1892 OPT_SECTION_BYTE_ORDER,
1893 option_code, option_length,
1894 option_content);
1895 break;
1896 case(OPT_PKT_VERDICT7):
1897 if (option_length < 1) {
1898 *err = WTAP_ERR_BAD_FILE-13;
1899 *err_info = ws_strdup_printf("pcapng: packet block verdict option length %u is < 1",wmem_strdup_printf(((void*)0), "pcapng: packet block verdict option length %u is < 1"
, option_length)
1900 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block verdict option length %u is < 1"
, option_length)
;
1901 /* XXX - free anything? */
1902 return false0;
1903 }
1904 switch (option_content[0]) {
1905
1906 case(OPT_VERDICT_TYPE_HW0):
1907 packet_verdict.type = packet_verdict_hardware;
1908 packet_verdict.data.verdict_bytes =
1909 g_byte_array_new_take((uint8_t *)g_memdup2(&option_content[1],
1910 option_length - 1),
1911 option_length - 1);
1912 break;
1913
1914 case(OPT_VERDICT_TYPE_TC1):
1915 if (option_length != 9) {
1916 *err = WTAP_ERR_BAD_FILE-13;
1917 *err_info = ws_strdup_printf("pcapng: packet block TC verdict option length %u is != 9",wmem_strdup_printf(((void*)0), "pcapng: packet block TC verdict option length %u is != 9"
, option_length)
1918 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block TC verdict option length %u is != 9"
, option_length)
;
1919 /* XXX - free anything? */
1920 return false0;
1921 }
1922 /* Don't cast a uint8_t * into a uint64_t *--the
1923 * uint8_t * may not point to something that's
1924 * aligned correctly.
1925 */
1926 memcpy(&tmp64, &option_content[1], sizeof(uint64_t));
1927 if (section_info->byte_swapped)
1928 tmp64 = GUINT64_SWAP_LE_BE(tmp64)(((guint64) ( (((guint64) (tmp64) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (tmp64) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (tmp64) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (tmp64) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (tmp64) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (tmp64) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (tmp64) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (tmp64) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
1929 packet_verdict.type = packet_verdict_linux_ebpf_tc;
1930 packet_verdict.data.verdict_linux_ebpf_tc = tmp64;
1931 break;
1932
1933 case(OPT_VERDICT_TYPE_XDP2):
1934 if (option_length != 9) {
1935 *err = WTAP_ERR_BAD_FILE-13;
1936 *err_info = ws_strdup_printf("pcapng: packet block XDP verdict option length %u is != 9",wmem_strdup_printf(((void*)0), "pcapng: packet block XDP verdict option length %u is != 9"
, option_length)
1937 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block XDP verdict option length %u is != 9"
, option_length)
;
1938 /* XXX - free anything? */
1939 return false0;
1940 }
1941 /* Don't cast a uint8_t * into a uint64_t *--the
1942 * uint8_t * may not point to something that's
1943 * aligned correctly.
1944 */
1945 memcpy(&tmp64, &option_content[1], sizeof(uint64_t));
1946 if (section_info->byte_swapped)
1947 tmp64 = GUINT64_SWAP_LE_BE(tmp64)(((guint64) ( (((guint64) (tmp64) & (guint64) (0x00000000000000ffUL
)) << 56) | (((guint64) (tmp64) & (guint64) (0x000000000000ff00UL
)) << 40) | (((guint64) (tmp64) & (guint64) (0x0000000000ff0000UL
)) << 24) | (((guint64) (tmp64) & (guint64) (0x00000000ff000000UL
)) << 8) | (((guint64) (tmp64) & (guint64) (0x000000ff00000000UL
)) >> 8) | (((guint64) (tmp64) & (guint64) (0x0000ff0000000000UL
)) >> 24) | (((guint64) (tmp64) & (guint64) (0x00ff000000000000UL
)) >> 40) | (((guint64) (tmp64) & (guint64) (0xff00000000000000UL
)) >> 56))))
;
1948 packet_verdict.type = packet_verdict_linux_ebpf_xdp;
1949 packet_verdict.data.verdict_linux_ebpf_xdp = tmp64;
1950 break;
1951
1952 default:
1953 /* Silently ignore unknown verdict types */
1954 return true1;
1955 }
1956 wtap_block_add_packet_verdict_option(wblock->block, option_code, &packet_verdict);
1957 wtap_packet_verdict_free(&packet_verdict);
1958 ws_debug("verdict type %u, data len %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1959, __func__, "verdict type %u, data len %u", option_content
[0], option_length - 1); } } while (0)
1959 option_content[0], option_length - 1)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 1959, __func__, "verdict type %u, data len %u", option_content
[0], option_length - 1); } } while (0)
;
1960 break;
1961 case(OPT_PKT_PROCIDTHRDID8):
1962 if (option_length != 8) {
1963 *err = WTAP_ERR_BAD_FILE-13;
1964 *err_info = ws_strdup_printf("pcapng: packet block process id thread id option length %u is not 8",wmem_strdup_printf(((void*)0), "pcapng: packet block process id thread id option length %u is not 8"
, option_length)
1965 option_length)wmem_strdup_printf(((void*)0), "pcapng: packet block process id thread id option length %u is not 8"
, option_length)
;
1966 /* XXX - free anything? */
1967 return false0;
1968 }
1969 // XXX - It's two concatenated 32 bit unsigned integers
1970 pcapng_process_uint64_option(wblock, section_info,
1971 OPT_SECTION_BYTE_ORDER,
1972 option_code, option_length,
1973 option_content);
1974 break;
1975 default:
1976 if (!pcapng_process_unhandled_option(wblock, section_info,
1977 option_code, option_length,
1978 option_content,
1979 err, err_info))
1980 return false0;
1981 break;
1982 }
1983 return true1;
1984}
1985
1986static bool_Bool
1987pcapng_read_packet_block(wtap *wth _U___attribute__((unused)), FILE_T fh, uint32_t block_type,
1988 uint32_t block_content_length,
1989 section_info_t *section_info,
1990 wtapng_block_t *wblock,
1991 int *err, char **err_info)
1992{
1993 unsigned block_read;
1994 unsigned opt_cont_buf_len;
1995 pcapng_enhanced_packet_block_t epb;
1996 pcapng_packet_block_t pb;
1997 wtapng_packet_t packet;
1998 uint32_t padding;
1999 uint32_t flags;
2000 uint64_t tmp64;
2001 interface_info_t iface_info;
2002 uint64_t ts;
2003 int pseudo_header_len;
2004 int fcslen;
2005 bool_Bool enhanced = (block_type == BLOCK_TYPE_EPB0x00000006);
2006
2007 wblock->block = wtap_block_create(WTAP_BLOCK_PACKET);
2008
2009 if (enhanced) {
2010 /*
2011 * Is this block long enough to be an EPB?
2012 */
2013 if (block_content_length < sizeof epb) {
2014 /*
2015 * No.
2016 */
2017 *err = WTAP_ERR_BAD_FILE-13;
2018 *err_info = ws_strdup_printf("pcapng: block content length %u of an EPB is less than the minimum EPB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an EPB is less than the minimum EPB content size %zu"
, block_content_length, sizeof epb)
2019 block_content_length, sizeof epb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an EPB is less than the minimum EPB content size %zu"
, block_content_length, sizeof epb)
;
2020 return false0;
2021 }
2022
2023 /* "Enhanced Packet Block" read fixed part */
2024 if (!wtap_read_bytes(fh, &epb, sizeof epb, err, err_info)) {
2025 ws_debug("failed to read EPB fixed portion")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2025, __func__, "failed to read EPB fixed portion"); } } while
(0)
;
2026 return false0;
2027 }
2028 block_read = (unsigned)sizeof epb;
2029
2030 if (section_info->byte_swapped) {
2031 packet.interface_id = GUINT32_SWAP_LE_BE(epb.interface_id)(((guint32) ( (((guint32) (epb.interface_id) & (guint32) 0x000000ffU
) << 24) | (((guint32) (epb.interface_id) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (epb.interface_id) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (epb.interface_id
) & (guint32) 0xff000000U) >> 24))))
;
2032 packet.drops_count = 0xFFFF; /* invalid */
2033 packet.ts_high = GUINT32_SWAP_LE_BE(epb.timestamp_high)(((guint32) ( (((guint32) (epb.timestamp_high) & (guint32
) 0x000000ffU) << 24) | (((guint32) (epb.timestamp_high
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (epb
.timestamp_high) & (guint32) 0x00ff0000U) >> 8) | (
((guint32) (epb.timestamp_high) & (guint32) 0xff000000U) >>
24))))
;
2034 packet.ts_low = GUINT32_SWAP_LE_BE(epb.timestamp_low)(((guint32) ( (((guint32) (epb.timestamp_low) & (guint32)
0x000000ffU) << 24) | (((guint32) (epb.timestamp_low) &
(guint32) 0x0000ff00U) << 8) | (((guint32) (epb.timestamp_low
) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (epb
.timestamp_low) & (guint32) 0xff000000U) >> 24))))
;
2035 packet.cap_len = GUINT32_SWAP_LE_BE(epb.captured_len)(((guint32) ( (((guint32) (epb.captured_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (epb.captured_len) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (epb.captured_len) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (epb.captured_len
) & (guint32) 0xff000000U) >> 24))))
;
2036 packet.packet_len = GUINT32_SWAP_LE_BE(epb.packet_len)(((guint32) ( (((guint32) (epb.packet_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (epb.packet_len) & (guint32)
0x0000ff00U) << 8) | (((guint32) (epb.packet_len) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (epb.packet_len
) & (guint32) 0xff000000U) >> 24))))
;
2037 } else {
2038 packet.interface_id = epb.interface_id;
2039 packet.drops_count = 0xFFFF; /* invalid */
2040 packet.ts_high = epb.timestamp_high;
2041 packet.ts_low = epb.timestamp_low;
2042 packet.cap_len = epb.captured_len;
2043 packet.packet_len = epb.packet_len;
2044 }
2045 ws_debug("EPB on interface_id %d, cap_len %d, packet_len %d",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2046, __func__, "EPB on interface_id %d, cap_len %d, packet_len %d"
, packet.interface_id, packet.cap_len, packet.packet_len); } }
while (0)
2046 packet.interface_id, packet.cap_len, packet.packet_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2046, __func__, "EPB on interface_id %d, cap_len %d, packet_len %d"
, packet.interface_id, packet.cap_len, packet.packet_len); } }
while (0)
;
2047 } else {
2048 /*
2049 * Is this block long enough to be a PB?
2050 */
2051 if (block_content_length < sizeof pb) {
2052 /*
2053 * No.
2054 */
2055 *err = WTAP_ERR_BAD_FILE-13;
2056 *err_info = ws_strdup_printf("pcapng: block content length %u of a PB is less than the minimum PB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a PB is less than the minimum PB content size %zu"
, block_content_length, sizeof pb)
2057 block_content_length, sizeof pb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a PB is less than the minimum PB content size %zu"
, block_content_length, sizeof pb)
;
2058 return false0;
2059 }
2060
2061 /* "Packet Block" read fixed part */
2062 if (!wtap_read_bytes(fh, &pb, sizeof pb, err, err_info)) {
2063 ws_debug("failed to read packet data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2063, __func__, "failed to read packet data"); } } while (0
)
;
2064 return false0;
2065 }
2066 block_read = (unsigned)sizeof pb;
2067
2068 if (section_info->byte_swapped) {
2069 packet.interface_id = GUINT16_SWAP_LE_BE(pb.interface_id)(((guint16) ( (guint16) ((guint16) (pb.interface_id) >>
8) | (guint16) ((guint16) (pb.interface_id) << 8))))
;
2070 packet.drops_count = GUINT16_SWAP_LE_BE(pb.drops_count)(((guint16) ( (guint16) ((guint16) (pb.drops_count) >> 8
) | (guint16) ((guint16) (pb.drops_count) << 8))))
;
2071 packet.ts_high = GUINT32_SWAP_LE_BE(pb.timestamp_high)(((guint32) ( (((guint32) (pb.timestamp_high) & (guint32)
0x000000ffU) << 24) | (((guint32) (pb.timestamp_high) &
(guint32) 0x0000ff00U) << 8) | (((guint32) (pb.timestamp_high
) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (pb.
timestamp_high) & (guint32) 0xff000000U) >> 24))))
;
2072 packet.ts_low = GUINT32_SWAP_LE_BE(pb.timestamp_low)(((guint32) ( (((guint32) (pb.timestamp_low) & (guint32) 0x000000ffU
) << 24) | (((guint32) (pb.timestamp_low) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (pb.timestamp_low) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (pb.timestamp_low
) & (guint32) 0xff000000U) >> 24))))
;
2073 packet.cap_len = GUINT32_SWAP_LE_BE(pb.captured_len)(((guint32) ( (((guint32) (pb.captured_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (pb.captured_len) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (pb.captured_len) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (pb.captured_len
) & (guint32) 0xff000000U) >> 24))))
;
2074 packet.packet_len = GUINT32_SWAP_LE_BE(pb.packet_len)(((guint32) ( (((guint32) (pb.packet_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (pb.packet_len) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (pb.packet_len) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (pb.packet_len) & (guint32) 0xff000000U
) >> 24))))
;
2075 } else {
2076 packet.interface_id = pb.interface_id;
2077 packet.drops_count = pb.drops_count;
2078 packet.ts_high = pb.timestamp_high;
2079 packet.ts_low = pb.timestamp_low;
2080 packet.cap_len = pb.captured_len;
2081 packet.packet_len = pb.packet_len;
2082 }
2083 ws_debug("PB on interface_id %d, cap_len %d, packet_len %d",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2084, __func__, "PB on interface_id %d, cap_len %d, packet_len %d"
, packet.interface_id, packet.cap_len, packet.packet_len); } }
while (0)
2084 packet.interface_id, packet.cap_len, packet.packet_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2084, __func__, "PB on interface_id %d, cap_len %d, packet_len %d"
, packet.interface_id, packet.cap_len, packet.packet_len); } }
while (0)
;
2085 }
2086 ws_debug("packet data: packet_len %u captured_len %u interface_id %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2089, __func__, "packet data: packet_len %u captured_len %u interface_id %u"
, packet.packet_len, packet.cap_len, packet.interface_id); } }
while (0)
2087 packet.packet_len,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2089, __func__, "packet data: packet_len %u captured_len %u interface_id %u"
, packet.packet_len, packet.cap_len, packet.interface_id); } }
while (0)
2088 packet.cap_len,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2089, __func__, "packet data: packet_len %u captured_len %u interface_id %u"
, packet.packet_len, packet.cap_len, packet.interface_id); } }
while (0)
2089 packet.interface_id)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2089, __func__, "packet data: packet_len %u captured_len %u interface_id %u"
, packet.packet_len, packet.cap_len, packet.interface_id); } }
while (0)
;
2090
2091 if (packet.interface_id >= section_info->interfaces->len) {
2092 *err = WTAP_ERR_BAD_FILE-13;
2093 *err_info = ws_strdup_printf("pcapng: interface index %u is not less than section interface count %u",wmem_strdup_printf(((void*)0), "pcapng: interface index %u is not less than section interface count %u"
, packet.interface_id, section_info->interfaces->len)
2094 packet.interface_id,wmem_strdup_printf(((void*)0), "pcapng: interface index %u is not less than section interface count %u"
, packet.interface_id, section_info->interfaces->len)
2095 section_info->interfaces->len)wmem_strdup_printf(((void*)0), "pcapng: interface index %u is not less than section interface count %u"
, packet.interface_id, section_info->interfaces->len)
;
2096 return false0;
2097 }
2098 iface_info = g_array_index(section_info->interfaces, interface_info_t,(((interface_info_t*) (void *) (section_info->interfaces)->
data) [(packet.interface_id)])
2099 packet.interface_id)(((interface_info_t*) (void *) (section_info->interfaces)->
data) [(packet.interface_id)])
;
2100
2101 if (packet.cap_len > wtap_max_snaplen_for_encap(iface_info.wtap_encap)) {
2102 *err = WTAP_ERR_BAD_FILE-13;
2103 *err_info = ws_strdup_printf("pcapng: cap_len %u is larger than maximum supported length %u",wmem_strdup_printf(((void*)0), "pcapng: cap_len %u is larger than maximum supported length %u"
, packet.cap_len, wtap_max_snaplen_for_encap(iface_info.wtap_encap
))
2104 packet.cap_len,wmem_strdup_printf(((void*)0), "pcapng: cap_len %u is larger than maximum supported length %u"
, packet.cap_len, wtap_max_snaplen_for_encap(iface_info.wtap_encap
))
2105 wtap_max_snaplen_for_encap(iface_info.wtap_encap))wmem_strdup_printf(((void*)0), "pcapng: cap_len %u is larger than maximum supported length %u"
, packet.cap_len, wtap_max_snaplen_for_encap(iface_info.wtap_encap
))
;
2106 return false0;
2107 }
2108
2109 /*
2110 * How much padding is there at the end of the packet data?
2111 */
2112 padding = WS_PADDING_TO_4(packet.cap_len)((4U - ((packet.cap_len) % 4U)) % 4U);
2113
2114 /*
2115 * Is this block long enough to hold the packet data?
2116 */
2117 if (enhanced) {
2118 if (block_content_length < sizeof epb + packet.cap_len + padding) {
2119 /*
2120 * No.
2121 */
2122 *err = WTAP_ERR_BAD_FILE-13;
2123 *err_info = ws_strdup_printf("pcapng: block content length %u of an EPB is too small for %u bytes of packet data",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an EPB is too small for %u bytes of packet data"
, block_content_length, packet.cap_len)
2124 block_content_length, packet.cap_len)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an EPB is too small for %u bytes of packet data"
, block_content_length, packet.cap_len)
;
2125 return false0;
2126 }
2127 } else {
2128 if (block_content_length < sizeof pb + packet.cap_len + padding) {
2129 /*
2130 * No.
2131 */
2132 *err = WTAP_ERR_BAD_FILE-13;
2133 *err_info = ws_strdup_printf("pcapng: total block length %u of a PB is too small for %u bytes of packet data",wmem_strdup_printf(((void*)0), "pcapng: total block length %u of a PB is too small for %u bytes of packet data"
, block_content_length, packet.cap_len)
2134 block_content_length, packet.cap_len)wmem_strdup_printf(((void*)0), "pcapng: total block length %u of a PB is too small for %u bytes of packet data"
, block_content_length, packet.cap_len)
;
2135 return false0;
2136 }
2137 }
2138
2139 ws_debug("Need to read pseudo header of size %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2140, __func__, "Need to read pseudo header of size %u", pcap_get_phdr_size
(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header
.pseudo_header)); } } while (0)
2140 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header.pseudo_header))do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2140, __func__, "Need to read pseudo header of size %u", pcap_get_phdr_size
(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header
.pseudo_header)); } } while (0)
;
2141
2142 wtap_setup_packet_rec(wblock->rec, iface_info.wtap_encap);
2143 wblock->rec->presence_flags = WTAP_HAS_TS0x00000001|WTAP_HAS_CAP_LEN0x00000002|WTAP_HAS_INTERFACE_ID0x00000004;
2144
2145 ws_debug("encapsulation = %d (%s), pseudo header size = %u.",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2148, __func__, "encapsulation = %d (%s), pseudo header size = %u."
, iface_info.wtap_encap, wtap_encap_description(iface_info.wtap_encap
), pcap_get_phdr_size(iface_info.wtap_encap, &wblock->
rec->rec_header.packet_header.pseudo_header)); } } while (
0)
2146 iface_info.wtap_encap,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2148, __func__, "encapsulation = %d (%s), pseudo header size = %u."
, iface_info.wtap_encap, wtap_encap_description(iface_info.wtap_encap
), pcap_get_phdr_size(iface_info.wtap_encap, &wblock->
rec->rec_header.packet_header.pseudo_header)); } } while (
0)
2147 wtap_encap_description(iface_info.wtap_encap),do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2148, __func__, "encapsulation = %d (%s), pseudo header size = %u."
, iface_info.wtap_encap, wtap_encap_description(iface_info.wtap_encap
), pcap_get_phdr_size(iface_info.wtap_encap, &wblock->
rec->rec_header.packet_header.pseudo_header)); } } while (
0)
2148 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header.pseudo_header))do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2148, __func__, "encapsulation = %d (%s), pseudo header size = %u."
, iface_info.wtap_encap, wtap_encap_description(iface_info.wtap_encap
), pcap_get_phdr_size(iface_info.wtap_encap, &wblock->
rec->rec_header.packet_header.pseudo_header)); } } while (
0)
;
2149 wblock->rec->rec_header.packet_header.interface_id = packet.interface_id;
2150 wblock->rec->tsprec = iface_info.tsprecision;
2151
2152 memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
2153 pseudo_header_len = pcap_process_pseudo_header(fh,
2154 false0, /* not a Nokia pcap - not a pcap at all */
2155 iface_info.wtap_encap,
2156 packet.cap_len,
2157 wblock->rec,
2158 err,
2159 err_info);
2160 if (pseudo_header_len < 0) {
2161 return false0;
2162 }
2163 block_read += pseudo_header_len;
2164 wblock->rec->rec_header.packet_header.caplen = packet.cap_len - pseudo_header_len;
2165 wblock->rec->rec_header.packet_header.len = packet.packet_len - pseudo_header_len;
2166
2167 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
2168 ts = (((uint64_t)packet.ts_high) << 32) | ((uint64_t)packet.ts_low);
2169
2170 /* Convert it to seconds and nanoseconds. */
2171 wblock->rec->ts.secs = (time_t)(ts / iface_info.time_units_per_second);
2172 wblock->rec->ts.nsecs = (int)(((ts % iface_info.time_units_per_second) * 1000000000) / iface_info.time_units_per_second);
2173
2174 /* Add the time stamp offset. */
2175 wblock->rec->ts.secs = (time_t)(wblock->rec->ts.secs + iface_info.tsoffset);
2176
2177 /* "(Enhanced) Packet Block" read capture data */
2178 if (!wtap_read_bytes_buffer(fh, &wblock->rec->data,
2179 packet.cap_len - pseudo_header_len, err, err_info))
2180 return false0;
2181 block_read += packet.cap_len - pseudo_header_len;
2182
2183 /* jump over potential padding bytes at end of the packet data */
2184 if (padding != 0) {
2185 if (!wtap_read_bytes(fh, NULL((void*)0), padding, err, err_info))
2186 return false0;
2187 block_read += padding;
2188 }
2189
2190 /* FCS length default */
2191 fcslen = iface_info.fcslen;
2192
2193 /* Options */
2194 opt_cont_buf_len = block_content_length - block_read;
2195 if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
2196 pcapng_process_packet_block_option,
2197 OPT_SECTION_BYTE_ORDER, err, err_info))
2198 return false0;
2199
2200 /*
2201 * Did we get a packet flags option?
2202 */
2203 if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_uint32_option_value(wblock->block, OPT_PKT_FLAGS2, &flags)) {
2204 if (PACK_FLAGS_FCS_LENGTH(flags)(((flags) & 0x000001E0) >> 5) != 0) {
2205 /*
2206 * The FCS length is present, but in units of octets, not
2207 * bits; convert it to bits.
2208 */
2209 fcslen = PACK_FLAGS_FCS_LENGTH(flags)(((flags) & 0x000001E0) >> 5)*8;
2210 }
2211 }
2212 /*
2213 * How about a drop_count option? If not, set it from other sources
2214 */
2215 if (WTAP_OPTTYPE_SUCCESS != wtap_block_get_uint64_option_value(wblock->block, OPT_PKT_DROPCOUNT4, &tmp64) && packet.drops_count != 0xFFFF) {
2216 wtap_block_add_uint64_option(wblock->block, OPT_PKT_DROPCOUNT4, (uint64_t)packet.drops_count);
2217 }
2218
2219 pcap_read_post_process(false0, iface_info.wtap_encap, wblock->rec,
2220 section_info->byte_swapped, fcslen);
2221
2222 /*
2223 * We return these to the caller in pcapng_read().
2224 */
2225 wblock->internal = false0;
2226
2227 /*
2228 * We want dissectors (particularly packet_frame) to be able to
2229 * access packet comments and whatnot that are in the block. wblock->block
2230 * will be unref'd by pcapng_seek_read(), so move the block to where
2231 * dissectors can find it.
2232 */
2233 wblock->rec->block = wblock->block;
2234 wblock->block = NULL((void*)0);
2235
2236 return true1;
2237}
2238
2239
2240static bool_Bool
2241pcapng_read_simple_packet_block(wtap *wth _U___attribute__((unused)), FILE_T fh,
2242 uint32_t block_type _U___attribute__((unused)),
2243 uint32_t block_content_length,
2244 section_info_t *section_info,
2245 wtapng_block_t *wblock,
2246 int *err, char **err_info)
2247{
2248 pcapng_simple_packet_block_t spb;
2249 wtapng_simple_packet_t simple_packet;
2250 uint32_t padding;
2251 interface_info_t iface_info;
2252 int pseudo_header_len;
2253
2254 /*
2255 * Is this block long enough to be an SPB?
2256 */
2257 if (block_content_length < sizeof spb) {
2258 /*
2259 * No.
2260 */
2261 *err = WTAP_ERR_BAD_FILE-13;
2262 *err_info = ws_strdup_printf("pcapng: block content length %u of an SPB is less than the minimum SPB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an SPB is less than the minimum SPB content size %zu"
, block_content_length, sizeof spb)
2263 block_content_length, sizeof spb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an SPB is less than the minimum SPB content size %zu"
, block_content_length, sizeof spb)
;
2264 return false0;
2265 }
2266
2267 /* "Simple Packet Block" read fixed part */
2268 if (!wtap_read_bytes(fh, &spb, sizeof spb, err, err_info)) {
2269 ws_debug("failed to read SPB fixed portion")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2269, __func__, "failed to read SPB fixed portion"); } } while
(0)
;
2270 return false0;
2271 }
2272
2273 if (section_info->byte_swapped) {
2274 simple_packet.packet_len = GUINT32_SWAP_LE_BE(spb.packet_len)(((guint32) ( (((guint32) (spb.packet_len) & (guint32) 0x000000ffU
) << 24) | (((guint32) (spb.packet_len) & (guint32)
0x0000ff00U) << 8) | (((guint32) (spb.packet_len) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (spb.packet_len
) & (guint32) 0xff000000U) >> 24))))
;
2275 } else {
2276 simple_packet.packet_len = spb.packet_len;
2277 }
2278
2279 if (0 >= section_info->interfaces->len) {
2280 *err = WTAP_ERR_BAD_FILE-13;
2281 *err_info = g_strdup("pcapng: SPB appeared before any IDBs in the section")g_strdup_inline ("pcapng: SPB appeared before any IDBs in the section"
)
;
2282 return false0;
2283 }
2284 iface_info = g_array_index(section_info->interfaces, interface_info_t, 0)(((interface_info_t*) (void *) (section_info->interfaces)->
data) [(0)])
;
2285
2286 /*
2287 * The captured length is not a field in the SPB; it can be
2288 * calculated as the minimum of the snapshot length from the
2289 * IDB and the packet length, as per the pcapng spec. An IDB
2290 * snapshot length of 0 means no limit.
2291 */
2292 simple_packet.cap_len = simple_packet.packet_len;
2293 if (simple_packet.cap_len > iface_info.snap_len && iface_info.snap_len != 0)
2294 simple_packet.cap_len = iface_info.snap_len;
2295 ws_debug("packet data: packet_len %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2296, __func__, "packet data: packet_len %u", simple_packet
.packet_len); } } while (0)
2296 simple_packet.packet_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2296, __func__, "packet data: packet_len %u", simple_packet
.packet_len); } } while (0)
;
2297
2298 if (simple_packet.cap_len > wtap_max_snaplen_for_encap(iface_info.wtap_encap)) {
2299 *err = WTAP_ERR_BAD_FILE-13;
2300 *err_info = ws_strdup_printf("pcapng: cap_len %u is larger than maximum supported length %u",wmem_strdup_printf(((void*)0), "pcapng: cap_len %u is larger than maximum supported length %u"
, simple_packet.cap_len, wtap_max_snaplen_for_encap(iface_info
.wtap_encap))
2301 simple_packet.cap_len,wmem_strdup_printf(((void*)0), "pcapng: cap_len %u is larger than maximum supported length %u"
, simple_packet.cap_len, wtap_max_snaplen_for_encap(iface_info
.wtap_encap))
2302 wtap_max_snaplen_for_encap(iface_info.wtap_encap))wmem_strdup_printf(((void*)0), "pcapng: cap_len %u is larger than maximum supported length %u"
, simple_packet.cap_len, wtap_max_snaplen_for_encap(iface_info
.wtap_encap))
;
2303 return false0;
2304 }
2305
2306 /*
2307 * How much padding is there at the end of the packet data?
2308 */
2309 padding = WS_PADDING_TO_4(simple_packet.cap_len)((4U - ((simple_packet.cap_len) % 4U)) % 4U);
2310
2311 /*
2312 * Is this block long enough to hold the packet data?
2313 */
2314 if (block_content_length < sizeof spb + simple_packet.cap_len + padding) {
2315 /*
2316 * No. That means that the problem is with the packet
2317 * length; the snapshot length can be bigger than the amount
2318 * of packet data in the block, as it's a *maximum* length,
2319 * not a *minimum* length.
2320 */
2321 *err = WTAP_ERR_BAD_FILE-13;
2322 *err_info = ws_strdup_printf("pcapng: block content length %u of an SPB is too small for %u bytes of packet data",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an SPB is too small for %u bytes of packet data"
, block_content_length, simple_packet.cap_len)
2323 block_content_length, simple_packet.cap_len)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an SPB is too small for %u bytes of packet data"
, block_content_length, simple_packet.cap_len)
;
2324 return false0;
2325 }
2326
2327 ws_debug("Need to read pseudo header of size %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2328, __func__, "Need to read pseudo header of size %u", pcap_get_phdr_size
(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header
.pseudo_header)); } } while (0)
2328 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header.pseudo_header))do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2328, __func__, "Need to read pseudo header of size %u", pcap_get_phdr_size
(iface_info.wtap_encap, &wblock->rec->rec_header.packet_header
.pseudo_header)); } } while (0)
;
2329
2330 /* No time stamp in a simple packet block; no options, either */
2331 wtap_setup_packet_rec(wblock->rec, iface_info.wtap_encap);
2332 wblock->rec->presence_flags = WTAP_HAS_CAP_LEN0x00000002|WTAP_HAS_INTERFACE_ID0x00000004;
2333 wblock->rec->rec_header.packet_header.interface_id = 0;
2334 wblock->rec->tsprec = iface_info.tsprecision;
2335 wblock->rec->ts.secs = 0;
2336 wblock->rec->ts.nsecs = 0;
2337 wblock->rec->rec_header.packet_header.interface_id = 0;
2338
2339 memset((void *)&wblock->rec->rec_header.packet_header.pseudo_header, 0, sizeof(union wtap_pseudo_header));
2340 pseudo_header_len = pcap_process_pseudo_header(fh,
2341 false0, /* not a Nokia pcap - not a pcap at all */
2342 iface_info.wtap_encap,
2343 simple_packet.cap_len,
2344 wblock->rec,
2345 err,
2346 err_info);
2347 if (pseudo_header_len < 0) {
2348 return false0;
2349 }
2350 wblock->rec->rec_header.packet_header.caplen = simple_packet.cap_len - pseudo_header_len;
2351 wblock->rec->rec_header.packet_header.len = simple_packet.packet_len - pseudo_header_len;
2352
2353 /* "Simple Packet Block" read capture data */
2354 if (!wtap_read_bytes_buffer(fh, &wblock->rec->data,
2355 simple_packet.cap_len - pseudo_header_len, err, err_info))
2356 return false0;
2357
2358 /* jump over potential padding bytes at end of the packet data */
2359 if (padding != 0) {
2360 if (!wtap_read_bytes(fh, NULL((void*)0), padding, err, err_info))
2361 return false0;
2362 }
2363
2364 pcap_read_post_process(false0, iface_info.wtap_encap, wblock->rec,
2365 section_info->byte_swapped, iface_info.fcslen);
2366
2367 /*
2368 * We return these to the caller in pcapng_read().
2369 */
2370 wblock->internal = false0;
2371
2372 /*
2373 * We want dissectors (particularly packet_frame) to be able to
2374 * access packet comments and whatnot that are in the block
2375 * (not that there will be any, as an SPB has no options). wblock->block
2376 * will be unref'd by pcapng_seek_read(), so move the block to where
2377 * dissectors can find it.
2378 */
2379 wblock->rec->block = wblock->block;
2380 wblock->block = NULL((void*)0);
2381
2382 return true1;
2383}
2384
2385#define NRES_ENDOFRECORD0 0
2386#define NRES_IP4RECORD1 1
2387#define NRES_IP6RECORD2 2
2388/* IPv6 + MAXDNSNAMELEN */
2389#define INITIAL_NRB_REC_SIZE(16 + 256) (16 + MAXDNSNAMELEN256)
2390
2391/*
2392 * Find the end of the NUL-terminated name the beginning of which is pointed
2393 * to by p; record_len is the number of bytes remaining in the record.
2394 *
2395 * Return the length of the name, including the terminating NUL.
2396 *
2397 * If we don't find a terminating NUL, return -1 and set *err and
2398 * *err_info appropriately.
2399 */
2400static int
2401name_resolution_block_find_name_end(const char *p, unsigned record_len, int *err,
2402 char **err_info)
2403{
2404 int namelen;
2405
2406 namelen = 0;
2407 for (;;) {
2408 if (record_len == 0) {
2409 /*
2410 * We ran out of bytes in the record without
2411 * finding a NUL.
2412 */
2413 *err = WTAP_ERR_BAD_FILE-13;
2414 *err_info = g_strdup("pcapng: NRB record has non-null-terminated host name")g_strdup_inline ("pcapng: NRB record has non-null-terminated host name"
)
;
2415 return -1;
2416 }
2417 if (*p == '\0')
2418 break; /* that's the terminating NUL */
2419 p++;
2420 record_len--;
2421 namelen++; /* count this byte */
2422 }
2423
2424 /* Include the NUL in the name length. */
2425 return namelen + 1;
2426}
2427
2428static bool_Bool
2429pcapng_process_name_resolution_block_option(wtapng_block_t *wblock,
2430 section_info_t *section_info,
2431 uint16_t option_code,
2432 uint16_t option_length,
2433 const uint8_t *option_content,
2434 int *err, char **err_info)
2435{
2436 /*
2437 * Handle option content.
2438 *
2439 * ***DO NOT*** add any items to this table that are not
2440 * standardized option codes in either section 3.5 "Options"
2441 * of the current pcapng spec, at
2442 *
2443 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-options
2444 *
2445 * or in the list of options in section 4.1 "Section Header Block"
2446 * of the current pcapng spec, at
2447 *
2448 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-section-header-block
2449 *
2450 * All option codes in this switch statement here must be listed
2451 * in one of those places as standardized option types.
2452 */
2453 switch (option_code) {
2454 /* TODO:
2455 * ns_dnsname 2
2456 * ns_dnsIP4addr 3
2457 * ns_dnsIP6addr 4
2458 */
2459 default:
2460 if (!pcapng_process_unhandled_option(wblock, section_info,
2461 option_code, option_length,
2462 option_content,
2463 err, err_info))
2464 return false0;
2465 break;
2466 }
2467 return true1;
2468}
2469
2470static bool_Bool
2471pcapng_read_name_resolution_block(wtap *wth _U___attribute__((unused)), FILE_T fh,
2472 uint32_t block_type _U___attribute__((unused)),
2473 uint32_t block_content_length,
2474 section_info_t *section_info,
2475 wtapng_block_t *wblock,
2476 int *err, char **err_info)
2477{
2478 unsigned to_read;
2479 pcapng_name_resolution_block_t nrb;
2480 Buffer nrb_rec;
2481 uint32_t v4_addr;
2482 unsigned record_len, opt_cont_buf_len;
2483 const char *namep;
2484 int namelen;
2485 wtapng_nrb_mandatory_t *nrb_mand;
2486
2487 /*
2488 * Is this block long enough to be an NRB?
2489 * There must be at least an "end of records" record.
2490 */
2491 if (block_content_length < sizeof nrb) {
2492 /*
2493 * No.
2494 */
2495 *err = WTAP_ERR_BAD_FILE-13;
2496 *err_info = ws_strdup_printf("pcapng: block content length %u of an NRB is less than the minimum NRB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an NRB is less than the minimum NRB content size %zu"
, block_content_length, sizeof nrb)
2497 block_content_length, sizeof nrb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an NRB is less than the minimum NRB content size %zu"
, block_content_length, sizeof nrb)
;
2498 return false0;
2499 }
2500
2501 to_read = block_content_length;
2502
2503 ws_debug("total content %u bytes", block_content_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2503, __func__, "total content %u bytes", block_content_length
); } } while (0)
;
2504
2505 /* Ensure we have a name resolution block */
2506 if (wblock->block == NULL((void*)0)) {
2507 wblock->block = wtap_block_create(WTAP_BLOCK_NAME_RESOLUTION);
2508 }
2509
2510 /*
2511 * Set the mandatory values for the block.
2512 */
2513 nrb_mand = (wtapng_nrb_mandatory_t *)wtap_block_get_mandatory_data(wblock->block);
2514
2515 /*
2516 * Start out with a buffer big enough for an IPv6 address and one
2517 * 64-byte name; we'll make the buffer bigger if necessary.
2518 */
2519 ws_buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE(16 + 256));
2520 while (to_read != 0) {
2521 unsigned padding;
2522
2523 /*
2524 * There must be at least one record's worth of data
2525 * here.
2526 */
2527 if (to_read < sizeof nrb) {
2528 ws_buffer_free(&nrb_rec);
2529 *err = WTAP_ERR_BAD_FILE-13;
2530 *err_info = ws_strdup_printf("pcapng: %u bytes left in the block < NRB record header size %zu",wmem_strdup_printf(((void*)0), "pcapng: %u bytes left in the block < NRB record header size %zu"
, to_read, sizeof nrb)
2531 to_read, sizeof nrb)wmem_strdup_printf(((void*)0), "pcapng: %u bytes left in the block < NRB record header size %zu"
, to_read, sizeof nrb)
;
2532 return false0;
2533 }
2534 if (!wtap_read_bytes(fh, &nrb, sizeof nrb, err, err_info)) {
2535 ws_buffer_free(&nrb_rec);
2536 ws_debug("failed to read record header")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2536, __func__, "failed to read record header"); } } while (
0)
;
2537 return false0;
2538 }
2539 to_read -= (unsigned)sizeof nrb;
2540
2541 if (section_info->byte_swapped) {
2542 nrb.record_type = GUINT16_SWAP_LE_BE(nrb.record_type)(((guint16) ( (guint16) ((guint16) (nrb.record_type) >>
8) | (guint16) ((guint16) (nrb.record_type) << 8))))
;
2543 nrb.record_len = GUINT16_SWAP_LE_BE(nrb.record_len)(((guint16) ( (guint16) ((guint16) (nrb.record_len) >> 8
) | (guint16) ((guint16) (nrb.record_len) << 8))))
;
2544 }
2545
2546 padding = WS_PADDING_TO_4(nrb.record_len)((4U - ((nrb.record_len) % 4U)) % 4U); /* padding at end of record */
2547 if (to_read < nrb.record_len + padding) {
2548 ws_buffer_free(&nrb_rec);
2549 *err = WTAP_ERR_BAD_FILE-13;
2550 *err_info = ws_strdup_printf("pcapng: %u bytes left in the block < NRB record length + padding %u",wmem_strdup_printf(((void*)0), "pcapng: %u bytes left in the block < NRB record length + padding %u"
, to_read, nrb.record_len + padding)
2551 to_read, nrb.record_len + padding)wmem_strdup_printf(((void*)0), "pcapng: %u bytes left in the block < NRB record length + padding %u"
, to_read, nrb.record_len + padding)
;
2552 return false0;
2553 }
2554 switch (nrb.record_type) {
2555 case NRES_ENDOFRECORD0:
2556 /* There shouldn't be any more data - but there MAY be options */
2557 goto read_options;
2558 break;
2559 case NRES_IP4RECORD1:
2560 /*
2561 * The smallest possible record must have
2562 * a 4-byte IPv4 address, hence a minimum
2563 * of 4 bytes.
2564 *
2565 * (The pcapng spec really indicates
2566 * that it must be at least 5 bytes,
2567 * as there must be at least one name,
2568 * and it really must be at least 6
2569 * bytes, as the name mustn't be null,
2570 * but there's no need to fail if there
2571 * aren't any names at all, and we
2572 * should report a null name as such.)
2573 */
2574 if (nrb.record_len < 4) {
2575 ws_buffer_free(&nrb_rec);
2576 *err = WTAP_ERR_BAD_FILE-13;
2577 *err_info = ws_strdup_printf("pcapng: NRB IPv4 record length %u < minimum length 4",wmem_strdup_printf(((void*)0), "pcapng: NRB IPv4 record length %u < minimum length 4"
, nrb.record_len)
2578 nrb.record_len)wmem_strdup_printf(((void*)0), "pcapng: NRB IPv4 record length %u < minimum length 4"
, nrb.record_len)
;
2579 return false0;
2580 }
2581 ws_buffer_assure_space(&nrb_rec, nrb.record_len);
2582 if (!wtap_read_bytes(fh, ws_buffer_start_ptr(&nrb_rec),
2583 nrb.record_len, err, err_info)) {
2584 ws_buffer_free(&nrb_rec);
2585 ws_debug("failed to read IPv4 record data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2585, __func__, "failed to read IPv4 record data"); } } while
(0)
;
2586 return false0;
2587 }
2588 to_read -= nrb.record_len;
2589
2590 /*
2591 * Scan through all the names in
2592 * the record and add them.
2593 */
2594 memcpy(&v4_addr,
2595 ws_buffer_start_ptr(&nrb_rec), 4);
2596 /* IPv4 address is in big-endian order in the file always, which is how we store
2597 it internally as well, so don't byte-swap it */
2598 for (namep = (const char *)ws_buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
2599 record_len != 0;
2600 namep += namelen, record_len -= namelen) {
2601 /*
2602 * Scan forward for a null byte.
2603 *
2604 * This will never return a value > record_len.
2605 */
2606 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
2607 if (namelen == -1) {
2608 ws_buffer_free(&nrb_rec);
2609 return false0; /* fail */
2610 }
2611 hashipv4_t *tp = g_new0(hashipv4_t, 1)((hashipv4_t *) g_malloc0_n ((1), sizeof (hashipv4_t)));
2612 tp->addr = v4_addr;
2613 (void) g_strlcpy(tp->name, namep, MAXDNSNAMELEN256);
2614 nrb_mand->ipv4_addr_list = g_list_prepend(nrb_mand->ipv4_addr_list, tp);
2615 }
2616 break;
2617 case NRES_IP6RECORD2:
2618 /*
2619 * The smallest possible record must have
2620 * a 16-byte IPv6 address, hence a minimum
2621 * of 16 bytes.
2622 *
2623 * (The pcapng spec really indicates
2624 * that it must be at least 17 bytes,
2625 * as there must be at least one name,
2626 * and it really must be at least 18
2627 * bytes, as the name mustn't be null,
2628 * but there's no need to fail if there
2629 * aren't any names at all, and we
2630 * should report a null name as such.)
2631 */
2632 if (nrb.record_len < 16) {
2633 ws_buffer_free(&nrb_rec);
2634 *err = WTAP_ERR_BAD_FILE-13;
2635 *err_info = ws_strdup_printf("pcapng: NRB record length for IPv6 record %u < minimum length 16",wmem_strdup_printf(((void*)0), "pcapng: NRB record length for IPv6 record %u < minimum length 16"
, nrb.record_len)
2636 nrb.record_len)wmem_strdup_printf(((void*)0), "pcapng: NRB record length for IPv6 record %u < minimum length 16"
, nrb.record_len)
;
2637 return false0;
2638 }
2639 ws_buffer_assure_space(&nrb_rec, nrb.record_len);
2640 if (!wtap_read_bytes(fh, ws_buffer_start_ptr(&nrb_rec),
2641 nrb.record_len, err, err_info)) {
2642 ws_buffer_free(&nrb_rec);
2643 return false0;
2644 }
2645 to_read -= nrb.record_len;
2646
2647 for (namep = (const char *)ws_buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
2648 record_len != 0;
2649 namep += namelen, record_len -= namelen) {
2650 /*
2651 * Scan forward for a null byte.
2652 *
2653 * This will never return a value > record_len.
2654 */
2655 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
2656 if (namelen == -1) {
2657 ws_buffer_free(&nrb_rec);
2658 return false0; /* fail */
2659 }
2660 hashipv6_t *tp = g_new0(hashipv6_t, 1)((hashipv6_t *) g_malloc0_n ((1), sizeof (hashipv6_t)));
2661 memcpy(tp->addr, ws_buffer_start_ptr(&nrb_rec), sizeof tp->addr);
2662 (void) g_strlcpy(tp->name, namep, MAXDNSNAMELEN256);
2663 nrb_mand->ipv6_addr_list = g_list_prepend(nrb_mand->ipv6_addr_list, tp);
2664 }
2665 break;
2666 default:
2667 ws_debug("unknown record type 0x%x", nrb.record_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2667, __func__, "unknown record type 0x%x", nrb.record_type
); } } while (0)
;
2668 if (!wtap_read_bytes(fh, NULL((void*)0), nrb.record_len, err, err_info)) {
2669 ws_buffer_free(&nrb_rec);
2670 return false0;
2671 }
2672 to_read -= nrb.record_len;
2673 break;
2674 }
2675
2676 /* Skip padding */
2677 if (!wtap_read_bytes(fh, NULL((void*)0), padding, err, err_info)) {
2678 ws_buffer_free(&nrb_rec);
2679 return false0;
2680 }
2681 to_read -= padding;
2682 }
2683
2684read_options:
2685 /* Options */
2686 opt_cont_buf_len = to_read;
2687 if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
2688 pcapng_process_name_resolution_block_option,
2689 OPT_SECTION_BYTE_ORDER, err, err_info))
2690 return false0;
2691
2692 ws_buffer_free(&nrb_rec);
2693
2694 /*
2695 * We don't return these to the caller in pcapng_read().
2696 */
2697 wblock->internal = true1;
2698
2699 return true1;
2700}
2701
2702static bool_Bool
2703pcapng_process_interface_statistics_block_option(wtapng_block_t *wblock,
2704 section_info_t *section_info,
2705 uint16_t option_code,
2706 uint16_t option_length,
2707 const uint8_t *option_content,
2708 int *err, char **err_info)
2709{
2710 /*
2711 * Handle option content.
2712 *
2713 * ***DO NOT*** add any items to this table that are not
2714 * standardized option codes in either section 3.5 "Options"
2715 * of the current pcapng spec, at
2716 *
2717 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-options
2718 *
2719 * or in the list of options in section 4.1 "Section Header Block"
2720 * of the current pcapng spec, at
2721 *
2722 * https://pcapng.github.io/pcapng/draft-ietf-opsawg-pcapng.html#name-section-header-block
2723 *
2724 * All option codes in this switch statement here must be listed
2725 * in one of those places as standardized option types.
2726 */
2727 switch (option_code) {
2728 case(OPT_ISB_STARTTIME2): /* isb_starttime */
2729 pcapng_process_timestamp_option(wblock, section_info,
2730 OPT_SECTION_BYTE_ORDER,
2731 option_code, option_length,
2732 option_content);
2733 break;
2734 case(OPT_ISB_ENDTIME3): /* isb_endtime */
2735 pcapng_process_timestamp_option(wblock, section_info,
2736 OPT_SECTION_BYTE_ORDER,
2737 option_code, option_length,
2738 option_content);
2739 break;
2740 case(OPT_ISB_IFRECV4): /* isb_ifrecv */
2741 pcapng_process_uint64_option(wblock, section_info,
2742 OPT_SECTION_BYTE_ORDER,
2743 option_code, option_length,
2744 option_content);
2745 break;
2746 case(OPT_ISB_IFDROP5): /* isb_ifdrop */
2747 pcapng_process_uint64_option(wblock, section_info,
2748 OPT_SECTION_BYTE_ORDER,
2749 option_code, option_length,
2750 option_content);
2751 break;
2752 case(OPT_ISB_FILTERACCEPT6): /* isb_filteraccept 6 */
2753 pcapng_process_uint64_option(wblock, section_info,
2754 OPT_SECTION_BYTE_ORDER,
2755 option_code, option_length,
2756 option_content);
2757 break;
2758 case(OPT_ISB_OSDROP7): /* isb_osdrop 7 */
2759 pcapng_process_uint64_option(wblock, section_info,
2760 OPT_SECTION_BYTE_ORDER,
2761 option_code, option_length,
2762 option_content);
2763 break;
2764 case(OPT_ISB_USRDELIV8): /* isb_usrdeliv 8 */
2765 pcapng_process_uint64_option(wblock, section_info,
2766 OPT_SECTION_BYTE_ORDER,
2767 option_code, option_length,
2768 option_content);
2769 break;
2770 default:
2771 if (!pcapng_process_unhandled_option(wblock, section_info,
2772 option_code, option_length,
2773 option_content,
2774 err, err_info))
2775 return false0;
2776 break;
2777 }
2778 return true1;
2779}
2780
2781static bool_Bool
2782pcapng_read_interface_statistics_block(wtap *wth _U___attribute__((unused)), FILE_T fh,
2783 uint32_t block_type _U___attribute__((unused)),
2784 uint32_t block_content_length,
2785 section_info_t *section_info,
2786 wtapng_block_t *wblock,
2787 int *err, char **err_info)
2788{
2789 unsigned opt_cont_buf_len;
2790 pcapng_interface_statistics_block_t isb;
2791 wtapng_if_stats_mandatory_t* if_stats_mand;
2792
2793 /*
2794 * Is this block long enough to be an ISB?
2795 */
2796 if (block_content_length < sizeof isb) {
2797 /*
2798 * No.
2799 */
2800 *err = WTAP_ERR_BAD_FILE-13;
2801 *err_info = ws_strdup_printf("pcapng: block content length %u of an ISB is less than the minimum ISB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an ISB is less than the minimum ISB content size %zu"
, block_content_length, sizeof isb)
2802 block_content_length, sizeof isb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of an ISB is less than the minimum ISB content size %zu"
, block_content_length, sizeof isb)
;
2803 return false0;
2804 }
2805
2806 /* "Interface Statistics Block" read fixed part */
2807 if (!wtap_read_bytes(fh, &isb, sizeof isb, err, err_info)) {
2808 ws_debug("failed to read packet data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2808, __func__, "failed to read packet data"); } } while (0
)
;
2809 return false0;
2810 }
2811
2812 /*
2813 * Set wblock->block to a newly-allocated interface statistics block.
2814 */
2815 wblock->block = wtap_block_create(WTAP_BLOCK_IF_STATISTICS);
2816
2817 /*
2818 * Set the mandatory values for the block.
2819 */
2820 if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
2821 if (section_info->byte_swapped) {
2822 if_stats_mand->interface_id = GUINT32_SWAP_LE_BE(isb.interface_id)(((guint32) ( (((guint32) (isb.interface_id) & (guint32) 0x000000ffU
) << 24) | (((guint32) (isb.interface_id) & (guint32
) 0x0000ff00U) << 8) | (((guint32) (isb.interface_id) &
(guint32) 0x00ff0000U) >> 8) | (((guint32) (isb.interface_id
) & (guint32) 0xff000000U) >> 24))))
;
2823 if_stats_mand->ts_high = GUINT32_SWAP_LE_BE(isb.timestamp_high)(((guint32) ( (((guint32) (isb.timestamp_high) & (guint32
) 0x000000ffU) << 24) | (((guint32) (isb.timestamp_high
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (isb
.timestamp_high) & (guint32) 0x00ff0000U) >> 8) | (
((guint32) (isb.timestamp_high) & (guint32) 0xff000000U) >>
24))))
;
2824 if_stats_mand->ts_low = GUINT32_SWAP_LE_BE(isb.timestamp_low)(((guint32) ( (((guint32) (isb.timestamp_low) & (guint32)
0x000000ffU) << 24) | (((guint32) (isb.timestamp_low) &
(guint32) 0x0000ff00U) << 8) | (((guint32) (isb.timestamp_low
) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (isb
.timestamp_low) & (guint32) 0xff000000U) >> 24))))
;
2825 } else {
2826 if_stats_mand->interface_id = isb.interface_id;
2827 if_stats_mand->ts_high = isb.timestamp_high;
2828 if_stats_mand->ts_low = isb.timestamp_low;
2829 }
2830 ws_debug("interface_id %u", if_stats_mand->interface_id)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2830, __func__, "interface_id %u", if_stats_mand->interface_id
); } } while (0)
;
2831
2832 /* Options */
2833 opt_cont_buf_len = block_content_length - sizeof isb;
2834 if (!pcapng_process_options(fh, wblock, section_info, opt_cont_buf_len,
2835 pcapng_process_interface_statistics_block_option,
2836 OPT_SECTION_BYTE_ORDER, err, err_info))
2837 return false0;
2838
2839 /*
2840 * We don't return these to the caller in pcapng_read().
2841 */
2842 wblock->internal = true1;
2843
2844 return true1;
2845}
2846
2847void
2848register_pcapng_custom_block_enterprise_handler(unsigned enterprise_number, pcapng_custom_block_enterprise_handler_t* handler)
2849{
2850 g_hash_table_insert(custom_enterprise_handlers, GUINT_TO_POINTER(enterprise_number)((gpointer) (gulong) (enterprise_number)), handler);
2851}
2852
2853static bool_Bool
2854pcapng_read_custom_block(wtap *wth _U___attribute__((unused)), FILE_T fh, uint32_t block_type,
2855 uint32_t block_content_length,
2856 section_info_t *section_info, wtapng_block_t *wblock,
2857 int *err, char **err_info)
2858{
2859 pcapng_custom_block_t cb;
2860 uint32_t pen;
2861 pcapng_custom_block_enterprise_handler_t* pen_handler;
2862
2863 /* Is this block long enough to be an CB? */
2864 if (block_content_length < sizeof cb) {
2865 /*
2866 * No.
2867 */
2868 *err = WTAP_ERR_BAD_FILE-13;
2869 *err_info = ws_strdup_printf("pcapng: block content length %u of a CB is less than the minimum CB content size %zu",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a CB is less than the minimum CB content size %zu"
, block_content_length, sizeof cb)
2870 block_content_length, sizeof cb)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a CB is less than the minimum CB content size %zu"
, block_content_length, sizeof cb)
;
2871 return false0;
2872 }
2873
2874 wblock->block = wtap_block_create(WTAP_BLOCK_CUSTOM);
2875
2876 /* Custom block read fixed part */
2877 if (!wtap_read_bytes(fh, &cb, sizeof cb, err, err_info)) {
2878 ws_debug("failed to read pen")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2878, __func__, "failed to read pen"); } } while (0)
;
2879 return false0;
2880 }
2881 if (section_info->byte_swapped) {
2882 pen = GUINT32_SWAP_LE_BE(cb.pen)(((guint32) ( (((guint32) (cb.pen) & (guint32) 0x000000ffU
) << 24) | (((guint32) (cb.pen) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (cb.pen) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (cb.pen) & (guint32) 0xff000000U
) >> 24))))
;
2883 } else {
2884 pen = cb.pen;
2885 }
2886 uint32_t block_payload_length = block_content_length - sizeof cb;
2887 ws_debug("pen %u, custom data and option length %u", pen, block_payload_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2887, __func__, "pen %u, custom data and option length %u",
pen, block_payload_length); } } while (0)
;
2888
2889 wtap_setup_custom_block_rec(wblock->rec, pen, block_payload_length,
2890 (block_type == BLOCK_TYPE_CB_COPY0x00000BAD));
2891
2892 pen_handler = (pcapng_custom_block_enterprise_handler_t*)g_hash_table_lookup(custom_enterprise_handlers, GUINT_TO_POINTER(pen)((gpointer) (gulong) (pen)));
2893
2894 if (pen_handler != NULL((void*)0))
2895 {
2896 if (!pen_handler->parser(fh, section_info, wblock, err, err_info))
2897 return false0;
2898 }
2899 else
2900 {
2901 ws_debug("unknown pen %u", pen)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2901, __func__, "unknown pen %u", pen); } } while (0)
;
2902 if (!wtap_read_bytes_buffer(fh, &wblock->rec->data,
2903 block_payload_length, err, err_info))
2904 return false0;
2905 }
2906
2907 wblock->rec->block = wblock->block;
2908 wblock->block = NULL((void*)0);
2909 /*
2910 * We return these to the caller in pcapng_read().
2911 */
2912 wblock->internal = false0;
2913
2914 return true1;
2915}
2916
2917static bool_Bool
2918pcapng_read_systemd_journal_export_block(wtap *wth, FILE_T fh,
2919 uint32_t block_type _U___attribute__((unused)),
2920 uint32_t block_content_length,
2921 section_info_t *section_info _U___attribute__((unused)),
2922 wtapng_block_t *wblock,
2923 int *err, char **err_info)
2924{
2925 uint32_t entry_length;
2926 uint64_t rt_ts;
2927 bool_Bool have_ts = false0;
2928
2929 if (block_content_length < MIN_SYSTEMD_JOURNAL_EXPORT_ENTRY_SIZE23) {
2930 *err = WTAP_ERR_BAD_FILE-13;
2931 *err_info = ws_strdup_printf("pcapng: block content length %u of a systemd journal export is less than the minimum systemd journal export content size %u",wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a systemd journal export is less than the minimum systemd journal export content size %u"
, block_content_length, 23)
2932 block_content_length,wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a systemd journal export is less than the minimum systemd journal export content size %u"
, block_content_length, 23)
2933 MIN_SYSTEMD_JOURNAL_EXPORT_ENTRY_SIZE)wmem_strdup_printf(((void*)0), "pcapng: block content length %u of a systemd journal export is less than the minimum systemd journal export content size %u"
, block_content_length, 23)
;
2934 return false0;
2935 }
2936
2937 entry_length = block_content_length;
2938
2939 /* Includes padding bytes. */
2940 if (!wtap_read_bytes_buffer(fh, &wblock->rec->data,
2941 entry_length, err, err_info)) {
2942 return false0;
2943 }
2944
2945 /*
2946 * We don't have memmem available everywhere, so we get to add space for
2947 * a trailing \0 for strstr below.
2948 */
2949 ws_buffer_assure_space(&wblock->rec->data, entry_length+1);
2950
2951 char *buf_ptr = (char *) ws_buffer_start_ptr(&wblock->rec->data);
2952 while (entry_length > 0 && buf_ptr[entry_length-1] == '\0') {
2953 entry_length--;
2954 }
2955
2956 if (entry_length < MIN_SYSTEMD_JOURNAL_EXPORT_ENTRY_SIZE23) {
2957 *err = WTAP_ERR_BAD_FILE-13;
2958 *err_info = ws_strdup_printf("pcapng: entry length %u is too small (< %u)",wmem_strdup_printf(((void*)0), "pcapng: entry length %u is too small (< %u)"
, entry_length, 23)
2959 entry_length, MIN_SYSTEMD_JOURNAL_EXPORT_ENTRY_SIZE)wmem_strdup_printf(((void*)0), "pcapng: entry length %u is too small (< %u)"
, entry_length, 23)
;
2960 return false0;
2961 }
2962
2963 ws_debug("entry_length %u", entry_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2963, __func__, "entry_length %u", entry_length); } } while
(0)
;
2964
2965 size_t rt_ts_len = strlen(SDJ__REALTIME_TIMESTAMP"__REALTIME_TIMESTAMP=");
2966
2967 buf_ptr[entry_length] = '\0';
2968 char *ts_pos = strstr(buf_ptr, SDJ__REALTIME_TIMESTAMP"__REALTIME_TIMESTAMP=");
2969
2970 if (!ts_pos) {
2971 ws_debug("no timestamp")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2971, __func__, "no timestamp"); } } while (0)
;
2972 } else if (ts_pos+rt_ts_len >= (char *) buf_ptr+entry_length) {
2973 ws_debug("timestamp past end of buffer")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2973, __func__, "timestamp past end of buffer"); } } while (
0)
;
2974 } else {
2975 const char *ts_end;
2976 have_ts = ws_strtou64(ts_pos+rt_ts_len, &ts_end, &rt_ts);
2977
2978 if (!have_ts) {
2979 ws_debug("invalid timestamp")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 2979, __func__, "invalid timestamp"); } } while (0)
;
2980 }
2981 }
2982
2983 wtap_setup_systemd_journal_export_rec(wblock->rec);
2984 wblock->rec->rec_header.systemd_journal_export_header.record_len = entry_length;
2985 wblock->rec->presence_flags = WTAP_HAS_CAP_LEN0x00000002;
2986 if (have_ts) {
2987 wblock->rec->presence_flags |= WTAP_HAS_TS0x00000001;
2988 wblock->rec->tsprec = WTAP_TSPREC_USEC6;
2989 wblock->rec->ts.secs = (time_t) (rt_ts / 1000000);
2990 wblock->rec->ts.nsecs = (rt_ts % 1000000) * 1000;
2991 }
2992
2993 /*
2994 * We return these to the caller in pcapng_read().
2995 */
2996 wblock->internal = false0;
2997
2998 if (wth->file_encap == WTAP_ENCAP_NONE-2) {
2999 /*
3000 * Nothing (most notably an IDB) has set a file encap at this point.
3001 * Do so here.
3002 * XXX Should we set WTAP_ENCAP_SYSTEMD_JOURNAL if appropriate?
3003 */
3004 wth->file_encap = WTAP_ENCAP_PER_PACKET-1;
3005 }
3006
3007 return true1;
3008}
3009
3010static bool_Bool
3011pcapng_read_unknown_block(FILE_T fh, guint32 block_content_length,
3012 section_info_t *section_info _U___attribute__((unused)), wtapng_block_t *wblock,
3013 int *err, char **err_info)
3014{
3015 /* Skip the block content. */
3016 if (!wtap_read_bytes(fh, NULL((void*)0), block_content_length, err, err_info)) {
3017 return false0;
3018 }
3019
3020 /*
3021 * We're skipping this, so we won't return these to the caller
3022 * in pcapng_read().
3023 */
3024 wblock->internal = true1;
3025
3026 return true1;
3027}
3028
3029static bool_Bool
3030pcapng_read_and_check_block_trailer(FILE_T fh, pcapng_block_header_t *bh,
3031 section_info_t *section_info,
3032 int *err, char **err_info)
3033{
3034 uint32_t block_total_length;
3035
3036 /* sanity check: first and second block lengths must match */
3037 if (!wtap_read_bytes(fh, &block_total_length, sizeof block_total_length,
3038 err, err_info)) {
3039 ws_debug("couldn't read second block length")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3039, __func__, "couldn't read second block length"); } } while
(0)
;
3040 return false0;
3041 }
3042
3043 if (section_info->byte_swapped)
3044 block_total_length = GUINT32_SWAP_LE_BE(block_total_length)(((guint32) ( (((guint32) (block_total_length) & (guint32
) 0x000000ffU) << 24) | (((guint32) (block_total_length
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (block_total_length
) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (block_total_length
) & (guint32) 0xff000000U) >> 24))))
;
3045
3046 /*
3047 * According to the pcapng spec, this should equal the block total
3048 * length value at the beginning of the block, which MUST (in the
3049 * IANA sense) be a multiple of 4.
3050 *
3051 * We round the value at the beginning of the block to a multiple
3052 * of 4, so do so with this value as well. This *does* mean that
3053 * the two values, if they're not both multiples of 4, can differ
3054 * and this code won't detect that, but we're already not detecting
3055 * non-multiple-of-4 total lengths.
3056 */
3057 block_total_length = WS_ROUNDUP_4(block_total_length)(((block_total_length) + ((unsigned)(4U-1U))) & (~((unsigned
)(4U-1U))))
;
3058
3059 if (block_total_length != bh->block_total_length) {
3060 *err = WTAP_ERR_BAD_FILE-13;
3061 *err_info = ws_strdup_printf("pcapng: total block lengths (first %u and second %u) don't match",wmem_strdup_printf(((void*)0), "pcapng: total block lengths (first %u and second %u) don't match"
, bh->block_total_length, block_total_length)
3062 bh->block_total_length, block_total_length)wmem_strdup_printf(((void*)0), "pcapng: total block lengths (first %u and second %u) don't match"
, bh->block_total_length, block_total_length)
;
3063 return false0;
3064 }
3065 return true1;
3066}
3067
3068static bool_Bool
3069pcapng_read_block(wtap *wth, FILE_T fh,
3070 section_info_t *section_info,
3071 section_info_t *new_section_info,
3072 wtapng_block_t *wblock,
3073 int *err, char **err_info)
3074{
3075 pcapng_block_type_information_t *handler;
3076 block_return_val ret;
3077 pcapng_block_header_t bh;
3078 uint32_t block_content_length;
3079
3080 wblock->block = NULL((void*)0);
3081
3082 /* Try to read the (next) block header */
3083 if (!wtap_read_bytes_or_eof(fh, &bh, sizeof bh, err, err_info)) {
3084 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3084, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
3085 return false0;
3086 }
3087
3088 /*
3089 * SHBs have to be treated differently from other blocks, because
3090 * the byte order of the fields in the block can only be determined
3091 * by looking at the byte-order magic number inside the block, not
3092 * by using the byte order of the section to which it belongs, as
3093 * it is the block that *defines* the byte order of the section to
3094 * which it belongs.
3095 */
3096 if (bh.block_type == BLOCK_TYPE_SHB0x0A0D0D0A) {
3097 /*
3098 * BLOCK_TYPE_SHB has the same value regardless of byte order,
3099 * so we don't need to byte-swap it.
3100 *
3101 * We *might* need to byte-swap the total length, but we
3102 * can't determine whether we do until we look inside the
3103 * block and find the byte-order magic number, so we rely
3104 * on pcapng_read_section_header_block() to do that and
3105 * to swap the total length (as it needs to get the total
3106 * length in the right byte order in order to read the
3107 * entire block).
3108 */
3109 wblock->type = bh.block_type;
3110
3111 ws_debug("block_type BLOCK_TYPE_SHB (0x%08x)", bh.block_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3111, __func__, "block_type BLOCK_TYPE_SHB (0x%08x)", bh.block_type
); } } while (0)
;
3112
3113 /*
3114 * Fill in the section_info_t passed to us for use when
3115 * there's a new SHB; don't overwrite the existing SHB,
3116 * if there is one.
3117 */
3118 ret = pcapng_read_section_header_block(fh, &bh, new_section_info,
3119 wblock, err, err_info);
3120 if (ret != PCAPNG_BLOCK_OK) {
3121 return false0;
3122 }
3123
3124 /*
3125 * This is the current section; use its byte order, not that
3126 * of the section pointed to by section_info (which could be
3127 * null).
3128 */
3129 section_info = new_section_info;
3130
3131 /*
3132 * Get information for this block type, for use when setting the
3133 * internal flag.
3134 */
3135 handler = g_hash_table_lookup(block_handlers, GUINT_TO_POINTER(bh.block_type)((gpointer) (gulong) (bh.block_type)));
Value stored to 'handler' is never read
3136 } else {
3137 /*
3138 * Not an SHB.
3139 */
3140 if (section_info->byte_swapped) {
3141 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type)(((guint32) ( (((guint32) (bh.block_type) & (guint32) 0x000000ffU
) << 24) | (((guint32) (bh.block_type) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (bh.block_type) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (bh.block_type) & (guint32) 0xff000000U
) >> 24))))
;
3142 bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length)(((guint32) ( (((guint32) (bh.block_total_length) & (guint32
) 0x000000ffU) << 24) | (((guint32) (bh.block_total_length
) & (guint32) 0x0000ff00U) << 8) | (((guint32) (bh.
block_total_length) & (guint32) 0x00ff0000U) >> 8) |
(((guint32) (bh.block_total_length) & (guint32) 0xff000000U
) >> 24))))
;
3143 }
3144
3145 if (bh.block_total_length < MIN_BLOCK_SIZE((uint32_t)(sizeof(pcapng_block_header_t) + sizeof(uint32_t))
)
) {
3146 *err = WTAP_ERR_BAD_FILE-13;
3147 *err_info = ws_strdup_printf("pcapng: total block length %u of block is less than the minimum block size %u",wmem_strdup_printf(((void*)0), "pcapng: total block length %u of block is less than the minimum block size %u"
, bh.block_total_length, ((uint32_t)(sizeof(pcapng_block_header_t
) + sizeof(uint32_t))))
3148 bh.block_total_length, MIN_BLOCK_SIZE)wmem_strdup_printf(((void*)0), "pcapng: total block length %u of block is less than the minimum block size %u"
, bh.block_total_length, ((uint32_t)(sizeof(pcapng_block_header_t
) + sizeof(uint32_t))))
;
3149 return false0;
3150 }
3151
3152 /*
3153 * Add padding bytes to the block total length.
3154 * (The "block total length" fields of some example files
3155 * don't contain the packet data padding bytes!)
3156 *
3157 * For all block types currently defined in the pcapng
3158 * specification, the portion of the block that precedes
3159 * the options is, if necessary, padded to be a multiple
3160 * of 4 octets, the header of an option is 4 octets long,
3161 * and the value of an option is also padded to be a
3162 * multiple of 4 octets, so the total length of a block
3163 * is always a multiple of 4 octets.
3164 *
3165 * If you have defined a block where that is not true, you
3166 * have violated the pcapng specification - where it says
3167 * that "[The value of the Block Total Length] MUST be a
3168 * multiple of 4.", with MUST as described in BCP 14 (RFC 2119/
3169 * RFC 8174).
3170 *
3171 * Therefore, if adjusting the block total length causes the
3172 * code to read your block type not to work, that's your
3173 * problem. It's bad enough that some blocks were written
3174 * out with the block total length not including the padding.
3175 * (Please note that libpcap is less forgiving that we are;
3176 * it reports an error if the block total length isn't a
3177 * multiple of 4.)
3178 */
3179 bh.block_total_length = WS_ROUNDUP_4(bh.block_total_length)(((bh.block_total_length) + ((unsigned)(4U-1U))) & (~((unsigned
)(4U-1U))))
;
3180
3181 wblock->type = bh.block_type;
3182
3183 ws_noisy("block_type 0x%08x", bh.block_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/pcapng.c"
, 3183, __func__, "block_type 0x%08x", bh.block_type); } } while
(0)
;
3184
3185 /* Don't try to allocate memory for a huge number of options, as
3186 that might fail and, even if it succeeds, it might not leave
3187 any address space or memory+backing store for anything else.
3188
3189 We do that by imposing a maximum block size of MAX_BLOCK_SIZE. */
3190 if (bh.block_total_length > MAX_BLOCK_SIZE(((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t) + sizeof
(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t))) + (128U
*1024U*1024U) + 131072)
) {
3191 *err = WTAP_ERR_BAD_FILE-13;
3192 *err_info = ws_strdup_printf("pcapng: total block length %u is too large (> %u)",wmem_strdup_printf(((void*)0), "pcapng: total block length %u is too large (> %u)"
, bh.block_total_length, (((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t
) + sizeof(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t
))) + (128U*1024U*1024U) + 131072))
3193 bh.block_total_length, MAX_BLOCK_SIZE)wmem_strdup_printf(((void*)0), "pcapng: total block length %u is too large (> %u)"
, bh.block_total_length, (((uint32_t)(((uint32_t)(sizeof(pcapng_block_header_t
) + sizeof(uint32_t))) + sizeof(pcapng_enhanced_packet_block_t
))) + (128U*1024U*1024U) + 131072))
;
3194 return false0;
3195 }
3196
3197 /*
3198 * Length of the contents of the block.
3199 */
3200 block_content_length = bh.block_total_length - MIN_BLOCK_SIZE((uint32_t)(sizeof(pcapng_block_header_t) + sizeof(uint32_t))
)
;
3201
3202 /*
3203 * Do we have a handler for this block type?
3204 */
3205 handler = g_hash_table_lookup(block_handlers, GUINT_TO_POINTER(bh.block_type)((gpointer) (gulong) (bh.block_type)));
3206 if (handler != NULL((void*)0)) {
3207 /* Yes - call it to read this block type. */
3208 if (!handler->reader(wth, fh, bh.block_type,
3209 block_content_length, section_info,
3210 wblock, err, err_info))
3211 return false0;
3212 } else {
3213 ws_debug("Unknown block_type: 0x%08x (block ignored), block total length %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3214, __func__, "Unknown block_type: 0x%08x (block ignored), block total length %u"
, bh.block_type, bh.block_total_length); } } while (0)
3214 bh.block_type, bh.block_total_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3214, __func__, "Unknown block_type: 0x%08x (block ignored), block total length %u"
, bh.block_type, bh.block_total_length); } } while (0)
;
3215 if (!pcapng_read_unknown_block(fh, block_content_length,
3216 section_info, wblock,
3217 err, err_info))
3218 return false0;
3219 }
3220 }
3221
3222 /*
3223 * Read and check the block trailer.
3224 */
3225 if (!pcapng_read_and_check_block_trailer(fh, &bh, section_info, err, err_info)) {
3226 /* Not readable or not valid. */
3227 return false0;
3228 }
3229
3230 return true1;
3231}
3232
3233static void
3234pcapng_process_shb(wtap *wth, pcapng_t *pcapng, section_info_t new_section, wtapng_block_t *wblock, const int64_t *data_offset)
3235{
3236 /*
3237 * Add this SHB to the table of SHBs.
3238 */
3239 g_array_append_val(wth->shb_hdrs, wblock->block)g_array_append_vals (wth->shb_hdrs, &(wblock->block
), 1)
;
3240 g_array_append_val(wth->shb_iface_to_global, wth->interface_data->len)g_array_append_vals (wth->shb_iface_to_global, &(wth->
interface_data->len), 1)
;
3241
3242 /*
3243 * Update the current section number, and add
3244 * the updated section_info_t to the array of
3245 * section_info_t's for this file.
3246 */
3247 pcapng->current_section_number++;
3248 new_section.interfaces = g_array_new(false0, false0, sizeof(interface_info_t));
3249 new_section.shb_off = *data_offset;
3250 g_array_append_val(pcapng->sections, new_section)g_array_append_vals (pcapng->sections, &(new_section),
1)
;
3251}
3252
3253/* Process an IDB that we've just read. The contents of wblock are copied as needed. */
3254static bool_Bool
3255pcapng_process_idb(wtap *wth, section_info_t *section_info,
3256 wtapng_block_t *wblock)
3257{
3258 wtap_block_t int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
3259 interface_info_t iface_info;
3260 wtapng_if_descr_mandatory_t *if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data),
3261 *wblock_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
3262 uint8_t if_fcslen;
3263
3264 wtap_block_copy(int_data, wblock->block);
3265
3266 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
3267 /* Interface statistics */
3268 if_descr_mand->num_stat_entries = 0;
3269 if_descr_mand->interface_statistics = NULL((void*)0);
3270
3271 wtap_add_idb(wth, int_data);
3272
3273 iface_info.wtap_encap = wblock_if_descr_mand->wtap_encap;
3274 iface_info.snap_len = wblock_if_descr_mand->snap_len;
3275 iface_info.time_units_per_second = wblock_if_descr_mand->time_units_per_second;
3276 iface_info.tsprecision = wblock_if_descr_mand->tsprecision;
3277
3278 /*
3279 * Did we get an FCS length option?
3280 */
3281 if (wtap_block_get_uint8_option_value(wblock->block, OPT_IDB_FCSLEN13,
3282 &if_fcslen) == WTAP_OPTTYPE_SUCCESS) {
3283 /*
3284 * Yes.
3285 */
3286 iface_info.fcslen = if_fcslen;
3287 } else {
3288 /*
3289 * No. Mark the FCS length as unknown.
3290 */
3291 iface_info.fcslen = -1;
3292 }
3293
3294 /*
3295 * Did we get a time stamp offset option?
3296 */
3297 if (wtap_block_get_int64_option_value(wblock->block, OPT_IDB_TSOFFSET14,
3298 &iface_info.tsoffset) == WTAP_OPTTYPE_SUCCESS) {
3299 /*
3300 * Yes.
3301 *
3302 * Remove the option, as the time stamps we provide will be
3303 * absolute time stamps, with the offset added in, so it will
3304 * appear as if there were no such option.
3305 */
3306 wtap_block_remove_option(wblock->block, OPT_IDB_TSOFFSET14);
3307 } else {
3308 /*
3309 * No. Default to 0, meahing that time stamps in the file are
3310 * absolute time stamps.
3311 */
3312 iface_info.tsoffset = 0;
3313 }
3314
3315 g_array_append_val(section_info->interfaces, iface_info)g_array_append_vals (section_info->interfaces, &(iface_info
), 1)
;
3316
3317 wtap_block_unref(wblock->block);
3318
3319 return true1;
3320}
3321
3322/* Process an NRB that we have just read. */
3323static bool_Bool
3324pcapng_process_nrb(wtap *wth, section_info_t *section_info _U___attribute__((unused)),
3325 wtapng_block_t *wblock)
3326{
3327 wtapng_process_nrb(wth, wblock->block);
3328
3329 if (wth->nrbs == NULL((void*)0)) {
3330 wth->nrbs = g_array_new(false0, false0, sizeof(wtap_block_t));
3331 }
3332 /* Store NRB such that it can be saved by the dumper. */
3333 g_array_append_val(wth->nrbs, wblock->block)g_array_append_vals (wth->nrbs, &(wblock->block), 1
)
;
3334 /* Do not free wblock->block, it is consumed above */
3335
3336 return true1;
3337}
3338
3339/* Process a DSB that we have just read. */
3340static bool_Bool
3341pcapng_process_dsb(wtap *wth, section_info_t *section_info _U___attribute__((unused)),
3342 wtapng_block_t *wblock)
3343{
3344 wtapng_process_dsb(wth, wblock->block);
3345
3346 /* Store DSB such that it can be saved by the dumper. */
3347 g_array_append_val(wth->dsbs, wblock->block)g_array_append_vals (wth->dsbs, &(wblock->block), 1
)
;
3348
3349 /* Do not free wblock->block, it is consumed above */
3350
3351 return true1;
3352}
3353
3354/* Process a ISB that we have just read. */
3355static bool_Bool
3356pcapng_process_isb(wtap *wth, section_info_t *section_info _U___attribute__((unused)),
3357 wtapng_block_t *wblock)
3358{
3359 wtapng_if_stats_mandatory_t *if_stats_mand_block, *if_stats_mand;
3360 wtap_block_t if_stats;
3361 wtap_block_t wtapng_if_descr;
3362 wtapng_if_descr_mandatory_t *wtapng_if_descr_mand;
3363
3364 /*
3365 * Another interface statistics report
3366 *
3367 * XXX - given that they're reports, we should be
3368 * supplying them in read calls, and displaying them
3369 * in the "packet" list, so you can see what the
3370 * statistics were *at the time when the report was
3371 * made*.
3372 *
3373 * The statistics from the *last* ISB could be displayed
3374 * in the summary, but if there are packets after the
3375 * last ISB, that could be misleading.
3376 *
3377 * If we only display them if that ISB has an isb_endtime
3378 * option, which *should* only appear when capturing ended
3379 * on that interface (so there should be no more packet
3380 * blocks or ISBs for that interface after that point,
3381 * that would be the best way of showing "summary"
3382 * statistics.
3383 */
3384 ws_debug("block type BLOCK_TYPE_ISB")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3384, __func__, "block type BLOCK_TYPE_ISB"); } } while (0)
;
3385 if_stats_mand_block = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
3386 if (wth->interface_data->len <= if_stats_mand_block->interface_id) {
3387 ws_debug("BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3388, __func__, "BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces"
, if_stats_mand_block->interface_id); } } while (0)
3388 if_stats_mand_block->interface_id)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3388, __func__, "BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces"
, if_stats_mand_block->interface_id); } } while (0)
;
3389 } else {
3390 /* Get the interface description */
3391 wtapng_if_descr = g_array_index(wth->interface_data, wtap_block_t, if_stats_mand_block->interface_id)(((wtap_block_t*) (void *) (wth->interface_data)->data)
[(if_stats_mand_block->interface_id)])
;
3392 wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wtapng_if_descr);
3393 if (wtapng_if_descr_mand->num_stat_entries == 0) {
3394 /* First ISB found, no previous entry */
3395 ws_debug("block type BLOCK_TYPE_ISB. First ISB found, no previous entry")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3395, __func__, "block type BLOCK_TYPE_ISB. First ISB found, no previous entry"
); } } while (0)
;
3396 wtapng_if_descr_mand->interface_statistics = g_array_new(false0, false0, sizeof(wtap_block_t));
3397 }
3398
3399 if_stats = wtap_block_create(WTAP_BLOCK_IF_STATISTICS);
3400 if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats);
3401 if_stats_mand->interface_id = if_stats_mand_block->interface_id;
3402 if_stats_mand->ts_high = if_stats_mand_block->ts_high;
3403 if_stats_mand->ts_low = if_stats_mand_block->ts_low;
3404
3405 wtap_block_copy(if_stats, wblock->block);
3406 g_array_append_val(wtapng_if_descr_mand->interface_statistics, if_stats)g_array_append_vals (wtapng_if_descr_mand->interface_statistics
, &(if_stats), 1)
;
3407 wtapng_if_descr_mand->num_stat_entries++;
3408 }
3409 wtap_block_unref(wblock->block);
3410 return true1;
3411}
3412
3413static void
3414pcapng_process_internal_block(wtap *wth, pcapng_t *pcapng, section_info_t *section, section_info_t new_section, wtapng_block_t *wblock, const int64_t *data_offset)
3415{
3416 if (wblock->type == BLOCK_TYPE_SHB0x0A0D0D0A) {
3417 pcapng_process_shb(wth, pcapng, new_section, wblock, data_offset);
3418 } else {
3419 pcapng_block_type_information_t* handler = g_hash_table_lookup(block_handlers, GUINT_TO_POINTER(wblock->type)((gpointer) (gulong) (wblock->type)));
3420
3421 if (handler != NULL((void*)0)) {
3422 /* XXX - Is it okay to not have a processor? */
3423 if (handler->processor != NULL((void*)0)) {
3424 handler->processor(wth, section, wblock);
3425 }
3426 } else {
3427 /* XXX - improve handling of "unknown" blocks */
3428 ws_debug("Unknown block type 0x%08x", wblock->type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3428, __func__, "Unknown block type 0x%08x", wblock->type
); } } while (0)
;
3429 }
3430 }
3431}
3432
3433/* classic wtap: open capture file */
3434wtap_open_return_val
3435pcapng_open(wtap *wth, int *err, char **err_info)
3436{
3437 wtapng_block_t wblock;
3438 pcapng_t *pcapng;
3439 pcapng_block_header_t bh;
3440 int64_t saved_offset;
3441 section_info_t first_section, new_section, *current_section;
3442
3443 ws_debug("opening file")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3443, __func__, "opening file"); } } while (0)
;
3444 /*
3445 * Read first block.
3446 *
3447 * First, try to read the block header.
3448 */
3449 if (!wtap_read_bytes_or_eof(wth->fh, &bh, sizeof bh, err, err_info)) {
3450 ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3450, __func__, "wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
3451 if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) {
3452 /*
3453 * Short read or EOF.
3454 *
3455 * We're reading this as part of an open, so
3456 * the file is too short to be a pcapng file.
3457 */
3458 *err = 0;
3459 g_free(*err_info);
3460 *err_info = NULL((void*)0);
3461 return WTAP_OPEN_NOT_MINE;
3462 }
3463 return WTAP_OPEN_ERROR;
3464 }
3465
3466 /*
3467 * If this is a pcapng file, the first block must be a
3468 * Section Header Block.
3469 */
3470 if (bh.block_type != BLOCK_TYPE_SHB0x0A0D0D0A) {
3471 /*
3472 * Not an SHB, so this isn't a pcapng file.
3473 *
3474 * XXX - check for damage from transferring a file
3475 * between Windows and UN*X as text rather than
3476 * binary data?
3477 */
3478 ws_debug("first block type 0x%08x not SHB", bh.block_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3478, __func__, "first block type 0x%08x not SHB", bh.block_type
); } } while (0)
;
3479 return WTAP_OPEN_NOT_MINE;
3480 }
3481
3482 ws_debug("got an SHB")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3482, __func__, "got an SHB"); } } while (0)
;
3483
3484 /*
3485 * Now try to read the block body, filling in the section_info_t
3486 * for the first section.
3487 */
3488 wblock.type = bh.block_type;
3489 wblock.block = NULL((void*)0);
3490 /* we don't expect any packet blocks yet */
3491 wblock.rec = NULL((void*)0);
3492
3493 switch (pcapng_read_section_header_block(wth->fh, &bh, &first_section,
3494 &wblock, err, err_info)) {
3495 case PCAPNG_BLOCK_OK:
3496 /* No problem */
3497 break;
3498
3499 case PCAPNG_BLOCK_NOT_SHB:
3500 /* This doesn't look like an SHB, so this isn't a pcapng file. */
3501 wtap_block_unref(wblock.block);
3502 *err = 0;
3503 g_free(*err_info);
3504 *err_info = NULL((void*)0);
3505 return WTAP_OPEN_NOT_MINE;
3506
3507 case PCAPNG_BLOCK_ERROR:
3508 wtap_block_unref(wblock.block);
3509 if (*err == WTAP_ERR_SHORT_READ-12) {
3510 /*
3511 * Short read.
3512 *
3513 * We're reading this as part of an open, so
3514 * the file is too short to be a pcapng file.
3515 */
3516 *err = 0;
3517 g_free(*err_info);
3518 *err_info = NULL((void*)0);
3519 return WTAP_OPEN_NOT_MINE;
3520 }
3521 /* An I/O error. */
3522 return WTAP_OPEN_ERROR;
3523 }
3524
3525 /*
3526 * Read and check the block trailer.
3527 */
3528 if (!pcapng_read_and_check_block_trailer(wth->fh, &bh, &first_section, err, err_info)) {
3529 /* Not readable or not valid. */
3530 wtap_block_unref(wblock.block);
3531 return WTAP_OPEN_ERROR;
3532 }
3533
3534 /*
3535 * At this point, we've decided this is a pcapng file, not
3536 * some other type of file, so we can't return WTAP_OPEN_NOT_MINE
3537 * past this point.
3538 *
3539 * Copy the SHB that we just read to the first entry in the table of
3540 * SHBs for this file.
3541 */
3542 wtap_block_copy(g_array_index(wth->shb_hdrs, wtap_block_t, 0)(((wtap_block_t*) (void *) (wth->shb_hdrs)->data) [(0)]
)
, wblock.block);
3543 wtap_block_unref(wblock.block);
3544 wblock.block = NULL((void*)0);
3545
3546 wth->file_encap = WTAP_ENCAP_NONE-2;
3547 wth->snapshot_length = 0;
3548 wth->file_tsprec = WTAP_TSPREC_UNKNOWN-2;
3549 pcapng = g_new(pcapng_t, 1)((pcapng_t *) g_malloc_n ((1), sizeof (pcapng_t)));
3550 wth->priv = (void *)pcapng;
3551 /*
3552 * We're currently processing the first section; as this is written
3553 * in C, that's section 0. :-)
3554 */
3555 pcapng->current_section_number = 0;
3556
3557 /*
3558 * Create the array of interfaces for the first section.
3559 */
3560 first_section.interfaces = g_array_new(false0, false0, sizeof(interface_info_t));
3561
3562 /*
3563 * The first section is at the very beginning of the file.
3564 */
3565 first_section.shb_off = 0;
3566
3567 /*
3568 * Allocate the sections table with space reserved for the first
3569 * section, and add that section.
3570 */
3571 pcapng->sections = g_array_sized_new(false0, false0, sizeof(section_info_t), 1);
3572 g_array_append_val(pcapng->sections, first_section)g_array_append_vals (pcapng->sections, &(first_section
), 1)
;
3573
3574 wth->subtype_read = pcapng_read;
3575 wth->subtype_seek_read = pcapng_seek_read;
3576 wth->subtype_close = pcapng_close;
3577 wth->file_type_subtype = pcapng_file_type_subtype;
3578
3579 /* Always initialize the lists of Decryption Secret Blocks, Name
3580 * Resolution Blocks, and Sysdig meta event blocks such that a
3581 * wtap_dumper can refer to them right after opening the capture
3582 * file. */
3583 wth->dsbs = g_array_new(false0, false0, sizeof(wtap_block_t));
3584 wth->nrbs = g_array_new(false0, false0, sizeof(wtap_block_t));
3585 wth->meta_events = g_array_new(false0, false0, sizeof(wtap_block_t));
3586
3587 /* Most other capture types (such as pcap) support a single link-layer
3588 * type, indicated in the header, and don't support WTAP_ENCAP_PER_PACKET.
3589 * Most programs that write such capture files want to know the link-layer
3590 * type when initially opening the destination file, and (unlike Wireshark)
3591 * don't want to read the entire source file to find all the link-layer
3592 * types before writing (particularly if reading from a pipe or FIFO.)
3593 *
3594 * In support of this, read all the internally-processed, non packet
3595 * blocks that appear before the first packet block (EPB or SPB).
3596 *
3597 * Note that such programs will still have issues when trying to read
3598 * a pcapng that has a new link-layer type in an IDB in the middle of
3599 * the file, as they will discover in the middle that no, they can't
3600 * successfully write the output file as desired.
3601 *
3602 * If this is a live capture, and we're reading the initially written
3603 * header, we'll loop until we reach EOF. (If compressed, it might
3604 * also set WTAP_ERR_SHORT_READ from the stream / frame end not being
3605 * present until the file is closed.) So we'll need to clear that at
3606 * some point before reading packets.
3607 */
3608 while (!file_eof(wth->fh)) {
3609 /* peek at next block */
3610 /* Try to read the (next) block header */
3611 saved_offset = file_tell(wth->fh);
3612 if (!wtap_read_bytes_or_eof(wth->fh, &bh, sizeof bh, err, err_info)) {
3613 if (*err == 0) {
3614 /* EOF */
3615 ws_debug("No more blocks available...")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3615, __func__, "No more blocks available..."); } } while (
0)
;
3616 break;
3617 }
3618 ws_debug("Check for more initial blocks, wtap_read_bytes_or_eof() failed, err = %d.",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3619, __func__, "Check for more initial blocks, wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
3619 *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3619, __func__, "Check for more initial blocks, wtap_read_bytes_or_eof() failed, err = %d."
, *err); } } while (0)
;
3620 return WTAP_OPEN_ERROR;
3621 }
3622
3623 /* go back to where we were */
3624 file_seek(wth->fh, saved_offset, SEEK_SET0, err);
3625
3626 /*
3627 * Get a pointer to the current section's section_info_t.
3628 */
3629 current_section = &g_array_index(pcapng->sections, section_info_t,(((section_info_t*) (void *) (pcapng->sections)->data) [
(pcapng->current_section_number)])
3630 pcapng->current_section_number)(((section_info_t*) (void *) (pcapng->sections)->data) [
(pcapng->current_section_number)])
;
3631
3632 if (current_section->byte_swapped) {
3633 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type)(((guint32) ( (((guint32) (bh.block_type) & (guint32) 0x000000ffU
) << 24) | (((guint32) (bh.block_type) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (bh.block_type) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (bh.block_type) & (guint32) 0xff000000U
) >> 24))))
;
3634 }
3635
3636 ws_debug("Check for more initial internal blocks, block_type 0x%08x",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3637, __func__, "Check for more initial internal blocks, block_type 0x%08x"
, bh.block_type); } } while (0)
3637 bh.block_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3637, __func__, "Check for more initial internal blocks, block_type 0x%08x"
, bh.block_type); } } while (0)
;
3638
3639 if (!get_block_type_internal(bh.block_type)) {
3640 break; /* Next block has to be returned in pcap_read */
3641 }
3642 /* Note that some custom block types, unlike packet blocks,
3643 * don't need to be preceded by an IDB and so theoretically
3644 * we could skip past them here. However, then there's no good
3645 * way to both later return those blocks in pcap_read() and
3646 * ensure that we don't read and process the IDBs (and other
3647 * internal block types) a second time.
3648 *
3649 * pcapng_read_systemd_journal_export_block() sets the file level
3650 * link-layer type if it's still UNKNOWN. We could do the same here
3651 * for it and possibly other types based on block type, even without
3652 * reading them.
3653 */
3654 if (!pcapng_read_block(wth, wth->fh, current_section,
3655 &new_section, &wblock, err, err_info)) {
3656 wtap_block_unref(wblock.block);
3657 if (*err == 0) {
3658 ws_debug("No more initial blocks available...")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3658, __func__, "No more initial blocks available..."); } }
while (0)
;
3659 break;
3660 } else {
3661 ws_debug("couldn't read block")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3661, __func__, "couldn't read block"); } } while (0)
;
3662 return WTAP_OPEN_ERROR;
3663 }
3664 }
3665 pcapng_process_internal_block(wth, pcapng, current_section, new_section, &wblock, &saved_offset);
3666 ws_debug("Read IDB number_of_interfaces %u, wtap_encap %i",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3667, __func__, "Read IDB number_of_interfaces %u, wtap_encap %i"
, wth->interface_data->len, wth->file_encap); } } while
(0)
3667 wth->interface_data->len, wth->file_encap)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3667, __func__, "Read IDB number_of_interfaces %u, wtap_encap %i"
, wth->interface_data->len, wth->file_encap); } } while
(0)
;
3668 }
3669 return WTAP_OPEN_MINE;
3670}
3671
3672/* classic wtap: read packet */
3673static bool_Bool
3674pcapng_read(wtap *wth, wtap_rec *rec, int *err, char **err_info,
3675 int64_t *data_offset)
3676{
3677 pcapng_t *pcapng = (pcapng_t *)wth->priv;
3678 section_info_t *current_section, new_section;
3679 wtapng_block_t wblock;
3680
3681 wblock.rec = rec;
3682
3683 /* read next block */
3684 while (1) {
3685 *data_offset = file_tell(wth->fh);
3686 ws_noisy("data_offset is %" PRId64, *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/pcapng.c"
, 3686, __func__, "data_offset is %" "l" "d", *data_offset); }
} while (0)
;
3687
3688 /*
3689 * Get the section_info_t for the current section.
3690 */
3691 current_section = &g_array_index(pcapng->sections, section_info_t,(((section_info_t*) (void *) (pcapng->sections)->data) [
(pcapng->current_section_number)])
3692 pcapng->current_section_number)(((section_info_t*) (void *) (pcapng->sections)->data) [
(pcapng->current_section_number)])
;
3693
3694 /*
3695 * Read the next block.
3696 */
3697 if (!pcapng_read_block(wth, wth->fh, current_section,
3698 &new_section, &wblock, err, err_info)) {
3699 ws_noisy("data_offset is finally %" PRId64, *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/pcapng.c"
, 3699, __func__, "data_offset is finally %" "l" "d", *data_offset
); } } while (0)
;
3700 ws_debug("couldn't read packet block")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3700, __func__, "couldn't read packet block"); } } while (0
)
;
3701 wtap_block_unref(wblock.block);
3702 return false0;
3703 }
3704
3705 if (!wblock.internal) {
3706 /*
3707 * This is a block type we return to the caller to process.
3708 */
3709 ws_noisy("rec_type %u", wblock.rec->rec_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/pcapng.c"
, 3709, __func__, "rec_type %u", wblock.rec->rec_type); } }
while (0)
;
3710 break;
3711 }
3712
3713 /*
3714 * This is a block type we process internally, rather than
3715 * returning it for the caller to process.
3716 */
3717 pcapng_process_internal_block(wth, pcapng, current_section, new_section, &wblock, data_offset);
3718 }
3719
3720 /*ws_debug("Read length: %u Packet length: %u", bytes_read, rec->rec_header.packet_header.caplen);*/
3721 ws_noisy("data_offset is finally %" PRId64, *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/pcapng.c"
, 3721, __func__, "data_offset is finally %" "l" "d", *data_offset
); } } while (0)
;
3722
3723 /* Provide the section number */
3724 rec->presence_flags |= WTAP_HAS_SECTION_NUMBER0x00000008;
3725 rec->section_number = pcapng->current_section_number;
3726
3727 return true1;
3728}
3729
3730/* classic wtap: seek to file position and read packet */
3731static bool_Bool
3732pcapng_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec,
3733 int *err, char **err_info)
3734{
3735 pcapng_t *pcapng = (pcapng_t *)wth->priv;
3736 section_info_t *section_info, new_section;
3737 wtapng_block_t wblock;
3738
3739
3740 /* seek to the right file position */
3741 if (file_seek(wth->random_fh, seek_off, SEEK_SET0, err) < 0) {
3742 return false0; /* Seek error */
3743 }
3744 ws_noisy("reading at offset %" PRIu64, seek_off)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/pcapng.c"
, 3744, __func__, "reading at offset %" "l" "u", seek_off); }
} while (0)
;
3745
3746 /*
3747 * Find the section_info_t for the section in which this block
3748 * appears.
3749 *
3750 * First, make sure we have at least one section; if we don't, that's
3751 * an internal error.
3752 */
3753 ws_assert(pcapng->sections->len >= 1)do { if ((1) && !(pcapng->sections->len >= 1
)) ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/pcapng.c"
, 3753, __func__, "assertion failed: %s", "pcapng->sections->len >= 1"
); } while (0)
;
3754
3755 /*
3756 * Now scan backwards through the array to find the first section
3757 * that begins at or before the offset of the block we're reading.
3758 *
3759 * Yes, that's O(n) in the number of blocks, but we're unlikely to
3760 * have many sections and pretty unlikely to have more than one.
3761 */
3762 unsigned section_number = pcapng->sections->len - 1;
3763 for (;;) {
3764 section_info = &g_array_index(pcapng->sections, section_info_t,(((section_info_t*) (void *) (pcapng->sections)->data) [
(section_number)])
3765 section_number)(((section_info_t*) (void *) (pcapng->sections)->data) [
(section_number)])
;
3766 if (section_info->shb_off <= seek_off)
3767 break;
3768
3769 /*
3770 * If that's section 0, something's wrong; that section should
3771 * have an offset of 0.
3772 */
3773 ws_assert(section_number != 0)do { if ((1) && !(section_number != 0)) ws_log_fatal_full
("Wiretap", LOG_LEVEL_ERROR, "wiretap/pcapng.c", 3773, __func__
, "assertion failed: %s", "section_number != 0"); } while (0)
;
3774 section_number--;
3775 }
3776
3777 wblock.rec = rec;
3778
3779 /* read the block */
3780 if (!pcapng_read_block(wth, wth->random_fh, section_info,
3781 &new_section, &wblock, err, err_info)) {
3782 ws_debug("couldn't read packet block (err=%d).", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3782, __func__, "couldn't read packet block (err=%d).", *err
); } } while (0)
;
3783 wtap_block_unref(wblock.block);
3784 return false0;
3785 }
3786
3787 /* block must not be one we process internally rather than supplying */
3788 if (wblock.internal) {
3789 ws_debug("block type 0x%08x is not one we return",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3790, __func__, "block type 0x%08x is not one we return", wblock
.type); } } while (0)
3790 wblock.type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3790, __func__, "block type 0x%08x is not one we return", wblock
.type); } } while (0)
;
3791 wtap_block_unref(wblock.block);
3792 return false0;
3793 }
3794
3795 wtap_block_unref(wblock.block);
3796
3797 /* Provide the section number */
3798 rec->presence_flags |= WTAP_HAS_SECTION_NUMBER0x00000008;
3799 rec->section_number = section_number;
3800
3801 return true1;
3802}
3803
3804/* classic wtap: close capture file */
3805static void
3806pcapng_close(wtap *wth)
3807{
3808 pcapng_t *pcapng = (pcapng_t *)wth->priv;
3809
3810 ws_debug("closing file")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 3810, __func__, "closing file"); } } while (0)
;
3811
3812 /*
3813 * Free up the interfaces tables for all the sections.
3814 */
3815 for (unsigned i = 0; i < pcapng->sections->len; i++) {
3816 section_info_t *section_info = &g_array_index(pcapng->sections,(((section_info_t*) (void *) (pcapng->sections)->data) [
(i)])
3817 section_info_t, i)(((section_info_t*) (void *) (pcapng->sections)->data) [
(i)])
;
3818 g_array_free(section_info->interfaces, true1);
3819 if (section_info->custom_block_data != NULL((void*)0))
3820 g_hash_table_destroy(section_info->custom_block_data);
3821 if (section_info->local_block_data != NULL((void*)0))
3822 g_hash_table_destroy(section_info->local_block_data);
3823 }
3824 g_array_free(pcapng->sections, true1);
3825}
3826
3827/*
3828 * As it says at the top of the file, an option sizer "calculates how many
3829 * bytes the option's data requires, not including any padding bytes."
3830 * Callers are responsible for rounding up to multiples of 4 bytes.
3831 * compute_block_options_size() does that for each option in the block;
3832 * option writers that call an option sizer (which helps ensure that the
3833 * sizes are internally consistent) should do the same.
3834 */
3835
3836static uint32_t pcapng_compute_string_option_size(wtap_optval_t *optval)
3837{
3838 uint32_t size = 0;
3839
3840 size = (uint32_t)strlen(optval->stringval) & 0xffff;
3841
3842 return size;
3843}
3844
3845#if 0
3846static uint32_t pcapng_compute_bytes_option_size(wtap_optval_t *optval)
3847{
3848 uint32_t size = 0;
3849
3850 size = (uint32_t)g_bytes_get_size(optval->byteval) & 0xffff;
3851
3852 return size;
3853}
3854#endif
3855
3856static uint32_t pcapng_compute_if_filter_option_size(wtap_optval_t *optval)
3857{
3858 if_filter_opt_t* filter = &optval->if_filterval;
3859 uint32_t size;
3860
3861 if (filter->type == if_filter_pcap) {
3862 size = (uint32_t)(strlen(filter->data.filter_str) + 1) & 0xffff;
3863 } else if (filter->type == if_filter_bpf) {
3864 size = (uint32_t)((filter->data.bpf_prog.bpf_prog_len * 8) + 1) & 0xffff;
3865 } else {
3866 /* Unknown type; don't write it */
3867 size = 0;
3868 }
3869 return size;
3870}
3871
3872static uint32_t pcapng_compute_custom_string_option_size(wtap_optval_t *optval)
3873{
3874 uint32_t size = 0;
3875
3876 size = (uint32_t)strlen(optval->custom_stringval.string) & 0xffff;
3877
3878 return size;
3879}
3880
3881static uint32_t pcapng_compute_custom_binary_option_size(wtap_optval_t *optval)
3882{
3883 size_t size;
3884
3885 /* PEN */
3886 size = sizeof(uint32_t) + optval->custom_binaryval.data.custom_data_len;
3887
3888 if (size > 65535) {
3889 size = 65535;
3890 }
3891
3892 return (uint32_t)size;
3893}
3894
3895static uint32_t pcapng_compute_packet_hash_option_size(wtap_optval_t *optval)
3896{
3897 packet_hash_opt_t* hash = &optval->packet_hash;
3898 uint32_t size;
3899
3900 switch (hash->type) {
3901 case OPT_HASH_CRC322:
3902 size = 4;
3903 break;
3904 case OPT_HASH_MD53:
3905 size = 16;
3906 break;
3907 case OPT_HASH_SHA14:
3908 size = 20;
3909 break;
3910 case OPT_HASH_TOEPLITZ5:
3911 size = 4;
3912 break;
3913 default:
3914 /* 2COMP and XOR size not defined in standard (yet) */
3915 size = hash->hash_bytes->len;
3916 break;
3917 }
3918 /* XXX - What if the size of the hash bytes doesn't match the
3919 * expected size? We can:
3920 * 1) Return 0, and omit it when writing
3921 * 2) Return hash_bytes->len, and write it out exactly as we have it
3922 * 3) Return the correct size here, and when writing err or possibly
3923 * truncate.
3924 */
3925 /* Account for the size of the algorithm type field. */
3926 size += 1;
3927
3928 return size;
3929}
3930
3931static uint32_t pcapng_compute_packet_verdict_option_size(wtap_optval_t *optval)
3932{
3933 packet_verdict_opt_t* verdict = &optval->packet_verdictval;
3934 uint32_t size;
3935
3936 switch (verdict->type) {
3937
3938 case packet_verdict_hardware:
3939 size = verdict->data.verdict_bytes->len;
3940 break;
3941
3942 case packet_verdict_linux_ebpf_tc:
3943 size = 8;
3944 break;
3945
3946 case packet_verdict_linux_ebpf_xdp:
3947 size = 8;
3948 break;
3949
3950 default:
3951 size = 0;
3952 break;
3953 }
3954 /* Account for the type octet */
3955 if (size) {
3956 size += 1;
3957 }
3958
3959 return size;
3960}
3961
3962static bool_Bool
3963compute_block_option_size(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type, wtap_optval_t *optval, void *user_data)
3964{
3965 compute_options_size_t* options_size = (compute_options_size_t*)user_data;
3966 uint32_t size = 0;
3967
3968 /*
3969 * Process the option IDs that are the same for all block types here;
3970 * call the block-type-specific compute_size function for others.
3971 */
3972 switch(option_id)
3973 {
3974 case OPT_COMMENT1:
3975 size = pcapng_compute_string_option_size(optval);
3976 break;
3977 case OPT_CUSTOM_STR_COPY2988:
3978 size = pcapng_compute_custom_string_option_size(optval);
3979 break;
3980 case OPT_CUSTOM_BIN_COPY2989:
3981 size = pcapng_compute_custom_binary_option_size(optval);
3982 break;
3983 case OPT_CUSTOM_STR_NO_COPY19372:
3984 case OPT_CUSTOM_BIN_NO_COPY19373:
3985 /*
3986 * Do not count these, as they're not supposed to be copied to
3987 * new files.
3988 *
3989 * XXX - what if we're writing out a file that's *not* based on
3990 * another file, so that we're *not* copying it from that file?
3991 */
3992 break;
3993 default:
3994 /* Block-type dependent; call the callback. */
3995 if (options_size->compute_option_size) {
3996 size = (*options_size->compute_option_size)(block, option_id, option_type, optval);
3997 }
3998 break;
3999 }
4000
4001 /*
4002 * Are we writing this option?
4003 */
4004 /*
4005 * XXX: The option length field is 16 bits. If size > 65535 (how?
4006 * was the block was obtained from some format other than pcapng?),
4007 * are we going to silently omit the option (in which case we shouldn't
4008 * add the size here), or err out when writing it (in which case
4009 * it's probably fine to add the size or not?) Adding it here and
4010 * then omitting it when writing, as some of the routines do, means
4011 * creating a corrupt file.
4012 */
4013 if (size != 0) {
4014 /*
4015 * Yes. The length of this option is 4 bytes for the option
4016 * header, plus the size of the option data, rounded up
4017 * to a multiple of 4 bytes (32 bits).
4018 */
4019 options_size->size += WS_ROUNDUP_4(4 + size)(((4 + size) + ((unsigned)(4U-1U))) & (~((unsigned)(4U-1U
))))
;
4020 }
4021 return true1; /* we always succeed */
4022}
4023
4024uint32_t
4025pcapng_compute_options_size(wtap_block_t block, compute_option_size_func compute_option_size)
4026{
4027 compute_options_size_t compute_options_size;
4028
4029 /*
4030 * Compute the total size of all the options in the block.
4031 * This always succeeds, so we don't check the return value.
4032 */
4033 compute_options_size.size = 0;
4034 compute_options_size.compute_option_size = compute_option_size;
4035 wtap_block_foreach_option(block, compute_block_option_size, &compute_options_size);
4036
4037 /* Are we writing any options? */
4038 if (compute_options_size.size != 0) {
4039 /* Yes, add the size of the End-of-options tag. */
4040 compute_options_size.size += 4;
4041 }
4042 return compute_options_size.size;
4043}
4044
4045static uint32_t compute_shb_option_size(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type _U___attribute__((unused)), wtap_optval_t* optval)
4046{
4047 uint32_t size;
4048
4049 switch(option_id)
4050 {
4051 case OPT_SHB_HARDWARE2:
4052 case OPT_SHB_OS3:
4053 case OPT_SHB_USERAPPL4:
4054 size = pcapng_compute_string_option_size(optval);
4055 break;
4056 default:
4057 /* Unknown options - size by datatype? */
4058 size = 0;
4059 break;
4060 }
4061 return size;
4062}
4063
4064typedef struct write_options_t
4065{
4066 wtap_dumper *wdh;
4067 pcapng_opt_byte_order_e byte_order;
4068 write_option_func write_option;
4069 int *err;
4070 char **err_info;
4071}
4072write_options_t;
4073
4074static bool_Bool pcapng_write_option_eofopt(wtap_dumper *wdh, int *err)
4075{
4076 struct pcapng_option_header option_hdr;
4077
4078 /*
4079 * Write end of options.
4080 *
4081 * OPT_EOFOPT is zero, so we don't need to know the byte order to
4082 * be used, as both fields in the option header are zero and thus
4083 * unchanged if byte-swapped.
4084 */
4085 option_hdr.type = OPT_EOFOPT0;
4086 option_hdr.value_length = 0;
4087 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4088 return false0;
4089 return true1;
4090}
4091
4092static bool_Bool pcapng_write_uint8_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4093{
4094 struct pcapng_option_header option_hdr;
4095
4096 option_hdr.type = (uint16_t)option_id;
4097 option_hdr.value_length = (uint16_t)1;
4098 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4099 return false0;
4100
4101 if (!wtap_dump_file_write(wdh, &optval->uint8val, 1, err))
4102 return false0;
4103
4104 if (!pcapng_write_padding(wdh, 3, err))
4105 return false0;
4106
4107 return true1;
4108}
4109
4110static bool_Bool pcapng_write_uint32_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4111{
4112 struct pcapng_option_header option_hdr;
4113
4114 option_hdr.type = (uint16_t)option_id;
4115 option_hdr.value_length = (uint16_t)4;
4116 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4117 return false0;
4118
4119 if (!wtap_dump_file_write(wdh, &optval->uint32val, 4, err))
4120 return false0;
4121
4122 return true1;
4123}
4124
4125static bool_Bool pcapng_write_uint64_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4126{
4127 struct pcapng_option_header option_hdr;
4128
4129 option_hdr.type = (uint16_t)option_id;
4130 option_hdr.value_length = (uint16_t)8;
4131 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4132 return false0;
4133
4134 if (!wtap_dump_file_write(wdh, &optval->uint64val, 8, err))
4135 return false0;
4136
4137 return true1;
4138}
4139
4140static bool_Bool pcapng_write_timestamp_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4141{
4142 struct pcapng_option_header option_hdr;
4143 uint32_t high, low;
4144
4145 option_hdr.type = (uint16_t)option_id;
4146 option_hdr.value_length = (uint16_t)8;
4147 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4148 return false0;
4149
4150 high = (uint32_t)(optval->uint64val >> 32);
4151 low = (uint32_t)(optval->uint64val >> 0);
4152 if (!wtap_dump_file_write(wdh, &high, 4, err))
4153 return false0;
4154 if (!wtap_dump_file_write(wdh, &low, 4, err))
4155 return false0;
4156
4157 return true1;
4158}
4159
4160static bool_Bool pcapng_write_string_option(wtap_dumper *wdh,
4161 pcapng_opt_byte_order_e byte_order,
4162 unsigned option_id,
4163 wtap_optval_t *optval,
4164 int *err, char **err_info)
4165{
4166 struct pcapng_option_header option_hdr;
4167 size_t size = strlen(optval->stringval);
4168
4169 if (size == 0)
4170 return true1;
4171 if (size > 65535) {
4172 /*
4173 * Too big to fit in the option.
4174 * Don't write anything.
4175 *
4176 * XXX - truncate it? Report an error?
4177 */
4178 return true1;
4179 }
4180
4181 /* write option header */
4182 /* String options don't consider pad bytes part of the length */
4183 option_hdr.type = (uint16_t)option_id;
4184 option_hdr.value_length = (uint16_t)size;
4185 switch (byte_order) {
4186
4187 case OPT_SECTION_BYTE_ORDER:
4188 /* This is host byte order when writing, so nothing to do. */
4189 break;
4190
4191 case OPT_BIG_ENDIAN:
4192 option_hdr.type = GUINT16_TO_BE(option_hdr.type)((((guint16) ( (guint16) ((guint16) (option_hdr.type) >>
8) | (guint16) ((guint16) (option_hdr.type) << 8)))))
;
4193 option_hdr.value_length = GUINT16_TO_BE(option_hdr.value_length)((((guint16) ( (guint16) ((guint16) (option_hdr.value_length)
>> 8) | (guint16) ((guint16) (option_hdr.value_length)
<< 8)))))
;
4194 break;
4195
4196 case OPT_LITTLE_ENDIAN:
4197 option_hdr.type = GUINT16_TO_LE(option_hdr.type)((guint16) (option_hdr.type));
4198 option_hdr.value_length = GUINT16_TO_LE(option_hdr.value_length)((guint16) (option_hdr.value_length));
4199 break;
4200
4201 default:
4202 /*
4203 * This indicates somebody passed an invalid option to
4204 * pcapng_write_options().
4205 *
4206 * Report this as an internal error.
4207 */
4208 *err = WTAP_ERR_INTERNAL-21;
4209 *err_info = ws_strdup_printf("pcapng: invalid byte order %d passed to pcapng_write_options()",wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_write_options()"
, byte_order)
4210 byte_order)wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_write_options()"
, byte_order)
;
4211 return true1;
4212 }
4213 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4214 return false0;
4215
4216 if (!wtap_dump_file_write(wdh, optval->stringval, size, err))
4217 return false0;
4218
4219 /* write padding (if any) */
4220 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4221}
4222
4223#if 0
4224static bool_Bool pcapng_write_bytes_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4225{
4226 struct pcapng_option_header option_hdr;
4227 size_t size = g_bytes_get_size(optval->byteval);
4228
4229 if (size == 0)
4230 return true1;
4231 if (size > 65535) {
4232 /*
4233 * Too big to fit in the option.
4234 * Don't write anything.
4235 *
4236 * XXX - truncate it? Report an error?
4237 */
4238 return true1;
4239 }
4240
4241 /* Bytes options don't consider pad bytes part of the length */
4242 option_hdr.type = (uint16_t)option_id;
4243 option_hdr.value_length = (uint16_t)size;
4244 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4245 return false0;
4246
4247 if (!wtap_dump_file_write(wdh, optval->stringval, size, err))
4248 return false0;
4249
4250 /* write padding (if any) */
4251 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4252}
4253
4254static bool_Bool pcapng_write_ipv4_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4255{
4256 struct pcapng_option_header option_hdr;
4257
4258 option_hdr.type = (uint16_t)option_id;
4259 option_hdr.value_length = (uint16_t)4;
4260 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4261 return false0;
4262
4263 if (!wtap_dump_file_write(wdh, &optval->ipv4val, 1, err))
4264 return false0;
4265
4266 return true1;
4267}
4268
4269static bool_Bool pcapng_write_ipv6_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4270{
4271 struct pcapng_option_header option_hdr;
4272
4273 option_hdr.type = (uint16_t)option_id;
4274 option_hdr.value_length = (uint16_t)IPv6_ADDR_SIZE;
4275 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4276 return false0;
4277
4278 if (!wtap_dump_file_write(wdh, &optval->ipv6val.bytes, IPv6_ADDR_SIZE, err))
4279 return false0;
4280
4281 return true1;
4282}
4283#endif
4284
4285static bool_Bool pcapng_write_if_filter_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4286{
4287 if_filter_opt_t* filter = &optval->if_filterval;
4288 uint32_t size;
4289 uint8_t filter_type;
4290 size_t filter_data_len;
4291 struct pcapng_option_header option_hdr;
4292
4293 switch (filter->type) {
4294
4295 case if_filter_pcap:
4296 filter_type = 0; /* pcap filter string */
4297 filter_data_len = strlen(filter->data.filter_str);
4298 if (filter_data_len > 65534) {
4299 /*
4300 * Too big to fit in the option.
4301 * Don't write anything.
4302 *
4303 * XXX - truncate it? Report an error?
4304 */
4305 return true1;
4306 }
4307 break;
4308
4309 case if_filter_bpf:
4310 filter_type = 1; /* BPF filter program */
4311 filter_data_len = filter->data.bpf_prog.bpf_prog_len*8;
4312 if (filter_data_len > 65528) {
4313 /*
4314 * Too big to fit in the option. (The filter length
4315 * must be a multiple of 8, as that's the length
4316 * of a BPF instruction.) Don't write anything.
4317 *
4318 * XXX - truncate it? Report an error?
4319 */
4320 return true1;
4321 }
4322 break;
4323
4324 default:
4325 /* Unknown filter type; don't write anything. */
4326 return true1;
4327 }
4328 size = (uint32_t)(filter_data_len + 1);
4329
4330 option_hdr.type = option_id;
4331 option_hdr.value_length = size;
4332 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4333 return false0;
4334
4335 /* Write the filter type */
4336 if (!wtap_dump_file_write(wdh, &filter_type, 1, err))
4337 return false0;
4338
4339 switch (filter->type) {
4340
4341 case if_filter_pcap:
4342 /* Write the filter string */
4343 if (!wtap_dump_file_write(wdh, filter->data.filter_str, filter_data_len, err))
4344 return false0;
4345 break;
4346
4347 case if_filter_bpf:
4348 if (!wtap_dump_file_write(wdh, filter->data.bpf_prog.bpf_prog, filter_data_len, err))
4349 return false0;
4350 break;
4351
4352 default:
4353 ws_assert_not_reached()ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/pcapng.c"
, 4353, __func__, "assertion \"not reached\" failed")
;
4354 return true1;
4355 }
4356
4357 /* write padding (if any) */
4358 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4359}
4360
4361static bool_Bool pcapng_write_custom_string_option(wtap_dumper *wdh,
4362 pcapng_opt_byte_order_e byte_order,
4363 unsigned option_id,
4364 wtap_optval_t *optval,
4365 int *err, char **err_info)
4366{
4367 struct pcapng_option_header option_hdr;
4368 size_t stringlen;
4369 size_t size;
4370 uint32_t pen;
4371
4372 if (option_id == OPT_CUSTOM_STR_NO_COPY19372)
4373 return true1;
4374 ws_debug("PEN %u", optval->custom_stringval.pen)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 4374, __func__, "PEN %u", optval->custom_stringval.pen);
} } while (0)
;
4375 stringlen = strlen(optval->custom_stringval.string);
4376 size = sizeof(uint32_t) + stringlen;
4377 if (size > 65535) {
4378 /*
4379 * Too big to fit in the option.
4380 * Don't write anything.
4381 *
4382 * XXX - truncate it? Report an error?
4383 */
4384 return true1;
4385 }
4386
4387 /* write option header and PEN */
4388 /* String options don't consider pad bytes part of the length */
4389 option_hdr.type = (uint16_t)option_id;
4390 option_hdr.value_length = (uint16_t)size;
4391 pen = optval->custom_stringval.pen;
4392 switch (byte_order) {
4393
4394 case OPT_SECTION_BYTE_ORDER:
4395 /* This is host byte order when writing, so nothing to do. */
4396 break;
4397
4398 case OPT_BIG_ENDIAN:
4399 option_hdr.type = GUINT16_TO_BE(option_hdr.type)((((guint16) ( (guint16) ((guint16) (option_hdr.type) >>
8) | (guint16) ((guint16) (option_hdr.type) << 8)))))
;
4400 option_hdr.value_length = GUINT16_TO_BE(option_hdr.value_length)((((guint16) ( (guint16) ((guint16) (option_hdr.value_length)
>> 8) | (guint16) ((guint16) (option_hdr.value_length)
<< 8)))))
;
4401 pen = GUINT32_TO_BE(pen)((((guint32) ( (((guint32) (pen) & (guint32) 0x000000ffU)
<< 24) | (((guint32) (pen) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (pen) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (pen) & (guint32) 0xff000000U
) >> 24)))))
;
4402 break;
4403
4404 case OPT_LITTLE_ENDIAN:
4405 option_hdr.type = GUINT16_TO_LE(option_hdr.type)((guint16) (option_hdr.type));
4406 option_hdr.value_length = GUINT16_TO_LE(option_hdr.value_length)((guint16) (option_hdr.value_length));
4407 pen = GUINT32_TO_LE(pen)((guint32) (pen));
4408 break;
4409
4410 default:
4411 /*
4412 * This indicates somebody passed an invalid option to
4413 * pcapng_write_options().
4414 *
4415 * Report this as an internal error.
4416 */
4417 *err = WTAP_ERR_INTERNAL-21;
4418 *err_info = ws_strdup_printf("pcapng: invalid byte order %d passed to pcapng_write_options()",wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_write_options()"
, byte_order)
4419 byte_order)wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_write_options()"
, byte_order)
;
4420 return true1;
4421 }
4422 if (!wtap_dump_file_write(wdh, &option_hdr, sizeof(struct pcapng_option_header), err))
4423 return false0;
4424 if (!wtap_dump_file_write(wdh, &pen, sizeof(uint32_t), err))
4425 return false0;
4426
4427 /* write custom data */
4428 if (!wtap_dump_file_write(wdh, optval->custom_stringval.string, stringlen, err)) {
4429 return false0;
4430 }
4431 ws_debug("Wrote custom option: type %u, length %u", option_hdr.type, option_hdr.value_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 4431, __func__, "Wrote custom option: type %u, length %u", option_hdr
.type, option_hdr.value_length); } } while (0)
;
4432
4433 /* write padding (if any) */
4434 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4435}
4436
4437static bool_Bool pcapng_write_custom_binary_option(wtap_dumper *wdh,
4438 pcapng_opt_byte_order_e byte_order,
4439 unsigned option_id,
4440 wtap_optval_t *optval,
4441 int *err, char **err_info)
4442{
4443 struct pcapng_option_header option_hdr;
4444 size_t size;
4445 uint32_t pen;
4446
4447 if (option_id == OPT_CUSTOM_BIN_NO_COPY19373)
4448 return true1;
4449 ws_debug("PEN %u", optval->custom_binaryval.pen)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 4449, __func__, "PEN %u", optval->custom_binaryval.pen);
} } while (0)
;
4450 size = sizeof(uint32_t) + optval->custom_binaryval.data.custom_data_len;
4451 if (size > 65535) {
4452 /*
4453 * Too big to fit in the option.
4454 * Don't write anything.
4455 *
4456 * XXX - truncate it? Report an error?
4457 */
4458 return true1;
4459 }
4460
4461 /* write option header and PEN */
4462 option_hdr.type = (uint16_t)option_id;
4463 option_hdr.value_length = (uint16_t)size;
4464 pen = optval->custom_binaryval.pen;
4465 switch (byte_order) {
4466
4467 case OPT_SECTION_BYTE_ORDER:
4468 /* This is host byte order when writing, so nothing to do. */
4469 break;
4470
4471 case OPT_BIG_ENDIAN:
4472 option_hdr.type = GUINT16_TO_BE(option_hdr.type)((((guint16) ( (guint16) ((guint16) (option_hdr.type) >>
8) | (guint16) ((guint16) (option_hdr.type) << 8)))))
;
4473 option_hdr.value_length = GUINT16_TO_BE(option_hdr.value_length)((((guint16) ( (guint16) ((guint16) (option_hdr.value_length)
>> 8) | (guint16) ((guint16) (option_hdr.value_length)
<< 8)))))
;
4474 pen = GUINT32_TO_BE(pen)((((guint32) ( (((guint32) (pen) & (guint32) 0x000000ffU)
<< 24) | (((guint32) (pen) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (pen) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (pen) & (guint32) 0xff000000U
) >> 24)))))
;
4475 break;
4476
4477 case OPT_LITTLE_ENDIAN:
4478 option_hdr.type = GUINT16_TO_LE(option_hdr.type)((guint16) (option_hdr.type));
4479 option_hdr.value_length = GUINT16_TO_LE(option_hdr.value_length)((guint16) (option_hdr.value_length));
4480 pen = GUINT32_TO_LE(pen)((guint32) (pen));
4481 break;
4482
4483 default:
4484 /*
4485 * This indicates somebody passed an invalid option to
4486 * pcapng_write_options().
4487 *
4488 * Report this as an internal error.
4489 */
4490 *err = WTAP_ERR_INTERNAL-21;
4491 *err_info = ws_strdup_printf("pcapng: invalid byte order %d passed to pcapng_write_options()",wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_write_options()"
, byte_order)
4492 byte_order)wmem_strdup_printf(((void*)0), "pcapng: invalid byte order %d passed to pcapng_write_options()"
, byte_order)
;
4493 return true1;
4494 }
4495 if (!wtap_dump_file_write(wdh, &option_hdr, sizeof(struct pcapng_option_header), err))
4496 return false0;
4497 if (!wtap_dump_file_write(wdh, &pen, sizeof(uint32_t), err))
4498 return false0;
4499
4500 /* write custom data */
4501 if (!wtap_dump_file_write(wdh, optval->custom_binaryval.data.custom_data, optval->custom_binaryval.data.custom_data_len, err)) {
4502 return false0;
4503 }
4504 ws_debug("Wrote custom option: type %u, length %u", option_hdr.type, option_hdr.value_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 4504, __func__, "Wrote custom option: type %u, length %u", option_hdr
.type, option_hdr.value_length); } } while (0)
;
4505
4506 /* write padding (if any) */
4507 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4508}
4509
4510static bool_Bool pcapng_write_packet_verdict_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4511{
4512 packet_verdict_opt_t* verdict = &optval->packet_verdictval;
4513 struct pcapng_option_header option_hdr;
4514 uint8_t type;
4515 size_t size;
4516
4517 size = pcapng_compute_packet_verdict_option_size(optval);
4518
4519 switch (verdict->type) {
4520
4521 case packet_verdict_hardware:
4522 if (size > 65535) {
4523 /*
4524 * Too big to fit in the option.
4525 * Don't write anything.
4526 *
4527 * XXX - truncate it? Report an error?
4528 */
4529 return true1;
4530 }
4531 option_hdr.type = option_id;
4532 option_hdr.value_length = (uint16_t)size;
4533 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4534 return false0;
4535
4536 type = packet_verdict_hardware;
4537 if (!wtap_dump_file_write(wdh, &type, sizeof(uint8_t), err))
4538 return false0;
4539
4540 if (!wtap_dump_file_write(wdh, verdict->data.verdict_bytes->data,
4541 verdict->data.verdict_bytes->len, err))
4542 return false0;
4543 break;
4544
4545 case packet_verdict_linux_ebpf_tc:
4546 option_hdr.type = option_id;
4547 option_hdr.value_length = (uint16_t)size;
4548 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4549 return false0;
4550
4551 type = packet_verdict_linux_ebpf_tc;
4552 if (!wtap_dump_file_write(wdh, &type, sizeof(uint8_t), err))
4553 return false0;
4554
4555 if (!wtap_dump_file_write(wdh, &verdict->data.verdict_linux_ebpf_tc,
4556 sizeof(uint64_t), err))
4557 return false0;
4558 break;
4559
4560 case packet_verdict_linux_ebpf_xdp:
4561 option_hdr.type = option_id;
4562 option_hdr.value_length = (uint16_t)size;
4563 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4564 return false0;
4565
4566 type = packet_verdict_linux_ebpf_xdp;
4567 if (!wtap_dump_file_write(wdh, &type, sizeof(uint8_t), err))
4568 return false0;
4569
4570 if (!wtap_dump_file_write(wdh, &verdict->data.verdict_linux_ebpf_xdp,
4571 sizeof(uint64_t), err))
4572 return false0;
4573 break;
4574
4575 default:
4576 /* Unknown - don't write it out. */
4577 return true1;
4578 }
4579
4580 /* write padding (if any) */
4581 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4582}
4583
4584static bool_Bool pcapng_write_packet_hash_option(wtap_dumper *wdh, unsigned option_id, wtap_optval_t *optval, int *err)
4585{
4586 packet_hash_opt_t* hash = &optval->packet_hash;
4587 struct pcapng_option_header option_hdr;
4588 uint8_t type;
4589 size_t size;
4590
4591 size = pcapng_compute_packet_hash_option_size(optval);
4592
4593 if (size > 65535) {
4594 /*
4595 * Too big to fit in the option.
4596 * Don't write anything.
4597 *
4598 * XXX - truncate it? Report an error?
4599 */
4600 return true1;
4601 }
4602
4603 if (size > hash->hash_bytes->len + 1) {
4604 /*
4605 * We don't have enough bytes to write.
4606 * pcapng_compute_packet_hash_option_size() should return 0 if
4607 * we want to silently omit the option instead, or should return
4608 * the length if we want to blindly copy it.
4609 * XXX - Is this the best error type?
4610 */
4611 *err = WTAP_ERR_UNWRITABLE_REC_DATA-25;
4612 return false0;
4613 }
4614
4615 type = hash->type;
4616
4617 option_hdr.type = option_id;
4618 /* Include type byte */
4619 option_hdr.value_length = (uint16_t)size;
4620 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
4621 return false0;
4622
4623 if (!wtap_dump_file_write(wdh, &type, sizeof(uint8_t), err))
4624 return false0;
4625
4626 if (!wtap_dump_file_write(wdh, hash->hash_bytes->data, size - 1,
4627 err))
4628 return false0;
4629
4630 /* write padding (if any) */
4631 return pcapng_write_padding(wdh, WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U), err);
4632}
4633
4634static bool_Bool write_block_option(wtap_block_t block,
4635 unsigned option_id,
4636 wtap_opttype_e option_type _U___attribute__((unused)),
4637 wtap_optval_t *optval, void* user_data)
4638{
4639 write_options_t* options = (write_options_t*)user_data;
4640
4641 /*
4642 * Process the option IDs that are the same for all block types here;
4643 * call the block-type-specific write function for others.
4644 */
4645 switch(option_id)
4646 {
4647 case OPT_COMMENT1:
4648 if (!pcapng_write_string_option(options->wdh, options->byte_order,
4649 option_id, optval,
4650 options->err, options->err_info))
4651 return false0;
4652 break;
4653 case OPT_CUSTOM_STR_COPY2988:
4654 if (!pcapng_write_custom_string_option(options->wdh,
4655 options->byte_order,
4656 option_id, optval,
4657 options->err, options->err_info))
4658 return false0;
4659 break;
4660 case OPT_CUSTOM_BIN_COPY2989:
4661 if (!pcapng_write_custom_binary_option(options->wdh,
4662 options->byte_order,
4663 option_id, optval,
4664 options->err,
4665 options->err_info))
4666 return false0;
4667 break;
4668 case OPT_CUSTOM_STR_NO_COPY19372:
4669 case OPT_CUSTOM_BIN_NO_COPY19373:
4670 /*
4671 * Do not write these, as they're not supposed to be copied to
4672 * new files.
4673 *
4674 * XXX - what if we're writing out a file that's *not* based on
4675 * another file, so that we're *not* copying it from that file?
4676 */
4677 break;
4678 default:
4679 /* Block-type dependent; call the callback, if we have one. */
4680 if (options->write_option != NULL((void*)0) &&
4681 !(*options->write_option)(options->wdh, block, option_id,
4682 option_type, optval,
4683 options->err, options->err_info))
4684 return false0;
4685 break;
4686 }
4687 return true1;
4688}
4689
4690bool_Bool
4691pcapng_write_options(wtap_dumper *wdh, pcapng_opt_byte_order_e byte_order,
4692 wtap_block_t block, write_option_func write_option,
4693 int *err, char **err_info)
4694{
4695 write_options_t options;
4696
4697 options.wdh = wdh;
4698 options.byte_order = byte_order;
4699 options.write_option = write_option;
4700 options.err = err;
4701 options.err_info = err_info;
4702 if (!wtap_block_foreach_option(block, write_block_option, &options))
4703 return false0;
4704
4705 /* Write end of options */
4706 return pcapng_write_option_eofopt(wdh, err);
4707}
4708
4709static bool_Bool write_wtap_shb_option(wtap_dumper *wdh, wtap_block_t block _U___attribute__((unused)),
4710 unsigned option_id,
4711 wtap_opttype_e option_type _U___attribute__((unused)),
4712 wtap_optval_t *optval,
4713 int *err, char **err_info)
4714{
4715 switch(option_id)
4716 {
4717 case OPT_SHB_HARDWARE2:
4718 case OPT_SHB_OS3:
4719 case OPT_SHB_USERAPPL4:
4720 if (!pcapng_write_string_option(wdh, OPT_SECTION_BYTE_ORDER,
4721 option_id, optval, err, err_info))
4722 return false0;
4723 break;
4724 default:
4725 /* Unknown options - write by datatype? */
4726 break;
4727 }
4728 return true1; /* success */
4729}
4730
4731/* Write a section header block.
4732 * If we don't have a section block header already, create a default
4733 * one with no options.
4734 */
4735static bool_Bool
4736pcapng_write_section_header_block(wtap_dumper *wdh, int *err, char **err_info)
4737{
4738 uint32_t block_content_length;
4739 pcapng_section_header_block_t shb;
4740 uint32_t options_size;
4741 wtap_block_t wdh_shb = NULL((void*)0);
4742
4743 if (wdh->shb_hdrs && (wdh->shb_hdrs->len > 0)) {
4744 wdh_shb = g_array_index(wdh->shb_hdrs, wtap_block_t, 0)(((wtap_block_t*) (void *) (wdh->shb_hdrs)->data) [(0)]
)
;
4745 }
4746
4747 block_content_length = (uint32_t)sizeof(shb);
4748 options_size = 0;
4749 if (wdh_shb) {
4750 ws_debug("Have shb_hdr")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 4750, __func__, "Have shb_hdr"); } } while (0)
;
4751
4752 /* Compute size of all the options */
4753 options_size = pcapng_compute_options_size(wdh_shb, compute_shb_option_size);
4754
4755 block_content_length += options_size;
4756 }
4757
4758 /* write block header */
4759 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_SHB0x0A0D0D0A, block_content_length,
4760 err))
4761 return false0;
4762
4763 /* write block fixed content */
4764 shb.magic = 0x1A2B3C4D;
4765 shb.version_major = 1;
4766 shb.version_minor = 0;
4767 if (wdh_shb) {
4768 wtapng_section_mandatory_t* section_data = (wtapng_section_mandatory_t*)wtap_block_get_mandatory_data(wdh_shb);
4769 shb.section_length = section_data->section_length;
4770 } else {
4771 shb.section_length = -1;
4772 }
4773
4774 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
4775 return false0;
4776
4777 if (wdh_shb) {
4778 /* Write options, if we have any */
4779 if (options_size != 0) {
4780 if (!pcapng_write_options(wdh, OPT_SECTION_BYTE_ORDER,
4781 wdh_shb, write_wtap_shb_option,
4782 err, err_info))
4783 return false0;
4784 }
4785 }
4786
4787 /* write block footer */
4788 return pcapng_write_block_footer(wdh, block_content_length, err);
4789}
4790
4791/* options defined in Section 2.5 (Options)
4792 * Name Code Length Description
4793 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
4794 *
4795 * Enhanced Packet Block options
4796 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
4797 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
4798 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
4799 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
4800 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
4801 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
4802 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
4803 * The hash covers only the packet, not the header added by the capture driver:
4804 * this gives the possibility to calculate it inside the network card.
4805 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
4806 * data acquisition system and the capture library.
4807 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
4808 * between this packet and the preceding one.
4809 * epb_packetid 5 8 The epb_packetid option is a 64-bit unsigned integer that
4810 * uniquely identifies the packet. If the same packet is seen
4811 * by multiple interfaces and there is a way for the capture
4812 * application to correlate them, the same epb_packetid value
4813 * must be used. An example could be a router that captures
4814 * packets on all its interfaces in both directions. When a
4815 * packet hits interface A on ingress, an EPB entry gets
4816 * created, TTL gets decremented, and right before it egresses
4817 * on interface B another EPB entry gets created in the trace
4818 * file. In this case, two packets are in the capture file,
4819 * which are not identical but the epb_packetid can be used to
4820 * correlate them.
4821 * epb_queue 6 4 The epb_queue option is a 32-bit unsigned integer that
4822 * identifies on which queue of the interface the specific
4823 * packet was received.
4824 * epb_verdict 7 variable The epb_verdict option stores a verdict of the packet. The
4825 * verdict indicates what would be done with the packet after
4826 * processing it. For example, a firewall could drop the
4827 * packet. This verdict can be set by various components, i.e.
4828 * Hardware, Linux's eBPF TC or XDP framework, etc. etc. The
4829 * first octet specifies the verdict type, while the following
4830 * octets contain the actual verdict data, whose size depends on
4831 * the verdict type, and hence from the value in the first
4832 * octet. The verdict type can be: Hardware (type octet = 0,
4833 * size = variable), Linux_eBPF_TC (type octet = 1, size = 8
4834 * (64-bit unsigned integer), value = TC_ACT_* as defined in the
4835 * Linux pck_cls.h include), Linux_eBPF_XDP (type octet = 2,
4836 * size = 8 (64-bit unsigned integer), value = xdp_action as
4837 * defined in the Linux pbf.h include).
4838 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
4839 */
4840static uint32_t
4841compute_epb_option_size(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type _U___attribute__((unused)), wtap_optval_t* optval)
4842{
4843 uint32_t size;
4844
4845 switch(option_id)
4846 {
4847 case OPT_PKT_FLAGS2:
4848 size = 4;
4849 break;
4850 case OPT_PKT_HASH3:
4851 size = pcapng_compute_packet_hash_option_size(optval);
4852 break;
4853 case OPT_PKT_DROPCOUNT4:
4854 size = 8;
4855 break;
4856 case OPT_PKT_PACKETID5:
4857 size = 8;
4858 break;
4859 case OPT_PKT_QUEUE6:
4860 size = 4;
4861 break;
4862 case OPT_PKT_VERDICT7:
4863 size = pcapng_compute_packet_verdict_option_size(optval);
4864 break;
4865 case OPT_PKT_PROCIDTHRDID8:
4866 size = 8;
4867 break;
4868 default:
4869 /* Unknown options - size by datatype? */
4870 size = 0;
4871 break;
4872 }
4873 return size;
4874}
4875
4876static bool_Bool write_wtap_epb_option(wtap_dumper *wdh, wtap_block_t block _U___attribute__((unused)),
4877 unsigned option_id,
4878 wtap_opttype_e option_type _U___attribute__((unused)),
4879 wtap_optval_t *optval,
4880 int *err, char **err_info _U___attribute__((unused)))
4881{
4882 switch(option_id)
4883 {
4884 case OPT_PKT_FLAGS2:
4885 if (!pcapng_write_uint32_option(wdh, OPT_PKT_FLAGS2, optval, err))
4886 return false0;
4887 break;
4888 case OPT_PKT_HASH3:
4889 if (!pcapng_write_packet_hash_option(wdh, OPT_PKT_HASH3, optval, err))
4890 return false0;
4891 break;
4892 case OPT_PKT_DROPCOUNT4:
4893 if (!pcapng_write_uint64_option(wdh, OPT_PKT_DROPCOUNT4, optval, err))
4894 return false0;
4895 break;
4896 case OPT_PKT_PACKETID5:
4897 if (!pcapng_write_uint64_option(wdh, OPT_PKT_PACKETID5, optval, err))
4898 return false0;
4899 break;
4900 case OPT_PKT_QUEUE6:
4901 if (!pcapng_write_uint32_option(wdh, OPT_PKT_QUEUE6, optval, err))
4902 return false0;
4903 break;
4904 case OPT_PKT_VERDICT7:
4905 if (!pcapng_write_packet_verdict_option(wdh, OPT_PKT_VERDICT7, optval, err))
4906 return false0;
4907 break;
4908 case OPT_PKT_PROCIDTHRDID8:
4909 if (!pcapng_write_uint64_option(wdh, OPT_PKT_PROCIDTHRDID8, optval, err))
4910 return false0;
4911 break;
4912 default:
4913 /* Unknown options - write by datatype? */
4914 break;
4915 }
4916 return true1; /* success */
4917}
4918
4919static bool_Bool
4920pcapng_write_simple_packet_block(wtap_dumper* wdh, const wtap_rec* rec,
4921 int* err, char** err_info _U___attribute__((unused)))
4922{
4923 const union wtap_pseudo_header* pseudo_header = &rec->rec_header.packet_header.pseudo_header;
4924 uint32_t block_content_length;
4925 pcapng_simple_packet_block_t spb;
4926 uint32_t pad_len;
4927 uint32_t phdr_len;
4928
4929 /* Don't write anything we're not willing to read. */
4930 if (rec->rec_header.packet_header.caplen > wtap_max_snaplen_for_encap(wdh->file_encap)) {
4931 *err = WTAP_ERR_PACKET_TOO_LARGE-22;
4932 return false0;
4933 }
4934
4935 phdr_len = pcap_get_phdr_size(rec->rec_header.packet_header.pkt_encap, pseudo_header);
4936 pad_len = WS_PADDING_TO_4(phdr_len + rec->rec_header.packet_header.caplen)((4U - ((phdr_len + rec->rec_header.packet_header.caplen) %
4U)) % 4U)
;
4937
4938 /* write (simple) packet block header */
4939 block_content_length = (uint32_t)sizeof(spb) + phdr_len + rec->rec_header.packet_header.caplen + pad_len;
4940 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_SPB0x00000003, block_content_length,
4941 err))
4942 return false0;
4943
4944 /* write block fixed content */
4945 spb.packet_len = rec->rec_header.packet_header.len + phdr_len;
4946
4947 if (!wtap_dump_file_write(wdh, &spb, sizeof spb, err))
4948 return false0;
4949
4950 /* write pseudo header */
4951 if (!pcap_write_phdr(wdh, rec->rec_header.packet_header.pkt_encap, pseudo_header, err)) {
4952 return false0;
4953 }
4954
4955 /* write packet data */
4956 if (!wtap_dump_file_write(wdh, ws_buffer_start_ptr(&rec->data), rec->rec_header.packet_header.caplen, err))
4957 return false0;
4958
4959 /* write padding (if any) */
4960 if (!pcapng_write_padding(wdh, pad_len, err))
4961 return false0;
4962
4963 /* write block footer */
4964 return pcapng_write_block_footer(wdh, block_content_length, err);
4965}
4966
4967static bool_Bool
4968pcapng_write_enhanced_packet_block(wtap_dumper *wdh, const wtap_rec *rec,
4969 int *err, char **err_info)
4970{
4971 const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
4972 uint32_t block_content_length;
4973 pcapng_enhanced_packet_block_t epb;
4974 uint32_t options_size = 0;
4975 uint64_t ts;
4976 uint32_t pad_len;
4977 uint32_t phdr_len;
4978 wtap_block_t int_data;
4979 wtapng_if_descr_mandatory_t *int_data_mand;
4980
4981 /* Don't write anything we're not willing to read. */
4982 if (rec->rec_header.packet_header.caplen > wtap_max_snaplen_for_encap(wdh->file_encap)) {
4983 *err = WTAP_ERR_PACKET_TOO_LARGE-22;
4984 return false0;
4985 }
4986
4987 phdr_len = pcap_get_phdr_size(rec->rec_header.packet_header.pkt_encap, pseudo_header);
4988 pad_len = WS_PADDING_TO_4(phdr_len + rec->rec_header.packet_header.caplen)((4U - ((phdr_len + rec->rec_header.packet_header.caplen) %
4U)) % 4U)
;
4989
4990 if (rec->block != NULL((void*)0)) {
4991 /* Compute size of all the options */
4992 options_size = pcapng_compute_options_size(rec->block, compute_epb_option_size);
4993 }
4994
4995 /*
4996 * Check the interface ID. Do this before writing the header,
4997 * in case we need to add a new IDB.
4998 */
4999 if (rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) {
5000 epb.interface_id = rec->rec_header.packet_header.interface_id;
5001 if (rec->presence_flags & WTAP_HAS_SECTION_NUMBER0x00000008 && wdh->shb_iface_to_global) {
5002 /*
5003 * In the extremely unlikely event this overflows we give the
5004 * wrong interface ID.
5005 */
5006 epb.interface_id += g_array_index(wdh->shb_iface_to_global, unsigned, rec->section_number)(((unsigned*) (void *) (wdh->shb_iface_to_global)->data
) [(rec->section_number)])
;
5007 }
5008 } else {
5009 /*
5010 * The source isn't sending us IDBs. See if we already have a
5011 * matching interface, and use it if so.
5012 */
5013 for (epb.interface_id = 0; epb.interface_id < wdh->interface_data->len; ++epb.interface_id) {
5014 int_data = g_array_index(wdh->interface_data, wtap_block_t,(((wtap_block_t*) (void *) (wdh->interface_data)->data)
[(epb.interface_id)])
5015 epb.interface_id)(((wtap_block_t*) (void *) (wdh->interface_data)->data)
[(epb.interface_id)])
;
5016 int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
5017 if (int_data_mand->wtap_encap == rec->rec_header.packet_header.pkt_encap) {
5018 if (int_data_mand->tsprecision == rec->tsprec || (!(rec->presence_flags & WTAP_HAS_TS0x00000001))) {
5019 break;
5020 }
5021 }
5022 }
5023 if (epb.interface_id == wdh->interface_data->len) {
5024 /*
5025 * We don't have a matching IDB. Generate a new one
5026 * and write it to the file.
5027 */
5028 int_data = wtap_rec_generate_idb(rec);
5029 g_array_append_val(wdh->interface_data, int_data)g_array_append_vals (wdh->interface_data, &(int_data),
1)
;
5030 if (!pcapng_write_if_descr_block(wdh, int_data, err, err_info)) {
5031 return false0;
5032 }
5033 }
5034 }
5035 if (epb.interface_id >= wdh->interface_data->len) {
5036 /*
5037 * Our caller is doing something bad.
5038 */
5039 *err = WTAP_ERR_INTERNAL-21;
5040 *err_info = ws_strdup_printf("pcapng: epb.interface_id (%u) >= wdh->interface_data->len (%u)",wmem_strdup_printf(((void*)0), "pcapng: epb.interface_id (%u) >= wdh->interface_data->len (%u)"
, epb.interface_id, wdh->interface_data->len)
5041 epb.interface_id, wdh->interface_data->len)wmem_strdup_printf(((void*)0), "pcapng: epb.interface_id (%u) >= wdh->interface_data->len (%u)"
, epb.interface_id, wdh->interface_data->len)
;
5042 return false0;
5043 }
5044 int_data = g_array_index(wdh->interface_data, wtap_block_t,(((wtap_block_t*) (void *) (wdh->interface_data)->data)
[(epb.interface_id)])
5045 epb.interface_id)(((wtap_block_t*) (void *) (wdh->interface_data)->data)
[(epb.interface_id)])
;
5046 int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
5047 if (int_data_mand->wtap_encap != rec->rec_header.packet_header.pkt_encap) {
5048 /*
5049 * Our caller is doing something bad.
5050 */
5051 *err = WTAP_ERR_INTERNAL-21;
5052 *err_info = ws_strdup_printf("pcapng: interface %u encap %d != packet encap %d",wmem_strdup_printf(((void*)0), "pcapng: interface %u encap %d != packet encap %d"
, epb.interface_id, int_data_mand->wtap_encap, rec->rec_header
.packet_header.pkt_encap)
5053 epb.interface_id,wmem_strdup_printf(((void*)0), "pcapng: interface %u encap %d != packet encap %d"
, epb.interface_id, int_data_mand->wtap_encap, rec->rec_header
.packet_header.pkt_encap)
5054 int_data_mand->wtap_encap,wmem_strdup_printf(((void*)0), "pcapng: interface %u encap %d != packet encap %d"
, epb.interface_id, int_data_mand->wtap_encap, rec->rec_header
.packet_header.pkt_encap)
5055 rec->rec_header.packet_header.pkt_encap)wmem_strdup_printf(((void*)0), "pcapng: interface %u encap %d != packet encap %d"
, epb.interface_id, int_data_mand->wtap_encap, rec->rec_header
.packet_header.pkt_encap)
;
5056 return false0;
5057 }
5058
5059 /* write (enhanced) packet block header */
5060 block_content_length = (uint32_t)sizeof(epb) + phdr_len + rec->rec_header.packet_header.caplen + pad_len + options_size;
5061 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_EPB0x00000006, block_content_length,
5062 err))
5063 return false0;
5064
5065 /* write block fixed content */
5066 /* Calculate the time stamp as a 64-bit integer. */
5067 ts = ((uint64_t)rec->ts.secs) * int_data_mand->time_units_per_second +
5068 (((uint64_t)rec->ts.nsecs) * int_data_mand->time_units_per_second) / 1000000000;
5069 /*
5070 * Split the 64-bit timestamp into two 32-bit pieces, using
5071 * the time stamp resolution for the interface.
5072 */
5073 epb.timestamp_high = (uint32_t)(ts >> 32);
5074 epb.timestamp_low = (uint32_t)ts;
5075 epb.captured_len = rec->rec_header.packet_header.caplen + phdr_len;
5076 epb.packet_len = rec->rec_header.packet_header.len + phdr_len;
5077
5078 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
5079 return false0;
5080
5081 /* write pseudo header */
5082 if (!pcap_write_phdr(wdh, rec->rec_header.packet_header.pkt_encap, pseudo_header, err)) {
5083 return false0;
5084 }
5085
5086 /* write packet data */
5087 if (!wtap_dump_file_write(wdh, ws_buffer_start_ptr(&rec->data), rec->rec_header.packet_header.caplen, err))
5088 return false0;
5089
5090 /* write padding (if any) */
5091 if (!pcapng_write_padding(wdh, pad_len, err))
5092 return false0;
5093
5094 /* Write options, if we have any */
5095 if (options_size != 0) {
5096 if (!pcapng_write_options(wdh, OPT_SECTION_BYTE_ORDER,
5097 rec->block, write_wtap_epb_option,
5098 err, err_info))
5099 return false0;
5100 }
5101
5102 /* write block footer */
5103 return pcapng_write_block_footer(wdh, block_content_length, err);
5104}
5105
5106static bool_Bool
5107pcapng_write_systemd_journal_export_block(wtap_dumper *wdh, const wtap_rec *rec,
5108 int *err, char **err_info _U___attribute__((unused)))
5109{
5110 uint32_t block_content_length;
5111 uint32_t pad_len;
5112
5113 /* Don't write anything we're not willing to read. */
5114 if (rec->rec_header.systemd_journal_export_header.record_len > WTAP_MAX_PACKET_SIZE_STANDARD262144U) {
5115 *err = WTAP_ERR_PACKET_TOO_LARGE-22;
5116 return false0;
5117 }
5118
5119 pad_len = WS_PADDING_TO_4(rec->rec_header.systemd_journal_export_header.record_len)((4U - ((rec->rec_header.systemd_journal_export_header.record_len
) % 4U)) % 4U)
;
5120
5121 /* write systemd journal export block header */
5122 block_content_length = rec->rec_header.systemd_journal_export_header.record_len + pad_len;
5123 ws_debug("writing %u bytes, %u padded",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5125, __func__, "writing %u bytes, %u padded", rec->rec_header
.systemd_journal_export_header.record_len, block_content_length
); } } while (0)
5124 rec->rec_header.systemd_journal_export_header.record_len,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5125, __func__, "writing %u bytes, %u padded", rec->rec_header
.systemd_journal_export_header.record_len, block_content_length
); } } while (0)
5125 block_content_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5125, __func__, "writing %u bytes, %u padded", rec->rec_header
.systemd_journal_export_header.record_len, block_content_length
); } } while (0)
;
5126 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_SYSTEMD_JOURNAL_EXPORT0x00000009,
5127 block_content_length, err))
5128 return false0;
5129
5130 /* write entry data */
5131 if (!wtap_dump_file_write(wdh, ws_buffer_start_ptr(&rec->data), rec->rec_header.systemd_journal_export_header.record_len, err))
5132 return false0;
5133
5134 /* write padding (if any) */
5135 if (!pcapng_write_padding(wdh, pad_len, err))
5136 return false0;
5137
5138 /* write block footer */
5139 return pcapng_write_block_footer(wdh, block_content_length, err);
5140}
5141
5142static bool_Bool
5143pcapng_write_custom_block_copy(wtap_dumper *wdh, const wtap_rec *rec,
5144 int *err, char **err_info _U___attribute__((unused)))
5145{
5146 pcapng_custom_block_enterprise_handler_t *pen_handler;
5147 uint32_t block_content_length;
5148 pcapng_custom_block_t cb;
5149 uint32_t pad_len;
5150
5151 /* Don't write anything we are not supposed to. */
5152 if (!rec->rec_header.custom_block_header.copy_allowed) {
5153 return true1;
5154 }
5155
5156 pen_handler = (pcapng_custom_block_enterprise_handler_t*)g_hash_table_lookup(custom_enterprise_handlers, GUINT_TO_POINTER(rec->rec_header.custom_block_header.pen)((gpointer) (gulong) (rec->rec_header.custom_block_header.
pen))
);
5157 if (pen_handler != NULL((void*)0))
5158 {
5159 if (!pen_handler->writer(wdh, rec, err, err_info))
5160 return false0;
5161 }
5162 else
5163 {
5164 /* Don't write anything we're not willing to read. */
5165 if (rec->rec_header.custom_block_header.length > WTAP_MAX_PACKET_SIZE_STANDARD262144U) {
5166 *err = WTAP_ERR_PACKET_TOO_LARGE-22;
5167 return false0;
5168 }
5169
5170 pad_len = WS_PADDING_TO_4(rec->rec_header.custom_block_header.length)((4U - ((rec->rec_header.custom_block_header.length) % 4U)
) % 4U)
;
5171
5172 /* write block header */
5173 block_content_length = (uint32_t)sizeof(cb) + rec->rec_header.custom_block_header.length + pad_len;
5174 ws_debug("writing %u bytes, %u padded, PEN %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5176, __func__, "writing %u bytes, %u padded, PEN %u", (uint32_t
)sizeof(cb) + rec->rec_header.custom_block_header.length, block_content_length
, rec->rec_header.custom_block_header.pen); } } while (0)
5175 (uint32_t)sizeof(cb) + rec->rec_header.custom_block_header.length,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5176, __func__, "writing %u bytes, %u padded, PEN %u", (uint32_t
)sizeof(cb) + rec->rec_header.custom_block_header.length, block_content_length
, rec->rec_header.custom_block_header.pen); } } while (0)
5176 block_content_length, rec->rec_header.custom_block_header.pen)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5176, __func__, "writing %u bytes, %u padded, PEN %u", (uint32_t
)sizeof(cb) + rec->rec_header.custom_block_header.length, block_content_length
, rec->rec_header.custom_block_header.pen); } } while (0)
;
5177 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_CB_COPY0x00000BAD,
5178 block_content_length, err))
5179 return false0;
5180
5181 /* write custom block header */
5182 cb.pen = rec->rec_header.custom_block_header.pen;
5183 if (!wtap_dump_file_write(wdh, &cb, sizeof cb, err)) {
5184 return false0;
5185 }
5186 ws_debug("wrote PEN = %u", cb.pen)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5186, __func__, "wrote PEN = %u", cb.pen); } } while (0)
;
5187
5188 /* write custom data */
5189 if (!wtap_dump_file_write(wdh, ws_buffer_start_ptr(&rec->data), rec->rec_header.custom_block_header.length, err)) {
5190 return false0;
5191 }
5192
5193 /* write padding (if any) */
5194 if (!pcapng_write_padding(wdh, pad_len, err))
5195 return false0;
5196
5197 /* write block footer */
5198 return pcapng_write_block_footer(wdh, block_content_length, err);
5199 }
5200 return true1;
5201}
5202
5203static bool_Bool
5204pcapng_write_custom_block_no_copy(wtap_dumper *wdh _U___attribute__((unused)), const wtap_rec *rec _U___attribute__((unused)),
5205 int *err _U___attribute__((unused)), char **err_info _U___attribute__((unused)))
5206{
5207 /* Don't write anything we are not supposed to. */
5208 return true1;
5209}
5210
5211static bool_Bool
5212pcapng_write_decryption_secrets_block(wtap_dumper *wdh, wtap_block_t sdata, int *err)
5213{
5214 uint32_t block_content_length;
5215 pcapng_decryption_secrets_block_t dsb;
5216 wtapng_dsb_mandatory_t *mand_data = (wtapng_dsb_mandatory_t *)wtap_block_get_mandatory_data(sdata);
5217 uint32_t pad_len;
5218
5219 pad_len = WS_PADDING_TO_4(mand_data->secrets_len)((4U - ((mand_data->secrets_len) % 4U)) % 4U);
5220
5221 /* write block header */
5222 block_content_length = (uint32_t)sizeof(dsb) + mand_data->secrets_len + pad_len;
5223 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_DSB0x0000000A, block_content_length,
5224 err))
5225 return false0;
5226
5227 /* write block fixed content */
5228 dsb.secrets_type = mand_data->secrets_type;
5229 dsb.secrets_len = mand_data->secrets_len;
5230 if (!wtap_dump_file_write(wdh, &dsb, sizeof dsb, err))
5231 return false0;
5232
5233 if (!wtap_dump_file_write(wdh, mand_data->secrets_data, mand_data->secrets_len, err))
5234 return false0;
5235
5236 /* write padding (if any) */
5237 if (!pcapng_write_padding(wdh, pad_len, err))
5238 return false0;
5239
5240 /* write block footer */
5241 return pcapng_write_block_footer(wdh, block_content_length, err);
5242}
5243
5244static bool_Bool
5245pcapng_write_meta_event_block(wtap_dumper *wdh, wtap_block_t mev_data, int *err)
5246{
5247 uint32_t block_content_length;
5248 wtapng_meta_event_mandatory_t *mand_data = (wtapng_meta_event_mandatory_t *)wtap_block_get_mandatory_data(mev_data);
5249 uint32_t pad_len;
5250
5251 pad_len = WS_PADDING_TO_4(mand_data->mev_data_len)((4U - ((mand_data->mev_data_len) % 4U)) % 4U);
5252
5253 /* write block header */
5254 block_content_length = mand_data->mev_data_len + pad_len;
5255 if (!pcapng_write_block_header(wdh, mand_data->mev_block_type,
5256 block_content_length, err))
5257 return false0;
5258 ws_debug("Sysdig mev len %u", block_content_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5258, __func__, "Sysdig mev len %u", block_content_length);
} } while (0)
;
5259
5260 /* write block fixed content */
5261 if (!wtap_dump_file_write(wdh, mand_data->mev_data, mand_data->mev_data_len, err))
5262 return false0;
5263
5264 /* write padding (if any) */
5265 if (!pcapng_write_padding(wdh, pad_len, err))
5266 return false0;
5267
5268 /* write block footer */
5269 return pcapng_write_block_footer(wdh, block_content_length, err);
5270}
5271
5272/*
5273 * libpcap's maximum pcapng block size is currently 16MB.
5274 *
5275 * The maximum pcapng block size in macOS's private pcapng reading code
5276 * is 1MB. (Yes, this means that a program using the standard pcap
5277 * code to read pcapng files can handle bigger blocks than can programs
5278 * using the private code, such as Apple's tcpdump, can handle.)
5279 *
5280 * The pcapng reading code here can handle NRBs of arbitrary size (less
5281 * than 4GB, obviously), as they read each NRB record independently,
5282 * rather than reading the entire block into memory.
5283 *
5284 * So, for now, we set the maximum NRB block size we write as 1 MB.
5285 *
5286 * (Yes, for the benefit of the fussy, "MB" is really "MiB".)
5287 */
5288
5289#define NRES_BLOCK_MAX_SIZE(1024*1024) (1024*1024)
5290
5291static uint32_t
5292compute_nrb_option_size(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type _U___attribute__((unused)), wtap_optval_t* optval)
5293{
5294 uint32_t size;
5295
5296 switch(option_id)
5297 {
5298 case OPT_NS_DNSNAME2:
5299 size = pcapng_compute_string_option_size(optval);
5300 break;
5301 case OPT_NS_DNSIP4ADDR3:
5302 size = 4;
5303 break;
5304 case OPT_NS_DNSIP6ADDR4:
5305 size = 16;
5306 break;
5307 default:
5308 /* Unknown options - size by datatype? */
5309 size = 0;
5310 break;
5311 }
5312 return size;
5313}
5314
5315static bool_Bool
5316put_nrb_option(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type _U___attribute__((unused)), wtap_optval_t* optval, void* user_data)
5317{
5318 uint8_t **opt_ptrp = (uint8_t **)user_data;
5319 size_t stringlen;
5320 size_t size = 0;
5321 struct pcapng_option_header option_hdr;
5322 uint32_t pad;
5323
5324 switch(option_id)
5325 {
5326 case OPT_COMMENT1:
5327 case OPT_NS_DNSNAME2:
5328 size = strlen(optval->stringval);
5329 if (size > 65535) {
5330 /*
5331 * Too big to fit in the option.
5332 * Don't write anything.
5333 *
5334 * XXX - truncate it? Report an error?
5335 */
5336 return true1;
5337 }
5338
5339 /* Put option header */
5340 /* String options don't consider pad bytes part of the length */
5341 option_hdr.type = (uint16_t)option_id;
5342 option_hdr.value_length = (uint16_t)size;
5343 memcpy(*opt_ptrp, &option_hdr, 4);
5344 *opt_ptrp += 4;
5345
5346 memcpy(*opt_ptrp, optval->stringval, size);
5347 *opt_ptrp += size;
5348
5349 /* put padding (if any) */
5350 pad = WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U);
5351 if (pad != 0) {
5352 memset(*opt_ptrp, 0, pad);
5353 *opt_ptrp += pad;
5354 }
5355 break;
5356 case OPT_CUSTOM_STR_COPY2988:
5357 /* String options don't consider pad bytes part of the length */
5358 stringlen = strlen(optval->custom_stringval.string);
5359 size = sizeof(uint32_t) + stringlen;
5360 if (size > 65535) {
5361 /*
5362 * Too big to fit in the option.
5363 * Don't write anything.
5364 *
5365 * XXX - truncate it? Report an error?
5366 */
5367 return true1;
5368 }
5369
5370 /* Put option header and PEN */
5371 /* String options don't consider pad bytes part of the length */
5372 option_hdr.type = (uint16_t)option_id;
5373 option_hdr.value_length = (uint16_t)size;
5374 memcpy(*opt_ptrp, &option_hdr, 4);
5375 *opt_ptrp += 4;
5376
5377 memcpy(*opt_ptrp, &optval->custom_stringval.pen, sizeof(uint32_t));
5378 *opt_ptrp += sizeof(uint32_t);
5379 memcpy(*opt_ptrp, optval->custom_stringval.string, size);
5380 *opt_ptrp += size;
5381
5382 /* put padding (if any) */
5383 pad = WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U);
5384 if (pad != 0) {
5385 memset(*opt_ptrp, 0, pad);
5386 *opt_ptrp += pad;
5387 }
5388 break;
5389 case OPT_CUSTOM_BIN_COPY2989:
5390 /* Custom options don't consider pad bytes part of the length */
5391 size = (uint32_t)(optval->custom_binaryval.data.custom_data_len + sizeof(uint32_t)) & 0xffff;
5392 option_hdr.type = (uint16_t)option_id;
5393 option_hdr.value_length = (uint16_t)size;
5394 memcpy(*opt_ptrp, &option_hdr, 4);
5395 *opt_ptrp += 4;
5396
5397 memcpy(*opt_ptrp, &optval->custom_binaryval.pen, sizeof(uint32_t));
5398 *opt_ptrp += sizeof(uint32_t);
5399
5400 memcpy(*opt_ptrp, optval->custom_binaryval.data.custom_data, optval->custom_binaryval.data.custom_data_len);
5401 *opt_ptrp += optval->custom_binaryval.data.custom_data_len;
5402
5403 /* put padding (if any) */
5404 pad = WS_PADDING_TO_4(size)((4U - ((size) % 4U)) % 4U);
5405 if (pad != 0) {
5406 memset(*opt_ptrp, 0, pad);
5407 *opt_ptrp += pad;
5408 }
5409 break;
5410 case OPT_NS_DNSIP4ADDR3:
5411 option_hdr.type = (uint16_t)option_id;
5412 option_hdr.value_length = 4;
5413 memcpy(*opt_ptrp, &option_hdr, 4);
5414 *opt_ptrp += 4;
5415
5416 memcpy(*opt_ptrp, &optval->ipv4val, 4);
5417 *opt_ptrp += 4;
5418 break;
5419 case OPT_NS_DNSIP6ADDR4:
5420 option_hdr.type = (uint16_t)option_id;
5421 option_hdr.value_length = 16;
5422 memcpy(*opt_ptrp, &option_hdr, 4);
5423 *opt_ptrp += 4;
5424
5425 memcpy(*opt_ptrp, &optval->ipv6val, 16);
5426 *opt_ptrp += 16;
5427 break;
5428 default:
5429 /* Unknown options - size by datatype? */
5430 break;
5431 }
5432 return true1; /* we always succeed */
5433}
5434
5435static void
5436put_nrb_options(wtap_dumper *wdh _U___attribute__((unused)), wtap_block_t nrb, uint8_t *opt_ptr)
5437{
5438 struct pcapng_option option_hdr;
5439
5440 wtap_block_foreach_option(nrb, put_nrb_option, &opt_ptr);
5441
5442 /* Put end of options */
5443 option_hdr.type = OPT_EOFOPT0;
5444 option_hdr.value_length = 0;
5445 memcpy(opt_ptr, &option_hdr, 4);
5446}
5447
5448static bool_Bool
5449pcapng_write_name_resolution_block(wtap_dumper *wdh, wtap_block_t sdata, int *err)
5450{
5451 pcapng_block_header_t bh;
5452 pcapng_name_resolution_block_t nrb;
5453 wtapng_nrb_mandatory_t *mand_data = (wtapng_nrb_mandatory_t *)wtap_block_get_mandatory_data(sdata);
5454 uint32_t options_size;
5455 size_t max_rec_data_size;
5456 uint8_t *block_data;
5457 uint32_t block_off;
5458 size_t hostnamelen;
5459 uint16_t namelen;
5460 uint32_t tot_rec_len;
5461 hashipv4_t *ipv4_hash_list_entry;
5462 hashipv6_t *ipv6_hash_list_entry;
5463 int i;
5464
5465 if (!mand_data) {
5466 /*
5467 * No name/address pairs to write.
5468 * XXX - what if we have options?
5469 */
5470 return true1;
5471 }
5472
5473 /* Calculate the space needed for options. */
5474 options_size = pcapng_compute_options_size(sdata, compute_nrb_option_size);
5475
5476 /*
5477 * Make sure we can fit at least one maximum-sized record, plus
5478 * an end-of-records record, plus the options, into a maximum-sized
5479 * block.
5480 *
5481 * That requires that there be enough space for the block header
5482 * (8 bytes), a maximum-sized record (2 bytes of record type, 2
5483 * bytes of record value length, 65535 bytes of record value,
5484 * and 1 byte of padding), an end-of-records record (4 bytes),
5485 * the options (options_size bytes), and the block trailer (4
5486 * bytes).
5487 */
5488 if (8 + 2 + 2 + 65535 + 1 + 4 + options_size + 4 > NRES_BLOCK_MAX_SIZE(1024*1024)) {
5489 /*
5490 * XXX - we can't even fit the options in the largest NRB size
5491 * we're willing to write and still have room enough for a
5492 * maximum-sized record. Just discard the information for now.
5493 */
5494 return true1;
5495 }
5496
5497 /*
5498 * Allocate a buffer for the largest block we'll write.
5499 */
5500 block_data = (uint8_t *)g_malloc(NRES_BLOCK_MAX_SIZE(1024*1024));
5501
5502 /*
5503 * Calculate the maximum amount of record data we'll be able to
5504 * fit into such a block, after taking into account the block header
5505 * (8 bytes), the end-of-records record (4 bytes), the options
5506 * (options_size bytes), and the block trailer (4 bytes).
5507 */
5508 max_rec_data_size = NRES_BLOCK_MAX_SIZE(1024*1024) - (8 + 4 + options_size + 4);
5509
5510 block_off = 8; /* block type + block total length */
5511 bh.block_type = BLOCK_TYPE_NRB0x00000004;
5512 bh.block_total_length = 12; /* block header + block trailer */
5513
5514 /*
5515 * Write out the IPv4 resolved addresses, if any.
5516 */
5517 if (mand_data->ipv4_addr_list){
5518 i = 0;
5519 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(mand_data->ipv4_addr_list, i);
5520 while(ipv4_hash_list_entry != NULL((void*)0)){
5521
5522 nrb.record_type = NRES_IP4RECORD1;
5523 hostnamelen = strlen(ipv4_hash_list_entry->name);
5524 if (hostnamelen > (UINT16_MAX(65535) - 4) - 1) {
5525 /*
5526 * This won't fit in the largest possible NRB record;
5527 * discard it.
5528 */
5529 i++;
5530 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(mand_data->ipv4_addr_list, i);
5531 continue;
5532 }
5533 namelen = (uint16_t)(hostnamelen + 1);
5534 nrb.record_len = 4 + namelen; /* 4 bytes IPv4 address length */
5535 /* 2 bytes record type, 2 bytes length field */
5536 tot_rec_len = 4 + nrb.record_len + WS_PADDING_TO_4(nrb.record_len)((4U - ((nrb.record_len) % 4U)) % 4U);
5537
5538 if (block_off + tot_rec_len > max_rec_data_size) {
5539 /*
5540 * This record would overflow our maximum size for Name
5541 * Resolution Blocks; write out all the records we created
5542 * before it, and start a new NRB.
5543 */
5544
5545 /* Append the end-of-records record */
5546 memset(block_data + block_off, 0, 4);
5547 block_off += 4;
5548 bh.block_total_length += 4;
5549
5550 /*
5551 * Put the options into the block.
5552 */
5553 put_nrb_options(wdh, sdata, block_data + block_off);
5554 block_off += options_size;
5555 bh.block_total_length += options_size;
5556
5557 /* Copy the block header. */
5558 memcpy(block_data, &bh, sizeof(bh));
5559
5560 /* Copy the block trailer. */
5561 memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
5562
5563 ws_debug("Write bh.block_total_length bytes %d, block_off %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5564, __func__, "Write bh.block_total_length bytes %d, block_off %u"
, bh.block_total_length, block_off); } } while (0)
5564 bh.block_total_length, block_off)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5564, __func__, "Write bh.block_total_length bytes %d, block_off %u"
, bh.block_total_length, block_off); } } while (0)
;
5565
5566 if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
5567 g_free(block_data);
5568 return false0;
5569 }
5570
5571 /*Start a new NRB */
5572 block_off = 8; /* block type + block total length */
5573 bh.block_type = BLOCK_TYPE_NRB0x00000004;
5574 bh.block_total_length = 12; /* block header + block trailer */
5575 }
5576
5577 bh.block_total_length += tot_rec_len;
5578 memcpy(block_data + block_off, &nrb, sizeof(nrb));
5579 block_off += 4;
5580 memcpy(block_data + block_off, &(ipv4_hash_list_entry->addr), 4);
5581 block_off += 4;
5582 memcpy(block_data + block_off, ipv4_hash_list_entry->name, namelen);
5583 block_off += namelen;
5584 memset(block_data + block_off, 0, WS_PADDING_TO_4(namelen)((4U - ((namelen) % 4U)) % 4U));
5585 block_off += WS_PADDING_TO_4(namelen)((4U - ((namelen) % 4U)) % 4U);
5586 ws_debug("added IPv4 record for %s", ipv4_hash_list_entry->name)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5586, __func__, "added IPv4 record for %s", ipv4_hash_list_entry
->name); } } while (0)
;
5587
5588 i++;
5589 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(mand_data->ipv4_addr_list, i);
5590 }
5591 }
5592
5593 if (mand_data->ipv6_addr_list){
5594 i = 0;
5595 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(mand_data->ipv6_addr_list, i);
5596 while(ipv6_hash_list_entry != NULL((void*)0)){
5597
5598 nrb.record_type = NRES_IP6RECORD2;
5599 hostnamelen = strlen(ipv6_hash_list_entry->name);
5600 if (hostnamelen > (UINT16_MAX(65535) - 16) - 1) {
5601 /*
5602 * This won't fit in the largest possible NRB record;
5603 * discard it.
5604 */
5605 i++;
5606 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(mand_data->ipv6_addr_list, i);
5607 continue;
5608 }
5609 namelen = (uint16_t)(hostnamelen + 1);
5610 nrb.record_len = 16 + namelen; /* 16 bytes IPv6 address length */
5611 /* 2 bytes record type, 2 bytes length field */
5612 tot_rec_len = 4 + nrb.record_len + WS_PADDING_TO_4(nrb.record_len)((4U - ((nrb.record_len) % 4U)) % 4U);
5613
5614 if (block_off + tot_rec_len > max_rec_data_size) {
5615 /*
5616 * This record would overflow our maximum size for Name
5617 * Resolution Blocks; write out all the records we created
5618 * before it, and start a new NRB.
5619 */
5620
5621 /* Append the end-of-records record */
5622 memset(block_data + block_off, 0, 4);
5623 block_off += 4;
5624 bh.block_total_length += 4;
5625
5626 /*
5627 * Put the options into the block.
5628 */
5629 put_nrb_options(wdh, sdata, block_data + block_off);
5630 block_off += options_size;
5631 bh.block_total_length += options_size;
5632
5633 /* Copy the block header. */
5634 memcpy(block_data, &bh, sizeof(bh));
5635
5636 /* Copy the block trailer. */
5637 memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
5638
5639 ws_debug("write bh.block_total_length bytes %d, block_off %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5640, __func__, "write bh.block_total_length bytes %d, block_off %u"
, bh.block_total_length, block_off); } } while (0)
5640 bh.block_total_length, block_off)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5640, __func__, "write bh.block_total_length bytes %d, block_off %u"
, bh.block_total_length, block_off); } } while (0)
;
5641
5642 if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
5643 g_free(block_data);
5644 return false0;
5645 }
5646
5647 /*Start a new NRB */
5648 block_off = 8; /* block type + block total length */
5649 bh.block_type = BLOCK_TYPE_NRB0x00000004;
5650 bh.block_total_length = 12; /* block header + block trailer */
5651 }
5652
5653 bh.block_total_length += tot_rec_len;
5654 memcpy(block_data + block_off, &nrb, sizeof(nrb));
5655 block_off += 4;
5656 memcpy(block_data + block_off, &(ipv6_hash_list_entry->addr), 16);
5657 block_off += 16;
5658 memcpy(block_data + block_off, ipv6_hash_list_entry->name, namelen);
5659 block_off += namelen;
5660 memset(block_data + block_off, 0, WS_PADDING_TO_4(namelen)((4U - ((namelen) % 4U)) % 4U));
5661 block_off += WS_PADDING_TO_4(namelen)((4U - ((namelen) % 4U)) % 4U);
5662 ws_debug("added IPv6 record for %s", ipv6_hash_list_entry->name)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5662, __func__, "added IPv6 record for %s", ipv6_hash_list_entry
->name); } } while (0)
;
5663
5664 i++;
5665 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(mand_data->ipv6_addr_list, i);
5666 }
5667 }
5668
5669 /* Append the end-of-records record */
5670 memset(block_data + block_off, 0, 4);
5671 block_off += 4;
5672 bh.block_total_length += 4;
5673
5674 /*
5675 * Put the options into the block.
5676 */
5677 put_nrb_options(wdh, sdata, block_data + block_off);
5678 block_off += options_size;
5679 bh.block_total_length += options_size;
5680
5681 /* Copy the block header. */
5682 memcpy(block_data, &bh, sizeof(bh));
5683
5684 /* Copy the block trailer. */
5685 memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
5686
5687 ws_debug("Write bh.block_total_length bytes %d, block_off %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5688, __func__, "Write bh.block_total_length bytes %d, block_off %u"
, bh.block_total_length, block_off); } } while (0)
5688 bh.block_total_length, block_off)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5688, __func__, "Write bh.block_total_length bytes %d, block_off %u"
, bh.block_total_length, block_off); } } while (0)
;
5689
5690 if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
5691 g_free(block_data);
5692 return false0;
5693 }
5694
5695 g_free(block_data);
5696
5697 return true1;
5698}
5699
5700static uint32_t compute_isb_option_size(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type _U___attribute__((unused)), wtap_optval_t *optval _U___attribute__((unused)))
5701{
5702 uint32_t size;
5703
5704 switch(option_id)
5705 {
5706 case OPT_ISB_STARTTIME2:
5707 case OPT_ISB_ENDTIME3:
5708 size = 8;
5709 break;
5710 case OPT_ISB_IFRECV4:
5711 case OPT_ISB_IFDROP5:
5712 case OPT_ISB_FILTERACCEPT6:
5713 case OPT_ISB_OSDROP7:
5714 case OPT_ISB_USRDELIV8:
5715 size = 8;
5716 break;
5717 default:
5718 /* Unknown options - size by datatype? */
5719 size = 0;
5720 break;
5721 }
5722 return size;
5723}
5724
5725static bool_Bool write_wtap_isb_option(wtap_dumper *wdh, wtap_block_t block _U___attribute__((unused)),
5726 unsigned option_id,
5727 wtap_opttype_e option_type _U___attribute__((unused)),
5728 wtap_optval_t *optval,
5729 int *err, char **err_info _U___attribute__((unused)))
5730{
5731 switch(option_id)
5732 {
5733 case OPT_ISB_STARTTIME2:
5734 case OPT_ISB_ENDTIME3:
5735 if (!pcapng_write_timestamp_option(wdh, option_id, optval, err))
5736 return false0;
5737 break;
5738 case OPT_ISB_IFRECV4:
5739 case OPT_ISB_IFDROP5:
5740 case OPT_ISB_FILTERACCEPT6:
5741 case OPT_ISB_OSDROP7:
5742 case OPT_ISB_USRDELIV8:
5743 if (!pcapng_write_uint64_option(wdh, option_id, optval, err))
5744 return false0;
5745 break;
5746 default:
5747 /* Unknown options - write by datatype? */
5748 break;
5749 }
5750 return true1; /* success */
5751}
5752
5753static bool_Bool
5754pcapng_write_interface_statistics_block(wtap_dumper *wdh,
5755 wtap_block_t if_stats,
5756 int *err, char **err_info)
5757{
5758 uint32_t block_content_length;
5759 pcapng_interface_statistics_block_t isb;
5760 uint32_t options_size;
5761 wtapng_if_stats_mandatory_t* mand_data = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats);
5762
5763 ws_debug("entering function")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5763, __func__, "entering function"); } } while (0)
;
5764
5765 /* Compute size of all the options */
5766 options_size = pcapng_compute_options_size(if_stats, compute_isb_option_size);
5767
5768 /* write block header */
5769 block_content_length = (uint32_t)sizeof(isb) + options_size;
5770 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_ISB0x00000005, block_content_length,
5771 err))
5772 return false0;
5773
5774 /* write block fixed content */
5775 isb.interface_id = mand_data->interface_id;
5776 isb.timestamp_high = mand_data->ts_high;
5777 isb.timestamp_low = mand_data->ts_low;
5778
5779 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
5780 return false0;
5781
5782 /* Write options */
5783 if (options_size != 0) {
5784 if (!pcapng_write_options(wdh, OPT_SECTION_BYTE_ORDER,
5785 if_stats, write_wtap_isb_option,
5786 err, err_info))
5787 return false0;
5788 }
5789
5790 /* write block footer */
5791 return pcapng_write_block_footer(wdh, block_content_length, err);
5792}
5793
5794static uint32_t compute_idb_option_size(wtap_block_t block _U___attribute__((unused)), unsigned option_id, wtap_opttype_e option_type _U___attribute__((unused)), wtap_optval_t *optval)
5795{
5796 uint32_t size;
5797
5798 switch(option_id)
5799 {
5800 case OPT_IDB_NAME2:
5801 case OPT_IDB_DESCRIPTION3:
5802 case OPT_IDB_OS12:
5803 case OPT_IDB_HARDWARE15:
5804 size = pcapng_compute_string_option_size(optval);
5805 break;
5806 case OPT_IDB_SPEED8:
5807 size = 8;
5808 break;
5809 case OPT_IDB_TSRESOL9:
5810 size = 1;
5811 break;
5812 case OPT_IDB_FILTER11:
5813 size = pcapng_compute_if_filter_option_size(optval);
5814 break;
5815 case OPT_IDB_FCSLEN13:
5816 size = 1;
5817 break;
5818 case OPT_IDB_TSOFFSET14:
5819 /*
5820 * The time stamps handed to us when writing a file are
5821 * absolute time staps, so the time stamp offset is
5822 * zero.
5823 *
5824 * We do not adjust them when writing, so we should not
5825 * write if_tsoffset options; that is interpreted as
5826 * the offset is zero, i.e. the time stamps in the file
5827 * are absolute.
5828 */
5829 size = 0;
5830 break;
5831 default:
5832 /* Unknown options - size by datatype? */
5833 size = 0;
5834 break;
5835 }
5836 return size;
5837}
5838
5839static bool_Bool write_wtap_idb_option(wtap_dumper *wdh, wtap_block_t block _U___attribute__((unused)),
5840 unsigned option_id,
5841 wtap_opttype_e option_type _U___attribute__((unused)),
5842 wtap_optval_t *optval,
5843 int *err, char **err_info)
5844{
5845 switch(option_id)
5846 {
5847 case OPT_IDB_NAME2:
5848 case OPT_IDB_DESCRIPTION3:
5849 case OPT_IDB_OS12:
5850 case OPT_IDB_HARDWARE15:
5851 if (!pcapng_write_string_option(wdh, OPT_SECTION_BYTE_ORDER,
5852 option_id, optval, err, err_info))
5853 return false0;
5854 break;
5855 case OPT_IDB_SPEED8:
5856 if (!pcapng_write_uint64_option(wdh, option_id, optval, err))
5857 return false0;
5858 break;
5859 case OPT_IDB_TSRESOL9:
5860 if (!pcapng_write_uint8_option(wdh, option_id, optval, err))
5861 return false0;
5862 break;
5863 case OPT_IDB_FILTER11:
5864 if (!pcapng_write_if_filter_option(wdh, option_id, optval, err))
5865 return false0;
5866 break;
5867 case OPT_IDB_FCSLEN13:
5868 if (!pcapng_write_uint8_option(wdh, option_id, optval, err))
5869 return false0;
5870 break;
5871 case OPT_IDB_TSOFFSET14:
5872 /*
5873 * As noted above, we discard these.
5874 */
5875 break;
5876 default:
5877 /* Unknown options - size by datatype? */
5878 break;
5879 }
5880 return true1;
5881}
5882
5883static bool_Bool
5884pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_block_t int_data,
5885 int *err, char **err_info)
5886{
5887 uint32_t block_content_length;
5888 pcapng_interface_description_block_t idb;
5889 uint32_t options_size;
5890 wtapng_if_descr_mandatory_t* mand_data = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
5891 int link_type;
5892
5893 ws_debug("encap = %d (%s), snaplen = %d",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5896, __func__, "encap = %d (%s), snaplen = %d", mand_data->
wtap_encap, wtap_encap_description(mand_data->wtap_encap),
mand_data->snap_len); } } while (0)
5894 mand_data->wtap_encap,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5896, __func__, "encap = %d (%s), snaplen = %d", mand_data->
wtap_encap, wtap_encap_description(mand_data->wtap_encap),
mand_data->snap_len); } } while (0)
5895 wtap_encap_description(mand_data->wtap_encap),do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5896, __func__, "encap = %d (%s), snaplen = %d", mand_data->
wtap_encap, wtap_encap_description(mand_data->wtap_encap),
mand_data->snap_len); } } while (0)
5896 mand_data->snap_len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5896, __func__, "encap = %d (%s), snaplen = %d", mand_data->
wtap_encap, wtap_encap_description(mand_data->wtap_encap),
mand_data->snap_len); } } while (0)
;
5897
5898 link_type = wtap_wtap_encap_to_pcap_encap(mand_data->wtap_encap);
5899 if (link_type == -1) {
5900 if (!pcapng_encap_is_ft_specific(mand_data->wtap_encap)) {
5901 *err = WTAP_ERR_UNWRITABLE_ENCAP-8;
5902 return false0;
5903 }
5904 }
5905
5906 /* Compute size of all the options */
5907 options_size = pcapng_compute_options_size(int_data, compute_idb_option_size);
5908
5909 /* write block header */
5910 block_content_length = (uint32_t)sizeof(idb) + options_size;
5911 if (!pcapng_write_block_header(wdh, BLOCK_TYPE_IDB0x00000001, block_content_length,
5912 err))
5913 return false0;
5914
5915 /* write block fixed content */
5916 idb.linktype = link_type;
5917 idb.reserved = 0;
5918 idb.snaplen = mand_data->snap_len;
5919
5920 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
5921 return false0;
5922
5923 if (options_size != 0) {
5924 /* Write options */
5925 if (!pcapng_write_options(wdh, OPT_SECTION_BYTE_ORDER,
5926 int_data, write_wtap_idb_option,
5927 err, err_info))
5928 return false0;
5929 }
5930
5931 /* write block footer */
5932 return pcapng_write_block_footer(wdh, block_content_length, err);
5933}
5934
5935static bool_Bool pcapng_add_idb(wtap_dumper *wdh, wtap_block_t idb,
5936 int *err, char **err_info)
5937{
5938 wtap_block_t idb_copy;
5939
5940 /*
5941 * Add a copy of this IDB to our array of IDBs.
5942 */
5943 idb_copy = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
5944 wtap_block_copy(idb_copy, idb);
5945 g_array_append_val(wdh->interface_data, idb_copy)g_array_append_vals (wdh->interface_data, &(idb_copy),
1)
;
5946
5947 /*
5948 * And write it to the output file.
5949 */
5950 return pcapng_write_if_descr_block(wdh, idb_copy, err, err_info);
5951}
5952
5953static bool_Bool pcapng_write_internal_blocks(wtap_dumper *wdh, int *err)
5954{
5955
5956 /* Write (optional) Decryption Secrets Blocks that were collected while
5957 * reading packet blocks. */
5958 if (wdh->dsbs_growing) {
5959 for (unsigned i = wdh->dsbs_growing_written; i < wdh->dsbs_growing->len; i++) {
5960 ws_debug("writing DSB %u", i)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5960, __func__, "writing DSB %u", i); } } while (0)
;
5961 wtap_block_t dsb = g_array_index(wdh->dsbs_growing, wtap_block_t, i)(((wtap_block_t*) (void *) (wdh->dsbs_growing)->data) [
(i)])
;
5962 if (!pcapng_write_decryption_secrets_block(wdh, dsb, err)) {
5963 return false0;
5964 }
5965 ++wdh->dsbs_growing_written;
5966 }
5967 }
5968
5969 /* Write (optional) Sysdig Meta Event Blocks that were collected while
5970 * reading packet blocks. */
5971 if (wdh->mevs_growing) {
5972 for (unsigned i = wdh->mevs_growing_written; i < wdh->mevs_growing->len; i++) {
5973 ws_debug("writing Sysdig mev %u", i)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 5973, __func__, "writing Sysdig mev %u", i); } } while (0)
;
5974 wtap_block_t mev = g_array_index(wdh->mevs_growing, wtap_block_t, i)(((wtap_block_t*) (void *) (wdh->mevs_growing)->data) [
(i)])
;
5975 if (!pcapng_write_meta_event_block(wdh, mev, err)) {
5976 return false0;
5977 }
5978 ++wdh->mevs_growing_written;
5979 }
5980 }
5981
5982 /* Write any hostname resolution info from wtap_dump_set_addrinfo_list() */
5983 if (!wtap_addrinfo_list_empty(wdh->addrinfo_lists)) {
5984 /*
5985 * XXX: get_addrinfo_list() returns a list of all known and used
5986 * resolved addresses, regardless of origin: existing NRBs, externally
5987 * resolved, DNS packet data, a hosts file, and manual host resolution
5988 * through the GUI. It does not include the source for each.
5989 *
5990 * If it did, we could instead create multiple NRBs, one for each
5991 * server (as the options can only be included once per block.)
5992 * Instead, we copy the options from the first already existing NRB
5993 * (if there is one), since some of the name resolutions may be
5994 * from that block.
5995 */
5996 wtap_block_t nrb;
5997 if (wdh->nrbs_growing && wdh->nrbs_growing->len) {
5998 nrb = wtap_block_make_copy(g_array_index(wdh->nrbs_growing, wtap_block_t, 0)(((wtap_block_t*) (void *) (wdh->nrbs_growing)->data) [
(0)])
);
5999 } else {
6000 nrb = wtap_block_create(WTAP_BLOCK_NAME_RESOLUTION);
6001 }
6002 wtapng_nrb_mandatory_t *mand_data = (wtapng_nrb_mandatory_t *)wtap_block_get_mandatory_data(nrb);
6003 mand_data->ipv4_addr_list = wdh->addrinfo_lists->ipv4_addr_list;
6004 mand_data->ipv6_addr_list = wdh->addrinfo_lists->ipv6_addr_list;
6005
6006 if (!pcapng_write_name_resolution_block(wdh, nrb, err)) {
6007 return false0;
6008 }
6009 mand_data->ipv4_addr_list = NULL((void*)0);
6010 mand_data->ipv6_addr_list = NULL((void*)0);
6011 wtap_block_unref(nrb);
6012 g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
6013 wdh->addrinfo_lists->ipv4_addr_list = NULL((void*)0);
6014 g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
6015 wdh->addrinfo_lists->ipv6_addr_list = NULL((void*)0);
6016 /* Since the addrinfo lists include information from existing NRBs,
6017 * avoid writing them to avoid duplication.
6018 *
6019 * XXX: Perhaps we don't want to include information from the NRBs
6020 * in get_addrinfo_list at all, so that we could write existing
6021 * NRBs as-is.
6022 *
6023 * This is still not well oriented for one-pass programs, where we
6024 * don't have addrinfo_lists until we've already written the
6025 * NRBs. We should not write both in such a situation. See bug 15502.
6026 */
6027 wtap_dump_discard_name_resolution(wdh);
6028 }
6029
6030 /* Write (optional) Name Resolution Blocks that were collected while
6031 * reading packet blocks. */
6032 if (wdh->nrbs_growing) {
6033 for (unsigned i = wdh->nrbs_growing_written; i < wdh->nrbs_growing->len; i++) {
6034 wtap_block_t nrb = g_array_index(wdh->nrbs_growing, wtap_block_t, i)(((wtap_block_t*) (void *) (wdh->nrbs_growing)->data) [
(i)])
;
6035 if (!pcapng_write_name_resolution_block(wdh, nrb, err)) {
6036 return false0;
6037 }
6038 ++wdh->nrbs_growing_written;
6039 }
6040 }
6041
6042 return true1;
6043}
6044
6045static bool_Bool pcapng_dump(wtap_dumper *wdh, const wtap_rec *rec,
6046 int *err, char **err_info)
6047{
6048 uint32_t block_type;
6049 pcapng_block_type_information_t* handler;
6050
6051 if (!pcapng_write_internal_blocks(wdh, err)) {
6052 return false0;
6053 }
6054
6055 ws_debug("encap = %d (%s) rec type = %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6058, __func__, "encap = %d (%s) rec type = %u", rec->rec_header
.packet_header.pkt_encap, wtap_encap_description(rec->rec_header
.packet_header.pkt_encap), rec->rec_type); } } while (0)
6056 rec->rec_header.packet_header.pkt_encap,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6058, __func__, "encap = %d (%s) rec type = %u", rec->rec_header
.packet_header.pkt_encap, wtap_encap_description(rec->rec_header
.packet_header.pkt_encap), rec->rec_type); } } while (0)
6057 wtap_encap_description(rec->rec_header.packet_header.pkt_encap),do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6058, __func__, "encap = %d (%s) rec type = %u", rec->rec_header
.packet_header.pkt_encap, wtap_encap_description(rec->rec_header
.packet_header.pkt_encap), rec->rec_type); } } while (0)
6058 rec->rec_type)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6058, __func__, "encap = %d (%s) rec type = %u", rec->rec_header
.packet_header.pkt_encap, wtap_encap_description(rec->rec_header
.packet_header.pkt_encap), rec->rec_type); } } while (0)
;
6059
6060 switch (rec->rec_type) {
6061
6062 case REC_TYPE_PACKET0:
6063 /* Write Simple Packet Block if appropriate, Enhanced Packet Block otherwise. */
6064 if (!(rec->presence_flags & WTAP_HAS_TS0x00000001) &&
6065 (!(rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004) || rec->rec_header.packet_header.interface_id == 0) &&
6066 (!(rec->presence_flags & WTAP_HAS_CAP_LEN0x00000002) || rec->rec_header.packet_header.len == rec->rec_header.packet_header.caplen) &&
6067 (rec->block == NULL((void*)0) || pcapng_compute_options_size(rec->block, compute_epb_option_size) == 0)) {
6068 block_type = BLOCK_TYPE_SPB0x00000003;
6069 }
6070 else {
6071 block_type = BLOCK_TYPE_EPB0x00000006;
6072 }
6073 break;
6074
6075 case REC_TYPE_FT_SPECIFIC_EVENT1:
6076 case REC_TYPE_FT_SPECIFIC_REPORT2:
6077 /*
6078 * Is this an event or report for our file type?
6079 */
6080 if (rec->rec_header.ft_specific_header.file_type_subtype != pcapng_file_type_subtype) {
6081 /*
6082 * No. We can't write that.
6083 */
6084 *err = WTAP_ERR_UNWRITABLE_REC_TYPE-24;
6085 *err_info = g_strdup_printf("%s records for \"%s\" files aren't supported for this file type",
6086 rec->rec_type_name,
6087 wtap_file_type_subtype_name(rec->rec_header.ft_specific_header.file_type_subtype));
6088 return false0;
6089 }
6090
6091 block_type = rec->rec_header.ft_specific_header.record_type;
6092 break;
6093
6094 case REC_TYPE_SYSCALL3:
6095 block_type = rec->rec_header.syscall_header.record_type;
6096 break;
6097
6098 case REC_TYPE_SYSTEMD_JOURNAL_EXPORT4:
6099 block_type = BLOCK_TYPE_SYSTEMD_JOURNAL_EXPORT0x00000009;
6100 break;
6101
6102 case REC_TYPE_CUSTOM_BLOCK5:
6103 {
6104 /* Don't write anything we are not supposed to. */
6105 if (!rec->rec_header.custom_block_header.copy_allowed) {
6106 return true1;
6107 }
6108 block_type = BLOCK_TYPE_CB_COPY0x00000BAD;
6109 break;
6110 }
6111
6112 default:
6113 /* We don't support writing this record type. */
6114 *err = WTAP_ERR_UNWRITABLE_REC_TYPE-24;
6115 *err_info = wtap_unwritable_rec_type_err_string(rec);
6116 return false0;
6117 }
6118
6119 /*
6120 * Do we have a handler for this block type?
6121 */
6122 handler = (pcapng_block_type_information_t*)g_hash_table_lookup(block_handlers,
6123 GUINT_TO_POINTER(block_type)((gpointer) (gulong) (block_type)));
6124 if (handler == NULL((void*)0)) {
6125 /* No. We can't write that. */
6126 *err = WTAP_ERR_UNWRITABLE_REC_TYPE-24;
6127 *err_info = g_strdup_printf("Pcapng blocks of type 0x%8x aren't supported",
6128 rec->rec_header.ft_specific_header.record_type);
6129 return false0;
6130 }
6131
6132 /* Yes. Call it to write out this record. */
6133 return handler->writer(wdh, rec, err, err_info);
6134}
6135
6136/*
6137 * Write block header.
6138 */
6139bool_Bool
6140pcapng_write_block_header(wtap_dumper *wdh, uint32_t block_type,
6141 uint32_t block_content_length, int *err)
6142{
6143 pcapng_block_header_t bh;
6144
6145 bh.block_type = block_type;
6146 /*
6147 * Total block length is the length of the header plus the length
6148 * of the block content (which is padded to a multiple of 4 bytes)
6149 * plus the length of the trailer.
6150 */
6151 bh.block_total_length = (uint32_t)sizeof(pcapng_block_header_t) + block_content_length + 4;
6152 ws_debug("Total len %u", bh.block_total_length)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6152, __func__, "Total len %u", bh.block_total_length); } }
while (0)
;
6153 return wtap_dump_file_write(wdh, &bh, sizeof bh, err);
6154}
6155
6156/*
6157 * Write block footer.
6158 */
6159bool_Bool
6160pcapng_write_block_footer(wtap_dumper *wdh, uint32_t block_content_length,
6161 int *err)
6162{
6163 uint32_t bf;
6164
6165 bf = (uint32_t)sizeof(pcapng_block_header_t) + block_content_length + 4;
6166 return wtap_dump_file_write(wdh, &bf, sizeof bf, err);
6167}
6168
6169/* Finish writing to a dump file.
6170 Returns true on success, false on failure. */
6171static bool_Bool pcapng_dump_finish(wtap_dumper *wdh, int *err, char **err_info)
6172{
6173 unsigned i, j;
6174
6175 /* Flush any hostname resolution or decryption secrets info we may have */
6176 if (!pcapng_write_internal_blocks(wdh, err)) {
6177 return false0;
6178 }
6179
6180 for (i = 0; i < wdh->interface_data->len; i++) {
6181
6182 /* Get the interface description */
6183 wtap_block_t int_data;
6184 wtapng_if_descr_mandatory_t *int_data_mand;
6185
6186 int_data = g_array_index(wdh->interface_data, wtap_block_t, i)(((wtap_block_t*) (void *) (wdh->interface_data)->data)
[(i)])
;
6187 int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
6188
6189 for (j = 0; j < int_data_mand->num_stat_entries; j++) {
6190 wtap_block_t if_stats;
6191
6192 if_stats = g_array_index(int_data_mand->interface_statistics, wtap_block_t, j)(((wtap_block_t*) (void *) (int_data_mand->interface_statistics
)->data) [(j)])
;
6193 ws_debug("write ISB for interface %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6194, __func__, "write ISB for interface %u", ((wtapng_if_stats_mandatory_t
*)wtap_block_get_mandatory_data(if_stats))->interface_id);
} } while (0)
6194 ((wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats))->interface_id)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6194, __func__, "write ISB for interface %u", ((wtapng_if_stats_mandatory_t
*)wtap_block_get_mandatory_data(if_stats))->interface_id);
} } while (0)
;
6195 if (!pcapng_write_interface_statistics_block(wdh, if_stats,
6196 err, err_info)) {
6197 return false0;
6198 }
6199 }
6200 }
6201
6202 ws_debug("leaving function")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6202, __func__, "leaving function"); } } while (0)
;
6203 return true1;
6204}
6205
6206/* Returns true on success, false on failure; sets "*err" to an error code on
6207 failure */
6208static bool_Bool
6209pcapng_dump_open(wtap_dumper *wdh, int *err, char **err_info)
6210{
6211 unsigned i;
6212
6213 ws_debug("entering function")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6213, __func__, "entering function"); } } while (0)
;
6214 /* This is a pcapng file */
6215 wdh->subtype_add_idb = pcapng_add_idb;
6216 wdh->subtype_write = pcapng_dump;
6217 wdh->subtype_finish = pcapng_dump_finish;
6218
6219 /* write the section header block */
6220 if (!pcapng_write_section_header_block(wdh, err, err_info)) {
6221 return false0;
6222 }
6223 ws_debug("wrote section header block.")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6223, __func__, "wrote section header block."); } } while (
0)
;
6224
6225 /* Write the Interface description blocks */
6226 ws_debug("Number of IDBs to write (number of interfaces) %u",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6227, __func__, "Number of IDBs to write (number of interfaces) %u"
, wdh->interface_data->len); } } while (0)
6227 wdh->interface_data->len)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6227, __func__, "Number of IDBs to write (number of interfaces) %u"
, wdh->interface_data->len); } } while (0)
;
6228
6229 for (i = 0; i < wdh->interface_data->len; i++) {
6230
6231 /* Get the interface description */
6232 wtap_block_t idb;
6233
6234 idb = g_array_index(wdh->interface_data, wtap_block_t, i)(((wtap_block_t*) (void *) (wdh->interface_data)->data)
[(i)])
;
6235
6236 if (!pcapng_write_if_descr_block(wdh, idb, err, err_info)) {
6237 return false0;
6238 }
6239
6240 }
6241
6242 /* Write (optional) fixed Decryption Secrets Blocks. */
6243 if (wdh->dsbs_initial) {
6244 for (i = 0; i < wdh->dsbs_initial->len; i++) {
6245 wtap_block_t dsb = g_array_index(wdh->dsbs_initial, wtap_block_t, i)(((wtap_block_t*) (void *) (wdh->dsbs_initial)->data) [
(i)])
;
6246 if (!pcapng_write_decryption_secrets_block(wdh, dsb, err)) {
6247 return false0;
6248 }
6249 }
6250 }
6251
6252 return true1;
6253}
6254
6255/* Returns 0 if we could write the specified encapsulation type,
6256 an error indication otherwise. */
6257static int pcapng_dump_can_write_encap(int wtap_encap)
6258{
6259 ws_debug("encap = %d (%s)",do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6261, __func__, "encap = %d (%s)", wtap_encap, wtap_encap_description
(wtap_encap)); } } while (0)
6260 wtap_encap,do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6261, __func__, "encap = %d (%s)", wtap_encap, wtap_encap_description
(wtap_encap)); } } while (0)
6261 wtap_encap_description(wtap_encap))do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/pcapng.c"
, 6261, __func__, "encap = %d (%s)", wtap_encap, wtap_encap_description
(wtap_encap)); } } while (0)
;
6262
6263 /* Per-packet encapsulation is supported. */
6264 if (wtap_encap == WTAP_ENCAP_PER_PACKET-1)
6265 return 0;
6266
6267 /* No encapsulation type (yet) is supported. */
6268 if (wtap_encap == WTAP_ENCAP_NONE-2)
6269 return 0;
6270
6271 /* Is it a filetype-specific encapsulation that we support? */
6272 if (pcapng_encap_is_ft_specific(wtap_encap)) {
6273 return 0;
6274 }
6275
6276 /* Make sure we can figure out this DLT type */
6277 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
6278 return WTAP_ERR_UNWRITABLE_ENCAP-8;
6279
6280 return 0;
6281}
6282
6283/*
6284 * Returns true if the specified encapsulation type is filetype-specific
6285 * and one that we support.
6286 */
6287bool_Bool pcapng_encap_is_ft_specific(int encap)
6288{
6289 switch (encap) {
6290 case WTAP_ENCAP_SYSTEMD_JOURNAL203:
6291 return true1;
6292 }
6293 return false0;
6294}
6295
6296/*
6297 * pcapng supports several block types, and supports more than one
6298 * of them.
6299 *
6300 * It also supports comments for many block types, as well as other
6301 * option types.
6302 */
6303
6304/* Options for section blocks. */
6305static const struct supported_option_type section_block_options_supported[] = {
6306 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6307 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6308 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6309 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6310 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED },
6311 { OPT_SHB_HARDWARE2, ONE_OPTION_SUPPORTED },
6312 { OPT_SHB_USERAPPL4, ONE_OPTION_SUPPORTED }
6313};
6314
6315/* Options for interface blocks. */
6316static const struct supported_option_type interface_block_options_supported[] = {
6317 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6318 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6319 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6320 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6321 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED },
6322 { OPT_IDB_NAME2, ONE_OPTION_SUPPORTED },
6323 { OPT_IDB_DESCRIPTION3, ONE_OPTION_SUPPORTED },
6324 { OPT_IDB_IP4ADDR4, MULTIPLE_OPTIONS_SUPPORTED },
6325 { OPT_IDB_IP6ADDR5, MULTIPLE_OPTIONS_SUPPORTED },
6326 { OPT_IDB_MACADDR6, ONE_OPTION_SUPPORTED },
6327 { OPT_IDB_EUIADDR7, ONE_OPTION_SUPPORTED },
6328 { OPT_IDB_SPEED8, ONE_OPTION_SUPPORTED },
6329 { OPT_IDB_TSRESOL9, ONE_OPTION_SUPPORTED },
6330 { OPT_IDB_TZONE10, ONE_OPTION_SUPPORTED },
6331 { OPT_IDB_FILTER11, ONE_OPTION_SUPPORTED },
6332 { OPT_IDB_OS12, ONE_OPTION_SUPPORTED },
6333 { OPT_IDB_FCSLEN13, ONE_OPTION_SUPPORTED },
6334 { OPT_IDB_TSOFFSET14, ONE_OPTION_SUPPORTED },
6335 { OPT_IDB_HARDWARE15, ONE_OPTION_SUPPORTED },
6336 { OPT_IDB_TXSPEED16, ONE_OPTION_SUPPORTED },
6337 { OPT_IDB_RXSPEED17, ONE_OPTION_SUPPORTED },
6338 { OPT_IDB_IANA_TZNAME18, ONE_OPTION_SUPPORTED }
6339};
6340
6341/* Options for name resolution blocks. */
6342static const struct supported_option_type name_resolution_block_options_supported[] = {
6343 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6344 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6345 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6346 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6347 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED },
6348 { OPT_NS_DNSNAME2, ONE_OPTION_SUPPORTED },
6349 { OPT_NS_DNSIP4ADDR3, ONE_OPTION_SUPPORTED },
6350 { OPT_NS_DNSIP6ADDR4, ONE_OPTION_SUPPORTED }
6351};
6352
6353/* Options for interface statistics blocks. */
6354static const struct supported_option_type interface_statistics_block_options_supported[] = {
6355 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6356 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6357 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6358 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6359 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED },
6360 { OPT_ISB_STARTTIME2, ONE_OPTION_SUPPORTED },
6361 { OPT_ISB_ENDTIME3, ONE_OPTION_SUPPORTED },
6362 { OPT_ISB_IFRECV4, ONE_OPTION_SUPPORTED },
6363 { OPT_ISB_IFDROP5, ONE_OPTION_SUPPORTED },
6364 { OPT_ISB_FILTERACCEPT6, ONE_OPTION_SUPPORTED },
6365 { OPT_ISB_OSDROP7, ONE_OPTION_SUPPORTED },
6366 { OPT_ISB_USRDELIV8, ONE_OPTION_SUPPORTED }
6367};
6368
6369/* Options for decryption secrets blocks. */
6370static const struct supported_option_type decryption_secrets_block_options_supported[] = {
6371 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6372 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6373 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6374 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6375 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
6376};
6377
6378/* Options for meta event blocks. */
6379static const struct supported_option_type meta_events_block_options_supported[] = {
6380 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6381 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6382 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6383 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6384 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
6385};
6386
6387/* Options for packet blocks. */
6388static const struct supported_option_type packet_block_options_supported[] = {
6389 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6390 { OPT_PKT_FLAGS2, ONE_OPTION_SUPPORTED },
6391 { OPT_PKT_HASH3, MULTIPLE_OPTIONS_SUPPORTED },
6392 { OPT_PKT_DROPCOUNT4, ONE_OPTION_SUPPORTED },
6393 { OPT_PKT_PACKETID5, ONE_OPTION_SUPPORTED },
6394 { OPT_PKT_QUEUE6, ONE_OPTION_SUPPORTED },
6395 { OPT_PKT_VERDICT7, MULTIPLE_OPTIONS_SUPPORTED },
6396 { OPT_PKT_PROCIDTHRDID8, ONE_OPTION_SUPPORTED },
6397 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6398 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6399 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6400 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
6401};
6402
6403/* Options for file-type-specific reports. */
6404static const struct supported_option_type ft_specific_report_block_options_supported[] = {
6405 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6406 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6407 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6408 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6409 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
6410};
6411
6412/* Options for file-type-specific event. */
6413static const struct supported_option_type ft_specific_event_block_options_supported[] = {
6414 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6415 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6416 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6417 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6418 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
6419};
6420
6421/* Options for systemd journal entry. */
6422static const struct supported_option_type systemd_journal_export_block_options_supported[] = {
6423 { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED },
6424 { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED },
6425 { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED },
6426 { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED },
6427 { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED }
6428};
6429
6430static const struct supported_block_type pcapng_blocks_supported[] = {
6431 /* Multiple sections. */
6432 { WTAP_BLOCK_SECTION, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(section_block_options_supported)(sizeof (section_block_options_supported) / sizeof (section_block_options_supported
)[0]), section_block_options_supported
},
6433
6434 /* Multiple interfaces. */
6435 { WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported)(sizeof (interface_block_options_supported) / sizeof (interface_block_options_supported
)[0]), interface_block_options_supported
},
6436
6437 /* Multiple blocks of name resolution information */
6438 { WTAP_BLOCK_NAME_RESOLUTION, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(name_resolution_block_options_supported)(sizeof (name_resolution_block_options_supported) / sizeof (name_resolution_block_options_supported
)[0]), name_resolution_block_options_supported
},
6439
6440 /* Multiple blocks of interface statistics. */
6441 { WTAP_BLOCK_IF_STATISTICS, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_statistics_block_options_supported)(sizeof (interface_statistics_block_options_supported) / sizeof
(interface_statistics_block_options_supported)[0]), interface_statistics_block_options_supported
},
6442
6443 /* Multiple blocks of decryption secrets. */
6444 { WTAP_BLOCK_DECRYPTION_SECRETS, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(decryption_secrets_block_options_supported)(sizeof (decryption_secrets_block_options_supported) / sizeof
(decryption_secrets_block_options_supported)[0]), decryption_secrets_block_options_supported
},
6445
6446 /* Multiple blocks of meta evens.. */
6447 { WTAP_BLOCK_META_EVENT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(meta_events_block_options_supported)(sizeof (meta_events_block_options_supported) / sizeof (meta_events_block_options_supported
)[0]), meta_events_block_options_supported
},
6448
6449 /* And, obviously, multiple packets. */
6450 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(packet_block_options_supported)(sizeof (packet_block_options_supported) / sizeof (packet_block_options_supported
)[0]), packet_block_options_supported
},
6451
6452 /* Multiple file-type specific reports (including local ones). */
6453 { WTAP_BLOCK_FT_SPECIFIC_REPORT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_report_block_options_supported)(sizeof (ft_specific_report_block_options_supported) / sizeof
(ft_specific_report_block_options_supported)[0]), ft_specific_report_block_options_supported
},
6454
6455 /* Multiple file-type specific events (including local ones). */
6456 { WTAP_BLOCK_FT_SPECIFIC_EVENT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_event_block_options_supported)(sizeof (ft_specific_event_block_options_supported) / sizeof (
ft_specific_event_block_options_supported)[0]), ft_specific_event_block_options_supported
},
6457
6458 /* Multiple systemd journal export records. */
6459 { WTAP_BLOCK_SYSTEMD_JOURNAL_EXPORT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(systemd_journal_export_block_options_supported)(sizeof (systemd_journal_export_block_options_supported) / sizeof
(systemd_journal_export_block_options_supported)[0]), systemd_journal_export_block_options_supported
},
6460
6461 /* Multiple custom blocks. */
6462 { WTAP_BLOCK_CUSTOM, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED0, ((void*)0) },
6463};
6464
6465static const struct file_type_subtype_info wireshark_pcapng_info = {
6466 "Wireshark/... - pcapng", "pcapng", "pcapng", "ntar",
6467 false0, BLOCKS_SUPPORTED(pcapng_blocks_supported)(sizeof (pcapng_blocks_supported) / sizeof (pcapng_blocks_supported
)[0]), pcapng_blocks_supported
,
6468 pcapng_dump_can_write_encap, pcapng_dump_open, NULL((void*)0)
6469};
6470
6471static const struct file_type_subtype_info stratoshark_pcapng_info = {
6472 "Stratoshark/... - scap", "scap", "scap", "scap",
6473 false0, BLOCKS_SUPPORTED(pcapng_blocks_supported)(sizeof (pcapng_blocks_supported) / sizeof (pcapng_blocks_supported
)[0]), pcapng_blocks_supported
,
6474 pcapng_dump_can_write_encap, pcapng_dump_open, NULL((void*)0)
6475};
6476
6477void register_pcapng(void)
6478{
6479 if (application_flavor_is_wireshark()) {
6480 pcapng_file_type_subtype = wtap_register_file_type_subtype(&wireshark_pcapng_info);
6481 } else {
6482 pcapng_file_type_subtype = wtap_register_file_type_subtype(&stratoshark_pcapng_info);
6483 }
6484
6485 wtap_register_backwards_compatibility_lua_name("PCAPNG",
6486 pcapng_file_type_subtype);
6487
6488 /* Setup the tables that will be used to handle custom block options */
6489
6490 /*
6491 * Create the table of option handlers for this block type.
6492 *
6493 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
6494 * so we use "g_direct_hash()" and "g_direct_equal()".
6495 */
6496 block_handlers = g_hash_table_new_full(g_direct_hash,
6497 g_direct_equal,
6498 NULL((void*)0), g_free);
6499
6500 custom_enterprise_handlers = g_hash_table_new_full(g_direct_hash,
6501 g_direct_equal,
6502 NULL((void*)0), g_free);
6503
6504 /* SHBs require special handling, so they don't have handlers here. */
6505 static pcapng_block_type_information_t SHB = { BLOCK_TYPE_SHB0x0A0D0D0A, NULL((void*)0), NULL((void*)0), NULL((void*)0), true1, NULL((void*)0) };
6506 SHB.option_handlers = pcapng_create_option_handler_table();
6507 register_pcapng_block_type_information(&SHB);
6508
6509 static pcapng_block_type_information_t IDB = { BLOCK_TYPE_IDB0x00000001, pcapng_read_if_descr_block, pcapng_process_idb, NULL((void*)0), true1, NULL((void*)0) };
6510 IDB.option_handlers = pcapng_create_option_handler_table();
6511 register_pcapng_block_type_information(&IDB);
6512
6513 static pcapng_block_type_information_t EPB = { BLOCK_TYPE_EPB0x00000006, pcapng_read_packet_block, NULL((void*)0), pcapng_write_enhanced_packet_block, false0, NULL((void*)0) };
6514 EPB.option_handlers = pcapng_create_option_handler_table();
6515 register_pcapng_block_type_information(&EPB);
6516
6517 static pcapng_block_type_information_t PB = { BLOCK_TYPE_PB0x00000002, pcapng_read_packet_block, NULL((void*)0), NULL((void*)0), false0, NULL((void*)0) };
6518 /* PBs and EPBs have the same options. */
6519 PB.option_handlers = EPB.option_handlers;
6520 register_pcapng_block_type_information(&PB);
6521
6522 static pcapng_block_type_information_t SPB = { BLOCK_TYPE_SPB0x00000003, pcapng_read_simple_packet_block, NULL((void*)0), pcapng_write_simple_packet_block, false0, NULL((void*)0) };
6523 /* SPBs don't support options */
6524 register_pcapng_block_type_information(&SPB);
6525
6526 static pcapng_block_type_information_t NRB = { BLOCK_TYPE_NRB0x00000004, pcapng_read_name_resolution_block, pcapng_process_nrb, NULL((void*)0), true1, NULL((void*)0) };
6527 NRB.option_handlers = pcapng_create_option_handler_table();
6528 register_pcapng_block_type_information(&NRB);
6529
6530 static pcapng_block_type_information_t ISB = { BLOCK_TYPE_ISB0x00000005, pcapng_read_interface_statistics_block, pcapng_process_isb, NULL((void*)0), true1, NULL((void*)0) };
6531 ISB.option_handlers = pcapng_create_option_handler_table();
6532 register_pcapng_block_type_information(&ISB);
6533
6534 static pcapng_block_type_information_t DSB = { BLOCK_TYPE_DSB0x0000000A, pcapng_read_decryption_secrets_block, pcapng_process_dsb, NULL((void*)0), true1, NULL((void*)0) };
6535 DSB.option_handlers = pcapng_create_option_handler_table();
6536 register_pcapng_block_type_information(&DSB);
6537
6538 static pcapng_block_type_information_t CB_COPY = { BLOCK_TYPE_CB_COPY0x00000BAD, pcapng_read_custom_block, NULL((void*)0), pcapng_write_custom_block_copy, false0, NULL((void*)0) };
6539 CB_COPY.option_handlers = pcapng_create_option_handler_table();
6540 register_pcapng_block_type_information(&CB_COPY);
6541
6542 static pcapng_block_type_information_t CB_NO_COPY = { BLOCK_TYPE_CB_NO_COPY0x40000BAD, pcapng_read_custom_block, NULL((void*)0), pcapng_write_custom_block_no_copy, false0, NULL((void*)0) };
6543 /* Copy and no-copy and CBs have the same options. */
6544 CB_NO_COPY.option_handlers = CB_COPY.option_handlers;
6545 register_pcapng_block_type_information(&CB_NO_COPY);
6546
6547 static pcapng_block_type_information_t SYSTEMD_JOURNAL_EXPORT = { BLOCK_TYPE_SYSTEMD_JOURNAL_EXPORT0x00000009, pcapng_read_systemd_journal_export_block, NULL((void*)0), pcapng_write_systemd_journal_export_block, false0, NULL((void*)0) };
6548 SYSTEMD_JOURNAL_EXPORT.option_handlers = pcapng_create_option_handler_table();
6549 register_pcapng_block_type_information(&SYSTEMD_JOURNAL_EXPORT);
6550}
6551
6552/*
6553 * Editor modelines - https://www.wireshark.org/tools/modelines.html
6554 *
6555 * Local variables:
6556 * c-basic-offset: 4
6557 * tab-width: 8
6558 * indent-tabs-mode: nil
6559 * End:
6560 *
6561 * vi: set shiftwidth=4 tabstop=8 expandtab:
6562 * :indentSize=4:tabSize=8:noTabs=true:
6563 */