source: lib/format_pcapfile.c @ 37ee856

developringdecrementfixringperformance
Last change on this file since 37ee856 was 37ee856, checked in by Shane Alcock <salcock@…>, 2 years ago

Tag each packet with the start iteration of the parent trace.

Traces can be started, paused and then restarted. For some
formats (especially live ones), this will mean that buffers
containing received packets can be destroyed and recreated as
a result of that process. However, in our parallel world we might
also have lingering references to packets that lived in a
now-destroyed buffer and bad things will happen if we try to
operate on it.

To try and avoid this, we keep track of how many times a trace has
been "started" and each packet read is tagged with the start count
at the time it was read. Later processing functions can now check
if the packet was read before the most recent "start" -- if it was,
then it is potentially bogus and should be ignored.

This shouldn't change anything for the vast majority of libtrace
use-cases. Normally, pausing is only used prior to ending an
input without subsequent restarting, i.e. there is only one start
iteration.

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