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 #include "file_wrappers.h"
43 #include "pcap-common.h"
44 #include "pcap-encap.h"
48 #define pcapng_debug0(str) g_warning(str)
49 #define pcapng_debug1(str,p1) g_warning(str,p1)
50 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
51 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
53 #define pcapng_debug0(str)
54 #define pcapng_debug1(str,p1)
55 #define pcapng_debug2(str,p1,p2)
56 #define pcapng_debug3(str,p1,p2,p3)
60 pcapng_read(wtap *wth, int *err, gchar **err_info,
63 pcapng_seek_read(wtap *wth, gint64 seek_off,
64 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
65 int *err, gchar **err_info);
67 pcapng_close(wtap *wth);
70 /* pcapng: common block header for every block type */
71 typedef struct pcapng_block_header_s {
73 guint32 block_total_length;
74 /* x bytes block_body */
75 /* guint32 block_total_length */
76 } pcapng_block_header_t;
78 /* pcapng: section header block */
79 typedef struct pcapng_section_header_block_s {
80 /* pcapng_block_header_t */
82 guint16 version_major;
83 guint16 version_minor;
84 guint64 section_length; /* might be -1 for unknown */
86 } pcapng_section_header_block_t;
88 /* pcapng: interface description block */
89 typedef struct pcapng_interface_description_block_s {
94 } pcapng_interface_description_block_t;
96 /* pcapng: packet block (obsolete) */
97 typedef struct pcapng_packet_block_s {
100 guint32 timestamp_high;
101 guint32 timestamp_low;
102 guint32 captured_len;
104 /* ... Packet Data ... */
105 /* ... Padding ... */
106 /* ... Options ... */
107 } pcapng_packet_block_t;
109 /* pcapng: enhanced packet block */
110 typedef struct pcapng_enhanced_packet_block_s {
111 guint32 interface_id;
112 guint32 timestamp_high;
113 guint32 timestamp_low;
114 guint32 captured_len;
116 /* ... Packet Data ... */
117 /* ... Padding ... */
118 /* ... Options ... */
119 } pcapng_enhanced_packet_block_t;
121 /* pcapng: simple packet block */
122 typedef struct pcapng_simple_packet_block_s {
124 /* ... Packet Data ... */
125 /* ... Padding ... */
126 } pcapng_simple_packet_block_t;
128 /* pcapng: interface statistics block */
129 typedef struct pcapng_interface_statistics_block_s {
130 guint32 interface_id;
131 guint32 timestamp_high;
132 guint32 timestamp_low;
133 /* ... Options ... */
134 } pcapng_interface_statistics_block_t;
136 /* pcapng: common option header for every option type */
137 typedef struct pcapng_option_header_s {
139 guint16 option_length;
140 /* ... x bytes Option Body ... */
141 /* ... Padding ... */
142 } pcapng_option_header_t;
145 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
146 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
147 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
148 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
149 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
150 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
151 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
155 /* Capture section */
156 typedef struct wtapng_section_s {
158 guint64 section_length;
160 gchar *opt_comment; /* NULL if not available */
161 gchar *shb_hardware; /* NULL if not available */
162 gchar *shb_os; /* NULL if not available */
163 gchar *shb_user_appl; /* NULL if not available */
166 /* Interface Description */
167 typedef struct wtapng_if_descr_s {
172 gchar *opt_comment; /* NULL if not available */
173 gchar *if_name; /* NULL if not available */
174 gchar *if_description;/* NULL if not available */
175 /* XXX: if_IPv4addr */
176 /* XXX: if_IPv6addr */
177 /* XXX: if_MACaddr */
178 /* XXX: if_EUIaddr */
179 guint64 if_speed; /* 0xFFFFFFFF if unknown */
180 guint8 if_tsresol; /* default is 6 for microsecond resolution */
181 gchar *if_filter; /* NULL if not available */
182 gchar *if_os; /* NULL if not available */
183 gint8 if_fcslen; /* -1 if unknown or changes between packets */
184 /* XXX: guint64 if_tsoffset; */
188 typedef struct wtapng_packet_s {
190 guint32 ts_high; /* seconds since 1.1.1970 */
191 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
192 guint32 cap_len; /* data length in the file */
193 guint32 packet_len; /* data length on the wire */
194 guint32 interface_id; /* identifier of the interface. */
195 guint16 drops_count; /* drops count, only valid for packet block */
196 /* 0xffff if information no available */
198 gchar *opt_comment; /* NULL if not available */
200 guint32 pack_flags; /* XXX - 0 for now (any value for "we don't have it"?) */
203 guint32 pseudo_header_len;
205 /* XXX - put the packet data / pseudo_header here as well? */
209 typedef struct wtapng_simple_packet_s {
211 guint32 cap_len; /* data length in the file */
212 guint32 packet_len; /* data length on the wire */
213 guint32 pseudo_header_len;
215 /* XXX - put the packet data / pseudo_header here as well? */
216 } wtapng_simple_packet_t;
218 /* Name Resolution */
219 typedef struct wtapng_name_res_s {
221 gchar *opt_comment; /* NULL if not available */
225 /* Interface Statistics */
226 typedef struct wtapng_if_stats_s {
228 guint64 interface_id;
232 gchar *opt_comment; /* NULL if not available */
234 /*guint32 isb_starttime_high;*/
235 /*guint32 isb_starttime_low;*/
236 /*guint32 isb_endtime_high;*/
237 /*guint32 isb_endtime_low;*/
240 /*guint64 isb_filteraccept;*/
241 /*guint64 isb_osdrop;*/
242 /*guint64 isb_usrdeliv;*/
246 typedef struct wtapng_block_s {
247 guint32 type; /* block_type as defined by pcapng */
249 wtapng_section_t section;
250 wtapng_if_descr_t if_descr;
251 wtapng_packet_t packet;
252 wtapng_simple_packet_t simple_packet;
253 wtapng_name_res_t name_res;
254 wtapng_if_stats_t if_stats;
258 * XXX - currently don't know how to handle these!
260 * For one thing, when we're reading a block, they must be
261 * writable, i.e. not const, so that we can read into them,
262 * but, when we're writing a block, they can be const, and,
263 * in fact, they sometimes point to const values.
265 const union wtap_pseudo_header *pseudo_header;
266 struct wtap_pkthdr *packet_header;
267 const guchar *frame_buffer;
271 typedef struct interface_data_s {
273 guint64 time_units_per_second;
278 gboolean byte_swapped;
279 guint16 version_major;
280 guint16 version_minor;
282 GArray *interface_data;
283 guint number_of_interfaces;
287 pcapng_get_encap(gint id, pcapng_t *pn)
289 interface_data_t int_data;
291 if ((id >= 0) && ((guint)id < pn->number_of_interfaces)) {
292 int_data = g_array_index(pn->interface_data, interface_data_t, id);
293 return int_data.wtap_encap;
295 return WTAP_ERR_UNSUPPORTED_ENCAP;
301 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
302 char *content, int len, int *err, gchar **err_info _U_)
306 guint64 file_offset64;
309 /* read option header */
310 errno = WTAP_ERR_CANT_READ;
311 bytes_read = file_read(oh, 1, sizeof (*oh), fh);
312 if (bytes_read != sizeof (*oh)) {
313 pcapng_debug0("pcapng_read_option: failed to read option");
314 *err = file_error(fh);
319 block_read = sizeof (*oh);
320 if(pn->byte_swapped) {
321 oh->option_code = BSWAP16(oh->option_code);
322 oh->option_length = BSWAP16(oh->option_length);
325 /* sanity check: option length */
326 if (oh->option_length > len) {
327 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
328 oh->option_length, len);
332 /* read option content */
333 errno = WTAP_ERR_CANT_READ;
334 bytes_read = file_read(content, 1, oh->option_length, fh);
335 if (bytes_read != oh->option_length) {
336 pcapng_debug1("pcapng_read_if_descr_block: failed to read content of option %u", oh->option_code);
337 *err = file_error(fh);
342 block_read += oh->option_length;
344 /* jump over potential padding bytes at end of option */
345 if( (oh->option_length % 4) != 0) {
346 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
347 if (file_offset64 <= 0) {
352 block_read += 4 - (oh->option_length % 4);
360 pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
361 pcapng_t *pn, wtapng_block_t *wblock, int *err,
367 pcapng_section_header_block_t shb;
368 pcapng_option_header_t oh;
369 char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
372 /* read block content */
373 errno = WTAP_ERR_CANT_READ;
374 bytes_read = file_read(&shb, 1, sizeof shb, fh);
375 if (bytes_read != sizeof shb) {
376 *err = file_error(fh);
381 block_read = bytes_read;
383 /* is the magic number one we expect? */
386 /* this seems pcapng with correct byte order */
387 pn->byte_swapped = FALSE;
388 pn->version_major = shb.version_major;
389 pn->version_minor = shb.version_minor;
391 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
392 pn->version_major, pn->version_minor, bh->block_total_length);
395 /* this seems pcapng with swapped byte order */
396 pn->byte_swapped = TRUE;
397 pn->version_major = BSWAP16(shb.version_major);
398 pn->version_minor = BSWAP16(shb.version_minor);
400 /* tweak the block length to meet current swapping that we know now */
401 bh->block_total_length = BSWAP32(bh->block_total_length);
403 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
404 pn->version_major, pn->version_minor, bh->block_total_length);
407 /* Not a "pcapng" magic number we know about. */
408 pcapng_debug1("pcapng_read_section_header_block: unknown magic number %u (probably not an pcapng file)", shb.magic);
412 /* we currently only understand SHB V1.0 */
413 if (pn->version_major != 1 || pn->version_minor != 0) {
414 pcapng_debug2("pcapng_read_section_header_block: unknown SHB version %u.%u",
415 pn->version_major, pn->version_minor);
419 /* 64bit section_length (currently unused) */
420 if (pn->byte_swapped) {
421 wblock->data.section.section_length = BSWAP64(shb.section_length);
423 wblock->data.section.section_length = shb.section_length;
426 /* Option defaults */
427 wblock->data.section.opt_comment = NULL;
428 wblock->data.section.shb_hardware = NULL;
429 wblock->data.section.shb_os = NULL;
430 wblock->data.section.shb_user_appl = NULL;
433 errno = WTAP_ERR_CANT_READ;
434 to_read = bh->block_total_length
435 - (int)sizeof(pcapng_block_header_t)
436 - (int)sizeof (pcapng_section_header_block_t)
437 - (int)sizeof(bh->block_total_length);
440 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, sizeof(option_content), err, err_info);
441 if (bytes_read <= 0) {
442 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
445 block_read += bytes_read;
446 to_read -= bytes_read;
448 /* handle option content */
449 switch(oh.option_code) {
450 case(0): /* opt_endofopt */
452 pcapng_debug1("pcapng_read_section_header_block: %u bytes after opt_endofopt", to_read);
454 /* padding should be ok here, just get out of this */
457 case(1): /* opt_comment */
458 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
459 wblock->data.section.opt_comment = g_strndup(option_content, sizeof(option_content));
460 pcapng_debug1("pcapng_read_section_header_block: opt_comment %s", wblock->data.section.opt_comment);
462 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
465 case(2): /* shb_hardware */
466 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
467 wblock->data.section.shb_hardware = g_strndup(option_content, sizeof(option_content));
468 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
470 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
473 case(3): /* shb_os */
474 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
475 wblock->data.section.shb_os = g_strndup(option_content, sizeof(option_content));
476 pcapng_debug1("pcapng_read_section_header_block: shb_os %s", wblock->data.section.shb_os);
478 pcapng_debug1("pcapng_read_section_header_block: shb_os length %u seems strange", oh.option_length);
481 case(4): /* shb_userappl */
482 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
483 wblock->data.section.shb_user_appl = g_strndup(option_content, sizeof(option_content));
484 pcapng_debug1("pcapng_read_section_header_block: shb_userappl %s", wblock->data.section.shb_user_appl);
486 pcapng_debug1("pcapng_read_section_header_block: shb_userappl length %u seems strange", oh.option_length);
490 pcapng_debug2("pcapng_read_section_header_block: unknown option %u - ignoring %u bytes",
491 oh.option_code, oh.option_length);
495 if (pn->interface_data != NULL) {
496 pcapng_debug0("pcapng_read_section_header_block: Multiple section header blocks!");
497 g_array_free(pn->interface_data, TRUE);
498 pn->interface_data = NULL;
499 *err = WTAP_ERR_BAD_RECORD;
500 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported.");
503 pn->interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
504 pn->number_of_interfaces = 0;
510 /* "Interface Description Block" */
512 pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
513 wtapng_block_t *wblock, int *err, gchar **err_info _U_)
515 guint64 time_units_per_second;
519 pcapng_interface_description_block_t idb;
520 pcapng_option_header_t oh;
521 interface_data_t int_data;
523 char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
526 time_units_per_second = 1000000; /* default */
527 /* read block content */
528 errno = WTAP_ERR_CANT_READ;
529 bytes_read = file_read(&idb, 1, sizeof idb, fh);
530 if (bytes_read != sizeof idb) {
531 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
532 *err = file_error(fh);
537 block_read = bytes_read;
539 /* mandatory values */
540 if (pn->byte_swapped) {
541 wblock->data.if_descr.link_type = BSWAP16(idb.linktype);
542 wblock->data.if_descr.snap_len = BSWAP32(idb.snaplen);
544 wblock->data.if_descr.link_type = idb.linktype;
545 wblock->data.if_descr.snap_len = idb.snaplen;
548 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
549 wblock->data.if_descr.link_type,
550 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
551 wblock->data.if_descr.snap_len);
553 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
554 /* This is unrealisitic, but text2pcap currently uses 102400.
555 * We do not use this value, maybe we should check the
556 * snap_len of the packets against it. For now, only warn.
558 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
559 wblock->data.if_descr.snap_len);
560 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
563 /* Option defaults */
564 wblock->data.if_descr.opt_comment = NULL;
565 wblock->data.if_descr.if_name = NULL;
566 wblock->data.if_descr.if_description = NULL;
567 /* XXX: if_IPv4addr */
568 /* XXX: if_IPv6addr */
569 /* XXX: if_MACaddr */
570 /* XXX: if_EUIaddr */
571 wblock->data.if_descr.if_speed = 0xFFFFFFFF; /* "unknown" */
572 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
573 wblock->data.if_descr.if_filter = NULL;
574 wblock->data.if_descr.if_os = NULL;
575 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
576 /* XXX: guint64 if_tsoffset; */
580 errno = WTAP_ERR_CANT_READ;
581 to_read = bh->block_total_length
582 - (int)sizeof(pcapng_block_header_t)
583 - (int)sizeof (pcapng_interface_description_block_t)
584 - (int)sizeof(bh->block_total_length);
585 while (to_read > 0) {
587 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, sizeof(option_content), err, err_info);
588 if (bytes_read <= 0) {
589 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
592 block_read += bytes_read;
593 to_read -= bytes_read;
595 /* handle option content */
596 switch(oh.option_code) {
597 case(0): /* opt_endofopt */
599 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
601 /* padding should be ok here, just get out of this */
604 case(1): /* opt_comment */
605 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
606 wblock->data.section.opt_comment = g_strndup(option_content, sizeof(option_content));
607 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.section.opt_comment);
609 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
612 case(2): /* if_name */
613 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
614 wblock->data.if_descr.if_name = g_strndup(option_content, sizeof(option_content));
615 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
617 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
620 case(3): /* if_description */
621 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
622 wblock->data.if_descr.if_description = g_strndup(option_content, sizeof(option_content));
623 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
625 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
628 case(8): /* if_speed */
629 if(oh.option_length == 8) {
630 /* Don't cast a char[] into a guint64--the
631 * char[] may not be aligned correctly.
633 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
635 wblock->data.if_descr.if_speed = BSWAP64(wblock->data.if_descr.if_speed);
636 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
638 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
641 case(9): /* if_tsresol */
642 if (oh.option_length == 1) {
647 wblock->data.if_descr.if_tsresol = option_content[0];
648 if (wblock->data.if_descr.if_tsresol & 0x80) {
653 exponent = (guint8)(wblock->data.if_descr.if_tsresol & 0x7f);
654 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
656 for (i = 0; i < exponent; i++) {
659 time_units_per_second = result;
661 time_units_per_second = G_MAXUINT64;
663 if (time_units_per_second > (((guint64)1) << 32)) {
664 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
666 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol %u", wblock->data.if_descr.if_tsresol);
668 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
671 case(11): /* if_filter */
672 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
673 wblock->data.if_descr.if_filter = g_strndup(option_content, sizeof(option_content));
674 pcapng_debug1("pcapng_read_if_descr_block: if_filter %s", wblock->data.if_descr.if_filter);
676 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
679 case(13): /* if_fcslen */
680 if(oh.option_length == 1) {
681 wblock->data.if_descr.if_fcslen = option_content[0];
682 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
683 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
684 /* XXX - add sanity check */
686 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
690 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
691 oh.option_code, oh.option_length);
695 encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
696 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
697 *wblock->file_encap = encap;
699 if (*wblock->file_encap != encap) {
700 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
704 int_data.wtap_encap = encap;
705 int_data.time_units_per_second = time_units_per_second;
706 g_array_append_val(pn->interface_data, int_data);
707 pn->number_of_interfaces++;
713 pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info _U_, gboolean enhanced)
718 guint64 file_offset64;
719 pcapng_enhanced_packet_block_t epb;
720 pcapng_packet_block_t pb;
721 guint32 block_total_length;
722 pcapng_option_header_t oh;
724 int pseudo_header_len;
725 char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
728 /* "(Enhanced) Packet Block" read fixed part */
729 errno = WTAP_ERR_CANT_READ;
731 bytes_read = file_read(&epb, 1, sizeof epb, fh);
732 if (bytes_read != sizeof epb) {
733 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
734 *err = file_error(fh);
737 block_read = bytes_read;
739 if (pn->byte_swapped) {
740 wblock->data.packet.interface_id = BSWAP32(epb.interface_id);
741 wblock->data.packet.drops_count = -1; /* invalid */
742 wblock->data.packet.ts_high = BSWAP32(epb.timestamp_high);
743 wblock->data.packet.ts_low = BSWAP32(epb.timestamp_low);
744 wblock->data.packet.cap_len = BSWAP32(epb.captured_len);
745 wblock->data.packet.packet_len = BSWAP32(epb.packet_len);
747 wblock->data.packet.interface_id = epb.interface_id;
748 wblock->data.packet.drops_count = -1; /* invalid */
749 wblock->data.packet.ts_high = epb.timestamp_high;
750 wblock->data.packet.ts_low = epb.timestamp_low;
751 wblock->data.packet.cap_len = epb.captured_len;
752 wblock->data.packet.packet_len = epb.packet_len;
755 bytes_read = file_read(&pb, 1, sizeof pb, fh);
756 if (bytes_read != sizeof pb) {
757 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
758 *err = file_error(fh);
761 block_read = bytes_read;
763 if (pn->byte_swapped) {
764 wblock->data.packet.interface_id = BSWAP16(pb.interface_id);
765 wblock->data.packet.drops_count = BSWAP16(pb.drops_count);
766 wblock->data.packet.ts_high = BSWAP32(pb.timestamp_high);
767 wblock->data.packet.ts_low = BSWAP32(pb.timestamp_low);
768 wblock->data.packet.cap_len = BSWAP32(pb.captured_len);
769 wblock->data.packet.packet_len = BSWAP32(pb.packet_len);
771 wblock->data.packet.interface_id = pb.interface_id;
772 wblock->data.packet.drops_count = pb.drops_count;
773 wblock->data.packet.ts_high = pb.timestamp_high;
774 wblock->data.packet.ts_low = pb.timestamp_low;
775 wblock->data.packet.cap_len = pb.captured_len;
776 wblock->data.packet.packet_len = pb.packet_len;
780 if (wblock->data.packet.cap_len > wblock->data.packet.packet_len) {
781 pcapng_debug2("pcapng_read_packet_block:cap_len %d is larger than packet_len %u.",
782 wblock->data.packet.cap_len, wblock->data.packet.packet_len);
783 *err = WTAP_ERR_BAD_RECORD;
786 if (wblock->data.packet.cap_len > WTAP_MAX_PACKET_SIZE) {
787 pcapng_debug2("pcapng_read_packet_block:cap_len %d is larger than WTAP_MAX_PACKET_SIZE %u.",
788 wblock->data.packet.cap_len, WTAP_MAX_PACKET_SIZE);
789 *err = WTAP_ERR_BAD_RECORD;
792 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
793 wblock->data.packet.packet_len,
794 wblock->data.packet.cap_len,
795 wblock->data.packet.interface_id);
797 wtap_encap = pcapng_get_encap(wblock->data.packet.interface_id, pn);
798 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
800 wtap_encap_string(wtap_encap),
801 pcap_get_phdr_size(wtap_encap, wblock->pseudo_header));
803 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
804 pseudo_header_len = pcap_process_pseudo_header(fh,
808 wblock->data.packet.cap_len,
810 wblock->packet_header,
811 (union wtap_pseudo_header *)wblock->pseudo_header,
814 if (pseudo_header_len < 0) {
817 wblock->data.packet.pseudo_header_len = (guint32)pseudo_header_len;
818 block_read += pseudo_header_len;
819 if (pseudo_header_len != pcap_get_phdr_size(wtap_encap, wblock->pseudo_header)) {
820 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
824 /* "(Enhanced) Packet Block" read capture data */
825 errno = WTAP_ERR_CANT_READ;
826 bytes_read = file_read((guchar *) (wblock->frame_buffer), 1, wblock->data.packet.cap_len - pseudo_header_len, fh);
827 if (bytes_read != (int) (wblock->data.packet.cap_len - pseudo_header_len)) {
828 *err = file_error(fh);
829 pcapng_debug1("pcapng_read_packet_block: couldn't read %u bytes of captured data",
830 wblock->data.packet.cap_len - pseudo_header_len);
832 *err = WTAP_ERR_SHORT_READ;
835 block_read += bytes_read;
837 /* jump over potential padding bytes at end of the packet data */
838 if( (wblock->data.packet.cap_len % 4) != 0) {
839 file_offset64 = file_seek(fh, 4 - (wblock->data.packet.cap_len % 4), SEEK_CUR, err);
840 if (file_offset64 <= 0) {
845 block_read += 4 - (wblock->data.packet.cap_len % 4);
848 /* add padding bytes to "block total length" */
849 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
850 if (bh->block_total_length % 4) {
851 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
853 block_total_length = bh->block_total_length;
856 /* Option defaults */
857 wblock->data.packet.opt_comment = NULL;
858 wblock->data.packet.drop_count = -1;
859 wblock->data.packet.pack_flags = 0; /* XXX - is 0 ok to signal "not used"? */
862 errno = WTAP_ERR_CANT_READ;
863 to_read = block_total_length
864 - (int)sizeof(pcapng_block_header_t)
865 - block_read /* fixed and variable part, including padding */
866 - (int)sizeof(bh->block_total_length);
869 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, sizeof(option_content), err, err_info);
870 if (bytes_read <= 0) {
871 pcapng_debug0("pcapng_read_packet_block: failed to read option");
874 block_read += bytes_read;
875 to_read -= bytes_read;
877 /* handle option content */
878 switch(oh.option_code) {
879 case(0): /* opt_endofopt */
881 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
883 /* padding should be ok here, just get out of this */
886 case(1): /* opt_comment */
887 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
888 wblock->data.section.opt_comment = g_strndup(option_content, sizeof(option_content));
889 pcapng_debug1("pcapng_read_packet_block: opt_comment %s", wblock->data.section.opt_comment);
891 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
894 case(2): /* pack_flags / epb_flags */
895 if(oh.option_length == 4) {
896 /* Don't cast a char[] into a guint32--the
897 * char[] may not be aligned correctly.
899 memcpy(&wblock->data.packet.pack_flags, option_content, sizeof(guint32));
901 wblock->data.packet.pack_flags = BSWAP32(wblock->data.packet.pack_flags);
902 pcapng_debug1("pcapng_read_if_descr_block: pack_flags %u (ignored)", wblock->data.packet.pack_flags);
904 pcapng_debug1("pcapng_read_if_descr_block: pack_flags length %u not 4 as expected", oh.option_length);
908 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
909 oh.option_code, oh.option_length);
918 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 _U_)
922 guint64 file_offset64;
924 int pseudo_header_len;
925 pcapng_simple_packet_block_t spb;
928 /* "Simple Packet Block" read fixed part */
929 errno = WTAP_ERR_CANT_READ;
930 bytes_read = file_read(&spb, 1, sizeof spb, fh);
931 if (bytes_read != sizeof spb) {
932 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
933 *err = file_error(fh);
936 block_read = bytes_read;
938 if (pn->byte_swapped) {
939 wblock->data.simple_packet.packet_len = BSWAP32(spb.packet_len);
941 wblock->data.simple_packet.packet_len = spb.packet_len;
944 wblock->data.simple_packet.cap_len = bh->block_total_length
945 - (guint32)sizeof(pcapng_simple_packet_block_t)
946 - (guint32)sizeof(bh->block_total_length);
948 if (wblock->data.simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
949 pcapng_debug2("pcapng_read_simple_packet_block:cap_len %d is larger than WTAP_MAX_PACKET_SIZE %u.",
950 wblock->data.simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
951 *err = WTAP_ERR_BAD_RECORD;
954 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
955 wblock->data.simple_packet.packet_len);
957 encap = pcapng_get_encap(0, pn);
958 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
959 pcap_get_phdr_size(encap, wblock->pseudo_header));
961 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
962 pseudo_header_len = pcap_process_pseudo_header(fh,
966 wblock->data.simple_packet.cap_len,
968 wblock->packet_header,
969 (union wtap_pseudo_header *)wblock->pseudo_header,
972 if (pseudo_header_len < 0) {
975 wblock->data.simple_packet.pseudo_header_len = (guint32)pseudo_header_len;
976 block_read += pseudo_header_len;
977 if (pseudo_header_len != pcap_get_phdr_size(encap, wblock->pseudo_header)) {
978 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
982 /* XXX - implement other linktypes then Ethernet */
983 /* (or even better share the code with libpcap.c) */
985 /* Ethernet FCS length, might be overwritten by "per packet" options */
986 memset((void *)wblock->pseudo_header, 0, sizeof(union wtap_pseudo_header));
987 ((union wtap_pseudo_header *) wblock->pseudo_header)->eth.fcs_len = pn->if_fcslen;
989 /* "Simple Packet Block" read capture data */
990 errno = WTAP_ERR_CANT_READ;
991 bytes_read = file_read((guchar *) (wblock->frame_buffer), 1, wblock->data.simple_packet.cap_len, fh);
992 if (bytes_read != (int) wblock->data.simple_packet.cap_len) {
993 *err = file_error(fh);
994 pcapng_debug1("pcapng_read_simple_packet_block: couldn't read %u bytes of captured data",
995 wblock->data.simple_packet.cap_len);
997 *err = WTAP_ERR_SHORT_READ;
1000 block_read += bytes_read;
1002 /* jump over potential padding bytes at end of the packet data */
1003 if ((wblock->data.simple_packet.cap_len % 4) != 0) {
1004 file_offset64 = file_seek(fh, 4 - (wblock->data.simple_packet.cap_len % 4), SEEK_CUR, err);
1005 if (file_offset64 <= 0) {
1010 block_read += 4 - (wblock->data.simple_packet.cap_len % 4);
1017 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 _U_)
1022 pcapng_interface_statistics_block_t isb;
1023 pcapng_option_header_t oh;
1024 char option_content[100]; /* XXX - size might need to be increased, if we see longer options */
1027 /* "Interface Statistics Block" read fixed part */
1028 errno = WTAP_ERR_CANT_READ;
1029 bytes_read = file_read(&isb, 1, sizeof isb, fh);
1030 if (bytes_read != sizeof isb) {
1031 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1032 *err = file_error(fh);
1035 block_read = bytes_read;
1037 if(pn->byte_swapped) {
1038 wblock->data.if_stats.interface_id = BSWAP64(isb.interface_id);
1039 wblock->data.if_stats.ts_high = BSWAP32(isb.timestamp_high);
1040 wblock->data.if_stats.ts_low = BSWAP32(isb.timestamp_low);
1042 wblock->data.if_stats.interface_id = isb.interface_id;
1043 wblock->data.if_stats.ts_high = isb.timestamp_high;
1044 wblock->data.if_stats.ts_low = isb.timestamp_low;
1046 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %" G_GINT64_MODIFIER "u", wblock->data.if_stats.interface_id);
1048 /* Option defaults */
1049 wblock->data.if_stats.opt_comment = NULL;
1050 wblock->data.if_stats.isb_ifrecv = -1;
1051 wblock->data.if_stats.isb_ifdrop = -1;
1054 errno = WTAP_ERR_CANT_READ;
1055 to_read = bh->block_total_length
1056 - sizeof(pcapng_block_header_t)
1057 - block_read /* fixed and variable part, including padding */
1058 - sizeof(bh->block_total_length);
1059 while(to_read > 0) {
1061 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, sizeof(option_content), err, err_info);
1062 if (bytes_read <= 0) {
1063 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1066 block_read += bytes_read;
1067 to_read -= bytes_read;
1069 /* handle option content */
1070 switch(oh.option_code) {
1071 case(0): /* opt_endofopt */
1073 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1075 /* padding should be ok here, just get out of this */
1078 case(1): /* opt_comment */
1079 if(oh.option_length > 0 && oh.option_length < sizeof(option_content)) {
1080 wblock->data.section.opt_comment = g_strndup(option_content, sizeof(option_content));
1081 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.section.opt_comment);
1083 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1086 case(4): /* isb_ifrecv */
1087 if(oh.option_length == 8) {
1088 /* Don't cast a char[] into a guint32--the
1089 * char[] may not be aligned correctly.
1091 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1092 if(pn->byte_swapped)
1093 wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
1094 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1096 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1099 case(5): /* isb_ifdrop */
1100 if(oh.option_length == 8) {
1101 /* Don't cast a char[] into a guint32--the
1102 * char[] may not be aligned correctly.
1104 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1105 if(pn->byte_swapped)
1106 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
1107 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1109 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1113 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1114 oh.option_code, oh.option_length);
1123 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_)
1126 guint64 file_offset64;
1127 guint32 block_total_length;
1130 /* add padding bytes to "block total length" */
1131 /* (the "block total length" of some example files don't contain any padding bytes!) */
1132 if (bh->block_total_length % 4) {
1133 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1135 block_total_length = bh->block_total_length;
1138 block_read = block_total_length - (guint32)sizeof(pcapng_block_header_t) - (guint32)sizeof(bh->block_total_length);
1140 /* jump over this unknown block */
1141 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1142 if (file_offset64 <= 0) {
1153 pcapng_read_block(FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1157 pcapng_block_header_t bh;
1158 guint32 block_total_length;
1161 /* Try to read the (next) block header */
1162 errno = WTAP_ERR_CANT_READ;
1163 bytes_read = file_read(&bh, 1, sizeof bh, fh);
1164 if (bytes_read != sizeof bh) {
1165 pcapng_debug0("pcapng_read_block: end of file");
1166 *err = file_error(fh);
1172 block_read = bytes_read;
1173 if (pn->byte_swapped) {
1174 bh.block_type = BSWAP32(bh.block_type);
1175 bh.block_total_length = BSWAP32(bh.block_total_length);
1178 wblock->type = bh.block_type;
1180 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
1182 switch(bh.block_type) {
1183 case(BLOCK_TYPE_SHB):
1184 bytes_read = pcapng_read_section_header_block(fh, &bh, pn, wblock, err, err_info);
1186 case(BLOCK_TYPE_IDB):
1187 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
1189 case(BLOCK_TYPE_PB):
1190 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
1192 case(BLOCK_TYPE_SPB):
1193 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
1195 case(BLOCK_TYPE_EPB):
1196 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
1198 case(BLOCK_TYPE_ISB):
1199 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
1202 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
1203 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
1206 if (bytes_read <= 0) {
1209 block_read += bytes_read;
1211 /* sanity check: first and second block lengths must match */
1212 errno = WTAP_ERR_CANT_READ;
1213 bytes_read = file_read(&block_total_length, 1, sizeof block_total_length, fh);
1214 if (bytes_read != sizeof block_total_length) {
1215 pcapng_debug0("pcapng_read_block: couldn't read second block length");
1216 *err = file_error(fh);
1221 block_read += bytes_read;
1223 if (pn->byte_swapped)
1224 block_total_length = BSWAP32(block_total_length);
1226 if (!(block_total_length == bh.block_total_length)) {
1227 pcapng_debug2("pcapng_read_block: total block lengths (first %u and second %u) don't match",
1228 bh.block_total_length, block_total_length);
1236 /* classic wtap: open capture file */
1238 pcapng_open(wtap *wth, int *err, gchar **err_info)
1242 wtapng_block_t wblock;
1245 /* we don't know the byte swapping of the file yet */
1246 pn.byte_swapped = FALSE;
1248 pn.version_major = -1;
1249 pn.version_minor = -1;
1250 pn.interface_data = NULL;
1251 pn.number_of_interfaces = 0;
1253 /* we don't expect any packet blocks yet */
1254 wblock.frame_buffer = NULL;
1255 wblock.pseudo_header = NULL;
1256 wblock.packet_header = NULL;
1257 wblock.file_encap = &wth->file_encap;
1259 pcapng_debug0("pcapng_open: opening file");
1260 /* read first block */
1261 bytes_read = pcapng_read_block(wth->fh, &pn, &wblock, err, err_info);
1262 if (bytes_read <= 0) {
1263 pcapng_debug0("pcapng_open: couldn't read first SHB");
1264 *err = file_error(wth->fh);
1269 wth->data_offset += bytes_read;
1271 /* first block must be a "Section Header Block" */
1272 if (wblock.type != BLOCK_TYPE_SHB) {
1274 * XXX - check for damage from transferring a file
1275 * between Windows and UN*X as text rather than
1278 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
1282 wth->file_encap = WTAP_ENCAP_UNKNOWN;
1283 wth->snapshot_length = 0;
1284 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
1285 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
1286 wth->priv = (void *)pcapng;
1288 wth->subtype_read = pcapng_read;
1289 wth->subtype_seek_read = pcapng_seek_read;
1290 wth->subtype_close = pcapng_close;
1291 wth->file_type = WTAP_FILE_PCAPNG;
1297 /* classic wtap: read packet */
1299 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1301 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1304 wtapng_block_t wblock;
1306 pcapng_debug1("pcapng_read: wth->data_offset is initially %" G_GINT64_MODIFIER "u", wth->data_offset);
1307 *data_offset = wth->data_offset;
1308 pcapng_debug1("pcapng_read: *data_offset is initially set to %" G_GINT64_MODIFIER "u", *data_offset);
1310 /* XXX - This should be done in the packet block reading function and
1311 * should make use of the caplen of the packet.
1313 if (wth->snapshot_length > 0) {
1314 buffer_assure_space(wth->frame_buffer, wth->snapshot_length);
1316 buffer_assure_space(wth->frame_buffer, WTAP_MAX_PACKET_SIZE);
1319 wblock.frame_buffer = buffer_start_ptr(wth->frame_buffer);
1320 wblock.pseudo_header = &wth->pseudo_header;
1321 wblock.packet_header = &wth->phdr;
1322 wblock.file_encap = &wth->file_encap;
1324 /* read next block */
1326 bytes_read = pcapng_read_block(wth->fh, pcapng, &wblock, err, err_info);
1327 if (bytes_read <= 0) {
1328 pcapng_debug0("pcapng_read: couldn't read packet block");
1332 /* block must be a "Packet Block" or an "Enhanced Packet Block" -> otherwise continue */
1333 if (wblock.type == BLOCK_TYPE_PB || wblock.type == BLOCK_TYPE_EPB) {
1337 /* XXX - improve handling of "unknown" blocks */
1338 pcapng_debug1("pcapng_read: block type 0x%x not PB/EPB", wblock.type);
1339 *data_offset += bytes_read;
1340 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "u", *data_offset);
1343 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1344 ts = (((guint64)wblock.data.packet.ts_high) << 32) | ((guint64)wblock.data.packet.ts_low);
1346 wth->phdr.caplen = wblock.data.packet.cap_len - wblock.data.packet.pseudo_header_len;
1347 wth->phdr.len = wblock.data.packet.packet_len - wblock.data.packet.pseudo_header_len;
1348 if (wblock.data.packet.interface_id < pcapng->number_of_interfaces) {
1349 interface_data_t int_data;
1350 guint64 time_units_per_second;
1353 id = (gint)wblock.data.packet.interface_id;
1354 int_data = g_array_index(pcapng->interface_data, interface_data_t, id);
1355 time_units_per_second = int_data.time_units_per_second;
1356 wth->phdr.pkt_encap = int_data.wtap_encap;
1357 wth->phdr.ts.secs = (time_t)(ts / time_units_per_second);
1358 wth->phdr.ts.nsecs = (int)(((ts % time_units_per_second) * 1000000000) / time_units_per_second);
1360 pcapng_debug1("pcapng_read: interface_id %d too large", wblock.data.packet.interface_id);
1361 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
1362 *err = WTAP_ERR_BAD_RECORD;
1363 *err_info = g_strdup_printf("pcapng: interface index %u is too large", wblock.data.packet.interface_id);
1367 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
1368 wth->data_offset = *data_offset + bytes_read;
1369 pcapng_debug1("pcapng_read: wth->data_offset is finally %" G_GINT64_MODIFIER "u", wth->data_offset);
1375 /* classic wtap: seek to file position and read packet */
1377 pcapng_seek_read(wtap *wth, gint64 seek_off,
1378 union wtap_pseudo_header *pseudo_header, guchar *pd, int length _U_,
1379 int *err, gchar **err_info)
1381 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1382 guint64 bytes_read64;
1384 wtapng_block_t wblock;
1387 /* seek to the right file position */
1388 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
1389 if (bytes_read64 <= 0) {
1390 return FALSE; /* Seek error */
1392 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
1394 wblock.frame_buffer = pd;
1395 wblock.pseudo_header = pseudo_header;
1396 wblock.packet_header = &wth->phdr;
1397 wblock.file_encap = &wth->file_encap;
1399 /* read the block */
1400 bytes_read = pcapng_read_block(wth->random_fh, pcapng, &wblock, err, err_info);
1401 if (bytes_read <= 0) {
1402 *err = file_error(wth->random_fh);
1403 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
1404 *err, errno, bytes_read);
1408 /* block must be a "Packet Block" or an "Enhanced Packet Block" */
1409 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB) {
1410 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB", wblock.type);
1418 /* classic wtap: close capture file */
1420 pcapng_close(wtap *wth)
1422 pcapng_t *pcapng = (pcapng_t *)wth->priv;
1424 pcapng_debug0("pcapng_close: closing file");
1425 if (pcapng->interface_data != NULL) {
1426 g_array_free(pcapng->interface_data, TRUE);
1433 GArray *interface_data;
1434 guint number_of_interfaces;
1438 pcapng_write_section_header_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
1440 pcapng_block_header_t bh;
1441 pcapng_section_header_block_t shb;
1445 /* write block header */
1446 bh.block_type = wblock->type;
1447 bh.block_total_length = sizeof(bh) + sizeof(shb) /* + options */ + 4;
1449 nwritten = wtap_dump_file_write(wdh, &bh, sizeof bh);
1450 if (nwritten != sizeof bh) {
1451 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1452 *err = wtap_dump_file_ferror(wdh);
1454 *err = WTAP_ERR_SHORT_WRITE;
1457 wdh->bytes_dumped += sizeof bh;
1459 /* write block fixed content */
1460 /* XXX - get these values from wblock? */
1461 shb.magic = 0x1A2B3C4D;
1462 shb.version_major = 1;
1463 shb.version_minor = 0;
1464 shb.section_length = -1;
1466 nwritten = wtap_dump_file_write(wdh, &shb, sizeof shb);
1467 if (nwritten != sizeof shb) {
1468 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1469 *err = wtap_dump_file_ferror(wdh);
1471 *err = WTAP_ERR_SHORT_WRITE;
1474 wdh->bytes_dumped += sizeof shb;
1476 /* XXX - write (optional) block options */
1478 /* write block footer */
1479 nwritten = wtap_dump_file_write(wdh, &bh.block_total_length, sizeof bh.block_total_length);
1480 if (nwritten != sizeof bh.block_total_length) {
1481 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1482 *err = wtap_dump_file_ferror(wdh);
1484 *err = WTAP_ERR_SHORT_WRITE;
1487 wdh->bytes_dumped += sizeof bh.block_total_length;
1495 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
1497 pcapng_block_header_t bh;
1498 pcapng_interface_description_block_t idb;
1502 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
1503 wblock->data.if_descr.link_type,
1504 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type)),
1505 wblock->data.if_descr.snap_len);
1507 if (wblock->data.if_descr.link_type == (guint16)-1) {
1508 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
1512 /* write block header */
1513 bh.block_type = wblock->type;
1514 bh.block_total_length = sizeof(bh) + sizeof(idb) /* + options */ + 4;
1516 nwritten = wtap_dump_file_write(wdh, &bh, sizeof bh);
1517 if (nwritten != sizeof bh) {
1518 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1519 *err = wtap_dump_file_ferror(wdh);
1521 *err = WTAP_ERR_SHORT_WRITE;
1524 wdh->bytes_dumped += sizeof bh;
1526 /* write block fixed content */
1527 idb.linktype = wblock->data.if_descr.link_type;
1529 idb.snaplen = wblock->data.if_descr.snap_len;
1531 nwritten = wtap_dump_file_write(wdh, &idb, sizeof idb);
1532 if (nwritten != sizeof idb) {
1533 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1534 *err = wtap_dump_file_ferror(wdh);
1536 *err = WTAP_ERR_SHORT_WRITE;
1539 wdh->bytes_dumped += sizeof idb;
1541 /* XXX - write (optional) block options */
1543 /* write block footer */
1544 nwritten = wtap_dump_file_write(wdh, &bh.block_total_length, sizeof bh.block_total_length);
1545 if (nwritten != sizeof bh.block_total_length) {
1546 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1547 *err = wtap_dump_file_ferror(wdh);
1549 *err = WTAP_ERR_SHORT_WRITE;
1552 wdh->bytes_dumped += sizeof bh.block_total_length;
1559 pcapng_write_packet_block(wtap_dumper *wdh, wtapng_block_t *wblock, int *err)
1561 pcapng_block_header_t bh;
1562 pcapng_enhanced_packet_block_t epb;
1564 const guint32 zero_pad = 0;
1568 phdr_len = (guint32)pcap_get_phdr_size(wblock->data.packet.wtap_encap, wblock->pseudo_header);
1569 if ((phdr_len + wblock->data.packet.cap_len) % 4) {
1570 pad_len = 4 - ((phdr_len + wblock->data.packet.cap_len) % 4);
1575 /* write (enhanced) packet block header */
1576 bh.block_type = wblock->type;
1577 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + wblock->data.packet.cap_len + pad_len /* + options */ + 4;
1579 nwritten = wtap_dump_file_write(wdh, &bh, sizeof bh);
1580 if (nwritten != sizeof bh) {
1581 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1582 *err = wtap_dump_file_ferror(wdh);
1584 *err = WTAP_ERR_SHORT_WRITE;
1587 wdh->bytes_dumped += sizeof bh;
1589 /* write block fixed content */
1590 epb.interface_id = wblock->data.packet.interface_id;
1591 epb.timestamp_high = wblock->data.packet.ts_high;
1592 epb.timestamp_low = wblock->data.packet.ts_low;
1593 epb.captured_len = wblock->data.packet.cap_len + phdr_len;
1594 epb.packet_len = wblock->data.packet.packet_len + phdr_len;
1596 nwritten = wtap_dump_file_write(wdh, &epb, sizeof epb);
1597 if (nwritten != sizeof epb) {
1598 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1599 *err = wtap_dump_file_ferror(wdh);
1601 *err = WTAP_ERR_SHORT_WRITE;
1604 wdh->bytes_dumped += sizeof epb;
1606 /* write pseudo header */
1607 if (!pcap_write_phdr(wdh, wblock->data.packet.wtap_encap, wblock->pseudo_header, err)) {
1610 wdh->bytes_dumped += phdr_len;
1612 /* write packet data */
1613 nwritten = wtap_dump_file_write(wdh, wblock->frame_buffer, wblock->data.packet.cap_len);
1614 if (nwritten != wblock->data.packet.cap_len) {
1615 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1616 *err = wtap_dump_file_ferror(wdh);
1618 *err = WTAP_ERR_SHORT_WRITE;
1621 wdh->bytes_dumped += wblock->data.packet.cap_len;
1623 /* write padding (if any) */
1625 nwritten = wtap_dump_file_write(wdh, &zero_pad, pad_len);
1626 if (nwritten != pad_len) {
1627 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1628 *err = wtap_dump_file_ferror(wdh);
1630 *err = WTAP_ERR_SHORT_WRITE;
1633 wdh->bytes_dumped += pad_len;
1636 /* XXX - write (optional) block options */
1638 /* write block footer */
1639 nwritten = wtap_dump_file_write(wdh, &bh.block_total_length, sizeof bh.block_total_length);
1640 if (nwritten != sizeof bh.block_total_length) {
1641 if (nwritten == 0 && wtap_dump_file_ferror(wdh))
1642 *err = wtap_dump_file_ferror(wdh);
1644 *err = WTAP_ERR_SHORT_WRITE;
1647 wdh->bytes_dumped += sizeof bh.block_total_length;
1654 pcapng_write_block(wtap_dumper *wdh, /*pcapng_t *pn, */wtapng_block_t *wblock, int *err)
1656 switch(wblock->type) {
1657 case(BLOCK_TYPE_SHB):
1658 return pcapng_write_section_header_block(wdh, wblock, err);
1659 case(BLOCK_TYPE_IDB):
1660 return pcapng_write_if_descr_block(wdh, wblock, err);
1661 case(BLOCK_TYPE_PB):
1662 /* Packet Block is obsolete */
1664 case(BLOCK_TYPE_EPB):
1665 return pcapng_write_packet_block(wdh, wblock, err);
1667 pcapng_debug1("Unknown block_type: 0x%x", wblock->type);
1674 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
1677 interface_data_t int_data;
1678 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
1680 for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
1681 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
1682 if (wtap_encap == int_data.wtap_encap) {
1690 static gboolean pcapng_dump(wtap_dumper *wdh,
1691 const struct wtap_pkthdr *phdr,
1692 const union wtap_pseudo_header *pseudo_header,
1693 const guchar *pd, int *err)
1695 wtapng_block_t wblock;
1696 interface_data_t int_data;
1697 guint32 interface_id;
1699 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
1701 pcapng_debug2("pcapng_dump: encap = %d (%s)",
1703 wtap_encap_string(phdr->pkt_encap));
1705 interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
1706 if (interface_id == G_MAXUINT32) {
1707 /* write the interface description block */
1708 wblock.frame_buffer = NULL;
1709 wblock.pseudo_header = NULL;
1710 wblock.packet_header = NULL;
1711 wblock.file_encap = NULL;
1712 wblock.type = BLOCK_TYPE_IDB;
1713 wblock.data.if_descr.link_type = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
1714 wblock.data.if_descr.snap_len = wdh->snaplen; /* XXX */
1716 /* XXX - options unused */
1717 wblock.data.if_descr.if_speed = -1;
1718 wblock.data.if_descr.if_tsresol = 6; /* default: usec */
1719 wblock.data.if_descr.if_os = NULL;
1720 wblock.data.if_descr.if_fcslen = -1;
1722 if (!pcapng_write_block(wdh, &wblock, err)) {
1726 interface_id = pcapng->number_of_interfaces;
1727 int_data.wtap_encap = phdr->pkt_encap;
1728 int_data.time_units_per_second = 0;
1729 g_array_append_val(pcapng->interface_data, int_data);
1730 pcapng->number_of_interfaces++;
1732 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
1735 wtap_encap_string(phdr->pkt_encap));
1738 wblock.frame_buffer = pd;
1739 wblock.pseudo_header = pseudo_header;
1740 wblock.packet_header = NULL;
1741 wblock.file_encap = NULL;
1743 /* write the (enhanced) packet block */
1744 wblock.type = BLOCK_TYPE_EPB;
1746 /* default is to write out in microsecond resolution */
1747 ts = (((guint64)phdr->ts.secs) * 1000000) + (phdr->ts.nsecs / 1000);
1749 /* Split the 64-bit timestamp into two 32-bit pieces */
1750 wblock.data.packet.ts_high = (guint32)(ts >> 32);
1751 wblock.data.packet.ts_low = (guint32)ts;
1753 wblock.data.packet.cap_len = phdr->caplen;
1754 wblock.data.packet.packet_len = phdr->len;
1755 wblock.data.packet.interface_id = interface_id;
1756 wblock.data.packet.wtap_encap = phdr->pkt_encap;
1758 /* currently unused */
1759 wblock.data.packet.drop_count = -1;
1760 wblock.data.packet.opt_comment = NULL;
1762 if (!pcapng_write_block(wdh, &wblock, err)) {
1770 /* Finish writing to a dump file.
1771 Returns TRUE on success, FALSE on failure. */
1772 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
1774 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
1776 pcapng_debug0("pcapng_dump_close");
1777 g_array_free(pcapng->interface_data, TRUE);
1778 pcapng->number_of_interfaces = 0;
1783 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1786 pcapng_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
1788 wtapng_block_t wblock;
1789 pcapng_dump_t *pcapng;
1791 wblock.frame_buffer = NULL;
1792 wblock.pseudo_header = NULL;
1793 wblock.packet_header = NULL;
1794 wblock.file_encap = NULL;
1796 pcapng_debug0("pcapng_dump_open");
1797 /* This is a pcapng file */
1798 wdh->subtype_write = pcapng_dump;
1799 wdh->subtype_close = pcapng_dump_close;
1800 pcapng = (pcapng_dump_t *)g_malloc(sizeof(pcapng_dump_t));
1801 wdh->priv = (void *)pcapng;
1802 pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
1803 pcapng->number_of_interfaces = 0;
1805 /* write the section header block */
1806 wblock.type = BLOCK_TYPE_SHB;
1807 wblock.data.section.section_length = -1;
1809 /* XXX - options unused */
1810 wblock.data.section.opt_comment = NULL;
1811 wblock.data.section.shb_hardware = NULL;
1812 wblock.data.section.shb_os = NULL;
1813 wblock.data.section.shb_user_appl = NULL;
1815 if (!pcapng_write_block(wdh, &wblock, err)) {
1818 pcapng_debug0("pcapng_dump_open: wrote section header block.");
1824 /* Returns 0 if we could write the specified encapsulation type,
1825 an error indication otherwise. */
1826 int pcapng_dump_can_write_encap(int wtap_encap)
1828 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
1830 wtap_encap_string(wtap_encap));
1832 /* Per-packet encapsulations is supported. */
1833 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
1836 /* Make sure we can figure out this DLT type */
1837 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
1838 return WTAP_ERR_UNSUPPORTED_ENCAP;