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 * http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
27 * http://wiki.wireshark.org/Development/PcapNg
38 #include <epan/addr_resolv.h>
39 #include "file_wrappers.h"
42 #include "pcap-common.h"
43 #include "pcap-encap.h"
47 #define pcapng_debug0(str) g_warning(str)
48 #define pcapng_debug1(str,p1) g_warning(str,p1)
49 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
50 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
52 #define pcapng_debug0(str)
53 #define pcapng_debug1(str,p1)
54 #define pcapng_debug2(str,p1,p2)
55 #define pcapng_debug3(str,p1,p2,p3)
59 pcapng_read(wtap *wth, int *err, gchar **err_info,
62 pcapng_seek_read(wtap *wth, gint64 seek_off,
63 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
65 pcapng_close(wtap *wth);
68 /* pcapng: common block header for every block type */
69 typedef struct pcapng_block_header_s {
71 guint32 block_total_length;
72 /* x bytes block_body */
73 /* guint32 block_total_length */
74 } pcapng_block_header_t;
77 * Minimum block size = size of block header + size of block trailer.
79 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
82 * In order to keep from trying to allocate large chunks of memory,
83 * which could either fail or, even if it succeeds, chew up so much
84 * address space or memory+backing store as not to leave room for
85 * anything else, we impose an upper limit on the size of blocks
86 * we're willing to handle.
88 * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
89 * don't try saying that on Wikipedia :-) :-) :-)).
91 #define MAX_BLOCK_SIZE (16*1024*1024)
93 /* pcapng: section header block */
94 typedef struct pcapng_section_header_block_s {
95 /* pcapng_block_header_t */
97 guint16 version_major;
98 guint16 version_minor;
99 guint64 section_length; /* might be -1 for unknown */
100 /* ... Options ... */
101 } pcapng_section_header_block_t;
104 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
106 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
108 /* pcapng: interface description block */
109 typedef struct pcapng_interface_description_block_s {
113 /* ... Options ... */
114 } pcapng_interface_description_block_t;
117 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
119 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
121 /* pcapng: packet block (obsolete) */
122 typedef struct pcapng_packet_block_s {
123 guint16 interface_id;
125 guint32 timestamp_high;
126 guint32 timestamp_low;
127 guint32 captured_len;
129 /* ... Packet Data ... */
130 /* ... Padding ... */
131 /* ... Options ... */
132 } pcapng_packet_block_t;
135 * Minimum PB size = minimum block size + size of fixed length portion of PB.
137 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
139 /* pcapng: enhanced packet block */
140 typedef struct pcapng_enhanced_packet_block_s {
141 guint32 interface_id;
142 guint32 timestamp_high;
143 guint32 timestamp_low;
144 guint32 captured_len;
146 /* ... Packet Data ... */
147 /* ... Padding ... */
148 /* ... Options ... */
149 } pcapng_enhanced_packet_block_t;
152 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
154 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
156 /* pcapng: simple packet block */
157 typedef struct pcapng_simple_packet_block_s {
159 /* ... Packet Data ... */
160 /* ... Padding ... */
161 } pcapng_simple_packet_block_t;
164 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
166 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
168 /* pcapng: name resolution block */
169 typedef struct pcapng_name_resolution_block_s {
173 } pcapng_name_resolution_block_t;
176 * Minimum NRB size = minimum block size + size of smallest NRB record
177 * (there must at least be an "end of records" record).
179 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
181 /* pcapng: interface statistics block */
182 typedef struct pcapng_interface_statistics_block_s {
183 guint32 interface_id;
184 guint32 timestamp_high;
185 guint32 timestamp_low;
186 /* ... Options ... */
187 } pcapng_interface_statistics_block_t;
190 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
192 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
194 /* pcapng: common option header for every option type */
195 typedef struct pcapng_option_header_s {
197 guint16 option_length;
198 /* ... x bytes Option Body ... */
199 /* ... Padding ... */
200 } pcapng_option_header_t;
204 guint16 value_length;
208 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
209 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
210 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
211 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
212 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
213 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
214 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
218 #define OPT_COMMENT 1
219 #define OPT_SHB_HARDWARE 2
221 #define OPT_SHB_USERAPPL 4
222 #define OPT_EPB_FLAGS 2
223 #define OPT_EPB_HASH 3
224 #define OPT_EPB_DROPCOUNT 4
226 /* Capture section */
228 /* Moved to wtap.h */
229 typedef struct wtapng_section_s {
231 guint64 section_length;
233 gchar *opt_comment; /* NULL if not available */
234 gchar *shb_hardware; /* NULL if not available */
235 gchar *shb_os; /* NULL if not available */
236 gchar *shb_user_appl; /* NULL if not available */
241 /* Moved to wtap.h */
243 /* Interface Description
246 * if_name 2 A UTF-8 string containing the name of the device used to capture data. "eth0" / "\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}" / ...
247 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
248 * if_IPv4addr 4 Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
249 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
250 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
251 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
252 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
253 * if_tsresol 9 Resolution of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10 (e.g. 6 means microsecond resolution, timestamps are the number of microseconds since 1/1/1970). If the Most Significant Bit is equal to one, the remaining bits indicates the resolution as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a resolution of 10^-6 is assumed (i.e. timestamps have the same resolution of the standard 'libpcap' timestamps). 6
254 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
255 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO). (TODO: better use different options for different fields? e.g. if_filter_pcap, if_filter_bpf, ...) 00 "tcp port 23 and host 10.0.0.5"
256 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory))) because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
257 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. For link layers whose FCS length can change during time, the Packet Block Flags Word can be used (see Appendix A (Packet Block Flags Word)). 4
258 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps. The time zone of the offset can be specified with the option if_tzone. TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
261 typedef struct wtapng_if_descr_s {
267 gchar *opt_comment; /* NULL if not available */
268 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
269 gchar *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
270 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
271 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
272 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
273 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
274 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
275 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
276 * If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10
278 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
279 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
280 * 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).
282 gchar *if_os; /* NULL if not available, 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. */
283 gint8 if_fcslen; /* -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. */
284 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
289 typedef struct wtapng_packet_s {
291 guint32 ts_high; /* seconds since 1.1.1970 */
292 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
293 guint32 cap_len; /* data length in the file */
294 guint32 packet_len; /* data length on the wire */
295 guint32 interface_id; /* identifier of the interface. */
296 guint16 drops_count; /* drops count, only valid for packet block */
297 /* 0xffff if information no available */
299 /* XXX - put the packet data / pseudo_header here as well? */
303 typedef struct wtapng_simple_packet_s {
305 guint32 cap_len; /* data length in the file */
306 guint32 packet_len; /* data length on the wire */
307 guint32 pseudo_header_len;
309 /* XXX - put the packet data / pseudo_header here as well? */
310 } wtapng_simple_packet_t;
312 /* Name Resolution */
313 typedef struct wtapng_name_res_s {
315 gchar *opt_comment; /* NULL if not available */
320 /* Interface Statistics moved to wtap.h*/
321 typedef struct wtapng_if_stats_s {
323 guint32 interface_id;
327 gchar *opt_comment; /* NULL if not available */
328 guint64 isb_starttime;
332 guint64 isb_filteraccept;
334 guint64 isb_usrdeliv;
338 typedef struct wtapng_block_s {
339 guint32 type; /* block_type as defined by pcapng */
341 wtapng_section_t section;
342 wtapng_if_descr_t if_descr;
343 wtapng_name_res_t name_res;
344 wtapng_if_stats_t if_stats;
348 * XXX - currently don't know how to handle these!
350 * For one thing, when we're reading a block, they must be
351 * writable, i.e. not const, so that we can read into them,
352 * but, when we're writing a block, they can be const, and,
353 * in fact, they sometimes point to const values.
355 struct wtap_pkthdr *packet_header;
356 Buffer *frame_buffer;
360 /* Interface data in private struct */
361 typedef struct interface_info_s {
364 guint64 time_units_per_second;
368 gboolean shb_read; /**< Set when first SHB read, second read will fail */
369 gboolean byte_swapped;
370 guint16 version_major;
371 guint16 version_minor;
372 GArray *interfaces; /**< Interfaces found in the capture file. */
374 wtap_new_ipv4_callback_t add_new_ipv4;
375 wtap_new_ipv6_callback_t add_new_ipv6;
379 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
380 char *content, guint len, guint to_read,
381 int *err, gchar **err_info)
385 guint64 file_offset64;
387 /* sanity check: don't run past the end of the block */
388 if (to_read < sizeof (*oh)) {
389 *err = WTAP_ERR_BAD_FILE;
390 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
394 /* read option header */
395 errno = WTAP_ERR_CANT_READ;
396 bytes_read = file_read(oh, sizeof (*oh), fh);
397 if (bytes_read != sizeof (*oh)) {
398 pcapng_debug0("pcapng_read_option: failed to read option");
399 *err = file_error(fh, err_info);
404 block_read = sizeof (*oh);
405 if (pn->byte_swapped) {
406 oh->option_code = GUINT16_SWAP_LE_BE(oh->option_code);
407 oh->option_length = GUINT16_SWAP_LE_BE(oh->option_length);
410 /* sanity check: don't run past the end of the block */
411 if (to_read < sizeof (*oh) + oh->option_length) {
412 *err = WTAP_ERR_BAD_FILE;
413 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
417 /* sanity check: option length */
418 if (oh->option_length > len) {
419 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
420 oh->option_length, len);
424 /* read option content */
425 errno = WTAP_ERR_CANT_READ;
426 bytes_read = file_read(content, oh->option_length, fh);
427 if (bytes_read != oh->option_length) {
428 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
429 *err = file_error(fh, err_info);
434 block_read += oh->option_length;
436 /* jump over potential padding bytes at end of option */
437 if ( (oh->option_length % 4) != 0) {
438 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
439 if (file_offset64 <= 0) {
444 block_read += 4 - (oh->option_length % 4);
452 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
453 pcapng_block_header_t *bh, pcapng_t *pn,
454 wtapng_block_t *wblock, int *err,
459 guint to_read, opt_cont_buf_len;
460 pcapng_section_header_block_t shb;
461 pcapng_option_header_t oh;
462 char *option_content = NULL; /* Allocate as large as the options block */
465 * Is this block long enough to be an SHB?
467 if (bh->block_total_length < MIN_SHB_SIZE) {
472 return 0; /* probably not a pcap-ng file */
473 *err = WTAP_ERR_BAD_FILE;
474 *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",
475 bh->block_total_length, MIN_SHB_SIZE);
479 /* read block content */
480 errno = WTAP_ERR_CANT_READ;
481 bytes_read = file_read(&shb, sizeof shb, fh);
482 if (bytes_read != sizeof shb) {
483 *err = file_error(fh, err_info);
487 * We're reading this as part of an open,
488 * and this block is too short to be
489 * an SHB, so the file is too short
490 * to be a pcap-ng file.
496 * Otherwise, just report this as an error.
498 *err = WTAP_ERR_SHORT_READ;
502 block_read = bytes_read;
504 /* is the magic number one we expect? */
507 /* this seems pcapng with correct byte order */
508 pn->byte_swapped = FALSE;
509 pn->version_major = shb.version_major;
510 pn->version_minor = shb.version_minor;
512 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
513 pn->version_major, pn->version_minor, bh->block_total_length);
516 /* this seems pcapng with swapped byte order */
517 pn->byte_swapped = TRUE;
518 pn->version_major = GUINT16_SWAP_LE_BE(shb.version_major);
519 pn->version_minor = GUINT16_SWAP_LE_BE(shb.version_minor);
521 /* tweak the block length to meet current swapping that we know now */
522 bh->block_total_length = GUINT32_SWAP_LE_BE(bh->block_total_length);
524 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
525 pn->version_major, pn->version_minor, bh->block_total_length);
528 /* Not a "pcapng" magic number we know about. */
530 /* Not a pcap-ng file. */
535 *err = WTAP_ERR_BAD_FILE;
536 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
540 /* OK, at this point we assume it's a pcap-ng file.
542 Don't try to allocate memory for a huge number of options, as
543 that might fail and, even if it succeeds, it might not leave
544 any address space or memory+backing store for anything else.
546 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
547 We check for this *after* checking the SHB for its byte
548 order magic number, so that non-pcap-ng files are less
549 likely to be treated as bad pcap-ng files. */
550 if (bh->block_total_length > MAX_BLOCK_SIZE) {
551 *err = WTAP_ERR_BAD_FILE;
552 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
553 bh->block_total_length, MAX_BLOCK_SIZE);
557 /* We currently only suport one SHB */
558 if (pn->shb_read == TRUE) {
559 *err = WTAP_ERR_UNSUPPORTED;
560 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported");
564 /* we currently only understand SHB V1.0 */
565 if (pn->version_major != 1 || pn->version_minor > 0) {
566 *err = WTAP_ERR_UNSUPPORTED;
567 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
568 pn->version_major, pn->version_minor);
573 /* 64bit section_length (currently unused) */
574 if (pn->byte_swapped) {
575 wblock->data.section.section_length = GUINT64_SWAP_LE_BE(shb.section_length);
577 wblock->data.section.section_length = shb.section_length;
580 /* Option defaults */
581 wblock->data.section.opt_comment = NULL;
582 wblock->data.section.shb_hardware = NULL;
583 wblock->data.section.shb_os = NULL;
584 wblock->data.section.shb_user_appl = NULL;
587 errno = WTAP_ERR_CANT_READ;
588 to_read = bh->block_total_length - MIN_SHB_SIZE;
590 /* Allocate enough memory to hold all options */
591 opt_cont_buf_len = to_read;
592 option_content = (char *)g_try_malloc(opt_cont_buf_len);
593 if (opt_cont_buf_len != 0 && option_content == NULL) {
594 *err = ENOMEM; /* we assume we're out of memory */
597 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
598 while (to_read != 0) {
600 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
601 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
602 if (bytes_read <= 0) {
603 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
606 block_read += bytes_read;
607 to_read -= bytes_read;
609 /* handle option content */
610 switch (oh.option_code) {
613 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
615 /* padding should be ok here, just get out of this */
619 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
620 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
621 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
623 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
626 case(OPT_SHB_HARDWARE):
627 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
628 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
629 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
631 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
635 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
636 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
637 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
639 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
642 case(OPT_SHB_USERAPPL):
643 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
644 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
645 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
647 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
651 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
652 oh.option_code, oh.option_length);
655 g_free(option_content);
661 /* "Interface Description Block" */
663 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
664 wtapng_block_t *wblock, int *err, gchar **err_info)
666 guint64 time_units_per_second = 1000000; /* default */
669 guint to_read, opt_cont_buf_len;
670 pcapng_interface_description_block_t idb;
671 pcapng_option_header_t oh;
672 char *option_content = NULL; /* Allocate as large as the options block */
675 * Is this block long enough to be an IDB?
677 if (bh->block_total_length < MIN_IDB_SIZE) {
681 *err = WTAP_ERR_BAD_FILE;
682 *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",
683 bh->block_total_length, MIN_IDB_SIZE);
687 /* Don't try to allocate memory for a huge number of options, as
688 that might fail and, even if it succeeds, it might not leave
689 any address space or memory+backing store for anything else.
691 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
692 We check for this *after* checking the SHB for its byte
693 order magic number, so that non-pcap-ng files are less
694 likely to be treated as bad pcap-ng files. */
695 if (bh->block_total_length > MAX_BLOCK_SIZE) {
696 *err = WTAP_ERR_BAD_FILE;
697 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
698 bh->block_total_length, MAX_BLOCK_SIZE);
702 /* read block content */
703 errno = WTAP_ERR_CANT_READ;
704 bytes_read = file_read(&idb, sizeof idb, fh);
705 if (bytes_read != sizeof idb) {
706 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
707 *err = file_error(fh, err_info);
712 block_read = bytes_read;
714 /* mandatory values */
715 if (pn->byte_swapped) {
716 wblock->data.if_descr.link_type = GUINT16_SWAP_LE_BE(idb.linktype);
717 wblock->data.if_descr.snap_len = GUINT32_SWAP_LE_BE(idb.snaplen);
719 wblock->data.if_descr.link_type = idb.linktype;
720 wblock->data.if_descr.snap_len = idb.snaplen;
723 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
724 wblock->data.if_descr.time_units_per_second = time_units_per_second;
726 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
727 wblock->data.if_descr.link_type,
728 wtap_encap_string(wblock->data.if_descr.wtap_encap),
729 wblock->data.if_descr.snap_len);
731 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
732 /* This is unrealistic, but text2pcap currently uses 102400.
733 * We do not use this value, maybe we should check the
734 * snap_len of the packets against it. For now, only warn.
736 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
737 wblock->data.if_descr.snap_len);
738 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
741 /* Option defaults */
742 wblock->data.if_descr.opt_comment = NULL;
743 wblock->data.if_descr.if_name = NULL;
744 wblock->data.if_descr.if_description = NULL;
745 /* XXX: if_IPv4addr */
746 /* XXX: if_IPv6addr */
747 /* XXX: if_MACaddr */
748 /* XXX: if_EUIaddr */
749 wblock->data.if_descr.if_speed = 0; /* "unknown" */
750 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
751 wblock->data.if_descr.if_filter_str = NULL;
752 wblock->data.if_descr.bpf_filter_len = 0;
753 wblock->data.if_descr.if_filter_bpf_bytes = NULL;
754 wblock->data.if_descr.if_os = NULL;
755 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
756 /* XXX: guint64 if_tsoffset; */
760 errno = WTAP_ERR_CANT_READ;
761 to_read = bh->block_total_length - MIN_IDB_SIZE;
763 /* Allocate enough memory to hold all options */
764 opt_cont_buf_len = to_read;
765 option_content = (char *)g_try_malloc(opt_cont_buf_len);
766 if (opt_cont_buf_len != 0 && option_content == NULL) {
767 *err = ENOMEM; /* we assume we're out of memory */
771 while (to_read != 0) {
773 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
774 if (bytes_read <= 0) {
775 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
778 block_read += bytes_read;
779 to_read -= bytes_read;
781 /* handle option content */
782 switch (oh.option_code) {
783 case(0): /* opt_endofopt */
785 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
787 /* padding should be ok here, just get out of this */
790 case(1): /* opt_comment */
791 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
792 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
793 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
795 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
798 case(2): /* if_name */
799 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
800 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
801 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
803 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
806 case(3): /* if_description */
807 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
808 wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
809 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
811 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
815 * if_IPv4addr 4 Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
816 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
817 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
818 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
820 case(8): /* if_speed */
821 if (oh.option_length == 8) {
822 /* Don't cast a char[] into a guint64--the
823 * char[] may not be aligned correctly.
825 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
826 if (pn->byte_swapped)
827 wblock->data.if_descr.if_speed = GUINT64_SWAP_LE_BE(wblock->data.if_descr.if_speed);
828 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
830 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
833 case(9): /* if_tsresol */
834 if (oh.option_length == 1) {
837 guint8 i, exponent, if_tsresol;
839 if_tsresol = option_content[0];
840 if (if_tsresol & 0x80) {
845 exponent = (guint8)(if_tsresol & 0x7f);
846 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
848 for (i = 0; i < exponent; i++) {
851 time_units_per_second = result;
853 time_units_per_second = G_MAXUINT64;
855 if (time_units_per_second > (((guint64)1) << 32)) {
856 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
858 wblock->data.if_descr.time_units_per_second = time_units_per_second;
859 wblock->data.if_descr.if_tsresol = if_tsresol;
860 pcapng_debug2("pcapng_read_if_descr_block: if_tsresol %u, units/s %" G_GINT64_MODIFIER "u", wblock->data.if_descr.if_tsresol, wblock->data.if_descr.time_units_per_second);
862 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
866 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
868 case(11): /* if_filter */
869 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
870 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
873 if (option_content[0] == 0) {
874 wblock->data.if_descr.if_filter_str = g_strndup(option_content+1, oh.option_length-1);
875 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);
876 } else if (option_content[0] == 1) {
877 wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
878 wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
879 memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, option_content+1, oh.option_length-1);
882 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
885 case(12): /* if_os */
887 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
888 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
889 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
891 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
892 wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
893 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
895 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
898 case(13): /* if_fcslen */
899 if (oh.option_length == 1) {
900 wblock->data.if_descr.if_fcslen = option_content[0];
901 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
902 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
903 /* XXX - add sanity check */
905 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
909 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
910 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
911 * The time zone of the offset can be specified with the option if_tzone.
912 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
915 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
916 oh.option_code, oh.option_length);
920 g_free(option_content);
922 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
923 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
925 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
926 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
935 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)
939 guint to_read, opt_cont_buf_len;
940 guint64 file_offset64;
941 pcapng_enhanced_packet_block_t epb;
942 pcapng_packet_block_t pb;
943 wtapng_packet_t packet;
944 guint32 block_total_length;
946 interface_info_t iface_info;
948 pcapng_option_header_t oh;
949 int pseudo_header_len;
950 char *option_content = NULL; /* Allocate as large as the options block */
953 /* Don't try to allocate memory for a huge number of options, as
954 that might fail and, even if it succeeds, it might not leave
955 any address space or memory+backing store for anything else.
957 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
958 We check for this *after* checking the SHB for its byte
959 order magic number, so that non-pcap-ng files are less
960 likely to be treated as bad pcap-ng files. */
961 if (bh->block_total_length > MAX_BLOCK_SIZE) {
962 *err = WTAP_ERR_BAD_FILE;
963 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
964 bh->block_total_length, MAX_BLOCK_SIZE);
968 /* "(Enhanced) Packet Block" read fixed part */
969 errno = WTAP_ERR_CANT_READ;
972 * Is this block long enough to be an EPB?
974 if (bh->block_total_length < MIN_EPB_SIZE) {
978 *err = WTAP_ERR_BAD_FILE;
979 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
980 bh->block_total_length, MIN_EPB_SIZE);
983 bytes_read = file_read(&epb, sizeof epb, fh);
984 if (bytes_read != sizeof epb) {
985 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
986 *err = file_error(fh, err_info);
989 block_read = bytes_read;
991 if (pn->byte_swapped) {
992 packet.interface_id = GUINT32_SWAP_LE_BE(epb.interface_id);
993 packet.drops_count = -1; /* invalid */
994 packet.ts_high = GUINT32_SWAP_LE_BE(epb.timestamp_high);
995 packet.ts_low = GUINT32_SWAP_LE_BE(epb.timestamp_low);
996 packet.cap_len = GUINT32_SWAP_LE_BE(epb.captured_len);
997 packet.packet_len = GUINT32_SWAP_LE_BE(epb.packet_len);
999 packet.interface_id = epb.interface_id;
1000 packet.drops_count = -1; /* invalid */
1001 packet.ts_high = epb.timestamp_high;
1002 packet.ts_low = epb.timestamp_low;
1003 packet.cap_len = epb.captured_len;
1004 packet.packet_len = epb.packet_len;
1006 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1007 packet.interface_id, packet.cap_len, packet.packet_len);
1010 * Is this block long enough to be a PB?
1012 if (bh->block_total_length < MIN_PB_SIZE) {
1016 *err = WTAP_ERR_BAD_FILE;
1017 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1018 bh->block_total_length, MIN_PB_SIZE);
1021 bytes_read = file_read(&pb, sizeof pb, fh);
1022 if (bytes_read != sizeof pb) {
1023 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1024 *err = file_error(fh, err_info);
1027 block_read = bytes_read;
1029 if (pn->byte_swapped) {
1030 packet.interface_id = GUINT16_SWAP_LE_BE(pb.interface_id);
1031 packet.drops_count = GUINT16_SWAP_LE_BE(pb.drops_count);
1032 packet.ts_high = GUINT32_SWAP_LE_BE(pb.timestamp_high);
1033 packet.ts_low = GUINT32_SWAP_LE_BE(pb.timestamp_low);
1034 packet.cap_len = GUINT32_SWAP_LE_BE(pb.captured_len);
1035 packet.packet_len = GUINT32_SWAP_LE_BE(pb.packet_len);
1037 packet.interface_id = pb.interface_id;
1038 packet.drops_count = pb.drops_count;
1039 packet.ts_high = pb.timestamp_high;
1040 packet.ts_low = pb.timestamp_low;
1041 packet.cap_len = pb.captured_len;
1042 packet.packet_len = pb.packet_len;
1044 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1045 packet.interface_id, packet.cap_len, packet.packet_len);
1049 * How much padding is there at the end of the packet data?
1051 if ((packet.cap_len % 4) != 0)
1052 padding = 4 - (packet.cap_len % 4);
1056 /* add padding bytes to "block total length" */
1057 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1058 if (bh->block_total_length % 4) {
1059 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1061 block_total_length = bh->block_total_length;
1063 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1066 * Is this block long enough to hold the packet data?
1069 if (block_total_length <
1070 MIN_EPB_SIZE + packet.cap_len + padding) {
1074 *err = WTAP_ERR_BAD_FILE;
1075 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1076 block_total_length, packet.cap_len);
1080 if (block_total_length <
1081 MIN_PB_SIZE + packet.cap_len + padding) {
1085 *err = WTAP_ERR_BAD_FILE;
1086 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1087 block_total_length, packet.cap_len);
1092 if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1093 *err = WTAP_ERR_BAD_FILE;
1094 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1095 packet.cap_len, WTAP_MAX_PACKET_SIZE);
1098 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1101 packet.interface_id);
1103 if (packet.interface_id >= pn->interfaces->len) {
1104 *err = WTAP_ERR_BAD_FILE;
1105 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u",
1106 packet.interface_id, pn->interfaces->len);
1109 iface_info = g_array_index(pn->interfaces, interface_info_t,
1110 packet.interface_id);
1112 wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1114 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1115 iface_info.wtap_encap,
1116 wtap_encap_string(iface_info.wtap_encap),
1117 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
1118 wblock->packet_header->interface_id = packet.interface_id;
1119 wblock->packet_header->pkt_encap = iface_info.wtap_encap;
1121 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1122 pseudo_header_len = pcap_process_pseudo_header(fh,
1123 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1124 iface_info.wtap_encap,
1127 wblock->packet_header,
1130 if (pseudo_header_len < 0) {
1133 block_read += pseudo_header_len;
1134 if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
1135 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1138 wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
1139 wblock->packet_header->len = packet.packet_len - pseudo_header_len;
1141 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1142 ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
1143 wblock->packet_header->ts.secs = (time_t)(ts / iface_info.time_units_per_second);
1144 wblock->packet_header->ts.nsecs = (int)(((ts % iface_info.time_units_per_second) * 1000000000) / iface_info.time_units_per_second);
1146 /* "(Enhanced) Packet Block" read capture data */
1147 errno = WTAP_ERR_CANT_READ;
1148 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1149 packet.cap_len - pseudo_header_len, err, err_info))
1151 block_read += packet.cap_len - pseudo_header_len;
1153 /* jump over potential padding bytes at end of the packet data */
1155 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1156 if (file_offset64 <= 0) {
1161 block_read += padding;
1164 /* Option defaults */
1165 wblock->packet_header->opt_comment = NULL;
1166 wblock->packet_header->drop_count = -1;
1167 wblock->packet_header->pack_flags = 0;
1169 /* FCS length default */
1170 fcslen = pn->if_fcslen;
1178 errno = WTAP_ERR_CANT_READ;
1179 to_read = block_total_length -
1180 (int)sizeof(pcapng_block_header_t) -
1181 block_read - /* fixed and variable part, including padding */
1182 (int)sizeof(bh->block_total_length);
1184 /* Allocate enough memory to hold all options */
1185 opt_cont_buf_len = to_read;
1186 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1187 if (opt_cont_buf_len != 0 && option_content == NULL) {
1188 *err = ENOMEM; /* we assume we're out of memory */
1192 while (to_read != 0) {
1194 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1195 if (bytes_read <= 0) {
1196 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1199 block_read += bytes_read;
1200 to_read -= bytes_read;
1202 /* handle option content */
1203 switch (oh.option_code) {
1206 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1208 /* padding should be ok here, just get out of this */
1212 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1213 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1214 wblock->packet_header->opt_comment = g_strndup(option_content, oh.option_length);
1215 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->packet_header->opt_comment);
1217 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1220 case(OPT_EPB_FLAGS):
1221 if (oh.option_length == 4) {
1222 /* Don't cast a char[] into a guint32--the
1223 * char[] may not be aligned correctly.
1225 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1226 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1227 if (pn->byte_swapped)
1228 wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
1229 if (wblock->packet_header->pack_flags & 0x000001E0) {
1230 /* The FCS length is present */
1231 fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1233 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1235 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1239 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1240 oh.option_code, oh.option_length);
1242 case(OPT_EPB_DROPCOUNT):
1243 if (oh.option_length == 8) {
1244 /* Don't cast a char[] into a guint32--the
1245 * char[] may not be aligned correctly.
1247 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1248 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1249 if (pn->byte_swapped)
1250 wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
1252 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1254 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1258 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1259 oh.option_code, oh.option_length);
1263 g_free(option_content);
1265 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
1266 wblock->packet_header, buffer_start_ptr(wblock->frame_buffer),
1267 pn->byte_swapped, fcslen);
1273 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)
1277 guint64 file_offset64;
1278 interface_info_t iface_info;
1279 pcapng_simple_packet_block_t spb;
1280 wtapng_simple_packet_t simple_packet;
1281 guint32 block_total_length;
1283 int pseudo_header_len;
1286 * Is this block long enough to be an SPB?
1288 if (bh->block_total_length < MIN_SPB_SIZE) {
1292 *err = WTAP_ERR_BAD_FILE;
1293 *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",
1294 bh->block_total_length, MIN_SPB_SIZE);
1298 /* Don't try to allocate memory for a huge number of options, as
1299 that might fail and, even if it succeeds, it might not leave
1300 any address space or memory+backing store for anything else.
1302 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1303 We check for this *after* checking the SHB for its byte
1304 order magic number, so that non-pcap-ng files are less
1305 likely to be treated as bad pcap-ng files. */
1306 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1307 *err = WTAP_ERR_BAD_FILE;
1308 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1309 bh->block_total_length, MAX_BLOCK_SIZE);
1313 /* "Simple Packet Block" read fixed part */
1314 errno = WTAP_ERR_CANT_READ;
1315 bytes_read = file_read(&spb, sizeof spb, fh);
1316 if (bytes_read != sizeof spb) {
1317 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1318 *err = file_error(fh, err_info);
1321 block_read = bytes_read;
1323 if (0 >= pn->interfaces->len) {
1324 *err = WTAP_ERR_BAD_FILE;
1325 *err_info = g_strdup_printf("pcapng: SPB appeared before any IDBs");
1328 iface_info = g_array_index(pn->interfaces, interface_info_t, 0);
1330 if (pn->byte_swapped) {
1331 simple_packet.packet_len = GUINT32_SWAP_LE_BE(spb.packet_len);
1333 simple_packet.packet_len = spb.packet_len;
1337 * The captured length is not a field in the SPB; it can be
1338 * calculated as the minimum of the snapshot length from the
1339 * IDB and the packet length, as per the pcap-ng spec.
1341 simple_packet.cap_len = simple_packet.packet_len;
1342 if (simple_packet.cap_len > iface_info.snap_len)
1343 simple_packet.cap_len = iface_info.snap_len;
1346 * How much padding is there at the end of the packet data?
1348 if ((simple_packet.cap_len % 4) != 0)
1349 padding = 4 - (simple_packet.cap_len % 4);
1353 /* add padding bytes to "block total length" */
1354 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1355 if (bh->block_total_length % 4) {
1356 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1358 block_total_length = bh->block_total_length;
1360 pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length);
1363 * Is this block long enough to hold the packet data?
1365 if (block_total_length < MIN_SPB_SIZE + simple_packet.cap_len + padding) {
1367 * No. That means that the problem is with the packet
1368 * length; the snapshot length can be bigger than the amount
1369 * of packet data in the block, as it's a *maximum* length,
1370 * not a *minimum* length.
1372 *err = WTAP_ERR_BAD_FILE;
1373 *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",
1374 block_total_length, simple_packet.packet_len);
1378 if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1379 *err = WTAP_ERR_BAD_FILE;
1380 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1381 simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1384 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1385 simple_packet.packet_len);
1387 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1388 pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header));
1390 /* No time stamp in a simple packet block; no options, either */
1391 wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1392 wblock->packet_header->interface_id = 0;
1393 wblock->packet_header->pkt_encap = iface_info.wtap_encap;
1394 wblock->packet_header->ts.secs = 0;
1395 wblock->packet_header->ts.nsecs = 0;
1396 wblock->packet_header->interface_id = 0;
1397 wblock->packet_header->opt_comment = NULL;
1398 wblock->packet_header->drop_count = 0;
1399 wblock->packet_header->pack_flags = 0;
1401 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1402 pseudo_header_len = pcap_process_pseudo_header(fh,
1403 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1404 iface_info.wtap_encap,
1405 simple_packet.cap_len,
1407 wblock->packet_header,
1410 if (pseudo_header_len < 0) {
1413 wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
1414 wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
1415 block_read += pseudo_header_len;
1416 if (pseudo_header_len != pcap_get_phdr_size(iface_info.wtap_encap, &wblock->packet_header->pseudo_header)) {
1417 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1421 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1423 /* "Simple Packet Block" read capture data */
1424 errno = WTAP_ERR_CANT_READ;
1425 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1426 simple_packet.cap_len, err, err_info))
1428 block_read += simple_packet.cap_len;
1430 /* jump over potential padding bytes at end of the packet data */
1431 if ((simple_packet.cap_len % 4) != 0) {
1432 file_offset64 = file_seek(fh, 4 - (simple_packet.cap_len % 4), SEEK_CUR, err);
1433 if (file_offset64 <= 0) {
1438 block_read += 4 - (simple_packet.cap_len % 4);
1441 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, iface_info.wtap_encap,
1442 wblock->packet_header, buffer_start_ptr(wblock->frame_buffer),
1443 pn->byte_swapped, pn->if_fcslen);
1447 #define NRES_ENDOFRECORD 0
1448 #define NRES_IP4RECORD 1
1449 #define NRES_IP6RECORD 2
1450 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1451 /* IPv6 + MAXNAMELEN */
1452 #define INITIAL_NRB_REC_SIZE (16 + 64)
1455 * Find the end of the NUL-terminated name the beginning of which is pointed
1456 * to by p; record_len is the number of bytes remaining in the record.
1458 * Return the length of the name, including the terminating NUL.
1460 * If we don't find a terminating NUL, return -1 and set *err and
1461 * *err_info appropriately.
1464 name_resolution_block_find_name_end(const char *p, guint record_len, int *err,
1471 if (record_len == 0) {
1473 * We ran out of bytes in the record without
1476 *err = WTAP_ERR_BAD_FILE;
1477 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1481 break; /* that's the terminating NUL */
1484 namelen++; /* count this byte */
1487 /* Include the NUL in the name length. */
1492 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)
1497 guint64 file_offset64;
1498 pcapng_name_resolution_block_t nrb;
1506 * Is this block long enough to be an NRB?
1508 if (bh->block_total_length < MIN_NRB_SIZE) {
1512 *err = WTAP_ERR_BAD_FILE;
1513 *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",
1514 bh->block_total_length, MIN_NRB_SIZE);
1518 /* Don't try to allocate memory for a huge number of options, as
1519 that might fail and, even if it succeeds, it might not leave
1520 any address space or memory+backing store for anything else.
1522 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1523 We check for this *after* checking the SHB for its byte
1524 order magic number, so that non-pcap-ng files are less
1525 likely to be treated as bad pcap-ng files. */
1526 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1527 *err = WTAP_ERR_BAD_FILE;
1528 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1529 bh->block_total_length, MAX_BLOCK_SIZE);
1533 errno = WTAP_ERR_CANT_READ;
1534 to_read = bh->block_total_length - 8 - 4; /* We have read the header adn should not read the final block_total_length */
1536 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1539 * Start out with a buffer big enough for an IPv6 address and one
1540 * 64-byte name; we'll make the buffer bigger if necessary.
1542 buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1543 while (block_read < to_read) {
1545 * There must be at least one record's worth of data
1548 if ((size_t)(to_read - block_read) < sizeof nrb) {
1549 buffer_free(&nrb_rec);
1550 *err = WTAP_ERR_BAD_FILE;
1551 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1552 to_read - block_read,
1556 bytes_read = file_read(&nrb, sizeof nrb, fh);
1557 if (bytes_read != sizeof nrb) {
1558 buffer_free(&nrb_rec);
1559 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1560 *err = file_error(fh, err_info);
1563 block_read += bytes_read;
1565 if (pn->byte_swapped) {
1566 nrb.record_type = GUINT16_SWAP_LE_BE(nrb.record_type);
1567 nrb.record_len = GUINT16_SWAP_LE_BE(nrb.record_len);
1570 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1571 buffer_free(&nrb_rec);
1572 *err = WTAP_ERR_BAD_FILE;
1573 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1574 to_read - block_read,
1575 nrb.record_len + PADDING4(nrb.record_len));
1578 switch (nrb.record_type) {
1579 case NRES_ENDOFRECORD:
1580 /* There shouldn't be any more data */
1583 case NRES_IP4RECORD:
1585 * The smallest possible record must have
1586 * a 4-byte IPv4 address, hence a minimum
1589 * (The pcap-NG spec really indicates
1590 * that it must be at least 5 bytes,
1591 * as there must be at least one name,
1592 * and it really must be at least 6
1593 * bytes, as the name mustn't be null,
1594 * but there's no need to fail if there
1595 * aren't any names at all, and we
1596 * should report a null name as such.)
1598 if (nrb.record_len < 4) {
1599 buffer_free(&nrb_rec);
1600 *err = WTAP_ERR_BAD_FILE;
1601 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1605 buffer_assure_space(&nrb_rec, nrb.record_len);
1606 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1607 nrb.record_len, fh);
1608 if (bytes_read != nrb.record_len) {
1609 buffer_free(&nrb_rec);
1610 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1611 *err = file_error(fh, err_info);
1614 block_read += bytes_read;
1616 if (pn->add_new_ipv4) {
1618 * Scan through all the names in
1619 * the record and add them.
1622 buffer_start_ptr(&nrb_rec), 4);
1623 if (pn->byte_swapped)
1624 v4_addr = GUINT32_SWAP_LE_BE(v4_addr);
1625 for (namep = (char *)buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1627 namep += namelen, record_len -= namelen) {
1629 * Scan forward for a null
1632 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1633 if (namelen == -1) {
1634 buffer_free(&nrb_rec);
1635 return -1; /* fail */
1637 pn->add_new_ipv4(v4_addr, namep);
1641 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1642 if (file_offset64 <= 0) {
1643 buffer_free(&nrb_rec);
1648 block_read += PADDING4(nrb.record_len);
1650 case NRES_IP6RECORD:
1652 * The smallest possible record must have
1653 * a 16-byte IPv6 address, hence a minimum
1656 * (The pcap-NG spec really indicates
1657 * that it must be at least 17 bytes,
1658 * as there must be at least one name,
1659 * and it really must be at least 18
1660 * bytes, as the name mustn't be null,
1661 * but there's no need to fail if there
1662 * aren't any names at all, and we
1663 * should report a null name as such.)
1665 if (nrb.record_len < 16) {
1666 buffer_free(&nrb_rec);
1667 *err = WTAP_ERR_BAD_FILE;
1668 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1672 if (to_read < nrb.record_len) {
1673 buffer_free(&nrb_rec);
1674 pcapng_debug0("pcapng_read_name_resolution_block: insufficient data for IPv6 record");
1677 buffer_assure_space(&nrb_rec, nrb.record_len);
1678 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1679 nrb.record_len, fh);
1680 if (bytes_read != nrb.record_len) {
1681 buffer_free(&nrb_rec);
1682 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1683 *err = file_error(fh, err_info);
1686 block_read += bytes_read;
1688 if (pn->add_new_ipv6) {
1689 for (namep = (char *)buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1691 namep += namelen, record_len -= namelen) {
1693 * Scan forward for a null
1696 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1697 if (namelen == -1) {
1698 buffer_free(&nrb_rec);
1699 return -1; /* fail */
1701 pn->add_new_ipv6(buffer_start_ptr(&nrb_rec),
1706 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1707 if (file_offset64 <= 0) {
1708 buffer_free(&nrb_rec);
1713 block_read += PADDING4(nrb.record_len);
1716 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1717 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1718 if (file_offset64 <= 0) {
1719 buffer_free(&nrb_rec);
1724 block_read += nrb.record_len + PADDING4(nrb.record_len);
1729 buffer_free(&nrb_rec);
1734 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)
1738 guint to_read, opt_cont_buf_len;
1739 pcapng_interface_statistics_block_t isb;
1740 pcapng_option_header_t oh;
1741 char *option_content = NULL; /* Allocate as large as the options block */
1744 * Is this block long enough to be an ISB?
1746 if (bh->block_total_length < MIN_ISB_SIZE) {
1750 *err = WTAP_ERR_BAD_FILE;
1751 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1752 bh->block_total_length, MIN_ISB_SIZE);
1756 /* Don't try to allocate memory for a huge number of options, as
1757 that might fail and, even if it succeeds, it might not leave
1758 any address space or memory+backing store for anything else.
1760 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1761 We check for this *after* checking the SHB for its byte
1762 order magic number, so that non-pcap-ng files are less
1763 likely to be treated as bad pcap-ng files. */
1764 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1765 *err = WTAP_ERR_BAD_FILE;
1766 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1767 bh->block_total_length, MAX_BLOCK_SIZE);
1771 /* "Interface Statistics Block" read fixed part */
1772 errno = WTAP_ERR_CANT_READ;
1773 bytes_read = file_read(&isb, sizeof isb, fh);
1774 if (bytes_read != sizeof isb) {
1775 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1776 *err = file_error(fh, err_info);
1779 block_read = bytes_read;
1781 if (pn->byte_swapped) {
1782 wblock->data.if_stats.interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
1783 wblock->data.if_stats.ts_high = GUINT32_SWAP_LE_BE(isb.timestamp_high);
1784 wblock->data.if_stats.ts_low = GUINT32_SWAP_LE_BE(isb.timestamp_low);
1786 wblock->data.if_stats.interface_id = isb.interface_id;
1787 wblock->data.if_stats.ts_high = isb.timestamp_high;
1788 wblock->data.if_stats.ts_low = isb.timestamp_low;
1790 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1792 /* Option defaults */
1793 wblock->data.if_stats.opt_comment = NULL;
1794 wblock->data.if_stats.isb_ifrecv = -1;
1795 wblock->data.if_stats.isb_ifdrop = -1;
1796 wblock->data.if_stats.isb_filteraccept = -1;
1797 wblock->data.if_stats.isb_osdrop = -1;
1798 wblock->data.if_stats.isb_usrdeliv = -1;
1801 errno = WTAP_ERR_CANT_READ;
1802 to_read = bh->block_total_length -
1803 (MIN_BLOCK_SIZE + block_read); /* fixed and variable part, including padding */
1805 /* Allocate enough memory to hold all options */
1806 opt_cont_buf_len = to_read;
1807 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1808 if (opt_cont_buf_len != 0 && option_content == NULL) {
1809 *err = ENOMEM; /* we assume we're out of memory */
1813 while (to_read != 0) {
1815 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1816 if (bytes_read <= 0) {
1817 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1820 block_read += bytes_read;
1821 to_read -= bytes_read;
1823 /* handle option content */
1824 switch (oh.option_code) {
1825 case(0): /* opt_endofopt */
1827 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1829 /* padding should be ok here, just get out of this */
1832 case(1): /* opt_comment */
1833 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1834 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1835 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1837 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1840 case(2): /* isb_starttime */
1841 if (oh.option_length == 8) {
1844 /* Don't cast a char[] into a guint32--the
1845 * char[] may not be aligned correctly.
1847 memcpy(&high, option_content, sizeof(guint32));
1848 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1849 if (pn->byte_swapped) {
1850 high = GUINT32_SWAP_LE_BE(high);
1851 low = GUINT32_SWAP_LE_BE(low);
1853 wblock->data.if_stats.isb_starttime = (guint64)high;
1854 wblock->data.if_stats.isb_starttime <<= 32;
1855 wblock->data.if_stats.isb_starttime += (guint64)low;
1856 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1858 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1861 case(3): /* isb_endtime */
1862 if (oh.option_length == 8) {
1865 /* Don't cast a char[] into a guint32--the
1866 * char[] may not be aligned correctly.
1868 memcpy(&high, option_content, sizeof(guint32));
1869 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1870 if (pn->byte_swapped) {
1871 high = GUINT32_SWAP_LE_BE(high);
1872 low = GUINT32_SWAP_LE_BE(low);
1874 wblock->data.if_stats.isb_endtime = (guint64)high;
1875 wblock->data.if_stats.isb_endtime <<= 32;
1876 wblock->data.if_stats.isb_endtime += (guint64)low;
1877 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1879 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1882 case(4): /* isb_ifrecv */
1883 if (oh.option_length == 8) {
1884 /* Don't cast a char[] into a guint32--the
1885 * char[] may not be aligned correctly.
1887 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1888 if (pn->byte_swapped)
1889 wblock->data.if_stats.isb_ifrecv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifrecv);
1890 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1892 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1895 case(5): /* isb_ifdrop */
1896 if (oh.option_length == 8) {
1897 /* Don't cast a char[] into a guint32--the
1898 * char[] may not be aligned correctly.
1900 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1901 if (pn->byte_swapped)
1902 wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifdrop);
1903 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1905 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1908 case(6): /* isb_filteraccept 6 */
1909 if (oh.option_length == 8) {
1910 /* Don't cast a char[] into a guint32--the
1911 * char[] may not be aligned correctly.
1913 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1914 if (pn->byte_swapped)
1915 wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_filteraccept);
1916 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1918 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1921 case(7): /* isb_osdrop 7 */
1922 if (oh.option_length == 8) {
1923 /* Don't cast a char[] into a guint32--the
1924 * char[] may not be aligned correctly.
1926 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1927 if (pn->byte_swapped)
1928 wblock->data.if_stats.isb_osdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
1929 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1931 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1934 case(8): /* isb_usrdeliv 8 */
1935 if (oh.option_length == 8) {
1936 /* Don't cast a char[] into a guint32--the
1937 * char[] may not be aligned correctly.
1939 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1940 if (pn->byte_swapped)
1941 wblock->data.if_stats.isb_usrdeliv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
1942 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1944 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1948 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1949 oh.option_code, oh.option_length);
1953 g_free(option_content);
1960 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)
1963 guint64 file_offset64;
1964 guint32 block_total_length;
1966 if (bh->block_total_length < MIN_BLOCK_SIZE) {
1967 *err = WTAP_ERR_BAD_FILE;
1968 *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",
1969 bh->block_total_length, MIN_BLOCK_SIZE);
1973 /* add padding bytes to "block total length" */
1974 /* (the "block total length" of some example files don't contain any padding bytes!) */
1975 if (bh->block_total_length % 4) {
1976 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1978 block_total_length = bh->block_total_length;
1981 block_read = block_total_length - MIN_BLOCK_SIZE;
1983 /* jump over this unknown block */
1984 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1985 if (file_offset64 <= 0) {
1996 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2000 pcapng_block_header_t bh;
2001 guint32 block_total_length;
2004 /* Try to read the (next) block header */
2005 errno = WTAP_ERR_CANT_READ;
2006 bytes_read = file_read(&bh, sizeof bh, fh);
2007 if (bytes_read != sizeof bh) {
2008 *err = file_error(fh, err_info);
2009 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2015 block_read = bytes_read;
2016 if (pn->byte_swapped) {
2017 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2018 bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
2021 wblock->type = bh.block_type;
2023 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2027 * This is being read in by pcapng_open(), so this block
2028 * must be an SHB. If it's not, this is not a pcap-ng
2031 * XXX - check for various forms of Windows <-> UN*X
2032 * mangling, and suggest that the file might be a
2033 * pcap-ng file that was damaged in transit?
2035 if (bh.block_type != BLOCK_TYPE_SHB)
2036 return 0; /* not a pcap-ng file */
2039 switch (bh.block_type) {
2040 case(BLOCK_TYPE_SHB):
2041 bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
2043 case(BLOCK_TYPE_IDB):
2044 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
2046 case(BLOCK_TYPE_PB):
2047 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
2049 case(BLOCK_TYPE_SPB):
2050 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
2052 case(BLOCK_TYPE_EPB):
2053 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
2055 case(BLOCK_TYPE_NRB):
2056 bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
2058 case(BLOCK_TYPE_ISB):
2059 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
2062 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2063 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
2066 if (bytes_read <= 0) {
2069 block_read += bytes_read;
2071 /* sanity check: first and second block lengths must match */
2072 errno = WTAP_ERR_CANT_READ;
2073 bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
2074 if (bytes_read != sizeof block_total_length) {
2075 pcapng_debug0("pcapng_read_block: couldn't read second block length");
2076 *err = file_error(fh, err_info);
2078 *err = WTAP_ERR_SHORT_READ;
2081 block_read += bytes_read;
2083 if (pn->byte_swapped)
2084 block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
2086 if (!(block_total_length == bh.block_total_length)) {
2087 *err = WTAP_ERR_BAD_FILE;
2088 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
2089 bh.block_total_length, block_total_length);
2096 /* Process an IDB that we've just read. */
2098 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2100 wtapng_if_descr_t int_data;
2101 interface_info_t iface_info;
2103 int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2104 int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2105 int_data.link_type = wblock->data.if_descr.link_type;
2106 int_data.snap_len = wblock->data.if_descr.snap_len;
2108 int_data.opt_comment = wblock->data.if_descr.opt_comment;
2109 int_data.if_name = wblock->data.if_descr.if_name;
2110 int_data.if_description = wblock->data.if_descr.if_description;
2111 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2112 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2113 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2114 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2115 int_data.if_speed = wblock->data.if_descr.if_speed;
2116 int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2117 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2118 int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2119 int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2120 int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2121 int_data.if_os = wblock->data.if_descr.if_os;
2122 int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2123 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2124 /* Interface statistics */
2125 int_data.num_stat_entries = 0;
2126 int_data.interface_statistics = NULL;
2128 g_array_append_val(wth->interface_data, int_data);
2130 iface_info.wtap_encap = wblock->data.if_descr.wtap_encap;
2131 iface_info.snap_len = wblock->data.if_descr.snap_len;
2132 iface_info.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2134 g_array_append_val(pcapng->interfaces, iface_info);
2137 /* classic wtap: open capture file */
2139 pcapng_open(wtap *wth, int *err, gchar **err_info)
2143 wtapng_block_t wblock;
2145 pcapng_block_header_t bh;
2146 gint64 saved_offset;
2148 pn.shb_read = FALSE;
2149 /* we don't know the byte swapping of the file yet */
2150 pn.byte_swapped = FALSE;
2152 pn.version_major = -1;
2153 pn.version_minor = -1;
2154 pn.interfaces = g_array_new(FALSE, FALSE, sizeof(interface_info_t));
2157 /* we don't expect any packet blocks yet */
2158 wblock.frame_buffer = NULL;
2159 wblock.packet_header = NULL;
2160 wblock.file_encap = &wth->file_encap;
2162 pcapng_debug0("pcapng_open: opening file");
2163 /* read first block */
2164 bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
2165 if (bytes_read <= 0) {
2166 pcapng_debug0("pcapng_open: couldn't read first SHB");
2167 *err = file_error(wth->fh, err_info);
2168 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
2173 /* first block must be a "Section Header Block" */
2174 if (wblock.type != BLOCK_TYPE_SHB) {
2176 * XXX - check for damage from transferring a file
2177 * between Windows and UN*X as text rather than
2180 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2186 * At this point, we've decided this is a pcap-NG file, not
2187 * some other type of file, so we can't return 0, as that
2188 * means "this isn't a pcap-NG file, try some other file
2191 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2192 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2193 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2194 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2196 wth->file_encap = WTAP_ENCAP_UNKNOWN;
2197 wth->snapshot_length = 0;
2198 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
2199 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2200 wth->priv = (void *)pcapng;
2203 wth->subtype_read = pcapng_read;
2204 wth->subtype_seek_read = pcapng_seek_read;
2205 wth->subtype_close = pcapng_close;
2206 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
2208 /* Loop over all IDB:s that appear before any packets */
2210 /* peek at next block */
2211 /* Try to read the (next) block header */
2212 saved_offset = file_tell(wth->fh);
2213 errno = WTAP_ERR_CANT_READ;
2214 bytes_read = file_read(&bh, sizeof bh, wth->fh);
2215 if (bytes_read == 0) {
2216 pcapng_debug0("No more IDBs available...");
2219 if (bytes_read != sizeof bh) {
2220 *err = file_error(wth->fh, err_info);
2221 pcapng_debug3("pcapng_open: Check for more IDB:s, file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2223 *err = WTAP_ERR_SHORT_READ;
2227 /* go back to where we were */
2228 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2230 if (pn.byte_swapped) {
2231 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2234 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2236 if (bh.block_type != BLOCK_TYPE_IDB) {
2237 break; /* No more IDB:s */
2239 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
2240 if (bytes_read == 0) {
2241 pcapng_debug0("No more IDBs available...");
2244 if (bytes_read <= 0) {
2245 pcapng_debug0("pcapng_open: couldn't read IDB");
2246 *err = file_error(wth->fh, err_info);
2248 *err = WTAP_ERR_SHORT_READ;
2251 pcapng_process_idb(wth, pcapng, &wblock);
2252 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i",
2253 wth->interface_data->len, *wblock.file_encap);
2259 /* classic wtap: read packet */
2261 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2263 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2265 wtapng_block_t wblock;
2266 wtapng_if_descr_t *wtapng_if_descr;
2267 wtapng_if_stats_t if_stats;
2269 *data_offset = file_tell(wth->fh);
2270 pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER "d", *data_offset);
2272 wblock.frame_buffer = wth->frame_buffer;
2273 wblock.packet_header = &wth->phdr;
2274 wblock.file_encap = &wth->file_encap;
2276 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2277 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2279 /* read next block */
2281 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2282 if (bytes_read <= 0) {
2283 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2284 pcapng_debug0("pcapng_read: couldn't read packet block");
2288 switch (wblock.type) {
2290 case(BLOCK_TYPE_SHB):
2291 /* We don't currently support multi-section files. */
2292 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2293 *err = WTAP_ERR_UNSUPPORTED;
2294 *err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
2297 case(BLOCK_TYPE_PB):
2298 case(BLOCK_TYPE_SPB):
2299 case(BLOCK_TYPE_EPB):
2300 /* packet block - we've found a packet */
2303 case(BLOCK_TYPE_IDB):
2304 /* A new interface */
2305 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2306 *data_offset += bytes_read;
2307 pcapng_process_idb(wth, pcapng, &wblock);
2310 case(BLOCK_TYPE_NRB):
2311 /* More name resolution entries */
2312 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2313 *data_offset += bytes_read;
2316 case(BLOCK_TYPE_ISB):
2317 /* Another interface statistics report */
2318 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2319 *data_offset += bytes_read;
2320 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2321 if (wth->interface_data->len < wblock.data.if_stats.interface_id) {
2322 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces", wblock.data.if_stats.interface_id);
2324 /* Get the interface description */
2325 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2326 if (wtapng_if_descr->num_stat_entries == 0) {
2327 /* First ISB found, no previous entry */
2328 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2329 wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2332 if_stats.interface_id = wblock.data.if_stats.interface_id;
2333 if_stats.ts_high = wblock.data.if_stats.ts_high;
2334 if_stats.ts_low = wblock.data.if_stats.ts_low;
2336 if_stats.opt_comment = wblock.data.if_stats.opt_comment; /* NULL if not available */
2337 if_stats.isb_starttime = wblock.data.if_stats.isb_starttime;
2338 if_stats.isb_endtime = wblock.data.if_stats.isb_endtime;
2339 if_stats.isb_ifrecv = wblock.data.if_stats.isb_ifrecv;
2340 if_stats.isb_ifdrop = wblock.data.if_stats.isb_ifdrop;
2341 if_stats.isb_filteraccept = wblock.data.if_stats.isb_filteraccept;
2342 if_stats.isb_osdrop = wblock.data.if_stats.isb_osdrop;
2343 if_stats.isb_usrdeliv = wblock.data.if_stats.isb_usrdeliv;
2345 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2346 wtapng_if_descr->num_stat_entries++;
2351 /* XXX - improve handling of "unknown" blocks */
2352 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2353 *data_offset += bytes_read;
2354 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2361 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2362 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
2368 /* classic wtap: seek to file position and read packet */
2370 pcapng_seek_read(wtap *wth, gint64 seek_off,
2371 struct wtap_pkthdr *phdr, Buffer *buf,
2372 int *err, gchar **err_info)
2374 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2375 guint64 bytes_read64;
2377 wtapng_block_t wblock;
2380 /* seek to the right file position */
2381 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2382 if (bytes_read64 <= 0) {
2383 return FALSE; /* Seek error */
2385 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2387 wblock.frame_buffer = buf;
2388 wblock.packet_header = phdr;
2389 wblock.file_encap = &wth->file_encap;
2391 /* read the block */
2392 bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2393 if (bytes_read <= 0) {
2394 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2395 *err, errno, bytes_read);
2399 /* block must be a "Packet Block", an "Enhanced Packet Block",
2400 or a "Simple Packet Block" */
2401 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2402 wblock.type != BLOCK_TYPE_SPB) {
2403 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2411 /* classic wtap: close capture file */
2413 pcapng_close(wtap *wth)
2415 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2417 pcapng_debug0("pcapng_close: closing file");
2418 g_array_free(pcapng->interfaces, TRUE);
2423 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2425 pcapng_block_header_t bh;
2426 pcapng_section_header_block_t shb;
2427 const guint32 zero_pad = 0;
2428 gboolean have_options = FALSE;
2429 struct option option_hdr; /* guint16 type, guint16 value_length; */
2430 guint32 options_total_length = 0;
2431 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2432 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2435 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2436 /* Check if we should write comment option */
2437 if (wdh->shb_hdr->opt_comment) {
2438 have_options = TRUE;
2439 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2440 if ((comment_len % 4)) {
2441 comment_pad_len = 4 - (comment_len % 4);
2443 comment_pad_len = 0;
2445 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2448 /* Check if we should write shb_hardware option */
2449 if (wdh->shb_hdr->shb_hardware) {
2450 have_options = TRUE;
2451 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2452 if ((shb_hardware_len % 4)) {
2453 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2455 shb_hardware_pad_len = 0;
2457 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2460 /* Check if we should write shb_os option */
2461 if (wdh->shb_hdr->shb_os) {
2462 have_options = TRUE;
2463 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2464 if ((shb_os_len % 4)) {
2465 shb_os_pad_len = 4 - (shb_os_len % 4);
2469 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2472 /* Check if we should write shb_user_appl option */
2473 if (wdh->shb_hdr->shb_user_appl) {
2474 have_options = TRUE;
2475 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2476 if ((shb_user_appl_len % 4)) {
2477 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2479 shb_user_appl_pad_len = 0;
2481 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2484 /* End-of-options tag */
2485 options_total_length += 4;
2489 /* write block header */
2490 bh.block_type = BLOCK_TYPE_SHB;
2491 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2492 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2494 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2496 wdh->bytes_dumped += sizeof bh;
2498 /* write block fixed content */
2499 /* XXX - get these values from wblock? */
2500 shb.magic = 0x1A2B3C4D;
2501 shb.version_major = 1;
2502 shb.version_minor = 0;
2503 shb.section_length = -1;
2505 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2507 wdh->bytes_dumped += sizeof shb;
2509 /* XXX - write (optional) block options
2517 option_hdr.type = OPT_COMMENT;
2518 option_hdr.value_length = comment_len;
2519 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2521 wdh->bytes_dumped += 4;
2523 /* Write the comments string */
2524 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);
2525 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2527 wdh->bytes_dumped += comment_len;
2529 /* write padding (if any) */
2530 if (comment_pad_len != 0) {
2531 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2533 wdh->bytes_dumped += comment_pad_len;
2537 if (shb_hardware_len) {
2538 option_hdr.type = OPT_SHB_HARDWARE;
2539 option_hdr.value_length = shb_hardware_len;
2540 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2542 wdh->bytes_dumped += 4;
2544 /* Write the string */
2545 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);
2546 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2548 wdh->bytes_dumped += shb_hardware_len;
2550 /* write padding (if any) */
2551 if (shb_hardware_pad_len != 0) {
2552 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2554 wdh->bytes_dumped += shb_hardware_pad_len;
2559 option_hdr.type = OPT_SHB_OS;
2560 option_hdr.value_length = shb_os_len;
2561 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2563 wdh->bytes_dumped += 4;
2565 /* Write the string */
2566 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);
2567 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2569 wdh->bytes_dumped += shb_os_len;
2571 /* write padding (if any) */
2572 if (shb_os_pad_len != 0) {
2573 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2575 wdh->bytes_dumped += shb_os_pad_len;
2579 if (shb_user_appl_len) {
2580 option_hdr.type = OPT_SHB_USERAPPL;
2581 option_hdr.value_length = shb_user_appl_len;
2582 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2584 wdh->bytes_dumped += 4;
2586 /* Write the comments string */
2587 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);
2588 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2590 wdh->bytes_dumped += shb_user_appl_len;
2592 /* write padding (if any) */
2593 if (shb_user_appl_pad_len != 0) {
2594 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2596 wdh->bytes_dumped += shb_user_appl_pad_len;
2600 /* Write end of options if we have otions */
2602 option_hdr.type = OPT_EOFOPT;
2603 option_hdr.value_length = 0;
2604 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2606 wdh->bytes_dumped += 4;
2609 /* write block footer */
2610 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2611 sizeof bh.block_total_length, err))
2613 wdh->bytes_dumped += sizeof bh.block_total_length;
2618 #define IDB_OPT_IF_NAME 2
2619 #define IDB_OPT_IF_DESCR 3
2620 #define IDB_OPT_IF_SPEED 8
2621 #define IDB_OPT_IF_TSRESOL 9
2622 #define IDB_OPT_IF_FILTER 11
2623 #define IDB_OPT_IF_OS 12
2626 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2628 pcapng_block_header_t bh;
2629 pcapng_interface_description_block_t idb;
2630 const guint32 zero_pad = 0;
2631 gboolean have_options = FALSE;
2632 struct option option_hdr; /* guint16 type, guint16 value_length; */
2633 guint32 options_total_length = 0;
2634 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2635 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;
2638 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2639 int_data->link_type,
2640 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2641 int_data->snap_len);
2643 if (int_data->link_type == (guint16)-1) {
2644 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2648 /* Calculate options length */
2649 if (int_data->opt_comment) {
2650 have_options = TRUE;
2651 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2652 if ((comment_len % 4)) {
2653 comment_pad_len = 4 - (comment_len % 4);
2655 comment_pad_len = 0;
2657 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2661 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2663 if (int_data->if_name) {
2664 have_options = TRUE;
2665 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2666 if ((if_name_len % 4)) {
2667 if_name_pad_len = 4 - (if_name_len % 4);
2669 if_name_pad_len = 0;
2671 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2675 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2677 if (int_data->if_description) {
2678 have_options = TRUE;
2679 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2680 if ((if_description_len % 4)) {
2681 if_description_pad_len = 4 - (if_description_len % 4);
2683 if_description_pad_len = 0;
2685 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2687 /* Currently not handled
2688 * if_IPv4addr 4 Interface network address and netmask.
2689 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2690 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2691 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2694 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2696 if (int_data->if_speed != 0) {
2697 have_options = TRUE;
2698 options_total_length = options_total_length + 8 + 4;
2701 * if_tsresol 9 Resolution of timestamps.
2703 if (int_data->if_tsresol != 0) {
2704 have_options = TRUE;
2705 options_total_length = options_total_length + 4 + 4;
2708 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2711 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2712 * 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).
2714 if (int_data->if_filter_str) {
2715 have_options = TRUE;
2716 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2717 if ((if_filter_str_len % 4)) {
2718 if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2720 if_filter_str_pad_len = 0;
2722 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2725 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2727 if (int_data->if_os) {
2728 have_options = TRUE;
2729 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2730 if ((if_os_len % 4)) {
2731 if_os_pad_len = 4 - (if_os_len % 4);
2735 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2738 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2739 * -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.
2741 if (int_data->if_fcslen != 0) {
2744 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2745 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2749 /* End-of-options tag */
2750 options_total_length += 4;
2753 /* write block header */
2754 bh.block_type = BLOCK_TYPE_IDB;
2755 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2757 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2759 wdh->bytes_dumped += sizeof bh;
2761 /* write block fixed content */
2762 idb.linktype = int_data->link_type;
2764 idb.snaplen = int_data->snap_len;
2766 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2768 wdh->bytes_dumped += sizeof idb;
2770 /* XXX - write (optional) block options */
2771 if (comment_len != 0) {
2772 option_hdr.type = OPT_COMMENT;
2773 option_hdr.value_length = comment_len;
2774 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2776 wdh->bytes_dumped += 4;
2778 /* Write the comments string */
2779 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);
2780 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2782 wdh->bytes_dumped += comment_len;
2784 /* write padding (if any) */
2785 if (comment_pad_len != 0) {
2786 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2788 wdh->bytes_dumped += comment_pad_len;
2792 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2794 if (if_name_len !=0) {
2795 option_hdr.type = IDB_OPT_IF_NAME;
2796 option_hdr.value_length = if_name_len;
2797 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2799 wdh->bytes_dumped += 4;
2801 /* Write the comments string */
2802 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);
2803 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
2805 wdh->bytes_dumped += if_name_len;
2807 /* write padding (if any) */
2808 if (if_name_pad_len != 0) {
2809 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2811 wdh->bytes_dumped += if_name_pad_len;
2815 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2817 if (if_description_len != 0) {
2818 option_hdr.type = IDB_OPT_IF_NAME;
2819 option_hdr.value_length = if_description_len;
2820 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2822 wdh->bytes_dumped += 4;
2824 /* Write the comments string */
2825 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);
2826 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
2828 wdh->bytes_dumped += if_description_len;
2830 /* write padding (if any) */
2831 if (if_description_pad_len != 0) {
2832 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2834 wdh->bytes_dumped += if_description_pad_len;
2837 /* Currently not handled
2838 * if_IPv4addr 4 Interface network address and netmask.
2839 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2840 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2841 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2844 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2846 if (int_data->if_speed != 0) {
2847 option_hdr.type = IDB_OPT_IF_SPEED;
2848 option_hdr.value_length = 8;
2849 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2851 wdh->bytes_dumped += 4;
2853 /* Write the comments string */
2854 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
2855 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
2857 wdh->bytes_dumped += 8;
2860 * if_tsresol 9 Resolution of timestamps.
2861 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
2862 * If the Most Significant Bit is equal to zero, the remaining bits indicates
2863 * the resolution of the timestamp as as a negative power of 10
2865 if (int_data->if_tsresol != 0) {
2866 option_hdr.type = IDB_OPT_IF_TSRESOL;
2867 option_hdr.value_length = 1;
2868 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2870 wdh->bytes_dumped += 4;
2872 /* Write the time stamp resolution */
2873 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
2874 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
2876 wdh->bytes_dumped += 1;
2877 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2879 wdh->bytes_dumped += 3;
2882 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2885 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2887 /* Libpcap string variant */
2888 if (if_filter_str_len !=0) {
2889 option_hdr.type = IDB_OPT_IF_FILTER;
2890 option_hdr.value_length = if_filter_str_len;
2891 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2892 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2894 wdh->bytes_dumped += 4;
2896 /* Write the zero indicating libpcap filter variant */
2897 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
2899 wdh->bytes_dumped += 1;
2901 /* Write the comments string */
2902 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);
2903 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2904 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
2906 wdh->bytes_dumped += if_filter_str_len - 1;
2908 /* write padding (if any) */
2909 if (if_filter_str_pad_len != 0) {
2910 if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
2912 wdh->bytes_dumped += if_filter_str_pad_len;
2916 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2918 if (if_os_len != 0) {
2919 option_hdr.type = IDB_OPT_IF_OS;
2920 option_hdr.value_length = if_os_len;
2921 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2923 wdh->bytes_dumped += 4;
2925 /* Write the comments string */
2926 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);
2927 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
2929 wdh->bytes_dumped += if_os_len;
2931 /* write padding (if any) */
2932 if (if_os_pad_len != 0) {
2933 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2935 wdh->bytes_dumped += if_os_pad_len;
2940 option_hdr.type = OPT_EOFOPT;
2941 option_hdr.value_length = 0;
2942 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2944 wdh->bytes_dumped += 4;
2948 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2951 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2952 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2955 /* write block footer */
2956 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2957 sizeof bh.block_total_length, err))
2959 wdh->bytes_dumped += sizeof bh.block_total_length;
2964 #define ISB_STARTTIME 2
2965 #define ISB_ENDTIME 3
2966 #define ISB_IFRECV 4
2967 #define ISB_IFDROP 5
2968 #define ISB_FILTERACCEPT 6
2969 #define ISB_OSDROP 7
2970 #define ISB_USRDELIV 8
2973 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
2976 pcapng_block_header_t bh;
2977 pcapng_interface_statistics_block_t isb;
2978 const guint32 zero_pad = 0;
2979 gboolean have_options = FALSE;
2980 struct option option_hdr; /* guint16 type, guint16 value_length; */
2981 guint32 options_total_length = 0;
2982 guint32 comment_len = 0;
2983 guint32 comment_pad_len = 0;
2985 pcapng_debug0("pcapng_write_interface_statistics_block");
2988 /* Calculate options length */
2989 if (if_stats->opt_comment) {
2990 have_options = TRUE;
2991 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
2992 if ((comment_len % 4)) {
2993 comment_pad_len = 4 - (comment_len % 4);
2995 comment_pad_len = 0;
2997 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2999 /*guint64 isb_starttime */
3000 if (if_stats->isb_starttime != 0) {
3001 have_options = TRUE;
3002 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3004 /*guint64 isb_endtime */
3005 if (if_stats->isb_endtime != 0) {
3006 have_options = TRUE;
3007 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3009 /*guint64 isb_ifrecv */
3010 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3011 have_options = TRUE;
3012 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3014 /*guint64 isb_ifdrop */
3015 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3016 have_options = TRUE;
3017 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3019 /*guint64 isb_filteraccept */
3020 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3021 have_options = TRUE;
3022 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3024 /*guint64 isb_osdrop */
3025 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3026 have_options = TRUE;
3027 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3029 /*guint64 isb_usrdeliv */
3030 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3031 have_options = TRUE;
3032 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3035 /* write block header */
3037 /* End-of-optios tag */
3038 options_total_length += 4;
3041 /* write block header */
3042 bh.block_type = BLOCK_TYPE_ISB;
3043 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3045 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3047 wdh->bytes_dumped += sizeof bh;
3049 /* write block fixed content */
3050 isb.interface_id = if_stats->interface_id;
3051 isb.timestamp_high = if_stats->ts_high;
3052 isb.timestamp_low = if_stats->ts_low;
3055 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3057 wdh->bytes_dumped += sizeof isb;
3059 /* write (optional) block options */
3061 option_hdr.type = OPT_COMMENT;
3062 option_hdr.value_length = comment_len;
3063 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3065 wdh->bytes_dumped += 4;
3067 /* Write the comments string */
3068 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);
3069 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3071 wdh->bytes_dumped += comment_len;
3073 /* write padding (if any) */
3074 if (comment_pad_len != 0) {
3075 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3077 wdh->bytes_dumped += comment_pad_len;
3080 /*guint64 isb_starttime */
3081 if (if_stats->isb_starttime != 0) {
3084 option_hdr.type = ISB_STARTTIME;
3085 option_hdr.value_length = 8;
3086 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3087 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3088 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3090 wdh->bytes_dumped += 4;
3092 /* Write isb_starttime */
3093 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3094 if (!wtap_dump_file_write(wdh, &high, 4, err))
3096 wdh->bytes_dumped += 4;
3097 if (!wtap_dump_file_write(wdh, &low, 4, err))
3099 wdh->bytes_dumped += 4;
3101 /*guint64 isb_endtime */
3102 if (if_stats->isb_endtime != 0) {
3105 option_hdr.type = ISB_ENDTIME;
3106 option_hdr.value_length = 8;
3107 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3108 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3109 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3111 wdh->bytes_dumped += 4;
3113 /* Write isb_endtime */
3114 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3115 if (!wtap_dump_file_write(wdh, &high, 4, err))
3117 wdh->bytes_dumped += 4;
3118 if (!wtap_dump_file_write(wdh, &low, 4, err))
3120 wdh->bytes_dumped += 4;
3122 /*guint64 isb_ifrecv;*/
3123 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3124 option_hdr.type = ISB_IFRECV;
3125 option_hdr.value_length = 8;
3126 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3128 wdh->bytes_dumped += 4;
3130 /* Write isb_ifrecv */
3131 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3132 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3134 wdh->bytes_dumped += 8;
3136 /*guint64 isb_ifdrop;*/
3137 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3138 option_hdr.type = ISB_IFDROP;
3139 option_hdr.value_length = 8;
3140 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3142 wdh->bytes_dumped += 4;
3144 /* Write isb_ifdrop */
3145 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3146 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3148 wdh->bytes_dumped += 8;
3150 /*guint64 isb_filteraccept;*/
3151 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3152 option_hdr.type = ISB_FILTERACCEPT;
3153 option_hdr.value_length = 8;
3154 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3156 wdh->bytes_dumped += 4;
3158 /* Write isb_filteraccept */
3159 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3160 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3162 wdh->bytes_dumped += 8;
3164 /*guint64 isb_osdrop;*/
3165 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3166 option_hdr.type = ISB_OSDROP;
3167 option_hdr.value_length = 8;
3168 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3170 wdh->bytes_dumped += 4;
3172 /* Write isb_osdrop */
3173 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3174 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3176 wdh->bytes_dumped += 8;
3178 /*guint64 isb_usrdeliv;*/
3179 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3180 option_hdr.type = ISB_USRDELIV;
3181 option_hdr.value_length = 8;
3182 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3184 wdh->bytes_dumped += 4;
3186 /* Write isb_usrdeliv */
3187 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3188 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3190 wdh->bytes_dumped += 8;
3194 option_hdr.type = OPT_EOFOPT;
3195 option_hdr.value_length = 0;
3196 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3198 wdh->bytes_dumped += 4;
3201 /* write block footer */
3202 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3203 sizeof bh.block_total_length, err))
3205 wdh->bytes_dumped += sizeof bh.block_total_length;
3213 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3214 const struct wtap_pkthdr *phdr,
3215 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3217 pcapng_block_header_t bh;
3218 pcapng_enhanced_packet_block_t epb;
3220 const guint32 zero_pad = 0;
3223 gboolean have_options = FALSE;
3224 guint32 options_total_length = 0;
3225 struct option option_hdr;
3226 guint32 comment_len = 0, comment_pad_len = 0;
3227 wtapng_if_descr_t int_data;
3229 /* Don't write anything we're not willing to read. */
3230 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
3231 *err = WTAP_ERR_PACKET_TOO_LARGE;
3235 phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3236 if ((phdr_len + phdr->caplen) % 4) {
3237 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3242 /* Check if we should write comment option */
3243 if (phdr->opt_comment) {
3244 have_options = TRUE;
3245 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3246 if ((comment_len % 4)) {
3247 comment_pad_len = 4 - (comment_len % 4);
3249 comment_pad_len = 0;
3251 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3253 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3254 have_options = TRUE;
3255 options_total_length = options_total_length + 8;
3258 /* End-of optios tag */
3259 options_total_length += 4;
3262 /* write (enhanced) packet block header */
3263 bh.block_type = BLOCK_TYPE_EPB;
3264 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3266 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3268 wdh->bytes_dumped += sizeof bh;
3270 /* write block fixed content */
3271 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3272 epb.interface_id = phdr->interface_id;
3275 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3276 * data to pcap-NG files even if we *don't* have interface
3279 epb.interface_id = 0;
3282 * Split the 64-bit timestamp into two 32-bit pieces, using
3283 * the time stamp resolution for the interface.
3285 if (epb.interface_id >= wdh->interface_data->len) {
3287 * Our caller is doing something bad.
3289 *err = WTAP_ERR_INTERNAL;
3292 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3294 ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3295 (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3296 epb.timestamp_high = (guint32)(ts >> 32);
3297 epb.timestamp_low = (guint32)ts;
3298 epb.captured_len = phdr->caplen + phdr_len;
3299 epb.packet_len = phdr->len + phdr_len;
3301 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3303 wdh->bytes_dumped += sizeof epb;
3305 /* write pseudo header */
3306 if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3309 wdh->bytes_dumped += phdr_len;
3311 /* write packet data */
3312 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3314 wdh->bytes_dumped += phdr->caplen;
3316 /* write padding (if any) */
3318 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3320 wdh->bytes_dumped += pad_len;
3323 /* XXX - write (optional) block options */
3324 /* options defined in Section 2.5 (Options)
3325 * Name Code Length Description
3326 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3328 * Enhanced Packet Block options
3329 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3330 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3331 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3332 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3333 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3334 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3335 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3336 * The hash covers only the packet, not the header added by the capture driver:
3337 * this gives the possibility to calculate it inside the network card.
3338 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3339 * data acquisition system and the capture library.
3340 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3341 * between this packet and the preceding one.
3342 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3344 if (phdr->opt_comment) {
3345 option_hdr.type = OPT_COMMENT;
3346 option_hdr.value_length = comment_len;
3347 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3349 wdh->bytes_dumped += 4;
3351 /* Write the comments string */
3352 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3353 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3355 wdh->bytes_dumped += comment_len;
3357 /* write padding (if any) */
3358 if (comment_pad_len != 0) {
3359 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3361 wdh->bytes_dumped += comment_pad_len;
3364 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3368 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3369 option_hdr.type = OPT_EPB_FLAGS;
3370 option_hdr.value_length = 4;
3371 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3373 wdh->bytes_dumped += 4;
3374 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3376 wdh->bytes_dumped += 4;
3377 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3379 /* Write end of options if we have otions */
3381 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3383 wdh->bytes_dumped += 4;
3386 /* write block footer */
3387 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3388 sizeof bh.block_total_length, err))
3390 wdh->bytes_dumped += sizeof bh.block_total_length;
3396 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3398 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
3400 pcapng_block_header_t bh;
3401 pcapng_name_resolution_block_t nrb;
3403 gint rec_off, namelen, tot_rec_len;
3404 hashipv4_t *ipv4_hash_list_entry;
3405 hashipv6_t *ipv6_hash_list_entry;
3408 if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
3412 rec_off = 8; /* block type + block total length */
3413 bh.block_type = BLOCK_TYPE_NRB;
3414 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3415 rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3417 if (wdh->addrinfo_lists->ipv4_addr_list){
3419 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3420 while(ipv4_hash_list_entry != NULL){
3422 nrb.record_type = NRES_IP4RECORD;
3423 namelen = (gint)strlen(ipv4_hash_list_entry->name) + 1;
3424 nrb.record_len = 4 + namelen;
3425 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3427 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3428 /* We know the total length now; copy the block header. */
3429 memcpy(rec_data, &bh, sizeof(bh));
3432 memset(rec_data + rec_off, 0, 4);
3435 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3437 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3439 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3443 wdh->bytes_dumped += bh.block_total_length;
3445 /*Start a new NRB */
3446 rec_off = 8; /* block type + block total length */
3447 bh.block_type = BLOCK_TYPE_NRB;
3448 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3452 bh.block_total_length += tot_rec_len;
3453 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3455 memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
3457 memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
3459 memset(rec_data + rec_off, 0, PADDING4(namelen));
3460 rec_off += PADDING4(namelen);
3461 pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
3464 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3466 g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
3467 wdh->addrinfo_lists->ipv4_addr_list = NULL;
3470 if (wdh->addrinfo_lists->ipv6_addr_list){
3472 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3473 while(ipv6_hash_list_entry != NULL){
3475 nrb.record_type = NRES_IP6RECORD;
3476 namelen = (gint)strlen(ipv6_hash_list_entry->name) + 1;
3477 nrb.record_len = 16 + namelen; /* 16 bytes IPv6 address length */
3478 /* 2 bytes record type, 2 bytes length field */
3479 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3481 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3482 /* We know the total length now; copy the block header. */
3483 memcpy(rec_data, &bh, sizeof(bh));
3486 memset(rec_data + rec_off, 0, 4);
3489 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3491 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3493 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3497 wdh->bytes_dumped += bh.block_total_length;
3499 /*Start a new NRB */
3500 rec_off = 8; /* block type + block total length */
3501 bh.block_type = BLOCK_TYPE_NRB;
3502 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3506 bh.block_total_length += tot_rec_len;
3507 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3509 memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
3511 memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
3513 memset(rec_data + rec_off, 0, PADDING4(namelen));
3514 rec_off += PADDING4(namelen);
3515 pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
3518 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3520 g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
3521 wdh->addrinfo_lists->ipv6_addr_list = NULL;
3524 /* We know the total length now; copy the block header. */
3525 memcpy(rec_data, &bh, sizeof(bh));
3528 memset(rec_data + rec_off, 0, 4);
3531 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3533 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3535 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3541 wdh->bytes_dumped += bh.block_total_length;
3545 static gboolean pcapng_dump(wtap_dumper *wdh,
3546 const struct wtap_pkthdr *phdr,
3547 const guint8 *pd, int *err)
3549 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3551 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3553 wtap_encap_string(phdr->pkt_encap));
3555 /* Flush any hostname resolution info we may have */
3556 pcapng_write_name_resolution_block(wdh, err);
3558 if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3566 /* Finish writing to a dump file.
3567 Returns TRUE on success, FALSE on failure. */
3568 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3572 for (i = 0; i < wdh->interface_data->len; i++) {
3574 /* Get the interface description */
3575 wtapng_if_descr_t int_data;
3577 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3578 for (j = 0; j < int_data.num_stat_entries; j++) {
3579 wtapng_if_stats_t if_stats;
3581 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3582 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3583 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3589 pcapng_debug0("pcapng_dump_close");
3594 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3597 pcapng_dump_open(wtap_dumper *wdh, int *err)
3601 pcapng_debug0("pcapng_dump_open");
3602 /* This is a pcapng file */
3603 wdh->subtype_write = pcapng_dump;
3604 wdh->subtype_close = pcapng_dump_close;
3606 if (wdh->interface_data->len == 0) {
3607 pcapng_debug0("There are no interfaces. Can't handle that...");
3608 *err = WTAP_ERR_INTERNAL;
3612 /* write the section header block */
3613 if (!pcapng_write_section_header_block(wdh, err)) {
3616 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3618 /* Write the Interface description blocks */
3619 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u",
3620 wdh->interface_data->len);
3622 for (i = 0; i < wdh->interface_data->len; i++) {
3624 /* Get the interface description */
3625 wtapng_if_descr_t int_data;
3627 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3629 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3639 /* Returns 0 if we could write the specified encapsulation type,
3640 an error indication otherwise. */
3641 int pcapng_dump_can_write_encap(int wtap_encap)
3643 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3645 wtap_encap_string(wtap_encap));
3647 /* Per-packet encapsulation is supported. */
3648 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3651 /* Make sure we can figure out this DLT type */
3652 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3653 return WTAP_ERR_UNSUPPORTED_ENCAP;
3659 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3664 * indent-tabs-mode: nil
3667 * vi: set shiftwidth=4 tabstop=8 expandtab:
3668 * :indentSize=4:tabSize=8:noTabs=true: