source: lib/format_erf.c @ 1935565

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 1935565 was e90d5a8, checked in by Shane Alcock <salcock@…>, 9 years ago
  • Added a couple of new error types: BAD_FILTER and RT_FAILURE, with the aim of trying to restrict the use of BAD_PACKET to cases where the packet is clearly corrupt or broken
  • Property mode set to 100644
File size: 20.5 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#define _GNU_SOURCE
36
37#include "config.h"
38#include "common.h"
39#include "libtrace.h"
40#include "libtrace_int.h"
41#include "format_helper.h"
42#include "format_erf.h"
43#include "wandio.h"
44
45#include <assert.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <stdio.h>
49#include <string.h>
50#include <stdlib.h>
51
52#ifdef WIN32
53#  include <io.h>
54#  include <share.h>
55#  define PATH_MAX _MAX_PATH
56#else
57#  include <netdb.h>
58#  ifndef PATH_MAX
59#       define PATH_MAX 4096
60#  endif
61#  include <sys/ioctl.h>
62#endif
63
64/* This format module deals with reading and writing ERF traces. ERF is the
65 * trace format developed by Endace for use by DAG hardware capture cards.
66 *
67 * ERF is not a live capture format.
68 *
69 */
70
71
72static struct libtrace_format_t erfformat;
73
74#define DATA(x) ((struct erf_format_data_t *)x->format_data)
75#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
76
77#define IN_OPTIONS DATA(libtrace)->options
78#define OUTPUT DATAOUT(libtrace)
79#define OUT_OPTIONS DATAOUT(libtrace)->options
80
81/* "Global" data that is stored for each ERF input trace */
82struct erf_format_data_t {
83       
84        /* Index used for seeking within a trace */
85        struct {
86                /* The index itself */
87                io_t *index;
88                /* The offset of the index */
89                off_t index_len;
90                /* Indicates the existence of an index */
91                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
92        } seek;
93
94        /* Number of packets that were dropped during the capture */
95        uint64_t drops;
96
97        /* Config options for the input trace */
98        struct {
99                /* Flag indicating whether the event API should replicate the
100                 * time gaps between each packet or return a PACKET event for
101                 * each packet */
102                int real_time;
103        } options;
104};
105
106/* "Global" data that is stored for each ERF output trace */
107struct erf_format_data_out_t {
108
109        /* Config options for the output trace */
110        struct {
111                /* Compression level for the output file */
112                int level;
113                /* Compression type */
114                int compress_type;
115                /* File flags used to open the file, e.g. O_CREATE */
116                int fileflag;
117        } options;
118
119        /* The output file itself */
120        iow_t *file;
121       
122};
123
124typedef struct erf_index_t {
125        uint64_t timestamp;
126        uint64_t offset; 
127} erf_index_t;
128
129
130/* Ethernet packets have a 2 byte padding before the packet
131 * so that the IP header is aligned on a 32 bit boundary.
132 */
133static int erf_get_padding(const libtrace_packet_t *packet)
134{
135        if (packet->trace->format->type==TRACE_FORMAT_ERF) {
136                dag_record_t *erfptr = (dag_record_t *)packet->header;
137                switch(erfptr->type) {
138                        case TYPE_ETH:         
139                        case TYPE_DSM_COLOR_ETH:
140                                return 2;
141                        default:                return 0;
142                }
143        }
144        else {
145                switch(trace_get_link_type(packet)) {
146                        case TRACE_TYPE_ETH:    return 2;
147                        default:                return 0;
148                }
149        }
150}
151
152int erf_get_framing_length(const libtrace_packet_t *packet)
153{
154        return dag_record_size + erf_get_padding(packet);
155}
156
157/* Attempts to determine whether a given trace file is using the ERF format
158 *
159 * Returns 1 if the trace is probably ERF, 0 otherwise
160 */
161static int erf_probe_magic(io_t *io)
162{
163        char buffer[4096];
164        int len;
165        dag_record_t *erf;
166        len = wandio_peek(io, buffer, sizeof(buffer));
167        if (len < (int)dag_record_size) {
168                return 0; /* False */
169        }
170        erf = (dag_record_t *) buffer;
171        /* If the record is too short */
172        if (ntohs(erf->rlen) < dag_record_size) {
173                return 0;
174        }
175        /* There aren't any erf traces before 1995-01-01 */
176        if (bswap_le_to_host64(erf->ts) < 0x2f0539b000000000ULL) {
177                return 0;
178        }
179        /* And not pcap! */
180        if (bswap_le_to_host64(erf->ts) >>32 == 0xa1b2c3d4) {
181                return 0;
182        }
183        /* And not the other pcap! */
184        if (bswap_le_to_host64(erf->ts) >>32 == 0xd4c3b2a1) {
185                return 0;
186        }
187        /* Is this a proper typed packet */
188        if (erf->type > TYPE_AAL2) {
189                return 0;
190        }
191        /* We should put some more tests in here. */
192        /* Yeah, this is probably ERF */
193        return 1;
194}
195
196static int erf_init_input(libtrace_t *libtrace) 
197{
198        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
199       
200        IN_OPTIONS.real_time = 0;
201        DATA(libtrace)->drops = 0;
202       
203        return 0; /* success */
204}
205
206static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
207                void *value) {
208
209        switch (option) {
210                case TRACE_OPTION_EVENT_REALTIME:
211                        IN_OPTIONS.real_time = *(int *)value;
212                        return 0;
213                case TRACE_OPTION_SNAPLEN:
214                case TRACE_OPTION_PROMISC:
215                case TRACE_OPTION_FILTER:
216                case TRACE_OPTION_META_FREQ:
217                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
218                                        "Unsupported option");
219                        return -1;
220                default:
221                        /* Unknown option */
222                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
223                                        "Unknown option");
224                        return -1;
225        }
226}
227
228static int erf_start_input(libtrace_t *libtrace)
229{
230        if (libtrace->io)
231                return 0; /* Success -- already done. */
232
233        libtrace->io = trace_open_file(libtrace);
234
235        if (!libtrace->io)
236                return -1;
237
238        DATA(libtrace)->drops = 0;
239
240        return 0; /* success */
241}
242
243/* Binary search through the index to find the closest point before
244 * the packet.  Consider in future having a btree index perhaps?
245 */
246static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
247{
248        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
249        size_t min_off = 0;
250        off_t current;
251        erf_index_t record;
252        do {
253                current=(max_off+min_off)>>2;
254
255                wandio_seek(DATA(libtrace)->seek.index,
256                                (int64_t)(current*sizeof(record)),
257                                SEEK_SET);
258                wandio_read(DATA(libtrace)->seek.index,
259                                &record,sizeof(record));
260                if (record.timestamp < erfts) {
261                        min_off=current;
262                }
263                if (record.timestamp > erfts) {
264                        max_off=current;
265                }
266                if (record.timestamp == erfts)
267                        break;
268        } while(min_off<max_off);
269
270        /* If we've passed it, seek backwards.  This loop shouldn't
271         * execute more than twice.
272         */
273        do {
274                wandio_seek(DATA(libtrace)->seek.index,
275                                (int64_t)(current*sizeof(record)),SEEK_SET);
276                wandio_read(DATA(libtrace)->seek.index,
277                                &record,sizeof(record));
278                current--;
279        } while(record.timestamp>erfts);
280
281        /* We've found our location in the trace, now use it. */
282        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
283
284        return 0; /* success */
285}
286
287/* There is no index.  Seek through the entire trace from the start, nice
288 * and slowly.
289 */
290static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
291{
292        if (libtrace->io) {
293                wandio_destroy(libtrace->io);
294        }
295        libtrace->io = trace_open_file(libtrace);
296        if (!libtrace->io)
297                return -1;
298        return 0;
299}
300
301/* Seek within an ERF trace based on an ERF timestamp */
302static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
303{
304        libtrace_packet_t *packet;
305        off_t off = 0;
306
307        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
308                char buffer[PATH_MAX];
309                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
310                DATA(libtrace)->seek.index=wandio_create(buffer);
311                if (DATA(libtrace)->seek.index) {
312                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
313                }
314                else {
315                        DATA(libtrace)->seek.exists=INDEX_NONE;
316                }
317        }
318
319        /* If theres an index, use it to find the nearest packet that isn't
320         * after the time we're looking for.  If there is no index we need
321         * to seek slowly through the trace from the beginning.  Sigh.
322         */
323        switch(DATA(libtrace)->seek.exists) {
324                case INDEX_EXISTS:
325                        erf_fast_seek_start(libtrace,erfts);
326                        break;
327                case INDEX_NONE:
328                        erf_slow_seek_start(libtrace,erfts);
329                        break;
330                case INDEX_UNKNOWN:
331                        assert(0);
332                        break;
333        }
334
335        /* Now seek forward looking for the correct timestamp */
336        packet=trace_create_packet();
337        do {
338                trace_read_packet(libtrace,packet);
339                if (trace_get_erf_timestamp(packet)==erfts)
340                        break;
341                off=wandio_tell(libtrace->io);
342        } while(trace_get_erf_timestamp(packet)<erfts);
343
344        wandio_seek(libtrace->io,off,SEEK_SET);
345
346        return 0;
347}
348
349static int erf_init_output(libtrace_out_t *libtrace) {
350        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
351
352        OUT_OPTIONS.level = 0;
353        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
354        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
355        OUTPUT->file = 0;
356
357        return 0;
358}
359
360static int erf_config_output(libtrace_out_t *libtrace, 
361                trace_option_output_t option, void *value) {
362
363        switch (option) {
364                case TRACE_OPTION_OUTPUT_COMPRESS:
365                        OUT_OPTIONS.level = *(int*)value;
366                        return 0;
367                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
368                        OUT_OPTIONS.compress_type = *(int*)value;
369                        return 0;
370                case TRACE_OPTION_OUTPUT_FILEFLAGS:
371                        OUT_OPTIONS.fileflag = *(int*)value;
372                        return 0;
373                default:
374                        /* Unknown option */
375                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
376                                        "Unknown option");
377                        return -1;
378        }
379}
380
381
382
383static int erf_fin_input(libtrace_t *libtrace) {
384        if (libtrace->io)
385                wandio_destroy(libtrace->io);
386        free(libtrace->format_data);
387        return 0;
388}
389
390static int erf_fin_output(libtrace_out_t *libtrace) {
391        if (OUTPUT->file)
392                wandio_wdestroy(OUTPUT->file);
393        free(libtrace->format_data);
394        return 0;
395}
396 
397static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
398                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
399       
400        dag_record_t *erfptr;
401       
402        if (packet->buffer != buffer && 
403                packet->buf_control == TRACE_CTRL_PACKET) {
404                free(packet->buffer);
405        }
406
407        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
408                packet->buf_control = TRACE_CTRL_PACKET;
409        } else
410                packet->buf_control = TRACE_CTRL_EXTERNAL;
411       
412       
413        packet->type = rt_type;
414        packet->buffer = buffer;
415        packet->header = buffer;
416        erfptr = (dag_record_t *)packet->buffer;
417        if (erfptr->flags.rxerror == 1) {
418                packet->payload = NULL;
419        } else {
420                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
421        }
422       
423        if (libtrace->format_data == NULL) {
424                /* Allocates the format_data structure */
425                if (erf_init_input(libtrace)) 
426                        return -1;
427        }
428
429        /* Check for loss */
430        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
431                /* No idea how we get this yet */
432
433        } else if (erfptr->lctr) {
434                DATA(libtrace)->drops += ntohs(erfptr->lctr);
435        }
436
437        return 0;
438}
439
440static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
441        int numbytes;
442        unsigned int size;
443        void *buffer2 = packet->buffer;
444        unsigned int rlen;
445        uint32_t flags = 0;
446       
447       
448        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
449                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
450                if (!packet->buffer) {
451                        trace_set_err(libtrace, errno, 
452                                        "Cannot allocate memory");
453                        return -1;
454                }
455        }
456
457        flags |= TRACE_PREP_OWN_BUFFER; 
458       
459        if ((numbytes=wandio_read(libtrace->io,
460                                        packet->buffer,
461                                        (size_t)dag_record_size)) == -1) {
462                trace_set_err(libtrace,errno,"read(%s)",
463                                libtrace->uridata);
464                return -1;
465        }
466        /* EOF */
467        if (numbytes == 0) {
468                return 0;
469        }
470
471        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
472        buffer2 = (char*)packet->buffer + dag_record_size;
473        size = rlen - dag_record_size;
474
475        if (size >= LIBTRACE_PACKET_BUFSIZE) {
476                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
477                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
478                                size);
479                return -1;
480        }
481
482        /* Unknown/corrupt */
483        if (((dag_record_t *)packet->buffer)->type >= TYPE_RAW_LINK) {
484                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
485                                "Corrupt or Unknown ERF type");
486                return -1;
487        }
488       
489        /* read in the rest of the packet */
490        if ((numbytes=wandio_read(libtrace->io,
491                                        buffer2,
492                                        (size_t)size)) != (int)size) {
493                if (numbytes==-1) {
494                        trace_set_err(libtrace,errno, "read(%s)", 
495                                        libtrace->uridata);
496                        return -1;
497                }
498                trace_set_err(libtrace,EIO,
499                                "Truncated packet (wanted %d, got %d)", 
500                                size, numbytes);
501                /* Failed to read the full packet?  must be EOF */
502                return -1;
503        }
504       
505        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
506                                TRACE_RT_DATA_ERF, flags))
507                return -1;
508       
509        return rlen;
510}
511
512static int erf_dump_packet(libtrace_out_t *libtrace,
513                dag_record_t *erfptr, unsigned int pad, void *buffer) {
514        int numbytes = 0;
515        int size;
516
517        if ((numbytes = 
518                wandio_wwrite(OUTPUT->file, 
519                                erfptr,
520                                (size_t)(dag_record_size + pad))) 
521                        != (int)(dag_record_size+pad)) {
522                trace_set_err_out(libtrace,errno,
523                                "write(%s)",libtrace->uridata);
524                return -1;
525        }
526
527        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
528        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
529        if (numbytes != size) {
530                trace_set_err_out(libtrace,errno,
531                                "write(%s)",libtrace->uridata);
532                return -1;
533        }
534        return numbytes + pad + dag_record_size;
535}
536
537static int erf_start_output(libtrace_out_t *libtrace)
538{
539        OUTPUT->file = trace_open_file_out(libtrace,
540                        OUT_OPTIONS.compress_type,
541                        OUT_OPTIONS.level,
542                        OUT_OPTIONS.fileflag);
543
544        if (!OUTPUT->file) {
545                return -1;
546        }
547        return 0;
548}
549
550static bool find_compatible_linktype(libtrace_out_t *libtrace,
551                                libtrace_packet_t *packet)
552{
553        /* Keep trying to simplify the packet until we can find
554         * something we can do with it */
555        do {
556                char type=libtrace_to_erf_type(trace_get_link_type(packet));
557
558                /* Success */
559                if (type != (char)-1)
560                        return true;
561
562                if (!demote_packet(packet)) {
563                        trace_set_err_out(libtrace,
564                                        TRACE_ERR_NO_CONVERSION,
565                                        "No erf type for packet (%i)",
566                                        trace_get_link_type(packet));
567                        return false;
568                }
569
570        } while(1);
571
572        return true;
573}
574               
575static int erf_write_packet(libtrace_out_t *libtrace, 
576                libtrace_packet_t *packet) 
577{
578        int numbytes = 0;
579        unsigned int pad = 0;
580        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
581        void *payload = packet->payload;
582
583        assert(OUTPUT->file);
584
585        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
586                return 0;
587
588        if (!packet->header) {
589                return -1;
590        }
591       
592        pad = erf_get_padding(packet);
593
594        /* If we've had an rxerror, we have no payload to write - fix
595         * rlen to be the correct length
596         */
597        /* I Think this is bogus, we should somehow figure out
598         * a way to write out the payload even if it is gibberish -- Perry */
599        if (payload == NULL) {
600                dag_hdr->rlen = htons(dag_record_size + pad);
601               
602        } 
603       
604        if (packet->type == TRACE_RT_DATA_ERF) {
605                        numbytes = erf_dump_packet(libtrace,
606                                (dag_record_t *)packet->header,
607                                pad,
608                                payload
609                                );
610        } else {
611                dag_record_t erfhdr;
612                int rlen;
613                /* convert format - build up a new erf header */
614                /* Timestamp */
615                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
616
617                /* Flags. Can't do this */
618                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
619                if (trace_get_direction(packet)!=~0U)
620                        erfhdr.flags.iface = trace_get_direction(packet);
621
622                if (!find_compatible_linktype(libtrace,packet))
623                        return -1;
624
625                payload=packet->payload;
626                pad = erf_get_padding(packet);
627
628                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
629
630                /* Packet length (rlen includes format overhead) */
631                assert(trace_get_capture_length(packet)>0 
632                                && trace_get_capture_length(packet)<=65536);
633                assert(erf_get_framing_length(packet)>0 
634                                && trace_get_framing_length(packet)<=65536);
635
636                rlen = trace_get_capture_length(packet) + 
637                                erf_get_framing_length(packet);
638                assert(rlen > 0 && rlen <= 65536);
639                erfhdr.rlen = htons(rlen);
640                /* loss counter. Can't do this */
641                erfhdr.lctr = 0;
642                /* Wire length, does not include padding! */
643                erfhdr.wlen = htons(trace_get_wire_length(packet));
644
645                /* Write it out */
646                numbytes = erf_dump_packet(libtrace,
647                                &erfhdr,
648                                pad,
649                                payload);
650        }
651        return numbytes;
652}
653
654libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
655        dag_record_t *erfptr = 0;
656        erfptr = (dag_record_t *)packet->header;
657        if (erfptr->type != TYPE_LEGACY)
658                return erf_type_to_libtrace(erfptr->type);
659        else {
660                /* Sigh, lets start wildly guessing */
661                if (((char*)packet->payload)[4]==0x45)
662                        return TRACE_TYPE_PPP;
663                return ~0;
664        }
665}
666
667libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
668        dag_record_t *erfptr = 0;
669        erfptr = (dag_record_t *)packet->header;
670        return erfptr->flags.iface;
671}
672
673libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
674        dag_record_t *erfptr = 0;
675        erfptr = (dag_record_t *)packet->header;
676        erfptr->flags.iface = direction;
677        return erfptr->flags.iface;
678}
679
680uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
681        dag_record_t *erfptr = 0;
682        erfptr = (dag_record_t *)packet->header;
683        return bswap_le_to_host64(erfptr->ts);
684}
685
686int erf_get_capture_length(const libtrace_packet_t *packet) {
687        dag_record_t *erfptr = 0;
688        int caplen;
689        if (packet->payload == NULL)
690                return 0; 
691       
692        erfptr = (dag_record_t *)packet->header;
693        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
694        if (ntohs(erfptr->wlen) < caplen)
695                return ntohs(erfptr->wlen);
696
697        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
698}
699
700int erf_get_wire_length(const libtrace_packet_t *packet) {
701        dag_record_t *erfptr = 0;
702        erfptr = (dag_record_t *)packet->header;
703        return ntohs(erfptr->wlen);
704}
705
706size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
707        dag_record_t *erfptr = 0;
708        assert(packet);
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 cached capture length - otherwise we will both return the
714         * wrong value here and subsequent get_capture_length() calls will
715         * return the wrong value. */
716        packet->capture_length = -1;
717        erfptr = (dag_record_t *)packet->header;
718        erfptr->rlen = htons(size + erf_get_framing_length(packet));
719        return trace_get_capture_length(packet);
720}
721
722static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
723        struct libtrace_eventobj_t event = {0,0,0.0,0};
724       
725        /* If we are being told to replay packets as fast as possible, then
726         * we just need to read and return the next packet in the trace */
727        if (IN_OPTIONS.real_time) {
728                event.size = erf_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               
735        } else {
736                /* Otherwise, use the generic event function */
737                return trace_event_trace(libtrace, packet);
738        }
739       
740}
741
742static uint64_t erf_get_dropped_packets(libtrace_t *trace)
743{
744        if (trace->format_data == NULL)
745                return (uint64_t)-1;
746        return DATA(trace)->drops;
747}
748
749static void erf_help(void) {
750        printf("erf format module: $Revision$\n");
751        printf("Supported input URIs:\n");
752        printf("\terf:/path/to/file\t(uncompressed)\n");
753        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
754        printf("\terf:-\t(stdin, either compressed or not)\n");
755        printf("\terf:/path/to/socket\n");
756        printf("\n");
757        printf("\te.g.: erf:/tmp/trace\n");
758        printf("\n");
759        printf("Supported output URIs:\n");
760        printf("\terf:path/to/file\t(uncompressed)\n");
761        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
762        printf("\terf:-\t(stdout, either compressed or not)\n");
763        printf("\n");
764        printf("\te.g.: erf:/tmp/trace\n");
765        printf("\n");
766
767       
768}
769
770static struct libtrace_format_t erfformat = {
771        "erf",
772        "$Id$",
773        TRACE_FORMAT_ERF,
774        NULL,                           /* probe filename */
775        erf_probe_magic,                /* probe magic */
776        erf_init_input,                 /* init_input */       
777        erf_config_input,               /* config_input */
778        erf_start_input,                /* start_input */
779        NULL,                           /* pause_input */
780        erf_init_output,                /* init_output */
781        erf_config_output,              /* config_output */
782        erf_start_output,               /* start_output */
783        erf_fin_input,                  /* fin_input */
784        erf_fin_output,                 /* fin_output */
785        erf_read_packet,                /* read_packet */
786        erf_prepare_packet,             /* prepare_packet */
787        NULL,                           /* fin_packet */
788        erf_write_packet,               /* write_packet */
789        erf_get_link_type,              /* get_link_type */
790        erf_get_direction,              /* get_direction */
791        erf_set_direction,              /* set_direction */
792        erf_get_erf_timestamp,          /* get_erf_timestamp */
793        NULL,                           /* get_timeval */
794        NULL,                           /* get_timespec */
795        NULL,                           /* get_seconds */
796        erf_seek_erf,                   /* seek_erf */
797        NULL,                           /* seek_timeval */
798        NULL,                           /* seek_seconds */
799        erf_get_capture_length,         /* get_capture_length */
800        erf_get_wire_length,            /* get_wire_length */
801        erf_get_framing_length,         /* get_framing_length */
802        erf_set_capture_length,         /* set_capture_length */
803        NULL,                           /* get_received_packets */
804        NULL,                           /* get_filtered_packets */
805        erf_get_dropped_packets,        /* get_dropped_packets */
806        NULL,                           /* get_captured_packets */
807        NULL,                           /* get_fd */
808        erf_event,                      /* trace_event */
809        erf_help,                       /* help */
810        NULL                            /* next pointer */
811};
812
813
814void erf_constructor(void) {
815        register_format(&erfformat);
816}
Note: See TracBrowser for help on using the repository browser.