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