source: lib/format_pcapfile.c @ db84bb2

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

Updated copyright blurb on all source files

In some cases, this meant adding copyright blurbs to files that
had never had them before.

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