source: lib/format_pcapfile.c @ 3a333e2

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 3a333e2 was c69aecb, checked in by Shane Alcock <salcock@…>, 7 years ago

Handle incomplete file reads in libtrace formats

Some file read function calls assumed that the full amount that was
asked for will be read from the file, which is not necessarily true
especially if the file was truncated.

  • Property mode set to 100644
File size: 21.5 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34#include "common.h"
35#include "config.h"
36#include "libtrace.h"
37#include "libtrace_int.h"
38#include "format_helper.h"
39
40#include <sys/stat.h>
41#include <assert.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <stdbool.h>
48
49/* This format module implements our own, more efficient, version of the PCAP
50 * file format. This should always be used in preference to the "pcap" format
51 * provided in format_pcap.c.
52 *
53 * This is a trace file format and does not implement any live interface
54 * capture. This is covered by "pcapint" in format_pcap.c.
55 *
56 * This format supports both reading and writing, regardless of the version
57 * of your PCAP library.
58 */
59
60#define DATA(x) ((struct pcapfile_format_data_t*)((x)->format_data))
61#define DATAOUT(x) ((struct pcapfile_format_data_out_t*)((x)->format_data))
62#define IN_OPTIONS DATA(libtrace)->options
63
64typedef struct pcapfile_header_t {
65                uint32_t magic_number;   /* magic number */
66                uint16_t version_major;  /* major version number */
67                uint16_t version_minor;  /* minor version number */
68                int32_t  thiszone;       /* GMT to local correction */
69                uint32_t sigfigs;        /* timestamp accuracy */
70                uint32_t snaplen;        /* aka "wirelen" */
71                uint32_t network;        /* data link type */
72} pcapfile_header_t;
73
74#define MAGIC1      0xa1b2c3d4  /* Original */
75#define MAGIC2      0xa1b23c4d  /* Newer nanosecond format */
76#define MAGIC1_REV  0xd4c3b2a1  /* Reversed byteorder detection */
77#define MAGIC2_REV  0x4d3cb2a1
78
79static inline int header_is_backwards_magic(pcapfile_header_t *header) {
80        return (header->magic_number == MAGIC1_REV || header->magic_number == MAGIC2_REV);
81}
82
83static inline int header_is_magic(pcapfile_header_t *header) {
84        return (header->magic_number == MAGIC1 || header->magic_number == MAGIC2 ||
85                header_is_backwards_magic(header));
86}
87
88static inline int trace_in_nanoseconds(pcapfile_header_t *header) {
89        return (header->magic_number == MAGIC2 || header->magic_number == MAGIC2_REV);
90}
91
92struct pcapfile_format_data_t {
93        struct {
94                /* Indicates whether the event API should replicate the pauses
95                 * between packets */
96                int real_time;
97        } options;
98
99        /* The PCAP meta-header that should be written at the start of each
100         * trace */
101        pcapfile_header_t header;
102        /* Indicates whether the input trace is started */
103        bool started;
104};
105
106struct pcapfile_format_data_out_t {
107        iow_t *file;
108        int compress_type;
109        int level;
110        int flag;
111
112};
113
114static int pcapfile_probe_magic(io_t *io)
115{
116        pcapfile_header_t header;
117        int len;
118        len = wandio_peek(io, &header, sizeof(header));
119
120        /* Is this long enough? */
121        if (len < (int)sizeof(header)) {
122                return 0;
123        }
124        /* Pcap magic? */
125        if (header_is_magic(&header)) {
126                return 1;
127        }
128        /* Nope, not pcap */
129        return 0;
130}
131
132
133static int pcapfile_init_input(libtrace_t *libtrace) {
134        libtrace->format_data = malloc(sizeof(struct pcapfile_format_data_t));
135
136        if (libtrace->format_data == NULL) {
137                trace_set_err(libtrace,ENOMEM,"Out of memory");
138                return -1;
139        }
140
141        IN_OPTIONS.real_time = 0;
142        DATA(libtrace)->started = false;
143        return 0;
144}
145
146static int pcapfile_init_output(libtrace_out_t *libtrace) {
147        libtrace->format_data = 
148                malloc(sizeof(struct pcapfile_format_data_out_t));
149
150        DATAOUT(libtrace)->file=NULL;
151        DATAOUT(libtrace)->compress_type=TRACE_OPTION_COMPRESSTYPE_NONE;
152        DATAOUT(libtrace)->level=0;
153        DATAOUT(libtrace)->flag=O_CREAT|O_WRONLY;
154
155        return 0;
156}
157
158
159static inline uint16_t swaps(libtrace_t *libtrace, uint16_t num)
160{
161        /* To deal with open_dead traces that might try and use this
162         * if we don't have any per trace data, assume host byte order
163         */
164        if (!DATA(libtrace))
165                return num;
166       
167        /* We can use the PCAP magic number to determine the byte order */
168        if (header_is_backwards_magic(&(DATA(libtrace)->header)))
169                return byteswap16(num);
170
171        return num;
172}
173
174static inline uint32_t swapl(libtrace_t *libtrace, uint32_t num)
175{
176        /* To deal with open_dead traces that might try and use this
177         * if we don't have any per trace data, assume host byte order
178         */
179        if (!DATA(libtrace))
180                return num;
181       
182        /* We can use the PCAP magic number to determine the byte order */
183        if (header_is_backwards_magic(&(DATA(libtrace)->header)))
184                return byteswap32(num);
185
186        return num;
187}
188
189
190static int pcapfile_start_input(libtrace_t *libtrace) 
191{
192        int err;
193
194        if (!libtrace->io) {
195                libtrace->io=trace_open_file(libtrace);
196                DATA(libtrace)->started=false;
197        }
198
199        if (!DATA(libtrace)->started) {
200
201                if (!libtrace->io)
202                        return -1;
203
204                err=wandio_read(libtrace->io,
205                                &DATA(libtrace)->header,
206                                sizeof(DATA(libtrace)->header));
207
208                DATA(libtrace)->started = true;
209                assert(sizeof(DATA(libtrace)->header) > 0);
210               
211                if (err<1) {
212                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
213                                "Error while reading pcap file header\n");
214                        return -1;
215                }
216       
217                if (err != (int)sizeof(DATA(libtrace)->header)) {
218                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
219                                "Incomplete pcap file header");
220                        return -1;
221                }
222               
223                if (!header_is_magic(&(DATA(libtrace)->header))) {
224                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
225                                        "Not a pcap tracefile (magic=%08x)\n",swapl(libtrace,DATA(libtrace)->header.magic_number));
226                        return -1; /* Not a pcap file */
227                }
228
229                if (swaps(libtrace,DATA(libtrace)->header.version_major)!=2
230                        && swaps(libtrace,DATA(libtrace)->header.version_minor)!=4) {
231                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
232                                        "Unknown pcap tracefile version %d.%d\n",
233                                        swaps(libtrace,
234                                                DATA(libtrace)->header.version_major),
235                                        swaps(libtrace,
236                                                DATA(libtrace)->header.version_minor));
237                        return -1;
238                }
239
240        }
241
242        return 0;
243}
244
245static int pcapfile_start_output(libtrace_out_t *libtrace UNUSED)
246{
247        /* We can't open the output file until we've seen the first packet.
248         * This is because we need to know the DLT to set the "network"
249         * value in the meta-header */
250       
251        return 0;
252}
253
254static int pcapfile_config_input(libtrace_t *libtrace,
255                trace_option_t option,
256                void *data)
257{
258        switch(option) {
259                case TRACE_OPTION_EVENT_REALTIME:
260                        IN_OPTIONS.real_time = *(int *)data;
261                        return 0;
262                case TRACE_OPTION_META_FREQ:
263                case TRACE_OPTION_SNAPLEN:
264                case TRACE_OPTION_PROMISC:
265                case TRACE_OPTION_FILTER:
266                        /* All these are either unsupported or handled
267                         * by trace_config */
268                        break;
269        }
270       
271        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
272                        "Unknown option %i", option);
273        return -1;
274}
275
276static int pcapfile_fin_input(libtrace_t *libtrace) 
277{
278        if (libtrace->io)
279                wandio_destroy(libtrace->io);
280        free(libtrace->format_data);
281        return 0; /* success */
282}
283
284static int pcapfile_fin_output(libtrace_out_t *libtrace)
285{
286        if (DATAOUT(libtrace)->file)
287                wandio_wdestroy(DATAOUT(libtrace)->file);
288        free(libtrace->format_data);
289        libtrace->format_data=NULL;
290        return 0; /* success */
291}
292
293static int pcapfile_config_output(libtrace_out_t *libtrace,
294                trace_option_output_t option,
295                void *value)
296{
297        switch (option) {
298                case TRACE_OPTION_OUTPUT_COMPRESS:
299                        DATAOUT(libtrace)->level = *(int*)value;
300                        return 0;
301                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
302                        DATAOUT(libtrace)->compress_type = *(int*)value;
303                        return 0;
304                case TRACE_OPTION_OUTPUT_FILEFLAGS:
305                        DATAOUT(libtrace)->flag = *(int*)value;
306                        return 0;
307                default:
308                        /* Unknown option */
309                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
310                                        "Unknown option");
311                        return -1;
312        }
313        return -1;
314}
315
316static int pcapfile_prepare_packet(libtrace_t *libtrace, 
317                libtrace_packet_t *packet, void *buffer, 
318                libtrace_rt_types_t rt_type, uint32_t flags) {
319
320        if (packet->buffer != buffer && 
321                        packet->buf_control == TRACE_CTRL_PACKET) {
322                free(packet->buffer);
323        }
324
325        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
326                packet->buf_control = TRACE_CTRL_PACKET;
327        } else
328                packet->buf_control = TRACE_CTRL_EXTERNAL;
329       
330       
331        packet->buffer = buffer;
332        packet->header = buffer;
333        packet->payload = (char*)packet->buffer
334                + sizeof(libtrace_pcapfile_pkt_hdr_t);
335        packet->type = rt_type; 
336
337        if (libtrace->format_data == NULL) {
338                if (pcapfile_init_input(libtrace))
339                        return -1;
340        }
341       
342        return 0;
343}
344
345static int pcapfile_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
346{
347        int err;
348        uint32_t flags = 0;
349        size_t bytes_to_read = 0;
350
351        assert(libtrace->format_data);
352
353        packet->type = pcap_linktype_to_rt(swapl(libtrace,
354                                DATA(libtrace)->header.network));
355
356        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
357                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
358        }
359
360        flags |= TRACE_PREP_OWN_BUFFER;
361       
362        err=wandio_read(libtrace->io,
363                        packet->buffer,
364                        sizeof(libtrace_pcapfile_pkt_hdr_t));
365        if (err<0) {
366                trace_set_err(libtrace,errno,"reading packet");
367                return -1;
368        }
369        if (err==0) {
370                /* EOF */
371                return 0;
372        }
373
374        if (err < (int)sizeof(libtrace_pcapfile_pkt_hdr_t)) {
375                trace_set_err(libtrace, errno, "Incomplete pcap packet header");
376                return -1;
377        }
378
379        bytes_to_read = swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen);
380
381        if (bytes_to_read >= LIBTRACE_PACKET_BUFSIZE) {
382                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Invalid caplen in pcap header (%u) - trace may be corrupt", (uint32_t)bytes_to_read);
383                return -1;
384        }
385
386        assert(bytes_to_read < LIBTRACE_PACKET_BUFSIZE);
387
388        /* If there is no payload to read, do not ask wandio_read to try and
389         * read zero bytes - we'll just get back a zero that we will
390         * misinterpret as EOF! */
391        if (bytes_to_read == 0) {
392                packet->header = packet->buffer;
393                return sizeof(libtrace_pcapfile_pkt_hdr_t);
394        }
395
396        err=wandio_read(libtrace->io,
397                        (char*)packet->buffer+sizeof(libtrace_pcapfile_pkt_hdr_t),
398                        (size_t)swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen)
399                        );
400
401        if (err<0) {
402                trace_set_err(libtrace,errno,"reading packet");
403                return -1;
404        }
405        if (err==0) {
406                return 0;
407        }
408
409        if (err < (int)bytes_to_read) {
410                trace_set_err(libtrace, errno, "Incomplete pcap packet body");
411                return -1;
412        }
413
414        if (pcapfile_prepare_packet(libtrace, packet, packet->buffer,
415                                packet->type, flags)) {
416                return -1;
417        }
418
419        /* We may as well cache this value now, seeing as we already had to
420         * look it up */
421        packet->capture_length = bytes_to_read; 
422        return sizeof(libtrace_pcapfile_pkt_hdr_t) + bytes_to_read;
423}
424
425static int pcapfile_write_packet(libtrace_out_t *out,
426                libtrace_packet_t *packet)
427{
428        struct libtrace_pcapfile_pkt_hdr_t hdr;
429        struct timeval tv = trace_get_timeval(packet);
430        int numbytes;
431        int ret;
432        void *ptr;
433        uint32_t remaining;
434        libtrace_linktype_t linktype;
435
436        ptr = trace_get_packet_buffer(packet,&linktype,&remaining);
437       
438        /* Silently discard RT metadata packets and packets with an
439         * unknown linktype. */
440        if (linktype == TRACE_TYPE_NONDATA || linktype == TRACE_TYPE_UNKNOWN) {
441                return 0;
442        }
443
444        /* If this packet cannot be converted to a pcap linktype then
445         * pop off the top header until it can be converted
446         */
447        while (libtrace_to_pcap_linktype(linktype)==TRACE_DLT_ERROR) {
448                if (!demote_packet(packet)) {
449                        trace_set_err_out(out, 
450                                TRACE_ERR_NO_CONVERSION,
451                                "pcap does not support this format");
452                        assert(0);
453                        return -1;
454                }
455
456                ptr = trace_get_packet_buffer(packet,&linktype,&remaining);
457        }
458
459
460        /* Now we know the link type write out a header if we've not done
461         * so already
462         */
463        if (!DATAOUT(out)->file) {
464                struct pcapfile_header_t pcaphdr;
465
466                DATAOUT(out)->file=trace_open_file_out(out,
467                                DATAOUT(out)->compress_type,
468                                DATAOUT(out)->level,
469                                DATAOUT(out)->flag);
470
471                if (!DATAOUT(out)->file) {
472                        trace_set_err_out(out,errno,"Unable to open file");
473                        return -1;
474                }
475
476                pcaphdr.magic_number = 0xa1b2c3d4;
477                pcaphdr.version_major = 2;
478                pcaphdr.version_minor = 4;
479                pcaphdr.thiszone = 0;
480                pcaphdr.sigfigs = 0;
481                pcaphdr.snaplen = 65536;
482                pcaphdr.network = 
483                        libtrace_to_pcap_linktype(linktype);
484
485                wandio_wwrite(DATAOUT(out)->file, 
486                                &pcaphdr, sizeof(pcaphdr));
487        }
488
489
490        hdr.ts_sec = (uint32_t)tv.tv_sec;
491        hdr.ts_usec = (uint32_t)tv.tv_usec;
492        hdr.caplen = trace_get_capture_length(packet);
493        assert(hdr.caplen < LIBTRACE_PACKET_BUFSIZE);
494        /* PCAP doesn't include the FCS in its wire length value, but we do */
495        if (linktype==TRACE_TYPE_ETH) {
496                if (trace_get_wire_length(packet) >= 4) {
497                        hdr.wirelen = trace_get_wire_length(packet)-4;
498                }
499                else {
500                        hdr.wirelen = 0;
501                }
502        }
503        else
504                hdr.wirelen = trace_get_wire_length(packet);
505
506        /* Reason for removing this assert:
507         *
508         * There exist some packets, e.g. in IPLS II, where the wire length
509         * is clearly corrupt. When converting to pcap, we *could* try to
510         * adjust the wire length to something sane but for now, I'll just let
511         * the broken length persist through the conversion.
512         *
513         * XXX Is setting the wire length to zero the best solution in such
514         * cases?
515         */
516
517        /* assert(hdr.wirelen < LIBTRACE_PACKET_BUFSIZE); */
518
519        /* Ensure we have a valid capture length, especially if we're going
520         * to "remove" the FCS from the wire length */
521        if (hdr.caplen > hdr.wirelen)
522                hdr.caplen = hdr.wirelen;
523
524        /* Write the packet header */
525        numbytes=wandio_wwrite(DATAOUT(out)->file,
526                        &hdr, sizeof(hdr));
527
528        if (numbytes!=sizeof(hdr)) 
529                return -1;
530
531        /* Write the rest of the packet now */
532        ret=wandio_wwrite(DATAOUT(out)->file,
533                        ptr,
534                        hdr.caplen);
535
536        if (ret!=(int)hdr.caplen)
537                return -1;
538
539        return numbytes+ret;
540}
541
542static libtrace_linktype_t pcapfile_get_link_type(
543                const libtrace_packet_t *packet) 
544{
545        return pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type));
546}
547
548static libtrace_direction_t pcapfile_get_direction(const libtrace_packet_t *packet) 
549{
550        libtrace_direction_t direction  = -1;
551        switch(pcapfile_get_link_type(packet)) {
552                /* We can only get the direction for PCAP packets that have
553                 * been encapsulated in Linux SLL or PFLOG */
554                case TRACE_TYPE_LINUX_SLL:
555                {
556                        libtrace_sll_header_t *sll;
557                        libtrace_linktype_t linktype;
558
559                        sll = (libtrace_sll_header_t*)trace_get_packet_buffer(
560                                        packet,
561                                        &linktype,
562                                        NULL);
563                        if (!sll) {
564                                trace_set_err(packet->trace,
565                                        TRACE_ERR_BAD_PACKET,
566                                                "Bad or missing packet");
567                                return -1;
568                        }
569                        /* 0 == LINUX_SLL_HOST */
570                        /* the Waikato Capture point defines "packets
571                         * originating locally" (ie, outbound), with a
572                         * direction of 0, and "packets destined locally"
573                         * (ie, inbound), with a direction of 1.
574                         * This is kind-of-opposite to LINUX_SLL.
575                         * We return consistent values here, however
576                         *
577                         * Note that in recent versions of pcap, you can
578                         * use "inbound" and "outbound" on ppp in linux
579                         */
580                        if (ntohs(sll->pkttype == 0)) {
581                                direction = TRACE_DIR_INCOMING;
582                        } else {
583                                direction = TRACE_DIR_OUTGOING;
584                        }
585                        break;
586
587                }
588                case TRACE_TYPE_PFLOG:
589                {
590                        libtrace_pflog_header_t *pflog;
591                        libtrace_linktype_t linktype;
592
593                        pflog=(libtrace_pflog_header_t*)trace_get_packet_buffer(
594                                        packet,&linktype,NULL);
595                        if (!pflog) {
596                                trace_set_err(packet->trace,
597                                                TRACE_ERR_BAD_PACKET,
598                                                "Bad or missing packet");
599                                return -1;
600                        }
601                        /* enum    { PF_IN=0, PF_OUT=1 }; */
602                        if (ntohs(pflog->dir==0)) {
603
604                                direction = TRACE_DIR_INCOMING;
605                        }
606                        else {
607                                direction = TRACE_DIR_OUTGOING;
608                        }
609                        break;
610                }
611                default:
612                        break;
613        }       
614        return direction;
615}
616
617
618static struct timeval pcapfile_get_timeval(
619                const libtrace_packet_t *packet) 
620{
621        libtrace_pcapfile_pkt_hdr_t *hdr;
622        struct timeval ts;
623       
624        assert(packet->header);
625       
626        hdr = (libtrace_pcapfile_pkt_hdr_t*)packet->header;
627        ts.tv_sec = swapl(packet->trace,hdr->ts_sec);
628        /* Check trace is not a dummy calling trace_in_nanoseconds */
629        if (DATA(packet->trace) && trace_in_nanoseconds(&DATA(packet->trace)->header))
630                ts.tv_usec = swapl(packet->trace, hdr->ts_usec) / 1000;
631        else
632                ts.tv_usec = swapl(packet->trace,hdr->ts_usec);
633        return ts;
634}
635
636static struct timespec pcapfile_get_timespec(
637                const libtrace_packet_t *packet) 
638{
639        libtrace_pcapfile_pkt_hdr_t *hdr;
640        struct timespec ts;
641       
642        assert(packet->header);
643       
644        hdr = (libtrace_pcapfile_pkt_hdr_t*)packet->header;
645        ts.tv_sec = swapl(packet->trace,hdr->ts_sec);
646        /* Check trace is not a dummy calling trace_in_nanoseconds */
647        if (DATA(packet->trace) && trace_in_nanoseconds(&DATA(packet->trace)->header))
648                ts.tv_nsec = swapl(packet->trace, hdr->ts_usec);
649        else
650                ts.tv_nsec = swapl(packet->trace, hdr->ts_usec) * 1000;
651        return ts;
652}
653
654
655static int pcapfile_get_capture_length(const libtrace_packet_t *packet) {
656        libtrace_pcapfile_pkt_hdr_t *pcapptr; 
657
658        assert(packet->header);
659        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
660
661        return swapl(packet->trace,pcapptr->caplen);
662}
663
664static int pcapfile_get_wire_length(const libtrace_packet_t *packet) {
665        libtrace_pcapfile_pkt_hdr_t *pcapptr;
666
667        assert(packet->header); 
668
669        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
670        if (packet->type==pcap_linktype_to_rt(TRACE_DLT_EN10MB))
671                /* Include the missing FCS */
672                return swapl(packet->trace,pcapptr->wirelen)+4; 
673        else if (packet->type==pcap_linktype_to_rt(TRACE_DLT_IEEE802_11_RADIO)){
674                /* If the packet is Radiotap and the flags field indicates
675                 * that the FCS is not included in the 802.11 frame, then
676                 * we need to add 4 to the wire-length to account for it.
677                 */
678                uint8_t flags;
679                void *link;
680                libtrace_linktype_t linktype;
681                link = trace_get_packet_buffer(packet, &linktype, NULL);
682                trace_get_wireless_flags(link, linktype, &flags);
683                if ((flags & TRACE_RADIOTAP_F_FCS) == 0)
684                        return swapl(packet->trace,pcapptr->wirelen)+4;
685        } else if (packet->type == pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL)) {
686                libtrace_sll_header_t *sll;
687                sll = (libtrace_sll_header_t *)packet->payload;
688
689                /* Account for FCS when dealing with Ethernet packets that are
690                 * encapsulated in Linux SLL. This should fix the problem
691                 * where the wire lengths differ if we convert the packet to
692                 * ERF */
693                if (ntohs(sll->protocol) == TRACE_ETHERTYPE_LOOPBACK)
694                        return swapl(packet->trace,pcapptr->wirelen)+4;
695        }
696
697        return swapl(packet->trace,pcapptr->wirelen);
698}
699
700static int pcapfile_get_framing_length(const libtrace_packet_t *packet UNUSED) {
701        return sizeof(libtrace_pcapfile_pkt_hdr_t);
702}
703
704static size_t pcapfile_set_capture_length(libtrace_packet_t *packet,size_t size) {
705        libtrace_pcapfile_pkt_hdr_t *pcapptr = 0;
706        assert(packet);
707        assert(packet->header);
708        if (size > trace_get_capture_length(packet)) {
709                /* Can't make a packet larger */
710                return trace_get_capture_length(packet);
711        }
712        /* Reset the cached capture length */
713        packet->capture_length = -1;
714        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
715        pcapptr->caplen = swapl(packet->trace,(uint32_t)size);
716        return trace_get_capture_length(packet);
717}
718
719static struct libtrace_eventobj_t pcapfile_event(libtrace_t *libtrace, libtrace_packet_t *packet) {
720       
721        libtrace_eventobj_t event = {0,0,0.0,0};
722       
723        /* If we are being told to replay packets as fast as possible, then
724         * we just need to read and return the next packet in the trace */
725
726        if (IN_OPTIONS.real_time) {
727                event.size = trace_read_packet(libtrace, packet);
728                if (event.size < 1)
729                        event.type = TRACE_EVENT_TERMINATE;
730                else
731                        event.type = TRACE_EVENT_PACKET;
732                return event;
733        } else {
734                return trace_event_trace(libtrace, packet);
735        }
736}
737
738static void pcapfile_help(void) {
739        printf("pcapfile format module: $Revision: 1768 $\n");
740        printf("Supported input URIs:\n");
741        printf("\tpcapfile:/path/to/file\n");
742        printf("\tpcapfile:/path/to/file.gz\n");
743        printf("\n");
744        printf("\te.g.: pcapfile:/tmp/trace.pcap\n");
745        printf("\n");
746}
747
748static struct libtrace_format_t pcapfile = {
749        "pcapfile",
750        "$Id$",
751        TRACE_FORMAT_PCAPFILE,
752        NULL,                           /* probe filename */
753        pcapfile_probe_magic,           /* probe magic */
754        pcapfile_init_input,            /* init_input */
755        pcapfile_config_input,          /* config_input */
756        pcapfile_start_input,           /* start_input */
757        NULL,                           /* pause_input */
758        pcapfile_init_output,           /* init_output */
759        pcapfile_config_output,         /* config_output */
760        pcapfile_start_output,          /* start_output */
761        pcapfile_fin_input,             /* fin_input */
762        pcapfile_fin_output,            /* fin_output */
763        pcapfile_read_packet,           /* read_packet */
764        pcapfile_prepare_packet,        /* prepare_packet */
765        NULL,                           /* fin_packet */
766        pcapfile_write_packet,          /* write_packet */
767        pcapfile_get_link_type,         /* get_link_type */
768        pcapfile_get_direction,         /* get_direction */
769        NULL,                           /* set_direction */
770        NULL,                           /* get_erf_timestamp */
771        pcapfile_get_timeval,           /* get_timeval */
772        pcapfile_get_timespec,          /* get_timespec */
773        NULL,                           /* get_seconds */
774        NULL,                           /* seek_erf */
775        NULL,                           /* seek_timeval */
776        NULL,                           /* seek_seconds */
777        pcapfile_get_capture_length,    /* get_capture_length */
778        pcapfile_get_wire_length,       /* get_wire_length */
779        pcapfile_get_framing_length,    /* get_framing_length */
780        pcapfile_set_capture_length,    /* set_capture_length */
781        NULL,                           /* get_received_packets */
782        NULL,                           /* get_filtered_packets */
783        NULL,                           /* get_dropped_packets */
784        NULL,                           /* get_captured_packets */
785        NULL,                           /* get_fd */
786        pcapfile_event,         /* trace_event */
787        pcapfile_help,                  /* help */
788        NULL                            /* next pointer */
789};
790
791
792void pcapfile_constructor(void) {
793        register_format(&pcapfile);
794}
795
796
Note: See TracBrowser for help on using the repository browser.