6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * File format support for pcap-ng file format
9 * Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 /* File format reference:
27 * http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
29 * http://wiki.wireshark.org/Development/PcapNg
38 /* Needed for addrinfo */
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #ifdef HAVE_SYS_SOCKET_H
44 #include <sys/socket.h>
47 #ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
55 #ifdef HAVE_WINSOCK2_H
56 # include <winsock2.h>
59 #if defined(_WIN32) && defined(INET6)
60 # include <ws2tcpip.h>
64 #include "file_wrappers.h"
67 #include "pcap-common.h"
68 #include "pcap-encap.h"
72 #define pcapng_debug0(str) g_warning(str)
73 #define pcapng_debug1(str,p1) g_warning(str,p1)
74 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
75 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
77 #define pcapng_debug0(str)
78 #define pcapng_debug1(str,p1)
79 #define pcapng_debug2(str,p1,p2)
80 #define pcapng_debug3(str,p1,p2,p3)
84 pcapng_read(wtap *wth, int *err, gchar **err_info,
87 pcapng_seek_read(wtap *wth, gint64 seek_off,
88 struct wtap_pkthdr *phdr, guint8 *pd, int length,
89 int *err, gchar **err_info);
91 pcapng_close(wtap *wth);
94 /* pcapng: common block header for every block type */
95 typedef struct pcapng_block_header_s {
97 guint32 block_total_length;
98 /* x bytes block_body */
99 /* guint32 block_total_length */
100 } pcapng_block_header_t;
103 * Minimum block size = size of block header + size of block trailer.
105 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
108 * In order to keep from trying to allocate large chunks of memory,
109 * which could either fail or, even if it succeeds, chew up so much
110 * address space or memory+backing store as not to leave room for
111 * anything else, we impose an upper limit on the size of blocks
112 * we're willing to handle.
114 * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
115 * don't try saying that on Wikipedia :-) :-) :-)).
117 #define MAX_BLOCK_SIZE (16*1024*1024)
119 /* pcapng: section header block */
120 typedef struct pcapng_section_header_block_s {
121 /* pcapng_block_header_t */
123 guint16 version_major;
124 guint16 version_minor;
125 guint64 section_length; /* might be -1 for unknown */
126 /* ... Options ... */
127 } pcapng_section_header_block_t;
130 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
132 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
134 /* pcapng: interface description block */
135 typedef struct pcapng_interface_description_block_s {
139 /* ... Options ... */
140 } pcapng_interface_description_block_t;
143 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
145 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
147 /* pcapng: packet block (obsolete) */
148 typedef struct pcapng_packet_block_s {
149 guint16 interface_id;
151 guint32 timestamp_high;
152 guint32 timestamp_low;
153 guint32 captured_len;
155 /* ... Packet Data ... */
156 /* ... Padding ... */
157 /* ... Options ... */
158 } pcapng_packet_block_t;
161 * Minimum PB size = minimum block size + size of fixed length portion of PB.
163 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
165 /* pcapng: enhanced packet block */
166 typedef struct pcapng_enhanced_packet_block_s {
167 guint32 interface_id;
168 guint32 timestamp_high;
169 guint32 timestamp_low;
170 guint32 captured_len;
172 /* ... Packet Data ... */
173 /* ... Padding ... */
174 /* ... Options ... */
175 } pcapng_enhanced_packet_block_t;
178 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
180 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
182 /* pcapng: simple packet block */
183 typedef struct pcapng_simple_packet_block_s {
185 /* ... Packet Data ... */
186 /* ... Padding ... */
187 } pcapng_simple_packet_block_t;
190 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
192 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
194 /* pcapng: name resolution block */
195 typedef struct pcapng_name_resolution_block_s {
199 } pcapng_name_resolution_block_t;
202 * Minimum NRB size = minimum block size + size of smallest NRB record
203 * (there must at least be an "end of records" record).
205 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
207 /* pcapng: interface statistics block */
208 typedef struct pcapng_interface_statistics_block_s {
209 guint32 interface_id;
210 guint32 timestamp_high;
211 guint32 timestamp_low;
212 /* ... Options ... */
213 } pcapng_interface_statistics_block_t;
216 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
218 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
220 /* pcapng: common option header for every option type */
221 typedef struct pcapng_option_header_s {
223 guint16 option_length;
224 /* ... x bytes Option Body ... */
225 /* ... Padding ... */
226 } pcapng_option_header_t;
230 guint16 value_length;
234 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
235 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
236 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
237 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
238 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
239 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
240 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
244 #define OPT_COMMENT 1
245 #define OPT_SHB_HARDWARE 2
247 #define OPT_SHB_USERAPPL 4
248 #define OPT_EPB_FLAGS 2
249 #define OPT_EPB_HASH 3
250 #define OPT_EPB_DROPCOUNT 4
252 /* Capture section */
254 /* Moved to wtap.h */
255 typedef struct wtapng_section_s {
257 guint64 section_length;
259 gchar *opt_comment; /* NULL if not available */
260 gchar *shb_hardware; /* NULL if not available */
261 gchar *shb_os; /* NULL if not available */
262 gchar *shb_user_appl; /* NULL if not available */
267 /* Moved to wtap.h */
269 /* Interface Description
272 * 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}" / ...
273 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
274 * 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
275 * 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"
276 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
277 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
278 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
279 * 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
280 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
281 * 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"
282 * 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" / ...
283 * 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
284 * 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
287 typedef struct wtapng_if_descr_s {
293 gchar *opt_comment; /* NULL if not available */
294 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
295 gchar *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
296 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
297 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
298 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
299 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
300 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
301 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
302 * 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
304 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
305 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
306 * 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).
308 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. */
309 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. */
310 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
315 typedef struct wtapng_packet_s {
317 guint32 ts_high; /* seconds since 1.1.1970 */
318 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
319 guint32 cap_len; /* data length in the file */
320 guint32 packet_len; /* data length on the wire */
321 guint32 interface_id; /* identifier of the interface. */
322 guint16 drops_count; /* drops count, only valid for packet block */
323 /* 0xffff if information no available */
325 /* XXX - put the packet data / pseudo_header here as well? */
329 typedef struct wtapng_simple_packet_s {
331 guint32 cap_len; /* data length in the file */
332 guint32 packet_len; /* data length on the wire */
333 guint32 pseudo_header_len;
335 /* XXX - put the packet data / pseudo_header here as well? */
336 } wtapng_simple_packet_t;
338 /* Name Resolution */
339 typedef struct wtapng_name_res_s {
341 gchar *opt_comment; /* NULL if not available */
346 /* Interface Statistics moved to wtap.h*/
347 typedef struct wtapng_if_stats_s {
349 guint32 interface_id;
353 gchar *opt_comment; /* NULL if not available */
354 guint64 isb_starttime;
358 guint64 isb_filteraccept;
360 guint64 isb_usrdeliv;
364 typedef struct wtapng_block_s {
365 guint32 type; /* block_type as defined by pcapng */
367 wtapng_section_t section;
368 wtapng_if_descr_t if_descr;
369 wtapng_packet_t packet;
370 wtapng_simple_packet_t simple_packet;
371 wtapng_name_res_t name_res;
372 wtapng_if_stats_t if_stats;
376 * XXX - currently don't know how to handle these!
378 * For one thing, when we're reading a block, they must be
379 * writable, i.e. not const, so that we can read into them,
380 * but, when we're writing a block, they can be const, and,
381 * in fact, they sometimes point to const values.
383 struct wtap_pkthdr *packet_header;
384 const guint8 *frame_buffer;
388 /* Interface data in private struct */
389 typedef struct interface_data_s {
391 guint64 time_units_per_second;
395 gboolean shb_read; /**< Set when first SHB read, second read will fail */
396 gboolean byte_swapped;
397 guint16 version_major;
398 guint16 version_minor;
399 GArray *interface_data;
400 guint number_of_interfaces;
402 wtap_new_ipv4_callback_t add_new_ipv4;
403 wtap_new_ipv6_callback_t add_new_ipv6;
407 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
408 char *content, guint len, guint to_read,
409 int *err, gchar **err_info)
413 guint64 file_offset64;
415 /* sanity check: don't run past the end of the block */
416 if (to_read < sizeof (*oh)) {
417 *err = WTAP_ERR_BAD_FILE;
418 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
422 /* read option header */
423 errno = WTAP_ERR_CANT_READ;
424 bytes_read = file_read(oh, sizeof (*oh), fh);
425 if (bytes_read != sizeof (*oh)) {
426 pcapng_debug0("pcapng_read_option: failed to read option");
427 *err = file_error(fh, err_info);
432 block_read = sizeof (*oh);
433 if (pn->byte_swapped) {
434 oh->option_code = BSWAP16(oh->option_code);
435 oh->option_length = BSWAP16(oh->option_length);
438 /* sanity check: don't run past the end of the block */
439 if (to_read < sizeof (*oh) + oh->option_length) {
440 *err = WTAP_ERR_BAD_FILE;
441 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
445 /* sanity check: option length */
446 if (oh->option_length > len) {
447 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
448 oh->option_length, len);
452 /* read option content */
453 errno = WTAP_ERR_CANT_READ;
454 bytes_read = file_read(content, oh->option_length, fh);
455 if (bytes_read != oh->option_length) {
456 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
457 *err = file_error(fh, err_info);
462 block_read += oh->option_length;
464 /* jump over potential padding bytes at end of option */
465 if ( (oh->option_length % 4) != 0) {
466 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
467 if (file_offset64 <= 0) {
472 block_read += 4 - (oh->option_length % 4);
480 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
481 pcapng_block_header_t *bh, pcapng_t *pn,
482 wtapng_block_t *wblock, int *err,
487 guint to_read, opt_cont_buf_len;
488 pcapng_section_header_block_t shb;
489 pcapng_option_header_t oh;
490 char *option_content = NULL; /* Allocate as large as the options block */
493 * Is this block long enough to be an SHB?
495 if (bh->block_total_length < MIN_SHB_SIZE) {
500 return 0; /* probably not a pcap-ng file */
501 *err = WTAP_ERR_BAD_FILE;
502 *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",
503 bh->block_total_length, MIN_SHB_SIZE);
507 /* read block content */
508 errno = WTAP_ERR_CANT_READ;
509 bytes_read = file_read(&shb, sizeof shb, fh);
510 if (bytes_read != sizeof shb) {
511 *err = file_error(fh, err_info);
515 * We're reading this as part of an open,
516 * and this block is too short to be
517 * an SHB, so the file is too short
518 * to be a pcap-ng file.
524 * Otherwise, just report this as an error.
526 *err = WTAP_ERR_SHORT_READ;
530 block_read = bytes_read;
532 /* is the magic number one we expect? */
535 /* this seems pcapng with correct byte order */
536 pn->byte_swapped = FALSE;
537 pn->version_major = shb.version_major;
538 pn->version_minor = shb.version_minor;
540 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
541 pn->version_major, pn->version_minor, bh->block_total_length);
544 /* this seems pcapng with swapped byte order */
545 pn->byte_swapped = TRUE;
546 pn->version_major = BSWAP16(shb.version_major);
547 pn->version_minor = BSWAP16(shb.version_minor);
549 /* tweak the block length to meet current swapping that we know now */
550 bh->block_total_length = BSWAP32(bh->block_total_length);
552 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
553 pn->version_major, pn->version_minor, bh->block_total_length);
556 /* Not a "pcapng" magic number we know about. */
558 /* Not a pcap-ng file. */
563 *err = WTAP_ERR_BAD_FILE;
564 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
568 /* OK, at this point we assume it's a pcap-ng file.
570 Don't try to allocate memory for a huge number of options, as
571 that might fail and, even if it succeeds, it might not leave
572 any address space or memory+backing store for anything else.
574 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
575 We check for this *after* checking the SHB for its byte
576 order magic number, so that non-pcap-ng files are less
577 likely to be treated as bad pcap-ng files. */
578 if (bh->block_total_length > MAX_BLOCK_SIZE) {
579 *err = WTAP_ERR_BAD_FILE;
580 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
581 bh->block_total_length, MAX_BLOCK_SIZE);
585 /* We currently only suport one SHB */
586 if (pn->shb_read == TRUE) {
587 *err = WTAP_ERR_UNSUPPORTED;
588 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported.");
592 /* we currently only understand SHB V1.0 */
593 if (pn->version_major != 1 || pn->version_minor > 0) {
594 *err = WTAP_ERR_UNSUPPORTED;
595 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
596 pn->version_major, pn->version_minor);
601 /* 64bit section_length (currently unused) */
602 if (pn->byte_swapped) {
603 wblock->data.section.section_length = BSWAP64(shb.section_length);
605 wblock->data.section.section_length = shb.section_length;
608 /* Option defaults */
609 wblock->data.section.opt_comment = NULL;
610 wblock->data.section.shb_hardware = NULL;
611 wblock->data.section.shb_os = NULL;
612 wblock->data.section.shb_user_appl = NULL;
615 errno = WTAP_ERR_CANT_READ;
616 to_read = bh->block_total_length - MIN_SHB_SIZE;
618 /* Allocate enough memory to hold all options */
619 opt_cont_buf_len = to_read;
620 option_content = (char *)g_try_malloc(opt_cont_buf_len);
621 if (opt_cont_buf_len != 0 && option_content == NULL) {
622 *err = ENOMEM; /* we assume we're out of memory */
625 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
626 while (to_read != 0) {
628 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
629 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
630 if (bytes_read <= 0) {
631 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
634 block_read += bytes_read;
635 to_read -= bytes_read;
637 /* handle option content */
638 switch (oh.option_code) {
641 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
643 /* padding should be ok here, just get out of this */
647 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
648 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
649 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
651 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
654 case(OPT_SHB_HARDWARE):
655 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
656 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
657 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
659 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
663 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
664 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
665 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
667 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
670 case(OPT_SHB_USERAPPL):
671 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
672 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
673 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
675 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
679 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
680 oh.option_code, oh.option_length);
683 g_free(option_content);
689 /* "Interface Description Block" */
691 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
692 wtapng_block_t *wblock, int *err, gchar **err_info)
694 guint64 time_units_per_second = 1000000; /* default */
697 guint to_read, opt_cont_buf_len;
698 pcapng_interface_description_block_t idb;
699 pcapng_option_header_t oh;
700 char *option_content = NULL; /* Allocate as large as the options block */
703 * Is this block long enough to be an IDB?
705 if (bh->block_total_length < MIN_IDB_SIZE) {
709 *err = WTAP_ERR_BAD_FILE;
710 *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",
711 bh->block_total_length, MIN_IDB_SIZE);
715 /* Don't try to allocate memory for a huge number of options, as
716 that might fail and, even if it succeeds, it might not leave
717 any address space or memory+backing store for anything else.
719 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
720 We check for this *after* checking the SHB for its byte
721 order magic number, so that non-pcap-ng files are less
722 likely to be treated as bad pcap-ng files. */
723 if (bh->block_total_length > MAX_BLOCK_SIZE) {
724 *err = WTAP_ERR_BAD_FILE;
725 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
726 bh->block_total_length, MAX_BLOCK_SIZE);
730 /* read block content */
731 errno = WTAP_ERR_CANT_READ;
732 bytes_read = file_read(&idb, sizeof idb, fh);
733 if (bytes_read != sizeof idb) {
734 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
735 *err = file_error(fh, err_info);
740 block_read = bytes_read;
742 /* mandatory values */
743 if (pn->byte_swapped) {
744 wblock->data.if_descr.link_type = BSWAP16(idb.linktype);
745 wblock->data.if_descr.snap_len = BSWAP32(idb.snaplen);
747 wblock->data.if_descr.link_type = idb.linktype;
748 wblock->data.if_descr.snap_len = idb.snaplen;
751 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
752 wblock->data.if_descr.time_units_per_second = time_units_per_second;
754 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
755 wblock->data.if_descr.link_type,
756 wtap_encap_string(wblock->data.if_descr.wtap_encap),
757 wblock->data.if_descr.snap_len);
759 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
760 /* This is unrealistic, but text2pcap currently uses 102400.
761 * We do not use this value, maybe we should check the
762 * snap_len of the packets against it. For now, only warn.
764 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
765 wblock->data.if_descr.snap_len);
766 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
769 /* Option defaults */
770 wblock->data.if_descr.opt_comment = NULL;
771 wblock->data.if_descr.if_name = NULL;
772 wblock->data.if_descr.if_description = NULL;
773 /* XXX: if_IPv4addr */
774 /* XXX: if_IPv6addr */
775 /* XXX: if_MACaddr */
776 /* XXX: if_EUIaddr */
777 wblock->data.if_descr.if_speed = 0; /* "unknown" */
778 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
779 wblock->data.if_descr.if_filter_str = NULL;
780 wblock->data.if_descr.bpf_filter_len = 0;
781 wblock->data.if_descr.if_filter_bpf_bytes = NULL;
782 wblock->data.if_descr.if_os = NULL;
783 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
784 /* XXX: guint64 if_tsoffset; */
788 errno = WTAP_ERR_CANT_READ;
789 to_read = bh->block_total_length - MIN_IDB_SIZE;
791 /* Allocate enough memory to hold all options */
792 opt_cont_buf_len = to_read;
793 option_content = (char *)g_try_malloc(opt_cont_buf_len);
794 if (opt_cont_buf_len != 0 && option_content == NULL) {
795 *err = ENOMEM; /* we assume we're out of memory */
799 while (to_read != 0) {
801 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
802 if (bytes_read <= 0) {
803 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
806 block_read += bytes_read;
807 to_read -= bytes_read;
809 /* handle option content */
810 switch (oh.option_code) {
811 case(0): /* opt_endofopt */
813 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
815 /* padding should be ok here, just get out of this */
818 case(1): /* opt_comment */
819 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
820 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
821 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
823 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
826 case(2): /* if_name */
827 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
828 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
829 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
831 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
834 case(3): /* if_description */
835 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
836 wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
837 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
839 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
843 * 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
844 * 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"
845 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
846 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
848 case(8): /* if_speed */
849 if (oh.option_length == 8) {
850 /* Don't cast a char[] into a guint64--the
851 * char[] may not be aligned correctly.
853 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
854 if (pn->byte_swapped)
855 wblock->data.if_descr.if_speed = BSWAP64(wblock->data.if_descr.if_speed);
856 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
858 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
861 case(9): /* if_tsresol */
862 if (oh.option_length == 1) {
865 guint8 i, exponent, if_tsresol;
867 if_tsresol = option_content[0];
868 if (if_tsresol & 0x80) {
873 exponent = (guint8)(if_tsresol & 0x7f);
874 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
876 for (i = 0; i < exponent; i++) {
879 time_units_per_second = result;
881 time_units_per_second = G_MAXUINT64;
883 if (time_units_per_second > (((guint64)1) << 32)) {
884 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
886 wblock->data.if_descr.time_units_per_second = time_units_per_second;
887 wblock->data.if_descr.if_tsresol = if_tsresol;
888 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);
890 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
894 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
896 case(11): /* if_filter */
897 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
898 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
901 if (option_content[0] == 0) {
902 wblock->data.if_descr.if_filter_str = g_strndup(option_content+1, oh.option_length-1);
903 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);
904 } else if (option_content[0] == 1) {
905 wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
906 wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
907 memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, option_content+1, oh.option_length-1);
910 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
913 case(12): /* if_os */
915 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
916 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
917 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
919 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
920 wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
921 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
923 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
926 case(13): /* if_fcslen */
927 if (oh.option_length == 1) {
928 wblock->data.if_descr.if_fcslen = option_content[0];
929 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
930 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
931 /* XXX - add sanity check */
933 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
937 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
938 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
939 * The time zone of the offset can be specified with the option if_tzone.
940 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
943 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
944 oh.option_code, oh.option_length);
948 g_free(option_content);
950 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
951 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
953 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
954 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
963 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)
967 guint to_read, opt_cont_buf_len;
968 guint64 file_offset64;
969 pcapng_enhanced_packet_block_t epb;
970 pcapng_packet_block_t pb;
971 guint32 block_total_length;
973 interface_data_t int_data;
975 pcapng_option_header_t oh;
976 int pseudo_header_len;
977 char *option_content = NULL; /* Allocate as large as the options block */
980 /* Don't try to allocate memory for a huge number of options, as
981 that might fail and, even if it succeeds, it might not leave
982 any address space or memory+backing store for anything else.
984 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
985 We check for this *after* checking the SHB for its byte
986 order magic number, so that non-pcap-ng files are less
987 likely to be treated as bad pcap-ng files. */
988 if (bh->block_total_length > MAX_BLOCK_SIZE) {
989 *err = WTAP_ERR_BAD_FILE;
990 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
991 bh->block_total_length, MAX_BLOCK_SIZE);
995 /* "(Enhanced) Packet Block" read fixed part */
996 errno = WTAP_ERR_CANT_READ;
999 * Is this block long enough to be an EPB?
1001 if (bh->block_total_length < MIN_EPB_SIZE) {
1005 *err = WTAP_ERR_BAD_FILE;
1006 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
1007 bh->block_total_length, MIN_EPB_SIZE);
1010 bytes_read = file_read(&epb, sizeof epb, fh);
1011 if (bytes_read != sizeof epb) {
1012 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1013 *err = file_error(fh, err_info);
1016 block_read = bytes_read;
1018 if (pn->byte_swapped) {
1019 wblock->data.packet.interface_id = BSWAP32(epb.interface_id);
1020 wblock->data.packet.drops_count = -1; /* invalid */
1021 wblock->data.packet.ts_high = BSWAP32(epb.timestamp_high);
1022 wblock->data.packet.ts_low = BSWAP32(epb.timestamp_low);
1023 wblock->data.packet.cap_len = BSWAP32(epb.captured_len);
1024 wblock->data.packet.packet_len = BSWAP32(epb.packet_len);
1026 wblock->data.packet.interface_id = epb.interface_id;
1027 wblock->data.packet.drops_count = -1; /* invalid */
1028 wblock->data.packet.ts_high = epb.timestamp_high;
1029 wblock->data.packet.ts_low = epb.timestamp_low;
1030 wblock->data.packet.cap_len = epb.captured_len;
1031 wblock->data.packet.packet_len = epb.packet_len;
1033 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1034 wblock->data.packet.interface_id, wblock->data.packet.cap_len, wblock->data.packet.packet_len);
1037 * Is this block long enough to be a PB?
1039 if (bh->block_total_length < MIN_PB_SIZE) {
1043 *err = WTAP_ERR_BAD_FILE;
1044 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1045 bh->block_total_length, MIN_PB_SIZE);
1048 bytes_read = file_read(&pb, sizeof pb, fh);
1049 if (bytes_read != sizeof pb) {
1050 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1051 *err = file_error(fh, err_info);
1054 block_read = bytes_read;
1056 if (pn->byte_swapped) {
1057 wblock->data.packet.interface_id = BSWAP16(pb.interface_id);
1058 wblock->data.packet.drops_count = BSWAP16(pb.drops_count);
1059 wblock->data.packet.ts_high = BSWAP32(pb.timestamp_high);
1060 wblock->data.packet.ts_low = BSWAP32(pb.timestamp_low);
1061 wblock->data.packet.cap_len = BSWAP32(pb.captured_len);
1062 wblock->data.packet.packet_len = BSWAP32(pb.packet_len);
1064 wblock->data.packet.interface_id = pb.interface_id;
1065 wblock->data.packet.drops_count = pb.drops_count;
1066 wblock->data.packet.ts_high = pb.timestamp_high;
1067 wblock->data.packet.ts_low = pb.timestamp_low;
1068 wblock->data.packet.cap_len = pb.captured_len;
1069 wblock->data.packet.packet_len = pb.packet_len;
1071 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1072 wblock->data.packet.interface_id, wblock->data.packet.cap_len, wblock->data.packet.packet_len);
1076 * How much padding is there at the end of the packet data?
1078 if ((wblock->data.packet.cap_len % 4) != 0)
1079 padding = 4 - (wblock->data.packet.cap_len % 4);
1083 /* add padding bytes to "block total length" */
1084 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1085 if (bh->block_total_length % 4) {
1086 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1088 block_total_length = bh->block_total_length;
1090 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1093 * Is this block long enough to hold the packet data?
1096 if (block_total_length <
1097 MIN_EPB_SIZE + wblock->data.packet.cap_len + padding) {
1101 *err = WTAP_ERR_BAD_FILE;
1102 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1103 block_total_length, wblock->data.packet.cap_len);
1107 if (block_total_length <
1108 MIN_PB_SIZE + wblock->data.packet.cap_len + padding) {
1112 *err = WTAP_ERR_BAD_FILE;
1113 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1114 block_total_length, wblock->data.packet.cap_len);
1119 if (wblock->data.packet.cap_len > wblock->data.packet.packet_len) {
1120 *err = WTAP_ERR_BAD_FILE;
1121 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u.",
1122 wblock->data.packet.cap_len, wblock->data.packet.packet_len);
1125 if (wblock->data.packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1126 *err = WTAP_ERR_BAD_FILE;
1127 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1128 wblock->data.packet.cap_len, WTAP_MAX_PACKET_SIZE);
1131 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1132 wblock->data.packet.packet_len,
1133 wblock->data.packet.cap_len,
1134 wblock->data.packet.interface_id);
1136 if (wblock->data.packet.interface_id >= pn->number_of_interfaces) {
1137 *err = WTAP_ERR_BAD_FILE;
1138 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
1139 wblock->data.packet.interface_id, pn->number_of_interfaces);
1142 int_data = g_array_index(pn->interface_data, interface_data_t,
1143 wblock->data.packet.interface_id);
1145 wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1147 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1148 int_data.wtap_encap,
1149 wtap_encap_string(int_data.wtap_encap),
1150 pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header.pseudo_header));
1151 wblock->packet_header->interface_id = wblock->data.packet.interface_id;
1152 wblock->packet_header->pkt_encap = int_data.wtap_encap;
1154 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1155 pseudo_header_len = pcap_process_pseudo_header(fh,
1157 int_data.wtap_encap,
1158 wblock->data.packet.cap_len,
1160 wblock->packet_header,
1163 if (pseudo_header_len < 0) {
1166 block_read += pseudo_header_len;
1167 if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1168 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1171 wblock->packet_header->caplen = wblock->data.packet.cap_len - pseudo_header_len;
1172 wblock->packet_header->len = wblock->data.packet.packet_len - pseudo_header_len;
1174 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1175 ts = (((guint64)wblock->data.packet.ts_high) << 32) | ((guint64)wblock->data.packet.ts_low);
1176 wblock->packet_header->ts.secs = (time_t)(ts / int_data.time_units_per_second);
1177 wblock->packet_header->ts.nsecs = (int)(((ts % int_data.time_units_per_second) * 1000000000) / int_data.time_units_per_second);
1179 /* "(Enhanced) Packet Block" read capture data */
1180 errno = WTAP_ERR_CANT_READ;
1181 bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.packet.cap_len - pseudo_header_len, fh);
1182 if (bytes_read != (int) (wblock->data.packet.cap_len - pseudo_header_len)) {
1183 *err = file_error(fh, err_info);
1184 pcapng_debug1("pcapng_read_packet_block: couldn't read %u bytes of captured data",
1185 wblock->data.packet.cap_len - pseudo_header_len);
1187 *err = WTAP_ERR_SHORT_READ;
1190 block_read += bytes_read;
1192 /* jump over potential padding bytes at end of the packet data */
1194 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1195 if (file_offset64 <= 0) {
1200 block_read += padding;
1203 /* Option defaults */
1204 wblock->packet_header->opt_comment = NULL;
1205 wblock->packet_header->drop_count = -1;
1206 wblock->packet_header->pack_flags = 0;
1208 /* FCS length default */
1209 fcslen = pn->if_fcslen;
1217 errno = WTAP_ERR_CANT_READ;
1218 to_read = block_total_length -
1219 (int)sizeof(pcapng_block_header_t) -
1220 block_read - /* fixed and variable part, including padding */
1221 (int)sizeof(bh->block_total_length);
1223 /* Allocate enough memory to hold all options */
1224 opt_cont_buf_len = to_read;
1225 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1226 if (opt_cont_buf_len != 0 && option_content == NULL) {
1227 *err = ENOMEM; /* we assume we're out of memory */
1231 while (to_read != 0) {
1233 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1234 if (bytes_read <= 0) {
1235 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1238 block_read += bytes_read;
1239 to_read -= bytes_read;
1241 /* handle option content */
1242 switch (oh.option_code) {
1245 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1247 /* padding should be ok here, just get out of this */
1251 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1252 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1253 wblock->packet_header->opt_comment = g_strndup(option_content, oh.option_length);
1254 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->packet_header->opt_comment);
1256 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1259 case(OPT_EPB_FLAGS):
1260 if (oh.option_length == 4) {
1261 /* Don't cast a char[] into a guint32--the
1262 * char[] may not be aligned correctly.
1264 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1265 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1266 if (pn->byte_swapped)
1267 wblock->packet_header->pack_flags = BSWAP32(wblock->packet_header->pack_flags);
1268 if (wblock->packet_header->pack_flags & 0x000001E0) {
1269 /* The FCS length is present */
1270 fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1272 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1274 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1278 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1279 oh.option_code, oh.option_length);
1281 case(OPT_EPB_DROPCOUNT):
1282 if (oh.option_length == 8) {
1283 /* Don't cast a char[] into a guint32--the
1284 * char[] may not be aligned correctly.
1286 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1287 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1288 if (pn->byte_swapped)
1289 wblock->packet_header->drop_count = BSWAP64(wblock->packet_header->drop_count);
1291 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1293 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1297 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1298 oh.option_code, oh.option_length);
1302 g_free(option_content);
1304 pcap_read_post_process(WTAP_FILE_PCAPNG, int_data.wtap_encap,
1305 (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1306 (guint8 *) (wblock->frame_buffer),
1307 (int) (wblock->data.packet.cap_len - pseudo_header_len),
1308 pn->byte_swapped, fcslen);
1314 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)
1318 guint64 file_offset64;
1319 interface_data_t int_data;
1320 int pseudo_header_len;
1321 pcapng_simple_packet_block_t spb;
1324 * Is this block long enough to be an SPB?
1326 if (bh->block_total_length < MIN_SPB_SIZE) {
1330 *err = WTAP_ERR_BAD_FILE;
1331 *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",
1332 bh->block_total_length, MIN_SPB_SIZE);
1336 /* Don't try to allocate memory for a huge number of options, as
1337 that might fail and, even if it succeeds, it might not leave
1338 any address space or memory+backing store for anything else.
1340 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1341 We check for this *after* checking the SHB for its byte
1342 order magic number, so that non-pcap-ng files are less
1343 likely to be treated as bad pcap-ng files. */
1344 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1345 *err = WTAP_ERR_BAD_FILE;
1346 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1347 bh->block_total_length, MAX_BLOCK_SIZE);
1351 /* "Simple Packet Block" read fixed part */
1352 errno = WTAP_ERR_CANT_READ;
1353 bytes_read = file_read(&spb, sizeof spb, fh);
1354 if (bytes_read != sizeof spb) {
1355 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1356 *err = file_error(fh, err_info);
1359 block_read = bytes_read;
1361 if (pn->byte_swapped) {
1362 wblock->data.simple_packet.packet_len = BSWAP32(spb.packet_len);
1364 wblock->data.simple_packet.packet_len = spb.packet_len;
1367 wblock->data.simple_packet.cap_len = bh->block_total_length
1368 - (guint32)sizeof(pcapng_simple_packet_block_t)
1369 - (guint32)sizeof(bh->block_total_length);
1371 if (wblock->data.simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1372 *err = WTAP_ERR_BAD_FILE;
1373 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1374 wblock->data.simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1377 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1378 wblock->data.simple_packet.packet_len);
1380 if (0 >= pn->number_of_interfaces) {
1381 *err = WTAP_ERR_BAD_FILE;
1382 *err_info = g_strdup_printf("pcapng: interface index 0 is not less than interface count %u.",
1383 pn->number_of_interfaces);
1386 int_data = g_array_index(pn->interface_data, interface_data_t, 0);
1388 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1389 pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1391 /* No time stamp in a simple packet block; no options, either */
1392 wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1393 wblock->packet_header->interface_id = 0;
1394 wblock->packet_header->pkt_encap = int_data.wtap_encap;
1395 wblock->packet_header->ts.secs = 0;
1396 wblock->packet_header->ts.nsecs = 0;
1397 wblock->packet_header->interface_id = 0;
1398 wblock->packet_header->opt_comment = NULL;
1399 wblock->packet_header->drop_count = 0;
1400 wblock->packet_header->pack_flags = 0;
1402 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1403 pseudo_header_len = pcap_process_pseudo_header(fh,
1405 int_data.wtap_encap,
1406 wblock->data.simple_packet.cap_len,
1408 wblock->packet_header,
1411 if (pseudo_header_len < 0) {
1414 wblock->packet_header->caplen = wblock->data.simple_packet.cap_len - pseudo_header_len;
1415 wblock->packet_header->len = wblock->data.packet.packet_len - pseudo_header_len;
1416 block_read += pseudo_header_len;
1417 if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1418 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1422 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1424 /* "Simple Packet Block" read capture data */
1425 errno = WTAP_ERR_CANT_READ;
1426 bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.simple_packet.cap_len, fh);
1427 if (bytes_read != (int) wblock->data.simple_packet.cap_len) {
1428 *err = file_error(fh, err_info);
1429 pcapng_debug1("pcapng_read_simple_packet_block: couldn't read %u bytes of captured data",
1430 wblock->data.simple_packet.cap_len);
1432 *err = WTAP_ERR_SHORT_READ;
1435 block_read += bytes_read;
1437 /* jump over potential padding bytes at end of the packet data */
1438 if ((wblock->data.simple_packet.cap_len % 4) != 0) {
1439 file_offset64 = file_seek(fh, 4 - (wblock->data.simple_packet.cap_len % 4), SEEK_CUR, err);
1440 if (file_offset64 <= 0) {
1445 block_read += 4 - (wblock->data.simple_packet.cap_len % 4);
1448 pcap_read_post_process(WTAP_FILE_PCAPNG, int_data.wtap_encap,
1449 (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1450 (guint8 *) (wblock->frame_buffer),
1451 (int) wblock->data.simple_packet.cap_len,
1452 pn->byte_swapped, pn->if_fcslen);
1456 #define NRES_ENDOFRECORD 0
1457 #define NRES_IP4RECORD 1
1458 #define NRES_IP6RECORD 2
1459 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1460 /* IPv6 + MAXNAMELEN */
1461 #define INITIAL_NRB_REC_SIZE (16 + 64)
1464 * Find the end of the NUL-terminated name the beginning of which is pointed
1465 * to by p; record_len is the number of bytes remaining in the record.
1467 * Return the length of the name, including the terminating NUL.
1469 * If we don't find the terminating NUL, or if the name is zero-length
1470 * (not counting the terminating NUL), return -1 and set *err and
1471 * *err_info appropriately.
1474 name_resolution_block_find_name_end(guint8 *p, guint record_len, int *err,
1481 if (record_len == 0) {
1483 * We ran out of bytes in the record without
1486 *err = WTAP_ERR_BAD_FILE;
1487 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1491 break; /* that's the terminating NUL */
1494 namelen++; /* count this byte */
1497 /* The name is empty. */
1498 *err = WTAP_ERR_BAD_FILE;
1499 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has empty host name");
1503 /* Include the NUL in the name length. */
1508 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)
1513 guint64 file_offset64;
1514 pcapng_name_resolution_block_t nrb;
1522 * Is this block long enough to be an NRB?
1524 if (bh->block_total_length < MIN_NRB_SIZE) {
1528 *err = WTAP_ERR_BAD_FILE;
1529 *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",
1530 bh->block_total_length, MIN_NRB_SIZE);
1534 /* Don't try to allocate memory for a huge number of options, as
1535 that might fail and, even if it succeeds, it might not leave
1536 any address space or memory+backing store for anything else.
1538 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1539 We check for this *after* checking the SHB for its byte
1540 order magic number, so that non-pcap-ng files are less
1541 likely to be treated as bad pcap-ng files. */
1542 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1543 *err = WTAP_ERR_BAD_FILE;
1544 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1545 bh->block_total_length, MAX_BLOCK_SIZE);
1549 errno = WTAP_ERR_CANT_READ;
1550 to_read = bh->block_total_length - 8 - 4; /* We have read the header adn should not read the final block_total_length */
1552 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1555 * Start out with a buffer big enough for an IPv6 address and one
1556 * 64-byte name; we'll make the buffer bigger if necessary.
1558 buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1559 while (block_read < to_read) {
1561 * There must be at least one record's worth of data
1564 if ((size_t)(to_read - block_read) < sizeof nrb) {
1565 buffer_free(&nrb_rec);
1566 *err = WTAP_ERR_BAD_FILE;
1567 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1568 to_read - block_read,
1572 bytes_read = file_read(&nrb, sizeof nrb, fh);
1573 if (bytes_read != sizeof nrb) {
1574 buffer_free(&nrb_rec);
1575 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1576 *err = file_error(fh, err_info);
1579 block_read += bytes_read;
1581 if (pn->byte_swapped) {
1582 nrb.record_type = BSWAP16(nrb.record_type);
1583 nrb.record_len = BSWAP16(nrb.record_len);
1586 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1587 buffer_free(&nrb_rec);
1588 *err = WTAP_ERR_BAD_FILE;
1589 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1590 to_read - block_read,
1591 nrb.record_len + PADDING4(nrb.record_len));
1594 switch (nrb.record_type) {
1595 case NRES_ENDOFRECORD:
1596 /* There shouldn't be any more data */
1599 case NRES_IP4RECORD:
1601 * The smallest possible record must have
1602 * a 4-byte IPv4 address, hence a minimum
1605 * (The pcap-NG spec really indicates
1606 * that it must be at least 5 bytes,
1607 * as there must be at least one name,
1608 * and it really must be at least 6
1609 * bytes, as the name mustn't be null,
1610 * but there's no need to fail if there
1611 * aren't any names at all, and we
1612 * should report a null name as such.)
1614 if (nrb.record_len < 4) {
1615 buffer_free(&nrb_rec);
1616 *err = WTAP_ERR_BAD_FILE;
1617 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1621 buffer_assure_space(&nrb_rec, nrb.record_len);
1622 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1623 nrb.record_len, fh);
1624 if (bytes_read != nrb.record_len) {
1625 buffer_free(&nrb_rec);
1626 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1627 *err = file_error(fh, err_info);
1630 block_read += bytes_read;
1632 if (pn->add_new_ipv4) {
1634 * Scan through all the names in
1635 * the record and add them.
1638 buffer_start_ptr(&nrb_rec), 4);
1639 if (pn->byte_swapped)
1640 v4_addr = BSWAP32(v4_addr);
1641 for (namep = buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1643 namep += namelen, record_len -= namelen) {
1645 * Scan forward for a null
1648 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1649 if (namelen == -1) {
1650 buffer_free(&nrb_rec);
1651 return -1; /* fail */
1653 pn->add_new_ipv4(v4_addr, namep);
1657 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1658 if (file_offset64 <= 0) {
1659 buffer_free(&nrb_rec);
1664 block_read += PADDING4(nrb.record_len);
1666 case NRES_IP6RECORD:
1668 * The smallest possible record must have
1669 * a 16-byte IPv6 address, hence a minimum
1672 * (The pcap-NG spec really indicates
1673 * that it must be at least 17 bytes,
1674 * as there must be at least one name,
1675 * and it really must be at least 18
1676 * bytes, as the name mustn't be null,
1677 * but there's no need to fail if there
1678 * aren't any names at all, and we
1679 * should report a null name as such.)
1681 if (nrb.record_len < 16) {
1682 buffer_free(&nrb_rec);
1683 *err = WTAP_ERR_BAD_FILE;
1684 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1688 if (to_read < nrb.record_len) {
1689 buffer_free(&nrb_rec);
1690 pcapng_debug0("pcapng_read_name_resolution_block: insufficient data for IPv6 record");
1693 buffer_assure_space(&nrb_rec, nrb.record_len);
1694 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1695 nrb.record_len, fh);
1696 if (bytes_read != nrb.record_len) {
1697 buffer_free(&nrb_rec);
1698 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1699 *err = file_error(fh, err_info);
1702 block_read += bytes_read;
1704 if (pn->add_new_ipv6) {
1705 for (namep = buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1707 namep += namelen, record_len -= namelen) {
1709 * Scan forward for a null
1712 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1713 if (namelen == -1) {
1714 buffer_free(&nrb_rec);
1715 return -1; /* fail */
1717 pn->add_new_ipv6(buffer_start_ptr(&nrb_rec),
1722 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1723 if (file_offset64 <= 0) {
1724 buffer_free(&nrb_rec);
1729 block_read += PADDING4(nrb.record_len);
1732 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1733 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1734 if (file_offset64 <= 0) {
1735 buffer_free(&nrb_rec);
1740 block_read += nrb.record_len + PADDING4(nrb.record_len);
1745 buffer_free(&nrb_rec);
1750 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)
1754 guint to_read, opt_cont_buf_len;
1755 pcapng_interface_statistics_block_t isb;
1756 pcapng_option_header_t oh;
1757 char *option_content = NULL; /* Allocate as large as the options block */
1760 * Is this block long enough to be an ISB?
1762 if (bh->block_total_length < MIN_ISB_SIZE) {
1766 *err = WTAP_ERR_BAD_FILE;
1767 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1768 bh->block_total_length, MIN_ISB_SIZE);
1772 /* Don't try to allocate memory for a huge number of options, as
1773 that might fail and, even if it succeeds, it might not leave
1774 any address space or memory+backing store for anything else.
1776 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1777 We check for this *after* checking the SHB for its byte
1778 order magic number, so that non-pcap-ng files are less
1779 likely to be treated as bad pcap-ng files. */
1780 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1781 *err = WTAP_ERR_BAD_FILE;
1782 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1783 bh->block_total_length, MAX_BLOCK_SIZE);
1787 /* "Interface Statistics Block" read fixed part */
1788 errno = WTAP_ERR_CANT_READ;
1789 bytes_read = file_read(&isb, sizeof isb, fh);
1790 if (bytes_read != sizeof isb) {
1791 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1792 *err = file_error(fh, err_info);
1795 block_read = bytes_read;
1797 if (pn->byte_swapped) {
1798 wblock->data.if_stats.interface_id = BSWAP32(isb.interface_id);
1799 wblock->data.if_stats.ts_high = BSWAP32(isb.timestamp_high);
1800 wblock->data.if_stats.ts_low = BSWAP32(isb.timestamp_low);
1802 wblock->data.if_stats.interface_id = isb.interface_id;
1803 wblock->data.if_stats.ts_high = isb.timestamp_high;
1804 wblock->data.if_stats.ts_low = isb.timestamp_low;
1806 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1808 /* Option defaults */
1809 wblock->data.if_stats.opt_comment = NULL;
1810 wblock->data.if_stats.isb_ifrecv = -1;
1811 wblock->data.if_stats.isb_ifdrop = -1;
1812 wblock->data.if_stats.isb_filteraccept = -1;
1813 wblock->data.if_stats.isb_osdrop = -1;
1814 wblock->data.if_stats.isb_usrdeliv = -1;
1817 errno = WTAP_ERR_CANT_READ;
1818 to_read = bh->block_total_length -
1819 (MIN_BLOCK_SIZE + block_read); /* fixed and variable part, including padding */
1821 /* Allocate enough memory to hold all options */
1822 opt_cont_buf_len = to_read;
1823 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1824 if (opt_cont_buf_len != 0 && option_content == NULL) {
1825 *err = ENOMEM; /* we assume we're out of memory */
1829 while (to_read != 0) {
1831 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1832 if (bytes_read <= 0) {
1833 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1836 block_read += bytes_read;
1837 to_read -= bytes_read;
1839 /* handle option content */
1840 switch (oh.option_code) {
1841 case(0): /* opt_endofopt */
1843 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1845 /* padding should be ok here, just get out of this */
1848 case(1): /* opt_comment */
1849 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1850 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1851 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1853 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1856 case(2): /* isb_starttime */
1857 if (oh.option_length == 8) {
1860 /* Don't cast a char[] into a guint32--the
1861 * char[] may not be aligned correctly.
1863 memcpy(&high, option_content, sizeof(guint32));
1864 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1865 if (pn->byte_swapped) {
1866 high = BSWAP32(high);
1869 wblock->data.if_stats.isb_starttime = (guint64)high;
1870 wblock->data.if_stats.isb_starttime <<= 32;
1871 wblock->data.if_stats.isb_starttime += (guint64)low;
1872 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1874 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1877 case(3): /* isb_endtime */
1878 if (oh.option_length == 8) {
1881 /* Don't cast a char[] into a guint32--the
1882 * char[] may not be aligned correctly.
1884 memcpy(&high, option_content, sizeof(guint32));
1885 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1886 if (pn->byte_swapped) {
1887 high = BSWAP32(high);
1890 wblock->data.if_stats.isb_endtime = (guint64)high;
1891 wblock->data.if_stats.isb_endtime <<= 32;
1892 wblock->data.if_stats.isb_endtime += (guint64)low;
1893 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1895 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1898 case(4): /* isb_ifrecv */
1899 if (oh.option_length == 8) {
1900 /* Don't cast a char[] into a guint32--the
1901 * char[] may not be aligned correctly.
1903 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1904 if (pn->byte_swapped)
1905 wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
1906 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1908 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1911 case(5): /* isb_ifdrop */
1912 if (oh.option_length == 8) {
1913 /* Don't cast a char[] into a guint32--the
1914 * char[] may not be aligned correctly.
1916 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1917 if (pn->byte_swapped)
1918 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
1919 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1921 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1924 case(6): /* isb_filteraccept 6 */
1925 if (oh.option_length == 8) {
1926 /* Don't cast a char[] into a guint32--the
1927 * char[] may not be aligned correctly.
1929 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1930 if (pn->byte_swapped)
1931 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_filteraccept);
1932 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1934 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1937 case(7): /* isb_osdrop 7 */
1938 if (oh.option_length == 8) {
1939 /* Don't cast a char[] into a guint32--the
1940 * char[] may not be aligned correctly.
1942 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1943 if (pn->byte_swapped)
1944 wblock->data.if_stats.isb_osdrop = BSWAP64(wblock->data.if_stats.isb_osdrop);
1945 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1947 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1950 case(8): /* isb_usrdeliv 8 */
1951 if (oh.option_length == 8) {
1952 /* Don't cast a char[] into a guint32--the
1953 * char[] may not be aligned correctly.
1955 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1956 if (pn->byte_swapped)
1957 wblock->data.if_stats.isb_usrdeliv = BSWAP64(wblock->data.if_stats.isb_osdrop);
1958 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1960 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1964 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1965 oh.option_code, oh.option_length);
1969 g_free(option_content);
1976 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)
1979 guint64 file_offset64;
1980 guint32 block_total_length;
1982 if (bh->block_total_length < MIN_BLOCK_SIZE) {
1983 *err = WTAP_ERR_BAD_FILE;
1984 *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",
1985 bh->block_total_length, MIN_BLOCK_SIZE);
1989 /* add padding bytes to "block total length" */
1990 /* (the "block total length" of some example files don't contain any padding bytes!) */
1991 if (bh->block_total_length % 4) {
1992 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1994 block_total_length = bh->block_total_length;
1997 block_read = block_total_length - MIN_BLOCK_SIZE;
1999 /* jump over this unknown block */
2000 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
2001 if (file_offset64 <= 0) {
2012 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2016 pcapng_block_header_t bh;
2017 guint32 block_total_length;
2020 /* Try to read the (next) block header */
2021 errno = WTAP_ERR_CANT_READ;
2022 bytes_read = file_read(&bh, sizeof bh, fh);
2023 if (bytes_read != sizeof bh) {
2024 *err = file_error(fh, err_info);
2025 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2031 block_read = bytes_read;
2032 if (pn->byte_swapped) {
2033 bh.block_type = BSWAP32(bh.block_type);
2034 bh.block_total_length = BSWAP32(bh.block_total_length);
2037 wblock->type = bh.block_type;
2039 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2043 * This is being read in by pcapng_open(), so this block
2044 * must be an SHB. If it's not, this is not a pcap-ng
2047 * XXX - check for various forms of Windows <-> UN*X
2048 * mangling, and suggest that the file might be a
2049 * pcap-ng file that was damaged in transit?
2051 if (bh.block_type != BLOCK_TYPE_SHB)
2052 return 0; /* not a pcap-ng file */
2055 switch (bh.block_type) {
2056 case(BLOCK_TYPE_SHB):
2057 bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
2059 case(BLOCK_TYPE_IDB):
2060 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
2062 case(BLOCK_TYPE_PB):
2063 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
2065 case(BLOCK_TYPE_SPB):
2066 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
2068 case(BLOCK_TYPE_EPB):
2069 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
2071 case(BLOCK_TYPE_NRB):
2072 bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
2074 case(BLOCK_TYPE_ISB):
2075 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
2078 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2079 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
2082 if (bytes_read <= 0) {
2085 block_read += bytes_read;
2087 /* sanity check: first and second block lengths must match */
2088 errno = WTAP_ERR_CANT_READ;
2089 bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
2090 if (bytes_read != sizeof block_total_length) {
2091 pcapng_debug0("pcapng_read_block: couldn't read second block length");
2092 *err = file_error(fh, err_info);
2094 *err = WTAP_ERR_SHORT_READ;
2097 block_read += bytes_read;
2099 if (pn->byte_swapped)
2100 block_total_length = BSWAP32(block_total_length);
2102 if (!(block_total_length == bh.block_total_length)) {
2103 *err = WTAP_ERR_BAD_FILE;
2104 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
2105 bh.block_total_length, block_total_length);
2112 /* Process an IDB that we've just read. */
2114 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2116 wtapng_if_descr_t int_data;
2117 interface_data_t interface_data;
2119 int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2120 int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2121 int_data.link_type = wblock->data.if_descr.link_type;
2122 int_data.snap_len = wblock->data.if_descr.snap_len;
2124 int_data.opt_comment = wblock->data.if_descr.opt_comment;
2125 int_data.if_name = wblock->data.if_descr.if_name;
2126 int_data.if_description = wblock->data.if_descr.if_description;
2127 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2128 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2129 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2130 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2131 int_data.if_speed = wblock->data.if_descr.if_speed;
2132 int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2133 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2134 int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2135 int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2136 int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2137 int_data.if_os = wblock->data.if_descr.if_os;
2138 int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2139 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2140 /* Interface statistics */
2141 int_data.num_stat_entries = 0;
2142 int_data.interface_statistics = NULL;
2144 g_array_append_val(wth->interface_data, int_data);
2145 wth->number_of_interfaces++;
2147 interface_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2148 interface_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2150 g_array_append_val(pcapng->interface_data, interface_data);
2151 pcapng->number_of_interfaces++;
2154 /* classic wtap: open capture file */
2156 pcapng_open(wtap *wth, int *err, gchar **err_info)
2160 wtapng_block_t wblock;
2162 pcapng_block_header_t bh;
2163 gint64 saved_offset;
2165 pn.shb_read = FALSE;
2166 /* we don't know the byte swapping of the file yet */
2167 pn.byte_swapped = FALSE;
2169 pn.version_major = -1;
2170 pn.version_minor = -1;
2171 pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
2172 pn.number_of_interfaces = 0;
2175 /* we don't expect any packet blocks yet */
2176 wblock.frame_buffer = NULL;
2177 wblock.packet_header = NULL;
2178 wblock.file_encap = &wth->file_encap;
2180 pcapng_debug0("pcapng_open: opening file");
2181 /* read first block */
2182 bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
2183 if (bytes_read <= 0) {
2184 pcapng_debug0("pcapng_open: couldn't read first SHB");
2185 *err = file_error(wth->fh, err_info);
2186 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
2191 /* first block must be a "Section Header Block" */
2192 if (wblock.type != BLOCK_TYPE_SHB) {
2194 * XXX - check for damage from transferring a file
2195 * between Windows and UN*X as text rather than
2198 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2204 * At this point, we've decided this is a pcap-NG file, not
2205 * some other type of file, so we can't return 0, as that
2206 * means "this isn't a pcap-NG file, try some other file
2209 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2210 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2211 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2212 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2214 wth->file_encap = WTAP_ENCAP_UNKNOWN;
2215 wth->snapshot_length = 0;
2216 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
2217 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2218 wth->priv = (void *)pcapng;
2221 wth->subtype_read = pcapng_read;
2222 wth->subtype_seek_read = pcapng_seek_read;
2223 wth->subtype_close = pcapng_close;
2224 wth->file_type = WTAP_FILE_PCAPNG;
2227 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
2228 wth->number_of_interfaces = 0;
2230 /* Loop over all IDB:s that appear before any packets */
2232 /* peek at next block */
2233 /* Try to read the (next) block header */
2234 saved_offset = file_tell(wth->fh);
2235 errno = WTAP_ERR_CANT_READ;
2236 bytes_read = file_read(&bh, sizeof bh, wth->fh);
2237 if (bytes_read == 0) {
2238 pcapng_debug0("No more IDBs available...");
2241 if (bytes_read != sizeof bh) {
2242 *err = file_error(wth->fh, err_info);
2243 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);
2245 *err = WTAP_ERR_SHORT_READ;
2249 /* go back to where we were */
2250 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2252 if (pn.byte_swapped) {
2253 bh.block_type = BSWAP32(bh.block_type);
2256 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2258 if (bh.block_type != BLOCK_TYPE_IDB) {
2259 break; /* No more IDB:s */
2261 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
2262 if (bytes_read == 0) {
2263 pcapng_debug0("No more IDBs available...");
2266 if (bytes_read <= 0) {
2267 pcapng_debug0("pcapng_open: couldn't read IDB");
2268 *err = file_error(wth->fh, err_info);
2270 *err = WTAP_ERR_SHORT_READ;
2273 pcapng_process_idb(wth, pcapng, &wblock);
2274 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, *wblock.file_encap);
2280 /* classic wtap: read packet */
2282 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2284 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2286 wtapng_block_t wblock;
2287 wtapng_if_descr_t *wtapng_if_descr;
2288 wtapng_if_stats_t if_stats;
2290 *data_offset = file_tell(wth->fh);
2291 pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER "d", *data_offset);
2293 /* XXX - This should be done in the packet block reading function and
2294 * should make use of the caplen of the packet.
2296 if (wth->snapshot_length > 0) {
2297 buffer_assure_space(wth->frame_buffer, wth->snapshot_length);
2299 buffer_assure_space(wth->frame_buffer, WTAP_MAX_PACKET_SIZE);
2302 wblock.frame_buffer = buffer_start_ptr(wth->frame_buffer);
2303 wblock.packet_header = &wth->phdr;
2304 wblock.file_encap = &wth->file_encap;
2306 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2307 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2309 /* read next block */
2311 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2312 if (bytes_read <= 0) {
2313 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2314 pcapng_debug0("pcapng_read: couldn't read packet block");
2318 switch (wblock.type) {
2320 case(BLOCK_TYPE_SHB):
2321 /* We don't currently support multi-section files. */
2322 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2323 *err = WTAP_ERR_UNSUPPORTED;
2324 *err_info = g_strdup_printf("pcapng: multi-section files not currently supported.");
2327 case(BLOCK_TYPE_PB):
2328 case(BLOCK_TYPE_SPB):
2329 case(BLOCK_TYPE_EPB):
2330 /* packet block - we've found a packet */
2333 case(BLOCK_TYPE_IDB):
2334 /* A new interface */
2335 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2336 *data_offset += bytes_read;
2337 pcapng_process_idb(wth, pcapng, &wblock);
2340 case(BLOCK_TYPE_NRB):
2341 /* More name resolution entries */
2342 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2343 *data_offset += bytes_read;
2346 case(BLOCK_TYPE_ISB):
2347 /* Another interface statistics report */
2348 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2349 *data_offset += bytes_read;
2350 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2351 if (wth->number_of_interfaces < wblock.data.if_stats.interface_id) {
2352 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces", wblock.data.if_stats.interface_id);
2354 /* Get the interface description */
2355 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2356 if (wtapng_if_descr->num_stat_entries == 0) {
2357 /* First ISB found, no previous entry */
2358 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2359 wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2362 if_stats.interface_id = wblock.data.if_stats.interface_id;
2363 if_stats.ts_high = wblock.data.if_stats.ts_high;
2364 if_stats.ts_low = wblock.data.if_stats.ts_low;
2366 if_stats.opt_comment = wblock.data.if_stats.opt_comment; /* NULL if not available */
2367 if_stats.isb_starttime = wblock.data.if_stats.isb_starttime;
2368 if_stats.isb_endtime = wblock.data.if_stats.isb_endtime;
2369 if_stats.isb_ifrecv = wblock.data.if_stats.isb_ifrecv;
2370 if_stats.isb_ifdrop = wblock.data.if_stats.isb_ifdrop;
2371 if_stats.isb_filteraccept = wblock.data.if_stats.isb_filteraccept;
2372 if_stats.isb_osdrop = wblock.data.if_stats.isb_osdrop;
2373 if_stats.isb_usrdeliv = wblock.data.if_stats.isb_usrdeliv;
2375 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2376 wtapng_if_descr->num_stat_entries++;
2381 /* XXX - improve handling of "unknown" blocks */
2382 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2383 *data_offset += bytes_read;
2384 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2390 if (wblock.data.packet.interface_id < pcapng->number_of_interfaces) {
2392 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2393 *err = WTAP_ERR_BAD_FILE;
2394 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
2395 wblock.data.packet.interface_id, pcapng->number_of_interfaces);
2396 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
2400 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2401 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
2407 /* classic wtap: seek to file position and read packet */
2409 pcapng_seek_read(wtap *wth, gint64 seek_off,
2410 struct wtap_pkthdr *phdr, guint8 *pd, int length _U_,
2411 int *err, gchar **err_info)
2413 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2414 guint64 bytes_read64;
2416 wtapng_block_t wblock;
2419 /* seek to the right file position */
2420 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2421 if (bytes_read64 <= 0) {
2422 return FALSE; /* Seek error */
2424 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2426 wblock.frame_buffer = pd;
2427 wblock.packet_header = phdr;
2428 wblock.file_encap = &wth->file_encap;
2430 /* read the block */
2431 bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2432 if (bytes_read <= 0) {
2433 *err = file_error(wth->random_fh, err_info);
2434 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2435 *err, errno, bytes_read);
2439 /* block must be a "Packet Block", an "Enhanced Packet Block",
2440 or a "Simple Packet Block" */
2441 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2442 wblock.type != BLOCK_TYPE_SPB) {
2443 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2451 /* classic wtap: close capture file */
2453 pcapng_close(wtap *wth)
2455 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2457 pcapng_debug0("pcapng_close: closing file");
2458 if (pcapng->interface_data != NULL) {
2459 g_array_free(pcapng->interface_data, TRUE);
2466 GArray *interface_data;
2467 guint number_of_interfaces;
2468 struct addrinfo *addrinfo_list_last;
2472 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2474 pcapng_block_header_t bh;
2475 pcapng_section_header_block_t shb;
2476 const guint32 zero_pad = 0;
2477 gboolean have_options = FALSE;
2478 struct option option_hdr; /* guint16 type, guint16 value_length; */
2479 guint32 options_total_length = 0;
2480 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2481 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2484 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2485 /* Check if we should write comment option */
2486 if (wdh->shb_hdr->opt_comment) {
2487 have_options = TRUE;
2488 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2489 if ((comment_len % 4)) {
2490 comment_pad_len = 4 - (comment_len % 4);
2492 comment_pad_len = 0;
2494 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2497 /* Check if we should write shb_hardware option */
2498 if (wdh->shb_hdr->shb_hardware) {
2499 have_options = TRUE;
2500 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2501 if ((shb_hardware_len % 4)) {
2502 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2504 shb_hardware_pad_len = 0;
2506 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2509 /* Check if we should write shb_os option */
2510 if (wdh->shb_hdr->shb_os) {
2511 have_options = TRUE;
2512 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2513 if ((shb_os_len % 4)) {
2514 shb_os_pad_len = 4 - (shb_os_len % 4);
2518 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2521 /* Check if we should write shb_user_appl option */
2522 if (wdh->shb_hdr->shb_user_appl) {
2523 have_options = TRUE;
2524 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2525 if ((shb_user_appl_len % 4)) {
2526 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2528 shb_user_appl_pad_len = 0;
2530 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2533 /* End-of-options tag */
2534 options_total_length += 4;
2538 /* write block header */
2539 bh.block_type = BLOCK_TYPE_SHB;
2540 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2541 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2543 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2545 wdh->bytes_dumped += sizeof bh;
2547 /* write block fixed content */
2548 /* XXX - get these values from wblock? */
2549 shb.magic = 0x1A2B3C4D;
2550 shb.version_major = 1;
2551 shb.version_minor = 0;
2552 shb.section_length = -1;
2554 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2556 wdh->bytes_dumped += sizeof shb;
2558 /* XXX - write (optional) block options
2566 option_hdr.type = OPT_COMMENT;
2567 option_hdr.value_length = comment_len;
2568 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2570 wdh->bytes_dumped += 4;
2572 /* Write the comments string */
2573 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);
2574 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2576 wdh->bytes_dumped += comment_len;
2578 /* write padding (if any) */
2579 if (comment_pad_len != 0) {
2580 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2582 wdh->bytes_dumped += comment_pad_len;
2586 if (shb_hardware_len) {
2587 option_hdr.type = OPT_SHB_HARDWARE;
2588 option_hdr.value_length = shb_hardware_len;
2589 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2591 wdh->bytes_dumped += 4;
2593 /* Write the string */
2594 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);
2595 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2597 wdh->bytes_dumped += shb_hardware_len;
2599 /* write padding (if any) */
2600 if (shb_hardware_pad_len != 0) {
2601 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2603 wdh->bytes_dumped += shb_hardware_pad_len;
2608 option_hdr.type = OPT_SHB_OS;
2609 option_hdr.value_length = shb_os_len;
2610 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2612 wdh->bytes_dumped += 4;
2614 /* Write the string */
2615 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);
2616 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2618 wdh->bytes_dumped += shb_os_len;
2620 /* write padding (if any) */
2621 if (shb_os_pad_len != 0) {
2622 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2624 wdh->bytes_dumped += shb_os_pad_len;
2628 if (shb_user_appl_len) {
2629 option_hdr.type = OPT_SHB_USERAPPL;
2630 option_hdr.value_length = shb_user_appl_len;
2631 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2633 wdh->bytes_dumped += 4;
2635 /* Write the comments string */
2636 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);
2637 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2639 wdh->bytes_dumped += shb_user_appl_len;
2641 /* write padding (if any) */
2642 if (shb_user_appl_pad_len != 0) {
2643 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2645 wdh->bytes_dumped += shb_user_appl_pad_len;
2649 /* Write end of options if we have otions */
2651 option_hdr.type = OPT_EOFOPT;
2652 option_hdr.value_length = 0;
2653 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2655 wdh->bytes_dumped += 4;
2658 /* write block footer */
2659 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2660 sizeof bh.block_total_length, err))
2662 wdh->bytes_dumped += sizeof bh.block_total_length;
2667 #define IDB_OPT_IF_NAME 2
2668 #define IDB_OPT_IF_DESCR 3
2669 #define IDB_OPT_IF_SPEED 8
2670 #define IDB_OPT_IF_TSRESOL 9
2671 #define IDB_OPT_IF_FILTER 11
2672 #define IDB_OPT_IF_OS 12
2675 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2677 pcapng_block_header_t bh;
2678 pcapng_interface_description_block_t idb;
2679 const guint32 zero_pad = 0;
2680 gboolean have_options = FALSE;
2681 struct option option_hdr; /* guint16 type, guint16 value_length; */
2682 guint32 options_total_length = 0;
2683 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2684 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;
2687 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2688 int_data->link_type,
2689 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2690 int_data->snap_len);
2692 if (int_data->link_type == (guint16)-1) {
2693 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2697 /* Calculate options length */
2698 if (int_data->opt_comment) {
2699 have_options = TRUE;
2700 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2701 if ((comment_len % 4)) {
2702 comment_pad_len = 4 - (comment_len % 4);
2704 comment_pad_len = 0;
2706 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2710 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2712 if (int_data->if_name) {
2713 have_options = TRUE;
2714 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2715 if ((if_name_len % 4)) {
2716 if_name_pad_len = 4 - (if_name_len % 4);
2718 if_name_pad_len = 0;
2720 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2724 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2726 if (int_data->if_description) {
2727 have_options = TRUE;
2728 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2729 if ((if_description_len % 4)) {
2730 if_description_pad_len = 4 - (if_description_len % 4);
2732 if_description_pad_len = 0;
2734 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2736 /* Currently not handled
2737 * if_IPv4addr 4 Interface network address and netmask.
2738 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2739 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2740 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2743 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2745 if (int_data->if_speed != 0) {
2746 have_options = TRUE;
2747 options_total_length = options_total_length + 8 + 4;
2750 * if_tsresol 9 Resolution of timestamps.
2752 if (int_data->if_tsresol != 0) {
2753 have_options = TRUE;
2754 options_total_length = options_total_length + 4 + 4;
2757 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2760 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2761 * 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).
2763 if (int_data->if_filter_str) {
2764 have_options = TRUE;
2765 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2766 if ((if_filter_str_len % 4)) {
2767 if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2769 if_filter_str_pad_len = 0;
2771 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2774 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2776 if (int_data->if_os) {
2777 have_options = TRUE;
2778 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2779 if ((if_os_len % 4)) {
2780 if_os_pad_len = 4 - (if_os_len % 4);
2784 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2787 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2788 * -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.
2790 if (int_data->if_fcslen != 0) {
2793 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2794 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2798 /* End-of-options tag */
2799 options_total_length += 4;
2802 /* write block header */
2803 bh.block_type = BLOCK_TYPE_IDB;
2804 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2806 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2808 wdh->bytes_dumped += sizeof bh;
2810 /* write block fixed content */
2811 idb.linktype = int_data->link_type;
2813 idb.snaplen = int_data->snap_len;
2815 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2817 wdh->bytes_dumped += sizeof idb;
2819 /* XXX - write (optional) block options */
2820 if (comment_len != 0) {
2821 option_hdr.type = OPT_COMMENT;
2822 option_hdr.value_length = comment_len;
2823 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2825 wdh->bytes_dumped += 4;
2827 /* Write the comments string */
2828 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);
2829 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2831 wdh->bytes_dumped += comment_len;
2833 /* write padding (if any) */
2834 if (comment_pad_len != 0) {
2835 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2837 wdh->bytes_dumped += comment_pad_len;
2841 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2843 if (if_name_len !=0) {
2844 option_hdr.type = IDB_OPT_IF_NAME;
2845 option_hdr.value_length = if_name_len;
2846 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2848 wdh->bytes_dumped += 4;
2850 /* Write the comments string */
2851 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);
2852 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
2854 wdh->bytes_dumped += if_name_len;
2856 /* write padding (if any) */
2857 if (if_name_pad_len != 0) {
2858 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2860 wdh->bytes_dumped += if_name_pad_len;
2864 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2866 if (if_description_len != 0) {
2867 option_hdr.type = IDB_OPT_IF_NAME;
2868 option_hdr.value_length = if_description_len;
2869 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2871 wdh->bytes_dumped += 4;
2873 /* Write the comments string */
2874 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);
2875 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
2877 wdh->bytes_dumped += if_description_len;
2879 /* write padding (if any) */
2880 if (if_description_pad_len != 0) {
2881 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2883 wdh->bytes_dumped += if_description_pad_len;
2886 /* Currently not handled
2887 * if_IPv4addr 4 Interface network address and netmask.
2888 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2889 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2890 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2893 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2895 if (int_data->if_speed != 0) {
2896 option_hdr.type = IDB_OPT_IF_SPEED;
2897 option_hdr.value_length = 8;
2898 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2900 wdh->bytes_dumped += 4;
2902 /* Write the comments string */
2903 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
2904 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
2906 wdh->bytes_dumped += 8;
2909 * if_tsresol 9 Resolution of timestamps.
2910 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
2911 * If the Most Significant Bit is equal to zero, the remaining bits indicates
2912 * the resolution of the timestamp as as a negative power of 10
2914 if (int_data->if_tsresol != 0) {
2915 option_hdr.type = IDB_OPT_IF_TSRESOL;
2916 option_hdr.value_length = 1;
2917 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2919 wdh->bytes_dumped += 4;
2921 /* Write the time stamp resolution */
2922 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
2923 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
2925 wdh->bytes_dumped += 1;
2926 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2928 wdh->bytes_dumped += 3;
2931 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2934 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2936 /* Libpcap string variant */
2937 if (if_filter_str_len !=0) {
2938 option_hdr.type = IDB_OPT_IF_FILTER;
2939 option_hdr.value_length = if_filter_str_len;
2940 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2941 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2943 wdh->bytes_dumped += 4;
2945 /* Write the zero indicating libpcap filter variant */
2946 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
2948 wdh->bytes_dumped += 1;
2950 /* Write the comments string */
2951 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);
2952 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2953 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
2955 wdh->bytes_dumped += if_filter_str_len - 1;
2957 /* write padding (if any) */
2958 if (if_filter_str_pad_len != 0) {
2959 if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
2961 wdh->bytes_dumped += if_filter_str_pad_len;
2965 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2967 if (if_os_len != 0) {
2968 option_hdr.type = IDB_OPT_IF_OS;
2969 option_hdr.value_length = if_os_len;
2970 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2972 wdh->bytes_dumped += 4;
2974 /* Write the comments string */
2975 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);
2976 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
2978 wdh->bytes_dumped += if_os_len;
2980 /* write padding (if any) */
2981 if (if_os_pad_len != 0) {
2982 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2984 wdh->bytes_dumped += if_os_pad_len;
2989 option_hdr.type = OPT_EOFOPT;
2990 option_hdr.value_length = 0;
2991 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2993 wdh->bytes_dumped += 4;
2997 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
3000 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
3001 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
3004 /* write block footer */
3005 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3006 sizeof bh.block_total_length, err))
3008 wdh->bytes_dumped += sizeof bh.block_total_length;
3013 #define ISB_STARTTIME 2
3014 #define ISB_ENDTIME 3
3015 #define ISB_IFRECV 4
3016 #define ISB_IFDROP 5
3017 #define ISB_FILTERACCEPT 6
3018 #define ISB_OSDROP 7
3019 #define ISB_USRDELIV 8
3022 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
3025 pcapng_block_header_t bh;
3026 pcapng_interface_statistics_block_t isb;
3027 const guint32 zero_pad = 0;
3028 gboolean have_options = FALSE;
3029 struct option option_hdr; /* guint16 type, guint16 value_length; */
3030 guint32 options_total_length = 0;
3031 guint32 comment_len = 0;
3032 guint32 comment_pad_len = 0;
3034 pcapng_debug0("pcapng_write_interface_statistics_block");
3037 /* Calculate options length */
3038 if (if_stats->opt_comment) {
3039 have_options = TRUE;
3040 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
3041 if ((comment_len % 4)) {
3042 comment_pad_len = 4 - (comment_len % 4);
3044 comment_pad_len = 0;
3046 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3048 /*guint64 isb_starttime */
3049 if (if_stats->isb_starttime != 0) {
3050 have_options = TRUE;
3051 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3053 /*guint64 isb_endtime */
3054 if (if_stats->isb_endtime != 0) {
3055 have_options = TRUE;
3056 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3058 /*guint64 isb_ifrecv */
3059 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3060 have_options = TRUE;
3061 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3063 /*guint64 isb_ifdrop */
3064 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3065 have_options = TRUE;
3066 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3068 /*guint64 isb_filteraccept */
3069 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3070 have_options = TRUE;
3071 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3073 /*guint64 isb_osdrop */
3074 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3075 have_options = TRUE;
3076 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3078 /*guint64 isb_usrdeliv */
3079 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3080 have_options = TRUE;
3081 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3084 /* write block header */
3086 /* End-of-optios tag */
3087 options_total_length += 4;
3090 /* write block header */
3091 bh.block_type = BLOCK_TYPE_ISB;
3092 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3094 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3096 wdh->bytes_dumped += sizeof bh;
3098 /* write block fixed content */
3099 isb.interface_id = if_stats->interface_id;
3100 isb.timestamp_high = if_stats->ts_high;
3101 isb.timestamp_low = if_stats->ts_low;
3104 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3106 wdh->bytes_dumped += sizeof isb;
3108 /* write (optional) block options */
3110 option_hdr.type = OPT_COMMENT;
3111 option_hdr.value_length = comment_len;
3112 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3114 wdh->bytes_dumped += 4;
3116 /* Write the comments string */
3117 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);
3118 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3120 wdh->bytes_dumped += comment_len;
3122 /* write padding (if any) */
3123 if (comment_pad_len != 0) {
3124 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3126 wdh->bytes_dumped += comment_pad_len;
3129 /*guint64 isb_starttime */
3130 if (if_stats->isb_starttime != 0) {
3133 option_hdr.type = ISB_STARTTIME;
3134 option_hdr.value_length = 8;
3135 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3136 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3137 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3139 wdh->bytes_dumped += 4;
3141 /* Write isb_starttime */
3142 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3143 if (!wtap_dump_file_write(wdh, &high, 4, err))
3145 wdh->bytes_dumped += 4;
3146 if (!wtap_dump_file_write(wdh, &low, 4, err))
3148 wdh->bytes_dumped += 4;
3150 /*guint64 isb_endtime */
3151 if (if_stats->isb_endtime != 0) {
3154 option_hdr.type = ISB_ENDTIME;
3155 option_hdr.value_length = 8;
3156 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3157 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3158 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3160 wdh->bytes_dumped += 4;
3162 /* Write isb_endtime */
3163 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3164 if (!wtap_dump_file_write(wdh, &high, 4, err))
3166 wdh->bytes_dumped += 4;
3167 if (!wtap_dump_file_write(wdh, &low, 4, err))
3169 wdh->bytes_dumped += 4;
3171 /*guint64 isb_ifrecv;*/
3172 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3173 option_hdr.type = ISB_IFRECV;
3174 option_hdr.value_length = 8;
3175 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3177 wdh->bytes_dumped += 4;
3179 /* Write isb_ifrecv */
3180 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3181 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3183 wdh->bytes_dumped += 8;
3185 /*guint64 isb_ifdrop;*/
3186 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3187 option_hdr.type = ISB_IFDROP;
3188 option_hdr.value_length = 8;
3189 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3191 wdh->bytes_dumped += 4;
3193 /* Write isb_ifdrop */
3194 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3195 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3197 wdh->bytes_dumped += 8;
3199 /*guint64 isb_filteraccept;*/
3200 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3201 option_hdr.type = ISB_FILTERACCEPT;
3202 option_hdr.value_length = 8;
3203 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3205 wdh->bytes_dumped += 4;
3207 /* Write isb_filteraccept */
3208 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3209 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3211 wdh->bytes_dumped += 8;
3213 /*guint64 isb_osdrop;*/
3214 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3215 option_hdr.type = ISB_OSDROP;
3216 option_hdr.value_length = 8;
3217 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3219 wdh->bytes_dumped += 4;
3221 /* Write isb_osdrop */
3222 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3223 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3225 wdh->bytes_dumped += 8;
3227 /*guint64 isb_usrdeliv;*/
3228 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3229 option_hdr.type = ISB_USRDELIV;
3230 option_hdr.value_length = 8;
3231 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3233 wdh->bytes_dumped += 4;
3235 /* Write isb_usrdeliv */
3236 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3237 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3239 wdh->bytes_dumped += 8;
3243 option_hdr.type = OPT_EOFOPT;
3244 option_hdr.value_length = 0;
3245 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3247 wdh->bytes_dumped += 4;
3250 /* write block footer */
3251 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3252 sizeof bh.block_total_length, err))
3254 wdh->bytes_dumped += sizeof bh.block_total_length;
3262 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3263 const struct wtap_pkthdr *phdr,
3264 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3266 pcapng_block_header_t bh;
3267 pcapng_enhanced_packet_block_t epb;
3269 const guint32 zero_pad = 0;
3272 gboolean have_options = FALSE;
3273 guint32 options_total_length = 0;
3274 struct option option_hdr;
3275 guint32 comment_len = 0, comment_pad_len = 0;
3276 wtapng_if_descr_t int_data;
3278 phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3279 if ((phdr_len + phdr->caplen) % 4) {
3280 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3285 /* Check if we should write comment option */
3286 if (phdr->opt_comment) {
3287 have_options = TRUE;
3288 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3289 if ((comment_len % 4)) {
3290 comment_pad_len = 4 - (comment_len % 4);
3292 comment_pad_len = 0;
3294 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3296 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3297 have_options = TRUE;
3298 options_total_length = options_total_length + 8;
3301 /* End-of optios tag */
3302 options_total_length += 4;
3305 /* write (enhanced) packet block header */
3306 bh.block_type = BLOCK_TYPE_EPB;
3307 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3309 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3311 wdh->bytes_dumped += sizeof bh;
3313 /* write block fixed content */
3314 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3315 epb.interface_id = phdr->interface_id;
3318 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3319 * data to pcap-NG files even if we *don't* have interface
3322 epb.interface_id = 0;
3325 * Split the 64-bit timestamp into two 32-bit pieces, using
3326 * the time stamp resolution for the interface.
3328 if (epb.interface_id >= wdh->number_of_interfaces) {
3330 * Our caller is doing something bad.
3332 *err = WTAP_ERR_INTERNAL;
3335 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3337 ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3338 (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3339 epb.timestamp_high = (guint32)(ts >> 32);
3340 epb.timestamp_low = (guint32)ts;
3341 epb.captured_len = phdr->caplen + phdr_len;
3342 epb.packet_len = phdr->len + phdr_len;
3344 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3346 wdh->bytes_dumped += sizeof epb;
3348 /* write pseudo header */
3349 if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3352 wdh->bytes_dumped += phdr_len;
3354 /* write packet data */
3355 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3357 wdh->bytes_dumped += phdr->caplen;
3359 /* write padding (if any) */
3361 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3363 wdh->bytes_dumped += pad_len;
3366 /* XXX - write (optional) block options */
3367 /* options defined in Section 2.5 (Options)
3368 * Name Code Length Description
3369 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3371 * Enhanced Packet Block options
3372 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3373 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3374 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3375 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3376 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3377 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3378 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3379 * The hash covers only the packet, not the header added by the capture driver:
3380 * this gives the possibility to calculate it inside the network card.
3381 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3382 * data acquisition system and the capture library.
3383 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3384 * between this packet and the preceding one.
3385 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3387 if (phdr->opt_comment) {
3388 option_hdr.type = OPT_COMMENT;
3389 option_hdr.value_length = comment_len;
3390 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3392 wdh->bytes_dumped += 4;
3394 /* Write the comments string */
3395 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3396 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3398 wdh->bytes_dumped += comment_len;
3400 /* write padding (if any) */
3401 if (comment_pad_len != 0) {
3402 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3404 wdh->bytes_dumped += comment_pad_len;
3407 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3411 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3412 option_hdr.type = OPT_EPB_FLAGS;
3413 option_hdr.value_length = 4;
3414 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3416 wdh->bytes_dumped += 4;
3417 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3419 wdh->bytes_dumped += 4;
3420 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3422 /* Write end of options if we have otions */
3424 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3426 wdh->bytes_dumped += 4;
3429 /* write block footer */
3430 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3431 sizeof bh.block_total_length, err))
3433 wdh->bytes_dumped += sizeof bh.block_total_length;
3439 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3441 pcapng_write_name_resolution_block(wtap_dumper *wdh, pcapng_dump_t *pcapng, int *err)
3443 pcapng_block_header_t bh;
3444 pcapng_name_resolution_block_t nrb;
3445 struct addrinfo *ai;
3446 struct sockaddr_in *sa4;
3447 struct sockaddr_in6 *sa6;
3449 gint rec_off, namelen, tot_rec_len;
3451 if (! pcapng->addrinfo_list_last || ! pcapng->addrinfo_list_last->ai_next) {
3455 rec_off = 8; /* block type + block total length */
3456 bh.block_type = BLOCK_TYPE_NRB;
3457 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3458 rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3460 for (; pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next; pcapng->addrinfo_list_last = pcapng->addrinfo_list_last->ai_next ) {
3461 ai = pcapng->addrinfo_list_last->ai_next; /* Skips over the first (dummy) entry */
3462 namelen = (gint)strlen(ai->ai_canonname) + 1;
3463 if (ai->ai_family == AF_INET) {
3464 nrb.record_type = NRES_IP4RECORD;
3465 nrb.record_len = 4 + namelen;
3466 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3467 bh.block_total_length += tot_rec_len;
3469 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
3473 * The joys of BSD sockaddrs. In practice, this
3474 * cast is alignment-safe.
3476 sa4 = (struct sockaddr_in *)(void *)ai->ai_addr;
3477 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3480 memcpy(rec_data + rec_off, &(sa4->sin_addr.s_addr), 4);
3483 memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
3486 memset(rec_data + rec_off, 0, PADDING4(namelen));
3487 rec_off += PADDING4(namelen);
3488 pcapng_debug1("NRB: added IPv4 record for %s", ai->ai_canonname);
3489 } else if (ai->ai_family == AF_INET6) {
3490 nrb.record_type = NRES_IP6RECORD;
3491 nrb.record_len = 16 + namelen;
3492 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3493 bh.block_total_length += tot_rec_len;
3495 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
3499 * The joys of BSD sockaddrs. In practice, this
3500 * cast is alignment-safe.
3502 sa6 = (struct sockaddr_in6 *)(void *)ai->ai_addr;
3503 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3506 memcpy(rec_data + rec_off, sa6->sin6_addr.s6_addr, 16);
3509 memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
3512 memset(rec_data + rec_off, 0, PADDING4(namelen));
3513 rec_off += PADDING4(namelen);
3514 pcapng_debug1("NRB: added IPv6 record for %s", ai->ai_canonname);
3518 /* We know the total length now; copy the block header. */
3519 memcpy(rec_data, &bh, sizeof(bh));
3522 memset(rec_data + rec_off, 0, 4);
3525 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3527 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3529 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3535 wdh->bytes_dumped += bh.block_total_length;
3541 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
3544 interface_data_t int_data;
3545 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3547 for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
3548 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
3549 if (wtap_encap == int_data.wtap_encap) {
3557 static gboolean pcapng_dump(wtap_dumper *wdh,
3558 const struct wtap_pkthdr *phdr,
3559 const guint8 *pd, int *err)
3561 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3562 /*interface_data_t int_data;*/
3563 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3566 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3568 wtap_encap_string(phdr->pkt_encap));
3570 if (!pcapng->addrinfo_list_last)
3571 pcapng->addrinfo_list_last = wdh->addrinfo_list;
3572 /* Flush any hostname resolution info we may have */
3573 while (pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next) {
3574 pcapng_write_name_resolution_block(wdh, pcapng, err);
3577 if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3585 /* Finish writing to a dump file.
3586 Returns TRUE on success, FALSE on failure. */
3587 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3590 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3592 if ((wdh->number_of_interfaces > 0) && (wdh->interface_data != NULL)) {
3593 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3595 /* Get the interface description */
3596 wtapng_if_descr_t int_data;
3598 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3599 for (j = 0; j < (int)int_data.num_stat_entries; j++) {
3600 wtapng_if_stats_t if_stats;
3602 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3603 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3604 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3611 pcapng_debug0("pcapng_dump_close");
3612 g_array_free(pcapng->interface_data, TRUE);
3613 pcapng->number_of_interfaces = 0;
3618 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3621 pcapng_dump_open(wtap_dumper *wdh, int *err)
3623 pcapng_dump_t *pcapng;
3625 interface_data_t interface_data;
3627 pcapng_debug0("pcapng_dump_open");
3628 /* This is a pcapng file */
3629 wdh->subtype_write = pcapng_dump;
3630 wdh->subtype_close = pcapng_dump_close;
3631 pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
3632 wdh->priv = (void *)pcapng;
3633 pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
3635 if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
3636 pcapng_debug0("There are no interfaces. Can't handle that...");
3637 *err = WTAP_ERR_INTERNAL;
3641 /* write the section header block */
3642 if (!pcapng_write_section_header_block(wdh, err)) {
3645 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3647 /* Write the Interface description blocks */
3648 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
3650 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3652 /* Get the interface description */
3653 wtapng_if_descr_t int_data;
3655 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3657 interface_data.wtap_encap = int_data.wtap_encap;
3658 interface_data.time_units_per_second = int_data.time_units_per_second;
3660 g_array_append_val(pcapng->interface_data, interface_data);
3661 pcapng->number_of_interfaces++;
3663 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3669 interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3670 if (interface_id == G_MAXUINT32) {
3672 * We haven't yet written out an interface description
3673 * block for an interface with this encapsulation.
3675 * Is this encapsulation even supported in pcap-ng?
3677 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3678 if (pcap_encap == -1) {
3682 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3686 /* write the interface description block */
3687 wblock.frame_buffer = NULL;
3688 wblock.pseudo_header = NULL;
3689 wblock.packet_header = NULL;
3690 wblock.file_encap = NULL;
3691 wblock.type = BLOCK_TYPE_IDB;
3692 wblock.data.if_descr.link_type = pcap_encap;
3693 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3694 WTAP_MAX_PACKET_SIZE; /* XXX */
3696 /* XXX - options unused */
3697 wblock.data.if_descr.if_speed = -1;
3698 /*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
3699 wblock.data.if_descr.if_os = NULL;
3700 wblock.data.if_descr.if_fcslen = -1;
3702 if (!pcapng_write_if_descr_block(wdh, &wblock, err)) {
3706 interface_id = pcapng->number_of_interfaces;
3707 int_data.wtap_encap = phdr->pkt_encap;
3708 int_data.time_units_per_second = 0;
3709 g_array_append_val(pcapng->interface_data, int_data);
3710 pcapng->number_of_interfaces++;
3712 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3715 wtap_encap_string(phdr->pkt_encap));
3723 /* Returns 0 if we could write the specified encapsulation type,
3724 an error indication otherwise. */
3725 int pcapng_dump_can_write_encap(int wtap_encap)
3727 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3729 wtap_encap_string(wtap_encap));
3731 /* Per-packet encapsulation is supported. */
3732 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3735 /* Make sure we can figure out this DLT type */
3736 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3737 return WTAP_ERR_UNSUPPORTED_ENCAP;
3743 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3748 * indent-tabs-mode: nil
3751 * vi: set shiftwidth=4 tabstop=8 expandtab:
3752 * :indentSize=4:tabSize=8:noTabs=true: