source: lib/format_erf.c @ ee6e802

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