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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 /* File format reference:
27 * http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
29 * http://wiki.wireshark.org/Development/PcapNg
40 /* Needed for addrinfo */
41 #ifdef HAVE_SYS_TYPES_H
42 # include <sys/types.h>
45 #ifdef HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
57 #ifdef HAVE_WINSOCK2_H
58 # include <winsock2.h>
61 #if defined(_WIN32) && defined(INET6)
62 # include <ws2tcpip.h>
66 #include "file_wrappers.h"
69 #include "pcap-common.h"
70 #include "pcap-encap.h"
74 #define pcapng_debug0(str) g_warning(str)
75 #define pcapng_debug1(str,p1) g_warning(str,p1)
76 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
77 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
79 #define pcapng_debug0(str)
80 #define pcapng_debug1(str,p1)
81 #define pcapng_debug2(str,p1,p2)
82 #define pcapng_debug3(str,p1,p2,p3)
86 pcapng_read(wtap *wth, int *err, gchar **err_info,
89 pcapng_seek_read(wtap *wth, gint64 seek_off,
90 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
91 int *err, gchar **err_info);
93 pcapng_close(wtap *wth);
96 /* pcapng: common block header for every block type */
97 typedef struct pcapng_block_header_s {
99 guint32 block_total_length;
100 /* x bytes block_body */
101 /* guint32 block_total_length */
102 } pcapng_block_header_t;
104 /* pcapng: section header block */
105 typedef struct pcapng_section_header_block_s {
106 /* pcapng_block_header_t */
108 guint16 version_major;
109 guint16 version_minor;
110 guint64 section_length; /* might be -1 for unknown */
111 /* ... Options ... */
112 } pcapng_section_header_block_t;
114 /* pcapng: interface description block */
115 typedef struct pcapng_interface_description_block_s {
119 /* ... Options ... */
120 } pcapng_interface_description_block_t;
122 /* pcapng: packet block (obsolete) */
123 typedef struct pcapng_packet_block_s {
124 guint16 interface_id;
126 guint32 timestamp_high;
127 guint32 timestamp_low;
128 guint32 captured_len;
130 /* ... Packet Data ... */
131 /* ... Padding ... */
132 /* ... Options ... */
133 } pcapng_packet_block_t;
135 /* pcapng: enhanced packet block */
136 typedef struct pcapng_enhanced_packet_block_s {
137 guint32 interface_id;
138 guint32 timestamp_high;
139 guint32 timestamp_low;
140 guint32 captured_len;
142 /* ... Packet Data ... */
143 /* ... Padding ... */
144 /* ... Options ... */
145 } pcapng_enhanced_packet_block_t;
147 /* pcapng: simple packet block */
148 typedef struct pcapng_simple_packet_block_s {
150 /* ... Packet Data ... */
151 /* ... Padding ... */
152 } pcapng_simple_packet_block_t;
154 /* pcapng: name resolution block */
155 typedef struct pcapng_name_resolution_block_s {
159 } pcapng_name_resolution_block_t;
161 /* pcapng: interface statistics block */
162 typedef struct pcapng_interface_statistics_block_s {
163 guint32 interface_id;
164 guint32 timestamp_high;
165 guint32 timestamp_low;
166 /* ... Options ... */
167 } pcapng_interface_statistics_block_t;
169 /* pcapng: common option header for every option type */
170 typedef struct pcapng_option_header_s {
172 guint16 option_length;
173 /* ... x bytes Option Body ... */
174 /* ... Padding ... */
175 } pcapng_option_header_t;
179 guint16 value_length;
183 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
184 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
185 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
186 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
187 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
188 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
189 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
193 #define OPT_COMMENT 1
194 #define OPT_SHB_HARDWARE 2
196 #define OPT_SHB_USERAPPL 4
198 /* Capture section */
200 /* Moved to wtap.h */
201 typedef struct wtapng_section_s {
203 guint64 section_length;
205 gchar *opt_comment; /* NULL if not available */
206 gchar *shb_hardware; /* NULL if not available */
207 gchar *shb_os; /* NULL if not available */
208 gchar *shb_user_appl; /* NULL if not available */
213 /* Moved to wtap.h */
215 /* Interface Description
218 * 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}" / ...
219 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
220 * 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
221 * 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"
222 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
223 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
224 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
225 * 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
226 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
227 * 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"
228 * 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" / ...
229 * 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
230 * 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 syncronized capture systems? 1234
233 typedef struct wtapng_if_descr_s {
239 gchar *opt_comment; /* NULL if not available */
240 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
241 gchar *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
242 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
243 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
244 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
245 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
246 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
247 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
248 * 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
250 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
251 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
252 * 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).
254 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. */
255 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. */
256 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
261 typedef struct wtapng_packet_s {
263 guint32 ts_high; /* seconds since 1.1.1970 */
264 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
265 guint32 cap_len; /* data length in the file */
266 guint32 packet_len; /* data length on the wire */
267 guint32 interface_id; /* identifier of the interface. */
268 guint16 drops_count; /* drops count, only valid for packet block */
269 /* 0xffff if information no available */
271 gchar *opt_comment; /* NULL if not available */
273 guint32 pack_flags; /* XXX - 0 for now (any value for "we don't have it"?) */
276 guint32 pseudo_header_len;
278 /* XXX - put the packet data / pseudo_header here as well? */
282 typedef struct wtapng_simple_packet_s {
284 guint32 cap_len; /* data length in the file */
285 guint32 packet_len; /* data length on the wire */
286 guint32 pseudo_header_len;
288 /* XXX - put the packet data / pseudo_header here as well? */
289 } wtapng_simple_packet_t;
291 /* Name Resolution */
292 typedef struct wtapng_name_res_s {
294 gchar *opt_comment; /* NULL if not available */
298 /* Interface Statistics */
299 typedef struct wtapng_if_stats_s {
301 guint32 interface_id;
305 gchar *opt_comment; /* NULL if not available */
306 guint64 isb_starttime;
310 guint64 isb_filteraccept;
312 guint64 isb_usrdeliv;
316 typedef struct wtapng_block_s {
317 guint32 type; /* block_type as defined by pcapng */
319 wtapng_section_t section;
320 wtapng_if_descr_t if_descr;
321 wtapng_packet_t packet;
322 wtapng_simple_packet_t simple_packet;
323 wtapng_name_res_t name_res;
324 wtapng_if_stats_t if_stats;
328 * XXX - currently don't know how to handle these!
330 * For one thing, when we're reading a block, they must be
331 * writable, i.e. not const, so that we can read into them,
332 * but, when we're writing a block, they can be const, and,
333 * in fact, they sometimes point to const values.
335 const union wtap_pseudo_header *pseudo_header;
336 struct wtap_pkthdr *packet_header;
337 const guint8 *frame_buffer;
341 /* Interface data in private struct */
342 typedef struct interface_data_s {
344 guint64 time_units_per_second;
348 gboolean shb_read; /**< Set when fisrt SHB read, second read will fail */
349 gboolean read_idbs; /**< Idicates that it is the first read after a SHB, atl east one IDB is expected */
350 gboolean byte_swapped;
351 guint16 version_major;
352 guint16 version_minor;
353 GArray *interface_data;
354 guint number_of_interfaces;
356 wtap_new_ipv4_callback_t add_new_ipv4;
357 wtap_new_ipv6_callback_t add_new_ipv6;
361 pcapng_get_encap(gint id, pcapng_t *pn)
363 interface_data_t int_data;
366 if ((id >= 0) && ((guint)id < pn->number_of_interfaces)) {
367 int_data = g_array_index(pn->interface_data, interface_data_t, id);
368 pcapng_debug2("pcapng_get_encap: id %i, wtap_encap %i",id, int_data.wtap_encap);
369 return int_data.wtap_encap;
371 pcapng_debug2("pcapng_get_encap: id %i number_of_interfaces %u, wtap_encap = WTAP_ERR_UNSUPPORTED_ENCAP",id,pn->number_of_interfaces);
372 return WTAP_ERR_UNSUPPORTED_ENCAP;
377 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
378 char *content, int len, int *err, gchar **err_info)
382 guint64 file_offset64;
385 /* read option header */
386 errno = WTAP_ERR_CANT_READ;
387 bytes_read = file_read(oh, sizeof (*oh), fh);
388 if (bytes_read != sizeof (*oh)) {
389 pcapng_debug0("pcapng_read_option: failed to read option");
390 *err = file_error(fh, err_info);
395 block_read = sizeof (*oh);
396 if(pn->byte_swapped) {
397 oh->option_code = BSWAP16(oh->option_code);
398 oh->option_length = BSWAP16(oh->option_length);
401 /* sanity check: option length */
402 if (oh->option_length > len) {
403 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
404 oh->option_length, len);
408 /* read option content */
409 errno = WTAP_ERR_CANT_READ;
410 bytes_read = file_read(content, oh->option_length, fh);
411 if (bytes_read != oh->option_length) {
412 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
413 *err = file_error(fh, err_info);
418 block_read += oh->option_length;
420 /* jump over potential padding bytes at end of option */
421 if( (oh->option_length % 4) != 0) {
422 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
423 if (file_offset64 <= 0) {
428 block_read += 4 - (oh->option_length % 4);
436 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
437 pcapng_block_header_t *bh, pcapng_t *pn,
438 wtapng_block_t *wblock, int *err,
443 int to_read, opt_cont_buf_len;
444 pcapng_section_header_block_t shb;
445 pcapng_option_header_t oh;
446 char *option_content = NULL; /* Allocate as large as the options block */
449 /* read block content */
450 errno = WTAP_ERR_CANT_READ;
451 bytes_read = file_read(&shb, sizeof shb, fh);
452 if (bytes_read != sizeof shb) {
453 *err = file_error(fh, err_info);
457 * We're reading this as part of an open,
458 * and this block is too short to be
459 * an SHB, so the file is too short
460 * to be a pcap-ng file.
466 * Otherwise, just report this as an error.
468 *err = WTAP_ERR_SHORT_READ;
472 block_read = bytes_read;
474 /* is the magic number one we expect? */
477 /* this seems pcapng with correct byte order */
478 pn->byte_swapped = FALSE;
479 pn->version_major = shb.version_major;
480 pn->version_minor = shb.version_minor;
482 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
483 pn->version_major, pn->version_minor, bh->block_total_length);
486 /* this seems pcapng with swapped byte order */
487 pn->byte_swapped = TRUE;
488 pn->version_major = BSWAP16(shb.version_major);
489 pn->version_minor = BSWAP16(shb.version_minor);
491 /* tweak the block length to meet current swapping that we know now */
492 bh->block_total_length = BSWAP32(bh->block_total_length);
494 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
495 pn->version_major, pn->version_minor, bh->block_total_length);
498 /* Not a "pcapng" magic number we know about. */
500 /* Not a pcap-ng file. */
505 *err = WTAP_ERR_BAD_FILE;
506 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
510 /* OK, at this point we assume it's a pcap-ng file. */
511 /* We currently only suport one SHB */
512 if (pn->shb_read == TRUE) {
513 *err = WTAP_ERR_UNSUPPORTED;
514 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported.");
518 /* we currently only understand SHB V1.0 */
519 if (pn->version_major != 1 || pn->version_minor > 0) {
520 *err = WTAP_ERR_UNSUPPORTED;
521 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
522 pn->version_major, pn->version_minor);
527 /* 64bit section_length (currently unused) */
528 if (pn->byte_swapped) {
529 wblock->data.section.section_length = BSWAP64(shb.section_length);
531 wblock->data.section.section_length = shb.section_length;
534 /* Option defaults */
535 wblock->data.section.opt_comment = NULL;
536 wblock->data.section.shb_hardware = NULL;
537 wblock->data.section.shb_os = NULL;
538 wblock->data.section.shb_user_appl = NULL;
541 errno = WTAP_ERR_CANT_READ;
542 to_read = bh->block_total_length -
543 (int)sizeof(pcapng_block_header_t) -
544 (int)sizeof(pcapng_section_header_block_t) -
545 (int)sizeof(bh->block_total_length);
546 /* Allocate enough memory to hold all options */
547 opt_cont_buf_len = to_read;
548 option_content = g_malloc(opt_cont_buf_len);
549 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
552 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
553 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
554 if (bytes_read <= 0) {
555 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
558 block_read += bytes_read;
559 to_read -= bytes_read;
561 /* handle option content */
562 switch(oh.option_code) {
563 case(0): /* opt_endofopt */
565 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
567 /* padding should be ok here, just get out of this */
570 case(1): /* opt_comment */
571 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
572 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
573 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
575 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
578 case(2): /* shb_hardware */
579 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
580 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
581 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
583 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
586 case(3): /* shb_os */
587 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
588 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
589 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
591 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
594 case(4): /* shb_user_appl */
595 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
596 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
597 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
599 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
603 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
604 oh.option_code, oh.option_length);
607 g_free(option_content);
613 /* "Interface Description Block" */
615 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
616 wtapng_block_t *wblock, int *err, gchar **err_info)
618 guint64 time_units_per_second = 1000000; /* default */
621 int to_read, opt_cont_buf_len;
622 pcapng_interface_description_block_t idb;
623 pcapng_option_header_t oh;
624 char *option_content = NULL; /* Allocate as large as the options block */
628 /* read block content */
629 errno = WTAP_ERR_CANT_READ;
630 bytes_read = file_read(&idb, sizeof idb, fh);
631 if (bytes_read != sizeof idb) {
632 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
633 *err = file_error(fh, err_info);
638 block_read = bytes_read;
640 /* mandatory values */
641 if (pn->byte_swapped) {
642 wblock->data.if_descr.link_type = BSWAP16(idb.linktype);
643 wblock->data.if_descr.snap_len = BSWAP32(idb.snaplen);
645 wblock->data.if_descr.link_type = idb.linktype;
646 wblock->data.if_descr.snap_len = idb.snaplen;
649 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
650 wblock->data.if_descr.time_units_per_second = time_units_per_second;
652 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
653 wblock->data.if_descr.link_type,
654 wtap_encap_string(wblock->data.if_descr.wtap_encap),
655 wblock->data.if_descr.snap_len);
657 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
658 /* This is unrealisitic, but text2pcap currently uses 102400.
659 * We do not use this value, maybe we should check the
660 * snap_len of the packets against it. For now, only warn.
662 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
663 wblock->data.if_descr.snap_len);
664 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
667 /* Option defaults */
668 wblock->data.if_descr.opt_comment = NULL;
669 wblock->data.if_descr.if_name = NULL;
670 wblock->data.if_descr.if_description = NULL;
671 /* XXX: if_IPv4addr */
672 /* XXX: if_IPv6addr */
673 /* XXX: if_MACaddr */
674 /* XXX: if_EUIaddr */
675 wblock->data.if_descr.if_speed = 0; /* "unknown" */
676 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
677 wblock->data.if_descr.if_filter = NULL;
678 wblock->data.if_descr.if_os = NULL;
679 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
680 /* XXX: guint64 if_tsoffset; */
684 errno = WTAP_ERR_CANT_READ;
685 to_read = bh->block_total_length -
686 (int)sizeof(pcapng_block_header_t) -
687 (int)sizeof (pcapng_interface_description_block_t) -
688 (int)sizeof(bh->block_total_length);
690 /* Allocate enough memory to hold all options */
691 opt_cont_buf_len = to_read;
692 option_content = g_malloc(opt_cont_buf_len);
694 while (to_read > 0) {
696 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
697 if (bytes_read <= 0) {
698 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
701 block_read += bytes_read;
702 to_read -= bytes_read;
704 /* handle option content */
705 switch(oh.option_code) {
706 case(0): /* opt_endofopt */
708 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
710 /* padding should be ok here, just get out of this */
713 case(1): /* opt_comment */
714 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
715 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
716 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
718 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
721 case(2): /* if_name */
722 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
723 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
724 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
726 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
729 case(3): /* if_description */
730 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
731 wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
732 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
734 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
738 * 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
739 * 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"
740 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
741 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
743 case(8): /* if_speed */
744 if (oh.option_length == 8) {
745 /* Don't cast a char[] into a guint64--the
746 * char[] may not be aligned correctly.
748 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
750 wblock->data.if_descr.if_speed = BSWAP64(wblock->data.if_descr.if_speed);
751 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
753 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
756 case(9): /* if_tsresol */
757 if (oh.option_length == 1) {
760 guint8 i, exponent, if_tsresol;
762 if_tsresol = option_content[0];
763 if (if_tsresol & 0x80) {
768 exponent = (guint8)(if_tsresol & 0x7f);
769 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
771 for (i = 0; i < exponent; i++) {
774 time_units_per_second = result;
776 time_units_per_second = G_MAXUINT64;
778 if (time_units_per_second > (((guint64)1) << 32)) {
779 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
781 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
782 wblock->data.if_descr.time_units_per_second = time_units_per_second;
783 wblock->data.if_descr.if_tsresol = if_tsresol;
785 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
789 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
791 case(11): /* if_filter */
792 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
793 wblock->data.if_descr.if_filter = g_strndup(option_content, oh.option_length);
794 pcapng_debug1("pcapng_read_if_descr_block: if_filter %s", wblock->data.if_descr.if_filter);
796 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
799 case(12): /* if_os */
801 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
802 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
803 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
805 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
806 wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
807 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
809 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
812 case(13): /* if_fcslen */
813 if (oh.option_length == 1) {
814 wblock->data.if_descr.if_fcslen = option_content[0];
815 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
816 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
817 /* XXX - add sanity check */
819 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
823 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
824 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
825 * The time zone of the offset can be specified with the option if_tzone.
826 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly syncronized capture systems? 1234
829 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
830 oh.option_code, oh.option_length);
834 g_free(option_content);
836 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
837 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
839 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
840 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
849 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)
853 int to_read, opt_cont_buf_len;
854 guint64 file_offset64;
855 pcapng_enhanced_packet_block_t epb;
856 pcapng_packet_block_t pb;
857 guint32 block_total_length;
858 pcapng_option_header_t oh;
860 int pseudo_header_len;
861 char *option_content = NULL; /* Allocate as large as the options block */
864 /* "(Enhanced) Packet Block" read fixed part */
865 errno = WTAP_ERR_CANT_READ;
867 bytes_read = file_read(&epb, sizeof epb, fh);
868 if (bytes_read != sizeof epb) {
869 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
870 *err = file_error(fh, err_info);
873 block_read = bytes_read;
875 if (pn->byte_swapped) {
876 wblock->data.packet.interface_id = BSWAP32(epb.interface_id);
877 wblock->data.packet.drops_count = -1; /* invalid */
878 wblock->data.packet.ts_high = BSWAP32(epb.timestamp_high);
879 wblock->data.packet.ts_low = BSWAP32(epb.timestamp_low);
880 wblock->data.packet.cap_len = BSWAP32(epb.captured_len);
881 wblock->data.packet.packet_len = BSWAP32(epb.packet_len);
883 wblock->data.packet.interface_id = epb.interface_id;
884 wblock->data.packet.drops_count = -1; /* invalid */
885 wblock->data.packet.ts_high = epb.timestamp_high;
886 wblock->data.packet.ts_low = epb.timestamp_low;
887 wblock->data.packet.cap_len = epb.captured_len;
888 wblock->data.packet.packet_len = epb.packet_len;
891 bytes_read = file_read(&pb, sizeof pb, fh);
892 if (bytes_read != sizeof pb) {
893 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
894 *err = file_error(fh, err_info);
897 block_read = bytes_read;
899 if (pn->byte_swapped) {
900 wblock->data.packet.interface_id = BSWAP16(pb.interface_id);
901 wblock->data.packet.drops_count = BSWAP16(pb.drops_count);
902 wblock->data.packet.ts_high = BSWAP32(pb.timestamp_high);
903 wblock->data.packet.ts_low = BSWAP32(pb.timestamp_low);
904 wblock->data.packet.cap_len = BSWAP32(pb.captured_len);
905 wblock->data.packet.packet_len = BSWAP32(pb.packet_len);
907 wblock->data.packet.interface_id = pb.interface_id;
908 wblock->data.packet.drops_count = pb.drops_count;
909 wblock->data.packet.ts_high = pb.timestamp_high;
910 wblock->data.packet.ts_low = pb.timestamp_low;
911 wblock->data.packet.cap_len = pb.captured_len;
912 wblock->data.packet.packet_len = pb.packet_len;
916 if (wblock->data.packet.cap_len > wblock->data.packet.packet_len) {
917 *err = WTAP_ERR_BAD_FILE;
918 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u.",
919 wblock->data.packet.cap_len, wblock->data.packet.packet_len);
922 if (wblock->data.packet.cap_len > WTAP_MAX_PACKET_SIZE) {
923 *err = WTAP_ERR_BAD_FILE;
924 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
925 wblock->data.packet.cap_len, WTAP_MAX_PACKET_SIZE);
928 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
929 wblock->data.packet.packet_len,
930 wblock->data.packet.cap_len,
931 wblock->data.packet.interface_id);
933 wtap_encap = pcapng_get_encap(wblock->data.packet.interface_id, pn);
934 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
936 wtap_encap_string(wtap_encap),
937 pcap_get_phdr_size(wtap_encap, wblock->pseudo_header));
939 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
940 pseudo_header_len = pcap_process_pseudo_header(fh,
943 wblock->data.packet.cap_len,
945 wblock->packet_header,
946 (union wtap_pseudo_header *)wblock->pseudo_header,
949 if (pseudo_header_len < 0) {
952 wblock->data.packet.pseudo_header_len = (guint32)pseudo_header_len;
953 block_read += pseudo_header_len;
954 if (pseudo_header_len != pcap_get_phdr_size(wtap_encap, wblock->pseudo_header)) {
955 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
959 /* "(Enhanced) Packet Block" read capture data */
960 errno = WTAP_ERR_CANT_READ;
961 bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.packet.cap_len - pseudo_header_len, fh);
962 if (bytes_read != (int) (wblock->data.packet.cap_len - pseudo_header_len)) {
963 *err = file_error(fh, err_info);
964 pcapng_debug1("pcapng_read_packet_block: couldn't read %u bytes of captured data",
965 wblock->data.packet.cap_len - pseudo_header_len);
967 *err = WTAP_ERR_SHORT_READ;
970 block_read += bytes_read;
972 /* jump over potential padding bytes at end of the packet data */
973 if( (wblock->data.packet.cap_len % 4) != 0) {
974 file_offset64 = file_seek(fh, 4 - (wblock->data.packet.cap_len % 4), SEEK_CUR, err);
975 if (file_offset64 <= 0) {
980 block_read += 4 - (wblock->data.packet.cap_len % 4);
983 /* add padding bytes to "block total length" */
984 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
985 if (bh->block_total_length % 4) {
986 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
988 block_total_length = bh->block_total_length;
991 /* Option defaults */
992 wblock->data.packet.opt_comment = NULL;
993 wblock->data.packet.drop_count = -1;
994 wblock->data.packet.pack_flags = 0; /* XXX - is 0 ok to signal "not used"? */
996 /* FCS length default */
997 fcslen = pn->if_fcslen;
1005 errno = WTAP_ERR_CANT_READ;
1006 to_read = block_total_length -
1007 (int)sizeof(pcapng_block_header_t) -
1008 block_read - /* fixed and variable part, including padding */
1009 (int)sizeof(bh->block_total_length);
1011 /* Allocate enough memory to hold all options */
1012 opt_cont_buf_len = to_read;
1013 option_content = g_malloc(opt_cont_buf_len);
1015 while(to_read > 0) {
1017 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
1018 if (bytes_read <= 0) {
1019 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1022 block_read += bytes_read;
1023 to_read -= bytes_read;
1025 /* handle option content */
1026 switch(oh.option_code) {
1027 case(0): /* opt_endofopt */
1029 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1031 /* padding should be ok here, just get out of this */
1034 case(1): /* opt_comment */
1035 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1036 wblock->data.packet.opt_comment = g_strndup(option_content, oh.option_length);
1037 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->data.packet.opt_comment);
1039 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1042 case(2): /* pack_flags / epb_flags */
1043 if(oh.option_length == 4) {
1044 /* Don't cast a char[] into a guint32--the
1045 * char[] may not be aligned correctly.
1047 memcpy(&wblock->data.packet.pack_flags, option_content, sizeof(guint32));
1048 if(pn->byte_swapped)
1049 wblock->data.packet.pack_flags = BSWAP32(wblock->data.packet.pack_flags);
1050 if (wblock->data.packet.pack_flags & 0x000001E0) {
1051 /* The FCS length is present */
1052 fcslen = (wblock->data.packet.pack_flags & 0x000001E0) >> 5;
1054 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->data.packet.pack_flags);
1056 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1059 case(3): /* epb_hash */
1060 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1061 oh.option_code, oh.option_length);
1063 case(4): /* epb_dropcount */
1064 if(oh.option_length == 8) {
1065 /* Don't cast a char[] into a guint32--the
1066 * char[] may not be aligned correctly.
1068 memcpy(&wblock->data.packet.drop_count, option_content, sizeof(guint64));
1069 if(pn->byte_swapped)
1070 wblock->data.packet.drop_count = BSWAP64(wblock->data.packet.drop_count);
1072 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->data.packet.drop_count);
1074 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1078 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1079 oh.option_code, oh.option_length);
1083 g_free(option_content);
1085 pcap_read_post_process(WTAP_FILE_PCAPNG, wtap_encap,
1086 (union wtap_pseudo_header *)wblock->pseudo_header,
1087 (guint8 *) (wblock->frame_buffer),
1088 (int) (wblock->data.packet.cap_len - pseudo_header_len),
1089 pn->byte_swapped, fcslen);
1095 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)
1099 guint64 file_offset64;
1101 int pseudo_header_len;
1102 pcapng_simple_packet_block_t spb;
1105 /* "Simple Packet Block" read fixed part */
1106 errno = WTAP_ERR_CANT_READ;
1107 bytes_read = file_read(&spb, sizeof spb, fh);
1108 if (bytes_read != sizeof spb) {
1109 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1110 *err = file_error(fh, err_info);
1113 block_read = bytes_read;
1115 if (pn->byte_swapped) {
1116 wblock->data.simple_packet.packet_len = BSWAP32(spb.packet_len);
1118 wblock->data.simple_packet.packet_len = spb.packet_len;
1121 wblock->data.simple_packet.cap_len = bh->block_total_length
1122 - (guint32)sizeof(pcapng_simple_packet_block_t)
1123 - (guint32)sizeof(bh->block_total_length);
1125 if (wblock->data.simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1126 *err = WTAP_ERR_BAD_FILE;
1127 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1128 wblock->data.simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1131 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1132 wblock->data.simple_packet.packet_len);
1134 encap = pcapng_get_encap(0, pn);
1135 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1136 pcap_get_phdr_size(encap, wblock->pseudo_header));
1138 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1139 pseudo_header_len = pcap_process_pseudo_header(fh,
1142 wblock->data.simple_packet.cap_len,
1144 wblock->packet_header,
1145 (union wtap_pseudo_header *)wblock->pseudo_header,
1148 if (pseudo_header_len < 0) {
1151 wblock->data.simple_packet.pseudo_header_len = (guint32)pseudo_header_len;
1152 block_read += pseudo_header_len;
1153 if (pseudo_header_len != pcap_get_phdr_size(encap, wblock->pseudo_header)) {
1154 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1158 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1160 /* "Simple Packet Block" read capture data */
1161 errno = WTAP_ERR_CANT_READ;
1162 bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.simple_packet.cap_len, fh);
1163 if (bytes_read != (int) wblock->data.simple_packet.cap_len) {
1164 *err = file_error(fh, err_info);
1165 pcapng_debug1("pcapng_read_simple_packet_block: couldn't read %u bytes of captured data",
1166 wblock->data.simple_packet.cap_len);
1168 *err = WTAP_ERR_SHORT_READ;
1171 block_read += bytes_read;
1173 /* jump over potential padding bytes at end of the packet data */
1174 if ((wblock->data.simple_packet.cap_len % 4) != 0) {
1175 file_offset64 = file_seek(fh, 4 - (wblock->data.simple_packet.cap_len % 4), SEEK_CUR, err);
1176 if (file_offset64 <= 0) {
1181 block_read += 4 - (wblock->data.simple_packet.cap_len % 4);
1184 pcap_read_post_process(WTAP_FILE_PCAPNG, encap,
1185 (union wtap_pseudo_header *)wblock->pseudo_header,
1186 (guint8 *) (wblock->frame_buffer),
1187 (int) wblock->data.simple_packet.cap_len,
1188 pn->byte_swapped, pn->if_fcslen);
1192 #define NRES_ENDOFRECORD 0
1193 #define NRES_IP4RECORD 1
1194 #define NRES_IP6RECORD 2
1195 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1196 /* IPv6 + MAXNAMELEN */
1197 #define MAX_NRB_REC_SIZE (16 + 64)
1199 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)
1204 guint64 file_offset64;
1205 pcapng_name_resolution_block_t nrb;
1206 guint8 nrb_rec[MAX_NRB_REC_SIZE];
1209 errno = WTAP_ERR_CANT_READ;
1210 to_read = bh->block_total_length
1211 - sizeof(pcapng_block_header_t)
1212 - sizeof(bh->block_total_length);
1214 while (block_read < to_read) {
1215 bytes_read = file_read(&nrb, sizeof nrb, fh);
1216 if (bytes_read != sizeof nrb) {
1217 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1218 *err = file_error(fh, err_info);
1221 block_read += bytes_read;
1223 if (pn->byte_swapped) {
1224 nrb.record_type = BSWAP16(nrb.record_type);
1225 nrb.record_len = BSWAP16(nrb.record_len);
1228 switch(nrb.record_type) {
1229 case NRES_ENDOFRECORD:
1230 /* There shouldn't be any more data */
1233 case NRES_IP4RECORD:
1234 if (nrb.record_len < 6 || nrb.record_len > MAX_NRB_REC_SIZE || to_read < nrb.record_len) {
1235 pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv4 record");
1238 bytes_read = file_read(nrb_rec, nrb.record_len, fh);
1239 if (bytes_read != nrb.record_len) {
1240 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1241 *err = file_error(fh, err_info);
1244 block_read += bytes_read;
1246 if (pn->add_new_ipv4) {
1247 memcpy(&v4_addr, nrb_rec, 4);
1248 if (pn->byte_swapped)
1249 v4_addr = BSWAP32(v4_addr);
1250 pn->add_new_ipv4(v4_addr, nrb_rec + 4);
1253 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1254 if (file_offset64 <= 0) {
1259 block_read += PADDING4(nrb.record_len);
1261 case NRES_IP6RECORD:
1262 if (nrb.record_len < 18 || nrb.record_len > MAX_NRB_REC_SIZE || to_read < nrb.record_len) {
1263 pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv6 record");
1266 bytes_read = file_read(nrb_rec, nrb.record_len, fh);
1267 if (bytes_read != nrb.record_len) {
1268 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1269 *err = file_error(fh, err_info);
1272 block_read += bytes_read;
1274 if (pn->add_new_ipv6) {
1275 pn->add_new_ipv6(nrb_rec, nrb_rec + 16);
1278 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1279 if (file_offset64 <= 0) {
1284 block_read += PADDING4(nrb.record_len);
1287 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1288 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1289 if (file_offset64 <= 0) {
1294 block_read += nrb.record_len + PADDING4(nrb.record_len);
1303 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)
1307 int to_read, opt_cont_buf_len;
1308 pcapng_interface_statistics_block_t isb;
1309 pcapng_option_header_t oh;
1310 char *option_content = NULL; /* Allocate as large as the options block */
1313 /* "Interface Statistics Block" read fixed part */
1314 errno = WTAP_ERR_CANT_READ;
1315 bytes_read = file_read(&isb, sizeof isb, fh);
1316 if (bytes_read != sizeof isb) {
1317 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1318 *err = file_error(fh, err_info);
1321 block_read = bytes_read;
1323 if(pn->byte_swapped) {
1324 wblock->data.if_stats.interface_id = BSWAP64(isb.interface_id);
1325 wblock->data.if_stats.ts_high = BSWAP32(isb.timestamp_high);
1326 wblock->data.if_stats.ts_low = BSWAP32(isb.timestamp_low);
1328 wblock->data.if_stats.interface_id = isb.interface_id;
1329 wblock->data.if_stats.ts_high = isb.timestamp_high;
1330 wblock->data.if_stats.ts_low = isb.timestamp_low;
1332 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %" G_GINT64_MODIFIER "u", wblock->data.if_stats.interface_id);
1334 /* Option defaults */
1335 wblock->data.if_stats.opt_comment = NULL;
1336 wblock->data.if_stats.isb_ifrecv = -1;
1337 wblock->data.if_stats.isb_ifdrop = -1;
1340 errno = WTAP_ERR_CANT_READ;
1341 to_read = bh->block_total_length -
1342 sizeof(pcapng_block_header_t) -
1343 block_read - /* fixed and variable part, including padding */
1344 sizeof(bh->block_total_length);
1346 /* Allocate enough memory to hold all options */
1347 opt_cont_buf_len = to_read;
1348 option_content = g_malloc(opt_cont_buf_len);
1350 while(to_read > 0) {
1352 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
1353 if (bytes_read <= 0) {
1354 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1357 block_read += bytes_read;
1358 to_read -= bytes_read;
1360 /* handle option content */
1361 switch(oh.option_code) {
1362 case(0): /* opt_endofopt */
1364 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1366 /* padding should be ok here, just get out of this */
1369 case(1): /* opt_comment */
1370 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1371 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1372 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1374 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1377 case(2): /* isb_starttime */
1378 if(oh.option_length == 8) {
1379 /* Don't cast a char[] into a guint32--the
1380 * char[] may not be aligned correctly.
1382 memcpy(&wblock->data.if_stats.isb_starttime, option_content, sizeof(guint64));
1383 if(pn->byte_swapped)
1384 wblock->data.if_stats.isb_starttime = BSWAP64(wblock->data.if_stats.isb_starttime);
1385 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1387 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1390 case(3): /* isb_endtime */
1391 if(oh.option_length == 8) {
1392 /* Don't cast a char[] into a guint32--the
1393 * char[] may not be aligned correctly.
1395 memcpy(&wblock->data.if_stats.isb_endtime, option_content, sizeof(guint64));
1396 if(pn->byte_swapped)
1397 wblock->data.if_stats.isb_endtime = BSWAP64(wblock->data.if_stats.isb_endtime);
1398 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1400 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1403 case(4): /* isb_ifrecv */
1404 if(oh.option_length == 8) {
1405 /* Don't cast a char[] into a guint32--the
1406 * char[] may not be aligned correctly.
1408 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1409 if(pn->byte_swapped)
1410 wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
1411 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1413 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1416 case(5): /* isb_ifdrop */
1417 if(oh.option_length == 8) {
1418 /* Don't cast a char[] into a guint32--the
1419 * char[] may not be aligned correctly.
1421 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1422 if(pn->byte_swapped)
1423 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
1424 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1426 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1429 case(6): /* isb_filteraccept 6 */
1430 if(oh.option_length == 8) {
1431 /* Don't cast a char[] into a guint32--the
1432 * char[] may not be aligned correctly.
1434 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1435 if(pn->byte_swapped)
1436 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_filteraccept);
1437 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1439 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1442 case(7): /* isb_osdrop 7 */
1443 if(oh.option_length == 8) {
1444 /* Don't cast a char[] into a guint32--the
1445 * char[] may not be aligned correctly.
1447 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1448 if(pn->byte_swapped)
1449 wblock->data.if_stats.isb_osdrop = BSWAP64(wblock->data.if_stats.isb_osdrop);
1450 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1452 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1455 case(8): /* isb_usrdeliv 8 */
1456 if(oh.option_length == 8) {
1457 /* Don't cast a char[] into a guint32--the
1458 * char[] may not be aligned correctly.
1460 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1461 if(pn->byte_swapped)
1462 wblock->data.if_stats.isb_usrdeliv = BSWAP64(wblock->data.if_stats.isb_osdrop);
1463 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1465 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1469 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1470 oh.option_code, oh.option_length);
1474 g_free(option_content);
1481 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 _U_)
1484 guint64 file_offset64;
1485 guint32 block_total_length;
1488 /* add padding bytes to "block total length" */
1489 /* (the "block total length" of some example files don't contain any padding bytes!) */
1490 if (bh->block_total_length % 4) {
1491 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1493 block_total_length = bh->block_total_length;
1496 block_read = block_total_length - (guint32)sizeof(pcapng_block_header_t) - (guint32)sizeof(bh->block_total_length);
1498 /* jump over this unknown block */
1499 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1500 if (file_offset64 <= 0) {
1511 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1515 pcapng_block_header_t bh;
1516 guint32 block_total_length;
1519 /* Try to read the (next) block header */
1520 errno = WTAP_ERR_CANT_READ;
1521 bytes_read = file_read(&bh, sizeof bh, fh);
1522 if (bytes_read != sizeof bh) {
1523 *err = file_error(fh, err_info);
1524 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
1530 block_read = bytes_read;
1531 if (pn->byte_swapped) {
1532 bh.block_type = BSWAP32(bh.block_type);
1533 bh.block_total_length = BSWAP32(bh.block_total_length);
1536 wblock->type = bh.block_type;
1538 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
1542 * This is being read in by pcapng_open(), so this block
1543 * must be an SHB. If it's not, this is not a pcap-ng
1546 * XXX - check for various forms of Windows <-> UN*X
1547 * mangling, and suggest that the file might be a
1548 * pcap-ng file that was damaged in transit?
1550 if (bh.block_type != BLOCK_TYPE_SHB)
1551 return 0; /* not a pcap-ng file */
1554 switch(bh.block_type) {
1555 case(BLOCK_TYPE_SHB):
1556 bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
1558 case(BLOCK_TYPE_IDB):
1559 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
1561 case(BLOCK_TYPE_PB):
1562 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
1564 case(BLOCK_TYPE_SPB):
1565 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
1567 case(BLOCK_TYPE_EPB):
1568 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
1570 case(BLOCK_TYPE_NRB):
1571 bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
1573 case(BLOCK_TYPE_ISB):
1574 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
1577 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
1578 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
1581 if (bytes_read <= 0) {
1584 block_read += bytes_read;
1586 /* sanity check: first and second block lengths must match */
1587 errno = WTAP_ERR_CANT_READ;
1588 bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
1589 if (bytes_read != sizeof block_total_length) {
1590 pcapng_debug0("pcapng_read_block: couldn't read second block length");
1591 *err = file_error(fh, err_info);
1593 *err = WTAP_ERR_SHORT_READ;
1596 block_read += bytes_read;
1598 if (pn->byte_swapped)
1599 block_total_length = BSWAP32(block_total_length);
1601 if (!(block_total_length == bh.block_total_length)) {
1602 *err = WTAP_ERR_BAD_FILE;
1603 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
1604 bh.block_total_length, block_total_length);
1612 /* classic wtap: open capture file */
1614 pcapng_open(wtap *wth, int *err, gchar **err_info)
1618 wtapng_block_t wblock;
1620 wtapng_if_descr_t int_data;
1621 interface_data_t interface_data;
1622 pcapng_block_header_t bh;
1625 pn.shb_read = FALSE;
1626 pn.read_idbs = TRUE; /* IDB expected after SHB */
1627 /* we don't know the byte swapping of the file yet */
1628 pn.byte_swapped = FALSE;
1630 pn.version_major = -1;
1631 pn.version_minor = -1;
1632 pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
1633 pn.number_of_interfaces = 0;
1636 /* we don't expect any packet blocks yet */
1637 wblock.frame_buffer = NULL;
1638 wblock.pseudo_header = NULL;
1639 wblock.packet_header = NULL;
1640 wblock.file_encap = &wth->file_encap;
1642 pcapng_debug0("pcapng_open: opening file");
1643 /* read first block */
1644 bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
1645 if (bytes_read <= 0) {
1646 pcapng_debug0("pcapng_open: couldn't read first SHB");
1647 *err = file_error(wth->fh, err_info);
1652 wth->data_offset += bytes_read;
1654 /* first block must be a "Section Header Block" */
1655 if (wblock.type != BLOCK_TYPE_SHB) {
1657 * XXX - check for damage from transferring a file
1658 * between Windows and UN*X as text rather than
1661 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
1667 * At this point, we've decided this is a pcap-NG file, not
1668 * some other type of file, so we can't return 0, as that
1669 * means "this isn't a pcap-NG file, try some other file
1672 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
1673 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
1674 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
1675 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
1677 wth->file_encap = WTAP_ENCAP_UNKNOWN;
1678 wth->snapshot_length = 0;
1679 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
1680 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
1681 wth->priv = (void *)pcapng;
1684 wth->subtype_read = pcapng_read;
1685 wth->subtype_seek_read = pcapng_seek_read;
1686 wth->subtype_close = pcapng_close;
1687 wth->file_type = WTAP_FILE_PCAPNG;
1690 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1691 wth->number_of_interfaces = 0;
1693 /* Loop ower all IDB:s that appear before any packets */
1695 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
1696 wth->data_offset += bytes_read;
1697 if (bytes_read == 0) {
1698 pcapng_debug0("No more IDBs available...");
1701 if (bytes_read <= 0) {
1702 pcapng_debug0("pcapng_open: couldn't read IDB");
1703 *err = file_error(wth->fh, err_info);
1705 *err = WTAP_ERR_SHORT_READ;
1709 int_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1710 int_data.time_units_per_second = wblock.data.if_descr.time_units_per_second;
1711 int_data.link_type = wblock.data.if_descr.link_type;
1712 int_data.snap_len = wblock.data.if_descr.snap_len;
1714 int_data.opt_comment = wblock.data.if_descr.opt_comment;
1715 int_data.if_name = wblock.data.if_descr.if_name;
1716 int_data.if_description = wblock.data.if_descr.if_description;
1717 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
1718 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
1719 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
1720 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
1721 int_data.if_speed = wblock.data.if_descr.if_speed;
1722 int_data.if_tsresol = wblock.data.if_descr.if_tsresol;
1723 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
1724 int_data.if_filter = wblock.data.if_descr.if_filter;
1725 int_data.if_os = wblock.data.if_descr.if_os;
1726 int_data.if_fcslen = wblock.data.if_descr.if_fcslen;
1727 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
1729 g_array_append_val(wth->interface_data, int_data);
1730 wth->number_of_interfaces++;
1732 interface_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1733 interface_data.time_units_per_second = 1000000; /* default */
1735 g_array_append_val(pcapng->interface_data, interface_data);
1736 pcapng->number_of_interfaces++;
1738 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, int_data.wtap_encap);
1740 /* peek at next block */
1741 /* Try to read the (next) block header */
1742 errno = WTAP_ERR_CANT_READ;
1743 bytes_read = file_read(&bh, sizeof bh, wth->fh);
1744 if (bytes_read == 0) {
1745 pcapng_debug0("No more IDBs available...");
1748 if (bytes_read != sizeof bh) {
1749 *err = file_error(wth->fh, err_info);
1750 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);
1752 *err = WTAP_ERR_SHORT_READ;
1756 /* go back to where we were */
1757 file_seek(wth->fh, wth->data_offset, SEEK_SET, err);
1759 if (pn.byte_swapped) {
1760 bh.block_type = BSWAP32(bh.block_type);
1763 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
1765 if (bh.block_type != BLOCK_TYPE_IDB){
1766 break; /* No more IDB:s */
1770 pcapng->read_idbs = FALSE;
1776 /* classic wtap: read packet */
1778 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1780 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1783 wtapng_block_t wblock;
1785 pcapng_debug1("pcapng_read: wth->data_offset is initially %" G_GINT64_MODIFIER "u", wth->data_offset);
1786 *data_offset = wth->data_offset;
1787 pcapng_debug1("pcapng_read: *data_offset is initially set to %" G_GINT64_MODIFIER "u", *data_offset);
1789 /* XXX - This should be done in the packet block reading function and
1790 * should make use of the caplen of the packet.
1792 if (wth->snapshot_length > 0) {
1793 buffer_assure_space(wth->frame_buffer, wth->snapshot_length);
1795 buffer_assure_space(wth->frame_buffer, WTAP_MAX_PACKET_SIZE);
1798 wblock.frame_buffer = buffer_start_ptr(wth->frame_buffer);
1799 wblock.pseudo_header = &wth->pseudo_header;
1800 wblock.packet_header = &wth->phdr;
1801 wblock.file_encap = &wth->file_encap;
1803 pcapng->add_new_ipv4 = wth->add_new_ipv4;
1804 pcapng->add_new_ipv6 = wth->add_new_ipv6;
1806 /* read next block */
1808 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
1809 if (bytes_read <= 0) {
1810 wth->data_offset = *data_offset;
1811 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
1812 pcapng_debug0("pcapng_read: couldn't read packet block");
1816 /* block must be a "Packet Block" or an "Enhanced Packet Block" -> otherwise continue */
1817 if (wblock.type == BLOCK_TYPE_PB || wblock.type == BLOCK_TYPE_EPB) {
1821 /* XXX - improve handling of "unknown" blocks */
1822 pcapng_debug1("pcapng_read: block type 0x%x not PB/EPB", wblock.type);
1823 *data_offset += bytes_read;
1824 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "u", *data_offset);
1827 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1828 ts = (((guint64)wblock.data.packet.ts_high) << 32) | ((guint64)wblock.data.packet.ts_low);
1830 wth->phdr.caplen = wblock.data.packet.cap_len - wblock.data.packet.pseudo_header_len;
1831 wth->phdr.len = wblock.data.packet.packet_len - wblock.data.packet.pseudo_header_len;
1832 if (wblock.data.packet.interface_id < pcapng->number_of_interfaces) {
1833 interface_data_t int_data;
1834 guint64 time_units_per_second;
1837 id = (gint)wblock.data.packet.interface_id;
1838 int_data = g_array_index(pcapng->interface_data, interface_data_t, id);
1839 time_units_per_second = int_data.time_units_per_second;
1840 wth->phdr.pkt_encap = int_data.wtap_encap;
1841 wth->phdr.ts.secs = (time_t)(ts / time_units_per_second);
1842 wth->phdr.ts.nsecs = (int)(((ts % time_units_per_second) * 1000000000) / time_units_per_second);
1844 wth->phdr.interface_id = wblock.data.packet.interface_id;
1845 wth->phdr.opt_comment = wblock.data.packet.opt_comment;
1846 wth->phdr.drop_count = wblock.data.packet.drop_count;
1847 wth->phdr.pack_flags = wblock.data.packet.pack_flags;
1849 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
1850 *err = WTAP_ERR_BAD_FILE;
1851 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
1852 wblock.data.packet.interface_id, pcapng->number_of_interfaces);
1853 wth->data_offset = *data_offset + bytes_read;
1854 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
1858 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
1859 wth->data_offset = *data_offset + bytes_read;
1860 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
1866 /* classic wtap: seek to file position and read packet */
1868 pcapng_seek_read(wtap *wth, gint64 seek_off,
1869 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length _U_,
1870 int *err, gchar **err_info)
1872 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1873 guint64 bytes_read64;
1875 wtapng_block_t wblock;
1878 /* seek to the right file position */
1879 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
1880 if (bytes_read64 <= 0) {
1881 return FALSE; /* Seek error */
1883 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
1885 wblock.frame_buffer = pd;
1886 wblock.pseudo_header = pseudo_header;
1887 wblock.packet_header = &wth->phdr;
1888 wblock.file_encap = &wth->file_encap;
1890 /* read the block */
1891 bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
1892 if (bytes_read <= 0) {
1893 *err = file_error(wth->random_fh, err_info);
1894 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
1895 *err, errno, bytes_read);
1899 /* block must be a "Packet Block" or an "Enhanced Packet Block" */
1900 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB) {
1901 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB", wblock.type);
1909 /* classic wtap: close capture file */
1911 pcapng_close(wtap *wth)
1913 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1915 pcapng_debug0("pcapng_close: closing file");
1916 if (pcapng->interface_data != NULL) {
1917 g_array_free(pcapng->interface_data, TRUE);
1924 GArray *interface_data;
1925 guint number_of_interfaces;
1926 struct addrinfo *addrinfo_list_last;
1930 pcapng_write_section_header_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
1932 pcapng_block_header_t bh;
1933 pcapng_section_header_block_t shb;
1934 const guint32 zero_pad = 0;
1935 gboolean have_options = FALSE;
1936 struct option option_hdr; /* guint16 type, guint16 value_length; */
1937 guint32 options_total_length = 0;
1938 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
1939 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
1942 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
1943 /* Check if we should write comment option */
1944 if (wdh->shb_hdr->opt_comment) {
1945 have_options = TRUE;
1946 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
1947 if ((comment_len % 4)) {
1948 comment_pad_len = 4 - (comment_len % 4);
1950 comment_pad_len = 0;
1952 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
1955 /* Check if we should write shb_hardware option */
1956 if (wdh->shb_hdr->shb_hardware) {
1957 have_options = TRUE;
1958 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
1959 if ((shb_hardware_len % 4)) {
1960 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
1962 shb_hardware_pad_len = 0;
1964 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
1967 /* Check if we should write shb_os option */
1968 if (wdh->shb_hdr->shb_os) {
1969 have_options = TRUE;
1970 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
1971 if ((shb_os_len % 4)) {
1972 shb_os_pad_len = 4 - (shb_os_len % 4);
1976 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
1979 /* Check if we should write shb_user_appl option */
1980 if (wdh->shb_hdr->shb_user_appl) {
1981 have_options = TRUE;
1982 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
1983 if ((shb_user_appl_len % 4)) {
1984 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
1986 shb_user_appl_pad_len = 0;
1988 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
1991 /* End-of-optios tag */
1992 options_total_length += 4;
1996 /* write block header */
1997 bh.block_type = wblock->type;
1998 bh.block_total_length = sizeof(bh) + sizeof(shb) + options_total_length + 4;
1999 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2001 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2003 wdh->bytes_dumped += sizeof bh;
2005 /* write block fixed content */
2006 /* XXX - get these values from wblock? */
2007 shb.magic = 0x1A2B3C4D;
2008 shb.version_major = 1;
2009 shb.version_minor = 0;
2010 shb.section_length = -1;
2012 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2014 wdh->bytes_dumped += sizeof shb;
2016 /* XXX - write (optional) block options
2024 option_hdr.type = OPT_COMMENT;
2025 option_hdr.value_length = comment_len;
2026 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2028 wdh->bytes_dumped += 4;
2030 /* Write the comments string */
2031 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);
2032 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2034 wdh->bytes_dumped += comment_len;
2036 /* write padding (if any) */
2037 if (comment_pad_len != 0) {
2038 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2040 wdh->bytes_dumped += comment_pad_len;
2044 if (shb_hardware_len) {
2045 option_hdr.type = OPT_SHB_HARDWARE;
2046 option_hdr.value_length = shb_hardware_len;
2047 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2049 wdh->bytes_dumped += 4;
2051 /* Write the string */
2052 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);
2053 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2055 wdh->bytes_dumped += shb_hardware_len;
2057 /* write padding (if any) */
2058 if (shb_hardware_pad_len != 0) {
2059 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2061 wdh->bytes_dumped += shb_hardware_pad_len;
2066 option_hdr.type = OPT_SHB_OS;
2067 option_hdr.value_length = shb_os_len;
2068 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2070 wdh->bytes_dumped += 4;
2072 /* Write the string */
2073 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);
2074 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2076 wdh->bytes_dumped += shb_os_len;
2078 /* write padding (if any) */
2079 if (shb_os_pad_len != 0) {
2080 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2082 wdh->bytes_dumped += shb_os_pad_len;
2086 if (shb_user_appl_len) {
2087 option_hdr.type = OPT_SHB_USERAPPL;
2088 option_hdr.value_length = shb_user_appl_len;
2089 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2091 wdh->bytes_dumped += 4;
2093 /* Write the comments string */
2094 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);
2095 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2097 wdh->bytes_dumped += shb_user_appl_len;
2099 /* write padding (if any) */
2100 if (shb_user_appl_pad_len != 0) {
2101 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2103 wdh->bytes_dumped += shb_user_appl_pad_len;
2107 /* Write end of options if we have otions */
2109 option_hdr.type = OPT_EOFOPT;
2110 option_hdr.value_length = 0;
2111 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2113 wdh->bytes_dumped += 4;
2116 /* write block footer */
2117 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2118 sizeof bh.block_total_length, err))
2120 wdh->bytes_dumped += sizeof bh.block_total_length;
2125 #define IDB_OPT_IF_NAME 2
2126 #define IDB_OPT_IF_DESCR 3
2127 #define IDB_OPT_IF_SPEED 8
2128 #define IDB_OPT_IF_TSRESOL 9
2129 #define IDB_OPT_IF_FILTER 11
2130 #define IDB_OPT_IF_OS 12
2133 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2135 pcapng_block_header_t bh;
2136 pcapng_interface_description_block_t idb;
2137 const guint32 zero_pad = 0;
2138 gboolean have_options = FALSE;
2139 struct option option_hdr; /* guint16 type, guint16 value_length; */
2140 guint32 options_total_length = 0;
2141 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0;
2142 guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0;
2145 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2146 wblock->data.if_descr.link_type,
2147 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
2148 wblock->data.if_descr.snap_len);
2150 if (wblock->data.if_descr.link_type == (guint16)-1) {
2151 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2155 /* Calculate options length */
2156 if (wblock->data.if_descr.opt_comment) {
2157 have_options = TRUE;
2158 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2159 if ((comment_len % 4)){
2160 comment_pad_len = 4 - (comment_len % 4);
2162 comment_pad_len = 0;
2164 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2168 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2170 if (wblock->data.if_descr.if_name){
2171 have_options = TRUE;
2172 if_name_len = (guint32)strlen(wblock->data.if_descr.if_name) & 0xffff;
2173 if ((if_name_len % 4)) {
2174 if_name_pad_len = 4 - (if_name_len % 4);
2176 if_name_pad_len = 0;
2178 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2182 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2184 if (wblock->data.if_descr.if_description) {
2185 have_options = TRUE;
2186 if_name_len = (guint32)strlen(wblock->data.if_descr.if_description) & 0xffff;
2187 if ((if_description_len % 4)) {
2188 if_description_pad_len = 4 - (if_description_len % 4);
2190 if_description_pad_len = 0;
2192 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2194 /* Currently not handled
2195 * if_IPv4addr 4 Interface network address and netmask.
2196 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2197 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2198 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2201 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2203 if (wblock->data.if_descr.if_speed != 0) {
2204 have_options = TRUE;
2205 options_total_length = options_total_length + 8 + 4;
2208 * if_tsresol 9 Resolution of timestamps.
2210 if (wblock->data.if_descr.if_tsresol != 0) {
2211 have_options = TRUE;
2212 options_total_length = options_total_length + 4 + 4;
2215 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2218 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2220 if (wblock->data.if_descr.if_filter) {
2223 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2225 if (wblock->data.if_descr.if_os) {
2226 have_options = TRUE;
2227 if_os_len = (guint32)strlen(wblock->data.if_descr.if_os) & 0xffff;
2228 if ((if_os_len % 4)) {
2229 if_os_pad_len = 4 - (if_os_len % 4);
2233 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2236 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2238 if (wblock->data.if_descr.opt_comment) {
2241 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2242 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2246 /* End-of-optios tag */
2247 options_total_length += 4;
2250 /* write block header */
2251 bh.block_type = wblock->type;
2252 bh.block_total_length = sizeof(bh) + sizeof(idb) + options_total_length + 4;
2254 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2256 wdh->bytes_dumped += sizeof bh;
2258 /* write block fixed content */
2259 idb.linktype = wblock->data.if_descr.link_type;
2261 idb.snaplen = wblock->data.if_descr.snap_len;
2263 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2265 wdh->bytes_dumped += sizeof idb;
2267 /* XXX - write (optional) block options */
2269 option_hdr.type = OPT_COMMENT;
2270 option_hdr.value_length = comment_len;
2271 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2273 wdh->bytes_dumped += 4;
2275 /* Write the comments string */
2276 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , wblock->data.if_descr.opt_comment, comment_len, comment_pad_len);
2277 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2279 wdh->bytes_dumped += comment_len;
2281 /* write padding (if any) */
2282 if (comment_pad_len != 0) {
2283 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2285 wdh->bytes_dumped += comment_pad_len;
2289 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2292 option_hdr.type = IDB_OPT_IF_NAME;
2293 option_hdr.value_length = if_name_len;
2294 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2296 wdh->bytes_dumped += 4;
2298 /* Write the comments string */
2299 pcapng_debug3("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , wblock->data.if_descr.if_name, if_name_len, if_name_pad_len);
2300 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_name, if_name_len, err))
2302 wdh->bytes_dumped += if_name_len;
2304 /* write padding (if any) */
2305 if (if_name_pad_len != 0) {
2306 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2308 wdh->bytes_dumped += if_name_pad_len;
2312 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2314 if (if_description_len) {
2315 option_hdr.type = IDB_OPT_IF_NAME;
2316 option_hdr.value_length = if_description_len;
2317 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2319 wdh->bytes_dumped += 4;
2321 /* Write the comments string */
2322 pcapng_debug3("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , wblock->data.if_descr.if_description, if_description_len, if_description_pad_len);
2323 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_description, if_description_len, err))
2325 wdh->bytes_dumped += comment_len;
2327 /* write padding (if any) */
2328 if (if_description_pad_len != 0) {
2329 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2331 wdh->bytes_dumped += if_description_pad_len;
2334 /* Currently not handled
2335 * if_IPv4addr 4 Interface network address and netmask.
2336 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2337 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2338 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2341 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2343 if (wblock->data.if_descr.if_speed != 0) {
2344 printf("HJKHJHK\n");
2345 option_hdr.type = IDB_OPT_IF_SPEED;
2346 option_hdr.value_length = 8;
2347 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2349 wdh->bytes_dumped += 4;
2351 /* Write the comments string */
2352 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
2353 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_speed, sizeof(guint64), err))
2355 wdh->bytes_dumped += 8;
2358 * if_tsresol 9 Resolution of timestamps.
2360 if (wblock->data.if_descr.if_tsresol != 0) {
2361 option_hdr.type = IDB_OPT_IF_TSRESOL;
2362 option_hdr.value_length = 1;
2363 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2365 wdh->bytes_dumped += 4;
2367 /* Write the comments string */
2368 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
2369 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_tsresol, 1, err))
2371 wdh->bytes_dumped += 1;
2372 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2374 wdh->bytes_dumped += 3;
2377 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2380 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2383 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2386 option_hdr.type = IDB_OPT_IF_OS;
2387 option_hdr.value_length = if_os_len;
2388 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2390 wdh->bytes_dumped += 4;
2392 /* Write the comments string */
2393 pcapng_debug3("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , wblock->data.if_descr.if_os, if_os_len, if_os_pad_len);
2394 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_os, if_os_len, err))
2396 wdh->bytes_dumped += comment_len;
2398 /* write padding (if any) */
2399 if (if_os_pad_len != 0) {
2400 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2402 wdh->bytes_dumped += if_os_pad_len;
2407 option_hdr.type = OPT_EOFOPT;
2408 option_hdr.value_length = 0;
2409 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2411 wdh->bytes_dumped += 4;
2415 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2418 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2419 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2422 /* write block footer */
2423 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2424 sizeof bh.block_total_length, err))
2426 wdh->bytes_dumped += sizeof bh.block_total_length;
2432 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2435 pcapng_block_header_t bh;
2436 pcapng_interface_statistics_block_t isb;
2437 const guint32 zero_pad = 0;
2438 gboolean have_options = FALSE;
2439 struct option option_hdr; /* guint16 type, guint16 value_length; */
2440 guint32 options_total_length = 0;
2441 guint32 comment_len = 0;
2442 guint32 comment_pad_len = 0;
2444 pcapng_debug0("pcapng_write_interface_statistics_block");
2447 /* Calculate options length */
2448 if (wblock->data.if_descr.opt_comment) {
2449 have_options = TRUE;
2450 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2451 if ((comment_len % 4)){
2452 comment_pad_len = 4 - (comment_len % 4);
2454 comment_pad_len = 0;
2456 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2459 /*guint32 isb_starttime_high;*/
2460 /*guint32 isb_starttime_low;*/
2461 /*guint32 isb_endtime_high;*/
2462 /*guint32 isb_endtime_low;*/
2463 /*guint64 isb_ifrecv;*/
2464 /*guint64 isb_ifdrop;*/
2465 /*guint64 isb_filteraccept;*/
2466 /*guint64 isb_osdrop;*/
2467 /*guint64 isb_usrdeliv;*/
2470 /* write block header */
2472 /* End-of-optios tag */
2473 options_total_length += 4;
2476 /* write block header */
2477 bh.block_type = wblock->type;
2478 bh.block_total_length = sizeof(bh) + sizeof(isb) + options_total_length + 4;
2480 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2482 wdh->bytes_dumped += sizeof bh;
2484 /* write block fixed content */
2485 isb.interface_id = wblock->data.if_stats.interface_id;
2486 isb.timestamp_high = wblock->data.if_stats.ts_high;
2487 isb.timestamp_low = wblock->data.if_stats.ts_low;
2490 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
2492 wdh->bytes_dumped += sizeof isb;
2494 /* write (optional) block options */
2496 option_hdr.type = OPT_COMMENT;
2497 option_hdr.value_length = comment_len;
2498 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2500 wdh->bytes_dumped += 4;
2502 /* Write the comments string */
2503 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , wblock->data.if_descr.opt_comment, comment_len, comment_pad_len);
2504 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2506 wdh->bytes_dumped += comment_len;
2508 /* write padding (if any) */
2509 if (comment_pad_len != 0) {
2510 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2512 wdh->bytes_dumped += comment_pad_len;
2516 /*guint32 isb_starttime */
2517 /*guint32 isb_endtime */
2518 /*guint64 isb_ifrecv;*/
2519 /*guint64 isb_ifdrop;*/
2520 /*guint64 isb_filteraccept;*/
2521 /*guint64 isb_osdrop;*/
2522 /*guint64 isb_usrdeliv;*/
2525 option_hdr.type = OPT_EOFOPT;
2526 option_hdr.value_length = 0;
2527 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2529 wdh->bytes_dumped += 4;
2532 /* write block footer */
2533 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2534 sizeof bh.block_total_length, err))
2536 wdh->bytes_dumped += sizeof bh.block_total_length;
2544 pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2546 pcapng_block_header_t bh;
2547 pcapng_enhanced_packet_block_t epb;
2548 const guint32 zero_pad = 0;
2551 gboolean have_options = FALSE;
2552 guint32 options_total_length = 0;
2553 guint32 options_hdr = 0;
2554 guint32 comment_len = 0, comment_pad_len = 0;
2556 phdr_len = (guint32)pcap_get_phdr_size(wblock->data.packet.wtap_encap, wblock->pseudo_header);
2557 if ((phdr_len + wblock->data.packet.cap_len) % 4) {
2558 pad_len = 4 - ((phdr_len + wblock->data.packet.cap_len) % 4);
2563 /* Check if we should write comment option */
2564 if(wblock->data.packet.opt_comment){
2565 have_options = TRUE;
2566 comment_len = (guint32)strlen(wblock->data.packet.opt_comment) & 0xffff;
2567 if((comment_len % 4)){
2568 comment_pad_len = 4 - (comment_len % 4);
2570 comment_pad_len = 0;
2572 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2576 /* End-of optios tag */
2577 options_total_length += 4;
2581 /* write (enhanced) packet block header */
2582 bh.block_type = wblock->type;
2583 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + wblock->data.packet.cap_len + pad_len + options_total_length + 4;
2585 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2587 wdh->bytes_dumped += sizeof bh;
2589 /* write block fixed content */
2590 epb.interface_id = wblock->data.packet.interface_id;
2591 epb.timestamp_high = wblock->data.packet.ts_high;
2592 epb.timestamp_low = wblock->data.packet.ts_low;
2593 epb.captured_len = wblock->data.packet.cap_len + phdr_len;
2594 epb.packet_len = wblock->data.packet.packet_len + phdr_len;
2596 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
2598 wdh->bytes_dumped += sizeof epb;
2600 /* write pseudo header */
2601 if (!pcap_write_phdr(wdh, wblock->data.packet.wtap_encap, wblock->pseudo_header, err)) {
2604 wdh->bytes_dumped += phdr_len;
2606 /* write packet data */
2607 if (!wtap_dump_file_write(wdh, wblock->frame_buffer,
2608 wblock->data.packet.cap_len, err))
2610 wdh->bytes_dumped += wblock->data.packet.cap_len;
2612 /* write padding (if any) */
2614 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
2616 wdh->bytes_dumped += pad_len;
2619 /* XXX - write (optional) block options */
2620 /* options defined in Section 2.5 (Options)
2621 * Name Code Length Description
2622 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
2624 * Enhanced Packet Block options
2625 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
2626 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
2627 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
2628 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
2629 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
2630 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
2631 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
2632 * The hash covers only the packet, not the header added by the capture driver:
2633 * this gives the possibility to calculate it inside the network card.
2634 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
2635 * data acquisition system and the capture library.
2636 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
2637 * between this packet and the preceding one.
2638 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
2640 if(wblock->data.packet.opt_comment){
2641 options_hdr = comment_len;
2642 options_hdr = options_hdr << 16;
2645 if (!wtap_dump_file_write(wdh, &options_hdr, 4, err))
2647 wdh->bytes_dumped += 4;
2649 /* Write the comments string */
2650 pcapng_debug3("pcapng_write_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , wblock->data.packet.opt_comment, comment_len, comment_pad_len);
2651 if (!wtap_dump_file_write(wdh, wblock->data.packet.opt_comment, comment_len, err))
2653 wdh->bytes_dumped += comment_len;
2655 /* write padding (if any) */
2656 if (comment_pad_len != 0) {
2657 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2659 wdh->bytes_dumped += comment_pad_len;
2662 pcapng_debug2("pcapng_write_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
2667 /* Write end of options if we have otions */
2669 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2671 wdh->bytes_dumped += 4;
2674 /* write block footer */
2675 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2676 sizeof bh.block_total_length, err))
2678 wdh->bytes_dumped += sizeof bh.block_total_length;
2684 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
2686 pcapng_write_name_resolution_block(wtap_dumper *wdh, pcapng_dump_t *pcapng, int *err)
2688 pcapng_block_header_t bh;
2689 pcapng_name_resolution_block_t nrb;
2690 struct addrinfo *ai;
2691 struct sockaddr_in *sa4;
2692 struct sockaddr_in6 *sa6;
2694 gint rec_off, namelen, tot_rec_len;
2696 if (! pcapng->addrinfo_list_last || ! pcapng->addrinfo_list_last->ai_next) {
2700 rec_off = 8; /* block type + block total length */
2701 bh.block_type = BLOCK_TYPE_NRB;
2702 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
2703 rec_data = g_malloc(NRES_REC_MAX_SIZE);
2705 for (; pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next; pcapng->addrinfo_list_last = pcapng->addrinfo_list_last->ai_next ) {
2706 ai = pcapng->addrinfo_list_last->ai_next; /* Skips over the first (dummy) entry */
2707 namelen = (gint)strlen(ai->ai_canonname) + 1;
2708 if (ai->ai_family == AF_INET) {
2709 nrb.record_type = NRES_IP4RECORD;
2710 nrb.record_len = 4 + namelen;
2711 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
2712 bh.block_total_length += tot_rec_len;
2714 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
2718 * The joys of BSD sockaddrs. In practice, this
2719 * cast is alignment-safe.
2721 sa4 = (struct sockaddr_in *)(void *)ai->ai_addr;
2722 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
2725 memcpy(rec_data + rec_off, &(sa4->sin_addr.s_addr), 4);
2728 memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
2731 memset(rec_data + rec_off, 0, PADDING4(namelen));
2732 rec_off += PADDING4(namelen);
2733 pcapng_debug1("NRB: added IPv4 record for %s", ai->ai_canonname);
2734 } else if (ai->ai_family == AF_INET6) {
2735 nrb.record_type = NRES_IP6RECORD;
2736 nrb.record_len = 16 + namelen;
2737 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
2738 bh.block_total_length += tot_rec_len;
2740 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
2744 * The joys of BSD sockaddrs. In practice, this
2745 * cast is alignment-safe.
2747 sa6 = (struct sockaddr_in6 *)(void *)ai->ai_addr;
2748 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
2751 memcpy(rec_data + rec_off, sa6->sin6_addr.s6_addr, 16);
2754 memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
2757 memset(rec_data + rec_off, 0, PADDING4(namelen));
2758 rec_off += PADDING4(namelen);
2759 pcapng_debug1("NRB: added IPv6 record for %s", ai->ai_canonname);
2763 /* We know the total length now; copy the block header. */
2764 memcpy(rec_data, &bh, sizeof(bh));
2767 memset(rec_data + rec_off, 0, 4);
2770 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
2772 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
2778 wdh->bytes_dumped += bh.block_total_length;
2784 pcapng_write_block(wtap_dumper *wdh, /*pcapng_t *pn, */wtapng_block_t *wblock, int *err)
2786 switch(wblock->type) {
2787 case(BLOCK_TYPE_SHB):
2788 return pcapng_write_section_header_block(wdh, wblock, err);
2789 case(BLOCK_TYPE_IDB):
2790 return pcapng_write_if_descr_block(wdh, wblock, err);
2791 case(BLOCK_TYPE_PB):
2792 /* Packet Block is obsolete */
2794 case(BLOCK_TYPE_ISB):
2795 /* Interface Statistics Block */
2796 return pcapng_write_interface_statistics_block(wdh, wblock, err);
2797 case(BLOCK_TYPE_EPB):
2798 return pcapng_write_packet_block(wdh, wblock, err);
2800 pcapng_debug1("Unknown block_type: 0x%x", wblock->type);
2807 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
2810 interface_data_t int_data;
2811 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
2813 for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
2814 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
2815 if (wtap_encap == int_data.wtap_encap) {
2823 static gboolean pcapng_dump(wtap_dumper *wdh,
2824 const struct wtap_pkthdr *phdr,
2825 const union wtap_pseudo_header *pseudo_header,
2826 const guint8 *pd, int *err)
2828 wtapng_block_t wblock;
2829 /*interface_data_t int_data;*/
2830 guint32 interface_id = 0;
2832 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
2835 pcapng_debug2("pcapng_dump: encap = %d (%s)",
2837 wtap_encap_string(phdr->pkt_encap));
2839 if (!pcapng->addrinfo_list_last)
2840 pcapng->addrinfo_list_last = wdh->addrinfo_list;
2841 /* Flush any hostname resolution info we may have */
2842 while (pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next) {
2843 pcapng_write_name_resolution_block(wdh, pcapng, err);
2846 wblock.frame_buffer = pd;
2847 wblock.pseudo_header = pseudo_header;
2848 wblock.packet_header = NULL;
2849 wblock.file_encap = NULL;
2851 /* write the (enhanced) packet block */
2852 wblock.type = BLOCK_TYPE_EPB;
2854 /* default is to write out in microsecond resolution */
2855 ts = (((guint64)phdr->ts.secs) * 1000000) + (phdr->ts.nsecs / 1000);
2857 /* Split the 64-bit timestamp into two 32-bit pieces */
2858 wblock.data.packet.ts_high = (guint32)(ts >> 32);
2859 wblock.data.packet.ts_low = (guint32)ts;
2861 wblock.data.packet.cap_len = phdr->caplen;
2862 wblock.data.packet.packet_len = phdr->len;
2863 wblock.data.packet.interface_id = interface_id;
2864 wblock.data.packet.wtap_encap = phdr->pkt_encap;
2866 /* currently unused */
2867 wblock.data.packet.drop_count = phdr->drop_count;
2868 wblock.data.packet.opt_comment = phdr->opt_comment;
2869 pcapng_debug1("pcapng_dump: Comment %s",phdr->opt_comment);
2871 if (!pcapng_write_block(wdh, &wblock, err)) {
2879 /* Finish writing to a dump file.
2880 Returns TRUE on success, FALSE on failure. */
2881 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
2883 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
2885 pcapng_debug0("pcapng_dump_close");
2886 g_array_free(pcapng->interface_data, TRUE);
2887 pcapng->number_of_interfaces = 0;
2892 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
2895 pcapng_dump_open(wtap_dumper *wdh, int *err)
2897 wtapng_block_t wblock;
2898 pcapng_dump_t *pcapng;
2900 interface_data_t interface_data;
2902 wblock.frame_buffer = NULL;
2903 wblock.pseudo_header = NULL;
2904 wblock.packet_header = NULL;
2905 wblock.file_encap = NULL;
2907 pcapng_debug0("pcapng_dump_open");
2908 /* This is a pcapng file */
2909 wdh->subtype_write = pcapng_dump;
2910 wdh->subtype_close = pcapng_dump_close;
2911 pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
2912 wdh->priv = (void *)pcapng;
2913 pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
2915 if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
2916 pcapng_debug0("There are no interfaces. Can't handle that...");
2917 *err = WTAP_ERR_INTERNAL;
2921 /* write the section header block */
2922 wblock.type = BLOCK_TYPE_SHB;
2923 wblock.data.section.section_length = -1;
2927 wblock.data.section.opt_comment = wdh->shb_hdr->opt_comment;
2928 wblock.data.section.shb_hardware = wdh->shb_hdr->shb_hardware;
2929 wblock.data.section.shb_os = wdh->shb_hdr->shb_os;
2930 wblock.data.section.shb_user_appl = wdh->shb_hdr->shb_user_appl;
2932 wblock.data.section.opt_comment = NULL;
2933 wblock.data.section.shb_hardware = NULL;
2934 wblock.data.section.shb_os = NULL;
2935 wblock.data.section.shb_user_appl = NULL;
2938 if (!pcapng_write_block(wdh, &wblock, err)) {
2941 pcapng_debug0("pcapng_dump_open: wrote section header block.");
2943 /* Write the Interface description blocks */
2944 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
2946 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
2948 /* Get the interface description */
2949 wtapng_if_descr_t int_data;
2951 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
2953 /* write the interface description block */
2954 wblock.data.if_descr.link_type = int_data.link_type;
2955 wblock.data.if_descr.wtap_encap = int_data.wtap_encap;
2956 wblock.data.if_descr.snap_len = int_data.snap_len;
2958 /* NULL if not available */
2959 wblock.data.if_descr.opt_comment = int_data.opt_comment;
2960 /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
2961 wblock.data.if_descr.if_name = int_data.if_name;
2962 /* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
2963 wblock.data.if_descr.if_description = int_data.if_description;
2964 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2965 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2966 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2967 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2968 /* 0xFFFFFFFF if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
2969 wblock.data.if_descr.if_speed = int_data.if_speed;
2970 /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
2971 * If the Most Significant Bit is equal to zero, the remaining bits indicates
2972 * the resolution of the timestamp as as a negative power of 10
2974 wblock.data.if_descr.if_tsresol = int_data.if_tsresol;
2975 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2976 /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2977 * 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).
2979 wblock.data.if_descr.if_filter = int_data.if_filter;
2980 /* 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. */
2981 wblock.data.if_descr.if_os = int_data.if_os;
2982 /* -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. */
2983 wblock.data.if_descr.if_fcslen = int_data.if_fcslen;
2984 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2986 wblock.frame_buffer = NULL;
2987 wblock.pseudo_header = NULL;
2988 wblock.packet_header = NULL;
2989 wblock.file_encap = NULL;
2990 wblock.type = BLOCK_TYPE_IDB;
2992 interface_data.wtap_encap = int_data.wtap_encap;;
2993 interface_data.time_units_per_second = int_data.time_units_per_second;
2995 g_array_append_val(pcapng->interface_data, interface_data);
2996 pcapng->number_of_interfaces++;
2998 if (!pcapng_write_block(wdh, &wblock, err)) {
3004 interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3005 if (interface_id == G_MAXUINT32) {
3007 * We haven't yet written out an interface description
3008 * block for an interface with this encapsulation.
3010 * Is this encapsulation even supported in pcap-ng?
3012 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3013 if (pcap_encap == -1) {
3017 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3021 /* write the interface description block */
3022 wblock.frame_buffer = NULL;
3023 wblock.pseudo_header = NULL;
3024 wblock.packet_header = NULL;
3025 wblock.file_encap = NULL;
3026 wblock.type = BLOCK_TYPE_IDB;
3027 wblock.data.if_descr.link_type = pcap_encap;
3028 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3029 WTAP_MAX_PACKET_SIZE; /* XXX */
3031 /* XXX - options unused */
3032 wblock.data.if_descr.if_speed = -1;
3033 /*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
3034 wblock.data.if_descr.if_os = NULL;
3035 wblock.data.if_descr.if_fcslen = -1;
3037 if (!pcapng_write_block(wdh, &wblock, err)) {
3041 interface_id = pcapng->number_of_interfaces;
3042 int_data.wtap_encap = phdr->pkt_encap;
3043 int_data.time_units_per_second = 0;
3044 g_array_append_val(pcapng->interface_data, int_data);
3045 pcapng->number_of_interfaces++;
3047 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3050 wtap_encap_string(phdr->pkt_encap));
3058 /* Returns 0 if we could write the specified encapsulation type,
3059 an error indication otherwise. */
3060 int pcapng_dump_can_write_encap(int wtap_encap)
3062 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3064 wtap_encap_string(wtap_encap));
3066 /* Per-packet encapsulations is supported. */
3067 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3070 /* Make sure we can figure out this DLT type */
3071 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3072 return WTAP_ERR_UNSUPPORTED_ENCAP;