xref: /freebsd-src/contrib/libpcap/sf-pcapng.c (revision afdbf109c6a661a729938f68211054a0a50d38ac)
1b00ab754SHans Petter Selasky /*
2b00ab754SHans Petter Selasky  * Copyright (c) 1993, 1994, 1995, 1996, 1997
3b00ab754SHans Petter Selasky  *	The Regents of the University of California.  All rights reserved.
4b00ab754SHans Petter Selasky  *
5b00ab754SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
6b00ab754SHans Petter Selasky  * modification, are permitted provided that: (1) source code distributions
7b00ab754SHans Petter Selasky  * retain the above copyright notice and this paragraph in its entirety, (2)
8b00ab754SHans Petter Selasky  * distributions including binary code include the above copyright notice and
9b00ab754SHans Petter Selasky  * this paragraph in its entirety in the documentation or other materials
10b00ab754SHans Petter Selasky  * provided with the distribution, and (3) all advertising materials mentioning
11b00ab754SHans Petter Selasky  * features or use of this software display the following acknowledgement:
12b00ab754SHans Petter Selasky  * ``This product includes software developed by the University of California,
13b00ab754SHans Petter Selasky  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14b00ab754SHans Petter Selasky  * the University nor the names of its contributors may be used to endorse
15b00ab754SHans Petter Selasky  * or promote products derived from this software without specific prior
16b00ab754SHans Petter Selasky  * written permission.
17b00ab754SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18b00ab754SHans Petter Selasky  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19b00ab754SHans Petter Selasky  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20b00ab754SHans Petter Selasky  *
21b00ab754SHans Petter Selasky  * sf-pcapng.c - pcapng-file-format-specific code from savefile.c
22b00ab754SHans Petter Selasky  */
23b00ab754SHans Petter Selasky 
24b00ab754SHans Petter Selasky #include <config.h>
25b00ab754SHans Petter Selasky 
26b00ab754SHans Petter Selasky #include <pcap/pcap-inttypes.h>
27b00ab754SHans Petter Selasky 
28b00ab754SHans Petter Selasky #include <errno.h>
29b00ab754SHans Petter Selasky #include <memory.h>
30b00ab754SHans Petter Selasky #include <stdio.h>
31b00ab754SHans Petter Selasky #include <stdlib.h>
32b00ab754SHans Petter Selasky #include <string.h>
33b00ab754SHans Petter Selasky 
34b00ab754SHans Petter Selasky #include "pcap-int.h"
356f9cba8fSJoseph Mingrone #include "pcap-util.h"
36b00ab754SHans Petter Selasky 
37b00ab754SHans Petter Selasky #include "pcap-common.h"
38b00ab754SHans Petter Selasky 
39b00ab754SHans Petter Selasky #ifdef HAVE_OS_PROTO_H
40b00ab754SHans Petter Selasky #include "os-proto.h"
41b00ab754SHans Petter Selasky #endif
42b00ab754SHans Petter Selasky 
43b00ab754SHans Petter Selasky #include "sf-pcapng.h"
44b00ab754SHans Petter Selasky 
45b00ab754SHans Petter Selasky /*
46b00ab754SHans Petter Selasky  * Block types.
47b00ab754SHans Petter Selasky  */
48b00ab754SHans Petter Selasky 
49b00ab754SHans Petter Selasky /*
50b00ab754SHans Petter Selasky  * Common part at the beginning of all blocks.
51b00ab754SHans Petter Selasky  */
52b00ab754SHans Petter Selasky struct block_header {
53b00ab754SHans Petter Selasky 	bpf_u_int32	block_type;
54b00ab754SHans Petter Selasky 	bpf_u_int32	total_length;
55b00ab754SHans Petter Selasky };
56b00ab754SHans Petter Selasky 
57b00ab754SHans Petter Selasky /*
58b00ab754SHans Petter Selasky  * Common trailer at the end of all blocks.
59b00ab754SHans Petter Selasky  */
60b00ab754SHans Petter Selasky struct block_trailer {
61b00ab754SHans Petter Selasky 	bpf_u_int32	total_length;
62b00ab754SHans Petter Selasky };
63b00ab754SHans Petter Selasky 
64b00ab754SHans Petter Selasky /*
65b00ab754SHans Petter Selasky  * Common options.
66b00ab754SHans Petter Selasky  */
67b00ab754SHans Petter Selasky #define OPT_ENDOFOPT	0	/* end of options */
68b00ab754SHans Petter Selasky #define OPT_COMMENT	1	/* comment string */
69b00ab754SHans Petter Selasky 
70b00ab754SHans Petter Selasky /*
71b00ab754SHans Petter Selasky  * Option header.
72b00ab754SHans Petter Selasky  */
73b00ab754SHans Petter Selasky struct option_header {
74b00ab754SHans Petter Selasky 	u_short		option_code;
75b00ab754SHans Petter Selasky 	u_short		option_length;
76b00ab754SHans Petter Selasky };
77b00ab754SHans Petter Selasky 
78b00ab754SHans Petter Selasky /*
79b00ab754SHans Petter Selasky  * Structures for the part of each block type following the common
80b00ab754SHans Petter Selasky  * part.
81b00ab754SHans Petter Selasky  */
82b00ab754SHans Petter Selasky 
83b00ab754SHans Petter Selasky /*
84b00ab754SHans Petter Selasky  * Section Header Block.
85b00ab754SHans Petter Selasky  */
86b00ab754SHans Petter Selasky #define BT_SHB			0x0A0D0D0A
8757e22627SCy Schubert #define BT_SHB_INSANE_MAX       1024U*1024U*1U  /* 1MB should be enough */
88b00ab754SHans Petter Selasky struct section_header_block {
89b00ab754SHans Petter Selasky 	bpf_u_int32	byte_order_magic;
90b00ab754SHans Petter Selasky 	u_short		major_version;
91b00ab754SHans Petter Selasky 	u_short		minor_version;
92b00ab754SHans Petter Selasky 	uint64_t	section_length;
93b00ab754SHans Petter Selasky 	/* followed by options and trailer */
94b00ab754SHans Petter Selasky };
95b00ab754SHans Petter Selasky 
96b00ab754SHans Petter Selasky /*
97b00ab754SHans Petter Selasky  * Byte-order magic value.
98b00ab754SHans Petter Selasky  */
99b00ab754SHans Petter Selasky #define BYTE_ORDER_MAGIC	0x1A2B3C4D
100b00ab754SHans Petter Selasky 
101b00ab754SHans Petter Selasky /*
102b00ab754SHans Petter Selasky  * Current version number.  If major_version isn't PCAP_NG_VERSION_MAJOR,
1036f9cba8fSJoseph Mingrone  * or if minor_version isn't PCAP_NG_VERSION_MINOR or 2, that means that
1046f9cba8fSJoseph Mingrone  * this code can't read the file.
105b00ab754SHans Petter Selasky  */
106b00ab754SHans Petter Selasky #define PCAP_NG_VERSION_MAJOR	1
107b00ab754SHans Petter Selasky #define PCAP_NG_VERSION_MINOR	0
108b00ab754SHans Petter Selasky 
109b00ab754SHans Petter Selasky /*
110b00ab754SHans Petter Selasky  * Interface Description Block.
111b00ab754SHans Petter Selasky  */
112b00ab754SHans Petter Selasky #define BT_IDB			0x00000001
113b00ab754SHans Petter Selasky 
114b00ab754SHans Petter Selasky struct interface_description_block {
115b00ab754SHans Petter Selasky 	u_short		linktype;
116b00ab754SHans Petter Selasky 	u_short		reserved;
117b00ab754SHans Petter Selasky 	bpf_u_int32	snaplen;
118b00ab754SHans Petter Selasky 	/* followed by options and trailer */
119b00ab754SHans Petter Selasky };
120b00ab754SHans Petter Selasky 
121b00ab754SHans Petter Selasky /*
122b00ab754SHans Petter Selasky  * Options in the IDB.
123b00ab754SHans Petter Selasky  */
124b00ab754SHans Petter Selasky #define IF_NAME		2	/* interface name string */
125b00ab754SHans Petter Selasky #define IF_DESCRIPTION	3	/* interface description string */
126b00ab754SHans Petter Selasky #define IF_IPV4ADDR	4	/* interface's IPv4 address and netmask */
127b00ab754SHans Petter Selasky #define IF_IPV6ADDR	5	/* interface's IPv6 address and prefix length */
128b00ab754SHans Petter Selasky #define IF_MACADDR	6	/* interface's MAC address */
129b00ab754SHans Petter Selasky #define IF_EUIADDR	7	/* interface's EUI address */
130b00ab754SHans Petter Selasky #define IF_SPEED	8	/* interface's speed, in bits/s */
131b00ab754SHans Petter Selasky #define IF_TSRESOL	9	/* interface's time stamp resolution */
132b00ab754SHans Petter Selasky #define IF_TZONE	10	/* interface's time zone */
133b00ab754SHans Petter Selasky #define IF_FILTER	11	/* filter used when capturing on interface */
134b00ab754SHans Petter Selasky #define IF_OS		12	/* string OS on which capture on this interface was done */
135b00ab754SHans Petter Selasky #define IF_FCSLEN	13	/* FCS length for this interface */
136b00ab754SHans Petter Selasky #define IF_TSOFFSET	14	/* time stamp offset for this interface */
137b00ab754SHans Petter Selasky 
138b00ab754SHans Petter Selasky /*
139b00ab754SHans Petter Selasky  * Enhanced Packet Block.
140b00ab754SHans Petter Selasky  */
141b00ab754SHans Petter Selasky #define BT_EPB			0x00000006
142b00ab754SHans Petter Selasky 
143b00ab754SHans Petter Selasky struct enhanced_packet_block {
144b00ab754SHans Petter Selasky 	bpf_u_int32	interface_id;
145b00ab754SHans Petter Selasky 	bpf_u_int32	timestamp_high;
146b00ab754SHans Petter Selasky 	bpf_u_int32	timestamp_low;
147b00ab754SHans Petter Selasky 	bpf_u_int32	caplen;
148b00ab754SHans Petter Selasky 	bpf_u_int32	len;
149b00ab754SHans Petter Selasky 	/* followed by packet data, options, and trailer */
150b00ab754SHans Petter Selasky };
151b00ab754SHans Petter Selasky 
152b00ab754SHans Petter Selasky /*
153b00ab754SHans Petter Selasky  * Simple Packet Block.
154b00ab754SHans Petter Selasky  */
155b00ab754SHans Petter Selasky #define BT_SPB			0x00000003
156b00ab754SHans Petter Selasky 
157b00ab754SHans Petter Selasky struct simple_packet_block {
158b00ab754SHans Petter Selasky 	bpf_u_int32	len;
159b00ab754SHans Petter Selasky 	/* followed by packet data and trailer */
160b00ab754SHans Petter Selasky };
161b00ab754SHans Petter Selasky 
162b00ab754SHans Petter Selasky /*
163b00ab754SHans Petter Selasky  * Packet Block.
164b00ab754SHans Petter Selasky  */
165b00ab754SHans Petter Selasky #define BT_PB			0x00000002
166b00ab754SHans Petter Selasky 
167b00ab754SHans Petter Selasky struct packet_block {
168b00ab754SHans Petter Selasky 	u_short		interface_id;
169b00ab754SHans Petter Selasky 	u_short		drops_count;
170b00ab754SHans Petter Selasky 	bpf_u_int32	timestamp_high;
171b00ab754SHans Petter Selasky 	bpf_u_int32	timestamp_low;
172b00ab754SHans Petter Selasky 	bpf_u_int32	caplen;
173b00ab754SHans Petter Selasky 	bpf_u_int32	len;
174b00ab754SHans Petter Selasky 	/* followed by packet data, options, and trailer */
175b00ab754SHans Petter Selasky };
176b00ab754SHans Petter Selasky 
177b00ab754SHans Petter Selasky /*
178b00ab754SHans Petter Selasky  * Block cursor - used when processing the contents of a block.
179b00ab754SHans Petter Selasky  * Contains a pointer into the data being processed and a count
180b00ab754SHans Petter Selasky  * of bytes remaining in the block.
181b00ab754SHans Petter Selasky  */
182b00ab754SHans Petter Selasky struct block_cursor {
183b00ab754SHans Petter Selasky 	u_char		*data;
184b00ab754SHans Petter Selasky 	size_t		data_remaining;
185b00ab754SHans Petter Selasky 	bpf_u_int32	block_type;
186b00ab754SHans Petter Selasky };
187b00ab754SHans Petter Selasky 
188b00ab754SHans Petter Selasky typedef enum {
189b00ab754SHans Petter Selasky 	PASS_THROUGH,
190b00ab754SHans Petter Selasky 	SCALE_UP_DEC,
191b00ab754SHans Petter Selasky 	SCALE_DOWN_DEC,
192b00ab754SHans Petter Selasky 	SCALE_UP_BIN,
193b00ab754SHans Petter Selasky 	SCALE_DOWN_BIN
194b00ab754SHans Petter Selasky } tstamp_scale_type_t;
195b00ab754SHans Petter Selasky 
196b00ab754SHans Petter Selasky /*
197b00ab754SHans Petter Selasky  * Per-interface information.
198b00ab754SHans Petter Selasky  */
199b00ab754SHans Petter Selasky struct pcap_ng_if {
2006f9cba8fSJoseph Mingrone 	uint32_t snaplen;		/* snapshot length */
20157e22627SCy Schubert 	uint64_t tsresol;		/* time stamp resolution */
202b00ab754SHans Petter Selasky 	tstamp_scale_type_t scale_type;	/* how to scale */
20357e22627SCy Schubert 	uint64_t scale_factor;		/* time stamp scale factor for power-of-10 tsresol */
204*afdbf109SJoseph Mingrone 	int64_t tsoffset;		/* time stamp offset */
205b00ab754SHans Petter Selasky };
206b00ab754SHans Petter Selasky 
207b00ab754SHans Petter Selasky /*
208b00ab754SHans Petter Selasky  * Per-pcap_t private data.
209b00ab754SHans Petter Selasky  *
210b00ab754SHans Petter Selasky  * max_blocksize is the maximum size of a block that we'll accept.  We
211b00ab754SHans Petter Selasky  * reject blocks bigger than this, so we don't consume too much memory
212b00ab754SHans Petter Selasky  * with a truly huge block.  It can change as we see IDBs with different
213b00ab754SHans Petter Selasky  * link-layer header types.  (Currently, we don't support IDBs with
214b00ab754SHans Petter Selasky  * different link-layer header types, but we will support it in the
215b00ab754SHans Petter Selasky  * future, when we offer file-reading APIs that support it.)
216b00ab754SHans Petter Selasky  *
217b00ab754SHans Petter Selasky  * XXX - that's an issue on ILP32 platforms, where the maximum block
218b00ab754SHans Petter Selasky  * size of 2^31-1 would eat all but one byte of the entire address space.
219b00ab754SHans Petter Selasky  * It's less of an issue on ILP64/LLP64 platforms, but the actual size
220b00ab754SHans Petter Selasky  * of the address space may be limited by 1) the number of *significant*
221b00ab754SHans Petter Selasky  * address bits (currently, x86-64 only supports 48 bits of address), 2)
222b00ab754SHans Petter Selasky  * any limitations imposed by the operating system; 3) any limitations
223b00ab754SHans Petter Selasky  * imposed by the amount of available backing store for anonymous pages,
224b00ab754SHans Petter Selasky  * so we impose a limit regardless of the size of a pointer.
225b00ab754SHans Petter Selasky  */
226b00ab754SHans Petter Selasky struct pcap_ng_sf {
22757e22627SCy Schubert 	uint64_t user_tsresol;		/* time stamp resolution requested by the user */
228b00ab754SHans Petter Selasky 	u_int max_blocksize;		/* don't grow buffer size past this */
229b00ab754SHans Petter Selasky 	bpf_u_int32 ifcount;		/* number of interfaces seen in this capture */
230b00ab754SHans Petter Selasky 	bpf_u_int32 ifaces_size;	/* size of array below */
231b00ab754SHans Petter Selasky 	struct pcap_ng_if *ifaces;	/* array of interface information */
232b00ab754SHans Petter Selasky };
233b00ab754SHans Petter Selasky 
234b00ab754SHans Petter Selasky /*
23557e22627SCy Schubert  * The maximum block size we start with; we use an arbitrary value of
23657e22627SCy Schubert  * 16 MiB.
237b00ab754SHans Petter Selasky  */
23857e22627SCy Schubert #define INITIAL_MAX_BLOCKSIZE	(16*1024*1024)
23957e22627SCy Schubert 
24057e22627SCy Schubert /*
24157e22627SCy Schubert  * Maximum block size for a given maximum snapshot length; we define it
24257e22627SCy Schubert  * as the size of an EPB with a max_snaplen-sized packet and 128KB of
24357e22627SCy Schubert  * options.
24457e22627SCy Schubert  */
24557e22627SCy Schubert #define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \
24657e22627SCy Schubert 	(sizeof (struct block_header) + \
247b00ab754SHans Petter Selasky 	 sizeof (struct enhanced_packet_block) + \
248b00ab754SHans Petter Selasky 	 (max_snaplen) + 131072 + \
249b00ab754SHans Petter Selasky 	 sizeof (struct block_trailer))
250b00ab754SHans Petter Selasky 
251b00ab754SHans Petter Selasky static void pcap_ng_cleanup(pcap_t *p);
252b00ab754SHans Petter Selasky static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
253b00ab754SHans Petter Selasky     u_char **data);
254b00ab754SHans Petter Selasky 
255b00ab754SHans Petter Selasky static int
256b00ab754SHans Petter Selasky read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
257b00ab754SHans Petter Selasky     char *errbuf)
258b00ab754SHans Petter Selasky {
259b00ab754SHans Petter Selasky 	size_t amt_read;
260b00ab754SHans Petter Selasky 
261b00ab754SHans Petter Selasky 	amt_read = fread(buf, 1, bytes_to_read, fp);
262b00ab754SHans Petter Selasky 	if (amt_read != bytes_to_read) {
263b00ab754SHans Petter Selasky 		if (ferror(fp)) {
264*afdbf109SJoseph Mingrone 			pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
265b00ab754SHans Petter Selasky 			    errno, "error reading dump file");
266b00ab754SHans Petter Selasky 		} else {
267b00ab754SHans Petter Selasky 			if (amt_read == 0 && !fail_on_eof)
268b00ab754SHans Petter Selasky 				return (0);	/* EOF */
2696f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
2706f9cba8fSJoseph Mingrone 			    "truncated pcapng dump file; tried to read %zu bytes, only got %zu",
27157e22627SCy Schubert 			    bytes_to_read, amt_read);
272b00ab754SHans Petter Selasky 		}
273b00ab754SHans Petter Selasky 		return (-1);
274b00ab754SHans Petter Selasky 	}
275b00ab754SHans Petter Selasky 	return (1);
276b00ab754SHans Petter Selasky }
277b00ab754SHans Petter Selasky 
278b00ab754SHans Petter Selasky static int
279b00ab754SHans Petter Selasky read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
280b00ab754SHans Petter Selasky {
281b00ab754SHans Petter Selasky 	struct pcap_ng_sf *ps;
282b00ab754SHans Petter Selasky 	int status;
283b00ab754SHans Petter Selasky 	struct block_header bhdr;
28457e22627SCy Schubert 	struct block_trailer *btrlr;
285b00ab754SHans Petter Selasky 	u_char *bdata;
286b00ab754SHans Petter Selasky 	size_t data_remaining;
287b00ab754SHans Petter Selasky 
288b00ab754SHans Petter Selasky 	ps = p->priv;
289b00ab754SHans Petter Selasky 
290b00ab754SHans Petter Selasky 	status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
291b00ab754SHans Petter Selasky 	if (status <= 0)
292b00ab754SHans Petter Selasky 		return (status);	/* error or EOF */
293b00ab754SHans Petter Selasky 
294b00ab754SHans Petter Selasky 	if (p->swapped) {
295b00ab754SHans Petter Selasky 		bhdr.block_type = SWAPLONG(bhdr.block_type);
296b00ab754SHans Petter Selasky 		bhdr.total_length = SWAPLONG(bhdr.total_length);
297b00ab754SHans Petter Selasky 	}
298b00ab754SHans Petter Selasky 
299b00ab754SHans Petter Selasky 	/*
300b00ab754SHans Petter Selasky 	 * Is this block "too small" - i.e., is it shorter than a block
301b00ab754SHans Petter Selasky 	 * header plus a block trailer?
302b00ab754SHans Petter Selasky 	 */
303b00ab754SHans Petter Selasky 	if (bhdr.total_length < sizeof(struct block_header) +
304b00ab754SHans Petter Selasky 	    sizeof(struct block_trailer)) {
3056f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
3066f9cba8fSJoseph Mingrone 		    "block in pcapng dump file has a length of %u < %zu",
307b00ab754SHans Petter Selasky 		    bhdr.total_length,
30857e22627SCy Schubert 		    sizeof(struct block_header) + sizeof(struct block_trailer));
30957e22627SCy Schubert 		return (-1);
31057e22627SCy Schubert 	}
31157e22627SCy Schubert 
31257e22627SCy Schubert 	/*
31357e22627SCy Schubert 	 * Is the block total length a multiple of 4?
31457e22627SCy Schubert 	 */
31557e22627SCy Schubert 	if ((bhdr.total_length % 4) != 0) {
31657e22627SCy Schubert 		/*
31757e22627SCy Schubert 		 * No.  Report that as an error.
31857e22627SCy Schubert 		 */
3196f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
3206f9cba8fSJoseph Mingrone 		    "block in pcapng dump file has a length of %u that is not a multiple of 4",
32157e22627SCy Schubert 		    bhdr.total_length);
322b00ab754SHans Petter Selasky 		return (-1);
323b00ab754SHans Petter Selasky 	}
324b00ab754SHans Petter Selasky 
325b00ab754SHans Petter Selasky 	/*
326b00ab754SHans Petter Selasky 	 * Is the buffer big enough?
327b00ab754SHans Petter Selasky 	 */
328b00ab754SHans Petter Selasky 	if (p->bufsize < bhdr.total_length) {
329b00ab754SHans Petter Selasky 		/*
33057e22627SCy Schubert 		 * No - make it big enough, unless it's too big, in
33157e22627SCy Schubert 		 * which case we fail.
332b00ab754SHans Petter Selasky 		 */
333b00ab754SHans Petter Selasky 		void *bigger_buffer;
334b00ab754SHans Petter Selasky 
335b00ab754SHans Petter Selasky 		if (bhdr.total_length > ps->max_blocksize) {
3366f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length,
337b00ab754SHans Petter Selasky 			    ps->max_blocksize);
338b00ab754SHans Petter Selasky 			return (-1);
339b00ab754SHans Petter Selasky 		}
340b00ab754SHans Petter Selasky 		bigger_buffer = realloc(p->buffer, bhdr.total_length);
341b00ab754SHans Petter Selasky 		if (bigger_buffer == NULL) {
3426f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
343b00ab754SHans Petter Selasky 			return (-1);
344b00ab754SHans Petter Selasky 		}
345b00ab754SHans Petter Selasky 		p->buffer = bigger_buffer;
346b00ab754SHans Petter Selasky 	}
347b00ab754SHans Petter Selasky 
348b00ab754SHans Petter Selasky 	/*
349b00ab754SHans Petter Selasky 	 * Copy the stuff we've read to the buffer, and read the rest
350b00ab754SHans Petter Selasky 	 * of the block.
351b00ab754SHans Petter Selasky 	 */
352b00ab754SHans Petter Selasky 	memcpy(p->buffer, &bhdr, sizeof(bhdr));
353b00ab754SHans Petter Selasky 	bdata = (u_char *)p->buffer + sizeof(bhdr);
354b00ab754SHans Petter Selasky 	data_remaining = bhdr.total_length - sizeof(bhdr);
355b00ab754SHans Petter Selasky 	if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
356b00ab754SHans Petter Selasky 		return (-1);
357b00ab754SHans Petter Selasky 
358b00ab754SHans Petter Selasky 	/*
35957e22627SCy Schubert 	 * Get the block size from the trailer.
36057e22627SCy Schubert 	 */
36157e22627SCy Schubert 	btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer));
36257e22627SCy Schubert 	if (p->swapped)
36357e22627SCy Schubert 		btrlr->total_length = SWAPLONG(btrlr->total_length);
36457e22627SCy Schubert 
36557e22627SCy Schubert 	/*
36657e22627SCy Schubert 	 * Is the total length from the trailer the same as the total
36757e22627SCy Schubert 	 * length from the header?
36857e22627SCy Schubert 	 */
36957e22627SCy Schubert 	if (bhdr.total_length != btrlr->total_length) {
37057e22627SCy Schubert 		/*
37157e22627SCy Schubert 		 * No.
37257e22627SCy Schubert 		 */
3736f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
37457e22627SCy Schubert 		    "block total length in header and trailer don't match");
37557e22627SCy Schubert 		return (-1);
37657e22627SCy Schubert 	}
37757e22627SCy Schubert 
37857e22627SCy Schubert 	/*
379b00ab754SHans Petter Selasky 	 * Initialize the cursor.
380b00ab754SHans Petter Selasky 	 */
381b00ab754SHans Petter Selasky 	cursor->data = bdata;
382b00ab754SHans Petter Selasky 	cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
383b00ab754SHans Petter Selasky 	cursor->block_type = bhdr.block_type;
384b00ab754SHans Petter Selasky 	return (1);
385b00ab754SHans Petter Selasky }
386b00ab754SHans Petter Selasky 
387b00ab754SHans Petter Selasky static void *
388b00ab754SHans Petter Selasky get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
389b00ab754SHans Petter Selasky     char *errbuf)
390b00ab754SHans Petter Selasky {
391b00ab754SHans Petter Selasky 	void *data;
392b00ab754SHans Petter Selasky 
393b00ab754SHans Petter Selasky 	/*
394b00ab754SHans Petter Selasky 	 * Make sure we have the specified amount of data remaining in
395b00ab754SHans Petter Selasky 	 * the block data.
396b00ab754SHans Petter Selasky 	 */
397b00ab754SHans Petter Selasky 	if (cursor->data_remaining < chunk_size) {
3986f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
399b00ab754SHans Petter Selasky 		    "block of type %u in pcapng dump file is too short",
400b00ab754SHans Petter Selasky 		    cursor->block_type);
401b00ab754SHans Petter Selasky 		return (NULL);
402b00ab754SHans Petter Selasky 	}
403b00ab754SHans Petter Selasky 
404b00ab754SHans Petter Selasky 	/*
405b00ab754SHans Petter Selasky 	 * Return the current pointer, and skip past the chunk.
406b00ab754SHans Petter Selasky 	 */
407b00ab754SHans Petter Selasky 	data = cursor->data;
408b00ab754SHans Petter Selasky 	cursor->data += chunk_size;
409b00ab754SHans Petter Selasky 	cursor->data_remaining -= chunk_size;
410b00ab754SHans Petter Selasky 	return (data);
411b00ab754SHans Petter Selasky }
412b00ab754SHans Petter Selasky 
413b00ab754SHans Petter Selasky static struct option_header *
414b00ab754SHans Petter Selasky get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
415b00ab754SHans Petter Selasky {
416b00ab754SHans Petter Selasky 	struct option_header *opthdr;
417b00ab754SHans Petter Selasky 
418b00ab754SHans Petter Selasky 	opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
419b00ab754SHans Petter Selasky 	if (opthdr == NULL) {
420b00ab754SHans Petter Selasky 		/*
421b00ab754SHans Petter Selasky 		 * Option header is cut short.
422b00ab754SHans Petter Selasky 		 */
423b00ab754SHans Petter Selasky 		return (NULL);
424b00ab754SHans Petter Selasky 	}
425b00ab754SHans Petter Selasky 
426b00ab754SHans Petter Selasky 	/*
427b00ab754SHans Petter Selasky 	 * Byte-swap it if necessary.
428b00ab754SHans Petter Selasky 	 */
429b00ab754SHans Petter Selasky 	if (p->swapped) {
430b00ab754SHans Petter Selasky 		opthdr->option_code = SWAPSHORT(opthdr->option_code);
431b00ab754SHans Petter Selasky 		opthdr->option_length = SWAPSHORT(opthdr->option_length);
432b00ab754SHans Petter Selasky 	}
433b00ab754SHans Petter Selasky 
434b00ab754SHans Petter Selasky 	return (opthdr);
435b00ab754SHans Petter Selasky }
436b00ab754SHans Petter Selasky 
437b00ab754SHans Petter Selasky static void *
438b00ab754SHans Petter Selasky get_optvalue_from_block_data(struct block_cursor *cursor,
439b00ab754SHans Petter Selasky     struct option_header *opthdr, char *errbuf)
440b00ab754SHans Petter Selasky {
441b00ab754SHans Petter Selasky 	size_t padded_option_len;
442b00ab754SHans Petter Selasky 	void *optvalue;
443b00ab754SHans Petter Selasky 
444b00ab754SHans Petter Selasky 	/* Pad option length to 4-byte boundary */
445b00ab754SHans Petter Selasky 	padded_option_len = opthdr->option_length;
446b00ab754SHans Petter Selasky 	padded_option_len = ((padded_option_len + 3)/4)*4;
447b00ab754SHans Petter Selasky 
448b00ab754SHans Petter Selasky 	optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
449b00ab754SHans Petter Selasky 	if (optvalue == NULL) {
450b00ab754SHans Petter Selasky 		/*
451b00ab754SHans Petter Selasky 		 * Option value is cut short.
452b00ab754SHans Petter Selasky 		 */
453b00ab754SHans Petter Selasky 		return (NULL);
454b00ab754SHans Petter Selasky 	}
455b00ab754SHans Petter Selasky 
456b00ab754SHans Petter Selasky 	return (optvalue);
457b00ab754SHans Petter Selasky }
458b00ab754SHans Petter Selasky 
459b00ab754SHans Petter Selasky static int
46057e22627SCy Schubert process_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol,
461*afdbf109SJoseph Mingrone     int64_t *tsoffset, int *is_binary, char *errbuf)
462b00ab754SHans Petter Selasky {
463b00ab754SHans Petter Selasky 	struct option_header *opthdr;
464b00ab754SHans Petter Selasky 	void *optvalue;
465b00ab754SHans Petter Selasky 	int saw_tsresol, saw_tsoffset;
46657e22627SCy Schubert 	uint8_t tsresol_opt;
467b00ab754SHans Petter Selasky 	u_int i;
468b00ab754SHans Petter Selasky 
469b00ab754SHans Petter Selasky 	saw_tsresol = 0;
470b00ab754SHans Petter Selasky 	saw_tsoffset = 0;
471b00ab754SHans Petter Selasky 	while (cursor->data_remaining != 0) {
472b00ab754SHans Petter Selasky 		/*
473b00ab754SHans Petter Selasky 		 * Get the option header.
474b00ab754SHans Petter Selasky 		 */
475b00ab754SHans Petter Selasky 		opthdr = get_opthdr_from_block_data(p, cursor, errbuf);
476b00ab754SHans Petter Selasky 		if (opthdr == NULL) {
477b00ab754SHans Petter Selasky 			/*
478b00ab754SHans Petter Selasky 			 * Option header is cut short.
479b00ab754SHans Petter Selasky 			 */
480b00ab754SHans Petter Selasky 			return (-1);
481b00ab754SHans Petter Selasky 		}
482b00ab754SHans Petter Selasky 
483b00ab754SHans Petter Selasky 		/*
484b00ab754SHans Petter Selasky 		 * Get option value.
485b00ab754SHans Petter Selasky 		 */
486b00ab754SHans Petter Selasky 		optvalue = get_optvalue_from_block_data(cursor, opthdr,
487b00ab754SHans Petter Selasky 		    errbuf);
488b00ab754SHans Petter Selasky 		if (optvalue == NULL) {
489b00ab754SHans Petter Selasky 			/*
490b00ab754SHans Petter Selasky 			 * Option value is cut short.
491b00ab754SHans Petter Selasky 			 */
492b00ab754SHans Petter Selasky 			return (-1);
493b00ab754SHans Petter Selasky 		}
494b00ab754SHans Petter Selasky 
495b00ab754SHans Petter Selasky 		switch (opthdr->option_code) {
496b00ab754SHans Petter Selasky 
497b00ab754SHans Petter Selasky 		case OPT_ENDOFOPT:
498b00ab754SHans Petter Selasky 			if (opthdr->option_length != 0) {
4996f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
500b00ab754SHans Petter Selasky 				    "Interface Description Block has opt_endofopt option with length %u != 0",
501b00ab754SHans Petter Selasky 				    opthdr->option_length);
502b00ab754SHans Petter Selasky 				return (-1);
503b00ab754SHans Petter Selasky 			}
504b00ab754SHans Petter Selasky 			goto done;
505b00ab754SHans Petter Selasky 
506b00ab754SHans Petter Selasky 		case IF_TSRESOL:
507b00ab754SHans Petter Selasky 			if (opthdr->option_length != 1) {
5086f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
509b00ab754SHans Petter Selasky 				    "Interface Description Block has if_tsresol option with length %u != 1",
510b00ab754SHans Petter Selasky 				    opthdr->option_length);
511b00ab754SHans Petter Selasky 				return (-1);
512b00ab754SHans Petter Selasky 			}
513b00ab754SHans Petter Selasky 			if (saw_tsresol) {
5146f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
515b00ab754SHans Petter Selasky 				    "Interface Description Block has more than one if_tsresol option");
516b00ab754SHans Petter Selasky 				return (-1);
517b00ab754SHans Petter Selasky 			}
518b00ab754SHans Petter Selasky 			saw_tsresol = 1;
519b00ab754SHans Petter Selasky 			memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt));
520b00ab754SHans Petter Selasky 			if (tsresol_opt & 0x80) {
521b00ab754SHans Petter Selasky 				/*
522b00ab754SHans Petter Selasky 				 * Resolution is negative power of 2.
523b00ab754SHans Petter Selasky 				 */
52457e22627SCy Schubert 				uint8_t tsresol_shift = (tsresol_opt & 0x7F);
52557e22627SCy Schubert 
52657e22627SCy Schubert 				if (tsresol_shift > 63) {
52757e22627SCy Schubert 					/*
52857e22627SCy Schubert 					 * Resolution is too high; 2^-{res}
52957e22627SCy Schubert 					 * won't fit in a 64-bit value.
53057e22627SCy Schubert 					 */
5316f9cba8fSJoseph Mingrone 					snprintf(errbuf, PCAP_ERRBUF_SIZE,
53257e22627SCy Schubert 					    "Interface Description Block if_tsresol option resolution 2^-%u is too high",
53357e22627SCy Schubert 					    tsresol_shift);
53457e22627SCy Schubert 					return (-1);
53557e22627SCy Schubert 				}
536b00ab754SHans Petter Selasky 				*is_binary = 1;
53757e22627SCy Schubert 				*tsresol = ((uint64_t)1) << tsresol_shift;
538b00ab754SHans Petter Selasky 			} else {
539b00ab754SHans Petter Selasky 				/*
540b00ab754SHans Petter Selasky 				 * Resolution is negative power of 10.
541b00ab754SHans Petter Selasky 				 */
54257e22627SCy Schubert 				if (tsresol_opt > 19) {
54357e22627SCy Schubert 					/*
54457e22627SCy Schubert 					 * Resolution is too high; 2^-{res}
54557e22627SCy Schubert 					 * won't fit in a 64-bit value (the
54657e22627SCy Schubert 					 * largest power of 10 that fits
54757e22627SCy Schubert 					 * in a 64-bit value is 10^19, as
54857e22627SCy Schubert 					 * the largest 64-bit unsigned
54957e22627SCy Schubert 					 * value is ~1.8*10^19).
55057e22627SCy Schubert 					 */
5516f9cba8fSJoseph Mingrone 					snprintf(errbuf, PCAP_ERRBUF_SIZE,
55257e22627SCy Schubert 					    "Interface Description Block if_tsresol option resolution 10^-%u is too high",
55357e22627SCy Schubert 					    tsresol_opt);
55457e22627SCy Schubert 					return (-1);
55557e22627SCy Schubert 				}
556b00ab754SHans Petter Selasky 				*is_binary = 0;
557b00ab754SHans Petter Selasky 				*tsresol = 1;
558b00ab754SHans Petter Selasky 				for (i = 0; i < tsresol_opt; i++)
559b00ab754SHans Petter Selasky 					*tsresol *= 10;
560b00ab754SHans Petter Selasky 			}
561b00ab754SHans Petter Selasky 			break;
562b00ab754SHans Petter Selasky 
563b00ab754SHans Petter Selasky 		case IF_TSOFFSET:
564b00ab754SHans Petter Selasky 			if (opthdr->option_length != 8) {
5656f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
566b00ab754SHans Petter Selasky 				    "Interface Description Block has if_tsoffset option with length %u != 8",
567b00ab754SHans Petter Selasky 				    opthdr->option_length);
568b00ab754SHans Petter Selasky 				return (-1);
569b00ab754SHans Petter Selasky 			}
570b00ab754SHans Petter Selasky 			if (saw_tsoffset) {
5716f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
572b00ab754SHans Petter Selasky 				    "Interface Description Block has more than one if_tsoffset option");
573b00ab754SHans Petter Selasky 				return (-1);
574b00ab754SHans Petter Selasky 			}
575b00ab754SHans Petter Selasky 			saw_tsoffset = 1;
576b00ab754SHans Petter Selasky 			memcpy(tsoffset, optvalue, sizeof(*tsoffset));
577b00ab754SHans Petter Selasky 			if (p->swapped)
578b00ab754SHans Petter Selasky 				*tsoffset = SWAPLL(*tsoffset);
579b00ab754SHans Petter Selasky 			break;
580b00ab754SHans Petter Selasky 
581b00ab754SHans Petter Selasky 		default:
582b00ab754SHans Petter Selasky 			break;
583b00ab754SHans Petter Selasky 		}
584b00ab754SHans Petter Selasky 	}
585b00ab754SHans Petter Selasky 
586b00ab754SHans Petter Selasky done:
587b00ab754SHans Petter Selasky 	return (0);
588b00ab754SHans Petter Selasky }
589b00ab754SHans Petter Selasky 
590b00ab754SHans Petter Selasky static int
5916f9cba8fSJoseph Mingrone add_interface(pcap_t *p, struct interface_description_block *idbp,
5926f9cba8fSJoseph Mingrone     struct block_cursor *cursor, char *errbuf)
593b00ab754SHans Petter Selasky {
594b00ab754SHans Petter Selasky 	struct pcap_ng_sf *ps;
59557e22627SCy Schubert 	uint64_t tsresol;
596*afdbf109SJoseph Mingrone 	int64_t tsoffset;
597b00ab754SHans Petter Selasky 	int is_binary;
598b00ab754SHans Petter Selasky 
599b00ab754SHans Petter Selasky 	ps = p->priv;
600b00ab754SHans Petter Selasky 
601b00ab754SHans Petter Selasky 	/*
602b00ab754SHans Petter Selasky 	 * Count this interface.
603b00ab754SHans Petter Selasky 	 */
604b00ab754SHans Petter Selasky 	ps->ifcount++;
605b00ab754SHans Petter Selasky 
606b00ab754SHans Petter Selasky 	/*
607b00ab754SHans Petter Selasky 	 * Grow the array of per-interface information as necessary.
608b00ab754SHans Petter Selasky 	 */
609b00ab754SHans Petter Selasky 	if (ps->ifcount > ps->ifaces_size) {
610b00ab754SHans Petter Selasky 		/*
611b00ab754SHans Petter Selasky 		 * We need to grow the array.
612b00ab754SHans Petter Selasky 		 */
613b00ab754SHans Petter Selasky 		bpf_u_int32 new_ifaces_size;
614b00ab754SHans Petter Selasky 		struct pcap_ng_if *new_ifaces;
615b00ab754SHans Petter Selasky 
616b00ab754SHans Petter Selasky 		if (ps->ifaces_size == 0) {
617b00ab754SHans Petter Selasky 			/*
618b00ab754SHans Petter Selasky 			 * It's currently empty.
619b00ab754SHans Petter Selasky 			 *
620b00ab754SHans Petter Selasky 			 * (The Clang static analyzer doesn't do enough,
621b00ab754SHans Petter Selasky 			 * err, umm, dataflow *analysis* to realize that
622b00ab754SHans Petter Selasky 			 * ps->ifaces_size == 0 if ps->ifaces == NULL,
623b00ab754SHans Petter Selasky 			 * and so complains about a possible zero argument
624b00ab754SHans Petter Selasky 			 * to realloc(), so we check for the former
625b00ab754SHans Petter Selasky 			 * condition to shut it up.
626b00ab754SHans Petter Selasky 			 *
627b00ab754SHans Petter Selasky 			 * However, it doesn't complain that one of the
628b00ab754SHans Petter Selasky 			 * multiplications below could overflow, which is
629b00ab754SHans Petter Selasky 			 * a real, albeit extremely unlikely, problem (you'd
630b00ab754SHans Petter Selasky 			 * need a pcapng file with tens of millions of
631b00ab754SHans Petter Selasky 			 * interfaces).)
632b00ab754SHans Petter Selasky 			 */
633b00ab754SHans Petter Selasky 			new_ifaces_size = 1;
634b00ab754SHans Petter Selasky 			new_ifaces = malloc(sizeof (struct pcap_ng_if));
635b00ab754SHans Petter Selasky 		} else {
636b00ab754SHans Petter Selasky 			/*
637b00ab754SHans Petter Selasky 			 * It's not currently empty; double its size.
638b00ab754SHans Petter Selasky 			 * (Perhaps overkill once we have a lot of interfaces.)
639b00ab754SHans Petter Selasky 			 *
640b00ab754SHans Petter Selasky 			 * Check for overflow if we double it.
641b00ab754SHans Petter Selasky 			 */
642b00ab754SHans Petter Selasky 			if (ps->ifaces_size * 2 < ps->ifaces_size) {
643b00ab754SHans Petter Selasky 				/*
644b00ab754SHans Petter Selasky 				 * The maximum number of interfaces before
645b00ab754SHans Petter Selasky 				 * ps->ifaces_size overflows is the largest
646b00ab754SHans Petter Selasky 				 * possible 32-bit power of 2, as we do
647b00ab754SHans Petter Selasky 				 * size doubling.
648b00ab754SHans Petter Selasky 				 */
6496f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
650b00ab754SHans Petter Selasky 				    "more than %u interfaces in the file",
651b00ab754SHans Petter Selasky 				    0x80000000U);
652b00ab754SHans Petter Selasky 				return (0);
653b00ab754SHans Petter Selasky 			}
654b00ab754SHans Petter Selasky 
655b00ab754SHans Petter Selasky 			/*
656b00ab754SHans Petter Selasky 			 * ps->ifaces_size * 2 doesn't overflow, so it's
657b00ab754SHans Petter Selasky 			 * safe to multiply.
658b00ab754SHans Petter Selasky 			 */
659b00ab754SHans Petter Selasky 			new_ifaces_size = ps->ifaces_size * 2;
660b00ab754SHans Petter Selasky 
661b00ab754SHans Petter Selasky 			/*
662b00ab754SHans Petter Selasky 			 * Now make sure that's not so big that it overflows
663b00ab754SHans Petter Selasky 			 * if we multiply by sizeof (struct pcap_ng_if).
664b00ab754SHans Petter Selasky 			 *
665b00ab754SHans Petter Selasky 			 * That can happen on 32-bit platforms, with a 32-bit
666b00ab754SHans Petter Selasky 			 * size_t; it shouldn't happen on 64-bit platforms,
667b00ab754SHans Petter Selasky 			 * with a 64-bit size_t, as new_ifaces_size is
668b00ab754SHans Petter Selasky 			 * 32 bits.
669b00ab754SHans Petter Selasky 			 */
670b00ab754SHans Petter Selasky 			if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
671b00ab754SHans Petter Selasky 				/*
672b00ab754SHans Petter Selasky 				 * As this fails only with 32-bit size_t,
673b00ab754SHans Petter Selasky 				 * the multiplication was 32x32->32, and
674b00ab754SHans Petter Selasky 				 * the largest 32-bit value that can safely
675b00ab754SHans Petter Selasky 				 * be multiplied by sizeof (struct pcap_ng_if)
676b00ab754SHans Petter Selasky 				 * without overflow is the largest 32-bit
677b00ab754SHans Petter Selasky 				 * (unsigned) value divided by
678b00ab754SHans Petter Selasky 				 * sizeof (struct pcap_ng_if).
679b00ab754SHans Petter Selasky 				 */
6806f9cba8fSJoseph Mingrone 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
681b00ab754SHans Petter Selasky 				    "more than %u interfaces in the file",
682b00ab754SHans Petter Selasky 				    0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
683b00ab754SHans Petter Selasky 				return (0);
684b00ab754SHans Petter Selasky 			}
685b00ab754SHans Petter Selasky 			new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
686b00ab754SHans Petter Selasky 		}
687b00ab754SHans Petter Selasky 		if (new_ifaces == NULL) {
688b00ab754SHans Petter Selasky 			/*
689b00ab754SHans Petter Selasky 			 * We ran out of memory.
690b00ab754SHans Petter Selasky 			 * Give up.
691b00ab754SHans Petter Selasky 			 */
6926f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
693b00ab754SHans Petter Selasky 			    "out of memory for per-interface information (%u interfaces)",
694b00ab754SHans Petter Selasky 			    ps->ifcount);
695b00ab754SHans Petter Selasky 			return (0);
696b00ab754SHans Petter Selasky 		}
697b00ab754SHans Petter Selasky 		ps->ifaces_size = new_ifaces_size;
698b00ab754SHans Petter Selasky 		ps->ifaces = new_ifaces;
699b00ab754SHans Petter Selasky 	}
700b00ab754SHans Petter Selasky 
7016f9cba8fSJoseph Mingrone 	ps->ifaces[ps->ifcount - 1].snaplen = idbp->snaplen;
7026f9cba8fSJoseph Mingrone 
703b00ab754SHans Petter Selasky 	/*
704b00ab754SHans Petter Selasky 	 * Set the default time stamp resolution and offset.
705b00ab754SHans Petter Selasky 	 */
706b00ab754SHans Petter Selasky 	tsresol = 1000000;	/* microsecond resolution */
707b00ab754SHans Petter Selasky 	is_binary = 0;		/* which is a power of 10 */
708b00ab754SHans Petter Selasky 	tsoffset = 0;		/* absolute timestamps */
709b00ab754SHans Petter Selasky 
710b00ab754SHans Petter Selasky 	/*
711b00ab754SHans Petter Selasky 	 * Now look for various time stamp options, so we know
712b00ab754SHans Petter Selasky 	 * how to interpret the time stamps for this interface.
713b00ab754SHans Petter Selasky 	 */
714b00ab754SHans Petter Selasky 	if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
715b00ab754SHans Petter Selasky 	    errbuf) == -1)
716b00ab754SHans Petter Selasky 		return (0);
717b00ab754SHans Petter Selasky 
718b00ab754SHans Petter Selasky 	ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
719b00ab754SHans Petter Selasky 	ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
720b00ab754SHans Petter Selasky 
721b00ab754SHans Petter Selasky 	/*
722b00ab754SHans Petter Selasky 	 * Determine whether we're scaling up or down or not
723b00ab754SHans Petter Selasky 	 * at all for this interface.
724b00ab754SHans Petter Selasky 	 */
725b00ab754SHans Petter Selasky 	if (tsresol == ps->user_tsresol) {
726b00ab754SHans Petter Selasky 		/*
727b00ab754SHans Petter Selasky 		 * The resolution is the resolution the user wants,
728b00ab754SHans Petter Selasky 		 * so we don't have to do scaling.
729b00ab754SHans Petter Selasky 		 */
730b00ab754SHans Petter Selasky 		ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
731b00ab754SHans Petter Selasky 	} else if (tsresol > ps->user_tsresol) {
732b00ab754SHans Petter Selasky 		/*
733b00ab754SHans Petter Selasky 		 * The resolution is greater than what the user wants,
734b00ab754SHans Petter Selasky 		 * so we have to scale the timestamps down.
735b00ab754SHans Petter Selasky 		 */
736b00ab754SHans Petter Selasky 		if (is_binary)
737b00ab754SHans Petter Selasky 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
738b00ab754SHans Petter Selasky 		else {
739b00ab754SHans Petter Selasky 			/*
740b00ab754SHans Petter Selasky 			 * Calculate the scale factor.
741b00ab754SHans Petter Selasky 			 */
742b00ab754SHans Petter Selasky 			ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
743b00ab754SHans Petter Selasky 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
744b00ab754SHans Petter Selasky 		}
745b00ab754SHans Petter Selasky 	} else {
746b00ab754SHans Petter Selasky 		/*
747b00ab754SHans Petter Selasky 		 * The resolution is less than what the user wants,
748b00ab754SHans Petter Selasky 		 * so we have to scale the timestamps up.
749b00ab754SHans Petter Selasky 		 */
750b00ab754SHans Petter Selasky 		if (is_binary)
751b00ab754SHans Petter Selasky 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
752b00ab754SHans Petter Selasky 		else {
753b00ab754SHans Petter Selasky 			/*
754b00ab754SHans Petter Selasky 			 * Calculate the scale factor.
755b00ab754SHans Petter Selasky 			 */
756b00ab754SHans Petter Selasky 			ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
757b00ab754SHans Petter Selasky 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
758b00ab754SHans Petter Selasky 		}
759b00ab754SHans Petter Selasky 	}
760b00ab754SHans Petter Selasky 	return (1);
761b00ab754SHans Petter Selasky }
762b00ab754SHans Petter Selasky 
763b00ab754SHans Petter Selasky /*
764b00ab754SHans Petter Selasky  * Check whether this is a pcapng savefile and, if it is, extract the
765b00ab754SHans Petter Selasky  * relevant information from the header.
766b00ab754SHans Petter Selasky  */
767b00ab754SHans Petter Selasky pcap_t *
76857e22627SCy Schubert pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
76957e22627SCy Schubert     char *errbuf, int *err)
770b00ab754SHans Petter Selasky {
77157e22627SCy Schubert 	bpf_u_int32 magic_int;
772b00ab754SHans Petter Selasky 	size_t amt_read;
773b00ab754SHans Petter Selasky 	bpf_u_int32 total_length;
774b00ab754SHans Petter Selasky 	bpf_u_int32 byte_order_magic;
775b00ab754SHans Petter Selasky 	struct block_header *bhdrp;
776b00ab754SHans Petter Selasky 	struct section_header_block *shbp;
777b00ab754SHans Petter Selasky 	pcap_t *p;
778b00ab754SHans Petter Selasky 	int swapped = 0;
779b00ab754SHans Petter Selasky 	struct pcap_ng_sf *ps;
780b00ab754SHans Petter Selasky 	int status;
781b00ab754SHans Petter Selasky 	struct block_cursor cursor;
782b00ab754SHans Petter Selasky 	struct interface_description_block *idbp;
783b00ab754SHans Petter Selasky 
784b00ab754SHans Petter Selasky 	/*
785b00ab754SHans Petter Selasky 	 * Assume no read errors.
786b00ab754SHans Petter Selasky 	 */
787b00ab754SHans Petter Selasky 	*err = 0;
788b00ab754SHans Petter Selasky 
789b00ab754SHans Petter Selasky 	/*
790b00ab754SHans Petter Selasky 	 * Check whether the first 4 bytes of the file are the block
791b00ab754SHans Petter Selasky 	 * type for a pcapng savefile.
792b00ab754SHans Petter Selasky 	 */
79357e22627SCy Schubert 	memcpy(&magic_int, magic, sizeof(magic_int));
79457e22627SCy Schubert 	if (magic_int != BT_SHB) {
795b00ab754SHans Petter Selasky 		/*
796b00ab754SHans Petter Selasky 		 * XXX - check whether this looks like what the block
797b00ab754SHans Petter Selasky 		 * type would be after being munged by mapping between
798b00ab754SHans Petter Selasky 		 * UN*X and DOS/Windows text file format and, if it
799b00ab754SHans Petter Selasky 		 * does, look for the byte-order magic number in
800b00ab754SHans Petter Selasky 		 * the appropriate place and, if we find it, report
801b00ab754SHans Petter Selasky 		 * this as possibly being a pcapng file transferred
802b00ab754SHans Petter Selasky 		 * between UN*X and Windows in text file format?
803b00ab754SHans Petter Selasky 		 */
804b00ab754SHans Petter Selasky 		return (NULL);	/* nope */
805b00ab754SHans Petter Selasky 	}
806b00ab754SHans Petter Selasky 
807b00ab754SHans Petter Selasky 	/*
808b00ab754SHans Petter Selasky 	 * OK, they are.  However, that's just \n\r\r\n, so it could,
809b00ab754SHans Petter Selasky 	 * conceivably, be an ordinary text file.
810b00ab754SHans Petter Selasky 	 *
811b00ab754SHans Petter Selasky 	 * It could not, however, conceivably be any other type of
812b00ab754SHans Petter Selasky 	 * capture file, so we can read the rest of the putative
813b00ab754SHans Petter Selasky 	 * Section Header Block; put the block type in the common
814b00ab754SHans Petter Selasky 	 * header, read the rest of the common header and the
815b00ab754SHans Petter Selasky 	 * fixed-length portion of the SHB, and look for the byte-order
816b00ab754SHans Petter Selasky 	 * magic value.
817b00ab754SHans Petter Selasky 	 */
818b00ab754SHans Petter Selasky 	amt_read = fread(&total_length, 1, sizeof(total_length), fp);
819b00ab754SHans Petter Selasky 	if (amt_read < sizeof(total_length)) {
820b00ab754SHans Petter Selasky 		if (ferror(fp)) {
821*afdbf109SJoseph Mingrone 			pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
822b00ab754SHans Petter Selasky 			    errno, "error reading dump file");
823b00ab754SHans Petter Selasky 			*err = 1;
824b00ab754SHans Petter Selasky 			return (NULL);	/* fail */
825b00ab754SHans Petter Selasky 		}
826b00ab754SHans Petter Selasky 
827b00ab754SHans Petter Selasky 		/*
828b00ab754SHans Petter Selasky 		 * Possibly a weird short text file, so just say
829b00ab754SHans Petter Selasky 		 * "not pcapng".
830b00ab754SHans Petter Selasky 		 */
831b00ab754SHans Petter Selasky 		return (NULL);
832b00ab754SHans Petter Selasky 	}
833b00ab754SHans Petter Selasky 	amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
834b00ab754SHans Petter Selasky 	if (amt_read < sizeof(byte_order_magic)) {
835b00ab754SHans Petter Selasky 		if (ferror(fp)) {
836*afdbf109SJoseph Mingrone 			pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
837b00ab754SHans Petter Selasky 			    errno, "error reading dump file");
838b00ab754SHans Petter Selasky 			*err = 1;
839b00ab754SHans Petter Selasky 			return (NULL);	/* fail */
840b00ab754SHans Petter Selasky 		}
841b00ab754SHans Petter Selasky 
842b00ab754SHans Petter Selasky 		/*
843b00ab754SHans Petter Selasky 		 * Possibly a weird short text file, so just say
844b00ab754SHans Petter Selasky 		 * "not pcapng".
845b00ab754SHans Petter Selasky 		 */
846b00ab754SHans Petter Selasky 		return (NULL);
847b00ab754SHans Petter Selasky 	}
848b00ab754SHans Petter Selasky 	if (byte_order_magic != BYTE_ORDER_MAGIC) {
849b00ab754SHans Petter Selasky 		byte_order_magic = SWAPLONG(byte_order_magic);
850b00ab754SHans Petter Selasky 		if (byte_order_magic != BYTE_ORDER_MAGIC) {
851b00ab754SHans Petter Selasky 			/*
852b00ab754SHans Petter Selasky 			 * Not a pcapng file.
853b00ab754SHans Petter Selasky 			 */
854b00ab754SHans Petter Selasky 			return (NULL);
855b00ab754SHans Petter Selasky 		}
856b00ab754SHans Petter Selasky 		swapped = 1;
857b00ab754SHans Petter Selasky 		total_length = SWAPLONG(total_length);
858b00ab754SHans Petter Selasky 	}
859b00ab754SHans Petter Selasky 
860b00ab754SHans Petter Selasky 	/*
861b00ab754SHans Petter Selasky 	 * Check the sanity of the total length.
862b00ab754SHans Petter Selasky 	 */
86357e22627SCy Schubert 	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) ||
86457e22627SCy Schubert             (total_length > BT_SHB_INSANE_MAX)) {
8656f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
8666f9cba8fSJoseph Mingrone 		    "Section Header Block in pcapng dump file has invalid length %zu < _%u_ < %u (BT_SHB_INSANE_MAX)",
86757e22627SCy Schubert 		    sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer),
868b00ab754SHans Petter Selasky 		    total_length,
86957e22627SCy Schubert 		    BT_SHB_INSANE_MAX);
87057e22627SCy Schubert 
871b00ab754SHans Petter Selasky 		*err = 1;
872b00ab754SHans Petter Selasky 		return (NULL);
873b00ab754SHans Petter Selasky 	}
874b00ab754SHans Petter Selasky 
875b00ab754SHans Petter Selasky 	/*
876b00ab754SHans Petter Selasky 	 * OK, this is a good pcapng file.
877b00ab754SHans Petter Selasky 	 * Allocate a pcap_t for it.
878b00ab754SHans Petter Selasky 	 */
8796f9cba8fSJoseph Mingrone 	p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_ng_sf);
880b00ab754SHans Petter Selasky 	if (p == NULL) {
881b00ab754SHans Petter Selasky 		/* Allocation failed. */
882b00ab754SHans Petter Selasky 		*err = 1;
883b00ab754SHans Petter Selasky 		return (NULL);
884b00ab754SHans Petter Selasky 	}
885b00ab754SHans Petter Selasky 	p->swapped = swapped;
886b00ab754SHans Petter Selasky 	ps = p->priv;
887b00ab754SHans Petter Selasky 
888b00ab754SHans Petter Selasky 	/*
889b00ab754SHans Petter Selasky 	 * What precision does the user want?
890b00ab754SHans Petter Selasky 	 */
891b00ab754SHans Petter Selasky 	switch (precision) {
892b00ab754SHans Petter Selasky 
893b00ab754SHans Petter Selasky 	case PCAP_TSTAMP_PRECISION_MICRO:
894b00ab754SHans Petter Selasky 		ps->user_tsresol = 1000000;
895b00ab754SHans Petter Selasky 		break;
896b00ab754SHans Petter Selasky 
897b00ab754SHans Petter Selasky 	case PCAP_TSTAMP_PRECISION_NANO:
898b00ab754SHans Petter Selasky 		ps->user_tsresol = 1000000000;
899b00ab754SHans Petter Selasky 		break;
900b00ab754SHans Petter Selasky 
901b00ab754SHans Petter Selasky 	default:
9026f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
903b00ab754SHans Petter Selasky 		    "unknown time stamp resolution %u", precision);
904b00ab754SHans Petter Selasky 		free(p);
905b00ab754SHans Petter Selasky 		*err = 1;
906b00ab754SHans Petter Selasky 		return (NULL);
907b00ab754SHans Petter Selasky 	}
908b00ab754SHans Petter Selasky 
909b00ab754SHans Petter Selasky 	p->opt.tstamp_precision = precision;
910b00ab754SHans Petter Selasky 
911b00ab754SHans Petter Selasky 	/*
912b00ab754SHans Petter Selasky 	 * Allocate a buffer into which to read blocks.  We default to
913b00ab754SHans Petter Selasky 	 * the maximum of:
914b00ab754SHans Petter Selasky 	 *
915b00ab754SHans Petter Selasky 	 *	the total length of the SHB for which we read the header;
916b00ab754SHans Petter Selasky 	 *
917b00ab754SHans Petter Selasky 	 *	2K, which should be more than large enough for an Enhanced
918b00ab754SHans Petter Selasky 	 *	Packet Block containing a full-size Ethernet frame, and
919b00ab754SHans Petter Selasky 	 *	leaving room for some options.
920b00ab754SHans Petter Selasky 	 *
921b00ab754SHans Petter Selasky 	 * If we find a bigger block, we reallocate the buffer, up to
92257e22627SCy Schubert 	 * the maximum size.  We start out with a maximum size of
92357e22627SCy Schubert 	 * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types
92457e22627SCy Schubert 	 * with a maximum snapshot that results in a larger maximum
92557e22627SCy Schubert 	 * block length, we boost the maximum.
926b00ab754SHans Petter Selasky 	 */
927b00ab754SHans Petter Selasky 	p->bufsize = 2048;
928b00ab754SHans Petter Selasky 	if (p->bufsize < total_length)
929b00ab754SHans Petter Selasky 		p->bufsize = total_length;
930b00ab754SHans Petter Selasky 	p->buffer = malloc(p->bufsize);
931b00ab754SHans Petter Selasky 	if (p->buffer == NULL) {
9326f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
933b00ab754SHans Petter Selasky 		free(p);
934b00ab754SHans Petter Selasky 		*err = 1;
935b00ab754SHans Petter Selasky 		return (NULL);
936b00ab754SHans Petter Selasky 	}
93757e22627SCy Schubert 	ps->max_blocksize = INITIAL_MAX_BLOCKSIZE;
938b00ab754SHans Petter Selasky 
939b00ab754SHans Petter Selasky 	/*
940b00ab754SHans Petter Selasky 	 * Copy the stuff we've read to the buffer, and read the rest
941b00ab754SHans Petter Selasky 	 * of the SHB.
942b00ab754SHans Petter Selasky 	 */
943b00ab754SHans Petter Selasky 	bhdrp = (struct block_header *)p->buffer;
944b00ab754SHans Petter Selasky 	shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
94557e22627SCy Schubert 	bhdrp->block_type = magic_int;
946b00ab754SHans Petter Selasky 	bhdrp->total_length = total_length;
947b00ab754SHans Petter Selasky 	shbp->byte_order_magic = byte_order_magic;
948b00ab754SHans Petter Selasky 	if (read_bytes(fp,
94957e22627SCy Schubert 	    (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
95057e22627SCy Schubert 	    total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
951b00ab754SHans Petter Selasky 	    1, errbuf) == -1)
952b00ab754SHans Petter Selasky 		goto fail;
953b00ab754SHans Petter Selasky 
954b00ab754SHans Petter Selasky 	if (p->swapped) {
955b00ab754SHans Petter Selasky 		/*
956b00ab754SHans Petter Selasky 		 * Byte-swap the fields we've read.
957b00ab754SHans Petter Selasky 		 */
958b00ab754SHans Petter Selasky 		shbp->major_version = SWAPSHORT(shbp->major_version);
959b00ab754SHans Petter Selasky 		shbp->minor_version = SWAPSHORT(shbp->minor_version);
960b00ab754SHans Petter Selasky 
961b00ab754SHans Petter Selasky 		/*
962b00ab754SHans Petter Selasky 		 * XXX - we don't care about the section length.
963b00ab754SHans Petter Selasky 		 */
964b00ab754SHans Petter Selasky 	}
9656f9cba8fSJoseph Mingrone 	/* Currently only SHB versions 1.0 and 1.2 are supported;
9666f9cba8fSJoseph Mingrone 	   version 1.2 is treated as being the same as version 1.0.
9676f9cba8fSJoseph Mingrone 	   See the current version of the pcapng specification.
9686f9cba8fSJoseph Mingrone 
9696f9cba8fSJoseph Mingrone 	   Version 1.2 is written by some programs that write additional
9706f9cba8fSJoseph Mingrone 	   block types (which can be read by any code that handles them,
9716f9cba8fSJoseph Mingrone 	   regardless of whether the minor version if 0 or 2, so that's
9726f9cba8fSJoseph Mingrone 	   not a reason to change the minor version number).
9736f9cba8fSJoseph Mingrone 
9746f9cba8fSJoseph Mingrone 	   XXX - the pcapng specification says that readers should
9756f9cba8fSJoseph Mingrone 	   just ignore sections with an unsupported version number;
9766f9cba8fSJoseph Mingrone 	   presumably they can also report an error if they skip
9776f9cba8fSJoseph Mingrone 	   all the way to the end of the file without finding
9786f9cba8fSJoseph Mingrone 	   any versions that they support. */
979b00ab754SHans Petter Selasky 	if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
9806f9cba8fSJoseph Mingrone 	       (shbp->minor_version == PCAP_NG_VERSION_MINOR ||
9816f9cba8fSJoseph Mingrone 	        shbp->minor_version == 2))) {
9826f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
983b00ab754SHans Petter Selasky 		    "unsupported pcapng savefile version %u.%u",
984b00ab754SHans Petter Selasky 		    shbp->major_version, shbp->minor_version);
985b00ab754SHans Petter Selasky 		goto fail;
986b00ab754SHans Petter Selasky 	}
987b00ab754SHans Petter Selasky 	p->version_major = shbp->major_version;
988b00ab754SHans Petter Selasky 	p->version_minor = shbp->minor_version;
989b00ab754SHans Petter Selasky 
990b00ab754SHans Petter Selasky 	/*
991b00ab754SHans Petter Selasky 	 * Save the time stamp resolution the user requested.
992b00ab754SHans Petter Selasky 	 */
993b00ab754SHans Petter Selasky 	p->opt.tstamp_precision = precision;
994b00ab754SHans Petter Selasky 
995b00ab754SHans Petter Selasky 	/*
996b00ab754SHans Petter Selasky 	 * Now start looking for an Interface Description Block.
997b00ab754SHans Petter Selasky 	 */
998b00ab754SHans Petter Selasky 	for (;;) {
999b00ab754SHans Petter Selasky 		/*
1000b00ab754SHans Petter Selasky 		 * Read the next block.
1001b00ab754SHans Petter Selasky 		 */
1002b00ab754SHans Petter Selasky 		status = read_block(fp, p, &cursor, errbuf);
1003b00ab754SHans Petter Selasky 		if (status == 0) {
1004b00ab754SHans Petter Selasky 			/* EOF - no IDB in this file */
10056f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
1006b00ab754SHans Petter Selasky 			    "the capture file has no Interface Description Blocks");
1007b00ab754SHans Petter Selasky 			goto fail;
1008b00ab754SHans Petter Selasky 		}
1009b00ab754SHans Petter Selasky 		if (status == -1)
1010b00ab754SHans Petter Selasky 			goto fail;	/* error */
1011b00ab754SHans Petter Selasky 		switch (cursor.block_type) {
1012b00ab754SHans Petter Selasky 
1013b00ab754SHans Petter Selasky 		case BT_IDB:
1014b00ab754SHans Petter Selasky 			/*
1015b00ab754SHans Petter Selasky 			 * Get a pointer to the fixed-length portion of the
1016b00ab754SHans Petter Selasky 			 * IDB.
1017b00ab754SHans Petter Selasky 			 */
1018b00ab754SHans Petter Selasky 			idbp = get_from_block_data(&cursor, sizeof(*idbp),
1019b00ab754SHans Petter Selasky 			    errbuf);
1020b00ab754SHans Petter Selasky 			if (idbp == NULL)
1021b00ab754SHans Petter Selasky 				goto fail;	/* error */
1022b00ab754SHans Petter Selasky 
1023b00ab754SHans Petter Selasky 			/*
1024b00ab754SHans Petter Selasky 			 * Byte-swap it if necessary.
1025b00ab754SHans Petter Selasky 			 */
1026b00ab754SHans Petter Selasky 			if (p->swapped) {
1027b00ab754SHans Petter Selasky 				idbp->linktype = SWAPSHORT(idbp->linktype);
1028b00ab754SHans Petter Selasky 				idbp->snaplen = SWAPLONG(idbp->snaplen);
1029b00ab754SHans Petter Selasky 			}
1030b00ab754SHans Petter Selasky 
1031b00ab754SHans Petter Selasky 			/*
1032b00ab754SHans Petter Selasky 			 * Try to add this interface.
1033b00ab754SHans Petter Selasky 			 */
10346f9cba8fSJoseph Mingrone 			if (!add_interface(p, idbp, &cursor, errbuf))
1035b00ab754SHans Petter Selasky 				goto fail;
1036b00ab754SHans Petter Selasky 
1037b00ab754SHans Petter Selasky 			goto done;
1038b00ab754SHans Petter Selasky 
1039b00ab754SHans Petter Selasky 		case BT_EPB:
1040b00ab754SHans Petter Selasky 		case BT_SPB:
1041b00ab754SHans Petter Selasky 		case BT_PB:
1042b00ab754SHans Petter Selasky 			/*
1043b00ab754SHans Petter Selasky 			 * Saw a packet before we saw any IDBs.  That's
1044b00ab754SHans Petter Selasky 			 * not valid, as we don't know what link-layer
1045b00ab754SHans Petter Selasky 			 * encapsulation the packet has.
1046b00ab754SHans Petter Selasky 			 */
10476f9cba8fSJoseph Mingrone 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
1048b00ab754SHans Petter Selasky 			    "the capture file has a packet block before any Interface Description Blocks");
1049b00ab754SHans Petter Selasky 			goto fail;
1050b00ab754SHans Petter Selasky 
1051b00ab754SHans Petter Selasky 		default:
1052b00ab754SHans Petter Selasky 			/*
1053b00ab754SHans Petter Selasky 			 * Just ignore it.
1054b00ab754SHans Petter Selasky 			 */
1055b00ab754SHans Petter Selasky 			break;
1056b00ab754SHans Petter Selasky 		}
1057b00ab754SHans Petter Selasky 	}
1058b00ab754SHans Petter Selasky 
1059b00ab754SHans Petter Selasky done:
1060b00ab754SHans Petter Selasky 	p->linktype = linktype_to_dlt(idbp->linktype);
1061*afdbf109SJoseph Mingrone 	p->snapshot = pcapint_adjust_snapshot(p->linktype, idbp->snaplen);
1062b00ab754SHans Petter Selasky 	p->linktype_ext = 0;
1063b00ab754SHans Petter Selasky 
1064b00ab754SHans Petter Selasky 	/*
1065b00ab754SHans Petter Selasky 	 * If the maximum block size for a packet with the maximum
1066b00ab754SHans Petter Selasky 	 * snapshot length for this DLT_ is bigger than the current
1067b00ab754SHans Petter Selasky 	 * maximum block size, increase the maximum.
1068b00ab754SHans Petter Selasky 	 */
106957e22627SCy Schubert 	if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
107057e22627SCy Schubert 		ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype));
1071b00ab754SHans Petter Selasky 
1072b00ab754SHans Petter Selasky 	p->next_packet_op = pcap_ng_next_packet;
1073b00ab754SHans Petter Selasky 	p->cleanup_op = pcap_ng_cleanup;
1074b00ab754SHans Petter Selasky 
1075b00ab754SHans Petter Selasky 	return (p);
1076b00ab754SHans Petter Selasky 
1077b00ab754SHans Petter Selasky fail:
1078b00ab754SHans Petter Selasky 	free(ps->ifaces);
1079b00ab754SHans Petter Selasky 	free(p->buffer);
1080b00ab754SHans Petter Selasky 	free(p);
1081b00ab754SHans Petter Selasky 	*err = 1;
1082b00ab754SHans Petter Selasky 	return (NULL);
1083b00ab754SHans Petter Selasky }
1084b00ab754SHans Petter Selasky 
1085b00ab754SHans Petter Selasky static void
1086b00ab754SHans Petter Selasky pcap_ng_cleanup(pcap_t *p)
1087b00ab754SHans Petter Selasky {
1088b00ab754SHans Petter Selasky 	struct pcap_ng_sf *ps = p->priv;
1089b00ab754SHans Petter Selasky 
1090b00ab754SHans Petter Selasky 	free(ps->ifaces);
1091*afdbf109SJoseph Mingrone 	pcapint_sf_cleanup(p);
1092b00ab754SHans Petter Selasky }
1093b00ab754SHans Petter Selasky 
1094b00ab754SHans Petter Selasky /*
1095b00ab754SHans Petter Selasky  * Read and return the next packet from the savefile.  Return the header
10966f9cba8fSJoseph Mingrone  * in hdr and a pointer to the contents in data.  Return 1 on success, 0
1097b00ab754SHans Petter Selasky  * if there were no more packets, and -1 on an error.
1098b00ab754SHans Petter Selasky  */
1099b00ab754SHans Petter Selasky static int
1100b00ab754SHans Petter Selasky pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
1101b00ab754SHans Petter Selasky {
1102b00ab754SHans Petter Selasky 	struct pcap_ng_sf *ps = p->priv;
1103b00ab754SHans Petter Selasky 	struct block_cursor cursor;
1104b00ab754SHans Petter Selasky 	int status;
1105b00ab754SHans Petter Selasky 	struct enhanced_packet_block *epbp;
1106b00ab754SHans Petter Selasky 	struct simple_packet_block *spbp;
1107b00ab754SHans Petter Selasky 	struct packet_block *pbp;
1108b00ab754SHans Petter Selasky 	bpf_u_int32 interface_id = 0xFFFFFFFF;
1109b00ab754SHans Petter Selasky 	struct interface_description_block *idbp;
1110b00ab754SHans Petter Selasky 	struct section_header_block *shbp;
1111b00ab754SHans Petter Selasky 	FILE *fp = p->rfile;
1112b00ab754SHans Petter Selasky 	uint64_t t, sec, frac;
1113b00ab754SHans Petter Selasky 
1114b00ab754SHans Petter Selasky 	/*
1115b00ab754SHans Petter Selasky 	 * Look for an Enhanced Packet Block, a Simple Packet Block,
1116b00ab754SHans Petter Selasky 	 * or a Packet Block.
1117b00ab754SHans Petter Selasky 	 */
1118b00ab754SHans Petter Selasky 	for (;;) {
1119b00ab754SHans Petter Selasky 		/*
1120b00ab754SHans Petter Selasky 		 * Read the block type and length; those are common
1121b00ab754SHans Petter Selasky 		 * to all blocks.
1122b00ab754SHans Petter Selasky 		 */
1123b00ab754SHans Petter Selasky 		status = read_block(fp, p, &cursor, p->errbuf);
1124b00ab754SHans Petter Selasky 		if (status == 0)
11256f9cba8fSJoseph Mingrone 			return (0);	/* EOF */
1126b00ab754SHans Petter Selasky 		if (status == -1)
1127b00ab754SHans Petter Selasky 			return (-1);	/* error */
1128b00ab754SHans Petter Selasky 		switch (cursor.block_type) {
1129b00ab754SHans Petter Selasky 
1130b00ab754SHans Petter Selasky 		case BT_EPB:
1131b00ab754SHans Petter Selasky 			/*
1132b00ab754SHans Petter Selasky 			 * Get a pointer to the fixed-length portion of the
1133b00ab754SHans Petter Selasky 			 * EPB.
1134b00ab754SHans Petter Selasky 			 */
1135b00ab754SHans Petter Selasky 			epbp = get_from_block_data(&cursor, sizeof(*epbp),
1136b00ab754SHans Petter Selasky 			    p->errbuf);
1137b00ab754SHans Petter Selasky 			if (epbp == NULL)
1138b00ab754SHans Petter Selasky 				return (-1);	/* error */
1139b00ab754SHans Petter Selasky 
1140b00ab754SHans Petter Selasky 			/*
1141b00ab754SHans Petter Selasky 			 * Byte-swap it if necessary.
1142b00ab754SHans Petter Selasky 			 */
1143b00ab754SHans Petter Selasky 			if (p->swapped) {
1144b00ab754SHans Petter Selasky 				/* these were written in opposite byte order */
1145b00ab754SHans Petter Selasky 				interface_id = SWAPLONG(epbp->interface_id);
1146b00ab754SHans Petter Selasky 				hdr->caplen = SWAPLONG(epbp->caplen);
1147b00ab754SHans Petter Selasky 				hdr->len = SWAPLONG(epbp->len);
1148b00ab754SHans Petter Selasky 				t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
1149b00ab754SHans Petter Selasky 				    SWAPLONG(epbp->timestamp_low);
1150b00ab754SHans Petter Selasky 			} else {
1151b00ab754SHans Petter Selasky 				interface_id = epbp->interface_id;
1152b00ab754SHans Petter Selasky 				hdr->caplen = epbp->caplen;
1153b00ab754SHans Petter Selasky 				hdr->len = epbp->len;
1154b00ab754SHans Petter Selasky 				t = ((uint64_t)epbp->timestamp_high) << 32 |
1155b00ab754SHans Petter Selasky 				    epbp->timestamp_low;
1156b00ab754SHans Petter Selasky 			}
1157b00ab754SHans Petter Selasky 			goto found;
1158b00ab754SHans Petter Selasky 
1159b00ab754SHans Petter Selasky 		case BT_SPB:
1160b00ab754SHans Petter Selasky 			/*
1161b00ab754SHans Petter Selasky 			 * Get a pointer to the fixed-length portion of the
1162b00ab754SHans Petter Selasky 			 * SPB.
1163b00ab754SHans Petter Selasky 			 */
1164b00ab754SHans Petter Selasky 			spbp = get_from_block_data(&cursor, sizeof(*spbp),
1165b00ab754SHans Petter Selasky 			    p->errbuf);
1166b00ab754SHans Petter Selasky 			if (spbp == NULL)
1167b00ab754SHans Petter Selasky 				return (-1);	/* error */
1168b00ab754SHans Petter Selasky 
1169b00ab754SHans Petter Selasky 			/*
1170b00ab754SHans Petter Selasky 			 * SPB packets are assumed to have arrived on
1171b00ab754SHans Petter Selasky 			 * the first interface.
1172b00ab754SHans Petter Selasky 			 */
1173b00ab754SHans Petter Selasky 			interface_id = 0;
1174b00ab754SHans Petter Selasky 
1175b00ab754SHans Petter Selasky 			/*
1176b00ab754SHans Petter Selasky 			 * Byte-swap it if necessary.
1177b00ab754SHans Petter Selasky 			 */
1178b00ab754SHans Petter Selasky 			if (p->swapped) {
1179b00ab754SHans Petter Selasky 				/* these were written in opposite byte order */
1180b00ab754SHans Petter Selasky 				hdr->len = SWAPLONG(spbp->len);
1181b00ab754SHans Petter Selasky 			} else
1182b00ab754SHans Petter Selasky 				hdr->len = spbp->len;
1183b00ab754SHans Petter Selasky 
1184b00ab754SHans Petter Selasky 			/*
1185b00ab754SHans Petter Selasky 			 * The SPB doesn't give the captured length;
1186b00ab754SHans Petter Selasky 			 * it's the minimum of the snapshot length
1187b00ab754SHans Petter Selasky 			 * and the packet length.
1188b00ab754SHans Petter Selasky 			 */
1189b00ab754SHans Petter Selasky 			hdr->caplen = hdr->len;
1190b00ab754SHans Petter Selasky 			if (hdr->caplen > (bpf_u_int32)p->snapshot)
1191b00ab754SHans Petter Selasky 				hdr->caplen = p->snapshot;
1192b00ab754SHans Petter Selasky 			t = 0;	/* no time stamps */
1193b00ab754SHans Petter Selasky 			goto found;
1194b00ab754SHans Petter Selasky 
1195b00ab754SHans Petter Selasky 		case BT_PB:
1196b00ab754SHans Petter Selasky 			/*
1197b00ab754SHans Petter Selasky 			 * Get a pointer to the fixed-length portion of the
1198b00ab754SHans Petter Selasky 			 * PB.
1199b00ab754SHans Petter Selasky 			 */
1200b00ab754SHans Petter Selasky 			pbp = get_from_block_data(&cursor, sizeof(*pbp),
1201b00ab754SHans Petter Selasky 			    p->errbuf);
1202b00ab754SHans Petter Selasky 			if (pbp == NULL)
1203b00ab754SHans Petter Selasky 				return (-1);	/* error */
1204b00ab754SHans Petter Selasky 
1205b00ab754SHans Petter Selasky 			/*
1206b00ab754SHans Petter Selasky 			 * Byte-swap it if necessary.
1207b00ab754SHans Petter Selasky 			 */
1208b00ab754SHans Petter Selasky 			if (p->swapped) {
1209b00ab754SHans Petter Selasky 				/* these were written in opposite byte order */
1210b00ab754SHans Petter Selasky 				interface_id = SWAPSHORT(pbp->interface_id);
1211b00ab754SHans Petter Selasky 				hdr->caplen = SWAPLONG(pbp->caplen);
1212b00ab754SHans Petter Selasky 				hdr->len = SWAPLONG(pbp->len);
1213b00ab754SHans Petter Selasky 				t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
1214b00ab754SHans Petter Selasky 				    SWAPLONG(pbp->timestamp_low);
1215b00ab754SHans Petter Selasky 			} else {
1216b00ab754SHans Petter Selasky 				interface_id = pbp->interface_id;
1217b00ab754SHans Petter Selasky 				hdr->caplen = pbp->caplen;
1218b00ab754SHans Petter Selasky 				hdr->len = pbp->len;
1219b00ab754SHans Petter Selasky 				t = ((uint64_t)pbp->timestamp_high) << 32 |
1220b00ab754SHans Petter Selasky 				    pbp->timestamp_low;
1221b00ab754SHans Petter Selasky 			}
1222b00ab754SHans Petter Selasky 			goto found;
1223b00ab754SHans Petter Selasky 
1224b00ab754SHans Petter Selasky 		case BT_IDB:
1225b00ab754SHans Petter Selasky 			/*
1226b00ab754SHans Petter Selasky 			 * Interface Description Block.  Get a pointer
1227b00ab754SHans Petter Selasky 			 * to its fixed-length portion.
1228b00ab754SHans Petter Selasky 			 */
1229b00ab754SHans Petter Selasky 			idbp = get_from_block_data(&cursor, sizeof(*idbp),
1230b00ab754SHans Petter Selasky 			    p->errbuf);
1231b00ab754SHans Petter Selasky 			if (idbp == NULL)
1232b00ab754SHans Petter Selasky 				return (-1);	/* error */
1233b00ab754SHans Petter Selasky 
1234b00ab754SHans Petter Selasky 			/*
1235b00ab754SHans Petter Selasky 			 * Byte-swap it if necessary.
1236b00ab754SHans Petter Selasky 			 */
1237b00ab754SHans Petter Selasky 			if (p->swapped) {
1238b00ab754SHans Petter Selasky 				idbp->linktype = SWAPSHORT(idbp->linktype);
1239b00ab754SHans Petter Selasky 				idbp->snaplen = SWAPLONG(idbp->snaplen);
1240b00ab754SHans Petter Selasky 			}
1241b00ab754SHans Petter Selasky 
1242b00ab754SHans Petter Selasky 			/*
1243b00ab754SHans Petter Selasky 			 * If the link-layer type or snapshot length
1244b00ab754SHans Petter Selasky 			 * differ from the ones for the first IDB we
1245b00ab754SHans Petter Selasky 			 * saw, quit.
1246b00ab754SHans Petter Selasky 			 *
1247b00ab754SHans Petter Selasky 			 * XXX - just discard packets from those
1248b00ab754SHans Petter Selasky 			 * interfaces?
1249b00ab754SHans Petter Selasky 			 */
1250b00ab754SHans Petter Selasky 			if (p->linktype != idbp->linktype) {
12516f9cba8fSJoseph Mingrone 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1252b00ab754SHans Petter Selasky 				    "an interface has a type %u different from the type of the first interface",
1253b00ab754SHans Petter Selasky 				    idbp->linktype);
1254b00ab754SHans Petter Selasky 				return (-1);
1255b00ab754SHans Petter Selasky 			}
125657e22627SCy Schubert 
125757e22627SCy Schubert 			/*
125857e22627SCy Schubert 			 * Check against the *adjusted* value of this IDB's
125957e22627SCy Schubert 			 * snapshot length.
126057e22627SCy Schubert 			 */
126157e22627SCy Schubert 			if ((bpf_u_int32)p->snapshot !=
1262*afdbf109SJoseph Mingrone 			    pcapint_adjust_snapshot(p->linktype, idbp->snaplen)) {
12636f9cba8fSJoseph Mingrone 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
12646f9cba8fSJoseph Mingrone 				    "an interface has a snapshot length %u different from the snapshot length of the first interface",
1265b00ab754SHans Petter Selasky 				    idbp->snaplen);
1266b00ab754SHans Petter Selasky 				return (-1);
1267b00ab754SHans Petter Selasky 			}
1268b00ab754SHans Petter Selasky 
1269b00ab754SHans Petter Selasky 			/*
1270b00ab754SHans Petter Selasky 			 * Try to add this interface.
1271b00ab754SHans Petter Selasky 			 */
12726f9cba8fSJoseph Mingrone 			if (!add_interface(p, idbp, &cursor, p->errbuf))
1273b00ab754SHans Petter Selasky 				return (-1);
1274b00ab754SHans Petter Selasky 			break;
1275b00ab754SHans Petter Selasky 
1276b00ab754SHans Petter Selasky 		case BT_SHB:
1277b00ab754SHans Petter Selasky 			/*
1278b00ab754SHans Petter Selasky 			 * Section Header Block.  Get a pointer
1279b00ab754SHans Petter Selasky 			 * to its fixed-length portion.
1280b00ab754SHans Petter Selasky 			 */
1281b00ab754SHans Petter Selasky 			shbp = get_from_block_data(&cursor, sizeof(*shbp),
1282b00ab754SHans Petter Selasky 			    p->errbuf);
1283b00ab754SHans Petter Selasky 			if (shbp == NULL)
1284b00ab754SHans Petter Selasky 				return (-1);	/* error */
1285b00ab754SHans Petter Selasky 
1286b00ab754SHans Petter Selasky 			/*
1287b00ab754SHans Petter Selasky 			 * Assume the byte order of this section is
1288b00ab754SHans Petter Selasky 			 * the same as that of the previous section.
1289b00ab754SHans Petter Selasky 			 * We'll check for that later.
1290b00ab754SHans Petter Selasky 			 */
1291b00ab754SHans Petter Selasky 			if (p->swapped) {
1292b00ab754SHans Petter Selasky 				shbp->byte_order_magic =
1293b00ab754SHans Petter Selasky 				    SWAPLONG(shbp->byte_order_magic);
1294b00ab754SHans Petter Selasky 				shbp->major_version =
1295b00ab754SHans Petter Selasky 				    SWAPSHORT(shbp->major_version);
1296b00ab754SHans Petter Selasky 			}
1297b00ab754SHans Petter Selasky 
1298b00ab754SHans Petter Selasky 			/*
1299b00ab754SHans Petter Selasky 			 * Make sure the byte order doesn't change;
1300b00ab754SHans Petter Selasky 			 * pcap_is_swapped() shouldn't change its
1301b00ab754SHans Petter Selasky 			 * return value in the middle of reading a capture.
1302b00ab754SHans Petter Selasky 			 */
1303b00ab754SHans Petter Selasky 			switch (shbp->byte_order_magic) {
1304b00ab754SHans Petter Selasky 
1305b00ab754SHans Petter Selasky 			case BYTE_ORDER_MAGIC:
1306b00ab754SHans Petter Selasky 				/*
1307b00ab754SHans Petter Selasky 				 * OK.
1308b00ab754SHans Petter Selasky 				 */
1309b00ab754SHans Petter Selasky 				break;
1310b00ab754SHans Petter Selasky 
1311b00ab754SHans Petter Selasky 			case SWAPLONG(BYTE_ORDER_MAGIC):
1312b00ab754SHans Petter Selasky 				/*
1313b00ab754SHans Petter Selasky 				 * Byte order changes.
1314b00ab754SHans Petter Selasky 				 */
13156f9cba8fSJoseph Mingrone 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1316b00ab754SHans Petter Selasky 				    "the file has sections with different byte orders");
1317b00ab754SHans Petter Selasky 				return (-1);
1318b00ab754SHans Petter Selasky 
1319b00ab754SHans Petter Selasky 			default:
1320b00ab754SHans Petter Selasky 				/*
1321b00ab754SHans Petter Selasky 				 * Not a valid SHB.
1322b00ab754SHans Petter Selasky 				 */
13236f9cba8fSJoseph Mingrone 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1324b00ab754SHans Petter Selasky 				    "the file has a section with a bad byte order magic field");
1325b00ab754SHans Petter Selasky 				return (-1);
1326b00ab754SHans Petter Selasky 			}
1327b00ab754SHans Petter Selasky 
1328b00ab754SHans Petter Selasky 			/*
1329b00ab754SHans Petter Selasky 			 * Make sure the major version is the version
1330b00ab754SHans Petter Selasky 			 * we handle.
1331b00ab754SHans Petter Selasky 			 */
1332b00ab754SHans Petter Selasky 			if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
13336f9cba8fSJoseph Mingrone 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1334b00ab754SHans Petter Selasky 				    "unknown pcapng savefile major version number %u",
1335b00ab754SHans Petter Selasky 				    shbp->major_version);
1336b00ab754SHans Petter Selasky 				return (-1);
1337b00ab754SHans Petter Selasky 			}
1338b00ab754SHans Petter Selasky 
1339b00ab754SHans Petter Selasky 			/*
1340b00ab754SHans Petter Selasky 			 * Reset the interface count; this section should
1341b00ab754SHans Petter Selasky 			 * have its own set of IDBs.  If any of them
1342b00ab754SHans Petter Selasky 			 * don't have the same interface type, snapshot
1343b00ab754SHans Petter Selasky 			 * length, or resolution as the first interface
1344b00ab754SHans Petter Selasky 			 * we saw, we'll fail.  (And if we don't see
1345b00ab754SHans Petter Selasky 			 * any IDBs, we'll fail when we see a packet
1346b00ab754SHans Petter Selasky 			 * block.)
1347b00ab754SHans Petter Selasky 			 */
1348b00ab754SHans Petter Selasky 			ps->ifcount = 0;
1349b00ab754SHans Petter Selasky 			break;
1350b00ab754SHans Petter Selasky 
1351b00ab754SHans Petter Selasky 		default:
1352b00ab754SHans Petter Selasky 			/*
1353b00ab754SHans Petter Selasky 			 * Not a packet block, IDB, or SHB; ignore it.
1354b00ab754SHans Petter Selasky 			 */
1355b00ab754SHans Petter Selasky 			break;
1356b00ab754SHans Petter Selasky 		}
1357b00ab754SHans Petter Selasky 	}
1358b00ab754SHans Petter Selasky 
1359b00ab754SHans Petter Selasky found:
1360b00ab754SHans Petter Selasky 	/*
1361b00ab754SHans Petter Selasky 	 * Is the interface ID an interface we know?
1362b00ab754SHans Petter Selasky 	 */
1363b00ab754SHans Petter Selasky 	if (interface_id >= ps->ifcount) {
1364b00ab754SHans Petter Selasky 		/*
1365b00ab754SHans Petter Selasky 		 * Yes.  Fail.
1366b00ab754SHans Petter Selasky 		 */
13676f9cba8fSJoseph Mingrone 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1368b00ab754SHans Petter Selasky 		    "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
1369b00ab754SHans Petter Selasky 		    interface_id);
1370b00ab754SHans Petter Selasky 		return (-1);
1371b00ab754SHans Petter Selasky 	}
1372b00ab754SHans Petter Selasky 
1373b00ab754SHans Petter Selasky 	if (hdr->caplen > (bpf_u_int32)p->snapshot) {
13746f9cba8fSJoseph Mingrone 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1375b00ab754SHans Petter Selasky 		    "invalid packet capture length %u, bigger than "
1376b00ab754SHans Petter Selasky 		    "snaplen of %d", hdr->caplen, p->snapshot);
1377b00ab754SHans Petter Selasky 		return (-1);
1378b00ab754SHans Petter Selasky 	}
1379b00ab754SHans Petter Selasky 
1380b00ab754SHans Petter Selasky 	/*
1381b00ab754SHans Petter Selasky 	 * Convert the time stamp to seconds and fractions of a second,
1382b00ab754SHans Petter Selasky 	 * with the fractions being in units of the file-supplied resolution.
1383b00ab754SHans Petter Selasky 	 */
1384b00ab754SHans Petter Selasky 	sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
1385b00ab754SHans Petter Selasky 	frac = t % ps->ifaces[interface_id].tsresol;
1386b00ab754SHans Petter Selasky 
1387b00ab754SHans Petter Selasky 	/*
1388b00ab754SHans Petter Selasky 	 * Convert the fractions from units of the file-supplied resolution
1389b00ab754SHans Petter Selasky 	 * to units of the user-requested resolution.
1390b00ab754SHans Petter Selasky 	 */
1391b00ab754SHans Petter Selasky 	switch (ps->ifaces[interface_id].scale_type) {
1392b00ab754SHans Petter Selasky 
1393b00ab754SHans Petter Selasky 	case PASS_THROUGH:
1394b00ab754SHans Petter Selasky 		/*
1395b00ab754SHans Petter Selasky 		 * The interface resolution is what the user wants,
1396b00ab754SHans Petter Selasky 		 * so we're done.
1397b00ab754SHans Petter Selasky 		 */
1398b00ab754SHans Petter Selasky 		break;
1399b00ab754SHans Petter Selasky 
1400b00ab754SHans Petter Selasky 	case SCALE_UP_DEC:
1401b00ab754SHans Petter Selasky 		/*
1402b00ab754SHans Petter Selasky 		 * The interface resolution is less than what the user
1403b00ab754SHans Petter Selasky 		 * wants; scale the fractional part up to the units of
1404b00ab754SHans Petter Selasky 		 * the resolution the user requested by multiplying by
1405b00ab754SHans Petter Selasky 		 * the quotient of the user-requested resolution and the
1406b00ab754SHans Petter Selasky 		 * file-supplied resolution.
1407b00ab754SHans Petter Selasky 		 *
1408b00ab754SHans Petter Selasky 		 * Those resolutions are both powers of 10, and the user-
1409b00ab754SHans Petter Selasky 		 * requested resolution is greater than the file-supplied
1410b00ab754SHans Petter Selasky 		 * resolution, so the quotient in question is an integer.
1411b00ab754SHans Petter Selasky 		 * We've calculated that quotient already, so we just
1412b00ab754SHans Petter Selasky 		 * multiply by it.
1413b00ab754SHans Petter Selasky 		 */
1414b00ab754SHans Petter Selasky 		frac *= ps->ifaces[interface_id].scale_factor;
1415b00ab754SHans Petter Selasky 		break;
1416b00ab754SHans Petter Selasky 
1417b00ab754SHans Petter Selasky 	case SCALE_UP_BIN:
1418b00ab754SHans Petter Selasky 		/*
1419b00ab754SHans Petter Selasky 		 * The interface resolution is less than what the user
1420b00ab754SHans Petter Selasky 		 * wants; scale the fractional part up to the units of
1421b00ab754SHans Petter Selasky 		 * the resolution the user requested by multiplying by
1422b00ab754SHans Petter Selasky 		 * the quotient of the user-requested resolution and the
1423b00ab754SHans Petter Selasky 		 * file-supplied resolution.
1424b00ab754SHans Petter Selasky 		 *
1425b00ab754SHans Petter Selasky 		 * The file-supplied resolution is a power of 2, so the
1426b00ab754SHans Petter Selasky 		 * quotient is not an integer, so, in order to do this
1427b00ab754SHans Petter Selasky 		 * entirely with integer arithmetic, we multiply by the
1428b00ab754SHans Petter Selasky 		 * user-requested resolution and divide by the file-
1429b00ab754SHans Petter Selasky 		 * supplied resolution.
1430b00ab754SHans Petter Selasky 		 *
1431b00ab754SHans Petter Selasky 		 * XXX - Is there something clever we could do here,
1432b00ab754SHans Petter Selasky 		 * given that we know that the file-supplied resolution
1433b00ab754SHans Petter Selasky 		 * is a power of 2?  Doing a multiplication followed by
1434b00ab754SHans Petter Selasky 		 * a division runs the risk of overflowing, and involves
1435b00ab754SHans Petter Selasky 		 * two non-simple arithmetic operations.
1436b00ab754SHans Petter Selasky 		 */
1437b00ab754SHans Petter Selasky 		frac *= ps->user_tsresol;
1438b00ab754SHans Petter Selasky 		frac /= ps->ifaces[interface_id].tsresol;
1439b00ab754SHans Petter Selasky 		break;
1440b00ab754SHans Petter Selasky 
1441b00ab754SHans Petter Selasky 	case SCALE_DOWN_DEC:
1442b00ab754SHans Petter Selasky 		/*
1443b00ab754SHans Petter Selasky 		 * The interface resolution is greater than what the user
1444b00ab754SHans Petter Selasky 		 * wants; scale the fractional part up to the units of
1445b00ab754SHans Petter Selasky 		 * the resolution the user requested by multiplying by
1446b00ab754SHans Petter Selasky 		 * the quotient of the user-requested resolution and the
1447b00ab754SHans Petter Selasky 		 * file-supplied resolution.
1448b00ab754SHans Petter Selasky 		 *
1449b00ab754SHans Petter Selasky 		 * Those resolutions are both powers of 10, and the user-
1450b00ab754SHans Petter Selasky 		 * requested resolution is less than the file-supplied
1451b00ab754SHans Petter Selasky 		 * resolution, so the quotient in question isn't an
1452b00ab754SHans Petter Selasky 		 * integer, but its reciprocal is, and we can just divide
1453b00ab754SHans Petter Selasky 		 * by the reciprocal of the quotient.  We've calculated
1454b00ab754SHans Petter Selasky 		 * the reciprocal of that quotient already, so we must
1455b00ab754SHans Petter Selasky 		 * divide by it.
1456b00ab754SHans Petter Selasky 		 */
1457b00ab754SHans Petter Selasky 		frac /= ps->ifaces[interface_id].scale_factor;
1458b00ab754SHans Petter Selasky 		break;
1459b00ab754SHans Petter Selasky 
1460b00ab754SHans Petter Selasky 
1461b00ab754SHans Petter Selasky 	case SCALE_DOWN_BIN:
1462b00ab754SHans Petter Selasky 		/*
1463b00ab754SHans Petter Selasky 		 * The interface resolution is greater than what the user
1464b00ab754SHans Petter Selasky 		 * wants; convert the fractional part to units of the
1465b00ab754SHans Petter Selasky 		 * resolution the user requested by multiplying by the
1466b00ab754SHans Petter Selasky 		 * quotient of the user-requested resolution and the
1467b00ab754SHans Petter Selasky 		 * file-supplied resolution.  We do that by multiplying
1468b00ab754SHans Petter Selasky 		 * by the user-requested resolution and dividing by the
1469b00ab754SHans Petter Selasky 		 * file-supplied resolution, as the quotient might not
1470b00ab754SHans Petter Selasky 		 * fit in an integer.
1471b00ab754SHans Petter Selasky 		 *
1472b00ab754SHans Petter Selasky 		 * The file-supplied resolution is a power of 2, so the
1473b00ab754SHans Petter Selasky 		 * quotient is not an integer, and neither is its
1474b00ab754SHans Petter Selasky 		 * reciprocal, so, in order to do this entirely with
1475b00ab754SHans Petter Selasky 		 * integer arithmetic, we multiply by the user-requested
1476b00ab754SHans Petter Selasky 		 * resolution and divide by the file-supplied resolution.
1477b00ab754SHans Petter Selasky 		 *
1478b00ab754SHans Petter Selasky 		 * XXX - Is there something clever we could do here,
1479b00ab754SHans Petter Selasky 		 * given that we know that the file-supplied resolution
1480b00ab754SHans Petter Selasky 		 * is a power of 2?  Doing a multiplication followed by
1481b00ab754SHans Petter Selasky 		 * a division runs the risk of overflowing, and involves
1482b00ab754SHans Petter Selasky 		 * two non-simple arithmetic operations.
1483b00ab754SHans Petter Selasky 		 */
1484b00ab754SHans Petter Selasky 		frac *= ps->user_tsresol;
1485b00ab754SHans Petter Selasky 		frac /= ps->ifaces[interface_id].tsresol;
1486b00ab754SHans Petter Selasky 		break;
1487b00ab754SHans Petter Selasky 	}
1488b00ab754SHans Petter Selasky #ifdef _WIN32
1489b00ab754SHans Petter Selasky 	/*
1490*afdbf109SJoseph Mingrone 	 * tv_sec and tv_usec in the Windows struct timeval are both
1491b00ab754SHans Petter Selasky 	 * longs.
1492b00ab754SHans Petter Selasky 	 */
1493b00ab754SHans Petter Selasky 	hdr->ts.tv_sec = (long)sec;
1494b00ab754SHans Petter Selasky 	hdr->ts.tv_usec = (long)frac;
1495b00ab754SHans Petter Selasky #else
1496b00ab754SHans Petter Selasky 	/*
1497b00ab754SHans Petter Selasky 	 * tv_sec in the UN*X struct timeval is a time_t; tv_usec is
1498b00ab754SHans Petter Selasky 	 * suseconds_t in UN*Xes that work the way the current Single
1499b00ab754SHans Petter Selasky 	 * UNIX Standard specify - but not all older UN*Xes necessarily
1500b00ab754SHans Petter Selasky 	 * support that type, so just cast to int.
1501b00ab754SHans Petter Selasky 	 */
1502b00ab754SHans Petter Selasky 	hdr->ts.tv_sec = (time_t)sec;
1503b00ab754SHans Petter Selasky 	hdr->ts.tv_usec = (int)frac;
1504b00ab754SHans Petter Selasky #endif
1505b00ab754SHans Petter Selasky 
1506b00ab754SHans Petter Selasky 	/*
1507b00ab754SHans Petter Selasky 	 * Get a pointer to the packet data.
1508b00ab754SHans Petter Selasky 	 */
1509b00ab754SHans Petter Selasky 	*data = get_from_block_data(&cursor, hdr->caplen, p->errbuf);
1510b00ab754SHans Petter Selasky 	if (*data == NULL)
1511b00ab754SHans Petter Selasky 		return (-1);
1512b00ab754SHans Petter Selasky 
1513*afdbf109SJoseph Mingrone 	pcapint_post_process(p->linktype, p->swapped, hdr, *data);
1514b00ab754SHans Petter Selasky 
15156f9cba8fSJoseph Mingrone 	return (1);
1516b00ab754SHans Petter Selasky }
1517