source: lib/format_pcapfile.c @ c70f59f

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

Don't increment accepted_packets in trace_event

For formats that use the normal trace_event_device and
trace_event_trace functions to implement trace_event functionality,
this was resulting in accepted_packets being incremented twice:
once in the call to trace_read_packet within the standard event
function and once again in trace_event.

Removed the increment from trace_event and updated all formats
that provide a custom trace_event implementation to make sure they
either call trace_read_packet themselves or update the counters
properly (with the former preferred wherever possible).

Thanks to Alistair King for finding this bug.

  • Property mode set to 100644
File size: 21.0 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                        if (err == 0) {
213                                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
214                                                "Reading pcap file header\n");
215                        }
216                        return -1;
217                }
218               
219                if (!header_is_magic(&(DATA(libtrace)->header))) {
220                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
221                                        "Not a pcap tracefile (magic=%08x)\n",swapl(libtrace,DATA(libtrace)->header.magic_number));
222                        return -1; /* Not a pcap file */
223                }
224
225                if (swaps(libtrace,DATA(libtrace)->header.version_major)!=2
226                        && swaps(libtrace,DATA(libtrace)->header.version_minor)!=4) {
227                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
228                                        "Unknown pcap tracefile version %d.%d\n",
229                                        swaps(libtrace,
230                                                DATA(libtrace)->header.version_major),
231                                        swaps(libtrace,
232                                                DATA(libtrace)->header.version_minor));
233                        return -1;
234                }
235
236        }
237
238        return 0;
239}
240
241static int pcapfile_start_output(libtrace_out_t *libtrace UNUSED)
242{
243        /* We can't open the output file until we've seen the first packet.
244         * This is because we need to know the DLT to set the "network"
245         * value in the meta-header */
246       
247        return 0;
248}
249
250static int pcapfile_config_input(libtrace_t *libtrace,
251                trace_option_t option,
252                void *data)
253{
254        switch(option) {
255                case TRACE_OPTION_EVENT_REALTIME:
256                        IN_OPTIONS.real_time = *(int *)data;
257                        return 0;
258                case TRACE_OPTION_META_FREQ:
259                case TRACE_OPTION_SNAPLEN:
260                case TRACE_OPTION_PROMISC:
261                case TRACE_OPTION_FILTER:
262                        /* All these are either unsupported or handled
263                         * by trace_config */
264                        break;
265        }
266       
267        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
268                        "Unknown option %i", option);
269        return -1;
270}
271
272static int pcapfile_fin_input(libtrace_t *libtrace) 
273{
274        if (libtrace->io)
275                wandio_destroy(libtrace->io);
276        free(libtrace->format_data);
277        return 0; /* success */
278}
279
280static int pcapfile_fin_output(libtrace_out_t *libtrace)
281{
282        if (DATAOUT(libtrace)->file)
283                wandio_wdestroy(DATAOUT(libtrace)->file);
284        free(libtrace->format_data);
285        libtrace->format_data=NULL;
286        return 0; /* success */
287}
288
289static int pcapfile_config_output(libtrace_out_t *libtrace,
290                trace_option_output_t option,
291                void *value)
292{
293        switch (option) {
294                case TRACE_OPTION_OUTPUT_COMPRESS:
295                        DATAOUT(libtrace)->level = *(int*)value;
296                        return 0;
297                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
298                        DATAOUT(libtrace)->compress_type = *(int*)value;
299                        return 0;
300                case TRACE_OPTION_OUTPUT_FILEFLAGS:
301                        DATAOUT(libtrace)->flag = *(int*)value;
302                        return 0;
303                default:
304                        /* Unknown option */
305                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
306                                        "Unknown option");
307                        return -1;
308        }
309        return -1;
310}
311
312static int pcapfile_prepare_packet(libtrace_t *libtrace, 
313                libtrace_packet_t *packet, void *buffer, 
314                libtrace_rt_types_t rt_type, uint32_t flags) {
315
316        if (packet->buffer != buffer && 
317                        packet->buf_control == TRACE_CTRL_PACKET) {
318                free(packet->buffer);
319        }
320
321        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
322                packet->buf_control = TRACE_CTRL_PACKET;
323        } else
324                packet->buf_control = TRACE_CTRL_EXTERNAL;
325       
326       
327        packet->buffer = buffer;
328        packet->header = buffer;
329        packet->payload = (char*)packet->buffer
330                + sizeof(libtrace_pcapfile_pkt_hdr_t);
331        packet->type = rt_type; 
332
333        if (libtrace->format_data == NULL) {
334                if (pcapfile_init_input(libtrace))
335                        return -1;
336        }
337       
338        return 0;
339}
340
341static int pcapfile_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
342{
343        int err;
344        uint32_t flags = 0;
345        size_t bytes_to_read = 0;
346
347        assert(libtrace->format_data);
348
349        packet->type = pcap_linktype_to_rt(swapl(libtrace,
350                                DATA(libtrace)->header.network));
351
352        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
353                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
354        }
355
356        flags |= TRACE_PREP_OWN_BUFFER;
357       
358        err=wandio_read(libtrace->io,
359                        packet->buffer,
360                        sizeof(libtrace_pcapfile_pkt_hdr_t));
361
362        if (err<0) {
363                trace_set_err(libtrace,errno,"reading packet");
364                return -1;
365        }
366        if (err==0) {
367                /* EOF */
368                return 0;
369        }
370
371        bytes_to_read = swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen);
372
373        if (bytes_to_read >= LIBTRACE_PACKET_BUFSIZE) {
374                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Invalid caplen in pcap header (%u) - trace may be corrupt", (uint32_t)bytes_to_read);
375                return -1;
376        }
377
378        assert(bytes_to_read < LIBTRACE_PACKET_BUFSIZE);
379
380        /* If there is no payload to read, do not ask wandio_read to try and
381         * read zero bytes - we'll just get back a zero that we will
382         * misinterpret as EOF! */
383        if (bytes_to_read == 0) {
384                packet->header = packet->buffer;
385                return sizeof(libtrace_pcapfile_pkt_hdr_t);
386        }
387
388        err=wandio_read(libtrace->io,
389                        (char*)packet->buffer+sizeof(libtrace_pcapfile_pkt_hdr_t),
390                        (size_t)swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen)
391                        );
392
393       
394        if (err<0) {
395                trace_set_err(libtrace,errno,"reading packet");
396                return -1;
397        }
398        if (err==0) {
399                return 0;
400        }
401
402        if (pcapfile_prepare_packet(libtrace, packet, packet->buffer,
403                                packet->type, flags)) {
404                return -1;
405        }
406
407        /* We may as well cache this value now, seeing as we already had to
408         * look it up */
409        packet->capture_length = bytes_to_read; 
410        return sizeof(libtrace_pcapfile_pkt_hdr_t) + bytes_to_read;
411}
412
413static int pcapfile_write_packet(libtrace_out_t *out,
414                libtrace_packet_t *packet)
415{
416        struct libtrace_pcapfile_pkt_hdr_t hdr;
417        struct timeval tv = trace_get_timeval(packet);
418        int numbytes;
419        int ret;
420        void *ptr;
421        uint32_t remaining;
422        libtrace_linktype_t linktype;
423
424        ptr = trace_get_packet_buffer(packet,&linktype,&remaining);
425       
426        /* Silently discard RT metadata packets and packets with an
427         * unknown linktype. */
428        if (linktype == TRACE_TYPE_NONDATA || linktype == TRACE_TYPE_UNKNOWN) {
429                return 0;
430        }
431
432        /* If this packet cannot be converted to a pcap linktype then
433         * pop off the top header until it can be converted
434         */
435        while (libtrace_to_pcap_linktype(linktype)==TRACE_DLT_ERROR) {
436                if (!demote_packet(packet)) {
437                        trace_set_err_out(out, 
438                                TRACE_ERR_NO_CONVERSION,
439                                "pcap does not support this format");
440                        assert(0);
441                        return -1;
442                }
443
444                ptr = trace_get_packet_buffer(packet,&linktype,&remaining);
445        }
446
447
448        /* Now we know the link type write out a header if we've not done
449         * so already
450         */
451        if (!DATAOUT(out)->file) {
452                struct pcapfile_header_t pcaphdr;
453
454                DATAOUT(out)->file=trace_open_file_out(out,
455                                DATAOUT(out)->compress_type,
456                                DATAOUT(out)->level,
457                                DATAOUT(out)->flag);
458
459                if (!DATAOUT(out)->file) {
460                        trace_set_err_out(out,errno,"Unable to open file");
461                        return -1;
462                }
463
464                pcaphdr.magic_number = 0xa1b2c3d4;
465                pcaphdr.version_major = 2;
466                pcaphdr.version_minor = 4;
467                pcaphdr.thiszone = 0;
468                pcaphdr.sigfigs = 0;
469                pcaphdr.snaplen = 65536;
470                pcaphdr.network = 
471                        libtrace_to_pcap_linktype(linktype);
472
473                wandio_wwrite(DATAOUT(out)->file, 
474                                &pcaphdr, sizeof(pcaphdr));
475        }
476
477
478        hdr.ts_sec = (uint32_t)tv.tv_sec;
479        hdr.ts_usec = (uint32_t)tv.tv_usec;
480        hdr.caplen = trace_get_capture_length(packet);
481        assert(hdr.caplen < LIBTRACE_PACKET_BUFSIZE);
482        /* PCAP doesn't include the FCS in its wire length value, but we do */
483        if (linktype==TRACE_TYPE_ETH) {
484                if (trace_get_wire_length(packet) >= 4) {
485                        hdr.wirelen = trace_get_wire_length(packet)-4;
486                }
487                else {
488                        hdr.wirelen = 0;
489                }
490        }
491        else
492                hdr.wirelen = trace_get_wire_length(packet);
493
494        /* Reason for removing this assert:
495         *
496         * There exist some packets, e.g. in IPLS II, where the wire length
497         * is clearly corrupt. When converting to pcap, we *could* try to
498         * adjust the wire length to something sane but for now, I'll just let
499         * the broken length persist through the conversion.
500         *
501         * XXX Is setting the wire length to zero the best solution in such
502         * cases?
503         */
504
505        /* assert(hdr.wirelen < LIBTRACE_PACKET_BUFSIZE); */
506
507        /* Ensure we have a valid capture length, especially if we're going
508         * to "remove" the FCS from the wire length */
509        if (hdr.caplen > hdr.wirelen)
510                hdr.caplen = hdr.wirelen;
511
512        /* Write the packet header */
513        numbytes=wandio_wwrite(DATAOUT(out)->file,
514                        &hdr, sizeof(hdr));
515
516        if (numbytes!=sizeof(hdr)) 
517                return -1;
518
519        /* Write the rest of the packet now */
520        ret=wandio_wwrite(DATAOUT(out)->file,
521                        ptr,
522                        hdr.caplen);
523
524        if (ret!=(int)hdr.caplen)
525                return -1;
526
527        return numbytes+ret;
528}
529
530static libtrace_linktype_t pcapfile_get_link_type(
531                const libtrace_packet_t *packet) 
532{
533        return pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type));
534}
535
536static libtrace_direction_t pcapfile_get_direction(const libtrace_packet_t *packet) 
537{
538        libtrace_direction_t direction  = -1;
539        switch(pcapfile_get_link_type(packet)) {
540                /* We can only get the direction for PCAP packets that have
541                 * been encapsulated in Linux SLL or PFLOG */
542                case TRACE_TYPE_LINUX_SLL:
543                {
544                        libtrace_sll_header_t *sll;
545                        libtrace_linktype_t linktype;
546
547                        sll = (libtrace_sll_header_t*)trace_get_packet_buffer(
548                                        packet,
549                                        &linktype,
550                                        NULL);
551                        if (!sll) {
552                                trace_set_err(packet->trace,
553                                        TRACE_ERR_BAD_PACKET,
554                                                "Bad or missing packet");
555                                return -1;
556                        }
557                        /* 0 == LINUX_SLL_HOST */
558                        /* the Waikato Capture point defines "packets
559                         * originating locally" (ie, outbound), with a
560                         * direction of 0, and "packets destined locally"
561                         * (ie, inbound), with a direction of 1.
562                         * This is kind-of-opposite to LINUX_SLL.
563                         * We return consistent values here, however
564                         *
565                         * Note that in recent versions of pcap, you can
566                         * use "inbound" and "outbound" on ppp in linux
567                         */
568                        if (ntohs(sll->pkttype == 0)) {
569                                direction = TRACE_DIR_INCOMING;
570                        } else {
571                                direction = TRACE_DIR_OUTGOING;
572                        }
573                        break;
574
575                }
576                case TRACE_TYPE_PFLOG:
577                {
578                        libtrace_pflog_header_t *pflog;
579                        libtrace_linktype_t linktype;
580
581                        pflog=(libtrace_pflog_header_t*)trace_get_packet_buffer(
582                                        packet,&linktype,NULL);
583                        if (!pflog) {
584                                trace_set_err(packet->trace,
585                                                TRACE_ERR_BAD_PACKET,
586                                                "Bad or missing packet");
587                                return -1;
588                        }
589                        /* enum    { PF_IN=0, PF_OUT=1 }; */
590                        if (ntohs(pflog->dir==0)) {
591
592                                direction = TRACE_DIR_INCOMING;
593                        }
594                        else {
595                                direction = TRACE_DIR_OUTGOING;
596                        }
597                        break;
598                }
599                default:
600                        break;
601        }       
602        return direction;
603}
604
605
606static struct timeval pcapfile_get_timeval(
607                const libtrace_packet_t *packet) 
608{
609        libtrace_pcapfile_pkt_hdr_t *hdr;
610        struct timeval ts;
611       
612        assert(packet->header);
613       
614        hdr = (libtrace_pcapfile_pkt_hdr_t*)packet->header;
615        ts.tv_sec = swapl(packet->trace,hdr->ts_sec);
616        /* Check trace is not a dummy calling trace_in_nanoseconds */
617        if (DATA(packet->trace) && trace_in_nanoseconds(&DATA(packet->trace)->header))
618                ts.tv_usec = swapl(packet->trace, hdr->ts_usec) / 1000;
619        else
620                ts.tv_usec = swapl(packet->trace,hdr->ts_usec);
621        return ts;
622}
623
624static struct timespec pcapfile_get_timespec(
625                const libtrace_packet_t *packet) 
626{
627        libtrace_pcapfile_pkt_hdr_t *hdr;
628        struct timespec ts;
629       
630        assert(packet->header);
631       
632        hdr = (libtrace_pcapfile_pkt_hdr_t*)packet->header;
633        ts.tv_sec = swapl(packet->trace,hdr->ts_sec);
634        /* Check trace is not a dummy calling trace_in_nanoseconds */
635        if (DATA(packet->trace) && trace_in_nanoseconds(&DATA(packet->trace)->header))
636                ts.tv_nsec = swapl(packet->trace, hdr->ts_usec);
637        else
638                ts.tv_nsec = swapl(packet->trace, hdr->ts_usec) * 1000;
639        return ts;
640}
641
642
643static int pcapfile_get_capture_length(const libtrace_packet_t *packet) {
644        libtrace_pcapfile_pkt_hdr_t *pcapptr; 
645
646        assert(packet->header);
647        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
648
649        return swapl(packet->trace,pcapptr->caplen);
650}
651
652static int pcapfile_get_wire_length(const libtrace_packet_t *packet) {
653        libtrace_pcapfile_pkt_hdr_t *pcapptr;
654
655        assert(packet->header); 
656
657        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
658        if (packet->type==pcap_linktype_to_rt(TRACE_DLT_EN10MB))
659                /* Include the missing FCS */
660                return swapl(packet->trace,pcapptr->wirelen)+4; 
661        else if (packet->type==pcap_linktype_to_rt(TRACE_DLT_IEEE802_11_RADIO)){
662                /* If the packet is Radiotap and the flags field indicates
663                 * that the FCS is not included in the 802.11 frame, then
664                 * we need to add 4 to the wire-length to account for it.
665                 */
666                uint8_t flags;
667                void *link;
668                libtrace_linktype_t linktype;
669                link = trace_get_packet_buffer(packet, &linktype, NULL);
670                trace_get_wireless_flags(link, linktype, &flags);
671                if ((flags & TRACE_RADIOTAP_F_FCS) == 0)
672                        return swapl(packet->trace,pcapptr->wirelen)+4;
673        } else if (packet->type == pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL)) {
674                libtrace_sll_header_t *sll;
675                sll = (libtrace_sll_header_t *)packet->payload;
676
677                /* Account for FCS when dealing with Ethernet packets that are
678                 * encapsulated in Linux SLL. This should fix the problem
679                 * where the wire lengths differ if we convert the packet to
680                 * ERF */
681                if (ntohs(sll->protocol) == TRACE_ETHERTYPE_LOOPBACK)
682                        return swapl(packet->trace,pcapptr->wirelen)+4;
683        }
684
685        return swapl(packet->trace,pcapptr->wirelen);
686}
687
688static int pcapfile_get_framing_length(const libtrace_packet_t *packet UNUSED) {
689        return sizeof(libtrace_pcapfile_pkt_hdr_t);
690}
691
692static size_t pcapfile_set_capture_length(libtrace_packet_t *packet,size_t size) {
693        libtrace_pcapfile_pkt_hdr_t *pcapptr = 0;
694        assert(packet);
695        assert(packet->header);
696        if (size > trace_get_capture_length(packet)) {
697                /* Can't make a packet larger */
698                return trace_get_capture_length(packet);
699        }
700        /* Reset the cached capture length */
701        packet->capture_length = -1;
702        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
703        pcapptr->caplen = swapl(packet->trace,(uint32_t)size);
704        return trace_get_capture_length(packet);
705}
706
707static struct libtrace_eventobj_t pcapfile_event(libtrace_t *libtrace, libtrace_packet_t *packet) {
708       
709        libtrace_eventobj_t event = {0,0,0.0,0};
710       
711        /* If we are being told to replay packets as fast as possible, then
712         * we just need to read and return the next packet in the trace */
713
714        if (IN_OPTIONS.real_time) {
715                event.size = trace_read_packet(libtrace, packet);
716                if (event.size < 1)
717                        event.type = TRACE_EVENT_TERMINATE;
718                else
719                        event.type = TRACE_EVENT_PACKET;
720                return event;
721        } else {
722                return trace_event_trace(libtrace, packet);
723        }
724}
725
726static void pcapfile_help(void) {
727        printf("pcapfile format module: $Revision: 1768 $\n");
728        printf("Supported input URIs:\n");
729        printf("\tpcapfile:/path/to/file\n");
730        printf("\tpcapfile:/path/to/file.gz\n");
731        printf("\n");
732        printf("\te.g.: pcapfile:/tmp/trace.pcap\n");
733        printf("\n");
734}
735
736static struct libtrace_format_t pcapfile = {
737        "pcapfile",
738        "$Id$",
739        TRACE_FORMAT_PCAPFILE,
740        NULL,                           /* probe filename */
741        pcapfile_probe_magic,           /* probe magic */
742        pcapfile_init_input,            /* init_input */
743        pcapfile_config_input,          /* config_input */
744        pcapfile_start_input,           /* start_input */
745        NULL,                           /* pause_input */
746        pcapfile_init_output,           /* init_output */
747        pcapfile_config_output,         /* config_output */
748        pcapfile_start_output,          /* start_output */
749        pcapfile_fin_input,             /* fin_input */
750        pcapfile_fin_output,            /* fin_output */
751        pcapfile_read_packet,           /* read_packet */
752        pcapfile_prepare_packet,        /* prepare_packet */
753        NULL,                           /* fin_packet */
754        pcapfile_write_packet,          /* write_packet */
755        pcapfile_get_link_type,         /* get_link_type */
756        pcapfile_get_direction,         /* get_direction */
757        NULL,                           /* set_direction */
758        NULL,                           /* get_erf_timestamp */
759        pcapfile_get_timeval,           /* get_timeval */
760        pcapfile_get_timespec,          /* get_timespec */
761        NULL,                           /* get_seconds */
762        NULL,                           /* seek_erf */
763        NULL,                           /* seek_timeval */
764        NULL,                           /* seek_seconds */
765        pcapfile_get_capture_length,    /* get_capture_length */
766        pcapfile_get_wire_length,       /* get_wire_length */
767        pcapfile_get_framing_length,    /* get_framing_length */
768        pcapfile_set_capture_length,    /* set_capture_length */
769        NULL,                           /* get_received_packets */
770        NULL,                           /* get_filtered_packets */
771        NULL,                           /* get_dropped_packets */
772        NULL,                           /* get_captured_packets */
773        NULL,                           /* get_fd */
774        pcapfile_event,         /* trace_event */
775        pcapfile_help,                  /* help */
776        NULL                            /* next pointer */
777};
778
779
780void pcapfile_constructor(void) {
781        register_format(&pcapfile);
782}
783
784
Note: See TracBrowser for help on using the repository browser.