1335640Shselasky/*
2335640Shselasky * Copyright (c) 1993, 1994, 1995, 1996, 1997
3335640Shselasky *	The Regents of the University of California.  All rights reserved.
4335640Shselasky *
5335640Shselasky * Redistribution and use in source and binary forms, with or without
6335640Shselasky * modification, are permitted provided that: (1) source code distributions
7335640Shselasky * retain the above copyright notice and this paragraph in its entirety, (2)
8335640Shselasky * distributions including binary code include the above copyright notice and
9335640Shselasky * this paragraph in its entirety in the documentation or other materials
10335640Shselasky * provided with the distribution, and (3) all advertising materials mentioning
11335640Shselasky * features or use of this software display the following acknowledgement:
12335640Shselasky * ``This product includes software developed by the University of California,
13335640Shselasky * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14335640Shselasky * the University nor the names of its contributors may be used to endorse
15335640Shselasky * or promote products derived from this software without specific prior
16335640Shselasky * written permission.
17335640Shselasky * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18335640Shselasky * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19335640Shselasky * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20335640Shselasky *
21335640Shselasky * sf-pcapng.c - pcapng-file-format-specific code from savefile.c
22335640Shselasky */
23335640Shselasky
24335640Shselasky#ifdef HAVE_CONFIG_H
25335640Shselasky#include <config.h>
26335640Shselasky#endif
27335640Shselasky
28335640Shselasky#include <pcap/pcap-inttypes.h>
29335640Shselasky
30335640Shselasky#include <errno.h>
31335640Shselasky#include <memory.h>
32335640Shselasky#include <stdio.h>
33335640Shselasky#include <stdlib.h>
34335640Shselasky#include <string.h>
35335640Shselasky
36335640Shselasky#include "pcap-int.h"
37335640Shselasky
38335640Shselasky#include "pcap-common.h"
39335640Shselasky
40335640Shselasky#ifdef HAVE_OS_PROTO_H
41335640Shselasky#include "os-proto.h"
42335640Shselasky#endif
43335640Shselasky
44335640Shselasky#include "sf-pcapng.h"
45335640Shselasky
46335640Shselasky/*
47335640Shselasky * Block types.
48335640Shselasky */
49335640Shselasky
50335640Shselasky/*
51335640Shselasky * Common part at the beginning of all blocks.
52335640Shselasky */
53335640Shselaskystruct block_header {
54335640Shselasky	bpf_u_int32	block_type;
55335640Shselasky	bpf_u_int32	total_length;
56335640Shselasky};
57335640Shselasky
58335640Shselasky/*
59335640Shselasky * Common trailer at the end of all blocks.
60335640Shselasky */
61335640Shselaskystruct block_trailer {
62335640Shselasky	bpf_u_int32	total_length;
63335640Shselasky};
64335640Shselasky
65335640Shselasky/*
66335640Shselasky * Common options.
67335640Shselasky */
68335640Shselasky#define OPT_ENDOFOPT	0	/* end of options */
69335640Shselasky#define OPT_COMMENT	1	/* comment string */
70335640Shselasky
71335640Shselasky/*
72335640Shselasky * Option header.
73335640Shselasky */
74335640Shselaskystruct option_header {
75335640Shselasky	u_short		option_code;
76335640Shselasky	u_short		option_length;
77335640Shselasky};
78335640Shselasky
79335640Shselasky/*
80335640Shselasky * Structures for the part of each block type following the common
81335640Shselasky * part.
82335640Shselasky */
83335640Shselasky
84335640Shselasky/*
85335640Shselasky * Section Header Block.
86335640Shselasky */
87335640Shselasky#define BT_SHB			0x0A0D0D0A
88356341Scy#define BT_SHB_INSANE_MAX       1024U*1024U*1U  /* 1MB should be enough */
89335640Shselaskystruct section_header_block {
90335640Shselasky	bpf_u_int32	byte_order_magic;
91335640Shselasky	u_short		major_version;
92335640Shselasky	u_short		minor_version;
93335640Shselasky	uint64_t	section_length;
94335640Shselasky	/* followed by options and trailer */
95335640Shselasky};
96335640Shselasky
97335640Shselasky/*
98335640Shselasky * Byte-order magic value.
99335640Shselasky */
100335640Shselasky#define BYTE_ORDER_MAGIC	0x1A2B3C4D
101335640Shselasky
102335640Shselasky/*
103335640Shselasky * Current version number.  If major_version isn't PCAP_NG_VERSION_MAJOR,
104335640Shselasky * that means that this code can't read the file.
105335640Shselasky */
106335640Shselasky#define PCAP_NG_VERSION_MAJOR	1
107335640Shselasky#define PCAP_NG_VERSION_MINOR	0
108335640Shselasky
109335640Shselasky/*
110335640Shselasky * Interface Description Block.
111335640Shselasky */
112335640Shselasky#define BT_IDB			0x00000001
113335640Shselasky
114335640Shselaskystruct interface_description_block {
115335640Shselasky	u_short		linktype;
116335640Shselasky	u_short		reserved;
117335640Shselasky	bpf_u_int32	snaplen;
118335640Shselasky	/* followed by options and trailer */
119335640Shselasky};
120335640Shselasky
121335640Shselasky/*
122335640Shselasky * Options in the IDB.
123335640Shselasky */
124335640Shselasky#define IF_NAME		2	/* interface name string */
125335640Shselasky#define IF_DESCRIPTION	3	/* interface description string */
126335640Shselasky#define IF_IPV4ADDR	4	/* interface's IPv4 address and netmask */
127335640Shselasky#define IF_IPV6ADDR	5	/* interface's IPv6 address and prefix length */
128335640Shselasky#define IF_MACADDR	6	/* interface's MAC address */
129335640Shselasky#define IF_EUIADDR	7	/* interface's EUI address */
130335640Shselasky#define IF_SPEED	8	/* interface's speed, in bits/s */
131335640Shselasky#define IF_TSRESOL	9	/* interface's time stamp resolution */
132335640Shselasky#define IF_TZONE	10	/* interface's time zone */
133335640Shselasky#define IF_FILTER	11	/* filter used when capturing on interface */
134335640Shselasky#define IF_OS		12	/* string OS on which capture on this interface was done */
135335640Shselasky#define IF_FCSLEN	13	/* FCS length for this interface */
136335640Shselasky#define IF_TSOFFSET	14	/* time stamp offset for this interface */
137335640Shselasky
138335640Shselasky/*
139335640Shselasky * Enhanced Packet Block.
140335640Shselasky */
141335640Shselasky#define BT_EPB			0x00000006
142335640Shselasky
143335640Shselaskystruct enhanced_packet_block {
144335640Shselasky	bpf_u_int32	interface_id;
145335640Shselasky	bpf_u_int32	timestamp_high;
146335640Shselasky	bpf_u_int32	timestamp_low;
147335640Shselasky	bpf_u_int32	caplen;
148335640Shselasky	bpf_u_int32	len;
149335640Shselasky	/* followed by packet data, options, and trailer */
150335640Shselasky};
151335640Shselasky
152335640Shselasky/*
153335640Shselasky * Simple Packet Block.
154335640Shselasky */
155335640Shselasky#define BT_SPB			0x00000003
156335640Shselasky
157335640Shselaskystruct simple_packet_block {
158335640Shselasky	bpf_u_int32	len;
159335640Shselasky	/* followed by packet data and trailer */
160335640Shselasky};
161335640Shselasky
162335640Shselasky/*
163335640Shselasky * Packet Block.
164335640Shselasky */
165335640Shselasky#define BT_PB			0x00000002
166335640Shselasky
167335640Shselaskystruct packet_block {
168335640Shselasky	u_short		interface_id;
169335640Shselasky	u_short		drops_count;
170335640Shselasky	bpf_u_int32	timestamp_high;
171335640Shselasky	bpf_u_int32	timestamp_low;
172335640Shselasky	bpf_u_int32	caplen;
173335640Shselasky	bpf_u_int32	len;
174335640Shselasky	/* followed by packet data, options, and trailer */
175335640Shselasky};
176335640Shselasky
177335640Shselasky/*
178335640Shselasky * Block cursor - used when processing the contents of a block.
179335640Shselasky * Contains a pointer into the data being processed and a count
180335640Shselasky * of bytes remaining in the block.
181335640Shselasky */
182335640Shselaskystruct block_cursor {
183335640Shselasky	u_char		*data;
184335640Shselasky	size_t		data_remaining;
185335640Shselasky	bpf_u_int32	block_type;
186335640Shselasky};
187335640Shselasky
188335640Shselaskytypedef enum {
189335640Shselasky	PASS_THROUGH,
190335640Shselasky	SCALE_UP_DEC,
191335640Shselasky	SCALE_DOWN_DEC,
192335640Shselasky	SCALE_UP_BIN,
193335640Shselasky	SCALE_DOWN_BIN
194335640Shselasky} tstamp_scale_type_t;
195335640Shselasky
196335640Shselasky/*
197335640Shselasky * Per-interface information.
198335640Shselasky */
199335640Shselaskystruct pcap_ng_if {
200356341Scy	uint64_t tsresol;		/* time stamp resolution */
201335640Shselasky	tstamp_scale_type_t scale_type;	/* how to scale */
202356341Scy	uint64_t scale_factor;		/* time stamp scale factor for power-of-10 tsresol */
203335640Shselasky	uint64_t tsoffset;		/* time stamp offset */
204335640Shselasky};
205335640Shselasky
206335640Shselasky/*
207335640Shselasky * Per-pcap_t private data.
208335640Shselasky *
209335640Shselasky * max_blocksize is the maximum size of a block that we'll accept.  We
210335640Shselasky * reject blocks bigger than this, so we don't consume too much memory
211335640Shselasky * with a truly huge block.  It can change as we see IDBs with different
212335640Shselasky * link-layer header types.  (Currently, we don't support IDBs with
213335640Shselasky * different link-layer header types, but we will support it in the
214335640Shselasky * future, when we offer file-reading APIs that support it.)
215335640Shselasky *
216335640Shselasky * XXX - that's an issue on ILP32 platforms, where the maximum block
217335640Shselasky * size of 2^31-1 would eat all but one byte of the entire address space.
218335640Shselasky * It's less of an issue on ILP64/LLP64 platforms, but the actual size
219335640Shselasky * of the address space may be limited by 1) the number of *significant*
220335640Shselasky * address bits (currently, x86-64 only supports 48 bits of address), 2)
221335640Shselasky * any limitations imposed by the operating system; 3) any limitations
222335640Shselasky * imposed by the amount of available backing store for anonymous pages,
223335640Shselasky * so we impose a limit regardless of the size of a pointer.
224335640Shselasky */
225335640Shselaskystruct pcap_ng_sf {
226356341Scy	uint64_t user_tsresol;		/* time stamp resolution requested by the user */
227335640Shselasky	u_int max_blocksize;		/* don't grow buffer size past this */
228335640Shselasky	bpf_u_int32 ifcount;		/* number of interfaces seen in this capture */
229335640Shselasky	bpf_u_int32 ifaces_size;	/* size of array below */
230335640Shselasky	struct pcap_ng_if *ifaces;	/* array of interface information */
231335640Shselasky};
232335640Shselasky
233335640Shselasky/*
234356341Scy * The maximum block size we start with; we use an arbitrary value of
235356341Scy * 16 MiB.
236335640Shselasky */
237356341Scy#define INITIAL_MAX_BLOCKSIZE	(16*1024*1024)
238335640Shselasky
239356341Scy/*
240356341Scy * Maximum block size for a given maximum snapshot length; we define it
241356341Scy * as the size of an EPB with a max_snaplen-sized packet and 128KB of
242356341Scy * options.
243356341Scy */
244356341Scy#define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \
245356341Scy	(sizeof (struct block_header) + \
246356341Scy	 sizeof (struct enhanced_packet_block) + \
247356341Scy	 (max_snaplen) + 131072 + \
248356341Scy	 sizeof (struct block_trailer))
249356341Scy
250335640Shselaskystatic void pcap_ng_cleanup(pcap_t *p);
251335640Shselaskystatic int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
252335640Shselasky    u_char **data);
253335640Shselasky
254335640Shselaskystatic int
255335640Shselaskyread_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
256335640Shselasky    char *errbuf)
257335640Shselasky{
258335640Shselasky	size_t amt_read;
259335640Shselasky
260335640Shselasky	amt_read = fread(buf, 1, bytes_to_read, fp);
261335640Shselasky	if (amt_read != bytes_to_read) {
262335640Shselasky		if (ferror(fp)) {
263335640Shselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
264335640Shselasky			    errno, "error reading dump file");
265335640Shselasky		} else {
266335640Shselasky			if (amt_read == 0 && !fail_on_eof)
267335640Shselasky				return (0);	/* EOF */
268335640Shselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
269356341Scy			    "truncated pcapng dump file; tried to read %" PRIsize " bytes, only got %" PRIsize,
270356341Scy			    bytes_to_read, amt_read);
271335640Shselasky		}
272335640Shselasky		return (-1);
273335640Shselasky	}
274335640Shselasky	return (1);
275335640Shselasky}
276335640Shselasky
277335640Shselaskystatic int
278335640Shselaskyread_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
279335640Shselasky{
280335640Shselasky	struct pcap_ng_sf *ps;
281335640Shselasky	int status;
282335640Shselasky	struct block_header bhdr;
283356341Scy	struct block_trailer *btrlr;
284335640Shselasky	u_char *bdata;
285335640Shselasky	size_t data_remaining;
286335640Shselasky
287335640Shselasky	ps = p->priv;
288335640Shselasky
289335640Shselasky	status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
290335640Shselasky	if (status <= 0)
291335640Shselasky		return (status);	/* error or EOF */
292335640Shselasky
293335640Shselasky	if (p->swapped) {
294335640Shselasky		bhdr.block_type = SWAPLONG(bhdr.block_type);
295335640Shselasky		bhdr.total_length = SWAPLONG(bhdr.total_length);
296335640Shselasky	}
297335640Shselasky
298335640Shselasky	/*
299335640Shselasky	 * Is this block "too small" - i.e., is it shorter than a block
300335640Shselasky	 * header plus a block trailer?
301335640Shselasky	 */
302335640Shselasky	if (bhdr.total_length < sizeof(struct block_header) +
303335640Shselasky	    sizeof(struct block_trailer)) {
304335640Shselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
305356341Scy		    "block in pcapng dump file has a length of %u < %" PRIsize,
306335640Shselasky		    bhdr.total_length,
307356341Scy		    sizeof(struct block_header) + sizeof(struct block_trailer));
308335640Shselasky		return (-1);
309335640Shselasky	}
310335640Shselasky
311335640Shselasky	/*
312356341Scy	 * Is the block total length a multiple of 4?
313356341Scy	 */
314356341Scy	if ((bhdr.total_length % 4) != 0) {
315356341Scy		/*
316356341Scy		 * No.  Report that as an error.
317356341Scy		 */
318356341Scy		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
319356341Scy		    "block in pcapng dump file has a length of %u that is not a multiple of 4" PRIsize,
320356341Scy		    bhdr.total_length);
321356341Scy		return (-1);
322356341Scy	}
323356341Scy
324356341Scy	/*
325335640Shselasky	 * Is the buffer big enough?
326335640Shselasky	 */
327335640Shselasky	if (p->bufsize < bhdr.total_length) {
328335640Shselasky		/*
329356341Scy		 * No - make it big enough, unless it's too big, in
330356341Scy		 * which case we fail.
331335640Shselasky		 */
332335640Shselasky		void *bigger_buffer;
333335640Shselasky
334335640Shselasky		if (bhdr.total_length > ps->max_blocksize) {
335356341Scy			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length,
336335640Shselasky			    ps->max_blocksize);
337335640Shselasky			return (-1);
338335640Shselasky		}
339335640Shselasky		bigger_buffer = realloc(p->buffer, bhdr.total_length);
340335640Shselasky		if (bigger_buffer == NULL) {
341335640Shselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
342335640Shselasky			return (-1);
343335640Shselasky		}
344335640Shselasky		p->buffer = bigger_buffer;
345335640Shselasky	}
346335640Shselasky
347335640Shselasky	/*
348335640Shselasky	 * Copy the stuff we've read to the buffer, and read the rest
349335640Shselasky	 * of the block.
350335640Shselasky	 */
351335640Shselasky	memcpy(p->buffer, &bhdr, sizeof(bhdr));
352335640Shselasky	bdata = (u_char *)p->buffer + sizeof(bhdr);
353335640Shselasky	data_remaining = bhdr.total_length - sizeof(bhdr);
354335640Shselasky	if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
355335640Shselasky		return (-1);
356335640Shselasky
357335640Shselasky	/*
358356341Scy	 * Get the block size from the trailer.
359356341Scy	 */
360356341Scy	btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer));
361356341Scy	if (p->swapped)
362356341Scy		btrlr->total_length = SWAPLONG(btrlr->total_length);
363356341Scy
364356341Scy	/*
365356341Scy	 * Is the total length from the trailer the same as the total
366356341Scy	 * length from the header?
367356341Scy	 */
368356341Scy	if (bhdr.total_length != btrlr->total_length) {
369356341Scy		/*
370356341Scy		 * No.
371356341Scy		 */
372356341Scy		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
373356341Scy		    "block total length in header and trailer don't match");
374356341Scy		return (-1);
375356341Scy	}
376356341Scy
377356341Scy	/*
378335640Shselasky	 * Initialize the cursor.
379335640Shselasky	 */
380335640Shselasky	cursor->data = bdata;
381335640Shselasky	cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
382335640Shselasky	cursor->block_type = bhdr.block_type;
383335640Shselasky	return (1);
384335640Shselasky}
385335640Shselasky
386335640Shselaskystatic void *
387335640Shselaskyget_from_block_data(struct block_cursor *cursor, size_t chunk_size,
388335640Shselasky    char *errbuf)
389335640Shselasky{
390335640Shselasky	void *data;
391335640Shselasky
392335640Shselasky	/*
393335640Shselasky	 * Make sure we have the specified amount of data remaining in
394335640Shselasky	 * the block data.
395335640Shselasky	 */
396335640Shselasky	if (cursor->data_remaining < chunk_size) {
397335640Shselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
398335640Shselasky		    "block of type %u in pcapng dump file is too short",
399335640Shselasky		    cursor->block_type);
400335640Shselasky		return (NULL);
401335640Shselasky	}
402335640Shselasky
403335640Shselasky	/*
404335640Shselasky	 * Return the current pointer, and skip past the chunk.
405335640Shselasky	 */
406335640Shselasky	data = cursor->data;
407335640Shselasky	cursor->data += chunk_size;
408335640Shselasky	cursor->data_remaining -= chunk_size;
409335640Shselasky	return (data);
410335640Shselasky}
411335640Shselasky
412335640Shselaskystatic struct option_header *
413335640Shselaskyget_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
414335640Shselasky{
415335640Shselasky	struct option_header *opthdr;
416335640Shselasky
417335640Shselasky	opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
418335640Shselasky	if (opthdr == NULL) {
419335640Shselasky		/*
420335640Shselasky		 * Option header is cut short.
421335640Shselasky		 */
422335640Shselasky		return (NULL);
423335640Shselasky	}
424335640Shselasky
425335640Shselasky	/*
426335640Shselasky	 * Byte-swap it if necessary.
427335640Shselasky	 */
428335640Shselasky	if (p->swapped) {
429335640Shselasky		opthdr->option_code = SWAPSHORT(opthdr->option_code);
430335640Shselasky		opthdr->option_length = SWAPSHORT(opthdr->option_length);
431335640Shselasky	}
432335640Shselasky
433335640Shselasky	return (opthdr);
434335640Shselasky}
435335640Shselasky
436335640Shselaskystatic void *
437335640Shselaskyget_optvalue_from_block_data(struct block_cursor *cursor,
438335640Shselasky    struct option_header *opthdr, char *errbuf)
439335640Shselasky{
440335640Shselasky	size_t padded_option_len;
441335640Shselasky	void *optvalue;
442335640Shselasky
443335640Shselasky	/* Pad option length to 4-byte boundary */
444335640Shselasky	padded_option_len = opthdr->option_length;
445335640Shselasky	padded_option_len = ((padded_option_len + 3)/4)*4;
446335640Shselasky
447335640Shselasky	optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
448335640Shselasky	if (optvalue == NULL) {
449335640Shselasky		/*
450335640Shselasky		 * Option value is cut short.
451335640Shselasky		 */
452335640Shselasky		return (NULL);
453335640Shselasky	}
454335640Shselasky
455335640Shselasky	return (optvalue);
456335640Shselasky}
457335640Shselasky
458335640Shselaskystatic int
459356341Scyprocess_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol,
460335640Shselasky    uint64_t *tsoffset, int *is_binary, char *errbuf)
461335640Shselasky{
462335640Shselasky	struct option_header *opthdr;
463335640Shselasky	void *optvalue;
464335640Shselasky	int saw_tsresol, saw_tsoffset;
465356341Scy	uint8_t tsresol_opt;
466335640Shselasky	u_int i;
467335640Shselasky
468335640Shselasky	saw_tsresol = 0;
469335640Shselasky	saw_tsoffset = 0;
470335640Shselasky	while (cursor->data_remaining != 0) {
471335640Shselasky		/*
472335640Shselasky		 * Get the option header.
473335640Shselasky		 */
474335640Shselasky		opthdr = get_opthdr_from_block_data(p, cursor, errbuf);
475335640Shselasky		if (opthdr == NULL) {
476335640Shselasky			/*
477335640Shselasky			 * Option header is cut short.
478335640Shselasky			 */
479335640Shselasky			return (-1);
480335640Shselasky		}
481335640Shselasky
482335640Shselasky		/*
483335640Shselasky		 * Get option value.
484335640Shselasky		 */
485335640Shselasky		optvalue = get_optvalue_from_block_data(cursor, opthdr,
486335640Shselasky		    errbuf);
487335640Shselasky		if (optvalue == NULL) {
488335640Shselasky			/*
489335640Shselasky			 * Option value is cut short.
490335640Shselasky			 */
491335640Shselasky			return (-1);
492335640Shselasky		}
493335640Shselasky
494335640Shselasky		switch (opthdr->option_code) {
495335640Shselasky
496335640Shselasky		case OPT_ENDOFOPT:
497335640Shselasky			if (opthdr->option_length != 0) {
498335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
499335640Shselasky				    "Interface Description Block has opt_endofopt option with length %u != 0",
500335640Shselasky				    opthdr->option_length);
501335640Shselasky				return (-1);
502335640Shselasky			}
503335640Shselasky			goto done;
504335640Shselasky
505335640Shselasky		case IF_TSRESOL:
506335640Shselasky			if (opthdr->option_length != 1) {
507335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
508335640Shselasky				    "Interface Description Block has if_tsresol option with length %u != 1",
509335640Shselasky				    opthdr->option_length);
510335640Shselasky				return (-1);
511335640Shselasky			}
512335640Shselasky			if (saw_tsresol) {
513335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
514335640Shselasky				    "Interface Description Block has more than one if_tsresol option");
515335640Shselasky				return (-1);
516335640Shselasky			}
517335640Shselasky			saw_tsresol = 1;
518335640Shselasky			memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt));
519335640Shselasky			if (tsresol_opt & 0x80) {
520335640Shselasky				/*
521335640Shselasky				 * Resolution is negative power of 2.
522335640Shselasky				 */
523356341Scy				uint8_t tsresol_shift = (tsresol_opt & 0x7F);
524356341Scy
525356341Scy				if (tsresol_shift > 63) {
526356341Scy					/*
527356341Scy					 * Resolution is too high; 2^-{res}
528356341Scy					 * won't fit in a 64-bit value.
529356341Scy					 */
530356341Scy					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
531356341Scy					    "Interface Description Block if_tsresol option resolution 2^-%u is too high",
532356341Scy					    tsresol_shift);
533356341Scy					return (-1);
534356341Scy				}
535335640Shselasky				*is_binary = 1;
536356341Scy				*tsresol = ((uint64_t)1) << tsresol_shift;
537335640Shselasky			} else {
538335640Shselasky				/*
539335640Shselasky				 * Resolution is negative power of 10.
540335640Shselasky				 */
541356341Scy				if (tsresol_opt > 19) {
542356341Scy					/*
543356341Scy					 * Resolution is too high; 2^-{res}
544356341Scy					 * won't fit in a 64-bit value (the
545356341Scy					 * largest power of 10 that fits
546356341Scy					 * in a 64-bit value is 10^19, as
547356341Scy					 * the largest 64-bit unsigned
548356341Scy					 * value is ~1.8*10^19).
549356341Scy					 */
550356341Scy					pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
551356341Scy					    "Interface Description Block if_tsresol option resolution 10^-%u is too high",
552356341Scy					    tsresol_opt);
553356341Scy					return (-1);
554356341Scy				}
555335640Shselasky				*is_binary = 0;
556335640Shselasky				*tsresol = 1;
557335640Shselasky				for (i = 0; i < tsresol_opt; i++)
558335640Shselasky					*tsresol *= 10;
559335640Shselasky			}
560335640Shselasky			break;
561335640Shselasky
562335640Shselasky		case IF_TSOFFSET:
563335640Shselasky			if (opthdr->option_length != 8) {
564335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
565335640Shselasky				    "Interface Description Block has if_tsoffset option with length %u != 8",
566335640Shselasky				    opthdr->option_length);
567335640Shselasky				return (-1);
568335640Shselasky			}
569335640Shselasky			if (saw_tsoffset) {
570335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
571335640Shselasky				    "Interface Description Block has more than one if_tsoffset option");
572335640Shselasky				return (-1);
573335640Shselasky			}
574335640Shselasky			saw_tsoffset = 1;
575335640Shselasky			memcpy(tsoffset, optvalue, sizeof(*tsoffset));
576335640Shselasky			if (p->swapped)
577335640Shselasky				*tsoffset = SWAPLL(*tsoffset);
578335640Shselasky			break;
579335640Shselasky
580335640Shselasky		default:
581335640Shselasky			break;
582335640Shselasky		}
583335640Shselasky	}
584335640Shselasky
585335640Shselaskydone:
586335640Shselasky	return (0);
587335640Shselasky}
588335640Shselasky
589335640Shselaskystatic int
590335640Shselaskyadd_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
591335640Shselasky{
592335640Shselasky	struct pcap_ng_sf *ps;
593356341Scy	uint64_t tsresol;
594335640Shselasky	uint64_t tsoffset;
595335640Shselasky	int is_binary;
596335640Shselasky
597335640Shselasky	ps = p->priv;
598335640Shselasky
599335640Shselasky	/*
600335640Shselasky	 * Count this interface.
601335640Shselasky	 */
602335640Shselasky	ps->ifcount++;
603335640Shselasky
604335640Shselasky	/*
605335640Shselasky	 * Grow the array of per-interface information as necessary.
606335640Shselasky	 */
607335640Shselasky	if (ps->ifcount > ps->ifaces_size) {
608335640Shselasky		/*
609335640Shselasky		 * We need to grow the array.
610335640Shselasky		 */
611335640Shselasky		bpf_u_int32 new_ifaces_size;
612335640Shselasky		struct pcap_ng_if *new_ifaces;
613335640Shselasky
614335640Shselasky		if (ps->ifaces_size == 0) {
615335640Shselasky			/*
616335640Shselasky			 * It's currently empty.
617335640Shselasky			 *
618335640Shselasky			 * (The Clang static analyzer doesn't do enough,
619335640Shselasky			 * err, umm, dataflow *analysis* to realize that
620335640Shselasky			 * ps->ifaces_size == 0 if ps->ifaces == NULL,
621335640Shselasky			 * and so complains about a possible zero argument
622335640Shselasky			 * to realloc(), so we check for the former
623335640Shselasky			 * condition to shut it up.
624335640Shselasky			 *
625335640Shselasky			 * However, it doesn't complain that one of the
626335640Shselasky			 * multiplications below could overflow, which is
627335640Shselasky			 * a real, albeit extremely unlikely, problem (you'd
628335640Shselasky			 * need a pcapng file with tens of millions of
629335640Shselasky			 * interfaces).)
630335640Shselasky			 */
631335640Shselasky			new_ifaces_size = 1;
632335640Shselasky			new_ifaces = malloc(sizeof (struct pcap_ng_if));
633335640Shselasky		} else {
634335640Shselasky			/*
635335640Shselasky			 * It's not currently empty; double its size.
636335640Shselasky			 * (Perhaps overkill once we have a lot of interfaces.)
637335640Shselasky			 *
638335640Shselasky			 * Check for overflow if we double it.
639335640Shselasky			 */
640335640Shselasky			if (ps->ifaces_size * 2 < ps->ifaces_size) {
641335640Shselasky				/*
642335640Shselasky				 * The maximum number of interfaces before
643335640Shselasky				 * ps->ifaces_size overflows is the largest
644335640Shselasky				 * possible 32-bit power of 2, as we do
645335640Shselasky				 * size doubling.
646335640Shselasky				 */
647335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
648335640Shselasky				    "more than %u interfaces in the file",
649335640Shselasky				    0x80000000U);
650335640Shselasky				return (0);
651335640Shselasky			}
652335640Shselasky
653335640Shselasky			/*
654335640Shselasky			 * ps->ifaces_size * 2 doesn't overflow, so it's
655335640Shselasky			 * safe to multiply.
656335640Shselasky			 */
657335640Shselasky			new_ifaces_size = ps->ifaces_size * 2;
658335640Shselasky
659335640Shselasky			/*
660335640Shselasky			 * Now make sure that's not so big that it overflows
661335640Shselasky			 * if we multiply by sizeof (struct pcap_ng_if).
662335640Shselasky			 *
663335640Shselasky			 * That can happen on 32-bit platforms, with a 32-bit
664335640Shselasky			 * size_t; it shouldn't happen on 64-bit platforms,
665335640Shselasky			 * with a 64-bit size_t, as new_ifaces_size is
666335640Shselasky			 * 32 bits.
667335640Shselasky			 */
668335640Shselasky			if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
669335640Shselasky				/*
670335640Shselasky				 * As this fails only with 32-bit size_t,
671335640Shselasky				 * the multiplication was 32x32->32, and
672335640Shselasky				 * the largest 32-bit value that can safely
673335640Shselasky				 * be multiplied by sizeof (struct pcap_ng_if)
674335640Shselasky				 * without overflow is the largest 32-bit
675335640Shselasky				 * (unsigned) value divided by
676335640Shselasky				 * sizeof (struct pcap_ng_if).
677335640Shselasky				 */
678335640Shselasky				pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
679335640Shselasky				    "more than %u interfaces in the file",
680335640Shselasky				    0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
681335640Shselasky				return (0);
682335640Shselasky			}
683335640Shselasky			new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
684335640Shselasky		}
685335640Shselasky		if (new_ifaces == NULL) {
686335640Shselasky			/*
687335640Shselasky			 * We ran out of memory.
688335640Shselasky			 * Give up.
689335640Shselasky			 */
690335640Shselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
691335640Shselasky			    "out of memory for per-interface information (%u interfaces)",
692335640Shselasky			    ps->ifcount);
693335640Shselasky			return (0);
694335640Shselasky		}
695335640Shselasky		ps->ifaces_size = new_ifaces_size;
696335640Shselasky		ps->ifaces = new_ifaces;
697335640Shselasky	}
698335640Shselasky
699335640Shselasky	/*
700335640Shselasky	 * Set the default time stamp resolution and offset.
701335640Shselasky	 */
702335640Shselasky	tsresol = 1000000;	/* microsecond resolution */
703335640Shselasky	is_binary = 0;		/* which is a power of 10 */
704335640Shselasky	tsoffset = 0;		/* absolute timestamps */
705335640Shselasky
706335640Shselasky	/*
707335640Shselasky	 * Now look for various time stamp options, so we know
708335640Shselasky	 * how to interpret the time stamps for this interface.
709335640Shselasky	 */
710335640Shselasky	if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
711335640Shselasky	    errbuf) == -1)
712335640Shselasky		return (0);
713335640Shselasky
714335640Shselasky	ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
715335640Shselasky	ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
716335640Shselasky
717335640Shselasky	/*
718335640Shselasky	 * Determine whether we're scaling up or down or not
719335640Shselasky	 * at all for this interface.
720335640Shselasky	 */
721335640Shselasky	if (tsresol == ps->user_tsresol) {
722335640Shselasky		/*
723335640Shselasky		 * The resolution is the resolution the user wants,
724335640Shselasky		 * so we don't have to do scaling.
725335640Shselasky		 */
726335640Shselasky		ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
727335640Shselasky	} else if (tsresol > ps->user_tsresol) {
728335640Shselasky		/*
729335640Shselasky		 * The resolution is greater than what the user wants,
730335640Shselasky		 * so we have to scale the timestamps down.
731335640Shselasky		 */
732335640Shselasky		if (is_binary)
733335640Shselasky			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
734335640Shselasky		else {
735335640Shselasky			/*
736335640Shselasky			 * Calculate the scale factor.
737335640Shselasky			 */
738335640Shselasky			ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
739335640Shselasky			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
740335640Shselasky		}
741335640Shselasky	} else {
742335640Shselasky		/*
743335640Shselasky		 * The resolution is less than what the user wants,
744335640Shselasky		 * so we have to scale the timestamps up.
745335640Shselasky		 */
746335640Shselasky		if (is_binary)
747335640Shselasky			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
748335640Shselasky		else {
749335640Shselasky			/*
750335640Shselasky			 * Calculate the scale factor.
751335640Shselasky			 */
752335640Shselasky			ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
753335640Shselasky			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
754335640Shselasky		}
755335640Shselasky	}
756335640Shselasky	return (1);
757335640Shselasky}
758335640Shselasky
759335640Shselasky/*
760335640Shselasky * Check whether this is a pcapng savefile and, if it is, extract the
761335640Shselasky * relevant information from the header.
762335640Shselasky */
763335640Shselaskypcap_t *
764356341Scypcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
765356341Scy    char *errbuf, int *err)
766335640Shselasky{
767356341Scy	bpf_u_int32 magic_int;
768335640Shselasky	size_t amt_read;
769335640Shselasky	bpf_u_int32 total_length;
770335640Shselasky	bpf_u_int32 byte_order_magic;
771335640Shselasky	struct block_header *bhdrp;
772335640Shselasky	struct section_header_block *shbp;
773335640Shselasky	pcap_t *p;
774335640Shselasky	int swapped = 0;
775335640Shselasky	struct pcap_ng_sf *ps;
776335640Shselasky	int status;
777335640Shselasky	struct block_cursor cursor;
778335640Shselasky	struct interface_description_block *idbp;
779335640Shselasky
780335640Shselasky	/*
781335640Shselasky	 * Assume no read errors.
782335640Shselasky	 */
783335640Shselasky	*err = 0;
784335640Shselasky
785335640Shselasky	/*
786335640Shselasky	 * Check whether the first 4 bytes of the file are the block
787335640Shselasky	 * type for a pcapng savefile.
788335640Shselasky	 */
789356341Scy	memcpy(&magic_int, magic, sizeof(magic_int));
790356341Scy	if (magic_int != BT_SHB) {
791335640Shselasky		/*
792335640Shselasky		 * XXX - check whether this looks like what the block
793335640Shselasky		 * type would be after being munged by mapping between
794335640Shselasky		 * UN*X and DOS/Windows text file format and, if it
795335640Shselasky		 * does, look for the byte-order magic number in
796335640Shselasky		 * the appropriate place and, if we find it, report
797335640Shselasky		 * this as possibly being a pcapng file transferred
798335640Shselasky		 * between UN*X and Windows in text file format?
799335640Shselasky		 */
800335640Shselasky		return (NULL);	/* nope */
801335640Shselasky	}
802335640Shselasky
803335640Shselasky	/*
804335640Shselasky	 * OK, they are.  However, that's just \n\r\r\n, so it could,
805335640Shselasky	 * conceivably, be an ordinary text file.
806335640Shselasky	 *
807335640Shselasky	 * It could not, however, conceivably be any other type of
808335640Shselasky	 * capture file, so we can read the rest of the putative
809335640Shselasky	 * Section Header Block; put the block type in the common
810335640Shselasky	 * header, read the rest of the common header and the
811335640Shselasky	 * fixed-length portion of the SHB, and look for the byte-order
812335640Shselasky	 * magic value.
813335640Shselasky	 */
814335640Shselasky	amt_read = fread(&total_length, 1, sizeof(total_length), fp);
815335640Shselasky	if (amt_read < sizeof(total_length)) {
816335640Shselasky		if (ferror(fp)) {
817335640Shselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
818335640Shselasky			    errno, "error reading dump file");
819335640Shselasky			*err = 1;
820335640Shselasky			return (NULL);	/* fail */
821335640Shselasky		}
822335640Shselasky
823335640Shselasky		/*
824335640Shselasky		 * Possibly a weird short text file, so just say
825335640Shselasky		 * "not pcapng".
826335640Shselasky		 */
827335640Shselasky		return (NULL);
828335640Shselasky	}
829335640Shselasky	amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
830335640Shselasky	if (amt_read < sizeof(byte_order_magic)) {
831335640Shselasky		if (ferror(fp)) {
832335640Shselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
833335640Shselasky			    errno, "error reading dump file");
834335640Shselasky			*err = 1;
835335640Shselasky			return (NULL);	/* fail */
836335640Shselasky		}
837335640Shselasky
838335640Shselasky		/*
839335640Shselasky		 * Possibly a weird short text file, so just say
840335640Shselasky		 * "not pcapng".
841335640Shselasky		 */
842335640Shselasky		return (NULL);
843335640Shselasky	}
844335640Shselasky	if (byte_order_magic != BYTE_ORDER_MAGIC) {
845335640Shselasky		byte_order_magic = SWAPLONG(byte_order_magic);
846335640Shselasky		if (byte_order_magic != BYTE_ORDER_MAGIC) {
847335640Shselasky			/*
848335640Shselasky			 * Not a pcapng file.
849335640Shselasky			 */
850335640Shselasky			return (NULL);
851335640Shselasky		}
852335640Shselasky		swapped = 1;
853335640Shselasky		total_length = SWAPLONG(total_length);
854335640Shselasky	}
855335640Shselasky
856335640Shselasky	/*
857335640Shselasky	 * Check the sanity of the total length.
858335640Shselasky	 */
859356341Scy	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) ||
860356341Scy            (total_length > BT_SHB_INSANE_MAX)) {
861335640Shselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
862356341Scy		    "Section Header Block in pcapng dump file has invalid length %" PRIsize " < _%u_ < %u (BT_SHB_INSANE_MAX)",
863356341Scy		    sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer),
864335640Shselasky		    total_length,
865356341Scy		    BT_SHB_INSANE_MAX);
866356341Scy
867335640Shselasky		*err = 1;
868335640Shselasky		return (NULL);
869335640Shselasky	}
870335640Shselasky
871335640Shselasky	/*
872335640Shselasky	 * OK, this is a good pcapng file.
873335640Shselasky	 * Allocate a pcap_t for it.
874335640Shselasky	 */
875335640Shselasky	p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
876335640Shselasky	if (p == NULL) {
877335640Shselasky		/* Allocation failed. */
878335640Shselasky		*err = 1;
879335640Shselasky		return (NULL);
880335640Shselasky	}
881335640Shselasky	p->swapped = swapped;
882335640Shselasky	ps = p->priv;
883335640Shselasky
884335640Shselasky	/*
885335640Shselasky	 * What precision does the user want?
886335640Shselasky	 */
887335640Shselasky	switch (precision) {
888335640Shselasky
889335640Shselasky	case PCAP_TSTAMP_PRECISION_MICRO:
890335640Shselasky		ps->user_tsresol = 1000000;
891335640Shselasky		break;
892335640Shselasky
893335640Shselasky	case PCAP_TSTAMP_PRECISION_NANO:
894335640Shselasky		ps->user_tsresol = 1000000000;
895335640Shselasky		break;
896335640Shselasky
897335640Shselasky	default:
898335640Shselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
899335640Shselasky		    "unknown time stamp resolution %u", precision);
900335640Shselasky		free(p);
901335640Shselasky		*err = 1;
902335640Shselasky		return (NULL);
903335640Shselasky	}
904335640Shselasky
905335640Shselasky	p->opt.tstamp_precision = precision;
906335640Shselasky
907335640Shselasky	/*
908335640Shselasky	 * Allocate a buffer into which to read blocks.  We default to
909335640Shselasky	 * the maximum of:
910335640Shselasky	 *
911335640Shselasky	 *	the total length of the SHB for which we read the header;
912335640Shselasky	 *
913335640Shselasky	 *	2K, which should be more than large enough for an Enhanced
914335640Shselasky	 *	Packet Block containing a full-size Ethernet frame, and
915335640Shselasky	 *	leaving room for some options.
916335640Shselasky	 *
917335640Shselasky	 * If we find a bigger block, we reallocate the buffer, up to
918356341Scy	 * the maximum size.  We start out with a maximum size of
919356341Scy	 * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types
920356341Scy	 * with a maximum snapshot that results in a larger maximum
921356341Scy	 * block length, we boost the maximum.
922335640Shselasky	 */
923335640Shselasky	p->bufsize = 2048;
924335640Shselasky	if (p->bufsize < total_length)
925335640Shselasky		p->bufsize = total_length;
926335640Shselasky	p->buffer = malloc(p->bufsize);
927335640Shselasky	if (p->buffer == NULL) {
928335640Shselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
929335640Shselasky		free(p);
930335640Shselasky		*err = 1;
931335640Shselasky		return (NULL);
932335640Shselasky	}
933356341Scy	ps->max_blocksize = INITIAL_MAX_BLOCKSIZE;
934335640Shselasky
935335640Shselasky	/*
936335640Shselasky	 * Copy the stuff we've read to the buffer, and read the rest
937335640Shselasky	 * of the SHB.
938335640Shselasky	 */
939335640Shselasky	bhdrp = (struct block_header *)p->buffer;
940335640Shselasky	shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
941356341Scy	bhdrp->block_type = magic_int;
942335640Shselasky	bhdrp->total_length = total_length;
943335640Shselasky	shbp->byte_order_magic = byte_order_magic;
944335640Shselasky	if (read_bytes(fp,
945356341Scy	    (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
946356341Scy	    total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
947335640Shselasky	    1, errbuf) == -1)
948335640Shselasky		goto fail;
949335640Shselasky
950335640Shselasky	if (p->swapped) {
951335640Shselasky		/*
952335640Shselasky		 * Byte-swap the fields we've read.
953335640Shselasky		 */
954335640Shselasky		shbp->major_version = SWAPSHORT(shbp->major_version);
955335640Shselasky		shbp->minor_version = SWAPSHORT(shbp->minor_version);
956335640Shselasky
957335640Shselasky		/*
958335640Shselasky		 * XXX - we don't care about the section length.
959335640Shselasky		 */
960335640Shselasky	}
961335640Shselasky	/* currently only SHB version 1.0 is supported */
962335640Shselasky	if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
963335640Shselasky	       shbp->minor_version == PCAP_NG_VERSION_MINOR)) {
964335640Shselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
965335640Shselasky		    "unsupported pcapng savefile version %u.%u",
966335640Shselasky		    shbp->major_version, shbp->minor_version);
967335640Shselasky		goto fail;
968335640Shselasky	}
969335640Shselasky	p->version_major = shbp->major_version;
970335640Shselasky	p->version_minor = shbp->minor_version;
971335640Shselasky
972335640Shselasky	/*
973335640Shselasky	 * Save the time stamp resolution the user requested.
974335640Shselasky	 */
975335640Shselasky	p->opt.tstamp_precision = precision;
976335640Shselasky
977335640Shselasky	/*
978335640Shselasky	 * Now start looking for an Interface Description Block.
979335640Shselasky	 */
980335640Shselasky	for (;;) {
981335640Shselasky		/*
982335640Shselasky		 * Read the next block.
983335640Shselasky		 */
984335640Shselasky		status = read_block(fp, p, &cursor, errbuf);
985335640Shselasky		if (status == 0) {
986335640Shselasky			/* EOF - no IDB in this file */
987335640Shselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
988335640Shselasky			    "the capture file has no Interface Description Blocks");
989335640Shselasky			goto fail;
990335640Shselasky		}
991335640Shselasky		if (status == -1)
992335640Shselasky			goto fail;	/* error */
993335640Shselasky		switch (cursor.block_type) {
994335640Shselasky
995335640Shselasky		case BT_IDB:
996335640Shselasky			/*
997335640Shselasky			 * Get a pointer to the fixed-length portion of the
998335640Shselasky			 * IDB.
999335640Shselasky			 */
1000335640Shselasky			idbp = get_from_block_data(&cursor, sizeof(*idbp),
1001335640Shselasky			    errbuf);
1002335640Shselasky			if (idbp == NULL)
1003335640Shselasky				goto fail;	/* error */
1004335640Shselasky
1005335640Shselasky			/*
1006335640Shselasky			 * Byte-swap it if necessary.
1007335640Shselasky			 */
1008335640Shselasky			if (p->swapped) {
1009335640Shselasky				idbp->linktype = SWAPSHORT(idbp->linktype);
1010335640Shselasky				idbp->snaplen = SWAPLONG(idbp->snaplen);
1011335640Shselasky			}
1012335640Shselasky
1013335640Shselasky			/*
1014335640Shselasky			 * Try to add this interface.
1015335640Shselasky			 */
1016335640Shselasky			if (!add_interface(p, &cursor, errbuf))
1017335640Shselasky				goto fail;
1018335640Shselasky
1019335640Shselasky			goto done;
1020335640Shselasky
1021335640Shselasky		case BT_EPB:
1022335640Shselasky		case BT_SPB:
1023335640Shselasky		case BT_PB:
1024335640Shselasky			/*
1025335640Shselasky			 * Saw a packet before we saw any IDBs.  That's
1026335640Shselasky			 * not valid, as we don't know what link-layer
1027335640Shselasky			 * encapsulation the packet has.
1028335640Shselasky			 */
1029335640Shselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1030335640Shselasky			    "the capture file has a packet block before any Interface Description Blocks");
1031335640Shselasky			goto fail;
1032335640Shselasky
1033335640Shselasky		default:
1034335640Shselasky			/*
1035335640Shselasky			 * Just ignore it.
1036335640Shselasky			 */
1037335640Shselasky			break;
1038335640Shselasky		}
1039335640Shselasky	}
1040335640Shselasky
1041335640Shselaskydone:
1042335640Shselasky	p->tzoff = 0;	/* XXX - not used in pcap */
1043335640Shselasky	p->linktype = linktype_to_dlt(idbp->linktype);
1044356341Scy	p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen);
1045335640Shselasky	p->linktype_ext = 0;
1046335640Shselasky
1047335640Shselasky	/*
1048335640Shselasky	 * If the maximum block size for a packet with the maximum
1049335640Shselasky	 * snapshot length for this DLT_ is bigger than the current
1050335640Shselasky	 * maximum block size, increase the maximum.
1051335640Shselasky	 */
1052356341Scy	if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
1053356341Scy		ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype));
1054335640Shselasky
1055335640Shselasky	p->next_packet_op = pcap_ng_next_packet;
1056335640Shselasky	p->cleanup_op = pcap_ng_cleanup;
1057335640Shselasky
1058335640Shselasky	return (p);
1059335640Shselasky
1060335640Shselaskyfail:
1061335640Shselasky	free(ps->ifaces);
1062335640Shselasky	free(p->buffer);
1063335640Shselasky	free(p);
1064335640Shselasky	*err = 1;
1065335640Shselasky	return (NULL);
1066335640Shselasky}
1067335640Shselasky
1068335640Shselaskystatic void
1069335640Shselaskypcap_ng_cleanup(pcap_t *p)
1070335640Shselasky{
1071335640Shselasky	struct pcap_ng_sf *ps = p->priv;
1072335640Shselasky
1073335640Shselasky	free(ps->ifaces);
1074335640Shselasky	sf_cleanup(p);
1075335640Shselasky}
1076335640Shselasky
1077335640Shselasky/*
1078335640Shselasky * Read and return the next packet from the savefile.  Return the header
1079335640Shselasky * in hdr and a pointer to the contents in data.  Return 0 on success, 1
1080335640Shselasky * if there were no more packets, and -1 on an error.
1081335640Shselasky */
1082335640Shselaskystatic int
1083335640Shselaskypcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
1084335640Shselasky{
1085335640Shselasky	struct pcap_ng_sf *ps = p->priv;
1086335640Shselasky	struct block_cursor cursor;
1087335640Shselasky	int status;
1088335640Shselasky	struct enhanced_packet_block *epbp;
1089335640Shselasky	struct simple_packet_block *spbp;
1090335640Shselasky	struct packet_block *pbp;
1091335640Shselasky	bpf_u_int32 interface_id = 0xFFFFFFFF;
1092335640Shselasky	struct interface_description_block *idbp;
1093335640Shselasky	struct section_header_block *shbp;
1094335640Shselasky	FILE *fp = p->rfile;
1095335640Shselasky	uint64_t t, sec, frac;
1096335640Shselasky
1097335640Shselasky	/*
1098335640Shselasky	 * Look for an Enhanced Packet Block, a Simple Packet Block,
1099335640Shselasky	 * or a Packet Block.
1100335640Shselasky	 */
1101335640Shselasky	for (;;) {
1102335640Shselasky		/*
1103335640Shselasky		 * Read the block type and length; those are common
1104335640Shselasky		 * to all blocks.
1105335640Shselasky		 */
1106335640Shselasky		status = read_block(fp, p, &cursor, p->errbuf);
1107335640Shselasky		if (status == 0)
1108335640Shselasky			return (1);	/* EOF */
1109335640Shselasky		if (status == -1)
1110335640Shselasky			return (-1);	/* error */
1111335640Shselasky		switch (cursor.block_type) {
1112335640Shselasky
1113335640Shselasky		case BT_EPB:
1114335640Shselasky			/*
1115335640Shselasky			 * Get a pointer to the fixed-length portion of the
1116335640Shselasky			 * EPB.
1117335640Shselasky			 */
1118335640Shselasky			epbp = get_from_block_data(&cursor, sizeof(*epbp),
1119335640Shselasky			    p->errbuf);
1120335640Shselasky			if (epbp == NULL)
1121335640Shselasky				return (-1);	/* error */
1122335640Shselasky
1123335640Shselasky			/*
1124335640Shselasky			 * Byte-swap it if necessary.
1125335640Shselasky			 */
1126335640Shselasky			if (p->swapped) {
1127335640Shselasky				/* these were written in opposite byte order */
1128335640Shselasky				interface_id = SWAPLONG(epbp->interface_id);
1129335640Shselasky				hdr->caplen = SWAPLONG(epbp->caplen);
1130335640Shselasky				hdr->len = SWAPLONG(epbp->len);
1131335640Shselasky				t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
1132335640Shselasky				    SWAPLONG(epbp->timestamp_low);
1133335640Shselasky			} else {
1134335640Shselasky				interface_id = epbp->interface_id;
1135335640Shselasky				hdr->caplen = epbp->caplen;
1136335640Shselasky				hdr->len = epbp->len;
1137335640Shselasky				t = ((uint64_t)epbp->timestamp_high) << 32 |
1138335640Shselasky				    epbp->timestamp_low;
1139335640Shselasky			}
1140335640Shselasky			goto found;
1141335640Shselasky
1142335640Shselasky		case BT_SPB:
1143335640Shselasky			/*
1144335640Shselasky			 * Get a pointer to the fixed-length portion of the
1145335640Shselasky			 * SPB.
1146335640Shselasky			 */
1147335640Shselasky			spbp = get_from_block_data(&cursor, sizeof(*spbp),
1148335640Shselasky			    p->errbuf);
1149335640Shselasky			if (spbp == NULL)
1150335640Shselasky				return (-1);	/* error */
1151335640Shselasky
1152335640Shselasky			/*
1153335640Shselasky			 * SPB packets are assumed to have arrived on
1154335640Shselasky			 * the first interface.
1155335640Shselasky			 */
1156335640Shselasky			interface_id = 0;
1157335640Shselasky
1158335640Shselasky			/*
1159335640Shselasky			 * Byte-swap it if necessary.
1160335640Shselasky			 */
1161335640Shselasky			if (p->swapped) {
1162335640Shselasky				/* these were written in opposite byte order */
1163335640Shselasky				hdr->len = SWAPLONG(spbp->len);
1164335640Shselasky			} else
1165335640Shselasky				hdr->len = spbp->len;
1166335640Shselasky
1167335640Shselasky			/*
1168335640Shselasky			 * The SPB doesn't give the captured length;
1169335640Shselasky			 * it's the minimum of the snapshot length
1170335640Shselasky			 * and the packet length.
1171335640Shselasky			 */
1172335640Shselasky			hdr->caplen = hdr->len;
1173335640Shselasky			if (hdr->caplen > (bpf_u_int32)p->snapshot)
1174335640Shselasky				hdr->caplen = p->snapshot;
1175335640Shselasky			t = 0;	/* no time stamps */
1176335640Shselasky			goto found;
1177335640Shselasky
1178335640Shselasky		case BT_PB:
1179335640Shselasky			/*
1180335640Shselasky			 * Get a pointer to the fixed-length portion of the
1181335640Shselasky			 * PB.
1182335640Shselasky			 */
1183335640Shselasky			pbp = get_from_block_data(&cursor, sizeof(*pbp),
1184335640Shselasky			    p->errbuf);
1185335640Shselasky			if (pbp == NULL)
1186335640Shselasky				return (-1);	/* error */
1187335640Shselasky
1188335640Shselasky			/*
1189335640Shselasky			 * Byte-swap it if necessary.
1190335640Shselasky			 */
1191335640Shselasky			if (p->swapped) {
1192335640Shselasky				/* these were written in opposite byte order */
1193335640Shselasky				interface_id = SWAPSHORT(pbp->interface_id);
1194335640Shselasky				hdr->caplen = SWAPLONG(pbp->caplen);
1195335640Shselasky				hdr->len = SWAPLONG(pbp->len);
1196335640Shselasky				t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
1197335640Shselasky				    SWAPLONG(pbp->timestamp_low);
1198335640Shselasky			} else {
1199335640Shselasky				interface_id = pbp->interface_id;
1200335640Shselasky				hdr->caplen = pbp->caplen;
1201335640Shselasky				hdr->len = pbp->len;
1202335640Shselasky				t = ((uint64_t)pbp->timestamp_high) << 32 |
1203335640Shselasky				    pbp->timestamp_low;
1204335640Shselasky			}
1205335640Shselasky			goto found;
1206335640Shselasky
1207335640Shselasky		case BT_IDB:
1208335640Shselasky			/*
1209335640Shselasky			 * Interface Description Block.  Get a pointer
1210335640Shselasky			 * to its fixed-length portion.
1211335640Shselasky			 */
1212335640Shselasky			idbp = get_from_block_data(&cursor, sizeof(*idbp),
1213335640Shselasky			    p->errbuf);
1214335640Shselasky			if (idbp == NULL)
1215335640Shselasky				return (-1);	/* error */
1216335640Shselasky
1217335640Shselasky			/*
1218335640Shselasky			 * Byte-swap it if necessary.
1219335640Shselasky			 */
1220335640Shselasky			if (p->swapped) {
1221335640Shselasky				idbp->linktype = SWAPSHORT(idbp->linktype);
1222335640Shselasky				idbp->snaplen = SWAPLONG(idbp->snaplen);
1223335640Shselasky			}
1224335640Shselasky
1225335640Shselasky			/*
1226335640Shselasky			 * If the link-layer type or snapshot length
1227335640Shselasky			 * differ from the ones for the first IDB we
1228335640Shselasky			 * saw, quit.
1229335640Shselasky			 *
1230335640Shselasky			 * XXX - just discard packets from those
1231335640Shselasky			 * interfaces?
1232335640Shselasky			 */
1233335640Shselasky			if (p->linktype != idbp->linktype) {
1234335640Shselasky				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1235335640Shselasky				    "an interface has a type %u different from the type of the first interface",
1236335640Shselasky				    idbp->linktype);
1237335640Shselasky				return (-1);
1238335640Shselasky			}
1239356341Scy
1240356341Scy			/*
1241356341Scy			 * Check against the *adjusted* value of this IDB's
1242356341Scy			 * snapshot length.
1243356341Scy			 */
1244356341Scy			if ((bpf_u_int32)p->snapshot !=
1245356341Scy			    pcap_adjust_snapshot(p->linktype, idbp->snaplen)) {
1246335640Shselasky				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1247335640Shselasky				    "an interface has a snapshot length %u different from the type of the first interface",
1248335640Shselasky				    idbp->snaplen);
1249335640Shselasky				return (-1);
1250335640Shselasky			}
1251335640Shselasky
1252335640Shselasky			/*
1253335640Shselasky			 * Try to add this interface.
1254335640Shselasky			 */
1255335640Shselasky			if (!add_interface(p, &cursor, p->errbuf))
1256335640Shselasky				return (-1);
1257335640Shselasky			break;
1258335640Shselasky
1259335640Shselasky		case BT_SHB:
1260335640Shselasky			/*
1261335640Shselasky			 * Section Header Block.  Get a pointer
1262335640Shselasky			 * to its fixed-length portion.
1263335640Shselasky			 */
1264335640Shselasky			shbp = get_from_block_data(&cursor, sizeof(*shbp),
1265335640Shselasky			    p->errbuf);
1266335640Shselasky			if (shbp == NULL)
1267335640Shselasky				return (-1);	/* error */
1268335640Shselasky
1269335640Shselasky			/*
1270335640Shselasky			 * Assume the byte order of this section is
1271335640Shselasky			 * the same as that of the previous section.
1272335640Shselasky			 * We'll check for that later.
1273335640Shselasky			 */
1274335640Shselasky			if (p->swapped) {
1275335640Shselasky				shbp->byte_order_magic =
1276335640Shselasky				    SWAPLONG(shbp->byte_order_magic);
1277335640Shselasky				shbp->major_version =
1278335640Shselasky				    SWAPSHORT(shbp->major_version);
1279335640Shselasky			}
1280335640Shselasky
1281335640Shselasky			/*
1282335640Shselasky			 * Make sure the byte order doesn't change;
1283335640Shselasky			 * pcap_is_swapped() shouldn't change its
1284335640Shselasky			 * return value in the middle of reading a capture.
1285335640Shselasky			 */
1286335640Shselasky			switch (shbp->byte_order_magic) {
1287335640Shselasky
1288335640Shselasky			case BYTE_ORDER_MAGIC:
1289335640Shselasky				/*
1290335640Shselasky				 * OK.
1291335640Shselasky				 */
1292335640Shselasky				break;
1293335640Shselasky
1294335640Shselasky			case SWAPLONG(BYTE_ORDER_MAGIC):
1295335640Shselasky				/*
1296335640Shselasky				 * Byte order changes.
1297335640Shselasky				 */
1298335640Shselasky				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1299335640Shselasky				    "the file has sections with different byte orders");
1300335640Shselasky				return (-1);
1301335640Shselasky
1302335640Shselasky			default:
1303335640Shselasky				/*
1304335640Shselasky				 * Not a valid SHB.
1305335640Shselasky				 */
1306335640Shselasky				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1307335640Shselasky				    "the file has a section with a bad byte order magic field");
1308335640Shselasky				return (-1);
1309335640Shselasky			}
1310335640Shselasky
1311335640Shselasky			/*
1312335640Shselasky			 * Make sure the major version is the version
1313335640Shselasky			 * we handle.
1314335640Shselasky			 */
1315335640Shselasky			if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
1316335640Shselasky				pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1317335640Shselasky				    "unknown pcapng savefile major version number %u",
1318335640Shselasky				    shbp->major_version);
1319335640Shselasky				return (-1);
1320335640Shselasky			}
1321335640Shselasky
1322335640Shselasky			/*
1323335640Shselasky			 * Reset the interface count; this section should
1324335640Shselasky			 * have its own set of IDBs.  If any of them
1325335640Shselasky			 * don't have the same interface type, snapshot
1326335640Shselasky			 * length, or resolution as the first interface
1327335640Shselasky			 * we saw, we'll fail.  (And if we don't see
1328335640Shselasky			 * any IDBs, we'll fail when we see a packet
1329335640Shselasky			 * block.)
1330335640Shselasky			 */
1331335640Shselasky			ps->ifcount = 0;
1332335640Shselasky			break;
1333335640Shselasky
1334335640Shselasky		default:
1335335640Shselasky			/*
1336335640Shselasky			 * Not a packet block, IDB, or SHB; ignore it.
1337335640Shselasky			 */
1338335640Shselasky			break;
1339335640Shselasky		}
1340335640Shselasky	}
1341335640Shselasky
1342335640Shselaskyfound:
1343335640Shselasky	/*
1344335640Shselasky	 * Is the interface ID an interface we know?
1345335640Shselasky	 */
1346335640Shselasky	if (interface_id >= ps->ifcount) {
1347335640Shselasky		/*
1348335640Shselasky		 * Yes.  Fail.
1349335640Shselasky		 */
1350335640Shselasky		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1351335640Shselasky		    "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
1352335640Shselasky		    interface_id);
1353335640Shselasky		return (-1);
1354335640Shselasky	}
1355335640Shselasky
1356335640Shselasky	if (hdr->caplen > (bpf_u_int32)p->snapshot) {
1357335640Shselasky		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1358335640Shselasky		    "invalid packet capture length %u, bigger than "
1359335640Shselasky		    "snaplen of %d", hdr->caplen, p->snapshot);
1360335640Shselasky		return (-1);
1361335640Shselasky	}
1362335640Shselasky
1363335640Shselasky	/*
1364335640Shselasky	 * Convert the time stamp to seconds and fractions of a second,
1365335640Shselasky	 * with the fractions being in units of the file-supplied resolution.
1366335640Shselasky	 */
1367335640Shselasky	sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
1368335640Shselasky	frac = t % ps->ifaces[interface_id].tsresol;
1369335640Shselasky
1370335640Shselasky	/*
1371335640Shselasky	 * Convert the fractions from units of the file-supplied resolution
1372335640Shselasky	 * to units of the user-requested resolution.
1373335640Shselasky	 */
1374335640Shselasky	switch (ps->ifaces[interface_id].scale_type) {
1375335640Shselasky
1376335640Shselasky	case PASS_THROUGH:
1377335640Shselasky		/*
1378335640Shselasky		 * The interface resolution is what the user wants,
1379335640Shselasky		 * so we're done.
1380335640Shselasky		 */
1381335640Shselasky		break;
1382335640Shselasky
1383335640Shselasky	case SCALE_UP_DEC:
1384335640Shselasky		/*
1385335640Shselasky		 * The interface resolution is less than what the user
1386335640Shselasky		 * wants; scale the fractional part up to the units of
1387335640Shselasky		 * the resolution the user requested by multiplying by
1388335640Shselasky		 * the quotient of the user-requested resolution and the
1389335640Shselasky		 * file-supplied resolution.
1390335640Shselasky		 *
1391335640Shselasky		 * Those resolutions are both powers of 10, and the user-
1392335640Shselasky		 * requested resolution is greater than the file-supplied
1393335640Shselasky		 * resolution, so the quotient in question is an integer.
1394335640Shselasky		 * We've calculated that quotient already, so we just
1395335640Shselasky		 * multiply by it.
1396335640Shselasky		 */
1397335640Shselasky		frac *= ps->ifaces[interface_id].scale_factor;
1398335640Shselasky		break;
1399335640Shselasky
1400335640Shselasky	case SCALE_UP_BIN:
1401335640Shselasky		/*
1402335640Shselasky		 * The interface resolution is less than what the user
1403335640Shselasky		 * wants; scale the fractional part up to the units of
1404335640Shselasky		 * the resolution the user requested by multiplying by
1405335640Shselasky		 * the quotient of the user-requested resolution and the
1406335640Shselasky		 * file-supplied resolution.
1407335640Shselasky		 *
1408335640Shselasky		 * The file-supplied resolution is a power of 2, so the
1409335640Shselasky		 * quotient is not an integer, so, in order to do this
1410335640Shselasky		 * entirely with integer arithmetic, we multiply by the
1411335640Shselasky		 * user-requested resolution and divide by the file-
1412335640Shselasky		 * supplied resolution.
1413335640Shselasky		 *
1414335640Shselasky		 * XXX - Is there something clever we could do here,
1415335640Shselasky		 * given that we know that the file-supplied resolution
1416335640Shselasky		 * is a power of 2?  Doing a multiplication followed by
1417335640Shselasky		 * a division runs the risk of overflowing, and involves
1418335640Shselasky		 * two non-simple arithmetic operations.
1419335640Shselasky		 */
1420335640Shselasky		frac *= ps->user_tsresol;
1421335640Shselasky		frac /= ps->ifaces[interface_id].tsresol;
1422335640Shselasky		break;
1423335640Shselasky
1424335640Shselasky	case SCALE_DOWN_DEC:
1425335640Shselasky		/*
1426335640Shselasky		 * The interface resolution is greater than what the user
1427335640Shselasky		 * wants; scale the fractional part up to the units of
1428335640Shselasky		 * the resolution the user requested by multiplying by
1429335640Shselasky		 * the quotient of the user-requested resolution and the
1430335640Shselasky		 * file-supplied resolution.
1431335640Shselasky		 *
1432335640Shselasky		 * Those resolutions are both powers of 10, and the user-
1433335640Shselasky		 * requested resolution is less than the file-supplied
1434335640Shselasky		 * resolution, so the quotient in question isn't an
1435335640Shselasky		 * integer, but its reciprocal is, and we can just divide
1436335640Shselasky		 * by the reciprocal of the quotient.  We've calculated
1437335640Shselasky		 * the reciprocal of that quotient already, so we must
1438335640Shselasky		 * divide by it.
1439335640Shselasky		 */
1440335640Shselasky		frac /= ps->ifaces[interface_id].scale_factor;
1441335640Shselasky		break;
1442335640Shselasky
1443335640Shselasky
1444335640Shselasky	case SCALE_DOWN_BIN:
1445335640Shselasky		/*
1446335640Shselasky		 * The interface resolution is greater than what the user
1447335640Shselasky		 * wants; convert the fractional part to units of the
1448335640Shselasky		 * resolution the user requested by multiplying by the
1449335640Shselasky		 * quotient of the user-requested resolution and the
1450335640Shselasky		 * file-supplied resolution.  We do that by multiplying
1451335640Shselasky		 * by the user-requested resolution and dividing by the
1452335640Shselasky		 * file-supplied resolution, as the quotient might not
1453335640Shselasky		 * fit in an integer.
1454335640Shselasky		 *
1455335640Shselasky		 * The file-supplied resolution is a power of 2, so the
1456335640Shselasky		 * quotient is not an integer, and neither is its
1457335640Shselasky		 * reciprocal, so, in order to do this entirely with
1458335640Shselasky		 * integer arithmetic, we multiply by the user-requested
1459335640Shselasky		 * resolution and divide by the file-supplied resolution.
1460335640Shselasky		 *
1461335640Shselasky		 * XXX - Is there something clever we could do here,
1462335640Shselasky		 * given that we know that the file-supplied resolution
1463335640Shselasky		 * is a power of 2?  Doing a multiplication followed by
1464335640Shselasky		 * a division runs the risk of overflowing, and involves
1465335640Shselasky		 * two non-simple arithmetic operations.
1466335640Shselasky		 */
1467335640Shselasky		frac *= ps->user_tsresol;
1468335640Shselasky		frac /= ps->ifaces[interface_id].tsresol;
1469335640Shselasky		break;
1470335640Shselasky	}
1471335640Shselasky#ifdef _WIN32
1472335640Shselasky	/*
1473335640Shselasky	 * tv_sec and tv_used in the Windows struct timeval are both
1474335640Shselasky	 * longs.
1475335640Shselasky	 */
1476335640Shselasky	hdr->ts.tv_sec = (long)sec;
1477335640Shselasky	hdr->ts.tv_usec = (long)frac;
1478335640Shselasky#else
1479335640Shselasky	/*
1480335640Shselasky	 * tv_sec in the UN*X struct timeval is a time_t; tv_usec is
1481335640Shselasky	 * suseconds_t in UN*Xes that work the way the current Single
1482335640Shselasky	 * UNIX Standard specify - but not all older UN*Xes necessarily
1483335640Shselasky	 * support that type, so just cast to int.
1484335640Shselasky	 */
1485335640Shselasky	hdr->ts.tv_sec = (time_t)sec;
1486335640Shselasky	hdr->ts.tv_usec = (int)frac;
1487335640Shselasky#endif
1488335640Shselasky
1489335640Shselasky	/*
1490335640Shselasky	 * Get a pointer to the packet data.
1491335640Shselasky	 */
1492335640Shselasky	*data = get_from_block_data(&cursor, hdr->caplen, p->errbuf);
1493335640Shselasky	if (*data == NULL)
1494335640Shselasky		return (-1);
1495335640Shselasky
1496335640Shselasky	if (p->swapped)
1497335640Shselasky		swap_pseudo_headers(p->linktype, hdr, *data);
1498335640Shselasky
1499335640Shselasky	return (0);
1500335640Shselasky}
1501