1 1.12 christos /* $NetBSD: sf-pcap.c,v 1.12 2026/03/18 23:43:21 christos Exp $ */ 2 1.3 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 1993, 1994, 1995, 1996, 1997 5 1.1 christos * The Regents of the University of California. All rights reserved. 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that: (1) source code distributions 9 1.1 christos * retain the above copyright notice and this paragraph in its entirety, (2) 10 1.1 christos * distributions including binary code include the above copyright notice and 11 1.1 christos * this paragraph in its entirety in the documentation or other materials 12 1.1 christos * provided with the distribution, and (3) all advertising materials mentioning 13 1.1 christos * features or use of this software display the following acknowledgement: 14 1.1 christos * ``This product includes software developed by the University of California, 15 1.1 christos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 1.1 christos * the University nor the names of its contributors may be used to endorse 17 1.1 christos * or promote products derived from this software without specific prior 18 1.1 christos * written permission. 19 1.1 christos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 1.1 christos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 1.1 christos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 1.1 christos * 23 1.1 christos * sf-pcap.c - libpcap-file-format-specific code from savefile.c 24 1.1 christos * Extraction/creation by Jeffrey Mogul, DECWRL 25 1.1 christos * Modified by Steve McCanne, LBL. 26 1.1 christos * 27 1.1 christos * Used to save the received packet headers, after filtering, to 28 1.1 christos * a file, and then read them later. 29 1.1 christos * The first record in the file contains saved values for the machine 30 1.1 christos * dependent values so we can print the dump file on any architecture. 31 1.1 christos */ 32 1.1 christos 33 1.5 christos #include <sys/cdefs.h> 34 1.12 christos __RCSID("$NetBSD: sf-pcap.c,v 1.12 2026/03/18 23:43:21 christos Exp $"); 35 1.5 christos 36 1.8 christos #include <config.h> 37 1.1 christos 38 1.8 christos #include <pcap-types.h> 39 1.7 christos #ifdef _WIN32 40 1.8 christos #include <io.h> 41 1.8 christos #include <fcntl.h> 42 1.7 christos #endif /* _WIN32 */ 43 1.1 christos 44 1.1 christos #include <errno.h> 45 1.1 christos #include <memory.h> 46 1.1 christos #include <stdio.h> 47 1.1 christos #include <stdlib.h> 48 1.1 christos #include <string.h> 49 1.9 christos #include <limits.h> /* for INT_MAX */ 50 1.1 christos 51 1.1 christos #include "pcap-int.h" 52 1.10 christos #include "pcap-util.h" 53 1.1 christos 54 1.1 christos #include "pcap-common.h" 55 1.1 christos 56 1.1 christos #ifdef HAVE_OS_PROTO_H 57 1.1 christos #include "os-proto.h" 58 1.1 christos #endif 59 1.1 christos 60 1.1 christos #include "sf-pcap.h" 61 1.1 christos 62 1.1 christos /* 63 1.1 christos * Setting O_BINARY on DOS/Windows is a bit tricky 64 1.1 christos */ 65 1.7 christos #if defined(_WIN32) 66 1.1 christos #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY) 67 1.1 christos #elif defined(MSDOS) 68 1.1 christos #if defined(__HIGHC__) 69 1.1 christos #define SET_BINMODE(f) setmode(f, O_BINARY) 70 1.1 christos #else 71 1.1 christos #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 72 1.1 christos #endif 73 1.1 christos #endif 74 1.1 christos 75 1.1 christos /* 76 1.1 christos * Standard libpcap format. 77 1.10 christos * 78 1.10 christos * The same value is used in the rpcap protocol as an indication of 79 1.10 christos * the server byte order, to let the client know whether it needs to 80 1.10 christos * byte-swap some host-byte-order metadata. 81 1.1 christos */ 82 1.1 christos #define TCPDUMP_MAGIC 0xa1b2c3d4 83 1.1 christos 84 1.1 christos /* 85 1.1 christos * Alexey Kuznetzov's modified libpcap format. 86 1.1 christos */ 87 1.1 christos #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34 88 1.1 christos 89 1.1 christos /* 90 1.1 christos * Reserved for Francisco Mesquita <francisco.mesquita (at) radiomovel.pt> 91 1.1 christos * for another modified format. 92 1.1 christos */ 93 1.1 christos #define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd 94 1.1 christos 95 1.1 christos /* 96 1.11 christos * Navtel Communications' format, with nanosecond timestamps, 97 1.1 christos * as per a request from Dumas Hwang <dumas.hwang (at) navtelcom.com>. 98 1.1 christos */ 99 1.1 christos #define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d 100 1.1 christos 101 1.1 christos /* 102 1.1 christos * Normal libpcap format, except for seconds/nanoseconds timestamps, 103 1.1 christos * as per a request by Ulf Lamping <ulf.lamping (at) web.de> 104 1.1 christos */ 105 1.1 christos #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d 106 1.1 christos 107 1.1 christos /* 108 1.11 christos * This is a timeval as stored in a savefile. 109 1.11 christos * It has to use the same types everywhere, independent of the actual 110 1.11 christos * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some 111 1.11 christos * platforms and 64-bit tv_sec values on other platforms, and writing 112 1.11 christos * out native `struct timeval' values would mean files could only be 113 1.11 christos * read on systems with the same tv_sec size as the system on which 114 1.11 christos * the file was written. 115 1.11 christos * 116 1.12 christos * The fields are unsigned, as that's what the pcap draft specification 117 1.11 christos * says they are. (That gives pcap a 68-year Y2.038K reprieve, although 118 1.11 christos * in 2106 it runs out for good. pcapng doesn't have that problem, 119 1.11 christos * unless you pick a *really* high time stamp precision.) 120 1.11 christos */ 121 1.11 christos 122 1.11 christos struct pcap_timeval { 123 1.11 christos bpf_u_int32 tv_sec; /* seconds */ 124 1.11 christos bpf_u_int32 tv_usec; /* microseconds */ 125 1.11 christos }; 126 1.11 christos 127 1.11 christos /* 128 1.11 christos * This is a `pcap_pkthdr' as actually stored in a savefile. 129 1.11 christos * 130 1.11 christos * Do not change the format of this structure, in any way (this includes 131 1.11 christos * changes that only affect the length of fields in this structure), 132 1.11 christos * and do not make the time stamp anything other than seconds and 133 1.11 christos * microseconds (e.g., seconds and nanoseconds). Instead: 134 1.11 christos * 135 1.11 christos * introduce a new structure for the new format; 136 1.11 christos * 137 1.11 christos * send mail to "tcpdump-workers (at) lists.tcpdump.org", requesting 138 1.11 christos * a new magic number for your new capture file format, and, when 139 1.11 christos * you get the new magic number, put it in "savefile.c"; 140 1.11 christos * 141 1.11 christos * use that magic number for save files with the changed record 142 1.11 christos * header; 143 1.11 christos * 144 1.11 christos * make the code in "savefile.c" capable of reading files with 145 1.11 christos * the old record header as well as files with the new record header 146 1.11 christos * (using the magic number to determine the header format). 147 1.11 christos * 148 1.11 christos * Then supply the changes by forking the branch at 149 1.11 christos * 150 1.11 christos * https://github.com/the-tcpdump-group/libpcap/tree/master 151 1.1 christos * 152 1.11 christos * and issuing a pull request, so that future versions of libpcap and 153 1.11 christos * programs that use it (such as tcpdump) will be able to read your new 154 1.11 christos * capture file format. 155 1.11 christos */ 156 1.11 christos 157 1.11 christos struct pcap_sf_pkthdr { 158 1.11 christos struct pcap_timeval ts; /* time stamp */ 159 1.11 christos bpf_u_int32 caplen; /* length of portion present */ 160 1.11 christos bpf_u_int32 len; /* length of this packet (off wire) */ 161 1.11 christos }; 162 1.11 christos 163 1.11 christos /* 164 1.11 christos * How a `pcap_pkthdr' is actually stored in savefiles written 165 1.11 christos * by some patched versions of libpcap (e.g. the ones in Red 166 1.11 christos * Hat Linux 6.1 and 6.2). 167 1.1 christos * 168 1.11 christos * Do not change the format of this structure, in any way (this includes 169 1.11 christos * changes that only affect the length of fields in this structure). 170 1.11 christos * Instead, introduce a new structure, as per the above. 171 1.1 christos */ 172 1.11 christos 173 1.11 christos struct pcap_sf_patched_pkthdr { 174 1.11 christos struct pcap_timeval ts; /* time stamp */ 175 1.11 christos bpf_u_int32 caplen; /* length of portion present */ 176 1.11 christos bpf_u_int32 len; /* length of this packet (off wire) */ 177 1.11 christos int index; 178 1.11 christos unsigned short protocol; 179 1.11 christos unsigned char pkt_type; 180 1.11 christos }; 181 1.1 christos 182 1.1 christos static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap); 183 1.1 christos 184 1.9 christos #ifdef _WIN32 185 1.9 christos /* 186 1.9 christos * This isn't exported on Windows, because it would only work if both 187 1.9 christos * libpcap and the code using it were using the same C runtime; otherwise they 188 1.9 christos * would be using different definitions of a FILE structure. 189 1.9 christos * 190 1.9 christos * Instead we define this as a macro in pcap/pcap.h that wraps the hopen 191 1.9 christos * version that we do export, passing it a raw OS HANDLE, as defined by the 192 1.9 christos * Win32 / Win64 ABI, obtained from the _fileno() and _get_osfhandle() 193 1.9 christos * functions of the appropriate CRT. 194 1.9 christos */ 195 1.9 christos static pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *f); 196 1.9 christos #endif /* _WIN32 */ 197 1.9 christos 198 1.1 christos /* 199 1.4 christos * Private data for reading pcap savefiles. 200 1.4 christos */ 201 1.4 christos typedef enum { 202 1.4 christos NOT_SWAPPED, 203 1.4 christos SWAPPED, 204 1.4 christos MAYBE_SWAPPED 205 1.4 christos } swapped_type_t; 206 1.4 christos 207 1.4 christos typedef enum { 208 1.4 christos PASS_THROUGH, 209 1.4 christos SCALE_UP, 210 1.4 christos SCALE_DOWN 211 1.4 christos } tstamp_scale_type_t; 212 1.4 christos 213 1.4 christos struct pcap_sf { 214 1.4 christos size_t hdrsize; 215 1.4 christos swapped_type_t lengths_swapped; 216 1.4 christos tstamp_scale_type_t scale_type; 217 1.4 christos }; 218 1.4 christos 219 1.4 christos /* 220 1.1 christos * Check whether this is a pcap savefile and, if it is, extract the 221 1.1 christos * relevant information from the header. 222 1.1 christos */ 223 1.4 christos pcap_t * 224 1.9 christos pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf, 225 1.7 christos int *err) 226 1.1 christos { 227 1.9 christos bpf_u_int32 magic_int; 228 1.1 christos struct pcap_file_header hdr; 229 1.1 christos size_t amt_read; 230 1.4 christos pcap_t *p; 231 1.4 christos int swapped = 0; 232 1.4 christos struct pcap_sf *ps; 233 1.4 christos 234 1.4 christos /* 235 1.4 christos * Assume no read errors. 236 1.4 christos */ 237 1.4 christos *err = 0; 238 1.1 christos 239 1.1 christos /* 240 1.1 christos * Check whether the first 4 bytes of the file are the magic 241 1.1 christos * number for a pcap savefile, or for a byte-swapped pcap 242 1.1 christos * savefile. 243 1.1 christos */ 244 1.9 christos memcpy(&magic_int, magic, sizeof(magic_int)); 245 1.9 christos if (magic_int != TCPDUMP_MAGIC && 246 1.9 christos magic_int != KUZNETZOV_TCPDUMP_MAGIC && 247 1.9 christos magic_int != NSEC_TCPDUMP_MAGIC) { 248 1.9 christos magic_int = SWAPLONG(magic_int); 249 1.9 christos if (magic_int != TCPDUMP_MAGIC && 250 1.9 christos magic_int != KUZNETZOV_TCPDUMP_MAGIC && 251 1.9 christos magic_int != NSEC_TCPDUMP_MAGIC) 252 1.4 christos return (NULL); /* nope */ 253 1.4 christos swapped = 1; 254 1.1 christos } 255 1.1 christos 256 1.1 christos /* 257 1.1 christos * They are. Put the magic number in the header, and read 258 1.1 christos * the rest of the header. 259 1.1 christos */ 260 1.9 christos hdr.magic = magic_int; 261 1.1 christos amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1, 262 1.1 christos sizeof(hdr) - sizeof(hdr.magic), fp); 263 1.1 christos if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) { 264 1.1 christos if (ferror(fp)) { 265 1.11 christos pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 266 1.8 christos errno, "error reading dump file"); 267 1.1 christos } else { 268 1.10 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, 269 1.10 christos "truncated dump file; tried to read %zu file header bytes, only got %zu", 270 1.9 christos sizeof(hdr), amt_read); 271 1.1 christos } 272 1.4 christos *err = 1; 273 1.4 christos return (NULL); 274 1.1 christos } 275 1.1 christos 276 1.1 christos /* 277 1.1 christos * If it's a byte-swapped capture file, byte-swap the header. 278 1.1 christos */ 279 1.4 christos if (swapped) { 280 1.1 christos hdr.version_major = SWAPSHORT(hdr.version_major); 281 1.1 christos hdr.version_minor = SWAPSHORT(hdr.version_minor); 282 1.1 christos hdr.thiszone = SWAPLONG(hdr.thiszone); 283 1.1 christos hdr.sigfigs = SWAPLONG(hdr.sigfigs); 284 1.1 christos hdr.snaplen = SWAPLONG(hdr.snaplen); 285 1.1 christos hdr.linktype = SWAPLONG(hdr.linktype); 286 1.1 christos } 287 1.1 christos 288 1.1 christos if (hdr.version_major < PCAP_VERSION_MAJOR) { 289 1.10 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, 290 1.1 christos "archaic pcap savefile format"); 291 1.4 christos *err = 1; 292 1.4 christos return (NULL); 293 1.4 christos } 294 1.4 christos 295 1.4 christos /* 296 1.7 christos * currently only versions 2.[0-4] are supported with 297 1.7 christos * the exception of 543.0 for DG/UX tcpdump. 298 1.7 christos */ 299 1.7 christos if (! ((hdr.version_major == PCAP_VERSION_MAJOR && 300 1.7 christos hdr.version_minor <= PCAP_VERSION_MINOR) || 301 1.7 christos (hdr.version_major == 543 && 302 1.7 christos hdr.version_minor == 0))) { 303 1.10 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, 304 1.7 christos "unsupported pcap savefile version %u.%u", 305 1.7 christos hdr.version_major, hdr.version_minor); 306 1.7 christos *err = 1; 307 1.7 christos return NULL; 308 1.7 christos } 309 1.7 christos 310 1.7 christos /* 311 1.11 christos * Check the main reserved field. 312 1.11 christos */ 313 1.11 christos if (LT_RESERVED1(hdr.linktype) != 0) { 314 1.11 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, 315 1.11 christos "savefile linktype reserved field not zero (0x%08x)", 316 1.11 christos LT_RESERVED1(hdr.linktype)); 317 1.11 christos *err = 1; 318 1.11 christos return NULL; 319 1.11 christos } 320 1.11 christos 321 1.11 christos /* 322 1.4 christos * OK, this is a good pcap file. 323 1.4 christos * Allocate a pcap_t for it. 324 1.4 christos */ 325 1.10 christos p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_sf); 326 1.4 christos if (p == NULL) { 327 1.4 christos /* Allocation failed. */ 328 1.4 christos *err = 1; 329 1.4 christos return (NULL); 330 1.1 christos } 331 1.4 christos p->swapped = swapped; 332 1.4 christos p->version_major = hdr.version_major; 333 1.4 christos p->version_minor = hdr.version_minor; 334 1.1 christos p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype)); 335 1.1 christos p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype); 336 1.11 christos p->snapshot = pcapint_adjust_snapshot(p->linktype, hdr.snaplen); 337 1.1 christos 338 1.4 christos p->next_packet_op = pcap_next_packet; 339 1.4 christos 340 1.4 christos ps = p->priv; 341 1.4 christos 342 1.4 christos p->opt.tstamp_precision = precision; 343 1.4 christos 344 1.4 christos /* 345 1.4 christos * Will we need to scale the timestamps to match what the 346 1.4 christos * user wants? 347 1.4 christos */ 348 1.4 christos switch (precision) { 349 1.4 christos 350 1.4 christos case PCAP_TSTAMP_PRECISION_MICRO: 351 1.9 christos if (magic_int == NSEC_TCPDUMP_MAGIC) { 352 1.4 christos /* 353 1.4 christos * The file has nanoseconds, the user 354 1.4 christos * wants microseconds; scale the 355 1.4 christos * precision down. 356 1.4 christos */ 357 1.4 christos ps->scale_type = SCALE_DOWN; 358 1.4 christos } else { 359 1.4 christos /* 360 1.4 christos * The file has microseconds, the 361 1.4 christos * user wants microseconds; nothing to do. 362 1.4 christos */ 363 1.4 christos ps->scale_type = PASS_THROUGH; 364 1.4 christos } 365 1.4 christos break; 366 1.4 christos 367 1.4 christos case PCAP_TSTAMP_PRECISION_NANO: 368 1.9 christos if (magic_int == NSEC_TCPDUMP_MAGIC) { 369 1.4 christos /* 370 1.4 christos * The file has nanoseconds, the 371 1.4 christos * user wants nanoseconds; nothing to do. 372 1.4 christos */ 373 1.4 christos ps->scale_type = PASS_THROUGH; 374 1.4 christos } else { 375 1.4 christos /* 376 1.10 christos * The file has microseconds, the user 377 1.4 christos * wants nanoseconds; scale the 378 1.4 christos * precision up. 379 1.4 christos */ 380 1.4 christos ps->scale_type = SCALE_UP; 381 1.4 christos } 382 1.4 christos break; 383 1.4 christos 384 1.4 christos default: 385 1.10 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, 386 1.4 christos "unknown time stamp resolution %u", precision); 387 1.4 christos free(p); 388 1.4 christos *err = 1; 389 1.4 christos return (NULL); 390 1.4 christos } 391 1.1 christos 392 1.1 christos /* 393 1.1 christos * We interchanged the caplen and len fields at version 2.3, 394 1.1 christos * in order to match the bpf header layout. But unfortunately 395 1.1 christos * some files were written with version 2.3 in their headers 396 1.1 christos * but without the interchanged fields. 397 1.1 christos * 398 1.1 christos * In addition, DG/UX tcpdump writes out files with a version 399 1.1 christos * number of 543.0, and with the caplen and len fields in the 400 1.1 christos * pre-2.3 order. 401 1.1 christos */ 402 1.1 christos switch (hdr.version_major) { 403 1.1 christos 404 1.1 christos case 2: 405 1.1 christos if (hdr.version_minor < 3) 406 1.4 christos ps->lengths_swapped = SWAPPED; 407 1.1 christos else if (hdr.version_minor == 3) 408 1.4 christos ps->lengths_swapped = MAYBE_SWAPPED; 409 1.1 christos else 410 1.4 christos ps->lengths_swapped = NOT_SWAPPED; 411 1.1 christos break; 412 1.1 christos 413 1.1 christos case 543: 414 1.4 christos ps->lengths_swapped = SWAPPED; 415 1.1 christos break; 416 1.1 christos 417 1.1 christos default: 418 1.4 christos ps->lengths_swapped = NOT_SWAPPED; 419 1.1 christos break; 420 1.1 christos } 421 1.1 christos 422 1.9 christos if (magic_int == KUZNETZOV_TCPDUMP_MAGIC) { 423 1.1 christos /* 424 1.1 christos * XXX - the patch that's in some versions of libpcap 425 1.1 christos * changes the packet header but not the magic number, 426 1.1 christos * and some other versions with this magic number have 427 1.1 christos * some extra debugging information in the packet header; 428 1.1 christos * we'd have to use some hacks^H^H^H^H^Hheuristics to 429 1.1 christos * detect those variants. 430 1.1 christos * 431 1.1 christos * Ethereal does that, but it does so by trying to read 432 1.1 christos * the first two packets of the file with each of the 433 1.1 christos * record header formats. That currently means it seeks 434 1.1 christos * backwards and retries the reads, which doesn't work 435 1.1 christos * on pipes. We want to be able to read from a pipe, so 436 1.1 christos * that strategy won't work; we'd have to buffer some 437 1.1 christos * data ourselves and read from that buffer in order to 438 1.1 christos * make that work. 439 1.1 christos */ 440 1.4 christos ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr); 441 1.1 christos 442 1.1 christos if (p->linktype == DLT_EN10MB) { 443 1.1 christos /* 444 1.1 christos * This capture might have been done in raw mode 445 1.1 christos * or cooked mode. 446 1.1 christos * 447 1.1 christos * If it was done in cooked mode, p->snapshot was 448 1.1 christos * passed to recvfrom() as the buffer size, meaning 449 1.1 christos * that the most packet data that would be copied 450 1.1 christos * would be p->snapshot. However, a faked Ethernet 451 1.1 christos * header would then have been added to it, so the 452 1.1 christos * most data that would be in a packet in the file 453 1.1 christos * would be p->snapshot + 14. 454 1.1 christos * 455 1.1 christos * We can't easily tell whether the capture was done 456 1.1 christos * in raw mode or cooked mode, so we'll assume it was 457 1.1 christos * cooked mode, and add 14 to the snapshot length. 458 1.1 christos * That means that, for a raw capture, the snapshot 459 1.1 christos * length will be misleading if you use it to figure 460 1.1 christos * out why a capture doesn't have all the packet data, 461 1.1 christos * but there's not much we can do to avoid that. 462 1.9 christos * 463 1.9 christos * But don't grow the snapshot length past the 464 1.9 christos * maximum value of an int. 465 1.1 christos */ 466 1.9 christos if (p->snapshot <= INT_MAX - 14) 467 1.9 christos p->snapshot += 14; 468 1.9 christos else 469 1.9 christos p->snapshot = INT_MAX; 470 1.1 christos } 471 1.1 christos } else 472 1.4 christos ps->hdrsize = sizeof(struct pcap_sf_pkthdr); 473 1.1 christos 474 1.1 christos /* 475 1.1 christos * Allocate a buffer for the packet data. 476 1.8 christos * Choose the minimum of the file's snapshot length and 2K bytes; 477 1.8 christos * that should be enough for most network packets - we'll grow it 478 1.8 christos * if necessary. That way, we don't allocate a huge chunk of 479 1.8 christos * memory just because there's a huge snapshot length, as the 480 1.8 christos * snapshot length might be larger than the size of the largest 481 1.8 christos * packet. 482 1.1 christos */ 483 1.1 christos p->bufsize = p->snapshot; 484 1.8 christos if (p->bufsize > 2048) 485 1.8 christos p->bufsize = 2048; 486 1.1 christos p->buffer = malloc(p->bufsize); 487 1.1 christos if (p->buffer == NULL) { 488 1.10 christos snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 489 1.4 christos free(p); 490 1.4 christos *err = 1; 491 1.4 christos return (NULL); 492 1.1 christos } 493 1.1 christos 494 1.11 christos p->cleanup_op = pcapint_sf_cleanup; 495 1.4 christos 496 1.4 christos return (p); 497 1.1 christos } 498 1.1 christos 499 1.1 christos /* 500 1.8 christos * Grow the packet buffer to the specified size. 501 1.8 christos */ 502 1.8 christos static int 503 1.8 christos grow_buffer(pcap_t *p, u_int bufsize) 504 1.8 christos { 505 1.8 christos void *bigger_buffer; 506 1.8 christos 507 1.8 christos bigger_buffer = realloc(p->buffer, bufsize); 508 1.8 christos if (bigger_buffer == NULL) { 509 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory"); 510 1.8 christos return (0); 511 1.8 christos } 512 1.8 christos p->buffer = bigger_buffer; 513 1.8 christos p->bufsize = bufsize; 514 1.8 christos return (1); 515 1.8 christos } 516 1.8 christos 517 1.8 christos /* 518 1.1 christos * Read and return the next packet from the savefile. Return the header 519 1.10 christos * in hdr and a pointer to the contents in data. Return 1 on success, 0 520 1.1 christos * if there were no more packets, and -1 on an error. 521 1.1 christos */ 522 1.1 christos static int 523 1.1 christos pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) 524 1.1 christos { 525 1.4 christos struct pcap_sf *ps = p->priv; 526 1.1 christos struct pcap_sf_patched_pkthdr sf_hdr; 527 1.4 christos FILE *fp = p->rfile; 528 1.1 christos size_t amt_read; 529 1.1 christos bpf_u_int32 t; 530 1.1 christos 531 1.1 christos /* 532 1.1 christos * Read the packet header; the structure we use as a buffer 533 1.1 christos * is the longer structure for files generated by the patched 534 1.1 christos * libpcap, but if the file has the magic number for an 535 1.1 christos * unpatched libpcap we only read as many bytes as the regular 536 1.1 christos * header has. 537 1.1 christos */ 538 1.4 christos amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp); 539 1.4 christos if (amt_read != ps->hdrsize) { 540 1.1 christos if (ferror(fp)) { 541 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 542 1.8 christos errno, "error reading dump file"); 543 1.1 christos return (-1); 544 1.1 christos } else { 545 1.1 christos if (amt_read != 0) { 546 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 547 1.10 christos "truncated dump file; tried to read %zu header bytes, only got %zu", 548 1.9 christos ps->hdrsize, amt_read); 549 1.1 christos return (-1); 550 1.1 christos } 551 1.1 christos /* EOF */ 552 1.10 christos return (0); 553 1.1 christos } 554 1.1 christos } 555 1.1 christos 556 1.4 christos if (p->swapped) { 557 1.1 christos /* these were written in opposite byte order */ 558 1.1 christos hdr->caplen = SWAPLONG(sf_hdr.caplen); 559 1.1 christos hdr->len = SWAPLONG(sf_hdr.len); 560 1.1 christos hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec); 561 1.1 christos hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec); 562 1.1 christos } else { 563 1.1 christos hdr->caplen = sf_hdr.caplen; 564 1.1 christos hdr->len = sf_hdr.len; 565 1.1 christos hdr->ts.tv_sec = sf_hdr.ts.tv_sec; 566 1.1 christos hdr->ts.tv_usec = sf_hdr.ts.tv_usec; 567 1.1 christos } 568 1.4 christos 569 1.4 christos switch (ps->scale_type) { 570 1.4 christos 571 1.4 christos case PASS_THROUGH: 572 1.4 christos /* 573 1.4 christos * Just pass the time stamp through. 574 1.4 christos */ 575 1.4 christos break; 576 1.4 christos 577 1.4 christos case SCALE_UP: 578 1.4 christos /* 579 1.4 christos * File has microseconds, user wants nanoseconds; convert 580 1.4 christos * it. 581 1.4 christos */ 582 1.4 christos hdr->ts.tv_usec = hdr->ts.tv_usec * 1000; 583 1.4 christos break; 584 1.4 christos 585 1.4 christos case SCALE_DOWN: 586 1.4 christos /* 587 1.4 christos * File has nanoseconds, user wants microseconds; convert 588 1.4 christos * it. 589 1.4 christos */ 590 1.4 christos hdr->ts.tv_usec = hdr->ts.tv_usec / 1000; 591 1.4 christos break; 592 1.4 christos } 593 1.4 christos 594 1.1 christos /* Swap the caplen and len fields, if necessary. */ 595 1.4 christos switch (ps->lengths_swapped) { 596 1.1 christos 597 1.1 christos case NOT_SWAPPED: 598 1.1 christos break; 599 1.1 christos 600 1.1 christos case MAYBE_SWAPPED: 601 1.1 christos if (hdr->caplen <= hdr->len) { 602 1.1 christos /* 603 1.1 christos * The captured length is <= the actual length, 604 1.1 christos * so presumably they weren't swapped. 605 1.1 christos */ 606 1.1 christos break; 607 1.1 christos } 608 1.1 christos /* FALLTHROUGH */ 609 1.1 christos 610 1.1 christos case SWAPPED: 611 1.1 christos t = hdr->caplen; 612 1.1 christos hdr->caplen = hdr->len; 613 1.1 christos hdr->len = t; 614 1.1 christos break; 615 1.1 christos } 616 1.1 christos 617 1.8 christos /* 618 1.8 christos * Is the packet bigger than we consider sane? 619 1.8 christos */ 620 1.8 christos if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) { 621 1.8 christos /* 622 1.8 christos * Yes. This may be a damaged or fuzzed file. 623 1.8 christos * 624 1.8 christos * Is it bigger than the snapshot length? 625 1.8 christos * (We don't treat that as an error if it's not 626 1.8 christos * bigger than the maximum we consider sane; see 627 1.8 christos * below.) 628 1.8 christos */ 629 1.8 christos if (hdr->caplen > (bpf_u_int32)p->snapshot) { 630 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 631 1.8 christos "invalid packet capture length %u, bigger than " 632 1.8 christos "snaplen of %d", hdr->caplen, p->snapshot); 633 1.8 christos } else { 634 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 635 1.8 christos "invalid packet capture length %u, bigger than " 636 1.8 christos "maximum of %u", hdr->caplen, 637 1.8 christos max_snaplen_for_dlt(p->linktype)); 638 1.8 christos } 639 1.8 christos return (-1); 640 1.8 christos } 641 1.8 christos 642 1.8 christos if (hdr->caplen > (bpf_u_int32)p->snapshot) { 643 1.1 christos /* 644 1.8 christos * The packet is bigger than the snapshot length 645 1.8 christos * for this file. 646 1.8 christos * 647 1.1 christos * This can happen due to Solaris 2.3 systems tripping 648 1.1 christos * over the BUFMOD problem and not setting the snapshot 649 1.8 christos * length correctly in the savefile header. 650 1.8 christos * 651 1.8 christos * libpcap 0.4 and later on Solaris 2.3 should set the 652 1.8 christos * snapshot length correctly in the pcap file header, 653 1.8 christos * even though they don't set a snapshot length in bufmod 654 1.8 christos * (the buggy bufmod chops off the *beginning* of the 655 1.8 christos * packet if a snapshot length is specified); they should 656 1.8 christos * also reduce the captured length, as supplied to the 657 1.8 christos * per-packet callback, to the snapshot length if it's 658 1.8 christos * greater than the snapshot length, so the code using 659 1.8 christos * libpcap should see the packet cut off at the snapshot 660 1.8 christos * length, even though the full packet is copied up to 661 1.8 christos * userland. 662 1.8 christos * 663 1.8 christos * However, perhaps some versions of libpcap failed to 664 1.10 christos * set the snapshot length correctly in the file header 665 1.8 christos * or the per-packet header, or perhaps this is a 666 1.11 christos * corrupted savefile or a savefile built/modified by a 667 1.8 christos * fuzz tester, so we check anyway. We grow the buffer 668 1.8 christos * to be big enough for the snapshot length, read up 669 1.8 christos * to the snapshot length, discard the rest of the 670 1.8 christos * packet, and report the snapshot length as the captured 671 1.8 christos * length; we don't want to hand our caller a packet 672 1.8 christos * bigger than the snapshot length, because they might 673 1.8 christos * be assuming they'll never be handed such a packet, 674 1.8 christos * and might copy the packet into a snapshot-length- 675 1.8 christos * sized buffer, assuming it'll fit. 676 1.1 christos */ 677 1.7 christos size_t bytes_to_discard; 678 1.7 christos size_t bytes_to_read, bytes_read; 679 1.7 christos char discard_buf[4096]; 680 1.1 christos 681 1.8 christos if (hdr->caplen > p->bufsize) { 682 1.8 christos /* 683 1.8 christos * Grow the buffer to the snapshot length. 684 1.8 christos */ 685 1.8 christos if (!grow_buffer(p, p->snapshot)) 686 1.8 christos return (-1); 687 1.1 christos } 688 1.1 christos 689 1.7 christos /* 690 1.8 christos * Read the first p->snapshot bytes into the buffer. 691 1.7 christos */ 692 1.8 christos amt_read = fread(p->buffer, 1, p->snapshot, fp); 693 1.8 christos if (amt_read != (bpf_u_int32)p->snapshot) { 694 1.1 christos if (ferror(fp)) { 695 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, 696 1.8 christos PCAP_ERRBUF_SIZE, errno, 697 1.8 christos "error reading dump file"); 698 1.1 christos } else { 699 1.7 christos /* 700 1.7 christos * Yes, this uses hdr->caplen; technically, 701 1.7 christos * it's true, because we would try to read 702 1.7 christos * and discard the rest of those bytes, and 703 1.7 christos * that would fail because we got EOF before 704 1.7 christos * the read finished. 705 1.7 christos */ 706 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 707 1.10 christos "truncated dump file; tried to read %d captured bytes, only got %zu", 708 1.9 christos p->snapshot, amt_read); 709 1.1 christos } 710 1.1 christos return (-1); 711 1.1 christos } 712 1.7 christos 713 1.1 christos /* 714 1.7 christos * Now read and discard what's left. 715 1.7 christos */ 716 1.8 christos bytes_to_discard = hdr->caplen - p->snapshot; 717 1.7 christos bytes_read = amt_read; 718 1.7 christos while (bytes_to_discard != 0) { 719 1.7 christos bytes_to_read = bytes_to_discard; 720 1.7 christos if (bytes_to_read > sizeof (discard_buf)) 721 1.7 christos bytes_to_read = sizeof (discard_buf); 722 1.7 christos amt_read = fread(discard_buf, 1, bytes_to_read, fp); 723 1.7 christos bytes_read += amt_read; 724 1.7 christos if (amt_read != bytes_to_read) { 725 1.7 christos if (ferror(fp)) { 726 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, 727 1.8 christos PCAP_ERRBUF_SIZE, errno, 728 1.8 christos "error reading dump file"); 729 1.7 christos } else { 730 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 731 1.10 christos "truncated dump file; tried to read %u captured bytes, only got %zu", 732 1.9 christos hdr->caplen, bytes_read); 733 1.7 christos } 734 1.7 christos return (-1); 735 1.7 christos } 736 1.7 christos bytes_to_discard -= amt_read; 737 1.7 christos } 738 1.7 christos 739 1.7 christos /* 740 1.7 christos * Adjust caplen accordingly, so we don't get confused later 741 1.7 christos * as to how many bytes we have to play with. 742 1.1 christos */ 743 1.8 christos hdr->caplen = p->snapshot; 744 1.1 christos } else { 745 1.9 christos /* 746 1.9 christos * The packet is within the snapshot length for this file. 747 1.9 christos */ 748 1.8 christos if (hdr->caplen > p->bufsize) { 749 1.8 christos /* 750 1.8 christos * Grow the buffer to the next power of 2, or 751 1.8 christos * the snaplen, whichever is lower. 752 1.8 christos */ 753 1.8 christos u_int new_bufsize; 754 1.8 christos 755 1.8 christos new_bufsize = hdr->caplen; 756 1.8 christos /* 757 1.10 christos * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 758 1.8 christos */ 759 1.8 christos new_bufsize--; 760 1.8 christos new_bufsize |= new_bufsize >> 1; 761 1.8 christos new_bufsize |= new_bufsize >> 2; 762 1.8 christos new_bufsize |= new_bufsize >> 4; 763 1.8 christos new_bufsize |= new_bufsize >> 8; 764 1.8 christos new_bufsize |= new_bufsize >> 16; 765 1.8 christos new_bufsize++; 766 1.8 christos 767 1.8 christos if (new_bufsize > (u_int)p->snapshot) 768 1.8 christos new_bufsize = p->snapshot; 769 1.8 christos 770 1.8 christos if (!grow_buffer(p, new_bufsize)) 771 1.8 christos return (-1); 772 1.8 christos } 773 1.8 christos 774 1.1 christos /* read the packet itself */ 775 1.1 christos amt_read = fread(p->buffer, 1, hdr->caplen, fp); 776 1.1 christos if (amt_read != hdr->caplen) { 777 1.1 christos if (ferror(fp)) { 778 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, 779 1.8 christos PCAP_ERRBUF_SIZE, errno, 780 1.8 christos "error reading dump file"); 781 1.1 christos } else { 782 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 783 1.10 christos "truncated dump file; tried to read %u captured bytes, only got %zu", 784 1.9 christos hdr->caplen, amt_read); 785 1.1 christos } 786 1.1 christos return (-1); 787 1.1 christos } 788 1.1 christos } 789 1.1 christos *data = p->buffer; 790 1.1 christos 791 1.11 christos pcapint_post_process(p->linktype, p->swapped, hdr, *data); 792 1.1 christos 793 1.10 christos return (1); 794 1.1 christos } 795 1.1 christos 796 1.1 christos static int 797 1.10 christos sf_write_header(pcap_t *p, FILE *fp, int linktype, int snaplen) 798 1.1 christos { 799 1.1 christos struct pcap_file_header hdr; 800 1.1 christos 801 1.4 christos hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC; 802 1.1 christos hdr.version_major = PCAP_VERSION_MAJOR; 803 1.1 christos hdr.version_minor = PCAP_VERSION_MINOR; 804 1.1 christos 805 1.10 christos /* 806 1.10 christos * https://www.tcpdump.org/manpages/pcap-savefile.5.txt states: 807 1.11 christos * thiszone (Reserved1): 4-byte not used - SHOULD be filled with 0 808 1.11 christos * sigfigs (Reserved2): 4-byte not used - SHOULD be filled with 0 809 1.10 christos */ 810 1.10 christos hdr.thiszone = 0; 811 1.10 christos hdr.sigfigs = 0; 812 1.1 christos hdr.snaplen = snaplen; 813 1.1 christos hdr.linktype = linktype; 814 1.1 christos 815 1.1 christos if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) 816 1.1 christos return (-1); 817 1.1 christos 818 1.1 christos return (0); 819 1.1 christos } 820 1.1 christos 821 1.1 christos /* 822 1.1 christos * Output a packet to the initialized dump file. 823 1.1 christos */ 824 1.1 christos void 825 1.1 christos pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 826 1.1 christos { 827 1.1 christos register FILE *f; 828 1.1 christos struct pcap_sf_pkthdr sf_hdr; 829 1.1 christos 830 1.1 christos f = (FILE *)user; 831 1.10 christos /* 832 1.10 christos * If the output file handle is in an error state, don't write 833 1.10 christos * anything. 834 1.10 christos * 835 1.10 christos * While in principle a file handle can return from an error state 836 1.10 christos * to a normal state (for example if a disk that is full has space 837 1.10 christos * freed), we have possibly left a broken file already, and won't 838 1.10 christos * be able to clean it up. The safest option is to do nothing. 839 1.10 christos * 840 1.10 christos * Note that if we could guarantee that fwrite() was atomic we 841 1.10 christos * might be able to insure that we don't produce a corrupted file, 842 1.10 christos * but the standard defines fwrite() as a series of fputc() calls, 843 1.10 christos * so we really have no insurance that things are not fubared. 844 1.10 christos * 845 1.10 christos * http://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html 846 1.10 christos */ 847 1.10 christos if (ferror(f)) 848 1.10 christos return; 849 1.10 christos /* 850 1.10 christos * Better not try writing pcap files after 851 1.11 christos * 2106-02-07 06:28:15 UTC; switch to pcapng. 852 1.11 christos * (And better not try writing pcap files with time stamps 853 1.11 christos * that predate 1970-01-01 00:00:00 UTC; that's not supported. 854 1.11 christos * You could try using pcapng with the if_tsoffset field in 855 1.11 christos * the IDB for the interface(s) with packets with those time 856 1.11 christos * stamps, but you may also have to get a link-layer type for 857 1.11 christos * IBM Bisync or whatever link layer even older forms 858 1.11 christos * of computer communication used.) 859 1.10 christos */ 860 1.11 christos sf_hdr.ts.tv_sec = (bpf_u_int32)h->ts.tv_sec; 861 1.11 christos sf_hdr.ts.tv_usec = (bpf_u_int32)h->ts.tv_usec; 862 1.1 christos sf_hdr.caplen = h->caplen; 863 1.1 christos sf_hdr.len = h->len; 864 1.10 christos /* 865 1.10 christos * We only write the packet if we can write the header properly. 866 1.10 christos * 867 1.10 christos * This doesn't prevent us from having corrupted output, and if we 868 1.10 christos * for some reason don't get a complete write we don't have any 869 1.10 christos * way to set ferror() to prevent future writes from being 870 1.10 christos * attempted, but it is better than nothing. 871 1.10 christos */ 872 1.10 christos if (fwrite(&sf_hdr, sizeof(sf_hdr), 1, f) == 1) { 873 1.10 christos (void)fwrite(sp, h->caplen, 1, f); 874 1.10 christos } 875 1.1 christos } 876 1.1 christos 877 1.1 christos static pcap_dumper_t * 878 1.1 christos pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname) 879 1.1 christos { 880 1.1 christos 881 1.7 christos #if defined(_WIN32) || defined(MSDOS) 882 1.1 christos /* 883 1.1 christos * If we're writing to the standard output, put it in binary 884 1.1 christos * mode, as savefiles are binary files. 885 1.1 christos * 886 1.1 christos * Otherwise, we turn off buffering. 887 1.1 christos * XXX - why? And why not on the standard output? 888 1.1 christos */ 889 1.1 christos if (f == stdout) 890 1.1 christos SET_BINMODE(f); 891 1.1 christos else 892 1.8 christos setvbuf(f, NULL, _IONBF, 0); 893 1.1 christos #endif 894 1.10 christos if (sf_write_header(p, f, linktype, p->snapshot) == -1) { 895 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 896 1.8 christos errno, "Can't write to %s", fname); 897 1.1 christos if (f != stdout) 898 1.1 christos (void)fclose(f); 899 1.1 christos return (NULL); 900 1.1 christos } 901 1.1 christos return ((pcap_dumper_t *)f); 902 1.1 christos } 903 1.1 christos 904 1.1 christos /* 905 1.1 christos * Initialize so that sf_write() will output to the file named 'fname'. 906 1.1 christos */ 907 1.1 christos pcap_dumper_t * 908 1.1 christos pcap_dump_open(pcap_t *p, const char *fname) 909 1.1 christos { 910 1.1 christos FILE *f; 911 1.1 christos int linktype; 912 1.1 christos 913 1.1 christos /* 914 1.1 christos * If this pcap_t hasn't been activated, it doesn't have a 915 1.1 christos * link-layer type, so we can't use it. 916 1.1 christos */ 917 1.1 christos if (!p->activated) { 918 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 919 1.1 christos "%s: not-yet-activated pcap_t passed to pcap_dump_open", 920 1.1 christos fname); 921 1.1 christos return (NULL); 922 1.1 christos } 923 1.1 christos linktype = dlt_to_linktype(p->linktype); 924 1.1 christos if (linktype == -1) { 925 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 926 1.1 christos "%s: link-layer type %d isn't supported in savefiles", 927 1.1 christos fname, p->linktype); 928 1.1 christos return (NULL); 929 1.1 christos } 930 1.1 christos linktype |= p->linktype_ext; 931 1.1 christos 932 1.7 christos if (fname == NULL) { 933 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 934 1.7 christos "A null pointer was supplied as the file name"); 935 1.7 christos return NULL; 936 1.7 christos } 937 1.1 christos if (fname[0] == '-' && fname[1] == '\0') { 938 1.1 christos f = stdout; 939 1.1 christos fname = "standard output"; 940 1.1 christos } else { 941 1.8 christos /* 942 1.8 christos * "b" is supported as of C90, so *all* UN*Xes should 943 1.8 christos * support it, even though it does nothing. It's 944 1.8 christos * required on Windows, as the file is a binary file 945 1.8 christos * and must be written in binary mode. 946 1.8 christos */ 947 1.11 christos f = pcapint_charset_fopen(fname, "wb"); 948 1.1 christos if (f == NULL) { 949 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 950 1.8 christos errno, "%s", fname); 951 1.1 christos return (NULL); 952 1.1 christos } 953 1.1 christos } 954 1.1 christos return (pcap_setup_dump(p, linktype, f, fname)); 955 1.1 christos } 956 1.1 christos 957 1.9 christos #ifdef _WIN32 958 1.9 christos /* 959 1.9 christos * Initialize so that sf_write() will output to a stream wrapping the given raw 960 1.9 christos * OS file HANDLE. 961 1.9 christos */ 962 1.9 christos pcap_dumper_t * 963 1.9 christos pcap_dump_hopen(pcap_t *p, intptr_t osfd) 964 1.9 christos { 965 1.9 christos int fd; 966 1.9 christos FILE *file; 967 1.9 christos 968 1.9 christos fd = _open_osfhandle(osfd, _O_APPEND); 969 1.9 christos if (fd < 0) { 970 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 971 1.9 christos errno, "_open_osfhandle"); 972 1.9 christos return NULL; 973 1.9 christos } 974 1.9 christos 975 1.9 christos file = _fdopen(fd, "wb"); 976 1.9 christos if (file == NULL) { 977 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 978 1.9 christos errno, "_fdopen"); 979 1.9 christos _close(fd); 980 1.9 christos return NULL; 981 1.9 christos } 982 1.9 christos 983 1.9 christos return pcap_dump_fopen(p, file); 984 1.9 christos } 985 1.9 christos #endif /* _WIN32 */ 986 1.9 christos 987 1.1 christos /* 988 1.1 christos * Initialize so that sf_write() will output to the given stream. 989 1.1 christos */ 990 1.9 christos #ifdef _WIN32 991 1.9 christos static 992 1.9 christos #endif /* _WIN32 */ 993 1.1 christos pcap_dumper_t * 994 1.1 christos pcap_dump_fopen(pcap_t *p, FILE *f) 995 1.6 christos { 996 1.1 christos int linktype; 997 1.1 christos 998 1.1 christos linktype = dlt_to_linktype(p->linktype); 999 1.1 christos if (linktype == -1) { 1000 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1001 1.1 christos "stream: link-layer type %d isn't supported in savefiles", 1002 1.1 christos p->linktype); 1003 1.1 christos return (NULL); 1004 1.1 christos } 1005 1.1 christos linktype |= p->linktype_ext; 1006 1.1 christos 1007 1.1 christos return (pcap_setup_dump(p, linktype, f, "stream")); 1008 1.1 christos } 1009 1.1 christos 1010 1.6 christos pcap_dumper_t * 1011 1.6 christos pcap_dump_open_append(pcap_t *p, const char *fname) 1012 1.6 christos { 1013 1.6 christos FILE *f; 1014 1.6 christos int linktype; 1015 1.7 christos size_t amt_read; 1016 1.6 christos struct pcap_file_header ph; 1017 1.6 christos 1018 1.6 christos linktype = dlt_to_linktype(p->linktype); 1019 1.6 christos if (linktype == -1) { 1020 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1021 1.6 christos "%s: link-layer type %d isn't supported in savefiles", 1022 1.6 christos fname, linktype); 1023 1.6 christos return (NULL); 1024 1.6 christos } 1025 1.7 christos 1026 1.7 christos if (fname == NULL) { 1027 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1028 1.7 christos "A null pointer was supplied as the file name"); 1029 1.7 christos return NULL; 1030 1.7 christos } 1031 1.6 christos if (fname[0] == '-' && fname[1] == '\0') 1032 1.6 christos return (pcap_setup_dump(p, linktype, stdout, "standard output")); 1033 1.6 christos 1034 1.8 christos /* 1035 1.9 christos * "a" will cause the file *not* to be truncated if it exists 1036 1.9 christos * but will cause it to be created if it doesn't. It will 1037 1.9 christos * also cause all writes to be done at the end of the file, 1038 1.9 christos * but will allow reads to be done anywhere in the file. This 1039 1.9 christos * is what we need, because we need to read from the beginning 1040 1.9 christos * of the file to see if it already has a header and packets 1041 1.9 christos * or if it doesn't. 1042 1.9 christos * 1043 1.8 christos * "b" is supported as of C90, so *all* UN*Xes should support it, 1044 1.8 christos * even though it does nothing. It's required on Windows, as the 1045 1.8 christos * file is a binary file and must be read in binary mode. 1046 1.8 christos */ 1047 1.11 christos f = pcapint_charset_fopen(fname, "ab+"); 1048 1.6 christos if (f == NULL) { 1049 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 1050 1.8 christos errno, "%s", fname); 1051 1.6 christos return (NULL); 1052 1.6 christos } 1053 1.6 christos 1054 1.6 christos /* 1055 1.6 christos * Try to read a pcap header. 1056 1.9 christos * 1057 1.9 christos * We do not assume that the file will be positioned at the 1058 1.9 christos * beginning immediately after we've opened it - we seek to 1059 1.9 christos * the beginning. ISO C says it's implementation-defined 1060 1.9 christos * whether the file position indicator is at the beginning 1061 1.9 christos * or the end of the file after an append-mode open, and 1062 1.9 christos * it wasn't obvious from the Single UNIX Specification 1063 1.9 christos * or the Microsoft documentation how that works on SUS- 1064 1.9 christos * compliant systems or on Windows. 1065 1.6 christos */ 1066 1.9 christos if (fseek(f, 0, SEEK_SET) == -1) { 1067 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 1068 1.9 christos errno, "Can't seek to the beginning of %s", fname); 1069 1.9 christos (void)fclose(f); 1070 1.9 christos return (NULL); 1071 1.9 christos } 1072 1.6 christos amt_read = fread(&ph, 1, sizeof (ph), f); 1073 1.6 christos if (amt_read != sizeof (ph)) { 1074 1.6 christos if (ferror(f)) { 1075 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 1076 1.8 christos errno, "%s", fname); 1077 1.9 christos (void)fclose(f); 1078 1.6 christos return (NULL); 1079 1.6 christos } else if (feof(f) && amt_read > 0) { 1080 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1081 1.6 christos "%s: truncated pcap file header", fname); 1082 1.9 christos (void)fclose(f); 1083 1.6 christos return (NULL); 1084 1.6 christos } 1085 1.6 christos } 1086 1.6 christos 1087 1.7 christos #if defined(_WIN32) || defined(MSDOS) 1088 1.6 christos /* 1089 1.6 christos * We turn off buffering. 1090 1.6 christos * XXX - why? And why not on the standard output? 1091 1.6 christos */ 1092 1.8 christos setvbuf(f, NULL, _IONBF, 0); 1093 1.6 christos #endif 1094 1.6 christos 1095 1.6 christos /* 1096 1.6 christos * If a header is already present and: 1097 1.6 christos * 1098 1.6 christos * it's not for a pcap file of the appropriate resolution 1099 1.6 christos * and the right byte order for this machine; 1100 1.6 christos * 1101 1.6 christos * the link-layer header types don't match; 1102 1.6 christos * 1103 1.6 christos * the snapshot lengths don't match; 1104 1.6 christos * 1105 1.6 christos * return an error. 1106 1.6 christos */ 1107 1.6 christos if (amt_read > 0) { 1108 1.6 christos /* 1109 1.6 christos * A header is already present. 1110 1.6 christos * Do the checks. 1111 1.6 christos */ 1112 1.6 christos switch (ph.magic) { 1113 1.6 christos 1114 1.6 christos case TCPDUMP_MAGIC: 1115 1.6 christos if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) { 1116 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1117 1.6 christos "%s: different time stamp precision, cannot append to file", fname); 1118 1.9 christos (void)fclose(f); 1119 1.6 christos return (NULL); 1120 1.6 christos } 1121 1.6 christos break; 1122 1.6 christos 1123 1.6 christos case NSEC_TCPDUMP_MAGIC: 1124 1.6 christos if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) { 1125 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1126 1.6 christos "%s: different time stamp precision, cannot append to file", fname); 1127 1.9 christos (void)fclose(f); 1128 1.6 christos return (NULL); 1129 1.6 christos } 1130 1.6 christos break; 1131 1.6 christos 1132 1.6 christos case SWAPLONG(TCPDUMP_MAGIC): 1133 1.6 christos case SWAPLONG(NSEC_TCPDUMP_MAGIC): 1134 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1135 1.6 christos "%s: different byte order, cannot append to file", fname); 1136 1.9 christos (void)fclose(f); 1137 1.6 christos return (NULL); 1138 1.6 christos 1139 1.6 christos case KUZNETZOV_TCPDUMP_MAGIC: 1140 1.6 christos case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC): 1141 1.6 christos case NAVTEL_TCPDUMP_MAGIC: 1142 1.6 christos case SWAPLONG(NAVTEL_TCPDUMP_MAGIC): 1143 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1144 1.6 christos "%s: not a pcap file to which we can append", fname); 1145 1.9 christos (void)fclose(f); 1146 1.6 christos return (NULL); 1147 1.6 christos 1148 1.6 christos default: 1149 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1150 1.6 christos "%s: not a pcap file", fname); 1151 1.9 christos (void)fclose(f); 1152 1.6 christos return (NULL); 1153 1.6 christos } 1154 1.6 christos 1155 1.6 christos /* 1156 1.6 christos * Good version? 1157 1.6 christos */ 1158 1.6 christos if (ph.version_major != PCAP_VERSION_MAJOR || 1159 1.6 christos ph.version_minor != PCAP_VERSION_MINOR) { 1160 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1161 1.6 christos "%s: version is %u.%u, cannot append to file", fname, 1162 1.6 christos ph.version_major, ph.version_minor); 1163 1.9 christos (void)fclose(f); 1164 1.6 christos return (NULL); 1165 1.6 christos } 1166 1.7 christos if ((bpf_u_int32)linktype != ph.linktype) { 1167 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1168 1.6 christos "%s: different linktype, cannot append to file", fname); 1169 1.9 christos (void)fclose(f); 1170 1.6 christos return (NULL); 1171 1.6 christos } 1172 1.7 christos if ((bpf_u_int32)p->snapshot != ph.snaplen) { 1173 1.10 christos snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 1174 1.6 christos "%s: different snaplen, cannot append to file", fname); 1175 1.9 christos (void)fclose(f); 1176 1.6 christos return (NULL); 1177 1.6 christos } 1178 1.6 christos } else { 1179 1.6 christos /* 1180 1.6 christos * A header isn't present; attempt to write it. 1181 1.6 christos */ 1182 1.10 christos if (sf_write_header(p, f, linktype, p->snapshot) == -1) { 1183 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 1184 1.8 christos errno, "Can't write to %s", fname); 1185 1.6 christos (void)fclose(f); 1186 1.6 christos return (NULL); 1187 1.6 christos } 1188 1.6 christos } 1189 1.6 christos 1190 1.6 christos /* 1191 1.6 christos * Start writing at the end of the file. 1192 1.9 christos * 1193 1.9 christos * XXX - this shouldn't be necessary, given that we're opening 1194 1.9 christos * the file in append mode, and ISO C specifies that all writes 1195 1.9 christos * are done at the end of the file in that mode. 1196 1.6 christos */ 1197 1.6 christos if (fseek(f, 0, SEEK_END) == -1) { 1198 1.11 christos pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE, 1199 1.9 christos errno, "Can't seek to the end of %s", fname); 1200 1.6 christos (void)fclose(f); 1201 1.6 christos return (NULL); 1202 1.6 christos } 1203 1.6 christos return ((pcap_dumper_t *)f); 1204 1.6 christos } 1205 1.6 christos 1206 1.1 christos FILE * 1207 1.1 christos pcap_dump_file(pcap_dumper_t *p) 1208 1.1 christos { 1209 1.1 christos return ((FILE *)p); 1210 1.1 christos } 1211 1.1 christos 1212 1.1 christos long 1213 1.1 christos pcap_dump_ftell(pcap_dumper_t *p) 1214 1.1 christos { 1215 1.1 christos return (ftell((FILE *)p)); 1216 1.1 christos } 1217 1.1 christos 1218 1.8 christos #if defined(HAVE_FSEEKO) 1219 1.8 christos /* 1220 1.8 christos * We have fseeko(), so we have ftello(). 1221 1.8 christos * If we have large file support (files larger than 2^31-1 bytes), 1222 1.8 christos * ftello() will give us a current file position with more than 32 1223 1.8 christos * bits. 1224 1.8 christos */ 1225 1.8 christos int64_t 1226 1.8 christos pcap_dump_ftell64(pcap_dumper_t *p) 1227 1.8 christos { 1228 1.8 christos return (ftello((FILE *)p)); 1229 1.8 christos } 1230 1.8 christos #elif defined(_MSC_VER) 1231 1.8 christos /* 1232 1.12 christos * We have Visual Studio; we support only 2015 and later, so we have 1233 1.8 christos * _ftelli64(). 1234 1.8 christos */ 1235 1.8 christos int64_t 1236 1.8 christos pcap_dump_ftell64(pcap_dumper_t *p) 1237 1.8 christos { 1238 1.8 christos return (_ftelli64((FILE *)p)); 1239 1.8 christos } 1240 1.8 christos #else 1241 1.8 christos /* 1242 1.8 christos * We don't have ftello() or _ftelli64(), so fall back on ftell(). 1243 1.8 christos * Either long is 64 bits, in which case ftell() should suffice, 1244 1.8 christos * or this is probably an older 32-bit UN*X without large file 1245 1.8 christos * support, which means you'll probably get errors trying to 1246 1.8 christos * write files > 2^31-1, so it won't matter anyway. 1247 1.8 christos * 1248 1.8 christos * XXX - what about MinGW? 1249 1.8 christos */ 1250 1.8 christos int64_t 1251 1.8 christos pcap_dump_ftell64(pcap_dumper_t *p) 1252 1.8 christos { 1253 1.8 christos return (ftell((FILE *)p)); 1254 1.8 christos } 1255 1.8 christos #endif 1256 1.8 christos 1257 1.1 christos int 1258 1.1 christos pcap_dump_flush(pcap_dumper_t *p) 1259 1.1 christos { 1260 1.1 christos 1261 1.1 christos if (fflush((FILE *)p) == EOF) 1262 1.1 christos return (-1); 1263 1.1 christos else 1264 1.1 christos return (0); 1265 1.1 christos } 1266 1.1 christos 1267 1.1 christos void 1268 1.1 christos pcap_dump_close(pcap_dumper_t *p) 1269 1.1 christos { 1270 1.12 christos FILE *fp = (FILE *)p; 1271 1.1 christos 1272 1.1 christos #ifdef notyet 1273 1.12 christos if (ferror(fp)) 1274 1.1 christos return-an-error; 1275 1.12 christos /* XXX should check return from fflush()/fclose() too */ 1276 1.1 christos #endif 1277 1.12 christos /* Don't close the standard output, but *do* flush it */ 1278 1.12 christos if (fp == stdout) 1279 1.12 christos (void)fflush(fp); 1280 1.12 christos else 1281 1.12 christos (void)fclose(fp); 1282 1.1 christos } 1283