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 file encoding 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 file encoding */
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 file encoding */
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 file encoding (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 file encoding */
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 file encoding */
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 file encoding */
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 file encoding */
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 file encoding 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 /* Option codes: 16-bit field */
210 #define OPT_EOFOPT 0x0000
211 #define OPT_COMMENT 0x0001
213 #define OPT_SHB_HARDWARE 0x0002
214 #define OPT_SHB_OS 0x0003
215 #define OPT_SHB_USERAPPL 0x0004
217 #define OPT_EPB_FLAGS 0x0002
218 #define OPT_EPB_HASH 0x0003
219 #define OPT_EPB_DROPCOUNT 0x0004
221 #define OPT_IDB_NAME 0x0002
222 #define OPT_IDB_DESCR 0x0003
223 #define OPT_IDB_IP4ADDR 0x0004
224 #define OPT_IDB_IP6ADDR 0x0005
225 #define OPT_IDB_MACADDR 0x0006
226 #define OPT_IDB_EUIADDR 0x0007
227 #define OPT_IDB_SPEED 0x0008
228 #define OPT_IDB_TSRESOL 0x0009
229 #define OPT_IDB_TZONE 0x000A
230 #define OPT_IDB_FILTER 0x000B
231 #define OPT_IDB_OS 0x000C
232 #define OPT_IDB_FCSLEN 0x000D
233 #define OPT_IDB_TSOFFSET 0x000E
235 #define OPT_ISB_STARTTIME 0x0002
236 #define OPT_ISB_ENDTIME 0x0003
237 #define OPT_ISB_IFRECV 0x0004
238 #define OPT_ISB_IFDROP 0x0005
239 #define OPT_ISB_FILTERACCEPT 0x0006
240 #define OPT_ISB_OSDROP 0x0007
241 #define OPT_ISB_USRDELIV 0x0008
243 #define OPT_NRB_DNSNAME 0x0002
244 #define OPT_NRB_DNSV4ADDR 0x0003
245 #define OPT_NRB_DNSV6ADDR 0x0004
247 /* MSBit of option code means "local type" */
248 #define OPT_LOCAL_FLAG 0x8000
250 /* Note: many of the defined structures for block data are defined in wtap.h */
252 /* Packet data - used for both Enhanced Packet Block and the obsolete Packet Block data */
253 typedef struct wtapng_packet_s {
255 guint32 ts_high; /* seconds since 1.1.1970 */
256 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
257 guint32 cap_len; /* data length in the file */
258 guint32 packet_len; /* data length on the wire */
259 guint32 interface_id; /* identifier of the interface. */
260 guint16 drops_count; /* drops count, only valid for packet block */
261 /* 0xffff if information no available */
263 /* XXX - put the packet data / pseudo_header here as well? */
266 /* Simple Packet data */
267 typedef struct wtapng_simple_packet_s {
269 guint32 cap_len; /* data length in the file */
270 guint32 packet_len; /* data length on the wire */
271 /* XXX - put the packet data / pseudo_header here as well? */
272 } wtapng_simple_packet_t;
274 /* Block data to be passed between functions during reading */
275 typedef struct wtapng_block_s {
276 guint32 type; /* block_type as defined by pcapng */
278 wtapng_section_t section;
279 wtapng_if_descr_t if_descr;
280 wtapng_name_res_t name_res;
281 wtapng_if_stats_t if_stats;
285 * XXX - currently don't know how to handle these!
287 * For one thing, when we're reading a block, they must be
288 * writable, i.e. not const, so that we can read into them,
289 * but, when we're writing a block, they can be const, and,
290 * in fact, they sometimes point to const values.
292 struct wtap_pkthdr *packet_header;
293 Buffer *frame_buffer;
296 /* Interface data in private struct */
297 typedef struct interface_info_s {
300 guint64 time_units_per_second;
305 gboolean shb_read; /**< Set when first SHB read, second read will fail */
306 gboolean byte_swapped;
307 guint16 version_major;
308 guint16 version_minor;
309 GArray *interfaces; /**< Interfaces found in the capture file. */
311 wtap_new_ipv4_callback_t add_new_ipv4;
312 wtap_new_ipv6_callback_t add_new_ipv6;
317 * Table for plugins to handle particular block types.
319 * A handler has a "read" routine and a "write" routine.
321 * A "read" routine returns a block as a libwiretap record, filling
322 * in the wtap_pkthdr structure with the appropriate record type and
323 * other information, and filling in the supplied Buffer with
324 * data for which there's no place in the wtap_pkthdr structure.
326 * A "write" routine takes a libwiretap record and Buffer and writes
334 static GHashTable *block_handlers;
337 register_pcapng_block_type_handler(guint block_type, block_reader read,
340 block_handler *handler;
342 if (block_handlers == NULL) {
344 * Create the table of block handlers.
346 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
347 * so we use "g_direct_hash()" and "g_direct_equal()".
349 block_handlers = g_hash_table_new_full(g_direct_hash,
353 handler = (block_handler *)g_malloc(sizeof *handler);
354 handler->read = read;
355 handler->write = write;
356 (void)g_hash_table_insert(block_handlers, GUINT_TO_POINTER(block_type),
361 * Tables for plugins to handle particular options for particular block
364 * An option has a handler routine, which is passed an indication of
365 * whether this section of the file is byte-swapped, the length of the
366 * option, the data of the option, a pointer to an error code, and a
367 * pointer to a pointer variable for an error string.
369 * It checks whether the length and option are valid, and, if they aren't,
370 * returns FALSE, setting the error code to the appropriate error (normally
371 * WTAP_ERR_BAD_FILE) and the error string to an appropriate string
372 * indicating the problem.
374 * Otherwise, if this section of the file is byte-swapped, it byte-swaps
375 * multi-byte numerical values, so that it's in the host byte order.
379 * Block types indices in the table of tables of option handlers.
381 * Block types are not guaranteed to be sequential, so we map the
382 * block types we support to a sequential set. Furthermore, all
383 * packet block types have the same set of options.
385 #define BT_INDEX_SHB 0
386 #define BT_INDEX_IDB 1
387 #define BT_INDEX_PBS 2 /* all packet blocks */
388 #define BT_INDEX_NRB 3
389 #define BT_INDEX_ISB 4
391 #define NUM_BT_INDICES 5
393 static GHashTable *option_handlers[NUM_BT_INDICES];
396 get_block_type_index(guint block_type, guint *bt_index)
400 switch (block_type) {
403 *bt_index = BT_INDEX_SHB;
407 *bt_index = BT_INDEX_IDB;
413 *bt_index = BT_INDEX_PBS;
417 *bt_index = BT_INDEX_NRB;
421 *bt_index = BT_INDEX_ISB;
426 * This is a block type we don't process; either we ignore it,
427 * in which case the options don't get processed, or there's
428 * a plugin routine to handle it, in which case that routine
429 * will do the option processing itself.
431 * XXX - report an error?
440 register_pcapng_option_handler(guint block_type, guint option_code,
441 option_handler handler)
445 if (!get_block_type_index(block_type, &bt_index))
448 if (option_handlers[bt_index] == NULL) {
450 * Create the table of option handlers for this block type.
452 * XXX - there's no "g_uint_hash()" or "g_uint_equal()",
453 * so we use "g_direct_hash()" and "g_direct_equal()".
455 option_handlers[bt_index] = g_hash_table_new_full(g_direct_hash,
459 (void)g_hash_table_insert(option_handlers[bt_index],
460 GUINT_TO_POINTER(option_code), handler);
462 #endif /* HAVE_PLUGINS */
465 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
466 guint8 *content, guint len, guint to_read,
467 int *err, gchar **err_info)
471 /* sanity check: don't run past the end of the block */
472 if (to_read < sizeof (*oh)) {
473 *err = WTAP_ERR_BAD_FILE;
474 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
478 /* read option header */
479 if (!wtap_read_bytes(fh, oh, sizeof (*oh), err, err_info)) {
480 pcapng_debug0("pcapng_read_option: failed to read option");
483 block_read = sizeof (*oh);
484 if (pn->byte_swapped) {
485 oh->option_code = GUINT16_SWAP_LE_BE(oh->option_code);
486 oh->option_length = GUINT16_SWAP_LE_BE(oh->option_length);
489 /* sanity check: don't run past the end of the block */
490 if (to_read < sizeof (*oh) + oh->option_length) {
491 *err = WTAP_ERR_BAD_FILE;
492 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
496 /* sanity check: option length */
497 if (len < oh->option_length) {
498 *err = WTAP_ERR_BAD_FILE;
499 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
503 /* read option content */
504 if (!wtap_read_bytes(fh, content, oh->option_length, err, err_info)) {
505 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
508 block_read += oh->option_length;
510 /* jump over potential padding bytes at end of option */
511 if ( (oh->option_length % 4) != 0) {
512 if (!file_skip(fh, 4 - (oh->option_length % 4), err))
514 block_read += 4 - (oh->option_length % 4);
522 pcapng_free_wtapng_block_data(wtapng_block_t *wblock)
524 switch (wblock->type) {
525 case(BLOCK_TYPE_SHB):
526 g_free(wblock->data.section.opt_comment);
527 g_free(wblock->data.section.shb_hardware);
528 g_free(wblock->data.section.shb_os);
529 g_free(wblock->data.section.shb_user_appl);
536 PCAPNG_BLOCK_NOT_SHB,
540 static block_return_val
541 pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
542 pcapng_t *pn, wtapng_block_t *wblock,
543 int *err, gchar **err_info)
546 guint to_read, opt_cont_buf_len;
547 pcapng_section_header_block_t shb;
548 pcapng_option_header_t oh;
549 guint8 *option_content = NULL; /* Allocate as large as the options block */
551 /* read fixed-length part of the block */
552 if (!wtap_read_bytes(fh, &shb, sizeof shb, err, err_info)) {
553 if (*err == WTAP_ERR_SHORT_READ) {
555 * This block is too short to be an SHB.
557 * If we're reading this as part of an open,
558 * the file is too short to be a pcap-ng file.
560 * If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
561 * PCAPNG_BLOCK_ERROR the same, so we can just return
562 * PCAPNG_BLOCK_NOT_SHB in both cases.
564 return PCAPNG_BLOCK_NOT_SHB;
566 return PCAPNG_BLOCK_ERROR;
569 /* is the magic number one we expect? */
572 /* this seems pcapng with correct byte order */
573 pn->byte_swapped = FALSE;
574 pn->version_major = shb.version_major;
575 pn->version_minor = shb.version_minor;
577 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
578 pn->version_major, pn->version_minor, bh->block_total_length);
581 /* this seems pcapng with swapped byte order */
582 pn->byte_swapped = TRUE;
583 pn->version_major = GUINT16_SWAP_LE_BE(shb.version_major);
584 pn->version_minor = GUINT16_SWAP_LE_BE(shb.version_minor);
586 /* tweak the block length to meet current swapping that we know now */
587 bh->block_total_length = GUINT32_SWAP_LE_BE(bh->block_total_length);
589 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
590 pn->version_major, pn->version_minor, bh->block_total_length);
593 /* Not a "pcapng" magic number we know about. */
594 *err = WTAP_ERR_BAD_FILE;
595 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
598 * See above comment about PCAPNG_BLOCK_NOT_SHB.
600 return PCAPNG_BLOCK_NOT_SHB;
604 * Is this block long enough to be an SHB?
606 if (bh->block_total_length < MIN_SHB_SIZE) {
610 *err = WTAP_ERR_BAD_FILE;
611 *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",
612 bh->block_total_length, MIN_SHB_SIZE);
613 return PCAPNG_BLOCK_ERROR;
616 /* OK, at this point we assume it's a pcap-ng file.
618 Don't try to allocate memory for a huge number of options, as
619 that might fail and, even if it succeeds, it might not leave
620 any address space or memory+backing store for anything else.
622 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
623 We check for this *after* checking the SHB for its byte
624 order magic number, so that non-pcap-ng files are less
625 likely to be treated as bad pcap-ng files. */
626 if (bh->block_total_length > MAX_BLOCK_SIZE) {
627 *err = WTAP_ERR_BAD_FILE;
628 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
629 bh->block_total_length, MAX_BLOCK_SIZE);
630 return PCAPNG_BLOCK_ERROR;
633 /* We currently only suport one SHB */
634 if (pn->shb_read == TRUE) {
635 *err = WTAP_ERR_UNSUPPORTED;
636 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported");
637 return PCAPNG_BLOCK_ERROR;
640 /* we currently only understand SHB V1.0 */
641 if (pn->version_major != 1 || pn->version_minor > 0) {
642 *err = WTAP_ERR_UNSUPPORTED;
643 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
644 pn->version_major, pn->version_minor);
645 return PCAPNG_BLOCK_ERROR;
649 /* 64bit section_length (currently unused) */
650 if (pn->byte_swapped) {
651 wblock->data.section.section_length = GUINT64_SWAP_LE_BE(shb.section_length);
653 wblock->data.section.section_length = shb.section_length;
657 to_read = bh->block_total_length - MIN_SHB_SIZE;
659 /* Allocate enough memory to hold all options */
660 opt_cont_buf_len = to_read;
661 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
662 if (opt_cont_buf_len != 0 && option_content == NULL) {
663 *err = ENOMEM; /* we assume we're out of memory */
664 return PCAPNG_BLOCK_ERROR;
666 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
667 while (to_read != 0) {
669 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
670 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
671 if (bytes_read <= 0) {
672 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
673 return PCAPNG_BLOCK_ERROR;
675 to_read -= bytes_read;
677 /* handle option content */
678 switch (oh.option_code) {
681 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
683 /* padding should be ok here, just get out of this */
687 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
688 g_free(wblock->data.section.opt_comment);
689 wblock->data.section.opt_comment = g_strndup((char *)option_content, oh.option_length);
690 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
692 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
695 case(OPT_SHB_HARDWARE):
696 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
697 g_free(wblock->data.section.shb_hardware);
698 wblock->data.section.shb_hardware = g_strndup((char *)option_content, oh.option_length);
699 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
701 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
705 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
706 g_free(wblock->data.section.shb_os);
707 wblock->data.section.shb_os = g_strndup((char *)option_content, oh.option_length);
708 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
710 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
713 case(OPT_SHB_USERAPPL):
714 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
715 g_free(wblock->data.section.shb_user_appl);
716 wblock->data.section.shb_user_appl = g_strndup((char *)option_content, oh.option_length);
717 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
719 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
723 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
724 oh.option_code, oh.option_length);
727 g_free(option_content);
729 return PCAPNG_BLOCK_OK;
733 /* "Interface Description Block" */
735 pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
736 pcapng_t *pn, wtapng_block_t *wblock, int *err,
739 guint64 time_units_per_second = 1000000; /* default = 10^6 */
740 int tsprecision = WTAP_TSPREC_USEC;
742 guint to_read, opt_cont_buf_len;
743 pcapng_interface_description_block_t idb;
744 pcapng_option_header_t oh;
745 guint8 *option_content = NULL; /* Allocate as large as the options block */
748 * Is this block long enough to be an IDB?
750 if (bh->block_total_length < MIN_IDB_SIZE) {
754 *err = WTAP_ERR_BAD_FILE;
755 *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",
756 bh->block_total_length, MIN_IDB_SIZE);
760 /* Don't try to allocate memory for a huge number of options, as
761 that might fail and, even if it succeeds, it might not leave
762 any address space or memory+backing store for anything else.
764 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
765 We check for this *after* checking the SHB for its byte
766 order magic number, so that non-pcap-ng files are less
767 likely to be treated as bad pcap-ng files. */
768 if (bh->block_total_length > MAX_BLOCK_SIZE) {
769 *err = WTAP_ERR_BAD_FILE;
770 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
771 bh->block_total_length, MAX_BLOCK_SIZE);
775 /* read block content */
776 if (!wtap_read_bytes(fh, &idb, sizeof idb, err, err_info)) {
777 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
781 /* mandatory values */
782 if (pn->byte_swapped) {
783 wblock->data.if_descr.link_type = GUINT16_SWAP_LE_BE(idb.linktype);
784 wblock->data.if_descr.snap_len = GUINT32_SWAP_LE_BE(idb.snaplen);
786 wblock->data.if_descr.link_type = idb.linktype;
787 wblock->data.if_descr.snap_len = idb.snaplen;
790 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
791 wblock->data.if_descr.time_units_per_second = time_units_per_second;
792 wblock->data.if_descr.tsprecision = tsprecision;
794 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
795 wblock->data.if_descr.link_type,
796 wtap_encap_string(wblock->data.if_descr.wtap_encap),
797 wblock->data.if_descr.snap_len);
799 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
800 /* This is unrealistic, but text2pcap currently uses 102400.
801 * We do not use this value, maybe we should check the
802 * snap_len of the packets against it. For now, only warn.
804 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
805 wblock->data.if_descr.snap_len);
806 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
809 /* Option defaults */
810 wblock->data.if_descr.opt_comment = NULL;
811 wblock->data.if_descr.if_name = NULL;
812 wblock->data.if_descr.if_description = NULL;
813 /* XXX: if_IPv4addr */
814 /* XXX: if_IPv6addr */
815 /* XXX: if_MACaddr */
816 /* XXX: if_EUIaddr */
817 wblock->data.if_descr.if_speed = 0; /* "unknown" */
818 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
819 wblock->data.if_descr.if_filter_str = NULL;
820 wblock->data.if_descr.bpf_filter_len = 0;
821 wblock->data.if_descr.if_filter_bpf_bytes = NULL;
822 wblock->data.if_descr.if_os = NULL;
823 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
824 /* XXX: guint64 if_tsoffset; */
828 to_read = bh->block_total_length - MIN_IDB_SIZE;
830 /* Allocate enough memory to hold all options */
831 opt_cont_buf_len = to_read;
832 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
833 if (opt_cont_buf_len != 0 && option_content == NULL) {
834 *err = ENOMEM; /* we assume we're out of memory */
838 while (to_read != 0) {
840 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
841 if (bytes_read <= 0) {
842 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
845 to_read -= bytes_read;
847 /* handle option content */
848 switch (oh.option_code) {
849 case(OPT_EOFOPT): /* opt_endofopt */
851 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
853 /* padding should be ok here, just get out of this */
856 case(OPT_COMMENT): /* opt_comment */
857 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
858 wblock->data.if_descr.opt_comment = g_strndup((char *)option_content, oh.option_length);
859 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
861 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
864 case(OPT_IDB_NAME): /* if_name */
865 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
866 wblock->data.if_descr.if_name = g_strndup((char *)option_content, oh.option_length);
867 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
869 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
872 case(OPT_IDB_DESCR): /* if_description */
873 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
874 wblock->data.if_descr.if_description = g_strndup((char *)option_content, oh.option_length);
875 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
877 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
880 case(OPT_IDB_SPEED): /* if_speed */
881 if (oh.option_length == 8) {
882 /* Don't cast a guint8 * into a guint64 *--the
883 * guint8 * may not point to something that's
886 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
887 if (pn->byte_swapped)
888 wblock->data.if_descr.if_speed = GUINT64_SWAP_LE_BE(wblock->data.if_descr.if_speed);
889 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
891 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
894 case(OPT_IDB_TSRESOL): /* if_tsresol */
895 if (oh.option_length == 1) {
898 guint8 i, exponent, if_tsresol;
900 if_tsresol = option_content[0];
901 if (if_tsresol & 0x80) {
906 exponent = (guint8)(if_tsresol & 0x7f);
907 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
909 for (i = 0; i < exponent; i++) {
912 time_units_per_second = result;
914 time_units_per_second = G_MAXUINT64;
916 if (time_units_per_second > (((guint64)1) << 32)) {
917 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
919 wblock->data.if_descr.time_units_per_second = time_units_per_second;
920 wblock->data.if_descr.if_tsresol = if_tsresol;
921 if (time_units_per_second >= 1000000000)
922 tsprecision = WTAP_TSPREC_NSEC;
923 else if (time_units_per_second >= 1000000)
924 tsprecision = WTAP_TSPREC_USEC;
925 else if (time_units_per_second >= 1000)
926 tsprecision = WTAP_TSPREC_MSEC;
927 else if (time_units_per_second >= 100)
928 tsprecision = WTAP_TSPREC_CSEC;
929 else if (time_units_per_second >= 10)
930 tsprecision = WTAP_TSPREC_DSEC;
932 tsprecision = WTAP_TSPREC_SEC;
933 wblock->data.if_descr.tsprecision = tsprecision;
934 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);
936 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
940 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
942 case(OPT_IDB_FILTER): /* if_filter */
943 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
944 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
947 if (option_content[0] == 0) {
948 wblock->data.if_descr.if_filter_str = g_strndup((char *)option_content+1, oh.option_length-1);
949 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);
950 } else if (option_content[0] == 1) {
951 wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
952 wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
953 memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, (char *)option_content+1, oh.option_length-1);
956 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
959 case(OPT_IDB_OS): /* if_os */
961 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
962 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
963 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
965 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
966 wblock->data.if_descr.if_os = g_strndup((char *)option_content, oh.option_length);
967 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
969 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
972 case(OPT_IDB_FCSLEN): /* if_fcslen */
973 if (oh.option_length == 1) {
974 wblock->data.if_descr.if_fcslen = option_content[0];
975 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
976 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
977 /* XXX - add sanity check */
979 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
983 /* TODO: process these! */
984 case(OPT_IDB_IP4ADDR):
986 * Interface network address and netmask. This option can be
987 * repeated multiple times within the same Interface
988 * Description Block when multiple IPv4 addresses are assigned
989 * to the interface. 192 168 1 1 255 255 255 0
991 case(OPT_IDB_IP6ADDR):
993 * Interface network address and prefix length (stored in the
994 * last byte). This option can be repeated multiple times
995 * within the same Interface Description Block when multiple
996 * IPv6 addresses are assigned to the interface.
997 * 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in
998 * hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44
1001 case(OPT_IDB_MACADDR):
1003 * Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
1005 case(OPT_IDB_EUIADDR):
1007 * Interface Hardware EUI address (64 bits), if available.
1008 * TODO: give a good example
1010 case(OPT_IDB_TZONE):
1012 * Time zone for GMT support. TODO: specify better.
1013 * TODO: give a good example.
1015 case(OPT_IDB_TSOFFSET):
1017 * A 64 bits integer value that specifies an offset (in
1018 * seconds) that must be added to the timestamp of each packet
1019 * to obtain the absolute timestamp of a packet. If the option
1020 * is missing, the timestamps stored in the packet must be
1021 * considered absolute timestamps. The time zone of the offset
1022 * can be specified with the option if_tzone.
1024 * TODO: won't a if_tsoffset_low for fractional second offsets
1025 * be useful for highly synchronized capture systems? 1234
1028 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
1029 oh.option_code, oh.option_length);
1033 g_free(option_content);
1036 * If the per-file encapsulation isn't known, set it to this
1037 * interface's encapsulation.
1039 * If it *is* known, and it isn't this interface's encapsulation,
1040 * set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
1041 * have a single encapsulation for all interfaces in the file,
1042 * so it probably doesn't have a single encapsulation for all
1043 * packets in the file.
1045 if (wth->file_encap == WTAP_ENCAP_UNKNOWN) {
1046 wth->file_encap = wblock->data.if_descr.wtap_encap;
1048 if (wth->file_encap != wblock->data.if_descr.wtap_encap) {
1049 wth->file_encap = WTAP_ENCAP_PER_PACKET;
1054 * The same applies to the per-file time stamp resolution.
1056 if (wth->file_tsprec == WTAP_TSPREC_UNKNOWN) {
1057 wth->file_tsprec = wblock->data.if_descr.tsprecision;
1059 if (wth->file_tsprec != wblock->data.if_descr.tsprecision) {
1060 wth->file_tsprec = WTAP_TSPREC_PER_PACKET;
1069 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)
1073 guint to_read, opt_cont_buf_len;
1074 pcapng_enhanced_packet_block_t epb;
1075 pcapng_packet_block_t pb;
1076 wtapng_packet_t packet;
1077 guint32 block_total_length;
1079 interface_info_t iface_info;
1082 pcapng_option_header_t *oh;
1083 guint8 *option_content;
1084 int pseudo_header_len;
1087 option_handler handler;
1090 /* Don't try to allocate memory for a huge number of options, as
1091 that might fail and, even if it succeeds, it might not leave
1092 any address space or memory+backing store for anything else.
1094 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1095 We check for this *after* checking the SHB for its byte
1096 order magic number, so that non-pcap-ng files are less
1097 likely to be treated as bad pcap-ng files. */
1098 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1099 *err = WTAP_ERR_BAD_FILE;
1100 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1101 bh->block_total_length, MAX_BLOCK_SIZE);
1105 /* "(Enhanced) Packet Block" read fixed part */
1108 * Is this block long enough to be an EPB?
1110 if (bh->block_total_length < MIN_EPB_SIZE) {
1114 *err = WTAP_ERR_BAD_FILE;
1115 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
1116 bh->block_total_length, MIN_EPB_SIZE);
1119 if (!wtap_read_bytes(fh, &epb, sizeof epb, err, err_info)) {
1120 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1123 block_read = (guint)sizeof epb;
1125 if (pn->byte_swapped) {
1126 packet.interface_id = GUINT32_SWAP_LE_BE(epb.interface_id);
1127 packet.drops_count = -1; /* invalid */
1128 packet.ts_high = GUINT32_SWAP_LE_BE(epb.timestamp_high);
1129 packet.ts_low = GUINT32_SWAP_LE_BE(epb.timestamp_low);
1130 packet.cap_len = GUINT32_SWAP_LE_BE(epb.captured_len);
1131 packet.packet_len = GUINT32_SWAP_LE_BE(epb.packet_len);
1133 packet.interface_id = epb.interface_id;
1134 packet.drops_count = -1; /* invalid */
1135 packet.ts_high = epb.timestamp_high;
1136 packet.ts_low = epb.timestamp_low;
1137 packet.cap_len = epb.captured_len;
1138 packet.packet_len = epb.packet_len;
1140 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1141 packet.interface_id, packet.cap_len, packet.packet_len);
1144 * Is this block long enough to be a PB?
1146 if (bh->block_total_length < MIN_PB_SIZE) {
1150 *err = WTAP_ERR_BAD_FILE;
1151 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1152 bh->block_total_length, MIN_PB_SIZE);
1155 if (!wtap_read_bytes(fh, &pb, sizeof pb, err, err_info)) {
1156 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1159 block_read = (guint)sizeof pb;
1161 if (pn->byte_swapped) {
1162 packet.interface_id = GUINT16_SWAP_LE_BE(pb.interface_id);
1163 packet.drops_count = GUINT16_SWAP_LE_BE(pb.drops_count);
1164 packet.ts_high = GUINT32_SWAP_LE_BE(pb.timestamp_high);
1165 packet.ts_low = GUINT32_SWAP_LE_BE(pb.timestamp_low);
1166 packet.cap_len = GUINT32_SWAP_LE_BE(pb.captured_len);
1167 packet.packet_len = GUINT32_SWAP_LE_BE(pb.packet_len);
1169 packet.interface_id = pb.interface_id;
1170 packet.drops_count = pb.drops_count;
1171 packet.ts_high = pb.timestamp_high;
1172 packet.ts_low = pb.timestamp_low;
1173 packet.cap_len = pb.captured_len;
1174 packet.packet_len = pb.packet_len;
1176 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1177 packet.interface_id, packet.cap_len, packet.packet_len);
1181 * How much padding is there at the end of the packet data?
1183 if ((packet.cap_len % 4) != 0)
1184 padding = 4 - (packet.cap_len % 4);
1188 /* add padding bytes to "block total length" */
1189 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1190 if (bh->block_total_length % 4) {
1191 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1193 block_total_length = bh->block_total_length;
1195 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1198 * Is this block long enough to hold the packet data?
1201 if (block_total_length <
1202 MIN_EPB_SIZE + packet.cap_len + padding) {
1206 *err = WTAP_ERR_BAD_FILE;
1207 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1208 block_total_length, packet.cap_len);
1212 if (block_total_length <
1213 MIN_PB_SIZE + packet.cap_len + padding) {
1217 *err = WTAP_ERR_BAD_FILE;
1218 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1219 block_total_length, packet.cap_len);
1224 if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1225 *err = WTAP_ERR_BAD_FILE;
1226 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1227 packet.cap_len, WTAP_MAX_PACKET_SIZE);
1230 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1233 packet.interface_id);
1235 if (packet.interface_id >= pn->interfaces->len) {
1236 *err = WTAP_ERR_BAD_FILE;
1237 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u",
1238 packet.interface_id, pn->interfaces->len);
1241 iface_info = g_array_index(pn->interfaces, interface_info_t,
1242 packet.interface_id);
1244 wblock->packet_header->rec_type = REC_TYPE_PACKET;
1245 wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1247 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1248 iface_info.wtap_encap,
1249 wtap_encap_string(iface_info.wtap_encap),
1250 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
1251 wblock->packet_header->interface_id = packet.interface_id;
1252 wblock->packet_header->pkt_encap = iface_info.wtap_encap;
1253 wblock->packet_header->pkt_tsprec = iface_info.tsprecision;
1255 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1256 pseudo_header_len = pcap_process_pseudo_header(fh,
1257 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1258 iface_info.wtap_encap,
1261 wblock->packet_header,
1264 if (pseudo_header_len < 0) {
1267 block_read += pseudo_header_len;
1268 if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
1269 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1272 wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
1273 wblock->packet_header->len = packet.packet_len - pseudo_header_len;
1275 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1276 ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
1277 wblock->packet_header->ts.secs = (time_t)(ts / iface_info.time_units_per_second);
1278 wblock->packet_header->ts.nsecs = (int)(((ts % iface_info.time_units_per_second) * 1000000000) / iface_info.time_units_per_second);
1280 /* "(Enhanced) Packet Block" read capture data */
1281 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1282 packet.cap_len - pseudo_header_len, err, err_info))
1284 block_read += packet.cap_len - pseudo_header_len;
1286 /* jump over potential padding bytes at end of the packet data */
1288 if (!file_skip(fh, padding, err))
1290 block_read += padding;
1293 /* Option defaults */
1294 wblock->packet_header->opt_comment = NULL;
1295 wblock->packet_header->drop_count = -1;
1296 wblock->packet_header->pack_flags = 0;
1298 /* FCS length default */
1299 fcslen = pn->if_fcslen;
1307 to_read = block_total_length -
1308 (int)sizeof(pcapng_block_header_t) -
1309 block_read - /* fixed and variable part, including padding */
1310 (int)sizeof(bh->block_total_length);
1312 /* Allocate enough memory to hold all options */
1313 opt_cont_buf_len = to_read;
1314 ws_buffer_assure_space(&wblock->packet_header->ft_specific_data, opt_cont_buf_len);
1315 opt_ptr = ws_buffer_start_ptr(&wblock->packet_header->ft_specific_data);
1317 while (to_read != 0) {
1319 oh = (pcapng_option_header_t *)(void *)opt_ptr;
1320 option_content = opt_ptr + sizeof (pcapng_option_header_t);
1321 bytes_read = pcapng_read_option(fh, pn, oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1322 if (bytes_read <= 0) {
1323 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1324 /* XXX - free anything? */
1327 block_read += bytes_read;
1328 to_read -= bytes_read;
1330 /* handle option content */
1331 switch (oh->option_code) {
1334 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1336 /* padding should be ok here, just get out of this */
1340 if (oh->option_length > 0 && oh->option_length < opt_cont_buf_len) {
1341 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1342 wblock->packet_header->opt_comment = g_strndup((char *)option_content, oh->option_length);
1343 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh->option_length, wblock->packet_header->opt_comment);
1345 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh->option_length);
1348 case(OPT_EPB_FLAGS):
1349 if (oh->option_length != 4) {
1350 *err = WTAP_ERR_BAD_FILE;
1351 *err_info = g_strdup_printf("pcapng: packet block flags option length %u is not 4",
1353 /* XXX - free anything? */
1356 /* Don't cast a guint8 * into a guint32 *--the
1357 * guint8 * may not point to something that's
1358 * aligned correctly.
1360 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1361 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1362 if (pn->byte_swapped) {
1363 wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
1364 memcpy(option_content, &wblock->packet_header->pack_flags, sizeof(guint32));
1366 if (wblock->packet_header->pack_flags & 0x000001E0) {
1367 /* The FCS length is present */
1368 fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1370 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1373 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1374 oh->option_code, oh->option_length);
1376 case(OPT_EPB_DROPCOUNT):
1377 if (oh->option_length != 8) {
1378 *err = WTAP_ERR_BAD_FILE;
1379 *err_info = g_strdup_printf("pcapng: packet block drop count option length %u is not 8",
1381 /* XXX - free anything? */
1384 /* Don't cast a guint8 * into a guint64 *--the
1385 * guint8 * may not point to something that's
1386 * aligned correctly.
1388 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1389 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1390 if (pn->byte_swapped) {
1391 wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
1392 memcpy(option_content, &wblock->packet_header->drop_count, sizeof(guint64));
1395 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1400 * Do we have a handler for this packet block option code?
1402 if (option_handlers[BT_INDEX_PBS] != NULL &&
1403 (handler = (option_handler)g_hash_table_lookup(option_handlers[BT_INDEX_PBS],
1404 GUINT_TO_POINTER((guint)oh->option_code))) != NULL) {
1405 /* Yes - call the handler. */
1406 if (!handler(pn->byte_swapped, oh->option_length,
1407 option_content, err, err_info))
1408 /* XXX - free anything? */
1413 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1414 oh->option_code, oh->option_length);
1419 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
1420 wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
1421 pn->byte_swapped, fcslen);
1427 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)
1429 interface_info_t iface_info;
1430 pcapng_simple_packet_block_t spb;
1431 wtapng_simple_packet_t simple_packet;
1432 guint32 block_total_length;
1434 int pseudo_header_len;
1437 * Is this block long enough to be an SPB?
1439 if (bh->block_total_length < MIN_SPB_SIZE) {
1443 *err = WTAP_ERR_BAD_FILE;
1444 *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",
1445 bh->block_total_length, MIN_SPB_SIZE);
1449 /* Don't try to allocate memory for a huge number of options, as
1450 that might fail and, even if it succeeds, it might not leave
1451 any address space or memory+backing store for anything else.
1453 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1454 We check for this *after* checking the SHB for its byte
1455 order magic number, so that non-pcap-ng files are less
1456 likely to be treated as bad pcap-ng files. */
1457 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1458 *err = WTAP_ERR_BAD_FILE;
1459 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1460 bh->block_total_length, MAX_BLOCK_SIZE);
1464 /* "Simple Packet Block" read fixed part */
1465 if (!wtap_read_bytes(fh, &spb, sizeof spb, err, err_info)) {
1466 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1470 if (0 >= pn->interfaces->len) {
1471 *err = WTAP_ERR_BAD_FILE;
1472 *err_info = g_strdup_printf("pcapng: SPB appeared before any IDBs");
1475 iface_info = g_array_index(pn->interfaces, interface_info_t, 0);
1477 if (pn->byte_swapped) {
1478 simple_packet.packet_len = GUINT32_SWAP_LE_BE(spb.packet_len);
1480 simple_packet.packet_len = spb.packet_len;
1484 * The captured length is not a field in the SPB; it can be
1485 * calculated as the minimum of the snapshot length from the
1486 * IDB and the packet length, as per the pcap-ng spec.
1488 simple_packet.cap_len = simple_packet.packet_len;
1489 if (simple_packet.cap_len > iface_info.snap_len)
1490 simple_packet.cap_len = iface_info.snap_len;
1493 * How much padding is there at the end of the packet data?
1495 if ((simple_packet.cap_len % 4) != 0)
1496 padding = 4 - (simple_packet.cap_len % 4);
1500 /* add padding bytes to "block total length" */
1501 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1502 if (bh->block_total_length % 4) {
1503 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1505 block_total_length = bh->block_total_length;
1507 pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length);
1510 * Is this block long enough to hold the packet data?
1512 if (block_total_length < MIN_SPB_SIZE + simple_packet.cap_len + padding) {
1514 * No. That means that the problem is with the packet
1515 * length; the snapshot length can be bigger than the amount
1516 * of packet data in the block, as it's a *maximum* length,
1517 * not a *minimum* length.
1519 *err = WTAP_ERR_BAD_FILE;
1520 *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",
1521 block_total_length, simple_packet.packet_len);
1525 if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1526 *err = WTAP_ERR_BAD_FILE;
1527 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1528 simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1531 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1532 simple_packet.packet_len);
1534 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1535 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
1537 /* No time stamp in a simple packet block; no options, either */
1538 wblock->packet_header->rec_type = REC_TYPE_PACKET;
1539 wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1540 wblock->packet_header->interface_id = 0;
1541 wblock->packet_header->pkt_encap = iface_info.wtap_encap;
1542 wblock->packet_header->pkt_tsprec = iface_info.tsprecision;
1543 wblock->packet_header->ts.secs = 0;
1544 wblock->packet_header->ts.nsecs = 0;
1545 wblock->packet_header->interface_id = 0;
1546 wblock->packet_header->opt_comment = NULL;
1547 wblock->packet_header->drop_count = 0;
1548 wblock->packet_header->pack_flags = 0;
1550 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1551 pseudo_header_len = pcap_process_pseudo_header(fh,
1552 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1553 iface_info.wtap_encap,
1554 simple_packet.cap_len,
1556 wblock->packet_header,
1559 if (pseudo_header_len < 0) {
1562 wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
1563 wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
1564 if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
1565 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1569 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1571 /* "Simple Packet Block" read capture data */
1572 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1573 simple_packet.cap_len, err, err_info))
1576 /* jump over potential padding bytes at end of the packet data */
1577 if ((simple_packet.cap_len % 4) != 0) {
1578 if (!file_skip(fh, 4 - (simple_packet.cap_len % 4), err))
1582 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
1583 wblock->packet_header, ws_buffer_start_ptr(wblock->frame_buffer),
1584 pn->byte_swapped, pn->if_fcslen);
1588 #define NRES_ENDOFRECORD 0
1589 #define NRES_IP4RECORD 1
1590 #define NRES_IP6RECORD 2
1591 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1592 /* IPv6 + MAXNAMELEN */
1593 #define INITIAL_NRB_REC_SIZE (16 + 64)
1596 * Find the end of the NUL-terminated name the beginning of which is pointed
1597 * to by p; record_len is the number of bytes remaining in the record.
1599 * Return the length of the name, including the terminating NUL.
1601 * If we don't find a terminating NUL, return -1 and set *err and
1602 * *err_info appropriately.
1605 name_resolution_block_find_name_end(const char *p, guint record_len, int *err,
1612 if (record_len == 0) {
1614 * We ran out of bytes in the record without
1617 *err = WTAP_ERR_BAD_FILE;
1618 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1622 break; /* that's the terminating NUL */
1625 namelen++; /* count this byte */
1628 /* Include the NUL in the name length. */
1633 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)
1637 pcapng_name_resolution_block_t nrb;
1640 guint record_len, opt_cont_buf_len;
1644 pcapng_option_header_t oh;
1645 guint8 *option_content;
1647 option_handler handler;
1651 * Is this block long enough to be an NRB?
1653 if (bh->block_total_length < MIN_NRB_SIZE) {
1657 *err = WTAP_ERR_BAD_FILE;
1658 *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",
1659 bh->block_total_length, MIN_NRB_SIZE);
1663 /* Don't try to allocate memory for a huge number of options, as
1664 that might fail and, even if it succeeds, it might not leave
1665 any address space or memory+backing store for anything else.
1667 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1668 We check for this *after* checking the SHB for its byte
1669 order magic number, so that non-pcap-ng files are less
1670 likely to be treated as bad pcap-ng files. */
1671 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1672 *err = WTAP_ERR_BAD_FILE;
1673 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1674 bh->block_total_length, MAX_BLOCK_SIZE);
1678 to_read = bh->block_total_length - 8 - 4; /* We have read the header and should not read the final block_total_length */
1680 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1683 * Start out with a buffer big enough for an IPv6 address and one
1684 * 64-byte name; we'll make the buffer bigger if necessary.
1686 ws_buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1688 while (block_read < to_read) {
1690 * There must be at least one record's worth of data
1693 if ((size_t)(to_read - block_read) < sizeof nrb) {
1694 ws_buffer_free(&nrb_rec);
1695 *err = WTAP_ERR_BAD_FILE;
1696 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1697 to_read - block_read,
1701 if (!wtap_read_bytes(fh, &nrb, sizeof nrb, err, err_info)) {
1702 ws_buffer_free(&nrb_rec);
1703 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1706 block_read += (int)sizeof nrb;
1708 if (pn->byte_swapped) {
1709 nrb.record_type = GUINT16_SWAP_LE_BE(nrb.record_type);
1710 nrb.record_len = GUINT16_SWAP_LE_BE(nrb.record_len);
1713 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1714 ws_buffer_free(&nrb_rec);
1715 *err = WTAP_ERR_BAD_FILE;
1716 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1717 to_read - block_read,
1718 nrb.record_len + PADDING4(nrb.record_len));
1721 switch (nrb.record_type) {
1722 case NRES_ENDOFRECORD:
1723 /* There shouldn't be any more data */
1726 case NRES_IP4RECORD:
1728 * The smallest possible record must have
1729 * a 4-byte IPv4 address, hence a minimum
1732 * (The pcap-NG spec really indicates
1733 * that it must be at least 5 bytes,
1734 * as there must be at least one name,
1735 * and it really must be at least 6
1736 * bytes, as the name mustn't be null,
1737 * but there's no need to fail if there
1738 * aren't any names at all, and we
1739 * should report a null name as such.)
1741 if (nrb.record_len < 4) {
1742 ws_buffer_free(&nrb_rec);
1743 *err = WTAP_ERR_BAD_FILE;
1744 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1748 ws_buffer_assure_space(&nrb_rec, nrb.record_len);
1749 if (!wtap_read_bytes(fh, ws_buffer_start_ptr(&nrb_rec),
1750 nrb.record_len, err, err_info)) {
1751 ws_buffer_free(&nrb_rec);
1752 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1755 block_read += nrb.record_len;
1757 if (pn->add_new_ipv4) {
1759 * Scan through all the names in
1760 * the record and add them.
1763 ws_buffer_start_ptr(&nrb_rec), 4);
1764 if (pn->byte_swapped)
1765 v4_addr = GUINT32_SWAP_LE_BE(v4_addr);
1766 for (namep = (char *)ws_buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1768 namep += namelen, record_len -= namelen) {
1770 * Scan forward for a null
1773 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1774 if (namelen == -1) {
1775 ws_buffer_free(&nrb_rec);
1776 return FALSE; /* fail */
1778 pn->add_new_ipv4(v4_addr, namep);
1782 if (!file_skip(fh, PADDING4(nrb.record_len), err)) {
1783 ws_buffer_free(&nrb_rec);
1786 block_read += PADDING4(nrb.record_len);
1788 case NRES_IP6RECORD:
1790 * The smallest possible record must have
1791 * a 16-byte IPv6 address, hence a minimum
1794 * (The pcap-NG spec really indicates
1795 * that it must be at least 17 bytes,
1796 * as there must be at least one name,
1797 * and it really must be at least 18
1798 * bytes, as the name mustn't be null,
1799 * but there's no need to fail if there
1800 * aren't any names at all, and we
1801 * should report a null name as such.)
1803 if (nrb.record_len < 16) {
1804 ws_buffer_free(&nrb_rec);
1805 *err = WTAP_ERR_BAD_FILE;
1806 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1810 if (to_read < nrb.record_len) {
1811 ws_buffer_free(&nrb_rec);
1812 *err = WTAP_ERR_BAD_FILE;
1813 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u > remaining data in NRB",
1817 ws_buffer_assure_space(&nrb_rec, nrb.record_len);
1818 if (!wtap_read_bytes(fh, ws_buffer_start_ptr(&nrb_rec),
1819 nrb.record_len, err, err_info)) {
1820 ws_buffer_free(&nrb_rec);
1823 block_read += nrb.record_len;
1825 if (pn->add_new_ipv6) {
1826 for (namep = (char *)ws_buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1828 namep += namelen, record_len -= namelen) {
1830 * Scan forward for a null
1833 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1834 if (namelen == -1) {
1835 ws_buffer_free(&nrb_rec);
1836 return FALSE; /* fail */
1838 pn->add_new_ipv6(ws_buffer_start_ptr(&nrb_rec),
1843 if (!file_skip(fh, PADDING4(nrb.record_len), err)) {
1844 ws_buffer_free(&nrb_rec);
1847 block_read += PADDING4(nrb.record_len);
1850 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1851 if (!file_skip(fh, nrb.record_len + PADDING4(nrb.record_len), err)) {
1852 ws_buffer_free(&nrb_rec);
1855 block_read += nrb.record_len + PADDING4(nrb.record_len);
1869 /* Allocate enough memory to hold all options */
1870 opt_cont_buf_len = to_read;
1871 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
1872 if (opt_cont_buf_len != 0 && option_content == NULL) {
1873 *err = ENOMEM; /* we assume we're out of memory */
1874 ws_buffer_free(&nrb_rec);
1878 while (to_read != 0) {
1880 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1881 if (bytes_read <= 0) {
1882 pcapng_debug0("pcapng_read_name_resolution_block: failed to read option");
1883 g_free(option_content);
1884 ws_buffer_free(&nrb_rec);
1887 to_read -= bytes_read;
1889 /* handle option content */
1890 switch (oh.option_code) {
1893 pcapng_debug1("pcapng_read_name_resolution_block: %u bytes after opt_endofopt", to_read);
1895 /* padding should be ok here, just get out of this */
1899 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1900 wblock->data.name_res.opt_comment = g_strndup((char *)option_content, oh.option_length);
1901 pcapng_debug2("pcapng_read_name_resolution_block: length %u opt_comment '%s'", oh.option_length, wblock->data.name_res.opt_comment);
1903 pcapng_debug1("pcapng_read_name_resolution_block: opt_comment length %u seems strange", oh.option_length);
1910 * Do we have a handler for this network resolution block option code?
1912 if (option_handlers[BT_INDEX_NRB] != NULL &&
1913 (handler = (option_handler)g_hash_table_lookup(option_handlers[BT_INDEX_NRB],
1914 GUINT_TO_POINTER((guint)oh.option_code))) != NULL) {
1915 /* Yes - call the handler. */
1916 if (!handler(pn->byte_swapped, oh.option_length,
1917 option_content, err, err_info)) {
1919 g_free(option_content);
1920 ws_buffer_free(&nrb_rec);
1926 pcapng_debug2("pcapng_read_name_resolution_block: unknown option %u - ignoring %u bytes",
1927 oh.option_code, oh.option_length);
1932 g_free(option_content);
1933 ws_buffer_free(&nrb_rec);
1938 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)
1941 guint to_read, opt_cont_buf_len;
1942 pcapng_interface_statistics_block_t isb;
1943 pcapng_option_header_t oh;
1944 guint8 *option_content = NULL; /* Allocate as large as the options block */
1947 * Is this block long enough to be an ISB?
1949 if (bh->block_total_length < MIN_ISB_SIZE) {
1953 *err = WTAP_ERR_BAD_FILE;
1954 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1955 bh->block_total_length, MIN_ISB_SIZE);
1959 /* Don't try to allocate memory for a huge number of options, as
1960 that might fail and, even if it succeeds, it might not leave
1961 any address space or memory+backing store for anything else.
1963 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1964 We check for this *after* checking the SHB for its byte
1965 order magic number, so that non-pcap-ng files are less
1966 likely to be treated as bad pcap-ng files. */
1967 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1968 *err = WTAP_ERR_BAD_FILE;
1969 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1970 bh->block_total_length, MAX_BLOCK_SIZE);
1974 /* "Interface Statistics Block" read fixed part */
1975 if (!wtap_read_bytes(fh, &isb, sizeof isb, err, err_info)) {
1976 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1980 if (pn->byte_swapped) {
1981 wblock->data.if_stats.interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
1982 wblock->data.if_stats.ts_high = GUINT32_SWAP_LE_BE(isb.timestamp_high);
1983 wblock->data.if_stats.ts_low = GUINT32_SWAP_LE_BE(isb.timestamp_low);
1985 wblock->data.if_stats.interface_id = isb.interface_id;
1986 wblock->data.if_stats.ts_high = isb.timestamp_high;
1987 wblock->data.if_stats.ts_low = isb.timestamp_low;
1989 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1991 /* Option defaults */
1992 wblock->data.if_stats.opt_comment = NULL;
1993 wblock->data.if_stats.isb_ifrecv = -1;
1994 wblock->data.if_stats.isb_ifdrop = -1;
1995 wblock->data.if_stats.isb_filteraccept = -1;
1996 wblock->data.if_stats.isb_osdrop = -1;
1997 wblock->data.if_stats.isb_usrdeliv = -1;
2000 to_read = bh->block_total_length -
2001 (MIN_BLOCK_SIZE + (guint)sizeof isb); /* fixed and variable part, including padding */
2003 /* Allocate enough memory to hold all options */
2004 opt_cont_buf_len = to_read;
2005 option_content = (guint8 *)g_try_malloc(opt_cont_buf_len);
2006 if (opt_cont_buf_len != 0 && option_content == NULL) {
2007 *err = ENOMEM; /* we assume we're out of memory */
2011 while (to_read != 0) {
2013 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
2014 if (bytes_read <= 0) {
2015 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
2018 to_read -= bytes_read;
2020 /* handle option content */
2021 switch (oh.option_code) {
2022 case(OPT_EOFOPT): /* opt_endofopt */
2024 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
2026 /* padding should be ok here, just get out of this */
2029 case(OPT_COMMENT): /* opt_comment */
2030 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
2031 wblock->data.if_stats.opt_comment = g_strndup((char *)option_content, oh.option_length);
2032 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
2034 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
2037 case(OPT_ISB_STARTTIME): /* isb_starttime */
2038 if (oh.option_length == 8) {
2041 /* Don't cast a guint8 * into a guint32 *--the
2042 * guint8 * may not point to something that's
2043 * aligned correctly.
2045 memcpy(&high, option_content, sizeof(guint32));
2046 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
2047 if (pn->byte_swapped) {
2048 high = GUINT32_SWAP_LE_BE(high);
2049 low = GUINT32_SWAP_LE_BE(low);
2051 wblock->data.if_stats.isb_starttime = (guint64)high;
2052 wblock->data.if_stats.isb_starttime <<= 32;
2053 wblock->data.if_stats.isb_starttime += (guint64)low;
2054 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
2056 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
2059 case(OPT_ISB_ENDTIME): /* isb_endtime */
2060 if (oh.option_length == 8) {
2063 /* Don't cast a guint8 * into a guint32 *--the
2064 * guint8 * may not point to something that's
2065 * aligned correctly.
2067 memcpy(&high, option_content, sizeof(guint32));
2068 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
2069 if (pn->byte_swapped) {
2070 high = GUINT32_SWAP_LE_BE(high);
2071 low = GUINT32_SWAP_LE_BE(low);
2073 wblock->data.if_stats.isb_endtime = (guint64)high;
2074 wblock->data.if_stats.isb_endtime <<= 32;
2075 wblock->data.if_stats.isb_endtime += (guint64)low;
2076 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
2078 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
2081 case(OPT_ISB_IFRECV): /* isb_ifrecv */
2082 if (oh.option_length == 8) {
2083 /* Don't cast a guint8 * into a guint64 *--the
2084 * guint8 * may not point to something that's
2085 * aligned correctly.
2087 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
2088 if (pn->byte_swapped)
2089 wblock->data.if_stats.isb_ifrecv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifrecv);
2090 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
2092 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
2095 case(OPT_ISB_IFDROP): /* isb_ifdrop */
2096 if (oh.option_length == 8) {
2097 /* Don't cast a guint8 * into a guint64 *--the
2098 * guint8 * may not point to something that's
2099 * aligned correctly.
2101 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
2102 if (pn->byte_swapped)
2103 wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifdrop);
2104 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
2106 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
2109 case(OPT_ISB_FILTERACCEPT): /* isb_filteraccept 6 */
2110 if (oh.option_length == 8) {
2111 /* Don't cast a guint8 * into a guint64 *--the
2112 * guint8 * may not point to something that's
2113 * aligned correctly.
2115 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
2116 if (pn->byte_swapped)
2117 wblock->data.if_stats.isb_filteraccept = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_filteraccept);
2118 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
2120 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
2123 case(OPT_ISB_OSDROP): /* isb_osdrop 7 */
2124 if (oh.option_length == 8) {
2125 /* Don't cast a guint8 * into a guint64 *--the
2126 * guint8 * may not point to something that's
2127 * aligned correctly.
2129 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
2130 if (pn->byte_swapped)
2131 wblock->data.if_stats.isb_osdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
2132 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
2134 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
2137 case(OPT_ISB_USRDELIV): /* isb_usrdeliv 8 */
2138 if (oh.option_length == 8) {
2139 /* Don't cast a guint8 * into a guint64 *--the
2140 * guint8 * may not point to something that's
2141 * aligned correctly.
2143 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
2144 if (pn->byte_swapped)
2145 wblock->data.if_stats.isb_usrdeliv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_usrdeliv);
2146 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
2148 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
2152 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
2153 oh.option_code, oh.option_length);
2157 g_free(option_content);
2164 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)
2167 guint32 block_total_length;
2169 block_handler *handler;
2172 if (bh->block_total_length < MIN_BLOCK_SIZE) {
2173 *err = WTAP_ERR_BAD_FILE;
2174 *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",
2175 bh->block_total_length, MIN_BLOCK_SIZE);
2179 /* add padding bytes to "block total length" */
2180 /* (the "block total length" of some example files don't contain any padding bytes!) */
2181 if (bh->block_total_length % 4) {
2182 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
2184 block_total_length = bh->block_total_length;
2187 block_read = block_total_length - MIN_BLOCK_SIZE;
2191 * Do we have a handler for this block type?
2193 if (block_handlers != NULL &&
2194 (handler = (block_handler *)g_hash_table_lookup(block_handlers,
2195 GUINT_TO_POINTER(bh->block_type))) != NULL) {
2196 /* Yes - call it to read this block type. */
2197 if (!handler->read(fh, block_read, pn->byte_swapped,
2198 wblock->packet_header, wblock->frame_buffer,
2204 /* No. Skip over this unknown block. */
2205 if (!file_skip(fh, block_read, err)) {
2214 static block_return_val
2215 pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2217 block_return_val ret;
2218 pcapng_block_header_t bh;
2219 guint32 block_total_length;
2221 memset(&(wblock->data), 0, sizeof(wblock->data));
2223 /* Try to read the (next) block header */
2224 if (!wtap_read_bytes_or_eof(fh, &bh, sizeof bh, err, err_info)) {
2225 pcapng_debug1("pcapng_read_block: wtap_read_bytes_or_eof() failed, err = %d.", *err);
2226 if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
2228 * Short read or EOF.
2230 * If we're reading this as part of an open,
2231 * the file is too short to be a pcap-ng file.
2233 * If we're not, we treat PCAPNG_BLOCK_NOT_SHB and
2234 * PCAPNG_BLOCK_ERROR the same, so we can just return
2235 * PCAPNG_BLOCK_NOT_SHB in both cases.
2237 return PCAPNG_BLOCK_NOT_SHB;
2239 return PCAPNG_BLOCK_ERROR;
2242 if (pn->byte_swapped) {
2243 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2244 bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
2247 wblock->type = bh.block_type;
2249 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2252 * SHBs have to be treated differently from other blocks, as we
2253 * might be doing an open and attempting to read a block at the
2254 * beginning of the file to see if it's a pcap-ng file or not.
2256 if (bh.block_type == BLOCK_TYPE_SHB) {
2257 ret = pcapng_read_section_header_block(fh, &bh, pn, wblock, err, err_info);
2258 if (ret != PCAPNG_BLOCK_OK) {
2262 if (!pn->shb_read) {
2264 * No SHB seen yet, so we're trying to read the first block
2265 * during an open, to see whether it's an SHB; if what we
2266 * read doesn't look like an SHB, this isn't a pcap-ng file.
2270 return PCAPNG_BLOCK_NOT_SHB;
2272 switch (bh.block_type) {
2273 case(BLOCK_TYPE_IDB):
2274 if (!pcapng_read_if_descr_block(wth, fh, &bh, pn, wblock, err, err_info))
2275 return PCAPNG_BLOCK_ERROR;
2277 case(BLOCK_TYPE_PB):
2278 if (!pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE))
2279 return PCAPNG_BLOCK_ERROR;
2281 case(BLOCK_TYPE_SPB):
2282 if (!pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info))
2283 return PCAPNG_BLOCK_ERROR;
2285 case(BLOCK_TYPE_EPB):
2286 if (!pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE))
2287 return PCAPNG_BLOCK_ERROR;
2289 case(BLOCK_TYPE_NRB):
2290 if (!pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info))
2291 return PCAPNG_BLOCK_ERROR;
2293 case(BLOCK_TYPE_ISB):
2294 if (!pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info))
2295 return PCAPNG_BLOCK_ERROR;
2298 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2299 if (!pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info))
2300 return PCAPNG_BLOCK_ERROR;
2305 /* sanity check: first and second block lengths must match */
2306 if (!wtap_read_bytes(fh, &block_total_length, sizeof block_total_length,
2308 pcapng_debug0("pcapng_check_block_trailer: couldn't read second block length");
2309 return PCAPNG_BLOCK_ERROR;
2312 if (pn->byte_swapped)
2313 block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
2315 if (block_total_length != bh.block_total_length) {
2316 *err = WTAP_ERR_BAD_FILE;
2317 *err_info = g_strdup_printf("pcapng_check_block_trailer: total block lengths (first %u and second %u) don't match",
2318 bh.block_total_length, block_total_length);
2319 return PCAPNG_BLOCK_ERROR;
2321 return PCAPNG_BLOCK_OK;
2324 /* Process an IDB that we've just read. */
2326 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2328 wtapng_if_descr_t int_data;
2329 interface_info_t iface_info;
2331 int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2332 int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2333 int_data.link_type = wblock->data.if_descr.link_type;
2334 int_data.snap_len = wblock->data.if_descr.snap_len;
2336 int_data.opt_comment = wblock->data.if_descr.opt_comment;
2337 int_data.if_name = wblock->data.if_descr.if_name;
2338 int_data.if_description = wblock->data.if_descr.if_description;
2339 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2340 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2341 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2342 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2343 int_data.if_speed = wblock->data.if_descr.if_speed;
2344 int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2345 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2346 int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2347 int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2348 int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2349 int_data.if_os = wblock->data.if_descr.if_os;
2350 int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2351 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2352 /* Interface statistics */
2353 int_data.num_stat_entries = 0;
2354 int_data.interface_statistics = NULL;
2356 g_array_append_val(wth->interface_data, int_data);
2358 iface_info.wtap_encap = wblock->data.if_descr.wtap_encap;
2359 iface_info.snap_len = wblock->data.if_descr.snap_len;
2360 iface_info.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2361 iface_info.tsprecision = wblock->data.if_descr.tsprecision;
2363 g_array_append_val(pcapng->interfaces, iface_info);
2366 /* classic wtap: open capture file */
2367 wtap_open_return_val
2368 pcapng_open(wtap *wth, int *err, gchar **err_info)
2371 wtapng_block_t wblock;
2373 pcapng_block_header_t bh;
2374 gint64 saved_offset;
2376 pn.shb_read = FALSE;
2377 /* we don't know the byte swapping of the file yet */
2378 pn.byte_swapped = FALSE;
2380 pn.version_major = -1;
2381 pn.version_minor = -1;
2382 pn.interfaces = NULL;
2384 /* we don't expect any packet blocks yet */
2385 wblock.frame_buffer = NULL;
2386 wblock.packet_header = NULL;
2388 pcapng_debug0("pcapng_open: opening file");
2389 /* read first block */
2390 switch (pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info)) {
2392 case PCAPNG_BLOCK_OK:
2396 case PCAPNG_BLOCK_NOT_SHB:
2397 /* An error indicating that this isn't a pcap-ng file. */
2398 pcapng_free_wtapng_block_data(&wblock);
2401 return WTAP_OPEN_NOT_MINE;
2403 case PCAPNG_BLOCK_ERROR:
2404 /* An I/O error, or this probably *is* a pcap-ng file but not a valid one. */
2405 pcapng_free_wtapng_block_data(&wblock);
2406 return WTAP_OPEN_ERROR;
2409 /* first block must be a "Section Header Block" */
2410 if (wblock.type != BLOCK_TYPE_SHB) {
2412 * XXX - check for damage from transferring a file
2413 * between Windows and UN*X as text rather than
2416 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2417 pcapng_free_wtapng_block_data(&wblock);
2418 return WTAP_OPEN_NOT_MINE;
2423 * At this point, we've decided this is a pcap-NG file, not
2424 * some other type of file, so we can't return WTAP_OPEN_NOT_MINE
2427 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2428 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2429 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2430 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2432 wth->file_encap = WTAP_ENCAP_UNKNOWN;
2433 wth->snapshot_length = 0;
2434 wth->file_tsprec = WTAP_TSPREC_UNKNOWN;
2435 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2436 wth->priv = (void *)pcapng;
2438 pcapng->interfaces = g_array_new(FALSE, FALSE, sizeof(interface_info_t));
2440 wth->subtype_read = pcapng_read;
2441 wth->subtype_seek_read = pcapng_seek_read;
2442 wth->subtype_close = pcapng_close;
2443 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
2445 /* Loop over all IDB:s that appear before any packets */
2447 /* peek at next block */
2448 /* Try to read the (next) block header */
2449 saved_offset = file_tell(wth->fh);
2450 if (!wtap_read_bytes_or_eof(wth->fh, &bh, sizeof bh, err, err_info)) {
2453 pcapng_debug0("No more IDBs available...");
2456 pcapng_debug1("pcapng_open: Check for more IDB:s, wtap_read_bytes_or_eof() failed, err = %d.", *err);
2457 return WTAP_OPEN_ERROR;
2460 /* go back to where we were */
2461 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2463 if (pn.byte_swapped) {
2464 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2467 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2469 if (bh.block_type != BLOCK_TYPE_IDB) {
2470 break; /* No more IDB:s */
2472 if (pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
2474 pcapng_debug0("No more IDBs available...");
2475 pcapng_free_wtapng_block_data(&wblock);
2478 pcapng_debug0("pcapng_open: couldn't read IDB");
2479 pcapng_free_wtapng_block_data(&wblock);
2480 return WTAP_OPEN_ERROR;
2483 pcapng_process_idb(wth, pcapng, &wblock);
2484 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i",
2485 wth->interface_data->len, wth->file_encap);
2487 return WTAP_OPEN_MINE;
2491 /* classic wtap: read packet */
2493 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2495 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2496 wtapng_block_t wblock;
2497 wtapng_if_descr_t *wtapng_if_descr;
2498 wtapng_if_stats_t if_stats;
2500 wblock.frame_buffer = wth->frame_buffer;
2501 wblock.packet_header = &wth->phdr;
2503 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2504 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2506 /* read next block */
2508 *data_offset = file_tell(wth->fh);
2509 pcapng_debug1("pcapng_read: data_offset is %" G_GINT64_MODIFIER "d", *data_offset);
2510 if (pcapng_read_block(wth, wth->fh, pcapng, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
2511 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2512 pcapng_debug0("pcapng_read: couldn't read packet block");
2516 switch (wblock.type) {
2518 case(BLOCK_TYPE_SHB):
2519 /* We don't currently support multi-section files. */
2520 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2521 wth->phdr.pkt_tsprec = WTAP_TSPREC_UNKNOWN;
2522 *err = WTAP_ERR_UNSUPPORTED;
2523 *err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
2526 case(BLOCK_TYPE_PB):
2527 case(BLOCK_TYPE_SPB):
2528 case(BLOCK_TYPE_EPB):
2529 /* packet block - we've found a packet */
2532 case(BLOCK_TYPE_IDB):
2533 /* A new interface */
2534 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2535 pcapng_process_idb(wth, pcapng, &wblock);
2538 case(BLOCK_TYPE_NRB):
2539 /* More name resolution entries */
2540 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2543 case(BLOCK_TYPE_ISB):
2544 /* Another interface statistics report */
2545 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2546 if (wth->interface_data->len <= wblock.data.if_stats.interface_id) {
2547 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces", wblock.data.if_stats.interface_id);
2549 /* Get the interface description */
2550 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2551 if (wtapng_if_descr->num_stat_entries == 0) {
2552 /* First ISB found, no previous entry */
2553 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2554 wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2557 if_stats.interface_id = wblock.data.if_stats.interface_id;
2558 if_stats.ts_high = wblock.data.if_stats.ts_high;
2559 if_stats.ts_low = wblock.data.if_stats.ts_low;
2561 if_stats.opt_comment = wblock.data.if_stats.opt_comment; /* NULL if not available */
2562 if_stats.isb_starttime = wblock.data.if_stats.isb_starttime;
2563 if_stats.isb_endtime = wblock.data.if_stats.isb_endtime;
2564 if_stats.isb_ifrecv = wblock.data.if_stats.isb_ifrecv;
2565 if_stats.isb_ifdrop = wblock.data.if_stats.isb_ifdrop;
2566 if_stats.isb_filteraccept = wblock.data.if_stats.isb_filteraccept;
2567 if_stats.isb_osdrop = wblock.data.if_stats.isb_osdrop;
2568 if_stats.isb_usrdeliv = wblock.data.if_stats.isb_usrdeliv;
2570 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2571 wtapng_if_descr->num_stat_entries++;
2576 /* XXX - improve handling of "unknown" blocks */
2577 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2584 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2585 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2591 /* classic wtap: seek to file position and read packet */
2593 pcapng_seek_read(wtap *wth, gint64 seek_off,
2594 struct wtap_pkthdr *phdr, Buffer *buf,
2595 int *err, gchar **err_info)
2597 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2598 block_return_val ret;
2599 wtapng_block_t wblock;
2602 /* seek to the right file position */
2603 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) < 0) {
2604 return FALSE; /* Seek error */
2606 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2608 wblock.frame_buffer = buf;
2609 wblock.packet_header = phdr;
2611 /* read the block */
2612 ret = pcapng_read_block(wth, wth->random_fh, pcapng, &wblock, err, err_info);
2613 pcapng_free_wtapng_block_data(&wblock);
2614 if (ret != PCAPNG_BLOCK_OK) {
2615 pcapng_debug1("pcapng_seek_read: couldn't read packet block (err=%d).",
2620 /* block must be a "Packet Block", an "Enhanced Packet Block",
2621 or a "Simple Packet Block" */
2622 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2623 wblock.type != BLOCK_TYPE_SPB) {
2624 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2632 /* classic wtap: close capture file */
2634 pcapng_close(wtap *wth)
2636 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2638 pcapng_debug0("pcapng_close: closing file");
2639 g_array_free(pcapng->interfaces, TRUE);
2644 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2646 pcapng_block_header_t bh;
2647 pcapng_section_header_block_t shb;
2648 const guint32 zero_pad = 0;
2649 gboolean have_options = FALSE;
2650 struct option option_hdr; /* guint16 type, guint16 value_length; */
2651 guint32 options_total_length = 0;
2652 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2653 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2656 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2657 /* Check if we should write comment option */
2658 if (wdh->shb_hdr->opt_comment) {
2659 have_options = TRUE;
2660 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2661 if ((comment_len % 4)) {
2662 comment_pad_len = 4 - (comment_len % 4);
2664 comment_pad_len = 0;
2666 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2669 /* Check if we should write shb_hardware option */
2670 if (wdh->shb_hdr->shb_hardware) {
2671 have_options = TRUE;
2672 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2673 if ((shb_hardware_len % 4)) {
2674 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2676 shb_hardware_pad_len = 0;
2678 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2681 /* Check if we should write shb_os option */
2682 if (wdh->shb_hdr->shb_os) {
2683 have_options = TRUE;
2684 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2685 if ((shb_os_len % 4)) {
2686 shb_os_pad_len = 4 - (shb_os_len % 4);
2690 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2693 /* Check if we should write shb_user_appl option */
2694 if (wdh->shb_hdr->shb_user_appl) {
2695 have_options = TRUE;
2696 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2697 if ((shb_user_appl_len % 4)) {
2698 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2700 shb_user_appl_pad_len = 0;
2702 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2706 /* End-of-options tag */
2707 options_total_length += 4;
2711 /* write block header */
2712 bh.block_type = BLOCK_TYPE_SHB;
2713 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2714 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2716 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2718 wdh->bytes_dumped += sizeof bh;
2720 /* write block fixed content */
2721 /* XXX - get these values from wblock? */
2722 shb.magic = 0x1A2B3C4D;
2723 shb.version_major = 1;
2724 shb.version_minor = 0;
2725 shb.section_length = -1;
2727 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2729 wdh->bytes_dumped += sizeof shb;
2731 /* XXX - write (optional) block options
2739 option_hdr.type = OPT_COMMENT;
2740 option_hdr.value_length = comment_len;
2741 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2743 wdh->bytes_dumped += 4;
2745 /* Write the comments string */
2746 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);
2747 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2749 wdh->bytes_dumped += comment_len;
2751 /* write padding (if any) */
2752 if (comment_pad_len != 0) {
2753 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2755 wdh->bytes_dumped += comment_pad_len;
2759 if (shb_hardware_len) {
2760 option_hdr.type = OPT_SHB_HARDWARE;
2761 option_hdr.value_length = shb_hardware_len;
2762 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2764 wdh->bytes_dumped += 4;
2766 /* Write the string */
2767 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);
2768 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2770 wdh->bytes_dumped += shb_hardware_len;
2772 /* write padding (if any) */
2773 if (shb_hardware_pad_len != 0) {
2774 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2776 wdh->bytes_dumped += shb_hardware_pad_len;
2781 option_hdr.type = OPT_SHB_OS;
2782 option_hdr.value_length = shb_os_len;
2783 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2785 wdh->bytes_dumped += 4;
2787 /* Write the string */
2788 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);
2789 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2791 wdh->bytes_dumped += shb_os_len;
2793 /* write padding (if any) */
2794 if (shb_os_pad_len != 0) {
2795 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2797 wdh->bytes_dumped += shb_os_pad_len;
2801 if (shb_user_appl_len) {
2802 option_hdr.type = OPT_SHB_USERAPPL;
2803 option_hdr.value_length = shb_user_appl_len;
2804 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2806 wdh->bytes_dumped += 4;
2808 /* Write the comments string */
2809 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);
2810 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2812 wdh->bytes_dumped += shb_user_appl_len;
2814 /* write padding (if any) */
2815 if (shb_user_appl_pad_len != 0) {
2816 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2818 wdh->bytes_dumped += shb_user_appl_pad_len;
2822 /* Write end of options if we have otions */
2824 option_hdr.type = OPT_EOFOPT;
2825 option_hdr.value_length = 0;
2826 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2828 wdh->bytes_dumped += 4;
2831 /* write block footer */
2832 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2833 sizeof bh.block_total_length, err))
2835 wdh->bytes_dumped += sizeof bh.block_total_length;
2842 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2844 pcapng_block_header_t bh;
2845 pcapng_interface_description_block_t idb;
2846 const guint32 zero_pad = 0;
2847 gboolean have_options = FALSE;
2848 struct option option_hdr; /* guint16 type, guint16 value_length; */
2849 guint32 options_total_length = 0;
2850 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2851 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;
2854 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2855 int_data->link_type,
2856 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2857 int_data->snap_len);
2859 if (int_data->link_type == (guint16)-1) {
2860 *err = WTAP_ERR_UNWRITABLE_ENCAP;
2864 /* Calculate options length */
2865 if (int_data->opt_comment) {
2866 have_options = TRUE;
2867 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2868 if ((comment_len % 4)) {
2869 comment_pad_len = 4 - (comment_len % 4);
2871 comment_pad_len = 0;
2873 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2877 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2879 if (int_data->if_name) {
2880 have_options = TRUE;
2881 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2882 if ((if_name_len % 4)) {
2883 if_name_pad_len = 4 - (if_name_len % 4);
2885 if_name_pad_len = 0;
2887 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2891 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2893 if (int_data->if_description) {
2894 have_options = TRUE;
2895 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2896 if ((if_description_len % 4)) {
2897 if_description_pad_len = 4 - (if_description_len % 4);
2899 if_description_pad_len = 0;
2901 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2903 /* Currently not handled
2904 * if_IPv4addr 4 Interface network address and netmask.
2905 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2906 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2907 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2910 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2912 if (int_data->if_speed != 0) {
2913 have_options = TRUE;
2914 options_total_length = options_total_length + 8 + 4;
2917 * if_tsresol 9 Resolution of timestamps.
2919 if (int_data->if_tsresol != 0) {
2920 have_options = TRUE;
2921 options_total_length = options_total_length + 4 + 4;
2924 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2927 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2928 * 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).
2930 if (int_data->if_filter_str) {
2931 have_options = TRUE;
2932 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2933 if ((if_filter_str_len % 4)) {
2934 if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2936 if_filter_str_pad_len = 0;
2938 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2941 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2943 if (int_data->if_os) {
2944 have_options = TRUE;
2945 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2946 if ((if_os_len % 4)) {
2947 if_os_pad_len = 4 - (if_os_len % 4);
2951 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2954 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2955 * -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.
2957 if (int_data->if_fcslen != 0) {
2960 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2961 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2965 /* End-of-options tag */
2966 options_total_length += 4;
2969 /* write block header */
2970 bh.block_type = BLOCK_TYPE_IDB;
2971 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2973 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2975 wdh->bytes_dumped += sizeof bh;
2977 /* write block fixed content */
2978 idb.linktype = int_data->link_type;
2980 idb.snaplen = int_data->snap_len;
2982 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2984 wdh->bytes_dumped += sizeof idb;
2986 /* XXX - write (optional) block options */
2987 if (comment_len != 0) {
2988 option_hdr.type = OPT_COMMENT;
2989 option_hdr.value_length = comment_len;
2990 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2992 wdh->bytes_dumped += 4;
2994 /* Write the comments string */
2995 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);
2996 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2998 wdh->bytes_dumped += comment_len;
3000 /* write padding (if any) */
3001 if (comment_pad_len != 0) {
3002 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3004 wdh->bytes_dumped += comment_pad_len;
3008 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
3010 if (if_name_len !=0) {
3011 option_hdr.type = OPT_IDB_NAME;
3012 option_hdr.value_length = if_name_len;
3013 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3015 wdh->bytes_dumped += 4;
3017 /* Write the comments string */
3018 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);
3019 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
3021 wdh->bytes_dumped += if_name_len;
3023 /* write padding (if any) */
3024 if (if_name_pad_len != 0) {
3025 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
3027 wdh->bytes_dumped += if_name_pad_len;
3031 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
3033 if (if_description_len != 0) {
3034 option_hdr.type = OPT_IDB_NAME;
3035 option_hdr.value_length = if_description_len;
3036 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3038 wdh->bytes_dumped += 4;
3040 /* Write the comments string */
3041 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);
3042 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
3044 wdh->bytes_dumped += if_description_len;
3046 /* write padding (if any) */
3047 if (if_description_pad_len != 0) {
3048 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
3050 wdh->bytes_dumped += if_description_pad_len;
3053 /* Currently not handled
3054 * if_IPv4addr 4 Interface network address and netmask.
3055 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
3056 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
3057 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
3060 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
3062 if (int_data->if_speed != 0) {
3063 option_hdr.type = OPT_IDB_SPEED;
3064 option_hdr.value_length = 8;
3065 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3067 wdh->bytes_dumped += 4;
3069 /* Write the comments string */
3070 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
3071 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
3073 wdh->bytes_dumped += 8;
3076 * if_tsresol 9 Resolution of timestamps.
3077 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
3078 * If the Most Significant Bit is equal to zero, the remaining bits indicates
3079 * the resolution of the timestamp as as a negative power of 10
3081 if (int_data->if_tsresol != 0) {
3082 option_hdr.type = OPT_IDB_TSRESOL;
3083 option_hdr.value_length = 1;
3084 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3086 wdh->bytes_dumped += 4;
3088 /* Write the time stamp resolution */
3089 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
3090 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
3092 wdh->bytes_dumped += 1;
3093 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
3095 wdh->bytes_dumped += 3;
3098 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
3101 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
3103 /* Libpcap string variant */
3104 if (if_filter_str_len !=0) {
3105 option_hdr.type = OPT_IDB_FILTER;
3106 option_hdr.value_length = if_filter_str_len;
3107 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
3108 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3110 wdh->bytes_dumped += 4;
3112 /* Write the zero indicating libpcap filter variant */
3113 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
3115 wdh->bytes_dumped += 1;
3117 /* Write the comments string */
3118 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);
3119 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
3120 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
3122 wdh->bytes_dumped += if_filter_str_len - 1;
3124 /* write padding (if any) */
3125 if (if_filter_str_pad_len != 0) {
3126 if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
3128 wdh->bytes_dumped += if_filter_str_pad_len;
3132 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
3134 if (if_os_len != 0) {
3135 option_hdr.type = OPT_IDB_OS;
3136 option_hdr.value_length = if_os_len;
3137 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3139 wdh->bytes_dumped += 4;
3141 /* Write the comments string */
3142 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);
3143 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
3145 wdh->bytes_dumped += if_os_len;
3147 /* write padding (if any) */
3148 if (if_os_pad_len != 0) {
3149 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
3151 wdh->bytes_dumped += if_os_pad_len;
3156 option_hdr.type = OPT_EOFOPT;
3157 option_hdr.value_length = 0;
3158 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3160 wdh->bytes_dumped += 4;
3164 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
3167 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
3168 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
3171 /* write block footer */
3172 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3173 sizeof bh.block_total_length, err))
3175 wdh->bytes_dumped += sizeof bh.block_total_length;
3181 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
3184 pcapng_block_header_t bh;
3185 pcapng_interface_statistics_block_t isb;
3186 const guint32 zero_pad = 0;
3187 gboolean have_options = FALSE;
3188 struct option option_hdr; /* guint16 type, guint16 value_length; */
3189 guint32 options_total_length = 0;
3190 guint32 comment_len = 0;
3191 guint32 comment_pad_len = 0;
3193 pcapng_debug0("pcapng_write_interface_statistics_block");
3196 /* Calculate options length */
3197 if (if_stats->opt_comment) {
3198 have_options = TRUE;
3199 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
3200 if ((comment_len % 4)) {
3201 comment_pad_len = 4 - (comment_len % 4);
3203 comment_pad_len = 0;
3205 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3207 /*guint64 isb_starttime */
3208 if (if_stats->isb_starttime != 0) {
3209 have_options = TRUE;
3210 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3212 /*guint64 isb_endtime */
3213 if (if_stats->isb_endtime != 0) {
3214 have_options = TRUE;
3215 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3217 /*guint64 isb_ifrecv */
3218 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3219 have_options = TRUE;
3220 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3222 /*guint64 isb_ifdrop */
3223 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3224 have_options = TRUE;
3225 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3227 /*guint64 isb_filteraccept */
3228 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3229 have_options = TRUE;
3230 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3232 /*guint64 isb_osdrop */
3233 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3234 have_options = TRUE;
3235 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3237 /*guint64 isb_usrdeliv */
3238 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3239 have_options = TRUE;
3240 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3243 /* write block header */
3245 /* End-of-optios tag */
3246 options_total_length += 4;
3249 /* write block header */
3250 bh.block_type = BLOCK_TYPE_ISB;
3251 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3253 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3255 wdh->bytes_dumped += sizeof bh;
3257 /* write block fixed content */
3258 isb.interface_id = if_stats->interface_id;
3259 isb.timestamp_high = if_stats->ts_high;
3260 isb.timestamp_low = if_stats->ts_low;
3263 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3265 wdh->bytes_dumped += sizeof isb;
3267 /* write (optional) block options */
3269 option_hdr.type = OPT_COMMENT;
3270 option_hdr.value_length = comment_len;
3271 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3273 wdh->bytes_dumped += 4;
3275 /* Write the comments string */
3276 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);
3277 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3279 wdh->bytes_dumped += comment_len;
3281 /* write padding (if any) */
3282 if (comment_pad_len != 0) {
3283 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3285 wdh->bytes_dumped += comment_pad_len;
3288 /*guint64 isb_starttime */
3289 if (if_stats->isb_starttime != 0) {
3292 option_hdr.type = OPT_ISB_STARTTIME;
3293 option_hdr.value_length = 8;
3294 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3295 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3296 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3298 wdh->bytes_dumped += 4;
3300 /* Write isb_starttime */
3301 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3302 if (!wtap_dump_file_write(wdh, &high, 4, err))
3304 wdh->bytes_dumped += 4;
3305 if (!wtap_dump_file_write(wdh, &low, 4, err))
3307 wdh->bytes_dumped += 4;
3309 /*guint64 isb_endtime */
3310 if (if_stats->isb_endtime != 0) {
3313 option_hdr.type = OPT_ISB_ENDTIME;
3314 option_hdr.value_length = 8;
3315 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3316 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3317 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3319 wdh->bytes_dumped += 4;
3321 /* Write isb_endtime */
3322 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3323 if (!wtap_dump_file_write(wdh, &high, 4, err))
3325 wdh->bytes_dumped += 4;
3326 if (!wtap_dump_file_write(wdh, &low, 4, err))
3328 wdh->bytes_dumped += 4;
3330 /*guint64 isb_ifrecv;*/
3331 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3332 option_hdr.type = OPT_ISB_IFRECV;
3333 option_hdr.value_length = 8;
3334 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3336 wdh->bytes_dumped += 4;
3338 /* Write isb_ifrecv */
3339 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3340 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3342 wdh->bytes_dumped += 8;
3344 /*guint64 isb_ifdrop;*/
3345 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3346 option_hdr.type = OPT_ISB_IFDROP;
3347 option_hdr.value_length = 8;
3348 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3350 wdh->bytes_dumped += 4;
3352 /* Write isb_ifdrop */
3353 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3354 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3356 wdh->bytes_dumped += 8;
3358 /*guint64 isb_filteraccept;*/
3359 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3360 option_hdr.type = OPT_ISB_FILTERACCEPT;
3361 option_hdr.value_length = 8;
3362 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3364 wdh->bytes_dumped += 4;
3366 /* Write isb_filteraccept */
3367 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3368 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3370 wdh->bytes_dumped += 8;
3372 /*guint64 isb_osdrop;*/
3373 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3374 option_hdr.type = OPT_ISB_OSDROP;
3375 option_hdr.value_length = 8;
3376 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3378 wdh->bytes_dumped += 4;
3380 /* Write isb_osdrop */
3381 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3382 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3384 wdh->bytes_dumped += 8;
3386 /*guint64 isb_usrdeliv;*/
3387 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3388 option_hdr.type = OPT_ISB_USRDELIV;
3389 option_hdr.value_length = 8;
3390 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3392 wdh->bytes_dumped += 4;
3394 /* Write isb_usrdeliv */
3395 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3396 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3398 wdh->bytes_dumped += 8;
3402 option_hdr.type = OPT_EOFOPT;
3403 option_hdr.value_length = 0;
3404 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3406 wdh->bytes_dumped += 4;
3409 /* write block footer */
3410 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3411 sizeof bh.block_total_length, err))
3413 wdh->bytes_dumped += sizeof bh.block_total_length;
3421 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3422 const struct wtap_pkthdr *phdr,
3423 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3425 pcapng_block_header_t bh;
3426 pcapng_enhanced_packet_block_t epb;
3428 const guint32 zero_pad = 0;
3431 gboolean have_options = FALSE;
3432 guint32 options_total_length = 0;
3433 struct option option_hdr;
3434 guint32 comment_len = 0, comment_pad_len = 0;
3435 wtapng_if_descr_t int_data;
3437 /* Don't write anything we're not willing to read. */
3438 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
3439 *err = WTAP_ERR_PACKET_TOO_LARGE;
3443 phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3444 if ((phdr_len + phdr->caplen) % 4) {
3445 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3450 /* Check if we should write comment option */
3451 if (phdr->opt_comment) {
3452 have_options = TRUE;
3453 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3454 if ((comment_len % 4)) {
3455 comment_pad_len = 4 - (comment_len % 4);
3457 comment_pad_len = 0;
3459 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3461 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3462 have_options = TRUE;
3463 options_total_length = options_total_length + 8;
3466 /* End-of options tag */
3467 options_total_length += 4;
3470 /* write (enhanced) packet block header */
3471 bh.block_type = BLOCK_TYPE_EPB;
3472 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3474 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3476 wdh->bytes_dumped += sizeof bh;
3478 /* write block fixed content */
3479 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3480 epb.interface_id = phdr->interface_id;
3483 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3484 * data to pcap-NG files even if we *don't* have interface
3487 epb.interface_id = 0;
3490 * Split the 64-bit timestamp into two 32-bit pieces, using
3491 * the time stamp resolution for the interface.
3493 if (epb.interface_id >= wdh->interface_data->len) {
3495 * Our caller is doing something bad.
3497 *err = WTAP_ERR_INTERNAL;
3500 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3502 ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3503 (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3504 epb.timestamp_high = (guint32)(ts >> 32);
3505 epb.timestamp_low = (guint32)ts;
3506 epb.captured_len = phdr->caplen + phdr_len;
3507 epb.packet_len = phdr->len + phdr_len;
3509 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3511 wdh->bytes_dumped += sizeof epb;
3513 /* write pseudo header */
3514 if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3517 wdh->bytes_dumped += phdr_len;
3519 /* write packet data */
3520 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3522 wdh->bytes_dumped += phdr->caplen;
3524 /* write padding (if any) */
3526 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3528 wdh->bytes_dumped += pad_len;
3531 /* XXX - write (optional) block options */
3532 /* options defined in Section 2.5 (Options)
3533 * Name Code Length Description
3534 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3536 * Enhanced Packet Block options
3537 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3538 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3539 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3540 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3541 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3542 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3543 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3544 * The hash covers only the packet, not the header added by the capture driver:
3545 * this gives the possibility to calculate it inside the network card.
3546 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3547 * data acquisition system and the capture library.
3548 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3549 * between this packet and the preceding one.
3550 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3552 if (phdr->opt_comment) {
3553 option_hdr.type = OPT_COMMENT;
3554 option_hdr.value_length = comment_len;
3555 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3557 wdh->bytes_dumped += 4;
3559 /* Write the comments string */
3560 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3561 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3563 wdh->bytes_dumped += comment_len;
3565 /* write padding (if any) */
3566 if (comment_pad_len != 0) {
3567 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3569 wdh->bytes_dumped += comment_pad_len;
3572 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3576 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3577 option_hdr.type = OPT_EPB_FLAGS;
3578 option_hdr.value_length = 4;
3579 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3581 wdh->bytes_dumped += 4;
3582 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3584 wdh->bytes_dumped += 4;
3585 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3587 /* Write end of options if we have options */
3589 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3591 wdh->bytes_dumped += 4;
3594 /* write block footer */
3595 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3596 sizeof bh.block_total_length, err))
3598 wdh->bytes_dumped += sizeof bh.block_total_length;
3604 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3606 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
3608 pcapng_block_header_t bh;
3609 pcapng_name_resolution_block_t nrb;
3611 gint rec_off, namelen, tot_rec_len;
3612 hashipv4_t *ipv4_hash_list_entry;
3613 hashipv6_t *ipv6_hash_list_entry;
3616 if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
3620 rec_off = 8; /* block type + block total length */
3621 bh.block_type = BLOCK_TYPE_NRB;
3622 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3623 rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3625 if (wdh->addrinfo_lists->ipv4_addr_list){
3627 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3628 while(ipv4_hash_list_entry != NULL){
3630 nrb.record_type = NRES_IP4RECORD;
3631 namelen = (gint)strlen(ipv4_hash_list_entry->name) + 1;
3632 nrb.record_len = 4 + namelen;
3633 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3635 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3636 /* We know the total length now; copy the block header. */
3637 memcpy(rec_data, &bh, sizeof(bh));
3640 memset(rec_data + rec_off, 0, 4);
3643 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3645 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3647 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3651 wdh->bytes_dumped += bh.block_total_length;
3653 /*Start a new NRB */
3654 rec_off = 8; /* block type + block total length */
3655 bh.block_type = BLOCK_TYPE_NRB;
3656 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3660 bh.block_total_length += tot_rec_len;
3661 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3663 memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
3665 memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
3667 memset(rec_data + rec_off, 0, PADDING4(namelen));
3668 rec_off += PADDING4(namelen);
3669 pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
3672 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3674 g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
3675 wdh->addrinfo_lists->ipv4_addr_list = NULL;
3678 if (wdh->addrinfo_lists->ipv6_addr_list){
3680 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3681 while(ipv6_hash_list_entry != NULL){
3683 nrb.record_type = NRES_IP6RECORD;
3684 namelen = (gint)strlen(ipv6_hash_list_entry->name) + 1;
3685 nrb.record_len = 16 + namelen; /* 16 bytes IPv6 address length */
3686 /* 2 bytes record type, 2 bytes length field */
3687 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3689 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3690 /* We know the total length now; copy the block header. */
3691 memcpy(rec_data, &bh, sizeof(bh));
3694 memset(rec_data + rec_off, 0, 4);
3697 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3699 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3701 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3705 wdh->bytes_dumped += bh.block_total_length;
3707 /*Start a new NRB */
3708 rec_off = 8; /* block type + block total length */
3709 bh.block_type = BLOCK_TYPE_NRB;
3710 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3714 bh.block_total_length += tot_rec_len;
3715 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3717 memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
3719 memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
3721 memset(rec_data + rec_off, 0, PADDING4(namelen));
3722 rec_off += PADDING4(namelen);
3723 pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
3726 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3728 g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
3729 wdh->addrinfo_lists->ipv6_addr_list = NULL;
3732 /* add options, if any */
3734 gboolean have_options = FALSE;
3735 guint32 options_total_length = 0;
3736 struct option option_hdr;
3737 guint32 comment_len = 0, comment_pad_len = 0;
3738 wtapng_name_res_t *nrb_hdr = wdh->nrb_hdr;
3739 gint prev_rec_off = rec_off;
3741 /* get lengths first to make sure we can fit this into the block */
3742 if (nrb_hdr->opt_comment) {
3743 have_options = TRUE;
3744 comment_len = (guint32)strlen(nrb_hdr->opt_comment) & 0xffff;
3745 if ((comment_len % 4)) {
3746 comment_pad_len = 4 - (comment_len % 4);
3748 comment_pad_len = 0;
3750 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3754 /* End-of options tag */
3755 options_total_length += 4;
3757 if (rec_off + options_total_length > NRES_REC_MAX_SIZE) {
3758 /* Too much; copy the block header. */
3759 memcpy(rec_data, &bh, sizeof(bh));
3762 memset(rec_data + rec_off, 0, 4);
3765 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3767 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3769 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3773 wdh->bytes_dumped += bh.block_total_length;
3775 /*Start a new NRB */
3776 prev_rec_off = rec_off = 8; /* block type + block total length */
3777 bh.block_type = BLOCK_TYPE_NRB;
3778 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3781 bh.block_total_length += options_total_length;
3783 if (comment_len > 0) {
3784 option_hdr.type = OPT_COMMENT;
3785 option_hdr.value_length = comment_len;
3787 memcpy(rec_data + rec_off, &option_hdr, sizeof(option_hdr));
3788 rec_off += (gint)sizeof(option_hdr);
3790 /* Write the comments string */
3791 memcpy(rec_data + rec_off, nrb_hdr->opt_comment, comment_len);
3792 rec_off += comment_len;
3793 memset(rec_data + rec_off, 0, comment_pad_len);
3794 rec_off += comment_pad_len;
3796 pcapng_debug2("pcapng_write_name_resolution_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3801 /* Write end of options */
3802 memset(rec_data + rec_off, 0, 4);
3806 g_assert((gint)options_total_length == rec_off - prev_rec_off);
3810 /* We know the total length now; copy the block header. */
3811 memcpy(rec_data, &bh, sizeof(bh));
3814 memset(rec_data + rec_off, 0, 4);
3817 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3819 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3821 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3827 wdh->bytes_dumped += bh.block_total_length;
3831 static gboolean pcapng_dump(wtap_dumper *wdh,
3832 const struct wtap_pkthdr *phdr,
3833 const guint8 *pd, int *err, gchar **err_info _U_)
3835 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3837 block_handler *handler;
3840 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3842 wtap_encap_string(phdr->pkt_encap));
3844 switch (phdr->rec_type) {
3846 case REC_TYPE_PACKET:
3847 if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3852 case REC_TYPE_FT_SPECIFIC_EVENT:
3853 case REC_TYPE_FT_SPECIFIC_REPORT:
3856 * Do we have a handler for this block type?
3858 if (block_handlers != NULL &&
3859 (handler = (block_handler *)g_hash_table_lookup(block_handlers,
3860 GUINT_TO_POINTER(pseudo_header->ftsrec.record_type))) != NULL) {
3861 /* Yes. Call it to write out this record. */
3862 if (!handler->write(wdh, phdr, pd, err))
3868 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
3874 /* We don't support writing this record type. */
3875 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
3883 /* Finish writing to a dump file.
3884 Returns TRUE on success, FALSE on failure. */
3885 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3889 /* Flush any hostname resolution info we may have */
3890 pcapng_write_name_resolution_block(wdh, err);
3892 for (i = 0; i < wdh->interface_data->len; i++) {
3894 /* Get the interface description */
3895 wtapng_if_descr_t int_data;
3897 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3898 for (j = 0; j < int_data.num_stat_entries; j++) {
3899 wtapng_if_stats_t if_stats;
3901 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3902 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3903 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3909 pcapng_debug0("pcapng_dump_close");
3914 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3917 pcapng_dump_open(wtap_dumper *wdh, int *err)
3921 pcapng_debug0("pcapng_dump_open");
3922 /* This is a pcapng file */
3923 wdh->subtype_write = pcapng_dump;
3924 wdh->subtype_close = pcapng_dump_close;
3926 if (wdh->interface_data->len == 0) {
3927 pcapng_debug0("There are no interfaces. Can't handle that...");
3928 *err = WTAP_ERR_INTERNAL;
3932 /* write the section header block */
3933 if (!pcapng_write_section_header_block(wdh, err)) {
3936 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3938 /* Write the Interface description blocks */
3939 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u",
3940 wdh->interface_data->len);
3942 for (i = 0; i < wdh->interface_data->len; i++) {
3944 /* Get the interface description */
3945 wtapng_if_descr_t int_data;
3947 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3949 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3959 /* Returns 0 if we could write the specified encapsulation type,
3960 an error indication otherwise. */
3961 int pcapng_dump_can_write_encap(int wtap_encap)
3963 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3965 wtap_encap_string(wtap_encap));
3967 /* Per-packet encapsulation is supported. */
3968 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3971 /* Make sure we can figure out this DLT type */
3972 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3973 return WTAP_ERR_UNWRITABLE_ENCAP;
3979 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3984 * indent-tabs-mode: nil
3987 * vi: set shiftwidth=4 tabstop=8 expandtab:
3988 * :indentSize=4:tabSize=8:noTabs=true: