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
40 #include <epan/addr_resolv.h>
41 #include "file_wrappers.h"
44 #include "pcap-common.h"
45 #include "pcap-encap.h"
49 #define pcapng_debug0(str) g_warning(str)
50 #define pcapng_debug1(str,p1) g_warning(str,p1)
51 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
52 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
54 #define pcapng_debug0(str)
55 #define pcapng_debug1(str,p1)
56 #define pcapng_debug2(str,p1,p2)
57 #define pcapng_debug3(str,p1,p2,p3)
61 pcapng_read(wtap *wth, int *err, gchar **err_info,
64 pcapng_seek_read(wtap *wth, gint64 seek_off,
65 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
67 pcapng_close(wtap *wth);
70 /* pcapng: common block header for every block type */
71 typedef struct pcapng_block_header_s {
73 guint32 block_total_length;
74 /* x bytes block_body */
75 /* guint32 block_total_length */
76 } pcapng_block_header_t;
79 * Minimum block size = size of block header + size of block trailer.
81 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
84 * In order to keep from trying to allocate large chunks of memory,
85 * which could either fail or, even if it succeeds, chew up so much
86 * address space or memory+backing store as not to leave room for
87 * anything else, we impose an upper limit on the size of blocks
88 * we're willing to handle.
90 * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
91 * don't try saying that on Wikipedia :-) :-) :-)).
93 #define MAX_BLOCK_SIZE (16*1024*1024)
95 /* pcapng: section header block */
96 typedef struct pcapng_section_header_block_s {
97 /* pcapng_block_header_t */
99 guint16 version_major;
100 guint16 version_minor;
101 guint64 section_length; /* might be -1 for unknown */
102 /* ... Options ... */
103 } pcapng_section_header_block_t;
106 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
108 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
110 /* pcapng: interface description block */
111 typedef struct pcapng_interface_description_block_s {
115 /* ... Options ... */
116 } pcapng_interface_description_block_t;
119 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
121 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
123 /* pcapng: packet block (obsolete) */
124 typedef struct pcapng_packet_block_s {
125 guint16 interface_id;
127 guint32 timestamp_high;
128 guint32 timestamp_low;
129 guint32 captured_len;
131 /* ... Packet Data ... */
132 /* ... Padding ... */
133 /* ... Options ... */
134 } pcapng_packet_block_t;
137 * Minimum PB size = minimum block size + size of fixed length portion of PB.
139 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
141 /* pcapng: enhanced packet block */
142 typedef struct pcapng_enhanced_packet_block_s {
143 guint32 interface_id;
144 guint32 timestamp_high;
145 guint32 timestamp_low;
146 guint32 captured_len;
148 /* ... Packet Data ... */
149 /* ... Padding ... */
150 /* ... Options ... */
151 } pcapng_enhanced_packet_block_t;
154 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
156 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
158 /* pcapng: simple packet block */
159 typedef struct pcapng_simple_packet_block_s {
161 /* ... Packet Data ... */
162 /* ... Padding ... */
163 } pcapng_simple_packet_block_t;
166 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
168 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
170 /* pcapng: name resolution block */
171 typedef struct pcapng_name_resolution_block_s {
175 } pcapng_name_resolution_block_t;
178 * Minimum NRB size = minimum block size + size of smallest NRB record
179 * (there must at least be an "end of records" record).
181 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
183 /* pcapng: interface statistics block */
184 typedef struct pcapng_interface_statistics_block_s {
185 guint32 interface_id;
186 guint32 timestamp_high;
187 guint32 timestamp_low;
188 /* ... Options ... */
189 } pcapng_interface_statistics_block_t;
192 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
194 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
196 /* pcapng: common option header for every option type */
197 typedef struct pcapng_option_header_s {
199 guint16 option_length;
200 /* ... x bytes Option Body ... */
201 /* ... Padding ... */
202 } pcapng_option_header_t;
206 guint16 value_length;
210 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
211 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
212 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
213 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
214 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
215 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
216 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
220 #define OPT_COMMENT 1
221 #define OPT_SHB_HARDWARE 2
223 #define OPT_SHB_USERAPPL 4
224 #define OPT_EPB_FLAGS 2
225 #define OPT_EPB_HASH 3
226 #define OPT_EPB_DROPCOUNT 4
228 /* Capture section */
230 /* Moved to wtap.h */
231 typedef struct wtapng_section_s {
233 guint64 section_length;
235 gchar *opt_comment; /* NULL if not available */
236 gchar *shb_hardware; /* NULL if not available */
237 gchar *shb_os; /* NULL if not available */
238 gchar *shb_user_appl; /* NULL if not available */
243 /* Moved to wtap.h */
245 /* Interface Description
248 * 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}" / ...
249 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
250 * 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
251 * 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"
252 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
253 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
254 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
255 * 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
256 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
257 * 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"
258 * 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" / ...
259 * 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
260 * 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
263 typedef struct wtapng_if_descr_s {
269 gchar *opt_comment; /* NULL if not available */
270 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
271 gchar *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
272 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
273 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
274 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
275 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
276 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
277 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
278 * 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
280 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
281 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
282 * 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).
284 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. */
285 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. */
286 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
291 typedef struct wtapng_packet_s {
293 guint32 ts_high; /* seconds since 1.1.1970 */
294 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
295 guint32 cap_len; /* data length in the file */
296 guint32 packet_len; /* data length on the wire */
297 guint32 interface_id; /* identifier of the interface. */
298 guint16 drops_count; /* drops count, only valid for packet block */
299 /* 0xffff if information no available */
301 /* XXX - put the packet data / pseudo_header here as well? */
305 typedef struct wtapng_simple_packet_s {
307 guint32 cap_len; /* data length in the file */
308 guint32 packet_len; /* data length on the wire */
309 guint32 pseudo_header_len;
311 /* XXX - put the packet data / pseudo_header here as well? */
312 } wtapng_simple_packet_t;
314 /* Name Resolution */
315 typedef struct wtapng_name_res_s {
317 gchar *opt_comment; /* NULL if not available */
322 /* Interface Statistics moved to wtap.h*/
323 typedef struct wtapng_if_stats_s {
325 guint32 interface_id;
329 gchar *opt_comment; /* NULL if not available */
330 guint64 isb_starttime;
334 guint64 isb_filteraccept;
336 guint64 isb_usrdeliv;
340 typedef struct wtapng_block_s {
341 guint32 type; /* block_type as defined by pcapng */
343 wtapng_section_t section;
344 wtapng_if_descr_t if_descr;
345 wtapng_name_res_t name_res;
346 wtapng_if_stats_t if_stats;
350 * XXX - currently don't know how to handle these!
352 * For one thing, when we're reading a block, they must be
353 * writable, i.e. not const, so that we can read into them,
354 * but, when we're writing a block, they can be const, and,
355 * in fact, they sometimes point to const values.
357 struct wtap_pkthdr *packet_header;
358 Buffer *frame_buffer;
362 /* Interface data in private struct */
363 typedef struct interface_data_s {
366 guint64 time_units_per_second;
370 gboolean shb_read; /**< Set when first SHB read, second read will fail */
371 gboolean byte_swapped;
372 guint16 version_major;
373 guint16 version_minor;
374 GArray *interface_data;
375 guint number_of_interfaces;
377 wtap_new_ipv4_callback_t add_new_ipv4;
378 wtap_new_ipv6_callback_t add_new_ipv6;
382 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
383 char *content, guint len, guint to_read,
384 int *err, gchar **err_info)
388 guint64 file_offset64;
390 /* sanity check: don't run past the end of the block */
391 if (to_read < sizeof (*oh)) {
392 *err = WTAP_ERR_BAD_FILE;
393 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
397 /* read option header */
398 errno = WTAP_ERR_CANT_READ;
399 bytes_read = file_read(oh, sizeof (*oh), fh);
400 if (bytes_read != sizeof (*oh)) {
401 pcapng_debug0("pcapng_read_option: failed to read option");
402 *err = file_error(fh, err_info);
407 block_read = sizeof (*oh);
408 if (pn->byte_swapped) {
409 oh->option_code = GUINT16_SWAP_LE_BE(oh->option_code);
410 oh->option_length = GUINT16_SWAP_LE_BE(oh->option_length);
413 /* sanity check: don't run past the end of the block */
414 if (to_read < sizeof (*oh) + oh->option_length) {
415 *err = WTAP_ERR_BAD_FILE;
416 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
420 /* sanity check: option length */
421 if (oh->option_length > len) {
422 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
423 oh->option_length, len);
427 /* read option content */
428 errno = WTAP_ERR_CANT_READ;
429 bytes_read = file_read(content, oh->option_length, fh);
430 if (bytes_read != oh->option_length) {
431 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
432 *err = file_error(fh, err_info);
437 block_read += oh->option_length;
439 /* jump over potential padding bytes at end of option */
440 if ( (oh->option_length % 4) != 0) {
441 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
442 if (file_offset64 <= 0) {
447 block_read += 4 - (oh->option_length % 4);
455 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
456 pcapng_block_header_t *bh, pcapng_t *pn,
457 wtapng_block_t *wblock, int *err,
462 guint to_read, opt_cont_buf_len;
463 pcapng_section_header_block_t shb;
464 pcapng_option_header_t oh;
465 char *option_content = NULL; /* Allocate as large as the options block */
468 * Is this block long enough to be an SHB?
470 if (bh->block_total_length < MIN_SHB_SIZE) {
475 return 0; /* probably not a pcap-ng file */
476 *err = WTAP_ERR_BAD_FILE;
477 *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",
478 bh->block_total_length, MIN_SHB_SIZE);
482 /* read block content */
483 errno = WTAP_ERR_CANT_READ;
484 bytes_read = file_read(&shb, sizeof shb, fh);
485 if (bytes_read != sizeof shb) {
486 *err = file_error(fh, err_info);
490 * We're reading this as part of an open,
491 * and this block is too short to be
492 * an SHB, so the file is too short
493 * to be a pcap-ng file.
499 * Otherwise, just report this as an error.
501 *err = WTAP_ERR_SHORT_READ;
505 block_read = bytes_read;
507 /* is the magic number one we expect? */
510 /* this seems pcapng with correct byte order */
511 pn->byte_swapped = FALSE;
512 pn->version_major = shb.version_major;
513 pn->version_minor = shb.version_minor;
515 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
516 pn->version_major, pn->version_minor, bh->block_total_length);
519 /* this seems pcapng with swapped byte order */
520 pn->byte_swapped = TRUE;
521 pn->version_major = GUINT16_SWAP_LE_BE(shb.version_major);
522 pn->version_minor = GUINT16_SWAP_LE_BE(shb.version_minor);
524 /* tweak the block length to meet current swapping that we know now */
525 bh->block_total_length = GUINT32_SWAP_LE_BE(bh->block_total_length);
527 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
528 pn->version_major, pn->version_minor, bh->block_total_length);
531 /* Not a "pcapng" magic number we know about. */
533 /* Not a pcap-ng file. */
538 *err = WTAP_ERR_BAD_FILE;
539 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
543 /* OK, at this point we assume it's a pcap-ng file.
545 Don't try to allocate memory for a huge number of options, as
546 that might fail and, even if it succeeds, it might not leave
547 any address space or memory+backing store for anything else.
549 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
550 We check for this *after* checking the SHB for its byte
551 order magic number, so that non-pcap-ng files are less
552 likely to be treated as bad pcap-ng files. */
553 if (bh->block_total_length > MAX_BLOCK_SIZE) {
554 *err = WTAP_ERR_BAD_FILE;
555 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
556 bh->block_total_length, MAX_BLOCK_SIZE);
560 /* We currently only suport one SHB */
561 if (pn->shb_read == TRUE) {
562 *err = WTAP_ERR_UNSUPPORTED;
563 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported");
567 /* we currently only understand SHB V1.0 */
568 if (pn->version_major != 1 || pn->version_minor > 0) {
569 *err = WTAP_ERR_UNSUPPORTED;
570 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
571 pn->version_major, pn->version_minor);
576 /* 64bit section_length (currently unused) */
577 if (pn->byte_swapped) {
578 wblock->data.section.section_length = GUINT64_SWAP_LE_BE(shb.section_length);
580 wblock->data.section.section_length = shb.section_length;
583 /* Option defaults */
584 wblock->data.section.opt_comment = NULL;
585 wblock->data.section.shb_hardware = NULL;
586 wblock->data.section.shb_os = NULL;
587 wblock->data.section.shb_user_appl = NULL;
590 errno = WTAP_ERR_CANT_READ;
591 to_read = bh->block_total_length - MIN_SHB_SIZE;
593 /* Allocate enough memory to hold all options */
594 opt_cont_buf_len = to_read;
595 option_content = (char *)g_try_malloc(opt_cont_buf_len);
596 if (opt_cont_buf_len != 0 && option_content == NULL) {
597 *err = ENOMEM; /* we assume we're out of memory */
600 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
601 while (to_read != 0) {
603 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
604 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
605 if (bytes_read <= 0) {
606 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
609 block_read += bytes_read;
610 to_read -= bytes_read;
612 /* handle option content */
613 switch (oh.option_code) {
616 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
618 /* padding should be ok here, just get out of this */
622 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
623 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
624 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
626 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
629 case(OPT_SHB_HARDWARE):
630 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
631 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
632 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
634 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
638 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
639 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
640 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
642 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
645 case(OPT_SHB_USERAPPL):
646 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
647 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
648 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
650 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
654 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
655 oh.option_code, oh.option_length);
658 g_free(option_content);
664 /* "Interface Description Block" */
666 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
667 wtapng_block_t *wblock, int *err, gchar **err_info)
669 guint64 time_units_per_second = 1000000; /* default */
672 guint to_read, opt_cont_buf_len;
673 pcapng_interface_description_block_t idb;
674 pcapng_option_header_t oh;
675 char *option_content = NULL; /* Allocate as large as the options block */
678 * Is this block long enough to be an IDB?
680 if (bh->block_total_length < MIN_IDB_SIZE) {
684 *err = WTAP_ERR_BAD_FILE;
685 *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",
686 bh->block_total_length, MIN_IDB_SIZE);
690 /* Don't try to allocate memory for a huge number of options, as
691 that might fail and, even if it succeeds, it might not leave
692 any address space or memory+backing store for anything else.
694 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
695 We check for this *after* checking the SHB for its byte
696 order magic number, so that non-pcap-ng files are less
697 likely to be treated as bad pcap-ng files. */
698 if (bh->block_total_length > MAX_BLOCK_SIZE) {
699 *err = WTAP_ERR_BAD_FILE;
700 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
701 bh->block_total_length, MAX_BLOCK_SIZE);
705 /* read block content */
706 errno = WTAP_ERR_CANT_READ;
707 bytes_read = file_read(&idb, sizeof idb, fh);
708 if (bytes_read != sizeof idb) {
709 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
710 *err = file_error(fh, err_info);
715 block_read = bytes_read;
717 /* mandatory values */
718 if (pn->byte_swapped) {
719 wblock->data.if_descr.link_type = GUINT16_SWAP_LE_BE(idb.linktype);
720 wblock->data.if_descr.snap_len = GUINT32_SWAP_LE_BE(idb.snaplen);
722 wblock->data.if_descr.link_type = idb.linktype;
723 wblock->data.if_descr.snap_len = idb.snaplen;
726 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
727 wblock->data.if_descr.time_units_per_second = time_units_per_second;
729 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
730 wblock->data.if_descr.link_type,
731 wtap_encap_string(wblock->data.if_descr.wtap_encap),
732 wblock->data.if_descr.snap_len);
734 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
735 /* This is unrealistic, but text2pcap currently uses 102400.
736 * We do not use this value, maybe we should check the
737 * snap_len of the packets against it. For now, only warn.
739 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
740 wblock->data.if_descr.snap_len);
741 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
744 /* Option defaults */
745 wblock->data.if_descr.opt_comment = NULL;
746 wblock->data.if_descr.if_name = NULL;
747 wblock->data.if_descr.if_description = NULL;
748 /* XXX: if_IPv4addr */
749 /* XXX: if_IPv6addr */
750 /* XXX: if_MACaddr */
751 /* XXX: if_EUIaddr */
752 wblock->data.if_descr.if_speed = 0; /* "unknown" */
753 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
754 wblock->data.if_descr.if_filter_str = NULL;
755 wblock->data.if_descr.bpf_filter_len = 0;
756 wblock->data.if_descr.if_filter_bpf_bytes = NULL;
757 wblock->data.if_descr.if_os = NULL;
758 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
759 /* XXX: guint64 if_tsoffset; */
763 errno = WTAP_ERR_CANT_READ;
764 to_read = bh->block_total_length - MIN_IDB_SIZE;
766 /* Allocate enough memory to hold all options */
767 opt_cont_buf_len = to_read;
768 option_content = (char *)g_try_malloc(opt_cont_buf_len);
769 if (opt_cont_buf_len != 0 && option_content == NULL) {
770 *err = ENOMEM; /* we assume we're out of memory */
774 while (to_read != 0) {
776 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
777 if (bytes_read <= 0) {
778 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
781 block_read += bytes_read;
782 to_read -= bytes_read;
784 /* handle option content */
785 switch (oh.option_code) {
786 case(0): /* opt_endofopt */
788 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
790 /* padding should be ok here, just get out of this */
793 case(1): /* opt_comment */
794 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
795 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
796 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
798 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
801 case(2): /* if_name */
802 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
803 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
804 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
806 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
809 case(3): /* if_description */
810 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
811 wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
812 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
814 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
818 * 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
819 * 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"
820 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
821 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
823 case(8): /* if_speed */
824 if (oh.option_length == 8) {
825 /* Don't cast a char[] into a guint64--the
826 * char[] may not be aligned correctly.
828 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
829 if (pn->byte_swapped)
830 wblock->data.if_descr.if_speed = GUINT64_SWAP_LE_BE(wblock->data.if_descr.if_speed);
831 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
833 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
836 case(9): /* if_tsresol */
837 if (oh.option_length == 1) {
840 guint8 i, exponent, if_tsresol;
842 if_tsresol = option_content[0];
843 if (if_tsresol & 0x80) {
848 exponent = (guint8)(if_tsresol & 0x7f);
849 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
851 for (i = 0; i < exponent; i++) {
854 time_units_per_second = result;
856 time_units_per_second = G_MAXUINT64;
858 if (time_units_per_second > (((guint64)1) << 32)) {
859 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
861 wblock->data.if_descr.time_units_per_second = time_units_per_second;
862 wblock->data.if_descr.if_tsresol = if_tsresol;
863 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);
865 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
869 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
871 case(11): /* if_filter */
872 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
873 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
876 if (option_content[0] == 0) {
877 wblock->data.if_descr.if_filter_str = g_strndup(option_content+1, oh.option_length-1);
878 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);
879 } else if (option_content[0] == 1) {
880 wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
881 wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
882 memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, option_content+1, oh.option_length-1);
885 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
888 case(12): /* if_os */
890 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
891 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
892 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
894 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
895 wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
896 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
898 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
901 case(13): /* if_fcslen */
902 if (oh.option_length == 1) {
903 wblock->data.if_descr.if_fcslen = option_content[0];
904 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
905 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
906 /* XXX - add sanity check */
908 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
912 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
913 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
914 * The time zone of the offset can be specified with the option if_tzone.
915 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
918 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
919 oh.option_code, oh.option_length);
923 g_free(option_content);
925 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
926 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
928 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
929 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
938 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)
942 guint to_read, opt_cont_buf_len;
943 guint64 file_offset64;
944 pcapng_enhanced_packet_block_t epb;
945 pcapng_packet_block_t pb;
946 wtapng_packet_t packet;
947 guint32 block_total_length;
949 interface_data_t int_data;
951 pcapng_option_header_t oh;
952 int pseudo_header_len;
953 char *option_content = NULL; /* Allocate as large as the options block */
956 /* Don't try to allocate memory for a huge number of options, as
957 that might fail and, even if it succeeds, it might not leave
958 any address space or memory+backing store for anything else.
960 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
961 We check for this *after* checking the SHB for its byte
962 order magic number, so that non-pcap-ng files are less
963 likely to be treated as bad pcap-ng files. */
964 if (bh->block_total_length > MAX_BLOCK_SIZE) {
965 *err = WTAP_ERR_BAD_FILE;
966 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
967 bh->block_total_length, MAX_BLOCK_SIZE);
971 /* "(Enhanced) Packet Block" read fixed part */
972 errno = WTAP_ERR_CANT_READ;
975 * Is this block long enough to be an EPB?
977 if (bh->block_total_length < MIN_EPB_SIZE) {
981 *err = WTAP_ERR_BAD_FILE;
982 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
983 bh->block_total_length, MIN_EPB_SIZE);
986 bytes_read = file_read(&epb, sizeof epb, fh);
987 if (bytes_read != sizeof epb) {
988 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
989 *err = file_error(fh, err_info);
992 block_read = bytes_read;
994 if (pn->byte_swapped) {
995 packet.interface_id = GUINT32_SWAP_LE_BE(epb.interface_id);
996 packet.drops_count = -1; /* invalid */
997 packet.ts_high = GUINT32_SWAP_LE_BE(epb.timestamp_high);
998 packet.ts_low = GUINT32_SWAP_LE_BE(epb.timestamp_low);
999 packet.cap_len = GUINT32_SWAP_LE_BE(epb.captured_len);
1000 packet.packet_len = GUINT32_SWAP_LE_BE(epb.packet_len);
1002 packet.interface_id = epb.interface_id;
1003 packet.drops_count = -1; /* invalid */
1004 packet.ts_high = epb.timestamp_high;
1005 packet.ts_low = epb.timestamp_low;
1006 packet.cap_len = epb.captured_len;
1007 packet.packet_len = epb.packet_len;
1009 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1010 packet.interface_id, packet.cap_len, packet.packet_len);
1013 * Is this block long enough to be a PB?
1015 if (bh->block_total_length < MIN_PB_SIZE) {
1019 *err = WTAP_ERR_BAD_FILE;
1020 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1021 bh->block_total_length, MIN_PB_SIZE);
1024 bytes_read = file_read(&pb, sizeof pb, fh);
1025 if (bytes_read != sizeof pb) {
1026 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1027 *err = file_error(fh, err_info);
1030 block_read = bytes_read;
1032 if (pn->byte_swapped) {
1033 packet.interface_id = GUINT16_SWAP_LE_BE(pb.interface_id);
1034 packet.drops_count = GUINT16_SWAP_LE_BE(pb.drops_count);
1035 packet.ts_high = GUINT32_SWAP_LE_BE(pb.timestamp_high);
1036 packet.ts_low = GUINT32_SWAP_LE_BE(pb.timestamp_low);
1037 packet.cap_len = GUINT32_SWAP_LE_BE(pb.captured_len);
1038 packet.packet_len = GUINT32_SWAP_LE_BE(pb.packet_len);
1040 packet.interface_id = pb.interface_id;
1041 packet.drops_count = pb.drops_count;
1042 packet.ts_high = pb.timestamp_high;
1043 packet.ts_low = pb.timestamp_low;
1044 packet.cap_len = pb.captured_len;
1045 packet.packet_len = pb.packet_len;
1047 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1048 packet.interface_id, packet.cap_len, packet.packet_len);
1052 * How much padding is there at the end of the packet data?
1054 if ((packet.cap_len % 4) != 0)
1055 padding = 4 - (packet.cap_len % 4);
1059 /* add padding bytes to "block total length" */
1060 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1061 if (bh->block_total_length % 4) {
1062 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1064 block_total_length = bh->block_total_length;
1066 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1069 * Is this block long enough to hold the packet data?
1072 if (block_total_length <
1073 MIN_EPB_SIZE + packet.cap_len + padding) {
1077 *err = WTAP_ERR_BAD_FILE;
1078 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1079 block_total_length, packet.cap_len);
1083 if (block_total_length <
1084 MIN_PB_SIZE + packet.cap_len + padding) {
1088 *err = WTAP_ERR_BAD_FILE;
1089 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1090 block_total_length, packet.cap_len);
1095 if (packet.cap_len > packet.packet_len) {
1096 *err = WTAP_ERR_BAD_FILE;
1097 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u",
1098 packet.cap_len, packet.packet_len);
1101 if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1102 *err = WTAP_ERR_BAD_FILE;
1103 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1104 packet.cap_len, WTAP_MAX_PACKET_SIZE);
1107 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1110 packet.interface_id);
1112 if (packet.interface_id >= pn->number_of_interfaces) {
1113 *err = WTAP_ERR_BAD_FILE;
1114 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u",
1115 packet.interface_id, pn->number_of_interfaces);
1118 int_data = g_array_index(pn->interface_data, interface_data_t,
1119 packet.interface_id);
1121 wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1123 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1124 int_data.wtap_encap,
1125 wtap_encap_string(int_data.wtap_encap),
1126 pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1127 wblock->packet_header->interface_id = packet.interface_id;
1128 wblock->packet_header->pkt_encap = int_data.wtap_encap;
1130 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1131 pseudo_header_len = pcap_process_pseudo_header(fh,
1132 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1133 int_data.wtap_encap,
1136 wblock->packet_header,
1139 if (pseudo_header_len < 0) {
1142 block_read += pseudo_header_len;
1143 if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1144 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1147 wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
1148 wblock->packet_header->len = packet.packet_len - pseudo_header_len;
1150 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1151 ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
1152 wblock->packet_header->ts.secs = (time_t)(ts / int_data.time_units_per_second);
1153 wblock->packet_header->ts.nsecs = (int)(((ts % int_data.time_units_per_second) * 1000000000) / int_data.time_units_per_second);
1155 /* "(Enhanced) Packet Block" read capture data */
1156 errno = WTAP_ERR_CANT_READ;
1157 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1158 packet.cap_len - pseudo_header_len, err, err_info))
1160 block_read += packet.cap_len - pseudo_header_len;
1162 /* jump over potential padding bytes at end of the packet data */
1164 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1165 if (file_offset64 <= 0) {
1170 block_read += padding;
1173 /* Option defaults */
1174 wblock->packet_header->opt_comment = NULL;
1175 wblock->packet_header->drop_count = -1;
1176 wblock->packet_header->pack_flags = 0;
1178 /* FCS length default */
1179 fcslen = pn->if_fcslen;
1187 errno = WTAP_ERR_CANT_READ;
1188 to_read = block_total_length -
1189 (int)sizeof(pcapng_block_header_t) -
1190 block_read - /* fixed and variable part, including padding */
1191 (int)sizeof(bh->block_total_length);
1193 /* Allocate enough memory to hold all options */
1194 opt_cont_buf_len = to_read;
1195 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1196 if (opt_cont_buf_len != 0 && option_content == NULL) {
1197 *err = ENOMEM; /* we assume we're out of memory */
1201 while (to_read != 0) {
1203 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1204 if (bytes_read <= 0) {
1205 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1208 block_read += bytes_read;
1209 to_read -= bytes_read;
1211 /* handle option content */
1212 switch (oh.option_code) {
1215 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1217 /* padding should be ok here, just get out of this */
1221 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1222 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1223 wblock->packet_header->opt_comment = g_strndup(option_content, oh.option_length);
1224 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->packet_header->opt_comment);
1226 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1229 case(OPT_EPB_FLAGS):
1230 if (oh.option_length == 4) {
1231 /* Don't cast a char[] into a guint32--the
1232 * char[] may not be aligned correctly.
1234 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1235 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1236 if (pn->byte_swapped)
1237 wblock->packet_header->pack_flags = GUINT32_SWAP_LE_BE(wblock->packet_header->pack_flags);
1238 if (wblock->packet_header->pack_flags & 0x000001E0) {
1239 /* The FCS length is present */
1240 fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1242 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1244 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1248 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1249 oh.option_code, oh.option_length);
1251 case(OPT_EPB_DROPCOUNT):
1252 if (oh.option_length == 8) {
1253 /* Don't cast a char[] into a guint32--the
1254 * char[] may not be aligned correctly.
1256 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1257 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1258 if (pn->byte_swapped)
1259 wblock->packet_header->drop_count = GUINT64_SWAP_LE_BE(wblock->packet_header->drop_count);
1261 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1263 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1267 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1268 oh.option_code, oh.option_length);
1272 g_free(option_content);
1274 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, int_data.wtap_encap,
1275 (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1276 buffer_start_ptr(wblock->frame_buffer),
1277 (int) (packet.cap_len - pseudo_header_len),
1278 pn->byte_swapped, fcslen);
1284 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)
1288 guint64 file_offset64;
1289 interface_data_t int_data;
1290 pcapng_simple_packet_block_t spb;
1291 wtapng_simple_packet_t simple_packet;
1292 guint32 block_total_length;
1294 int pseudo_header_len;
1297 * Is this block long enough to be an SPB?
1299 if (bh->block_total_length < MIN_SPB_SIZE) {
1303 *err = WTAP_ERR_BAD_FILE;
1304 *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",
1305 bh->block_total_length, MIN_SPB_SIZE);
1309 /* Don't try to allocate memory for a huge number of options, as
1310 that might fail and, even if it succeeds, it might not leave
1311 any address space or memory+backing store for anything else.
1313 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1314 We check for this *after* checking the SHB for its byte
1315 order magic number, so that non-pcap-ng files are less
1316 likely to be treated as bad pcap-ng files. */
1317 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1318 *err = WTAP_ERR_BAD_FILE;
1319 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1320 bh->block_total_length, MAX_BLOCK_SIZE);
1324 /* "Simple Packet Block" read fixed part */
1325 errno = WTAP_ERR_CANT_READ;
1326 bytes_read = file_read(&spb, sizeof spb, fh);
1327 if (bytes_read != sizeof spb) {
1328 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1329 *err = file_error(fh, err_info);
1332 block_read = bytes_read;
1334 if (0 >= pn->number_of_interfaces) {
1335 *err = WTAP_ERR_BAD_FILE;
1336 *err_info = g_strdup_printf("pcapng: SPB appeared before any IDBs");
1339 int_data = g_array_index(pn->interface_data, interface_data_t, 0);
1341 if (pn->byte_swapped) {
1342 simple_packet.packet_len = GUINT32_SWAP_LE_BE(spb.packet_len);
1344 simple_packet.packet_len = spb.packet_len;
1348 * The captured length is not a field in the SPB; it can be
1349 * calculated as the minimum of the snapshot length from the
1350 * IDB and the packet length, as per the pcap-ng spec.
1352 simple_packet.cap_len = simple_packet.packet_len;
1353 if (simple_packet.cap_len > int_data.snap_len)
1354 simple_packet.cap_len = int_data.snap_len;
1357 * How much padding is there at the end of the packet data?
1359 if ((simple_packet.cap_len % 4) != 0)
1360 padding = 4 - (simple_packet.cap_len % 4);
1364 /* add padding bytes to "block total length" */
1365 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1366 if (bh->block_total_length % 4) {
1367 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1369 block_total_length = bh->block_total_length;
1371 pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length);
1374 * Is this block long enough to hold the packet data?
1376 if (block_total_length < MIN_SPB_SIZE + simple_packet.cap_len + padding) {
1378 * No. That means that the problem is with the packet
1379 * length; the snapshot length can be bigger than the amount
1380 * of packet data in the block, as it's a *maximum* length,
1381 * not a *minimum* length.
1383 *err = WTAP_ERR_BAD_FILE;
1384 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1385 block_total_length, simple_packet.packet_len);
1389 if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1390 *err = WTAP_ERR_BAD_FILE;
1391 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u",
1392 simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1395 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1396 simple_packet.packet_len);
1398 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1399 pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1401 /* No time stamp in a simple packet block; no options, either */
1402 wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1403 wblock->packet_header->interface_id = 0;
1404 wblock->packet_header->pkt_encap = int_data.wtap_encap;
1405 wblock->packet_header->ts.secs = 0;
1406 wblock->packet_header->ts.nsecs = 0;
1407 wblock->packet_header->interface_id = 0;
1408 wblock->packet_header->opt_comment = NULL;
1409 wblock->packet_header->drop_count = 0;
1410 wblock->packet_header->pack_flags = 0;
1412 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1413 pseudo_header_len = pcap_process_pseudo_header(fh,
1414 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1415 int_data.wtap_encap,
1416 simple_packet.cap_len,
1418 wblock->packet_header,
1421 if (pseudo_header_len < 0) {
1424 wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
1425 wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
1426 block_read += pseudo_header_len;
1427 if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1428 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1432 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1434 /* "Simple Packet Block" read capture data */
1435 errno = WTAP_ERR_CANT_READ;
1436 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1437 simple_packet.cap_len, err, err_info))
1439 block_read += simple_packet.cap_len;
1441 /* jump over potential padding bytes at end of the packet data */
1442 if ((simple_packet.cap_len % 4) != 0) {
1443 file_offset64 = file_seek(fh, 4 - (simple_packet.cap_len % 4), SEEK_CUR, err);
1444 if (file_offset64 <= 0) {
1449 block_read += 4 - (simple_packet.cap_len % 4);
1452 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, int_data.wtap_encap,
1453 (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1454 buffer_start_ptr(wblock->frame_buffer),
1455 (int) simple_packet.cap_len,
1456 pn->byte_swapped, pn->if_fcslen);
1460 #define NRES_ENDOFRECORD 0
1461 #define NRES_IP4RECORD 1
1462 #define NRES_IP6RECORD 2
1463 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1464 /* IPv6 + MAXNAMELEN */
1465 #define INITIAL_NRB_REC_SIZE (16 + 64)
1468 * Find the end of the NUL-terminated name the beginning of which is pointed
1469 * to by p; record_len is the number of bytes remaining in the record.
1471 * Return the length of the name, including the terminating NUL.
1473 * If we don't find a terminating NUL, return -1 and set *err and
1474 * *err_info appropriately.
1477 name_resolution_block_find_name_end(const char *p, guint record_len, int *err,
1484 if (record_len == 0) {
1486 * We ran out of bytes in the record without
1489 *err = WTAP_ERR_BAD_FILE;
1490 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1494 break; /* that's the terminating NUL */
1497 namelen++; /* count this byte */
1500 /* Include the NUL in the name length. */
1505 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)
1510 guint64 file_offset64;
1511 pcapng_name_resolution_block_t nrb;
1519 * Is this block long enough to be an NRB?
1521 if (bh->block_total_length < MIN_NRB_SIZE) {
1525 *err = WTAP_ERR_BAD_FILE;
1526 *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",
1527 bh->block_total_length, MIN_NRB_SIZE);
1531 /* Don't try to allocate memory for a huge number of options, as
1532 that might fail and, even if it succeeds, it might not leave
1533 any address space or memory+backing store for anything else.
1535 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1536 We check for this *after* checking the SHB for its byte
1537 order magic number, so that non-pcap-ng files are less
1538 likely to be treated as bad pcap-ng files. */
1539 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1540 *err = WTAP_ERR_BAD_FILE;
1541 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1542 bh->block_total_length, MAX_BLOCK_SIZE);
1546 errno = WTAP_ERR_CANT_READ;
1547 to_read = bh->block_total_length - 8 - 4; /* We have read the header adn should not read the final block_total_length */
1549 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1552 * Start out with a buffer big enough for an IPv6 address and one
1553 * 64-byte name; we'll make the buffer bigger if necessary.
1555 buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1556 while (block_read < to_read) {
1558 * There must be at least one record's worth of data
1561 if ((size_t)(to_read - block_read) < sizeof nrb) {
1562 buffer_free(&nrb_rec);
1563 *err = WTAP_ERR_BAD_FILE;
1564 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1565 to_read - block_read,
1569 bytes_read = file_read(&nrb, sizeof nrb, fh);
1570 if (bytes_read != sizeof nrb) {
1571 buffer_free(&nrb_rec);
1572 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1573 *err = file_error(fh, err_info);
1576 block_read += bytes_read;
1578 if (pn->byte_swapped) {
1579 nrb.record_type = GUINT16_SWAP_LE_BE(nrb.record_type);
1580 nrb.record_len = GUINT16_SWAP_LE_BE(nrb.record_len);
1583 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1584 buffer_free(&nrb_rec);
1585 *err = WTAP_ERR_BAD_FILE;
1586 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1587 to_read - block_read,
1588 nrb.record_len + PADDING4(nrb.record_len));
1591 switch (nrb.record_type) {
1592 case NRES_ENDOFRECORD:
1593 /* There shouldn't be any more data */
1596 case NRES_IP4RECORD:
1598 * The smallest possible record must have
1599 * a 4-byte IPv4 address, hence a minimum
1602 * (The pcap-NG spec really indicates
1603 * that it must be at least 5 bytes,
1604 * as there must be at least one name,
1605 * and it really must be at least 6
1606 * bytes, as the name mustn't be null,
1607 * but there's no need to fail if there
1608 * aren't any names at all, and we
1609 * should report a null name as such.)
1611 if (nrb.record_len < 4) {
1612 buffer_free(&nrb_rec);
1613 *err = WTAP_ERR_BAD_FILE;
1614 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1618 buffer_assure_space(&nrb_rec, nrb.record_len);
1619 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1620 nrb.record_len, fh);
1621 if (bytes_read != nrb.record_len) {
1622 buffer_free(&nrb_rec);
1623 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1624 *err = file_error(fh, err_info);
1627 block_read += bytes_read;
1629 if (pn->add_new_ipv4) {
1631 * Scan through all the names in
1632 * the record and add them.
1635 buffer_start_ptr(&nrb_rec), 4);
1636 if (pn->byte_swapped)
1637 v4_addr = GUINT32_SWAP_LE_BE(v4_addr);
1638 for (namep = (char *)buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1640 namep += namelen, record_len -= namelen) {
1642 * Scan forward for a null
1645 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1646 if (namelen == -1) {
1647 buffer_free(&nrb_rec);
1648 return -1; /* fail */
1650 pn->add_new_ipv4(v4_addr, namep);
1654 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1655 if (file_offset64 <= 0) {
1656 buffer_free(&nrb_rec);
1661 block_read += PADDING4(nrb.record_len);
1663 case NRES_IP6RECORD:
1665 * The smallest possible record must have
1666 * a 16-byte IPv6 address, hence a minimum
1669 * (The pcap-NG spec really indicates
1670 * that it must be at least 17 bytes,
1671 * as there must be at least one name,
1672 * and it really must be at least 18
1673 * bytes, as the name mustn't be null,
1674 * but there's no need to fail if there
1675 * aren't any names at all, and we
1676 * should report a null name as such.)
1678 if (nrb.record_len < 16) {
1679 buffer_free(&nrb_rec);
1680 *err = WTAP_ERR_BAD_FILE;
1681 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1685 if (to_read < nrb.record_len) {
1686 buffer_free(&nrb_rec);
1687 pcapng_debug0("pcapng_read_name_resolution_block: insufficient data for IPv6 record");
1690 buffer_assure_space(&nrb_rec, nrb.record_len);
1691 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1692 nrb.record_len, fh);
1693 if (bytes_read != nrb.record_len) {
1694 buffer_free(&nrb_rec);
1695 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1696 *err = file_error(fh, err_info);
1699 block_read += bytes_read;
1701 if (pn->add_new_ipv6) {
1702 for (namep = (char *)buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1704 namep += namelen, record_len -= namelen) {
1706 * Scan forward for a null
1709 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1710 if (namelen == -1) {
1711 buffer_free(&nrb_rec);
1712 return -1; /* fail */
1714 pn->add_new_ipv6(buffer_start_ptr(&nrb_rec),
1719 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1720 if (file_offset64 <= 0) {
1721 buffer_free(&nrb_rec);
1726 block_read += PADDING4(nrb.record_len);
1729 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1730 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1731 if (file_offset64 <= 0) {
1732 buffer_free(&nrb_rec);
1737 block_read += nrb.record_len + PADDING4(nrb.record_len);
1742 buffer_free(&nrb_rec);
1747 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)
1751 guint to_read, opt_cont_buf_len;
1752 pcapng_interface_statistics_block_t isb;
1753 pcapng_option_header_t oh;
1754 char *option_content = NULL; /* Allocate as large as the options block */
1757 * Is this block long enough to be an ISB?
1759 if (bh->block_total_length < MIN_ISB_SIZE) {
1763 *err = WTAP_ERR_BAD_FILE;
1764 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1765 bh->block_total_length, MIN_ISB_SIZE);
1769 /* Don't try to allocate memory for a huge number of options, as
1770 that might fail and, even if it succeeds, it might not leave
1771 any address space or memory+backing store for anything else.
1773 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1774 We check for this *after* checking the SHB for its byte
1775 order magic number, so that non-pcap-ng files are less
1776 likely to be treated as bad pcap-ng files. */
1777 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1778 *err = WTAP_ERR_BAD_FILE;
1779 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1780 bh->block_total_length, MAX_BLOCK_SIZE);
1784 /* "Interface Statistics Block" read fixed part */
1785 errno = WTAP_ERR_CANT_READ;
1786 bytes_read = file_read(&isb, sizeof isb, fh);
1787 if (bytes_read != sizeof isb) {
1788 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1789 *err = file_error(fh, err_info);
1792 block_read = bytes_read;
1794 if (pn->byte_swapped) {
1795 wblock->data.if_stats.interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
1796 wblock->data.if_stats.ts_high = GUINT32_SWAP_LE_BE(isb.timestamp_high);
1797 wblock->data.if_stats.ts_low = GUINT32_SWAP_LE_BE(isb.timestamp_low);
1799 wblock->data.if_stats.interface_id = isb.interface_id;
1800 wblock->data.if_stats.ts_high = isb.timestamp_high;
1801 wblock->data.if_stats.ts_low = isb.timestamp_low;
1803 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1805 /* Option defaults */
1806 wblock->data.if_stats.opt_comment = NULL;
1807 wblock->data.if_stats.isb_ifrecv = -1;
1808 wblock->data.if_stats.isb_ifdrop = -1;
1809 wblock->data.if_stats.isb_filteraccept = -1;
1810 wblock->data.if_stats.isb_osdrop = -1;
1811 wblock->data.if_stats.isb_usrdeliv = -1;
1814 errno = WTAP_ERR_CANT_READ;
1815 to_read = bh->block_total_length -
1816 (MIN_BLOCK_SIZE + block_read); /* fixed and variable part, including padding */
1818 /* Allocate enough memory to hold all options */
1819 opt_cont_buf_len = to_read;
1820 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1821 if (opt_cont_buf_len != 0 && option_content == NULL) {
1822 *err = ENOMEM; /* we assume we're out of memory */
1826 while (to_read != 0) {
1828 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1829 if (bytes_read <= 0) {
1830 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1833 block_read += bytes_read;
1834 to_read -= bytes_read;
1836 /* handle option content */
1837 switch (oh.option_code) {
1838 case(0): /* opt_endofopt */
1840 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1842 /* padding should be ok here, just get out of this */
1845 case(1): /* opt_comment */
1846 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1847 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1848 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1850 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1853 case(2): /* isb_starttime */
1854 if (oh.option_length == 8) {
1857 /* Don't cast a char[] into a guint32--the
1858 * char[] may not be aligned correctly.
1860 memcpy(&high, option_content, sizeof(guint32));
1861 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1862 if (pn->byte_swapped) {
1863 high = GUINT32_SWAP_LE_BE(high);
1864 low = GUINT32_SWAP_LE_BE(low);
1866 wblock->data.if_stats.isb_starttime = (guint64)high;
1867 wblock->data.if_stats.isb_starttime <<= 32;
1868 wblock->data.if_stats.isb_starttime += (guint64)low;
1869 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1871 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1874 case(3): /* isb_endtime */
1875 if (oh.option_length == 8) {
1878 /* Don't cast a char[] into a guint32--the
1879 * char[] may not be aligned correctly.
1881 memcpy(&high, option_content, sizeof(guint32));
1882 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1883 if (pn->byte_swapped) {
1884 high = GUINT32_SWAP_LE_BE(high);
1885 low = GUINT32_SWAP_LE_BE(low);
1887 wblock->data.if_stats.isb_endtime = (guint64)high;
1888 wblock->data.if_stats.isb_endtime <<= 32;
1889 wblock->data.if_stats.isb_endtime += (guint64)low;
1890 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1892 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1895 case(4): /* isb_ifrecv */
1896 if (oh.option_length == 8) {
1897 /* Don't cast a char[] into a guint32--the
1898 * char[] may not be aligned correctly.
1900 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1901 if (pn->byte_swapped)
1902 wblock->data.if_stats.isb_ifrecv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifrecv);
1903 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1905 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1908 case(5): /* isb_ifdrop */
1909 if (oh.option_length == 8) {
1910 /* Don't cast a char[] into a guint32--the
1911 * char[] may not be aligned correctly.
1913 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1914 if (pn->byte_swapped)
1915 wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_ifdrop);
1916 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1918 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1921 case(6): /* isb_filteraccept 6 */
1922 if (oh.option_length == 8) {
1923 /* Don't cast a char[] into a guint32--the
1924 * char[] may not be aligned correctly.
1926 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1927 if (pn->byte_swapped)
1928 wblock->data.if_stats.isb_ifdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_filteraccept);
1929 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1931 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1934 case(7): /* isb_osdrop 7 */
1935 if (oh.option_length == 8) {
1936 /* Don't cast a char[] into a guint32--the
1937 * char[] may not be aligned correctly.
1939 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1940 if (pn->byte_swapped)
1941 wblock->data.if_stats.isb_osdrop = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
1942 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1944 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1947 case(8): /* isb_usrdeliv 8 */
1948 if (oh.option_length == 8) {
1949 /* Don't cast a char[] into a guint32--the
1950 * char[] may not be aligned correctly.
1952 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1953 if (pn->byte_swapped)
1954 wblock->data.if_stats.isb_usrdeliv = GUINT64_SWAP_LE_BE(wblock->data.if_stats.isb_osdrop);
1955 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1957 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1961 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1962 oh.option_code, oh.option_length);
1966 g_free(option_content);
1973 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)
1976 guint64 file_offset64;
1977 guint32 block_total_length;
1979 if (bh->block_total_length < MIN_BLOCK_SIZE) {
1980 *err = WTAP_ERR_BAD_FILE;
1981 *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",
1982 bh->block_total_length, MIN_BLOCK_SIZE);
1986 /* add padding bytes to "block total length" */
1987 /* (the "block total length" of some example files don't contain any padding bytes!) */
1988 if (bh->block_total_length % 4) {
1989 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1991 block_total_length = bh->block_total_length;
1994 block_read = block_total_length - MIN_BLOCK_SIZE;
1996 /* jump over this unknown block */
1997 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1998 if (file_offset64 <= 0) {
2009 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2013 pcapng_block_header_t bh;
2014 guint32 block_total_length;
2017 /* Try to read the (next) block header */
2018 errno = WTAP_ERR_CANT_READ;
2019 bytes_read = file_read(&bh, sizeof bh, fh);
2020 if (bytes_read != sizeof bh) {
2021 *err = file_error(fh, err_info);
2022 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2028 block_read = bytes_read;
2029 if (pn->byte_swapped) {
2030 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2031 bh.block_total_length = GUINT32_SWAP_LE_BE(bh.block_total_length);
2034 wblock->type = bh.block_type;
2036 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2040 * This is being read in by pcapng_open(), so this block
2041 * must be an SHB. If it's not, this is not a pcap-ng
2044 * XXX - check for various forms of Windows <-> UN*X
2045 * mangling, and suggest that the file might be a
2046 * pcap-ng file that was damaged in transit?
2048 if (bh.block_type != BLOCK_TYPE_SHB)
2049 return 0; /* not a pcap-ng file */
2052 switch (bh.block_type) {
2053 case(BLOCK_TYPE_SHB):
2054 bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
2056 case(BLOCK_TYPE_IDB):
2057 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
2059 case(BLOCK_TYPE_PB):
2060 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
2062 case(BLOCK_TYPE_SPB):
2063 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
2065 case(BLOCK_TYPE_EPB):
2066 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
2068 case(BLOCK_TYPE_NRB):
2069 bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
2071 case(BLOCK_TYPE_ISB):
2072 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
2075 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2076 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
2079 if (bytes_read <= 0) {
2082 block_read += bytes_read;
2084 /* sanity check: first and second block lengths must match */
2085 errno = WTAP_ERR_CANT_READ;
2086 bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
2087 if (bytes_read != sizeof block_total_length) {
2088 pcapng_debug0("pcapng_read_block: couldn't read second block length");
2089 *err = file_error(fh, err_info);
2091 *err = WTAP_ERR_SHORT_READ;
2094 block_read += bytes_read;
2096 if (pn->byte_swapped)
2097 block_total_length = GUINT32_SWAP_LE_BE(block_total_length);
2099 if (!(block_total_length == bh.block_total_length)) {
2100 *err = WTAP_ERR_BAD_FILE;
2101 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
2102 bh.block_total_length, block_total_length);
2109 /* Process an IDB that we've just read. */
2111 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2113 wtapng_if_descr_t int_data;
2114 interface_data_t interface_data;
2116 int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2117 int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2118 int_data.link_type = wblock->data.if_descr.link_type;
2119 int_data.snap_len = wblock->data.if_descr.snap_len;
2121 int_data.opt_comment = wblock->data.if_descr.opt_comment;
2122 int_data.if_name = wblock->data.if_descr.if_name;
2123 int_data.if_description = wblock->data.if_descr.if_description;
2124 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2125 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2126 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2127 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2128 int_data.if_speed = wblock->data.if_descr.if_speed;
2129 int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2130 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2131 int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2132 int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2133 int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2134 int_data.if_os = wblock->data.if_descr.if_os;
2135 int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2136 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2137 /* Interface statistics */
2138 int_data.num_stat_entries = 0;
2139 int_data.interface_statistics = NULL;
2141 g_array_append_val(wth->interface_data, int_data);
2142 wth->number_of_interfaces++;
2144 interface_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2145 interface_data.snap_len = wblock->data.if_descr.snap_len;
2146 interface_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2148 g_array_append_val(pcapng->interface_data, interface_data);
2149 pcapng->number_of_interfaces++;
2152 /* classic wtap: open capture file */
2154 pcapng_open(wtap *wth, int *err, gchar **err_info)
2158 wtapng_block_t wblock;
2160 pcapng_block_header_t bh;
2161 gint64 saved_offset;
2163 pn.shb_read = FALSE;
2164 /* we don't know the byte swapping of the file yet */
2165 pn.byte_swapped = FALSE;
2167 pn.version_major = -1;
2168 pn.version_minor = -1;
2169 pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
2170 pn.number_of_interfaces = 0;
2173 /* we don't expect any packet blocks yet */
2174 wblock.frame_buffer = NULL;
2175 wblock.packet_header = NULL;
2176 wblock.file_encap = &wth->file_encap;
2178 pcapng_debug0("pcapng_open: opening file");
2179 /* read first block */
2180 bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
2181 if (bytes_read <= 0) {
2182 pcapng_debug0("pcapng_open: couldn't read first SHB");
2183 *err = file_error(wth->fh, err_info);
2184 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
2189 /* first block must be a "Section Header Block" */
2190 if (wblock.type != BLOCK_TYPE_SHB) {
2192 * XXX - check for damage from transferring a file
2193 * between Windows and UN*X as text rather than
2196 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2202 * At this point, we've decided this is a pcap-NG file, not
2203 * some other type of file, so we can't return 0, as that
2204 * means "this isn't a pcap-NG file, try some other file
2207 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2208 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2209 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2210 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2212 wth->file_encap = WTAP_ENCAP_UNKNOWN;
2213 wth->snapshot_length = 0;
2214 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
2215 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2216 wth->priv = (void *)pcapng;
2219 wth->subtype_read = pcapng_read;
2220 wth->subtype_seek_read = pcapng_seek_read;
2221 wth->subtype_close = pcapng_close;
2222 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
2225 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
2226 wth->number_of_interfaces = 0;
2228 /* Loop over all IDB:s that appear before any packets */
2230 /* peek at next block */
2231 /* Try to read the (next) block header */
2232 saved_offset = file_tell(wth->fh);
2233 errno = WTAP_ERR_CANT_READ;
2234 bytes_read = file_read(&bh, sizeof bh, wth->fh);
2235 if (bytes_read == 0) {
2236 pcapng_debug0("No more IDBs available...");
2239 if (bytes_read != sizeof bh) {
2240 *err = file_error(wth->fh, err_info);
2241 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);
2243 *err = WTAP_ERR_SHORT_READ;
2247 /* go back to where we were */
2248 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2250 if (pn.byte_swapped) {
2251 bh.block_type = GUINT32_SWAP_LE_BE(bh.block_type);
2254 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2256 if (bh.block_type != BLOCK_TYPE_IDB) {
2257 break; /* No more IDB:s */
2259 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
2260 if (bytes_read == 0) {
2261 pcapng_debug0("No more IDBs available...");
2264 if (bytes_read <= 0) {
2265 pcapng_debug0("pcapng_open: couldn't read IDB");
2266 *err = file_error(wth->fh, err_info);
2268 *err = WTAP_ERR_SHORT_READ;
2271 pcapng_process_idb(wth, pcapng, &wblock);
2272 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, *wblock.file_encap);
2278 /* classic wtap: read packet */
2280 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2282 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2284 wtapng_block_t wblock;
2285 wtapng_if_descr_t *wtapng_if_descr;
2286 wtapng_if_stats_t if_stats;
2288 *data_offset = file_tell(wth->fh);
2289 pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER "d", *data_offset);
2291 wblock.frame_buffer = wth->frame_buffer;
2292 wblock.packet_header = &wth->phdr;
2293 wblock.file_encap = &wth->file_encap;
2295 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2296 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2298 /* read next block */
2300 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2301 if (bytes_read <= 0) {
2302 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2303 pcapng_debug0("pcapng_read: couldn't read packet block");
2307 switch (wblock.type) {
2309 case(BLOCK_TYPE_SHB):
2310 /* We don't currently support multi-section files. */
2311 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2312 *err = WTAP_ERR_UNSUPPORTED;
2313 *err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
2316 case(BLOCK_TYPE_PB):
2317 case(BLOCK_TYPE_SPB):
2318 case(BLOCK_TYPE_EPB):
2319 /* packet block - we've found a packet */
2322 case(BLOCK_TYPE_IDB):
2323 /* A new interface */
2324 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2325 *data_offset += bytes_read;
2326 pcapng_process_idb(wth, pcapng, &wblock);
2329 case(BLOCK_TYPE_NRB):
2330 /* More name resolution entries */
2331 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2332 *data_offset += bytes_read;
2335 case(BLOCK_TYPE_ISB):
2336 /* Another interface statistics report */
2337 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2338 *data_offset += bytes_read;
2339 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2340 if (wth->number_of_interfaces < wblock.data.if_stats.interface_id) {
2341 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces", wblock.data.if_stats.interface_id);
2343 /* Get the interface description */
2344 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2345 if (wtapng_if_descr->num_stat_entries == 0) {
2346 /* First ISB found, no previous entry */
2347 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2348 wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2351 if_stats.interface_id = wblock.data.if_stats.interface_id;
2352 if_stats.ts_high = wblock.data.if_stats.ts_high;
2353 if_stats.ts_low = wblock.data.if_stats.ts_low;
2355 if_stats.opt_comment = wblock.data.if_stats.opt_comment; /* NULL if not available */
2356 if_stats.isb_starttime = wblock.data.if_stats.isb_starttime;
2357 if_stats.isb_endtime = wblock.data.if_stats.isb_endtime;
2358 if_stats.isb_ifrecv = wblock.data.if_stats.isb_ifrecv;
2359 if_stats.isb_ifdrop = wblock.data.if_stats.isb_ifdrop;
2360 if_stats.isb_filteraccept = wblock.data.if_stats.isb_filteraccept;
2361 if_stats.isb_osdrop = wblock.data.if_stats.isb_osdrop;
2362 if_stats.isb_usrdeliv = wblock.data.if_stats.isb_usrdeliv;
2364 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2365 wtapng_if_descr->num_stat_entries++;
2370 /* XXX - improve handling of "unknown" blocks */
2371 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2372 *data_offset += bytes_read;
2373 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2380 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2381 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
2387 /* classic wtap: seek to file position and read packet */
2389 pcapng_seek_read(wtap *wth, gint64 seek_off,
2390 struct wtap_pkthdr *phdr, Buffer *buf,
2391 int *err, gchar **err_info)
2393 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2394 guint64 bytes_read64;
2396 wtapng_block_t wblock;
2399 /* seek to the right file position */
2400 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2401 if (bytes_read64 <= 0) {
2402 return FALSE; /* Seek error */
2404 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2406 wblock.frame_buffer = buf;
2407 wblock.packet_header = phdr;
2408 wblock.file_encap = &wth->file_encap;
2410 /* read the block */
2411 bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2412 if (bytes_read <= 0) {
2413 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2414 *err, errno, bytes_read);
2418 /* block must be a "Packet Block", an "Enhanced Packet Block",
2419 or a "Simple Packet Block" */
2420 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2421 wblock.type != BLOCK_TYPE_SPB) {
2422 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2430 /* classic wtap: close capture file */
2432 pcapng_close(wtap *wth)
2434 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2436 pcapng_debug0("pcapng_close: closing file");
2437 if (pcapng->interface_data != NULL) {
2438 g_array_free(pcapng->interface_data, TRUE);
2445 GArray *interface_data;
2446 guint number_of_interfaces;
2450 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2452 pcapng_block_header_t bh;
2453 pcapng_section_header_block_t shb;
2454 const guint32 zero_pad = 0;
2455 gboolean have_options = FALSE;
2456 struct option option_hdr; /* guint16 type, guint16 value_length; */
2457 guint32 options_total_length = 0;
2458 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2459 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2462 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2463 /* Check if we should write comment option */
2464 if (wdh->shb_hdr->opt_comment) {
2465 have_options = TRUE;
2466 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2467 if ((comment_len % 4)) {
2468 comment_pad_len = 4 - (comment_len % 4);
2470 comment_pad_len = 0;
2472 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2475 /* Check if we should write shb_hardware option */
2476 if (wdh->shb_hdr->shb_hardware) {
2477 have_options = TRUE;
2478 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2479 if ((shb_hardware_len % 4)) {
2480 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2482 shb_hardware_pad_len = 0;
2484 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2487 /* Check if we should write shb_os option */
2488 if (wdh->shb_hdr->shb_os) {
2489 have_options = TRUE;
2490 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2491 if ((shb_os_len % 4)) {
2492 shb_os_pad_len = 4 - (shb_os_len % 4);
2496 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2499 /* Check if we should write shb_user_appl option */
2500 if (wdh->shb_hdr->shb_user_appl) {
2501 have_options = TRUE;
2502 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2503 if ((shb_user_appl_len % 4)) {
2504 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2506 shb_user_appl_pad_len = 0;
2508 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2511 /* End-of-options tag */
2512 options_total_length += 4;
2516 /* write block header */
2517 bh.block_type = BLOCK_TYPE_SHB;
2518 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2519 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2521 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2523 wdh->bytes_dumped += sizeof bh;
2525 /* write block fixed content */
2526 /* XXX - get these values from wblock? */
2527 shb.magic = 0x1A2B3C4D;
2528 shb.version_major = 1;
2529 shb.version_minor = 0;
2530 shb.section_length = -1;
2532 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2534 wdh->bytes_dumped += sizeof shb;
2536 /* XXX - write (optional) block options
2544 option_hdr.type = OPT_COMMENT;
2545 option_hdr.value_length = comment_len;
2546 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2548 wdh->bytes_dumped += 4;
2550 /* Write the comments string */
2551 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);
2552 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2554 wdh->bytes_dumped += comment_len;
2556 /* write padding (if any) */
2557 if (comment_pad_len != 0) {
2558 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2560 wdh->bytes_dumped += comment_pad_len;
2564 if (shb_hardware_len) {
2565 option_hdr.type = OPT_SHB_HARDWARE;
2566 option_hdr.value_length = shb_hardware_len;
2567 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2569 wdh->bytes_dumped += 4;
2571 /* Write the string */
2572 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);
2573 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2575 wdh->bytes_dumped += shb_hardware_len;
2577 /* write padding (if any) */
2578 if (shb_hardware_pad_len != 0) {
2579 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2581 wdh->bytes_dumped += shb_hardware_pad_len;
2586 option_hdr.type = OPT_SHB_OS;
2587 option_hdr.value_length = shb_os_len;
2588 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2590 wdh->bytes_dumped += 4;
2592 /* Write the string */
2593 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);
2594 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2596 wdh->bytes_dumped += shb_os_len;
2598 /* write padding (if any) */
2599 if (shb_os_pad_len != 0) {
2600 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2602 wdh->bytes_dumped += shb_os_pad_len;
2606 if (shb_user_appl_len) {
2607 option_hdr.type = OPT_SHB_USERAPPL;
2608 option_hdr.value_length = shb_user_appl_len;
2609 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2611 wdh->bytes_dumped += 4;
2613 /* Write the comments string */
2614 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);
2615 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2617 wdh->bytes_dumped += shb_user_appl_len;
2619 /* write padding (if any) */
2620 if (shb_user_appl_pad_len != 0) {
2621 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2623 wdh->bytes_dumped += shb_user_appl_pad_len;
2627 /* Write end of options if we have otions */
2629 option_hdr.type = OPT_EOFOPT;
2630 option_hdr.value_length = 0;
2631 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2633 wdh->bytes_dumped += 4;
2636 /* write block footer */
2637 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2638 sizeof bh.block_total_length, err))
2640 wdh->bytes_dumped += sizeof bh.block_total_length;
2645 #define IDB_OPT_IF_NAME 2
2646 #define IDB_OPT_IF_DESCR 3
2647 #define IDB_OPT_IF_SPEED 8
2648 #define IDB_OPT_IF_TSRESOL 9
2649 #define IDB_OPT_IF_FILTER 11
2650 #define IDB_OPT_IF_OS 12
2653 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2655 pcapng_block_header_t bh;
2656 pcapng_interface_description_block_t idb;
2657 const guint32 zero_pad = 0;
2658 gboolean have_options = FALSE;
2659 struct option option_hdr; /* guint16 type, guint16 value_length; */
2660 guint32 options_total_length = 0;
2661 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2662 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;
2665 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2666 int_data->link_type,
2667 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2668 int_data->snap_len);
2670 if (int_data->link_type == (guint16)-1) {
2671 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2675 /* Calculate options length */
2676 if (int_data->opt_comment) {
2677 have_options = TRUE;
2678 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2679 if ((comment_len % 4)) {
2680 comment_pad_len = 4 - (comment_len % 4);
2682 comment_pad_len = 0;
2684 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2688 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2690 if (int_data->if_name) {
2691 have_options = TRUE;
2692 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2693 if ((if_name_len % 4)) {
2694 if_name_pad_len = 4 - (if_name_len % 4);
2696 if_name_pad_len = 0;
2698 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2702 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2704 if (int_data->if_description) {
2705 have_options = TRUE;
2706 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2707 if ((if_description_len % 4)) {
2708 if_description_pad_len = 4 - (if_description_len % 4);
2710 if_description_pad_len = 0;
2712 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2714 /* Currently not handled
2715 * if_IPv4addr 4 Interface network address and netmask.
2716 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2717 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2718 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2721 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2723 if (int_data->if_speed != 0) {
2724 have_options = TRUE;
2725 options_total_length = options_total_length + 8 + 4;
2728 * if_tsresol 9 Resolution of timestamps.
2730 if (int_data->if_tsresol != 0) {
2731 have_options = TRUE;
2732 options_total_length = options_total_length + 4 + 4;
2735 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2738 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2739 * 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).
2741 if (int_data->if_filter_str) {
2742 have_options = TRUE;
2743 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2744 if ((if_filter_str_len % 4)) {
2745 if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2747 if_filter_str_pad_len = 0;
2749 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2752 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2754 if (int_data->if_os) {
2755 have_options = TRUE;
2756 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2757 if ((if_os_len % 4)) {
2758 if_os_pad_len = 4 - (if_os_len % 4);
2762 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2765 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2766 * -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.
2768 if (int_data->if_fcslen != 0) {
2771 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2772 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2776 /* End-of-options tag */
2777 options_total_length += 4;
2780 /* write block header */
2781 bh.block_type = BLOCK_TYPE_IDB;
2782 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2784 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2786 wdh->bytes_dumped += sizeof bh;
2788 /* write block fixed content */
2789 idb.linktype = int_data->link_type;
2791 idb.snaplen = int_data->snap_len;
2793 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2795 wdh->bytes_dumped += sizeof idb;
2797 /* XXX - write (optional) block options */
2798 if (comment_len != 0) {
2799 option_hdr.type = OPT_COMMENT;
2800 option_hdr.value_length = comment_len;
2801 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2803 wdh->bytes_dumped += 4;
2805 /* Write the comments string */
2806 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);
2807 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2809 wdh->bytes_dumped += comment_len;
2811 /* write padding (if any) */
2812 if (comment_pad_len != 0) {
2813 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2815 wdh->bytes_dumped += comment_pad_len;
2819 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2821 if (if_name_len !=0) {
2822 option_hdr.type = IDB_OPT_IF_NAME;
2823 option_hdr.value_length = if_name_len;
2824 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2826 wdh->bytes_dumped += 4;
2828 /* Write the comments string */
2829 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);
2830 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
2832 wdh->bytes_dumped += if_name_len;
2834 /* write padding (if any) */
2835 if (if_name_pad_len != 0) {
2836 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2838 wdh->bytes_dumped += if_name_pad_len;
2842 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2844 if (if_description_len != 0) {
2845 option_hdr.type = IDB_OPT_IF_NAME;
2846 option_hdr.value_length = if_description_len;
2847 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2849 wdh->bytes_dumped += 4;
2851 /* Write the comments string */
2852 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);
2853 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
2855 wdh->bytes_dumped += if_description_len;
2857 /* write padding (if any) */
2858 if (if_description_pad_len != 0) {
2859 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2861 wdh->bytes_dumped += if_description_pad_len;
2864 /* Currently not handled
2865 * if_IPv4addr 4 Interface network address and netmask.
2866 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2867 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2868 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2871 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2873 if (int_data->if_speed != 0) {
2874 option_hdr.type = IDB_OPT_IF_SPEED;
2875 option_hdr.value_length = 8;
2876 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2878 wdh->bytes_dumped += 4;
2880 /* Write the comments string */
2881 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
2882 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
2884 wdh->bytes_dumped += 8;
2887 * if_tsresol 9 Resolution of timestamps.
2888 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
2889 * If the Most Significant Bit is equal to zero, the remaining bits indicates
2890 * the resolution of the timestamp as as a negative power of 10
2892 if (int_data->if_tsresol != 0) {
2893 option_hdr.type = IDB_OPT_IF_TSRESOL;
2894 option_hdr.value_length = 1;
2895 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2897 wdh->bytes_dumped += 4;
2899 /* Write the time stamp resolution */
2900 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
2901 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
2903 wdh->bytes_dumped += 1;
2904 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2906 wdh->bytes_dumped += 3;
2909 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2912 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2914 /* Libpcap string variant */
2915 if (if_filter_str_len !=0) {
2916 option_hdr.type = IDB_OPT_IF_FILTER;
2917 option_hdr.value_length = if_filter_str_len;
2918 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2919 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2921 wdh->bytes_dumped += 4;
2923 /* Write the zero indicating libpcap filter variant */
2924 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
2926 wdh->bytes_dumped += 1;
2928 /* Write the comments string */
2929 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);
2930 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2931 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
2933 wdh->bytes_dumped += if_filter_str_len - 1;
2935 /* write padding (if any) */
2936 if (if_filter_str_pad_len != 0) {
2937 if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
2939 wdh->bytes_dumped += if_filter_str_pad_len;
2943 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2945 if (if_os_len != 0) {
2946 option_hdr.type = IDB_OPT_IF_OS;
2947 option_hdr.value_length = if_os_len;
2948 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2950 wdh->bytes_dumped += 4;
2952 /* Write the comments string */
2953 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);
2954 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
2956 wdh->bytes_dumped += if_os_len;
2958 /* write padding (if any) */
2959 if (if_os_pad_len != 0) {
2960 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2962 wdh->bytes_dumped += if_os_pad_len;
2967 option_hdr.type = OPT_EOFOPT;
2968 option_hdr.value_length = 0;
2969 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2971 wdh->bytes_dumped += 4;
2975 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2978 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2979 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2982 /* write block footer */
2983 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2984 sizeof bh.block_total_length, err))
2986 wdh->bytes_dumped += sizeof bh.block_total_length;
2991 #define ISB_STARTTIME 2
2992 #define ISB_ENDTIME 3
2993 #define ISB_IFRECV 4
2994 #define ISB_IFDROP 5
2995 #define ISB_FILTERACCEPT 6
2996 #define ISB_OSDROP 7
2997 #define ISB_USRDELIV 8
3000 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
3003 pcapng_block_header_t bh;
3004 pcapng_interface_statistics_block_t isb;
3005 const guint32 zero_pad = 0;
3006 gboolean have_options = FALSE;
3007 struct option option_hdr; /* guint16 type, guint16 value_length; */
3008 guint32 options_total_length = 0;
3009 guint32 comment_len = 0;
3010 guint32 comment_pad_len = 0;
3012 pcapng_debug0("pcapng_write_interface_statistics_block");
3015 /* Calculate options length */
3016 if (if_stats->opt_comment) {
3017 have_options = TRUE;
3018 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
3019 if ((comment_len % 4)) {
3020 comment_pad_len = 4 - (comment_len % 4);
3022 comment_pad_len = 0;
3024 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3026 /*guint64 isb_starttime */
3027 if (if_stats->isb_starttime != 0) {
3028 have_options = TRUE;
3029 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3031 /*guint64 isb_endtime */
3032 if (if_stats->isb_endtime != 0) {
3033 have_options = TRUE;
3034 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3036 /*guint64 isb_ifrecv */
3037 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3038 have_options = TRUE;
3039 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3041 /*guint64 isb_ifdrop */
3042 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3043 have_options = TRUE;
3044 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3046 /*guint64 isb_filteraccept */
3047 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3048 have_options = TRUE;
3049 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3051 /*guint64 isb_osdrop */
3052 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3053 have_options = TRUE;
3054 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3056 /*guint64 isb_usrdeliv */
3057 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3058 have_options = TRUE;
3059 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3062 /* write block header */
3064 /* End-of-optios tag */
3065 options_total_length += 4;
3068 /* write block header */
3069 bh.block_type = BLOCK_TYPE_ISB;
3070 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3072 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3074 wdh->bytes_dumped += sizeof bh;
3076 /* write block fixed content */
3077 isb.interface_id = if_stats->interface_id;
3078 isb.timestamp_high = if_stats->ts_high;
3079 isb.timestamp_low = if_stats->ts_low;
3082 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3084 wdh->bytes_dumped += sizeof isb;
3086 /* write (optional) block options */
3088 option_hdr.type = OPT_COMMENT;
3089 option_hdr.value_length = comment_len;
3090 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3092 wdh->bytes_dumped += 4;
3094 /* Write the comments string */
3095 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);
3096 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3098 wdh->bytes_dumped += comment_len;
3100 /* write padding (if any) */
3101 if (comment_pad_len != 0) {
3102 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3104 wdh->bytes_dumped += comment_pad_len;
3107 /*guint64 isb_starttime */
3108 if (if_stats->isb_starttime != 0) {
3111 option_hdr.type = ISB_STARTTIME;
3112 option_hdr.value_length = 8;
3113 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3114 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3115 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3117 wdh->bytes_dumped += 4;
3119 /* Write isb_starttime */
3120 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3121 if (!wtap_dump_file_write(wdh, &high, 4, err))
3123 wdh->bytes_dumped += 4;
3124 if (!wtap_dump_file_write(wdh, &low, 4, err))
3126 wdh->bytes_dumped += 4;
3128 /*guint64 isb_endtime */
3129 if (if_stats->isb_endtime != 0) {
3132 option_hdr.type = ISB_ENDTIME;
3133 option_hdr.value_length = 8;
3134 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3135 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3136 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3138 wdh->bytes_dumped += 4;
3140 /* Write isb_endtime */
3141 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3142 if (!wtap_dump_file_write(wdh, &high, 4, err))
3144 wdh->bytes_dumped += 4;
3145 if (!wtap_dump_file_write(wdh, &low, 4, err))
3147 wdh->bytes_dumped += 4;
3149 /*guint64 isb_ifrecv;*/
3150 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3151 option_hdr.type = ISB_IFRECV;
3152 option_hdr.value_length = 8;
3153 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3155 wdh->bytes_dumped += 4;
3157 /* Write isb_ifrecv */
3158 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3159 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3161 wdh->bytes_dumped += 8;
3163 /*guint64 isb_ifdrop;*/
3164 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3165 option_hdr.type = ISB_IFDROP;
3166 option_hdr.value_length = 8;
3167 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3169 wdh->bytes_dumped += 4;
3171 /* Write isb_ifdrop */
3172 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3173 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3175 wdh->bytes_dumped += 8;
3177 /*guint64 isb_filteraccept;*/
3178 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3179 option_hdr.type = ISB_FILTERACCEPT;
3180 option_hdr.value_length = 8;
3181 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3183 wdh->bytes_dumped += 4;
3185 /* Write isb_filteraccept */
3186 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3187 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3189 wdh->bytes_dumped += 8;
3191 /*guint64 isb_osdrop;*/
3192 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3193 option_hdr.type = ISB_OSDROP;
3194 option_hdr.value_length = 8;
3195 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3197 wdh->bytes_dumped += 4;
3199 /* Write isb_osdrop */
3200 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3201 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3203 wdh->bytes_dumped += 8;
3205 /*guint64 isb_usrdeliv;*/
3206 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3207 option_hdr.type = ISB_USRDELIV;
3208 option_hdr.value_length = 8;
3209 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3211 wdh->bytes_dumped += 4;
3213 /* Write isb_usrdeliv */
3214 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3215 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3217 wdh->bytes_dumped += 8;
3221 option_hdr.type = OPT_EOFOPT;
3222 option_hdr.value_length = 0;
3223 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3225 wdh->bytes_dumped += 4;
3228 /* write block footer */
3229 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3230 sizeof bh.block_total_length, err))
3232 wdh->bytes_dumped += sizeof bh.block_total_length;
3240 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3241 const struct wtap_pkthdr *phdr,
3242 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3244 pcapng_block_header_t bh;
3245 pcapng_enhanced_packet_block_t epb;
3247 const guint32 zero_pad = 0;
3250 gboolean have_options = FALSE;
3251 guint32 options_total_length = 0;
3252 struct option option_hdr;
3253 guint32 comment_len = 0, comment_pad_len = 0;
3254 wtapng_if_descr_t int_data;
3256 /* Don't write anything we're not willing to read. */
3257 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
3258 *err = WTAP_ERR_PACKET_TOO_LARGE;
3262 phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3263 if ((phdr_len + phdr->caplen) % 4) {
3264 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3269 /* Check if we should write comment option */
3270 if (phdr->opt_comment) {
3271 have_options = TRUE;
3272 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3273 if ((comment_len % 4)) {
3274 comment_pad_len = 4 - (comment_len % 4);
3276 comment_pad_len = 0;
3278 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3280 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3281 have_options = TRUE;
3282 options_total_length = options_total_length + 8;
3285 /* End-of optios tag */
3286 options_total_length += 4;
3289 /* write (enhanced) packet block header */
3290 bh.block_type = BLOCK_TYPE_EPB;
3291 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3293 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3295 wdh->bytes_dumped += sizeof bh;
3297 /* write block fixed content */
3298 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3299 epb.interface_id = phdr->interface_id;
3302 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3303 * data to pcap-NG files even if we *don't* have interface
3306 epb.interface_id = 0;
3309 * Split the 64-bit timestamp into two 32-bit pieces, using
3310 * the time stamp resolution for the interface.
3312 if (epb.interface_id >= wdh->number_of_interfaces) {
3314 * Our caller is doing something bad.
3316 *err = WTAP_ERR_INTERNAL;
3319 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3321 ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3322 (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3323 epb.timestamp_high = (guint32)(ts >> 32);
3324 epb.timestamp_low = (guint32)ts;
3325 epb.captured_len = phdr->caplen + phdr_len;
3326 epb.packet_len = phdr->len + phdr_len;
3328 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3330 wdh->bytes_dumped += sizeof epb;
3332 /* write pseudo header */
3333 if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3336 wdh->bytes_dumped += phdr_len;
3338 /* write packet data */
3339 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3341 wdh->bytes_dumped += phdr->caplen;
3343 /* write padding (if any) */
3345 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3347 wdh->bytes_dumped += pad_len;
3350 /* XXX - write (optional) block options */
3351 /* options defined in Section 2.5 (Options)
3352 * Name Code Length Description
3353 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3355 * Enhanced Packet Block options
3356 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3357 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3358 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3359 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3360 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3361 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3362 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3363 * The hash covers only the packet, not the header added by the capture driver:
3364 * this gives the possibility to calculate it inside the network card.
3365 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3366 * data acquisition system and the capture library.
3367 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3368 * between this packet and the preceding one.
3369 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3371 if (phdr->opt_comment) {
3372 option_hdr.type = OPT_COMMENT;
3373 option_hdr.value_length = comment_len;
3374 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3376 wdh->bytes_dumped += 4;
3378 /* Write the comments string */
3379 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3380 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3382 wdh->bytes_dumped += comment_len;
3384 /* write padding (if any) */
3385 if (comment_pad_len != 0) {
3386 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3388 wdh->bytes_dumped += comment_pad_len;
3391 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3395 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3396 option_hdr.type = OPT_EPB_FLAGS;
3397 option_hdr.value_length = 4;
3398 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3400 wdh->bytes_dumped += 4;
3401 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3403 wdh->bytes_dumped += 4;
3404 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3406 /* Write end of options if we have otions */
3408 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3410 wdh->bytes_dumped += 4;
3413 /* write block footer */
3414 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3415 sizeof bh.block_total_length, err))
3417 wdh->bytes_dumped += sizeof bh.block_total_length;
3423 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3425 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
3427 pcapng_block_header_t bh;
3428 pcapng_name_resolution_block_t nrb;
3430 gint rec_off, namelen, tot_rec_len;
3431 hashipv4_t *ipv4_hash_list_entry;
3432 hashipv6_t *ipv6_hash_list_entry;
3435 if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
3439 rec_off = 8; /* block type + block total length */
3440 bh.block_type = BLOCK_TYPE_NRB;
3441 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3442 rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3444 if (wdh->addrinfo_lists->ipv4_addr_list){
3446 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3447 while(ipv4_hash_list_entry != NULL){
3449 nrb.record_type = NRES_IP4RECORD;
3450 namelen = (gint)strlen(ipv4_hash_list_entry->name) + 1;
3451 nrb.record_len = 4 + namelen;
3452 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3454 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3455 /* We know the total length now; copy the block header. */
3456 memcpy(rec_data, &bh, sizeof(bh));
3459 memset(rec_data + rec_off, 0, 4);
3462 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3464 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3466 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3470 wdh->bytes_dumped += bh.block_total_length;
3472 /*Start a new NRB */
3473 rec_off = 8; /* block type + block total length */
3474 bh.block_type = BLOCK_TYPE_NRB;
3475 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3479 bh.block_total_length += tot_rec_len;
3480 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3482 memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
3484 memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
3486 memset(rec_data + rec_off, 0, PADDING4(namelen));
3487 rec_off += PADDING4(namelen);
3488 pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
3491 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3493 g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
3494 wdh->addrinfo_lists->ipv4_addr_list = NULL;
3497 if (wdh->addrinfo_lists->ipv6_addr_list){
3499 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3500 while(ipv6_hash_list_entry != NULL){
3502 nrb.record_type = NRES_IP6RECORD;
3503 namelen = (gint)strlen(ipv6_hash_list_entry->name) + 1;
3504 nrb.record_len = 16 + namelen; /* 16 bytes IPv6 address length */
3505 /* 2 bytes record type, 2 bytes length field */
3506 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3508 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3509 /* We know the total length now; copy the block header. */
3510 memcpy(rec_data, &bh, sizeof(bh));
3513 memset(rec_data + rec_off, 0, 4);
3516 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3518 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3520 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3524 wdh->bytes_dumped += bh.block_total_length;
3526 /*Start a new NRB */
3527 rec_off = 8; /* block type + block total length */
3528 bh.block_type = BLOCK_TYPE_NRB;
3529 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3533 bh.block_total_length += tot_rec_len;
3534 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3536 memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
3538 memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
3540 memset(rec_data + rec_off, 0, PADDING4(namelen));
3541 rec_off += PADDING4(namelen);
3542 pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
3545 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3547 g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
3548 wdh->addrinfo_lists->ipv6_addr_list = NULL;
3551 /* We know the total length now; copy the block header. */
3552 memcpy(rec_data, &bh, sizeof(bh));
3555 memset(rec_data + rec_off, 0, 4);
3558 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3560 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3562 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3568 wdh->bytes_dumped += bh.block_total_length;
3574 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
3577 interface_data_t int_data;
3578 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3580 for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
3581 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
3582 if (wtap_encap == int_data.wtap_encap) {
3590 static gboolean pcapng_dump(wtap_dumper *wdh,
3591 const struct wtap_pkthdr *phdr,
3592 const guint8 *pd, int *err)
3594 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3595 /*interface_data_t int_data;*/
3596 /* pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv; */
3599 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3601 wtap_encap_string(phdr->pkt_encap));
3603 /* Flush any hostname resolution info we may have */
3604 pcapng_write_name_resolution_block(wdh, err);
3606 if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3614 /* Finish writing to a dump file.
3615 Returns TRUE on success, FALSE on failure. */
3616 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3619 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3621 if ((wdh->number_of_interfaces > 0) && (wdh->interface_data != NULL)) {
3622 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3624 /* Get the interface description */
3625 wtapng_if_descr_t int_data;
3627 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3628 for (j = 0; j < (int)int_data.num_stat_entries; j++) {
3629 wtapng_if_stats_t if_stats;
3631 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3632 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3633 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3640 pcapng_debug0("pcapng_dump_close");
3641 g_array_free(pcapng->interface_data, TRUE);
3642 pcapng->number_of_interfaces = 0;
3647 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3650 pcapng_dump_open(wtap_dumper *wdh, int *err)
3652 pcapng_dump_t *pcapng;
3654 interface_data_t interface_data;
3656 pcapng_debug0("pcapng_dump_open");
3657 /* This is a pcapng file */
3658 wdh->subtype_write = pcapng_dump;
3659 wdh->subtype_close = pcapng_dump_close;
3660 pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
3661 wdh->priv = (void *)pcapng;
3662 pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
3664 if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
3665 pcapng_debug0("There are no interfaces. Can't handle that...");
3666 *err = WTAP_ERR_INTERNAL;
3670 /* write the section header block */
3671 if (!pcapng_write_section_header_block(wdh, err)) {
3674 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3676 /* Write the Interface description blocks */
3677 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
3679 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3681 /* Get the interface description */
3682 wtapng_if_descr_t int_data;
3684 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3686 interface_data.wtap_encap = int_data.wtap_encap;
3687 interface_data.time_units_per_second = int_data.time_units_per_second;
3689 g_array_append_val(pcapng->interface_data, interface_data);
3690 pcapng->number_of_interfaces++;
3692 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3698 interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3699 if (interface_id == G_MAXUINT32) {
3701 * We haven't yet written out an interface description
3702 * block for an interface with this encapsulation.
3704 * Is this encapsulation even supported in pcap-ng?
3706 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3707 if (pcap_encap == -1) {
3711 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3715 /* write the interface description block */
3716 wblock.frame_buffer = NULL;
3717 wblock.pseudo_header = NULL;
3718 wblock.packet_header = NULL;
3719 wblock.file_encap = NULL;
3720 wblock.type = BLOCK_TYPE_IDB;
3721 wblock.data.if_descr.link_type = pcap_encap;
3722 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3723 WTAP_MAX_PACKET_SIZE; /* XXX */
3725 /* XXX - options unused */
3726 wblock.data.if_descr.if_speed = -1;
3727 /*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
3728 wblock.data.if_descr.if_os = NULL;
3729 wblock.data.if_descr.if_fcslen = -1;
3731 if (!pcapng_write_if_descr_block(wdh, &wblock, err)) {
3735 interface_id = pcapng->number_of_interfaces;
3736 int_data.wtap_encap = phdr->pkt_encap;
3737 int_data.time_units_per_second = 0;
3738 g_array_append_val(pcapng->interface_data, int_data);
3739 pcapng->number_of_interfaces++;
3741 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3744 wtap_encap_string(phdr->pkt_encap));
3752 /* Returns 0 if we could write the specified encapsulation type,
3753 an error indication otherwise. */
3754 int pcapng_dump_can_write_encap(int wtap_encap)
3756 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3758 wtap_encap_string(wtap_encap));
3760 /* Per-packet encapsulation is supported. */
3761 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3764 /* Make sure we can figure out this DLT type */
3765 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3766 return WTAP_ERR_UNSUPPORTED_ENCAP;
3772 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3777 * indent-tabs-mode: nil
3780 * vi: set shiftwidth=4 tabstop=8 expandtab:
3781 * :indentSize=4:tabSize=8:noTabs=true: