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