DCERPC: factor out proto_tree_add_dcerpc_drep()
[wireshark-wip.git] / wiretap / pcapng.c
blobc96fc84afd331551485c317e0620ceb3d94a56ec
1 /* pcapng.c
3 * $Id$
5 * Wiretap Library
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * File format support for pcap-ng file format
9 * Copyright (c) 2007 by Ulf Lamping <ulf.lamping@web.de>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 /* File format reference:
27 * http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
28 * Related Wiki page:
29 * http://wiki.wireshark.org/Development/PcapNg
32 #include "config.h"
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
39 #include "wtap-int.h"
40 #include <epan/addr_resolv.h>
41 #include "file_wrappers.h"
42 #include "buffer.h"
43 #include "libpcap.h"
44 #include "pcap-common.h"
45 #include "pcap-encap.h"
46 #include "pcapng.h"
48 #if 0
49 #define pcapng_debug0(str) g_warning(str)
50 #define pcapng_debug1(str,p1) g_warning(str,p1)
51 #define pcapng_debug2(str,p1,p2) g_warning(str,p1,p2)
52 #define pcapng_debug3(str,p1,p2,p3) g_warning(str,p1,p2,p3)
53 #else
54 #define pcapng_debug0(str)
55 #define pcapng_debug1(str,p1)
56 #define pcapng_debug2(str,p1,p2)
57 #define pcapng_debug3(str,p1,p2,p3)
58 #endif
60 static gboolean
61 pcapng_read(wtap *wth, int *err, gchar **err_info,
62 gint64 *data_offset);
63 static gboolean
64 pcapng_seek_read(wtap *wth, gint64 seek_off,
65 struct wtap_pkthdr *phdr, Buffer *buf, int length,
66 int *err, gchar **err_info);
67 static void
68 pcapng_close(wtap *wth);
71 /* pcapng: common block header for every block type */
72 typedef struct pcapng_block_header_s {
73 guint32 block_type;
74 guint32 block_total_length;
75 /* x bytes block_body */
76 /* guint32 block_total_length */
77 } pcapng_block_header_t;
80 * Minimum block size = size of block header + size of block trailer.
82 #define MIN_BLOCK_SIZE ((guint32)(sizeof(pcapng_block_header_t) + sizeof(guint32)))
85 * In order to keep from trying to allocate large chunks of memory,
86 * which could either fail or, even if it succeeds, chew up so much
87 * address space or memory+backing store as not to leave room for
88 * anything else, we impose an upper limit on the size of blocks
89 * we're willing to handle.
91 * For now, we pick an arbitrary limit of 16MB (OK, fine, 16MiB, but
92 * don't try saying that on Wikipedia :-) :-) :-)).
94 #define MAX_BLOCK_SIZE (16*1024*1024)
96 /* pcapng: section header block */
97 typedef struct pcapng_section_header_block_s {
98 /* pcapng_block_header_t */
99 guint32 magic;
100 guint16 version_major;
101 guint16 version_minor;
102 guint64 section_length; /* might be -1 for unknown */
103 /* ... Options ... */
104 } pcapng_section_header_block_t;
107 * Minimum SHB size = minimum block size + size of fixed length portion of SHB.
109 #define MIN_SHB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_section_header_block_t)))
111 /* pcapng: interface description block */
112 typedef struct pcapng_interface_description_block_s {
113 guint16 linktype;
114 guint16 reserved;
115 guint32 snaplen;
116 /* ... Options ... */
117 } pcapng_interface_description_block_t;
120 * Minimum IDB size = minimum block size + size of fixed length portion of IDB.
122 #define MIN_IDB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_description_block_t)))
124 /* pcapng: packet block (obsolete) */
125 typedef struct pcapng_packet_block_s {
126 guint16 interface_id;
127 guint16 drops_count;
128 guint32 timestamp_high;
129 guint32 timestamp_low;
130 guint32 captured_len;
131 guint32 packet_len;
132 /* ... Packet Data ... */
133 /* ... Padding ... */
134 /* ... Options ... */
135 } pcapng_packet_block_t;
138 * Minimum PB size = minimum block size + size of fixed length portion of PB.
140 #define MIN_PB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_packet_block_t)))
142 /* pcapng: enhanced packet block */
143 typedef struct pcapng_enhanced_packet_block_s {
144 guint32 interface_id;
145 guint32 timestamp_high;
146 guint32 timestamp_low;
147 guint32 captured_len;
148 guint32 packet_len;
149 /* ... Packet Data ... */
150 /* ... Padding ... */
151 /* ... Options ... */
152 } pcapng_enhanced_packet_block_t;
155 * Minimum EPB size = minimum block size + size of fixed length portion of EPB.
157 #define MIN_EPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_enhanced_packet_block_t)))
159 /* pcapng: simple packet block */
160 typedef struct pcapng_simple_packet_block_s {
161 guint32 packet_len;
162 /* ... Packet Data ... */
163 /* ... Padding ... */
164 } pcapng_simple_packet_block_t;
167 * Minimum SPB size = minimum block size + size of fixed length portion of SPB.
169 #define MIN_SPB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_simple_packet_block_t)))
171 /* pcapng: name resolution block */
172 typedef struct pcapng_name_resolution_block_s {
173 guint16 record_type;
174 guint16 record_len;
175 /* ... Record ... */
176 } pcapng_name_resolution_block_t;
179 * Minimum NRB size = minimum block size + size of smallest NRB record
180 * (there must at least be an "end of records" record).
182 #define MIN_NRB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_name_resolution_block_t)))
184 /* pcapng: interface statistics block */
185 typedef struct pcapng_interface_statistics_block_s {
186 guint32 interface_id;
187 guint32 timestamp_high;
188 guint32 timestamp_low;
189 /* ... Options ... */
190 } pcapng_interface_statistics_block_t;
193 * Minimum ISB size = minimum block size + size of fixed length portion of ISB.
195 #define MIN_ISB_SIZE ((guint32)(MIN_BLOCK_SIZE + sizeof(pcapng_interface_statistics_block_t)))
197 /* pcapng: common option header for every option type */
198 typedef struct pcapng_option_header_s {
199 guint16 option_code;
200 guint16 option_length;
201 /* ... x bytes Option Body ... */
202 /* ... Padding ... */
203 } pcapng_option_header_t;
205 struct option {
206 guint16 type;
207 guint16 value_length;
210 /* Block types */
211 #define BLOCK_TYPE_IDB 0x00000001 /* Interface Description Block */
212 #define BLOCK_TYPE_PB 0x00000002 /* Packet Block (obsolete) */
213 #define BLOCK_TYPE_SPB 0x00000003 /* Simple Packet Block */
214 #define BLOCK_TYPE_NRB 0x00000004 /* Name Resolution Block */
215 #define BLOCK_TYPE_ISB 0x00000005 /* Interface Statistics Block */
216 #define BLOCK_TYPE_EPB 0x00000006 /* Enhanced Packet Block */
217 #define BLOCK_TYPE_SHB 0x0A0D0D0A /* Section Header Block */
219 /* Options */
220 #define OPT_EOFOPT 0
221 #define OPT_COMMENT 1
222 #define OPT_SHB_HARDWARE 2
223 #define OPT_SHB_OS 3
224 #define OPT_SHB_USERAPPL 4
225 #define OPT_EPB_FLAGS 2
226 #define OPT_EPB_HASH 3
227 #define OPT_EPB_DROPCOUNT 4
229 /* Capture section */
230 #if 0
231 /* Moved to wtap.h */
232 typedef struct wtapng_section_s {
233 /* mandatory */
234 guint64 section_length;
235 /* options */
236 gchar *opt_comment; /* NULL if not available */
237 gchar *shb_hardware; /* NULL if not available */
238 gchar *shb_os; /* NULL if not available */
239 gchar *shb_user_appl; /* NULL if not available */
240 } wtapng_section_t;
241 #endif
243 #if 0
244 /* Moved to wtap.h */
246 /* Interface Description
248 * Options:
249 * if_name 2 A UTF-8 string containing the name of the device used to capture data. "eth0" / "\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}" / ...
250 * if_description 3 A UTF-8 string containing the description of the device used to capture data. "Broadcom NetXtreme" / "First Ethernet Interface" / ...
251 * if_IPv4addr 4 Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
252 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
253 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
254 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
255 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
256 * if_tsresol 9 Resolution of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10 (e.g. 6 means microsecond resolution, timestamps are the number of microseconds since 1/1/1970). If the Most Significant Bit is equal to one, the remaining bits indicates the resolution as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a resolution of 10^-6 is assumed (i.e. timestamps have the same resolution of the standard 'libpcap' timestamps). 6
257 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
258 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO). (TODO: better use different options for different fields? e.g. if_filter_pcap, if_filter_bpf, ...) 00 "tcp port 23 and host 10.0.0.5"
259 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory))) because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
260 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. For link layers whose FCS length can change during time, the Packet Block Flags Word can be used (see Appendix A (Packet Block Flags Word)). 4
261 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps. The time zone of the offset can be specified with the option if_tzone. TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
264 typedef struct wtapng_if_descr_s {
265 /* mandatory */
266 guint16 link_type;
267 guint encap;
268 guint32 snap_len;
269 /* options */
270 gchar *opt_comment; /* NULL if not available */
271 gchar *if_name; /* NULL if not available, opt 2 A UTF-8 string containing the name of the device used to capture data. */
272 gchar *if_description;/* NULL if not available, opt 3 A UTF-8 string containing the description of the device used to capture data. */
273 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
274 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
275 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
276 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
277 guint64 if_speed; /* 0 if unknown, opt 8 Interface speed (in bps). 100000000 for 100Mbps */
278 guint8 if_tsresol; /* default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
279 * If the Most Significant Bit is equal to zero, the remaining bits indicates the resolution of the timestamp as as a negative power of 10
281 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
282 gchar *if_filter; /* NULL if not available, opt 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
283 * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
285 gchar *if_os; /* NULL if not available, 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed. */
286 gint8 if_fcslen; /* -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface. */
287 /* XXX: guint64 if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
288 } wtapng_if_descr_t;
289 #endif
291 /* Packets */
292 typedef struct wtapng_packet_s {
293 /* mandatory */
294 guint32 ts_high; /* seconds since 1.1.1970 */
295 guint32 ts_low; /* fraction of seconds, depends on if_tsresol */
296 guint32 cap_len; /* data length in the file */
297 guint32 packet_len; /* data length on the wire */
298 guint32 interface_id; /* identifier of the interface. */
299 guint16 drops_count; /* drops count, only valid for packet block */
300 /* 0xffff if information no available */
301 /* pack_hash */
302 /* XXX - put the packet data / pseudo_header here as well? */
303 } wtapng_packet_t;
305 /* Simple Packets */
306 typedef struct wtapng_simple_packet_s {
307 /* mandatory */
308 guint32 cap_len; /* data length in the file */
309 guint32 packet_len; /* data length on the wire */
310 guint32 pseudo_header_len;
311 int wtap_encap;
312 /* XXX - put the packet data / pseudo_header here as well? */
313 } wtapng_simple_packet_t;
315 /* Name Resolution */
316 typedef struct wtapng_name_res_s {
317 /* options */
318 gchar *opt_comment; /* NULL if not available */
319 /* XXX */
320 } wtapng_name_res_t;
322 #if 0
323 /* Interface Statistics moved to wtap.h*/
324 typedef struct wtapng_if_stats_s {
325 /* mandatory */
326 guint32 interface_id;
327 guint32 ts_high;
328 guint32 ts_low;
329 /* options */
330 gchar *opt_comment; /* NULL if not available */
331 guint64 isb_starttime;
332 guint64 isb_endtime;
333 guint64 isb_ifrecv;
334 guint64 isb_ifdrop;
335 guint64 isb_filteraccept;
336 guint64 isb_osdrop;
337 guint64 isb_usrdeliv;
338 } wtapng_if_stats_t;
339 #endif
341 typedef struct wtapng_block_s {
342 guint32 type; /* block_type as defined by pcapng */
343 union {
344 wtapng_section_t section;
345 wtapng_if_descr_t if_descr;
346 wtapng_name_res_t name_res;
347 wtapng_if_stats_t if_stats;
348 } data;
351 * XXX - currently don't know how to handle these!
353 * For one thing, when we're reading a block, they must be
354 * writable, i.e. not const, so that we can read into them,
355 * but, when we're writing a block, they can be const, and,
356 * in fact, they sometimes point to const values.
358 struct wtap_pkthdr *packet_header;
359 Buffer *frame_buffer;
360 int *file_encap;
361 } wtapng_block_t;
363 /* Interface data in private struct */
364 typedef struct interface_data_s {
365 int wtap_encap;
366 guint32 snap_len;
367 guint64 time_units_per_second;
368 } interface_data_t;
370 typedef struct {
371 gboolean shb_read; /**< Set when first SHB read, second read will fail */
372 gboolean byte_swapped;
373 guint16 version_major;
374 guint16 version_minor;
375 GArray *interface_data;
376 guint number_of_interfaces;
377 gint8 if_fcslen;
378 wtap_new_ipv4_callback_t add_new_ipv4;
379 wtap_new_ipv6_callback_t add_new_ipv6;
380 } pcapng_t;
382 static int
383 pcapng_read_option(FILE_T fh, pcapng_t *pn, pcapng_option_header_t *oh,
384 char *content, guint len, guint to_read,
385 int *err, gchar **err_info)
387 int bytes_read;
388 int block_read;
389 guint64 file_offset64;
391 /* sanity check: don't run past the end of the block */
392 if (to_read < sizeof (*oh)) {
393 *err = WTAP_ERR_BAD_FILE;
394 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
395 return -1;
398 /* read option header */
399 errno = WTAP_ERR_CANT_READ;
400 bytes_read = file_read(oh, sizeof (*oh), fh);
401 if (bytes_read != sizeof (*oh)) {
402 pcapng_debug0("pcapng_read_option: failed to read option");
403 *err = file_error(fh, err_info);
404 if (*err != 0)
405 return -1;
406 return 0;
408 block_read = sizeof (*oh);
409 if (pn->byte_swapped) {
410 oh->option_code = BSWAP16(oh->option_code);
411 oh->option_length = BSWAP16(oh->option_length);
414 /* sanity check: don't run past the end of the block */
415 if (to_read < sizeof (*oh) + oh->option_length) {
416 *err = WTAP_ERR_BAD_FILE;
417 *err_info = g_strdup("pcapng_read_option: option goes past the end of the block");
418 return -1;
421 /* sanity check: option length */
422 if (oh->option_length > len) {
423 pcapng_debug2("pcapng_read_option: option_length %u larger than buffer (%u)",
424 oh->option_length, len);
425 return 0;
428 /* read option content */
429 errno = WTAP_ERR_CANT_READ;
430 bytes_read = file_read(content, oh->option_length, fh);
431 if (bytes_read != oh->option_length) {
432 pcapng_debug1("pcapng_read_option: failed to read content of option %u", oh->option_code);
433 *err = file_error(fh, err_info);
434 if (*err != 0)
435 return -1;
436 return 0;
438 block_read += oh->option_length;
440 /* jump over potential padding bytes at end of option */
441 if ( (oh->option_length % 4) != 0) {
442 file_offset64 = file_seek(fh, 4 - (oh->option_length % 4), SEEK_CUR, err);
443 if (file_offset64 <= 0) {
444 if (*err != 0)
445 return -1;
446 return 0;
448 block_read += 4 - (oh->option_length % 4);
451 return block_read;
455 static int
456 pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
457 pcapng_block_header_t *bh, pcapng_t *pn,
458 wtapng_block_t *wblock, int *err,
459 gchar **err_info)
461 int bytes_read;
462 guint block_read;
463 guint to_read, opt_cont_buf_len;
464 pcapng_section_header_block_t shb;
465 pcapng_option_header_t oh;
466 char *option_content = NULL; /* Allocate as large as the options block */
469 * Is this block long enough to be an SHB?
471 if (bh->block_total_length < MIN_SHB_SIZE) {
473 * No.
475 if (first_block)
476 return 0; /* probably not a pcap-ng file */
477 *err = WTAP_ERR_BAD_FILE;
478 *err_info = g_strdup_printf("pcapng_read_section_header_block: total block length %u of an SHB is less than the minimum SHB size %u",
479 bh->block_total_length, MIN_SHB_SIZE);
480 return -1;
483 /* read block content */
484 errno = WTAP_ERR_CANT_READ;
485 bytes_read = file_read(&shb, sizeof shb, fh);
486 if (bytes_read != sizeof shb) {
487 *err = file_error(fh, err_info);
488 if (*err == 0) {
489 if (first_block) {
491 * We're reading this as part of an open,
492 * and this block is too short to be
493 * an SHB, so the file is too short
494 * to be a pcap-ng file.
496 return 0;
500 * Otherwise, just report this as an error.
502 *err = WTAP_ERR_SHORT_READ;
504 return -1;
506 block_read = bytes_read;
508 /* is the magic number one we expect? */
509 switch (shb.magic) {
510 case(0x1A2B3C4D):
511 /* this seems pcapng with correct byte order */
512 pn->byte_swapped = FALSE;
513 pn->version_major = shb.version_major;
514 pn->version_minor = shb.version_minor;
516 pcapng_debug3("pcapng_read_section_header_block: SHB (little endian) V%u.%u, len %u",
517 pn->version_major, pn->version_minor, bh->block_total_length);
518 break;
519 case(0x4D3C2B1A):
520 /* this seems pcapng with swapped byte order */
521 pn->byte_swapped = TRUE;
522 pn->version_major = BSWAP16(shb.version_major);
523 pn->version_minor = BSWAP16(shb.version_minor);
525 /* tweak the block length to meet current swapping that we know now */
526 bh->block_total_length = BSWAP32(bh->block_total_length);
528 pcapng_debug3("pcapng_read_section_header_block: SHB (big endian) V%u.%u, len %u",
529 pn->version_major, pn->version_minor, bh->block_total_length);
530 break;
531 default:
532 /* Not a "pcapng" magic number we know about. */
533 if (first_block) {
534 /* Not a pcap-ng file. */
535 return 0;
538 /* A bad block */
539 *err = WTAP_ERR_BAD_FILE;
540 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown byte-order magic number 0x%08x", shb.magic);
541 return 0;
544 /* OK, at this point we assume it's a pcap-ng file.
546 Don't try to allocate memory for a huge number of options, as
547 that might fail and, even if it succeeds, it might not leave
548 any address space or memory+backing store for anything else.
550 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
551 We check for this *after* checking the SHB for its byte
552 order magic number, so that non-pcap-ng files are less
553 likely to be treated as bad pcap-ng files. */
554 if (bh->block_total_length > MAX_BLOCK_SIZE) {
555 *err = WTAP_ERR_BAD_FILE;
556 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
557 bh->block_total_length, MAX_BLOCK_SIZE);
558 return -1;
561 /* We currently only suport one SHB */
562 if (pn->shb_read == TRUE) {
563 *err = WTAP_ERR_UNSUPPORTED;
564 *err_info = g_strdup_printf("pcapng: multiple section header blocks not supported.");
565 return 0;
568 /* we currently only understand SHB V1.0 */
569 if (pn->version_major != 1 || pn->version_minor > 0) {
570 *err = WTAP_ERR_UNSUPPORTED;
571 *err_info = g_strdup_printf("pcapng_read_section_header_block: unknown SHB version %u.%u",
572 pn->version_major, pn->version_minor);
573 return -1;
577 /* 64bit section_length (currently unused) */
578 if (pn->byte_swapped) {
579 wblock->data.section.section_length = BSWAP64(shb.section_length);
580 } else {
581 wblock->data.section.section_length = shb.section_length;
584 /* Option defaults */
585 wblock->data.section.opt_comment = NULL;
586 wblock->data.section.shb_hardware = NULL;
587 wblock->data.section.shb_os = NULL;
588 wblock->data.section.shb_user_appl = NULL;
590 /* Options */
591 errno = WTAP_ERR_CANT_READ;
592 to_read = bh->block_total_length - MIN_SHB_SIZE;
594 /* Allocate enough memory to hold all options */
595 opt_cont_buf_len = to_read;
596 option_content = (char *)g_try_malloc(opt_cont_buf_len);
597 if (opt_cont_buf_len != 0 && option_content == NULL) {
598 *err = ENOMEM; /* we assume we're out of memory */
599 return -1;
601 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes", to_read);
602 while (to_read != 0) {
603 /* read option */
604 pcapng_debug1("pcapng_read_section_header_block: Options %u bytes remaining", to_read);
605 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
606 if (bytes_read <= 0) {
607 pcapng_debug0("pcapng_read_section_header_block: failed to read option");
608 return bytes_read;
610 block_read += bytes_read;
611 to_read -= bytes_read;
613 /* handle option content */
614 switch (oh.option_code) {
615 case(OPT_EOFOPT):
616 if (to_read != 0) {
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 */
620 to_read = 0;
621 break;
622 case(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);
626 } else {
627 pcapng_debug1("pcapng_read_section_header_block: opt_comment length %u seems strange", oh.option_length);
629 break;
630 case(OPT_SHB_HARDWARE):
631 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
632 wblock->data.section.shb_hardware = g_strndup(option_content, oh.option_length);
633 pcapng_debug1("pcapng_read_section_header_block: shb_hardware %s", wblock->data.section.shb_hardware);
634 } else {
635 pcapng_debug1("pcapng_read_section_header_block: shb_hardware length %u seems strange", oh.option_length);
637 break;
638 case(OPT_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);
642 } else {
643 pcapng_debug2("pcapng_read_section_header_block: shb_os length %u seems strange, opt buffsize %u", oh.option_length,to_read);
645 break;
646 case(OPT_SHB_USERAPPL):
647 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
648 wblock->data.section.shb_user_appl = g_strndup(option_content, oh.option_length);
649 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl %s", wblock->data.section.shb_user_appl);
650 } else {
651 pcapng_debug1("pcapng_read_section_header_block: shb_user_appl length %u seems strange", oh.option_length);
653 break;
654 default:
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);
661 return block_read;
665 /* "Interface Description Block" */
666 static int
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 */
671 int bytes_read;
672 guint block_read;
673 guint to_read, opt_cont_buf_len;
674 pcapng_interface_description_block_t idb;
675 pcapng_option_header_t oh;
676 char *option_content = NULL; /* Allocate as large as the options block */
679 * Is this block long enough to be an IDB?
681 if (bh->block_total_length < MIN_IDB_SIZE) {
683 * No.
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);
688 return -1;
691 /* Don't try to allocate memory for a huge number of options, as
692 that might fail and, even if it succeeds, it might not leave
693 any address space or memory+backing store for anything else.
695 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
696 We check for this *after* checking the SHB for its byte
697 order magic number, so that non-pcap-ng files are less
698 likely to be treated as bad pcap-ng files. */
699 if (bh->block_total_length > MAX_BLOCK_SIZE) {
700 *err = WTAP_ERR_BAD_FILE;
701 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
702 bh->block_total_length, MAX_BLOCK_SIZE);
703 return -1;
706 /* read block content */
707 errno = WTAP_ERR_CANT_READ;
708 bytes_read = file_read(&idb, sizeof idb, fh);
709 if (bytes_read != sizeof idb) {
710 pcapng_debug0("pcapng_read_if_descr_block: failed to read IDB");
711 *err = file_error(fh, err_info);
712 if (*err != 0)
713 return -1;
714 return 0;
716 block_read = bytes_read;
718 /* mandatory values */
719 if (pn->byte_swapped) {
720 wblock->data.if_descr.link_type = BSWAP16(idb.linktype);
721 wblock->data.if_descr.snap_len = BSWAP32(idb.snaplen);
722 } else {
723 wblock->data.if_descr.link_type = idb.linktype;
724 wblock->data.if_descr.snap_len = idb.snaplen;
727 wblock->data.if_descr.wtap_encap = wtap_pcap_encap_to_wtap_encap(wblock->data.if_descr.link_type);
728 wblock->data.if_descr.time_units_per_second = time_units_per_second;
730 pcapng_debug3("pcapng_read_if_descr_block: IDB link_type %u (%s), snap %u",
731 wblock->data.if_descr.link_type,
732 wtap_encap_string(wblock->data.if_descr.wtap_encap),
733 wblock->data.if_descr.snap_len);
735 if (wblock->data.if_descr.snap_len > WTAP_MAX_PACKET_SIZE) {
736 /* This is unrealistic, but text2pcap currently uses 102400.
737 * We do not use this value, maybe we should check the
738 * snap_len of the packets against it. For now, only warn.
740 pcapng_debug1("pcapng_read_if_descr_block: snapshot length %u unrealistic.",
741 wblock->data.if_descr.snap_len);
742 /*wblock->data.if_descr.snap_len = WTAP_MAX_PACKET_SIZE;*/
745 /* Option defaults */
746 wblock->data.if_descr.opt_comment = NULL;
747 wblock->data.if_descr.if_name = NULL;
748 wblock->data.if_descr.if_description = NULL;
749 /* XXX: if_IPv4addr */
750 /* XXX: if_IPv6addr */
751 /* XXX: if_MACaddr */
752 /* XXX: if_EUIaddr */
753 wblock->data.if_descr.if_speed = 0; /* "unknown" */
754 wblock->data.if_descr.if_tsresol = 6; /* default is 6 for microsecond resolution */
755 wblock->data.if_descr.if_filter_str = NULL;
756 wblock->data.if_descr.bpf_filter_len = 0;
757 wblock->data.if_descr.if_filter_bpf_bytes = NULL;
758 wblock->data.if_descr.if_os = NULL;
759 wblock->data.if_descr.if_fcslen = -1; /* unknown or changes between packets */
760 /* XXX: guint64 if_tsoffset; */
763 /* Options */
764 errno = WTAP_ERR_CANT_READ;
765 to_read = bh->block_total_length - MIN_IDB_SIZE;
767 /* Allocate enough memory to hold all options */
768 opt_cont_buf_len = to_read;
769 option_content = (char *)g_try_malloc(opt_cont_buf_len);
770 if (opt_cont_buf_len != 0 && option_content == NULL) {
771 *err = ENOMEM; /* we assume we're out of memory */
772 return -1;
775 while (to_read != 0) {
776 /* read option */
777 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
778 if (bytes_read <= 0) {
779 pcapng_debug0("pcapng_read_if_descr_block: failed to read option");
780 return bytes_read;
782 block_read += bytes_read;
783 to_read -= bytes_read;
785 /* handle option content */
786 switch (oh.option_code) {
787 case(0): /* opt_endofopt */
788 if (to_read != 0) {
789 pcapng_debug1("pcapng_read_if_descr_block: %u bytes after opt_endofopt", to_read);
791 /* padding should be ok here, just get out of this */
792 to_read = 0;
793 break;
794 case(1): /* opt_comment */
795 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
796 wblock->data.if_descr.opt_comment = g_strndup(option_content, oh.option_length);
797 pcapng_debug1("pcapng_read_if_descr_block: opt_comment %s", wblock->data.if_descr.opt_comment);
798 } else {
799 pcapng_debug1("pcapng_read_if_descr_block: opt_comment length %u seems strange", oh.option_length);
801 break;
802 case(2): /* if_name */
803 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
804 wblock->data.if_descr.if_name = g_strndup(option_content, oh.option_length);
805 pcapng_debug1("pcapng_read_if_descr_block: if_name %s", wblock->data.if_descr.if_name);
806 } else {
807 pcapng_debug1("pcapng_read_if_descr_block: if_name length %u seems strange", oh.option_length);
809 break;
810 case(3): /* if_description */
811 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
812 wblock->data.if_descr.if_description = g_strndup(option_content, oh.option_length);
813 pcapng_debug1("pcapng_read_if_descr_block: if_description %s", wblock->data.if_descr.if_description);
814 } else {
815 pcapng_debug1("pcapng_read_if_descr_block: if_description length %u seems strange", oh.option_length);
817 break;
819 * if_IPv4addr 4 Interface network address and netmask. This option can be repeated multiple times within the same Interface Description Block when multiple IPv4 addresses are assigned to the interface. 192 168 1 1 255 255 255 0
820 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte). This option can be repeated multiple times within the same Interface Description Block when multiple IPv6 addresses are assigned to the interface. 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64 is written (in hex) as "20 01 0d b8 85 a3 08 d3 13 19 8a 2e 03 70 73 44 40"
821 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
822 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
824 case(8): /* if_speed */
825 if (oh.option_length == 8) {
826 /* Don't cast a char[] into a guint64--the
827 * char[] may not be aligned correctly.
829 memcpy(&wblock->data.if_descr.if_speed, option_content, sizeof(guint64));
830 if (pn->byte_swapped)
831 wblock->data.if_descr.if_speed = BSWAP64(wblock->data.if_descr.if_speed);
832 pcapng_debug1("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", wblock->data.if_descr.if_speed);
833 } else {
834 pcapng_debug1("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
836 break;
837 case(9): /* if_tsresol */
838 if (oh.option_length == 1) {
839 guint64 base;
840 guint64 result;
841 guint8 i, exponent, if_tsresol;
843 if_tsresol = option_content[0];
844 if (if_tsresol & 0x80) {
845 base = 2;
846 } else {
847 base = 10;
849 exponent = (guint8)(if_tsresol & 0x7f);
850 if (((base == 2) && (exponent < 64)) || ((base == 10) && (exponent < 20))) {
851 result = 1;
852 for (i = 0; i < exponent; i++) {
853 result *= base;
855 time_units_per_second = result;
856 } else {
857 time_units_per_second = G_MAXUINT64;
859 if (time_units_per_second > (((guint64)1) << 32)) {
860 pcapng_debug0("pcapng_open: time conversion might be inaccurate");
862 wblock->data.if_descr.time_units_per_second = time_units_per_second;
863 wblock->data.if_descr.if_tsresol = if_tsresol;
864 pcapng_debug2("pcapng_read_if_descr_block: if_tsresol %u, units/s %" G_GINT64_MODIFIER "u", wblock->data.if_descr.if_tsresol, wblock->data.if_descr.time_units_per_second);
865 } else {
866 pcapng_debug1("pcapng_read_if_descr_block: if_tsresol length %u not 1 as expected", oh.option_length);
868 break;
870 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
872 case(11): /* if_filter */
873 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
874 /* The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string,
875 * or BPF bytecode.
877 if (option_content[0] == 0) {
878 wblock->data.if_descr.if_filter_str = g_strndup(option_content+1, oh.option_length-1);
879 pcapng_debug2("pcapng_read_if_descr_block: if_filter_str %s oh.option_length %u", wblock->data.if_descr.if_filter_str, oh.option_length);
880 } else if (option_content[0] == 1) {
881 wblock->data.if_descr.bpf_filter_len = oh.option_length-1;
882 wblock->data.if_descr.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
883 memcpy(&wblock->data.if_descr.if_filter_bpf_bytes, option_content+1, oh.option_length-1);
885 } else {
886 pcapng_debug1("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
888 break;
889 case(12): /* if_os */
891 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
892 * This can be different from the same information that can be contained by the Section Header Block (Section 3.1 (Section Header Block (mandatory)))
893 * because the capture can have been done on a remote machine. "Windows XP SP2" / "openSUSE 10.2" / ...
895 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
896 wblock->data.if_descr.if_os = g_strndup(option_content, oh.option_length);
897 pcapng_debug1("pcapng_read_if_descr_block: if_os %s", wblock->data.if_descr.if_os);
898 } else {
899 pcapng_debug1("pcapng_read_if_descr_block: if_os length %u seems strange", oh.option_length);
901 break;
902 case(13): /* if_fcslen */
903 if (oh.option_length == 1) {
904 wblock->data.if_descr.if_fcslen = option_content[0];
905 pn->if_fcslen = wblock->data.if_descr.if_fcslen;
906 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen %u", wblock->data.if_descr.if_fcslen);
907 /* XXX - add sanity check */
908 } else {
909 pcapng_debug1("pcapng_read_if_descr_block: if_fcslen length %u not 1 as expected", oh.option_length);
911 break;
913 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
914 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
915 * The time zone of the offset can be specified with the option if_tzone.
916 * TODO: won't a if_tsoffset_low for fractional second offsets be useful for highly synchronized capture systems? 1234
918 default:
919 pcapng_debug2("pcapng_read_if_descr_block: unknown option %u - ignoring %u bytes",
920 oh.option_code, oh.option_length);
924 g_free(option_content);
926 if (*wblock->file_encap == WTAP_ENCAP_UNKNOWN) {
927 *wblock->file_encap = wblock->data.if_descr.wtap_encap;
928 } else {
929 if (*wblock->file_encap != wblock->data.if_descr.wtap_encap) {
930 *wblock->file_encap = WTAP_ENCAP_PER_PACKET;
934 return block_read;
938 static int
939 pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info, gboolean enhanced)
941 int bytes_read;
942 guint block_read;
943 guint to_read, opt_cont_buf_len;
944 guint64 file_offset64;
945 pcapng_enhanced_packet_block_t epb;
946 pcapng_packet_block_t pb;
947 wtapng_packet_t packet;
948 guint32 block_total_length;
949 guint32 padding;
950 interface_data_t int_data;
951 guint64 ts;
952 pcapng_option_header_t oh;
953 int pseudo_header_len;
954 char *option_content = NULL; /* Allocate as large as the options block */
955 int fcslen;
957 /* Don't try to allocate memory for a huge number of options, as
958 that might fail and, even if it succeeds, it might not leave
959 any address space or memory+backing store for anything else.
961 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
962 We check for this *after* checking the SHB for its byte
963 order magic number, so that non-pcap-ng files are less
964 likely to be treated as bad pcap-ng files. */
965 if (bh->block_total_length > MAX_BLOCK_SIZE) {
966 *err = WTAP_ERR_BAD_FILE;
967 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
968 bh->block_total_length, MAX_BLOCK_SIZE);
969 return -1;
972 /* "(Enhanced) Packet Block" read fixed part */
973 errno = WTAP_ERR_CANT_READ;
974 if (enhanced) {
976 * Is this block long enough to be an EPB?
978 if (bh->block_total_length < MIN_EPB_SIZE) {
980 * No.
982 *err = WTAP_ERR_BAD_FILE;
983 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of an EPB is less than the minimum EPB size %u",
984 bh->block_total_length, MIN_EPB_SIZE);
985 return -1;
987 bytes_read = file_read(&epb, sizeof epb, fh);
988 if (bytes_read != sizeof epb) {
989 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
990 *err = file_error(fh, err_info);
991 return 0;
993 block_read = bytes_read;
995 if (pn->byte_swapped) {
996 packet.interface_id = BSWAP32(epb.interface_id);
997 packet.drops_count = -1; /* invalid */
998 packet.ts_high = BSWAP32(epb.timestamp_high);
999 packet.ts_low = BSWAP32(epb.timestamp_low);
1000 packet.cap_len = BSWAP32(epb.captured_len);
1001 packet.packet_len = BSWAP32(epb.packet_len);
1002 } else {
1003 packet.interface_id = epb.interface_id;
1004 packet.drops_count = -1; /* invalid */
1005 packet.ts_high = epb.timestamp_high;
1006 packet.ts_low = epb.timestamp_low;
1007 packet.cap_len = epb.captured_len;
1008 packet.packet_len = epb.packet_len;
1010 pcapng_debug3("pcapng_read_packet_block: EPB on interface_id %d, cap_len %d, packet_len %d",
1011 packet.interface_id, packet.cap_len, packet.packet_len);
1012 } else {
1014 * Is this block long enough to be a PB?
1016 if (bh->block_total_length < MIN_PB_SIZE) {
1018 * No.
1020 *err = WTAP_ERR_BAD_FILE;
1021 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of a PB is less than the minimum PB size %u",
1022 bh->block_total_length, MIN_PB_SIZE);
1023 return -1;
1025 bytes_read = file_read(&pb, sizeof pb, fh);
1026 if (bytes_read != sizeof pb) {
1027 pcapng_debug0("pcapng_read_packet_block: failed to read packet data");
1028 *err = file_error(fh, err_info);
1029 return 0;
1031 block_read = bytes_read;
1033 if (pn->byte_swapped) {
1034 packet.interface_id = BSWAP16(pb.interface_id);
1035 packet.drops_count = BSWAP16(pb.drops_count);
1036 packet.ts_high = BSWAP32(pb.timestamp_high);
1037 packet.ts_low = BSWAP32(pb.timestamp_low);
1038 packet.cap_len = BSWAP32(pb.captured_len);
1039 packet.packet_len = BSWAP32(pb.packet_len);
1040 } else {
1041 packet.interface_id = pb.interface_id;
1042 packet.drops_count = pb.drops_count;
1043 packet.ts_high = pb.timestamp_high;
1044 packet.ts_low = pb.timestamp_low;
1045 packet.cap_len = pb.captured_len;
1046 packet.packet_len = pb.packet_len;
1048 pcapng_debug3("pcapng_read_packet_block: PB on interface_id %d, cap_len %d, packet_len %d",
1049 packet.interface_id, packet.cap_len, packet.packet_len);
1053 * How much padding is there at the end of the packet data?
1055 if ((packet.cap_len % 4) != 0)
1056 padding = 4 - (packet.cap_len % 4);
1057 else
1058 padding = 0;
1060 /* add padding bytes to "block total length" */
1061 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1062 if (bh->block_total_length % 4) {
1063 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1064 } else {
1065 block_total_length = bh->block_total_length;
1067 pcapng_debug1("pcapng_read_packet_block: block_total_length %d", block_total_length);
1070 * Is this block long enough to hold the packet data?
1072 if (enhanced) {
1073 if (block_total_length <
1074 MIN_EPB_SIZE + packet.cap_len + padding) {
1076 * No.
1078 *err = WTAP_ERR_BAD_FILE;
1079 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of EPB is too small for %u bytes of packet data",
1080 block_total_length, packet.cap_len);
1081 return -1;
1083 } else {
1084 if (block_total_length <
1085 MIN_PB_SIZE + packet.cap_len + padding) {
1087 * No.
1089 *err = WTAP_ERR_BAD_FILE;
1090 *err_info = g_strdup_printf("pcapng_read_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1091 block_total_length, packet.cap_len);
1092 return -1;
1096 if (packet.cap_len > packet.packet_len) {
1097 *err = WTAP_ERR_BAD_FILE;
1098 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than packet_len %u.",
1099 packet.cap_len, packet.packet_len);
1100 return 0;
1102 if (packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1103 *err = WTAP_ERR_BAD_FILE;
1104 *err_info = g_strdup_printf("pcapng_read_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1105 packet.cap_len, WTAP_MAX_PACKET_SIZE);
1106 return 0;
1108 pcapng_debug3("pcapng_read_packet_block: packet data: packet_len %u captured_len %u interface_id %u",
1109 packet.packet_len,
1110 packet.cap_len,
1111 packet.interface_id);
1113 if (packet.interface_id >= pn->number_of_interfaces) {
1114 *err = WTAP_ERR_BAD_FILE;
1115 *err_info = g_strdup_printf("pcapng: interface index %u is not less than interface count %u.",
1116 packet.interface_id, pn->number_of_interfaces);
1117 return 0;
1119 int_data = g_array_index(pn->interface_data, interface_data_t,
1120 packet.interface_id);
1122 wblock->packet_header->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1124 pcapng_debug3("pcapng_read_packet_block: encapsulation = %d (%s), pseudo header size = %d.",
1125 int_data.wtap_encap,
1126 wtap_encap_string(int_data.wtap_encap),
1127 pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1128 wblock->packet_header->interface_id = packet.interface_id;
1129 wblock->packet_header->pkt_encap = int_data.wtap_encap;
1131 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1132 pseudo_header_len = pcap_process_pseudo_header(fh,
1133 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1134 int_data.wtap_encap,
1135 packet.cap_len,
1136 TRUE,
1137 wblock->packet_header,
1138 err,
1139 err_info);
1140 if (pseudo_header_len < 0) {
1141 return 0;
1143 block_read += pseudo_header_len;
1144 if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1145 pcapng_debug1("pcapng_read_packet_block: Could only read %d bytes for pseudo header.",
1146 pseudo_header_len);
1148 wblock->packet_header->caplen = packet.cap_len - pseudo_header_len;
1149 wblock->packet_header->len = packet.packet_len - pseudo_header_len;
1151 /* Combine the two 32-bit pieces of the timestamp into one 64-bit value */
1152 ts = (((guint64)packet.ts_high) << 32) | ((guint64)packet.ts_low);
1153 wblock->packet_header->ts.secs = (time_t)(ts / int_data.time_units_per_second);
1154 wblock->packet_header->ts.nsecs = (int)(((ts % int_data.time_units_per_second) * 1000000000) / int_data.time_units_per_second);
1156 /* "(Enhanced) Packet Block" read capture data */
1157 errno = WTAP_ERR_CANT_READ;
1158 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1159 packet.cap_len - pseudo_header_len, err, err_info))
1160 return 0;
1161 block_read += packet.cap_len - pseudo_header_len;
1163 /* jump over potential padding bytes at end of the packet data */
1164 if (padding != 0) {
1165 file_offset64 = file_seek(fh, padding, SEEK_CUR, err);
1166 if (file_offset64 <= 0) {
1167 if (*err != 0)
1168 return -1;
1169 return 0;
1171 block_read += padding;
1174 /* Option defaults */
1175 wblock->packet_header->opt_comment = NULL;
1176 wblock->packet_header->drop_count = -1;
1177 wblock->packet_header->pack_flags = 0;
1179 /* FCS length default */
1180 fcslen = pn->if_fcslen;
1182 /* Options
1183 * opt_comment 1
1184 * epb_flags 2
1185 * epb_hash 3
1186 * epb_dropcount 4
1188 errno = WTAP_ERR_CANT_READ;
1189 to_read = block_total_length -
1190 (int)sizeof(pcapng_block_header_t) -
1191 block_read - /* fixed and variable part, including padding */
1192 (int)sizeof(bh->block_total_length);
1194 /* Allocate enough memory to hold all options */
1195 opt_cont_buf_len = to_read;
1196 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1197 if (opt_cont_buf_len != 0 && option_content == NULL) {
1198 *err = ENOMEM; /* we assume we're out of memory */
1199 return -1;
1202 while (to_read != 0) {
1203 /* read option */
1204 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1205 if (bytes_read <= 0) {
1206 pcapng_debug0("pcapng_read_packet_block: failed to read option");
1207 return bytes_read;
1209 block_read += bytes_read;
1210 to_read -= bytes_read;
1212 /* handle option content */
1213 switch (oh.option_code) {
1214 case(OPT_EOFOPT):
1215 if (to_read != 0) {
1216 pcapng_debug1("pcapng_read_packet_block: %u bytes after opt_endofopt", to_read);
1218 /* padding should be ok here, just get out of this */
1219 to_read = 0;
1220 break;
1221 case(OPT_COMMENT):
1222 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1223 wblock->packet_header->presence_flags |= WTAP_HAS_COMMENTS;
1224 wblock->packet_header->opt_comment = g_strndup(option_content, oh.option_length);
1225 pcapng_debug2("pcapng_read_packet_block: length %u opt_comment '%s'", oh.option_length, wblock->packet_header->opt_comment);
1226 } else {
1227 pcapng_debug1("pcapng_read_packet_block: opt_comment length %u seems strange", oh.option_length);
1229 break;
1230 case(OPT_EPB_FLAGS):
1231 if (oh.option_length == 4) {
1232 /* Don't cast a char[] into a guint32--the
1233 * char[] may not be aligned correctly.
1235 wblock->packet_header->presence_flags |= WTAP_HAS_PACK_FLAGS;
1236 memcpy(&wblock->packet_header->pack_flags, option_content, sizeof(guint32));
1237 if (pn->byte_swapped)
1238 wblock->packet_header->pack_flags = BSWAP32(wblock->packet_header->pack_flags);
1239 if (wblock->packet_header->pack_flags & 0x000001E0) {
1240 /* The FCS length is present */
1241 fcslen = (wblock->packet_header->pack_flags & 0x000001E0) >> 5;
1243 pcapng_debug1("pcapng_read_packet_block: pack_flags %u (ignored)", wblock->packet_header->pack_flags);
1244 } else {
1245 pcapng_debug1("pcapng_read_packet_block: pack_flags length %u not 4 as expected", oh.option_length);
1247 break;
1248 case(OPT_EPB_HASH):
1249 pcapng_debug2("pcapng_read_packet_block: epb_hash %u currently not handled - ignoring %u bytes",
1250 oh.option_code, oh.option_length);
1251 break;
1252 case(OPT_EPB_DROPCOUNT):
1253 if (oh.option_length == 8) {
1254 /* Don't cast a char[] into a guint32--the
1255 * char[] may not be aligned correctly.
1257 wblock->packet_header->presence_flags |= WTAP_HAS_DROP_COUNT;
1258 memcpy(&wblock->packet_header->drop_count, option_content, sizeof(guint64));
1259 if (pn->byte_swapped)
1260 wblock->packet_header->drop_count = BSWAP64(wblock->packet_header->drop_count);
1262 pcapng_debug1("pcapng_read_packet_block: drop_count %" G_GINT64_MODIFIER "u", wblock->packet_header->drop_count);
1263 } else {
1264 pcapng_debug1("pcapng_read_packet_block: drop_count length %u not 8 as expected", oh.option_length);
1266 break;
1267 default:
1268 pcapng_debug2("pcapng_read_packet_block: unknown option %u - ignoring %u bytes",
1269 oh.option_code, oh.option_length);
1273 g_free(option_content);
1275 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, int_data.wtap_encap,
1276 (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1277 buffer_start_ptr(wblock->frame_buffer),
1278 (int) (packet.cap_len - pseudo_header_len),
1279 pn->byte_swapped, fcslen);
1280 return block_read;
1284 static int
1285 pcapng_read_simple_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
1287 int bytes_read;
1288 guint block_read;
1289 guint64 file_offset64;
1290 interface_data_t int_data;
1291 pcapng_simple_packet_block_t spb;
1292 wtapng_simple_packet_t simple_packet;
1293 guint32 block_total_length;
1294 guint32 padding;
1295 int pseudo_header_len;
1298 * Is this block long enough to be an SPB?
1300 if (bh->block_total_length < MIN_SPB_SIZE) {
1302 * No.
1304 *err = WTAP_ERR_BAD_FILE;
1305 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of an SPB is less than the minimum SPB size %u",
1306 bh->block_total_length, MIN_SPB_SIZE);
1307 return -1;
1310 /* Don't try to allocate memory for a huge number of options, as
1311 that might fail and, even if it succeeds, it might not leave
1312 any address space or memory+backing store for anything else.
1314 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1315 We check for this *after* checking the SHB for its byte
1316 order magic number, so that non-pcap-ng files are less
1317 likely to be treated as bad pcap-ng files. */
1318 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1319 *err = WTAP_ERR_BAD_FILE;
1320 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1321 bh->block_total_length, MAX_BLOCK_SIZE);
1322 return -1;
1325 /* "Simple Packet Block" read fixed part */
1326 errno = WTAP_ERR_CANT_READ;
1327 bytes_read = file_read(&spb, sizeof spb, fh);
1328 if (bytes_read != sizeof spb) {
1329 pcapng_debug0("pcapng_read_simple_packet_block: failed to read packet data");
1330 *err = file_error(fh, err_info);
1331 return 0;
1333 block_read = bytes_read;
1335 if (0 >= pn->number_of_interfaces) {
1336 *err = WTAP_ERR_BAD_FILE;
1337 *err_info = g_strdup_printf("pcapng: SPB appeared before any IDBs");
1338 return 0;
1340 int_data = g_array_index(pn->interface_data, interface_data_t, 0);
1342 if (pn->byte_swapped) {
1343 simple_packet.packet_len = BSWAP32(spb.packet_len);
1344 } else {
1345 simple_packet.packet_len = spb.packet_len;
1349 * The captured length is not a field in the SPB; it can be
1350 * calculated as the minimum of the snapshot length from the
1351 * IDB and the packet length, as per the pcap-ng spec.
1353 simple_packet.cap_len = simple_packet.packet_len;
1354 if (simple_packet.cap_len > int_data.snap_len)
1355 simple_packet.cap_len = int_data.snap_len;
1358 * How much padding is there at the end of the packet data?
1360 if ((simple_packet.cap_len % 4) != 0)
1361 padding = 4 - (simple_packet.cap_len % 4);
1362 else
1363 padding = 0;
1365 /* add padding bytes to "block total length" */
1366 /* (the "block total length" of some example files don't contain the packet data padding bytes!) */
1367 if (bh->block_total_length % 4) {
1368 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1369 } else {
1370 block_total_length = bh->block_total_length;
1372 pcapng_debug1("pcapng_read_simple_packet_block: block_total_length %d", block_total_length);
1375 * Is this block long enough to hold the packet data?
1377 if (block_total_length < MIN_SPB_SIZE + simple_packet.cap_len + padding) {
1379 * No. That means that the problem is with the packet
1380 * length; the snapshot length can be bigger than the amount
1381 * of packet data in the block, as it's a *maximum* length,
1382 * not a *minimum* length.
1384 *err = WTAP_ERR_BAD_FILE;
1385 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: total block length %u of PB is too small for %u bytes of packet data",
1386 block_total_length, simple_packet.packet_len);
1387 return -1;
1390 if (simple_packet.cap_len > WTAP_MAX_PACKET_SIZE) {
1391 *err = WTAP_ERR_BAD_FILE;
1392 *err_info = g_strdup_printf("pcapng_read_simple_packet_block: cap_len %u is larger than WTAP_MAX_PACKET_SIZE %u.",
1393 simple_packet.cap_len, WTAP_MAX_PACKET_SIZE);
1394 return 0;
1396 pcapng_debug1("pcapng_read_simple_packet_block: packet data: packet_len %u",
1397 simple_packet.packet_len);
1399 pcapng_debug1("pcapng_read_simple_packet_block: Need to read pseudo header of size %d",
1400 pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header));
1402 /* No time stamp in a simple packet block; no options, either */
1403 wblock->packet_header->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_INTERFACE_ID;
1404 wblock->packet_header->interface_id = 0;
1405 wblock->packet_header->pkt_encap = int_data.wtap_encap;
1406 wblock->packet_header->ts.secs = 0;
1407 wblock->packet_header->ts.nsecs = 0;
1408 wblock->packet_header->interface_id = 0;
1409 wblock->packet_header->opt_comment = NULL;
1410 wblock->packet_header->drop_count = 0;
1411 wblock->packet_header->pack_flags = 0;
1413 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1414 pseudo_header_len = pcap_process_pseudo_header(fh,
1415 WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
1416 int_data.wtap_encap,
1417 simple_packet.cap_len,
1418 TRUE,
1419 wblock->packet_header,
1420 err,
1421 err_info);
1422 if (pseudo_header_len < 0) {
1423 return 0;
1425 wblock->packet_header->caplen = simple_packet.cap_len - pseudo_header_len;
1426 wblock->packet_header->len = simple_packet.packet_len - pseudo_header_len;
1427 block_read += pseudo_header_len;
1428 if (pseudo_header_len != pcap_get_phdr_size(int_data.wtap_encap, &wblock->packet_header->pseudo_header)) {
1429 pcapng_debug1("pcapng_read_simple_packet_block: Could only read %d bytes for pseudo header.",
1430 pseudo_header_len);
1433 memset((void *)&wblock->packet_header->pseudo_header, 0, sizeof(union wtap_pseudo_header));
1435 /* "Simple Packet Block" read capture data */
1436 errno = WTAP_ERR_CANT_READ;
1437 if (!wtap_read_packet_bytes(fh, wblock->frame_buffer,
1438 simple_packet.cap_len, err, err_info))
1439 return 0;
1440 block_read += simple_packet.cap_len;
1442 /* jump over potential padding bytes at end of the packet data */
1443 if ((simple_packet.cap_len % 4) != 0) {
1444 file_offset64 = file_seek(fh, 4 - (simple_packet.cap_len % 4), SEEK_CUR, err);
1445 if (file_offset64 <= 0) {
1446 if (*err != 0)
1447 return -1;
1448 return 0;
1450 block_read += 4 - (simple_packet.cap_len % 4);
1453 pcap_read_post_process(WTAP_FILE_TYPE_SUBTYPE_PCAPNG, int_data.wtap_encap,
1454 (union wtap_pseudo_header *)&wblock->packet_header->pseudo_header,
1455 buffer_start_ptr(wblock->frame_buffer),
1456 (int) simple_packet.cap_len,
1457 pn->byte_swapped, pn->if_fcslen);
1458 return block_read;
1461 #define NRES_ENDOFRECORD 0
1462 #define NRES_IP4RECORD 1
1463 #define NRES_IP6RECORD 2
1464 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
1465 /* IPv6 + MAXNAMELEN */
1466 #define INITIAL_NRB_REC_SIZE (16 + 64)
1469 * Find the end of the NUL-terminated name the beginning of which is pointed
1470 * to by p; record_len is the number of bytes remaining in the record.
1472 * Return the length of the name, including the terminating NUL.
1474 * If we don't find a terminating NUL, return -1 and set *err and
1475 * *err_info appropriately.
1477 static int
1478 name_resolution_block_find_name_end(const char *p, guint record_len, int *err,
1479 gchar **err_info)
1481 int namelen;
1483 namelen = 0;
1484 for (;;) {
1485 if (record_len == 0) {
1487 * We ran out of bytes in the record without
1488 * finding a NUL.
1490 *err = WTAP_ERR_BAD_FILE;
1491 *err_info = g_strdup("pcapng_read_name_resolution_block: NRB record has non-null-terminated host name");
1492 return -1;
1494 if (*p == '\0')
1495 break; /* that's the terminating NUL */
1496 p++;
1497 record_len--;
1498 namelen++; /* count this byte */
1501 /* Include the NUL in the name length. */
1502 return namelen + 1;
1505 static int
1506 pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock _U_,int *err, gchar **err_info)
1508 int bytes_read = 0;
1509 int block_read = 0;
1510 int to_read;
1511 guint64 file_offset64;
1512 pcapng_name_resolution_block_t nrb;
1513 Buffer nrb_rec;
1514 guint32 v4_addr;
1515 guint record_len;
1516 char *namep;
1517 int namelen;
1520 * Is this block long enough to be an NRB?
1522 if (bh->block_total_length < MIN_NRB_SIZE) {
1524 * No.
1526 *err = WTAP_ERR_BAD_FILE;
1527 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: total block length %u of an NRB is less than the minimum NRB size %u",
1528 bh->block_total_length, MIN_NRB_SIZE);
1529 return -1;
1532 /* Don't try to allocate memory for a huge number of options, as
1533 that might fail and, even if it succeeds, it might not leave
1534 any address space or memory+backing store for anything else.
1536 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1537 We check for this *after* checking the SHB for its byte
1538 order magic number, so that non-pcap-ng files are less
1539 likely to be treated as bad pcap-ng files. */
1540 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1541 *err = WTAP_ERR_BAD_FILE;
1542 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1543 bh->block_total_length, MAX_BLOCK_SIZE);
1544 return -1;
1547 errno = WTAP_ERR_CANT_READ;
1548 to_read = bh->block_total_length - 8 - 4; /* We have read the header adn should not read the final block_total_length */
1550 pcapng_debug1("pcapng_read_name_resolution_block, total %d bytes", bh->block_total_length);
1553 * Start out with a buffer big enough for an IPv6 address and one
1554 * 64-byte name; we'll make the buffer bigger if necessary.
1556 buffer_init(&nrb_rec, INITIAL_NRB_REC_SIZE);
1557 while (block_read < to_read) {
1559 * There must be at least one record's worth of data
1560 * here.
1562 if ((size_t)(to_read - block_read) < sizeof nrb) {
1563 buffer_free(&nrb_rec);
1564 *err = WTAP_ERR_BAD_FILE;
1565 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record header size %u",
1566 to_read - block_read,
1567 (guint)sizeof nrb);
1568 return -1;
1570 bytes_read = file_read(&nrb, sizeof nrb, fh);
1571 if (bytes_read != sizeof nrb) {
1572 buffer_free(&nrb_rec);
1573 pcapng_debug0("pcapng_read_name_resolution_block: failed to read record header");
1574 *err = file_error(fh, err_info);
1575 return 0;
1577 block_read += bytes_read;
1579 if (pn->byte_swapped) {
1580 nrb.record_type = BSWAP16(nrb.record_type);
1581 nrb.record_len = BSWAP16(nrb.record_len);
1584 if (to_read - block_read < nrb.record_len + PADDING4(nrb.record_len)) {
1585 buffer_free(&nrb_rec);
1586 *err = WTAP_ERR_BAD_FILE;
1587 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: %d bytes left in the block < NRB record length + padding %u",
1588 to_read - block_read,
1589 nrb.record_len + PADDING4(nrb.record_len));
1590 return -1;
1592 switch (nrb.record_type) {
1593 case NRES_ENDOFRECORD:
1594 /* There shouldn't be any more data */
1595 to_read = 0;
1596 break;
1597 case NRES_IP4RECORD:
1599 * The smallest possible record must have
1600 * a 4-byte IPv4 address, hence a minimum
1601 * of 4 bytes.
1603 * (The pcap-NG spec really indicates
1604 * that it must be at least 5 bytes,
1605 * as there must be at least one name,
1606 * and it really must be at least 6
1607 * bytes, as the name mustn't be null,
1608 * but there's no need to fail if there
1609 * aren't any names at all, and we
1610 * should report a null name as such.)
1612 if (nrb.record_len < 4) {
1613 buffer_free(&nrb_rec);
1614 *err = WTAP_ERR_BAD_FILE;
1615 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv4 record %u < minimum length 4",
1616 nrb.record_len);
1617 return -1;
1619 buffer_assure_space(&nrb_rec, nrb.record_len);
1620 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1621 nrb.record_len, fh);
1622 if (bytes_read != nrb.record_len) {
1623 buffer_free(&nrb_rec);
1624 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv4 record data");
1625 *err = file_error(fh, err_info);
1626 return 0;
1628 block_read += bytes_read;
1630 if (pn->add_new_ipv4) {
1632 * Scan through all the names in
1633 * the record and add them.
1635 memcpy(&v4_addr,
1636 buffer_start_ptr(&nrb_rec), 4);
1637 if (pn->byte_swapped)
1638 v4_addr = BSWAP32(v4_addr);
1639 for (namep = (char *)buffer_start_ptr(&nrb_rec) + 4, record_len = nrb.record_len - 4;
1640 record_len != 0;
1641 namep += namelen, record_len -= namelen) {
1643 * Scan forward for a null
1644 * byte.
1646 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1647 if (namelen == -1) {
1648 buffer_free(&nrb_rec);
1649 return -1; /* fail */
1651 pn->add_new_ipv4(v4_addr, namep);
1655 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1656 if (file_offset64 <= 0) {
1657 buffer_free(&nrb_rec);
1658 if (*err != 0)
1659 return -1;
1660 return 0;
1662 block_read += PADDING4(nrb.record_len);
1663 break;
1664 case NRES_IP6RECORD:
1666 * The smallest possible record must have
1667 * a 16-byte IPv6 address, hence a minimum
1668 * of 16 bytes.
1670 * (The pcap-NG spec really indicates
1671 * that it must be at least 17 bytes,
1672 * as there must be at least one name,
1673 * and it really must be at least 18
1674 * bytes, as the name mustn't be null,
1675 * but there's no need to fail if there
1676 * aren't any names at all, and we
1677 * should report a null name as such.)
1679 if (nrb.record_len < 16) {
1680 buffer_free(&nrb_rec);
1681 *err = WTAP_ERR_BAD_FILE;
1682 *err_info = g_strdup_printf("pcapng_read_name_resolution_block: NRB record length for IPv6 record %u < minimum length 16",
1683 nrb.record_len);
1684 return -1;
1686 if (to_read < nrb.record_len) {
1687 buffer_free(&nrb_rec);
1688 pcapng_debug0("pcapng_read_name_resolution_block: insufficient data for IPv6 record");
1689 return 0;
1691 buffer_assure_space(&nrb_rec, nrb.record_len);
1692 bytes_read = file_read(buffer_start_ptr(&nrb_rec),
1693 nrb.record_len, fh);
1694 if (bytes_read != nrb.record_len) {
1695 buffer_free(&nrb_rec);
1696 pcapng_debug0("pcapng_read_name_resolution_block: failed to read IPv6 record data");
1697 *err = file_error(fh, err_info);
1698 return 0;
1700 block_read += bytes_read;
1702 if (pn->add_new_ipv6) {
1703 for (namep = (char *)buffer_start_ptr(&nrb_rec) + 16, record_len = nrb.record_len - 16;
1704 record_len != 0;
1705 namep += namelen, record_len -= namelen) {
1707 * Scan forward for a null
1708 * byte.
1710 namelen = name_resolution_block_find_name_end(namep, record_len, err, err_info);
1711 if (namelen == -1) {
1712 buffer_free(&nrb_rec);
1713 return -1; /* fail */
1715 pn->add_new_ipv6(buffer_start_ptr(&nrb_rec),
1716 namep);
1720 file_offset64 = file_seek(fh, PADDING4(nrb.record_len), SEEK_CUR, err);
1721 if (file_offset64 <= 0) {
1722 buffer_free(&nrb_rec);
1723 if (*err != 0)
1724 return -1;
1725 return 0;
1727 block_read += PADDING4(nrb.record_len);
1728 break;
1729 default:
1730 pcapng_debug1("pcapng_read_name_resolution_block: unknown record type 0x%x", nrb.record_type);
1731 file_offset64 = file_seek(fh, nrb.record_len + PADDING4(nrb.record_len), SEEK_CUR, err);
1732 if (file_offset64 <= 0) {
1733 buffer_free(&nrb_rec);
1734 if (*err != 0)
1735 return -1;
1736 return 0;
1738 block_read += nrb.record_len + PADDING4(nrb.record_len);
1739 break;
1743 buffer_free(&nrb_rec);
1744 return block_read;
1747 static int
1748 pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wtapng_block_t *wblock,int *err, gchar **err_info)
1750 int bytes_read;
1751 guint block_read;
1752 guint to_read, opt_cont_buf_len;
1753 pcapng_interface_statistics_block_t isb;
1754 pcapng_option_header_t oh;
1755 char *option_content = NULL; /* Allocate as large as the options block */
1758 * Is this block long enough to be an ISB?
1760 if (bh->block_total_length < MIN_ISB_SIZE) {
1762 * No.
1764 *err = WTAP_ERR_BAD_FILE;
1765 *err_info = g_strdup_printf("pcapng_read_interface_statistics_block: total block length %u is too small (< %u)",
1766 bh->block_total_length, MIN_ISB_SIZE);
1767 return -1;
1770 /* Don't try to allocate memory for a huge number of options, as
1771 that might fail and, even if it succeeds, it might not leave
1772 any address space or memory+backing store for anything else.
1774 We do that by imposing a maximum block size of MAX_BLOCK_SIZE.
1775 We check for this *after* checking the SHB for its byte
1776 order magic number, so that non-pcap-ng files are less
1777 likely to be treated as bad pcap-ng files. */
1778 if (bh->block_total_length > MAX_BLOCK_SIZE) {
1779 *err = WTAP_ERR_BAD_FILE;
1780 *err_info = g_strdup_printf("pcapng: total block length %u is too large (> %u)",
1781 bh->block_total_length, MAX_BLOCK_SIZE);
1782 return -1;
1785 /* "Interface Statistics Block" read fixed part */
1786 errno = WTAP_ERR_CANT_READ;
1787 bytes_read = file_read(&isb, sizeof isb, fh);
1788 if (bytes_read != sizeof isb) {
1789 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read packet data");
1790 *err = file_error(fh, err_info);
1791 return 0;
1793 block_read = bytes_read;
1795 if (pn->byte_swapped) {
1796 wblock->data.if_stats.interface_id = BSWAP32(isb.interface_id);
1797 wblock->data.if_stats.ts_high = BSWAP32(isb.timestamp_high);
1798 wblock->data.if_stats.ts_low = BSWAP32(isb.timestamp_low);
1799 } else {
1800 wblock->data.if_stats.interface_id = isb.interface_id;
1801 wblock->data.if_stats.ts_high = isb.timestamp_high;
1802 wblock->data.if_stats.ts_low = isb.timestamp_low;
1804 pcapng_debug1("pcapng_read_interface_statistics_block: interface_id %u", wblock->data.if_stats.interface_id);
1806 /* Option defaults */
1807 wblock->data.if_stats.opt_comment = NULL;
1808 wblock->data.if_stats.isb_ifrecv = -1;
1809 wblock->data.if_stats.isb_ifdrop = -1;
1810 wblock->data.if_stats.isb_filteraccept = -1;
1811 wblock->data.if_stats.isb_osdrop = -1;
1812 wblock->data.if_stats.isb_usrdeliv = -1;
1814 /* Options */
1815 errno = WTAP_ERR_CANT_READ;
1816 to_read = bh->block_total_length -
1817 (MIN_BLOCK_SIZE + block_read); /* fixed and variable part, including padding */
1819 /* Allocate enough memory to hold all options */
1820 opt_cont_buf_len = to_read;
1821 option_content = (char *)g_try_malloc(opt_cont_buf_len);
1822 if (opt_cont_buf_len != 0 && option_content == NULL) {
1823 *err = ENOMEM; /* we assume we're out of memory */
1824 return -1;
1827 while (to_read != 0) {
1828 /* read option */
1829 bytes_read = pcapng_read_option(fh, pn, &oh, option_content, opt_cont_buf_len, to_read, err, err_info);
1830 if (bytes_read <= 0) {
1831 pcapng_debug0("pcapng_read_interface_statistics_block: failed to read option");
1832 return bytes_read;
1834 block_read += bytes_read;
1835 to_read -= bytes_read;
1837 /* handle option content */
1838 switch (oh.option_code) {
1839 case(0): /* opt_endofopt */
1840 if (to_read != 0) {
1841 pcapng_debug1("pcapng_read_interface_statistics_block: %u bytes after opt_endofopt", to_read);
1843 /* padding should be ok here, just get out of this */
1844 to_read = 0;
1845 break;
1846 case(1): /* opt_comment */
1847 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
1848 wblock->data.if_stats.opt_comment = g_strndup(option_content, oh.option_length);
1849 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment %s", wblock->data.if_stats.opt_comment);
1850 } else {
1851 pcapng_debug1("pcapng_read_interface_statistics_block: opt_comment length %u seems strange", oh.option_length);
1853 break;
1854 case(2): /* isb_starttime */
1855 if (oh.option_length == 8) {
1856 guint32 high, low;
1858 /* Don't cast a char[] into a guint32--the
1859 * char[] may not be aligned correctly.
1861 memcpy(&high, option_content, sizeof(guint32));
1862 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1863 if (pn->byte_swapped) {
1864 high = BSWAP32(high);
1865 low = BSWAP32(low);
1867 wblock->data.if_stats.isb_starttime = (guint64)high;
1868 wblock->data.if_stats.isb_starttime <<= 32;
1869 wblock->data.if_stats.isb_starttime += (guint64)low;
1870 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_starttime);
1871 } else {
1872 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1874 break;
1875 case(3): /* isb_endtime */
1876 if (oh.option_length == 8) {
1877 guint32 high, low;
1879 /* Don't cast a char[] into a guint32--the
1880 * char[] may not be aligned correctly.
1882 memcpy(&high, option_content, sizeof(guint32));
1883 memcpy(&low, option_content + sizeof(guint32), sizeof(guint32));
1884 if (pn->byte_swapped) {
1885 high = BSWAP32(high);
1886 low = BSWAP32(low);
1888 wblock->data.if_stats.isb_endtime = (guint64)high;
1889 wblock->data.if_stats.isb_endtime <<= 32;
1890 wblock->data.if_stats.isb_endtime += (guint64)low;
1891 pcapng_debug1("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_endtime);
1892 } else {
1893 pcapng_debug1("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
1895 break;
1896 case(4): /* isb_ifrecv */
1897 if (oh.option_length == 8) {
1898 /* Don't cast a char[] into a guint32--the
1899 * char[] may not be aligned correctly.
1901 memcpy(&wblock->data.if_stats.isb_ifrecv, option_content, sizeof(guint64));
1902 if (pn->byte_swapped)
1903 wblock->data.if_stats.isb_ifrecv = BSWAP64(wblock->data.if_stats.isb_ifrecv);
1904 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifrecv);
1905 } else {
1906 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
1908 break;
1909 case(5): /* isb_ifdrop */
1910 if (oh.option_length == 8) {
1911 /* Don't cast a char[] into a guint32--the
1912 * char[] may not be aligned correctly.
1914 memcpy(&wblock->data.if_stats.isb_ifdrop, option_content, sizeof(guint64));
1915 if (pn->byte_swapped)
1916 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_ifdrop);
1917 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_ifdrop);
1918 } else {
1919 pcapng_debug1("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
1921 break;
1922 case(6): /* isb_filteraccept 6 */
1923 if (oh.option_length == 8) {
1924 /* Don't cast a char[] into a guint32--the
1925 * char[] may not be aligned correctly.
1927 memcpy(&wblock->data.if_stats.isb_filteraccept, option_content, sizeof(guint64));
1928 if (pn->byte_swapped)
1929 wblock->data.if_stats.isb_ifdrop = BSWAP64(wblock->data.if_stats.isb_filteraccept);
1930 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_filteraccept);
1931 } else {
1932 pcapng_debug1("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
1934 break;
1935 case(7): /* isb_osdrop 7 */
1936 if (oh.option_length == 8) {
1937 /* Don't cast a char[] into a guint32--the
1938 * char[] may not be aligned correctly.
1940 memcpy(&wblock->data.if_stats.isb_osdrop, option_content, sizeof(guint64));
1941 if (pn->byte_swapped)
1942 wblock->data.if_stats.isb_osdrop = BSWAP64(wblock->data.if_stats.isb_osdrop);
1943 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_osdrop);
1944 } else {
1945 pcapng_debug1("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
1947 break;
1948 case(8): /* isb_usrdeliv 8 */
1949 if (oh.option_length == 8) {
1950 /* Don't cast a char[] into a guint32--the
1951 * char[] may not be aligned correctly.
1953 memcpy(&wblock->data.if_stats.isb_usrdeliv, option_content, sizeof(guint64));
1954 if (pn->byte_swapped)
1955 wblock->data.if_stats.isb_usrdeliv = BSWAP64(wblock->data.if_stats.isb_osdrop);
1956 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", wblock->data.if_stats.isb_usrdeliv);
1957 } else {
1958 pcapng_debug1("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
1960 break;
1961 default:
1962 pcapng_debug2("pcapng_read_interface_statistics_block: unknown option %u - ignoring %u bytes",
1963 oh.option_code, oh.option_length);
1967 g_free(option_content);
1969 return block_read;
1973 static int
1974 pcapng_read_unknown_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn _U_, wtapng_block_t *wblock _U_, int *err, gchar **err_info)
1976 int block_read;
1977 guint64 file_offset64;
1978 guint32 block_total_length;
1980 if (bh->block_total_length < MIN_BLOCK_SIZE) {
1981 *err = WTAP_ERR_BAD_FILE;
1982 *err_info = g_strdup_printf("pcapng_read_unknown_block: total block length %u of an unknown block type is less than the minimum block size %u",
1983 bh->block_total_length, MIN_BLOCK_SIZE);
1984 return -1;
1987 /* add padding bytes to "block total length" */
1988 /* (the "block total length" of some example files don't contain any padding bytes!) */
1989 if (bh->block_total_length % 4) {
1990 block_total_length = bh->block_total_length + 4 - (bh->block_total_length % 4);
1991 } else {
1992 block_total_length = bh->block_total_length;
1995 block_read = block_total_length - MIN_BLOCK_SIZE;
1997 /* jump over this unknown block */
1998 file_offset64 = file_seek(fh, block_read, SEEK_CUR, err);
1999 if (file_offset64 <= 0) {
2000 if (*err != 0)
2001 return -1;
2002 return 0;
2005 return block_read;
2009 static int
2010 pcapng_read_block(FILE_T fh, gboolean first_block, pcapng_t *pn, wtapng_block_t *wblock, int *err, gchar **err_info)
2012 int block_read;
2013 int bytes_read;
2014 pcapng_block_header_t bh;
2015 guint32 block_total_length;
2018 /* Try to read the (next) block header */
2019 errno = WTAP_ERR_CANT_READ;
2020 bytes_read = file_read(&bh, sizeof bh, fh);
2021 if (bytes_read != sizeof bh) {
2022 *err = file_error(fh, err_info);
2023 pcapng_debug3("pcapng_read_block: file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2024 if (*err != 0)
2025 return -1;
2026 return 0;
2029 block_read = bytes_read;
2030 if (pn->byte_swapped) {
2031 bh.block_type = BSWAP32(bh.block_type);
2032 bh.block_total_length = BSWAP32(bh.block_total_length);
2035 wblock->type = bh.block_type;
2037 pcapng_debug1("pcapng_read_block: block_type 0x%x", bh.block_type);
2039 if (first_block) {
2041 * This is being read in by pcapng_open(), so this block
2042 * must be an SHB. If it's not, this is not a pcap-ng
2043 * file.
2045 * XXX - check for various forms of Windows <-> UN*X
2046 * mangling, and suggest that the file might be a
2047 * pcap-ng file that was damaged in transit?
2049 if (bh.block_type != BLOCK_TYPE_SHB)
2050 return 0; /* not a pcap-ng file */
2053 switch (bh.block_type) {
2054 case(BLOCK_TYPE_SHB):
2055 bytes_read = pcapng_read_section_header_block(fh, first_block, &bh, pn, wblock, err, err_info);
2056 break;
2057 case(BLOCK_TYPE_IDB):
2058 bytes_read = pcapng_read_if_descr_block(fh, &bh, pn, wblock, err, err_info);
2059 break;
2060 case(BLOCK_TYPE_PB):
2061 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, FALSE);
2062 break;
2063 case(BLOCK_TYPE_SPB):
2064 bytes_read = pcapng_read_simple_packet_block(fh, &bh, pn, wblock, err, err_info);
2065 break;
2066 case(BLOCK_TYPE_EPB):
2067 bytes_read = pcapng_read_packet_block(fh, &bh, pn, wblock, err, err_info, TRUE);
2068 break;
2069 case(BLOCK_TYPE_NRB):
2070 bytes_read = pcapng_read_name_resolution_block(fh, &bh, pn, wblock, err, err_info);
2071 break;
2072 case(BLOCK_TYPE_ISB):
2073 bytes_read = pcapng_read_interface_statistics_block(fh, &bh, pn, wblock, err, err_info);
2074 break;
2075 default:
2076 pcapng_debug2("pcapng_read_block: Unknown block_type: 0x%x (block ignored), block total length %d", bh.block_type, bh.block_total_length);
2077 bytes_read = pcapng_read_unknown_block(fh, &bh, pn, wblock, err, err_info);
2080 if (bytes_read <= 0) {
2081 return bytes_read;
2083 block_read += bytes_read;
2085 /* sanity check: first and second block lengths must match */
2086 errno = WTAP_ERR_CANT_READ;
2087 bytes_read = file_read(&block_total_length, sizeof block_total_length, fh);
2088 if (bytes_read != sizeof block_total_length) {
2089 pcapng_debug0("pcapng_read_block: couldn't read second block length");
2090 *err = file_error(fh, err_info);
2091 if (*err == 0)
2092 *err = WTAP_ERR_SHORT_READ;
2093 return -1;
2095 block_read += bytes_read;
2097 if (pn->byte_swapped)
2098 block_total_length = BSWAP32(block_total_length);
2100 if (!(block_total_length == bh.block_total_length)) {
2101 *err = WTAP_ERR_BAD_FILE;
2102 *err_info = g_strdup_printf("pcapng_read_block: total block lengths (first %u and second %u) don't match",
2103 bh.block_total_length, block_total_length);
2104 return -1;
2107 return block_read;
2110 /* Process an IDB that we've just read. */
2111 static void
2112 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
2114 wtapng_if_descr_t int_data;
2115 interface_data_t interface_data;
2117 int_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2118 int_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2119 int_data.link_type = wblock->data.if_descr.link_type;
2120 int_data.snap_len = wblock->data.if_descr.snap_len;
2121 /* Options */
2122 int_data.opt_comment = wblock->data.if_descr.opt_comment;
2123 int_data.if_name = wblock->data.if_descr.if_name;
2124 int_data.if_description = wblock->data.if_descr.if_description;
2125 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
2126 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
2127 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
2128 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
2129 int_data.if_speed = wblock->data.if_descr.if_speed;
2130 int_data.if_tsresol = wblock->data.if_descr.if_tsresol;
2131 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
2132 int_data.if_filter_str = wblock->data.if_descr.if_filter_str;
2133 int_data.bpf_filter_len = wblock->data.if_descr.bpf_filter_len;
2134 int_data.if_filter_bpf_bytes = wblock->data.if_descr.if_filter_bpf_bytes;
2135 int_data.if_os = wblock->data.if_descr.if_os;
2136 int_data.if_fcslen = wblock->data.if_descr.if_fcslen;
2137 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
2138 /* Interface statistics */
2139 int_data.num_stat_entries = 0;
2140 int_data.interface_statistics = NULL;
2142 g_array_append_val(wth->interface_data, int_data);
2143 wth->number_of_interfaces++;
2145 interface_data.wtap_encap = wblock->data.if_descr.wtap_encap;
2146 interface_data.snap_len = wblock->data.if_descr.snap_len;
2147 interface_data.time_units_per_second = wblock->data.if_descr.time_units_per_second;
2149 g_array_append_val(pcapng->interface_data, interface_data);
2150 pcapng->number_of_interfaces++;
2153 /* classic wtap: open capture file */
2155 pcapng_open(wtap *wth, int *err, gchar **err_info)
2157 int bytes_read;
2158 pcapng_t pn;
2159 wtapng_block_t wblock;
2160 pcapng_t *pcapng;
2161 pcapng_block_header_t bh;
2162 gint64 saved_offset;
2164 pn.shb_read = FALSE;
2165 /* we don't know the byte swapping of the file yet */
2166 pn.byte_swapped = FALSE;
2167 pn.if_fcslen = -1;
2168 pn.version_major = -1;
2169 pn.version_minor = -1;
2170 pn.interface_data = g_array_new(FALSE, FALSE, sizeof(interface_data_t));
2171 pn.number_of_interfaces = 0;
2174 /* we don't expect any packet blocks yet */
2175 wblock.frame_buffer = NULL;
2176 wblock.packet_header = NULL;
2177 wblock.file_encap = &wth->file_encap;
2179 pcapng_debug0("pcapng_open: opening file");
2180 /* read first block */
2181 bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
2182 if (bytes_read <= 0) {
2183 pcapng_debug0("pcapng_open: couldn't read first SHB");
2184 *err = file_error(wth->fh, err_info);
2185 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
2186 return -1;
2187 return 0;
2190 /* first block must be a "Section Header Block" */
2191 if (wblock.type != BLOCK_TYPE_SHB) {
2193 * XXX - check for damage from transferring a file
2194 * between Windows and UN*X as text rather than
2195 * binary data?
2197 pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
2198 return 0;
2200 pn.shb_read = TRUE;
2203 * At this point, we've decided this is a pcap-NG file, not
2204 * some other type of file, so we can't return 0, as that
2205 * means "this isn't a pcap-NG file, try some other file
2206 * type".
2208 wth->shb_hdr.opt_comment = wblock.data.section.opt_comment;
2209 wth->shb_hdr.shb_hardware = wblock.data.section.shb_hardware;
2210 wth->shb_hdr.shb_os = wblock.data.section.shb_os;
2211 wth->shb_hdr.shb_user_appl = wblock.data.section.shb_user_appl;
2213 wth->file_encap = WTAP_ENCAP_UNKNOWN;
2214 wth->snapshot_length = 0;
2215 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
2216 pcapng = (pcapng_t *)g_malloc(sizeof(pcapng_t));
2217 wth->priv = (void *)pcapng;
2218 *pcapng = pn;
2220 wth->subtype_read = pcapng_read;
2221 wth->subtype_seek_read = pcapng_seek_read;
2222 wth->subtype_close = pcapng_close;
2223 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
2225 /* Read IDBs */
2226 wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
2227 wth->number_of_interfaces = 0;
2229 /* Loop over all IDB:s that appear before any packets */
2230 while (1) {
2231 /* peek at next block */
2232 /* Try to read the (next) block header */
2233 saved_offset = file_tell(wth->fh);
2234 errno = WTAP_ERR_CANT_READ;
2235 bytes_read = file_read(&bh, sizeof bh, wth->fh);
2236 if (bytes_read == 0) {
2237 pcapng_debug0("No more IDBs available...");
2238 break;
2240 if (bytes_read != sizeof bh) {
2241 *err = file_error(wth->fh, err_info);
2242 pcapng_debug3("pcapng_open: Check for more IDB:s, file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
2243 if (*err == 0)
2244 *err = WTAP_ERR_SHORT_READ;
2245 return -1;
2248 /* go back to where we were */
2249 file_seek(wth->fh, saved_offset, SEEK_SET, err);
2251 if (pn.byte_swapped) {
2252 bh.block_type = BSWAP32(bh.block_type);
2255 pcapng_debug1("pcapng_open: Check for more IDB:s block_type 0x%x", bh.block_type);
2257 if (bh.block_type != BLOCK_TYPE_IDB) {
2258 break; /* No more IDB:s */
2260 bytes_read = pcapng_read_block(wth->fh, FALSE, &pn, &wblock, err, err_info);
2261 if (bytes_read == 0) {
2262 pcapng_debug0("No more IDBs available...");
2263 break;
2265 if (bytes_read <= 0) {
2266 pcapng_debug0("pcapng_open: couldn't read IDB");
2267 *err = file_error(wth->fh, err_info);
2268 if (*err == 0)
2269 *err = WTAP_ERR_SHORT_READ;
2270 return -1;
2272 pcapng_process_idb(wth, pcapng, &wblock);
2273 pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, *wblock.file_encap);
2275 return 1;
2279 /* classic wtap: read packet */
2280 static gboolean
2281 pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
2283 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2284 int bytes_read;
2285 wtapng_block_t wblock;
2286 wtapng_if_descr_t *wtapng_if_descr;
2287 wtapng_if_stats_t if_stats;
2289 *data_offset = file_tell(wth->fh);
2290 pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER "d", *data_offset);
2292 wblock.frame_buffer = wth->frame_buffer;
2293 wblock.packet_header = &wth->phdr;
2294 wblock.file_encap = &wth->file_encap;
2296 pcapng->add_new_ipv4 = wth->add_new_ipv4;
2297 pcapng->add_new_ipv6 = wth->add_new_ipv6;
2299 /* read next block */
2300 while (1) {
2301 bytes_read = pcapng_read_block(wth->fh, FALSE, pcapng, &wblock, err, err_info);
2302 if (bytes_read <= 0) {
2303 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
2304 pcapng_debug0("pcapng_read: couldn't read packet block");
2305 return FALSE;
2308 switch (wblock.type) {
2310 case(BLOCK_TYPE_SHB):
2311 /* We don't currently support multi-section files. */
2312 wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
2313 *err = WTAP_ERR_UNSUPPORTED;
2314 *err_info = g_strdup_printf("pcapng: multi-section files not currently supported.");
2315 return FALSE;
2317 case(BLOCK_TYPE_PB):
2318 case(BLOCK_TYPE_SPB):
2319 case(BLOCK_TYPE_EPB):
2320 /* packet block - we've found a packet */
2321 goto got_packet;
2323 case(BLOCK_TYPE_IDB):
2324 /* A new interface */
2325 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_IDB");
2326 *data_offset += bytes_read;
2327 pcapng_process_idb(wth, pcapng, &wblock);
2328 break;
2330 case(BLOCK_TYPE_NRB):
2331 /* More name resolution entries */
2332 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_NRB");
2333 *data_offset += bytes_read;
2334 break;
2336 case(BLOCK_TYPE_ISB):
2337 /* Another interface statistics report */
2338 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB");
2339 *data_offset += bytes_read;
2340 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2341 if (wth->number_of_interfaces < wblock.data.if_stats.interface_id) {
2342 pcapng_debug1("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u > number_of_interfaces", wblock.data.if_stats.interface_id);
2343 } else {
2344 /* Get the interface description */
2345 wtapng_if_descr = &g_array_index(wth->interface_data, wtapng_if_descr_t, wblock.data.if_stats.interface_id);
2346 if (wtapng_if_descr->num_stat_entries == 0) {
2347 /* First ISB found, no previous entry */
2348 pcapng_debug0("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
2349 wtapng_if_descr->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtapng_if_stats_t));
2352 if_stats.interface_id = wblock.data.if_stats.interface_id;
2353 if_stats.ts_high = wblock.data.if_stats.ts_high;
2354 if_stats.ts_low = wblock.data.if_stats.ts_low;
2355 /* options */
2356 if_stats.opt_comment = wblock.data.if_stats.opt_comment; /* NULL if not available */
2357 if_stats.isb_starttime = wblock.data.if_stats.isb_starttime;
2358 if_stats.isb_endtime = wblock.data.if_stats.isb_endtime;
2359 if_stats.isb_ifrecv = wblock.data.if_stats.isb_ifrecv;
2360 if_stats.isb_ifdrop = wblock.data.if_stats.isb_ifdrop;
2361 if_stats.isb_filteraccept = wblock.data.if_stats.isb_filteraccept;
2362 if_stats.isb_osdrop = wblock.data.if_stats.isb_osdrop;
2363 if_stats.isb_usrdeliv = wblock.data.if_stats.isb_usrdeliv;
2365 g_array_append_val(wtapng_if_descr->interface_statistics, if_stats);
2366 wtapng_if_descr->num_stat_entries++;
2368 break;
2370 default:
2371 /* XXX - improve handling of "unknown" blocks */
2372 pcapng_debug1("pcapng_read: Unknown block type 0x%08x", wblock.type);
2373 *data_offset += bytes_read;
2374 pcapng_debug1("pcapng_read: *data_offset is updated to %" G_GINT64_MODIFIER "d", *data_offset);
2375 break;
2379 got_packet:
2381 /*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
2382 pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
2384 return TRUE;
2388 /* classic wtap: seek to file position and read packet */
2389 static gboolean
2390 pcapng_seek_read(wtap *wth, gint64 seek_off,
2391 struct wtap_pkthdr *phdr, Buffer *buf, int length _U_,
2392 int *err, gchar **err_info)
2394 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2395 guint64 bytes_read64;
2396 int bytes_read;
2397 wtapng_block_t wblock;
2400 /* seek to the right file position */
2401 bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
2402 if (bytes_read64 <= 0) {
2403 return FALSE; /* Seek error */
2405 pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
2407 wblock.frame_buffer = buf;
2408 wblock.packet_header = phdr;
2409 wblock.file_encap = &wth->file_encap;
2411 /* read the block */
2412 bytes_read = pcapng_read_block(wth->random_fh, FALSE, pcapng, &wblock, err, err_info);
2413 if (bytes_read <= 0) {
2414 pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
2415 *err, errno, bytes_read);
2416 return FALSE;
2419 /* block must be a "Packet Block", an "Enhanced Packet Block",
2420 or a "Simple Packet Block" */
2421 if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
2422 wblock.type != BLOCK_TYPE_SPB) {
2423 pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
2424 return FALSE;
2427 return TRUE;
2431 /* classic wtap: close capture file */
2432 static void
2433 pcapng_close(wtap *wth)
2435 pcapng_t *pcapng = (pcapng_t *)wth->priv;
2437 pcapng_debug0("pcapng_close: closing file");
2438 if (pcapng->interface_data != NULL) {
2439 g_array_free(pcapng->interface_data, TRUE);
2445 typedef struct {
2446 GArray *interface_data;
2447 guint number_of_interfaces;
2448 } pcapng_dump_t;
2450 static gboolean
2451 pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
2453 pcapng_block_header_t bh;
2454 pcapng_section_header_block_t shb;
2455 const guint32 zero_pad = 0;
2456 gboolean have_options = FALSE;
2457 struct option option_hdr; /* guint16 type, guint16 value_length; */
2458 guint32 options_total_length = 0;
2459 guint32 comment_len = 0, shb_hardware_len = 0, shb_os_len = 0, shb_user_appl_len = 0;
2460 guint32 comment_pad_len = 0, shb_hardware_pad_len = 0, shb_os_pad_len = 0, shb_user_appl_pad_len = 0;
2462 if (wdh->shb_hdr) {
2463 pcapng_debug0("pcapng_write_section_header_block: Have shb_hdr");
2464 /* Check if we should write comment option */
2465 if (wdh->shb_hdr->opt_comment) {
2466 have_options = TRUE;
2467 comment_len = (guint32)strlen(wdh->shb_hdr->opt_comment) & 0xffff;
2468 if ((comment_len % 4)) {
2469 comment_pad_len = 4 - (comment_len % 4);
2470 } else {
2471 comment_pad_len = 0;
2473 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2476 /* Check if we should write shb_hardware option */
2477 if (wdh->shb_hdr->shb_hardware) {
2478 have_options = TRUE;
2479 shb_hardware_len = (guint32)strlen(wdh->shb_hdr->shb_hardware) & 0xffff;
2480 if ((shb_hardware_len % 4)) {
2481 shb_hardware_pad_len = 4 - (shb_hardware_len % 4);
2482 } else {
2483 shb_hardware_pad_len = 0;
2485 options_total_length = options_total_length + shb_hardware_len + shb_hardware_pad_len + 4 /* options tag */ ;
2488 /* Check if we should write shb_os option */
2489 if (wdh->shb_hdr->shb_os) {
2490 have_options = TRUE;
2491 shb_os_len = (guint32)strlen(wdh->shb_hdr->shb_os) & 0xffff;
2492 if ((shb_os_len % 4)) {
2493 shb_os_pad_len = 4 - (shb_os_len % 4);
2494 } else {
2495 shb_os_pad_len = 0;
2497 options_total_length = options_total_length + shb_os_len + shb_os_pad_len + 4 /* options tag */ ;
2500 /* Check if we should write shb_user_appl option */
2501 if (wdh->shb_hdr->shb_user_appl) {
2502 have_options = TRUE;
2503 shb_user_appl_len = (guint32)strlen(wdh->shb_hdr->shb_user_appl) & 0xffff;
2504 if ((shb_user_appl_len % 4)) {
2505 shb_user_appl_pad_len = 4 - (shb_user_appl_len % 4);
2506 } else {
2507 shb_user_appl_pad_len = 0;
2509 options_total_length = options_total_length + shb_user_appl_len + shb_user_appl_pad_len + 4 /* options tag */ ;
2511 if (have_options) {
2512 /* End-of-options tag */
2513 options_total_length += 4;
2517 /* write block header */
2518 bh.block_type = BLOCK_TYPE_SHB;
2519 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(shb) + options_total_length + 4);
2520 pcapng_debug2("pcapng_write_section_header_block: Total len %u, Options total len %u",bh.block_total_length, options_total_length);
2522 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2523 return FALSE;
2524 wdh->bytes_dumped += sizeof bh;
2526 /* write block fixed content */
2527 /* XXX - get these values from wblock? */
2528 shb.magic = 0x1A2B3C4D;
2529 shb.version_major = 1;
2530 shb.version_minor = 0;
2531 shb.section_length = -1;
2533 if (!wtap_dump_file_write(wdh, &shb, sizeof shb, err))
2534 return FALSE;
2535 wdh->bytes_dumped += sizeof shb;
2537 /* XXX - write (optional) block options
2538 * opt_comment 1
2539 * shb_hardware 2
2540 * shb_os 3
2541 * shb_user_appl 4
2544 if (comment_len) {
2545 option_hdr.type = OPT_COMMENT;
2546 option_hdr.value_length = comment_len;
2547 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2548 return FALSE;
2549 wdh->bytes_dumped += 4;
2551 /* Write the comments string */
2552 pcapng_debug3("pcapng_write_section_header_block, comment:'%s' comment_len %u comment_pad_len %u" , wdh->shb_hdr->opt_comment, comment_len, comment_pad_len);
2553 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->opt_comment, comment_len, err))
2554 return FALSE;
2555 wdh->bytes_dumped += comment_len;
2557 /* write padding (if any) */
2558 if (comment_pad_len != 0) {
2559 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2560 return FALSE;
2561 wdh->bytes_dumped += comment_pad_len;
2565 if (shb_hardware_len) {
2566 option_hdr.type = OPT_SHB_HARDWARE;
2567 option_hdr.value_length = shb_hardware_len;
2568 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2569 return FALSE;
2570 wdh->bytes_dumped += 4;
2572 /* Write the string */
2573 pcapng_debug3("pcapng_write_section_header_block, shb_hardware:'%s' shb_hardware_len %u shb_hardware_pad_len %u" , wdh->shb_hdr->shb_hardware, shb_hardware_len, shb_hardware_pad_len);
2574 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_hardware, shb_hardware_len, err))
2575 return FALSE;
2576 wdh->bytes_dumped += shb_hardware_len;
2578 /* write padding (if any) */
2579 if (shb_hardware_pad_len != 0) {
2580 if (!wtap_dump_file_write(wdh, &zero_pad, shb_hardware_pad_len, err))
2581 return FALSE;
2582 wdh->bytes_dumped += shb_hardware_pad_len;
2586 if (shb_os_len) {
2587 option_hdr.type = OPT_SHB_OS;
2588 option_hdr.value_length = shb_os_len;
2589 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2590 return FALSE;
2591 wdh->bytes_dumped += 4;
2593 /* Write the string */
2594 pcapng_debug3("pcapng_write_section_header_block, shb_os:'%s' shb_os_len %u shb_os_pad_len %u" , wdh->shb_hdr->shb_os, shb_os_len, shb_os_pad_len);
2595 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_os, shb_os_len, err))
2596 return FALSE;
2597 wdh->bytes_dumped += shb_os_len;
2599 /* write padding (if any) */
2600 if (shb_os_pad_len != 0) {
2601 if (!wtap_dump_file_write(wdh, &zero_pad, shb_os_pad_len, err))
2602 return FALSE;
2603 wdh->bytes_dumped += shb_os_pad_len;
2607 if (shb_user_appl_len) {
2608 option_hdr.type = OPT_SHB_USERAPPL;
2609 option_hdr.value_length = shb_user_appl_len;
2610 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2611 return FALSE;
2612 wdh->bytes_dumped += 4;
2614 /* Write the comments string */
2615 pcapng_debug3("pcapng_write_section_header_block, shb_user_appl:'%s' shb_user_appl_len %u shb_user_appl_pad_len %u" , wdh->shb_hdr->shb_user_appl, shb_user_appl_len, shb_user_appl_pad_len);
2616 if (!wtap_dump_file_write(wdh, wdh->shb_hdr->shb_user_appl, shb_user_appl_len, err))
2617 return FALSE;
2618 wdh->bytes_dumped += shb_user_appl_len;
2620 /* write padding (if any) */
2621 if (shb_user_appl_pad_len != 0) {
2622 if (!wtap_dump_file_write(wdh, &zero_pad, shb_user_appl_pad_len, err))
2623 return FALSE;
2624 wdh->bytes_dumped += shb_user_appl_pad_len;
2628 /* Write end of options if we have otions */
2629 if (have_options) {
2630 option_hdr.type = OPT_EOFOPT;
2631 option_hdr.value_length = 0;
2632 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
2633 return FALSE;
2634 wdh->bytes_dumped += 4;
2637 /* write block footer */
2638 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2639 sizeof bh.block_total_length, err))
2640 return FALSE;
2641 wdh->bytes_dumped += sizeof bh.block_total_length;
2643 return TRUE;
2646 #define IDB_OPT_IF_NAME 2
2647 #define IDB_OPT_IF_DESCR 3
2648 #define IDB_OPT_IF_SPEED 8
2649 #define IDB_OPT_IF_TSRESOL 9
2650 #define IDB_OPT_IF_FILTER 11
2651 #define IDB_OPT_IF_OS 12
2653 static gboolean
2654 pcapng_write_if_descr_block(wtap_dumper *wdh, wtapng_if_descr_t *int_data, int *err)
2656 pcapng_block_header_t bh;
2657 pcapng_interface_description_block_t idb;
2658 const guint32 zero_pad = 0;
2659 gboolean have_options = FALSE;
2660 struct option option_hdr; /* guint16 type, guint16 value_length; */
2661 guint32 options_total_length = 0;
2662 guint32 comment_len = 0, if_name_len = 0, if_description_len = 0 , if_os_len = 0, if_filter_str_len = 0;
2663 guint32 comment_pad_len = 0, if_name_pad_len = 0, if_description_pad_len = 0, if_os_pad_len = 0, if_filter_str_pad_len = 0;
2666 pcapng_debug3("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
2667 int_data->link_type,
2668 wtap_encap_string(wtap_pcap_encap_to_wtap_encap(int_data->link_type)),
2669 int_data->snap_len);
2671 if (int_data->link_type == (guint16)-1) {
2672 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
2673 return FALSE;
2676 /* Calculate options length */
2677 if (int_data->opt_comment) {
2678 have_options = TRUE;
2679 comment_len = (guint32)strlen(int_data->opt_comment) & 0xffff;
2680 if ((comment_len % 4)) {
2681 comment_pad_len = 4 - (comment_len % 4);
2682 } else {
2683 comment_pad_len = 0;
2685 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
2689 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2691 if (int_data->if_name) {
2692 have_options = TRUE;
2693 if_name_len = (guint32)strlen(int_data->if_name) & 0xffff;
2694 if ((if_name_len % 4)) {
2695 if_name_pad_len = 4 - (if_name_len % 4);
2696 } else {
2697 if_name_pad_len = 0;
2699 options_total_length = options_total_length + if_name_len + if_name_pad_len + 4 /* comment options tag */ ;
2703 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2705 if (int_data->if_description) {
2706 have_options = TRUE;
2707 if_description_len = (guint32)strlen(int_data->if_description) & 0xffff;
2708 if ((if_description_len % 4)) {
2709 if_description_pad_len = 4 - (if_description_len % 4);
2710 } else {
2711 if_description_pad_len = 0;
2713 options_total_length = options_total_length + if_description_len + if_description_pad_len + 4 /* comment options tag */ ;
2715 /* Currently not handled
2716 * if_IPv4addr 4 Interface network address and netmask.
2717 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2718 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2719 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2722 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2724 if (int_data->if_speed != 0) {
2725 have_options = TRUE;
2726 options_total_length = options_total_length + 8 + 4;
2729 * if_tsresol 9 Resolution of timestamps.
2731 if (int_data->if_tsresol != 0) {
2732 have_options = TRUE;
2733 options_total_length = options_total_length + 4 + 4;
2735 /* Not used
2736 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2739 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2740 * The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more).
2742 if (int_data->if_filter_str) {
2743 have_options = TRUE;
2744 if_filter_str_len = (guint32)(strlen(int_data->if_filter_str) + 1) & 0xffff;
2745 if ((if_filter_str_len % 4)) {
2746 if_filter_str_pad_len = 4 - (if_filter_str_len % 4);
2747 } else {
2748 if_filter_str_pad_len = 0;
2750 options_total_length = options_total_length + if_filter_str_len + if_filter_str_pad_len + 4 /* comment options tag */ ;
2753 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2755 if (int_data->if_os) {
2756 have_options = TRUE;
2757 if_os_len = (guint32)strlen(int_data->if_os) & 0xffff;
2758 if ((if_os_len % 4)) {
2759 if_os_pad_len = 4 - (if_os_len % 4);
2760 } else {
2761 if_os_pad_len = 0;
2763 options_total_length = options_total_length + if_os_len + if_os_pad_len + 4 /* comment options tag */ ;
2766 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2767 * -1 if unknown or changes between packets, opt 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2769 if (int_data->if_fcslen != 0) {
2771 /* Not used
2772 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2773 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2776 if (have_options) {
2777 /* End-of-options tag */
2778 options_total_length += 4;
2781 /* write block header */
2782 bh.block_type = BLOCK_TYPE_IDB;
2783 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(idb) + options_total_length + 4);
2785 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
2786 return FALSE;
2787 wdh->bytes_dumped += sizeof bh;
2789 /* write block fixed content */
2790 idb.linktype = int_data->link_type;
2791 idb.reserved = 0;
2792 idb.snaplen = int_data->snap_len;
2794 if (!wtap_dump_file_write(wdh, &idb, sizeof idb, err))
2795 return FALSE;
2796 wdh->bytes_dumped += sizeof idb;
2798 /* XXX - write (optional) block options */
2799 if (comment_len != 0) {
2800 option_hdr.type = OPT_COMMENT;
2801 option_hdr.value_length = comment_len;
2802 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2803 return FALSE;
2804 wdh->bytes_dumped += 4;
2806 /* Write the comments string */
2807 pcapng_debug3("pcapng_write_if_descr_block, comment:'%s' comment_len %u comment_pad_len %u" , int_data->opt_comment, comment_len, comment_pad_len);
2808 if (!wtap_dump_file_write(wdh, int_data->opt_comment, comment_len, err))
2809 return FALSE;
2810 wdh->bytes_dumped += comment_len;
2812 /* write padding (if any) */
2813 if (comment_pad_len != 0) {
2814 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
2815 return FALSE;
2816 wdh->bytes_dumped += comment_pad_len;
2820 * if_name 2 A UTF-8 string containing the name of the device used to capture data.
2822 if (if_name_len !=0) {
2823 option_hdr.type = IDB_OPT_IF_NAME;
2824 option_hdr.value_length = if_name_len;
2825 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2826 return FALSE;
2827 wdh->bytes_dumped += 4;
2829 /* Write the comments string */
2830 pcapng_debug3("pcapng_write_if_descr_block, if_name:'%s' if_name_len %u if_name_pad_len %u" , int_data->if_name, if_name_len, if_name_pad_len);
2831 if (!wtap_dump_file_write(wdh, int_data->if_name, if_name_len, err))
2832 return FALSE;
2833 wdh->bytes_dumped += if_name_len;
2835 /* write padding (if any) */
2836 if (if_name_pad_len != 0) {
2837 if (!wtap_dump_file_write(wdh, &zero_pad, if_name_pad_len, err))
2838 return FALSE;
2839 wdh->bytes_dumped += if_name_pad_len;
2843 * if_description 3 A UTF-8 string containing the description of the device used to capture data.
2845 if (if_description_len != 0) {
2846 option_hdr.type = IDB_OPT_IF_NAME;
2847 option_hdr.value_length = if_description_len;
2848 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2849 return FALSE;
2850 wdh->bytes_dumped += 4;
2852 /* Write the comments string */
2853 pcapng_debug3("pcapng_write_if_descr_block, if_description:'%s' if_description_len %u if_description_pad_len %u" , int_data->if_description, if_description_len, if_description_pad_len);
2854 if (!wtap_dump_file_write(wdh, int_data->if_description, if_description_len, err))
2855 return FALSE;
2856 wdh->bytes_dumped += if_description_len;
2858 /* write padding (if any) */
2859 if (if_description_pad_len != 0) {
2860 if (!wtap_dump_file_write(wdh, &zero_pad, if_description_pad_len, err))
2861 return FALSE;
2862 wdh->bytes_dumped += if_description_pad_len;
2865 /* Currently not handled
2866 * if_IPv4addr 4 Interface network address and netmask.
2867 * if_IPv6addr 5 Interface network address and prefix length (stored in the last byte).
2868 * if_MACaddr 6 Interface Hardware MAC address (48 bits). 00 01 02 03 04 05
2869 * if_EUIaddr 7 Interface Hardware EUI address (64 bits), if available. TODO: give a good example
2872 * if_speed 8 Interface speed (in bps). 100000000 for 100Mbps
2874 if (int_data->if_speed != 0) {
2875 option_hdr.type = IDB_OPT_IF_SPEED;
2876 option_hdr.value_length = 8;
2877 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2878 return FALSE;
2879 wdh->bytes_dumped += 4;
2881 /* Write the comments string */
2882 pcapng_debug1("pcapng_write_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", int_data->if_speed);
2883 if (!wtap_dump_file_write(wdh, &int_data->if_speed, sizeof(guint64), err))
2884 return FALSE;
2885 wdh->bytes_dumped += 8;
2888 * if_tsresol 9 Resolution of timestamps.
2889 * default is 6 for microsecond resolution, opt 9 Resolution of timestamps.
2890 * If the Most Significant Bit is equal to zero, the remaining bits indicates
2891 * the resolution of the timestamp as as a negative power of 10
2893 if (int_data->if_tsresol != 0) {
2894 option_hdr.type = IDB_OPT_IF_TSRESOL;
2895 option_hdr.value_length = 1;
2896 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2897 return FALSE;
2898 wdh->bytes_dumped += 4;
2900 /* Write the time stamp resolution */
2901 pcapng_debug1("pcapng_write_if_descr_block: if_tsresol %u", int_data->if_tsresol);
2902 if (!wtap_dump_file_write(wdh, &int_data->if_tsresol, 1, err))
2903 return FALSE;
2904 wdh->bytes_dumped += 1;
2905 if (!wtap_dump_file_write(wdh, &zero_pad, 3, err))
2906 return FALSE;
2907 wdh->bytes_dumped += 3;
2909 /* not used
2910 * if_tzone 10 Time zone for GMT support (TODO: specify better). TODO: give a good example
2913 * if_filter 11 The filter (e.g. "capture only TCP traffic") used to capture traffic.
2915 /* Libpcap string variant */
2916 if (if_filter_str_len !=0) {
2917 option_hdr.type = IDB_OPT_IF_FILTER;
2918 option_hdr.value_length = if_filter_str_len;
2919 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2920 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2921 return FALSE;
2922 wdh->bytes_dumped += 4;
2924 /* Write the zero indicating libpcap filter variant */
2925 if (!wtap_dump_file_write(wdh, &zero_pad, 1, err))
2926 return FALSE;
2927 wdh->bytes_dumped += 1;
2929 /* Write the comments string */
2930 pcapng_debug3("pcapng_write_if_descr_block, if_filter_str:'%s' if_filter_str_len %u if_filter_str_pad_len %u" , int_data->if_filter_str, if_filter_str_len, if_filter_str_pad_len);
2931 /* if_filter_str_len includes the leading byte indicating filter type (libpcap str or BPF code) */
2932 if (!wtap_dump_file_write(wdh, int_data->if_filter_str, if_filter_str_len-1, err))
2933 return FALSE;
2934 wdh->bytes_dumped += if_filter_str_len - 1;
2936 /* write padding (if any) */
2937 if (if_filter_str_pad_len != 0) {
2938 if (!wtap_dump_file_write(wdh, &zero_pad, if_filter_str_pad_len, err))
2939 return FALSE;
2940 wdh->bytes_dumped += if_filter_str_pad_len;
2944 * if_os 12 A UTF-8 string containing the name of the operating system of the machine in which this interface is installed.
2946 if (if_os_len != 0) {
2947 option_hdr.type = IDB_OPT_IF_OS;
2948 option_hdr.value_length = if_os_len;
2949 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2950 return FALSE;
2951 wdh->bytes_dumped += 4;
2953 /* Write the comments string */
2954 pcapng_debug3("pcapng_write_if_descr_block, if_os:'%s' if_os_len %u if_os_pad_len %u" , int_data->if_os, if_os_len, if_os_pad_len);
2955 if (!wtap_dump_file_write(wdh, int_data->if_os, if_os_len, err))
2956 return FALSE;
2957 wdh->bytes_dumped += if_os_len;
2959 /* write padding (if any) */
2960 if (if_os_pad_len != 0) {
2961 if (!wtap_dump_file_write(wdh, &zero_pad, if_os_pad_len, err))
2962 return FALSE;
2963 wdh->bytes_dumped += if_os_pad_len;
2967 if (have_options) {
2968 option_hdr.type = OPT_EOFOPT;
2969 option_hdr.value_length = 0;
2970 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
2971 return FALSE;
2972 wdh->bytes_dumped += 4;
2976 * if_fcslen 13 An integer value that specified the length of the Frame Check Sequence (in bits) for this interface.
2979 * if_tsoffset 14 A 64 bits integer value that specifies an offset (in seconds) that must be added to the timestamp of each packet
2980 * to obtain the absolute timestamp of a packet. If the option is missing, the timestamps stored in the packet must be considered absolute timestamps.
2983 /* write block footer */
2984 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
2985 sizeof bh.block_total_length, err))
2986 return FALSE;
2987 wdh->bytes_dumped += sizeof bh.block_total_length;
2989 return TRUE;
2992 #define ISB_STARTTIME 2
2993 #define ISB_ENDTIME 3
2994 #define ISB_IFRECV 4
2995 #define ISB_IFDROP 5
2996 #define ISB_FILTERACCEPT 6
2997 #define ISB_OSDROP 7
2998 #define ISB_USRDELIV 8
3000 static gboolean
3001 pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtapng_if_stats_t *if_stats, int *err)
3004 pcapng_block_header_t bh;
3005 pcapng_interface_statistics_block_t isb;
3006 const guint32 zero_pad = 0;
3007 gboolean have_options = FALSE;
3008 struct option option_hdr; /* guint16 type, guint16 value_length; */
3009 guint32 options_total_length = 0;
3010 guint32 comment_len = 0;
3011 guint32 comment_pad_len = 0;
3013 pcapng_debug0("pcapng_write_interface_statistics_block");
3016 /* Calculate options length */
3017 if (if_stats->opt_comment) {
3018 have_options = TRUE;
3019 comment_len = (guint32)strlen(if_stats->opt_comment) & 0xffff;
3020 if ((comment_len % 4)) {
3021 comment_pad_len = 4 - (comment_len % 4);
3022 } else {
3023 comment_pad_len = 0;
3025 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3027 /*guint64 isb_starttime */
3028 if (if_stats->isb_starttime != 0) {
3029 have_options = TRUE;
3030 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3032 /*guint64 isb_endtime */
3033 if (if_stats->isb_endtime != 0) {
3034 have_options = TRUE;
3035 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3037 /*guint64 isb_ifrecv */
3038 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3039 have_options = TRUE;
3040 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3042 /*guint64 isb_ifdrop */
3043 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3044 have_options = TRUE;
3045 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3047 /*guint64 isb_filteraccept */
3048 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3049 have_options = TRUE;
3050 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3052 /*guint64 isb_osdrop */
3053 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3054 have_options = TRUE;
3055 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3057 /*guint64 isb_usrdeliv */
3058 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3059 have_options = TRUE;
3060 options_total_length = options_total_length + 8 + 4 /* options tag */ ;
3063 /* write block header */
3064 if (have_options) {
3065 /* End-of-optios tag */
3066 options_total_length += 4;
3069 /* write block header */
3070 bh.block_type = BLOCK_TYPE_ISB;
3071 bh.block_total_length = (guint32)(sizeof(bh) + sizeof(isb) + options_total_length + 4);
3073 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3074 return FALSE;
3075 wdh->bytes_dumped += sizeof bh;
3077 /* write block fixed content */
3078 isb.interface_id = if_stats->interface_id;
3079 isb.timestamp_high = if_stats->ts_high;
3080 isb.timestamp_low = if_stats->ts_low;
3083 if (!wtap_dump_file_write(wdh, &isb, sizeof isb, err))
3084 return FALSE;
3085 wdh->bytes_dumped += sizeof isb;
3087 /* write (optional) block options */
3088 if (comment_len) {
3089 option_hdr.type = OPT_COMMENT;
3090 option_hdr.value_length = comment_len;
3091 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3092 return FALSE;
3093 wdh->bytes_dumped += 4;
3095 /* Write the comments string */
3096 pcapng_debug3("pcapng_write_interface_statistics_block, comment:'%s' comment_len %u comment_pad_len %u" , if_stats->opt_comment, comment_len, comment_pad_len);
3097 if (!wtap_dump_file_write(wdh, if_stats->opt_comment, comment_len, err))
3098 return FALSE;
3099 wdh->bytes_dumped += comment_len;
3101 /* write padding (if any) */
3102 if (comment_pad_len != 0) {
3103 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3104 return FALSE;
3105 wdh->bytes_dumped += comment_pad_len;
3108 /*guint64 isb_starttime */
3109 if (if_stats->isb_starttime != 0) {
3110 guint32 high, low;
3112 option_hdr.type = ISB_STARTTIME;
3113 option_hdr.value_length = 8;
3114 high = (guint32)((if_stats->isb_starttime>>32) & 0xffffffff);
3115 low = (guint32)(if_stats->isb_starttime & 0xffffffff);
3116 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3117 return FALSE;
3118 wdh->bytes_dumped += 4;
3120 /* Write isb_starttime */
3121 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_starttime);
3122 if (!wtap_dump_file_write(wdh, &high, 4, err))
3123 return FALSE;
3124 wdh->bytes_dumped += 4;
3125 if (!wtap_dump_file_write(wdh, &low, 4, err))
3126 return FALSE;
3127 wdh->bytes_dumped += 4;
3129 /*guint64 isb_endtime */
3130 if (if_stats->isb_endtime != 0) {
3131 guint32 high, low;
3133 option_hdr.type = ISB_ENDTIME;
3134 option_hdr.value_length = 8;
3135 high = (guint32)((if_stats->isb_endtime>>32) & 0xffffffff);
3136 low = (guint32)(if_stats->isb_endtime & 0xffffffff);
3137 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3138 return FALSE;
3139 wdh->bytes_dumped += 4;
3141 /* Write isb_endtime */
3142 pcapng_debug1("pcapng_write_interface_statistics_block, isb_starttime: %" G_GINT64_MODIFIER "u" , if_stats->isb_endtime);
3143 if (!wtap_dump_file_write(wdh, &high, 4, err))
3144 return FALSE;
3145 wdh->bytes_dumped += 4;
3146 if (!wtap_dump_file_write(wdh, &low, 4, err))
3147 return FALSE;
3148 wdh->bytes_dumped += 4;
3150 /*guint64 isb_ifrecv;*/
3151 if (if_stats->isb_ifrecv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3152 option_hdr.type = ISB_IFRECV;
3153 option_hdr.value_length = 8;
3154 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3155 return FALSE;
3156 wdh->bytes_dumped += 4;
3158 /* Write isb_ifrecv */
3159 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifrecv: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifrecv);
3160 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifrecv, 8, err))
3161 return FALSE;
3162 wdh->bytes_dumped += 8;
3164 /*guint64 isb_ifdrop;*/
3165 if (if_stats->isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3166 option_hdr.type = ISB_IFDROP;
3167 option_hdr.value_length = 8;
3168 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3169 return FALSE;
3170 wdh->bytes_dumped += 4;
3172 /* Write isb_ifdrop */
3173 pcapng_debug1("pcapng_write_interface_statistics_block, isb_ifdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_ifdrop);
3174 if (!wtap_dump_file_write(wdh, &if_stats->isb_ifdrop, 8, err))
3175 return FALSE;
3176 wdh->bytes_dumped += 8;
3178 /*guint64 isb_filteraccept;*/
3179 if (if_stats->isb_filteraccept != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3180 option_hdr.type = ISB_FILTERACCEPT;
3181 option_hdr.value_length = 8;
3182 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3183 return FALSE;
3184 wdh->bytes_dumped += 4;
3186 /* Write isb_filteraccept */
3187 pcapng_debug1("pcapng_write_interface_statistics_block, isb_filteraccept: %" G_GINT64_MODIFIER "u" , if_stats->isb_filteraccept);
3188 if (!wtap_dump_file_write(wdh, &if_stats->isb_filteraccept, 8, err))
3189 return FALSE;
3190 wdh->bytes_dumped += 8;
3192 /*guint64 isb_osdrop;*/
3193 if (if_stats->isb_osdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3194 option_hdr.type = ISB_OSDROP;
3195 option_hdr.value_length = 8;
3196 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3197 return FALSE;
3198 wdh->bytes_dumped += 4;
3200 /* Write isb_osdrop */
3201 pcapng_debug1("pcapng_write_interface_statistics_block, isb_osdrop: %" G_GINT64_MODIFIER "u" , if_stats->isb_osdrop);
3202 if (!wtap_dump_file_write(wdh, &if_stats->isb_osdrop, 8, err))
3203 return FALSE;
3204 wdh->bytes_dumped += 8;
3206 /*guint64 isb_usrdeliv;*/
3207 if (if_stats->isb_usrdeliv != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
3208 option_hdr.type = ISB_USRDELIV;
3209 option_hdr.value_length = 8;
3210 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3211 return FALSE;
3212 wdh->bytes_dumped += 4;
3214 /* Write isb_usrdeliv */
3215 pcapng_debug1("pcapng_write_interface_statistics_block, isb_usrdeliv: %" G_GINT64_MODIFIER "u" , if_stats->isb_usrdeliv);
3216 if (!wtap_dump_file_write(wdh, &if_stats->isb_usrdeliv, 8, err))
3217 return FALSE;
3218 wdh->bytes_dumped += 8;
3221 if (have_options) {
3222 option_hdr.type = OPT_EOFOPT;
3223 option_hdr.value_length = 0;
3224 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3225 return FALSE;
3226 wdh->bytes_dumped += 4;
3229 /* write block footer */
3230 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3231 sizeof bh.block_total_length, err))
3232 return FALSE;
3233 wdh->bytes_dumped += sizeof bh.block_total_length;
3235 return TRUE;
3240 static gboolean
3241 pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
3242 const struct wtap_pkthdr *phdr,
3243 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
3245 pcapng_block_header_t bh;
3246 pcapng_enhanced_packet_block_t epb;
3247 guint64 ts;
3248 const guint32 zero_pad = 0;
3249 guint32 pad_len;
3250 guint32 phdr_len;
3251 gboolean have_options = FALSE;
3252 guint32 options_total_length = 0;
3253 struct option option_hdr;
3254 guint32 comment_len = 0, comment_pad_len = 0;
3255 wtapng_if_descr_t int_data;
3257 phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header);
3258 if ((phdr_len + phdr->caplen) % 4) {
3259 pad_len = 4 - ((phdr_len + phdr->caplen) % 4);
3260 } else {
3261 pad_len = 0;
3264 /* Check if we should write comment option */
3265 if (phdr->opt_comment) {
3266 have_options = TRUE;
3267 comment_len = (guint32)strlen(phdr->opt_comment) & 0xffff;
3268 if ((comment_len % 4)) {
3269 comment_pad_len = 4 - (comment_len % 4);
3270 } else {
3271 comment_pad_len = 0;
3273 options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
3275 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3276 have_options = TRUE;
3277 options_total_length = options_total_length + 8;
3279 if (have_options) {
3280 /* End-of optios tag */
3281 options_total_length += 4;
3284 /* write (enhanced) packet block header */
3285 bh.block_type = BLOCK_TYPE_EPB;
3286 bh.block_total_length = (guint32)sizeof(bh) + (guint32)sizeof(epb) + phdr_len + phdr->caplen + pad_len + options_total_length + 4;
3288 if (!wtap_dump_file_write(wdh, &bh, sizeof bh, err))
3289 return FALSE;
3290 wdh->bytes_dumped += sizeof bh;
3292 /* write block fixed content */
3293 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3294 epb.interface_id = phdr->interface_id;
3295 else {
3297 * XXX - we should support writing WTAP_ENCAP_PER_PACKET
3298 * data to pcap-NG files even if we *don't* have interface
3299 * IDs.
3301 epb.interface_id = 0;
3304 * Split the 64-bit timestamp into two 32-bit pieces, using
3305 * the time stamp resolution for the interface.
3307 if (epb.interface_id >= wdh->number_of_interfaces) {
3309 * Our caller is doing something bad.
3311 *err = WTAP_ERR_INTERNAL;
3312 return FALSE;
3314 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t,
3315 epb.interface_id);
3316 ts = ((guint64)phdr->ts.secs) * int_data.time_units_per_second +
3317 (((guint64)phdr->ts.nsecs) * int_data.time_units_per_second) / 1000000000;
3318 epb.timestamp_high = (guint32)(ts >> 32);
3319 epb.timestamp_low = (guint32)ts;
3320 epb.captured_len = phdr->caplen + phdr_len;
3321 epb.packet_len = phdr->len + phdr_len;
3323 if (!wtap_dump_file_write(wdh, &epb, sizeof epb, err))
3324 return FALSE;
3325 wdh->bytes_dumped += sizeof epb;
3327 /* write pseudo header */
3328 if (!pcap_write_phdr(wdh, phdr->pkt_encap, pseudo_header, err)) {
3329 return FALSE;
3331 wdh->bytes_dumped += phdr_len;
3333 /* write packet data */
3334 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
3335 return FALSE;
3336 wdh->bytes_dumped += phdr->caplen;
3338 /* write padding (if any) */
3339 if (pad_len != 0) {
3340 if (!wtap_dump_file_write(wdh, &zero_pad, pad_len, err))
3341 return FALSE;
3342 wdh->bytes_dumped += pad_len;
3345 /* XXX - write (optional) block options */
3346 /* options defined in Section 2.5 (Options)
3347 * Name Code Length Description
3348 * opt_comment 1 variable A UTF-8 string containing a comment that is associated to the current block.
3350 * Enhanced Packet Block options
3351 * epb_flags 2 4 A flags word containing link-layer information. A complete specification of
3352 * the allowed flags can be found in Appendix A (Packet Block Flags Word).
3353 * epb_hash 3 variable This option contains a hash of the packet. The first byte specifies the hashing algorithm,
3354 * while the following bytes contain the actual hash, whose size depends on the hashing algorithm,
3355 * and hence from the value in the first bit. The hashing algorithm can be: 2s complement
3356 * (algorithm byte = 0, size=XXX), XOR (algorithm byte = 1, size=XXX), CRC32 (algorithm byte = 2, size = 4),
3357 * MD-5 (algorithm byte = 3, size=XXX), SHA-1 (algorithm byte = 4, size=XXX).
3358 * The hash covers only the packet, not the header added by the capture driver:
3359 * this gives the possibility to calculate it inside the network card.
3360 * The hash allows easier comparison/merging of different capture files, and reliable data transfer between the
3361 * data acquisition system and the capture library.
3362 * epb_dropcount 4 8 A 64bit integer value specifying the number of packets lost (by the interface and the operating system)
3363 * between this packet and the preceding one.
3364 * opt_endofopt 0 0 It delimits the end of the optional fields. This block cannot be repeated within a given list of options.
3366 if (phdr->opt_comment) {
3367 option_hdr.type = OPT_COMMENT;
3368 option_hdr.value_length = comment_len;
3369 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3370 return FALSE;
3371 wdh->bytes_dumped += 4;
3373 /* Write the comments string */
3374 pcapng_debug3("pcapng_write_enhanced_packet_block, comment:'%s' comment_len %u comment_pad_len %u" , phdr->opt_comment, comment_len, comment_pad_len);
3375 if (!wtap_dump_file_write(wdh, phdr->opt_comment, comment_len, err))
3376 return FALSE;
3377 wdh->bytes_dumped += comment_len;
3379 /* write padding (if any) */
3380 if (comment_pad_len != 0) {
3381 if (!wtap_dump_file_write(wdh, &zero_pad, comment_pad_len, err))
3382 return FALSE;
3383 wdh->bytes_dumped += comment_pad_len;
3386 pcapng_debug2("pcapng_write_enhanced_packet_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
3387 comment_len,
3388 comment_pad_len);
3390 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
3391 option_hdr.type = OPT_EPB_FLAGS;
3392 option_hdr.value_length = 4;
3393 if (!wtap_dump_file_write(wdh, &option_hdr, 4, err))
3394 return FALSE;
3395 wdh->bytes_dumped += 4;
3396 if (!wtap_dump_file_write(wdh, &phdr->pack_flags, 4, err))
3397 return FALSE;
3398 wdh->bytes_dumped += 4;
3399 pcapng_debug1("pcapng_write_enhanced_packet_block: Wrote Options packet flags: %x", phdr->pack_flags);
3401 /* Write end of options if we have otions */
3402 if (have_options) {
3403 if (!wtap_dump_file_write(wdh, &zero_pad, 4, err))
3404 return FALSE;
3405 wdh->bytes_dumped += 4;
3408 /* write block footer */
3409 if (!wtap_dump_file_write(wdh, &bh.block_total_length,
3410 sizeof bh.block_total_length, err))
3411 return FALSE;
3412 wdh->bytes_dumped += sizeof bh.block_total_length;
3414 return TRUE;
3417 /* Arbitrary. */
3418 #define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
3419 static gboolean
3420 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
3422 pcapng_block_header_t bh;
3423 pcapng_name_resolution_block_t nrb;
3424 guint8 *rec_data;
3425 gint rec_off, namelen, tot_rec_len;
3426 hashipv4_t *ipv4_hash_list_entry;
3427 hashipv6_t *ipv6_hash_list_entry;
3428 int i;
3430 if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
3431 return TRUE;
3434 rec_off = 8; /* block type + block total length */
3435 bh.block_type = BLOCK_TYPE_NRB;
3436 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3437 rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
3439 if (wdh->addrinfo_lists->ipv4_addr_list){
3440 i = 0;
3441 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3442 while(ipv4_hash_list_entry != NULL){
3444 nrb.record_type = NRES_IP4RECORD;
3445 namelen = (gint)strlen(ipv4_hash_list_entry->name) + 1;
3446 nrb.record_len = 4 + namelen;
3447 tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
3449 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3450 /* We know the total length now; copy the block header. */
3451 memcpy(rec_data, &bh, sizeof(bh));
3453 /* End of record */
3454 memset(rec_data + rec_off, 0, 4);
3455 rec_off += 4;
3457 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3459 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3461 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3462 g_free(rec_data);
3463 return FALSE;
3465 wdh->bytes_dumped += bh.block_total_length;
3467 /*Start a new NRB */
3468 rec_off = 8; /* block type + block total length */
3469 bh.block_type = BLOCK_TYPE_NRB;
3470 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3474 bh.block_total_length += tot_rec_len;
3475 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3476 rec_off += 4;
3477 memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
3478 rec_off += 4;
3479 memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
3480 rec_off += namelen;
3481 memset(rec_data + rec_off, 0, PADDING4(namelen));
3482 rec_off += PADDING4(namelen);
3483 pcapng_debug1("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
3485 i++;
3486 ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
3488 g_list_free(wdh->addrinfo_lists->ipv4_addr_list);
3489 wdh->addrinfo_lists->ipv4_addr_list = NULL;
3492 if (wdh->addrinfo_lists->ipv6_addr_list){
3493 i = 0;
3494 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3495 while(ipv6_hash_list_entry != NULL){
3497 nrb.record_type = NRES_IP6RECORD;
3498 namelen = (gint)strlen(ipv6_hash_list_entry->name) + 1;
3499 nrb.record_len = 16 + namelen;
3500 tot_rec_len = 16 + nrb.record_len + PADDING4(nrb.record_len);
3502 if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
3503 /* We know the total length now; copy the block header. */
3504 memcpy(rec_data, &bh, sizeof(bh));
3506 /* End of record */
3507 memset(rec_data + rec_off, 0, 4);
3508 rec_off += 4;
3510 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3512 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3514 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3515 g_free(rec_data);
3516 return FALSE;
3518 wdh->bytes_dumped += bh.block_total_length;
3520 /*Start a new NRB */
3521 rec_off = 8; /* block type + block total length */
3522 bh.block_type = BLOCK_TYPE_NRB;
3523 bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
3527 bh.block_total_length += tot_rec_len;
3528 memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
3529 rec_off += 4;
3530 memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
3531 rec_off += 16;
3532 memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
3533 rec_off += namelen;
3534 memset(rec_data + rec_off, 0, PADDING4(namelen));
3535 rec_off += PADDING4(namelen);
3536 pcapng_debug1("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
3538 i++;
3539 ipv6_hash_list_entry = (hashipv6_t *)g_list_nth_data(wdh->addrinfo_lists->ipv6_addr_list, i);
3541 g_list_free(wdh->addrinfo_lists->ipv6_addr_list);
3542 wdh->addrinfo_lists->ipv6_addr_list = NULL;
3545 /* We know the total length now; copy the block header. */
3546 memcpy(rec_data, &bh, sizeof(bh));
3548 /* End of record */
3549 memset(rec_data + rec_off, 0, 4);
3550 rec_off += 4;
3552 memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
3554 pcapng_debug2("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
3556 if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
3557 g_free(rec_data);
3558 return FALSE;
3561 g_free(rec_data);
3562 wdh->bytes_dumped += bh.block_total_length;
3563 return TRUE;
3566 #if 0
3567 static guint32
3568 pcapng_lookup_interface_id_by_encap(int wtap_encap, wtap_dumper *wdh)
3570 gint i;
3571 interface_data_t int_data;
3572 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3574 for(i = 0; i < (gint)pcapng->number_of_interfaces; i++) {
3575 int_data = g_array_index(pcapng->interface_data, interface_data_t, i);
3576 if (wtap_encap == int_data.wtap_encap) {
3577 return (guint32)i;
3580 return G_MAXUINT32;
3582 #endif
3584 static gboolean pcapng_dump(wtap_dumper *wdh,
3585 const struct wtap_pkthdr *phdr,
3586 const guint8 *pd, int *err)
3588 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
3589 /*interface_data_t int_data;*/
3590 /* pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv; */
3591 /*int pcap_encap;*/
3593 pcapng_debug2("pcapng_dump: encap = %d (%s)",
3594 phdr->pkt_encap,
3595 wtap_encap_string(phdr->pkt_encap));
3597 /* Flush any hostname resolution info we may have */
3598 pcapng_write_name_resolution_block(wdh, err);
3600 if (!pcapng_write_enhanced_packet_block(wdh, phdr, pseudo_header, pd, err)) {
3601 return FALSE;
3604 return TRUE;
3608 /* Finish writing to a dump file.
3609 Returns TRUE on success, FALSE on failure. */
3610 static gboolean pcapng_dump_close(wtap_dumper *wdh, int *err _U_)
3612 int i, j;
3613 pcapng_dump_t *pcapng = (pcapng_dump_t *)wdh->priv;
3615 if ((wdh->number_of_interfaces > 0) && (wdh->interface_data != NULL)) {
3616 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3618 /* Get the interface description */
3619 wtapng_if_descr_t int_data;
3621 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3622 for (j = 0; j < (int)int_data.num_stat_entries; j++) {
3623 wtapng_if_stats_t if_stats;
3625 if_stats = g_array_index(int_data.interface_statistics, wtapng_if_stats_t, j);
3626 pcapng_debug1("pcapng_dump_close: write ISB for interface %u",if_stats.interface_id);
3627 if (!pcapng_write_interface_statistics_block(wdh, &if_stats, err)) {
3628 return FALSE;
3634 pcapng_debug0("pcapng_dump_close");
3635 g_array_free(pcapng->interface_data, TRUE);
3636 pcapng->number_of_interfaces = 0;
3637 return TRUE;
3641 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
3642 failure */
3643 gboolean
3644 pcapng_dump_open(wtap_dumper *wdh, int *err)
3646 pcapng_dump_t *pcapng;
3647 int i;
3648 interface_data_t interface_data;
3650 pcapng_debug0("pcapng_dump_open");
3651 /* This is a pcapng file */
3652 wdh->subtype_write = pcapng_dump;
3653 wdh->subtype_close = pcapng_dump_close;
3654 pcapng = (pcapng_dump_t *)g_malloc0(sizeof(pcapng_dump_t));
3655 wdh->priv = (void *)pcapng;
3656 pcapng->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
3658 if ((wdh->number_of_interfaces == 0) || (wdh->interface_data == NULL)) {
3659 pcapng_debug0("There are no interfaces. Can't handle that...");
3660 *err = WTAP_ERR_INTERNAL;
3661 return FALSE;
3664 /* write the section header block */
3665 if (!pcapng_write_section_header_block(wdh, err)) {
3666 return FALSE;
3668 pcapng_debug0("pcapng_dump_open: wrote section header block.");
3670 /* Write the Interface description blocks */
3671 pcapng_debug1("pcapng_dump_open: Number of IDB:s to write (number of interfaces) %u", wdh->number_of_interfaces);
3673 for (i = 0; i < (int)wdh->number_of_interfaces; i++) {
3675 /* Get the interface description */
3676 wtapng_if_descr_t int_data;
3678 int_data = g_array_index(wdh->interface_data, wtapng_if_descr_t, i);
3680 interface_data.wtap_encap = int_data.wtap_encap;
3681 interface_data.time_units_per_second = int_data.time_units_per_second;
3683 g_array_append_val(pcapng->interface_data, interface_data);
3684 pcapng->number_of_interfaces++;
3686 if (!pcapng_write_if_descr_block(wdh, &int_data, err)) {
3687 return FALSE;
3691 #if 0
3692 interface_id = pcapng_lookup_interface_id_by_encap(phdr->pkt_encap, wdh);
3693 if (interface_id == G_MAXUINT32) {
3695 * We haven't yet written out an interface description
3696 * block for an interface with this encapsulation.
3698 * Is this encapsulation even supported in pcap-ng?
3700 pcap_encap = wtap_wtap_encap_to_pcap_encap(phdr->pkt_encap);
3701 if (pcap_encap == -1) {
3703 * No. Fail.
3705 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
3706 return FALSE;
3709 /* write the interface description block */
3710 wblock.frame_buffer = NULL;
3711 wblock.pseudo_header = NULL;
3712 wblock.packet_header = NULL;
3713 wblock.file_encap = NULL;
3714 wblock.type = BLOCK_TYPE_IDB;
3715 wblock.data.if_descr.link_type = pcap_encap;
3716 wblock.data.if_descr.snap_len = (wdh->snaplen != 0) ? wdh->snaplen :
3717 WTAP_MAX_PACKET_SIZE; /* XXX */
3719 /* XXX - options unused */
3720 wblock.data.if_descr.if_speed = -1;
3721 /*wblock.data.if_descr.if_tsresol = 6;*/ /* default: usec */
3722 wblock.data.if_descr.if_os = NULL;
3723 wblock.data.if_descr.if_fcslen = -1;
3725 if (!pcapng_write_if_descr_block(wdh, &wblock, err)) {
3726 return FALSE;
3729 interface_id = pcapng->number_of_interfaces;
3730 int_data.wtap_encap = phdr->pkt_encap;
3731 int_data.time_units_per_second = 0;
3732 g_array_append_val(pcapng->interface_data, int_data);
3733 pcapng->number_of_interfaces++;
3735 pcapng_debug3("pcapng_dump: added interface description block with index %u for encap = %d (%s).",
3736 interface_id,
3737 phdr->pkt_encap,
3738 wtap_encap_string(phdr->pkt_encap));
3740 #endif
3742 return TRUE;
3746 /* Returns 0 if we could write the specified encapsulation type,
3747 an error indication otherwise. */
3748 int pcapng_dump_can_write_encap(int wtap_encap)
3750 pcapng_debug2("pcapng_dump_can_write_encap: encap = %d (%s)",
3751 wtap_encap,
3752 wtap_encap_string(wtap_encap));
3754 /* Per-packet encapsulation is supported. */
3755 if (wtap_encap == WTAP_ENCAP_PER_PACKET)
3756 return 0;
3758 /* Make sure we can figure out this DLT type */
3759 if (wtap_wtap_encap_to_pcap_encap(wtap_encap) == -1)
3760 return WTAP_ERR_UNSUPPORTED_ENCAP;
3762 return 0;
3766 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3768 * Local variables:
3769 * c-basic-offset: 4
3770 * tab-width: 8
3771 * indent-tabs-mode: nil
3772 * End:
3774 * vi: set shiftwidth=4 tabstop=8 expandtab:
3775 * :indentSize=4:tabSize=8:noTabs=true: