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