1 /* Copyright (c) 2007 by Errata Security, All Rights Reserved
2 * Programer(s): Robert David Graham [rdg]
3 */
4 /*
5
6 PCAPFILE
7
8 This is a small bit of code for reading/writing libpcap files.
9 This is for offline use of the product in cases where people
10 want to post-process files without having to install libpcap.
11
12 Since the file format is trivial to parse, and a lot of people
13 may not have libpcap installed, we decode it ourselves in this
14 module rather than using the libpcap module.
15
16 Also, this has the feature of being able to read corrupted
17 files. When it encounters a malformed back (such as one with
18 an impossibly large packet), it skips the malformed data and
19 searches forward for a packet that looks good.
20
21 */
22 #define _CRT_SECURE_NO_WARNINGS
23 #define _FILE_OFFSET_BITS 64
24
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <sys/stat.h>
31 #include "rawsock-pcapfile.h"
32
33 /****************************************************************************
34 * <PORTABILITY BLOCK>
35 ****************************************************************************/
36 #ifdef _MSC_VER
37 #define snprintf _snprintf
38 #define PRId64 "I64d"
39 #define PRIu64 "I64u"
40 #define PRIx64 "I64x"
41 #else
42 #include <inttypes.h>
43 #endif
ftell_x(FILE * fp)44 static int64_t ftell_x(FILE *fp)
45 {
46 #if defined(WIN32) && defined(__GNUC__)
47 return ftello64(fp);
48 #elif defined(WIN32) && defined(_MSC_VER)
49 return _ftelli64(fp);
50 #else
51 return ftello(fp);
52 #endif
53 }
fseek_x(FILE * fp,int64_t offset,int origin)54 static int fseek_x(FILE *fp, int64_t offset, int origin)
55 {
56 #if defined(WIN32) && defined(__GNUC__)
57 return fseeko64(fp, offset, origin);
58 #elif defined(WIN32) && defined(_MSC_VER)
59 return _fseeki64(fp, offset, origin);
60 #else
61 return fseeko(fp, offset, origin);
62 #endif
63 }
64 /****************************************************************************
65 * </PORTABILITY BLOCK>
66 ****************************************************************************/
67
68
69
70
71 /* PCAP file-format
72
73 typedef struct pcap_hdr_s {
74 guint32 magic_number; / * magic number * /
75 guint16 version_major; / * major version number * /
76 guint16 version_minor; / * minor version number * /
77 gint32 thiszone; / * GMT to local correction * /
78 guint32 sigfigs; / * accuracy of timestamps * /
79 guint32 snaplen; / * max length of captured packets, in octets * /
80 guint32 network; / * data link type * /
81 } pcap_hdr_t;
82
83
84 0 32-bits - "magic number"
85 4 16-bits - major version
86 16-bits - minor version
87 8 32-bits - timezone offset (should be zero)
88 12 32-bits - time stamp accuracy (should be zero)
89 16 32-bits - snap/slice length (maximum packet size)
90 20 32-bits - link layer type
91
92 Magic number:
93 a1 b2 c3 d4 = big-endian
94 d4 c3 b2 a1 = little-endian
95
96 Version:
97 2.4 = most common version
98
99 Timezone offset, Timestamp accuracy:
100 these fields are no longer used
101
102 Link-layer type:
103 0 BSD loopback devices, except for later OpenBSD
104 1 Ethernet, and Linux loopback devices
105 6 802.5 Token Ring
106 7 ARCnet
107 8 SLIP
108 9 PPP
109 10 FDDI
110 100 LLC/SNAP-encapsulated ATM
111 101 "raw IP", with no link
112 102 BSD/OS SLIP
113 103 BSD/OS PPP
114 104 Cisco HDLC
115 105 802.11
116 108 later OpenBSD loopback devices (with the AF_
117 value in network byte order)
118 113 special Linux "cooked" capture
119 114 LocalTalk
120
121
122 */
123 /*
124
125 802.11
126 11 * 802.11b - 11-mbps
127 12 * 802.11d - operation in multiple regulatory domains
128 13 * 802.11e - wireless multimedia extensions
129 14 * 802.11g - 54-mbps
130 15 * 802.11h - power management
131 16 * 802.11i - MAC security enhancements
132
133 */
134
135 struct PcapFile
136 {
137 FILE *fp;
138
139 unsigned is_file_header_written:1;
140
141 unsigned start_sec;
142 unsigned start_usec;
143 unsigned end_sec;
144 unsigned end_usec;
145 char filename[256];
146 int byte_order;
147 int linktype;
148 long long frame_number;
149
150 uint64_t file_size;
151 uint64_t bytes_read;
152
153 /**
154 * This is for asynchronous reading of the file.
155 */
156 unsigned char *aio_buffer;
157 size_t aio_buffer_size;
158 };
159
160 #define CAPFILE_BIGENDIAN 1
161 #define CAPFILE_LITTLEENDIAN 2
162 #define CAPFILE_ENDIANUNKNOWN 3
163
164
165 /** Read a 16-bit value from a capture file, depending upon the byte
166 * order within that file */
PCAP16(unsigned byte_order,const unsigned char * buf)167 static unsigned PCAP16(unsigned byte_order, const unsigned char *buf)
168 {
169 switch (byte_order) {
170 case CAPFILE_BIGENDIAN: return buf[0]*256 + buf[1];
171 case CAPFILE_LITTLEENDIAN: return buf[1]*256 + buf[0];
172 default: return (unsigned)0xa3a3;
173 }
174 }
175 /** Read a 32-bit value from a capture file, depending upon the byte
176 * order within that file */
PCAP32(unsigned byte_order,const unsigned char * buf)177 static unsigned PCAP32(unsigned byte_order, const unsigned char *buf)
178 {
179 switch (byte_order) {
180 case CAPFILE_BIGENDIAN: return buf[0]<<24 | buf[1]<<16 | buf[2] << 8 | buf[3];
181 case CAPFILE_LITTLEENDIAN: return buf[3]<<24 | buf[2]<<16 | buf[1] << 8 | buf[0];
182 default: return (unsigned)0xa3a3;
183 }
184 }
185
186 /**
187 * Return the "link" type, such as Ethernet, WiFi, Token Ring, etc.
188 */
189 int
pcapfile_datalink(struct PcapFile * handle)190 pcapfile_datalink(struct PcapFile *handle)
191 {
192 if (handle)
193 return handle->linktype;
194 else
195 return 0;
196 }
197
198
199 /**
200 * Determine if the blob (the chunk of from the file read at a certain offset)
201 * looks like a valid packet
202 */
203 static unsigned
smells_like_valid_packet(const unsigned char * px,unsigned length,unsigned byte_order,unsigned link_type)204 smells_like_valid_packet(const unsigned char *px, unsigned length, unsigned byte_order, unsigned link_type)
205 {
206 unsigned secs, usecs, original_length, captured_length;
207
208 if (length < 16)
209 return 0;
210
211 secs = PCAP32(byte_order, px+0);
212 usecs = PCAP32(byte_order, px+4);
213 captured_length = PCAP32(byte_order, px+8);
214 original_length = PCAP32(byte_order, px+12);
215
216 if (secs > 0x50000000) return 0; /* after 2010 */
217 if (secs < 0x26000000) return 0; /* before 1990 */
218 if (usecs > 1000000) return 0;
219 if (captured_length > 10000) return 0;
220 if (captured_length < 16) return 0;
221 if (original_length < captured_length) return 0;
222 if (original_length > 10000) return 0;
223
224 if (captured_length + 16 < length) {
225 unsigned secs2, usecs2, original_length2, captured_length2;
226 const unsigned char *px2 = px + captured_length + 16;
227
228 secs2 = PCAP32(byte_order, px2+0);
229 usecs2 = PCAP32(byte_order, px2+4);
230 captured_length2 = PCAP32(byte_order, px2+8);
231 original_length2 = PCAP32(byte_order, px2+12);
232
233 if (secs2 > 0x50000000)
234 return 0;
235 if (secs2 < 0x26000000)
236 return 0;
237 if (usecs2 > 1000000)
238 return 0;
239 if (captured_length2 > 10000)
240 return 0;
241 if (captured_length2 < 16)
242 return 0;
243 if (original_length2 < captured_length2)
244 return 0;
245 if (original_length2 > 10000)
246 return 0;
247 return 1;
248 } else
249 switch (link_type) {
250 case 1: /*ethernet*/
251 if (px[12] == 0x08 && px[13] == 0x00 && px[14] == 0x45)
252 return 1;
253 }
254
255 return 0;
256 }
257
258
pcapfile_percentdone(struct PcapFile * capfile,uint64_t * r_bytes_read)259 unsigned pcapfile_percentdone(struct PcapFile *capfile, uint64_t *r_bytes_read)
260 {
261 if (r_bytes_read)
262 *r_bytes_read = capfile->bytes_read;
263
264 if (capfile->fp == NULL)
265 return 100;
266 return (unsigned)(capfile->bytes_read*100/capfile->file_size);
267 }
268
269
270 /**
271 * Read the next packet from the file stream.
272 */
pcapfile_readframe(struct PcapFile * capfile,unsigned * r_time_secs,unsigned * r_time_usecs,unsigned * r_original_length,unsigned * r_captured_length,unsigned char * buf,unsigned sizeof_buf)273 int pcapfile_readframe(
274 struct PcapFile *capfile,
275 unsigned *r_time_secs,
276 unsigned *r_time_usecs,
277 unsigned *r_original_length,
278 unsigned *r_captured_length,
279 unsigned char *buf,
280 unsigned sizeof_buf
281 )
282 {
283 size_t bytes_read;
284 unsigned char header[16];
285 unsigned byte_order = capfile->byte_order;
286 unsigned is_corrupt = 0;
287
288 again:
289 /* Read in the 16-byte frame header. */
290 bytes_read = fread(header, 1, 16, capfile->fp);
291 if (bytes_read < 16) {
292 if (bytes_read <= 0) {
293 //fprintf(stderr, "%s: failed to read header\n", capfile->filename);
294 //perror(capfile->filename);
295 } else if (bytes_read == 0)
296 ; /* normal end-of-file */
297 else
298 fprintf(stderr, "%s: premature end-of-file\n", capfile->filename);
299 return 0;
300 }
301 capfile->bytes_read += bytes_read;
302
303 /* Parse the frame header into its four fields */
304 *r_time_secs = PCAP32(byte_order, header);
305 *r_time_usecs = PCAP32(byte_order, header+4);
306 *r_captured_length = PCAP32(byte_order, header+8);
307 *r_original_length = PCAP32(byte_order, header+12);
308
309
310 /* Test the frame heade fields to make sure they are sane */
311 if (*r_time_usecs > 1000100) {
312 if (*r_time_usecs < 1000100) {
313 *r_time_secs += 1;
314 *r_time_usecs -= 1000000;
315 } else if (*r_time_usecs > 0xFFFFFF00) {
316 *r_time_secs -= 1;
317 *r_time_usecs += 1000000;
318 *r_time_usecs &= 0xFFFFFFFF; /* mask off in case of 64-bit ints */
319 } else
320 is_corrupt = 1; /* shouldn't be more than 1-second, but some capture porgrams erroneously do that */
321 }
322 if (*r_time_usecs == 0
323 && *r_time_secs == 0
324 && *r_original_length == 0
325 && *r_captured_length == 0)
326 goto again;
327
328 if (*r_captured_length > sizeof_buf)
329 is_corrupt = 1;
330 if (*r_original_length < *r_captured_length)
331 is_corrupt = 1;
332 if (*r_original_length < 8)
333 is_corrupt = 1;
334 if (*r_original_length > 160000)
335 is_corrupt = 1;
336
337
338 /*
339 * If the file is corrupted, let's move forward in the
340 * stream and look for packets that aren't corrupted
341 */
342 while (is_corrupt) {
343 /* TODO: we should go backwards a bit in the file */
344 unsigned char tmp[16384];
345 int64_t position;
346 unsigned i;
347
348
349
350 /* Remember the current location. We are going to seek
351 * back to an offset from this location once we find a good
352 * packet.*/
353 position = ftell_x(capfile->fp);
354 if (position == -1) {
355 fprintf(stderr, "%s:%lld: could not resolve file corruption (ftell)\n",
356 capfile->filename, capfile->frame_number);
357 perror(capfile->filename);
358 fseek_x(capfile->fp, 0, SEEK_END);
359 return 0;
360 }
361
362 /* Print an error message indicating corruption was found. Note
363 * that if corruption happens past 4-gigs on a 32-bit system, this
364 * will print an inaccurate number */
365 fprintf(stderr, "%s:%lld: corruption found at 0x%08" PRIx64 " (%" PRId64 ")\n",
366 capfile->filename,
367 capfile->frame_number,
368 position,
369 position
370 );
371
372
373
374 /* Read in the next chunk of data following the corruption. We'll search
375 * this chunk looking for a non-corrupt packet */
376 bytes_read = fread(tmp, 1, sizeof(tmp), capfile->fp);
377
378 /* If we reach the end without finding a good frame, then stop */
379 if (bytes_read == 0) {
380 if (bytes_read <= 0) {
381 fprintf(stderr, "%s: error at end of file\n", capfile->filename);
382 perror(capfile->filename);
383 } else
384 fprintf(stderr, "%s: premature end of file\n", capfile->filename);
385 return 0;
386 }
387 capfile->bytes_read += bytes_read;
388
389 /* Scan forward (one byte at a time ) looking for a non-corrupt
390 * packet located at that spot */
391 for (i=0; i<bytes_read; i++) {
392
393 /* Test the current location */
394 if (!smells_like_valid_packet(tmp+i, (unsigned)(bytes_read-i), byte_order, capfile->linktype))
395 continue;
396
397 /* Woot! We have a non-corrupt packet. Let's now change the
398 * the current file-pointer to point to that location.
399 * Notice that we have to be careful when working with
400 * large (>4gig) files on 32-bit systems. The 'fpos_t' is
401 * usually a 64-bit value and can be used to set a position,
402 * but we cannot manipulate it directory (it's an opaque
403 * structure, not an integer), so we have seek back to the
404 * saved value, fthen seek relatively forward to the
405 * known-good spot */
406 position = position + i;
407 if (fseek_x(capfile->fp, position, SEEK_SET) != 0) {
408 fprintf(stderr, "%s: could not resolve file corruption (seek forward)\n", capfile->filename);
409 perror(capfile->filename);
410 fseek_x(capfile->fp, 0, SEEK_END);
411 return 0;
412 }
413
414 #if 0
415 /* We could stop here, but we are going to try one more thing.
416 * Most cases of corruption will be because the PREVOUS packet
417 * was truncated, not becausae the CURRENT packet was bad.
418 * Since we have seeked forward to find the NEXT packet, we
419 * want to now seek backwards and see if there is actually
420 * a good CURRENT packet. */
421 if (fseek(capfile->fp, -2000, SEEK_CUR) == 0) {
422 unsigned endpoint = 2000;
423 unsigned j;
424
425 /* We read in the 2000 bytes prior to the known-good
426 * packet that we discovered above, and also 16 bytes
427 * of the current frame (because the validity check
428 * looks for back-to-back good headers */
429 bytes_read = fread(tmp, 1, endpoint+16, capfile->fp);
430
431 /* Scan BACKWARDS through this chunk looking for a
432 * length field that points forward back to the known
433 * good packet */
434 for (j=0; j<endpoint-16; j++) {
435
436 /* Test the current 4-byte length field and see if it
437 * matches it's reverse offset. In other words, 108 bytes
438 * backwards in the data should be a 4-byte length field
439 * with a value of 100 */
440 if (PCAP32(byte_order, tmp+endpoint-j-8) != j)
441 continue;
442
443 /* Woot! Now that we have found the length field, let's
444 * test the rest of the data around this point to see
445 * if it also matches. Note that we are checking the
446 * PREVIOUS 16-byte header, PREVIOUS contents, and the
447 * CURRENT 16-byte header */
448 if (smells_like_valid_packet(tmp+endpoint-j-16, j+16+16, byte_order, capfile->linktype)) {
449 /* Woot! We have found a good packet. Let's now use that
450 * as the new location. */
451 fseek(capfile->fp, -(signed)(j+16+16), SEEK_CUR);
452 break;
453 }
454 }
455 } else {
456 /* Oops, there was an error seeking backwards. I'm
457 * not quite sure what to do here, so we are just
458 * going to repeat the reset of the file location
459 * that we did above */
460 if (fseek_x(capfile->fp, position, SEEK_SET) != 0) {
461 perror(capfile->filename);
462 fseek_x(capfile->fp, 0, SEEK_END);
463 return 0;
464 }
465 fseek_x(capfile->fp, i, SEEK_CUR);
466
467 }
468 #endif
469
470 /* Print a message saying we've found a good packet. This will
471 * help people figure out where in the file the corruption
472 * happened, so they can figure out why it was corrupt.*/
473 position = ftell_x(capfile->fp);
474 fprintf(stderr, "%s:%lld: good packet found at 0x%08" PRIx64 " (%" PRId64 ")\n",
475 capfile->filename,
476 capfile->frame_number,
477 position,
478 position
479 );
480
481 /* Recurse, continue reading from where we know a good
482 * packet is within the file */
483 return pcapfile_readframe(capfile, r_time_secs, r_time_usecs, r_original_length, r_captured_length, buf, sizeof_buf);
484 }
485
486 /* If we get to this point, we are totally hosed and the corruption
487 * is more severe than a few packets. */
488 printf("No valid packet found in chunk\n");
489 }
490
491 /*
492 * Read the packet data
493 */
494 bytes_read = fread(buf, 1, *r_captured_length, capfile->fp);
495 if (bytes_read < *r_captured_length) {
496 if (bytes_read <= 0) {
497 fprintf(stderr, "%s: could not read packet data, frame #%lld\n",
498 capfile->filename,
499 (long long)capfile->frame_number);
500 perror(capfile->filename);
501 } else
502 fprintf(stderr, "%s: premature end of file\n", capfile->filename);
503 return 0;
504 }
505 capfile->bytes_read += bytes_read;
506
507 if (capfile->frame_number == 0) {
508 capfile->start_sec = *r_time_secs;
509 capfile->start_usec = *r_time_usecs;
510 }
511 capfile->end_sec = *r_time_secs;
512 capfile->end_usec = *r_time_usecs;
513 capfile->frame_number++;
514 return 1;
515 }
516
pcapfile_get_timestamps(struct PcapFile * capfile,time_t * start,time_t * end)517 void pcapfile_get_timestamps(struct PcapFile *capfile, time_t *start, time_t *end)
518 {
519 *start = capfile->start_sec;
520 *end = capfile->end_sec;
521 }
522
523
524 /**
525 * Open a capture file for reading.
526 */
pcapfile_openread(const char * capfilename)527 struct PcapFile *pcapfile_openread(const char *capfilename)
528 {
529 FILE *fp;
530 size_t bytes_read;
531 unsigned char buf[24];
532 unsigned byte_order;
533 unsigned linktype;
534 uint64_t file_size = 0xFFFFffff;
535
536 if (capfilename == NULL)
537 return 0;
538
539 /*
540 * Open the file
541 */
542 fp = fopen(capfilename, "rb");
543 if (fp == NULL) {
544 fprintf(stderr, "%s: could not open capture file\n", capfilename);
545 perror(capfilename);
546 return 0;
547 }
548
549 /* Grab info about the file */
550 {
551 struct stat s;
552 memset(&s, 0, sizeof(s));
553 if (stat(capfilename, &s) == 0) {
554 file_size = s.st_size;
555 }
556 }
557
558 /*
559 * Read in the file header
560 */
561 bytes_read = fread(buf, 1, 24, fp);
562 if (bytes_read < 24) {
563 if (bytes_read <= 0) {
564 fprintf(stderr, "%s: could not read PCAP header\n", capfilename);
565 perror(capfilename);
566 } else
567 fprintf(stderr, "%s: file too short\n", capfilename);
568 fclose(fp);
569 return 0;
570 }
571
572 /*
573 * Find the "Magic Number", which will tell us what the byte-order
574 * is going to be. There are also odd magic number used by some
575 * speciality systems that hint at other features, such as a 64-bit
576 * version of the file.
577 */
578 switch (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]) {
579 case 0xa1b2c3d4: byte_order = CAPFILE_BIGENDIAN; break;
580 case 0xd4c3b2a1: byte_order = CAPFILE_LITTLEENDIAN; break;
581 default:
582 fprintf(stderr, "%s: unknown byte-order in cap file\n", capfilename);
583 byte_order = CAPFILE_ENDIANUNKNOWN; break;
584 }
585
586
587 /* Version (of the libpcap standard) */
588 {
589 unsigned major = PCAP16(byte_order, buf+4);
590 unsigned minor = PCAP16(byte_order, buf+6);
591
592 if (major != 2 || minor != 4)
593 fprintf(stderr, "%s: unknown version %d.%d\n", capfilename, major, minor);
594 }
595
596 /* Protocol (ethernet, wifi, etc.) */
597 linktype = PCAP32(byte_order, buf+20);
598 if (linktype == 0)
599 linktype = 1;
600 switch (linktype) {
601 case 0x7f: /* WiFi, with radiotap headers */
602 case 1: /*ethernet*/
603 case 0x69: /* WiFi, no radiotap headers */
604 case 119: /* Prism II headers (also used for things like Atheros madwifi) */
605 break;
606 default:
607 fprintf(stderr, "%s: unknown cap file linktype = %d (expected Ethernet or wifi)\n", capfilename, linktype);
608 fclose(fp);
609 return 0;
610 break;
611 }
612
613 /* Read the first frame's timestamp */
614 {
615 long loc;
616 char tsbuf[8];
617 size_t x;
618
619 loc = ftell(fp);
620 if (loc == -1) {
621 fprintf(stderr, "%s: ftell failed (file system error? seen with VMware HGFS bug)\n", capfilename);
622 perror(capfilename);
623 fclose(fp);
624 return 0;
625 }
626 x = fread(tsbuf, 1, 8, fp);
627 if (x != 8) {
628 perror(capfilename);
629 fclose(fp);
630 return 0;
631 }
632
633 if (fseek(fp, loc, SEEK_SET) != 0) {
634 fprintf(stderr, "%s: fseek failed (file system error?)\n", capfilename);
635 perror(capfilename);
636 fclose(fp);
637 return 0;
638 }
639 }
640
641 /*
642 * Now that the file is open and we have read in the header,
643 * allocate a structure that contains this information
644 * and return that structure.
645 */
646 {
647 struct PcapFile *capfile = 0;
648 capfile = (struct PcapFile*)malloc(sizeof(*capfile));
649 if (capfile == NULL)
650 exit(1);
651 memset(capfile,0,sizeof(*capfile));
652 capfile->byte_order = byte_order;
653
654 snprintf(capfile->filename, sizeof(capfile->filename),
655 "%s", capfilename);
656 capfile->fp = fp;
657 capfile->byte_order = byte_order;
658 capfile->linktype = linktype;
659 capfile->file_size = file_size;
660 capfile->bytes_read = 24; /*from the header*/
661 return capfile;
662 }
663 }
664
665
666 /**
667 * Open a capture file for writing
668 */
pcapfile_openwrite(const char * capfilename,unsigned linktype)669 struct PcapFile *pcapfile_openwrite(const char *capfilename, unsigned linktype)
670 {
671 char buf[] =
672 "\xd4\xc3\xb2\xa1\x02\x00\x04\x00"
673 "\x00\x00\x00\x00\x00\x00\x00\x00"
674 "\xff\xff\x00\x00\x69\x00\x00\x00";
675 FILE *fp;
676
677 buf[20] = (char)(linktype>>0);
678 buf[21] = (char)(linktype>>8);
679
680
681 fp = fopen(capfilename, "wb");
682 if (fp == NULL) {
683 fprintf(stderr, "Could not open capture file\n");
684 perror(capfilename);
685 return 0;
686 }
687
688
689 if (fwrite(buf, 1, 24, fp) != 24) {
690 fprintf(stderr, "Could not write capture file header\n");
691 perror(capfilename);
692 fclose(fp);
693 return 0;
694 }
695
696 {
697 struct PcapFile *capfile = 0;
698 capfile = (struct PcapFile*)malloc(sizeof(*capfile));
699 if (capfile == NULL)
700 exit(1);
701 memset(capfile,0,sizeof(*capfile));
702
703 snprintf(capfile->filename, sizeof(capfile->filename),
704 "%s", capfilename);
705
706 capfile->fp = fp;
707 capfile->byte_order = CAPFILE_LITTLEENDIAN;
708 capfile->linktype = linktype;
709 return capfile;
710 }
711
712 }
713
714 /**
715 * Open a capture file for "appending". This requires that we first
716 * read from it and find out how it's formatted, then figure out
717 * where the end of the file is so that we can start adding
718 * packets at that point.
719 */
pcapfile_openappend(const char * capfilename,unsigned linktype)720 struct PcapFile *pcapfile_openappend(const char *capfilename, unsigned linktype)
721 {
722 struct PcapFile *capfile;
723 unsigned char buf[24];
724 unsigned byte_order;
725 unsigned file_linktype;
726 FILE *fp;
727
728
729
730 /* open the file for appending and reading */
731 fp = fopen(capfilename, "ab+");
732 if (fp == NULL && errno == ENOENT) {
733 return pcapfile_openwrite(capfilename, linktype);
734 }
735 if (fp == NULL) {
736 fprintf(stderr, "Could not open capture file to append frame\n");
737 perror(capfilename);
738 return pcapfile_openappend(capfilename, linktype);
739 }
740
741 /* Read in the header to discover link type and byte order */
742 if (fread(buf, 1, 24, fp) != 24) {
743 fprintf(stderr, "Error reading capture file header\n");
744 perror(capfilename);
745 fclose(fp);
746 return pcapfile_openappend(capfilename, linktype);
747 }
748
749 /* Seek to the end of the file, where we will start writing
750 * frames from now on. Note that we aren't checking to see if the frames
751 * are corrupt at the end (which happens when the program crashes),
752 * so we may end up writing these frames in a way that cannot be read. */
753 if (fseek(fp, 0, SEEK_END) != 0) {
754 fprintf(stderr, "Could not seek to end of capture file\n");
755 perror(capfilename);
756 fclose(fp);
757 return 0;
758 }
759
760
761 /* Find out the byte order */
762 switch (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]) {
763 case 0xa1b2c3d4: byte_order = CAPFILE_BIGENDIAN; break;
764 case 0xd4c3b2a1: byte_order = CAPFILE_LITTLEENDIAN; break;
765 default:
766 fprintf(stderr, "%s: unknown byte-order in cap file\n", capfilename);
767 fclose(fp);
768 return pcapfile_openappend(capfilename, linktype);
769 }
770
771
772 /* Version */
773 {
774 unsigned major = PCAP16(byte_order, buf+4);
775 unsigned minor = PCAP16(byte_order, buf+6);
776
777 if (major != 2 || minor != 4)
778 fprintf(stderr, "%s: unknown version %u.%u\n", capfilename, major, minor);
779 }
780
781 /* Protocol */
782 file_linktype = PCAP32(byte_order, buf+20);
783 if (linktype != file_linktype) {
784 /* oops, the link types do not agree. Since we want a program to generate
785 * dumps while simultaneously processing multiple inputs, we are going to
786 * create a kludge. Instead of writing to the originally specified file,
787 * we are going to create a new file with the linktype added to it's name */
788 char linkspec[32];
789 size_t linkspec_length;
790 char newname[sizeof(capfile->filename)];
791 size_t i;
792
793 fclose(fp);
794
795 linkspec_length = snprintf(linkspec, sizeof(linkspec), "-linktype%d", linktype);
796
797 if (strstr(capfilename, linkspec) || strlen(capfilename) + linkspec_length + 1 > sizeof(newname)) {
798 /* Oops, we have a problem, it looks like the filename already
799 * has the previous linktype in its name for some reason. At this
800 * unlikely point, we just give up */
801 fprintf(stderr, "Giving up on appending %u-type frames onto a %u-type file\n",
802 linktype, file_linktype);
803 return 0;
804 }
805
806 if (strchr(capfilename, '.'))
807 i = strchr(capfilename, '.')-capfilename;
808 else
809 i = strlen(capfilename);
810
811 memcpy(newname, capfilename, i);
812 memcpy(newname+i, linkspec, linkspec_length);
813 memcpy(newname+i+linkspec_length, capfilename+i, strlen(capfilename+i)+1);
814
815 return pcapfile_openappend(newname, linktype);
816 }
817
818 /* Now that everything has checked out, create a file structure and
819 * return it */
820 {
821
822 capfile = (struct PcapFile*)malloc(sizeof(*capfile));
823 if (capfile == NULL)
824 exit(1);
825 memset(capfile,0,sizeof(*capfile));
826 capfile->byte_order = byte_order;
827 snprintf(capfile->filename, sizeof(capfile->filename),
828 "%s", capfilename);
829 capfile->fp = fp;
830 capfile->byte_order = byte_order;
831 capfile->linktype = linktype;
832 }
833
834 return capfile;
835 }
836
837
838 /**
839 * Close a capture file created by one of the open functions
840 * such as 'pcapfile_openread()', 'pcapfile_openwrite()', or
841 * 'pcapfile_openappend()'.
842 */
pcapfile_close(struct PcapFile * handle)843 void pcapfile_close(struct PcapFile *handle)
844 {
845 if (handle == NULL)
846 return;
847 if (handle->fp)
848 fclose(handle->fp);
849 free(handle);
850 }
851
852
853 /**
854 * Called to write a frame of data in libpcap format. This format has a
855 * 16-byte header (microseconds, seconds, sliced-length, original-length)
856 * followed by the captured data */
pcapfile_writeframe(struct PcapFile * capfile,const void * buffer,unsigned buffer_size,unsigned original_length,unsigned time_sec,unsigned time_usec)857 void pcapfile_writeframe(
858 struct PcapFile *capfile,
859 const void *buffer,
860 unsigned buffer_size,
861 unsigned original_length,
862 unsigned time_sec,
863 unsigned time_usec)
864 {
865 unsigned char header[16];
866
867 if (capfile == NULL || capfile->fp == NULL)
868 return;
869
870 /*
871 * Write timestamp
872 */
873 if (capfile->byte_order == CAPFILE_BIGENDIAN) {
874 header[ 0] = (unsigned char)(time_sec>>24);
875 header[ 1] = (unsigned char)(time_sec>>16);
876 header[ 2] = (unsigned char)(time_sec>> 8);
877 header[ 3] = (unsigned char)(time_sec>> 0);
878
879 header[ 4] = (unsigned char)(time_usec>>24);
880 header[ 5] = (unsigned char)(time_usec>>16);
881 header[ 6] = (unsigned char)(time_usec>> 8);
882 header[ 7] = (unsigned char)(time_usec>> 0);
883
884 header[ 8] = (unsigned char)(buffer_size>>24);
885 header[ 9] = (unsigned char)(buffer_size>>16);
886 header[10] = (unsigned char)(buffer_size>> 8);
887 header[11] = (unsigned char)(buffer_size>> 0);
888
889 header[12] = (unsigned char)(original_length>>24);
890 header[13] = (unsigned char)(original_length>>16);
891 header[14] = (unsigned char)(original_length>> 8);
892 header[15] = (unsigned char)(original_length>> 0);
893
894 } else {
895 header[ 0] = (unsigned char)(time_sec>> 0);
896 header[ 1] = (unsigned char)(time_sec>> 8);
897 header[ 2] = (unsigned char)(time_sec>>16);
898 header[ 3] = (unsigned char)(time_sec>>24);
899
900 header[ 4] = (unsigned char)(time_usec>> 0);
901 header[ 5] = (unsigned char)(time_usec>> 8);
902 header[ 6] = (unsigned char)(time_usec>>16);
903 header[ 7] = (unsigned char)(time_usec>>24);
904
905 header[ 8] = (unsigned char)(buffer_size>> 0);
906 header[ 9] = (unsigned char)(buffer_size>> 8);
907 header[10] = (unsigned char)(buffer_size>>16);
908 header[11] = (unsigned char)(buffer_size>>24);
909
910 header[12] = (unsigned char)(original_length>> 0);
911 header[13] = (unsigned char)(original_length>> 8);
912 header[14] = (unsigned char)(original_length>>16);
913 header[15] = (unsigned char)(original_length>>24);
914
915 }
916
917 if (fwrite(header, 1, 16, capfile->fp) != 16) {
918 fprintf(stderr, "%s:%lld: could not write packet header\n",
919 capfile->filename, capfile->frame_number);
920 perror(capfile->filename);
921 fclose(capfile->fp);
922 capfile->fp = NULL;
923 }
924
925 if (fwrite(buffer, 1, buffer_size, capfile->fp) != buffer_size) {
926 fprintf(stderr, "%s:%lld: could not write packet contents\n",
927 capfile->filename, capfile->frame_number);
928 perror(capfile->filename);
929 fclose(capfile->fp);
930 capfile->fp = NULL;
931 }
932 }
933
934