xref: /dragonfly/contrib/libpcap/sf-pcapng.c (revision ea16f64e)
13a289941SAaron LI /*
23a289941SAaron LI  * Copyright (c) 1993, 1994, 1995, 1996, 1997
33a289941SAaron LI  *	The Regents of the University of California.  All rights reserved.
43a289941SAaron LI  *
53a289941SAaron LI  * Redistribution and use in source and binary forms, with or without
63a289941SAaron LI  * modification, are permitted provided that: (1) source code distributions
73a289941SAaron LI  * retain the above copyright notice and this paragraph in its entirety, (2)
83a289941SAaron LI  * distributions including binary code include the above copyright notice and
93a289941SAaron LI  * this paragraph in its entirety in the documentation or other materials
103a289941SAaron LI  * provided with the distribution, and (3) all advertising materials mentioning
113a289941SAaron LI  * features or use of this software display the following acknowledgement:
123a289941SAaron LI  * ``This product includes software developed by the University of California,
133a289941SAaron LI  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
143a289941SAaron LI  * the University nor the names of its contributors may be used to endorse
153a289941SAaron LI  * or promote products derived from this software without specific prior
163a289941SAaron LI  * written permission.
173a289941SAaron LI  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
183a289941SAaron LI  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
193a289941SAaron LI  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
203a289941SAaron LI  *
213a289941SAaron LI  * sf-pcapng.c - pcapng-file-format-specific code from savefile.c
223a289941SAaron LI  */
233a289941SAaron LI 
243a289941SAaron LI #ifdef HAVE_CONFIG_H
253a289941SAaron LI #include <config.h>
263a289941SAaron LI #endif
273a289941SAaron LI 
283a289941SAaron LI #include <pcap/pcap-inttypes.h>
293a289941SAaron LI 
303a289941SAaron LI #include <errno.h>
313a289941SAaron LI #include <memory.h>
323a289941SAaron LI #include <stdio.h>
333a289941SAaron LI #include <stdlib.h>
343a289941SAaron LI #include <string.h>
353a289941SAaron LI 
363a289941SAaron LI #include "pcap-int.h"
373a289941SAaron LI 
383a289941SAaron LI #include "pcap-common.h"
393a289941SAaron LI 
403a289941SAaron LI #ifdef HAVE_OS_PROTO_H
413a289941SAaron LI #include "os-proto.h"
423a289941SAaron LI #endif
433a289941SAaron LI 
443a289941SAaron LI #include "sf-pcapng.h"
453a289941SAaron LI 
463a289941SAaron LI /*
473a289941SAaron LI  * Block types.
483a289941SAaron LI  */
493a289941SAaron LI 
503a289941SAaron LI /*
513a289941SAaron LI  * Common part at the beginning of all blocks.
523a289941SAaron LI  */
533a289941SAaron LI struct block_header {
543a289941SAaron LI 	bpf_u_int32	block_type;
553a289941SAaron LI 	bpf_u_int32	total_length;
563a289941SAaron LI };
573a289941SAaron LI 
583a289941SAaron LI /*
593a289941SAaron LI  * Common trailer at the end of all blocks.
603a289941SAaron LI  */
613a289941SAaron LI struct block_trailer {
623a289941SAaron LI 	bpf_u_int32	total_length;
633a289941SAaron LI };
643a289941SAaron LI 
653a289941SAaron LI /*
663a289941SAaron LI  * Common options.
673a289941SAaron LI  */
683a289941SAaron LI #define OPT_ENDOFOPT	0	/* end of options */
693a289941SAaron LI #define OPT_COMMENT	1	/* comment string */
703a289941SAaron LI 
713a289941SAaron LI /*
723a289941SAaron LI  * Option header.
733a289941SAaron LI  */
743a289941SAaron LI struct option_header {
753a289941SAaron LI 	u_short		option_code;
763a289941SAaron LI 	u_short		option_length;
773a289941SAaron LI };
783a289941SAaron LI 
793a289941SAaron LI /*
803a289941SAaron LI  * Structures for the part of each block type following the common
813a289941SAaron LI  * part.
823a289941SAaron LI  */
833a289941SAaron LI 
843a289941SAaron LI /*
853a289941SAaron LI  * Section Header Block.
863a289941SAaron LI  */
873a289941SAaron LI #define BT_SHB			0x0A0D0D0A
883a289941SAaron LI #define BT_SHB_INSANE_MAX       1024U*1024U*1U  /* 1MB should be enough */
893a289941SAaron LI struct section_header_block {
903a289941SAaron LI 	bpf_u_int32	byte_order_magic;
913a289941SAaron LI 	u_short		major_version;
923a289941SAaron LI 	u_short		minor_version;
933a289941SAaron LI 	uint64_t	section_length;
943a289941SAaron LI 	/* followed by options and trailer */
953a289941SAaron LI };
963a289941SAaron LI 
973a289941SAaron LI /*
983a289941SAaron LI  * Byte-order magic value.
993a289941SAaron LI  */
1003a289941SAaron LI #define BYTE_ORDER_MAGIC	0x1A2B3C4D
1013a289941SAaron LI 
1023a289941SAaron LI /*
1033a289941SAaron LI  * Current version number.  If major_version isn't PCAP_NG_VERSION_MAJOR,
104*ea16f64eSAntonio Huete Jimenez  * or if minor_version isn't PCAP_NG_VERSION_MINOR or 2, that means that
105*ea16f64eSAntonio Huete Jimenez  * this code can't read the file.
1063a289941SAaron LI  */
1073a289941SAaron LI #define PCAP_NG_VERSION_MAJOR	1
1083a289941SAaron LI #define PCAP_NG_VERSION_MINOR	0
1093a289941SAaron LI 
1103a289941SAaron LI /*
1113a289941SAaron LI  * Interface Description Block.
1123a289941SAaron LI  */
1133a289941SAaron LI #define BT_IDB			0x00000001
1143a289941SAaron LI 
1153a289941SAaron LI struct interface_description_block {
1163a289941SAaron LI 	u_short		linktype;
1173a289941SAaron LI 	u_short		reserved;
1183a289941SAaron LI 	bpf_u_int32	snaplen;
1193a289941SAaron LI 	/* followed by options and trailer */
1203a289941SAaron LI };
1213a289941SAaron LI 
1223a289941SAaron LI /*
1233a289941SAaron LI  * Options in the IDB.
1243a289941SAaron LI  */
1253a289941SAaron LI #define IF_NAME		2	/* interface name string */
1263a289941SAaron LI #define IF_DESCRIPTION	3	/* interface description string */
1273a289941SAaron LI #define IF_IPV4ADDR	4	/* interface's IPv4 address and netmask */
1283a289941SAaron LI #define IF_IPV6ADDR	5	/* interface's IPv6 address and prefix length */
1293a289941SAaron LI #define IF_MACADDR	6	/* interface's MAC address */
1303a289941SAaron LI #define IF_EUIADDR	7	/* interface's EUI address */
1313a289941SAaron LI #define IF_SPEED	8	/* interface's speed, in bits/s */
1323a289941SAaron LI #define IF_TSRESOL	9	/* interface's time stamp resolution */
1333a289941SAaron LI #define IF_TZONE	10	/* interface's time zone */
1343a289941SAaron LI #define IF_FILTER	11	/* filter used when capturing on interface */
1353a289941SAaron LI #define IF_OS		12	/* string OS on which capture on this interface was done */
1363a289941SAaron LI #define IF_FCSLEN	13	/* FCS length for this interface */
1373a289941SAaron LI #define IF_TSOFFSET	14	/* time stamp offset for this interface */
1383a289941SAaron LI 
1393a289941SAaron LI /*
1403a289941SAaron LI  * Enhanced Packet Block.
1413a289941SAaron LI  */
1423a289941SAaron LI #define BT_EPB			0x00000006
1433a289941SAaron LI 
1443a289941SAaron LI struct enhanced_packet_block {
1453a289941SAaron LI 	bpf_u_int32	interface_id;
1463a289941SAaron LI 	bpf_u_int32	timestamp_high;
1473a289941SAaron LI 	bpf_u_int32	timestamp_low;
1483a289941SAaron LI 	bpf_u_int32	caplen;
1493a289941SAaron LI 	bpf_u_int32	len;
1503a289941SAaron LI 	/* followed by packet data, options, and trailer */
1513a289941SAaron LI };
1523a289941SAaron LI 
1533a289941SAaron LI /*
1543a289941SAaron LI  * Simple Packet Block.
1553a289941SAaron LI  */
1563a289941SAaron LI #define BT_SPB			0x00000003
1573a289941SAaron LI 
1583a289941SAaron LI struct simple_packet_block {
1593a289941SAaron LI 	bpf_u_int32	len;
1603a289941SAaron LI 	/* followed by packet data and trailer */
1613a289941SAaron LI };
1623a289941SAaron LI 
1633a289941SAaron LI /*
1643a289941SAaron LI  * Packet Block.
1653a289941SAaron LI  */
1663a289941SAaron LI #define BT_PB			0x00000002
1673a289941SAaron LI 
1683a289941SAaron LI struct packet_block {
1693a289941SAaron LI 	u_short		interface_id;
1703a289941SAaron LI 	u_short		drops_count;
1713a289941SAaron LI 	bpf_u_int32	timestamp_high;
1723a289941SAaron LI 	bpf_u_int32	timestamp_low;
1733a289941SAaron LI 	bpf_u_int32	caplen;
1743a289941SAaron LI 	bpf_u_int32	len;
1753a289941SAaron LI 	/* followed by packet data, options, and trailer */
1763a289941SAaron LI };
1773a289941SAaron LI 
1783a289941SAaron LI /*
1793a289941SAaron LI  * Block cursor - used when processing the contents of a block.
1803a289941SAaron LI  * Contains a pointer into the data being processed and a count
1813a289941SAaron LI  * of bytes remaining in the block.
1823a289941SAaron LI  */
1833a289941SAaron LI struct block_cursor {
1843a289941SAaron LI 	u_char		*data;
1853a289941SAaron LI 	size_t		data_remaining;
1863a289941SAaron LI 	bpf_u_int32	block_type;
1873a289941SAaron LI };
1883a289941SAaron LI 
1893a289941SAaron LI typedef enum {
1903a289941SAaron LI 	PASS_THROUGH,
1913a289941SAaron LI 	SCALE_UP_DEC,
1923a289941SAaron LI 	SCALE_DOWN_DEC,
1933a289941SAaron LI 	SCALE_UP_BIN,
1943a289941SAaron LI 	SCALE_DOWN_BIN
1953a289941SAaron LI } tstamp_scale_type_t;
1963a289941SAaron LI 
1973a289941SAaron LI /*
1983a289941SAaron LI  * Per-interface information.
1993a289941SAaron LI  */
2003a289941SAaron LI struct pcap_ng_if {
201*ea16f64eSAntonio Huete Jimenez 	uint32_t snaplen;		/* snapshot length */
2023a289941SAaron LI 	uint64_t tsresol;		/* time stamp resolution */
2033a289941SAaron LI 	tstamp_scale_type_t scale_type;	/* how to scale */
2043a289941SAaron LI 	uint64_t scale_factor;		/* time stamp scale factor for power-of-10 tsresol */
2053a289941SAaron LI 	uint64_t tsoffset;		/* time stamp offset */
2063a289941SAaron LI };
2073a289941SAaron LI 
2083a289941SAaron LI /*
2093a289941SAaron LI  * Per-pcap_t private data.
2103a289941SAaron LI  *
2113a289941SAaron LI  * max_blocksize is the maximum size of a block that we'll accept.  We
2123a289941SAaron LI  * reject blocks bigger than this, so we don't consume too much memory
2133a289941SAaron LI  * with a truly huge block.  It can change as we see IDBs with different
2143a289941SAaron LI  * link-layer header types.  (Currently, we don't support IDBs with
2153a289941SAaron LI  * different link-layer header types, but we will support it in the
2163a289941SAaron LI  * future, when we offer file-reading APIs that support it.)
2173a289941SAaron LI  *
2183a289941SAaron LI  * XXX - that's an issue on ILP32 platforms, where the maximum block
2193a289941SAaron LI  * size of 2^31-1 would eat all but one byte of the entire address space.
2203a289941SAaron LI  * It's less of an issue on ILP64/LLP64 platforms, but the actual size
2213a289941SAaron LI  * of the address space may be limited by 1) the number of *significant*
2223a289941SAaron LI  * address bits (currently, x86-64 only supports 48 bits of address), 2)
2233a289941SAaron LI  * any limitations imposed by the operating system; 3) any limitations
2243a289941SAaron LI  * imposed by the amount of available backing store for anonymous pages,
2253a289941SAaron LI  * so we impose a limit regardless of the size of a pointer.
2263a289941SAaron LI  */
2273a289941SAaron LI struct pcap_ng_sf {
2283a289941SAaron LI 	uint64_t user_tsresol;		/* time stamp resolution requested by the user */
2293a289941SAaron LI 	u_int max_blocksize;		/* don't grow buffer size past this */
2303a289941SAaron LI 	bpf_u_int32 ifcount;		/* number of interfaces seen in this capture */
2313a289941SAaron LI 	bpf_u_int32 ifaces_size;	/* size of array below */
2323a289941SAaron LI 	struct pcap_ng_if *ifaces;	/* array of interface information */
2333a289941SAaron LI };
2343a289941SAaron LI 
2353a289941SAaron LI /*
2363a289941SAaron LI  * The maximum block size we start with; we use an arbitrary value of
2373a289941SAaron LI  * 16 MiB.
2383a289941SAaron LI  */
2393a289941SAaron LI #define INITIAL_MAX_BLOCKSIZE	(16*1024*1024)
2403a289941SAaron LI 
2413a289941SAaron LI /*
2423a289941SAaron LI  * Maximum block size for a given maximum snapshot length; we define it
2433a289941SAaron LI  * as the size of an EPB with a max_snaplen-sized packet and 128KB of
2443a289941SAaron LI  * options.
2453a289941SAaron LI  */
2463a289941SAaron LI #define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \
2473a289941SAaron LI 	(sizeof (struct block_header) + \
2483a289941SAaron LI 	 sizeof (struct enhanced_packet_block) + \
2493a289941SAaron LI 	 (max_snaplen) + 131072 + \
2503a289941SAaron LI 	 sizeof (struct block_trailer))
2513a289941SAaron LI 
2523a289941SAaron LI static void pcap_ng_cleanup(pcap_t *p);
2533a289941SAaron LI static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
2543a289941SAaron LI     u_char **data);
2553a289941SAaron LI 
2563a289941SAaron LI static int
read_bytes(FILE * fp,void * buf,size_t bytes_to_read,int fail_on_eof,char * errbuf)2573a289941SAaron LI read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
2583a289941SAaron LI     char *errbuf)
2593a289941SAaron LI {
2603a289941SAaron LI 	size_t amt_read;
2613a289941SAaron LI 
2623a289941SAaron LI 	amt_read = fread(buf, 1, bytes_to_read, fp);
2633a289941SAaron LI 	if (amt_read != bytes_to_read) {
2643a289941SAaron LI 		if (ferror(fp)) {
2653a289941SAaron LI 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
2663a289941SAaron LI 			    errno, "error reading dump file");
2673a289941SAaron LI 		} else {
2683a289941SAaron LI 			if (amt_read == 0 && !fail_on_eof)
2693a289941SAaron LI 				return (0);	/* EOF */
270*ea16f64eSAntonio Huete Jimenez 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
271*ea16f64eSAntonio Huete Jimenez 			    "truncated pcapng dump file; tried to read %zu bytes, only got %zu",
2723a289941SAaron LI 			    bytes_to_read, amt_read);
2733a289941SAaron LI 		}
2743a289941SAaron LI 		return (-1);
2753a289941SAaron LI 	}
2763a289941SAaron LI 	return (1);
2773a289941SAaron LI }
2783a289941SAaron LI 
2793a289941SAaron LI static int
read_block(FILE * fp,pcap_t * p,struct block_cursor * cursor,char * errbuf)2803a289941SAaron LI read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
2813a289941SAaron LI {
2823a289941SAaron LI 	struct pcap_ng_sf *ps;
2833a289941SAaron LI 	int status;
2843a289941SAaron LI 	struct block_header bhdr;
2853a289941SAaron LI 	struct block_trailer *btrlr;
2863a289941SAaron LI 	u_char *bdata;
2873a289941SAaron LI 	size_t data_remaining;
2883a289941SAaron LI 
2893a289941SAaron LI 	ps = p->priv;
2903a289941SAaron LI 
2913a289941SAaron LI 	status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
2923a289941SAaron LI 	if (status <= 0)
2933a289941SAaron LI 		return (status);	/* error or EOF */
2943a289941SAaron LI 
2953a289941SAaron LI 	if (p->swapped) {
2963a289941SAaron LI 		bhdr.block_type = SWAPLONG(bhdr.block_type);
2973a289941SAaron LI 		bhdr.total_length = SWAPLONG(bhdr.total_length);
2983a289941SAaron LI 	}
2993a289941SAaron LI 
3003a289941SAaron LI 	/*
3013a289941SAaron LI 	 * Is this block "too small" - i.e., is it shorter than a block
3023a289941SAaron LI 	 * header plus a block trailer?
3033a289941SAaron LI 	 */
3043a289941SAaron LI 	if (bhdr.total_length < sizeof(struct block_header) +
3053a289941SAaron LI 	    sizeof(struct block_trailer)) {
306*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
307*ea16f64eSAntonio Huete Jimenez 		    "block in pcapng dump file has a length of %u < %zu",
3083a289941SAaron LI 		    bhdr.total_length,
3093a289941SAaron LI 		    sizeof(struct block_header) + sizeof(struct block_trailer));
3103a289941SAaron LI 		return (-1);
3113a289941SAaron LI 	}
3123a289941SAaron LI 
3133a289941SAaron LI 	/*
3143a289941SAaron LI 	 * Is the block total length a multiple of 4?
3153a289941SAaron LI 	 */
3163a289941SAaron LI 	if ((bhdr.total_length % 4) != 0) {
3173a289941SAaron LI 		/*
3183a289941SAaron LI 		 * No.  Report that as an error.
3193a289941SAaron LI 		 */
320*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
321*ea16f64eSAntonio Huete Jimenez 		    "block in pcapng dump file has a length of %u that is not a multiple of 4",
3223a289941SAaron LI 		    bhdr.total_length);
3233a289941SAaron LI 		return (-1);
3243a289941SAaron LI 	}
3253a289941SAaron LI 
3263a289941SAaron LI 	/*
3273a289941SAaron LI 	 * Is the buffer big enough?
3283a289941SAaron LI 	 */
3293a289941SAaron LI 	if (p->bufsize < bhdr.total_length) {
3303a289941SAaron LI 		/*
3313a289941SAaron LI 		 * No - make it big enough, unless it's too big, in
3323a289941SAaron LI 		 * which case we fail.
3333a289941SAaron LI 		 */
3343a289941SAaron LI 		void *bigger_buffer;
3353a289941SAaron LI 
3363a289941SAaron LI 		if (bhdr.total_length > ps->max_blocksize) {
337*ea16f64eSAntonio Huete Jimenez 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length,
3383a289941SAaron LI 			    ps->max_blocksize);
3393a289941SAaron LI 			return (-1);
3403a289941SAaron LI 		}
3413a289941SAaron LI 		bigger_buffer = realloc(p->buffer, bhdr.total_length);
3423a289941SAaron LI 		if (bigger_buffer == NULL) {
343*ea16f64eSAntonio Huete Jimenez 			snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
3443a289941SAaron LI 			return (-1);
3453a289941SAaron LI 		}
3463a289941SAaron LI 		p->buffer = bigger_buffer;
3473a289941SAaron LI 	}
3483a289941SAaron LI 
3493a289941SAaron LI 	/*
3503a289941SAaron LI 	 * Copy the stuff we've read to the buffer, and read the rest
3513a289941SAaron LI 	 * of the block.
3523a289941SAaron LI 	 */
3533a289941SAaron LI 	memcpy(p->buffer, &bhdr, sizeof(bhdr));
3543a289941SAaron LI 	bdata = (u_char *)p->buffer + sizeof(bhdr);
3553a289941SAaron LI 	data_remaining = bhdr.total_length - sizeof(bhdr);
3563a289941SAaron LI 	if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
3573a289941SAaron LI 		return (-1);
3583a289941SAaron LI 
3593a289941SAaron LI 	/*
3603a289941SAaron LI 	 * Get the block size from the trailer.
3613a289941SAaron LI 	 */
3623a289941SAaron LI 	btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer));
3633a289941SAaron LI 	if (p->swapped)
3643a289941SAaron LI 		btrlr->total_length = SWAPLONG(btrlr->total_length);
3653a289941SAaron LI 
3663a289941SAaron LI 	/*
3673a289941SAaron LI 	 * Is the total length from the trailer the same as the total
3683a289941SAaron LI 	 * length from the header?
3693a289941SAaron LI 	 */
3703a289941SAaron LI 	if (bhdr.total_length != btrlr->total_length) {
3713a289941SAaron LI 		/*
3723a289941SAaron LI 		 * No.
3733a289941SAaron LI 		 */
374*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
3753a289941SAaron LI 		    "block total length in header and trailer don't match");
3763a289941SAaron LI 		return (-1);
3773a289941SAaron LI 	}
3783a289941SAaron LI 
3793a289941SAaron LI 	/*
3803a289941SAaron LI 	 * Initialize the cursor.
3813a289941SAaron LI 	 */
3823a289941SAaron LI 	cursor->data = bdata;
3833a289941SAaron LI 	cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
3843a289941SAaron LI 	cursor->block_type = bhdr.block_type;
3853a289941SAaron LI 	return (1);
3863a289941SAaron LI }
3873a289941SAaron LI 
3883a289941SAaron LI static void *
get_from_block_data(struct block_cursor * cursor,size_t chunk_size,char * errbuf)3893a289941SAaron LI get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
3903a289941SAaron LI     char *errbuf)
3913a289941SAaron LI {
3923a289941SAaron LI 	void *data;
3933a289941SAaron LI 
3943a289941SAaron LI 	/*
3953a289941SAaron LI 	 * Make sure we have the specified amount of data remaining in
3963a289941SAaron LI 	 * the block data.
3973a289941SAaron LI 	 */
3983a289941SAaron LI 	if (cursor->data_remaining < chunk_size) {
399*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
4003a289941SAaron LI 		    "block of type %u in pcapng dump file is too short",
4013a289941SAaron LI 		    cursor->block_type);
4023a289941SAaron LI 		return (NULL);
4033a289941SAaron LI 	}
4043a289941SAaron LI 
4053a289941SAaron LI 	/*
4063a289941SAaron LI 	 * Return the current pointer, and skip past the chunk.
4073a289941SAaron LI 	 */
4083a289941SAaron LI 	data = cursor->data;
4093a289941SAaron LI 	cursor->data += chunk_size;
4103a289941SAaron LI 	cursor->data_remaining -= chunk_size;
4113a289941SAaron LI 	return (data);
4123a289941SAaron LI }
4133a289941SAaron LI 
4143a289941SAaron LI static struct option_header *
get_opthdr_from_block_data(pcap_t * p,struct block_cursor * cursor,char * errbuf)4153a289941SAaron LI get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
4163a289941SAaron LI {
4173a289941SAaron LI 	struct option_header *opthdr;
4183a289941SAaron LI 
4193a289941SAaron LI 	opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
4203a289941SAaron LI 	if (opthdr == NULL) {
4213a289941SAaron LI 		/*
4223a289941SAaron LI 		 * Option header is cut short.
4233a289941SAaron LI 		 */
4243a289941SAaron LI 		return (NULL);
4253a289941SAaron LI 	}
4263a289941SAaron LI 
4273a289941SAaron LI 	/*
4283a289941SAaron LI 	 * Byte-swap it if necessary.
4293a289941SAaron LI 	 */
4303a289941SAaron LI 	if (p->swapped) {
4313a289941SAaron LI 		opthdr->option_code = SWAPSHORT(opthdr->option_code);
4323a289941SAaron LI 		opthdr->option_length = SWAPSHORT(opthdr->option_length);
4333a289941SAaron LI 	}
4343a289941SAaron LI 
4353a289941SAaron LI 	return (opthdr);
4363a289941SAaron LI }
4373a289941SAaron LI 
4383a289941SAaron LI static void *
get_optvalue_from_block_data(struct block_cursor * cursor,struct option_header * opthdr,char * errbuf)4393a289941SAaron LI get_optvalue_from_block_data(struct block_cursor *cursor,
4403a289941SAaron LI     struct option_header *opthdr, char *errbuf)
4413a289941SAaron LI {
4423a289941SAaron LI 	size_t padded_option_len;
4433a289941SAaron LI 	void *optvalue;
4443a289941SAaron LI 
4453a289941SAaron LI 	/* Pad option length to 4-byte boundary */
4463a289941SAaron LI 	padded_option_len = opthdr->option_length;
4473a289941SAaron LI 	padded_option_len = ((padded_option_len + 3)/4)*4;
4483a289941SAaron LI 
4493a289941SAaron LI 	optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
4503a289941SAaron LI 	if (optvalue == NULL) {
4513a289941SAaron LI 		/*
4523a289941SAaron LI 		 * Option value is cut short.
4533a289941SAaron LI 		 */
4543a289941SAaron LI 		return (NULL);
4553a289941SAaron LI 	}
4563a289941SAaron LI 
4573a289941SAaron LI 	return (optvalue);
4583a289941SAaron LI }
4593a289941SAaron LI 
4603a289941SAaron LI static int
process_idb_options(pcap_t * p,struct block_cursor * cursor,uint64_t * tsresol,uint64_t * tsoffset,int * is_binary,char * errbuf)4613a289941SAaron LI process_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol,
4623a289941SAaron LI     uint64_t *tsoffset, int *is_binary, char *errbuf)
4633a289941SAaron LI {
4643a289941SAaron LI 	struct option_header *opthdr;
4653a289941SAaron LI 	void *optvalue;
4663a289941SAaron LI 	int saw_tsresol, saw_tsoffset;
4673a289941SAaron LI 	uint8_t tsresol_opt;
4683a289941SAaron LI 	u_int i;
4693a289941SAaron LI 
4703a289941SAaron LI 	saw_tsresol = 0;
4713a289941SAaron LI 	saw_tsoffset = 0;
4723a289941SAaron LI 	while (cursor->data_remaining != 0) {
4733a289941SAaron LI 		/*
4743a289941SAaron LI 		 * Get the option header.
4753a289941SAaron LI 		 */
4763a289941SAaron LI 		opthdr = get_opthdr_from_block_data(p, cursor, errbuf);
4773a289941SAaron LI 		if (opthdr == NULL) {
4783a289941SAaron LI 			/*
4793a289941SAaron LI 			 * Option header is cut short.
4803a289941SAaron LI 			 */
4813a289941SAaron LI 			return (-1);
4823a289941SAaron LI 		}
4833a289941SAaron LI 
4843a289941SAaron LI 		/*
4853a289941SAaron LI 		 * Get option value.
4863a289941SAaron LI 		 */
4873a289941SAaron LI 		optvalue = get_optvalue_from_block_data(cursor, opthdr,
4883a289941SAaron LI 		    errbuf);
4893a289941SAaron LI 		if (optvalue == NULL) {
4903a289941SAaron LI 			/*
4913a289941SAaron LI 			 * Option value is cut short.
4923a289941SAaron LI 			 */
4933a289941SAaron LI 			return (-1);
4943a289941SAaron LI 		}
4953a289941SAaron LI 
4963a289941SAaron LI 		switch (opthdr->option_code) {
4973a289941SAaron LI 
4983a289941SAaron LI 		case OPT_ENDOFOPT:
4993a289941SAaron LI 			if (opthdr->option_length != 0) {
500*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
5013a289941SAaron LI 				    "Interface Description Block has opt_endofopt option with length %u != 0",
5023a289941SAaron LI 				    opthdr->option_length);
5033a289941SAaron LI 				return (-1);
5043a289941SAaron LI 			}
5053a289941SAaron LI 			goto done;
5063a289941SAaron LI 
5073a289941SAaron LI 		case IF_TSRESOL:
5083a289941SAaron LI 			if (opthdr->option_length != 1) {
509*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
5103a289941SAaron LI 				    "Interface Description Block has if_tsresol option with length %u != 1",
5113a289941SAaron LI 				    opthdr->option_length);
5123a289941SAaron LI 				return (-1);
5133a289941SAaron LI 			}
5143a289941SAaron LI 			if (saw_tsresol) {
515*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
5163a289941SAaron LI 				    "Interface Description Block has more than one if_tsresol option");
5173a289941SAaron LI 				return (-1);
5183a289941SAaron LI 			}
5193a289941SAaron LI 			saw_tsresol = 1;
5203a289941SAaron LI 			memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt));
5213a289941SAaron LI 			if (tsresol_opt & 0x80) {
5223a289941SAaron LI 				/*
5233a289941SAaron LI 				 * Resolution is negative power of 2.
5243a289941SAaron LI 				 */
5253a289941SAaron LI 				uint8_t tsresol_shift = (tsresol_opt & 0x7F);
5263a289941SAaron LI 
5273a289941SAaron LI 				if (tsresol_shift > 63) {
5283a289941SAaron LI 					/*
5293a289941SAaron LI 					 * Resolution is too high; 2^-{res}
5303a289941SAaron LI 					 * won't fit in a 64-bit value.
5313a289941SAaron LI 					 */
532*ea16f64eSAntonio Huete Jimenez 					snprintf(errbuf, PCAP_ERRBUF_SIZE,
5333a289941SAaron LI 					    "Interface Description Block if_tsresol option resolution 2^-%u is too high",
5343a289941SAaron LI 					    tsresol_shift);
5353a289941SAaron LI 					return (-1);
5363a289941SAaron LI 				}
5373a289941SAaron LI 				*is_binary = 1;
5383a289941SAaron LI 				*tsresol = ((uint64_t)1) << tsresol_shift;
5393a289941SAaron LI 			} else {
5403a289941SAaron LI 				/*
5413a289941SAaron LI 				 * Resolution is negative power of 10.
5423a289941SAaron LI 				 */
5433a289941SAaron LI 				if (tsresol_opt > 19) {
5443a289941SAaron LI 					/*
5453a289941SAaron LI 					 * Resolution is too high; 2^-{res}
5463a289941SAaron LI 					 * won't fit in a 64-bit value (the
5473a289941SAaron LI 					 * largest power of 10 that fits
5483a289941SAaron LI 					 * in a 64-bit value is 10^19, as
5493a289941SAaron LI 					 * the largest 64-bit unsigned
5503a289941SAaron LI 					 * value is ~1.8*10^19).
5513a289941SAaron LI 					 */
552*ea16f64eSAntonio Huete Jimenez 					snprintf(errbuf, PCAP_ERRBUF_SIZE,
5533a289941SAaron LI 					    "Interface Description Block if_tsresol option resolution 10^-%u is too high",
5543a289941SAaron LI 					    tsresol_opt);
5553a289941SAaron LI 					return (-1);
5563a289941SAaron LI 				}
5573a289941SAaron LI 				*is_binary = 0;
5583a289941SAaron LI 				*tsresol = 1;
5593a289941SAaron LI 				for (i = 0; i < tsresol_opt; i++)
5603a289941SAaron LI 					*tsresol *= 10;
5613a289941SAaron LI 			}
5623a289941SAaron LI 			break;
5633a289941SAaron LI 
5643a289941SAaron LI 		case IF_TSOFFSET:
5653a289941SAaron LI 			if (opthdr->option_length != 8) {
566*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
5673a289941SAaron LI 				    "Interface Description Block has if_tsoffset option with length %u != 8",
5683a289941SAaron LI 				    opthdr->option_length);
5693a289941SAaron LI 				return (-1);
5703a289941SAaron LI 			}
5713a289941SAaron LI 			if (saw_tsoffset) {
572*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
5733a289941SAaron LI 				    "Interface Description Block has more than one if_tsoffset option");
5743a289941SAaron LI 				return (-1);
5753a289941SAaron LI 			}
5763a289941SAaron LI 			saw_tsoffset = 1;
5773a289941SAaron LI 			memcpy(tsoffset, optvalue, sizeof(*tsoffset));
5783a289941SAaron LI 			if (p->swapped)
5793a289941SAaron LI 				*tsoffset = SWAPLL(*tsoffset);
5803a289941SAaron LI 			break;
5813a289941SAaron LI 
5823a289941SAaron LI 		default:
5833a289941SAaron LI 			break;
5843a289941SAaron LI 		}
5853a289941SAaron LI 	}
5863a289941SAaron LI 
5873a289941SAaron LI done:
5883a289941SAaron LI 	return (0);
5893a289941SAaron LI }
5903a289941SAaron LI 
5913a289941SAaron LI static int
add_interface(pcap_t * p,struct interface_description_block * idbp,struct block_cursor * cursor,char * errbuf)592*ea16f64eSAntonio Huete Jimenez add_interface(pcap_t *p, struct interface_description_block *idbp,
593*ea16f64eSAntonio Huete Jimenez     struct block_cursor *cursor, char *errbuf)
5943a289941SAaron LI {
5953a289941SAaron LI 	struct pcap_ng_sf *ps;
5963a289941SAaron LI 	uint64_t tsresol;
5973a289941SAaron LI 	uint64_t tsoffset;
5983a289941SAaron LI 	int is_binary;
5993a289941SAaron LI 
6003a289941SAaron LI 	ps = p->priv;
6013a289941SAaron LI 
6023a289941SAaron LI 	/*
6033a289941SAaron LI 	 * Count this interface.
6043a289941SAaron LI 	 */
6053a289941SAaron LI 	ps->ifcount++;
6063a289941SAaron LI 
6073a289941SAaron LI 	/*
6083a289941SAaron LI 	 * Grow the array of per-interface information as necessary.
6093a289941SAaron LI 	 */
6103a289941SAaron LI 	if (ps->ifcount > ps->ifaces_size) {
6113a289941SAaron LI 		/*
6123a289941SAaron LI 		 * We need to grow the array.
6133a289941SAaron LI 		 */
6143a289941SAaron LI 		bpf_u_int32 new_ifaces_size;
6153a289941SAaron LI 		struct pcap_ng_if *new_ifaces;
6163a289941SAaron LI 
6173a289941SAaron LI 		if (ps->ifaces_size == 0) {
6183a289941SAaron LI 			/*
6193a289941SAaron LI 			 * It's currently empty.
6203a289941SAaron LI 			 *
6213a289941SAaron LI 			 * (The Clang static analyzer doesn't do enough,
6223a289941SAaron LI 			 * err, umm, dataflow *analysis* to realize that
6233a289941SAaron LI 			 * ps->ifaces_size == 0 if ps->ifaces == NULL,
6243a289941SAaron LI 			 * and so complains about a possible zero argument
6253a289941SAaron LI 			 * to realloc(), so we check for the former
6263a289941SAaron LI 			 * condition to shut it up.
6273a289941SAaron LI 			 *
6283a289941SAaron LI 			 * However, it doesn't complain that one of the
6293a289941SAaron LI 			 * multiplications below could overflow, which is
6303a289941SAaron LI 			 * a real, albeit extremely unlikely, problem (you'd
6313a289941SAaron LI 			 * need a pcapng file with tens of millions of
6323a289941SAaron LI 			 * interfaces).)
6333a289941SAaron LI 			 */
6343a289941SAaron LI 			new_ifaces_size = 1;
6353a289941SAaron LI 			new_ifaces = malloc(sizeof (struct pcap_ng_if));
6363a289941SAaron LI 		} else {
6373a289941SAaron LI 			/*
6383a289941SAaron LI 			 * It's not currently empty; double its size.
6393a289941SAaron LI 			 * (Perhaps overkill once we have a lot of interfaces.)
6403a289941SAaron LI 			 *
6413a289941SAaron LI 			 * Check for overflow if we double it.
6423a289941SAaron LI 			 */
6433a289941SAaron LI 			if (ps->ifaces_size * 2 < ps->ifaces_size) {
6443a289941SAaron LI 				/*
6453a289941SAaron LI 				 * The maximum number of interfaces before
6463a289941SAaron LI 				 * ps->ifaces_size overflows is the largest
6473a289941SAaron LI 				 * possible 32-bit power of 2, as we do
6483a289941SAaron LI 				 * size doubling.
6493a289941SAaron LI 				 */
650*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
6513a289941SAaron LI 				    "more than %u interfaces in the file",
6523a289941SAaron LI 				    0x80000000U);
6533a289941SAaron LI 				return (0);
6543a289941SAaron LI 			}
6553a289941SAaron LI 
6563a289941SAaron LI 			/*
6573a289941SAaron LI 			 * ps->ifaces_size * 2 doesn't overflow, so it's
6583a289941SAaron LI 			 * safe to multiply.
6593a289941SAaron LI 			 */
6603a289941SAaron LI 			new_ifaces_size = ps->ifaces_size * 2;
6613a289941SAaron LI 
6623a289941SAaron LI 			/*
6633a289941SAaron LI 			 * Now make sure that's not so big that it overflows
6643a289941SAaron LI 			 * if we multiply by sizeof (struct pcap_ng_if).
6653a289941SAaron LI 			 *
6663a289941SAaron LI 			 * That can happen on 32-bit platforms, with a 32-bit
6673a289941SAaron LI 			 * size_t; it shouldn't happen on 64-bit platforms,
6683a289941SAaron LI 			 * with a 64-bit size_t, as new_ifaces_size is
6693a289941SAaron LI 			 * 32 bits.
6703a289941SAaron LI 			 */
6713a289941SAaron LI 			if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
6723a289941SAaron LI 				/*
6733a289941SAaron LI 				 * As this fails only with 32-bit size_t,
6743a289941SAaron LI 				 * the multiplication was 32x32->32, and
6753a289941SAaron LI 				 * the largest 32-bit value that can safely
6763a289941SAaron LI 				 * be multiplied by sizeof (struct pcap_ng_if)
6773a289941SAaron LI 				 * without overflow is the largest 32-bit
6783a289941SAaron LI 				 * (unsigned) value divided by
6793a289941SAaron LI 				 * sizeof (struct pcap_ng_if).
6803a289941SAaron LI 				 */
681*ea16f64eSAntonio Huete Jimenez 				snprintf(errbuf, PCAP_ERRBUF_SIZE,
6823a289941SAaron LI 				    "more than %u interfaces in the file",
6833a289941SAaron LI 				    0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
6843a289941SAaron LI 				return (0);
6853a289941SAaron LI 			}
6863a289941SAaron LI 			new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
6873a289941SAaron LI 		}
6883a289941SAaron LI 		if (new_ifaces == NULL) {
6893a289941SAaron LI 			/*
6903a289941SAaron LI 			 * We ran out of memory.
6913a289941SAaron LI 			 * Give up.
6923a289941SAaron LI 			 */
693*ea16f64eSAntonio Huete Jimenez 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
6943a289941SAaron LI 			    "out of memory for per-interface information (%u interfaces)",
6953a289941SAaron LI 			    ps->ifcount);
6963a289941SAaron LI 			return (0);
6973a289941SAaron LI 		}
6983a289941SAaron LI 		ps->ifaces_size = new_ifaces_size;
6993a289941SAaron LI 		ps->ifaces = new_ifaces;
7003a289941SAaron LI 	}
7013a289941SAaron LI 
702*ea16f64eSAntonio Huete Jimenez 	ps->ifaces[ps->ifcount - 1].snaplen = idbp->snaplen;
703*ea16f64eSAntonio Huete Jimenez 
7043a289941SAaron LI 	/*
7053a289941SAaron LI 	 * Set the default time stamp resolution and offset.
7063a289941SAaron LI 	 */
7073a289941SAaron LI 	tsresol = 1000000;	/* microsecond resolution */
7083a289941SAaron LI 	is_binary = 0;		/* which is a power of 10 */
7093a289941SAaron LI 	tsoffset = 0;		/* absolute timestamps */
7103a289941SAaron LI 
7113a289941SAaron LI 	/*
7123a289941SAaron LI 	 * Now look for various time stamp options, so we know
7133a289941SAaron LI 	 * how to interpret the time stamps for this interface.
7143a289941SAaron LI 	 */
7153a289941SAaron LI 	if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
7163a289941SAaron LI 	    errbuf) == -1)
7173a289941SAaron LI 		return (0);
7183a289941SAaron LI 
7193a289941SAaron LI 	ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
7203a289941SAaron LI 	ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
7213a289941SAaron LI 
7223a289941SAaron LI 	/*
7233a289941SAaron LI 	 * Determine whether we're scaling up or down or not
7243a289941SAaron LI 	 * at all for this interface.
7253a289941SAaron LI 	 */
7263a289941SAaron LI 	if (tsresol == ps->user_tsresol) {
7273a289941SAaron LI 		/*
7283a289941SAaron LI 		 * The resolution is the resolution the user wants,
7293a289941SAaron LI 		 * so we don't have to do scaling.
7303a289941SAaron LI 		 */
7313a289941SAaron LI 		ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
7323a289941SAaron LI 	} else if (tsresol > ps->user_tsresol) {
7333a289941SAaron LI 		/*
7343a289941SAaron LI 		 * The resolution is greater than what the user wants,
7353a289941SAaron LI 		 * so we have to scale the timestamps down.
7363a289941SAaron LI 		 */
7373a289941SAaron LI 		if (is_binary)
7383a289941SAaron LI 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
7393a289941SAaron LI 		else {
7403a289941SAaron LI 			/*
7413a289941SAaron LI 			 * Calculate the scale factor.
7423a289941SAaron LI 			 */
7433a289941SAaron LI 			ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
7443a289941SAaron LI 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
7453a289941SAaron LI 		}
7463a289941SAaron LI 	} else {
7473a289941SAaron LI 		/*
7483a289941SAaron LI 		 * The resolution is less than what the user wants,
7493a289941SAaron LI 		 * so we have to scale the timestamps up.
7503a289941SAaron LI 		 */
7513a289941SAaron LI 		if (is_binary)
7523a289941SAaron LI 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
7533a289941SAaron LI 		else {
7543a289941SAaron LI 			/*
7553a289941SAaron LI 			 * Calculate the scale factor.
7563a289941SAaron LI 			 */
7573a289941SAaron LI 			ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
7583a289941SAaron LI 			ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
7593a289941SAaron LI 		}
7603a289941SAaron LI 	}
7613a289941SAaron LI 	return (1);
7623a289941SAaron LI }
7633a289941SAaron LI 
7643a289941SAaron LI /*
7653a289941SAaron LI  * Check whether this is a pcapng savefile and, if it is, extract the
7663a289941SAaron LI  * relevant information from the header.
7673a289941SAaron LI  */
7683a289941SAaron LI pcap_t *
pcap_ng_check_header(const uint8_t * magic,FILE * fp,u_int precision,char * errbuf,int * err)7693a289941SAaron LI pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
7703a289941SAaron LI     char *errbuf, int *err)
7713a289941SAaron LI {
7723a289941SAaron LI 	bpf_u_int32 magic_int;
7733a289941SAaron LI 	size_t amt_read;
7743a289941SAaron LI 	bpf_u_int32 total_length;
7753a289941SAaron LI 	bpf_u_int32 byte_order_magic;
7763a289941SAaron LI 	struct block_header *bhdrp;
7773a289941SAaron LI 	struct section_header_block *shbp;
7783a289941SAaron LI 	pcap_t *p;
7793a289941SAaron LI 	int swapped = 0;
7803a289941SAaron LI 	struct pcap_ng_sf *ps;
7813a289941SAaron LI 	int status;
7823a289941SAaron LI 	struct block_cursor cursor;
7833a289941SAaron LI 	struct interface_description_block *idbp;
7843a289941SAaron LI 
7853a289941SAaron LI 	/*
7863a289941SAaron LI 	 * Assume no read errors.
7873a289941SAaron LI 	 */
7883a289941SAaron LI 	*err = 0;
7893a289941SAaron LI 
7903a289941SAaron LI 	/*
7913a289941SAaron LI 	 * Check whether the first 4 bytes of the file are the block
7923a289941SAaron LI 	 * type for a pcapng savefile.
7933a289941SAaron LI 	 */
7943a289941SAaron LI 	memcpy(&magic_int, magic, sizeof(magic_int));
7953a289941SAaron LI 	if (magic_int != BT_SHB) {
7963a289941SAaron LI 		/*
7973a289941SAaron LI 		 * XXX - check whether this looks like what the block
7983a289941SAaron LI 		 * type would be after being munged by mapping between
7993a289941SAaron LI 		 * UN*X and DOS/Windows text file format and, if it
8003a289941SAaron LI 		 * does, look for the byte-order magic number in
8013a289941SAaron LI 		 * the appropriate place and, if we find it, report
8023a289941SAaron LI 		 * this as possibly being a pcapng file transferred
8033a289941SAaron LI 		 * between UN*X and Windows in text file format?
8043a289941SAaron LI 		 */
8053a289941SAaron LI 		return (NULL);	/* nope */
8063a289941SAaron LI 	}
8073a289941SAaron LI 
8083a289941SAaron LI 	/*
8093a289941SAaron LI 	 * OK, they are.  However, that's just \n\r\r\n, so it could,
8103a289941SAaron LI 	 * conceivably, be an ordinary text file.
8113a289941SAaron LI 	 *
8123a289941SAaron LI 	 * It could not, however, conceivably be any other type of
8133a289941SAaron LI 	 * capture file, so we can read the rest of the putative
8143a289941SAaron LI 	 * Section Header Block; put the block type in the common
8153a289941SAaron LI 	 * header, read the rest of the common header and the
8163a289941SAaron LI 	 * fixed-length portion of the SHB, and look for the byte-order
8173a289941SAaron LI 	 * magic value.
8183a289941SAaron LI 	 */
8193a289941SAaron LI 	amt_read = fread(&total_length, 1, sizeof(total_length), fp);
8203a289941SAaron LI 	if (amt_read < sizeof(total_length)) {
8213a289941SAaron LI 		if (ferror(fp)) {
8223a289941SAaron LI 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
8233a289941SAaron LI 			    errno, "error reading dump file");
8243a289941SAaron LI 			*err = 1;
8253a289941SAaron LI 			return (NULL);	/* fail */
8263a289941SAaron LI 		}
8273a289941SAaron LI 
8283a289941SAaron LI 		/*
8293a289941SAaron LI 		 * Possibly a weird short text file, so just say
8303a289941SAaron LI 		 * "not pcapng".
8313a289941SAaron LI 		 */
8323a289941SAaron LI 		return (NULL);
8333a289941SAaron LI 	}
8343a289941SAaron LI 	amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
8353a289941SAaron LI 	if (amt_read < sizeof(byte_order_magic)) {
8363a289941SAaron LI 		if (ferror(fp)) {
8373a289941SAaron LI 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
8383a289941SAaron LI 			    errno, "error reading dump file");
8393a289941SAaron LI 			*err = 1;
8403a289941SAaron LI 			return (NULL);	/* fail */
8413a289941SAaron LI 		}
8423a289941SAaron LI 
8433a289941SAaron LI 		/*
8443a289941SAaron LI 		 * Possibly a weird short text file, so just say
8453a289941SAaron LI 		 * "not pcapng".
8463a289941SAaron LI 		 */
8473a289941SAaron LI 		return (NULL);
8483a289941SAaron LI 	}
8493a289941SAaron LI 	if (byte_order_magic != BYTE_ORDER_MAGIC) {
8503a289941SAaron LI 		byte_order_magic = SWAPLONG(byte_order_magic);
8513a289941SAaron LI 		if (byte_order_magic != BYTE_ORDER_MAGIC) {
8523a289941SAaron LI 			/*
8533a289941SAaron LI 			 * Not a pcapng file.
8543a289941SAaron LI 			 */
8553a289941SAaron LI 			return (NULL);
8563a289941SAaron LI 		}
8573a289941SAaron LI 		swapped = 1;
8583a289941SAaron LI 		total_length = SWAPLONG(total_length);
8593a289941SAaron LI 	}
8603a289941SAaron LI 
8613a289941SAaron LI 	/*
8623a289941SAaron LI 	 * Check the sanity of the total length.
8633a289941SAaron LI 	 */
8643a289941SAaron LI 	if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) ||
8653a289941SAaron LI             (total_length > BT_SHB_INSANE_MAX)) {
866*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
867*ea16f64eSAntonio Huete Jimenez 		    "Section Header Block in pcapng dump file has invalid length %zu < _%u_ < %u (BT_SHB_INSANE_MAX)",
8683a289941SAaron LI 		    sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer),
8693a289941SAaron LI 		    total_length,
8703a289941SAaron LI 		    BT_SHB_INSANE_MAX);
8713a289941SAaron LI 
8723a289941SAaron LI 		*err = 1;
8733a289941SAaron LI 		return (NULL);
8743a289941SAaron LI 	}
8753a289941SAaron LI 
8763a289941SAaron LI 	/*
8773a289941SAaron LI 	 * OK, this is a good pcapng file.
8783a289941SAaron LI 	 * Allocate a pcap_t for it.
8793a289941SAaron LI 	 */
880*ea16f64eSAntonio Huete Jimenez 	p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_ng_sf);
8813a289941SAaron LI 	if (p == NULL) {
8823a289941SAaron LI 		/* Allocation failed. */
8833a289941SAaron LI 		*err = 1;
8843a289941SAaron LI 		return (NULL);
8853a289941SAaron LI 	}
8863a289941SAaron LI 	p->swapped = swapped;
8873a289941SAaron LI 	ps = p->priv;
8883a289941SAaron LI 
8893a289941SAaron LI 	/*
8903a289941SAaron LI 	 * What precision does the user want?
8913a289941SAaron LI 	 */
8923a289941SAaron LI 	switch (precision) {
8933a289941SAaron LI 
8943a289941SAaron LI 	case PCAP_TSTAMP_PRECISION_MICRO:
8953a289941SAaron LI 		ps->user_tsresol = 1000000;
8963a289941SAaron LI 		break;
8973a289941SAaron LI 
8983a289941SAaron LI 	case PCAP_TSTAMP_PRECISION_NANO:
8993a289941SAaron LI 		ps->user_tsresol = 1000000000;
9003a289941SAaron LI 		break;
9013a289941SAaron LI 
9023a289941SAaron LI 	default:
903*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
9043a289941SAaron LI 		    "unknown time stamp resolution %u", precision);
9053a289941SAaron LI 		free(p);
9063a289941SAaron LI 		*err = 1;
9073a289941SAaron LI 		return (NULL);
9083a289941SAaron LI 	}
9093a289941SAaron LI 
9103a289941SAaron LI 	p->opt.tstamp_precision = precision;
9113a289941SAaron LI 
9123a289941SAaron LI 	/*
9133a289941SAaron LI 	 * Allocate a buffer into which to read blocks.  We default to
9143a289941SAaron LI 	 * the maximum of:
9153a289941SAaron LI 	 *
9163a289941SAaron LI 	 *	the total length of the SHB for which we read the header;
9173a289941SAaron LI 	 *
9183a289941SAaron LI 	 *	2K, which should be more than large enough for an Enhanced
9193a289941SAaron LI 	 *	Packet Block containing a full-size Ethernet frame, and
9203a289941SAaron LI 	 *	leaving room for some options.
9213a289941SAaron LI 	 *
9223a289941SAaron LI 	 * If we find a bigger block, we reallocate the buffer, up to
9233a289941SAaron LI 	 * the maximum size.  We start out with a maximum size of
9243a289941SAaron LI 	 * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types
9253a289941SAaron LI 	 * with a maximum snapshot that results in a larger maximum
9263a289941SAaron LI 	 * block length, we boost the maximum.
9273a289941SAaron LI 	 */
9283a289941SAaron LI 	p->bufsize = 2048;
9293a289941SAaron LI 	if (p->bufsize < total_length)
9303a289941SAaron LI 		p->bufsize = total_length;
9313a289941SAaron LI 	p->buffer = malloc(p->bufsize);
9323a289941SAaron LI 	if (p->buffer == NULL) {
933*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
9343a289941SAaron LI 		free(p);
9353a289941SAaron LI 		*err = 1;
9363a289941SAaron LI 		return (NULL);
9373a289941SAaron LI 	}
9383a289941SAaron LI 	ps->max_blocksize = INITIAL_MAX_BLOCKSIZE;
9393a289941SAaron LI 
9403a289941SAaron LI 	/*
9413a289941SAaron LI 	 * Copy the stuff we've read to the buffer, and read the rest
9423a289941SAaron LI 	 * of the SHB.
9433a289941SAaron LI 	 */
9443a289941SAaron LI 	bhdrp = (struct block_header *)p->buffer;
9453a289941SAaron LI 	shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
9463a289941SAaron LI 	bhdrp->block_type = magic_int;
9473a289941SAaron LI 	bhdrp->total_length = total_length;
9483a289941SAaron LI 	shbp->byte_order_magic = byte_order_magic;
9493a289941SAaron LI 	if (read_bytes(fp,
9503a289941SAaron LI 	    (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
9513a289941SAaron LI 	    total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
9523a289941SAaron LI 	    1, errbuf) == -1)
9533a289941SAaron LI 		goto fail;
9543a289941SAaron LI 
9553a289941SAaron LI 	if (p->swapped) {
9563a289941SAaron LI 		/*
9573a289941SAaron LI 		 * Byte-swap the fields we've read.
9583a289941SAaron LI 		 */
9593a289941SAaron LI 		shbp->major_version = SWAPSHORT(shbp->major_version);
9603a289941SAaron LI 		shbp->minor_version = SWAPSHORT(shbp->minor_version);
9613a289941SAaron LI 
9623a289941SAaron LI 		/*
9633a289941SAaron LI 		 * XXX - we don't care about the section length.
9643a289941SAaron LI 		 */
9653a289941SAaron LI 	}
966*ea16f64eSAntonio Huete Jimenez 	/* Currently only SHB versions 1.0 and 1.2 are supported;
967*ea16f64eSAntonio Huete Jimenez 	   version 1.2 is treated as being the same as version 1.0.
968*ea16f64eSAntonio Huete Jimenez 	   See the current version of the pcapng specification.
969*ea16f64eSAntonio Huete Jimenez 
970*ea16f64eSAntonio Huete Jimenez 	   Version 1.2 is written by some programs that write additional
971*ea16f64eSAntonio Huete Jimenez 	   block types (which can be read by any code that handles them,
972*ea16f64eSAntonio Huete Jimenez 	   regardless of whether the minor version if 0 or 2, so that's
973*ea16f64eSAntonio Huete Jimenez 	   not a reason to change the minor version number).
974*ea16f64eSAntonio Huete Jimenez 
975*ea16f64eSAntonio Huete Jimenez 	   XXX - the pcapng specification says that readers should
976*ea16f64eSAntonio Huete Jimenez 	   just ignore sections with an unsupported version number;
977*ea16f64eSAntonio Huete Jimenez 	   presumably they can also report an error if they skip
978*ea16f64eSAntonio Huete Jimenez 	   all the way to the end of the file without finding
979*ea16f64eSAntonio Huete Jimenez 	   any versions that they support. */
9803a289941SAaron LI 	if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
981*ea16f64eSAntonio Huete Jimenez 	       (shbp->minor_version == PCAP_NG_VERSION_MINOR ||
982*ea16f64eSAntonio Huete Jimenez 	        shbp->minor_version == 2))) {
983*ea16f64eSAntonio Huete Jimenez 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
9843a289941SAaron LI 		    "unsupported pcapng savefile version %u.%u",
9853a289941SAaron LI 		    shbp->major_version, shbp->minor_version);
9863a289941SAaron LI 		goto fail;
9873a289941SAaron LI 	}
9883a289941SAaron LI 	p->version_major = shbp->major_version;
9893a289941SAaron LI 	p->version_minor = shbp->minor_version;
9903a289941SAaron LI 
9913a289941SAaron LI 	/*
9923a289941SAaron LI 	 * Save the time stamp resolution the user requested.
9933a289941SAaron LI 	 */
9943a289941SAaron LI 	p->opt.tstamp_precision = precision;
9953a289941SAaron LI 
9963a289941SAaron LI 	/*
9973a289941SAaron LI 	 * Now start looking for an Interface Description Block.
9983a289941SAaron LI 	 */
9993a289941SAaron LI 	for (;;) {
10003a289941SAaron LI 		/*
10013a289941SAaron LI 		 * Read the next block.
10023a289941SAaron LI 		 */
10033a289941SAaron LI 		status = read_block(fp, p, &cursor, errbuf);
10043a289941SAaron LI 		if (status == 0) {
10053a289941SAaron LI 			/* EOF - no IDB in this file */
1006*ea16f64eSAntonio Huete Jimenez 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
10073a289941SAaron LI 			    "the capture file has no Interface Description Blocks");
10083a289941SAaron LI 			goto fail;
10093a289941SAaron LI 		}
10103a289941SAaron LI 		if (status == -1)
10113a289941SAaron LI 			goto fail;	/* error */
10123a289941SAaron LI 		switch (cursor.block_type) {
10133a289941SAaron LI 
10143a289941SAaron LI 		case BT_IDB:
10153a289941SAaron LI 			/*
10163a289941SAaron LI 			 * Get a pointer to the fixed-length portion of the
10173a289941SAaron LI 			 * IDB.
10183a289941SAaron LI 			 */
10193a289941SAaron LI 			idbp = get_from_block_data(&cursor, sizeof(*idbp),
10203a289941SAaron LI 			    errbuf);
10213a289941SAaron LI 			if (idbp == NULL)
10223a289941SAaron LI 				goto fail;	/* error */
10233a289941SAaron LI 
10243a289941SAaron LI 			/*
10253a289941SAaron LI 			 * Byte-swap it if necessary.
10263a289941SAaron LI 			 */
10273a289941SAaron LI 			if (p->swapped) {
10283a289941SAaron LI 				idbp->linktype = SWAPSHORT(idbp->linktype);
10293a289941SAaron LI 				idbp->snaplen = SWAPLONG(idbp->snaplen);
10303a289941SAaron LI 			}
10313a289941SAaron LI 
10323a289941SAaron LI 			/*
10333a289941SAaron LI 			 * Try to add this interface.
10343a289941SAaron LI 			 */
1035*ea16f64eSAntonio Huete Jimenez 			if (!add_interface(p, idbp, &cursor, errbuf))
10363a289941SAaron LI 				goto fail;
10373a289941SAaron LI 
10383a289941SAaron LI 			goto done;
10393a289941SAaron LI 
10403a289941SAaron LI 		case BT_EPB:
10413a289941SAaron LI 		case BT_SPB:
10423a289941SAaron LI 		case BT_PB:
10433a289941SAaron LI 			/*
10443a289941SAaron LI 			 * Saw a packet before we saw any IDBs.  That's
10453a289941SAaron LI 			 * not valid, as we don't know what link-layer
10463a289941SAaron LI 			 * encapsulation the packet has.
10473a289941SAaron LI 			 */
1048*ea16f64eSAntonio Huete Jimenez 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
10493a289941SAaron LI 			    "the capture file has a packet block before any Interface Description Blocks");
10503a289941SAaron LI 			goto fail;
10513a289941SAaron LI 
10523a289941SAaron LI 		default:
10533a289941SAaron LI 			/*
10543a289941SAaron LI 			 * Just ignore it.
10553a289941SAaron LI 			 */
10563a289941SAaron LI 			break;
10573a289941SAaron LI 		}
10583a289941SAaron LI 	}
10593a289941SAaron LI 
10603a289941SAaron LI done:
10613a289941SAaron LI 	p->linktype = linktype_to_dlt(idbp->linktype);
10623a289941SAaron LI 	p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen);
10633a289941SAaron LI 	p->linktype_ext = 0;
10643a289941SAaron LI 
10653a289941SAaron LI 	/*
10663a289941SAaron LI 	 * If the maximum block size for a packet with the maximum
10673a289941SAaron LI 	 * snapshot length for this DLT_ is bigger than the current
10683a289941SAaron LI 	 * maximum block size, increase the maximum.
10693a289941SAaron LI 	 */
10703a289941SAaron LI 	if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
10713a289941SAaron LI 		ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype));
10723a289941SAaron LI 
10733a289941SAaron LI 	p->next_packet_op = pcap_ng_next_packet;
10743a289941SAaron LI 	p->cleanup_op = pcap_ng_cleanup;
10753a289941SAaron LI 
10763a289941SAaron LI 	return (p);
10773a289941SAaron LI 
10783a289941SAaron LI fail:
10793a289941SAaron LI 	free(ps->ifaces);
10803a289941SAaron LI 	free(p->buffer);
10813a289941SAaron LI 	free(p);
10823a289941SAaron LI 	*err = 1;
10833a289941SAaron LI 	return (NULL);
10843a289941SAaron LI }
10853a289941SAaron LI 
10863a289941SAaron LI static void
pcap_ng_cleanup(pcap_t * p)10873a289941SAaron LI pcap_ng_cleanup(pcap_t *p)
10883a289941SAaron LI {
10893a289941SAaron LI 	struct pcap_ng_sf *ps = p->priv;
10903a289941SAaron LI 
10913a289941SAaron LI 	free(ps->ifaces);
10923a289941SAaron LI 	sf_cleanup(p);
10933a289941SAaron LI }
10943a289941SAaron LI 
10953a289941SAaron LI /*
10963a289941SAaron LI  * Read and return the next packet from the savefile.  Return the header
10973a289941SAaron LI  * in hdr and a pointer to the contents in data.  Return 0 on success, 1
10983a289941SAaron LI  * if there were no more packets, and -1 on an error.
10993a289941SAaron LI  */
11003a289941SAaron LI static int
pcap_ng_next_packet(pcap_t * p,struct pcap_pkthdr * hdr,u_char ** data)11013a289941SAaron LI pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
11023a289941SAaron LI {
11033a289941SAaron LI 	struct pcap_ng_sf *ps = p->priv;
11043a289941SAaron LI 	struct block_cursor cursor;
11053a289941SAaron LI 	int status;
11063a289941SAaron LI 	struct enhanced_packet_block *epbp;
11073a289941SAaron LI 	struct simple_packet_block *spbp;
11083a289941SAaron LI 	struct packet_block *pbp;
11093a289941SAaron LI 	bpf_u_int32 interface_id = 0xFFFFFFFF;
11103a289941SAaron LI 	struct interface_description_block *idbp;
11113a289941SAaron LI 	struct section_header_block *shbp;
11123a289941SAaron LI 	FILE *fp = p->rfile;
11133a289941SAaron LI 	uint64_t t, sec, frac;
11143a289941SAaron LI 
11153a289941SAaron LI 	/*
11163a289941SAaron LI 	 * Look for an Enhanced Packet Block, a Simple Packet Block,
11173a289941SAaron LI 	 * or a Packet Block.
11183a289941SAaron LI 	 */
11193a289941SAaron LI 	for (;;) {
11203a289941SAaron LI 		/*
11213a289941SAaron LI 		 * Read the block type and length; those are common
11223a289941SAaron LI 		 * to all blocks.
11233a289941SAaron LI 		 */
11243a289941SAaron LI 		status = read_block(fp, p, &cursor, p->errbuf);
11253a289941SAaron LI 		if (status == 0)
11263a289941SAaron LI 			return (1);	/* EOF */
11273a289941SAaron LI 		if (status == -1)
11283a289941SAaron LI 			return (-1);	/* error */
11293a289941SAaron LI 		switch (cursor.block_type) {
11303a289941SAaron LI 
11313a289941SAaron LI 		case BT_EPB:
11323a289941SAaron LI 			/*
11333a289941SAaron LI 			 * Get a pointer to the fixed-length portion of the
11343a289941SAaron LI 			 * EPB.
11353a289941SAaron LI 			 */
11363a289941SAaron LI 			epbp = get_from_block_data(&cursor, sizeof(*epbp),
11373a289941SAaron LI 			    p->errbuf);
11383a289941SAaron LI 			if (epbp == NULL)
11393a289941SAaron LI 				return (-1);	/* error */
11403a289941SAaron LI 
11413a289941SAaron LI 			/*
11423a289941SAaron LI 			 * Byte-swap it if necessary.
11433a289941SAaron LI 			 */
11443a289941SAaron LI 			if (p->swapped) {
11453a289941SAaron LI 				/* these were written in opposite byte order */
11463a289941SAaron LI 				interface_id = SWAPLONG(epbp->interface_id);
11473a289941SAaron LI 				hdr->caplen = SWAPLONG(epbp->caplen);
11483a289941SAaron LI 				hdr->len = SWAPLONG(epbp->len);
11493a289941SAaron LI 				t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
11503a289941SAaron LI 				    SWAPLONG(epbp->timestamp_low);
11513a289941SAaron LI 			} else {
11523a289941SAaron LI 				interface_id = epbp->interface_id;
11533a289941SAaron LI 				hdr->caplen = epbp->caplen;
11543a289941SAaron LI 				hdr->len = epbp->len;
11553a289941SAaron LI 				t = ((uint64_t)epbp->timestamp_high) << 32 |
11563a289941SAaron LI 				    epbp->timestamp_low;
11573a289941SAaron LI 			}
11583a289941SAaron LI 			goto found;
11593a289941SAaron LI 
11603a289941SAaron LI 		case BT_SPB:
11613a289941SAaron LI 			/*
11623a289941SAaron LI 			 * Get a pointer to the fixed-length portion of the
11633a289941SAaron LI 			 * SPB.
11643a289941SAaron LI 			 */
11653a289941SAaron LI 			spbp = get_from_block_data(&cursor, sizeof(*spbp),
11663a289941SAaron LI 			    p->errbuf);
11673a289941SAaron LI 			if (spbp == NULL)
11683a289941SAaron LI 				return (-1);	/* error */
11693a289941SAaron LI 
11703a289941SAaron LI 			/*
11713a289941SAaron LI 			 * SPB packets are assumed to have arrived on
11723a289941SAaron LI 			 * the first interface.
11733a289941SAaron LI 			 */
11743a289941SAaron LI 			interface_id = 0;
11753a289941SAaron LI 
11763a289941SAaron LI 			/*
11773a289941SAaron LI 			 * Byte-swap it if necessary.
11783a289941SAaron LI 			 */
11793a289941SAaron LI 			if (p->swapped) {
11803a289941SAaron LI 				/* these were written in opposite byte order */
11813a289941SAaron LI 				hdr->len = SWAPLONG(spbp->len);
11823a289941SAaron LI 			} else
11833a289941SAaron LI 				hdr->len = spbp->len;
11843a289941SAaron LI 
11853a289941SAaron LI 			/*
11863a289941SAaron LI 			 * The SPB doesn't give the captured length;
11873a289941SAaron LI 			 * it's the minimum of the snapshot length
11883a289941SAaron LI 			 * and the packet length.
11893a289941SAaron LI 			 */
11903a289941SAaron LI 			hdr->caplen = hdr->len;
11913a289941SAaron LI 			if (hdr->caplen > (bpf_u_int32)p->snapshot)
11923a289941SAaron LI 				hdr->caplen = p->snapshot;
11933a289941SAaron LI 			t = 0;	/* no time stamps */
11943a289941SAaron LI 			goto found;
11953a289941SAaron LI 
11963a289941SAaron LI 		case BT_PB:
11973a289941SAaron LI 			/*
11983a289941SAaron LI 			 * Get a pointer to the fixed-length portion of the
11993a289941SAaron LI 			 * PB.
12003a289941SAaron LI 			 */
12013a289941SAaron LI 			pbp = get_from_block_data(&cursor, sizeof(*pbp),
12023a289941SAaron LI 			    p->errbuf);
12033a289941SAaron LI 			if (pbp == NULL)
12043a289941SAaron LI 				return (-1);	/* error */
12053a289941SAaron LI 
12063a289941SAaron LI 			/*
12073a289941SAaron LI 			 * Byte-swap it if necessary.
12083a289941SAaron LI 			 */
12093a289941SAaron LI 			if (p->swapped) {
12103a289941SAaron LI 				/* these were written in opposite byte order */
12113a289941SAaron LI 				interface_id = SWAPSHORT(pbp->interface_id);
12123a289941SAaron LI 				hdr->caplen = SWAPLONG(pbp->caplen);
12133a289941SAaron LI 				hdr->len = SWAPLONG(pbp->len);
12143a289941SAaron LI 				t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
12153a289941SAaron LI 				    SWAPLONG(pbp->timestamp_low);
12163a289941SAaron LI 			} else {
12173a289941SAaron LI 				interface_id = pbp->interface_id;
12183a289941SAaron LI 				hdr->caplen = pbp->caplen;
12193a289941SAaron LI 				hdr->len = pbp->len;
12203a289941SAaron LI 				t = ((uint64_t)pbp->timestamp_high) << 32 |
12213a289941SAaron LI 				    pbp->timestamp_low;
12223a289941SAaron LI 			}
12233a289941SAaron LI 			goto found;
12243a289941SAaron LI 
12253a289941SAaron LI 		case BT_IDB:
12263a289941SAaron LI 			/*
12273a289941SAaron LI 			 * Interface Description Block.  Get a pointer
12283a289941SAaron LI 			 * to its fixed-length portion.
12293a289941SAaron LI 			 */
12303a289941SAaron LI 			idbp = get_from_block_data(&cursor, sizeof(*idbp),
12313a289941SAaron LI 			    p->errbuf);
12323a289941SAaron LI 			if (idbp == NULL)
12333a289941SAaron LI 				return (-1);	/* error */
12343a289941SAaron LI 
12353a289941SAaron LI 			/*
12363a289941SAaron LI 			 * Byte-swap it if necessary.
12373a289941SAaron LI 			 */
12383a289941SAaron LI 			if (p->swapped) {
12393a289941SAaron LI 				idbp->linktype = SWAPSHORT(idbp->linktype);
12403a289941SAaron LI 				idbp->snaplen = SWAPLONG(idbp->snaplen);
12413a289941SAaron LI 			}
12423a289941SAaron LI 
12433a289941SAaron LI 			/*
12443a289941SAaron LI 			 * If the link-layer type or snapshot length
12453a289941SAaron LI 			 * differ from the ones for the first IDB we
12463a289941SAaron LI 			 * saw, quit.
12473a289941SAaron LI 			 *
12483a289941SAaron LI 			 * XXX - just discard packets from those
12493a289941SAaron LI 			 * interfaces?
12503a289941SAaron LI 			 */
12513a289941SAaron LI 			if (p->linktype != idbp->linktype) {
1252*ea16f64eSAntonio Huete Jimenez 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
12533a289941SAaron LI 				    "an interface has a type %u different from the type of the first interface",
12543a289941SAaron LI 				    idbp->linktype);
12553a289941SAaron LI 				return (-1);
12563a289941SAaron LI 			}
12573a289941SAaron LI 
12583a289941SAaron LI 			/*
12593a289941SAaron LI 			 * Check against the *adjusted* value of this IDB's
12603a289941SAaron LI 			 * snapshot length.
12613a289941SAaron LI 			 */
12623a289941SAaron LI 			if ((bpf_u_int32)p->snapshot !=
12633a289941SAaron LI 			    pcap_adjust_snapshot(p->linktype, idbp->snaplen)) {
1264*ea16f64eSAntonio Huete Jimenez 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1265*ea16f64eSAntonio Huete Jimenez 				    "an interface has a snapshot length %u different from the snapshot length of the first interface",
12663a289941SAaron LI 				    idbp->snaplen);
12673a289941SAaron LI 				return (-1);
12683a289941SAaron LI 			}
12693a289941SAaron LI 
12703a289941SAaron LI 			/*
12713a289941SAaron LI 			 * Try to add this interface.
12723a289941SAaron LI 			 */
1273*ea16f64eSAntonio Huete Jimenez 			if (!add_interface(p, idbp, &cursor, p->errbuf))
12743a289941SAaron LI 				return (-1);
12753a289941SAaron LI 			break;
12763a289941SAaron LI 
12773a289941SAaron LI 		case BT_SHB:
12783a289941SAaron LI 			/*
12793a289941SAaron LI 			 * Section Header Block.  Get a pointer
12803a289941SAaron LI 			 * to its fixed-length portion.
12813a289941SAaron LI 			 */
12823a289941SAaron LI 			shbp = get_from_block_data(&cursor, sizeof(*shbp),
12833a289941SAaron LI 			    p->errbuf);
12843a289941SAaron LI 			if (shbp == NULL)
12853a289941SAaron LI 				return (-1);	/* error */
12863a289941SAaron LI 
12873a289941SAaron LI 			/*
12883a289941SAaron LI 			 * Assume the byte order of this section is
12893a289941SAaron LI 			 * the same as that of the previous section.
12903a289941SAaron LI 			 * We'll check for that later.
12913a289941SAaron LI 			 */
12923a289941SAaron LI 			if (p->swapped) {
12933a289941SAaron LI 				shbp->byte_order_magic =
12943a289941SAaron LI 				    SWAPLONG(shbp->byte_order_magic);
12953a289941SAaron LI 				shbp->major_version =
12963a289941SAaron LI 				    SWAPSHORT(shbp->major_version);
12973a289941SAaron LI 			}
12983a289941SAaron LI 
12993a289941SAaron LI 			/*
13003a289941SAaron LI 			 * Make sure the byte order doesn't change;
13013a289941SAaron LI 			 * pcap_is_swapped() shouldn't change its
13023a289941SAaron LI 			 * return value in the middle of reading a capture.
13033a289941SAaron LI 			 */
13043a289941SAaron LI 			switch (shbp->byte_order_magic) {
13053a289941SAaron LI 
13063a289941SAaron LI 			case BYTE_ORDER_MAGIC:
13073a289941SAaron LI 				/*
13083a289941SAaron LI 				 * OK.
13093a289941SAaron LI 				 */
13103a289941SAaron LI 				break;
13113a289941SAaron LI 
13123a289941SAaron LI 			case SWAPLONG(BYTE_ORDER_MAGIC):
13133a289941SAaron LI 				/*
13143a289941SAaron LI 				 * Byte order changes.
13153a289941SAaron LI 				 */
1316*ea16f64eSAntonio Huete Jimenez 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
13173a289941SAaron LI 				    "the file has sections with different byte orders");
13183a289941SAaron LI 				return (-1);
13193a289941SAaron LI 
13203a289941SAaron LI 			default:
13213a289941SAaron LI 				/*
13223a289941SAaron LI 				 * Not a valid SHB.
13233a289941SAaron LI 				 */
1324*ea16f64eSAntonio Huete Jimenez 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
13253a289941SAaron LI 				    "the file has a section with a bad byte order magic field");
13263a289941SAaron LI 				return (-1);
13273a289941SAaron LI 			}
13283a289941SAaron LI 
13293a289941SAaron LI 			/*
13303a289941SAaron LI 			 * Make sure the major version is the version
13313a289941SAaron LI 			 * we handle.
13323a289941SAaron LI 			 */
13333a289941SAaron LI 			if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
1334*ea16f64eSAntonio Huete Jimenez 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
13353a289941SAaron LI 				    "unknown pcapng savefile major version number %u",
13363a289941SAaron LI 				    shbp->major_version);
13373a289941SAaron LI 				return (-1);
13383a289941SAaron LI 			}
13393a289941SAaron LI 
13403a289941SAaron LI 			/*
13413a289941SAaron LI 			 * Reset the interface count; this section should
13423a289941SAaron LI 			 * have its own set of IDBs.  If any of them
13433a289941SAaron LI 			 * don't have the same interface type, snapshot
13443a289941SAaron LI 			 * length, or resolution as the first interface
13453a289941SAaron LI 			 * we saw, we'll fail.  (And if we don't see
13463a289941SAaron LI 			 * any IDBs, we'll fail when we see a packet
13473a289941SAaron LI 			 * block.)
13483a289941SAaron LI 			 */
13493a289941SAaron LI 			ps->ifcount = 0;
13503a289941SAaron LI 			break;
13513a289941SAaron LI 
13523a289941SAaron LI 		default:
13533a289941SAaron LI 			/*
13543a289941SAaron LI 			 * Not a packet block, IDB, or SHB; ignore it.
13553a289941SAaron LI 			 */
13563a289941SAaron LI 			break;
13573a289941SAaron LI 		}
13583a289941SAaron LI 	}
13593a289941SAaron LI 
13603a289941SAaron LI found:
13613a289941SAaron LI 	/*
13623a289941SAaron LI 	 * Is the interface ID an interface we know?
13633a289941SAaron LI 	 */
13643a289941SAaron LI 	if (interface_id >= ps->ifcount) {
13653a289941SAaron LI 		/*
13663a289941SAaron LI 		 * Yes.  Fail.
13673a289941SAaron LI 		 */
1368*ea16f64eSAntonio Huete Jimenez 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
13693a289941SAaron LI 		    "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
13703a289941SAaron LI 		    interface_id);
13713a289941SAaron LI 		return (-1);
13723a289941SAaron LI 	}
13733a289941SAaron LI 
13743a289941SAaron LI 	if (hdr->caplen > (bpf_u_int32)p->snapshot) {
1375*ea16f64eSAntonio Huete Jimenez 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
13763a289941SAaron LI 		    "invalid packet capture length %u, bigger than "
13773a289941SAaron LI 		    "snaplen of %d", hdr->caplen, p->snapshot);
13783a289941SAaron LI 		return (-1);
13793a289941SAaron LI 	}
13803a289941SAaron LI 
13813a289941SAaron LI 	/*
13823a289941SAaron LI 	 * Convert the time stamp to seconds and fractions of a second,
13833a289941SAaron LI 	 * with the fractions being in units of the file-supplied resolution.
13843a289941SAaron LI 	 */
13853a289941SAaron LI 	sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
13863a289941SAaron LI 	frac = t % ps->ifaces[interface_id].tsresol;
13873a289941SAaron LI 
13883a289941SAaron LI 	/*
13893a289941SAaron LI 	 * Convert the fractions from units of the file-supplied resolution
13903a289941SAaron LI 	 * to units of the user-requested resolution.
13913a289941SAaron LI 	 */
13923a289941SAaron LI 	switch (ps->ifaces[interface_id].scale_type) {
13933a289941SAaron LI 
13943a289941SAaron LI 	case PASS_THROUGH:
13953a289941SAaron LI 		/*
13963a289941SAaron LI 		 * The interface resolution is what the user wants,
13973a289941SAaron LI 		 * so we're done.
13983a289941SAaron LI 		 */
13993a289941SAaron LI 		break;
14003a289941SAaron LI 
14013a289941SAaron LI 	case SCALE_UP_DEC:
14023a289941SAaron LI 		/*
14033a289941SAaron LI 		 * The interface resolution is less than what the user
14043a289941SAaron LI 		 * wants; scale the fractional part up to the units of
14053a289941SAaron LI 		 * the resolution the user requested by multiplying by
14063a289941SAaron LI 		 * the quotient of the user-requested resolution and the
14073a289941SAaron LI 		 * file-supplied resolution.
14083a289941SAaron LI 		 *
14093a289941SAaron LI 		 * Those resolutions are both powers of 10, and the user-
14103a289941SAaron LI 		 * requested resolution is greater than the file-supplied
14113a289941SAaron LI 		 * resolution, so the quotient in question is an integer.
14123a289941SAaron LI 		 * We've calculated that quotient already, so we just
14133a289941SAaron LI 		 * multiply by it.
14143a289941SAaron LI 		 */
14153a289941SAaron LI 		frac *= ps->ifaces[interface_id].scale_factor;
14163a289941SAaron LI 		break;
14173a289941SAaron LI 
14183a289941SAaron LI 	case SCALE_UP_BIN:
14193a289941SAaron LI 		/*
14203a289941SAaron LI 		 * The interface resolution is less than what the user
14213a289941SAaron LI 		 * wants; scale the fractional part up to the units of
14223a289941SAaron LI 		 * the resolution the user requested by multiplying by
14233a289941SAaron LI 		 * the quotient of the user-requested resolution and the
14243a289941SAaron LI 		 * file-supplied resolution.
14253a289941SAaron LI 		 *
14263a289941SAaron LI 		 * The file-supplied resolution is a power of 2, so the
14273a289941SAaron LI 		 * quotient is not an integer, so, in order to do this
14283a289941SAaron LI 		 * entirely with integer arithmetic, we multiply by the
14293a289941SAaron LI 		 * user-requested resolution and divide by the file-
14303a289941SAaron LI 		 * supplied resolution.
14313a289941SAaron LI 		 *
14323a289941SAaron LI 		 * XXX - Is there something clever we could do here,
14333a289941SAaron LI 		 * given that we know that the file-supplied resolution
14343a289941SAaron LI 		 * is a power of 2?  Doing a multiplication followed by
14353a289941SAaron LI 		 * a division runs the risk of overflowing, and involves
14363a289941SAaron LI 		 * two non-simple arithmetic operations.
14373a289941SAaron LI 		 */
14383a289941SAaron LI 		frac *= ps->user_tsresol;
14393a289941SAaron LI 		frac /= ps->ifaces[interface_id].tsresol;
14403a289941SAaron LI 		break;
14413a289941SAaron LI 
14423a289941SAaron LI 	case SCALE_DOWN_DEC:
14433a289941SAaron LI 		/*
14443a289941SAaron LI 		 * The interface resolution is greater than what the user
14453a289941SAaron LI 		 * wants; scale the fractional part up to the units of
14463a289941SAaron LI 		 * the resolution the user requested by multiplying by
14473a289941SAaron LI 		 * the quotient of the user-requested resolution and the
14483a289941SAaron LI 		 * file-supplied resolution.
14493a289941SAaron LI 		 *
14503a289941SAaron LI 		 * Those resolutions are both powers of 10, and the user-
14513a289941SAaron LI 		 * requested resolution is less than the file-supplied
14523a289941SAaron LI 		 * resolution, so the quotient in question isn't an
14533a289941SAaron LI 		 * integer, but its reciprocal is, and we can just divide
14543a289941SAaron LI 		 * by the reciprocal of the quotient.  We've calculated
14553a289941SAaron LI 		 * the reciprocal of that quotient already, so we must
14563a289941SAaron LI 		 * divide by it.
14573a289941SAaron LI 		 */
14583a289941SAaron LI 		frac /= ps->ifaces[interface_id].scale_factor;
14593a289941SAaron LI 		break;
14603a289941SAaron LI 
14613a289941SAaron LI 
14623a289941SAaron LI 	case SCALE_DOWN_BIN:
14633a289941SAaron LI 		/*
14643a289941SAaron LI 		 * The interface resolution is greater than what the user
14653a289941SAaron LI 		 * wants; convert the fractional part to units of the
14663a289941SAaron LI 		 * resolution the user requested by multiplying by the
14673a289941SAaron LI 		 * quotient of the user-requested resolution and the
14683a289941SAaron LI 		 * file-supplied resolution.  We do that by multiplying
14693a289941SAaron LI 		 * by the user-requested resolution and dividing by the
14703a289941SAaron LI 		 * file-supplied resolution, as the quotient might not
14713a289941SAaron LI 		 * fit in an integer.
14723a289941SAaron LI 		 *
14733a289941SAaron LI 		 * The file-supplied resolution is a power of 2, so the
14743a289941SAaron LI 		 * quotient is not an integer, and neither is its
14753a289941SAaron LI 		 * reciprocal, so, in order to do this entirely with
14763a289941SAaron LI 		 * integer arithmetic, we multiply by the user-requested
14773a289941SAaron LI 		 * resolution and divide by the file-supplied resolution.
14783a289941SAaron LI 		 *
14793a289941SAaron LI 		 * XXX - Is there something clever we could do here,
14803a289941SAaron LI 		 * given that we know that the file-supplied resolution
14813a289941SAaron LI 		 * is a power of 2?  Doing a multiplication followed by
14823a289941SAaron LI 		 * a division runs the risk of overflowing, and involves
14833a289941SAaron LI 		 * two non-simple arithmetic operations.
14843a289941SAaron LI 		 */
14853a289941SAaron LI 		frac *= ps->user_tsresol;
14863a289941SAaron LI 		frac /= ps->ifaces[interface_id].tsresol;
14873a289941SAaron LI 		break;
14883a289941SAaron LI 	}
14893a289941SAaron LI #ifdef _WIN32
14903a289941SAaron LI 	/*
14913a289941SAaron LI 	 * tv_sec and tv_used in the Windows struct timeval are both
14923a289941SAaron LI 	 * longs.
14933a289941SAaron LI 	 */
14943a289941SAaron LI 	hdr->ts.tv_sec = (long)sec;
14953a289941SAaron LI 	hdr->ts.tv_usec = (long)frac;
14963a289941SAaron LI #else
14973a289941SAaron LI 	/*
14983a289941SAaron LI 	 * tv_sec in the UN*X struct timeval is a time_t; tv_usec is
14993a289941SAaron LI 	 * suseconds_t in UN*Xes that work the way the current Single
15003a289941SAaron LI 	 * UNIX Standard specify - but not all older UN*Xes necessarily
15013a289941SAaron LI 	 * support that type, so just cast to int.
15023a289941SAaron LI 	 */
15033a289941SAaron LI 	hdr->ts.tv_sec = (time_t)sec;
15043a289941SAaron LI 	hdr->ts.tv_usec = (int)frac;
15053a289941SAaron LI #endif
15063a289941SAaron LI 
15073a289941SAaron LI 	/*
15083a289941SAaron LI 	 * Get a pointer to the packet data.
15093a289941SAaron LI 	 */
15103a289941SAaron LI 	*data = get_from_block_data(&cursor, hdr->caplen, p->errbuf);
15113a289941SAaron LI 	if (*data == NULL)
15123a289941SAaron LI 		return (-1);
15133a289941SAaron LI 
15143a289941SAaron LI 	if (p->swapped)
15153a289941SAaron LI 		swap_pseudo_headers(p->linktype, hdr, *data);
15163a289941SAaron LI 
15173a289941SAaron LI 	return (0);
15183a289941SAaron LI }
1519