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;
105 * Minimum block size = size of block header + size of block trailer.
107 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
109 /* pcapng: section header block */
110 typedef struct pcapng_section_header_block_s {
111 /* pcapng_block_header_t */
113 guint16 version_major;
114 guint16 version_minor;
115 guint64 section_length; /* might be -1 for unknown */
116 /* ... Options ... */
117 } pcapng_section_header_block_t;
120 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
122 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
124 /* pcapng: interface description block */
125 typedef struct pcapng_interface_description_block_s {
129 /* ... Options ... */
130 } pcapng_interface_description_block_t;
133 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
135 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
137 /* pcapng: packet block (obsolete) */
138 typedef struct pcapng_packet_block_s {
139 guint16 interface_id;
141 guint32 timestamp_high;
142 guint32 timestamp_low;
143 guint32 captured_len;
145 /* ... Packet Data ... */
146 /* ... Padding ... */
147 /* ... Options ... */
148 } pcapng_packet_block_t;
151 * Minimum PB size = minimum block size + size of fixed length portion of PB.
153 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
155 /* pcapng: enhanced packet block */
156 typedef struct pcapng_enhanced_packet_block_s {
157 guint32 interface_id;
158 guint32 timestamp_high;
159 guint32 timestamp_low;
160 guint32 captured_len;
162 /* ... Packet Data ... */
163 /* ... Padding ... */
164 /* ... Options ... */
165 } pcapng_enhanced_packet_block_t;
168 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
170 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
172 /* pcapng: simple packet block */
173 typedef struct pcapng_simple_packet_block_s {
175 /* ... Packet Data ... */
176 /* ... Padding ... */
177 } pcapng_simple_packet_block_t;
180 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
182 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
184 /* pcapng: name resolution block */
185 typedef struct pcapng_name_resolution_block_s {
189 } pcapng_name_resolution_block_t;
192 * Minimum NRB size = minimum block size + size of smallest NRB record
193 * (there must at least be an "end of records" record).
195 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
197 /* pcapng: interface statistics block */
198 typedef struct pcapng_interface_statistics_block_s {
199 guint32 interface_id;
200 guint32 timestamp_high;
201 guint32 timestamp_low;
202 /* ... Options ... */
203 } pcapng_interface_statistics_block_t;
206 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
208 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
210 /* pcapng: common option header for every option type */
211 typedef struct pcapng_option_header_s {
213 guint16 option_length;
214 /* ... x bytes Option Body ... */
215 /* ... Padding ... */
216 } pcapng_option_header_t;
220 guint16 value_length;
224 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
225 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
226 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
227 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
228 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
229 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
230 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
234 #define OPT_COMMENT 1
235 #define OPT_SHB_HARDWARE 2
237 #define OPT_SHB_USERAPPL 4
239 /* Capture section */
241 /* Moved to wtap.h */
242 typedef struct wtapng_section_s {
244 guint64 section_length;
246 gchar *opt_comment; /* NULL if not available */
247 gchar *shb_hardware; /* NULL if not available */
248 gchar *shb_os; /* NULL if not available */
249 gchar *shb_user_appl; /* NULL if not available */
254 /* Moved to wtap.h */
256 /* Interface Description
259 * 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}" / ...
260 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
261 * 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
262 * 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"
263 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
264 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
265 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
266 * 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
267 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
268 * 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"
269 * 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" / ...
270 * 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
271 * 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
274 typedef struct wtapng_if_descr_s {
280 gchar *opt_comment; /* NULL if not available */
281 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
282 gchar *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
283 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
284 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
285 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
286 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
287 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
288 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
289 * 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
291 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
292 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
293 * 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).
295 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. */
296 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. */
297 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
302 typedef struct wtapng_packet_s {
304 guint32 ts_high; /* seconds since 1.1.1970 */
305 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
306 guint32 cap_len; /* data length in the file */
307 guint32 packet_len; /* data length on the wire */
308 guint32 interface_id; /* identifier of the interface. */
309 guint16 drops_count; /* drops count, only valid for packet block */
310 /* 0xffff if information no available */
312 gchar *opt_comment; /* NULL if not available */
314 guint32 pack_flags; /* XXX - 0 for now (any value for "we don't have it"?) */
317 guint32 pseudo_header_len;
319 /* XXX - put the packet data / pseudo_header here as well? */
323 typedef struct wtapng_simple_packet_s {
325 guint32 cap_len; /* data length in the file */
326 guint32 packet_len; /* data length on the wire */
327 guint32 pseudo_header_len;
329 /* XXX - put the packet data / pseudo_header here as well? */
330 } wtapng_simple_packet_t;
332 /* Name Resolution */
333 typedef struct wtapng_name_res_s {
335 gchar *opt_comment; /* NULL if not available */
339 /* Interface Statistics */
340 typedef struct wtapng_if_stats_s {
342 guint32 interface_id;
346 gchar *opt_comment; /* NULL if not available */
347 guint64 isb_starttime;
351 guint64 isb_filteraccept;
353 guint64 isb_usrdeliv;
357 typedef struct wtapng_block_s {
358 guint32 type; /* block_type as defined by pcapng */
360 wtapng_section_t section;
361 wtapng_if_descr_t if_descr;
362 wtapng_packet_t packet;
363 wtapng_simple_packet_t simple_packet;
364 wtapng_name_res_t name_res;
365 wtapng_if_stats_t if_stats;
369 * XXX - currently don't know how to handle these!
371 * For one thing, when we're reading a block, they must be
372 * writable, i.e. not const, so that we can read into them,
373 * but, when we're writing a block, they can be const, and,
374 * in fact, they sometimes point to const values.
376 const union wtap_pseudo_header *pseudo_header;
377 struct wtap_pkthdr *packet_header;
378 const guint8 *frame_buffer;
382 /* Interface data in private struct */
383 typedef struct interface_data_s {
385 guint64 time_units_per_second;
389 gboolean shb_read; /**< Set when fisrt SHB read, second read will fail */
390 gboolean read_idbs; /**< Idicates that it is the first read after a SHB, atl east one IDB is expected */
391 gboolean byte_swapped;
392 guint16 version_major;
393 guint16 version_minor;
394 GArray *interface_data;
395 guint number_of_interfaces;
397 wtap_new_ipv4_callback_t add_new_ipv4;
398 wtap_new_ipv6_callback_t add_new_ipv6;
402 pcapng_get_encap(gint id, pcapng_t *pn)
404 interface_data_t int_data;
407 if ((id >= 0) && ((guint)id < pn->number_of_interfaces)) {
408 int_data = g_array_index(pn->interface_data, interface_data_t, id);
409 pcapng_debug2("pcapng_get_encap: id %i, wtap_encap %i",id, int_data.wtap_encap);
410 return int_data.wtap_encap;
412 pcapng_debug2("pcapng_get_encap: id %i number_of_interfaces %u, wtap_encap = WTAP_ERR_UNSUPPORTED_ENCAP",id,pn->number_of_interfaces);
413 return WTAP_ERR_UNSUPPORTED_ENCAP;
418 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
419 char *content, int len, int *err, gchar **err_info)
423 guint64 file_offset64;
426 /* read option header */
427 errno = WTAP_ERR_CANT_READ;
428 bytes_read = file_read(oh, sizeof (*oh), fh);
429 if (bytes_read != sizeof (*oh)) {
430 pcapng_debug0("pcapng_read_option: failed to read option");
431 *err = file_error(fh, err_info);
436 block_read = sizeof (*oh);
437 if(pn->byte_swapped) {
438 oh->option_code = BSWAP16(oh->option_code);
439 oh->option_length = BSWAP16(oh->option_length);
442 /* sanity check: option length */
443 if (oh->option_length > len) {
444 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
445 oh->option_length, len);
449 /* read option content */
450 errno = WTAP_ERR_CANT_READ;
451 bytes_read = file_read(content, oh->option_length, fh);
452 if (bytes_read != oh->option_length) {
453 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
454 *err = file_error(fh, err_info);
459 block_read += oh->option_length;
461 /* jump over potential padding bytes at end of option */
462 if( (oh->option_length % 4) != 0) {
463 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
464 if (file_offset64 <= 0) {
469 block_read += 4 - (oh->option_length % 4);
477 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
478 pcapng_block_header_t *bh, pcapng_t *pn,
479 wtapng_block_t *wblock, int *err,
484 int to_read, opt_cont_buf_len;
485 pcapng_section_header_block_t shb;
486 pcapng_option_header_t oh;
487 char *option_content = NULL; /* Allocate as large as the options block */
490 * Is this block long enough to be an SHB?
492 if (bh->block_total_length < MIN_SHB_SIZE) {
497 return 0; /* probably not a pcap-ng file */
498 *err = WTAP_ERR_BAD_FILE;
499 *err_info = g_strdup_printf("pcapng_read_section_header_block: total block length %u of an SHB is less than the minimum SHB size %u",
500 bh->block_total_length, MIN_SHB_SIZE);
504 /* read block content */
505 errno = WTAP_ERR_CANT_READ;
506 bytes_read = file_read(&shb, sizeof shb, fh);
507 if (bytes_read != sizeof shb) {
508 *err = file_error(fh, err_info);
512 * We're reading this as part of an open,
513 * and this block is too short to be
514 * an SHB, so the file is too short
515 * to be a pcap-ng file.
521 * Otherwise, just report this as an error.
523 *err = WTAP_ERR_SHORT_READ;
527 block_read = bytes_read;
529 /* is the magic number one we expect? */
532 /* this seems pcapng with correct byte order */
533 pn->byte_swapped = FALSE;
534 pn->version_major = shb.version_major;
535 pn->version_minor = shb.version_minor;
537 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
538 pn->version_major, pn->version_minor, bh->block_total_length);
541 /* this seems pcapng with swapped byte order */
542 pn->byte_swapped = TRUE;
543 pn->version_major = BSWAP16(shb.version_major);
544 pn->version_minor = BSWAP16(shb.version_minor);
546 /* tweak the block length to meet current swapping that we know now */
547 bh->block_total_length = BSWAP32(bh->block_total_length);
549 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
550 pn->version_major, pn->version_minor, bh->block_total_length);
553 /* Not a "pcapng" magic number we know about. */
555 /* Not a pcap-ng file. */
560 *err = WTAP_ERR_BAD_FILE;
561 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
565 /* OK, at this point we assume it's a pcap-ng file. */
566 /* We currently only suport one SHB */
567 if (pn->shb_read == TRUE) {
568 *err = WTAP_ERR_UNSUPPORTED;
569 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported.");
573 /* we currently only understand SHB V1.0 */
574 if (pn->version_major != 1 || pn->version_minor > 0) {
575 *err = WTAP_ERR_UNSUPPORTED;
576 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
577 pn->version_major, pn->version_minor);
582 /* 64bit section_length (currently unused) */
583 if (pn->byte_swapped) {
584 wblock->data.section.section_length = BSWAP64(shb.section_length);
586 wblock->data.section.section_length = shb.section_length;
589 /* Option defaults */
590 wblock->data.section.opt_comment = NULL;
591 wblock->data.section.shb_hardware = NULL;
592 wblock->data.section.shb_os = NULL;
593 wblock->data.section.shb_user_appl = NULL;
596 errno = WTAP_ERR_CANT_READ;
597 to_read = bh->block_total_length - MIN_SHB_SIZE;
598 /* Allocate enough memory to hold all options */
599 opt_cont_buf_len = to_read;
600 option_content = g_malloc(opt_cont_buf_len);
601 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
604 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
605 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
606 if (bytes_read <= 0) {
607 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
610 block_read += bytes_read;
611 to_read -= bytes_read;
613 /* handle option content */
614 switch(oh.option_code) {
615 case(0): /* opt_endofopt */
617 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
619 /* padding should be ok here, just get out of this */
622 case(1): /* opt_comment */
623 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
624 wblock->data.section.opt_comment = g_strndup(option_content, oh.option_length);
625 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
627 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
630 case(2): /* shb_hardware */
631 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
632 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
633 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
635 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
638 case(3): /* shb_os */
639 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
640 wblock->data.section.shb_os = g_strndup(option_content, oh.option_length);
641 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
643 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
646 case(4): /* shb_user_appl */
647 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
648 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
649 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
651 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
655 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
656 oh.option_code, oh.option_length);
659 g_free(option_content);
665 /* "Interface Description Block" */
667 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
668 wtapng_block_t *wblock, int *err, gchar **err_info)
670 guint64 time_units_per_second = 1000000; /* default */
673 int to_read, opt_cont_buf_len;
674 pcapng_interface_description_block_t idb;
675 pcapng_option_header_t oh;
676 char *option_content = NULL; /* Allocate as large as the options block */
679 * Is this block long enough to be an IDB?
681 if (bh->block_total_length < MIN_IDB_SIZE) {
685 *err = WTAP_ERR_BAD_FILE;
686 *err_info = g_strdup_printf("pcapng_read_if_descr_block: total block length %u of an IDB is less than the minimum IDB size %u",
687 bh->block_total_length, MIN_IDB_SIZE);
691 /* read block content */
692 errno = WTAP_ERR_CANT_READ;
693 bytes_read = file_read(&idb, sizeof idb, fh);
694 if (bytes_read != sizeof idb) {
695 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
696 *err = file_error(fh, err_info);
701 block_read = bytes_read;
703 /* mandatory values */
704 if (pn->byte_swapped) {
705 wblock->data.if_descr.link_type = BSWAP16(idb.linktype);
706 wblock->data.if_descr.snap_len = BSWAP32(idb.snaplen);
708 wblock->data.if_descr.link_type = idb.linktype;
709 wblock->data.if_descr.snap_len = idb.snaplen;
712 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
713 wblock->data.if_descr.time_units_per_second = time_units_per_second;
715 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
716 wblock->data.if_descr.link_type,
717 wtap_encap_string(wblock->data.if_descr.wtap_encap),
718 wblock->data.if_descr.snap_len);
720 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
721 /* This is unrealisitic, but text2pcap currently uses 102400.
722 * We do not use this value, maybe we should check the
723 * snap_len of the packets against it. For now, only warn.
725 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
726 wblock->data.if_descr.snap_len);
727 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
730 /* Option defaults */
731 wblock->data.if_descr.opt_comment = NULL;
732 wblock->data.if_descr.if_name = NULL;
733 wblock->data.if_descr.if_description = NULL;
734 /* XXX: if_IPv4addr */
735 /* XXX: if_IPv6addr */
736 /* XXX: if_MACaddr */
737 /* XXX: if_EUIaddr */
738 wblock->data.if_descr.if_speed = 0; /* "unknown" */
739 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
740 wblock->data.if_descr.if_filter = NULL;
741 wblock->data.if_descr.if_os = NULL;
742 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
743 /* XXX: guint64 if_tsoffset; */
747 errno = WTAP_ERR_CANT_READ;
748 to_read = bh->block_total_length - MIN_IDB_SIZE;
750 /* Allocate enough memory to hold all options */
751 opt_cont_buf_len = to_read;
752 option_content = g_malloc(opt_cont_buf_len);
754 while (to_read > 0) {
756 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
757 if (bytes_read <= 0) {
758 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
761 block_read += bytes_read;
762 to_read -= bytes_read;
764 /* handle option content */
765 switch(oh.option_code) {
766 case(0): /* opt_endofopt */
768 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
770 /* padding should be ok here, just get out of this */
773 case(1): /* opt_comment */
774 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
775 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
776 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
778 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
781 case(2): /* if_name */
782 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
783 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
784 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
786 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
789 case(3): /* if_description */
790 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
791 wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
792 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
794 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
798 * 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
799 * 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"
800 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
801 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
803 case(8): /* if_speed */
804 if (oh.option_length == 8) {
805 /* Don't cast a char[] into a guint64--the
806 * char[] may not be aligned correctly.
808 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
810 wblock->data.if_descr.if_speed = BSWAP64(wblock->data.if_descr.if_speed);
811 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
813 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
816 case(9): /* if_tsresol */
817 if (oh.option_length == 1) {
820 guint8 i, exponent, if_tsresol;
822 if_tsresol = option_content[0];
823 if (if_tsresol & 0x80) {
828 exponent = (guint8)(if_tsresol & 0x7f);
829 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
831 for (i = 0; i < exponent; i++) {
834 time_units_per_second = result;
836 time_units_per_second = G_MAXUINT64;
838 if (time_units_per_second > (((guint64)1) << 32)) {
839 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
841 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
842 wblock->data.if_descr.time_units_per_second = time_units_per_second;
843 wblock->data.if_descr.if_tsresol = if_tsresol;
845 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
849 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
851 case(11): /* if_filter */
852 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
853 wblock->data.if_descr.if_filter = g_strndup(option_content, oh.option_length);
854 pcapng_debug1("pcapng_read_if_descr_block: if_filter %s", wblock->data.if_descr.if_filter);
856 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
859 case(12): /* if_os */
861 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
862 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
863 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
865 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
866 wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
867 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
869 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
872 case(13): /* if_fcslen */
873 if (oh.option_length == 1) {
874 wblock->data.if_descr.if_fcslen = option_content[0];
875 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
876 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
877 /* XXX - add sanity check */
879 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
883 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
884 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
885 * The time zone of the offset can be specified with the option if_tzone.
886 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly syncronized capture systems? 1234
889 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
890 oh.option_code, oh.option_length);
894 g_free(option_content);
896 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
897 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
899 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
900 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
909 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)
913 int to_read, opt_cont_buf_len;
914 guint64 file_offset64;
915 pcapng_enhanced_packet_block_t epb;
916 pcapng_packet_block_t pb;
917 guint32 block_total_length;
919 pcapng_option_header_t oh;
921 int pseudo_header_len;
922 char *option_content = NULL; /* Allocate as large as the options block */
925 /* "(Enhanced) Packet Block" read fixed part */
926 errno = WTAP_ERR_CANT_READ;
929 * Is this block long enough to be an EPB?
931 if (bh->block_total_length < MIN_EPB_SIZE) {
935 *err = WTAP_ERR_BAD_FILE;
936 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
937 bh->block_total_length, MIN_EPB_SIZE);
940 bytes_read = file_read(&epb, sizeof epb, fh);
941 if (bytes_read != sizeof epb) {
942 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
943 *err = file_error(fh, err_info);
946 block_read = bytes_read;
948 if (pn->byte_swapped) {
949 wblock->data.packet.interface_id = BSWAP32(epb.interface_id);
950 wblock->data.packet.drops_count = -1; /* invalid */
951 wblock->data.packet.ts_high = BSWAP32(epb.timestamp_high);
952 wblock->data.packet.ts_low = BSWAP32(epb.timestamp_low);
953 wblock->data.packet.cap_len = BSWAP32(epb.captured_len);
954 wblock->data.packet.packet_len = BSWAP32(epb.packet_len);
956 wblock->data.packet.interface_id = epb.interface_id;
957 wblock->data.packet.drops_count = -1; /* invalid */
958 wblock->data.packet.ts_high = epb.timestamp_high;
959 wblock->data.packet.ts_low = epb.timestamp_low;
960 wblock->data.packet.cap_len = epb.captured_len;
961 wblock->data.packet.packet_len = epb.packet_len;
965 * Is this block long enough to be a PB?
967 if (bh->block_total_length < MIN_PB_SIZE) {
971 *err = WTAP_ERR_BAD_FILE;
972 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
973 bh->block_total_length, MIN_PB_SIZE);
976 bytes_read = file_read(&pb, sizeof pb, fh);
977 if (bytes_read != sizeof pb) {
978 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
979 *err = file_error(fh, err_info);
982 block_read = bytes_read;
984 if (pn->byte_swapped) {
985 wblock->data.packet.interface_id = BSWAP16(pb.interface_id);
986 wblock->data.packet.drops_count = BSWAP16(pb.drops_count);
987 wblock->data.packet.ts_high = BSWAP32(pb.timestamp_high);
988 wblock->data.packet.ts_low = BSWAP32(pb.timestamp_low);
989 wblock->data.packet.cap_len = BSWAP32(pb.captured_len);
990 wblock->data.packet.packet_len = BSWAP32(pb.packet_len);
992 wblock->data.packet.interface_id = pb.interface_id;
993 wblock->data.packet.drops_count = pb.drops_count;
994 wblock->data.packet.ts_high = pb.timestamp_high;
995 wblock->data.packet.ts_low = pb.timestamp_low;
996 wblock->data.packet.cap_len = pb.captured_len;
997 wblock->data.packet.packet_len = pb.packet_len;
1003 * How much padding is there at the end of the packet data?
1005 if ((wblock->data.packet.cap_len % 4) != 0)
1006 padding = 4 - (wblock->data.packet.cap_len % 4);
1010 /* add padding bytes to "block total length" */
1011 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1012 if (bh->block_total_length % 4) {
1013 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1015 block_total_length = bh->block_total_length;
1019 * Is this block long enough to hold the packet data?
1022 if (block_total_length <
1023 MIN_EPB_SIZE + wblock->data.packet.cap_len + padding) {
1027 *err = WTAP_ERR_BAD_FILE;
1028 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1029 block_total_length, wblock->data.packet.cap_len);
1033 if (block_total_length <
1034 MIN_PB_SIZE + wblock->data.packet.cap_len + padding) {
1038 *err = WTAP_ERR_BAD_FILE;
1039 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1040 block_total_length, wblock->data.packet.cap_len);
1045 if (wblock->data.packet.cap_len > wblock->data.packet.packet_len) {
1046 *err = WTAP_ERR_BAD_FILE;
1047 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u.",
1048 wblock->data.packet.cap_len, wblock->data.packet.packet_len);
1051 if (wblock->data.packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1052 *err = WTAP_ERR_BAD_FILE;
1053 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1054 wblock->data.packet.cap_len, WTAP_MAX_PACKET_SIZE);
1057 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1058 wblock->data.packet.packet_len,
1059 wblock->data.packet.cap_len,
1060 wblock->data.packet.interface_id);
1062 wtap_encap = pcapng_get_encap(wblock->data.packet.interface_id, pn);
1063 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1065 wtap_encap_string(wtap_encap),
1066 pcap_get_phdr_size(wtap_encap, wblock->pseudo_header));
1068 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1069 pseudo_header_len = pcap_process_pseudo_header(fh,
1072 wblock->data.packet.cap_len,
1074 wblock->packet_header,
1075 (union wtap_pseudo_header *)wblock->pseudo_header,
1078 if (pseudo_header_len < 0) {
1081 wblock->data.packet.pseudo_header_len = (guint32)pseudo_header_len;
1082 block_read += pseudo_header_len;
1083 if (pseudo_header_len != pcap_get_phdr_size(wtap_encap, wblock->pseudo_header)) {
1084 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1088 /* "(Enhanced) Packet Block" read capture data */
1089 errno = WTAP_ERR_CANT_READ;
1090 bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.packet.cap_len - pseudo_header_len, fh);
1091 if (bytes_read != (int) (wblock->data.packet.cap_len - pseudo_header_len)) {
1092 *err = file_error(fh, err_info);
1093 pcapng_debug1("pcapng_read_packet_block: couldn't read %u bytes of captured data",
1094 wblock->data.packet.cap_len - pseudo_header_len);
1096 *err = WTAP_ERR_SHORT_READ;
1099 block_read += bytes_read;
1101 /* jump over potential padding bytes at end of the packet data */
1103 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1104 if (file_offset64 <= 0) {
1109 block_read += padding;
1112 /* Option defaults */
1113 wblock->data.packet.opt_comment = NULL;
1114 wblock->data.packet.drop_count = -1;
1115 wblock->data.packet.pack_flags = 0; /* XXX - is 0 ok to signal "not used"? */
1117 /* FCS length default */
1118 fcslen = pn->if_fcslen;
1126 errno = WTAP_ERR_CANT_READ;
1127 to_read = block_total_length -
1128 (int)sizeof(pcapng_block_header_t) -
1129 block_read - /* fixed and variable part, including padding */
1130 (int)sizeof(bh->block_total_length);
1132 /* Allocate enough memory to hold all options */
1133 opt_cont_buf_len = to_read;
1134 option_content = g_malloc(opt_cont_buf_len);
1136 while(to_read > 0) {
1138 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
1139 if (bytes_read <= 0) {
1140 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1143 block_read += bytes_read;
1144 to_read -= bytes_read;
1146 /* handle option content */
1147 switch(oh.option_code) {
1148 case(0): /* opt_endofopt */
1150 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1152 /* padding should be ok here, just get out of this */
1155 case(1): /* opt_comment */
1156 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1157 wblock->data.packet.opt_comment = g_strndup(option_content, oh.option_length);
1158 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->data.packet.opt_comment);
1160 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1163 case(2): /* pack_flags / epb_flags */
1164 if(oh.option_length == 4) {
1165 /* Don't cast a char[] into a guint32--the
1166 * char[] may not be aligned correctly.
1168 memcpy(&wblock->data.packet.pack_flags, option_content, sizeof(guint32));
1169 if(pn->byte_swapped)
1170 wblock->data.packet.pack_flags = BSWAP32(wblock->data.packet.pack_flags);
1171 if (wblock->data.packet.pack_flags & 0x000001E0) {
1172 /* The FCS length is present */
1173 fcslen = (wblock->data.packet.pack_flags & 0x000001E0) >> 5;
1175 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->data.packet.pack_flags);
1177 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1180 case(3): /* epb_hash */
1181 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1182 oh.option_code, oh.option_length);
1184 case(4): /* epb_dropcount */
1185 if(oh.option_length == 8) {
1186 /* Don't cast a char[] into a guint32--the
1187 * char[] may not be aligned correctly.
1189 memcpy(&wblock->data.packet.drop_count, option_content, sizeof(guint64));
1190 if(pn->byte_swapped)
1191 wblock->data.packet.drop_count = BSWAP64(wblock->data.packet.drop_count);
1193 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->data.packet.drop_count);
1195 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1199 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1200 oh.option_code, oh.option_length);
1204 g_free(option_content);
1206 pcap_read_post_process(WTAP_FILE_PCAPNG, wtap_encap,
1207 (union wtap_pseudo_header *)wblock->pseudo_header,
1208 (guint8 *) (wblock->frame_buffer),
1209 (int) (wblock->data.packet.cap_len - pseudo_header_len),
1210 pn->byte_swapped, fcslen);
1216 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)
1220 guint64 file_offset64;
1222 int pseudo_header_len;
1223 pcapng_simple_packet_block_t spb;
1226 * Is this block long enough to be an SPB?
1228 if (bh->block_total_length < MIN_SPB_SIZE) {
1232 *err = WTAP_ERR_BAD_FILE;
1233 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of an SPB is less than the minimum SPB size %u",
1234 bh->block_total_length, MIN_SPB_SIZE);
1238 /* "Simple Packet Block" read fixed part */
1239 errno = WTAP_ERR_CANT_READ;
1240 bytes_read = file_read(&spb, sizeof spb, fh);
1241 if (bytes_read != sizeof spb) {
1242 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1243 *err = file_error(fh, err_info);
1246 block_read = bytes_read;
1248 if (pn->byte_swapped) {
1249 wblock->data.simple_packet.packet_len = BSWAP32(spb.packet_len);
1251 wblock->data.simple_packet.packet_len = spb.packet_len;
1254 wblock->data.simple_packet.cap_len = bh->block_total_length
1255 - (guint32)sizeof(pcapng_simple_packet_block_t)
1256 - (guint32)sizeof(bh->block_total_length);
1258 if (wblock->data.simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1259 *err = WTAP_ERR_BAD_FILE;
1260 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1261 wblock->data.simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1264 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1265 wblock->data.simple_packet.packet_len);
1267 encap = pcapng_get_encap(0, pn);
1268 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1269 pcap_get_phdr_size(encap, wblock->pseudo_header));
1271 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1272 pseudo_header_len = pcap_process_pseudo_header(fh,
1275 wblock->data.simple_packet.cap_len,
1277 wblock->packet_header,
1278 (union wtap_pseudo_header *)wblock->pseudo_header,
1281 if (pseudo_header_len < 0) {
1284 wblock->data.simple_packet.pseudo_header_len = (guint32)pseudo_header_len;
1285 block_read += pseudo_header_len;
1286 if (pseudo_header_len != pcap_get_phdr_size(encap, wblock->pseudo_header)) {
1287 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1291 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1293 /* "Simple Packet Block" read capture data */
1294 errno = WTAP_ERR_CANT_READ;
1295 bytes_read = file_read((guint8 *) (wblock->frame_buffer), wblock->data.simple_packet.cap_len, fh);
1296 if (bytes_read != (int) wblock->data.simple_packet.cap_len) {
1297 *err = file_error(fh, err_info);
1298 pcapng_debug1("pcapng_read_simple_packet_block: couldn't read %u bytes of captured data",
1299 wblock->data.simple_packet.cap_len);
1301 *err = WTAP_ERR_SHORT_READ;
1304 block_read += bytes_read;
1306 /* jump over potential padding bytes at end of the packet data */
1307 if ((wblock->data.simple_packet.cap_len % 4) != 0) {
1308 file_offset64 = file_seek(fh, 4 - (wblock->data.simple_packet.cap_len % 4), SEEK_CUR, err);
1309 if (file_offset64 <= 0) {
1314 block_read += 4 - (wblock->data.simple_packet.cap_len % 4);
1317 pcap_read_post_process(WTAP_FILE_PCAPNG, encap,
1318 (union wtap_pseudo_header *)wblock->pseudo_header,
1319 (guint8 *) (wblock->frame_buffer),
1320 (int) wblock->data.simple_packet.cap_len,
1321 pn->byte_swapped, pn->if_fcslen);
1325 #define NRES_ENDOFRECORD 0
1326 #define NRES_IP4RECORD 1
1327 #define NRES_IP6RECORD 2
1328 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1329 /* IPv6 + MAXNAMELEN */
1330 #define MAX_NRB_REC_SIZE (16 + 64)
1332 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)
1337 guint64 file_offset64;
1338 pcapng_name_resolution_block_t nrb;
1339 guint8 nrb_rec[MAX_NRB_REC_SIZE];
1343 * Is this block long enough to be an NRB?
1345 if (bh->block_total_length < MIN_NRB_SIZE) {
1349 *err = WTAP_ERR_BAD_FILE;
1350 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u is too small (< %u)",
1351 bh->block_total_length, MIN_NRB_SIZE);
1355 errno = WTAP_ERR_CANT_READ;
1356 to_read = bh->block_total_length - MIN_NRB_SIZE;
1358 while (block_read < to_read) {
1360 * There must be at least one record's worth of data
1363 if ((size_t)(to_read - block_read) < sizeof nrb) {
1364 *err = WTAP_ERR_BAD_FILE;
1365 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1366 to_read - block_read,
1370 bytes_read = file_read(&nrb, sizeof nrb, fh);
1371 if (bytes_read != sizeof nrb) {
1372 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1373 *err = file_error(fh, err_info);
1376 block_read += bytes_read;
1378 if (pn->byte_swapped) {
1379 nrb.record_type = BSWAP16(nrb.record_type);
1380 nrb.record_len = BSWAP16(nrb.record_len);
1383 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1384 *err = WTAP_ERR_BAD_FILE;
1385 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1386 to_read - block_read,
1387 nrb.record_len + PADDING4(nrb.record_len));
1390 switch(nrb.record_type) {
1391 case NRES_ENDOFRECORD:
1392 /* There shouldn't be any more data */
1395 case NRES_IP4RECORD:
1396 if (nrb.record_len < 4) {
1397 *err = WTAP_ERR_BAD_FILE;
1398 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1402 if (nrb.record_len > MAX_NRB_REC_SIZE) {
1403 pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv4 record");
1406 bytes_read = file_read(nrb_rec, nrb.record_len, fh);
1407 if (bytes_read != nrb.record_len) {
1408 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1409 *err = file_error(fh, err_info);
1412 block_read += bytes_read;
1414 if (pn->add_new_ipv4) {
1415 memcpy(&v4_addr, nrb_rec, 4);
1416 if (pn->byte_swapped)
1417 v4_addr = BSWAP32(v4_addr);
1418 pn->add_new_ipv4(v4_addr, nrb_rec + 4);
1421 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1422 if (file_offset64 <= 0) {
1427 block_read += PADDING4(nrb.record_len);
1429 case NRES_IP6RECORD:
1430 if (nrb.record_len < 16) {
1431 *err = WTAP_ERR_BAD_FILE;
1432 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1436 if (nrb.record_len > MAX_NRB_REC_SIZE || to_read < nrb.record_len) {
1437 pcapng_debug0("pcapng_read_name_resolution_block: bad length or insufficient data for IPv6 record");
1440 bytes_read = file_read(nrb_rec, nrb.record_len, fh);
1441 if (bytes_read != nrb.record_len) {
1442 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1443 *err = file_error(fh, err_info);
1446 block_read += bytes_read;
1448 if (pn->add_new_ipv6) {
1449 pn->add_new_ipv6(nrb_rec, nrb_rec + 16);
1452 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1453 if (file_offset64 <= 0) {
1458 block_read += PADDING4(nrb.record_len);
1461 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1462 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1463 if (file_offset64 <= 0) {
1468 block_read += nrb.record_len + PADDING4(nrb.record_len);
1477 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)
1481 int to_read, opt_cont_buf_len;
1482 pcapng_interface_statistics_block_t isb;
1483 pcapng_option_header_t oh;
1484 char *option_content = NULL; /* Allocate as large as the options block */
1487 * Is this block long enough to be an ISB?
1489 if (bh->block_total_length < MIN_ISB_SIZE) {
1493 *err = WTAP_ERR_BAD_FILE;
1494 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u is too small (< %u)",
1495 bh->block_total_length, MIN_NRB_SIZE);
1499 /* "Interface Statistics Block" read fixed part */
1500 errno = WTAP_ERR_CANT_READ;
1501 bytes_read = file_read(&isb, sizeof isb, fh);
1502 if (bytes_read != sizeof isb) {
1503 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1504 *err = file_error(fh, err_info);
1507 block_read = bytes_read;
1509 if(pn->byte_swapped) {
1510 wblock->data.if_stats.interface_id = BSWAP64(isb.interface_id);
1511 wblock->data.if_stats.ts_high = BSWAP32(isb.timestamp_high);
1512 wblock->data.if_stats.ts_low = BSWAP32(isb.timestamp_low);
1514 wblock->data.if_stats.interface_id = isb.interface_id;
1515 wblock->data.if_stats.ts_high = isb.timestamp_high;
1516 wblock->data.if_stats.ts_low = isb.timestamp_low;
1518 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %" G_GINT64_MODIFIER "u", wblock->data.if_stats.interface_id);
1520 /* Option defaults */
1521 wblock->data.if_stats.opt_comment = NULL;
1522 wblock->data.if_stats.isb_ifrecv = -1;
1523 wblock->data.if_stats.isb_ifdrop = -1;
1526 errno = WTAP_ERR_CANT_READ;
1527 to_read = bh->block_total_length -
1528 (MIN_BLOCK_SIZE + block_read); /* fixed and variable part, including padding */
1530 /* Allocate enough memory to hold all options */
1531 opt_cont_buf_len = to_read;
1532 option_content = g_malloc(opt_cont_buf_len);
1534 while(to_read > 0) {
1536 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, err, err_info);
1537 if (bytes_read <= 0) {
1538 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1541 block_read += bytes_read;
1542 to_read -= bytes_read;
1544 /* handle option content */
1545 switch(oh.option_code) {
1546 case(0): /* opt_endofopt */
1548 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1550 /* padding should be ok here, just get out of this */
1553 case(1): /* opt_comment */
1554 if(oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1555 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1556 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1558 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1561 case(2): /* isb_starttime */
1562 if(oh.option_length == 8) {
1563 /* Don't cast a char[] into a guint32--the
1564 * char[] may not be aligned correctly.
1566 memcpy(&wblock->data.if_stats.isb_starttime, option_content, sizeof(guint64));
1567 if(pn->byte_swapped)
1568 wblock->data.if_stats.isb_starttime = BSWAP64(wblock->data.if_stats.isb_starttime);
1569 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1571 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1574 case(3): /* isb_endtime */
1575 if(oh.option_length == 8) {
1576 /* Don't cast a char[] into a guint32--the
1577 * char[] may not be aligned correctly.
1579 memcpy(&wblock->data.if_stats.isb_endtime, option_content, sizeof(guint64));
1580 if(pn->byte_swapped)
1581 wblock->data.if_stats.isb_endtime = BSWAP64(wblock->data.if_stats.isb_endtime);
1582 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1584 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1587 case(4): /* isb_ifrecv */
1588 if(oh.option_length == 8) {
1589 /* Don't cast a char[] into a guint32--the
1590 * char[] may not be aligned correctly.
1592 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1593 if(pn->byte_swapped)
1594 wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
1595 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1597 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1600 case(5): /* isb_ifdrop */
1601 if(oh.option_length == 8) {
1602 /* Don't cast a char[] into a guint32--the
1603 * char[] may not be aligned correctly.
1605 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1606 if(pn->byte_swapped)
1607 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
1608 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1610 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1613 case(6): /* isb_filteraccept 6 */
1614 if(oh.option_length == 8) {
1615 /* Don't cast a char[] into a guint32--the
1616 * char[] may not be aligned correctly.
1618 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1619 if(pn->byte_swapped)
1620 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_filteraccept);
1621 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1623 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1626 case(7): /* isb_osdrop 7 */
1627 if(oh.option_length == 8) {
1628 /* Don't cast a char[] into a guint32--the
1629 * char[] may not be aligned correctly.
1631 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1632 if(pn->byte_swapped)
1633 wblock->data.if_stats.isb_osdrop = BSWAP64(wblock->data.if_stats.isb_osdrop);
1634 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1636 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1639 case(8): /* isb_usrdeliv 8 */
1640 if(oh.option_length == 8) {
1641 /* Don't cast a char[] into a guint32--the
1642 * char[] may not be aligned correctly.
1644 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1645 if(pn->byte_swapped)
1646 wblock->data.if_stats.isb_usrdeliv = BSWAP64(wblock->data.if_stats.isb_osdrop);
1647 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1649 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1653 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1654 oh.option_code, oh.option_length);
1658 g_free(option_content);
1665 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_)
1668 guint64 file_offset64;
1669 guint32 block_total_length;
1672 /* add padding bytes to "block total length" */
1673 /* (the "block total length" of some example files don't contain any padding bytes!) */
1674 if (bh->block_total_length % 4) {
1675 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1677 block_total_length = bh->block_total_length;
1680 block_read = block_total_length - MIN_BLOCK_SIZE;
1682 /* jump over this unknown block */
1683 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1684 if (file_offset64 <= 0) {
1695 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1699 pcapng_block_header_t bh;
1700 guint32 block_total_length;
1703 /* Try to read the (next) block header */
1704 errno = WTAP_ERR_CANT_READ;
1705 bytes_read = file_read(&bh, sizeof bh, fh);
1706 if (bytes_read != sizeof bh) {
1707 *err = file_error(fh, err_info);
1708 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
1714 block_read = bytes_read;
1715 if (pn->byte_swapped) {
1716 bh.block_type = BSWAP32(bh.block_type);
1717 bh.block_total_length = BSWAP32(bh.block_total_length);
1720 wblock->type = bh.block_type;
1722 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
1726 * This is being read in by pcapng_open(), so this block
1727 * must be an SHB. If it's not, this is not a pcap-ng
1730 * XXX - check for various forms of Windows <-> UN*X
1731 * mangling, and suggest that the file might be a
1732 * pcap-ng file that was damaged in transit?
1734 if (bh.block_type != BLOCK_TYPE_SHB)
1735 return 0; /* not a pcap-ng file */
1738 if (bh.block_total_length < MIN_BLOCK_SIZE) {
1740 * This isn't even enough for the block type and 2
1741 * block total length fields.
1744 return 0; /* probably not a pcap-ng file */
1745 *err = WTAP_ERR_BAD_FILE;
1746 *err_info = g_strdup_printf("pcapng_read_block: total block length %u is too small (< %u)",
1747 bh.block_total_length, (guint32)MIN_BLOCK_SIZE);
1751 switch(bh.block_type) {
1752 case(BLOCK_TYPE_SHB):
1753 bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
1755 case(BLOCK_TYPE_IDB):
1756 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
1758 case(BLOCK_TYPE_PB):
1759 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
1761 case(BLOCK_TYPE_SPB):
1762 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
1764 case(BLOCK_TYPE_EPB):
1765 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
1767 case(BLOCK_TYPE_NRB):
1768 bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
1770 case(BLOCK_TYPE_ISB):
1771 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
1774 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
1775 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
1778 if (bytes_read <= 0) {
1781 block_read += bytes_read;
1783 /* sanity check: first and second block lengths must match */
1784 errno = WTAP_ERR_CANT_READ;
1785 bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
1786 if (bytes_read != sizeof block_total_length) {
1787 pcapng_debug0("pcapng_read_block: couldn't read second block length");
1788 *err = file_error(fh, err_info);
1790 *err = WTAP_ERR_SHORT_READ;
1793 block_read += bytes_read;
1795 if (pn->byte_swapped)
1796 block_total_length = BSWAP32(block_total_length);
1798 if (!(block_total_length == bh.block_total_length)) {
1799 *err = WTAP_ERR_BAD_FILE;
1800 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
1801 bh.block_total_length, block_total_length);
1809 /* classic wtap: open capture file */
1811 pcapng_open(wtap *wth, int *err, gchar **err_info)
1815 wtapng_block_t wblock;
1817 wtapng_if_descr_t int_data;
1818 interface_data_t interface_data;
1819 pcapng_block_header_t bh;
1822 pn.shb_read = FALSE;
1823 pn.read_idbs = TRUE; /* IDB expected after SHB */
1824 /* we don't know the byte swapping of the file yet */
1825 pn.byte_swapped = FALSE;
1827 pn.version_major = -1;
1828 pn.version_minor = -1;
1829 pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
1830 pn.number_of_interfaces = 0;
1833 /* we don't expect any packet blocks yet */
1834 wblock.frame_buffer = NULL;
1835 wblock.pseudo_header = NULL;
1836 wblock.packet_header = NULL;
1837 wblock.file_encap = &wth->file_encap;
1839 pcapng_debug0("pcapng_open: opening file");
1840 /* read first block */
1841 bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
1842 if (bytes_read <= 0) {
1843 pcapng_debug0("pcapng_open: couldn't read first SHB");
1844 *err = file_error(wth->fh, err_info);
1849 wth->data_offset += bytes_read;
1851 /* first block must be a "Section Header Block" */
1852 if (wblock.type != BLOCK_TYPE_SHB) {
1854 * XXX - check for damage from transferring a file
1855 * between Windows and UN*X as text rather than
1858 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
1864 * At this point, we've decided this is a pcap-NG file, not
1865 * some other type of file, so we can't return 0, as that
1866 * means "this isn't a pcap-NG file, try some other file
1869 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
1870 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
1871 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
1872 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
1874 wth->file_encap = WTAP_ENCAP_UNKNOWN;
1875 wth->snapshot_length = 0;
1876 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
1877 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
1878 wth->priv = (void *)pcapng;
1881 wth->subtype_read = pcapng_read;
1882 wth->subtype_seek_read = pcapng_seek_read;
1883 wth->subtype_close = pcapng_close;
1884 wth->file_type = WTAP_FILE_PCAPNG;
1887 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1888 wth->number_of_interfaces = 0;
1890 /* Loop ower all IDB:s that appear before any packets */
1892 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
1893 wth->data_offset += bytes_read;
1894 if (bytes_read == 0) {
1895 pcapng_debug0("No more IDBs available...");
1898 if (bytes_read <= 0) {
1899 pcapng_debug0("pcapng_open: couldn't read IDB");
1900 *err = file_error(wth->fh, err_info);
1902 *err = WTAP_ERR_SHORT_READ;
1906 int_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1907 int_data.time_units_per_second = wblock.data.if_descr.time_units_per_second;
1908 int_data.link_type = wblock.data.if_descr.link_type;
1909 int_data.snap_len = wblock.data.if_descr.snap_len;
1911 int_data.opt_comment = wblock.data.if_descr.opt_comment;
1912 int_data.if_name = wblock.data.if_descr.if_name;
1913 int_data.if_description = wblock.data.if_descr.if_description;
1914 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
1915 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
1916 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
1917 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
1918 int_data.if_speed = wblock.data.if_descr.if_speed;
1919 int_data.if_tsresol = wblock.data.if_descr.if_tsresol;
1920 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
1921 int_data.if_filter = wblock.data.if_descr.if_filter;
1922 int_data.if_os = wblock.data.if_descr.if_os;
1923 int_data.if_fcslen = wblock.data.if_descr.if_fcslen;
1924 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
1926 g_array_append_val(wth->interface_data, int_data);
1927 wth->number_of_interfaces++;
1929 interface_data.wtap_encap = wblock.data.if_descr.wtap_encap;
1930 interface_data.time_units_per_second = 1000000; /* default */
1932 g_array_append_val(pcapng->interface_data, interface_data);
1933 pcapng->number_of_interfaces++;
1935 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, int_data.wtap_encap);
1937 /* peek at next block */
1938 /* Try to read the (next) block header */
1939 errno = WTAP_ERR_CANT_READ;
1940 bytes_read = file_read(&bh, sizeof bh, wth->fh);
1941 if (bytes_read == 0) {
1942 pcapng_debug0("No more IDBs available...");
1945 if (bytes_read != sizeof bh) {
1946 *err = file_error(wth->fh, err_info);
1947 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);
1949 *err = WTAP_ERR_SHORT_READ;
1953 /* go back to where we were */
1954 file_seek(wth->fh, wth->data_offset, SEEK_SET, err);
1956 if (pn.byte_swapped) {
1957 bh.block_type = BSWAP32(bh.block_type);
1960 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
1962 if (bh.block_type != BLOCK_TYPE_IDB){
1963 break; /* No more IDB:s */
1967 pcapng->read_idbs = FALSE;
1973 /* classic wtap: read packet */
1975 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1977 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1980 wtapng_block_t wblock;
1982 pcapng_debug1("pcapng_read: wth->data_offset is initially %" G_GINT64_MODIFIER "u", wth->data_offset);
1983 *data_offset = wth->data_offset;
1984 pcapng_debug1("pcapng_read: *data_offset is initially set to %" G_GINT64_MODIFIER "u", *data_offset);
1986 /* XXX - This should be done in the packet block reading function and
1987 * should make use of the caplen of the packet.
1989 if (wth->snapshot_length > 0) {
1990 buffer_assure_space(wth->frame_buffer, wth->snapshot_length);
1992 buffer_assure_space(wth->frame_buffer, WTAP_MAX_PACKET_SIZE);
1995 wblock.frame_buffer = buffer_start_ptr(wth->frame_buffer);
1996 wblock.pseudo_header = &wth->pseudo_header;
1997 wblock.packet_header = &wth->phdr;
1998 wblock.file_encap = &wth->file_encap;
2000 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2001 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2003 /* read next block */
2005 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2006 if (bytes_read <= 0) {
2007 wth->data_offset = *data_offset;
2008 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2009 pcapng_debug0("pcapng_read: couldn't read packet block");
2013 /* block must be a "Packet Block" or an "Enhanced Packet Block" -> otherwise continue */
2014 if (wblock.type == BLOCK_TYPE_PB || wblock.type == BLOCK_TYPE_EPB) {
2018 /* XXX - improve handling of "unknown" blocks */
2019 pcapng_debug1("pcapng_read: block type 0x%x not PB/EPB", wblock.type);
2020 *data_offset += bytes_read;
2021 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "u", *data_offset);
2024 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
2025 ts = (((guint64)wblock.data.packet.ts_high) << 32) | ((guint64)wblock.data.packet.ts_low);
2027 wth->phdr.caplen = wblock.data.packet.cap_len - wblock.data.packet.pseudo_header_len;
2028 wth->phdr.len = wblock.data.packet.packet_len - wblock.data.packet.pseudo_header_len;
2029 if (wblock.data.packet.interface_id < pcapng->number_of_interfaces) {
2030 interface_data_t int_data;
2031 guint64 time_units_per_second;
2034 id = (gint)wblock.data.packet.interface_id;
2035 int_data = g_array_index(pcapng->interface_data, interface_data_t, id);
2036 time_units_per_second = int_data.time_units_per_second;
2037 wth->phdr.pkt_encap = int_data.wtap_encap;
2038 wth->phdr.ts.secs = (time_t)(ts / time_units_per_second);
2039 wth->phdr.ts.nsecs = (int)(((ts % time_units_per_second) * 1000000000) / time_units_per_second);
2041 wth->phdr.interface_id = wblock.data.packet.interface_id;
2042 wth->phdr.opt_comment = wblock.data.packet.opt_comment;
2043 wth->phdr.drop_count = wblock.data.packet.drop_count;
2044 wth->phdr.pack_flags = wblock.data.packet.pack_flags;
2046 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2047 *err = WTAP_ERR_BAD_FILE;
2048 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
2049 wblock.data.packet.interface_id, pcapng->number_of_interfaces);
2050 wth->data_offset = *data_offset + bytes_read;
2051 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2055 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2056 wth->data_offset = *data_offset + bytes_read;
2057 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
2063 /* classic wtap: seek to file position and read packet */
2065 pcapng_seek_read(wtap *wth, gint64 seek_off,
2066 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length _U_,
2067 int *err, gchar **err_info)
2069 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2070 guint64 bytes_read64;
2072 wtapng_block_t wblock;
2075 /* seek to the right file position */
2076 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2077 if (bytes_read64 <= 0) {
2078 return FALSE; /* Seek error */
2080 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2082 wblock.frame_buffer = pd;
2083 wblock.pseudo_header = pseudo_header;
2084 wblock.packet_header = &wth->phdr;
2085 wblock.file_encap = &wth->file_encap;
2087 /* read the block */
2088 bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2089 if (bytes_read <= 0) {
2090 *err = file_error(wth->random_fh, err_info);
2091 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2092 *err, errno, bytes_read);
2096 /* block must be a "Packet Block" or an "Enhanced Packet Block" */
2097 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB) {
2098 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB", wblock.type);
2106 /* classic wtap: close capture file */
2108 pcapng_close(wtap *wth)
2110 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2112 pcapng_debug0("pcapng_close: closing file");
2113 if (pcapng->interface_data != NULL) {
2114 g_array_free(pcapng->interface_data, TRUE);
2121 GArray *interface_data;
2122 guint number_of_interfaces;
2123 struct addrinfo *addrinfo_list_last;
2127 pcapng_write_section_header_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2129 pcapng_block_header_t bh;
2130 pcapng_section_header_block_t shb;
2131 const guint32 zero_pad = 0;
2132 gboolean have_options = FALSE;
2133 struct option option_hdr; /* guint16 type, guint16 value_length; */
2134 guint32 options_total_length = 0;
2135 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2136 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2139 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2140 /* Check if we should write comment option */
2141 if (wdh->shb_hdr->opt_comment) {
2142 have_options = TRUE;
2143 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2144 if ((comment_len % 4)) {
2145 comment_pad_len = 4 - (comment_len % 4);
2147 comment_pad_len = 0;
2149 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2152 /* Check if we should write shb_hardware option */
2153 if (wdh->shb_hdr->shb_hardware) {
2154 have_options = TRUE;
2155 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2156 if ((shb_hardware_len % 4)) {
2157 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2159 shb_hardware_pad_len = 0;
2161 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2164 /* Check if we should write shb_os option */
2165 if (wdh->shb_hdr->shb_os) {
2166 have_options = TRUE;
2167 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2168 if ((shb_os_len % 4)) {
2169 shb_os_pad_len = 4 - (shb_os_len % 4);
2173 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2176 /* Check if we should write shb_user_appl option */
2177 if (wdh->shb_hdr->shb_user_appl) {
2178 have_options = TRUE;
2179 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2180 if ((shb_user_appl_len % 4)) {
2181 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2183 shb_user_appl_pad_len = 0;
2185 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2188 /* End-of-optios tag */
2189 options_total_length += 4;
2193 /* write block header */
2194 bh.block_type = wblock->type;
2195 bh.block_total_length = sizeof(bh) + sizeof(shb) + options_total_length + 4;
2196 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2198 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2200 wdh->bytes_dumped += sizeof bh;
2202 /* write block fixed content */
2203 /* XXX - get these values from wblock? */
2204 shb.magic = 0x1A2B3C4D;
2205 shb.version_major = 1;
2206 shb.version_minor = 0;
2207 shb.section_length = -1;
2209 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2211 wdh->bytes_dumped += sizeof shb;
2213 /* XXX - write (optional) block options
2221 option_hdr.type = OPT_COMMENT;
2222 option_hdr.value_length = comment_len;
2223 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2225 wdh->bytes_dumped += 4;
2227 /* Write the comments string */
2228 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);
2229 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2231 wdh->bytes_dumped += comment_len;
2233 /* write padding (if any) */
2234 if (comment_pad_len != 0) {
2235 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2237 wdh->bytes_dumped += comment_pad_len;
2241 if (shb_hardware_len) {
2242 option_hdr.type = OPT_SHB_HARDWARE;
2243 option_hdr.value_length = shb_hardware_len;
2244 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2246 wdh->bytes_dumped += 4;
2248 /* Write the string */
2249 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);
2250 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2252 wdh->bytes_dumped += shb_hardware_len;
2254 /* write padding (if any) */
2255 if (shb_hardware_pad_len != 0) {
2256 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2258 wdh->bytes_dumped += shb_hardware_pad_len;
2263 option_hdr.type = OPT_SHB_OS;
2264 option_hdr.value_length = shb_os_len;
2265 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2267 wdh->bytes_dumped += 4;
2269 /* Write the string */
2270 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);
2271 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2273 wdh->bytes_dumped += shb_os_len;
2275 /* write padding (if any) */
2276 if (shb_os_pad_len != 0) {
2277 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2279 wdh->bytes_dumped += shb_os_pad_len;
2283 if (shb_user_appl_len) {
2284 option_hdr.type = OPT_SHB_USERAPPL;
2285 option_hdr.value_length = shb_user_appl_len;
2286 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2288 wdh->bytes_dumped += 4;
2290 /* Write the comments string */
2291 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);
2292 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2294 wdh->bytes_dumped += shb_user_appl_len;
2296 /* write padding (if any) */
2297 if (shb_user_appl_pad_len != 0) {
2298 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2300 wdh->bytes_dumped += shb_user_appl_pad_len;
2304 /* Write end of options if we have otions */
2306 option_hdr.type = OPT_EOFOPT;
2307 option_hdr.value_length = 0;
2308 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2310 wdh->bytes_dumped += 4;
2313 /* write block footer */
2314 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2315 sizeof bh.block_total_length, err))
2317 wdh->bytes_dumped += sizeof bh.block_total_length;
2322 #define IDB_OPT_IF_NAME 2
2323 #define IDB_OPT_IF_DESCR 3
2324 #define IDB_OPT_IF_SPEED 8
2325 #define IDB_OPT_IF_TSRESOL 9
2326 #define IDB_OPT_IF_FILTER 11
2327 #define IDB_OPT_IF_OS 12
2330 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2332 pcapng_block_header_t bh;
2333 pcapng_interface_description_block_t idb;
2334 const guint32 zero_pad = 0;
2335 gboolean have_options = FALSE;
2336 struct option option_hdr; /* guint16 type, guint16 value_length; */
2337 guint32 options_total_length = 0;
2338 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0;
2339 guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0;
2342 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2343 wblock->data.if_descr.link_type,
2344 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
2345 wblock->data.if_descr.snap_len);
2347 if (wblock->data.if_descr.link_type == (guint16)-1) {
2348 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2352 /* Calculate options length */
2353 if (wblock->data.if_descr.opt_comment) {
2354 have_options = TRUE;
2355 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2356 if ((comment_len % 4)){
2357 comment_pad_len = 4 - (comment_len % 4);
2359 comment_pad_len = 0;
2361 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2365 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2367 if (wblock->data.if_descr.if_name){
2368 have_options = TRUE;
2369 if_name_len = (guint32)strlen(wblock->data.if_descr.if_name) & 0xffff;
2370 if ((if_name_len % 4)) {
2371 if_name_pad_len = 4 - (if_name_len % 4);
2373 if_name_pad_len = 0;
2375 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2379 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2381 if (wblock->data.if_descr.if_description) {
2382 have_options = TRUE;
2383 if_name_len = (guint32)strlen(wblock->data.if_descr.if_description) & 0xffff;
2384 if ((if_description_len % 4)) {
2385 if_description_pad_len = 4 - (if_description_len % 4);
2387 if_description_pad_len = 0;
2389 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2391 /* Currently not handled
2392 * if_IPv4addr 4 Interface network address and netmask.
2393 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2394 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2395 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2398 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2400 if (wblock->data.if_descr.if_speed != 0) {
2401 have_options = TRUE;
2402 options_total_length = options_total_length + 8 + 4;
2405 * if_tsresol 9 Resolution of timestamps.
2407 if (wblock->data.if_descr.if_tsresol != 0) {
2408 have_options = TRUE;
2409 options_total_length = options_total_length + 4 + 4;
2412 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2415 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2417 if (wblock->data.if_descr.if_filter) {
2420 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2422 if (wblock->data.if_descr.if_os) {
2423 have_options = TRUE;
2424 if_os_len = (guint32)strlen(wblock->data.if_descr.if_os) & 0xffff;
2425 if ((if_os_len % 4)) {
2426 if_os_pad_len = 4 - (if_os_len % 4);
2430 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2433 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2435 if (wblock->data.if_descr.opt_comment) {
2438 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2439 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2443 /* End-of-optios tag */
2444 options_total_length += 4;
2447 /* write block header */
2448 bh.block_type = wblock->type;
2449 bh.block_total_length = sizeof(bh) + sizeof(idb) + options_total_length + 4;
2451 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2453 wdh->bytes_dumped += sizeof bh;
2455 /* write block fixed content */
2456 idb.linktype = wblock->data.if_descr.link_type;
2458 idb.snaplen = wblock->data.if_descr.snap_len;
2460 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2462 wdh->bytes_dumped += sizeof idb;
2464 /* XXX - write (optional) block options */
2466 option_hdr.type = OPT_COMMENT;
2467 option_hdr.value_length = comment_len;
2468 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2470 wdh->bytes_dumped += 4;
2472 /* Write the comments string */
2473 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);
2474 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2476 wdh->bytes_dumped += comment_len;
2478 /* write padding (if any) */
2479 if (comment_pad_len != 0) {
2480 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2482 wdh->bytes_dumped += comment_pad_len;
2486 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2489 option_hdr.type = IDB_OPT_IF_NAME;
2490 option_hdr.value_length = if_name_len;
2491 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2493 wdh->bytes_dumped += 4;
2495 /* Write the comments string */
2496 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);
2497 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_name, if_name_len, err))
2499 wdh->bytes_dumped += if_name_len;
2501 /* write padding (if any) */
2502 if (if_name_pad_len != 0) {
2503 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2505 wdh->bytes_dumped += if_name_pad_len;
2509 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2511 if (if_description_len) {
2512 option_hdr.type = IDB_OPT_IF_NAME;
2513 option_hdr.value_length = if_description_len;
2514 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2516 wdh->bytes_dumped += 4;
2518 /* Write the comments string */
2519 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);
2520 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_description, if_description_len, err))
2522 wdh->bytes_dumped += comment_len;
2524 /* write padding (if any) */
2525 if (if_description_pad_len != 0) {
2526 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2528 wdh->bytes_dumped += if_description_pad_len;
2531 /* Currently not handled
2532 * if_IPv4addr 4 Interface network address and netmask.
2533 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2534 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2535 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2538 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2540 if (wblock->data.if_descr.if_speed != 0) {
2541 printf("HJKHJHK\n");
2542 option_hdr.type = IDB_OPT_IF_SPEED;
2543 option_hdr.value_length = 8;
2544 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2546 wdh->bytes_dumped += 4;
2548 /* Write the comments string */
2549 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
2550 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_speed, sizeof(guint64), err))
2552 wdh->bytes_dumped += 8;
2555 * if_tsresol 9 Resolution of timestamps.
2557 if (wblock->data.if_descr.if_tsresol != 0) {
2558 option_hdr.type = IDB_OPT_IF_TSRESOL;
2559 option_hdr.value_length = 1;
2560 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2562 wdh->bytes_dumped += 4;
2564 /* Write the comments string */
2565 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
2566 if (!wtap_dump_file_write(wdh, &wblock->data.if_descr.if_tsresol, 1, err))
2568 wdh->bytes_dumped += 1;
2569 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2571 wdh->bytes_dumped += 3;
2574 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2577 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2580 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2583 option_hdr.type = IDB_OPT_IF_OS;
2584 option_hdr.value_length = if_os_len;
2585 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2587 wdh->bytes_dumped += 4;
2589 /* Write the comments string */
2590 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);
2591 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.if_os, if_os_len, err))
2593 wdh->bytes_dumped += comment_len;
2595 /* write padding (if any) */
2596 if (if_os_pad_len != 0) {
2597 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2599 wdh->bytes_dumped += if_os_pad_len;
2604 option_hdr.type = OPT_EOFOPT;
2605 option_hdr.value_length = 0;
2606 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2608 wdh->bytes_dumped += 4;
2612 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2615 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2616 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2619 /* write block footer */
2620 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2621 sizeof bh.block_total_length, err))
2623 wdh->bytes_dumped += sizeof bh.block_total_length;
2629 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2632 pcapng_block_header_t bh;
2633 pcapng_interface_statistics_block_t isb;
2634 const guint32 zero_pad = 0;
2635 gboolean have_options = FALSE;
2636 struct option option_hdr; /* guint16 type, guint16 value_length; */
2637 guint32 options_total_length = 0;
2638 guint32 comment_len = 0;
2639 guint32 comment_pad_len = 0;
2641 pcapng_debug0("pcapng_write_interface_statistics_block");
2644 /* Calculate options length */
2645 if (wblock->data.if_descr.opt_comment) {
2646 have_options = TRUE;
2647 comment_len = (guint32)strlen(wblock->data.if_descr.opt_comment) & 0xffff;
2648 if ((comment_len % 4)){
2649 comment_pad_len = 4 - (comment_len % 4);
2651 comment_pad_len = 0;
2653 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2656 /*guint32 isb_starttime_high;*/
2657 /*guint32 isb_starttime_low;*/
2658 /*guint32 isb_endtime_high;*/
2659 /*guint32 isb_endtime_low;*/
2660 /*guint64 isb_ifrecv;*/
2661 /*guint64 isb_ifdrop;*/
2662 /*guint64 isb_filteraccept;*/
2663 /*guint64 isb_osdrop;*/
2664 /*guint64 isb_usrdeliv;*/
2667 /* write block header */
2669 /* End-of-optios tag */
2670 options_total_length += 4;
2673 /* write block header */
2674 bh.block_type = wblock->type;
2675 bh.block_total_length = sizeof(bh) + sizeof(isb) + options_total_length + 4;
2677 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2679 wdh->bytes_dumped += sizeof bh;
2681 /* write block fixed content */
2682 isb.interface_id = wblock->data.if_stats.interface_id;
2683 isb.timestamp_high = wblock->data.if_stats.ts_high;
2684 isb.timestamp_low = wblock->data.if_stats.ts_low;
2687 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
2689 wdh->bytes_dumped += sizeof isb;
2691 /* write (optional) block options */
2693 option_hdr.type = OPT_COMMENT;
2694 option_hdr.value_length = comment_len;
2695 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2697 wdh->bytes_dumped += 4;
2699 /* Write the comments string */
2700 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);
2701 if (!wtap_dump_file_write(wdh, wblock->data.if_descr.opt_comment, comment_len, err))
2703 wdh->bytes_dumped += comment_len;
2705 /* write padding (if any) */
2706 if (comment_pad_len != 0) {
2707 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2709 wdh->bytes_dumped += comment_pad_len;
2713 /*guint32 isb_starttime */
2714 /*guint32 isb_endtime */
2715 /*guint64 isb_ifrecv;*/
2716 /*guint64 isb_ifdrop;*/
2717 /*guint64 isb_filteraccept;*/
2718 /*guint64 isb_osdrop;*/
2719 /*guint64 isb_usrdeliv;*/
2722 option_hdr.type = OPT_EOFOPT;
2723 option_hdr.value_length = 0;
2724 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2726 wdh->bytes_dumped += 4;
2729 /* write block footer */
2730 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2731 sizeof bh.block_total_length, err))
2733 wdh->bytes_dumped += sizeof bh.block_total_length;
2741 pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
2743 pcapng_block_header_t bh;
2744 pcapng_enhanced_packet_block_t epb;
2745 const guint32 zero_pad = 0;
2748 gboolean have_options = FALSE;
2749 guint32 options_total_length = 0;
2750 guint32 options_hdr = 0;
2751 guint32 comment_len = 0, comment_pad_len = 0;
2753 phdr_len = (guint32)pcap_get_phdr_size(wblock->data.packet.wtap_encap, wblock->pseudo_header);
2754 if ((phdr_len + wblock->data.packet.cap_len) % 4) {
2755 pad_len = 4 - ((phdr_len + wblock->data.packet.cap_len) % 4);
2760 /* Check if we should write comment option */
2761 if(wblock->data.packet.opt_comment){
2762 have_options = TRUE;
2763 comment_len = (guint32)strlen(wblock->data.packet.opt_comment) & 0xffff;
2764 if((comment_len % 4)){
2765 comment_pad_len = 4 - (comment_len % 4);
2767 comment_pad_len = 0;
2769 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2773 /* End-of optios tag */
2774 options_total_length += 4;
2778 /* write (enhanced) packet block header */
2779 bh.block_type = wblock->type;
2780 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + wblock->data.packet.cap_len + pad_len + options_total_length + 4;
2782 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2784 wdh->bytes_dumped += sizeof bh;
2786 /* write block fixed content */
2787 epb.interface_id = wblock->data.packet.interface_id;
2788 epb.timestamp_high = wblock->data.packet.ts_high;
2789 epb.timestamp_low = wblock->data.packet.ts_low;
2790 epb.captured_len = wblock->data.packet.cap_len + phdr_len;
2791 epb.packet_len = wblock->data.packet.packet_len + phdr_len;
2793 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
2795 wdh->bytes_dumped += sizeof epb;
2797 /* write pseudo header */
2798 if (!pcap_write_phdr(wdh, wblock->data.packet.wtap_encap, wblock->pseudo_header, err)) {
2801 wdh->bytes_dumped += phdr_len;
2803 /* write packet data */
2804 if (!wtap_dump_file_write(wdh, wblock->frame_buffer,
2805 wblock->data.packet.cap_len, err))
2807 wdh->bytes_dumped += wblock->data.packet.cap_len;
2809 /* write padding (if any) */
2811 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
2813 wdh->bytes_dumped += pad_len;
2816 /* XXX - write (optional) block options */
2817 /* options defined in Section 2.5 (Options)
2818 * Name Code Length Description
2819 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
2821 * Enhanced Packet Block options
2822 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
2823 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
2824 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
2825 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
2826 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
2827 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
2828 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
2829 * The hash covers only the packet, not the header added by the capture driver:
2830 * this gives the possibility to calculate it inside the network card.
2831 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
2832 * data acquisition system and the capture library.
2833 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
2834 * between this packet and the preceding one.
2835 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
2837 if(wblock->data.packet.opt_comment){
2838 options_hdr = comment_len;
2839 options_hdr = options_hdr << 16;
2842 if (!wtap_dump_file_write(wdh, &options_hdr, 4, err))
2844 wdh->bytes_dumped += 4;
2846 /* Write the comments string */
2847 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);
2848 if (!wtap_dump_file_write(wdh, wblock->data.packet.opt_comment, comment_len, err))
2850 wdh->bytes_dumped += comment_len;
2852 /* write padding (if any) */
2853 if (comment_pad_len != 0) {
2854 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2856 wdh->bytes_dumped += comment_pad_len;
2859 pcapng_debug2("pcapng_write_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
2864 /* Write end of options if we have otions */
2866 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2868 wdh->bytes_dumped += 4;
2871 /* write block footer */
2872 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2873 sizeof bh.block_total_length, err))
2875 wdh->bytes_dumped += sizeof bh.block_total_length;
2881 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
2883 pcapng_write_name_resolution_block(wtap_dumper *wdh, pcapng_dump_t *pcapng, int *err)
2885 pcapng_block_header_t bh;
2886 pcapng_name_resolution_block_t nrb;
2887 struct addrinfo *ai;
2888 struct sockaddr_in *sa4;
2889 struct sockaddr_in6 *sa6;
2891 gint rec_off, namelen, tot_rec_len;
2893 if (! pcapng->addrinfo_list_last || ! pcapng->addrinfo_list_last->ai_next) {
2897 rec_off = 8; /* block type + block total length */
2898 bh.block_type = BLOCK_TYPE_NRB;
2899 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
2900 rec_data = g_malloc(NRES_REC_MAX_SIZE);
2902 for (; pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next; pcapng->addrinfo_list_last = pcapng->addrinfo_list_last->ai_next ) {
2903 ai = pcapng->addrinfo_list_last->ai_next; /* Skips over the first (dummy) entry */
2904 namelen = (gint)strlen(ai->ai_canonname) + 1;
2905 if (ai->ai_family == AF_INET) {
2906 nrb.record_type = NRES_IP4RECORD;
2907 nrb.record_len = 4 + namelen;
2908 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
2909 bh.block_total_length += tot_rec_len;
2911 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
2915 * The joys of BSD sockaddrs. In practice, this
2916 * cast is alignment-safe.
2918 sa4 = (struct sockaddr_in *)(void *)ai->ai_addr;
2919 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
2922 memcpy(rec_data + rec_off, &(sa4->sin_addr.s_addr), 4);
2925 memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
2928 memset(rec_data + rec_off, 0, PADDING4(namelen));
2929 rec_off += PADDING4(namelen);
2930 pcapng_debug1("NRB: added IPv4 record for %s", ai->ai_canonname);
2931 } else if (ai->ai_family == AF_INET6) {
2932 nrb.record_type = NRES_IP6RECORD;
2933 nrb.record_len = 16 + namelen;
2934 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
2935 bh.block_total_length += tot_rec_len;
2937 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE)
2941 * The joys of BSD sockaddrs. In practice, this
2942 * cast is alignment-safe.
2944 sa6 = (struct sockaddr_in6 *)(void *)ai->ai_addr;
2945 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
2948 memcpy(rec_data + rec_off, sa6->sin6_addr.s6_addr, 16);
2951 memcpy(rec_data + rec_off, ai->ai_canonname, namelen);
2954 memset(rec_data + rec_off, 0, PADDING4(namelen));
2955 rec_off += PADDING4(namelen);
2956 pcapng_debug1("NRB: added IPv6 record for %s", ai->ai_canonname);
2960 /* We know the total length now; copy the block header. */
2961 memcpy(rec_data, &bh, sizeof(bh));
2964 memset(rec_data + rec_off, 0, 4);
2967 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
2969 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
2975 wdh->bytes_dumped += bh.block_total_length;
2981 pcapng_write_block(wtap_dumper *wdh, /*pcapng_t *pn, */wtapng_block_t *wblock, int *err)
2983 switch(wblock->type) {
2984 case(BLOCK_TYPE_SHB):
2985 return pcapng_write_section_header_block(wdh, wblock, err);
2986 case(BLOCK_TYPE_IDB):
2987 return pcapng_write_if_descr_block(wdh, wblock, err);
2988 case(BLOCK_TYPE_PB):
2989 /* Packet Block is obsolete */
2991 case(BLOCK_TYPE_ISB):
2992 /* Interface Statistics Block */
2993 return pcapng_write_interface_statistics_block(wdh, wblock, err);
2994 case(BLOCK_TYPE_EPB):
2995 return pcapng_write_packet_block(wdh, wblock, err);
2997 pcapng_debug1("Unknown block_type: 0x%x", wblock->type);
3004 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
3007 interface_data_t int_data;
3008 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3010 for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
3011 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
3012 if (wtap_encap == int_data.wtap_encap) {
3020 static gboolean pcapng_dump(wtap_dumper *wdh,
3021 const struct wtap_pkthdr *phdr,
3022 const union wtap_pseudo_header *pseudo_header,
3023 const guint8 *pd, int *err)
3025 wtapng_block_t wblock;
3026 /*interface_data_t int_data;*/
3027 guint32 interface_id = 0;
3029 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3032 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3034 wtap_encap_string(phdr->pkt_encap));
3036 if (!pcapng->addrinfo_list_last)
3037 pcapng->addrinfo_list_last = wdh->addrinfo_list;
3038 /* Flush any hostname resolution info we may have */
3039 while (pcapng->addrinfo_list_last && pcapng->addrinfo_list_last->ai_next) {
3040 pcapng_write_name_resolution_block(wdh, pcapng, err);
3043 wblock.frame_buffer = pd;
3044 wblock.pseudo_header = pseudo_header;
3045 wblock.packet_header = NULL;
3046 wblock.file_encap = NULL;
3048 /* write the (enhanced) packet block */
3049 wblock.type = BLOCK_TYPE_EPB;
3051 /* default is to write out in microsecond resolution */
3052 ts = (((guint64)phdr->ts.secs) * 1000000) + (phdr->ts.nsecs / 1000);
3054 /* Split the 64-bit timestamp into two 32-bit pieces */
3055 wblock.data.packet.ts_high = (guint32)(ts >> 32);
3056 wblock.data.packet.ts_low = (guint32)ts;
3058 wblock.data.packet.cap_len = phdr->caplen;
3059 wblock.data.packet.packet_len = phdr->len;
3060 wblock.data.packet.interface_id = interface_id;
3061 wblock.data.packet.wtap_encap = phdr->pkt_encap;
3063 /* currently unused */
3064 wblock.data.packet.drop_count = phdr->drop_count;
3065 wblock.data.packet.opt_comment = phdr->opt_comment;
3066 pcapng_debug1("pcapng_dump: Comment %s",phdr->opt_comment);
3068 if (!pcapng_write_block(wdh, &wblock, err)) {
3076 /* Finish writing to a dump file.
3077 Returns TRUE on success, FALSE on failure. */
3078 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3080 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3082 pcapng_debug0("pcapng_dump_close");
3083 g_array_free(pcapng->interface_data, TRUE);
3084 pcapng->number_of_interfaces = 0;
3089 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3092 pcapng_dump_open(wtap_dumper *wdh, int *err)
3094 wtapng_block_t wblock;
3095 pcapng_dump_t *pcapng;
3097 interface_data_t interface_data;
3099 wblock.frame_buffer = NULL;
3100 wblock.pseudo_header = NULL;
3101 wblock.packet_header = NULL;
3102 wblock.file_encap = NULL;
3104 pcapng_debug0("pcapng_dump_open");
3105 /* This is a pcapng file */
3106 wdh->subtype_write = pcapng_dump;
3107 wdh->subtype_close = pcapng_dump_close;
3108 pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
3109 wdh->priv = (void *)pcapng;
3110 pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
3112 if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
3113 pcapng_debug0("There are no interfaces. Can't handle that...");
3114 *err = WTAP_ERR_INTERNAL;
3118 /* write the section header block */
3119 wblock.type = BLOCK_TYPE_SHB;
3120 wblock.data.section.section_length = -1;
3124 wblock.data.section.opt_comment = wdh->shb_hdr->opt_comment;
3125 wblock.data.section.shb_hardware = wdh->shb_hdr->shb_hardware;
3126 wblock.data.section.shb_os = wdh->shb_hdr->shb_os;
3127 wblock.data.section.shb_user_appl = wdh->shb_hdr->shb_user_appl;
3129 wblock.data.section.opt_comment = NULL;
3130 wblock.data.section.shb_hardware = NULL;
3131 wblock.data.section.shb_os = NULL;
3132 wblock.data.section.shb_user_appl = NULL;
3135 if (!pcapng_write_block(wdh, &wblock, err)) {
3138 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3140 /* Write the Interface description blocks */
3141 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
3143 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3145 /* Get the interface description */
3146 wtapng_if_descr_t int_data;
3148 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3150 /* write the interface description block */
3151 wblock.data.if_descr.link_type = int_data.link_type;
3152 wblock.data.if_descr.wtap_encap = int_data.wtap_encap;
3153 wblock.data.if_descr.snap_len = int_data.snap_len;
3155 /* NULL if not available */
3156 wblock.data.if_descr.opt_comment = int_data.opt_comment;
3157 /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
3158 wblock.data.if_descr.if_name = int_data.if_name;
3159 /* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
3160 wblock.data.if_descr.if_description = int_data.if_description;
3161 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
3162 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
3163 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
3164 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
3165 /* 0xFFFFFFFF if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
3166 wblock.data.if_descr.if_speed = int_data.if_speed;
3167 /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
3168 * If the Most Significant Bit is equal to zero, the remaining bits indicates
3169 * the resolution of the timestamp as as a negative power of 10
3171 wblock.data.if_descr.if_tsresol = int_data.if_tsresol;
3172 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
3173 /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
3174 * 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).
3176 wblock.data.if_descr.if_filter = int_data.if_filter;
3177 /* 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. */
3178 wblock.data.if_descr.if_os = int_data.if_os;
3179 /* -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. */
3180 wblock.data.if_descr.if_fcslen = int_data.if_fcslen;
3181 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
3183 wblock.frame_buffer = NULL;
3184 wblock.pseudo_header = NULL;
3185 wblock.packet_header = NULL;
3186 wblock.file_encap = NULL;
3187 wblock.type = BLOCK_TYPE_IDB;
3189 interface_data.wtap_encap = int_data.wtap_encap;;
3190 interface_data.time_units_per_second = int_data.time_units_per_second;
3192 g_array_append_val(pcapng->interface_data, interface_data);
3193 pcapng->number_of_interfaces++;
3195 if (!pcapng_write_block(wdh, &wblock, err)) {
3201 interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3202 if (interface_id == G_MAXUINT32) {
3204 * We haven't yet written out an interface description
3205 * block for an interface with this encapsulation.
3207 * Is this encapsulation even supported in pcap-ng?
3209 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3210 if (pcap_encap == -1) {
3214 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3218 /* write the interface description block */
3219 wblock.frame_buffer = NULL;
3220 wblock.pseudo_header = NULL;
3221 wblock.packet_header = NULL;
3222 wblock.file_encap = NULL;
3223 wblock.type = BLOCK_TYPE_IDB;
3224 wblock.data.if_descr.link_type = pcap_encap;
3225 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3226 WTAP_MAX_PACKET_SIZE; /* XXX */
3228 /* XXX - options unused */
3229 wblock.data.if_descr.if_speed = -1;
3230 /*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
3231 wblock.data.if_descr.if_os = NULL;
3232 wblock.data.if_descr.if_fcslen = -1;
3234 if (!pcapng_write_block(wdh, &wblock, err)) {
3238 interface_id = pcapng->number_of_interfaces;
3239 int_data.wtap_encap = phdr->pkt_encap;
3240 int_data.time_units_per_second = 0;
3241 g_array_append_val(pcapng->interface_data, int_data);
3242 pcapng->number_of_interfaces++;
3244 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3247 wtap_encap_string(phdr->pkt_encap));
3255 /* Returns 0 if we could write the specified encapsulation type,
3256 an error indication otherwise. */
3257 int pcapng_dump_can_write_encap(int wtap_encap)
3259 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3261 wtap_encap_string(wtap_encap));
3263 /* Per-packet encapsulations is supported. */
3264 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3267 /* Make sure we can figure out this DLT type */
3268 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3269 return WTAP_ERR_UNSUPPORTED_ENCAP;