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