source: lib/format_pcapfile.c @ 756b8f9

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

Make sure our copyright covers recent years

Consistency across all of our source files is also nice.

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