source: lib/format_erf.c @ 10553bf

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

Fix all outstanding warnings

Implemented trace_get_statistics for formats that were missing it, so
we no longer need to use the deprecated trace_get_dropped_packets anywhere
within libtrace.

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