source: lib/format_erf.c @ 97d170d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 97d170d was 97d170d, checked in by Dan Collins <dan@…>, 7 years ago

Merge branch 'develop' of github.com:wanduow/libtrace into develop

Conflicts:

lib/format_dag25.c

  • Property mode set to 100644
File size: 22.9 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        return 0; /* success */
240}
241
242/* Raw ERF is a special case -- we want to force libwandio to treat the file
243 * as uncompressed so we can't just use trace_open_file() */
244static int rawerf_start_input(libtrace_t *libtrace)
245{
246        if (libtrace->io)
247                return 0; 
248
249        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
250
251        if (!libtrace->io) {
252                if (errno != 0) {
253                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
254                }
255                return -1;
256        }
257
258        DATA(libtrace)->drops = 0;
259
260        return 0; /* success */
261}
262
263/* Binary search through the index to find the closest point before
264 * the packet.  Consider in future having a btree index perhaps?
265 */
266static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
267{
268        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
269        size_t min_off = 0;
270        off_t current;
271        erf_index_t record;
272        do {
273                current=(max_off+min_off)>>2;
274
275                wandio_seek(DATA(libtrace)->seek.index,
276                                (int64_t)(current*sizeof(record)),
277                                SEEK_SET);
278                wandio_read(DATA(libtrace)->seek.index,
279                                &record,sizeof(record));
280                if (record.timestamp < erfts) {
281                        min_off=current;
282                }
283                if (record.timestamp > erfts) {
284                        max_off=current;
285                }
286                if (record.timestamp == erfts)
287                        break;
288        } while(min_off<max_off);
289
290        /* If we've passed it, seek backwards.  This loop shouldn't
291         * execute more than twice.
292         */
293        do {
294                wandio_seek(DATA(libtrace)->seek.index,
295                                (int64_t)(current*sizeof(record)),SEEK_SET);
296                wandio_read(DATA(libtrace)->seek.index,
297                                &record,sizeof(record));
298                current--;
299        } while(record.timestamp>erfts);
300
301        /* We've found our location in the trace, now use it. */
302        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
303
304        return 0; /* success */
305}
306
307/* There is no index.  Seek through the entire trace from the start, nice
308 * and slowly.
309 */
310static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
311{
312        if (libtrace->io) {
313                wandio_destroy(libtrace->io);
314        }
315        libtrace->io = trace_open_file(libtrace);
316        if (!libtrace->io)
317                return -1;
318        return 0;
319}
320
321/* Seek within an ERF trace based on an ERF timestamp */
322static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
323{
324        libtrace_packet_t *packet;
325        off_t off = 0;
326
327        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
328                char buffer[PATH_MAX];
329                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
330                DATA(libtrace)->seek.index=wandio_create(buffer);
331                if (DATA(libtrace)->seek.index) {
332                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
333                }
334                else {
335                        DATA(libtrace)->seek.exists=INDEX_NONE;
336                }
337        }
338
339        /* If theres an index, use it to find the nearest packet that isn't
340         * after the time we're looking for.  If there is no index we need
341         * to seek slowly through the trace from the beginning.  Sigh.
342         */
343        switch(DATA(libtrace)->seek.exists) {
344                case INDEX_EXISTS:
345                        erf_fast_seek_start(libtrace,erfts);
346                        break;
347                case INDEX_NONE:
348                        erf_slow_seek_start(libtrace,erfts);
349                        break;
350                case INDEX_UNKNOWN:
351                        assert(0);
352                        break;
353        }
354
355        /* Now seek forward looking for the correct timestamp */
356        packet=trace_create_packet();
357        do {
358                trace_read_packet(libtrace,packet);
359                if (trace_get_erf_timestamp(packet)==erfts)
360                        break;
361                off=wandio_tell(libtrace->io);
362        } while(trace_get_erf_timestamp(packet)<erfts);
363
364        wandio_seek(libtrace->io,off,SEEK_SET);
365
366        return 0;
367}
368
369static int erf_init_output(libtrace_out_t *libtrace) {
370        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
371
372        OUT_OPTIONS.level = 0;
373        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
374        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
375        OUTPUT->file = 0;
376
377        return 0;
378}
379
380static int erf_config_output(libtrace_out_t *libtrace, 
381                trace_option_output_t option, void *value) {
382
383        switch (option) {
384                case TRACE_OPTION_OUTPUT_COMPRESS:
385                        OUT_OPTIONS.level = *(int*)value;
386                        return 0;
387                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
388                        OUT_OPTIONS.compress_type = *(int*)value;
389                        return 0;
390                case TRACE_OPTION_OUTPUT_FILEFLAGS:
391                        OUT_OPTIONS.fileflag = *(int*)value;
392                        return 0;
393                default:
394                        /* Unknown option */
395                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
396                                        "Unknown option");
397                        return -1;
398        }
399}
400
401
402
403static int erf_fin_input(libtrace_t *libtrace) {
404        if (libtrace->io)
405                wandio_destroy(libtrace->io);
406        free(libtrace->format_data);
407        return 0;
408}
409
410static int erf_fin_output(libtrace_out_t *libtrace) {
411        if (OUTPUT->file)
412                wandio_wdestroy(OUTPUT->file);
413        free(libtrace->format_data);
414        return 0;
415}
416 
417static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
418                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
419       
420        dag_record_t *erfptr;
421       
422        if (packet->buffer != buffer && 
423                packet->buf_control == TRACE_CTRL_PACKET) {
424                free(packet->buffer);
425        }
426
427        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
428                packet->buf_control = TRACE_CTRL_PACKET;
429        } else
430                packet->buf_control = TRACE_CTRL_EXTERNAL;
431       
432       
433        packet->type = rt_type;
434        packet->buffer = buffer;
435        packet->header = buffer;
436        erfptr = (dag_record_t *)packet->buffer;
437        if (erfptr->flags.rxerror == 1) {
438                packet->payload = NULL;
439        } else {
440                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
441        }
442       
443        if (libtrace->format_data == NULL) {
444                /* Allocates the format_data structure */
445                if (erf_init_input(libtrace)) 
446                        return -1;
447        }
448
449        /* Check for loss */
450        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
451                /* No idea how we get this yet */
452
453        } else if (erfptr->lctr) {
454                DATA(libtrace)->drops += ntohs(erfptr->lctr);
455        }
456
457        return 0;
458}
459
460static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
461        int numbytes;
462        unsigned int size;
463        void *buffer2 = packet->buffer;
464        unsigned int rlen;
465        uint32_t flags = 0;
466       
467       
468        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
469                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
470                if (!packet->buffer) {
471                        trace_set_err(libtrace, errno, 
472                                        "Cannot allocate memory");
473                        return -1;
474                }
475        }
476
477        flags |= TRACE_PREP_OWN_BUFFER; 
478       
479        if ((numbytes=wandio_read(libtrace->io,
480                                        packet->buffer,
481                                        (size_t)dag_record_size)) == -1) {
482                trace_set_err(libtrace,errno,"reading ERF file");
483                return -1;
484        }
485        /* EOF */
486        if (numbytes == 0) {
487                return 0;
488        }
489
490        if (numbytes < (int)dag_record_size) {
491                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header");
492                return -1;
493        }
494
495        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
496        buffer2 = (char*)packet->buffer + dag_record_size;
497        size = rlen - dag_record_size;
498
499        if (size >= LIBTRACE_PACKET_BUFSIZE) {
500                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
501                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
502                                size);
503                return -1;
504        }
505
506        /* Unknown/corrupt */
507        if (((dag_record_t *)packet->buffer)->type >= TYPE_RAW_LINK) {
508                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
509                                "Corrupt or Unknown ERF type");
510                return -1;
511        }
512       
513        /* read in the rest of the packet */
514        if ((numbytes=wandio_read(libtrace->io,
515                                        buffer2,
516                                        (size_t)size)) != (int)size) {
517                if (numbytes==-1) {
518                        trace_set_err(libtrace,errno, "read(%s)", 
519                                        libtrace->uridata);
520                        return -1;
521                }
522                trace_set_err(libtrace,EIO,
523                                "Truncated packet (wanted %d, got %d)", 
524                                size, numbytes);
525                /* Failed to read the full packet?  must be EOF */
526                return -1;
527        }
528
529        if (numbytes < (int)size) {
530                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record");
531                return -1;
532        }
533       
534        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
535                                TRACE_RT_DATA_ERF, flags))
536                return -1;
537       
538        return rlen;
539}
540
541static int erf_dump_packet(libtrace_out_t *libtrace,
542                dag_record_t *erfptr, unsigned int pad, void *buffer) {
543        int numbytes = 0;
544        int size;
545
546        if ((numbytes = 
547                wandio_wwrite(OUTPUT->file, 
548                                erfptr,
549                                (size_t)(dag_record_size + pad))) 
550                        != (int)(dag_record_size+pad)) {
551                trace_set_err_out(libtrace,errno,
552                                "write(%s)",libtrace->uridata);
553                return -1;
554        }
555
556        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
557        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
558        if (numbytes != size) {
559                trace_set_err_out(libtrace,errno,
560                                "write(%s)",libtrace->uridata);
561                return -1;
562        }
563        return numbytes + pad + dag_record_size;
564}
565
566static int erf_start_output(libtrace_out_t *libtrace)
567{
568        OUTPUT->file = trace_open_file_out(libtrace,
569                        OUT_OPTIONS.compress_type,
570                        OUT_OPTIONS.level,
571                        OUT_OPTIONS.fileflag);
572
573        if (!OUTPUT->file) {
574                return -1;
575        }
576        return 0;
577}
578
579static bool find_compatible_linktype(libtrace_out_t *libtrace,
580                                libtrace_packet_t *packet)
581{
582        /* Keep trying to simplify the packet until we can find
583         * something we can do with it */
584        do {
585                char type=libtrace_to_erf_type(trace_get_link_type(packet));
586
587                /* Success */
588                if (type != (char)-1)
589                        return true;
590
591                if (!demote_packet(packet)) {
592                        trace_set_err_out(libtrace,
593                                        TRACE_ERR_NO_CONVERSION,
594                                        "No erf type for packet (%i)",
595                                        trace_get_link_type(packet));
596                        return false;
597                }
598
599        } while(1);
600
601        return true;
602}
603               
604static int erf_write_packet(libtrace_out_t *libtrace, 
605                libtrace_packet_t *packet) 
606{
607        int numbytes = 0;
608        unsigned int pad = 0;
609        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
610        void *payload = packet->payload;
611
612        assert(OUTPUT->file);
613
614        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
615                return 0;
616
617        if (!packet->header) {
618                return -1;
619        }
620       
621        pad = erf_get_padding(packet);
622
623        /* If we've had an rxerror, we have no payload to write - fix
624         * rlen to be the correct length
625         */
626        /* I Think this is bogus, we should somehow figure out
627         * a way to write out the payload even if it is gibberish -- Perry */
628        if (payload == NULL) {
629                dag_hdr->rlen = htons(dag_record_size + pad);
630               
631        } 
632       
633        if (packet->type == TRACE_RT_DATA_ERF) {
634                        numbytes = erf_dump_packet(libtrace,
635                                (dag_record_t *)packet->header,
636                                pad,
637                                payload
638                                );
639        } else {
640                dag_record_t erfhdr;
641                int rlen;
642                /* convert format - build up a new erf header */
643                /* Timestamp */
644                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
645
646                /* Flags. Can't do this */
647                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
648                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
649                        erfhdr.flags.iface = trace_get_direction(packet);
650
651                if (!find_compatible_linktype(libtrace,packet))
652                        return -1;
653
654                payload=packet->payload;
655                pad = erf_get_padding(packet);
656
657                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
658
659                /* Packet length (rlen includes format overhead) */
660                assert(trace_get_capture_length(packet)>0 
661                                && trace_get_capture_length(packet)<=65536);
662                assert(erf_get_framing_length(packet)>0 
663                                && trace_get_framing_length(packet)<=65536);
664
665                rlen = trace_get_capture_length(packet) + 
666                                erf_get_framing_length(packet);
667                assert(rlen > 0 && rlen <= 65536);
668                erfhdr.rlen = htons(rlen);
669                /* loss counter. Can't do this */
670                erfhdr.lctr = 0;
671                /* Wire length, does not include padding! */
672                erfhdr.wlen = htons(trace_get_wire_length(packet));
673
674                /* Write it out */
675                numbytes = erf_dump_packet(libtrace,
676                                &erfhdr,
677                                pad,
678                                payload);
679        }
680        return numbytes;
681}
682
683libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
684        dag_record_t *erfptr = 0;
685        erfptr = (dag_record_t *)packet->header;
686        if (erfptr->type != TYPE_LEGACY)
687                return erf_type_to_libtrace(erfptr->type);
688        else {
689                /* Sigh, lets start wildly guessing */
690                if (((char*)packet->payload)[4]==0x45)
691                        return TRACE_TYPE_PPP;
692                return ~0;
693        }
694}
695
696libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
697        dag_record_t *erfptr = 0;
698        erfptr = (dag_record_t *)packet->header;
699        return erfptr->flags.iface;
700}
701
702libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
703        dag_record_t *erfptr = 0;
704        erfptr = (dag_record_t *)packet->header;
705        erfptr->flags.iface = direction;
706        return erfptr->flags.iface;
707}
708
709uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
710        dag_record_t *erfptr = 0;
711        erfptr = (dag_record_t *)packet->header;
712        return bswap_le_to_host64(erfptr->ts);
713}
714
715int erf_get_capture_length(const libtrace_packet_t *packet) {
716        dag_record_t *erfptr = 0;
717        int caplen;
718        if (packet->payload == NULL)
719                return 0; 
720       
721        erfptr = (dag_record_t *)packet->header;
722        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
723        if (ntohs(erfptr->wlen) < caplen)
724                return ntohs(erfptr->wlen);
725
726        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
727}
728
729int erf_get_wire_length(const libtrace_packet_t *packet) {
730        dag_record_t *erfptr = 0;
731        erfptr = (dag_record_t *)packet->header;
732        return ntohs(erfptr->wlen);
733}
734
735size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
736        dag_record_t *erfptr = 0;
737        assert(packet);
738        if(size  > trace_get_capture_length(packet)) {
739                /* Can't make a packet larger */
740                return trace_get_capture_length(packet);
741        }
742        /* Reset cached capture length - otherwise we will both return the
743         * wrong value here and subsequent get_capture_length() calls will
744         * return the wrong value. */
745        packet->capture_length = -1;
746        erfptr = (dag_record_t *)packet->header;
747        erfptr->rlen = htons(size + erf_get_framing_length(packet));
748        return trace_get_capture_length(packet);
749}
750
751static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
752        struct libtrace_eventobj_t event = {0,0,0.0,0};
753       
754        /* If we are being told to replay packets as fast as possible, then
755         * we just need to read and return the next packet in the trace */
756        if (IN_OPTIONS.real_time) {
757                event.size = trace_read_packet(libtrace, packet);
758                if (event.size < 1)
759                        event.type = TRACE_EVENT_TERMINATE;
760                else
761                        event.type = TRACE_EVENT_PACKET;
762                return event;
763               
764        } else {
765                /* Otherwise, use the generic event function */
766                return trace_event_trace(libtrace, packet);
767        }
768       
769}
770
771static uint64_t erf_get_dropped_packets(libtrace_t *trace)
772{
773        if (trace->format_data == NULL)
774                return (uint64_t)-1;
775        return DATA(trace)->drops;
776}
777
778static void erf_help(void) {
779        printf("erf format module: $Revision: 1752 $\n");
780        printf("Supported input URIs:\n");
781        printf("\terf:/path/to/file\t(uncompressed)\n");
782        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
783        printf("\terf:-\t(stdin, either compressed or not)\n");
784        printf("\terf:/path/to/socket\n");
785        printf("\n");
786        printf("\te.g.: erf:/tmp/trace\n");
787        printf("\n");
788        printf("Supported output URIs:\n");
789        printf("\terf:path/to/file\t(uncompressed)\n");
790        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
791        printf("\terf:-\t(stdout, either compressed or not)\n");
792        printf("\n");
793        printf("\te.g.: erf:/tmp/trace\n");
794        printf("\n");
795
796       
797}
798
799static struct libtrace_format_t erfformat = {
800        "erf",
801        "$Id$",
802        TRACE_FORMAT_ERF,
803        NULL,                           /* probe filename */
804        erf_probe_magic,                /* probe magic */
805        erf_init_input,                 /* init_input */       
806        erf_config_input,               /* config_input */
807        erf_start_input,                /* start_input */
808        NULL,                           /* pause_input */
809        erf_init_output,                /* init_output */
810        erf_config_output,              /* config_output */
811        erf_start_output,               /* start_output */
812        erf_fin_input,                  /* fin_input */
813        erf_fin_output,                 /* fin_output */
814        erf_read_packet,                /* read_packet */
815        erf_prepare_packet,             /* prepare_packet */
816        NULL,                           /* fin_packet */
817        erf_write_packet,               /* write_packet */
818        erf_get_link_type,              /* get_link_type */
819        erf_get_direction,              /* get_direction */
820        erf_set_direction,              /* set_direction */
821        erf_get_erf_timestamp,          /* get_erf_timestamp */
822        NULL,                           /* get_timeval */
823        NULL,                           /* get_timespec */
824        NULL,                           /* get_seconds */
825        erf_seek_erf,                   /* seek_erf */
826        NULL,                           /* seek_timeval */
827        NULL,                           /* seek_seconds */
828        erf_get_capture_length,         /* get_capture_length */
829        erf_get_wire_length,            /* get_wire_length */
830        erf_get_framing_length,         /* get_framing_length */
831        erf_set_capture_length,         /* set_capture_length */
832        NULL,                           /* get_received_packets */
833        NULL,                           /* get_filtered_packets */
834        erf_get_dropped_packets,        /* get_dropped_packets */
835        NULL,                           /* get_captured_packets */
836        NULL,                           /* get_fd */
837        erf_event,                      /* trace_event */
838        erf_help,                       /* help */
839        NULL,                           /* next pointer */
840        NON_PARALLEL(false)
841};
842
843static struct libtrace_format_t rawerfformat = {
844        "rawerf",
845        "$Id$",
846        TRACE_FORMAT_RAWERF,
847        NULL,                           /* probe filename */
848        NULL,           /* probe magic */
849        erf_init_input,                 /* init_input */       
850        erf_config_input,               /* config_input */
851        rawerf_start_input,             /* start_input */
852        NULL,                           /* pause_input */
853        erf_init_output,                /* init_output */
854        erf_config_output,              /* config_output */
855        erf_start_output,               /* start_output */
856        erf_fin_input,                  /* fin_input */
857        erf_fin_output,                 /* fin_output */
858        erf_read_packet,                /* read_packet */
859        erf_prepare_packet,             /* prepare_packet */
860        NULL,                           /* fin_packet */
861        erf_write_packet,               /* write_packet */
862        erf_get_link_type,              /* get_link_type */
863        erf_get_direction,              /* get_direction */
864        erf_set_direction,              /* set_direction */
865        erf_get_erf_timestamp,          /* get_erf_timestamp */
866        NULL,                           /* get_timeval */
867        NULL,                           /* get_timespec */
868        NULL,                           /* get_seconds */
869        erf_seek_erf,                   /* seek_erf */
870        NULL,                           /* seek_timeval */
871        NULL,                           /* seek_seconds */
872        erf_get_capture_length,         /* get_capture_length */
873        erf_get_wire_length,            /* get_wire_length */
874        erf_get_framing_length,         /* get_framing_length */
875        erf_set_capture_length,         /* set_capture_length */
876        NULL,                           /* get_received_packets */
877        NULL,                           /* get_filtered_packets */
878        erf_get_dropped_packets,        /* get_dropped_packets */
879        NULL,                           /* get_captured_packets */
880        NULL,                           /* get_fd */
881        erf_event,                      /* trace_event */
882        erf_help,                       /* help */
883        NULL,                           /* next pointer */
884        NON_PARALLEL(false)
885};
886
887
888
889void erf_constructor(void) {
890        register_format(&erfformat);
891        register_format(&rawerfformat);
892}
Note: See TracBrowser for help on using the repository browser.