xref: /netbsd-src/external/bsd/libpcap/dist/sf-pcap.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: sf-pcap.c,v 1.3 2013/04/06 17:29:53 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1993, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  *
23  * sf-pcap.c - libpcap-file-format-specific code from savefile.c
24  *	Extraction/creation by Jeffrey Mogul, DECWRL
25  *	Modified by Steve McCanne, LBL.
26  *
27  * Used to save the received packet headers, after filtering, to
28  * a file, and then read them later.
29  * The first record in the file contains saved values for the machine
30  * dependent values so we can print the dump file on any architecture.
31  */
32 
33 #ifndef lint
34 static const char rcsid[] _U_ =
35     "@(#) Header (LBL)";
36 #endif
37 
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 
42 #ifdef WIN32
43 #include <pcap-stdinc.h>
44 #else /* WIN32 */
45 #if HAVE_INTTYPES_H
46 #include <inttypes.h>
47 #elif HAVE_STDINT_H
48 #include <stdint.h>
49 #endif
50 #ifdef HAVE_SYS_BITYPES_H
51 #include <sys/bitypes.h>
52 #endif
53 #include <sys/types.h>
54 #endif /* WIN32 */
55 
56 #include <errno.h>
57 #include <memory.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 
62 #include "pcap-int.h"
63 
64 #include "pcap-common.h"
65 
66 #ifdef HAVE_OS_PROTO_H
67 #include "os-proto.h"
68 #endif
69 
70 #include "sf-pcap.h"
71 
72 /*
73  * Setting O_BINARY on DOS/Windows is a bit tricky
74  */
75 #if defined(WIN32)
76   #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
77 #elif defined(MSDOS)
78   #if defined(__HIGHC__)
79   #define SET_BINMODE(f)  setmode(f, O_BINARY)
80   #else
81   #define SET_BINMODE(f)  setmode(fileno(f), O_BINARY)
82   #endif
83 #endif
84 
85 /*
86  * Standard libpcap format.
87  */
88 #define TCPDUMP_MAGIC		0xa1b2c3d4
89 
90 /*
91  * Alexey Kuznetzov's modified libpcap format.
92  */
93 #define KUZNETZOV_TCPDUMP_MAGIC	0xa1b2cd34
94 
95 /*
96  * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt>
97  * for another modified format.
98  */
99 #define FMESQUITA_TCPDUMP_MAGIC	0xa1b234cd
100 
101 /*
102  * Navtel Communcations' format, with nanosecond timestamps,
103  * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
104  */
105 #define NAVTEL_TCPDUMP_MAGIC	0xa12b3c4d
106 
107 /*
108  * Normal libpcap format, except for seconds/nanoseconds timestamps,
109  * as per a request by Ulf Lamping <ulf.lamping@web.de>
110  */
111 #define NSEC_TCPDUMP_MAGIC	0xa1b23c4d
112 
113 /*
114  * Mechanism for storing information about a capture in the upper
115  * 6 bits of a linktype value in a capture file.
116  *
117  * LT_LINKTYPE_EXT(x) extracts the additional information.
118  *
119  * The rest of the bits are for a value describing the link-layer
120  * value.  LT_LINKTYPE(x) extracts that value.
121  */
122 #define LT_LINKTYPE(x)		((x) & 0x03FFFFFF)
123 #define LT_LINKTYPE_EXT(x)	((x) & 0xFC000000)
124 
125 static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
126 
127 /*
128  * Check whether this is a pcap savefile and, if it is, extract the
129  * relevant information from the header.
130  */
131 int
132 pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf)
133 {
134 	struct pcap_file_header hdr;
135 	size_t amt_read;
136 
137 	/*
138 	 * Check whether the first 4 bytes of the file are the magic
139 	 * number for a pcap savefile, or for a byte-swapped pcap
140 	 * savefile.
141 	 */
142 	if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) {
143 		magic = SWAPLONG(magic);
144 		if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC)
145 			return (0);	/* nope */
146 		p->sf.swapped = 1;
147 	}
148 
149 	/*
150 	 * They are.  Put the magic number in the header, and read
151 	 * the rest of the header.
152 	 */
153 	hdr.magic = magic;
154 	amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
155 	    sizeof(hdr) - sizeof(hdr.magic), fp);
156 	if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
157 		if (ferror(fp)) {
158 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
159 			    "error reading dump file: %s",
160 			    pcap_strerror(errno));
161 		} else {
162 			snprintf(errbuf, PCAP_ERRBUF_SIZE,
163 			    "truncated dump file; tried to read %lu file header bytes, only got %lu",
164 			    (unsigned long)sizeof(hdr),
165 			    (unsigned long)amt_read);
166 		}
167 		return (-1);
168 	}
169 
170 	/*
171 	 * If it's a byte-swapped capture file, byte-swap the header.
172 	 */
173 	if (p->sf.swapped) {
174 		hdr.version_major = SWAPSHORT(hdr.version_major);
175 		hdr.version_minor = SWAPSHORT(hdr.version_minor);
176 		hdr.thiszone = SWAPLONG(hdr.thiszone);
177 		hdr.sigfigs = SWAPLONG(hdr.sigfigs);
178 		hdr.snaplen = SWAPLONG(hdr.snaplen);
179 		hdr.linktype = SWAPLONG(hdr.linktype);
180 	}
181 
182 	if (hdr.version_major < PCAP_VERSION_MAJOR) {
183 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
184 		    "archaic pcap savefile format");
185 		return (-1);
186 	}
187 	p->sf.version_major = hdr.version_major;
188 	p->sf.version_minor = hdr.version_minor;
189 	p->tzoff = hdr.thiszone;
190 	p->snapshot = hdr.snaplen;
191 	p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
192 	p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
193 
194 	p->sf.next_packet_op = pcap_next_packet;
195 
196 	/*
197 	 * We interchanged the caplen and len fields at version 2.3,
198 	 * in order to match the bpf header layout.  But unfortunately
199 	 * some files were written with version 2.3 in their headers
200 	 * but without the interchanged fields.
201 	 *
202 	 * In addition, DG/UX tcpdump writes out files with a version
203 	 * number of 543.0, and with the caplen and len fields in the
204 	 * pre-2.3 order.
205 	 */
206 	switch (hdr.version_major) {
207 
208 	case 2:
209 		if (hdr.version_minor < 3)
210 			p->sf.lengths_swapped = SWAPPED;
211 		else if (hdr.version_minor == 3)
212 			p->sf.lengths_swapped = MAYBE_SWAPPED;
213 		else
214 			p->sf.lengths_swapped = NOT_SWAPPED;
215 		break;
216 
217 	case 543:
218 		p->sf.lengths_swapped = SWAPPED;
219 		break;
220 
221 	default:
222 		p->sf.lengths_swapped = NOT_SWAPPED;
223 		break;
224 	}
225 
226 	if (magic == KUZNETZOV_TCPDUMP_MAGIC) {
227 		/*
228 		 * XXX - the patch that's in some versions of libpcap
229 		 * changes the packet header but not the magic number,
230 		 * and some other versions with this magic number have
231 		 * some extra debugging information in the packet header;
232 		 * we'd have to use some hacks^H^H^H^H^Hheuristics to
233 		 * detect those variants.
234 		 *
235 		 * Ethereal does that, but it does so by trying to read
236 		 * the first two packets of the file with each of the
237 		 * record header formats.  That currently means it seeks
238 		 * backwards and retries the reads, which doesn't work
239 		 * on pipes.  We want to be able to read from a pipe, so
240 		 * that strategy won't work; we'd have to buffer some
241 		 * data ourselves and read from that buffer in order to
242 		 * make that work.
243 		 */
244 		p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
245 
246 		if (p->linktype == DLT_EN10MB) {
247 			/*
248 			 * This capture might have been done in raw mode
249 			 * or cooked mode.
250 			 *
251 			 * If it was done in cooked mode, p->snapshot was
252 			 * passed to recvfrom() as the buffer size, meaning
253 			 * that the most packet data that would be copied
254 			 * would be p->snapshot.  However, a faked Ethernet
255 			 * header would then have been added to it, so the
256 			 * most data that would be in a packet in the file
257 			 * would be p->snapshot + 14.
258 			 *
259 			 * We can't easily tell whether the capture was done
260 			 * in raw mode or cooked mode, so we'll assume it was
261 			 * cooked mode, and add 14 to the snapshot length.
262 			 * That means that, for a raw capture, the snapshot
263 			 * length will be misleading if you use it to figure
264 			 * out why a capture doesn't have all the packet data,
265 			 * but there's not much we can do to avoid that.
266 			 */
267 			p->snapshot += 14;
268 		}
269 	} else
270 		p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr);
271 
272 	/*
273 	 * Allocate a buffer for the packet data.
274 	 */
275 	p->bufsize = p->snapshot;
276 	if (p->bufsize <= 0) {
277 		/*
278 		 * Bogus snapshot length; use 64KiB as a fallback.
279 		 */
280 		p->bufsize = 65536;
281 	}
282 	p->buffer = malloc(p->bufsize);
283 	if (p->buffer == NULL) {
284 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
285 		return (-1);
286 	}
287 
288 	return (1);
289 }
290 
291 /*
292  * Read and return the next packet from the savefile.  Return the header
293  * in hdr and a pointer to the contents in data.  Return 0 on success, 1
294  * if there were no more packets, and -1 on an error.
295  */
296 static int
297 pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
298 {
299 	struct pcap_sf_patched_pkthdr sf_hdr;
300 	FILE *fp = p->sf.rfile;
301 	size_t amt_read;
302 	bpf_u_int32 t;
303 
304 	/*
305 	 * Read the packet header; the structure we use as a buffer
306 	 * is the longer structure for files generated by the patched
307 	 * libpcap, but if the file has the magic number for an
308 	 * unpatched libpcap we only read as many bytes as the regular
309 	 * header has.
310 	 */
311 	amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp);
312 	if (amt_read != p->sf.hdrsize) {
313 		if (ferror(fp)) {
314 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
315 			    "error reading dump file: %s",
316 			    pcap_strerror(errno));
317 			return (-1);
318 		} else {
319 			if (amt_read != 0) {
320 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
321 				    "truncated dump file; tried to read %lu header bytes, only got %lu",
322 				    (unsigned long)p->sf.hdrsize,
323 				    (unsigned long)amt_read);
324 				return (-1);
325 			}
326 			/* EOF */
327 			return (1);
328 		}
329 	}
330 
331 	if (p->sf.swapped) {
332 		/* these were written in opposite byte order */
333 		hdr->caplen = SWAPLONG(sf_hdr.caplen);
334 		hdr->len = SWAPLONG(sf_hdr.len);
335 		hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec);
336 		hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec);
337 	} else {
338 		hdr->caplen = sf_hdr.caplen;
339 		hdr->len = sf_hdr.len;
340 		hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
341 		hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
342 	}
343 	/* Swap the caplen and len fields, if necessary. */
344 	switch (p->sf.lengths_swapped) {
345 
346 	case NOT_SWAPPED:
347 		break;
348 
349 	case MAYBE_SWAPPED:
350 		if (hdr->caplen <= hdr->len) {
351 			/*
352 			 * The captured length is <= the actual length,
353 			 * so presumably they weren't swapped.
354 			 */
355 			break;
356 		}
357 		/* FALLTHROUGH */
358 
359 	case SWAPPED:
360 		t = hdr->caplen;
361 		hdr->caplen = hdr->len;
362 		hdr->len = t;
363 		break;
364 	}
365 
366 	if ((int)hdr->caplen > p->bufsize) {
367 		/*
368 		 * This can happen due to Solaris 2.3 systems tripping
369 		 * over the BUFMOD problem and not setting the snapshot
370 		 * correctly in the savefile header.  If the caplen isn't
371 		 * grossly wrong, try to salvage.
372 		 */
373 		static u_char *tp = NULL;
374 		static size_t tsize = 0;
375 
376 		if (hdr->caplen > 65535) {
377 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
378 			    "bogus savefile header");
379 			return (-1);
380 		}
381 
382 		if (tsize < hdr->caplen) {
383 			tsize = ((hdr->caplen + 1023) / 1024) * 1024;
384 			if (tp != NULL)
385 				free((u_char *)tp);
386 			tp = (u_char *)malloc(tsize);
387 			if (tp == NULL) {
388 				tsize = 0;
389 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
390 				    "BUFMOD hack malloc");
391 				return (-1);
392 			}
393 		}
394 		amt_read = fread((char *)tp, 1, hdr->caplen, fp);
395 		if (amt_read != hdr->caplen) {
396 			if (ferror(fp)) {
397 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
398 				    "error reading dump file: %s",
399 				    pcap_strerror(errno));
400 			} else {
401 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
402 				    "truncated dump file; tried to read %u captured bytes, only got %lu",
403 				    hdr->caplen, (unsigned long)amt_read);
404 			}
405 			return (-1);
406 		}
407 		/*
408 		 * We can only keep up to p->bufsize bytes.  Since
409 		 * caplen > p->bufsize is exactly how we got here,
410 		 * we know we can only keep the first p->bufsize bytes
411 		 * and must drop the remainder.  Adjust caplen accordingly,
412 		 * so we don't get confused later as to how many bytes we
413 		 * have to play with.
414 		 */
415 		hdr->caplen = p->bufsize;
416 		memcpy(p->buffer, (char *)tp, p->bufsize);
417 	} else {
418 		/* read the packet itself */
419 		amt_read = fread(p->buffer, 1, hdr->caplen, fp);
420 		if (amt_read != hdr->caplen) {
421 			if (ferror(fp)) {
422 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
423 				    "error reading dump file: %s",
424 				    pcap_strerror(errno));
425 			} else {
426 				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
427 				    "truncated dump file; tried to read %u captured bytes, only got %lu",
428 				    hdr->caplen, (unsigned long)amt_read);
429 			}
430 			return (-1);
431 		}
432 	}
433 	*data = p->buffer;
434 
435 	if (p->sf.swapped) {
436 		/*
437 		 * Convert pseudo-headers from the byte order of
438 		 * the host on which the file was saved to our
439 		 * byte order, as necessary.
440 		 */
441 		switch (p->linktype) {
442 
443 		case DLT_USB_LINUX:
444 			swap_linux_usb_header(hdr, *data, 0);
445 			break;
446 
447 		case DLT_USB_LINUX_MMAPPED:
448 			swap_linux_usb_header(hdr, *data, 1);
449 			break;
450 		}
451 	}
452 
453 	return (0);
454 }
455 
456 static int
457 sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
458 {
459 	struct pcap_file_header hdr;
460 
461 	hdr.magic = TCPDUMP_MAGIC;
462 	hdr.version_major = PCAP_VERSION_MAJOR;
463 	hdr.version_minor = PCAP_VERSION_MINOR;
464 
465 	hdr.thiszone = thiszone;
466 	hdr.snaplen = snaplen;
467 	hdr.sigfigs = 0;
468 	hdr.linktype = linktype;
469 
470 	if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
471 		return (-1);
472 
473 	return (0);
474 }
475 
476 /*
477  * Output a packet to the initialized dump file.
478  */
479 void
480 pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
481 {
482 	register FILE *f;
483 	struct pcap_sf_pkthdr sf_hdr;
484 
485 	f = (FILE *)user;
486 	sf_hdr.ts.tv_sec  = h->ts.tv_sec;
487 	sf_hdr.ts.tv_usec = h->ts.tv_usec;
488 	sf_hdr.caplen     = h->caplen;
489 	sf_hdr.len        = h->len;
490 	/* XXX we should check the return status */
491 	(void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f);
492 	(void)fwrite(sp, h->caplen, 1, f);
493 }
494 
495 static pcap_dumper_t *
496 pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
497 {
498 
499 #if defined(WIN32) || defined(MSDOS)
500 	/*
501 	 * If we're writing to the standard output, put it in binary
502 	 * mode, as savefiles are binary files.
503 	 *
504 	 * Otherwise, we turn off buffering.
505 	 * XXX - why?  And why not on the standard output?
506 	 */
507 	if (f == stdout)
508 		SET_BINMODE(f);
509 	else
510 		setbuf(f, NULL);
511 #endif
512 	if (sf_write_header(f, linktype, p->tzoff, p->snapshot) == -1) {
513 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
514 		    fname, pcap_strerror(errno));
515 		if (f != stdout)
516 			(void)fclose(f);
517 		return (NULL);
518 	}
519 	return ((pcap_dumper_t *)f);
520 }
521 
522 /*
523  * Initialize so that sf_write() will output to the file named 'fname'.
524  */
525 pcap_dumper_t *
526 pcap_dump_open(pcap_t *p, const char *fname)
527 {
528 	FILE *f;
529 	int linktype;
530 
531 	/*
532 	 * If this pcap_t hasn't been activated, it doesn't have a
533 	 * link-layer type, so we can't use it.
534 	 */
535 	if (!p->activated) {
536 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
537 		    "%s: not-yet-activated pcap_t passed to pcap_dump_open",
538 		    fname);
539 		return (NULL);
540 	}
541 	linktype = dlt_to_linktype(p->linktype);
542 	if (linktype == -1) {
543 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
544 		    "%s: link-layer type %d isn't supported in savefiles",
545 		    fname, p->linktype);
546 		return (NULL);
547 	}
548 	linktype |= p->linktype_ext;
549 
550 	if (fname[0] == '-' && fname[1] == '\0') {
551 		f = stdout;
552 		fname = "standard output";
553 	} else {
554 #if !defined(WIN32) && !defined(MSDOS)
555 		f = fopen(fname, "w");
556 #else
557 		f = fopen(fname, "wb");
558 #endif
559 		if (f == NULL) {
560 			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
561 			    fname, pcap_strerror(errno));
562 			return (NULL);
563 		}
564 	}
565 	return (pcap_setup_dump(p, linktype, f, fname));
566 }
567 
568 /*
569  * Initialize so that sf_write() will output to the given stream.
570  */
571 pcap_dumper_t *
572 pcap_dump_fopen(pcap_t *p, FILE *f)
573 {
574 	int linktype;
575 
576 	linktype = dlt_to_linktype(p->linktype);
577 	if (linktype == -1) {
578 		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
579 		    "stream: link-layer type %d isn't supported in savefiles",
580 		    p->linktype);
581 		return (NULL);
582 	}
583 	linktype |= p->linktype_ext;
584 
585 	return (pcap_setup_dump(p, linktype, f, "stream"));
586 }
587 
588 FILE *
589 pcap_dump_file(pcap_dumper_t *p)
590 {
591 	return ((FILE *)p);
592 }
593 
594 long
595 pcap_dump_ftell(pcap_dumper_t *p)
596 {
597 	return (ftell((FILE *)p));
598 }
599 
600 int
601 pcap_dump_flush(pcap_dumper_t *p)
602 {
603 
604 	if (fflush((FILE *)p) == EOF)
605 		return (-1);
606 	else
607 		return (0);
608 }
609 
610 void
611 pcap_dump_close(pcap_dumper_t *p)
612 {
613 
614 #ifdef notyet
615 	if (ferror((FILE *)p))
616 		return-an-error;
617 	/* XXX should check return from fclose() too */
618 #endif
619 	(void)fclose((FILE *)p);
620 }
621