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 #ifdef HAVE_CONFIG_H 25b00ab754SHans Petter Selasky #include <config.h> 26b00ab754SHans Petter Selasky #endif 27b00ab754SHans Petter Selasky 28b00ab754SHans Petter Selasky #include <pcap/pcap-inttypes.h> 29b00ab754SHans Petter Selasky 30b00ab754SHans Petter Selasky #include <errno.h> 31b00ab754SHans Petter Selasky #include <memory.h> 32b00ab754SHans Petter Selasky #include <stdio.h> 33b00ab754SHans Petter Selasky #include <stdlib.h> 34b00ab754SHans Petter Selasky #include <string.h> 35b00ab754SHans Petter Selasky 36b00ab754SHans Petter Selasky #include "pcap-int.h" 37b00ab754SHans Petter Selasky 38b00ab754SHans Petter Selasky #include "pcap-common.h" 39b00ab754SHans Petter Selasky 40b00ab754SHans Petter Selasky #ifdef HAVE_OS_PROTO_H 41b00ab754SHans Petter Selasky #include "os-proto.h" 42b00ab754SHans Petter Selasky #endif 43b00ab754SHans Petter Selasky 44b00ab754SHans Petter Selasky #include "sf-pcapng.h" 45b00ab754SHans Petter Selasky 46b00ab754SHans Petter Selasky /* 47b00ab754SHans Petter Selasky * Block types. 48b00ab754SHans Petter Selasky */ 49b00ab754SHans Petter Selasky 50b00ab754SHans Petter Selasky /* 51b00ab754SHans Petter Selasky * Common part at the beginning of all blocks. 52b00ab754SHans Petter Selasky */ 53b00ab754SHans Petter Selasky struct block_header { 54b00ab754SHans Petter Selasky bpf_u_int32 block_type; 55b00ab754SHans Petter Selasky bpf_u_int32 total_length; 56b00ab754SHans Petter Selasky }; 57b00ab754SHans Petter Selasky 58b00ab754SHans Petter Selasky /* 59b00ab754SHans Petter Selasky * Common trailer at the end of all blocks. 60b00ab754SHans Petter Selasky */ 61b00ab754SHans Petter Selasky struct block_trailer { 62b00ab754SHans Petter Selasky bpf_u_int32 total_length; 63b00ab754SHans Petter Selasky }; 64b00ab754SHans Petter Selasky 65b00ab754SHans Petter Selasky /* 66b00ab754SHans Petter Selasky * Common options. 67b00ab754SHans Petter Selasky */ 68b00ab754SHans Petter Selasky #define OPT_ENDOFOPT 0 /* end of options */ 69b00ab754SHans Petter Selasky #define OPT_COMMENT 1 /* comment string */ 70b00ab754SHans Petter Selasky 71b00ab754SHans Petter Selasky /* 72b00ab754SHans Petter Selasky * Option header. 73b00ab754SHans Petter Selasky */ 74b00ab754SHans Petter Selasky struct option_header { 75b00ab754SHans Petter Selasky u_short option_code; 76b00ab754SHans Petter Selasky u_short option_length; 77b00ab754SHans Petter Selasky }; 78b00ab754SHans Petter Selasky 79b00ab754SHans Petter Selasky /* 80b00ab754SHans Petter Selasky * Structures for the part of each block type following the common 81b00ab754SHans Petter Selasky * part. 82b00ab754SHans Petter Selasky */ 83b00ab754SHans Petter Selasky 84b00ab754SHans Petter Selasky /* 85b00ab754SHans Petter Selasky * Section Header Block. 86b00ab754SHans Petter Selasky */ 87b00ab754SHans Petter Selasky #define BT_SHB 0x0A0D0D0A 88*57e22627SCy Schubert #define BT_SHB_INSANE_MAX 1024U*1024U*1U /* 1MB should be enough */ 89b00ab754SHans Petter Selasky struct section_header_block { 90b00ab754SHans Petter Selasky bpf_u_int32 byte_order_magic; 91b00ab754SHans Petter Selasky u_short major_version; 92b00ab754SHans Petter Selasky u_short minor_version; 93b00ab754SHans Petter Selasky uint64_t section_length; 94b00ab754SHans Petter Selasky /* followed by options and trailer */ 95b00ab754SHans Petter Selasky }; 96b00ab754SHans Petter Selasky 97b00ab754SHans Petter Selasky /* 98b00ab754SHans Petter Selasky * Byte-order magic value. 99b00ab754SHans Petter Selasky */ 100b00ab754SHans Petter Selasky #define BYTE_ORDER_MAGIC 0x1A2B3C4D 101b00ab754SHans Petter Selasky 102b00ab754SHans Petter Selasky /* 103b00ab754SHans Petter Selasky * Current version number. If major_version isn't PCAP_NG_VERSION_MAJOR, 104b00ab754SHans Petter Selasky * that means that 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 { 200*57e22627SCy Schubert uint64_t tsresol; /* time stamp resolution */ 201b00ab754SHans Petter Selasky tstamp_scale_type_t scale_type; /* how to scale */ 202*57e22627SCy Schubert uint64_t scale_factor; /* time stamp scale factor for power-of-10 tsresol */ 203b00ab754SHans Petter Selasky uint64_t tsoffset; /* time stamp offset */ 204b00ab754SHans Petter Selasky }; 205b00ab754SHans Petter Selasky 206b00ab754SHans Petter Selasky /* 207b00ab754SHans Petter Selasky * Per-pcap_t private data. 208b00ab754SHans Petter Selasky * 209b00ab754SHans Petter Selasky * max_blocksize is the maximum size of a block that we'll accept. We 210b00ab754SHans Petter Selasky * reject blocks bigger than this, so we don't consume too much memory 211b00ab754SHans Petter Selasky * with a truly huge block. It can change as we see IDBs with different 212b00ab754SHans Petter Selasky * link-layer header types. (Currently, we don't support IDBs with 213b00ab754SHans Petter Selasky * different link-layer header types, but we will support it in the 214b00ab754SHans Petter Selasky * future, when we offer file-reading APIs that support it.) 215b00ab754SHans Petter Selasky * 216b00ab754SHans Petter Selasky * XXX - that's an issue on ILP32 platforms, where the maximum block 217b00ab754SHans Petter Selasky * size of 2^31-1 would eat all but one byte of the entire address space. 218b00ab754SHans Petter Selasky * It's less of an issue on ILP64/LLP64 platforms, but the actual size 219b00ab754SHans Petter Selasky * of the address space may be limited by 1) the number of *significant* 220b00ab754SHans Petter Selasky * address bits (currently, x86-64 only supports 48 bits of address), 2) 221b00ab754SHans Petter Selasky * any limitations imposed by the operating system; 3) any limitations 222b00ab754SHans Petter Selasky * imposed by the amount of available backing store for anonymous pages, 223b00ab754SHans Petter Selasky * so we impose a limit regardless of the size of a pointer. 224b00ab754SHans Petter Selasky */ 225b00ab754SHans Petter Selasky struct pcap_ng_sf { 226*57e22627SCy Schubert uint64_t user_tsresol; /* time stamp resolution requested by the user */ 227b00ab754SHans Petter Selasky u_int max_blocksize; /* don't grow buffer size past this */ 228b00ab754SHans Petter Selasky bpf_u_int32 ifcount; /* number of interfaces seen in this capture */ 229b00ab754SHans Petter Selasky bpf_u_int32 ifaces_size; /* size of array below */ 230b00ab754SHans Petter Selasky struct pcap_ng_if *ifaces; /* array of interface information */ 231b00ab754SHans Petter Selasky }; 232b00ab754SHans Petter Selasky 233b00ab754SHans Petter Selasky /* 234*57e22627SCy Schubert * The maximum block size we start with; we use an arbitrary value of 235*57e22627SCy Schubert * 16 MiB. 236b00ab754SHans Petter Selasky */ 237*57e22627SCy Schubert #define INITIAL_MAX_BLOCKSIZE (16*1024*1024) 238*57e22627SCy Schubert 239*57e22627SCy Schubert /* 240*57e22627SCy Schubert * Maximum block size for a given maximum snapshot length; we define it 241*57e22627SCy Schubert * as the size of an EPB with a max_snaplen-sized packet and 128KB of 242*57e22627SCy Schubert * options. 243*57e22627SCy Schubert */ 244*57e22627SCy Schubert #define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \ 245*57e22627SCy Schubert (sizeof (struct block_header) + \ 246b00ab754SHans Petter Selasky sizeof (struct enhanced_packet_block) + \ 247b00ab754SHans Petter Selasky (max_snaplen) + 131072 + \ 248b00ab754SHans Petter Selasky sizeof (struct block_trailer)) 249b00ab754SHans Petter Selasky 250b00ab754SHans Petter Selasky static void pcap_ng_cleanup(pcap_t *p); 251b00ab754SHans Petter Selasky static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, 252b00ab754SHans Petter Selasky u_char **data); 253b00ab754SHans Petter Selasky 254b00ab754SHans Petter Selasky static int 255b00ab754SHans Petter Selasky read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof, 256b00ab754SHans Petter Selasky char *errbuf) 257b00ab754SHans Petter Selasky { 258b00ab754SHans Petter Selasky size_t amt_read; 259b00ab754SHans Petter Selasky 260b00ab754SHans Petter Selasky amt_read = fread(buf, 1, bytes_to_read, fp); 261b00ab754SHans Petter Selasky if (amt_read != bytes_to_read) { 262b00ab754SHans Petter Selasky if (ferror(fp)) { 263b00ab754SHans Petter Selasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 264b00ab754SHans Petter Selasky errno, "error reading dump file"); 265b00ab754SHans Petter Selasky } else { 266b00ab754SHans Petter Selasky if (amt_read == 0 && !fail_on_eof) 267b00ab754SHans Petter Selasky return (0); /* EOF */ 268b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 269*57e22627SCy Schubert "truncated pcapng dump file; tried to read %" PRIsize " bytes, only got %" PRIsize, 270*57e22627SCy Schubert bytes_to_read, amt_read); 271b00ab754SHans Petter Selasky } 272b00ab754SHans Petter Selasky return (-1); 273b00ab754SHans Petter Selasky } 274b00ab754SHans Petter Selasky return (1); 275b00ab754SHans Petter Selasky } 276b00ab754SHans Petter Selasky 277b00ab754SHans Petter Selasky static int 278b00ab754SHans Petter Selasky read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf) 279b00ab754SHans Petter Selasky { 280b00ab754SHans Petter Selasky struct pcap_ng_sf *ps; 281b00ab754SHans Petter Selasky int status; 282b00ab754SHans Petter Selasky struct block_header bhdr; 283*57e22627SCy Schubert struct block_trailer *btrlr; 284b00ab754SHans Petter Selasky u_char *bdata; 285b00ab754SHans Petter Selasky size_t data_remaining; 286b00ab754SHans Petter Selasky 287b00ab754SHans Petter Selasky ps = p->priv; 288b00ab754SHans Petter Selasky 289b00ab754SHans Petter Selasky status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf); 290b00ab754SHans Petter Selasky if (status <= 0) 291b00ab754SHans Petter Selasky return (status); /* error or EOF */ 292b00ab754SHans Petter Selasky 293b00ab754SHans Petter Selasky if (p->swapped) { 294b00ab754SHans Petter Selasky bhdr.block_type = SWAPLONG(bhdr.block_type); 295b00ab754SHans Petter Selasky bhdr.total_length = SWAPLONG(bhdr.total_length); 296b00ab754SHans Petter Selasky } 297b00ab754SHans Petter Selasky 298b00ab754SHans Petter Selasky /* 299b00ab754SHans Petter Selasky * Is this block "too small" - i.e., is it shorter than a block 300b00ab754SHans Petter Selasky * header plus a block trailer? 301b00ab754SHans Petter Selasky */ 302b00ab754SHans Petter Selasky if (bhdr.total_length < sizeof(struct block_header) + 303b00ab754SHans Petter Selasky sizeof(struct block_trailer)) { 304b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 305*57e22627SCy Schubert "block in pcapng dump file has a length of %u < %" PRIsize, 306b00ab754SHans Petter Selasky bhdr.total_length, 307*57e22627SCy Schubert sizeof(struct block_header) + sizeof(struct block_trailer)); 308*57e22627SCy Schubert return (-1); 309*57e22627SCy Schubert } 310*57e22627SCy Schubert 311*57e22627SCy Schubert /* 312*57e22627SCy Schubert * Is the block total length a multiple of 4? 313*57e22627SCy Schubert */ 314*57e22627SCy Schubert if ((bhdr.total_length % 4) != 0) { 315*57e22627SCy Schubert /* 316*57e22627SCy Schubert * No. Report that as an error. 317*57e22627SCy Schubert */ 318*57e22627SCy Schubert pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 319*57e22627SCy Schubert "block in pcapng dump file has a length of %u that is not a multiple of 4" PRIsize, 320*57e22627SCy Schubert bhdr.total_length); 321b00ab754SHans Petter Selasky return (-1); 322b00ab754SHans Petter Selasky } 323b00ab754SHans Petter Selasky 324b00ab754SHans Petter Selasky /* 325b00ab754SHans Petter Selasky * Is the buffer big enough? 326b00ab754SHans Petter Selasky */ 327b00ab754SHans Petter Selasky if (p->bufsize < bhdr.total_length) { 328b00ab754SHans Petter Selasky /* 329*57e22627SCy Schubert * No - make it big enough, unless it's too big, in 330*57e22627SCy Schubert * which case we fail. 331b00ab754SHans Petter Selasky */ 332b00ab754SHans Petter Selasky void *bigger_buffer; 333b00ab754SHans Petter Selasky 334b00ab754SHans Petter Selasky if (bhdr.total_length > ps->max_blocksize) { 335*57e22627SCy Schubert pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length, 336b00ab754SHans Petter Selasky ps->max_blocksize); 337b00ab754SHans Petter Selasky return (-1); 338b00ab754SHans Petter Selasky } 339b00ab754SHans Petter Selasky bigger_buffer = realloc(p->buffer, bhdr.total_length); 340b00ab754SHans Petter Selasky if (bigger_buffer == NULL) { 341b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 342b00ab754SHans Petter Selasky return (-1); 343b00ab754SHans Petter Selasky } 344b00ab754SHans Petter Selasky p->buffer = bigger_buffer; 345b00ab754SHans Petter Selasky } 346b00ab754SHans Petter Selasky 347b00ab754SHans Petter Selasky /* 348b00ab754SHans Petter Selasky * Copy the stuff we've read to the buffer, and read the rest 349b00ab754SHans Petter Selasky * of the block. 350b00ab754SHans Petter Selasky */ 351b00ab754SHans Petter Selasky memcpy(p->buffer, &bhdr, sizeof(bhdr)); 352b00ab754SHans Petter Selasky bdata = (u_char *)p->buffer + sizeof(bhdr); 353b00ab754SHans Petter Selasky data_remaining = bhdr.total_length - sizeof(bhdr); 354b00ab754SHans Petter Selasky if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1) 355b00ab754SHans Petter Selasky return (-1); 356b00ab754SHans Petter Selasky 357b00ab754SHans Petter Selasky /* 358*57e22627SCy Schubert * Get the block size from the trailer. 359*57e22627SCy Schubert */ 360*57e22627SCy Schubert btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer)); 361*57e22627SCy Schubert if (p->swapped) 362*57e22627SCy Schubert btrlr->total_length = SWAPLONG(btrlr->total_length); 363*57e22627SCy Schubert 364*57e22627SCy Schubert /* 365*57e22627SCy Schubert * Is the total length from the trailer the same as the total 366*57e22627SCy Schubert * length from the header? 367*57e22627SCy Schubert */ 368*57e22627SCy Schubert if (bhdr.total_length != btrlr->total_length) { 369*57e22627SCy Schubert /* 370*57e22627SCy Schubert * No. 371*57e22627SCy Schubert */ 372*57e22627SCy Schubert pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 373*57e22627SCy Schubert "block total length in header and trailer don't match"); 374*57e22627SCy Schubert return (-1); 375*57e22627SCy Schubert } 376*57e22627SCy Schubert 377*57e22627SCy Schubert /* 378b00ab754SHans Petter Selasky * Initialize the cursor. 379b00ab754SHans Petter Selasky */ 380b00ab754SHans Petter Selasky cursor->data = bdata; 381b00ab754SHans Petter Selasky cursor->data_remaining = data_remaining - sizeof(struct block_trailer); 382b00ab754SHans Petter Selasky cursor->block_type = bhdr.block_type; 383b00ab754SHans Petter Selasky return (1); 384b00ab754SHans Petter Selasky } 385b00ab754SHans Petter Selasky 386b00ab754SHans Petter Selasky static void * 387b00ab754SHans Petter Selasky get_from_block_data(struct block_cursor *cursor, size_t chunk_size, 388b00ab754SHans Petter Selasky char *errbuf) 389b00ab754SHans Petter Selasky { 390b00ab754SHans Petter Selasky void *data; 391b00ab754SHans Petter Selasky 392b00ab754SHans Petter Selasky /* 393b00ab754SHans Petter Selasky * Make sure we have the specified amount of data remaining in 394b00ab754SHans Petter Selasky * the block data. 395b00ab754SHans Petter Selasky */ 396b00ab754SHans Petter Selasky if (cursor->data_remaining < chunk_size) { 397b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 398b00ab754SHans Petter Selasky "block of type %u in pcapng dump file is too short", 399b00ab754SHans Petter Selasky cursor->block_type); 400b00ab754SHans Petter Selasky return (NULL); 401b00ab754SHans Petter Selasky } 402b00ab754SHans Petter Selasky 403b00ab754SHans Petter Selasky /* 404b00ab754SHans Petter Selasky * Return the current pointer, and skip past the chunk. 405b00ab754SHans Petter Selasky */ 406b00ab754SHans Petter Selasky data = cursor->data; 407b00ab754SHans Petter Selasky cursor->data += chunk_size; 408b00ab754SHans Petter Selasky cursor->data_remaining -= chunk_size; 409b00ab754SHans Petter Selasky return (data); 410b00ab754SHans Petter Selasky } 411b00ab754SHans Petter Selasky 412b00ab754SHans Petter Selasky static struct option_header * 413b00ab754SHans Petter Selasky get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf) 414b00ab754SHans Petter Selasky { 415b00ab754SHans Petter Selasky struct option_header *opthdr; 416b00ab754SHans Petter Selasky 417b00ab754SHans Petter Selasky opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf); 418b00ab754SHans Petter Selasky if (opthdr == NULL) { 419b00ab754SHans Petter Selasky /* 420b00ab754SHans Petter Selasky * Option header is cut short. 421b00ab754SHans Petter Selasky */ 422b00ab754SHans Petter Selasky return (NULL); 423b00ab754SHans Petter Selasky } 424b00ab754SHans Petter Selasky 425b00ab754SHans Petter Selasky /* 426b00ab754SHans Petter Selasky * Byte-swap it if necessary. 427b00ab754SHans Petter Selasky */ 428b00ab754SHans Petter Selasky if (p->swapped) { 429b00ab754SHans Petter Selasky opthdr->option_code = SWAPSHORT(opthdr->option_code); 430b00ab754SHans Petter Selasky opthdr->option_length = SWAPSHORT(opthdr->option_length); 431b00ab754SHans Petter Selasky } 432b00ab754SHans Petter Selasky 433b00ab754SHans Petter Selasky return (opthdr); 434b00ab754SHans Petter Selasky } 435b00ab754SHans Petter Selasky 436b00ab754SHans Petter Selasky static void * 437b00ab754SHans Petter Selasky get_optvalue_from_block_data(struct block_cursor *cursor, 438b00ab754SHans Petter Selasky struct option_header *opthdr, char *errbuf) 439b00ab754SHans Petter Selasky { 440b00ab754SHans Petter Selasky size_t padded_option_len; 441b00ab754SHans Petter Selasky void *optvalue; 442b00ab754SHans Petter Selasky 443b00ab754SHans Petter Selasky /* Pad option length to 4-byte boundary */ 444b00ab754SHans Petter Selasky padded_option_len = opthdr->option_length; 445b00ab754SHans Petter Selasky padded_option_len = ((padded_option_len + 3)/4)*4; 446b00ab754SHans Petter Selasky 447b00ab754SHans Petter Selasky optvalue = get_from_block_data(cursor, padded_option_len, errbuf); 448b00ab754SHans Petter Selasky if (optvalue == NULL) { 449b00ab754SHans Petter Selasky /* 450b00ab754SHans Petter Selasky * Option value is cut short. 451b00ab754SHans Petter Selasky */ 452b00ab754SHans Petter Selasky return (NULL); 453b00ab754SHans Petter Selasky } 454b00ab754SHans Petter Selasky 455b00ab754SHans Petter Selasky return (optvalue); 456b00ab754SHans Petter Selasky } 457b00ab754SHans Petter Selasky 458b00ab754SHans Petter Selasky static int 459*57e22627SCy Schubert process_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol, 460b00ab754SHans Petter Selasky uint64_t *tsoffset, int *is_binary, char *errbuf) 461b00ab754SHans Petter Selasky { 462b00ab754SHans Petter Selasky struct option_header *opthdr; 463b00ab754SHans Petter Selasky void *optvalue; 464b00ab754SHans Petter Selasky int saw_tsresol, saw_tsoffset; 465*57e22627SCy Schubert uint8_t tsresol_opt; 466b00ab754SHans Petter Selasky u_int i; 467b00ab754SHans Petter Selasky 468b00ab754SHans Petter Selasky saw_tsresol = 0; 469b00ab754SHans Petter Selasky saw_tsoffset = 0; 470b00ab754SHans Petter Selasky while (cursor->data_remaining != 0) { 471b00ab754SHans Petter Selasky /* 472b00ab754SHans Petter Selasky * Get the option header. 473b00ab754SHans Petter Selasky */ 474b00ab754SHans Petter Selasky opthdr = get_opthdr_from_block_data(p, cursor, errbuf); 475b00ab754SHans Petter Selasky if (opthdr == NULL) { 476b00ab754SHans Petter Selasky /* 477b00ab754SHans Petter Selasky * Option header is cut short. 478b00ab754SHans Petter Selasky */ 479b00ab754SHans Petter Selasky return (-1); 480b00ab754SHans Petter Selasky } 481b00ab754SHans Petter Selasky 482b00ab754SHans Petter Selasky /* 483b00ab754SHans Petter Selasky * Get option value. 484b00ab754SHans Petter Selasky */ 485b00ab754SHans Petter Selasky optvalue = get_optvalue_from_block_data(cursor, opthdr, 486b00ab754SHans Petter Selasky errbuf); 487b00ab754SHans Petter Selasky if (optvalue == NULL) { 488b00ab754SHans Petter Selasky /* 489b00ab754SHans Petter Selasky * Option value is cut short. 490b00ab754SHans Petter Selasky */ 491b00ab754SHans Petter Selasky return (-1); 492b00ab754SHans Petter Selasky } 493b00ab754SHans Petter Selasky 494b00ab754SHans Petter Selasky switch (opthdr->option_code) { 495b00ab754SHans Petter Selasky 496b00ab754SHans Petter Selasky case OPT_ENDOFOPT: 497b00ab754SHans Petter Selasky if (opthdr->option_length != 0) { 498b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 499b00ab754SHans Petter Selasky "Interface Description Block has opt_endofopt option with length %u != 0", 500b00ab754SHans Petter Selasky opthdr->option_length); 501b00ab754SHans Petter Selasky return (-1); 502b00ab754SHans Petter Selasky } 503b00ab754SHans Petter Selasky goto done; 504b00ab754SHans Petter Selasky 505b00ab754SHans Petter Selasky case IF_TSRESOL: 506b00ab754SHans Petter Selasky if (opthdr->option_length != 1) { 507b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 508b00ab754SHans Petter Selasky "Interface Description Block has if_tsresol option with length %u != 1", 509b00ab754SHans Petter Selasky opthdr->option_length); 510b00ab754SHans Petter Selasky return (-1); 511b00ab754SHans Petter Selasky } 512b00ab754SHans Petter Selasky if (saw_tsresol) { 513b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 514b00ab754SHans Petter Selasky "Interface Description Block has more than one if_tsresol option"); 515b00ab754SHans Petter Selasky return (-1); 516b00ab754SHans Petter Selasky } 517b00ab754SHans Petter Selasky saw_tsresol = 1; 518b00ab754SHans Petter Selasky memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt)); 519b00ab754SHans Petter Selasky if (tsresol_opt & 0x80) { 520b00ab754SHans Petter Selasky /* 521b00ab754SHans Petter Selasky * Resolution is negative power of 2. 522b00ab754SHans Petter Selasky */ 523*57e22627SCy Schubert uint8_t tsresol_shift = (tsresol_opt & 0x7F); 524*57e22627SCy Schubert 525*57e22627SCy Schubert if (tsresol_shift > 63) { 526*57e22627SCy Schubert /* 527*57e22627SCy Schubert * Resolution is too high; 2^-{res} 528*57e22627SCy Schubert * won't fit in a 64-bit value. 529*57e22627SCy Schubert */ 530*57e22627SCy Schubert pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 531*57e22627SCy Schubert "Interface Description Block if_tsresol option resolution 2^-%u is too high", 532*57e22627SCy Schubert tsresol_shift); 533*57e22627SCy Schubert return (-1); 534*57e22627SCy Schubert } 535b00ab754SHans Petter Selasky *is_binary = 1; 536*57e22627SCy Schubert *tsresol = ((uint64_t)1) << tsresol_shift; 537b00ab754SHans Petter Selasky } else { 538b00ab754SHans Petter Selasky /* 539b00ab754SHans Petter Selasky * Resolution is negative power of 10. 540b00ab754SHans Petter Selasky */ 541*57e22627SCy Schubert if (tsresol_opt > 19) { 542*57e22627SCy Schubert /* 543*57e22627SCy Schubert * Resolution is too high; 2^-{res} 544*57e22627SCy Schubert * won't fit in a 64-bit value (the 545*57e22627SCy Schubert * largest power of 10 that fits 546*57e22627SCy Schubert * in a 64-bit value is 10^19, as 547*57e22627SCy Schubert * the largest 64-bit unsigned 548*57e22627SCy Schubert * value is ~1.8*10^19). 549*57e22627SCy Schubert */ 550*57e22627SCy Schubert pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 551*57e22627SCy Schubert "Interface Description Block if_tsresol option resolution 10^-%u is too high", 552*57e22627SCy Schubert tsresol_opt); 553*57e22627SCy Schubert return (-1); 554*57e22627SCy Schubert } 555b00ab754SHans Petter Selasky *is_binary = 0; 556b00ab754SHans Petter Selasky *tsresol = 1; 557b00ab754SHans Petter Selasky for (i = 0; i < tsresol_opt; i++) 558b00ab754SHans Petter Selasky *tsresol *= 10; 559b00ab754SHans Petter Selasky } 560b00ab754SHans Petter Selasky break; 561b00ab754SHans Petter Selasky 562b00ab754SHans Petter Selasky case IF_TSOFFSET: 563b00ab754SHans Petter Selasky if (opthdr->option_length != 8) { 564b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 565b00ab754SHans Petter Selasky "Interface Description Block has if_tsoffset option with length %u != 8", 566b00ab754SHans Petter Selasky opthdr->option_length); 567b00ab754SHans Petter Selasky return (-1); 568b00ab754SHans Petter Selasky } 569b00ab754SHans Petter Selasky if (saw_tsoffset) { 570b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 571b00ab754SHans Petter Selasky "Interface Description Block has more than one if_tsoffset option"); 572b00ab754SHans Petter Selasky return (-1); 573b00ab754SHans Petter Selasky } 574b00ab754SHans Petter Selasky saw_tsoffset = 1; 575b00ab754SHans Petter Selasky memcpy(tsoffset, optvalue, sizeof(*tsoffset)); 576b00ab754SHans Petter Selasky if (p->swapped) 577b00ab754SHans Petter Selasky *tsoffset = SWAPLL(*tsoffset); 578b00ab754SHans Petter Selasky break; 579b00ab754SHans Petter Selasky 580b00ab754SHans Petter Selasky default: 581b00ab754SHans Petter Selasky break; 582b00ab754SHans Petter Selasky } 583b00ab754SHans Petter Selasky } 584b00ab754SHans Petter Selasky 585b00ab754SHans Petter Selasky done: 586b00ab754SHans Petter Selasky return (0); 587b00ab754SHans Petter Selasky } 588b00ab754SHans Petter Selasky 589b00ab754SHans Petter Selasky static int 590b00ab754SHans Petter Selasky add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf) 591b00ab754SHans Petter Selasky { 592b00ab754SHans Petter Selasky struct pcap_ng_sf *ps; 593*57e22627SCy Schubert uint64_t tsresol; 594b00ab754SHans Petter Selasky uint64_t tsoffset; 595b00ab754SHans Petter Selasky int is_binary; 596b00ab754SHans Petter Selasky 597b00ab754SHans Petter Selasky ps = p->priv; 598b00ab754SHans Petter Selasky 599b00ab754SHans Petter Selasky /* 600b00ab754SHans Petter Selasky * Count this interface. 601b00ab754SHans Petter Selasky */ 602b00ab754SHans Petter Selasky ps->ifcount++; 603b00ab754SHans Petter Selasky 604b00ab754SHans Petter Selasky /* 605b00ab754SHans Petter Selasky * Grow the array of per-interface information as necessary. 606b00ab754SHans Petter Selasky */ 607b00ab754SHans Petter Selasky if (ps->ifcount > ps->ifaces_size) { 608b00ab754SHans Petter Selasky /* 609b00ab754SHans Petter Selasky * We need to grow the array. 610b00ab754SHans Petter Selasky */ 611b00ab754SHans Petter Selasky bpf_u_int32 new_ifaces_size; 612b00ab754SHans Petter Selasky struct pcap_ng_if *new_ifaces; 613b00ab754SHans Petter Selasky 614b00ab754SHans Petter Selasky if (ps->ifaces_size == 0) { 615b00ab754SHans Petter Selasky /* 616b00ab754SHans Petter Selasky * It's currently empty. 617b00ab754SHans Petter Selasky * 618b00ab754SHans Petter Selasky * (The Clang static analyzer doesn't do enough, 619b00ab754SHans Petter Selasky * err, umm, dataflow *analysis* to realize that 620b00ab754SHans Petter Selasky * ps->ifaces_size == 0 if ps->ifaces == NULL, 621b00ab754SHans Petter Selasky * and so complains about a possible zero argument 622b00ab754SHans Petter Selasky * to realloc(), so we check for the former 623b00ab754SHans Petter Selasky * condition to shut it up. 624b00ab754SHans Petter Selasky * 625b00ab754SHans Petter Selasky * However, it doesn't complain that one of the 626b00ab754SHans Petter Selasky * multiplications below could overflow, which is 627b00ab754SHans Petter Selasky * a real, albeit extremely unlikely, problem (you'd 628b00ab754SHans Petter Selasky * need a pcapng file with tens of millions of 629b00ab754SHans Petter Selasky * interfaces).) 630b00ab754SHans Petter Selasky */ 631b00ab754SHans Petter Selasky new_ifaces_size = 1; 632b00ab754SHans Petter Selasky new_ifaces = malloc(sizeof (struct pcap_ng_if)); 633b00ab754SHans Petter Selasky } else { 634b00ab754SHans Petter Selasky /* 635b00ab754SHans Petter Selasky * It's not currently empty; double its size. 636b00ab754SHans Petter Selasky * (Perhaps overkill once we have a lot of interfaces.) 637b00ab754SHans Petter Selasky * 638b00ab754SHans Petter Selasky * Check for overflow if we double it. 639b00ab754SHans Petter Selasky */ 640b00ab754SHans Petter Selasky if (ps->ifaces_size * 2 < ps->ifaces_size) { 641b00ab754SHans Petter Selasky /* 642b00ab754SHans Petter Selasky * The maximum number of interfaces before 643b00ab754SHans Petter Selasky * ps->ifaces_size overflows is the largest 644b00ab754SHans Petter Selasky * possible 32-bit power of 2, as we do 645b00ab754SHans Petter Selasky * size doubling. 646b00ab754SHans Petter Selasky */ 647b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 648b00ab754SHans Petter Selasky "more than %u interfaces in the file", 649b00ab754SHans Petter Selasky 0x80000000U); 650b00ab754SHans Petter Selasky return (0); 651b00ab754SHans Petter Selasky } 652b00ab754SHans Petter Selasky 653b00ab754SHans Petter Selasky /* 654b00ab754SHans Petter Selasky * ps->ifaces_size * 2 doesn't overflow, so it's 655b00ab754SHans Petter Selasky * safe to multiply. 656b00ab754SHans Petter Selasky */ 657b00ab754SHans Petter Selasky new_ifaces_size = ps->ifaces_size * 2; 658b00ab754SHans Petter Selasky 659b00ab754SHans Petter Selasky /* 660b00ab754SHans Petter Selasky * Now make sure that's not so big that it overflows 661b00ab754SHans Petter Selasky * if we multiply by sizeof (struct pcap_ng_if). 662b00ab754SHans Petter Selasky * 663b00ab754SHans Petter Selasky * That can happen on 32-bit platforms, with a 32-bit 664b00ab754SHans Petter Selasky * size_t; it shouldn't happen on 64-bit platforms, 665b00ab754SHans Petter Selasky * with a 64-bit size_t, as new_ifaces_size is 666b00ab754SHans Petter Selasky * 32 bits. 667b00ab754SHans Petter Selasky */ 668b00ab754SHans Petter Selasky if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) { 669b00ab754SHans Petter Selasky /* 670b00ab754SHans Petter Selasky * As this fails only with 32-bit size_t, 671b00ab754SHans Petter Selasky * the multiplication was 32x32->32, and 672b00ab754SHans Petter Selasky * the largest 32-bit value that can safely 673b00ab754SHans Petter Selasky * be multiplied by sizeof (struct pcap_ng_if) 674b00ab754SHans Petter Selasky * without overflow is the largest 32-bit 675b00ab754SHans Petter Selasky * (unsigned) value divided by 676b00ab754SHans Petter Selasky * sizeof (struct pcap_ng_if). 677b00ab754SHans Petter Selasky */ 678b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 679b00ab754SHans Petter Selasky "more than %u interfaces in the file", 680b00ab754SHans Petter Selasky 0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if))); 681b00ab754SHans Petter Selasky return (0); 682b00ab754SHans Petter Selasky } 683b00ab754SHans Petter Selasky new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if)); 684b00ab754SHans Petter Selasky } 685b00ab754SHans Petter Selasky if (new_ifaces == NULL) { 686b00ab754SHans Petter Selasky /* 687b00ab754SHans Petter Selasky * We ran out of memory. 688b00ab754SHans Petter Selasky * Give up. 689b00ab754SHans Petter Selasky */ 690b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 691b00ab754SHans Petter Selasky "out of memory for per-interface information (%u interfaces)", 692b00ab754SHans Petter Selasky ps->ifcount); 693b00ab754SHans Petter Selasky return (0); 694b00ab754SHans Petter Selasky } 695b00ab754SHans Petter Selasky ps->ifaces_size = new_ifaces_size; 696b00ab754SHans Petter Selasky ps->ifaces = new_ifaces; 697b00ab754SHans Petter Selasky } 698b00ab754SHans Petter Selasky 699b00ab754SHans Petter Selasky /* 700b00ab754SHans Petter Selasky * Set the default time stamp resolution and offset. 701b00ab754SHans Petter Selasky */ 702b00ab754SHans Petter Selasky tsresol = 1000000; /* microsecond resolution */ 703b00ab754SHans Petter Selasky is_binary = 0; /* which is a power of 10 */ 704b00ab754SHans Petter Selasky tsoffset = 0; /* absolute timestamps */ 705b00ab754SHans Petter Selasky 706b00ab754SHans Petter Selasky /* 707b00ab754SHans Petter Selasky * Now look for various time stamp options, so we know 708b00ab754SHans Petter Selasky * how to interpret the time stamps for this interface. 709b00ab754SHans Petter Selasky */ 710b00ab754SHans Petter Selasky if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary, 711b00ab754SHans Petter Selasky errbuf) == -1) 712b00ab754SHans Petter Selasky return (0); 713b00ab754SHans Petter Selasky 714b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].tsresol = tsresol; 715b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset; 716b00ab754SHans Petter Selasky 717b00ab754SHans Petter Selasky /* 718b00ab754SHans Petter Selasky * Determine whether we're scaling up or down or not 719b00ab754SHans Petter Selasky * at all for this interface. 720b00ab754SHans Petter Selasky */ 721b00ab754SHans Petter Selasky if (tsresol == ps->user_tsresol) { 722b00ab754SHans Petter Selasky /* 723b00ab754SHans Petter Selasky * The resolution is the resolution the user wants, 724b00ab754SHans Petter Selasky * so we don't have to do scaling. 725b00ab754SHans Petter Selasky */ 726b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH; 727b00ab754SHans Petter Selasky } else if (tsresol > ps->user_tsresol) { 728b00ab754SHans Petter Selasky /* 729b00ab754SHans Petter Selasky * The resolution is greater than what the user wants, 730b00ab754SHans Petter Selasky * so we have to scale the timestamps down. 731b00ab754SHans Petter Selasky */ 732b00ab754SHans Petter Selasky if (is_binary) 733b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN; 734b00ab754SHans Petter Selasky else { 735b00ab754SHans Petter Selasky /* 736b00ab754SHans Petter Selasky * Calculate the scale factor. 737b00ab754SHans Petter Selasky */ 738b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol; 739b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC; 740b00ab754SHans Petter Selasky } 741b00ab754SHans Petter Selasky } else { 742b00ab754SHans Petter Selasky /* 743b00ab754SHans Petter Selasky * The resolution is less than what the user wants, 744b00ab754SHans Petter Selasky * so we have to scale the timestamps up. 745b00ab754SHans Petter Selasky */ 746b00ab754SHans Petter Selasky if (is_binary) 747b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN; 748b00ab754SHans Petter Selasky else { 749b00ab754SHans Petter Selasky /* 750b00ab754SHans Petter Selasky * Calculate the scale factor. 751b00ab754SHans Petter Selasky */ 752b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol; 753b00ab754SHans Petter Selasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC; 754b00ab754SHans Petter Selasky } 755b00ab754SHans Petter Selasky } 756b00ab754SHans Petter Selasky return (1); 757b00ab754SHans Petter Selasky } 758b00ab754SHans Petter Selasky 759b00ab754SHans Petter Selasky /* 760b00ab754SHans Petter Selasky * Check whether this is a pcapng savefile and, if it is, extract the 761b00ab754SHans Petter Selasky * relevant information from the header. 762b00ab754SHans Petter Selasky */ 763b00ab754SHans Petter Selasky pcap_t * 764*57e22627SCy Schubert pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision, 765*57e22627SCy Schubert char *errbuf, int *err) 766b00ab754SHans Petter Selasky { 767*57e22627SCy Schubert bpf_u_int32 magic_int; 768b00ab754SHans Petter Selasky size_t amt_read; 769b00ab754SHans Petter Selasky bpf_u_int32 total_length; 770b00ab754SHans Petter Selasky bpf_u_int32 byte_order_magic; 771b00ab754SHans Petter Selasky struct block_header *bhdrp; 772b00ab754SHans Petter Selasky struct section_header_block *shbp; 773b00ab754SHans Petter Selasky pcap_t *p; 774b00ab754SHans Petter Selasky int swapped = 0; 775b00ab754SHans Petter Selasky struct pcap_ng_sf *ps; 776b00ab754SHans Petter Selasky int status; 777b00ab754SHans Petter Selasky struct block_cursor cursor; 778b00ab754SHans Petter Selasky struct interface_description_block *idbp; 779b00ab754SHans Petter Selasky 780b00ab754SHans Petter Selasky /* 781b00ab754SHans Petter Selasky * Assume no read errors. 782b00ab754SHans Petter Selasky */ 783b00ab754SHans Petter Selasky *err = 0; 784b00ab754SHans Petter Selasky 785b00ab754SHans Petter Selasky /* 786b00ab754SHans Petter Selasky * Check whether the first 4 bytes of the file are the block 787b00ab754SHans Petter Selasky * type for a pcapng savefile. 788b00ab754SHans Petter Selasky */ 789*57e22627SCy Schubert memcpy(&magic_int, magic, sizeof(magic_int)); 790*57e22627SCy Schubert if (magic_int != BT_SHB) { 791b00ab754SHans Petter Selasky /* 792b00ab754SHans Petter Selasky * XXX - check whether this looks like what the block 793b00ab754SHans Petter Selasky * type would be after being munged by mapping between 794b00ab754SHans Petter Selasky * UN*X and DOS/Windows text file format and, if it 795b00ab754SHans Petter Selasky * does, look for the byte-order magic number in 796b00ab754SHans Petter Selasky * the appropriate place and, if we find it, report 797b00ab754SHans Petter Selasky * this as possibly being a pcapng file transferred 798b00ab754SHans Petter Selasky * between UN*X and Windows in text file format? 799b00ab754SHans Petter Selasky */ 800b00ab754SHans Petter Selasky return (NULL); /* nope */ 801b00ab754SHans Petter Selasky } 802b00ab754SHans Petter Selasky 803b00ab754SHans Petter Selasky /* 804b00ab754SHans Petter Selasky * OK, they are. However, that's just \n\r\r\n, so it could, 805b00ab754SHans Petter Selasky * conceivably, be an ordinary text file. 806b00ab754SHans Petter Selasky * 807b00ab754SHans Petter Selasky * It could not, however, conceivably be any other type of 808b00ab754SHans Petter Selasky * capture file, so we can read the rest of the putative 809b00ab754SHans Petter Selasky * Section Header Block; put the block type in the common 810b00ab754SHans Petter Selasky * header, read the rest of the common header and the 811b00ab754SHans Petter Selasky * fixed-length portion of the SHB, and look for the byte-order 812b00ab754SHans Petter Selasky * magic value. 813b00ab754SHans Petter Selasky */ 814b00ab754SHans Petter Selasky amt_read = fread(&total_length, 1, sizeof(total_length), fp); 815b00ab754SHans Petter Selasky if (amt_read < sizeof(total_length)) { 816b00ab754SHans Petter Selasky if (ferror(fp)) { 817b00ab754SHans Petter Selasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 818b00ab754SHans Petter Selasky errno, "error reading dump file"); 819b00ab754SHans Petter Selasky *err = 1; 820b00ab754SHans Petter Selasky return (NULL); /* fail */ 821b00ab754SHans Petter Selasky } 822b00ab754SHans Petter Selasky 823b00ab754SHans Petter Selasky /* 824b00ab754SHans Petter Selasky * Possibly a weird short text file, so just say 825b00ab754SHans Petter Selasky * "not pcapng". 826b00ab754SHans Petter Selasky */ 827b00ab754SHans Petter Selasky return (NULL); 828b00ab754SHans Petter Selasky } 829b00ab754SHans Petter Selasky amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp); 830b00ab754SHans Petter Selasky if (amt_read < sizeof(byte_order_magic)) { 831b00ab754SHans Petter Selasky if (ferror(fp)) { 832b00ab754SHans Petter Selasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 833b00ab754SHans Petter Selasky errno, "error reading dump file"); 834b00ab754SHans Petter Selasky *err = 1; 835b00ab754SHans Petter Selasky return (NULL); /* fail */ 836b00ab754SHans Petter Selasky } 837b00ab754SHans Petter Selasky 838b00ab754SHans Petter Selasky /* 839b00ab754SHans Petter Selasky * Possibly a weird short text file, so just say 840b00ab754SHans Petter Selasky * "not pcapng". 841b00ab754SHans Petter Selasky */ 842b00ab754SHans Petter Selasky return (NULL); 843b00ab754SHans Petter Selasky } 844b00ab754SHans Petter Selasky if (byte_order_magic != BYTE_ORDER_MAGIC) { 845b00ab754SHans Petter Selasky byte_order_magic = SWAPLONG(byte_order_magic); 846b00ab754SHans Petter Selasky if (byte_order_magic != BYTE_ORDER_MAGIC) { 847b00ab754SHans Petter Selasky /* 848b00ab754SHans Petter Selasky * Not a pcapng file. 849b00ab754SHans Petter Selasky */ 850b00ab754SHans Petter Selasky return (NULL); 851b00ab754SHans Petter Selasky } 852b00ab754SHans Petter Selasky swapped = 1; 853b00ab754SHans Petter Selasky total_length = SWAPLONG(total_length); 854b00ab754SHans Petter Selasky } 855b00ab754SHans Petter Selasky 856b00ab754SHans Petter Selasky /* 857b00ab754SHans Petter Selasky * Check the sanity of the total length. 858b00ab754SHans Petter Selasky */ 859*57e22627SCy Schubert if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) || 860*57e22627SCy Schubert (total_length > BT_SHB_INSANE_MAX)) { 861b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 862*57e22627SCy Schubert "Section Header Block in pcapng dump file has invalid length %" PRIsize " < _%u_ < %u (BT_SHB_INSANE_MAX)", 863*57e22627SCy Schubert sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer), 864b00ab754SHans Petter Selasky total_length, 865*57e22627SCy Schubert BT_SHB_INSANE_MAX); 866*57e22627SCy Schubert 867b00ab754SHans Petter Selasky *err = 1; 868b00ab754SHans Petter Selasky return (NULL); 869b00ab754SHans Petter Selasky } 870b00ab754SHans Petter Selasky 871b00ab754SHans Petter Selasky /* 872b00ab754SHans Petter Selasky * OK, this is a good pcapng file. 873b00ab754SHans Petter Selasky * Allocate a pcap_t for it. 874b00ab754SHans Petter Selasky */ 875b00ab754SHans Petter Selasky p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf)); 876b00ab754SHans Petter Selasky if (p == NULL) { 877b00ab754SHans Petter Selasky /* Allocation failed. */ 878b00ab754SHans Petter Selasky *err = 1; 879b00ab754SHans Petter Selasky return (NULL); 880b00ab754SHans Petter Selasky } 881b00ab754SHans Petter Selasky p->swapped = swapped; 882b00ab754SHans Petter Selasky ps = p->priv; 883b00ab754SHans Petter Selasky 884b00ab754SHans Petter Selasky /* 885b00ab754SHans Petter Selasky * What precision does the user want? 886b00ab754SHans Petter Selasky */ 887b00ab754SHans Petter Selasky switch (precision) { 888b00ab754SHans Petter Selasky 889b00ab754SHans Petter Selasky case PCAP_TSTAMP_PRECISION_MICRO: 890b00ab754SHans Petter Selasky ps->user_tsresol = 1000000; 891b00ab754SHans Petter Selasky break; 892b00ab754SHans Petter Selasky 893b00ab754SHans Petter Selasky case PCAP_TSTAMP_PRECISION_NANO: 894b00ab754SHans Petter Selasky ps->user_tsresol = 1000000000; 895b00ab754SHans Petter Selasky break; 896b00ab754SHans Petter Selasky 897b00ab754SHans Petter Selasky default: 898b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 899b00ab754SHans Petter Selasky "unknown time stamp resolution %u", precision); 900b00ab754SHans Petter Selasky free(p); 901b00ab754SHans Petter Selasky *err = 1; 902b00ab754SHans Petter Selasky return (NULL); 903b00ab754SHans Petter Selasky } 904b00ab754SHans Petter Selasky 905b00ab754SHans Petter Selasky p->opt.tstamp_precision = precision; 906b00ab754SHans Petter Selasky 907b00ab754SHans Petter Selasky /* 908b00ab754SHans Petter Selasky * Allocate a buffer into which to read blocks. We default to 909b00ab754SHans Petter Selasky * the maximum of: 910b00ab754SHans Petter Selasky * 911b00ab754SHans Petter Selasky * the total length of the SHB for which we read the header; 912b00ab754SHans Petter Selasky * 913b00ab754SHans Petter Selasky * 2K, which should be more than large enough for an Enhanced 914b00ab754SHans Petter Selasky * Packet Block containing a full-size Ethernet frame, and 915b00ab754SHans Petter Selasky * leaving room for some options. 916b00ab754SHans Petter Selasky * 917b00ab754SHans Petter Selasky * If we find a bigger block, we reallocate the buffer, up to 918*57e22627SCy Schubert * the maximum size. We start out with a maximum size of 919*57e22627SCy Schubert * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types 920*57e22627SCy Schubert * with a maximum snapshot that results in a larger maximum 921*57e22627SCy Schubert * block length, we boost the maximum. 922b00ab754SHans Petter Selasky */ 923b00ab754SHans Petter Selasky p->bufsize = 2048; 924b00ab754SHans Petter Selasky if (p->bufsize < total_length) 925b00ab754SHans Petter Selasky p->bufsize = total_length; 926b00ab754SHans Petter Selasky p->buffer = malloc(p->bufsize); 927b00ab754SHans Petter Selasky if (p->buffer == NULL) { 928b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 929b00ab754SHans Petter Selasky free(p); 930b00ab754SHans Petter Selasky *err = 1; 931b00ab754SHans Petter Selasky return (NULL); 932b00ab754SHans Petter Selasky } 933*57e22627SCy Schubert ps->max_blocksize = INITIAL_MAX_BLOCKSIZE; 934b00ab754SHans Petter Selasky 935b00ab754SHans Petter Selasky /* 936b00ab754SHans Petter Selasky * Copy the stuff we've read to the buffer, and read the rest 937b00ab754SHans Petter Selasky * of the SHB. 938b00ab754SHans Petter Selasky */ 939b00ab754SHans Petter Selasky bhdrp = (struct block_header *)p->buffer; 940b00ab754SHans Petter Selasky shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header)); 941*57e22627SCy Schubert bhdrp->block_type = magic_int; 942b00ab754SHans Petter Selasky bhdrp->total_length = total_length; 943b00ab754SHans Petter Selasky shbp->byte_order_magic = byte_order_magic; 944b00ab754SHans Petter Selasky if (read_bytes(fp, 945*57e22627SCy Schubert (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)), 946*57e22627SCy Schubert total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)), 947b00ab754SHans Petter Selasky 1, errbuf) == -1) 948b00ab754SHans Petter Selasky goto fail; 949b00ab754SHans Petter Selasky 950b00ab754SHans Petter Selasky if (p->swapped) { 951b00ab754SHans Petter Selasky /* 952b00ab754SHans Petter Selasky * Byte-swap the fields we've read. 953b00ab754SHans Petter Selasky */ 954b00ab754SHans Petter Selasky shbp->major_version = SWAPSHORT(shbp->major_version); 955b00ab754SHans Petter Selasky shbp->minor_version = SWAPSHORT(shbp->minor_version); 956b00ab754SHans Petter Selasky 957b00ab754SHans Petter Selasky /* 958b00ab754SHans Petter Selasky * XXX - we don't care about the section length. 959b00ab754SHans Petter Selasky */ 960b00ab754SHans Petter Selasky } 961b00ab754SHans Petter Selasky /* currently only SHB version 1.0 is supported */ 962b00ab754SHans Petter Selasky if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR && 963b00ab754SHans Petter Selasky shbp->minor_version == PCAP_NG_VERSION_MINOR)) { 964b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 965b00ab754SHans Petter Selasky "unsupported pcapng savefile version %u.%u", 966b00ab754SHans Petter Selasky shbp->major_version, shbp->minor_version); 967b00ab754SHans Petter Selasky goto fail; 968b00ab754SHans Petter Selasky } 969b00ab754SHans Petter Selasky p->version_major = shbp->major_version; 970b00ab754SHans Petter Selasky p->version_minor = shbp->minor_version; 971b00ab754SHans Petter Selasky 972b00ab754SHans Petter Selasky /* 973b00ab754SHans Petter Selasky * Save the time stamp resolution the user requested. 974b00ab754SHans Petter Selasky */ 975b00ab754SHans Petter Selasky p->opt.tstamp_precision = precision; 976b00ab754SHans Petter Selasky 977b00ab754SHans Petter Selasky /* 978b00ab754SHans Petter Selasky * Now start looking for an Interface Description Block. 979b00ab754SHans Petter Selasky */ 980b00ab754SHans Petter Selasky for (;;) { 981b00ab754SHans Petter Selasky /* 982b00ab754SHans Petter Selasky * Read the next block. 983b00ab754SHans Petter Selasky */ 984b00ab754SHans Petter Selasky status = read_block(fp, p, &cursor, errbuf); 985b00ab754SHans Petter Selasky if (status == 0) { 986b00ab754SHans Petter Selasky /* EOF - no IDB in this file */ 987b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 988b00ab754SHans Petter Selasky "the capture file has no Interface Description Blocks"); 989b00ab754SHans Petter Selasky goto fail; 990b00ab754SHans Petter Selasky } 991b00ab754SHans Petter Selasky if (status == -1) 992b00ab754SHans Petter Selasky goto fail; /* error */ 993b00ab754SHans Petter Selasky switch (cursor.block_type) { 994b00ab754SHans Petter Selasky 995b00ab754SHans Petter Selasky case BT_IDB: 996b00ab754SHans Petter Selasky /* 997b00ab754SHans Petter Selasky * Get a pointer to the fixed-length portion of the 998b00ab754SHans Petter Selasky * IDB. 999b00ab754SHans Petter Selasky */ 1000b00ab754SHans Petter Selasky idbp = get_from_block_data(&cursor, sizeof(*idbp), 1001b00ab754SHans Petter Selasky errbuf); 1002b00ab754SHans Petter Selasky if (idbp == NULL) 1003b00ab754SHans Petter Selasky goto fail; /* error */ 1004b00ab754SHans Petter Selasky 1005b00ab754SHans Petter Selasky /* 1006b00ab754SHans Petter Selasky * Byte-swap it if necessary. 1007b00ab754SHans Petter Selasky */ 1008b00ab754SHans Petter Selasky if (p->swapped) { 1009b00ab754SHans Petter Selasky idbp->linktype = SWAPSHORT(idbp->linktype); 1010b00ab754SHans Petter Selasky idbp->snaplen = SWAPLONG(idbp->snaplen); 1011b00ab754SHans Petter Selasky } 1012b00ab754SHans Petter Selasky 1013b00ab754SHans Petter Selasky /* 1014b00ab754SHans Petter Selasky * Try to add this interface. 1015b00ab754SHans Petter Selasky */ 1016b00ab754SHans Petter Selasky if (!add_interface(p, &cursor, errbuf)) 1017b00ab754SHans Petter Selasky goto fail; 1018b00ab754SHans Petter Selasky 1019b00ab754SHans Petter Selasky goto done; 1020b00ab754SHans Petter Selasky 1021b00ab754SHans Petter Selasky case BT_EPB: 1022b00ab754SHans Petter Selasky case BT_SPB: 1023b00ab754SHans Petter Selasky case BT_PB: 1024b00ab754SHans Petter Selasky /* 1025b00ab754SHans Petter Selasky * Saw a packet before we saw any IDBs. That's 1026b00ab754SHans Petter Selasky * not valid, as we don't know what link-layer 1027b00ab754SHans Petter Selasky * encapsulation the packet has. 1028b00ab754SHans Petter Selasky */ 1029b00ab754SHans Petter Selasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 1030b00ab754SHans Petter Selasky "the capture file has a packet block before any Interface Description Blocks"); 1031b00ab754SHans Petter Selasky goto fail; 1032b00ab754SHans Petter Selasky 1033b00ab754SHans Petter Selasky default: 1034b00ab754SHans Petter Selasky /* 1035b00ab754SHans Petter Selasky * Just ignore it. 1036b00ab754SHans Petter Selasky */ 1037b00ab754SHans Petter Selasky break; 1038b00ab754SHans Petter Selasky } 1039b00ab754SHans Petter Selasky } 1040b00ab754SHans Petter Selasky 1041b00ab754SHans Petter Selasky done: 1042b00ab754SHans Petter Selasky p->tzoff = 0; /* XXX - not used in pcap */ 1043b00ab754SHans Petter Selasky p->linktype = linktype_to_dlt(idbp->linktype); 1044*57e22627SCy Schubert p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen); 1045b00ab754SHans Petter Selasky p->linktype_ext = 0; 1046b00ab754SHans Petter Selasky 1047b00ab754SHans Petter Selasky /* 1048b00ab754SHans Petter Selasky * If the maximum block size for a packet with the maximum 1049b00ab754SHans Petter Selasky * snapshot length for this DLT_ is bigger than the current 1050b00ab754SHans Petter Selasky * maximum block size, increase the maximum. 1051b00ab754SHans Petter Selasky */ 1052*57e22627SCy Schubert if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize) 1053*57e22627SCy Schubert ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)); 1054b00ab754SHans Petter Selasky 1055b00ab754SHans Petter Selasky p->next_packet_op = pcap_ng_next_packet; 1056b00ab754SHans Petter Selasky p->cleanup_op = pcap_ng_cleanup; 1057b00ab754SHans Petter Selasky 1058b00ab754SHans Petter Selasky return (p); 1059b00ab754SHans Petter Selasky 1060b00ab754SHans Petter Selasky fail: 1061b00ab754SHans Petter Selasky free(ps->ifaces); 1062b00ab754SHans Petter Selasky free(p->buffer); 1063b00ab754SHans Petter Selasky free(p); 1064b00ab754SHans Petter Selasky *err = 1; 1065b00ab754SHans Petter Selasky return (NULL); 1066b00ab754SHans Petter Selasky } 1067b00ab754SHans Petter Selasky 1068b00ab754SHans Petter Selasky static void 1069b00ab754SHans Petter Selasky pcap_ng_cleanup(pcap_t *p) 1070b00ab754SHans Petter Selasky { 1071b00ab754SHans Petter Selasky struct pcap_ng_sf *ps = p->priv; 1072b00ab754SHans Petter Selasky 1073b00ab754SHans Petter Selasky free(ps->ifaces); 1074b00ab754SHans Petter Selasky sf_cleanup(p); 1075b00ab754SHans Petter Selasky } 1076b00ab754SHans Petter Selasky 1077b00ab754SHans Petter Selasky /* 1078b00ab754SHans Petter Selasky * Read and return the next packet from the savefile. Return the header 1079b00ab754SHans Petter Selasky * in hdr and a pointer to the contents in data. Return 0 on success, 1 1080b00ab754SHans Petter Selasky * if there were no more packets, and -1 on an error. 1081b00ab754SHans Petter Selasky */ 1082b00ab754SHans Petter Selasky static int 1083b00ab754SHans Petter Selasky pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) 1084b00ab754SHans Petter Selasky { 1085b00ab754SHans Petter Selasky struct pcap_ng_sf *ps = p->priv; 1086b00ab754SHans Petter Selasky struct block_cursor cursor; 1087b00ab754SHans Petter Selasky int status; 1088b00ab754SHans Petter Selasky struct enhanced_packet_block *epbp; 1089b00ab754SHans Petter Selasky struct simple_packet_block *spbp; 1090b00ab754SHans Petter Selasky struct packet_block *pbp; 1091b00ab754SHans Petter Selasky bpf_u_int32 interface_id = 0xFFFFFFFF; 1092b00ab754SHans Petter Selasky struct interface_description_block *idbp; 1093b00ab754SHans Petter Selasky struct section_header_block *shbp; 1094b00ab754SHans Petter Selasky FILE *fp = p->rfile; 1095b00ab754SHans Petter Selasky uint64_t t, sec, frac; 1096b00ab754SHans Petter Selasky 1097b00ab754SHans Petter Selasky /* 1098b00ab754SHans Petter Selasky * Look for an Enhanced Packet Block, a Simple Packet Block, 1099b00ab754SHans Petter Selasky * or a Packet Block. 1100b00ab754SHans Petter Selasky */ 1101b00ab754SHans Petter Selasky for (;;) { 1102b00ab754SHans Petter Selasky /* 1103b00ab754SHans Petter Selasky * Read the block type and length; those are common 1104b00ab754SHans Petter Selasky * to all blocks. 1105b00ab754SHans Petter Selasky */ 1106b00ab754SHans Petter Selasky status = read_block(fp, p, &cursor, p->errbuf); 1107b00ab754SHans Petter Selasky if (status == 0) 1108b00ab754SHans Petter Selasky return (1); /* EOF */ 1109b00ab754SHans Petter Selasky if (status == -1) 1110b00ab754SHans Petter Selasky return (-1); /* error */ 1111b00ab754SHans Petter Selasky switch (cursor.block_type) { 1112b00ab754SHans Petter Selasky 1113b00ab754SHans Petter Selasky case BT_EPB: 1114b00ab754SHans Petter Selasky /* 1115b00ab754SHans Petter Selasky * Get a pointer to the fixed-length portion of the 1116b00ab754SHans Petter Selasky * EPB. 1117b00ab754SHans Petter Selasky */ 1118b00ab754SHans Petter Selasky epbp = get_from_block_data(&cursor, sizeof(*epbp), 1119b00ab754SHans Petter Selasky p->errbuf); 1120b00ab754SHans Petter Selasky if (epbp == NULL) 1121b00ab754SHans Petter Selasky return (-1); /* error */ 1122b00ab754SHans Petter Selasky 1123b00ab754SHans Petter Selasky /* 1124b00ab754SHans Petter Selasky * Byte-swap it if necessary. 1125b00ab754SHans Petter Selasky */ 1126b00ab754SHans Petter Selasky if (p->swapped) { 1127b00ab754SHans Petter Selasky /* these were written in opposite byte order */ 1128b00ab754SHans Petter Selasky interface_id = SWAPLONG(epbp->interface_id); 1129b00ab754SHans Petter Selasky hdr->caplen = SWAPLONG(epbp->caplen); 1130b00ab754SHans Petter Selasky hdr->len = SWAPLONG(epbp->len); 1131b00ab754SHans Petter Selasky t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 | 1132b00ab754SHans Petter Selasky SWAPLONG(epbp->timestamp_low); 1133b00ab754SHans Petter Selasky } else { 1134b00ab754SHans Petter Selasky interface_id = epbp->interface_id; 1135b00ab754SHans Petter Selasky hdr->caplen = epbp->caplen; 1136b00ab754SHans Petter Selasky hdr->len = epbp->len; 1137b00ab754SHans Petter Selasky t = ((uint64_t)epbp->timestamp_high) << 32 | 1138b00ab754SHans Petter Selasky epbp->timestamp_low; 1139b00ab754SHans Petter Selasky } 1140b00ab754SHans Petter Selasky goto found; 1141b00ab754SHans Petter Selasky 1142b00ab754SHans Petter Selasky case BT_SPB: 1143b00ab754SHans Petter Selasky /* 1144b00ab754SHans Petter Selasky * Get a pointer to the fixed-length portion of the 1145b00ab754SHans Petter Selasky * SPB. 1146b00ab754SHans Petter Selasky */ 1147b00ab754SHans Petter Selasky spbp = get_from_block_data(&cursor, sizeof(*spbp), 1148b00ab754SHans Petter Selasky p->errbuf); 1149b00ab754SHans Petter Selasky if (spbp == NULL) 1150b00ab754SHans Petter Selasky return (-1); /* error */ 1151b00ab754SHans Petter Selasky 1152b00ab754SHans Petter Selasky /* 1153b00ab754SHans Petter Selasky * SPB packets are assumed to have arrived on 1154b00ab754SHans Petter Selasky * the first interface. 1155b00ab754SHans Petter Selasky */ 1156b00ab754SHans Petter Selasky interface_id = 0; 1157b00ab754SHans Petter Selasky 1158b00ab754SHans Petter Selasky /* 1159b00ab754SHans Petter Selasky * Byte-swap it if necessary. 1160b00ab754SHans Petter Selasky */ 1161b00ab754SHans Petter Selasky if (p->swapped) { 1162b00ab754SHans Petter Selasky /* these were written in opposite byte order */ 1163b00ab754SHans Petter Selasky hdr->len = SWAPLONG(spbp->len); 1164b00ab754SHans Petter Selasky } else 1165b00ab754SHans Petter Selasky hdr->len = spbp->len; 1166b00ab754SHans Petter Selasky 1167b00ab754SHans Petter Selasky /* 1168b00ab754SHans Petter Selasky * The SPB doesn't give the captured length; 1169b00ab754SHans Petter Selasky * it's the minimum of the snapshot length 1170b00ab754SHans Petter Selasky * and the packet length. 1171b00ab754SHans Petter Selasky */ 1172b00ab754SHans Petter Selasky hdr->caplen = hdr->len; 1173b00ab754SHans Petter Selasky if (hdr->caplen > (bpf_u_int32)p->snapshot) 1174b00ab754SHans Petter Selasky hdr->caplen = p->snapshot; 1175b00ab754SHans Petter Selasky t = 0; /* no time stamps */ 1176b00ab754SHans Petter Selasky goto found; 1177b00ab754SHans Petter Selasky 1178b00ab754SHans Petter Selasky case BT_PB: 1179b00ab754SHans Petter Selasky /* 1180b00ab754SHans Petter Selasky * Get a pointer to the fixed-length portion of the 1181b00ab754SHans Petter Selasky * PB. 1182b00ab754SHans Petter Selasky */ 1183b00ab754SHans Petter Selasky pbp = get_from_block_data(&cursor, sizeof(*pbp), 1184b00ab754SHans Petter Selasky p->errbuf); 1185b00ab754SHans Petter Selasky if (pbp == NULL) 1186b00ab754SHans Petter Selasky return (-1); /* error */ 1187b00ab754SHans Petter Selasky 1188b00ab754SHans Petter Selasky /* 1189b00ab754SHans Petter Selasky * Byte-swap it if necessary. 1190b00ab754SHans Petter Selasky */ 1191b00ab754SHans Petter Selasky if (p->swapped) { 1192b00ab754SHans Petter Selasky /* these were written in opposite byte order */ 1193b00ab754SHans Petter Selasky interface_id = SWAPSHORT(pbp->interface_id); 1194b00ab754SHans Petter Selasky hdr->caplen = SWAPLONG(pbp->caplen); 1195b00ab754SHans Petter Selasky hdr->len = SWAPLONG(pbp->len); 1196b00ab754SHans Petter Selasky t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 | 1197b00ab754SHans Petter Selasky SWAPLONG(pbp->timestamp_low); 1198b00ab754SHans Petter Selasky } else { 1199b00ab754SHans Petter Selasky interface_id = pbp->interface_id; 1200b00ab754SHans Petter Selasky hdr->caplen = pbp->caplen; 1201b00ab754SHans Petter Selasky hdr->len = pbp->len; 1202b00ab754SHans Petter Selasky t = ((uint64_t)pbp->timestamp_high) << 32 | 1203b00ab754SHans Petter Selasky pbp->timestamp_low; 1204b00ab754SHans Petter Selasky } 1205b00ab754SHans Petter Selasky goto found; 1206b00ab754SHans Petter Selasky 1207b00ab754SHans Petter Selasky case BT_IDB: 1208b00ab754SHans Petter Selasky /* 1209b00ab754SHans Petter Selasky * Interface Description Block. Get a pointer 1210b00ab754SHans Petter Selasky * to its fixed-length portion. 1211b00ab754SHans Petter Selasky */ 1212b00ab754SHans Petter Selasky idbp = get_from_block_data(&cursor, sizeof(*idbp), 1213b00ab754SHans Petter Selasky p->errbuf); 1214b00ab754SHans Petter Selasky if (idbp == NULL) 1215b00ab754SHans Petter Selasky return (-1); /* error */ 1216b00ab754SHans Petter Selasky 1217b00ab754SHans Petter Selasky /* 1218b00ab754SHans Petter Selasky * Byte-swap it if necessary. 1219b00ab754SHans Petter Selasky */ 1220b00ab754SHans Petter Selasky if (p->swapped) { 1221b00ab754SHans Petter Selasky idbp->linktype = SWAPSHORT(idbp->linktype); 1222b00ab754SHans Petter Selasky idbp->snaplen = SWAPLONG(idbp->snaplen); 1223b00ab754SHans Petter Selasky } 1224b00ab754SHans Petter Selasky 1225b00ab754SHans Petter Selasky /* 1226b00ab754SHans Petter Selasky * If the link-layer type or snapshot length 1227b00ab754SHans Petter Selasky * differ from the ones for the first IDB we 1228b00ab754SHans Petter Selasky * saw, quit. 1229b00ab754SHans Petter Selasky * 1230b00ab754SHans Petter Selasky * XXX - just discard packets from those 1231b00ab754SHans Petter Selasky * interfaces? 1232b00ab754SHans Petter Selasky */ 1233b00ab754SHans Petter Selasky if (p->linktype != idbp->linktype) { 1234b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1235b00ab754SHans Petter Selasky "an interface has a type %u different from the type of the first interface", 1236b00ab754SHans Petter Selasky idbp->linktype); 1237b00ab754SHans Petter Selasky return (-1); 1238b00ab754SHans Petter Selasky } 1239*57e22627SCy Schubert 1240*57e22627SCy Schubert /* 1241*57e22627SCy Schubert * Check against the *adjusted* value of this IDB's 1242*57e22627SCy Schubert * snapshot length. 1243*57e22627SCy Schubert */ 1244*57e22627SCy Schubert if ((bpf_u_int32)p->snapshot != 1245*57e22627SCy Schubert pcap_adjust_snapshot(p->linktype, idbp->snaplen)) { 1246b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1247b00ab754SHans Petter Selasky "an interface has a snapshot length %u different from the type of the first interface", 1248b00ab754SHans Petter Selasky idbp->snaplen); 1249b00ab754SHans Petter Selasky return (-1); 1250b00ab754SHans Petter Selasky } 1251b00ab754SHans Petter Selasky 1252b00ab754SHans Petter Selasky /* 1253b00ab754SHans Petter Selasky * Try to add this interface. 1254b00ab754SHans Petter Selasky */ 1255b00ab754SHans Petter Selasky if (!add_interface(p, &cursor, p->errbuf)) 1256b00ab754SHans Petter Selasky return (-1); 1257b00ab754SHans Petter Selasky break; 1258b00ab754SHans Petter Selasky 1259b00ab754SHans Petter Selasky case BT_SHB: 1260b00ab754SHans Petter Selasky /* 1261b00ab754SHans Petter Selasky * Section Header Block. Get a pointer 1262b00ab754SHans Petter Selasky * to its fixed-length portion. 1263b00ab754SHans Petter Selasky */ 1264b00ab754SHans Petter Selasky shbp = get_from_block_data(&cursor, sizeof(*shbp), 1265b00ab754SHans Petter Selasky p->errbuf); 1266b00ab754SHans Petter Selasky if (shbp == NULL) 1267b00ab754SHans Petter Selasky return (-1); /* error */ 1268b00ab754SHans Petter Selasky 1269b00ab754SHans Petter Selasky /* 1270b00ab754SHans Petter Selasky * Assume the byte order of this section is 1271b00ab754SHans Petter Selasky * the same as that of the previous section. 1272b00ab754SHans Petter Selasky * We'll check for that later. 1273b00ab754SHans Petter Selasky */ 1274b00ab754SHans Petter Selasky if (p->swapped) { 1275b00ab754SHans Petter Selasky shbp->byte_order_magic = 1276b00ab754SHans Petter Selasky SWAPLONG(shbp->byte_order_magic); 1277b00ab754SHans Petter Selasky shbp->major_version = 1278b00ab754SHans Petter Selasky SWAPSHORT(shbp->major_version); 1279b00ab754SHans Petter Selasky } 1280b00ab754SHans Petter Selasky 1281b00ab754SHans Petter Selasky /* 1282b00ab754SHans Petter Selasky * Make sure the byte order doesn't change; 1283b00ab754SHans Petter Selasky * pcap_is_swapped() shouldn't change its 1284b00ab754SHans Petter Selasky * return value in the middle of reading a capture. 1285b00ab754SHans Petter Selasky */ 1286b00ab754SHans Petter Selasky switch (shbp->byte_order_magic) { 1287b00ab754SHans Petter Selasky 1288b00ab754SHans Petter Selasky case BYTE_ORDER_MAGIC: 1289b00ab754SHans Petter Selasky /* 1290b00ab754SHans Petter Selasky * OK. 1291b00ab754SHans Petter Selasky */ 1292b00ab754SHans Petter Selasky break; 1293b00ab754SHans Petter Selasky 1294b00ab754SHans Petter Selasky case SWAPLONG(BYTE_ORDER_MAGIC): 1295b00ab754SHans Petter Selasky /* 1296b00ab754SHans Petter Selasky * Byte order changes. 1297b00ab754SHans Petter Selasky */ 1298b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1299b00ab754SHans Petter Selasky "the file has sections with different byte orders"); 1300b00ab754SHans Petter Selasky return (-1); 1301b00ab754SHans Petter Selasky 1302b00ab754SHans Petter Selasky default: 1303b00ab754SHans Petter Selasky /* 1304b00ab754SHans Petter Selasky * Not a valid SHB. 1305b00ab754SHans Petter Selasky */ 1306b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1307b00ab754SHans Petter Selasky "the file has a section with a bad byte order magic field"); 1308b00ab754SHans Petter Selasky return (-1); 1309b00ab754SHans Petter Selasky } 1310b00ab754SHans Petter Selasky 1311b00ab754SHans Petter Selasky /* 1312b00ab754SHans Petter Selasky * Make sure the major version is the version 1313b00ab754SHans Petter Selasky * we handle. 1314b00ab754SHans Petter Selasky */ 1315b00ab754SHans Petter Selasky if (shbp->major_version != PCAP_NG_VERSION_MAJOR) { 1316b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1317b00ab754SHans Petter Selasky "unknown pcapng savefile major version number %u", 1318b00ab754SHans Petter Selasky shbp->major_version); 1319b00ab754SHans Petter Selasky return (-1); 1320b00ab754SHans Petter Selasky } 1321b00ab754SHans Petter Selasky 1322b00ab754SHans Petter Selasky /* 1323b00ab754SHans Petter Selasky * Reset the interface count; this section should 1324b00ab754SHans Petter Selasky * have its own set of IDBs. If any of them 1325b00ab754SHans Petter Selasky * don't have the same interface type, snapshot 1326b00ab754SHans Petter Selasky * length, or resolution as the first interface 1327b00ab754SHans Petter Selasky * we saw, we'll fail. (And if we don't see 1328b00ab754SHans Petter Selasky * any IDBs, we'll fail when we see a packet 1329b00ab754SHans Petter Selasky * block.) 1330b00ab754SHans Petter Selasky */ 1331b00ab754SHans Petter Selasky ps->ifcount = 0; 1332b00ab754SHans Petter Selasky break; 1333b00ab754SHans Petter Selasky 1334b00ab754SHans Petter Selasky default: 1335b00ab754SHans Petter Selasky /* 1336b00ab754SHans Petter Selasky * Not a packet block, IDB, or SHB; ignore it. 1337b00ab754SHans Petter Selasky */ 1338b00ab754SHans Petter Selasky break; 1339b00ab754SHans Petter Selasky } 1340b00ab754SHans Petter Selasky } 1341b00ab754SHans Petter Selasky 1342b00ab754SHans Petter Selasky found: 1343b00ab754SHans Petter Selasky /* 1344b00ab754SHans Petter Selasky * Is the interface ID an interface we know? 1345b00ab754SHans Petter Selasky */ 1346b00ab754SHans Petter Selasky if (interface_id >= ps->ifcount) { 1347b00ab754SHans Petter Selasky /* 1348b00ab754SHans Petter Selasky * Yes. Fail. 1349b00ab754SHans Petter Selasky */ 1350b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1351b00ab754SHans Petter Selasky "a packet arrived on interface %u, but there's no Interface Description Block for that interface", 1352b00ab754SHans Petter Selasky interface_id); 1353b00ab754SHans Petter Selasky return (-1); 1354b00ab754SHans Petter Selasky } 1355b00ab754SHans Petter Selasky 1356b00ab754SHans Petter Selasky if (hdr->caplen > (bpf_u_int32)p->snapshot) { 1357b00ab754SHans Petter Selasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1358b00ab754SHans Petter Selasky "invalid packet capture length %u, bigger than " 1359b00ab754SHans Petter Selasky "snaplen of %d", hdr->caplen, p->snapshot); 1360b00ab754SHans Petter Selasky return (-1); 1361b00ab754SHans Petter Selasky } 1362b00ab754SHans Petter Selasky 1363b00ab754SHans Petter Selasky /* 1364b00ab754SHans Petter Selasky * Convert the time stamp to seconds and fractions of a second, 1365b00ab754SHans Petter Selasky * with the fractions being in units of the file-supplied resolution. 1366b00ab754SHans Petter Selasky */ 1367b00ab754SHans Petter Selasky sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset; 1368b00ab754SHans Petter Selasky frac = t % ps->ifaces[interface_id].tsresol; 1369b00ab754SHans Petter Selasky 1370b00ab754SHans Petter Selasky /* 1371b00ab754SHans Petter Selasky * Convert the fractions from units of the file-supplied resolution 1372b00ab754SHans Petter Selasky * to units of the user-requested resolution. 1373b00ab754SHans Petter Selasky */ 1374b00ab754SHans Petter Selasky switch (ps->ifaces[interface_id].scale_type) { 1375b00ab754SHans Petter Selasky 1376b00ab754SHans Petter Selasky case PASS_THROUGH: 1377b00ab754SHans Petter Selasky /* 1378b00ab754SHans Petter Selasky * The interface resolution is what the user wants, 1379b00ab754SHans Petter Selasky * so we're done. 1380b00ab754SHans Petter Selasky */ 1381b00ab754SHans Petter Selasky break; 1382b00ab754SHans Petter Selasky 1383b00ab754SHans Petter Selasky case SCALE_UP_DEC: 1384b00ab754SHans Petter Selasky /* 1385b00ab754SHans Petter Selasky * The interface resolution is less than what the user 1386b00ab754SHans Petter Selasky * wants; scale the fractional part up to the units of 1387b00ab754SHans Petter Selasky * the resolution the user requested by multiplying by 1388b00ab754SHans Petter Selasky * the quotient of the user-requested resolution and the 1389b00ab754SHans Petter Selasky * file-supplied resolution. 1390b00ab754SHans Petter Selasky * 1391b00ab754SHans Petter Selasky * Those resolutions are both powers of 10, and the user- 1392b00ab754SHans Petter Selasky * requested resolution is greater than the file-supplied 1393b00ab754SHans Petter Selasky * resolution, so the quotient in question is an integer. 1394b00ab754SHans Petter Selasky * We've calculated that quotient already, so we just 1395b00ab754SHans Petter Selasky * multiply by it. 1396b00ab754SHans Petter Selasky */ 1397b00ab754SHans Petter Selasky frac *= ps->ifaces[interface_id].scale_factor; 1398b00ab754SHans Petter Selasky break; 1399b00ab754SHans Petter Selasky 1400b00ab754SHans Petter Selasky case SCALE_UP_BIN: 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 * The file-supplied resolution is a power of 2, so the 1409b00ab754SHans Petter Selasky * quotient is not an integer, so, in order to do this 1410b00ab754SHans Petter Selasky * entirely with integer arithmetic, we multiply by the 1411b00ab754SHans Petter Selasky * user-requested resolution and divide by the file- 1412b00ab754SHans Petter Selasky * supplied resolution. 1413b00ab754SHans Petter Selasky * 1414b00ab754SHans Petter Selasky * XXX - Is there something clever we could do here, 1415b00ab754SHans Petter Selasky * given that we know that the file-supplied resolution 1416b00ab754SHans Petter Selasky * is a power of 2? Doing a multiplication followed by 1417b00ab754SHans Petter Selasky * a division runs the risk of overflowing, and involves 1418b00ab754SHans Petter Selasky * two non-simple arithmetic operations. 1419b00ab754SHans Petter Selasky */ 1420b00ab754SHans Petter Selasky frac *= ps->user_tsresol; 1421b00ab754SHans Petter Selasky frac /= ps->ifaces[interface_id].tsresol; 1422b00ab754SHans Petter Selasky break; 1423b00ab754SHans Petter Selasky 1424b00ab754SHans Petter Selasky case SCALE_DOWN_DEC: 1425b00ab754SHans Petter Selasky /* 1426b00ab754SHans Petter Selasky * The interface resolution is greater than what the user 1427b00ab754SHans Petter Selasky * wants; scale the fractional part up to the units of 1428b00ab754SHans Petter Selasky * the resolution the user requested by multiplying by 1429b00ab754SHans Petter Selasky * the quotient of the user-requested resolution and the 1430b00ab754SHans Petter Selasky * file-supplied resolution. 1431b00ab754SHans Petter Selasky * 1432b00ab754SHans Petter Selasky * Those resolutions are both powers of 10, and the user- 1433b00ab754SHans Petter Selasky * requested resolution is less than the file-supplied 1434b00ab754SHans Petter Selasky * resolution, so the quotient in question isn't an 1435b00ab754SHans Petter Selasky * integer, but its reciprocal is, and we can just divide 1436b00ab754SHans Petter Selasky * by the reciprocal of the quotient. We've calculated 1437b00ab754SHans Petter Selasky * the reciprocal of that quotient already, so we must 1438b00ab754SHans Petter Selasky * divide by it. 1439b00ab754SHans Petter Selasky */ 1440b00ab754SHans Petter Selasky frac /= ps->ifaces[interface_id].scale_factor; 1441b00ab754SHans Petter Selasky break; 1442b00ab754SHans Petter Selasky 1443b00ab754SHans Petter Selasky 1444b00ab754SHans Petter Selasky case SCALE_DOWN_BIN: 1445b00ab754SHans Petter Selasky /* 1446b00ab754SHans Petter Selasky * The interface resolution is greater than what the user 1447b00ab754SHans Petter Selasky * wants; convert the fractional part to units of the 1448b00ab754SHans Petter Selasky * resolution the user requested by multiplying by the 1449b00ab754SHans Petter Selasky * quotient of the user-requested resolution and the 1450b00ab754SHans Petter Selasky * file-supplied resolution. We do that by multiplying 1451b00ab754SHans Petter Selasky * by the user-requested resolution and dividing by the 1452b00ab754SHans Petter Selasky * file-supplied resolution, as the quotient might not 1453b00ab754SHans Petter Selasky * fit in an integer. 1454b00ab754SHans Petter Selasky * 1455b00ab754SHans Petter Selasky * The file-supplied resolution is a power of 2, so the 1456b00ab754SHans Petter Selasky * quotient is not an integer, and neither is its 1457b00ab754SHans Petter Selasky * reciprocal, so, in order to do this entirely with 1458b00ab754SHans Petter Selasky * integer arithmetic, we multiply by the user-requested 1459b00ab754SHans Petter Selasky * resolution and divide by the file-supplied resolution. 1460b00ab754SHans Petter Selasky * 1461b00ab754SHans Petter Selasky * XXX - Is there something clever we could do here, 1462b00ab754SHans Petter Selasky * given that we know that the file-supplied resolution 1463b00ab754SHans Petter Selasky * is a power of 2? Doing a multiplication followed by 1464b00ab754SHans Petter Selasky * a division runs the risk of overflowing, and involves 1465b00ab754SHans Petter Selasky * two non-simple arithmetic operations. 1466b00ab754SHans Petter Selasky */ 1467b00ab754SHans Petter Selasky frac *= ps->user_tsresol; 1468b00ab754SHans Petter Selasky frac /= ps->ifaces[interface_id].tsresol; 1469b00ab754SHans Petter Selasky break; 1470b00ab754SHans Petter Selasky } 1471b00ab754SHans Petter Selasky #ifdef _WIN32 1472b00ab754SHans Petter Selasky /* 1473b00ab754SHans Petter Selasky * tv_sec and tv_used in the Windows struct timeval are both 1474b00ab754SHans Petter Selasky * longs. 1475b00ab754SHans Petter Selasky */ 1476b00ab754SHans Petter Selasky hdr->ts.tv_sec = (long)sec; 1477b00ab754SHans Petter Selasky hdr->ts.tv_usec = (long)frac; 1478b00ab754SHans Petter Selasky #else 1479b00ab754SHans Petter Selasky /* 1480b00ab754SHans Petter Selasky * tv_sec in the UN*X struct timeval is a time_t; tv_usec is 1481b00ab754SHans Petter Selasky * suseconds_t in UN*Xes that work the way the current Single 1482b00ab754SHans Petter Selasky * UNIX Standard specify - but not all older UN*Xes necessarily 1483b00ab754SHans Petter Selasky * support that type, so just cast to int. 1484b00ab754SHans Petter Selasky */ 1485b00ab754SHans Petter Selasky hdr->ts.tv_sec = (time_t)sec; 1486b00ab754SHans Petter Selasky hdr->ts.tv_usec = (int)frac; 1487b00ab754SHans Petter Selasky #endif 1488b00ab754SHans Petter Selasky 1489b00ab754SHans Petter Selasky /* 1490b00ab754SHans Petter Selasky * Get a pointer to the packet data. 1491b00ab754SHans Petter Selasky */ 1492b00ab754SHans Petter Selasky *data = get_from_block_data(&cursor, hdr->caplen, p->errbuf); 1493b00ab754SHans Petter Selasky if (*data == NULL) 1494b00ab754SHans Petter Selasky return (-1); 1495b00ab754SHans Petter Selasky 1496b00ab754SHans Petter Selasky if (p->swapped) 1497b00ab754SHans Petter Selasky swap_pseudo_headers(p->linktype, hdr, *data); 1498b00ab754SHans Petter Selasky 1499b00ab754SHans Petter Selasky return (0); 1500b00ab754SHans Petter Selasky } 1501