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 length
,
66 int *err
, gchar
**err_info
);
68 pcapng_close(wtap
*wth
);
71 /* pcapng: common block header for every block type */
72 typedef struct pcapng_block_header_s
{
74 guint32 block_total_length
;
75 /* x bytes block_body */
76 /* guint32 block_total_length */
77 } pcapng_block_header_t
;
80 * Minimum block size = size of block header + size of block trailer.
82 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
85 * In order to keep from trying to allocate large chunks of memory,
86 * which could either fail or, even if it succeeds, chew up so much
87 * address space or memory+backing store as not to leave room for
88 * anything else, we impose an upper limit on the size of blocks
89 * we're willing to handle.
91 * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
92 * don't try saying that on Wikipedia :-) :-) :-)).
94 #define MAX_BLOCK_SIZE (16*1024*1024)
96 /* pcapng: section header block */
97 typedef struct pcapng_section_header_block_s
{
98 /* pcapng_block_header_t */
100 guint16 version_major
;
101 guint16 version_minor
;
102 guint64 section_length
; /* might be -1 for unknown */
103 /* ... Options ... */
104 } pcapng_section_header_block_t
;
107 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
109 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
111 /* pcapng: interface description block */
112 typedef struct pcapng_interface_description_block_s
{
116 /* ... Options ... */
117 } pcapng_interface_description_block_t
;
120 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
122 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
124 /* pcapng: packet block (obsolete) */
125 typedef struct pcapng_packet_block_s
{
126 guint16 interface_id
;
128 guint32 timestamp_high
;
129 guint32 timestamp_low
;
130 guint32 captured_len
;
132 /* ... Packet Data ... */
133 /* ... Padding ... */
134 /* ... Options ... */
135 } pcapng_packet_block_t
;
138 * Minimum PB size = minimum block size + size of fixed length portion of PB.
140 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
142 /* pcapng: enhanced packet block */
143 typedef struct pcapng_enhanced_packet_block_s
{
144 guint32 interface_id
;
145 guint32 timestamp_high
;
146 guint32 timestamp_low
;
147 guint32 captured_len
;
149 /* ... Packet Data ... */
150 /* ... Padding ... */
151 /* ... Options ... */
152 } pcapng_enhanced_packet_block_t
;
155 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
157 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
159 /* pcapng: simple packet block */
160 typedef struct pcapng_simple_packet_block_s
{
162 /* ... Packet Data ... */
163 /* ... Padding ... */
164 } pcapng_simple_packet_block_t
;
167 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
169 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
171 /* pcapng: name resolution block */
172 typedef struct pcapng_name_resolution_block_s
{
176 } pcapng_name_resolution_block_t
;
179 * Minimum NRB size = minimum block size + size of smallest NRB record
180 * (there must at least be an "end of records" record).
182 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
184 /* pcapng: interface statistics block */
185 typedef struct pcapng_interface_statistics_block_s
{
186 guint32 interface_id
;
187 guint32 timestamp_high
;
188 guint32 timestamp_low
;
189 /* ... Options ... */
190 } pcapng_interface_statistics_block_t
;
193 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
195 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
197 /* pcapng: common option header for every option type */
198 typedef struct pcapng_option_header_s
{
200 guint16 option_length
;
201 /* ... x bytes Option Body ... */
202 /* ... Padding ... */
203 } pcapng_option_header_t
;
207 guint16 value_length
;
211 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
212 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
213 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
214 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
215 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
216 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
217 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
221 #define OPT_COMMENT 1
222 #define OPT_SHB_HARDWARE 2
224 #define OPT_SHB_USERAPPL 4
225 #define OPT_EPB_FLAGS 2
226 #define OPT_EPB_HASH 3
227 #define OPT_EPB_DROPCOUNT 4
229 /* Capture section */
231 /* Moved to wtap.h */
232 typedef struct wtapng_section_s
{
234 guint64 section_length
;
236 gchar
*opt_comment
; /* NULL if not available */
237 gchar
*shb_hardware
; /* NULL if not available */
238 gchar
*shb_os
; /* NULL if not available */
239 gchar
*shb_user_appl
; /* NULL if not available */
244 /* Moved to wtap.h */
246 /* Interface Description
249 * 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}" / ...
250 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
251 * 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
252 * 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"
253 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
254 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
255 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
256 * 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
257 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
258 * 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"
259 * 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" / ...
260 * 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
261 * 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
264 typedef struct wtapng_if_descr_s
{
270 gchar
*opt_comment
; /* NULL if not available */
271 gchar
*if_name
; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
272 gchar
*if_description
;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
273 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
274 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
275 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
276 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
277 guint64 if_speed
; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
278 guint8 if_tsresol
; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
279 * 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
281 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
282 gchar
*if_filter
; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
283 * 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).
285 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. */
286 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. */
287 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
292 typedef struct wtapng_packet_s
{
294 guint32 ts_high
; /* seconds since 1.1.1970 */
295 guint32 ts_low
; /* fraction of seconds, depends on if_tsresol */
296 guint32 cap_len
; /* data length in the file */
297 guint32 packet_len
; /* data length on the wire */
298 guint32 interface_id
; /* identifier of the interface. */
299 guint16 drops_count
; /* drops count, only valid for packet block */
300 /* 0xffff if information no available */
302 /* XXX - put the packet data / pseudo_header here as well? */
306 typedef struct wtapng_simple_packet_s
{
308 guint32 cap_len
; /* data length in the file */
309 guint32 packet_len
; /* data length on the wire */
310 guint32 pseudo_header_len
;
312 /* XXX - put the packet data / pseudo_header here as well? */
313 } wtapng_simple_packet_t
;
315 /* Name Resolution */
316 typedef struct wtapng_name_res_s
{
318 gchar
*opt_comment
; /* NULL if not available */
323 /* Interface Statistics moved to wtap.h*/
324 typedef struct wtapng_if_stats_s
{
326 guint32 interface_id
;
330 gchar
*opt_comment
; /* NULL if not available */
331 guint64 isb_starttime
;
335 guint64 isb_filteraccept
;
337 guint64 isb_usrdeliv
;
341 typedef struct wtapng_block_s
{
342 guint32 type
; /* block_type as defined by pcapng */
344 wtapng_section_t section
;
345 wtapng_if_descr_t if_descr
;
346 wtapng_name_res_t name_res
;
347 wtapng_if_stats_t if_stats
;
351 * XXX - currently don't know how to handle these!
353 * For one thing, when we're reading a block, they must be
354 * writable, i.e. not const, so that we can read into them,
355 * but, when we're writing a block, they can be const, and,
356 * in fact, they sometimes point to const values.
358 struct wtap_pkthdr
*packet_header
;
359 Buffer
*frame_buffer
;
363 /* Interface data in private struct */
364 typedef struct interface_data_s
{
367 guint64 time_units_per_second
;
371 gboolean shb_read
; /**< Set when first SHB read, second read will fail */
372 gboolean byte_swapped
;
373 guint16 version_major
;
374 guint16 version_minor
;
375 GArray
*interface_data
;
376 guint number_of_interfaces
;
378 wtap_new_ipv4_callback_t add_new_ipv4
;
379 wtap_new_ipv6_callback_t add_new_ipv6
;
383 pcapng_read_option(FILE_T fh
, pcapng_t
*pn
, pcapng_option_header_t
*oh
,
384 char *content
, guint len
, guint to_read
,
385 int *err
, gchar
**err_info
)
389 guint64 file_offset64
;
391 /* sanity check: don't run past the end of the block */
392 if (to_read
< sizeof (*oh
)) {
393 *err
= WTAP_ERR_BAD_FILE
;
394 *err_info
= g_strdup("pcapng_read_option: option goes past the end of the block");
398 /* read option header */
399 errno
= WTAP_ERR_CANT_READ
;
400 bytes_read
= file_read(oh
, sizeof (*oh
), fh
);
401 if (bytes_read
!= sizeof (*oh
)) {
402 pcapng_debug0("pcapng_read_option: failed to read option");
403 *err
= file_error(fh
, err_info
);
408 block_read
= sizeof (*oh
);
409 if (pn
->byte_swapped
) {
410 oh
->option_code
= BSWAP16(oh
->option_code
);
411 oh
->option_length
= BSWAP16(oh
->option_length
);
414 /* sanity check: don't run past the end of the block */
415 if (to_read
< sizeof (*oh
) + oh
->option_length
) {
416 *err
= WTAP_ERR_BAD_FILE
;
417 *err_info
= g_strdup("pcapng_read_option: option goes past the end of the block");
421 /* sanity check: option length */
422 if (oh
->option_length
> len
) {
423 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
424 oh
->option_length
, len
);
428 /* read option content */
429 errno
= WTAP_ERR_CANT_READ
;
430 bytes_read
= file_read(content
, oh
->option_length
, fh
);
431 if (bytes_read
!= oh
->option_length
) {
432 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh
->option_code
);
433 *err
= file_error(fh
, err_info
);
438 block_read
+= oh
->option_length
;
440 /* jump over potential padding bytes at end of option */
441 if ( (oh
->option_length
% 4) != 0) {
442 file_offset64
= file_seek(fh
, 4 - (oh
->option_length
% 4), SEEK_CUR
, err
);
443 if (file_offset64
<= 0) {
448 block_read
+= 4 - (oh
->option_length
% 4);
456 pcapng_read_section_header_block(FILE_T fh
, gboolean first_block
,
457 pcapng_block_header_t
*bh
, pcapng_t
*pn
,
458 wtapng_block_t
*wblock
, int *err
,
463 guint to_read
, opt_cont_buf_len
;
464 pcapng_section_header_block_t shb
;
465 pcapng_option_header_t oh
;
466 char *option_content
= NULL
; /* Allocate as large as the options block */
469 * Is this block long enough to be an SHB?
471 if (bh
->block_total_length
< MIN_SHB_SIZE
) {
476 return 0; /* probably not a pcap-ng file */
477 *err
= WTAP_ERR_BAD_FILE
;
478 *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",
479 bh
->block_total_length
, MIN_SHB_SIZE
);
483 /* read block content */
484 errno
= WTAP_ERR_CANT_READ
;
485 bytes_read
= file_read(&shb
, sizeof shb
, fh
);
486 if (bytes_read
!= sizeof shb
) {
487 *err
= file_error(fh
, err_info
);
491 * We're reading this as part of an open,
492 * and this block is too short to be
493 * an SHB, so the file is too short
494 * to be a pcap-ng file.
500 * Otherwise, just report this as an error.
502 *err
= WTAP_ERR_SHORT_READ
;
506 block_read
= bytes_read
;
508 /* is the magic number one we expect? */
511 /* this seems pcapng with correct byte order */
512 pn
->byte_swapped
= FALSE
;
513 pn
->version_major
= shb
.version_major
;
514 pn
->version_minor
= shb
.version_minor
;
516 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
517 pn
->version_major
, pn
->version_minor
, bh
->block_total_length
);
520 /* this seems pcapng with swapped byte order */
521 pn
->byte_swapped
= TRUE
;
522 pn
->version_major
= BSWAP16(shb
.version_major
);
523 pn
->version_minor
= BSWAP16(shb
.version_minor
);
525 /* tweak the block length to meet current swapping that we know now */
526 bh
->block_total_length
= BSWAP32(bh
->block_total_length
);
528 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
529 pn
->version_major
, pn
->version_minor
, bh
->block_total_length
);
532 /* Not a "pcapng" magic number we know about. */
534 /* Not a pcap-ng file. */
539 *err
= WTAP_ERR_BAD_FILE
;
540 *err_info
= g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb
.magic
);
544 /* OK, at this point we assume it's a pcap-ng file.
546 Don't try to allocate memory for a huge number of options, as
547 that might fail and, even if it succeeds, it might not leave
548 any address space or memory+backing store for anything else.
550 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
551 We check for this *after* checking the SHB for its byte
552 order magic number, so that non-pcap-ng files are less
553 likely to be treated as bad pcap-ng files. */
554 if (bh
->block_total_length
> MAX_BLOCK_SIZE
) {
555 *err
= WTAP_ERR_BAD_FILE
;
556 *err_info
= g_strdup_printf("pcapng: total block length %u is too large (> %u)",
557 bh
->block_total_length
, MAX_BLOCK_SIZE
);
561 /* We currently only suport one SHB */
562 if (pn
->shb_read
== TRUE
) {
563 *err
= WTAP_ERR_UNSUPPORTED
;
564 *err_info
= g_strdup_printf("pcapng: multiple section header blocks not supported.");
568 /* we currently only understand SHB V1.0 */
569 if (pn
->version_major
!= 1 || pn
->version_minor
> 0) {
570 *err
= WTAP_ERR_UNSUPPORTED
;
571 *err_info
= g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
572 pn
->version_major
, pn
->version_minor
);
577 /* 64bit section_length (currently unused) */
578 if (pn
->byte_swapped
) {
579 wblock
->data
.section
.section_length
= BSWAP64(shb
.section_length
);
581 wblock
->data
.section
.section_length
= shb
.section_length
;
584 /* Option defaults */
585 wblock
->data
.section
.opt_comment
= NULL
;
586 wblock
->data
.section
.shb_hardware
= NULL
;
587 wblock
->data
.section
.shb_os
= NULL
;
588 wblock
->data
.section
.shb_user_appl
= NULL
;
591 errno
= WTAP_ERR_CANT_READ
;
592 to_read
= bh
->block_total_length
- MIN_SHB_SIZE
;
594 /* Allocate enough memory to hold all options */
595 opt_cont_buf_len
= to_read
;
596 option_content
= (char *)g_try_malloc(opt_cont_buf_len
);
597 if (opt_cont_buf_len
!= 0 && option_content
== NULL
) {
598 *err
= ENOMEM
; /* we assume we're out of memory */
601 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read
);
602 while (to_read
!= 0) {
604 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read
);
605 bytes_read
= pcapng_read_option(fh
, pn
, &oh
, option_content
, opt_cont_buf_len
, to_read
, err
, err_info
);
606 if (bytes_read
<= 0) {
607 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
610 block_read
+= bytes_read
;
611 to_read
-= bytes_read
;
613 /* handle option content */
614 switch (oh
.option_code
) {
617 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read
);
619 /* padding should be ok here, just get out of this */
623 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
624 wblock
->data
.section
.opt_comment
= g_strndup(option_content
, oh
.option_length
);
625 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock
->data
.section
.opt_comment
);
627 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh
.option_length
);
630 case(OPT_SHB_HARDWARE
):
631 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
632 wblock
->data
.section
.shb_hardware
= g_strndup(option_content
, oh
.option_length
);
633 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock
->data
.section
.shb_hardware
);
635 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh
.option_length
);
639 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
640 wblock
->data
.section
.shb_os
= g_strndup(option_content
, oh
.option_length
);
641 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock
->data
.section
.shb_os
);
643 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh
.option_length
,to_read
);
646 case(OPT_SHB_USERAPPL
):
647 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
648 wblock
->data
.section
.shb_user_appl
= g_strndup(option_content
, oh
.option_length
);
649 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock
->data
.section
.shb_user_appl
);
651 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh
.option_length
);
655 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
656 oh
.option_code
, oh
.option_length
);
659 g_free(option_content
);
665 /* "Interface Description Block" */
667 pcapng_read_if_descr_block(FILE_T fh
, pcapng_block_header_t
*bh
, pcapng_t
*pn
,
668 wtapng_block_t
*wblock
, int *err
, gchar
**err_info
)
670 guint64 time_units_per_second
= 1000000; /* default */
673 guint to_read
, opt_cont_buf_len
;
674 pcapng_interface_description_block_t idb
;
675 pcapng_option_header_t oh
;
676 char *option_content
= NULL
; /* Allocate as large as the options block */
679 * Is this block long enough to be an IDB?
681 if (bh
->block_total_length
< MIN_IDB_SIZE
) {
685 *err
= WTAP_ERR_BAD_FILE
;
686 *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",
687 bh
->block_total_length
, MIN_IDB_SIZE
);
691 /* Don't try to allocate memory for a huge number of options, as
692 that might fail and, even if it succeeds, it might not leave
693 any address space or memory+backing store for anything else.
695 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
696 We check for this *after* checking the SHB for its byte
697 order magic number, so that non-pcap-ng files are less
698 likely to be treated as bad pcap-ng files. */
699 if (bh
->block_total_length
> MAX_BLOCK_SIZE
) {
700 *err
= WTAP_ERR_BAD_FILE
;
701 *err_info
= g_strdup_printf("pcapng: total block length %u is too large (> %u)",
702 bh
->block_total_length
, MAX_BLOCK_SIZE
);
706 /* read block content */
707 errno
= WTAP_ERR_CANT_READ
;
708 bytes_read
= file_read(&idb
, sizeof idb
, fh
);
709 if (bytes_read
!= sizeof idb
) {
710 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
711 *err
= file_error(fh
, err_info
);
716 block_read
= bytes_read
;
718 /* mandatory values */
719 if (pn
->byte_swapped
) {
720 wblock
->data
.if_descr
.link_type
= BSWAP16(idb
.linktype
);
721 wblock
->data
.if_descr
.snap_len
= BSWAP32(idb
.snaplen
);
723 wblock
->data
.if_descr
.link_type
= idb
.linktype
;
724 wblock
->data
.if_descr
.snap_len
= idb
.snaplen
;
727 wblock
->data
.if_descr
.wtap_encap
= wtap_pcap_encap_to_wtap_encap(wblock
->data
.if_descr
.link_type
);
728 wblock
->data
.if_descr
.time_units_per_second
= time_units_per_second
;
730 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
731 wblock
->data
.if_descr
.link_type
,
732 wtap_encap_string(wblock
->data
.if_descr
.wtap_encap
),
733 wblock
->data
.if_descr
.snap_len
);
735 if (wblock
->data
.if_descr
.snap_len
> WTAP_MAX_PACKET_SIZE
) {
736 /* This is unrealistic, but text2pcap currently uses 102400.
737 * We do not use this value, maybe we should check the
738 * snap_len of the packets against it. For now, only warn.
740 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
741 wblock
->data
.if_descr
.snap_len
);
742 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
745 /* Option defaults */
746 wblock
->data
.if_descr
.opt_comment
= NULL
;
747 wblock
->data
.if_descr
.if_name
= NULL
;
748 wblock
->data
.if_descr
.if_description
= NULL
;
749 /* XXX: if_IPv4addr */
750 /* XXX: if_IPv6addr */
751 /* XXX: if_MACaddr */
752 /* XXX: if_EUIaddr */
753 wblock
->data
.if_descr
.if_speed
= 0; /* "unknown" */
754 wblock
->data
.if_descr
.if_tsresol
= 6; /* default is 6 for microsecond resolution */
755 wblock
->data
.if_descr
.if_filter_str
= NULL
;
756 wblock
->data
.if_descr
.bpf_filter_len
= 0;
757 wblock
->data
.if_descr
.if_filter_bpf_bytes
= NULL
;
758 wblock
->data
.if_descr
.if_os
= NULL
;
759 wblock
->data
.if_descr
.if_fcslen
= -1; /* unknown or changes between packets */
760 /* XXX: guint64 if_tsoffset; */
764 errno
= WTAP_ERR_CANT_READ
;
765 to_read
= bh
->block_total_length
- MIN_IDB_SIZE
;
767 /* Allocate enough memory to hold all options */
768 opt_cont_buf_len
= to_read
;
769 option_content
= (char *)g_try_malloc(opt_cont_buf_len
);
770 if (opt_cont_buf_len
!= 0 && option_content
== NULL
) {
771 *err
= ENOMEM
; /* we assume we're out of memory */
775 while (to_read
!= 0) {
777 bytes_read
= pcapng_read_option(fh
, pn
, &oh
, option_content
, opt_cont_buf_len
, to_read
, err
, err_info
);
778 if (bytes_read
<= 0) {
779 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
782 block_read
+= bytes_read
;
783 to_read
-= bytes_read
;
785 /* handle option content */
786 switch (oh
.option_code
) {
787 case(0): /* opt_endofopt */
789 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read
);
791 /* padding should be ok here, just get out of this */
794 case(1): /* opt_comment */
795 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
796 wblock
->data
.if_descr
.opt_comment
= g_strndup(option_content
, oh
.option_length
);
797 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock
->data
.if_descr
.opt_comment
);
799 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh
.option_length
);
802 case(2): /* if_name */
803 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
804 wblock
->data
.if_descr
.if_name
= g_strndup(option_content
, oh
.option_length
);
805 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock
->data
.if_descr
.if_name
);
807 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh
.option_length
);
810 case(3): /* if_description */
811 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
812 wblock
->data
.if_descr
.if_description
= g_strndup(option_content
, oh
.option_length
);
813 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock
->data
.if_descr
.if_description
);
815 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh
.option_length
);
819 * 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
820 * 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"
821 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
822 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
824 case(8): /* if_speed */
825 if (oh
.option_length
== 8) {
826 /* Don't cast a char[] into a guint64--the
827 * char[] may not be aligned correctly.
829 memcpy(&wblock
->data
.if_descr
.if_speed
, option_content
, sizeof(guint64
));
830 if (pn
->byte_swapped
)
831 wblock
->data
.if_descr
.if_speed
= BSWAP64(wblock
->data
.if_descr
.if_speed
);
832 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER
"u (bps)", wblock
->data
.if_descr
.if_speed
);
834 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh
.option_length
);
837 case(9): /* if_tsresol */
838 if (oh
.option_length
== 1) {
841 guint8 i
, exponent
, if_tsresol
;
843 if_tsresol
= option_content
[0];
844 if (if_tsresol
& 0x80) {
849 exponent
= (guint8
)(if_tsresol
& 0x7f);
850 if (((base
== 2) && (exponent
< 64)) || ((base
== 10) && (exponent
< 20))) {
852 for (i
= 0; i
< exponent
; i
++) {
855 time_units_per_second
= result
;
857 time_units_per_second
= G_MAXUINT64
;
859 if (time_units_per_second
> (((guint64
)1) << 32)) {
860 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
862 wblock
->data
.if_descr
.time_units_per_second
= time_units_per_second
;
863 wblock
->data
.if_descr
.if_tsresol
= if_tsresol
;
864 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
);
866 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh
.option_length
);
870 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
872 case(11): /* if_filter */
873 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
874 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
877 if (option_content
[0] == 0) {
878 wblock
->data
.if_descr
.if_filter_str
= g_strndup(option_content
+1, oh
.option_length
-1);
879 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
);
880 } else if (option_content
[0] == 1) {
881 wblock
->data
.if_descr
.bpf_filter_len
= oh
.option_length
-1;
882 wblock
->data
.if_descr
.if_filter_bpf_bytes
= (gchar
*)g_malloc(oh
.option_length
-1);
883 memcpy(&wblock
->data
.if_descr
.if_filter_bpf_bytes
, option_content
+1, oh
.option_length
-1);
886 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh
.option_length
);
889 case(12): /* if_os */
891 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
892 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
893 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
895 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
896 wblock
->data
.if_descr
.if_os
= g_strndup(option_content
, oh
.option_length
);
897 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock
->data
.if_descr
.if_os
);
899 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh
.option_length
);
902 case(13): /* if_fcslen */
903 if (oh
.option_length
== 1) {
904 wblock
->data
.if_descr
.if_fcslen
= option_content
[0];
905 pn
->if_fcslen
= wblock
->data
.if_descr
.if_fcslen
;
906 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock
->data
.if_descr
.if_fcslen
);
907 /* XXX - add sanity check */
909 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh
.option_length
);
913 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
914 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
915 * The time zone of the offset can be specified with the option if_tzone.
916 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
919 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
920 oh
.option_code
, oh
.option_length
);
924 g_free(option_content
);
926 if (*wblock
->file_encap
== WTAP_ENCAP_UNKNOWN
) {
927 *wblock
->file_encap
= wblock
->data
.if_descr
.wtap_encap
;
929 if (*wblock
->file_encap
!= wblock
->data
.if_descr
.wtap_encap
) {
930 *wblock
->file_encap
= WTAP_ENCAP_PER_PACKET
;
939 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
)
943 guint to_read
, opt_cont_buf_len
;
944 guint64 file_offset64
;
945 pcapng_enhanced_packet_block_t epb
;
946 pcapng_packet_block_t pb
;
947 wtapng_packet_t packet
;
948 guint32 block_total_length
;
950 interface_data_t int_data
;
952 pcapng_option_header_t oh
;
953 int pseudo_header_len
;
954 char *option_content
= NULL
; /* Allocate as large as the options block */
957 /* Don't try to allocate memory for a huge number of options, as
958 that might fail and, even if it succeeds, it might not leave
959 any address space or memory+backing store for anything else.
961 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
962 We check for this *after* checking the SHB for its byte
963 order magic number, so that non-pcap-ng files are less
964 likely to be treated as bad pcap-ng files. */
965 if (bh
->block_total_length
> MAX_BLOCK_SIZE
) {
966 *err
= WTAP_ERR_BAD_FILE
;
967 *err_info
= g_strdup_printf("pcapng: total block length %u is too large (> %u)",
968 bh
->block_total_length
, MAX_BLOCK_SIZE
);
972 /* "(Enhanced) Packet Block" read fixed part */
973 errno
= WTAP_ERR_CANT_READ
;
976 * Is this block long enough to be an EPB?
978 if (bh
->block_total_length
< MIN_EPB_SIZE
) {
982 *err
= WTAP_ERR_BAD_FILE
;
983 *err_info
= g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
984 bh
->block_total_length
, MIN_EPB_SIZE
);
987 bytes_read
= file_read(&epb
, sizeof epb
, fh
);
988 if (bytes_read
!= sizeof epb
) {
989 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
990 *err
= file_error(fh
, err_info
);
993 block_read
= bytes_read
;
995 if (pn
->byte_swapped
) {
996 packet
.interface_id
= BSWAP32(epb
.interface_id
);
997 packet
.drops_count
= -1; /* invalid */
998 packet
.ts_high
= BSWAP32(epb
.timestamp_high
);
999 packet
.ts_low
= BSWAP32(epb
.timestamp_low
);
1000 packet
.cap_len
= BSWAP32(epb
.captured_len
);
1001 packet
.packet_len
= BSWAP32(epb
.packet_len
);
1003 packet
.interface_id
= epb
.interface_id
;
1004 packet
.drops_count
= -1; /* invalid */
1005 packet
.ts_high
= epb
.timestamp_high
;
1006 packet
.ts_low
= epb
.timestamp_low
;
1007 packet
.cap_len
= epb
.captured_len
;
1008 packet
.packet_len
= epb
.packet_len
;
1010 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1011 packet
.interface_id
, packet
.cap_len
, packet
.packet_len
);
1014 * Is this block long enough to be a PB?
1016 if (bh
->block_total_length
< MIN_PB_SIZE
) {
1020 *err
= WTAP_ERR_BAD_FILE
;
1021 *err_info
= g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1022 bh
->block_total_length
, MIN_PB_SIZE
);
1025 bytes_read
= file_read(&pb
, sizeof pb
, fh
);
1026 if (bytes_read
!= sizeof pb
) {
1027 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1028 *err
= file_error(fh
, err_info
);
1031 block_read
= bytes_read
;
1033 if (pn
->byte_swapped
) {
1034 packet
.interface_id
= BSWAP16(pb
.interface_id
);
1035 packet
.drops_count
= BSWAP16(pb
.drops_count
);
1036 packet
.ts_high
= BSWAP32(pb
.timestamp_high
);
1037 packet
.ts_low
= BSWAP32(pb
.timestamp_low
);
1038 packet
.cap_len
= BSWAP32(pb
.captured_len
);
1039 packet
.packet_len
= BSWAP32(pb
.packet_len
);
1041 packet
.interface_id
= pb
.interface_id
;
1042 packet
.drops_count
= pb
.drops_count
;
1043 packet
.ts_high
= pb
.timestamp_high
;
1044 packet
.ts_low
= pb
.timestamp_low
;
1045 packet
.cap_len
= pb
.captured_len
;
1046 packet
.packet_len
= pb
.packet_len
;
1048 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1049 packet
.interface_id
, packet
.cap_len
, packet
.packet_len
);
1053 * How much padding is there at the end of the packet data?
1055 if ((packet
.cap_len
% 4) != 0)
1056 padding
= 4 - (packet
.cap_len
% 4);
1060 /* add padding bytes to "block total length" */
1061 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1062 if (bh
->block_total_length
% 4) {
1063 block_total_length
= bh
->block_total_length
+ 4 - (bh
->block_total_length
% 4);
1065 block_total_length
= bh
->block_total_length
;
1067 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length
);
1070 * Is this block long enough to hold the packet data?
1073 if (block_total_length
<
1074 MIN_EPB_SIZE
+ packet
.cap_len
+ padding
) {
1078 *err
= WTAP_ERR_BAD_FILE
;
1079 *err_info
= g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1080 block_total_length
, packet
.cap_len
);
1084 if (block_total_length
<
1085 MIN_PB_SIZE
+ packet
.cap_len
+ padding
) {
1089 *err
= WTAP_ERR_BAD_FILE
;
1090 *err_info
= g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1091 block_total_length
, packet
.cap_len
);
1096 if (packet
.cap_len
> packet
.packet_len
) {
1097 *err
= WTAP_ERR_BAD_FILE
;
1098 *err_info
= g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u.",
1099 packet
.cap_len
, packet
.packet_len
);
1102 if (packet
.cap_len
> WTAP_MAX_PACKET_SIZE
) {
1103 *err
= WTAP_ERR_BAD_FILE
;
1104 *err_info
= g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1105 packet
.cap_len
, WTAP_MAX_PACKET_SIZE
);
1108 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1111 packet
.interface_id
);
1113 if (packet
.interface_id
>= pn
->number_of_interfaces
) {
1114 *err
= WTAP_ERR_BAD_FILE
;
1115 *err_info
= g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
1116 packet
.interface_id
, pn
->number_of_interfaces
);
1119 int_data
= g_array_index(pn
->interface_data
, interface_data_t
,
1120 packet
.interface_id
);
1122 wblock
->packet_header
->presence_flags
= WTAP_HAS_TS
|WTAP_HAS_CAP_LEN
|WTAP_HAS_INTERFACE_ID
;
1124 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1125 int_data
.wtap_encap
,
1126 wtap_encap_string(int_data
.wtap_encap
),
1127 pcap_get_phdr_size(int_data
.wtap_encap
, &wblock
->packet_header
->pseudo_header
));
1128 wblock
->packet_header
->interface_id
= packet
.interface_id
;
1129 wblock
->packet_header
->pkt_encap
= int_data
.wtap_encap
;
1131 memset((void *)&wblock
->packet_header
->pseudo_header
, 0, sizeof(union wtap_pseudo_header
));
1132 pseudo_header_len
= pcap_process_pseudo_header(fh
,
1133 WTAP_FILE_TYPE_SUBTYPE_PCAPNG
,
1134 int_data
.wtap_encap
,
1137 wblock
->packet_header
,
1140 if (pseudo_header_len
< 0) {
1143 block_read
+= pseudo_header_len
;
1144 if (pseudo_header_len
!= pcap_get_phdr_size(int_data
.wtap_encap
, &wblock
->packet_header
->pseudo_header
)) {
1145 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1148 wblock
->packet_header
->caplen
= packet
.cap_len
- pseudo_header_len
;
1149 wblock
->packet_header
->len
= packet
.packet_len
- pseudo_header_len
;
1151 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1152 ts
= (((guint64
)packet
.ts_high
) << 32) | ((guint64
)packet
.ts_low
);
1153 wblock
->packet_header
->ts
.secs
= (time_t)(ts
/ int_data
.time_units_per_second
);
1154 wblock
->packet_header
->ts
.nsecs
= (int)(((ts
% int_data
.time_units_per_second
) * 1000000000) / int_data
.time_units_per_second
);
1156 /* "(Enhanced) Packet Block" read capture data */
1157 errno
= WTAP_ERR_CANT_READ
;
1158 if (!wtap_read_packet_bytes(fh
, wblock
->frame_buffer
,
1159 packet
.cap_len
- pseudo_header_len
, err
, err_info
))
1161 block_read
+= packet
.cap_len
- pseudo_header_len
;
1163 /* jump over potential padding bytes at end of the packet data */
1165 file_offset64
= file_seek(fh
, padding
, SEEK_CUR
, err
);
1166 if (file_offset64
<= 0) {
1171 block_read
+= padding
;
1174 /* Option defaults */
1175 wblock
->packet_header
->opt_comment
= NULL
;
1176 wblock
->packet_header
->drop_count
= -1;
1177 wblock
->packet_header
->pack_flags
= 0;
1179 /* FCS length default */
1180 fcslen
= pn
->if_fcslen
;
1188 errno
= WTAP_ERR_CANT_READ
;
1189 to_read
= block_total_length
-
1190 (int)sizeof(pcapng_block_header_t
) -
1191 block_read
- /* fixed and variable part, including padding */
1192 (int)sizeof(bh
->block_total_length
);
1194 /* Allocate enough memory to hold all options */
1195 opt_cont_buf_len
= to_read
;
1196 option_content
= (char *)g_try_malloc(opt_cont_buf_len
);
1197 if (opt_cont_buf_len
!= 0 && option_content
== NULL
) {
1198 *err
= ENOMEM
; /* we assume we're out of memory */
1202 while (to_read
!= 0) {
1204 bytes_read
= pcapng_read_option(fh
, pn
, &oh
, option_content
, opt_cont_buf_len
, to_read
, err
, err_info
);
1205 if (bytes_read
<= 0) {
1206 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1209 block_read
+= bytes_read
;
1210 to_read
-= bytes_read
;
1212 /* handle option content */
1213 switch (oh
.option_code
) {
1216 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read
);
1218 /* padding should be ok here, just get out of this */
1222 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
1223 wblock
->packet_header
->presence_flags
|= WTAP_HAS_COMMENTS
;
1224 wblock
->packet_header
->opt_comment
= g_strndup(option_content
, oh
.option_length
);
1225 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh
.option_length
, wblock
->packet_header
->opt_comment
);
1227 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh
.option_length
);
1230 case(OPT_EPB_FLAGS
):
1231 if (oh
.option_length
== 4) {
1232 /* Don't cast a char[] into a guint32--the
1233 * char[] may not be aligned correctly.
1235 wblock
->packet_header
->presence_flags
|= WTAP_HAS_PACK_FLAGS
;
1236 memcpy(&wblock
->packet_header
->pack_flags
, option_content
, sizeof(guint32
));
1237 if (pn
->byte_swapped
)
1238 wblock
->packet_header
->pack_flags
= BSWAP32(wblock
->packet_header
->pack_flags
);
1239 if (wblock
->packet_header
->pack_flags
& 0x000001E0) {
1240 /* The FCS length is present */
1241 fcslen
= (wblock
->packet_header
->pack_flags
& 0x000001E0) >> 5;
1243 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock
->packet_header
->pack_flags
);
1245 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh
.option_length
);
1249 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1250 oh
.option_code
, oh
.option_length
);
1252 case(OPT_EPB_DROPCOUNT
):
1253 if (oh
.option_length
== 8) {
1254 /* Don't cast a char[] into a guint32--the
1255 * char[] may not be aligned correctly.
1257 wblock
->packet_header
->presence_flags
|= WTAP_HAS_DROP_COUNT
;
1258 memcpy(&wblock
->packet_header
->drop_count
, option_content
, sizeof(guint64
));
1259 if (pn
->byte_swapped
)
1260 wblock
->packet_header
->drop_count
= BSWAP64(wblock
->packet_header
->drop_count
);
1262 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER
"u", wblock
->packet_header
->drop_count
);
1264 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh
.option_length
);
1268 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1269 oh
.option_code
, oh
.option_length
);
1273 g_free(option_content
);
1275 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG
, int_data
.wtap_encap
,
1276 (union wtap_pseudo_header
*)&wblock
->packet_header
->pseudo_header
,
1277 buffer_start_ptr(wblock
->frame_buffer
),
1278 (int) (packet
.cap_len
- pseudo_header_len
),
1279 pn
->byte_swapped
, fcslen
);
1285 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
)
1289 guint64 file_offset64
;
1290 interface_data_t int_data
;
1291 pcapng_simple_packet_block_t spb
;
1292 wtapng_simple_packet_t simple_packet
;
1293 guint32 block_total_length
;
1295 int pseudo_header_len
;
1298 * Is this block long enough to be an SPB?
1300 if (bh
->block_total_length
< MIN_SPB_SIZE
) {
1304 *err
= WTAP_ERR_BAD_FILE
;
1305 *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",
1306 bh
->block_total_length
, MIN_SPB_SIZE
);
1310 /* Don't try to allocate memory for a huge number of options, as
1311 that might fail and, even if it succeeds, it might not leave
1312 any address space or memory+backing store for anything else.
1314 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1315 We check for this *after* checking the SHB for its byte
1316 order magic number, so that non-pcap-ng files are less
1317 likely to be treated as bad pcap-ng files. */
1318 if (bh
->block_total_length
> MAX_BLOCK_SIZE
) {
1319 *err
= WTAP_ERR_BAD_FILE
;
1320 *err_info
= g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1321 bh
->block_total_length
, MAX_BLOCK_SIZE
);
1325 /* "Simple Packet Block" read fixed part */
1326 errno
= WTAP_ERR_CANT_READ
;
1327 bytes_read
= file_read(&spb
, sizeof spb
, fh
);
1328 if (bytes_read
!= sizeof spb
) {
1329 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1330 *err
= file_error(fh
, err_info
);
1333 block_read
= bytes_read
;
1335 if (0 >= pn
->number_of_interfaces
) {
1336 *err
= WTAP_ERR_BAD_FILE
;
1337 *err_info
= g_strdup_printf("pcapng: SPB appeared before any IDBs");
1340 int_data
= g_array_index(pn
->interface_data
, interface_data_t
, 0);
1342 if (pn
->byte_swapped
) {
1343 simple_packet
.packet_len
= BSWAP32(spb
.packet_len
);
1345 simple_packet
.packet_len
= spb
.packet_len
;
1349 * The captured length is not a field in the SPB; it can be
1350 * calculated as the minimum of the snapshot length from the
1351 * IDB and the packet length, as per the pcap-ng spec.
1353 simple_packet
.cap_len
= simple_packet
.packet_len
;
1354 if (simple_packet
.cap_len
> int_data
.snap_len
)
1355 simple_packet
.cap_len
= int_data
.snap_len
;
1358 * How much padding is there at the end of the packet data?
1360 if ((simple_packet
.cap_len
% 4) != 0)
1361 padding
= 4 - (simple_packet
.cap_len
% 4);
1365 /* add padding bytes to "block total length" */
1366 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1367 if (bh
->block_total_length
% 4) {
1368 block_total_length
= bh
->block_total_length
+ 4 - (bh
->block_total_length
% 4);
1370 block_total_length
= bh
->block_total_length
;
1372 pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length
);
1375 * Is this block long enough to hold the packet data?
1377 if (block_total_length
< MIN_SPB_SIZE
+ simple_packet
.cap_len
+ padding
) {
1379 * No. That means that the problem is with the packet
1380 * length; the snapshot length can be bigger than the amount
1381 * of packet data in the block, as it's a *maximum* length,
1382 * not a *minimum* length.
1384 *err
= WTAP_ERR_BAD_FILE
;
1385 *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",
1386 block_total_length
, simple_packet
.packet_len
);
1390 if (simple_packet
.cap_len
> WTAP_MAX_PACKET_SIZE
) {
1391 *err
= WTAP_ERR_BAD_FILE
;
1392 *err_info
= g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1393 simple_packet
.cap_len
, WTAP_MAX_PACKET_SIZE
);
1396 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1397 simple_packet
.packet_len
);
1399 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1400 pcap_get_phdr_size(int_data
.wtap_encap
, &wblock
->packet_header
->pseudo_header
));
1402 /* No time stamp in a simple packet block; no options, either */
1403 wblock
->packet_header
->presence_flags
= WTAP_HAS_CAP_LEN
|WTAP_HAS_INTERFACE_ID
;
1404 wblock
->packet_header
->interface_id
= 0;
1405 wblock
->packet_header
->pkt_encap
= int_data
.wtap_encap
;
1406 wblock
->packet_header
->ts
.secs
= 0;
1407 wblock
->packet_header
->ts
.nsecs
= 0;
1408 wblock
->packet_header
->interface_id
= 0;
1409 wblock
->packet_header
->opt_comment
= NULL
;
1410 wblock
->packet_header
->drop_count
= 0;
1411 wblock
->packet_header
->pack_flags
= 0;
1413 memset((void *)&wblock
->packet_header
->pseudo_header
, 0, sizeof(union wtap_pseudo_header
));
1414 pseudo_header_len
= pcap_process_pseudo_header(fh
,
1415 WTAP_FILE_TYPE_SUBTYPE_PCAPNG
,
1416 int_data
.wtap_encap
,
1417 simple_packet
.cap_len
,
1419 wblock
->packet_header
,
1422 if (pseudo_header_len
< 0) {
1425 wblock
->packet_header
->caplen
= simple_packet
.cap_len
- pseudo_header_len
;
1426 wblock
->packet_header
->len
= simple_packet
.packet_len
- pseudo_header_len
;
1427 block_read
+= pseudo_header_len
;
1428 if (pseudo_header_len
!= pcap_get_phdr_size(int_data
.wtap_encap
, &wblock
->packet_header
->pseudo_header
)) {
1429 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1433 memset((void *)&wblock
->packet_header
->pseudo_header
, 0, sizeof(union wtap_pseudo_header
));
1435 /* "Simple Packet Block" read capture data */
1436 errno
= WTAP_ERR_CANT_READ
;
1437 if (!wtap_read_packet_bytes(fh
, wblock
->frame_buffer
,
1438 simple_packet
.cap_len
, err
, err_info
))
1440 block_read
+= simple_packet
.cap_len
;
1442 /* jump over potential padding bytes at end of the packet data */
1443 if ((simple_packet
.cap_len
% 4) != 0) {
1444 file_offset64
= file_seek(fh
, 4 - (simple_packet
.cap_len
% 4), SEEK_CUR
, err
);
1445 if (file_offset64
<= 0) {
1450 block_read
+= 4 - (simple_packet
.cap_len
% 4);
1453 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG
, int_data
.wtap_encap
,
1454 (union wtap_pseudo_header
*)&wblock
->packet_header
->pseudo_header
,
1455 buffer_start_ptr(wblock
->frame_buffer
),
1456 (int) simple_packet
.cap_len
,
1457 pn
->byte_swapped
, pn
->if_fcslen
);
1461 #define NRES_ENDOFRECORD 0
1462 #define NRES_IP4RECORD 1
1463 #define NRES_IP6RECORD 2
1464 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1465 /* IPv6 + MAXNAMELEN */
1466 #define INITIAL_NRB_REC_SIZE (16 + 64)
1469 * Find the end of the NUL-terminated name the beginning of which is pointed
1470 * to by p; record_len is the number of bytes remaining in the record.
1472 * Return the length of the name, including the terminating NUL.
1474 * If we don't find a terminating NUL, return -1 and set *err and
1475 * *err_info appropriately.
1478 name_resolution_block_find_name_end(const char *p
, guint record_len
, int *err
,
1485 if (record_len
== 0) {
1487 * We ran out of bytes in the record without
1490 *err
= WTAP_ERR_BAD_FILE
;
1491 *err_info
= g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1495 break; /* that's the terminating NUL */
1498 namelen
++; /* count this byte */
1501 /* Include the NUL in the name length. */
1506 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
)
1511 guint64 file_offset64
;
1512 pcapng_name_resolution_block_t nrb
;
1520 * Is this block long enough to be an NRB?
1522 if (bh
->block_total_length
< MIN_NRB_SIZE
) {
1526 *err
= WTAP_ERR_BAD_FILE
;
1527 *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",
1528 bh
->block_total_length
, MIN_NRB_SIZE
);
1532 /* Don't try to allocate memory for a huge number of options, as
1533 that might fail and, even if it succeeds, it might not leave
1534 any address space or memory+backing store for anything else.
1536 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1537 We check for this *after* checking the SHB for its byte
1538 order magic number, so that non-pcap-ng files are less
1539 likely to be treated as bad pcap-ng files. */
1540 if (bh
->block_total_length
> MAX_BLOCK_SIZE
) {
1541 *err
= WTAP_ERR_BAD_FILE
;
1542 *err_info
= g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1543 bh
->block_total_length
, MAX_BLOCK_SIZE
);
1547 errno
= WTAP_ERR_CANT_READ
;
1548 to_read
= bh
->block_total_length
- 8 - 4; /* We have read the header adn should not read the final block_total_length */
1550 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh
->block_total_length
);
1553 * Start out with a buffer big enough for an IPv6 address and one
1554 * 64-byte name; we'll make the buffer bigger if necessary.
1556 buffer_init(&nrb_rec
, INITIAL_NRB_REC_SIZE
);
1557 while (block_read
< to_read
) {
1559 * There must be at least one record's worth of data
1562 if ((size_t)(to_read
- block_read
) < sizeof nrb
) {
1563 buffer_free(&nrb_rec
);
1564 *err
= WTAP_ERR_BAD_FILE
;
1565 *err_info
= g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1566 to_read
- block_read
,
1570 bytes_read
= file_read(&nrb
, sizeof nrb
, fh
);
1571 if (bytes_read
!= sizeof nrb
) {
1572 buffer_free(&nrb_rec
);
1573 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1574 *err
= file_error(fh
, err_info
);
1577 block_read
+= bytes_read
;
1579 if (pn
->byte_swapped
) {
1580 nrb
.record_type
= BSWAP16(nrb
.record_type
);
1581 nrb
.record_len
= BSWAP16(nrb
.record_len
);
1584 if (to_read
- block_read
< nrb
.record_len
+ PADDING4(nrb
.record_len
)) {
1585 buffer_free(&nrb_rec
);
1586 *err
= WTAP_ERR_BAD_FILE
;
1587 *err_info
= g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1588 to_read
- block_read
,
1589 nrb
.record_len
+ PADDING4(nrb
.record_len
));
1592 switch (nrb
.record_type
) {
1593 case NRES_ENDOFRECORD
:
1594 /* There shouldn't be any more data */
1597 case NRES_IP4RECORD
:
1599 * The smallest possible record must have
1600 * a 4-byte IPv4 address, hence a minimum
1603 * (The pcap-NG spec really indicates
1604 * that it must be at least 5 bytes,
1605 * as there must be at least one name,
1606 * and it really must be at least 6
1607 * bytes, as the name mustn't be null,
1608 * but there's no need to fail if there
1609 * aren't any names at all, and we
1610 * should report a null name as such.)
1612 if (nrb
.record_len
< 4) {
1613 buffer_free(&nrb_rec
);
1614 *err
= WTAP_ERR_BAD_FILE
;
1615 *err_info
= g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1619 buffer_assure_space(&nrb_rec
, nrb
.record_len
);
1620 bytes_read
= file_read(buffer_start_ptr(&nrb_rec
),
1621 nrb
.record_len
, fh
);
1622 if (bytes_read
!= nrb
.record_len
) {
1623 buffer_free(&nrb_rec
);
1624 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1625 *err
= file_error(fh
, err_info
);
1628 block_read
+= bytes_read
;
1630 if (pn
->add_new_ipv4
) {
1632 * Scan through all the names in
1633 * the record and add them.
1636 buffer_start_ptr(&nrb_rec
), 4);
1637 if (pn
->byte_swapped
)
1638 v4_addr
= BSWAP32(v4_addr
);
1639 for (namep
= (char *)buffer_start_ptr(&nrb_rec
) + 4, record_len
= nrb
.record_len
- 4;
1641 namep
+= namelen
, record_len
-= namelen
) {
1643 * Scan forward for a null
1646 namelen
= name_resolution_block_find_name_end(namep
, record_len
, err
, err_info
);
1647 if (namelen
== -1) {
1648 buffer_free(&nrb_rec
);
1649 return -1; /* fail */
1651 pn
->add_new_ipv4(v4_addr
, namep
);
1655 file_offset64
= file_seek(fh
, PADDING4(nrb
.record_len
), SEEK_CUR
, err
);
1656 if (file_offset64
<= 0) {
1657 buffer_free(&nrb_rec
);
1662 block_read
+= PADDING4(nrb
.record_len
);
1664 case NRES_IP6RECORD
:
1666 * The smallest possible record must have
1667 * a 16-byte IPv6 address, hence a minimum
1670 * (The pcap-NG spec really indicates
1671 * that it must be at least 17 bytes,
1672 * as there must be at least one name,
1673 * and it really must be at least 18
1674 * bytes, as the name mustn't be null,
1675 * but there's no need to fail if there
1676 * aren't any names at all, and we
1677 * should report a null name as such.)
1679 if (nrb
.record_len
< 16) {
1680 buffer_free(&nrb_rec
);
1681 *err
= WTAP_ERR_BAD_FILE
;
1682 *err_info
= g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1686 if (to_read
< nrb
.record_len
) {
1687 buffer_free(&nrb_rec
);
1688 pcapng_debug0("pcapng_read_name_resolution_block: insufficient data for IPv6 record");
1691 buffer_assure_space(&nrb_rec
, nrb
.record_len
);
1692 bytes_read
= file_read(buffer_start_ptr(&nrb_rec
),
1693 nrb
.record_len
, fh
);
1694 if (bytes_read
!= nrb
.record_len
) {
1695 buffer_free(&nrb_rec
);
1696 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1697 *err
= file_error(fh
, err_info
);
1700 block_read
+= bytes_read
;
1702 if (pn
->add_new_ipv6
) {
1703 for (namep
= (char *)buffer_start_ptr(&nrb_rec
) + 16, record_len
= nrb
.record_len
- 16;
1705 namep
+= namelen
, record_len
-= namelen
) {
1707 * Scan forward for a null
1710 namelen
= name_resolution_block_find_name_end(namep
, record_len
, err
, err_info
);
1711 if (namelen
== -1) {
1712 buffer_free(&nrb_rec
);
1713 return -1; /* fail */
1715 pn
->add_new_ipv6(buffer_start_ptr(&nrb_rec
),
1720 file_offset64
= file_seek(fh
, PADDING4(nrb
.record_len
), SEEK_CUR
, err
);
1721 if (file_offset64
<= 0) {
1722 buffer_free(&nrb_rec
);
1727 block_read
+= PADDING4(nrb
.record_len
);
1730 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb
.record_type
);
1731 file_offset64
= file_seek(fh
, nrb
.record_len
+ PADDING4(nrb
.record_len
), SEEK_CUR
, err
);
1732 if (file_offset64
<= 0) {
1733 buffer_free(&nrb_rec
);
1738 block_read
+= nrb
.record_len
+ PADDING4(nrb
.record_len
);
1743 buffer_free(&nrb_rec
);
1748 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
)
1752 guint to_read
, opt_cont_buf_len
;
1753 pcapng_interface_statistics_block_t isb
;
1754 pcapng_option_header_t oh
;
1755 char *option_content
= NULL
; /* Allocate as large as the options block */
1758 * Is this block long enough to be an ISB?
1760 if (bh
->block_total_length
< MIN_ISB_SIZE
) {
1764 *err
= WTAP_ERR_BAD_FILE
;
1765 *err_info
= g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1766 bh
->block_total_length
, MIN_ISB_SIZE
);
1770 /* Don't try to allocate memory for a huge number of options, as
1771 that might fail and, even if it succeeds, it might not leave
1772 any address space or memory+backing store for anything else.
1774 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1775 We check for this *after* checking the SHB for its byte
1776 order magic number, so that non-pcap-ng files are less
1777 likely to be treated as bad pcap-ng files. */
1778 if (bh
->block_total_length
> MAX_BLOCK_SIZE
) {
1779 *err
= WTAP_ERR_BAD_FILE
;
1780 *err_info
= g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1781 bh
->block_total_length
, MAX_BLOCK_SIZE
);
1785 /* "Interface Statistics Block" read fixed part */
1786 errno
= WTAP_ERR_CANT_READ
;
1787 bytes_read
= file_read(&isb
, sizeof isb
, fh
);
1788 if (bytes_read
!= sizeof isb
) {
1789 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1790 *err
= file_error(fh
, err_info
);
1793 block_read
= bytes_read
;
1795 if (pn
->byte_swapped
) {
1796 wblock
->data
.if_stats
.interface_id
= BSWAP32(isb
.interface_id
);
1797 wblock
->data
.if_stats
.ts_high
= BSWAP32(isb
.timestamp_high
);
1798 wblock
->data
.if_stats
.ts_low
= BSWAP32(isb
.timestamp_low
);
1800 wblock
->data
.if_stats
.interface_id
= isb
.interface_id
;
1801 wblock
->data
.if_stats
.ts_high
= isb
.timestamp_high
;
1802 wblock
->data
.if_stats
.ts_low
= isb
.timestamp_low
;
1804 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock
->data
.if_stats
.interface_id
);
1806 /* Option defaults */
1807 wblock
->data
.if_stats
.opt_comment
= NULL
;
1808 wblock
->data
.if_stats
.isb_ifrecv
= -1;
1809 wblock
->data
.if_stats
.isb_ifdrop
= -1;
1810 wblock
->data
.if_stats
.isb_filteraccept
= -1;
1811 wblock
->data
.if_stats
.isb_osdrop
= -1;
1812 wblock
->data
.if_stats
.isb_usrdeliv
= -1;
1815 errno
= WTAP_ERR_CANT_READ
;
1816 to_read
= bh
->block_total_length
-
1817 (MIN_BLOCK_SIZE
+ block_read
); /* fixed and variable part, including padding */
1819 /* Allocate enough memory to hold all options */
1820 opt_cont_buf_len
= to_read
;
1821 option_content
= (char *)g_try_malloc(opt_cont_buf_len
);
1822 if (opt_cont_buf_len
!= 0 && option_content
== NULL
) {
1823 *err
= ENOMEM
; /* we assume we're out of memory */
1827 while (to_read
!= 0) {
1829 bytes_read
= pcapng_read_option(fh
, pn
, &oh
, option_content
, opt_cont_buf_len
, to_read
, err
, err_info
);
1830 if (bytes_read
<= 0) {
1831 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1834 block_read
+= bytes_read
;
1835 to_read
-= bytes_read
;
1837 /* handle option content */
1838 switch (oh
.option_code
) {
1839 case(0): /* opt_endofopt */
1841 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read
);
1843 /* padding should be ok here, just get out of this */
1846 case(1): /* opt_comment */
1847 if (oh
.option_length
> 0 && oh
.option_length
< opt_cont_buf_len
) {
1848 wblock
->data
.if_stats
.opt_comment
= g_strndup(option_content
, oh
.option_length
);
1849 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock
->data
.if_stats
.opt_comment
);
1851 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh
.option_length
);
1854 case(2): /* isb_starttime */
1855 if (oh
.option_length
== 8) {
1858 /* Don't cast a char[] into a guint32--the
1859 * char[] may not be aligned correctly.
1861 memcpy(&high
, option_content
, sizeof(guint32
));
1862 memcpy(&low
, option_content
+ sizeof(guint32
), sizeof(guint32
));
1863 if (pn
->byte_swapped
) {
1864 high
= BSWAP32(high
);
1867 wblock
->data
.if_stats
.isb_starttime
= (guint64
)high
;
1868 wblock
->data
.if_stats
.isb_starttime
<<= 32;
1869 wblock
->data
.if_stats
.isb_starttime
+= (guint64
)low
;
1870 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_starttime
);
1872 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh
.option_length
);
1875 case(3): /* isb_endtime */
1876 if (oh
.option_length
== 8) {
1879 /* Don't cast a char[] into a guint32--the
1880 * char[] may not be aligned correctly.
1882 memcpy(&high
, option_content
, sizeof(guint32
));
1883 memcpy(&low
, option_content
+ sizeof(guint32
), sizeof(guint32
));
1884 if (pn
->byte_swapped
) {
1885 high
= BSWAP32(high
);
1888 wblock
->data
.if_stats
.isb_endtime
= (guint64
)high
;
1889 wblock
->data
.if_stats
.isb_endtime
<<= 32;
1890 wblock
->data
.if_stats
.isb_endtime
+= (guint64
)low
;
1891 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_endtime
);
1893 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh
.option_length
);
1896 case(4): /* isb_ifrecv */
1897 if (oh
.option_length
== 8) {
1898 /* Don't cast a char[] into a guint32--the
1899 * char[] may not be aligned correctly.
1901 memcpy(&wblock
->data
.if_stats
.isb_ifrecv
, option_content
, sizeof(guint64
));
1902 if (pn
->byte_swapped
)
1903 wblock
->data
.if_stats
.isb_ifrecv
= BSWAP64(wblock
->data
.if_stats
.isb_ifrecv
);
1904 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_ifrecv
);
1906 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh
.option_length
);
1909 case(5): /* isb_ifdrop */
1910 if (oh
.option_length
== 8) {
1911 /* Don't cast a char[] into a guint32--the
1912 * char[] may not be aligned correctly.
1914 memcpy(&wblock
->data
.if_stats
.isb_ifdrop
, option_content
, sizeof(guint64
));
1915 if (pn
->byte_swapped
)
1916 wblock
->data
.if_stats
.isb_ifdrop
= BSWAP64(wblock
->data
.if_stats
.isb_ifdrop
);
1917 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_ifdrop
);
1919 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh
.option_length
);
1922 case(6): /* isb_filteraccept 6 */
1923 if (oh
.option_length
== 8) {
1924 /* Don't cast a char[] into a guint32--the
1925 * char[] may not be aligned correctly.
1927 memcpy(&wblock
->data
.if_stats
.isb_filteraccept
, option_content
, sizeof(guint64
));
1928 if (pn
->byte_swapped
)
1929 wblock
->data
.if_stats
.isb_ifdrop
= BSWAP64(wblock
->data
.if_stats
.isb_filteraccept
);
1930 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_filteraccept
);
1932 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh
.option_length
);
1935 case(7): /* isb_osdrop 7 */
1936 if (oh
.option_length
== 8) {
1937 /* Don't cast a char[] into a guint32--the
1938 * char[] may not be aligned correctly.
1940 memcpy(&wblock
->data
.if_stats
.isb_osdrop
, option_content
, sizeof(guint64
));
1941 if (pn
->byte_swapped
)
1942 wblock
->data
.if_stats
.isb_osdrop
= BSWAP64(wblock
->data
.if_stats
.isb_osdrop
);
1943 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_osdrop
);
1945 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh
.option_length
);
1948 case(8): /* isb_usrdeliv 8 */
1949 if (oh
.option_length
== 8) {
1950 /* Don't cast a char[] into a guint32--the
1951 * char[] may not be aligned correctly.
1953 memcpy(&wblock
->data
.if_stats
.isb_usrdeliv
, option_content
, sizeof(guint64
));
1954 if (pn
->byte_swapped
)
1955 wblock
->data
.if_stats
.isb_usrdeliv
= BSWAP64(wblock
->data
.if_stats
.isb_osdrop
);
1956 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER
"u", wblock
->data
.if_stats
.isb_usrdeliv
);
1958 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh
.option_length
);
1962 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1963 oh
.option_code
, oh
.option_length
);
1967 g_free(option_content
);
1974 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
)
1977 guint64 file_offset64
;
1978 guint32 block_total_length
;
1980 if (bh
->block_total_length
< MIN_BLOCK_SIZE
) {
1981 *err
= WTAP_ERR_BAD_FILE
;
1982 *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",
1983 bh
->block_total_length
, MIN_BLOCK_SIZE
);
1987 /* add padding bytes to "block total length" */
1988 /* (the "block total length" of some example files don't contain any padding bytes!) */
1989 if (bh
->block_total_length
% 4) {
1990 block_total_length
= bh
->block_total_length
+ 4 - (bh
->block_total_length
% 4);
1992 block_total_length
= bh
->block_total_length
;
1995 block_read
= block_total_length
- MIN_BLOCK_SIZE
;
1997 /* jump over this unknown block */
1998 file_offset64
= file_seek(fh
, block_read
, SEEK_CUR
, err
);
1999 if (file_offset64
<= 0) {
2010 pcapng_read_block(FILE_T fh
, gboolean first_block
, pcapng_t
*pn
, wtapng_block_t
*wblock
, int *err
, gchar
**err_info
)
2014 pcapng_block_header_t bh
;
2015 guint32 block_total_length
;
2018 /* Try to read the (next) block header */
2019 errno
= WTAP_ERR_CANT_READ
;
2020 bytes_read
= file_read(&bh
, sizeof bh
, fh
);
2021 if (bytes_read
!= sizeof bh
) {
2022 *err
= file_error(fh
, err_info
);
2023 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read
, (unsigned int)sizeof bh
, *err
);
2029 block_read
= bytes_read
;
2030 if (pn
->byte_swapped
) {
2031 bh
.block_type
= BSWAP32(bh
.block_type
);
2032 bh
.block_total_length
= BSWAP32(bh
.block_total_length
);
2035 wblock
->type
= bh
.block_type
;
2037 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh
.block_type
);
2041 * This is being read in by pcapng_open(), so this block
2042 * must be an SHB. If it's not, this is not a pcap-ng
2045 * XXX - check for various forms of Windows <-> UN*X
2046 * mangling, and suggest that the file might be a
2047 * pcap-ng file that was damaged in transit?
2049 if (bh
.block_type
!= BLOCK_TYPE_SHB
)
2050 return 0; /* not a pcap-ng file */
2053 switch (bh
.block_type
) {
2054 case(BLOCK_TYPE_SHB
):
2055 bytes_read
= pcapng_read_section_header_block(fh
, first_block
, &bh
, pn
, wblock
, err
, err_info
);
2057 case(BLOCK_TYPE_IDB
):
2058 bytes_read
= pcapng_read_if_descr_block(fh
, &bh
, pn
, wblock
, err
, err_info
);
2060 case(BLOCK_TYPE_PB
):
2061 bytes_read
= pcapng_read_packet_block(fh
, &bh
, pn
, wblock
, err
, err_info
, FALSE
);
2063 case(BLOCK_TYPE_SPB
):
2064 bytes_read
= pcapng_read_simple_packet_block(fh
, &bh
, pn
, wblock
, err
, err_info
);
2066 case(BLOCK_TYPE_EPB
):
2067 bytes_read
= pcapng_read_packet_block(fh
, &bh
, pn
, wblock
, err
, err_info
, TRUE
);
2069 case(BLOCK_TYPE_NRB
):
2070 bytes_read
= pcapng_read_name_resolution_block(fh
, &bh
, pn
, wblock
, err
, err_info
);
2072 case(BLOCK_TYPE_ISB
):
2073 bytes_read
= pcapng_read_interface_statistics_block(fh
, &bh
, pn
, wblock
, err
, err_info
);
2076 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh
.block_type
, bh
.block_total_length
);
2077 bytes_read
= pcapng_read_unknown_block(fh
, &bh
, pn
, wblock
, err
, err_info
);
2080 if (bytes_read
<= 0) {
2083 block_read
+= bytes_read
;
2085 /* sanity check: first and second block lengths must match */
2086 errno
= WTAP_ERR_CANT_READ
;
2087 bytes_read
= file_read(&block_total_length
, sizeof block_total_length
, fh
);
2088 if (bytes_read
!= sizeof block_total_length
) {
2089 pcapng_debug0("pcapng_read_block: couldn't read second block length");
2090 *err
= file_error(fh
, err_info
);
2092 *err
= WTAP_ERR_SHORT_READ
;
2095 block_read
+= bytes_read
;
2097 if (pn
->byte_swapped
)
2098 block_total_length
= BSWAP32(block_total_length
);
2100 if (!(block_total_length
== bh
.block_total_length
)) {
2101 *err
= WTAP_ERR_BAD_FILE
;
2102 *err_info
= g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
2103 bh
.block_total_length
, block_total_length
);
2110 /* Process an IDB that we've just read. */
2112 pcapng_process_idb(wtap
*wth
, pcapng_t
*pcapng
, wtapng_block_t
*wblock
)
2114 wtapng_if_descr_t int_data
;
2115 interface_data_t interface_data
;
2117 int_data
.wtap_encap
= wblock
->data
.if_descr
.wtap_encap
;
2118 int_data
.time_units_per_second
= wblock
->data
.if_descr
.time_units_per_second
;
2119 int_data
.link_type
= wblock
->data
.if_descr
.link_type
;
2120 int_data
.snap_len
= wblock
->data
.if_descr
.snap_len
;
2122 int_data
.opt_comment
= wblock
->data
.if_descr
.opt_comment
;
2123 int_data
.if_name
= wblock
->data
.if_descr
.if_name
;
2124 int_data
.if_description
= wblock
->data
.if_descr
.if_description
;
2125 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2126 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2127 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2128 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2129 int_data
.if_speed
= wblock
->data
.if_descr
.if_speed
;
2130 int_data
.if_tsresol
= wblock
->data
.if_descr
.if_tsresol
;
2131 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2132 int_data
.if_filter_str
= wblock
->data
.if_descr
.if_filter_str
;
2133 int_data
.bpf_filter_len
= wblock
->data
.if_descr
.bpf_filter_len
;
2134 int_data
.if_filter_bpf_bytes
= wblock
->data
.if_descr
.if_filter_bpf_bytes
;
2135 int_data
.if_os
= wblock
->data
.if_descr
.if_os
;
2136 int_data
.if_fcslen
= wblock
->data
.if_descr
.if_fcslen
;
2137 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2138 /* Interface statistics */
2139 int_data
.num_stat_entries
= 0;
2140 int_data
.interface_statistics
= NULL
;
2142 g_array_append_val(wth
->interface_data
, int_data
);
2143 wth
->number_of_interfaces
++;
2145 interface_data
.wtap_encap
= wblock
->data
.if_descr
.wtap_encap
;
2146 interface_data
.snap_len
= wblock
->data
.if_descr
.snap_len
;
2147 interface_data
.time_units_per_second
= wblock
->data
.if_descr
.time_units_per_second
;
2149 g_array_append_val(pcapng
->interface_data
, interface_data
);
2150 pcapng
->number_of_interfaces
++;
2153 /* classic wtap: open capture file */
2155 pcapng_open(wtap
*wth
, int *err
, gchar
**err_info
)
2159 wtapng_block_t wblock
;
2161 pcapng_block_header_t bh
;
2162 gint64 saved_offset
;
2164 pn
.shb_read
= FALSE
;
2165 /* we don't know the byte swapping of the file yet */
2166 pn
.byte_swapped
= FALSE
;
2168 pn
.version_major
= -1;
2169 pn
.version_minor
= -1;
2170 pn
.interface_data
= g_array_new(FALSE
, FALSE
, sizeof(interface_data_t
));
2171 pn
.number_of_interfaces
= 0;
2174 /* we don't expect any packet blocks yet */
2175 wblock
.frame_buffer
= NULL
;
2176 wblock
.packet_header
= NULL
;
2177 wblock
.file_encap
= &wth
->file_encap
;
2179 pcapng_debug0("pcapng_open: opening file");
2180 /* read first block */
2181 bytes_read
= pcapng_read_block(wth
->fh
, TRUE
, &pn
, &wblock
, err
, err_info
);
2182 if (bytes_read
<= 0) {
2183 pcapng_debug0("pcapng_open: couldn't read first SHB");
2184 *err
= file_error(wth
->fh
, err_info
);
2185 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
2190 /* first block must be a "Section Header Block" */
2191 if (wblock
.type
!= BLOCK_TYPE_SHB
) {
2193 * XXX - check for damage from transferring a file
2194 * between Windows and UN*X as text rather than
2197 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock
.type
);
2203 * At this point, we've decided this is a pcap-NG file, not
2204 * some other type of file, so we can't return 0, as that
2205 * means "this isn't a pcap-NG file, try some other file
2208 wth
->shb_hdr
.opt_comment
= wblock
.data
.section
.opt_comment
;
2209 wth
->shb_hdr
.shb_hardware
= wblock
.data
.section
.shb_hardware
;
2210 wth
->shb_hdr
.shb_os
= wblock
.data
.section
.shb_os
;
2211 wth
->shb_hdr
.shb_user_appl
= wblock
.data
.section
.shb_user_appl
;
2213 wth
->file_encap
= WTAP_ENCAP_UNKNOWN
;
2214 wth
->snapshot_length
= 0;
2215 wth
->tsprecision
= WTAP_FILE_TSPREC_NSEC
;
2216 pcapng
= (pcapng_t
*)g_malloc(sizeof(pcapng_t
));
2217 wth
->priv
= (void *)pcapng
;
2220 wth
->subtype_read
= pcapng_read
;
2221 wth
->subtype_seek_read
= pcapng_seek_read
;
2222 wth
->subtype_close
= pcapng_close
;
2223 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_PCAPNG
;
2226 wth
->interface_data
= g_array_new(FALSE
, FALSE
, sizeof(wtapng_if_descr_t
));
2227 wth
->number_of_interfaces
= 0;
2229 /* Loop over all IDB:s that appear before any packets */
2231 /* peek at next block */
2232 /* Try to read the (next) block header */
2233 saved_offset
= file_tell(wth
->fh
);
2234 errno
= WTAP_ERR_CANT_READ
;
2235 bytes_read
= file_read(&bh
, sizeof bh
, wth
->fh
);
2236 if (bytes_read
== 0) {
2237 pcapng_debug0("No more IDBs available...");
2240 if (bytes_read
!= sizeof bh
) {
2241 *err
= file_error(wth
->fh
, err_info
);
2242 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
);
2244 *err
= WTAP_ERR_SHORT_READ
;
2248 /* go back to where we were */
2249 file_seek(wth
->fh
, saved_offset
, SEEK_SET
, err
);
2251 if (pn
.byte_swapped
) {
2252 bh
.block_type
= BSWAP32(bh
.block_type
);
2255 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh
.block_type
);
2257 if (bh
.block_type
!= BLOCK_TYPE_IDB
) {
2258 break; /* No more IDB:s */
2260 bytes_read
= pcapng_read_block(wth
->fh
, FALSE
, &pn
, &wblock
, err
, err_info
);
2261 if (bytes_read
== 0) {
2262 pcapng_debug0("No more IDBs available...");
2265 if (bytes_read
<= 0) {
2266 pcapng_debug0("pcapng_open: couldn't read IDB");
2267 *err
= file_error(wth
->fh
, err_info
);
2269 *err
= WTAP_ERR_SHORT_READ
;
2272 pcapng_process_idb(wth
, pcapng
, &wblock
);
2273 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth
->number_of_interfaces
, *wblock
.file_encap
);
2279 /* classic wtap: read packet */
2281 pcapng_read(wtap
*wth
, int *err
, gchar
**err_info
, gint64
*data_offset
)
2283 pcapng_t
*pcapng
= (pcapng_t
*)wth
->priv
;
2285 wtapng_block_t wblock
;
2286 wtapng_if_descr_t
*wtapng_if_descr
;
2287 wtapng_if_stats_t if_stats
;
2289 *data_offset
= file_tell(wth
->fh
);
2290 pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER
"d", *data_offset
);
2292 wblock
.frame_buffer
= wth
->frame_buffer
;
2293 wblock
.packet_header
= &wth
->phdr
;
2294 wblock
.file_encap
= &wth
->file_encap
;
2296 pcapng
->add_new_ipv4
= wth
->add_new_ipv4
;
2297 pcapng
->add_new_ipv6
= wth
->add_new_ipv6
;
2299 /* read next block */
2301 bytes_read
= pcapng_read_block(wth
->fh
, FALSE
, pcapng
, &wblock
, err
, err_info
);
2302 if (bytes_read
<= 0) {
2303 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER
"d", *data_offset
);
2304 pcapng_debug0("pcapng_read: couldn't read packet block");
2308 switch (wblock
.type
) {
2310 case(BLOCK_TYPE_SHB
):
2311 /* We don't currently support multi-section files. */
2312 wth
->phdr
.pkt_encap
= WTAP_ENCAP_UNKNOWN
;
2313 *err
= WTAP_ERR_UNSUPPORTED
;
2314 *err_info
= g_strdup_printf("pcapng: multi-section files not currently supported.");
2317 case(BLOCK_TYPE_PB
):
2318 case(BLOCK_TYPE_SPB
):
2319 case(BLOCK_TYPE_EPB
):
2320 /* packet block - we've found a packet */
2323 case(BLOCK_TYPE_IDB
):
2324 /* A new interface */
2325 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2326 *data_offset
+= bytes_read
;
2327 pcapng_process_idb(wth
, pcapng
, &wblock
);
2330 case(BLOCK_TYPE_NRB
):
2331 /* More name resolution entries */
2332 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2333 *data_offset
+= bytes_read
;
2336 case(BLOCK_TYPE_ISB
):
2337 /* Another interface statistics report */
2338 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2339 *data_offset
+= bytes_read
;
2340 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER
"d", *data_offset
);
2341 if (wth
->number_of_interfaces
< wblock
.data
.if_stats
.interface_id
) {
2342 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces", wblock
.data
.if_stats
.interface_id
);
2344 /* Get the interface description */
2345 wtapng_if_descr
= &g_array_index(wth
->interface_data
, wtapng_if_descr_t
, wblock
.data
.if_stats
.interface_id
);
2346 if (wtapng_if_descr
->num_stat_entries
== 0) {
2347 /* First ISB found, no previous entry */
2348 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2349 wtapng_if_descr
->interface_statistics
= g_array_new(FALSE
, FALSE
, sizeof(wtapng_if_stats_t
));
2352 if_stats
.interface_id
= wblock
.data
.if_stats
.interface_id
;
2353 if_stats
.ts_high
= wblock
.data
.if_stats
.ts_high
;
2354 if_stats
.ts_low
= wblock
.data
.if_stats
.ts_low
;
2356 if_stats
.opt_comment
= wblock
.data
.if_stats
.opt_comment
; /* NULL if not available */
2357 if_stats
.isb_starttime
= wblock
.data
.if_stats
.isb_starttime
;
2358 if_stats
.isb_endtime
= wblock
.data
.if_stats
.isb_endtime
;
2359 if_stats
.isb_ifrecv
= wblock
.data
.if_stats
.isb_ifrecv
;
2360 if_stats
.isb_ifdrop
= wblock
.data
.if_stats
.isb_ifdrop
;
2361 if_stats
.isb_filteraccept
= wblock
.data
.if_stats
.isb_filteraccept
;
2362 if_stats
.isb_osdrop
= wblock
.data
.if_stats
.isb_osdrop
;
2363 if_stats
.isb_usrdeliv
= wblock
.data
.if_stats
.isb_usrdeliv
;
2365 g_array_append_val(wtapng_if_descr
->interface_statistics
, if_stats
);
2366 wtapng_if_descr
->num_stat_entries
++;
2371 /* XXX - improve handling of "unknown" blocks */
2372 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock
.type
);
2373 *data_offset
+= bytes_read
;
2374 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER
"d", *data_offset
);
2381 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2382 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER
"d", *data_offset
+ bytes_read
);
2388 /* classic wtap: seek to file position and read packet */
2390 pcapng_seek_read(wtap
*wth
, gint64 seek_off
,
2391 struct wtap_pkthdr
*phdr
, Buffer
*buf
, int length _U_
,
2392 int *err
, gchar
**err_info
)
2394 pcapng_t
*pcapng
= (pcapng_t
*)wth
->priv
;
2395 guint64 bytes_read64
;
2397 wtapng_block_t wblock
;
2400 /* seek to the right file position */
2401 bytes_read64
= file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
);
2402 if (bytes_read64
<= 0) {
2403 return FALSE
; /* Seek error */
2405 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER
"u", seek_off
);
2407 wblock
.frame_buffer
= buf
;
2408 wblock
.packet_header
= phdr
;
2409 wblock
.file_encap
= &wth
->file_encap
;
2411 /* read the block */
2412 bytes_read
= pcapng_read_block(wth
->random_fh
, FALSE
, pcapng
, &wblock
, err
, err_info
);
2413 if (bytes_read
<= 0) {
2414 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2415 *err
, errno
, bytes_read
);
2419 /* block must be a "Packet Block", an "Enhanced Packet Block",
2420 or a "Simple Packet Block" */
2421 if (wblock
.type
!= BLOCK_TYPE_PB
&& wblock
.type
!= BLOCK_TYPE_EPB
&&
2422 wblock
.type
!= BLOCK_TYPE_SPB
) {
2423 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock
.type
);
2431 /* classic wtap: close capture file */
2433 pcapng_close(wtap
*wth
)
2435 pcapng_t
*pcapng
= (pcapng_t
*)wth
->priv
;
2437 pcapng_debug0("pcapng_close: closing file");
2438 if (pcapng
->interface_data
!= NULL
) {
2439 g_array_free(pcapng
->interface_data
, TRUE
);
2446 GArray
*interface_data
;
2447 guint number_of_interfaces
;
2451 pcapng_write_section_header_block(wtap_dumper
*wdh
, int *err
)
2453 pcapng_block_header_t bh
;
2454 pcapng_section_header_block_t shb
;
2455 const guint32 zero_pad
= 0;
2456 gboolean have_options
= FALSE
;
2457 struct option option_hdr
; /* guint16 type, guint16 value_length; */
2458 guint32 options_total_length
= 0;
2459 guint32 comment_len
= 0, shb_hardware_len
= 0, shb_os_len
= 0, shb_user_appl_len
= 0;
2460 guint32 comment_pad_len
= 0, shb_hardware_pad_len
= 0, shb_os_pad_len
= 0, shb_user_appl_pad_len
= 0;
2463 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2464 /* Check if we should write comment option */
2465 if (wdh
->shb_hdr
->opt_comment
) {
2466 have_options
= TRUE
;
2467 comment_len
= (guint32
)strlen(wdh
->shb_hdr
->opt_comment
) & 0xffff;
2468 if ((comment_len
% 4)) {
2469 comment_pad_len
= 4 - (comment_len
% 4);
2471 comment_pad_len
= 0;
2473 options_total_length
= options_total_length
+ comment_len
+ comment_pad_len
+ 4 /* comment options tag */ ;
2476 /* Check if we should write shb_hardware option */
2477 if (wdh
->shb_hdr
->shb_hardware
) {
2478 have_options
= TRUE
;
2479 shb_hardware_len
= (guint32
)strlen(wdh
->shb_hdr
->shb_hardware
) & 0xffff;
2480 if ((shb_hardware_len
% 4)) {
2481 shb_hardware_pad_len
= 4 - (shb_hardware_len
% 4);
2483 shb_hardware_pad_len
= 0;
2485 options_total_length
= options_total_length
+ shb_hardware_len
+ shb_hardware_pad_len
+ 4 /* options tag */ ;
2488 /* Check if we should write shb_os option */
2489 if (wdh
->shb_hdr
->shb_os
) {
2490 have_options
= TRUE
;
2491 shb_os_len
= (guint32
)strlen(wdh
->shb_hdr
->shb_os
) & 0xffff;
2492 if ((shb_os_len
% 4)) {
2493 shb_os_pad_len
= 4 - (shb_os_len
% 4);
2497 options_total_length
= options_total_length
+ shb_os_len
+ shb_os_pad_len
+ 4 /* options tag */ ;
2500 /* Check if we should write shb_user_appl option */
2501 if (wdh
->shb_hdr
->shb_user_appl
) {
2502 have_options
= TRUE
;
2503 shb_user_appl_len
= (guint32
)strlen(wdh
->shb_hdr
->shb_user_appl
) & 0xffff;
2504 if ((shb_user_appl_len
% 4)) {
2505 shb_user_appl_pad_len
= 4 - (shb_user_appl_len
% 4);
2507 shb_user_appl_pad_len
= 0;
2509 options_total_length
= options_total_length
+ shb_user_appl_len
+ shb_user_appl_pad_len
+ 4 /* options tag */ ;
2512 /* End-of-options tag */
2513 options_total_length
+= 4;
2517 /* write block header */
2518 bh
.block_type
= BLOCK_TYPE_SHB
;
2519 bh
.block_total_length
= (guint32
)(sizeof(bh
) + sizeof(shb
) + options_total_length
+ 4);
2520 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh
.block_total_length
, options_total_length
);
2522 if (!wtap_dump_file_write(wdh
, &bh
, sizeof bh
, err
))
2524 wdh
->bytes_dumped
+= sizeof bh
;
2526 /* write block fixed content */
2527 /* XXX - get these values from wblock? */
2528 shb
.magic
= 0x1A2B3C4D;
2529 shb
.version_major
= 1;
2530 shb
.version_minor
= 0;
2531 shb
.section_length
= -1;
2533 if (!wtap_dump_file_write(wdh
, &shb
, sizeof shb
, err
))
2535 wdh
->bytes_dumped
+= sizeof shb
;
2537 /* XXX - write (optional) block options
2545 option_hdr
.type
= OPT_COMMENT
;
2546 option_hdr
.value_length
= comment_len
;
2547 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2549 wdh
->bytes_dumped
+= 4;
2551 /* Write the comments string */
2552 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
);
2553 if (!wtap_dump_file_write(wdh
, wdh
->shb_hdr
->opt_comment
, comment_len
, err
))
2555 wdh
->bytes_dumped
+= comment_len
;
2557 /* write padding (if any) */
2558 if (comment_pad_len
!= 0) {
2559 if (!wtap_dump_file_write(wdh
, &zero_pad
, comment_pad_len
, err
))
2561 wdh
->bytes_dumped
+= comment_pad_len
;
2565 if (shb_hardware_len
) {
2566 option_hdr
.type
= OPT_SHB_HARDWARE
;
2567 option_hdr
.value_length
= shb_hardware_len
;
2568 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2570 wdh
->bytes_dumped
+= 4;
2572 /* Write the string */
2573 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
);
2574 if (!wtap_dump_file_write(wdh
, wdh
->shb_hdr
->shb_hardware
, shb_hardware_len
, err
))
2576 wdh
->bytes_dumped
+= shb_hardware_len
;
2578 /* write padding (if any) */
2579 if (shb_hardware_pad_len
!= 0) {
2580 if (!wtap_dump_file_write(wdh
, &zero_pad
, shb_hardware_pad_len
, err
))
2582 wdh
->bytes_dumped
+= shb_hardware_pad_len
;
2587 option_hdr
.type
= OPT_SHB_OS
;
2588 option_hdr
.value_length
= shb_os_len
;
2589 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2591 wdh
->bytes_dumped
+= 4;
2593 /* Write the string */
2594 pcapng_debug3("pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u" , wdh
->shb_hdr
->shb_os
, shb_os_len
, shb_os_pad_len
);
2595 if (!wtap_dump_file_write(wdh
, wdh
->shb_hdr
->shb_os
, shb_os_len
, err
))
2597 wdh
->bytes_dumped
+= shb_os_len
;
2599 /* write padding (if any) */
2600 if (shb_os_pad_len
!= 0) {
2601 if (!wtap_dump_file_write(wdh
, &zero_pad
, shb_os_pad_len
, err
))
2603 wdh
->bytes_dumped
+= shb_os_pad_len
;
2607 if (shb_user_appl_len
) {
2608 option_hdr
.type
= OPT_SHB_USERAPPL
;
2609 option_hdr
.value_length
= shb_user_appl_len
;
2610 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2612 wdh
->bytes_dumped
+= 4;
2614 /* Write the comments string */
2615 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
);
2616 if (!wtap_dump_file_write(wdh
, wdh
->shb_hdr
->shb_user_appl
, shb_user_appl_len
, err
))
2618 wdh
->bytes_dumped
+= shb_user_appl_len
;
2620 /* write padding (if any) */
2621 if (shb_user_appl_pad_len
!= 0) {
2622 if (!wtap_dump_file_write(wdh
, &zero_pad
, shb_user_appl_pad_len
, err
))
2624 wdh
->bytes_dumped
+= shb_user_appl_pad_len
;
2628 /* Write end of options if we have otions */
2630 option_hdr
.type
= OPT_EOFOPT
;
2631 option_hdr
.value_length
= 0;
2632 if (!wtap_dump_file_write(wdh
, &zero_pad
, 4, err
))
2634 wdh
->bytes_dumped
+= 4;
2637 /* write block footer */
2638 if (!wtap_dump_file_write(wdh
, &bh
.block_total_length
,
2639 sizeof bh
.block_total_length
, err
))
2641 wdh
->bytes_dumped
+= sizeof bh
.block_total_length
;
2646 #define IDB_OPT_IF_NAME 2
2647 #define IDB_OPT_IF_DESCR 3
2648 #define IDB_OPT_IF_SPEED 8
2649 #define IDB_OPT_IF_TSRESOL 9
2650 #define IDB_OPT_IF_FILTER 11
2651 #define IDB_OPT_IF_OS 12
2654 pcapng_write_if_descr_block(wtap_dumper
*wdh
, wtapng_if_descr_t
*int_data
, int *err
)
2656 pcapng_block_header_t bh
;
2657 pcapng_interface_description_block_t idb
;
2658 const guint32 zero_pad
= 0;
2659 gboolean have_options
= FALSE
;
2660 struct option option_hdr
; /* guint16 type, guint16 value_length; */
2661 guint32 options_total_length
= 0;
2662 guint32 comment_len
= 0, if_name_len
= 0, if_description_len
= 0 , if_os_len
= 0, if_filter_str_len
= 0;
2663 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;
2666 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2667 int_data
->link_type
,
2668 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data
->link_type
)),
2669 int_data
->snap_len
);
2671 if (int_data
->link_type
== (guint16
)-1) {
2672 *err
= WTAP_ERR_UNSUPPORTED_ENCAP
;
2676 /* Calculate options length */
2677 if (int_data
->opt_comment
) {
2678 have_options
= TRUE
;
2679 comment_len
= (guint32
)strlen(int_data
->opt_comment
) & 0xffff;
2680 if ((comment_len
% 4)) {
2681 comment_pad_len
= 4 - (comment_len
% 4);
2683 comment_pad_len
= 0;
2685 options_total_length
= options_total_length
+ comment_len
+ comment_pad_len
+ 4 /* comment options tag */ ;
2689 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2691 if (int_data
->if_name
) {
2692 have_options
= TRUE
;
2693 if_name_len
= (guint32
)strlen(int_data
->if_name
) & 0xffff;
2694 if ((if_name_len
% 4)) {
2695 if_name_pad_len
= 4 - (if_name_len
% 4);
2697 if_name_pad_len
= 0;
2699 options_total_length
= options_total_length
+ if_name_len
+ if_name_pad_len
+ 4 /* comment options tag */ ;
2703 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2705 if (int_data
->if_description
) {
2706 have_options
= TRUE
;
2707 if_description_len
= (guint32
)strlen(int_data
->if_description
) & 0xffff;
2708 if ((if_description_len
% 4)) {
2709 if_description_pad_len
= 4 - (if_description_len
% 4);
2711 if_description_pad_len
= 0;
2713 options_total_length
= options_total_length
+ if_description_len
+ if_description_pad_len
+ 4 /* comment options tag */ ;
2715 /* Currently not handled
2716 * if_IPv4addr 4 Interface network address and netmask.
2717 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2718 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2719 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2722 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2724 if (int_data
->if_speed
!= 0) {
2725 have_options
= TRUE
;
2726 options_total_length
= options_total_length
+ 8 + 4;
2729 * if_tsresol 9 Resolution of timestamps.
2731 if (int_data
->if_tsresol
!= 0) {
2732 have_options
= TRUE
;
2733 options_total_length
= options_total_length
+ 4 + 4;
2736 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2739 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2740 * 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).
2742 if (int_data
->if_filter_str
) {
2743 have_options
= TRUE
;
2744 if_filter_str_len
= (guint32
)(strlen(int_data
->if_filter_str
) + 1) & 0xffff;
2745 if ((if_filter_str_len
% 4)) {
2746 if_filter_str_pad_len
= 4 - (if_filter_str_len
% 4);
2748 if_filter_str_pad_len
= 0;
2750 options_total_length
= options_total_length
+ if_filter_str_len
+ if_filter_str_pad_len
+ 4 /* comment options tag */ ;
2753 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2755 if (int_data
->if_os
) {
2756 have_options
= TRUE
;
2757 if_os_len
= (guint32
)strlen(int_data
->if_os
) & 0xffff;
2758 if ((if_os_len
% 4)) {
2759 if_os_pad_len
= 4 - (if_os_len
% 4);
2763 options_total_length
= options_total_length
+ if_os_len
+ if_os_pad_len
+ 4 /* comment options tag */ ;
2766 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2767 * -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.
2769 if (int_data
->if_fcslen
!= 0) {
2772 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2773 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2777 /* End-of-options tag */
2778 options_total_length
+= 4;
2781 /* write block header */
2782 bh
.block_type
= BLOCK_TYPE_IDB
;
2783 bh
.block_total_length
= (guint32
)(sizeof(bh
) + sizeof(idb
) + options_total_length
+ 4);
2785 if (!wtap_dump_file_write(wdh
, &bh
, sizeof bh
, err
))
2787 wdh
->bytes_dumped
+= sizeof bh
;
2789 /* write block fixed content */
2790 idb
.linktype
= int_data
->link_type
;
2792 idb
.snaplen
= int_data
->snap_len
;
2794 if (!wtap_dump_file_write(wdh
, &idb
, sizeof idb
, err
))
2796 wdh
->bytes_dumped
+= sizeof idb
;
2798 /* XXX - write (optional) block options */
2799 if (comment_len
!= 0) {
2800 option_hdr
.type
= OPT_COMMENT
;
2801 option_hdr
.value_length
= comment_len
;
2802 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2804 wdh
->bytes_dumped
+= 4;
2806 /* Write the comments string */
2807 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
);
2808 if (!wtap_dump_file_write(wdh
, int_data
->opt_comment
, comment_len
, err
))
2810 wdh
->bytes_dumped
+= comment_len
;
2812 /* write padding (if any) */
2813 if (comment_pad_len
!= 0) {
2814 if (!wtap_dump_file_write(wdh
, &zero_pad
, comment_pad_len
, err
))
2816 wdh
->bytes_dumped
+= comment_pad_len
;
2820 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2822 if (if_name_len
!=0) {
2823 option_hdr
.type
= IDB_OPT_IF_NAME
;
2824 option_hdr
.value_length
= if_name_len
;
2825 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2827 wdh
->bytes_dumped
+= 4;
2829 /* Write the comments string */
2830 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
);
2831 if (!wtap_dump_file_write(wdh
, int_data
->if_name
, if_name_len
, err
))
2833 wdh
->bytes_dumped
+= if_name_len
;
2835 /* write padding (if any) */
2836 if (if_name_pad_len
!= 0) {
2837 if (!wtap_dump_file_write(wdh
, &zero_pad
, if_name_pad_len
, err
))
2839 wdh
->bytes_dumped
+= if_name_pad_len
;
2843 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2845 if (if_description_len
!= 0) {
2846 option_hdr
.type
= IDB_OPT_IF_NAME
;
2847 option_hdr
.value_length
= if_description_len
;
2848 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2850 wdh
->bytes_dumped
+= 4;
2852 /* Write the comments string */
2853 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
);
2854 if (!wtap_dump_file_write(wdh
, int_data
->if_description
, if_description_len
, err
))
2856 wdh
->bytes_dumped
+= if_description_len
;
2858 /* write padding (if any) */
2859 if (if_description_pad_len
!= 0) {
2860 if (!wtap_dump_file_write(wdh
, &zero_pad
, if_description_pad_len
, err
))
2862 wdh
->bytes_dumped
+= if_description_pad_len
;
2865 /* Currently not handled
2866 * if_IPv4addr 4 Interface network address and netmask.
2867 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2868 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2869 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2872 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2874 if (int_data
->if_speed
!= 0) {
2875 option_hdr
.type
= IDB_OPT_IF_SPEED
;
2876 option_hdr
.value_length
= 8;
2877 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2879 wdh
->bytes_dumped
+= 4;
2881 /* Write the comments string */
2882 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER
"u (bps)", int_data
->if_speed
);
2883 if (!wtap_dump_file_write(wdh
, &int_data
->if_speed
, sizeof(guint64
), err
))
2885 wdh
->bytes_dumped
+= 8;
2888 * if_tsresol 9 Resolution of timestamps.
2889 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
2890 * If the Most Significant Bit is equal to zero, the remaining bits indicates
2891 * the resolution of the timestamp as as a negative power of 10
2893 if (int_data
->if_tsresol
!= 0) {
2894 option_hdr
.type
= IDB_OPT_IF_TSRESOL
;
2895 option_hdr
.value_length
= 1;
2896 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2898 wdh
->bytes_dumped
+= 4;
2900 /* Write the time stamp resolution */
2901 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data
->if_tsresol
);
2902 if (!wtap_dump_file_write(wdh
, &int_data
->if_tsresol
, 1, err
))
2904 wdh
->bytes_dumped
+= 1;
2905 if (!wtap_dump_file_write(wdh
, &zero_pad
, 3, err
))
2907 wdh
->bytes_dumped
+= 3;
2910 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2913 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2915 /* Libpcap string variant */
2916 if (if_filter_str_len
!=0) {
2917 option_hdr
.type
= IDB_OPT_IF_FILTER
;
2918 option_hdr
.value_length
= if_filter_str_len
;
2919 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2920 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2922 wdh
->bytes_dumped
+= 4;
2924 /* Write the zero indicating libpcap filter variant */
2925 if (!wtap_dump_file_write(wdh
, &zero_pad
, 1, err
))
2927 wdh
->bytes_dumped
+= 1;
2929 /* Write the comments string */
2930 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
);
2931 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2932 if (!wtap_dump_file_write(wdh
, int_data
->if_filter_str
, if_filter_str_len
-1, err
))
2934 wdh
->bytes_dumped
+= if_filter_str_len
- 1;
2936 /* write padding (if any) */
2937 if (if_filter_str_pad_len
!= 0) {
2938 if (!wtap_dump_file_write(wdh
, &zero_pad
, if_filter_str_pad_len
, err
))
2940 wdh
->bytes_dumped
+= if_filter_str_pad_len
;
2944 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2946 if (if_os_len
!= 0) {
2947 option_hdr
.type
= IDB_OPT_IF_OS
;
2948 option_hdr
.value_length
= if_os_len
;
2949 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2951 wdh
->bytes_dumped
+= 4;
2953 /* Write the comments string */
2954 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
);
2955 if (!wtap_dump_file_write(wdh
, int_data
->if_os
, if_os_len
, err
))
2957 wdh
->bytes_dumped
+= if_os_len
;
2959 /* write padding (if any) */
2960 if (if_os_pad_len
!= 0) {
2961 if (!wtap_dump_file_write(wdh
, &zero_pad
, if_os_pad_len
, err
))
2963 wdh
->bytes_dumped
+= if_os_pad_len
;
2968 option_hdr
.type
= OPT_EOFOPT
;
2969 option_hdr
.value_length
= 0;
2970 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
2972 wdh
->bytes_dumped
+= 4;
2976 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2979 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2980 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2983 /* write block footer */
2984 if (!wtap_dump_file_write(wdh
, &bh
.block_total_length
,
2985 sizeof bh
.block_total_length
, err
))
2987 wdh
->bytes_dumped
+= sizeof bh
.block_total_length
;
2992 #define ISB_STARTTIME 2
2993 #define ISB_ENDTIME 3
2994 #define ISB_IFRECV 4
2995 #define ISB_IFDROP 5
2996 #define ISB_FILTERACCEPT 6
2997 #define ISB_OSDROP 7
2998 #define ISB_USRDELIV 8
3001 pcapng_write_interface_statistics_block(wtap_dumper
*wdh
, wtapng_if_stats_t
*if_stats
, int *err
)
3004 pcapng_block_header_t bh
;
3005 pcapng_interface_statistics_block_t isb
;
3006 const guint32 zero_pad
= 0;
3007 gboolean have_options
= FALSE
;
3008 struct option option_hdr
; /* guint16 type, guint16 value_length; */
3009 guint32 options_total_length
= 0;
3010 guint32 comment_len
= 0;
3011 guint32 comment_pad_len
= 0;
3013 pcapng_debug0("pcapng_write_interface_statistics_block");
3016 /* Calculate options length */
3017 if (if_stats
->opt_comment
) {
3018 have_options
= TRUE
;
3019 comment_len
= (guint32
)strlen(if_stats
->opt_comment
) & 0xffff;
3020 if ((comment_len
% 4)) {
3021 comment_pad_len
= 4 - (comment_len
% 4);
3023 comment_pad_len
= 0;
3025 options_total_length
= options_total_length
+ comment_len
+ comment_pad_len
+ 4 /* comment options tag */ ;
3027 /*guint64 isb_starttime */
3028 if (if_stats
->isb_starttime
!= 0) {
3029 have_options
= TRUE
;
3030 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3032 /*guint64 isb_endtime */
3033 if (if_stats
->isb_endtime
!= 0) {
3034 have_options
= TRUE
;
3035 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3037 /*guint64 isb_ifrecv */
3038 if (if_stats
->isb_ifrecv
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3039 have_options
= TRUE
;
3040 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3042 /*guint64 isb_ifdrop */
3043 if (if_stats
->isb_ifdrop
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3044 have_options
= TRUE
;
3045 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3047 /*guint64 isb_filteraccept */
3048 if (if_stats
->isb_filteraccept
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3049 have_options
= TRUE
;
3050 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3052 /*guint64 isb_osdrop */
3053 if (if_stats
->isb_osdrop
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3054 have_options
= TRUE
;
3055 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3057 /*guint64 isb_usrdeliv */
3058 if (if_stats
->isb_usrdeliv
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3059 have_options
= TRUE
;
3060 options_total_length
= options_total_length
+ 8 + 4 /* options tag */ ;
3063 /* write block header */
3065 /* End-of-optios tag */
3066 options_total_length
+= 4;
3069 /* write block header */
3070 bh
.block_type
= BLOCK_TYPE_ISB
;
3071 bh
.block_total_length
= (guint32
)(sizeof(bh
) + sizeof(isb
) + options_total_length
+ 4);
3073 if (!wtap_dump_file_write(wdh
, &bh
, sizeof bh
, err
))
3075 wdh
->bytes_dumped
+= sizeof bh
;
3077 /* write block fixed content */
3078 isb
.interface_id
= if_stats
->interface_id
;
3079 isb
.timestamp_high
= if_stats
->ts_high
;
3080 isb
.timestamp_low
= if_stats
->ts_low
;
3083 if (!wtap_dump_file_write(wdh
, &isb
, sizeof isb
, err
))
3085 wdh
->bytes_dumped
+= sizeof isb
;
3087 /* write (optional) block options */
3089 option_hdr
.type
= OPT_COMMENT
;
3090 option_hdr
.value_length
= comment_len
;
3091 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3093 wdh
->bytes_dumped
+= 4;
3095 /* Write the comments string */
3096 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
);
3097 if (!wtap_dump_file_write(wdh
, if_stats
->opt_comment
, comment_len
, err
))
3099 wdh
->bytes_dumped
+= comment_len
;
3101 /* write padding (if any) */
3102 if (comment_pad_len
!= 0) {
3103 if (!wtap_dump_file_write(wdh
, &zero_pad
, comment_pad_len
, err
))
3105 wdh
->bytes_dumped
+= comment_pad_len
;
3108 /*guint64 isb_starttime */
3109 if (if_stats
->isb_starttime
!= 0) {
3112 option_hdr
.type
= ISB_STARTTIME
;
3113 option_hdr
.value_length
= 8;
3114 high
= (guint32
)((if_stats
->isb_starttime
>>32) & 0xffffffff);
3115 low
= (guint32
)(if_stats
->isb_starttime
& 0xffffffff);
3116 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3118 wdh
->bytes_dumped
+= 4;
3120 /* Write isb_starttime */
3121 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_starttime
);
3122 if (!wtap_dump_file_write(wdh
, &high
, 4, err
))
3124 wdh
->bytes_dumped
+= 4;
3125 if (!wtap_dump_file_write(wdh
, &low
, 4, err
))
3127 wdh
->bytes_dumped
+= 4;
3129 /*guint64 isb_endtime */
3130 if (if_stats
->isb_endtime
!= 0) {
3133 option_hdr
.type
= ISB_ENDTIME
;
3134 option_hdr
.value_length
= 8;
3135 high
= (guint32
)((if_stats
->isb_endtime
>>32) & 0xffffffff);
3136 low
= (guint32
)(if_stats
->isb_endtime
& 0xffffffff);
3137 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3139 wdh
->bytes_dumped
+= 4;
3141 /* Write isb_endtime */
3142 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_endtime
);
3143 if (!wtap_dump_file_write(wdh
, &high
, 4, err
))
3145 wdh
->bytes_dumped
+= 4;
3146 if (!wtap_dump_file_write(wdh
, &low
, 4, err
))
3148 wdh
->bytes_dumped
+= 4;
3150 /*guint64 isb_ifrecv;*/
3151 if (if_stats
->isb_ifrecv
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3152 option_hdr
.type
= ISB_IFRECV
;
3153 option_hdr
.value_length
= 8;
3154 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3156 wdh
->bytes_dumped
+= 4;
3158 /* Write isb_ifrecv */
3159 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_ifrecv
);
3160 if (!wtap_dump_file_write(wdh
, &if_stats
->isb_ifrecv
, 8, err
))
3162 wdh
->bytes_dumped
+= 8;
3164 /*guint64 isb_ifdrop;*/
3165 if (if_stats
->isb_ifdrop
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3166 option_hdr
.type
= ISB_IFDROP
;
3167 option_hdr
.value_length
= 8;
3168 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3170 wdh
->bytes_dumped
+= 4;
3172 /* Write isb_ifdrop */
3173 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_ifdrop
);
3174 if (!wtap_dump_file_write(wdh
, &if_stats
->isb_ifdrop
, 8, err
))
3176 wdh
->bytes_dumped
+= 8;
3178 /*guint64 isb_filteraccept;*/
3179 if (if_stats
->isb_filteraccept
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3180 option_hdr
.type
= ISB_FILTERACCEPT
;
3181 option_hdr
.value_length
= 8;
3182 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3184 wdh
->bytes_dumped
+= 4;
3186 /* Write isb_filteraccept */
3187 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_filteraccept
);
3188 if (!wtap_dump_file_write(wdh
, &if_stats
->isb_filteraccept
, 8, err
))
3190 wdh
->bytes_dumped
+= 8;
3192 /*guint64 isb_osdrop;*/
3193 if (if_stats
->isb_osdrop
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3194 option_hdr
.type
= ISB_OSDROP
;
3195 option_hdr
.value_length
= 8;
3196 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3198 wdh
->bytes_dumped
+= 4;
3200 /* Write isb_osdrop */
3201 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_osdrop
);
3202 if (!wtap_dump_file_write(wdh
, &if_stats
->isb_osdrop
, 8, err
))
3204 wdh
->bytes_dumped
+= 8;
3206 /*guint64 isb_usrdeliv;*/
3207 if (if_stats
->isb_usrdeliv
!= G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3208 option_hdr
.type
= ISB_USRDELIV
;
3209 option_hdr
.value_length
= 8;
3210 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3212 wdh
->bytes_dumped
+= 4;
3214 /* Write isb_usrdeliv */
3215 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER
"u" , if_stats
->isb_usrdeliv
);
3216 if (!wtap_dump_file_write(wdh
, &if_stats
->isb_usrdeliv
, 8, err
))
3218 wdh
->bytes_dumped
+= 8;
3222 option_hdr
.type
= OPT_EOFOPT
;
3223 option_hdr
.value_length
= 0;
3224 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3226 wdh
->bytes_dumped
+= 4;
3229 /* write block footer */
3230 if (!wtap_dump_file_write(wdh
, &bh
.block_total_length
,
3231 sizeof bh
.block_total_length
, err
))
3233 wdh
->bytes_dumped
+= sizeof bh
.block_total_length
;
3241 pcapng_write_enhanced_packet_block(wtap_dumper
*wdh
,
3242 const struct wtap_pkthdr
*phdr
,
3243 const union wtap_pseudo_header
*pseudo_header
, const guint8
*pd
, int *err
)
3245 pcapng_block_header_t bh
;
3246 pcapng_enhanced_packet_block_t epb
;
3248 const guint32 zero_pad
= 0;
3251 gboolean have_options
= FALSE
;
3252 guint32 options_total_length
= 0;
3253 struct option option_hdr
;
3254 guint32 comment_len
= 0, comment_pad_len
= 0;
3255 wtapng_if_descr_t int_data
;
3257 phdr_len
= (guint32
)pcap_get_phdr_size(phdr
->pkt_encap
, pseudo_header
);
3258 if ((phdr_len
+ phdr
->caplen
) % 4) {
3259 pad_len
= 4 - ((phdr_len
+ phdr
->caplen
) % 4);
3264 /* Check if we should write comment option */
3265 if (phdr
->opt_comment
) {
3266 have_options
= TRUE
;
3267 comment_len
= (guint32
)strlen(phdr
->opt_comment
) & 0xffff;
3268 if ((comment_len
% 4)) {
3269 comment_pad_len
= 4 - (comment_len
% 4);
3271 comment_pad_len
= 0;
3273 options_total_length
= options_total_length
+ comment_len
+ comment_pad_len
+ 4 /* comment options tag */ ;
3275 if (phdr
->presence_flags
& WTAP_HAS_PACK_FLAGS
) {
3276 have_options
= TRUE
;
3277 options_total_length
= options_total_length
+ 8;
3280 /* End-of optios tag */
3281 options_total_length
+= 4;
3284 /* write (enhanced) packet block header */
3285 bh
.block_type
= BLOCK_TYPE_EPB
;
3286 bh
.block_total_length
= (guint32
)sizeof(bh
) + (guint32
)sizeof(epb
) + phdr_len
+ phdr
->caplen
+ pad_len
+ options_total_length
+ 4;
3288 if (!wtap_dump_file_write(wdh
, &bh
, sizeof bh
, err
))
3290 wdh
->bytes_dumped
+= sizeof bh
;
3292 /* write block fixed content */
3293 if (phdr
->presence_flags
& WTAP_HAS_INTERFACE_ID
)
3294 epb
.interface_id
= phdr
->interface_id
;
3297 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3298 * data to pcap-NG files even if we *don't* have interface
3301 epb
.interface_id
= 0;
3304 * Split the 64-bit timestamp into two 32-bit pieces, using
3305 * the time stamp resolution for the interface.
3307 if (epb
.interface_id
>= wdh
->number_of_interfaces
) {
3309 * Our caller is doing something bad.
3311 *err
= WTAP_ERR_INTERNAL
;
3314 int_data
= g_array_index(wdh
->interface_data
, wtapng_if_descr_t
,
3316 ts
= ((guint64
)phdr
->ts
.secs
) * int_data
.time_units_per_second
+
3317 (((guint64
)phdr
->ts
.nsecs
) * int_data
.time_units_per_second
) / 1000000000;
3318 epb
.timestamp_high
= (guint32
)(ts
>> 32);
3319 epb
.timestamp_low
= (guint32
)ts
;
3320 epb
.captured_len
= phdr
->caplen
+ phdr_len
;
3321 epb
.packet_len
= phdr
->len
+ phdr_len
;
3323 if (!wtap_dump_file_write(wdh
, &epb
, sizeof epb
, err
))
3325 wdh
->bytes_dumped
+= sizeof epb
;
3327 /* write pseudo header */
3328 if (!pcap_write_phdr(wdh
, phdr
->pkt_encap
, pseudo_header
, err
)) {
3331 wdh
->bytes_dumped
+= phdr_len
;
3333 /* write packet data */
3334 if (!wtap_dump_file_write(wdh
, pd
, phdr
->caplen
, err
))
3336 wdh
->bytes_dumped
+= phdr
->caplen
;
3338 /* write padding (if any) */
3340 if (!wtap_dump_file_write(wdh
, &zero_pad
, pad_len
, err
))
3342 wdh
->bytes_dumped
+= pad_len
;
3345 /* XXX - write (optional) block options */
3346 /* options defined in Section 2.5 (Options)
3347 * Name Code Length Description
3348 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3350 * Enhanced Packet Block options
3351 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3352 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3353 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3354 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3355 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3356 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3357 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3358 * The hash covers only the packet, not the header added by the capture driver:
3359 * this gives the possibility to calculate it inside the network card.
3360 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3361 * data acquisition system and the capture library.
3362 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3363 * between this packet and the preceding one.
3364 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3366 if (phdr
->opt_comment
) {
3367 option_hdr
.type
= OPT_COMMENT
;
3368 option_hdr
.value_length
= comment_len
;
3369 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3371 wdh
->bytes_dumped
+= 4;
3373 /* Write the comments string */
3374 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr
->opt_comment
, comment_len
, comment_pad_len
);
3375 if (!wtap_dump_file_write(wdh
, phdr
->opt_comment
, comment_len
, err
))
3377 wdh
->bytes_dumped
+= comment_len
;
3379 /* write padding (if any) */
3380 if (comment_pad_len
!= 0) {
3381 if (!wtap_dump_file_write(wdh
, &zero_pad
, comment_pad_len
, err
))
3383 wdh
->bytes_dumped
+= comment_pad_len
;
3386 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3390 if (phdr
->presence_flags
& WTAP_HAS_PACK_FLAGS
) {
3391 option_hdr
.type
= OPT_EPB_FLAGS
;
3392 option_hdr
.value_length
= 4;
3393 if (!wtap_dump_file_write(wdh
, &option_hdr
, 4, err
))
3395 wdh
->bytes_dumped
+= 4;
3396 if (!wtap_dump_file_write(wdh
, &phdr
->pack_flags
, 4, err
))
3398 wdh
->bytes_dumped
+= 4;
3399 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr
->pack_flags
);
3401 /* Write end of options if we have otions */
3403 if (!wtap_dump_file_write(wdh
, &zero_pad
, 4, err
))
3405 wdh
->bytes_dumped
+= 4;
3408 /* write block footer */
3409 if (!wtap_dump_file_write(wdh
, &bh
.block_total_length
,
3410 sizeof bh
.block_total_length
, err
))
3412 wdh
->bytes_dumped
+= sizeof bh
.block_total_length
;
3418 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3420 pcapng_write_name_resolution_block(wtap_dumper
*wdh
, int *err
)
3422 pcapng_block_header_t bh
;
3423 pcapng_name_resolution_block_t nrb
;
3425 gint rec_off
, namelen
, tot_rec_len
;
3426 hashipv4_t
*ipv4_hash_list_entry
;
3427 hashipv6_t
*ipv6_hash_list_entry
;
3430 if ((!wdh
->addrinfo_lists
) || ((!wdh
->addrinfo_lists
->ipv4_addr_list
)&&(!wdh
->addrinfo_lists
->ipv6_addr_list
))) {
3434 rec_off
= 8; /* block type + block total length */
3435 bh
.block_type
= BLOCK_TYPE_NRB
;
3436 bh
.block_total_length
= rec_off
+ 8; /* end-of-record + block total length */
3437 rec_data
= (guint8
*)g_malloc(NRES_REC_MAX_SIZE
);
3439 if (wdh
->addrinfo_lists
->ipv4_addr_list
){
3441 ipv4_hash_list_entry
= (hashipv4_t
*)g_list_nth_data(wdh
->addrinfo_lists
->ipv4_addr_list
, i
);
3442 while(ipv4_hash_list_entry
!= NULL
){
3444 nrb
.record_type
= NRES_IP4RECORD
;
3445 namelen
= (gint
)strlen(ipv4_hash_list_entry
->name
) + 1;
3446 nrb
.record_len
= 4 + namelen
;
3447 tot_rec_len
= 4 + nrb
.record_len
+ PADDING4(nrb
.record_len
);
3449 if (rec_off
+ tot_rec_len
> NRES_REC_MAX_SIZE
){
3450 /* We know the total length now; copy the block header. */
3451 memcpy(rec_data
, &bh
, sizeof(bh
));
3454 memset(rec_data
+ rec_off
, 0, 4);
3457 memcpy(rec_data
+ rec_off
, &bh
.block_total_length
, sizeof(bh
.block_total_length
));
3459 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh
.block_total_length
, rec_off
);
3461 if (!wtap_dump_file_write(wdh
, rec_data
, bh
.block_total_length
, err
)) {
3465 wdh
->bytes_dumped
+= bh
.block_total_length
;
3467 /*Start a new NRB */
3468 rec_off
= 8; /* block type + block total length */
3469 bh
.block_type
= BLOCK_TYPE_NRB
;
3470 bh
.block_total_length
= rec_off
+ 8; /* end-of-record + block total length */
3474 bh
.block_total_length
+= tot_rec_len
;
3475 memcpy(rec_data
+ rec_off
, &nrb
, sizeof(nrb
));
3477 memcpy(rec_data
+ rec_off
, &(ipv4_hash_list_entry
->addr
), 4);
3479 memcpy(rec_data
+ rec_off
, ipv4_hash_list_entry
->name
, namelen
);
3481 memset(rec_data
+ rec_off
, 0, PADDING4(namelen
));
3482 rec_off
+= PADDING4(namelen
);
3483 pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry
->name
);
3486 ipv4_hash_list_entry
= (hashipv4_t
*)g_list_nth_data(wdh
->addrinfo_lists
->ipv4_addr_list
, i
);
3488 g_list_free(wdh
->addrinfo_lists
->ipv4_addr_list
);
3489 wdh
->addrinfo_lists
->ipv4_addr_list
= NULL
;
3492 if (wdh
->addrinfo_lists
->ipv6_addr_list
){
3494 ipv6_hash_list_entry
= (hashipv6_t
*)g_list_nth_data(wdh
->addrinfo_lists
->ipv6_addr_list
, i
);
3495 while(ipv6_hash_list_entry
!= NULL
){
3497 nrb
.record_type
= NRES_IP6RECORD
;
3498 namelen
= (gint
)strlen(ipv6_hash_list_entry
->name
) + 1;
3499 nrb
.record_len
= 16 + namelen
;
3500 tot_rec_len
= 16 + nrb
.record_len
+ PADDING4(nrb
.record_len
);
3502 if (rec_off
+ tot_rec_len
> NRES_REC_MAX_SIZE
){
3503 /* We know the total length now; copy the block header. */
3504 memcpy(rec_data
, &bh
, sizeof(bh
));
3507 memset(rec_data
+ rec_off
, 0, 4);
3510 memcpy(rec_data
+ rec_off
, &bh
.block_total_length
, sizeof(bh
.block_total_length
));
3512 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh
.block_total_length
, rec_off
);
3514 if (!wtap_dump_file_write(wdh
, rec_data
, bh
.block_total_length
, err
)) {
3518 wdh
->bytes_dumped
+= bh
.block_total_length
;
3520 /*Start a new NRB */
3521 rec_off
= 8; /* block type + block total length */
3522 bh
.block_type
= BLOCK_TYPE_NRB
;
3523 bh
.block_total_length
= rec_off
+ 8; /* end-of-record + block total length */
3527 bh
.block_total_length
+= tot_rec_len
;
3528 memcpy(rec_data
+ rec_off
, &nrb
, sizeof(nrb
));
3530 memcpy(rec_data
+ rec_off
, &(ipv6_hash_list_entry
->addr
), 16);
3532 memcpy(rec_data
+ rec_off
, ipv6_hash_list_entry
->name
, namelen
);
3534 memset(rec_data
+ rec_off
, 0, PADDING4(namelen
));
3535 rec_off
+= PADDING4(namelen
);
3536 pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry
->name
);
3539 ipv6_hash_list_entry
= (hashipv6_t
*)g_list_nth_data(wdh
->addrinfo_lists
->ipv6_addr_list
, i
);
3541 g_list_free(wdh
->addrinfo_lists
->ipv6_addr_list
);
3542 wdh
->addrinfo_lists
->ipv6_addr_list
= NULL
;
3545 /* We know the total length now; copy the block header. */
3546 memcpy(rec_data
, &bh
, sizeof(bh
));
3549 memset(rec_data
+ rec_off
, 0, 4);
3552 memcpy(rec_data
+ rec_off
, &bh
.block_total_length
, sizeof(bh
.block_total_length
));
3554 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh
.block_total_length
, rec_off
);
3556 if (!wtap_dump_file_write(wdh
, rec_data
, bh
.block_total_length
, err
)) {
3562 wdh
->bytes_dumped
+= bh
.block_total_length
;
3568 pcapng_lookup_interface_id_by_encap(int wtap_encap
, wtap_dumper
*wdh
)
3571 interface_data_t int_data
;
3572 pcapng_dump_t
*pcapng
= (pcapng_dump_t
*)wdh
->priv
;
3574 for(i
= 0; i
< (gint
)pcapng
->number_of_interfaces
; i
++) {
3575 int_data
= g_array_index(pcapng
->interface_data
, interface_data_t
, i
);
3576 if (wtap_encap
== int_data
.wtap_encap
) {
3584 static gboolean
pcapng_dump(wtap_dumper
*wdh
,
3585 const struct wtap_pkthdr
*phdr
,
3586 const guint8
*pd
, int *err
)
3588 const union wtap_pseudo_header
*pseudo_header
= &phdr
->pseudo_header
;
3589 /*interface_data_t int_data;*/
3590 /* pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv; */
3593 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3595 wtap_encap_string(phdr
->pkt_encap
));
3597 /* Flush any hostname resolution info we may have */
3598 pcapng_write_name_resolution_block(wdh
, err
);
3600 if (!pcapng_write_enhanced_packet_block(wdh
, phdr
, pseudo_header
, pd
, err
)) {
3608 /* Finish writing to a dump file.
3609 Returns TRUE on success, FALSE on failure. */
3610 static gboolean
pcapng_dump_close(wtap_dumper
*wdh
, int *err _U_
)
3613 pcapng_dump_t
*pcapng
= (pcapng_dump_t
*)wdh
->priv
;
3615 if ((wdh
->number_of_interfaces
> 0) && (wdh
->interface_data
!= NULL
)) {
3616 for (i
= 0; i
< (int)wdh
->number_of_interfaces
; i
++) {
3618 /* Get the interface description */
3619 wtapng_if_descr_t int_data
;
3621 int_data
= g_array_index(wdh
->interface_data
, wtapng_if_descr_t
, i
);
3622 for (j
= 0; j
< (int)int_data
.num_stat_entries
; j
++) {
3623 wtapng_if_stats_t if_stats
;
3625 if_stats
= g_array_index(int_data
.interface_statistics
, wtapng_if_stats_t
, j
);
3626 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats
.interface_id
);
3627 if (!pcapng_write_interface_statistics_block(wdh
, &if_stats
, err
)) {
3634 pcapng_debug0("pcapng_dump_close");
3635 g_array_free(pcapng
->interface_data
, TRUE
);
3636 pcapng
->number_of_interfaces
= 0;
3641 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3644 pcapng_dump_open(wtap_dumper
*wdh
, int *err
)
3646 pcapng_dump_t
*pcapng
;
3648 interface_data_t interface_data
;
3650 pcapng_debug0("pcapng_dump_open");
3651 /* This is a pcapng file */
3652 wdh
->subtype_write
= pcapng_dump
;
3653 wdh
->subtype_close
= pcapng_dump_close
;
3654 pcapng
= (pcapng_dump_t
*)g_malloc0(sizeof(pcapng_dump_t
));
3655 wdh
->priv
= (void *)pcapng
;
3656 pcapng
->interface_data
= g_array_new(FALSE
, FALSE
, sizeof(wtapng_if_descr_t
));
3658 if ((wdh
->number_of_interfaces
== 0) || (wdh
->interface_data
== NULL
)) {
3659 pcapng_debug0("There are no interfaces. Can't handle that...");
3660 *err
= WTAP_ERR_INTERNAL
;
3664 /* write the section header block */
3665 if (!pcapng_write_section_header_block(wdh
, err
)) {
3668 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3670 /* Write the Interface description blocks */
3671 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh
->number_of_interfaces
);
3673 for (i
= 0; i
< (int)wdh
->number_of_interfaces
; i
++) {
3675 /* Get the interface description */
3676 wtapng_if_descr_t int_data
;
3678 int_data
= g_array_index(wdh
->interface_data
, wtapng_if_descr_t
, i
);
3680 interface_data
.wtap_encap
= int_data
.wtap_encap
;
3681 interface_data
.time_units_per_second
= int_data
.time_units_per_second
;
3683 g_array_append_val(pcapng
->interface_data
, interface_data
);
3684 pcapng
->number_of_interfaces
++;
3686 if (!pcapng_write_if_descr_block(wdh
, &int_data
, err
)) {
3692 interface_id
= pcapng_lookup_interface_id_by_encap(phdr
->pkt_encap
, wdh
);
3693 if (interface_id
== G_MAXUINT32
) {
3695 * We haven't yet written out an interface description
3696 * block for an interface with this encapsulation.
3698 * Is this encapsulation even supported in pcap-ng?
3700 pcap_encap
= wtap_wtap_encap_to_pcap_encap(phdr
->pkt_encap
);
3701 if (pcap_encap
== -1) {
3705 *err
= WTAP_ERR_UNSUPPORTED_ENCAP
;
3709 /* write the interface description block */
3710 wblock
.frame_buffer
= NULL
;
3711 wblock
.pseudo_header
= NULL
;
3712 wblock
.packet_header
= NULL
;
3713 wblock
.file_encap
= NULL
;
3714 wblock
.type
= BLOCK_TYPE_IDB
;
3715 wblock
.data
.if_descr
.link_type
= pcap_encap
;
3716 wblock
.data
.if_descr
.snap_len
= (wdh
->snaplen
!= 0) ? wdh
->snaplen
:
3717 WTAP_MAX_PACKET_SIZE
; /* XXX */
3719 /* XXX - options unused */
3720 wblock
.data
.if_descr
.if_speed
= -1;
3721 /*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
3722 wblock
.data
.if_descr
.if_os
= NULL
;
3723 wblock
.data
.if_descr
.if_fcslen
= -1;
3725 if (!pcapng_write_if_descr_block(wdh
, &wblock
, err
)) {
3729 interface_id
= pcapng
->number_of_interfaces
;
3730 int_data
.wtap_encap
= phdr
->pkt_encap
;
3731 int_data
.time_units_per_second
= 0;
3732 g_array_append_val(pcapng
->interface_data
, int_data
);
3733 pcapng
->number_of_interfaces
++;
3735 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3738 wtap_encap_string(phdr
->pkt_encap
));
3746 /* Returns 0 if we could write the specified encapsulation type,
3747 an error indication otherwise. */
3748 int pcapng_dump_can_write_encap(int wtap_encap
)
3750 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3752 wtap_encap_string(wtap_encap
));
3754 /* Per-packet encapsulation is supported. */
3755 if (wtap_encap
== WTAP_ENCAP_PER_PACKET
)
3758 /* Make sure we can figure out this DLT type */
3759 if (wtap_wtap_encap_to_pcap_encap(wtap_encap
) == -1)
3760 return WTAP_ERR_UNSUPPORTED_ENCAP
;
3766 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3771 * indent-tabs-mode: nil
3774 * vi: set shiftwidth=4 tabstop=8 expandtab:
3775 * :indentSize=4:tabSize=8:noTabs=true: