1335640Shselasky/* 2335640Shselasky * Copyright (c) 1993, 1994, 1995, 1996, 1997 3335640Shselasky * The Regents of the University of California. All rights reserved. 4335640Shselasky * 5335640Shselasky * Redistribution and use in source and binary forms, with or without 6335640Shselasky * modification, are permitted provided that: (1) source code distributions 7335640Shselasky * retain the above copyright notice and this paragraph in its entirety, (2) 8335640Shselasky * distributions including binary code include the above copyright notice and 9335640Shselasky * this paragraph in its entirety in the documentation or other materials 10335640Shselasky * provided with the distribution, and (3) all advertising materials mentioning 11335640Shselasky * features or use of this software display the following acknowledgement: 12335640Shselasky * ``This product includes software developed by the University of California, 13335640Shselasky * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14335640Shselasky * the University nor the names of its contributors may be used to endorse 15335640Shselasky * or promote products derived from this software without specific prior 16335640Shselasky * written permission. 17335640Shselasky * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18335640Shselasky * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19335640Shselasky * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20335640Shselasky * 21335640Shselasky * sf-pcapng.c - pcapng-file-format-specific code from savefile.c 22335640Shselasky */ 23335640Shselasky 24335640Shselasky#ifdef HAVE_CONFIG_H 25335640Shselasky#include <config.h> 26335640Shselasky#endif 27335640Shselasky 28335640Shselasky#include <pcap/pcap-inttypes.h> 29335640Shselasky 30335640Shselasky#include <errno.h> 31335640Shselasky#include <memory.h> 32335640Shselasky#include <stdio.h> 33335640Shselasky#include <stdlib.h> 34335640Shselasky#include <string.h> 35335640Shselasky 36335640Shselasky#include "pcap-int.h" 37335640Shselasky 38335640Shselasky#include "pcap-common.h" 39335640Shselasky 40335640Shselasky#ifdef HAVE_OS_PROTO_H 41335640Shselasky#include "os-proto.h" 42335640Shselasky#endif 43335640Shselasky 44335640Shselasky#include "sf-pcapng.h" 45335640Shselasky 46335640Shselasky/* 47335640Shselasky * Block types. 48335640Shselasky */ 49335640Shselasky 50335640Shselasky/* 51335640Shselasky * Common part at the beginning of all blocks. 52335640Shselasky */ 53335640Shselaskystruct block_header { 54335640Shselasky bpf_u_int32 block_type; 55335640Shselasky bpf_u_int32 total_length; 56335640Shselasky}; 57335640Shselasky 58335640Shselasky/* 59335640Shselasky * Common trailer at the end of all blocks. 60335640Shselasky */ 61335640Shselaskystruct block_trailer { 62335640Shselasky bpf_u_int32 total_length; 63335640Shselasky}; 64335640Shselasky 65335640Shselasky/* 66335640Shselasky * Common options. 67335640Shselasky */ 68335640Shselasky#define OPT_ENDOFOPT 0 /* end of options */ 69335640Shselasky#define OPT_COMMENT 1 /* comment string */ 70335640Shselasky 71335640Shselasky/* 72335640Shselasky * Option header. 73335640Shselasky */ 74335640Shselaskystruct option_header { 75335640Shselasky u_short option_code; 76335640Shselasky u_short option_length; 77335640Shselasky}; 78335640Shselasky 79335640Shselasky/* 80335640Shselasky * Structures for the part of each block type following the common 81335640Shselasky * part. 82335640Shselasky */ 83335640Shselasky 84335640Shselasky/* 85335640Shselasky * Section Header Block. 86335640Shselasky */ 87335640Shselasky#define BT_SHB 0x0A0D0D0A 88356341Scy#define BT_SHB_INSANE_MAX 1024U*1024U*1U /* 1MB should be enough */ 89335640Shselaskystruct section_header_block { 90335640Shselasky bpf_u_int32 byte_order_magic; 91335640Shselasky u_short major_version; 92335640Shselasky u_short minor_version; 93335640Shselasky uint64_t section_length; 94335640Shselasky /* followed by options and trailer */ 95335640Shselasky}; 96335640Shselasky 97335640Shselasky/* 98335640Shselasky * Byte-order magic value. 99335640Shselasky */ 100335640Shselasky#define BYTE_ORDER_MAGIC 0x1A2B3C4D 101335640Shselasky 102335640Shselasky/* 103335640Shselasky * Current version number. If major_version isn't PCAP_NG_VERSION_MAJOR, 104335640Shselasky * that means that this code can't read the file. 105335640Shselasky */ 106335640Shselasky#define PCAP_NG_VERSION_MAJOR 1 107335640Shselasky#define PCAP_NG_VERSION_MINOR 0 108335640Shselasky 109335640Shselasky/* 110335640Shselasky * Interface Description Block. 111335640Shselasky */ 112335640Shselasky#define BT_IDB 0x00000001 113335640Shselasky 114335640Shselaskystruct interface_description_block { 115335640Shselasky u_short linktype; 116335640Shselasky u_short reserved; 117335640Shselasky bpf_u_int32 snaplen; 118335640Shselasky /* followed by options and trailer */ 119335640Shselasky}; 120335640Shselasky 121335640Shselasky/* 122335640Shselasky * Options in the IDB. 123335640Shselasky */ 124335640Shselasky#define IF_NAME 2 /* interface name string */ 125335640Shselasky#define IF_DESCRIPTION 3 /* interface description string */ 126335640Shselasky#define IF_IPV4ADDR 4 /* interface's IPv4 address and netmask */ 127335640Shselasky#define IF_IPV6ADDR 5 /* interface's IPv6 address and prefix length */ 128335640Shselasky#define IF_MACADDR 6 /* interface's MAC address */ 129335640Shselasky#define IF_EUIADDR 7 /* interface's EUI address */ 130335640Shselasky#define IF_SPEED 8 /* interface's speed, in bits/s */ 131335640Shselasky#define IF_TSRESOL 9 /* interface's time stamp resolution */ 132335640Shselasky#define IF_TZONE 10 /* interface's time zone */ 133335640Shselasky#define IF_FILTER 11 /* filter used when capturing on interface */ 134335640Shselasky#define IF_OS 12 /* string OS on which capture on this interface was done */ 135335640Shselasky#define IF_FCSLEN 13 /* FCS length for this interface */ 136335640Shselasky#define IF_TSOFFSET 14 /* time stamp offset for this interface */ 137335640Shselasky 138335640Shselasky/* 139335640Shselasky * Enhanced Packet Block. 140335640Shselasky */ 141335640Shselasky#define BT_EPB 0x00000006 142335640Shselasky 143335640Shselaskystruct enhanced_packet_block { 144335640Shselasky bpf_u_int32 interface_id; 145335640Shselasky bpf_u_int32 timestamp_high; 146335640Shselasky bpf_u_int32 timestamp_low; 147335640Shselasky bpf_u_int32 caplen; 148335640Shselasky bpf_u_int32 len; 149335640Shselasky /* followed by packet data, options, and trailer */ 150335640Shselasky}; 151335640Shselasky 152335640Shselasky/* 153335640Shselasky * Simple Packet Block. 154335640Shselasky */ 155335640Shselasky#define BT_SPB 0x00000003 156335640Shselasky 157335640Shselaskystruct simple_packet_block { 158335640Shselasky bpf_u_int32 len; 159335640Shselasky /* followed by packet data and trailer */ 160335640Shselasky}; 161335640Shselasky 162335640Shselasky/* 163335640Shselasky * Packet Block. 164335640Shselasky */ 165335640Shselasky#define BT_PB 0x00000002 166335640Shselasky 167335640Shselaskystruct packet_block { 168335640Shselasky u_short interface_id; 169335640Shselasky u_short drops_count; 170335640Shselasky bpf_u_int32 timestamp_high; 171335640Shselasky bpf_u_int32 timestamp_low; 172335640Shselasky bpf_u_int32 caplen; 173335640Shselasky bpf_u_int32 len; 174335640Shselasky /* followed by packet data, options, and trailer */ 175335640Shselasky}; 176335640Shselasky 177335640Shselasky/* 178335640Shselasky * Block cursor - used when processing the contents of a block. 179335640Shselasky * Contains a pointer into the data being processed and a count 180335640Shselasky * of bytes remaining in the block. 181335640Shselasky */ 182335640Shselaskystruct block_cursor { 183335640Shselasky u_char *data; 184335640Shselasky size_t data_remaining; 185335640Shselasky bpf_u_int32 block_type; 186335640Shselasky}; 187335640Shselasky 188335640Shselaskytypedef enum { 189335640Shselasky PASS_THROUGH, 190335640Shselasky SCALE_UP_DEC, 191335640Shselasky SCALE_DOWN_DEC, 192335640Shselasky SCALE_UP_BIN, 193335640Shselasky SCALE_DOWN_BIN 194335640Shselasky} tstamp_scale_type_t; 195335640Shselasky 196335640Shselasky/* 197335640Shselasky * Per-interface information. 198335640Shselasky */ 199335640Shselaskystruct pcap_ng_if { 200356341Scy uint64_t tsresol; /* time stamp resolution */ 201335640Shselasky tstamp_scale_type_t scale_type; /* how to scale */ 202356341Scy uint64_t scale_factor; /* time stamp scale factor for power-of-10 tsresol */ 203335640Shselasky uint64_t tsoffset; /* time stamp offset */ 204335640Shselasky}; 205335640Shselasky 206335640Shselasky/* 207335640Shselasky * Per-pcap_t private data. 208335640Shselasky * 209335640Shselasky * max_blocksize is the maximum size of a block that we'll accept. We 210335640Shselasky * reject blocks bigger than this, so we don't consume too much memory 211335640Shselasky * with a truly huge block. It can change as we see IDBs with different 212335640Shselasky * link-layer header types. (Currently, we don't support IDBs with 213335640Shselasky * different link-layer header types, but we will support it in the 214335640Shselasky * future, when we offer file-reading APIs that support it.) 215335640Shselasky * 216335640Shselasky * XXX - that's an issue on ILP32 platforms, where the maximum block 217335640Shselasky * size of 2^31-1 would eat all but one byte of the entire address space. 218335640Shselasky * It's less of an issue on ILP64/LLP64 platforms, but the actual size 219335640Shselasky * of the address space may be limited by 1) the number of *significant* 220335640Shselasky * address bits (currently, x86-64 only supports 48 bits of address), 2) 221335640Shselasky * any limitations imposed by the operating system; 3) any limitations 222335640Shselasky * imposed by the amount of available backing store for anonymous pages, 223335640Shselasky * so we impose a limit regardless of the size of a pointer. 224335640Shselasky */ 225335640Shselaskystruct pcap_ng_sf { 226356341Scy uint64_t user_tsresol; /* time stamp resolution requested by the user */ 227335640Shselasky u_int max_blocksize; /* don't grow buffer size past this */ 228335640Shselasky bpf_u_int32 ifcount; /* number of interfaces seen in this capture */ 229335640Shselasky bpf_u_int32 ifaces_size; /* size of array below */ 230335640Shselasky struct pcap_ng_if *ifaces; /* array of interface information */ 231335640Shselasky}; 232335640Shselasky 233335640Shselasky/* 234356341Scy * The maximum block size we start with; we use an arbitrary value of 235356341Scy * 16 MiB. 236335640Shselasky */ 237356341Scy#define INITIAL_MAX_BLOCKSIZE (16*1024*1024) 238335640Shselasky 239356341Scy/* 240356341Scy * Maximum block size for a given maximum snapshot length; we define it 241356341Scy * as the size of an EPB with a max_snaplen-sized packet and 128KB of 242356341Scy * options. 243356341Scy */ 244356341Scy#define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \ 245356341Scy (sizeof (struct block_header) + \ 246356341Scy sizeof (struct enhanced_packet_block) + \ 247356341Scy (max_snaplen) + 131072 + \ 248356341Scy sizeof (struct block_trailer)) 249356341Scy 250335640Shselaskystatic void pcap_ng_cleanup(pcap_t *p); 251335640Shselaskystatic int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, 252335640Shselasky u_char **data); 253335640Shselasky 254335640Shselaskystatic int 255335640Shselaskyread_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof, 256335640Shselasky char *errbuf) 257335640Shselasky{ 258335640Shselasky size_t amt_read; 259335640Shselasky 260335640Shselasky amt_read = fread(buf, 1, bytes_to_read, fp); 261335640Shselasky if (amt_read != bytes_to_read) { 262335640Shselasky if (ferror(fp)) { 263335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 264335640Shselasky errno, "error reading dump file"); 265335640Shselasky } else { 266335640Shselasky if (amt_read == 0 && !fail_on_eof) 267335640Shselasky return (0); /* EOF */ 268335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 269356341Scy "truncated pcapng dump file; tried to read %" PRIsize " bytes, only got %" PRIsize, 270356341Scy bytes_to_read, amt_read); 271335640Shselasky } 272335640Shselasky return (-1); 273335640Shselasky } 274335640Shselasky return (1); 275335640Shselasky} 276335640Shselasky 277335640Shselaskystatic int 278335640Shselaskyread_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf) 279335640Shselasky{ 280335640Shselasky struct pcap_ng_sf *ps; 281335640Shselasky int status; 282335640Shselasky struct block_header bhdr; 283356341Scy struct block_trailer *btrlr; 284335640Shselasky u_char *bdata; 285335640Shselasky size_t data_remaining; 286335640Shselasky 287335640Shselasky ps = p->priv; 288335640Shselasky 289335640Shselasky status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf); 290335640Shselasky if (status <= 0) 291335640Shselasky return (status); /* error or EOF */ 292335640Shselasky 293335640Shselasky if (p->swapped) { 294335640Shselasky bhdr.block_type = SWAPLONG(bhdr.block_type); 295335640Shselasky bhdr.total_length = SWAPLONG(bhdr.total_length); 296335640Shselasky } 297335640Shselasky 298335640Shselasky /* 299335640Shselasky * Is this block "too small" - i.e., is it shorter than a block 300335640Shselasky * header plus a block trailer? 301335640Shselasky */ 302335640Shselasky if (bhdr.total_length < sizeof(struct block_header) + 303335640Shselasky sizeof(struct block_trailer)) { 304335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 305356341Scy "block in pcapng dump file has a length of %u < %" PRIsize, 306335640Shselasky bhdr.total_length, 307356341Scy sizeof(struct block_header) + sizeof(struct block_trailer)); 308335640Shselasky return (-1); 309335640Shselasky } 310335640Shselasky 311335640Shselasky /* 312356341Scy * Is the block total length a multiple of 4? 313356341Scy */ 314356341Scy if ((bhdr.total_length % 4) != 0) { 315356341Scy /* 316356341Scy * No. Report that as an error. 317356341Scy */ 318356341Scy pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 319356341Scy "block in pcapng dump file has a length of %u that is not a multiple of 4" PRIsize, 320356341Scy bhdr.total_length); 321356341Scy return (-1); 322356341Scy } 323356341Scy 324356341Scy /* 325335640Shselasky * Is the buffer big enough? 326335640Shselasky */ 327335640Shselasky if (p->bufsize < bhdr.total_length) { 328335640Shselasky /* 329356341Scy * No - make it big enough, unless it's too big, in 330356341Scy * which case we fail. 331335640Shselasky */ 332335640Shselasky void *bigger_buffer; 333335640Shselasky 334335640Shselasky if (bhdr.total_length > ps->max_blocksize) { 335356341Scy pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length, 336335640Shselasky ps->max_blocksize); 337335640Shselasky return (-1); 338335640Shselasky } 339335640Shselasky bigger_buffer = realloc(p->buffer, bhdr.total_length); 340335640Shselasky if (bigger_buffer == NULL) { 341335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 342335640Shselasky return (-1); 343335640Shselasky } 344335640Shselasky p->buffer = bigger_buffer; 345335640Shselasky } 346335640Shselasky 347335640Shselasky /* 348335640Shselasky * Copy the stuff we've read to the buffer, and read the rest 349335640Shselasky * of the block. 350335640Shselasky */ 351335640Shselasky memcpy(p->buffer, &bhdr, sizeof(bhdr)); 352335640Shselasky bdata = (u_char *)p->buffer + sizeof(bhdr); 353335640Shselasky data_remaining = bhdr.total_length - sizeof(bhdr); 354335640Shselasky if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1) 355335640Shselasky return (-1); 356335640Shselasky 357335640Shselasky /* 358356341Scy * Get the block size from the trailer. 359356341Scy */ 360356341Scy btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer)); 361356341Scy if (p->swapped) 362356341Scy btrlr->total_length = SWAPLONG(btrlr->total_length); 363356341Scy 364356341Scy /* 365356341Scy * Is the total length from the trailer the same as the total 366356341Scy * length from the header? 367356341Scy */ 368356341Scy if (bhdr.total_length != btrlr->total_length) { 369356341Scy /* 370356341Scy * No. 371356341Scy */ 372356341Scy pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 373356341Scy "block total length in header and trailer don't match"); 374356341Scy return (-1); 375356341Scy } 376356341Scy 377356341Scy /* 378335640Shselasky * Initialize the cursor. 379335640Shselasky */ 380335640Shselasky cursor->data = bdata; 381335640Shselasky cursor->data_remaining = data_remaining - sizeof(struct block_trailer); 382335640Shselasky cursor->block_type = bhdr.block_type; 383335640Shselasky return (1); 384335640Shselasky} 385335640Shselasky 386335640Shselaskystatic void * 387335640Shselaskyget_from_block_data(struct block_cursor *cursor, size_t chunk_size, 388335640Shselasky char *errbuf) 389335640Shselasky{ 390335640Shselasky void *data; 391335640Shselasky 392335640Shselasky /* 393335640Shselasky * Make sure we have the specified amount of data remaining in 394335640Shselasky * the block data. 395335640Shselasky */ 396335640Shselasky if (cursor->data_remaining < chunk_size) { 397335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 398335640Shselasky "block of type %u in pcapng dump file is too short", 399335640Shselasky cursor->block_type); 400335640Shselasky return (NULL); 401335640Shselasky } 402335640Shselasky 403335640Shselasky /* 404335640Shselasky * Return the current pointer, and skip past the chunk. 405335640Shselasky */ 406335640Shselasky data = cursor->data; 407335640Shselasky cursor->data += chunk_size; 408335640Shselasky cursor->data_remaining -= chunk_size; 409335640Shselasky return (data); 410335640Shselasky} 411335640Shselasky 412335640Shselaskystatic struct option_header * 413335640Shselaskyget_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf) 414335640Shselasky{ 415335640Shselasky struct option_header *opthdr; 416335640Shselasky 417335640Shselasky opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf); 418335640Shselasky if (opthdr == NULL) { 419335640Shselasky /* 420335640Shselasky * Option header is cut short. 421335640Shselasky */ 422335640Shselasky return (NULL); 423335640Shselasky } 424335640Shselasky 425335640Shselasky /* 426335640Shselasky * Byte-swap it if necessary. 427335640Shselasky */ 428335640Shselasky if (p->swapped) { 429335640Shselasky opthdr->option_code = SWAPSHORT(opthdr->option_code); 430335640Shselasky opthdr->option_length = SWAPSHORT(opthdr->option_length); 431335640Shselasky } 432335640Shselasky 433335640Shselasky return (opthdr); 434335640Shselasky} 435335640Shselasky 436335640Shselaskystatic void * 437335640Shselaskyget_optvalue_from_block_data(struct block_cursor *cursor, 438335640Shselasky struct option_header *opthdr, char *errbuf) 439335640Shselasky{ 440335640Shselasky size_t padded_option_len; 441335640Shselasky void *optvalue; 442335640Shselasky 443335640Shselasky /* Pad option length to 4-byte boundary */ 444335640Shselasky padded_option_len = opthdr->option_length; 445335640Shselasky padded_option_len = ((padded_option_len + 3)/4)*4; 446335640Shselasky 447335640Shselasky optvalue = get_from_block_data(cursor, padded_option_len, errbuf); 448335640Shselasky if (optvalue == NULL) { 449335640Shselasky /* 450335640Shselasky * Option value is cut short. 451335640Shselasky */ 452335640Shselasky return (NULL); 453335640Shselasky } 454335640Shselasky 455335640Shselasky return (optvalue); 456335640Shselasky} 457335640Shselasky 458335640Shselaskystatic int 459356341Scyprocess_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol, 460335640Shselasky uint64_t *tsoffset, int *is_binary, char *errbuf) 461335640Shselasky{ 462335640Shselasky struct option_header *opthdr; 463335640Shselasky void *optvalue; 464335640Shselasky int saw_tsresol, saw_tsoffset; 465356341Scy uint8_t tsresol_opt; 466335640Shselasky u_int i; 467335640Shselasky 468335640Shselasky saw_tsresol = 0; 469335640Shselasky saw_tsoffset = 0; 470335640Shselasky while (cursor->data_remaining != 0) { 471335640Shselasky /* 472335640Shselasky * Get the option header. 473335640Shselasky */ 474335640Shselasky opthdr = get_opthdr_from_block_data(p, cursor, errbuf); 475335640Shselasky if (opthdr == NULL) { 476335640Shselasky /* 477335640Shselasky * Option header is cut short. 478335640Shselasky */ 479335640Shselasky return (-1); 480335640Shselasky } 481335640Shselasky 482335640Shselasky /* 483335640Shselasky * Get option value. 484335640Shselasky */ 485335640Shselasky optvalue = get_optvalue_from_block_data(cursor, opthdr, 486335640Shselasky errbuf); 487335640Shselasky if (optvalue == NULL) { 488335640Shselasky /* 489335640Shselasky * Option value is cut short. 490335640Shselasky */ 491335640Shselasky return (-1); 492335640Shselasky } 493335640Shselasky 494335640Shselasky switch (opthdr->option_code) { 495335640Shselasky 496335640Shselasky case OPT_ENDOFOPT: 497335640Shselasky if (opthdr->option_length != 0) { 498335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 499335640Shselasky "Interface Description Block has opt_endofopt option with length %u != 0", 500335640Shselasky opthdr->option_length); 501335640Shselasky return (-1); 502335640Shselasky } 503335640Shselasky goto done; 504335640Shselasky 505335640Shselasky case IF_TSRESOL: 506335640Shselasky if (opthdr->option_length != 1) { 507335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 508335640Shselasky "Interface Description Block has if_tsresol option with length %u != 1", 509335640Shselasky opthdr->option_length); 510335640Shselasky return (-1); 511335640Shselasky } 512335640Shselasky if (saw_tsresol) { 513335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 514335640Shselasky "Interface Description Block has more than one if_tsresol option"); 515335640Shselasky return (-1); 516335640Shselasky } 517335640Shselasky saw_tsresol = 1; 518335640Shselasky memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt)); 519335640Shselasky if (tsresol_opt & 0x80) { 520335640Shselasky /* 521335640Shselasky * Resolution is negative power of 2. 522335640Shselasky */ 523356341Scy uint8_t tsresol_shift = (tsresol_opt & 0x7F); 524356341Scy 525356341Scy if (tsresol_shift > 63) { 526356341Scy /* 527356341Scy * Resolution is too high; 2^-{res} 528356341Scy * won't fit in a 64-bit value. 529356341Scy */ 530356341Scy pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 531356341Scy "Interface Description Block if_tsresol option resolution 2^-%u is too high", 532356341Scy tsresol_shift); 533356341Scy return (-1); 534356341Scy } 535335640Shselasky *is_binary = 1; 536356341Scy *tsresol = ((uint64_t)1) << tsresol_shift; 537335640Shselasky } else { 538335640Shselasky /* 539335640Shselasky * Resolution is negative power of 10. 540335640Shselasky */ 541356341Scy if (tsresol_opt > 19) { 542356341Scy /* 543356341Scy * Resolution is too high; 2^-{res} 544356341Scy * won't fit in a 64-bit value (the 545356341Scy * largest power of 10 that fits 546356341Scy * in a 64-bit value is 10^19, as 547356341Scy * the largest 64-bit unsigned 548356341Scy * value is ~1.8*10^19). 549356341Scy */ 550356341Scy pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 551356341Scy "Interface Description Block if_tsresol option resolution 10^-%u is too high", 552356341Scy tsresol_opt); 553356341Scy return (-1); 554356341Scy } 555335640Shselasky *is_binary = 0; 556335640Shselasky *tsresol = 1; 557335640Shselasky for (i = 0; i < tsresol_opt; i++) 558335640Shselasky *tsresol *= 10; 559335640Shselasky } 560335640Shselasky break; 561335640Shselasky 562335640Shselasky case IF_TSOFFSET: 563335640Shselasky if (opthdr->option_length != 8) { 564335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 565335640Shselasky "Interface Description Block has if_tsoffset option with length %u != 8", 566335640Shselasky opthdr->option_length); 567335640Shselasky return (-1); 568335640Shselasky } 569335640Shselasky if (saw_tsoffset) { 570335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 571335640Shselasky "Interface Description Block has more than one if_tsoffset option"); 572335640Shselasky return (-1); 573335640Shselasky } 574335640Shselasky saw_tsoffset = 1; 575335640Shselasky memcpy(tsoffset, optvalue, sizeof(*tsoffset)); 576335640Shselasky if (p->swapped) 577335640Shselasky *tsoffset = SWAPLL(*tsoffset); 578335640Shselasky break; 579335640Shselasky 580335640Shselasky default: 581335640Shselasky break; 582335640Shselasky } 583335640Shselasky } 584335640Shselasky 585335640Shselaskydone: 586335640Shselasky return (0); 587335640Shselasky} 588335640Shselasky 589335640Shselaskystatic int 590335640Shselaskyadd_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf) 591335640Shselasky{ 592335640Shselasky struct pcap_ng_sf *ps; 593356341Scy uint64_t tsresol; 594335640Shselasky uint64_t tsoffset; 595335640Shselasky int is_binary; 596335640Shselasky 597335640Shselasky ps = p->priv; 598335640Shselasky 599335640Shselasky /* 600335640Shselasky * Count this interface. 601335640Shselasky */ 602335640Shselasky ps->ifcount++; 603335640Shselasky 604335640Shselasky /* 605335640Shselasky * Grow the array of per-interface information as necessary. 606335640Shselasky */ 607335640Shselasky if (ps->ifcount > ps->ifaces_size) { 608335640Shselasky /* 609335640Shselasky * We need to grow the array. 610335640Shselasky */ 611335640Shselasky bpf_u_int32 new_ifaces_size; 612335640Shselasky struct pcap_ng_if *new_ifaces; 613335640Shselasky 614335640Shselasky if (ps->ifaces_size == 0) { 615335640Shselasky /* 616335640Shselasky * It's currently empty. 617335640Shselasky * 618335640Shselasky * (The Clang static analyzer doesn't do enough, 619335640Shselasky * err, umm, dataflow *analysis* to realize that 620335640Shselasky * ps->ifaces_size == 0 if ps->ifaces == NULL, 621335640Shselasky * and so complains about a possible zero argument 622335640Shselasky * to realloc(), so we check for the former 623335640Shselasky * condition to shut it up. 624335640Shselasky * 625335640Shselasky * However, it doesn't complain that one of the 626335640Shselasky * multiplications below could overflow, which is 627335640Shselasky * a real, albeit extremely unlikely, problem (you'd 628335640Shselasky * need a pcapng file with tens of millions of 629335640Shselasky * interfaces).) 630335640Shselasky */ 631335640Shselasky new_ifaces_size = 1; 632335640Shselasky new_ifaces = malloc(sizeof (struct pcap_ng_if)); 633335640Shselasky } else { 634335640Shselasky /* 635335640Shselasky * It's not currently empty; double its size. 636335640Shselasky * (Perhaps overkill once we have a lot of interfaces.) 637335640Shselasky * 638335640Shselasky * Check for overflow if we double it. 639335640Shselasky */ 640335640Shselasky if (ps->ifaces_size * 2 < ps->ifaces_size) { 641335640Shselasky /* 642335640Shselasky * The maximum number of interfaces before 643335640Shselasky * ps->ifaces_size overflows is the largest 644335640Shselasky * possible 32-bit power of 2, as we do 645335640Shselasky * size doubling. 646335640Shselasky */ 647335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 648335640Shselasky "more than %u interfaces in the file", 649335640Shselasky 0x80000000U); 650335640Shselasky return (0); 651335640Shselasky } 652335640Shselasky 653335640Shselasky /* 654335640Shselasky * ps->ifaces_size * 2 doesn't overflow, so it's 655335640Shselasky * safe to multiply. 656335640Shselasky */ 657335640Shselasky new_ifaces_size = ps->ifaces_size * 2; 658335640Shselasky 659335640Shselasky /* 660335640Shselasky * Now make sure that's not so big that it overflows 661335640Shselasky * if we multiply by sizeof (struct pcap_ng_if). 662335640Shselasky * 663335640Shselasky * That can happen on 32-bit platforms, with a 32-bit 664335640Shselasky * size_t; it shouldn't happen on 64-bit platforms, 665335640Shselasky * with a 64-bit size_t, as new_ifaces_size is 666335640Shselasky * 32 bits. 667335640Shselasky */ 668335640Shselasky if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) { 669335640Shselasky /* 670335640Shselasky * As this fails only with 32-bit size_t, 671335640Shselasky * the multiplication was 32x32->32, and 672335640Shselasky * the largest 32-bit value that can safely 673335640Shselasky * be multiplied by sizeof (struct pcap_ng_if) 674335640Shselasky * without overflow is the largest 32-bit 675335640Shselasky * (unsigned) value divided by 676335640Shselasky * sizeof (struct pcap_ng_if). 677335640Shselasky */ 678335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 679335640Shselasky "more than %u interfaces in the file", 680335640Shselasky 0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if))); 681335640Shselasky return (0); 682335640Shselasky } 683335640Shselasky new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if)); 684335640Shselasky } 685335640Shselasky if (new_ifaces == NULL) { 686335640Shselasky /* 687335640Shselasky * We ran out of memory. 688335640Shselasky * Give up. 689335640Shselasky */ 690335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 691335640Shselasky "out of memory for per-interface information (%u interfaces)", 692335640Shselasky ps->ifcount); 693335640Shselasky return (0); 694335640Shselasky } 695335640Shselasky ps->ifaces_size = new_ifaces_size; 696335640Shselasky ps->ifaces = new_ifaces; 697335640Shselasky } 698335640Shselasky 699335640Shselasky /* 700335640Shselasky * Set the default time stamp resolution and offset. 701335640Shselasky */ 702335640Shselasky tsresol = 1000000; /* microsecond resolution */ 703335640Shselasky is_binary = 0; /* which is a power of 10 */ 704335640Shselasky tsoffset = 0; /* absolute timestamps */ 705335640Shselasky 706335640Shselasky /* 707335640Shselasky * Now look for various time stamp options, so we know 708335640Shselasky * how to interpret the time stamps for this interface. 709335640Shselasky */ 710335640Shselasky if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary, 711335640Shselasky errbuf) == -1) 712335640Shselasky return (0); 713335640Shselasky 714335640Shselasky ps->ifaces[ps->ifcount - 1].tsresol = tsresol; 715335640Shselasky ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset; 716335640Shselasky 717335640Shselasky /* 718335640Shselasky * Determine whether we're scaling up or down or not 719335640Shselasky * at all for this interface. 720335640Shselasky */ 721335640Shselasky if (tsresol == ps->user_tsresol) { 722335640Shselasky /* 723335640Shselasky * The resolution is the resolution the user wants, 724335640Shselasky * so we don't have to do scaling. 725335640Shselasky */ 726335640Shselasky ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH; 727335640Shselasky } else if (tsresol > ps->user_tsresol) { 728335640Shselasky /* 729335640Shselasky * The resolution is greater than what the user wants, 730335640Shselasky * so we have to scale the timestamps down. 731335640Shselasky */ 732335640Shselasky if (is_binary) 733335640Shselasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN; 734335640Shselasky else { 735335640Shselasky /* 736335640Shselasky * Calculate the scale factor. 737335640Shselasky */ 738335640Shselasky ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol; 739335640Shselasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC; 740335640Shselasky } 741335640Shselasky } else { 742335640Shselasky /* 743335640Shselasky * The resolution is less than what the user wants, 744335640Shselasky * so we have to scale the timestamps up. 745335640Shselasky */ 746335640Shselasky if (is_binary) 747335640Shselasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN; 748335640Shselasky else { 749335640Shselasky /* 750335640Shselasky * Calculate the scale factor. 751335640Shselasky */ 752335640Shselasky ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol; 753335640Shselasky ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC; 754335640Shselasky } 755335640Shselasky } 756335640Shselasky return (1); 757335640Shselasky} 758335640Shselasky 759335640Shselasky/* 760335640Shselasky * Check whether this is a pcapng savefile and, if it is, extract the 761335640Shselasky * relevant information from the header. 762335640Shselasky */ 763335640Shselaskypcap_t * 764356341Scypcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision, 765356341Scy char *errbuf, int *err) 766335640Shselasky{ 767356341Scy bpf_u_int32 magic_int; 768335640Shselasky size_t amt_read; 769335640Shselasky bpf_u_int32 total_length; 770335640Shselasky bpf_u_int32 byte_order_magic; 771335640Shselasky struct block_header *bhdrp; 772335640Shselasky struct section_header_block *shbp; 773335640Shselasky pcap_t *p; 774335640Shselasky int swapped = 0; 775335640Shselasky struct pcap_ng_sf *ps; 776335640Shselasky int status; 777335640Shselasky struct block_cursor cursor; 778335640Shselasky struct interface_description_block *idbp; 779335640Shselasky 780335640Shselasky /* 781335640Shselasky * Assume no read errors. 782335640Shselasky */ 783335640Shselasky *err = 0; 784335640Shselasky 785335640Shselasky /* 786335640Shselasky * Check whether the first 4 bytes of the file are the block 787335640Shselasky * type for a pcapng savefile. 788335640Shselasky */ 789356341Scy memcpy(&magic_int, magic, sizeof(magic_int)); 790356341Scy if (magic_int != BT_SHB) { 791335640Shselasky /* 792335640Shselasky * XXX - check whether this looks like what the block 793335640Shselasky * type would be after being munged by mapping between 794335640Shselasky * UN*X and DOS/Windows text file format and, if it 795335640Shselasky * does, look for the byte-order magic number in 796335640Shselasky * the appropriate place and, if we find it, report 797335640Shselasky * this as possibly being a pcapng file transferred 798335640Shselasky * between UN*X and Windows in text file format? 799335640Shselasky */ 800335640Shselasky return (NULL); /* nope */ 801335640Shselasky } 802335640Shselasky 803335640Shselasky /* 804335640Shselasky * OK, they are. However, that's just \n\r\r\n, so it could, 805335640Shselasky * conceivably, be an ordinary text file. 806335640Shselasky * 807335640Shselasky * It could not, however, conceivably be any other type of 808335640Shselasky * capture file, so we can read the rest of the putative 809335640Shselasky * Section Header Block; put the block type in the common 810335640Shselasky * header, read the rest of the common header and the 811335640Shselasky * fixed-length portion of the SHB, and look for the byte-order 812335640Shselasky * magic value. 813335640Shselasky */ 814335640Shselasky amt_read = fread(&total_length, 1, sizeof(total_length), fp); 815335640Shselasky if (amt_read < sizeof(total_length)) { 816335640Shselasky if (ferror(fp)) { 817335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 818335640Shselasky errno, "error reading dump file"); 819335640Shselasky *err = 1; 820335640Shselasky return (NULL); /* fail */ 821335640Shselasky } 822335640Shselasky 823335640Shselasky /* 824335640Shselasky * Possibly a weird short text file, so just say 825335640Shselasky * "not pcapng". 826335640Shselasky */ 827335640Shselasky return (NULL); 828335640Shselasky } 829335640Shselasky amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp); 830335640Shselasky if (amt_read < sizeof(byte_order_magic)) { 831335640Shselasky if (ferror(fp)) { 832335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 833335640Shselasky errno, "error reading dump file"); 834335640Shselasky *err = 1; 835335640Shselasky return (NULL); /* fail */ 836335640Shselasky } 837335640Shselasky 838335640Shselasky /* 839335640Shselasky * Possibly a weird short text file, so just say 840335640Shselasky * "not pcapng". 841335640Shselasky */ 842335640Shselasky return (NULL); 843335640Shselasky } 844335640Shselasky if (byte_order_magic != BYTE_ORDER_MAGIC) { 845335640Shselasky byte_order_magic = SWAPLONG(byte_order_magic); 846335640Shselasky if (byte_order_magic != BYTE_ORDER_MAGIC) { 847335640Shselasky /* 848335640Shselasky * Not a pcapng file. 849335640Shselasky */ 850335640Shselasky return (NULL); 851335640Shselasky } 852335640Shselasky swapped = 1; 853335640Shselasky total_length = SWAPLONG(total_length); 854335640Shselasky } 855335640Shselasky 856335640Shselasky /* 857335640Shselasky * Check the sanity of the total length. 858335640Shselasky */ 859356341Scy if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) || 860356341Scy (total_length > BT_SHB_INSANE_MAX)) { 861335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 862356341Scy "Section Header Block in pcapng dump file has invalid length %" PRIsize " < _%u_ < %u (BT_SHB_INSANE_MAX)", 863356341Scy sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer), 864335640Shselasky total_length, 865356341Scy BT_SHB_INSANE_MAX); 866356341Scy 867335640Shselasky *err = 1; 868335640Shselasky return (NULL); 869335640Shselasky } 870335640Shselasky 871335640Shselasky /* 872335640Shselasky * OK, this is a good pcapng file. 873335640Shselasky * Allocate a pcap_t for it. 874335640Shselasky */ 875335640Shselasky p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf)); 876335640Shselasky if (p == NULL) { 877335640Shselasky /* Allocation failed. */ 878335640Shselasky *err = 1; 879335640Shselasky return (NULL); 880335640Shselasky } 881335640Shselasky p->swapped = swapped; 882335640Shselasky ps = p->priv; 883335640Shselasky 884335640Shselasky /* 885335640Shselasky * What precision does the user want? 886335640Shselasky */ 887335640Shselasky switch (precision) { 888335640Shselasky 889335640Shselasky case PCAP_TSTAMP_PRECISION_MICRO: 890335640Shselasky ps->user_tsresol = 1000000; 891335640Shselasky break; 892335640Shselasky 893335640Shselasky case PCAP_TSTAMP_PRECISION_NANO: 894335640Shselasky ps->user_tsresol = 1000000000; 895335640Shselasky break; 896335640Shselasky 897335640Shselasky default: 898335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 899335640Shselasky "unknown time stamp resolution %u", precision); 900335640Shselasky free(p); 901335640Shselasky *err = 1; 902335640Shselasky return (NULL); 903335640Shselasky } 904335640Shselasky 905335640Shselasky p->opt.tstamp_precision = precision; 906335640Shselasky 907335640Shselasky /* 908335640Shselasky * Allocate a buffer into which to read blocks. We default to 909335640Shselasky * the maximum of: 910335640Shselasky * 911335640Shselasky * the total length of the SHB for which we read the header; 912335640Shselasky * 913335640Shselasky * 2K, which should be more than large enough for an Enhanced 914335640Shselasky * Packet Block containing a full-size Ethernet frame, and 915335640Shselasky * leaving room for some options. 916335640Shselasky * 917335640Shselasky * If we find a bigger block, we reallocate the buffer, up to 918356341Scy * the maximum size. We start out with a maximum size of 919356341Scy * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types 920356341Scy * with a maximum snapshot that results in a larger maximum 921356341Scy * block length, we boost the maximum. 922335640Shselasky */ 923335640Shselasky p->bufsize = 2048; 924335640Shselasky if (p->bufsize < total_length) 925335640Shselasky p->bufsize = total_length; 926335640Shselasky p->buffer = malloc(p->bufsize); 927335640Shselasky if (p->buffer == NULL) { 928335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 929335640Shselasky free(p); 930335640Shselasky *err = 1; 931335640Shselasky return (NULL); 932335640Shselasky } 933356341Scy ps->max_blocksize = INITIAL_MAX_BLOCKSIZE; 934335640Shselasky 935335640Shselasky /* 936335640Shselasky * Copy the stuff we've read to the buffer, and read the rest 937335640Shselasky * of the SHB. 938335640Shselasky */ 939335640Shselasky bhdrp = (struct block_header *)p->buffer; 940335640Shselasky shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header)); 941356341Scy bhdrp->block_type = magic_int; 942335640Shselasky bhdrp->total_length = total_length; 943335640Shselasky shbp->byte_order_magic = byte_order_magic; 944335640Shselasky if (read_bytes(fp, 945356341Scy (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)), 946356341Scy total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)), 947335640Shselasky 1, errbuf) == -1) 948335640Shselasky goto fail; 949335640Shselasky 950335640Shselasky if (p->swapped) { 951335640Shselasky /* 952335640Shselasky * Byte-swap the fields we've read. 953335640Shselasky */ 954335640Shselasky shbp->major_version = SWAPSHORT(shbp->major_version); 955335640Shselasky shbp->minor_version = SWAPSHORT(shbp->minor_version); 956335640Shselasky 957335640Shselasky /* 958335640Shselasky * XXX - we don't care about the section length. 959335640Shselasky */ 960335640Shselasky } 961335640Shselasky /* currently only SHB version 1.0 is supported */ 962335640Shselasky if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR && 963335640Shselasky shbp->minor_version == PCAP_NG_VERSION_MINOR)) { 964335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 965335640Shselasky "unsupported pcapng savefile version %u.%u", 966335640Shselasky shbp->major_version, shbp->minor_version); 967335640Shselasky goto fail; 968335640Shselasky } 969335640Shselasky p->version_major = shbp->major_version; 970335640Shselasky p->version_minor = shbp->minor_version; 971335640Shselasky 972335640Shselasky /* 973335640Shselasky * Save the time stamp resolution the user requested. 974335640Shselasky */ 975335640Shselasky p->opt.tstamp_precision = precision; 976335640Shselasky 977335640Shselasky /* 978335640Shselasky * Now start looking for an Interface Description Block. 979335640Shselasky */ 980335640Shselasky for (;;) { 981335640Shselasky /* 982335640Shselasky * Read the next block. 983335640Shselasky */ 984335640Shselasky status = read_block(fp, p, &cursor, errbuf); 985335640Shselasky if (status == 0) { 986335640Shselasky /* EOF - no IDB in this file */ 987335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 988335640Shselasky "the capture file has no Interface Description Blocks"); 989335640Shselasky goto fail; 990335640Shselasky } 991335640Shselasky if (status == -1) 992335640Shselasky goto fail; /* error */ 993335640Shselasky switch (cursor.block_type) { 994335640Shselasky 995335640Shselasky case BT_IDB: 996335640Shselasky /* 997335640Shselasky * Get a pointer to the fixed-length portion of the 998335640Shselasky * IDB. 999335640Shselasky */ 1000335640Shselasky idbp = get_from_block_data(&cursor, sizeof(*idbp), 1001335640Shselasky errbuf); 1002335640Shselasky if (idbp == NULL) 1003335640Shselasky goto fail; /* error */ 1004335640Shselasky 1005335640Shselasky /* 1006335640Shselasky * Byte-swap it if necessary. 1007335640Shselasky */ 1008335640Shselasky if (p->swapped) { 1009335640Shselasky idbp->linktype = SWAPSHORT(idbp->linktype); 1010335640Shselasky idbp->snaplen = SWAPLONG(idbp->snaplen); 1011335640Shselasky } 1012335640Shselasky 1013335640Shselasky /* 1014335640Shselasky * Try to add this interface. 1015335640Shselasky */ 1016335640Shselasky if (!add_interface(p, &cursor, errbuf)) 1017335640Shselasky goto fail; 1018335640Shselasky 1019335640Shselasky goto done; 1020335640Shselasky 1021335640Shselasky case BT_EPB: 1022335640Shselasky case BT_SPB: 1023335640Shselasky case BT_PB: 1024335640Shselasky /* 1025335640Shselasky * Saw a packet before we saw any IDBs. That's 1026335640Shselasky * not valid, as we don't know what link-layer 1027335640Shselasky * encapsulation the packet has. 1028335640Shselasky */ 1029335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 1030335640Shselasky "the capture file has a packet block before any Interface Description Blocks"); 1031335640Shselasky goto fail; 1032335640Shselasky 1033335640Shselasky default: 1034335640Shselasky /* 1035335640Shselasky * Just ignore it. 1036335640Shselasky */ 1037335640Shselasky break; 1038335640Shselasky } 1039335640Shselasky } 1040335640Shselasky 1041335640Shselaskydone: 1042335640Shselasky p->tzoff = 0; /* XXX - not used in pcap */ 1043335640Shselasky p->linktype = linktype_to_dlt(idbp->linktype); 1044356341Scy p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen); 1045335640Shselasky p->linktype_ext = 0; 1046335640Shselasky 1047335640Shselasky /* 1048335640Shselasky * If the maximum block size for a packet with the maximum 1049335640Shselasky * snapshot length for this DLT_ is bigger than the current 1050335640Shselasky * maximum block size, increase the maximum. 1051335640Shselasky */ 1052356341Scy if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize) 1053356341Scy ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)); 1054335640Shselasky 1055335640Shselasky p->next_packet_op = pcap_ng_next_packet; 1056335640Shselasky p->cleanup_op = pcap_ng_cleanup; 1057335640Shselasky 1058335640Shselasky return (p); 1059335640Shselasky 1060335640Shselaskyfail: 1061335640Shselasky free(ps->ifaces); 1062335640Shselasky free(p->buffer); 1063335640Shselasky free(p); 1064335640Shselasky *err = 1; 1065335640Shselasky return (NULL); 1066335640Shselasky} 1067335640Shselasky 1068335640Shselaskystatic void 1069335640Shselaskypcap_ng_cleanup(pcap_t *p) 1070335640Shselasky{ 1071335640Shselasky struct pcap_ng_sf *ps = p->priv; 1072335640Shselasky 1073335640Shselasky free(ps->ifaces); 1074335640Shselasky sf_cleanup(p); 1075335640Shselasky} 1076335640Shselasky 1077335640Shselasky/* 1078335640Shselasky * Read and return the next packet from the savefile. Return the header 1079335640Shselasky * in hdr and a pointer to the contents in data. Return 0 on success, 1 1080335640Shselasky * if there were no more packets, and -1 on an error. 1081335640Shselasky */ 1082335640Shselaskystatic int 1083335640Shselaskypcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) 1084335640Shselasky{ 1085335640Shselasky struct pcap_ng_sf *ps = p->priv; 1086335640Shselasky struct block_cursor cursor; 1087335640Shselasky int status; 1088335640Shselasky struct enhanced_packet_block *epbp; 1089335640Shselasky struct simple_packet_block *spbp; 1090335640Shselasky struct packet_block *pbp; 1091335640Shselasky bpf_u_int32 interface_id = 0xFFFFFFFF; 1092335640Shselasky struct interface_description_block *idbp; 1093335640Shselasky struct section_header_block *shbp; 1094335640Shselasky FILE *fp = p->rfile; 1095335640Shselasky uint64_t t, sec, frac; 1096335640Shselasky 1097335640Shselasky /* 1098335640Shselasky * Look for an Enhanced Packet Block, a Simple Packet Block, 1099335640Shselasky * or a Packet Block. 1100335640Shselasky */ 1101335640Shselasky for (;;) { 1102335640Shselasky /* 1103335640Shselasky * Read the block type and length; those are common 1104335640Shselasky * to all blocks. 1105335640Shselasky */ 1106335640Shselasky status = read_block(fp, p, &cursor, p->errbuf); 1107335640Shselasky if (status == 0) 1108335640Shselasky return (1); /* EOF */ 1109335640Shselasky if (status == -1) 1110335640Shselasky return (-1); /* error */ 1111335640Shselasky switch (cursor.block_type) { 1112335640Shselasky 1113335640Shselasky case BT_EPB: 1114335640Shselasky /* 1115335640Shselasky * Get a pointer to the fixed-length portion of the 1116335640Shselasky * EPB. 1117335640Shselasky */ 1118335640Shselasky epbp = get_from_block_data(&cursor, sizeof(*epbp), 1119335640Shselasky p->errbuf); 1120335640Shselasky if (epbp == NULL) 1121335640Shselasky return (-1); /* error */ 1122335640Shselasky 1123335640Shselasky /* 1124335640Shselasky * Byte-swap it if necessary. 1125335640Shselasky */ 1126335640Shselasky if (p->swapped) { 1127335640Shselasky /* these were written in opposite byte order */ 1128335640Shselasky interface_id = SWAPLONG(epbp->interface_id); 1129335640Shselasky hdr->caplen = SWAPLONG(epbp->caplen); 1130335640Shselasky hdr->len = SWAPLONG(epbp->len); 1131335640Shselasky t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 | 1132335640Shselasky SWAPLONG(epbp->timestamp_low); 1133335640Shselasky } else { 1134335640Shselasky interface_id = epbp->interface_id; 1135335640Shselasky hdr->caplen = epbp->caplen; 1136335640Shselasky hdr->len = epbp->len; 1137335640Shselasky t = ((uint64_t)epbp->timestamp_high) << 32 | 1138335640Shselasky epbp->timestamp_low; 1139335640Shselasky } 1140335640Shselasky goto found; 1141335640Shselasky 1142335640Shselasky case BT_SPB: 1143335640Shselasky /* 1144335640Shselasky * Get a pointer to the fixed-length portion of the 1145335640Shselasky * SPB. 1146335640Shselasky */ 1147335640Shselasky spbp = get_from_block_data(&cursor, sizeof(*spbp), 1148335640Shselasky p->errbuf); 1149335640Shselasky if (spbp == NULL) 1150335640Shselasky return (-1); /* error */ 1151335640Shselasky 1152335640Shselasky /* 1153335640Shselasky * SPB packets are assumed to have arrived on 1154335640Shselasky * the first interface. 1155335640Shselasky */ 1156335640Shselasky interface_id = 0; 1157335640Shselasky 1158335640Shselasky /* 1159335640Shselasky * Byte-swap it if necessary. 1160335640Shselasky */ 1161335640Shselasky if (p->swapped) { 1162335640Shselasky /* these were written in opposite byte order */ 1163335640Shselasky hdr->len = SWAPLONG(spbp->len); 1164335640Shselasky } else 1165335640Shselasky hdr->len = spbp->len; 1166335640Shselasky 1167335640Shselasky /* 1168335640Shselasky * The SPB doesn't give the captured length; 1169335640Shselasky * it's the minimum of the snapshot length 1170335640Shselasky * and the packet length. 1171335640Shselasky */ 1172335640Shselasky hdr->caplen = hdr->len; 1173335640Shselasky if (hdr->caplen > (bpf_u_int32)p->snapshot) 1174335640Shselasky hdr->caplen = p->snapshot; 1175335640Shselasky t = 0; /* no time stamps */ 1176335640Shselasky goto found; 1177335640Shselasky 1178335640Shselasky case BT_PB: 1179335640Shselasky /* 1180335640Shselasky * Get a pointer to the fixed-length portion of the 1181335640Shselasky * PB. 1182335640Shselasky */ 1183335640Shselasky pbp = get_from_block_data(&cursor, sizeof(*pbp), 1184335640Shselasky p->errbuf); 1185335640Shselasky if (pbp == NULL) 1186335640Shselasky return (-1); /* error */ 1187335640Shselasky 1188335640Shselasky /* 1189335640Shselasky * Byte-swap it if necessary. 1190335640Shselasky */ 1191335640Shselasky if (p->swapped) { 1192335640Shselasky /* these were written in opposite byte order */ 1193335640Shselasky interface_id = SWAPSHORT(pbp->interface_id); 1194335640Shselasky hdr->caplen = SWAPLONG(pbp->caplen); 1195335640Shselasky hdr->len = SWAPLONG(pbp->len); 1196335640Shselasky t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 | 1197335640Shselasky SWAPLONG(pbp->timestamp_low); 1198335640Shselasky } else { 1199335640Shselasky interface_id = pbp->interface_id; 1200335640Shselasky hdr->caplen = pbp->caplen; 1201335640Shselasky hdr->len = pbp->len; 1202335640Shselasky t = ((uint64_t)pbp->timestamp_high) << 32 | 1203335640Shselasky pbp->timestamp_low; 1204335640Shselasky } 1205335640Shselasky goto found; 1206335640Shselasky 1207335640Shselasky case BT_IDB: 1208335640Shselasky /* 1209335640Shselasky * Interface Description Block. Get a pointer 1210335640Shselasky * to its fixed-length portion. 1211335640Shselasky */ 1212335640Shselasky idbp = get_from_block_data(&cursor, sizeof(*idbp), 1213335640Shselasky p->errbuf); 1214335640Shselasky if (idbp == NULL) 1215335640Shselasky return (-1); /* error */ 1216335640Shselasky 1217335640Shselasky /* 1218335640Shselasky * Byte-swap it if necessary. 1219335640Shselasky */ 1220335640Shselasky if (p->swapped) { 1221335640Shselasky idbp->linktype = SWAPSHORT(idbp->linktype); 1222335640Shselasky idbp->snaplen = SWAPLONG(idbp->snaplen); 1223335640Shselasky } 1224335640Shselasky 1225335640Shselasky /* 1226335640Shselasky * If the link-layer type or snapshot length 1227335640Shselasky * differ from the ones for the first IDB we 1228335640Shselasky * saw, quit. 1229335640Shselasky * 1230335640Shselasky * XXX - just discard packets from those 1231335640Shselasky * interfaces? 1232335640Shselasky */ 1233335640Shselasky if (p->linktype != idbp->linktype) { 1234335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1235335640Shselasky "an interface has a type %u different from the type of the first interface", 1236335640Shselasky idbp->linktype); 1237335640Shselasky return (-1); 1238335640Shselasky } 1239356341Scy 1240356341Scy /* 1241356341Scy * Check against the *adjusted* value of this IDB's 1242356341Scy * snapshot length. 1243356341Scy */ 1244356341Scy if ((bpf_u_int32)p->snapshot != 1245356341Scy pcap_adjust_snapshot(p->linktype, idbp->snaplen)) { 1246335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1247335640Shselasky "an interface has a snapshot length %u different from the type of the first interface", 1248335640Shselasky idbp->snaplen); 1249335640Shselasky return (-1); 1250335640Shselasky } 1251335640Shselasky 1252335640Shselasky /* 1253335640Shselasky * Try to add this interface. 1254335640Shselasky */ 1255335640Shselasky if (!add_interface(p, &cursor, p->errbuf)) 1256335640Shselasky return (-1); 1257335640Shselasky break; 1258335640Shselasky 1259335640Shselasky case BT_SHB: 1260335640Shselasky /* 1261335640Shselasky * Section Header Block. Get a pointer 1262335640Shselasky * to its fixed-length portion. 1263335640Shselasky */ 1264335640Shselasky shbp = get_from_block_data(&cursor, sizeof(*shbp), 1265335640Shselasky p->errbuf); 1266335640Shselasky if (shbp == NULL) 1267335640Shselasky return (-1); /* error */ 1268335640Shselasky 1269335640Shselasky /* 1270335640Shselasky * Assume the byte order of this section is 1271335640Shselasky * the same as that of the previous section. 1272335640Shselasky * We'll check for that later. 1273335640Shselasky */ 1274335640Shselasky if (p->swapped) { 1275335640Shselasky shbp->byte_order_magic = 1276335640Shselasky SWAPLONG(shbp->byte_order_magic); 1277335640Shselasky shbp->major_version = 1278335640Shselasky SWAPSHORT(shbp->major_version); 1279335640Shselasky } 1280335640Shselasky 1281335640Shselasky /* 1282335640Shselasky * Make sure the byte order doesn't change; 1283335640Shselasky * pcap_is_swapped() shouldn't change its 1284335640Shselasky * return value in the middle of reading a capture. 1285335640Shselasky */ 1286335640Shselasky switch (shbp->byte_order_magic) { 1287335640Shselasky 1288335640Shselasky case BYTE_ORDER_MAGIC: 1289335640Shselasky /* 1290335640Shselasky * OK. 1291335640Shselasky */ 1292335640Shselasky break; 1293335640Shselasky 1294335640Shselasky case SWAPLONG(BYTE_ORDER_MAGIC): 1295335640Shselasky /* 1296335640Shselasky * Byte order changes. 1297335640Shselasky */ 1298335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1299335640Shselasky "the file has sections with different byte orders"); 1300335640Shselasky return (-1); 1301335640Shselasky 1302335640Shselasky default: 1303335640Shselasky /* 1304335640Shselasky * Not a valid SHB. 1305335640Shselasky */ 1306335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1307335640Shselasky "the file has a section with a bad byte order magic field"); 1308335640Shselasky return (-1); 1309335640Shselasky } 1310335640Shselasky 1311335640Shselasky /* 1312335640Shselasky * Make sure the major version is the version 1313335640Shselasky * we handle. 1314335640Shselasky */ 1315335640Shselasky if (shbp->major_version != PCAP_NG_VERSION_MAJOR) { 1316335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1317335640Shselasky "unknown pcapng savefile major version number %u", 1318335640Shselasky shbp->major_version); 1319335640Shselasky return (-1); 1320335640Shselasky } 1321335640Shselasky 1322335640Shselasky /* 1323335640Shselasky * Reset the interface count; this section should 1324335640Shselasky * have its own set of IDBs. If any of them 1325335640Shselasky * don't have the same interface type, snapshot 1326335640Shselasky * length, or resolution as the first interface 1327335640Shselasky * we saw, we'll fail. (And if we don't see 1328335640Shselasky * any IDBs, we'll fail when we see a packet 1329335640Shselasky * block.) 1330335640Shselasky */ 1331335640Shselasky ps->ifcount = 0; 1332335640Shselasky break; 1333335640Shselasky 1334335640Shselasky default: 1335335640Shselasky /* 1336335640Shselasky * Not a packet block, IDB, or SHB; ignore it. 1337335640Shselasky */ 1338335640Shselasky break; 1339335640Shselasky } 1340335640Shselasky } 1341335640Shselasky 1342335640Shselaskyfound: 1343335640Shselasky /* 1344335640Shselasky * Is the interface ID an interface we know? 1345335640Shselasky */ 1346335640Shselasky if (interface_id >= ps->ifcount) { 1347335640Shselasky /* 1348335640Shselasky * Yes. Fail. 1349335640Shselasky */ 1350335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1351335640Shselasky "a packet arrived on interface %u, but there's no Interface Description Block for that interface", 1352335640Shselasky interface_id); 1353335640Shselasky return (-1); 1354335640Shselasky } 1355335640Shselasky 1356335640Shselasky if (hdr->caplen > (bpf_u_int32)p->snapshot) { 1357335640Shselasky pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1358335640Shselasky "invalid packet capture length %u, bigger than " 1359335640Shselasky "snaplen of %d", hdr->caplen, p->snapshot); 1360335640Shselasky return (-1); 1361335640Shselasky } 1362335640Shselasky 1363335640Shselasky /* 1364335640Shselasky * Convert the time stamp to seconds and fractions of a second, 1365335640Shselasky * with the fractions being in units of the file-supplied resolution. 1366335640Shselasky */ 1367335640Shselasky sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset; 1368335640Shselasky frac = t % ps->ifaces[interface_id].tsresol; 1369335640Shselasky 1370335640Shselasky /* 1371335640Shselasky * Convert the fractions from units of the file-supplied resolution 1372335640Shselasky * to units of the user-requested resolution. 1373335640Shselasky */ 1374335640Shselasky switch (ps->ifaces[interface_id].scale_type) { 1375335640Shselasky 1376335640Shselasky case PASS_THROUGH: 1377335640Shselasky /* 1378335640Shselasky * The interface resolution is what the user wants, 1379335640Shselasky * so we're done. 1380335640Shselasky */ 1381335640Shselasky break; 1382335640Shselasky 1383335640Shselasky case SCALE_UP_DEC: 1384335640Shselasky /* 1385335640Shselasky * The interface resolution is less than what the user 1386335640Shselasky * wants; scale the fractional part up to the units of 1387335640Shselasky * the resolution the user requested by multiplying by 1388335640Shselasky * the quotient of the user-requested resolution and the 1389335640Shselasky * file-supplied resolution. 1390335640Shselasky * 1391335640Shselasky * Those resolutions are both powers of 10, and the user- 1392335640Shselasky * requested resolution is greater than the file-supplied 1393335640Shselasky * resolution, so the quotient in question is an integer. 1394335640Shselasky * We've calculated that quotient already, so we just 1395335640Shselasky * multiply by it. 1396335640Shselasky */ 1397335640Shselasky frac *= ps->ifaces[interface_id].scale_factor; 1398335640Shselasky break; 1399335640Shselasky 1400335640Shselasky case SCALE_UP_BIN: 1401335640Shselasky /* 1402335640Shselasky * The interface resolution is less than what the user 1403335640Shselasky * wants; scale the fractional part up to the units of 1404335640Shselasky * the resolution the user requested by multiplying by 1405335640Shselasky * the quotient of the user-requested resolution and the 1406335640Shselasky * file-supplied resolution. 1407335640Shselasky * 1408335640Shselasky * The file-supplied resolution is a power of 2, so the 1409335640Shselasky * quotient is not an integer, so, in order to do this 1410335640Shselasky * entirely with integer arithmetic, we multiply by the 1411335640Shselasky * user-requested resolution and divide by the file- 1412335640Shselasky * supplied resolution. 1413335640Shselasky * 1414335640Shselasky * XXX - Is there something clever we could do here, 1415335640Shselasky * given that we know that the file-supplied resolution 1416335640Shselasky * is a power of 2? Doing a multiplication followed by 1417335640Shselasky * a division runs the risk of overflowing, and involves 1418335640Shselasky * two non-simple arithmetic operations. 1419335640Shselasky */ 1420335640Shselasky frac *= ps->user_tsresol; 1421335640Shselasky frac /= ps->ifaces[interface_id].tsresol; 1422335640Shselasky break; 1423335640Shselasky 1424335640Shselasky case SCALE_DOWN_DEC: 1425335640Shselasky /* 1426335640Shselasky * The interface resolution is greater than what the user 1427335640Shselasky * wants; scale the fractional part up to the units of 1428335640Shselasky * the resolution the user requested by multiplying by 1429335640Shselasky * the quotient of the user-requested resolution and the 1430335640Shselasky * file-supplied resolution. 1431335640Shselasky * 1432335640Shselasky * Those resolutions are both powers of 10, and the user- 1433335640Shselasky * requested resolution is less than the file-supplied 1434335640Shselasky * resolution, so the quotient in question isn't an 1435335640Shselasky * integer, but its reciprocal is, and we can just divide 1436335640Shselasky * by the reciprocal of the quotient. We've calculated 1437335640Shselasky * the reciprocal of that quotient already, so we must 1438335640Shselasky * divide by it. 1439335640Shselasky */ 1440335640Shselasky frac /= ps->ifaces[interface_id].scale_factor; 1441335640Shselasky break; 1442335640Shselasky 1443335640Shselasky 1444335640Shselasky case SCALE_DOWN_BIN: 1445335640Shselasky /* 1446335640Shselasky * The interface resolution is greater than what the user 1447335640Shselasky * wants; convert the fractional part to units of the 1448335640Shselasky * resolution the user requested by multiplying by the 1449335640Shselasky * quotient of the user-requested resolution and the 1450335640Shselasky * file-supplied resolution. We do that by multiplying 1451335640Shselasky * by the user-requested resolution and dividing by the 1452335640Shselasky * file-supplied resolution, as the quotient might not 1453335640Shselasky * fit in an integer. 1454335640Shselasky * 1455335640Shselasky * The file-supplied resolution is a power of 2, so the 1456335640Shselasky * quotient is not an integer, and neither is its 1457335640Shselasky * reciprocal, so, in order to do this entirely with 1458335640Shselasky * integer arithmetic, we multiply by the user-requested 1459335640Shselasky * resolution and divide by the file-supplied resolution. 1460335640Shselasky * 1461335640Shselasky * XXX - Is there something clever we could do here, 1462335640Shselasky * given that we know that the file-supplied resolution 1463335640Shselasky * is a power of 2? Doing a multiplication followed by 1464335640Shselasky * a division runs the risk of overflowing, and involves 1465335640Shselasky * two non-simple arithmetic operations. 1466335640Shselasky */ 1467335640Shselasky frac *= ps->user_tsresol; 1468335640Shselasky frac /= ps->ifaces[interface_id].tsresol; 1469335640Shselasky break; 1470335640Shselasky } 1471335640Shselasky#ifdef _WIN32 1472335640Shselasky /* 1473335640Shselasky * tv_sec and tv_used in the Windows struct timeval are both 1474335640Shselasky * longs. 1475335640Shselasky */ 1476335640Shselasky hdr->ts.tv_sec = (long)sec; 1477335640Shselasky hdr->ts.tv_usec = (long)frac; 1478335640Shselasky#else 1479335640Shselasky /* 1480335640Shselasky * tv_sec in the UN*X struct timeval is a time_t; tv_usec is 1481335640Shselasky * suseconds_t in UN*Xes that work the way the current Single 1482335640Shselasky * UNIX Standard specify - but not all older UN*Xes necessarily 1483335640Shselasky * support that type, so just cast to int. 1484335640Shselasky */ 1485335640Shselasky hdr->ts.tv_sec = (time_t)sec; 1486335640Shselasky hdr->ts.tv_usec = (int)frac; 1487335640Shselasky#endif 1488335640Shselasky 1489335640Shselasky /* 1490335640Shselasky * Get a pointer to the packet data. 1491335640Shselasky */ 1492335640Shselasky *data = get_from_block_data(&cursor, hdr->caplen, p->errbuf); 1493335640Shselasky if (*data == NULL) 1494335640Shselasky return (-1); 1495335640Shselasky 1496335640Shselasky if (p->swapped) 1497335640Shselasky swap_pseudo_headers(p->linktype, hdr, *data); 1498335640Shselasky 1499335640Shselasky return (0); 1500335640Shselasky} 1501