4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * File format support for pcap-ng file format
7 * Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 /* File format reference:
25 * https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
26 * File format specification:
27 * https://github.com/pcapng/pcapng
29 * https://wiki.wireshark.org/Development/PcapNg
40 #include <epan/addr_resolv.h>
41 #include "file_wrappers.h"
42 #include "pcap-common.h"
43 #include "pcap-encap.h"
45 #include "pcapng_module.h"
48 #define pcapng_debug0(str) g_warning(str)
49 #define pcapng_debug1(str,p1) g_warning(str,p1)
50 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
51 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
53 #define pcapng_debug0(str)
54 #define pcapng_debug1(str,p1)
55 #define pcapng_debug2(str,p1,p2)
56 #define pcapng_debug3(str,p1,p2,p3)
60 pcapng_read(wtap *wth, int *err, gchar **err_info,
63 pcapng_seek_read(wtap *wth, gint64 seek_off,
64 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
66 pcapng_close(wtap *wth);
69 /* pcapng: common block header for every block type */
70 typedef struct pcapng_block_header_s {
72 guint32 block_total_length;
73 /* x bytes block_body */
74 /* guint32 block_total_length */
75 } pcapng_block_header_t;
78 * Minimum block size = size of block header + size of block trailer.
80 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
83 * In order to keep from trying to allocate large chunks of memory,
84 * which could either fail or, even if it succeeds, chew up so much
85 * address space or memory+backing store as not to leave room for
86 * anything else, we impose an upper limit on the size of blocks
87 * we're willing to handle.
89 * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
90 * don't try saying that on Wikipedia :-) :-) :-)).
92 #define MAX_BLOCK_SIZE (16*1024*1024)
94 /* pcapng: section header block */
95 typedef struct pcapng_section_header_block_s {
96 /* pcapng_block_header_t */
98 guint16 version_major;
99 guint16 version_minor;
100 guint64 section_length; /* might be -1 for unknown */
101 /* ... Options ... */
102 } pcapng_section_header_block_t;
105 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
107 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
109 /* pcapng: interface description block */
110 typedef struct pcapng_interface_description_block_s {
114 /* ... Options ... */
115 } pcapng_interface_description_block_t;
118 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
120 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
122 /* pcapng: packet block (obsolete) */
123 typedef struct pcapng_packet_block_s {
124 guint16 interface_id;
126 guint32 timestamp_high;
127 guint32 timestamp_low;
128 guint32 captured_len;
130 /* ... Packet Data ... */
131 /* ... Padding ... */
132 /* ... Options ... */
133 } pcapng_packet_block_t;
136 * Minimum PB size = minimum block size + size of fixed length portion of PB.
138 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
140 /* pcapng: enhanced packet block */
141 typedef struct pcapng_enhanced_packet_block_s {
142 guint32 interface_id;
143 guint32 timestamp_high;
144 guint32 timestamp_low;
145 guint32 captured_len;
147 /* ... Packet Data ... */
148 /* ... Padding ... */
149 /* ... Options ... */
150 } pcapng_enhanced_packet_block_t;
153 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
155 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
157 /* pcapng: simple packet block */
158 typedef struct pcapng_simple_packet_block_s {
160 /* ... Packet Data ... */
161 /* ... Padding ... */
162 } pcapng_simple_packet_block_t;
165 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
167 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
169 /* pcapng: name resolution block */
170 typedef struct pcapng_name_resolution_block_s {
174 } pcapng_name_resolution_block_t;
177 * Minimum NRB size = minimum block size + size of smallest NRB record
178 * (there must at least be an "end of records" record).
180 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
182 /* pcapng: interface statistics block */
183 typedef struct pcapng_interface_statistics_block_s {
184 guint32 interface_id;
185 guint32 timestamp_high;
186 guint32 timestamp_low;
187 /* ... Options ... */
188 } pcapng_interface_statistics_block_t;
191 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
193 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
195 /* pcapng: common option header for every option type */
196 typedef struct pcapng_option_header_s {
198 guint16 option_length;
199 /* ... x bytes Option Body ... */
200 /* ... Padding ... */
201 } pcapng_option_header_t;
205 guint16 value_length;
209 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
210 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
211 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
212 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
213 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
214 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
215 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
219 #define OPT_COMMENT 1
220 #define OPT_SHB_HARDWARE 2
222 #define OPT_SHB_USERAPPL 4
223 #define OPT_EPB_FLAGS 2
224 #define OPT_EPB_HASH 3
225 #define OPT_EPB_DROPCOUNT 4
227 /* Capture section */
229 /* Moved to wtap.h */
230 typedef struct wtapng_section_s {
232 guint64 section_length;
234 gchar *opt_comment; /* NULL if not available */
235 gchar *shb_hardware; /* NULL if not available */
236 gchar *shb_os; /* NULL if not available */
237 gchar *shb_user_appl; /* NULL if not available */
242 /* Moved to wtap.h */
244 /* Interface Description
247 * if_name 2 A UTF-8 string containing the name of the device used to capture data. "eth0" / "\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}" / ...
248 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
249 * if_IPv4addr 4 Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
250 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
251 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
252 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
253 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
254 * if_tsresol 9 Resolution of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10 (e.g. 6 means microsecond resolution, timestamps are the number of microseconds since 1/1/1970). If the Most Significant Bit is equal to one, the remaining bits indicates the resolution as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a resolution of 10^-6 is assumed (i.e. timestamps have the same resolution of the standard 'libpcap' timestamps). 6
255 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
256 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO). (TODO: better use different options for different fields? e.g. if_filter_pcap, if_filter_bpf, ...) 00 "tcp port 23 and host 10.0.0.5"
257 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory))) because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
258 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. For link layers whose FCS length can change during time, the Packet Block Flags Word can be used (see Appendix A (Packet Block Flags Word)). 4
259 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps. The time zone of the offset can be specified with the option if_tzone. TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
262 typedef struct wtapng_if_descr_s {
268 gchar *opt_comment; /* NULL if not available */
269 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
270 gchar *if_description; /* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
271 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
272 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
273 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
274 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
275 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
276 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
277 * If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10
279 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
280 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
281 * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
283 gchar *if_os; /* NULL if not available, 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. */
284 gint8 if_fcslen; /* -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. */
285 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
290 typedef struct wtapng_packet_s {
292 guint32 ts_high; /* seconds since 1.1.1970 */
293 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
294 guint32 cap_len; /* data length in the file */
295 guint32 packet_len; /* data length on the wire */
296 guint32 interface_id; /* identifier of the interface. */
297 guint16 drops_count; /* drops count, only valid for packet block */
298 /* 0xffff if information no available */
300 /* XXX - put the packet data / pseudo_header here as well? */
304 typedef struct wtapng_simple_packet_s {
306 guint32 cap_len; /* data length in the file */
307 guint32 packet_len; /* data length on the wire */
308 /* XXX - put the packet data / pseudo_header here as well? */
309 } wtapng_simple_packet_t;
311 /* Name Resolution */
312 typedef struct wtapng_name_res_s {
314 gchar *opt_comment; /* NULL if not available */
319 /* Interface Statistics moved to wtap.h*/
320 typedef struct wtapng_if_stats_s {
322 guint32 interface_id;
326 gchar *opt_comment; /* NULL if not available */
327 guint64 isb_starttime;
331 guint64 isb_filteraccept;
333 guint64 isb_usrdeliv;
337 typedef struct wtapng_block_s {
338 guint32 type; /* block_type as defined by pcapng */
340 wtapng_section_t section;
341 wtapng_if_descr_t if_descr;
342 wtapng_name_res_t name_res;
343 wtapng_if_stats_t if_stats;
347 * XXX - currently don't know how to handle these!
349 * For one thing, when we're reading a block, they must be
350 * writable, i.e. not const, so that we can read into them,
351 * but, when we're writing a block, they can be const, and,
352 * in fact, they sometimes point to const values.
354 struct wtap_pkthdr *packet_header;
355 Buffer *frame_buffer;
358 /* Interface data in private struct */
359 typedef struct interface_info_s {
362 guint64 time_units_per_second;
367 gboolean shb_read; /**< Set when first SHB read, second read will fail */
368 gboolean byte_swapped;
369 guint16 version_major;
370 guint16 version_minor;
371 GArray *interfaces; /**< Interfaces found in the capture file. */
373 wtap_new_ipv4_callback_t add_new_ipv4;
374 wtap_new_ipv6_callback_t add_new_ipv6;
379 * Table for plugins to handle particular block types.
381 * A handler has a "read" routine and a "write" routine.
383 * A "read" routine returns a block as a libwiretap record, filling
384 * in the wtap_pkthdr structure with the appropriate record type and
385 * other information, and filling in the supplied Buffer with
386 * data for which there's no place in the wtap_pkthdr structure.
388 * A "write" routine takes a libwiretap record and Buffer and writes
396 static GHashTable *block_handlers;
399 register_pcapng_block_type_handler(guint block_type, block_reader read,
402 block_handler *handler;
404 if (block_handlers == NULL) {
406 * Create the table of block handlers.
408 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
409 * so we use "g_direct_hash()" and "g_direct_equal()".
411 block_handlers = g_hash_table_new_full(g_direct_hash,
415 handler = (block_handler *)g_malloc(sizeof *handler);
416 handler->read = read;
417 handler->write = write;
418 (void)g_hash_table_insert(block_handlers, GUINT_TO_POINTER(block_type),
423 * Tables for plugins to handle particular options for particular block
426 * An option has a handler routine, which is passed an indication of
427 * whether this section of the file is byte-swapped, the length of the
428 * option, the data of the option, a pointer to an error code, and a
429 * pointer to a pointer variable for an error string.
431 * It checks whether the length and option are valid, and, if they aren't,
432 * returns FALSE, setting the error code to the appropriate error (normally
433 * WTAP_ERR_BAD_FILE) and the error string to an appropriate string
434 * indicating the problem.
436 * Otherwise, if this section of the file is byte-swapped, it byte-swaps
437 * multi-byte numerical values, so that it's in the host byte order.
441 * Block types indices in the table of tables of option handlers.
443 * Block types are not guaranteed to be sequential, so we map the
444 * block types we support to a sequential set. Furthermore, all
445 * packet block types have the same set of options.
447 #define BT_INDEX_SHB 0
448 #define BT_INDEX_IDB 1
449 #define BT_INDEX_PBS 2 /* all packet blocks */
450 #define BT_INDEX_NRB 3
451 #define BT_INDEX_ISB 4
453 #define NUM_BT_INDICES 5
455 static GHashTable *option_handlers[NUM_BT_INDICES];
458 register_pcapng_option_handler(guint block_type, guint option_code,
459 option_handler handler)
463 switch (block_type) {
466 bt_index = BT_INDEX_SHB;
470 bt_index = BT_INDEX_IDB;
476 bt_index = BT_INDEX_PBS;
480 bt_index = BT_INDEX_NRB;
484 bt_index = BT_INDEX_ISB;
489 * This is a block type we don't process; either we ignore it,
490 * in which case the options don't get processed, or there's
491 * a plugin routine to handle it, in which case that routine
492 * will do the option processing itself.
494 * XXX - report an error?
499 if (option_handlers[bt_index] == NULL) {
501 * Create the table of option handlers for this block type.
503 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
504 * so we use "g_direct_hash()" and "g_direct_equal()".
506 option_handlers[bt_index] = g_hash_table_new_full(g_direct_hash,
510 (void)g_hash_table_insert(option_handlers[bt_index],
511 GUINT_TO_POINTER(option_code), handler);
513 #endif /* HAVE_PLUGINS */
516 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
517 guint8 *content, guint len, guint to_read,
518 int *err, gchar **err_info)
522 /* sanity check: don't run past the end of the block */
523 if (to_read < sizeof (*oh)) {
524 *err = WTAP_ERR_BAD_FILE;
525 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
529 /* read option header */
530 if (!wtap_read_bytes(fh, oh, sizeof (*oh), err, err_info)) {
531 pcapng_debug0("pcapng_read_option: failed to read option");
534 block_read = sizeof (*oh);
535 if (pn->byte_swapped) {
536 oh->option_code = GUINT16_SWAP_LE_BE(oh->option_code);
537 oh->option_length = GUINT16_SWAP_LE_BE(oh->option_length);
540 /* sanity check: don't run past the end of the block */
541 if (to_read < sizeof (*oh) + oh->option_length) {
542 *err = WTAP_ERR_BAD_FILE;
543 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
547 /* sanity check: option length */
548 if (len < oh->option_length) {
549 *err = WTAP_ERR_BAD_FILE;
550 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
554 /* read option content */
555 if (!wtap_read_bytes(fh, content, oh->option_length, err, err_info)) {
556 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
559 block_read += oh->option_length;
561 /* jump over potential padding bytes at end of option */
562 if ( (oh->option_length % 4) != 0) {
563 if (!file_skip(fh, 4 - (oh->option_length % 4), err))
565 block_read += 4 - (oh->option_length % 4);
573 pcapng_free_wtapng_block_data(wtapng_block_t *wblock)
575 switch (wblock->type) {
576 case(BLOCK_TYPE_SHB):
577 g_free(wblock->data.section.opt_comment);
578 g_free(wblock->data.section.shb_hardware);
579 g_free(wblock->data.section.shb_os);
580 g_free(wblock->data.section.shb_user_appl);
587 PCAPNG_BLOCK_NOT_SHB,
591 static block_return_val
592 pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
593 pcapng_t *pn, wtapng_block_t *wblock,
594 int *err, gchar **err_info)
597 guint to_read, opt_cont_buf_len;
598 pcapng_section_header_block_t shb;
599 pcapng_option_header_t oh;
600 guint8 *option_content = NULL; /* Allocate as large as the options block */
602 /* read fixed-length part of the block */
603 if (!wtap_read_bytes(fh, &shb, sizeof shb, err, err_info)) {
604 if (*err == WTAP_ERR_SHORT_READ) {
606 * This block is too short to be an SHB.
608 * If we're reading this as part of an open,
609 * the file is too short to be a pcap-ng file.
611 * If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
612 * PCAPNG_BLOCK_ERROR the same, so we can just return
613 * PCAPNG_BLOCK_NOT_SHB in both cases.
615 return PCAPNG_BLOCK_NOT_SHB;
617 return PCAPNG_BLOCK_ERROR;
620 /* is the magic number one we expect? */
623 /* this seems pcapng with correct byte order */
624 pn->byte_swapped = FALSE;
625 pn->version_major = shb.version_major;
626 pn->version_minor = shb.version_minor;
628 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
629 pn->version_major, pn->version_minor, bh->block_total_length);
632 /* this seems pcapng with swapped byte order */
633 pn->byte_swapped = TRUE;
634 pn->version_major = GUINT16_SWAP_LE_BE(shb.version_major);
635 pn->version_minor = GUINT16_SWAP_LE_BE(shb.version_minor);
637 /* tweak the block length to meet current swapping that we know now */
638 bh->block_total_length = GUINT32_SWAP_LE_BE(bh->block_total_length);
640 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
641 pn->version_major, pn->version_minor, bh->block_total_length);
644 /* Not a "pcapng" magic number we know about. */
645 *err = WTAP_ERR_BAD_FILE;
646 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
649 * See above comment about PCAPNG_BLOCK_NOT_SHB.
651 return PCAPNG_BLOCK_NOT_SHB;
655 * Is this block long enough to be an SHB?
657 if (bh->block_total_length < MIN_SHB_SIZE) {
661 *err = WTAP_ERR_BAD_FILE;
662 *err_info = g_strdup_printf("pcapng_read_section_header_block: total block length %u of an SHB is less than the minimum SHB size %u",
663 bh->block_total_length, MIN_SHB_SIZE);
664 return PCAPNG_BLOCK_ERROR;
667 /* OK, at this point we assume it's a pcap-ng file.
669 Don't try to allocate memory for a huge number of options, as
670 that might fail and, even if it succeeds, it might not leave
671 any address space or memory+backing store for anything else.
673 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
674 We check for this *after* checking the SHB for its byte
675 order magic number, so that non-pcap-ng files are less
676 likely to be treated as bad pcap-ng files. */
677 if (bh->block_total_length > MAX_BLOCK_SIZE) {
678 *err = WTAP_ERR_BAD_FILE;
679 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
680 bh->block_total_length, MAX_BLOCK_SIZE);
681 return PCAPNG_BLOCK_ERROR;
684 /* We currently only suport one SHB */
685 if (pn->shb_read == TRUE) {
686 *err = WTAP_ERR_UNSUPPORTED;
687 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported");
688 return PCAPNG_BLOCK_ERROR;
691 /* we currently only understand SHB V1.0 */
692 if (pn->version_major != 1 || pn->version_minor > 0) {
693 *err = WTAP_ERR_UNSUPPORTED;
694 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
695 pn->version_major, pn->version_minor);
696 return PCAPNG_BLOCK_ERROR;
700 /* 64bit section_length (currently unused) */
701 if (pn->byte_swapped) {
702 wblock->data.section.section_length = GUINT64_SWAP_LE_BE(shb.section_length);
704 wblock->data.section.section_length = shb.section_length;
708 to_read = bh->block_total_length - MIN_SHB_SIZE;
710 /* Allocate enough memory to hold all options */
711 opt_cont_buf_len = to_read;
712 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
713 if (opt_cont_buf_len != 0 && option_content == NULL) {
714 *err = ENOMEM; /* we assume we're out of memory */
715 return PCAPNG_BLOCK_ERROR;
717 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
718 while (to_read != 0) {
720 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
721 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
722 if (bytes_read <= 0) {
723 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
724 return PCAPNG_BLOCK_ERROR;
726 to_read -= bytes_read;
728 /* handle option content */
729 switch (oh.option_code) {
732 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
734 /* padding should be ok here, just get out of this */
738 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
739 g_free(wblock->data.section.opt_comment);
740 wblock->data.section.opt_comment = g_strndup((char *)option_content, oh.option_length);
741 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
743 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
746 case(OPT_SHB_HARDWARE):
747 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
748 g_free(wblock->data.section.shb_hardware);
749 wblock->data.section.shb_hardware = g_strndup((char *)option_content, oh.option_length);
750 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
752 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
756 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
757 g_free(wblock->data.section.shb_os);
758 wblock->data.section.shb_os = g_strndup((char *)option_content, oh.option_length);
759 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
761 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
764 case(OPT_SHB_USERAPPL):
765 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
766 g_free(wblock->data.section.shb_user_appl);
767 wblock->data.section.shb_user_appl = g_strndup((char *)option_content, oh.option_length);
768 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
770 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
774 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
775 oh.option_code, oh.option_length);
778 g_free(option_content);
780 return PCAPNG_BLOCK_OK;
784 /* "Interface Description Block" */
786 pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
787 pcapng_t *pn, wtapng_block_t *wblock, int *err,
790 guint64 time_units_per_second = 1000000; /* default = 10^6 */
791 int tsprecision = WTAP_TSPREC_USEC;
793 guint to_read, opt_cont_buf_len;
794 pcapng_interface_description_block_t idb;
795 pcapng_option_header_t oh;
796 guint8 *option_content = NULL; /* Allocate as large as the options block */
799 * Is this block long enough to be an IDB?
801 if (bh->block_total_length < MIN_IDB_SIZE) {
805 *err = WTAP_ERR_BAD_FILE;
806 *err_info = g_strdup_printf("pcapng_read_if_descr_block: total block length %u of an IDB is less than the minimum IDB size %u",
807 bh->block_total_length, MIN_IDB_SIZE);
811 /* Don't try to allocate memory for a huge number of options, as
812 that might fail and, even if it succeeds, it might not leave
813 any address space or memory+backing store for anything else.
815 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
816 We check for this *after* checking the SHB for its byte
817 order magic number, so that non-pcap-ng files are less
818 likely to be treated as bad pcap-ng files. */
819 if (bh->block_total_length > MAX_BLOCK_SIZE) {
820 *err = WTAP_ERR_BAD_FILE;
821 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
822 bh->block_total_length, MAX_BLOCK_SIZE);
826 /* read block content */
827 if (!wtap_read_bytes(fh, &idb, sizeof idb, err, err_info)) {
828 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
832 /* mandatory values */
833 if (pn->byte_swapped) {
834 wblock->data.if_descr.link_type = GUINT16_SWAP_LE_BE(idb.linktype);
835 wblock->data.if_descr.snap_len = GUINT32_SWAP_LE_BE(idb.snaplen);
837 wblock->data.if_descr.link_type = idb.linktype;
838 wblock->data.if_descr.snap_len = idb.snaplen;
841 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
842 wblock->data.if_descr.time_units_per_second = time_units_per_second;
843 wblock->data.if_descr.tsprecision = tsprecision;
845 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
846 wblock->data.if_descr.link_type,
847 wtap_encap_string(wblock->data.if_descr.wtap_encap),
848 wblock->data.if_descr.snap_len);
850 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
851 /* This is unrealistic, but text2pcap currently uses 102400.
852 * We do not use this value, maybe we should check the
853 * snap_len of the packets against it. For now, only warn.
855 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
856 wblock->data.if_descr.snap_len);
857 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
860 /* Option defaults */
861 wblock->data.if_descr.opt_comment = NULL;
862 wblock->data.if_descr.if_name = NULL;
863 wblock->data.if_descr.if_description = NULL;
864 /* XXX: if_IPv4addr */
865 /* XXX: if_IPv6addr */
866 /* XXX: if_MACaddr */
867 /* XXX: if_EUIaddr */
868 wblock->data.if_descr.if_speed = 0; /* "unknown" */
869 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
870 wblock->data.if_descr.if_filter_str = NULL;
871 wblock->data.if_descr.bpf_filter_len = 0;
872 wblock->data.if_descr.if_filter_bpf_bytes = NULL;
873 wblock->data.if_descr.if_os = NULL;
874 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
875 /* XXX: guint64 if_tsoffset; */
879 to_read = bh->block_total_length - MIN_IDB_SIZE;
881 /* Allocate enough memory to hold all options */
882 opt_cont_buf_len = to_read;
883 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
884 if (opt_cont_buf_len != 0 && option_content == NULL) {
885 *err = ENOMEM; /* we assume we're out of memory */
889 while (to_read != 0) {
891 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
892 if (bytes_read <= 0) {
893 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
896 to_read -= bytes_read;
898 /* handle option content */
899 switch (oh.option_code) {
900 case(0): /* opt_endofopt */
902 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
904 /* padding should be ok here, just get out of this */
907 case(1): /* opt_comment */
908 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
909 wblock->data.if_descr.opt_comment = g_strndup((char *)option_content, oh.option_length);
910 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
912 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
915 case(2): /* if_name */
916 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
917 wblock->data.if_descr.if_name = g_strndup((char *)option_content, oh.option_length);
918 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
920 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
923 case(3): /* if_description */
924 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
925 wblock->data.if_descr.if_description = g_strndup((char *)option_content, oh.option_length);
926 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
928 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
932 * if_IPv4addr 4 Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
933 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
934 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
935 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
937 case(8): /* if_speed */
938 if (oh.option_length == 8) {
939 /* Don't cast a guint8 * into a guint64 *--the
940 * guint8 * may not point to something that's
943 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
944 if (pn->byte_swapped)
945 wblock->data.if_descr.if_speed = GUINT64_SWAP_LE_BE(wblock->data.if_descr.if_speed);
946 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
948 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
951 case(9): /* if_tsresol */
952 if (oh.option_length == 1) {
955 guint8 i, exponent, if_tsresol;
957 if_tsresol = option_content[0];
958 if (if_tsresol & 0x80) {
963 exponent = (guint8)(if_tsresol & 0x7f);
964 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
966 for (i = 0; i < exponent; i++) {
969 time_units_per_second = result;
971 time_units_per_second = G_MAXUINT64;
973 if (time_units_per_second > (((guint64)1) << 32)) {
974 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
976 wblock->data.if_descr.time_units_per_second = time_units_per_second;
977 wblock->data.if_descr.if_tsresol = if_tsresol;
978 if (time_units_per_second >= 1000000000)
979 tsprecision = WTAP_TSPREC_NSEC;
980 else if (time_units_per_second >= 1000000)
981 tsprecision = WTAP_TSPREC_USEC;
982 else if (time_units_per_second >= 1000)
983 tsprecision = WTAP_TSPREC_MSEC;
984 else if (time_units_per_second >= 100)
985 tsprecision = WTAP_TSPREC_CSEC;
986 else if (time_units_per_second >= 10)
987 tsprecision = WTAP_TSPREC_DSEC;
989 tsprecision = WTAP_TSPREC_SEC;
990 wblock->data.if_descr.tsprecision = tsprecision;
991 pcapng_debug3("pcapng_read_if_descr_block: if_tsresol %u, units/s %" G_GINT64_MODIFIER "u, tsprecision %d", wblock->data.if_descr.if_tsresol, wblock->data.if_descr.time_units_per_second, tsprecision);
993 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
997 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
999 case(11): /* if_filter */
1000 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1001 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
1004 if (option_content[0] == 0) {
1005 wblock->data.if_descr.if_filter_str = g_strndup((char *)option_content+1, oh.option_length-1);
1006 pcapng_debug2("pcapng_read_if_descr_block: if_filter_str %s oh.option_length %u", wblock->data.if_descr.if_filter_str, oh.option_length);
1007 } else if (option_content[0] == 1) {
1008 wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
1009 wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
1010 memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, (char *)option_content+1, oh.option_length-1);
1013 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
1016 case(12): /* if_os */
1018 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
1019 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
1020 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
1022 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1023 wblock->data.if_descr.if_os = g_strndup((char *)option_content, oh.option_length);
1024 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
1026 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
1029 case(13): /* if_fcslen */
1030 if (oh.option_length == 1) {
1031 wblock->data.if_descr.if_fcslen = option_content[0];
1032 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
1033 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
1034 /* XXX - add sanity check */
1036 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
1040 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
1041 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
1042 * The time zone of the offset can be specified with the option if_tzone.
1043 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
1046 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
1047 oh.option_code, oh.option_length);
1051 g_free(option_content);
1054 * If the per-file encapsulation isn't known, set it to this
1055 * interface's encapsulation.
1057 * If it *is* known, and it isn't this interface's encapsulation,
1058 * set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
1059 * have a single encapsulation for all interfaces in the file,
1060 * so it probably doesn't have a single encapsulation for all
1061 * packets in the file.
1063 if (wth->file_encap == WTAP_ENCAP_UNKNOWN) {
1064 wth->file_encap = wblock->data.if_descr.wtap_encap;
1066 if (wth->file_encap != wblock->data.if_descr.wtap_encap) {
1067 wth->file_encap = WTAP_ENCAP_PER_PACKET;
1072 * The same applies to the per-file time stamp resolution.
1074 if (wth->file_tsprec == WTAP_TSPREC_UNKNOWN) {
1075 wth->file_tsprec = wblock->data.if_descr.tsprecision;
1077 if (wth->file_tsprec != wblock->data.if_descr.tsprecision) {
1078 wth->file_tsprec = WTAP_TSPREC_PER_PACKET;
1087 pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info, gboolean enhanced)
1091 guint to_read, opt_cont_buf_len;
1092 pcapng_enhanced_packet_block_t epb;
1093 pcapng_packet_block_t pb;
1094 wtapng_packet_t packet;
1095 guint32 block_total_length;
1097 interface_info_t iface_info;
1100 pcapng_option_header_t *oh;
1101 guint8 *option_content;
1102 int pseudo_header_len;
1105 option_handler handler;
1108 /* Don't try to allocate memory for a huge number of options, as
1109 that might fail and, even if it succeeds, it might not leave
1110 any address space or memory+backing store for anything else.
1112 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1113 We check for this *after* checking the SHB for its byte
1114 order magic number, so that non-pcap-ng files are less
1115 likely to be treated as bad pcap-ng files. */
1116 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1117 *err = WTAP_ERR_BAD_FILE;
1118 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1119 bh->block_total_length, MAX_BLOCK_SIZE);
1123 /* "(Enhanced) Packet Block" read fixed part */
1126 * Is this block long enough to be an EPB?
1128 if (bh->block_total_length < MIN_EPB_SIZE) {
1132 *err = WTAP_ERR_BAD_FILE;
1133 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
1134 bh->block_total_length, MIN_EPB_SIZE);
1137 if (!wtap_read_bytes(fh, &epb, sizeof epb, err, err_info)) {
1138 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1141 block_read = (guint)sizeof epb;
1143 if (pn->byte_swapped) {
1144 packet.interface_id = GUINT32_SWAP_LE_BE(epb.interface_id);
1145 packet.drops_count = -1; /* invalid */
1146 packet.ts_high = GUINT32_SWAP_LE_BE(epb.timestamp_high);
1147 packet.ts_low = GUINT32_SWAP_LE_BE(epb.timestamp_low);
1148 packet.cap_len = GUINT32_SWAP_LE_BE(epb.captured_len);
1149 packet.packet_len = GUINT32_SWAP_LE_BE(epb.packet_len);
1151 packet.interface_id = epb.interface_id;
1152 packet.drops_count = -1; /* invalid */
1153 packet.ts_high = epb.timestamp_high;
1154 packet.ts_low = epb.timestamp_low;
1155 packet.cap_len = epb.captured_len;
1156 packet.packet_len = epb.packet_len;
1158 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1159 packet.interface_id, packet.cap_len, packet.packet_len);
1162 * Is this block long enough to be a PB?
1164 if (bh->block_total_length < MIN_PB_SIZE) {
1168 *err = WTAP_ERR_BAD_FILE;
1169 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1170 bh->block_total_length, MIN_PB_SIZE);
1173 if (!wtap_read_bytes(fh, &pb, sizeof pb, err, err_info)) {
1174 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1177 block_read = (guint)sizeof pb;
1179 if (pn->byte_swapped) {
1180 packet.interface_id = GUINT16_SWAP_LE_BE(pb.interface_id);
1181 packet.drops_count = GUINT16_SWAP_LE_BE(pb.drops_count);
1182 packet.ts_high = GUINT32_SWAP_LE_BE(pb.timestamp_high);
1183 packet.ts_low = GUINT32_SWAP_LE_BE(pb.timestamp_low);
1184 packet.cap_len = GUINT32_SWAP_LE_BE(pb.captured_len);
1185 packet.packet_len = GUINT32_SWAP_LE_BE(pb.packet_len);
1187 packet.interface_id = pb.interface_id;
1188 packet.drops_count = pb.drops_count;
1189 packet.ts_high = pb.timestamp_high;
1190 packet.ts_low = pb.timestamp_low;
1191 packet.cap_len = pb.captured_len;
1192 packet.packet_len = pb.packet_len;
1194 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1195 packet.interface_id, packet.cap_len, packet.packet_len);
1199 * How much padding is there at the end of the packet data?
1201 if ((packet.cap_len % 4) != 0)
1202 padding = 4 - (packet.cap_len % 4);
1206 /* add padding bytes to "block total length" */
1207 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1208 if (bh->block_total_length % 4) {
1209 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1211 block_total_length = bh->block_total_length;
1213 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1216 * Is this block long enough to hold the packet data?
1219 if (block_total_length <
1220 MIN_EPB_SIZE + packet.cap_len + padding) {
1224 *err = WTAP_ERR_BAD_FILE;
1225 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1226 block_total_length, packet.cap_len);
1230 if (block_total_length <
1231 MIN_PB_SIZE + packet.cap_len + padding) {
1235 *err = WTAP_ERR_BAD_FILE;
1236 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1237 block_total_length, packet.cap_len);
1242 if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1243 *err = WTAP_ERR_BAD_FILE;
1244 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1245 packet.cap_len, WTAP_MAX_PACKET_SIZE);
1248 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1251 packet.interface_id);
1253 if (packet.interface_id >= pn->interfaces->len) {
1254 *err = WTAP_ERR_BAD_FILE;
1255 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u",
1256 packet.interface_id, pn->interfaces->len);
1259 iface_info = g_array_index(pn->interfaces, interface_info_t,
1260 packet.interface_id);
1262 wblock->packet_header->rec_type = REC_TYPE_PACKET;
1263 wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1265 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1266 iface_info.wtap_encap,
1267 wtap_encap_string(iface_info.wtap_encap),
1268 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
1269 wblock->packet_header->interface_id = packet.interface_id;
1270 wblock->packet_header->pkt_encap = iface_info.wtap_encap;
1271 wblock->packet_header->pkt_tsprec = iface_info.tsprecision;
1273 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1274 pseudo_header_len = pcap_process_pseudo_header(fh,
1275 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1276 iface_info.wtap_encap,
1279 wblock->packet_header,
1282 if (pseudo_header_len < 0) {
1285 block_read += pseudo_header_len;
1286 if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
1287 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1290 wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
1291 wblock->packet_header->len = packet.packet_len - pseudo_header_len;
1293 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1294 ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
1295 wblock->packet_header->ts.secs = (time_t)(ts / iface_info.time_units_per_second);
1296 wblock->packet_header->ts.nsecs = (int)(((ts % iface_info.time_units_per_second) * 1000000000) / iface_info.time_units_per_second);
1298 /* "(Enhanced) Packet Block" read capture data */
1299 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1300 packet.cap_len - pseudo_header_len, err, err_info))
1302 block_read += packet.cap_len - pseudo_header_len;
1304 /* jump over potential padding bytes at end of the packet data */
1306 if (!file_skip(fh, padding, err))
1308 block_read += padding;
1311 /* Option defaults */
1312 wblock->packet_header->opt_comment = NULL;
1313 wblock->packet_header->drop_count = -1;
1314 wblock->packet_header->pack_flags = 0;
1316 /* FCS length default */
1317 fcslen = pn->if_fcslen;
1325 to_read = block_total_length -
1326 (int)sizeof(pcapng_block_header_t) -
1327 block_read - /* fixed and variable part, including padding */
1328 (int)sizeof(bh->block_total_length);
1330 /* Allocate enough memory to hold all options */
1331 opt_cont_buf_len = to_read;
1332 ws_buffer_assure_space(&wblock->packet_header->ft_specific_data, opt_cont_buf_len);
1333 opt_ptr = ws_buffer_start_ptr(&wblock->packet_header->ft_specific_data);
1335 while (to_read != 0) {
1337 oh = (pcapng_option_header_t *)(void *)opt_ptr;
1338 option_content = opt_ptr + sizeof (pcapng_option_header_t);
1339 bytes_read = pcapng_read_option(fh, pn, oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1340 if (bytes_read <= 0) {
1341 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1342 /* XXX - free anything? */
1345 block_read += bytes_read;
1346 to_read -= bytes_read;
1348 /* handle option content */
1349 switch (oh->option_code) {
1352 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1354 /* padding should be ok here, just get out of this */
1358 if (oh->option_length > 0 && oh->option_length < opt_cont_buf_len) {
1359 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1360 wblock->packet_header->opt_comment = g_strndup((char *)option_content, oh->option_length);
1361 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh->option_length, wblock->packet_header->opt_comment);
1363 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh->option_length);
1366 case(OPT_EPB_FLAGS):
1367 if (oh->option_length != 4) {
1368 *err = WTAP_ERR_BAD_FILE;
1369 *err_info = g_strdup_printf("pcapng: packet block flags option length %u is not 4",
1371 /* XXX - free anything? */
1374 /* Don't cast a guint8 * into a guint32 *--the
1375 * guint8 * may not point to something that's
1376 * aligned correctly.
1378 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1379 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1380 if (pn->byte_swapped) {
1381 wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
1382 memcpy(option_content, &wblock->packet_header->pack_flags, sizeof(guint32));
1384 if (wblock->packet_header->pack_flags & 0x000001E0) {
1385 /* The FCS length is present */
1386 fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1388 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1391 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1392 oh->option_code, oh->option_length);
1394 case(OPT_EPB_DROPCOUNT):
1395 if (oh->option_length != 8) {
1396 *err = WTAP_ERR_BAD_FILE;
1397 *err_info = g_strdup_printf("pcapng: packet block drop count option length %u is not 8",
1399 /* XXX - free anything? */
1402 /* Don't cast a guint8 * into a guint64 *--the
1403 * guint8 * may not point to something that's
1404 * aligned correctly.
1406 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1407 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1408 if (pn->byte_swapped) {
1409 wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
1410 memcpy(option_content, &wblock->packet_header->drop_count, sizeof(guint64));
1413 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1418 * Do we have a handler for this packet block option code?
1420 if (option_handlers[BT_INDEX_PBS] != NULL &&
1421 (handler = (option_handler)g_hash_table_lookup(option_handlers[BT_INDEX_PBS],
1422 GUINT_TO_POINTER((guint)oh->option_code))) != NULL) {
1423 /* Yes - call the handler. */
1424 if (!handler(pn->byte_swapped, oh->option_length,
1425 option_content, err, err_info))
1426 /* XXX - free anything? */
1431 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1432 oh->option_code, oh->option_length);
1437 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
1438 wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
1439 pn->byte_swapped, fcslen);
1445 pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1447 interface_info_t iface_info;
1448 pcapng_simple_packet_block_t spb;
1449 wtapng_simple_packet_t simple_packet;
1450 guint32 block_total_length;
1452 int pseudo_header_len;
1455 * Is this block long enough to be an SPB?
1457 if (bh->block_total_length < MIN_SPB_SIZE) {
1461 *err = WTAP_ERR_BAD_FILE;
1462 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of an SPB is less than the minimum SPB size %u",
1463 bh->block_total_length, MIN_SPB_SIZE);
1467 /* Don't try to allocate memory for a huge number of options, as
1468 that might fail and, even if it succeeds, it might not leave
1469 any address space or memory+backing store for anything else.
1471 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1472 We check for this *after* checking the SHB for its byte
1473 order magic number, so that non-pcap-ng files are less
1474 likely to be treated as bad pcap-ng files. */
1475 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1476 *err = WTAP_ERR_BAD_FILE;
1477 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1478 bh->block_total_length, MAX_BLOCK_SIZE);
1482 /* "Simple Packet Block" read fixed part */
1483 if (!wtap_read_bytes(fh, &spb, sizeof spb, err, err_info)) {
1484 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1488 if (0 >= pn->interfaces->len) {
1489 *err = WTAP_ERR_BAD_FILE;
1490 *err_info = g_strdup_printf("pcapng: SPB appeared before any IDBs");
1493 iface_info = g_array_index(pn->interfaces, interface_info_t, 0);
1495 if (pn->byte_swapped) {
1496 simple_packet.packet_len = GUINT32_SWAP_LE_BE(spb.packet_len);
1498 simple_packet.packet_len = spb.packet_len;
1502 * The captured length is not a field in the SPB; it can be
1503 * calculated as the minimum of the snapshot length from the
1504 * IDB and the packet length, as per the pcap-ng spec.
1506 simple_packet.cap_len = simple_packet.packet_len;
1507 if (simple_packet.cap_len > iface_info.snap_len)
1508 simple_packet.cap_len = iface_info.snap_len;
1511 * How much padding is there at the end of the packet data?
1513 if ((simple_packet.cap_len % 4) != 0)
1514 padding = 4 - (simple_packet.cap_len % 4);
1518 /* add padding bytes to "block total length" */
1519 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1520 if (bh->block_total_length % 4) {
1521 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1523 block_total_length = bh->block_total_length;
1525 pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length);
1528 * Is this block long enough to hold the packet data?
1530 if (block_total_length < MIN_SPB_SIZE + simple_packet.cap_len + padding) {
1532 * No. That means that the problem is with the packet
1533 * length; the snapshot length can be bigger than the amount
1534 * of packet data in the block, as it's a *maximum* length,
1535 * not a *minimum* length.
1537 *err = WTAP_ERR_BAD_FILE;
1538 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1539 block_total_length, simple_packet.packet_len);
1543 if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1544 *err = WTAP_ERR_BAD_FILE;
1545 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1546 simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1549 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1550 simple_packet.packet_len);
1552 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1553 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
1555 /* No time stamp in a simple packet block; no options, either */
1556 wblock->packet_header->rec_type = REC_TYPE_PACKET;
1557 wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1558 wblock->packet_header->interface_id = 0;
1559 wblock->packet_header->pkt_encap = iface_info.wtap_encap;
1560 wblock->packet_header->pkt_tsprec = iface_info.tsprecision;
1561 wblock->packet_header->ts.secs = 0;
1562 wblock->packet_header->ts.nsecs = 0;
1563 wblock->packet_header->interface_id = 0;
1564 wblock->packet_header->opt_comment = NULL;
1565 wblock->packet_header->drop_count = 0;
1566 wblock->packet_header->pack_flags = 0;
1568 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1569 pseudo_header_len = pcap_process_pseudo_header(fh,
1570 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1571 iface_info.wtap_encap,
1572 simple_packet.cap_len,
1574 wblock->packet_header,
1577 if (pseudo_header_len < 0) {
1580 wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
1581 wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
1582 if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
1583 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1587 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1589 /* "Simple Packet Block" read capture data */
1590 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1591 simple_packet.cap_len, err, err_info))
1594 /* jump over potential padding bytes at end of the packet data */
1595 if ((simple_packet.cap_len % 4) != 0) {
1596 if (!file_skip(fh, 4 - (simple_packet.cap_len % 4), err))
1600 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
1601 wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
1602 pn->byte_swapped, pn->if_fcslen);
1606 #define NRES_ENDOFRECORD 0
1607 #define NRES_IP4RECORD 1
1608 #define NRES_IP6RECORD 2
1609 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1610 /* IPv6 + MAXNAMELEN */
1611 #define INITIAL_NRB_REC_SIZE (16 + 64)
1614 * Find the end of the NUL-terminated name the beginning of which is pointed
1615 * to by p; record_len is the number of bytes remaining in the record.
1617 * Return the length of the name, including the terminating NUL.
1619 * If we don't find a terminating NUL, return -1 and set *err and
1620 * *err_info appropriately.
1623 name_resolution_block_find_name_end(const char *p, guint record_len, int *err,
1630 if (record_len == 0) {
1632 * We ran out of bytes in the record without
1635 *err = WTAP_ERR_BAD_FILE;
1636 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1640 break; /* that's the terminating NUL */
1643 namelen++; /* count this byte */
1646 /* Include the NUL in the name length. */
1651 pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock _U_,int *err, gchar **err_info)
1655 pcapng_name_resolution_block_t nrb;
1663 * Is this block long enough to be an NRB?
1665 if (bh->block_total_length < MIN_NRB_SIZE) {
1669 *err = WTAP_ERR_BAD_FILE;
1670 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u of an NRB is less than the minimum NRB size %u",
1671 bh->block_total_length, MIN_NRB_SIZE);
1675 /* Don't try to allocate memory for a huge number of options, as
1676 that might fail and, even if it succeeds, it might not leave
1677 any address space or memory+backing store for anything else.
1679 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1680 We check for this *after* checking the SHB for its byte
1681 order magic number, so that non-pcap-ng files are less
1682 likely to be treated as bad pcap-ng files. */
1683 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1684 *err = WTAP_ERR_BAD_FILE;
1685 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1686 bh->block_total_length, MAX_BLOCK_SIZE);
1690 to_read = bh->block_total_length - 8 - 4; /* We have read the header adn should not read the final block_total_length */
1692 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1695 * Start out with a buffer big enough for an IPv6 address and one
1696 * 64-byte name; we'll make the buffer bigger if necessary.
1698 ws_buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1700 while (block_read < to_read) {
1702 * There must be at least one record's worth of data
1705 if ((size_t)(to_read - block_read) < sizeof nrb) {
1706 ws_buffer_free(&nrb_rec);
1707 *err = WTAP_ERR_BAD_FILE;
1708 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1709 to_read - block_read,
1713 if (!wtap_read_bytes(fh, &nrb, sizeof nrb, err, err_info)) {
1714 ws_buffer_free(&nrb_rec);
1715 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1718 block_read += (int)sizeof nrb;
1720 if (pn->byte_swapped) {
1721 nrb.record_type = GUINT16_SWAP_LE_BE(nrb.record_type);
1722 nrb.record_len = GUINT16_SWAP_LE_BE(nrb.record_len);
1725 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1726 ws_buffer_free(&nrb_rec);
1727 *err = WTAP_ERR_BAD_FILE;
1728 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1729 to_read - block_read,
1730 nrb.record_len + PADDING4(nrb.record_len));
1733 switch (nrb.record_type) {
1734 case NRES_ENDOFRECORD:
1735 /* There shouldn't be any more data */
1738 case NRES_IP4RECORD:
1740 * The smallest possible record must have
1741 * a 4-byte IPv4 address, hence a minimum
1744 * (The pcap-NG spec really indicates
1745 * that it must be at least 5 bytes,
1746 * as there must be at least one name,
1747 * and it really must be at least 6
1748 * bytes, as the name mustn't be null,
1749 * but there's no need to fail if there
1750 * aren't any names at all, and we
1751 * should report a null name as such.)
1753 if (nrb.record_len < 4) {
1754 ws_buffer_free(&nrb_rec);
1755 *err = WTAP_ERR_BAD_FILE;
1756 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1760 ws_buffer_assure_space(&nrb_rec, nrb.record_len);
1761 if (!wtap_read_bytes(fh, ws_buffer_start_ptr(&nrb_rec),
1762 nrb.record_len, err, err_info)) {
1763 ws_buffer_free(&nrb_rec);
1764 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1767 block_read += nrb.record_len;
1769 if (pn->add_new_ipv4) {
1771 * Scan through all the names in
1772 * the record and add them.
1775 ws_buffer_start_ptr(&nrb_rec), 4);
1776 if (pn->byte_swapped)
1777 v4_addr = GUINT32_SWAP_LE_BE(v4_addr);
1778 for (namep = (char *)ws_buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1780 namep += namelen, record_len -= namelen) {
1782 * Scan forward for a null
1785 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1786 if (namelen == -1) {
1787 ws_buffer_free(&nrb_rec);
1788 return FALSE; /* fail */
1790 pn->add_new_ipv4(v4_addr, namep);
1794 if (!file_skip(fh, PADDING4(nrb.record_len), err)) {
1795 ws_buffer_free(&nrb_rec);
1798 block_read += PADDING4(nrb.record_len);
1800 case NRES_IP6RECORD:
1802 * The smallest possible record must have
1803 * a 16-byte IPv6 address, hence a minimum
1806 * (The pcap-NG spec really indicates
1807 * that it must be at least 17 bytes,
1808 * as there must be at least one name,
1809 * and it really must be at least 18
1810 * bytes, as the name mustn't be null,
1811 * but there's no need to fail if there
1812 * aren't any names at all, and we
1813 * should report a null name as such.)
1815 if (nrb.record_len < 16) {
1816 ws_buffer_free(&nrb_rec);
1817 *err = WTAP_ERR_BAD_FILE;
1818 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1822 if (to_read < nrb.record_len) {
1823 ws_buffer_free(&nrb_rec);
1824 *err = WTAP_ERR_BAD_FILE;
1825 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u > remaining data in NRB",
1829 ws_buffer_assure_space(&nrb_rec, nrb.record_len);
1830 if (!wtap_read_bytes(fh, ws_buffer_start_ptr(&nrb_rec),
1831 nrb.record_len, err, err_info)) {
1832 ws_buffer_free(&nrb_rec);
1835 block_read += nrb.record_len;
1837 if (pn->add_new_ipv6) {
1838 for (namep = (char *)ws_buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1840 namep += namelen, record_len -= namelen) {
1842 * Scan forward for a null
1845 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1846 if (namelen == -1) {
1847 ws_buffer_free(&nrb_rec);
1848 return FALSE; /* fail */
1850 pn->add_new_ipv6(ws_buffer_start_ptr(&nrb_rec),
1855 if (!file_skip(fh, PADDING4(nrb.record_len), err)) {
1856 ws_buffer_free(&nrb_rec);
1859 block_read += PADDING4(nrb.record_len);
1862 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1863 if (!file_skip(fh, nrb.record_len + PADDING4(nrb.record_len), err)) {
1864 ws_buffer_free(&nrb_rec);
1867 block_read += nrb.record_len + PADDING4(nrb.record_len);
1872 ws_buffer_free(&nrb_rec);
1877 pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock,int *err, gchar **err_info)
1880 guint to_read, opt_cont_buf_len;
1881 pcapng_interface_statistics_block_t isb;
1882 pcapng_option_header_t oh;
1883 guint8 *option_content = NULL; /* Allocate as large as the options block */
1886 * Is this block long enough to be an ISB?
1888 if (bh->block_total_length < MIN_ISB_SIZE) {
1892 *err = WTAP_ERR_BAD_FILE;
1893 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1894 bh->block_total_length, MIN_ISB_SIZE);
1898 /* Don't try to allocate memory for a huge number of options, as
1899 that might fail and, even if it succeeds, it might not leave
1900 any address space or memory+backing store for anything else.
1902 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1903 We check for this *after* checking the SHB for its byte
1904 order magic number, so that non-pcap-ng files are less
1905 likely to be treated as bad pcap-ng files. */
1906 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1907 *err = WTAP_ERR_BAD_FILE;
1908 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1909 bh->block_total_length, MAX_BLOCK_SIZE);
1913 /* "Interface Statistics Block" read fixed part */
1914 if (!wtap_read_bytes(fh, &isb, sizeof isb, err, err_info)) {
1915 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1919 if (pn->byte_swapped) {
1920 wblock->data.if_stats.interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
1921 wblock->data.if_stats.ts_high = GUINT32_SWAP_LE_BE(isb.timestamp_high);
1922 wblock->data.if_stats.ts_low = GUINT32_SWAP_LE_BE(isb.timestamp_low);
1924 wblock->data.if_stats.interface_id = isb.interface_id;
1925 wblock->data.if_stats.ts_high = isb.timestamp_high;
1926 wblock->data.if_stats.ts_low = isb.timestamp_low;
1928 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1930 /* Option defaults */
1931 wblock->data.if_stats.opt_comment = NULL;
1932 wblock->data.if_stats.isb_ifrecv = -1;
1933 wblock->data.if_stats.isb_ifdrop = -1;
1934 wblock->data.if_stats.isb_filteraccept = -1;
1935 wblock->data.if_stats.isb_osdrop = -1;
1936 wblock->data.if_stats.isb_usrdeliv = -1;
1939 to_read = bh->block_total_length -
1940 (MIN_BLOCK_SIZE + (guint)sizeof isb); /* fixed and variable part, including padding */
1942 /* Allocate enough memory to hold all options */
1943 opt_cont_buf_len = to_read;
1944 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
1945 if (opt_cont_buf_len != 0 && option_content == NULL) {
1946 *err = ENOMEM; /* we assume we're out of memory */
1950 while (to_read != 0) {
1952 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1953 if (bytes_read <= 0) {
1954 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1957 to_read -= bytes_read;
1959 /* handle option content */
1960 switch (oh.option_code) {
1961 case(0): /* opt_endofopt */
1963 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1965 /* padding should be ok here, just get out of this */
1968 case(1): /* opt_comment */
1969 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1970 wblock->data.if_stats.opt_comment = g_strndup((char *)option_content, oh.option_length);
1971 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1973 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1976 case(2): /* isb_starttime */
1977 if (oh.option_length == 8) {
1980 /* Don't cast a guint8 * into a guint32 *--the
1981 * guint8 * may not point to something that's
1982 * aligned correctly.
1984 memcpy(&high, option_content, sizeof(guint32));
1985 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1986 if (pn->byte_swapped) {
1987 high = GUINT32_SWAP_LE_BE(high);
1988 low = GUINT32_SWAP_LE_BE(low);
1990 wblock->data.if_stats.isb_starttime = (guint64)high;
1991 wblock->data.if_stats.isb_starttime <<= 32;
1992 wblock->data.if_stats.isb_starttime += (guint64)low;
1993 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1995 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1998 case(3): /* isb_endtime */
1999 if (oh.option_length == 8) {
2002 /* Don't cast a guint8 * into a guint32 *--the
2003 * guint8 * may not point to something that's
2004 * aligned correctly.
2006 memcpy(&high, option_content, sizeof(guint32));
2007 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
2008 if (pn->byte_swapped) {
2009 high = GUINT32_SWAP_LE_BE(high);
2010 low = GUINT32_SWAP_LE_BE(low);
2012 wblock->data.if_stats.isb_endtime = (guint64)high;
2013 wblock->data.if_stats.isb_endtime <<= 32;
2014 wblock->data.if_stats.isb_endtime += (guint64)low;
2015 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
2017 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
2020 case(4): /* isb_ifrecv */
2021 if (oh.option_length == 8) {
2022 /* Don't cast a guint8 * into a guint64 *--the
2023 * guint8 * may not point to something that's
2024 * aligned correctly.
2026 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
2027 if (pn->byte_swapped)
2028 wblock->data.if_stats.isb_ifrecv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifrecv);
2029 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
2031 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
2034 case(5): /* isb_ifdrop */
2035 if (oh.option_length == 8) {
2036 /* Don't cast a guint8 * into a guint64 *--the
2037 * guint8 * may not point to something that's
2038 * aligned correctly.
2040 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
2041 if (pn->byte_swapped)
2042 wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifdrop);
2043 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
2045 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
2048 case(6): /* isb_filteraccept 6 */
2049 if (oh.option_length == 8) {
2050 /* Don't cast a guint8 * into a guint64 *--the
2051 * guint8 * may not point to something that's
2052 * aligned correctly.
2054 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
2055 if (pn->byte_swapped)
2056 wblock->data.if_stats.isb_filteraccept = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_filteraccept);
2057 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
2059 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
2062 case(7): /* isb_osdrop 7 */
2063 if (oh.option_length == 8) {
2064 /* Don't cast a guint8 * into a guint64 *--the
2065 * guint8 * may not point to something that's
2066 * aligned correctly.
2068 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
2069 if (pn->byte_swapped)
2070 wblock->data.if_stats.isb_osdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
2071 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
2073 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
2076 case(8): /* isb_usrdeliv 8 */
2077 if (oh.option_length == 8) {
2078 /* Don't cast a guint8 * into a guint64 *--the
2079 * guint8 * may not point to something that's
2080 * aligned correctly.
2082 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
2083 if (pn->byte_swapped)
2084 wblock->data.if_stats.isb_usrdeliv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_usrdeliv);
2085 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
2087 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
2091 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
2092 oh.option_code, oh.option_length);
2096 g_free(option_content);
2103 pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock _U_, int *err, gchar **err_info)
2106 guint32 block_total_length;
2108 block_handler *handler;
2111 if (bh->block_total_length < MIN_BLOCK_SIZE) {
2112 *err = WTAP_ERR_BAD_FILE;
2113 *err_info = g_strdup_printf("pcapng_read_unknown_block: total block length %u of an unknown block type is less than the minimum block size %u",
2114 bh->block_total_length, MIN_BLOCK_SIZE);
2118 /* add padding bytes to "block total length" */
2119 /* (the "block total length" of some example files don't contain any padding bytes!) */
2120 if (bh->block_total_length % 4) {
2121 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
2123 block_total_length = bh->block_total_length;
2126 block_read = block_total_length - MIN_BLOCK_SIZE;
2130 * Do we have a handler for this block type?
2132 if (block_handlers != NULL &&
2133 (handler = (block_handler *)g_hash_table_lookup(block_handlers,
2134 GUINT_TO_POINTER(bh->block_type))) != NULL) {
2135 /* Yes - call it to read this block type. */
2136 if (!handler->read(fh, block_read, pn->byte_swapped,
2137 wblock->packet_header, wblock->frame_buffer,
2143 /* No. Skip over this unknown block. */
2144 if (!file_skip(fh, block_read, err)) {
2153 static block_return_val
2154 pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2156 block_return_val ret;
2157 pcapng_block_header_t bh;
2158 guint32 block_total_length;
2160 memset(&(wblock->data), 0, sizeof(wblock->data));
2162 /* Try to read the (next) block header */
2163 if (!wtap_read_bytes_or_eof(fh, &bh, sizeof bh, err, err_info)) {
2164 pcapng_debug1("pcapng_read_block: wtap_read_bytes_or_eof() failed, err = %d.", *err);
2165 if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
2167 * Short read or EOF.
2169 * If we're reading this as part of an open,
2170 * the file is too short to be a pcap-ng file.
2172 * If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
2173 * PCAPNG_BLOCK_ERROR the same, so we can just return
2174 * PCAPNG_BLOCK_NOT_SHB in both cases.
2176 return PCAPNG_BLOCK_NOT_SHB;
2178 return PCAPNG_BLOCK_ERROR;
2181 if (pn->byte_swapped) {
2182 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2183 bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
2186 wblock->type = bh.block_type;
2188 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2191 * SHBs have to be treated differently from other blocks, as we
2192 * might be doing an open and attempting to read a block at the
2193 * beginning of the file to see if it's a pcap-ng file or not.
2195 if (bh.block_type == BLOCK_TYPE_SHB) {
2196 ret = pcapng_read_section_header_block(fh, &bh, pn, wblock, err, err_info);
2197 if (ret != PCAPNG_BLOCK_OK) {
2201 if (!pn->shb_read) {
2203 * No SHB seen yet, so we're trying to read the first block
2204 * during an open, to see whether it's an SHB; if what we
2205 * read doesn't look like an SHB, this isn't a pcap-ng file.
2209 return PCAPNG_BLOCK_NOT_SHB;
2211 switch (bh.block_type) {
2212 case(BLOCK_TYPE_IDB):
2213 if (!pcapng_read_if_descr_block(wth, fh, &bh, pn, wblock, err, err_info))
2214 return PCAPNG_BLOCK_ERROR;
2216 case(BLOCK_TYPE_PB):
2217 if (!pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE))
2218 return PCAPNG_BLOCK_ERROR;
2220 case(BLOCK_TYPE_SPB):
2221 if (!pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info))
2222 return PCAPNG_BLOCK_ERROR;
2224 case(BLOCK_TYPE_EPB):
2225 if (!pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE))
2226 return PCAPNG_BLOCK_ERROR;
2228 case(BLOCK_TYPE_NRB):
2229 if (!pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info))
2230 return PCAPNG_BLOCK_ERROR;
2232 case(BLOCK_TYPE_ISB):
2233 if (!pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info))
2234 return PCAPNG_BLOCK_ERROR;
2237 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2238 if (!pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info))
2239 return PCAPNG_BLOCK_ERROR;
2244 /* sanity check: first and second block lengths must match */
2245 if (!wtap_read_bytes(fh, &block_total_length, sizeof block_total_length,
2247 pcapng_debug0("pcapng_check_block_trailer: couldn't read second block length");
2248 return PCAPNG_BLOCK_ERROR;
2251 if (pn->byte_swapped)
2252 block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
2254 if (block_total_length != bh.block_total_length) {
2255 *err = WTAP_ERR_BAD_FILE;
2256 *err_info = g_strdup_printf("pcapng_check_block_trailer: total block lengths (first %u and second %u) don't match",
2257 bh.block_total_length, block_total_length);
2258 return PCAPNG_BLOCK_ERROR;
2260 return PCAPNG_BLOCK_OK;
2263 /* Process an IDB that we've just read. */
2265 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2267 wtapng_if_descr_t int_data;
2268 interface_info_t iface_info;
2270 int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2271 int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2272 int_data.link_type = wblock->data.if_descr.link_type;
2273 int_data.snap_len = wblock->data.if_descr.snap_len;
2275 int_data.opt_comment = wblock->data.if_descr.opt_comment;
2276 int_data.if_name = wblock->data.if_descr.if_name;
2277 int_data.if_description = wblock->data.if_descr.if_description;
2278 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2279 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2280 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2281 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2282 int_data.if_speed = wblock->data.if_descr.if_speed;
2283 int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2284 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2285 int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2286 int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2287 int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2288 int_data.if_os = wblock->data.if_descr.if_os;
2289 int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2290 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2291 /* Interface statistics */
2292 int_data.num_stat_entries = 0;
2293 int_data.interface_statistics = NULL;
2295 g_array_append_val(wth->interface_data, int_data);
2297 iface_info.wtap_encap = wblock->data.if_descr.wtap_encap;
2298 iface_info.snap_len = wblock->data.if_descr.snap_len;
2299 iface_info.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2300 iface_info.tsprecision = wblock->data.if_descr.tsprecision;
2302 g_array_append_val(pcapng->interfaces, iface_info);
2305 /* classic wtap: open capture file */
2306 wtap_open_return_val
2307 pcapng_open(wtap *wth, int *err, gchar **err_info)
2310 wtapng_block_t wblock;
2312 pcapng_block_header_t bh;
2313 gint64 saved_offset;
2315 pn.shb_read = FALSE;
2316 /* we don't know the byte swapping of the file yet */
2317 pn.byte_swapped = FALSE;
2319 pn.version_major = -1;
2320 pn.version_minor = -1;
2321 pn.interfaces = NULL;
2323 /* we don't expect any packet blocks yet */
2324 wblock.frame_buffer = NULL;
2325 wblock.packet_header = NULL;
2327 pcapng_debug0("pcapng_open: opening file");
2328 /* read first block */
2329 switch (pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info)) {
2331 case PCAPNG_BLOCK_OK:
2335 case PCAPNG_BLOCK_NOT_SHB:
2336 /* An error indicating that this isn't a pcap-ng file. */
2337 pcapng_free_wtapng_block_data(&wblock);
2340 return WTAP_OPEN_NOT_MINE;
2342 case PCAPNG_BLOCK_ERROR:
2343 /* An I/O error, or this probably *is* a pcap-ng file but not a valid one. */
2344 pcapng_free_wtapng_block_data(&wblock);
2345 return WTAP_OPEN_ERROR;
2348 /* first block must be a "Section Header Block" */
2349 if (wblock.type != BLOCK_TYPE_SHB) {
2351 * XXX - check for damage from transferring a file
2352 * between Windows and UN*X as text rather than
2355 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2356 pcapng_free_wtapng_block_data(&wblock);
2357 return WTAP_OPEN_NOT_MINE;
2362 * At this point, we've decided this is a pcap-NG file, not
2363 * some other type of file, so we can't return WTAP_OPEN_NOT_MINE
2366 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2367 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2368 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2369 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2371 wth->file_encap = WTAP_ENCAP_UNKNOWN;
2372 wth->snapshot_length = 0;
2373 wth->file_tsprec = WTAP_TSPREC_UNKNOWN;
2374 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2375 wth->priv = (void *)pcapng;
2377 pcapng->interfaces = g_array_new(FALSE, FALSE, sizeof(interface_info_t));
2379 wth->subtype_read = pcapng_read;
2380 wth->subtype_seek_read = pcapng_seek_read;
2381 wth->subtype_close = pcapng_close;
2382 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
2384 /* Loop over all IDB:s that appear before any packets */
2386 /* peek at next block */
2387 /* Try to read the (next) block header */
2388 saved_offset = file_tell(wth->fh);
2389 if (!wtap_read_bytes_or_eof(wth->fh, &bh, sizeof bh, err, err_info)) {
2392 pcapng_debug0("No more IDBs available...");
2395 pcapng_debug1("pcapng_open: Check for more IDB:s, wtap_read_bytes_or_eof() failed, err = %d.", *err);
2396 return WTAP_OPEN_ERROR;
2399 /* go back to where we were */
2400 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2402 if (pn.byte_swapped) {
2403 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2406 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2408 if (bh.block_type != BLOCK_TYPE_IDB) {
2409 break; /* No more IDB:s */
2411 if (pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
2413 pcapng_debug0("No more IDBs available...");
2414 pcapng_free_wtapng_block_data(&wblock);
2417 pcapng_debug0("pcapng_open: couldn't read IDB");
2418 pcapng_free_wtapng_block_data(&wblock);
2419 return WTAP_OPEN_ERROR;
2422 pcapng_process_idb(wth, pcapng, &wblock);
2423 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i",
2424 wth->interface_data->len, wth->file_encap);
2426 return WTAP_OPEN_MINE;
2430 /* classic wtap: read packet */
2432 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2434 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2435 wtapng_block_t wblock;
2436 wtapng_if_descr_t *wtapng_if_descr;
2437 wtapng_if_stats_t if_stats;
2439 wblock.frame_buffer = wth->frame_buffer;
2440 wblock.packet_header = &wth->phdr;
2442 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2443 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2445 /* read next block */
2447 *data_offset = file_tell(wth->fh);
2448 pcapng_debug1("pcapng_read: data_offset is %" G_GINT64_MODIFIER "d", *data_offset);
2449 if (pcapng_read_block(wth, wth->fh, pcapng, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
2450 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2451 pcapng_debug0("pcapng_read: couldn't read packet block");
2455 switch (wblock.type) {
2457 case(BLOCK_TYPE_SHB):
2458 /* We don't currently support multi-section files. */
2459 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2460 wth->phdr.pkt_tsprec = WTAP_TSPREC_UNKNOWN;
2461 *err = WTAP_ERR_UNSUPPORTED;
2462 *err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
2465 case(BLOCK_TYPE_PB):
2466 case(BLOCK_TYPE_SPB):
2467 case(BLOCK_TYPE_EPB):
2468 /* packet block - we've found a packet */
2471 case(BLOCK_TYPE_IDB):
2472 /* A new interface */
2473 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2474 pcapng_process_idb(wth, pcapng, &wblock);
2477 case(BLOCK_TYPE_NRB):
2478 /* More name resolution entries */
2479 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2482 case(BLOCK_TYPE_ISB):
2483 /* Another interface statistics report */
2484 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2485 if (wth->interface_data->len <= wblock.data.if_stats.interface_id) {
2486 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces", wblock.data.if_stats.interface_id);
2488 /* Get the interface description */
2489 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2490 if (wtapng_if_descr->num_stat_entries == 0) {
2491 /* First ISB found, no previous entry */
2492 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2493 wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2496 if_stats.interface_id = wblock.data.if_stats.interface_id;
2497 if_stats.ts_high = wblock.data.if_stats.ts_high;
2498 if_stats.ts_low = wblock.data.if_stats.ts_low;
2500 if_stats.opt_comment = wblock.data.if_stats.opt_comment; /* NULL if not available */
2501 if_stats.isb_starttime = wblock.data.if_stats.isb_starttime;
2502 if_stats.isb_endtime = wblock.data.if_stats.isb_endtime;
2503 if_stats.isb_ifrecv = wblock.data.if_stats.isb_ifrecv;
2504 if_stats.isb_ifdrop = wblock.data.if_stats.isb_ifdrop;
2505 if_stats.isb_filteraccept = wblock.data.if_stats.isb_filteraccept;
2506 if_stats.isb_osdrop = wblock.data.if_stats.isb_osdrop;
2507 if_stats.isb_usrdeliv = wblock.data.if_stats.isb_usrdeliv;
2509 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2510 wtapng_if_descr->num_stat_entries++;
2515 /* XXX - improve handling of "unknown" blocks */
2516 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2523 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2524 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2530 /* classic wtap: seek to file position and read packet */
2532 pcapng_seek_read(wtap *wth, gint64 seek_off,
2533 struct wtap_pkthdr *phdr, Buffer *buf,
2534 int *err, gchar **err_info)
2536 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2537 block_return_val ret;
2538 wtapng_block_t wblock;
2541 /* seek to the right file position */
2542 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) < 0) {
2543 return FALSE; /* Seek error */
2545 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2547 wblock.frame_buffer = buf;
2548 wblock.packet_header = phdr;
2550 /* read the block */
2551 ret = pcapng_read_block(wth, wth->random_fh, pcapng, &wblock, err, err_info);
2552 pcapng_free_wtapng_block_data(&wblock);
2553 if (ret != PCAPNG_BLOCK_OK) {
2554 pcapng_debug1("pcapng_seek_read: couldn't read packet block (err=%d).",
2559 /* block must be a "Packet Block", an "Enhanced Packet Block",
2560 or a "Simple Packet Block" */
2561 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2562 wblock.type != BLOCK_TYPE_SPB) {
2563 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2571 /* classic wtap: close capture file */
2573 pcapng_close(wtap *wth)
2575 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2577 pcapng_debug0("pcapng_close: closing file");
2578 g_array_free(pcapng->interfaces, TRUE);
2583 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2585 pcapng_block_header_t bh;
2586 pcapng_section_header_block_t shb;
2587 const guint32 zero_pad = 0;
2588 gboolean have_options = FALSE;
2589 struct option option_hdr; /* guint16 type, guint16 value_length; */
2590 guint32 options_total_length = 0;
2591 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2592 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2595 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2596 /* Check if we should write comment option */
2597 if (wdh->shb_hdr->opt_comment) {
2598 have_options = TRUE;
2599 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2600 if ((comment_len % 4)) {
2601 comment_pad_len = 4 - (comment_len % 4);
2603 comment_pad_len = 0;
2605 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2608 /* Check if we should write shb_hardware option */
2609 if (wdh->shb_hdr->shb_hardware) {
2610 have_options = TRUE;
2611 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2612 if ((shb_hardware_len % 4)) {
2613 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2615 shb_hardware_pad_len = 0;
2617 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2620 /* Check if we should write shb_os option */
2621 if (wdh->shb_hdr->shb_os) {
2622 have_options = TRUE;
2623 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2624 if ((shb_os_len % 4)) {
2625 shb_os_pad_len = 4 - (shb_os_len % 4);
2629 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2632 /* Check if we should write shb_user_appl option */
2633 if (wdh->shb_hdr->shb_user_appl) {
2634 have_options = TRUE;
2635 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2636 if ((shb_user_appl_len % 4)) {
2637 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2639 shb_user_appl_pad_len = 0;
2641 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2644 /* End-of-options tag */
2645 options_total_length += 4;
2649 /* write block header */
2650 bh.block_type = BLOCK_TYPE_SHB;
2651 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2652 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2654 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2656 wdh->bytes_dumped += sizeof bh;
2658 /* write block fixed content */
2659 /* XXX - get these values from wblock? */
2660 shb.magic = 0x1A2B3C4D;
2661 shb.version_major = 1;
2662 shb.version_minor = 0;
2663 shb.section_length = -1;
2665 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2667 wdh->bytes_dumped += sizeof shb;
2669 /* XXX - write (optional) block options
2677 option_hdr.type = OPT_COMMENT;
2678 option_hdr.value_length = comment_len;
2679 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2681 wdh->bytes_dumped += 4;
2683 /* Write the comments string */
2684 pcapng_debug3("pcapng_write_section_header_block, comment:'%s' comment_len %u comment_pad_len %u" , wdh->shb_hdr->opt_comment, comment_len, comment_pad_len);
2685 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2687 wdh->bytes_dumped += comment_len;
2689 /* write padding (if any) */
2690 if (comment_pad_len != 0) {
2691 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2693 wdh->bytes_dumped += comment_pad_len;
2697 if (shb_hardware_len) {
2698 option_hdr.type = OPT_SHB_HARDWARE;
2699 option_hdr.value_length = shb_hardware_len;
2700 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2702 wdh->bytes_dumped += 4;
2704 /* Write the string */
2705 pcapng_debug3("pcapng_write_section_header_block, shb_hardware:'%s' shb_hardware_len %u shb_hardware_pad_len %u" , wdh->shb_hdr->shb_hardware, shb_hardware_len, shb_hardware_pad_len);
2706 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2708 wdh->bytes_dumped += shb_hardware_len;
2710 /* write padding (if any) */
2711 if (shb_hardware_pad_len != 0) {
2712 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2714 wdh->bytes_dumped += shb_hardware_pad_len;
2719 option_hdr.type = OPT_SHB_OS;
2720 option_hdr.value_length = shb_os_len;
2721 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2723 wdh->bytes_dumped += 4;
2725 /* Write the string */
2726 pcapng_debug3("pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u" , wdh->shb_hdr->shb_os, shb_os_len, shb_os_pad_len);
2727 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2729 wdh->bytes_dumped += shb_os_len;
2731 /* write padding (if any) */
2732 if (shb_os_pad_len != 0) {
2733 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2735 wdh->bytes_dumped += shb_os_pad_len;
2739 if (shb_user_appl_len) {
2740 option_hdr.type = OPT_SHB_USERAPPL;
2741 option_hdr.value_length = shb_user_appl_len;
2742 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2744 wdh->bytes_dumped += 4;
2746 /* Write the comments string */
2747 pcapng_debug3("pcapng_write_section_header_block, shb_user_appl:'%s' shb_user_appl_len %u shb_user_appl_pad_len %u" , wdh->shb_hdr->shb_user_appl, shb_user_appl_len, shb_user_appl_pad_len);
2748 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2750 wdh->bytes_dumped += shb_user_appl_len;
2752 /* write padding (if any) */
2753 if (shb_user_appl_pad_len != 0) {
2754 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2756 wdh->bytes_dumped += shb_user_appl_pad_len;
2760 /* Write end of options if we have otions */
2762 option_hdr.type = OPT_EOFOPT;
2763 option_hdr.value_length = 0;
2764 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2766 wdh->bytes_dumped += 4;
2769 /* write block footer */
2770 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2771 sizeof bh.block_total_length, err))
2773 wdh->bytes_dumped += sizeof bh.block_total_length;
2778 #define IDB_OPT_IF_NAME 2
2779 #define IDB_OPT_IF_DESCR 3
2780 #define IDB_OPT_IF_SPEED 8
2781 #define IDB_OPT_IF_TSRESOL 9
2782 #define IDB_OPT_IF_FILTER 11
2783 #define IDB_OPT_IF_OS 12
2786 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2788 pcapng_block_header_t bh;
2789 pcapng_interface_description_block_t idb;
2790 const guint32 zero_pad = 0;
2791 gboolean have_options = FALSE;
2792 struct option option_hdr; /* guint16 type, guint16 value_length; */
2793 guint32 options_total_length = 0;
2794 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2795 guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0, if_filter_str_pad_len = 0;
2798 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2799 int_data->link_type,
2800 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2801 int_data->snap_len);
2803 if (int_data->link_type == (guint16)-1) {
2804 *err = WTAP_ERR_UNWRITABLE_ENCAP;
2808 /* Calculate options length */
2809 if (int_data->opt_comment) {
2810 have_options = TRUE;
2811 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2812 if ((comment_len % 4)) {
2813 comment_pad_len = 4 - (comment_len % 4);
2815 comment_pad_len = 0;
2817 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2821 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2823 if (int_data->if_name) {
2824 have_options = TRUE;
2825 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2826 if ((if_name_len % 4)) {
2827 if_name_pad_len = 4 - (if_name_len % 4);
2829 if_name_pad_len = 0;
2831 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2835 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2837 if (int_data->if_description) {
2838 have_options = TRUE;
2839 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2840 if ((if_description_len % 4)) {
2841 if_description_pad_len = 4 - (if_description_len % 4);
2843 if_description_pad_len = 0;
2845 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2847 /* Currently not handled
2848 * if_IPv4addr 4 Interface network address and netmask.
2849 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2850 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2851 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2854 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2856 if (int_data->if_speed != 0) {
2857 have_options = TRUE;
2858 options_total_length = options_total_length + 8 + 4;
2861 * if_tsresol 9 Resolution of timestamps.
2863 if (int_data->if_tsresol != 0) {
2864 have_options = TRUE;
2865 options_total_length = options_total_length + 4 + 4;
2868 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2871 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2872 * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
2874 if (int_data->if_filter_str) {
2875 have_options = TRUE;
2876 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2877 if ((if_filter_str_len % 4)) {
2878 if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2880 if_filter_str_pad_len = 0;
2882 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2885 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2887 if (int_data->if_os) {
2888 have_options = TRUE;
2889 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2890 if ((if_os_len % 4)) {
2891 if_os_pad_len = 4 - (if_os_len % 4);
2895 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2898 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2899 * -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2901 if (int_data->if_fcslen != 0) {
2904 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2905 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2909 /* End-of-options tag */
2910 options_total_length += 4;
2913 /* write block header */
2914 bh.block_type = BLOCK_TYPE_IDB;
2915 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2917 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2919 wdh->bytes_dumped += sizeof bh;
2921 /* write block fixed content */
2922 idb.linktype = int_data->link_type;
2924 idb.snaplen = int_data->snap_len;
2926 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2928 wdh->bytes_dumped += sizeof idb;
2930 /* XXX - write (optional) block options */
2931 if (comment_len != 0) {
2932 option_hdr.type = OPT_COMMENT;
2933 option_hdr.value_length = comment_len;
2934 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2936 wdh->bytes_dumped += 4;
2938 /* Write the comments string */
2939 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , int_data->opt_comment, comment_len, comment_pad_len);
2940 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2942 wdh->bytes_dumped += comment_len;
2944 /* write padding (if any) */
2945 if (comment_pad_len != 0) {
2946 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2948 wdh->bytes_dumped += comment_pad_len;
2952 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2954 if (if_name_len !=0) {
2955 option_hdr.type = IDB_OPT_IF_NAME;
2956 option_hdr.value_length = if_name_len;
2957 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2959 wdh->bytes_dumped += 4;
2961 /* Write the comments string */
2962 pcapng_debug3("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , int_data->if_name, if_name_len, if_name_pad_len);
2963 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
2965 wdh->bytes_dumped += if_name_len;
2967 /* write padding (if any) */
2968 if (if_name_pad_len != 0) {
2969 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2971 wdh->bytes_dumped += if_name_pad_len;
2975 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2977 if (if_description_len != 0) {
2978 option_hdr.type = IDB_OPT_IF_NAME;
2979 option_hdr.value_length = if_description_len;
2980 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2982 wdh->bytes_dumped += 4;
2984 /* Write the comments string */
2985 pcapng_debug3("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , int_data->if_description, if_description_len, if_description_pad_len);
2986 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
2988 wdh->bytes_dumped += if_description_len;
2990 /* write padding (if any) */
2991 if (if_description_pad_len != 0) {
2992 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2994 wdh->bytes_dumped += if_description_pad_len;
2997 /* Currently not handled
2998 * if_IPv4addr 4 Interface network address and netmask.
2999 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
3000 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
3001 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
3004 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
3006 if (int_data->if_speed != 0) {
3007 option_hdr.type = IDB_OPT_IF_SPEED;
3008 option_hdr.value_length = 8;
3009 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3011 wdh->bytes_dumped += 4;
3013 /* Write the comments string */
3014 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
3015 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
3017 wdh->bytes_dumped += 8;
3020 * if_tsresol 9 Resolution of timestamps.
3021 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
3022 * If the Most Significant Bit is equal to zero, the remaining bits indicates
3023 * the resolution of the timestamp as as a negative power of 10
3025 if (int_data->if_tsresol != 0) {
3026 option_hdr.type = IDB_OPT_IF_TSRESOL;
3027 option_hdr.value_length = 1;
3028 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3030 wdh->bytes_dumped += 4;
3032 /* Write the time stamp resolution */
3033 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
3034 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
3036 wdh->bytes_dumped += 1;
3037 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
3039 wdh->bytes_dumped += 3;
3042 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
3045 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
3047 /* Libpcap string variant */
3048 if (if_filter_str_len !=0) {
3049 option_hdr.type = IDB_OPT_IF_FILTER;
3050 option_hdr.value_length = if_filter_str_len;
3051 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
3052 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3054 wdh->bytes_dumped += 4;
3056 /* Write the zero indicating libpcap filter variant */
3057 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
3059 wdh->bytes_dumped += 1;
3061 /* Write the comments string */
3062 pcapng_debug3("pcapng_write_if_descr_block, if_filter_str:'%s' if_filter_str_len %u if_filter_str_pad_len %u" , int_data->if_filter_str, if_filter_str_len, if_filter_str_pad_len);
3063 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
3064 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
3066 wdh->bytes_dumped += if_filter_str_len - 1;
3068 /* write padding (if any) */
3069 if (if_filter_str_pad_len != 0) {
3070 if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
3072 wdh->bytes_dumped += if_filter_str_pad_len;
3076 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
3078 if (if_os_len != 0) {
3079 option_hdr.type = IDB_OPT_IF_OS;
3080 option_hdr.value_length = if_os_len;
3081 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3083 wdh->bytes_dumped += 4;
3085 /* Write the comments string */
3086 pcapng_debug3("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , int_data->if_os, if_os_len, if_os_pad_len);
3087 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
3089 wdh->bytes_dumped += if_os_len;
3091 /* write padding (if any) */
3092 if (if_os_pad_len != 0) {
3093 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
3095 wdh->bytes_dumped += if_os_pad_len;
3100 option_hdr.type = OPT_EOFOPT;
3101 option_hdr.value_length = 0;
3102 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3104 wdh->bytes_dumped += 4;
3108 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
3111 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
3112 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
3115 /* write block footer */
3116 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3117 sizeof bh.block_total_length, err))
3119 wdh->bytes_dumped += sizeof bh.block_total_length;
3124 #define ISB_STARTTIME 2
3125 #define ISB_ENDTIME 3
3126 #define ISB_IFRECV 4
3127 #define ISB_IFDROP 5
3128 #define ISB_FILTERACCEPT 6
3129 #define ISB_OSDROP 7
3130 #define ISB_USRDELIV 8
3133 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
3136 pcapng_block_header_t bh;
3137 pcapng_interface_statistics_block_t isb;
3138 const guint32 zero_pad = 0;
3139 gboolean have_options = FALSE;
3140 struct option option_hdr; /* guint16 type, guint16 value_length; */
3141 guint32 options_total_length = 0;
3142 guint32 comment_len = 0;
3143 guint32 comment_pad_len = 0;
3145 pcapng_debug0("pcapng_write_interface_statistics_block");
3148 /* Calculate options length */
3149 if (if_stats->opt_comment) {
3150 have_options = TRUE;
3151 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
3152 if ((comment_len % 4)) {
3153 comment_pad_len = 4 - (comment_len % 4);
3155 comment_pad_len = 0;
3157 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3159 /*guint64 isb_starttime */
3160 if (if_stats->isb_starttime != 0) {
3161 have_options = TRUE;
3162 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3164 /*guint64 isb_endtime */
3165 if (if_stats->isb_endtime != 0) {
3166 have_options = TRUE;
3167 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3169 /*guint64 isb_ifrecv */
3170 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3171 have_options = TRUE;
3172 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3174 /*guint64 isb_ifdrop */
3175 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3176 have_options = TRUE;
3177 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3179 /*guint64 isb_filteraccept */
3180 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3181 have_options = TRUE;
3182 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3184 /*guint64 isb_osdrop */
3185 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3186 have_options = TRUE;
3187 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3189 /*guint64 isb_usrdeliv */
3190 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3191 have_options = TRUE;
3192 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3195 /* write block header */
3197 /* End-of-optios tag */
3198 options_total_length += 4;
3201 /* write block header */
3202 bh.block_type = BLOCK_TYPE_ISB;
3203 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3205 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3207 wdh->bytes_dumped += sizeof bh;
3209 /* write block fixed content */
3210 isb.interface_id = if_stats->interface_id;
3211 isb.timestamp_high = if_stats->ts_high;
3212 isb.timestamp_low = if_stats->ts_low;
3215 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3217 wdh->bytes_dumped += sizeof isb;
3219 /* write (optional) block options */
3221 option_hdr.type = OPT_COMMENT;
3222 option_hdr.value_length = comment_len;
3223 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3225 wdh->bytes_dumped += 4;
3227 /* Write the comments string */
3228 pcapng_debug3("pcapng_write_interface_statistics_block, comment:'%s' comment_len %u comment_pad_len %u" , if_stats->opt_comment, comment_len, comment_pad_len);
3229 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3231 wdh->bytes_dumped += comment_len;
3233 /* write padding (if any) */
3234 if (comment_pad_len != 0) {
3235 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3237 wdh->bytes_dumped += comment_pad_len;
3240 /*guint64 isb_starttime */
3241 if (if_stats->isb_starttime != 0) {
3244 option_hdr.type = ISB_STARTTIME;
3245 option_hdr.value_length = 8;
3246 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3247 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3248 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3250 wdh->bytes_dumped += 4;
3252 /* Write isb_starttime */
3253 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3254 if (!wtap_dump_file_write(wdh, &high, 4, err))
3256 wdh->bytes_dumped += 4;
3257 if (!wtap_dump_file_write(wdh, &low, 4, err))
3259 wdh->bytes_dumped += 4;
3261 /*guint64 isb_endtime */
3262 if (if_stats->isb_endtime != 0) {
3265 option_hdr.type = ISB_ENDTIME;
3266 option_hdr.value_length = 8;
3267 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3268 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3269 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3271 wdh->bytes_dumped += 4;
3273 /* Write isb_endtime */
3274 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3275 if (!wtap_dump_file_write(wdh, &high, 4, err))
3277 wdh->bytes_dumped += 4;
3278 if (!wtap_dump_file_write(wdh, &low, 4, err))
3280 wdh->bytes_dumped += 4;
3282 /*guint64 isb_ifrecv;*/
3283 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3284 option_hdr.type = ISB_IFRECV;
3285 option_hdr.value_length = 8;
3286 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3288 wdh->bytes_dumped += 4;
3290 /* Write isb_ifrecv */
3291 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3292 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3294 wdh->bytes_dumped += 8;
3296 /*guint64 isb_ifdrop;*/
3297 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3298 option_hdr.type = ISB_IFDROP;
3299 option_hdr.value_length = 8;
3300 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3302 wdh->bytes_dumped += 4;
3304 /* Write isb_ifdrop */
3305 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3306 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3308 wdh->bytes_dumped += 8;
3310 /*guint64 isb_filteraccept;*/
3311 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3312 option_hdr.type = ISB_FILTERACCEPT;
3313 option_hdr.value_length = 8;
3314 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3316 wdh->bytes_dumped += 4;
3318 /* Write isb_filteraccept */
3319 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3320 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3322 wdh->bytes_dumped += 8;
3324 /*guint64 isb_osdrop;*/
3325 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3326 option_hdr.type = ISB_OSDROP;
3327 option_hdr.value_length = 8;
3328 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3330 wdh->bytes_dumped += 4;
3332 /* Write isb_osdrop */
3333 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3334 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3336 wdh->bytes_dumped += 8;
3338 /*guint64 isb_usrdeliv;*/
3339 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3340 option_hdr.type = ISB_USRDELIV;
3341 option_hdr.value_length = 8;
3342 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3344 wdh->bytes_dumped += 4;
3346 /* Write isb_usrdeliv */
3347 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3348 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3350 wdh->bytes_dumped += 8;
3354 option_hdr.type = OPT_EOFOPT;
3355 option_hdr.value_length = 0;
3356 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3358 wdh->bytes_dumped += 4;
3361 /* write block footer */
3362 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3363 sizeof bh.block_total_length, err))
3365 wdh->bytes_dumped += sizeof bh.block_total_length;
3373 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3374 const struct wtap_pkthdr *phdr,
3375 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3377 pcapng_block_header_t bh;
3378 pcapng_enhanced_packet_block_t epb;
3380 const guint32 zero_pad = 0;
3383 gboolean have_options = FALSE;
3384 guint32 options_total_length = 0;
3385 struct option option_hdr;
3386 guint32 comment_len = 0, comment_pad_len = 0;
3387 wtapng_if_descr_t int_data;
3389 /* Don't write anything we're not willing to read. */
3390 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
3391 *err = WTAP_ERR_PACKET_TOO_LARGE;
3395 phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3396 if ((phdr_len + phdr->caplen) % 4) {
3397 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3402 /* Check if we should write comment option */
3403 if (phdr->opt_comment) {
3404 have_options = TRUE;
3405 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3406 if ((comment_len % 4)) {
3407 comment_pad_len = 4 - (comment_len % 4);
3409 comment_pad_len = 0;
3411 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3413 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3414 have_options = TRUE;
3415 options_total_length = options_total_length + 8;
3418 /* End-of optios tag */
3419 options_total_length += 4;
3422 /* write (enhanced) packet block header */
3423 bh.block_type = BLOCK_TYPE_EPB;
3424 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3426 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3428 wdh->bytes_dumped += sizeof bh;
3430 /* write block fixed content */
3431 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3432 epb.interface_id = phdr->interface_id;
3435 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3436 * data to pcap-NG files even if we *don't* have interface
3439 epb.interface_id = 0;
3442 * Split the 64-bit timestamp into two 32-bit pieces, using
3443 * the time stamp resolution for the interface.
3445 if (epb.interface_id >= wdh->interface_data->len) {
3447 * Our caller is doing something bad.
3449 *err = WTAP_ERR_INTERNAL;
3452 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3454 ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3455 (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3456 epb.timestamp_high = (guint32)(ts >> 32);
3457 epb.timestamp_low = (guint32)ts;
3458 epb.captured_len = phdr->caplen + phdr_len;
3459 epb.packet_len = phdr->len + phdr_len;
3461 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3463 wdh->bytes_dumped += sizeof epb;
3465 /* write pseudo header */
3466 if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3469 wdh->bytes_dumped += phdr_len;
3471 /* write packet data */
3472 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3474 wdh->bytes_dumped += phdr->caplen;
3476 /* write padding (if any) */
3478 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3480 wdh->bytes_dumped += pad_len;
3483 /* XXX - write (optional) block options */
3484 /* options defined in Section 2.5 (Options)
3485 * Name Code Length Description
3486 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3488 * Enhanced Packet Block options
3489 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3490 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3491 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3492 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3493 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3494 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3495 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3496 * The hash covers only the packet, not the header added by the capture driver:
3497 * this gives the possibility to calculate it inside the network card.
3498 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3499 * data acquisition system and the capture library.
3500 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3501 * between this packet and the preceding one.
3502 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3504 if (phdr->opt_comment) {
3505 option_hdr.type = OPT_COMMENT;
3506 option_hdr.value_length = comment_len;
3507 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3509 wdh->bytes_dumped += 4;
3511 /* Write the comments string */
3512 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3513 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3515 wdh->bytes_dumped += comment_len;
3517 /* write padding (if any) */
3518 if (comment_pad_len != 0) {
3519 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3521 wdh->bytes_dumped += comment_pad_len;
3524 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3528 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3529 option_hdr.type = OPT_EPB_FLAGS;
3530 option_hdr.value_length = 4;
3531 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3533 wdh->bytes_dumped += 4;
3534 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3536 wdh->bytes_dumped += 4;
3537 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3539 /* Write end of options if we have otions */
3541 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3543 wdh->bytes_dumped += 4;
3546 /* write block footer */
3547 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3548 sizeof bh.block_total_length, err))
3550 wdh->bytes_dumped += sizeof bh.block_total_length;
3556 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3558 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
3560 pcapng_block_header_t bh;
3561 pcapng_name_resolution_block_t nrb;
3563 gint rec_off, namelen, tot_rec_len;
3564 hashipv4_t *ipv4_hash_list_entry;
3565 hashipv6_t *ipv6_hash_list_entry;
3568 if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
3572 rec_off = 8; /* block type + block total length */
3573 bh.block_type = BLOCK_TYPE_NRB;
3574 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3575 rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3577 if (wdh->addrinfo_lists->ipv4_addr_list){
3579 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3580 while(ipv4_hash_list_entry != NULL){
3582 nrb.record_type = NRES_IP4RECORD;
3583 namelen = (gint)strlen(ipv4_hash_list_entry->name) + 1;
3584 nrb.record_len = 4 + namelen;
3585 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3587 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3588 /* We know the total length now; copy the block header. */
3589 memcpy(rec_data, &bh, sizeof(bh));
3592 memset(rec_data + rec_off, 0, 4);
3595 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3597 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3599 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3603 wdh->bytes_dumped += bh.block_total_length;
3605 /*Start a new NRB */
3606 rec_off = 8; /* block type + block total length */
3607 bh.block_type = BLOCK_TYPE_NRB;
3608 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3612 bh.block_total_length += tot_rec_len;
3613 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3615 memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
3617 memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
3619 memset(rec_data + rec_off, 0, PADDING4(namelen));
3620 rec_off += PADDING4(namelen);
3621 pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
3624 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3626 g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
3627 wdh->addrinfo_lists->ipv4_addr_list = NULL;
3630 if (wdh->addrinfo_lists->ipv6_addr_list){
3632 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3633 while(ipv6_hash_list_entry != NULL){
3635 nrb.record_type = NRES_IP6RECORD;
3636 namelen = (gint)strlen(ipv6_hash_list_entry->name) + 1;
3637 nrb.record_len = 16 + namelen; /* 16 bytes IPv6 address length */
3638 /* 2 bytes record type, 2 bytes length field */
3639 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3641 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3642 /* We know the total length now; copy the block header. */
3643 memcpy(rec_data, &bh, sizeof(bh));
3646 memset(rec_data + rec_off, 0, 4);
3649 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3651 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3653 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3657 wdh->bytes_dumped += bh.block_total_length;
3659 /*Start a new NRB */
3660 rec_off = 8; /* block type + block total length */
3661 bh.block_type = BLOCK_TYPE_NRB;
3662 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3666 bh.block_total_length += tot_rec_len;
3667 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3669 memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
3671 memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
3673 memset(rec_data + rec_off, 0, PADDING4(namelen));
3674 rec_off += PADDING4(namelen);
3675 pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
3678 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3680 g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
3681 wdh->addrinfo_lists->ipv6_addr_list = NULL;
3684 /* We know the total length now; copy the block header. */
3685 memcpy(rec_data, &bh, sizeof(bh));
3688 memset(rec_data + rec_off, 0, 4);
3691 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3693 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3695 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3701 wdh->bytes_dumped += bh.block_total_length;
3705 static gboolean pcapng_dump(wtap_dumper *wdh,
3706 const struct wtap_pkthdr *phdr,
3707 const guint8 *pd, int *err, gchar **err_info _U_)
3709 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3711 block_handler *handler;
3714 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3716 wtap_encap_string(phdr->pkt_encap));
3718 switch (phdr->rec_type) {
3720 case REC_TYPE_PACKET:
3721 if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3726 case REC_TYPE_FT_SPECIFIC_EVENT:
3727 case REC_TYPE_FT_SPECIFIC_REPORT:
3730 * Do we have a handler for this block type?
3732 if (block_handlers != NULL &&
3733 (handler = (block_handler *)g_hash_table_lookup(block_handlers,
3734 GUINT_TO_POINTER(pseudo_header->ftsrec.record_type))) != NULL) {
3735 /* Yes. Call it to write out this record. */
3736 if (!handler->write(wdh, phdr, pd, err))
3742 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
3748 /* We don't support writing this record type. */
3749 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
3757 /* Finish writing to a dump file.
3758 Returns TRUE on success, FALSE on failure. */
3759 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3763 /* Flush any hostname resolution info we may have */
3764 pcapng_write_name_resolution_block(wdh, err);
3766 for (i = 0; i < wdh->interface_data->len; i++) {
3768 /* Get the interface description */
3769 wtapng_if_descr_t int_data;
3771 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3772 for (j = 0; j < int_data.num_stat_entries; j++) {
3773 wtapng_if_stats_t if_stats;
3775 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3776 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3777 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3783 pcapng_debug0("pcapng_dump_close");
3788 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3791 pcapng_dump_open(wtap_dumper *wdh, int *err)
3795 pcapng_debug0("pcapng_dump_open");
3796 /* This is a pcapng file */
3797 wdh->subtype_write = pcapng_dump;
3798 wdh->subtype_close = pcapng_dump_close;
3800 if (wdh->interface_data->len == 0) {
3801 pcapng_debug0("There are no interfaces. Can't handle that...");
3802 *err = WTAP_ERR_INTERNAL;
3806 /* write the section header block */
3807 if (!pcapng_write_section_header_block(wdh, err)) {
3810 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3812 /* Write the Interface description blocks */
3813 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u",
3814 wdh->interface_data->len);
3816 for (i = 0; i < wdh->interface_data->len; i++) {
3818 /* Get the interface description */
3819 wtapng_if_descr_t int_data;
3821 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3823 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3833 /* Returns 0 if we could write the specified encapsulation type,
3834 an error indication otherwise. */
3835 int pcapng_dump_can_write_encap(int wtap_encap)
3837 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3839 wtap_encap_string(wtap_encap));
3841 /* Per-packet encapsulation is supported. */
3842 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3845 /* Make sure we can figure out this DLT type */
3846 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3847 return WTAP_ERR_UNWRITABLE_ENCAP;
3853 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3858 * indent-tabs-mode: nil
3861 * vi: set shiftwidth=4 tabstop=8 expandtab:
3862 * :indentSize=4:tabSize=8:noTabs=true: