source: lib/format_erf.c @ 7aa2a21

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

Fix bad framing calculation when converting to ERF

The bug was caused by our newly added support for ERF extension
headers. Previously, erf_get_framing_length() didn't actually
inspect the contents of the packet passed to it but now it does (to
try and detect any extension headers).

This means that when converting from another format, we can't call
erf_get_framing_length on the original packet anymore to work out
how much framing space we need as it will interpret the original
packet contents as an ERF header.

  • Property mode set to 100644
File size: 23.8 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        if (libtrace->format_data == NULL) {
463                /* Allocates the format_data structure */
464                if (erf_init_input(libtrace)) 
465                        return -1;
466        }
467
468        /* Check for loss */
469        if ((erfptr->type & 0x7f) == TYPE_DSM_COLOR_ETH) {
470                /* No idea how we get this yet */
471
472        } else if (erfptr->lctr) {
473                DATA(libtrace)->drops += ntohs(erfptr->lctr);
474        }
475
476        return 0;
477}
478
479static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
480        int numbytes;
481        unsigned int size;
482        void *buffer2 = packet->buffer;
483        unsigned int rlen;
484        uint32_t flags = 0;
485       
486       
487        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
488                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
489                if (!packet->buffer) {
490                        trace_set_err(libtrace, errno, 
491                                        "Cannot allocate memory");
492                        return -1;
493                }
494        }
495
496        flags |= TRACE_PREP_OWN_BUFFER; 
497       
498        if ((numbytes=wandio_read(libtrace->io,
499                                        packet->buffer,
500                                        (size_t)dag_record_size)) == -1) {
501                trace_set_err(libtrace,errno,"reading ERF file");
502                return -1;
503        }
504        /* EOF */
505        if (numbytes == 0) {
506                return 0;
507        }
508
509        if (numbytes < (int)dag_record_size) {
510                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header");
511                return -1;
512        }
513
514        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
515        buffer2 = (char*)packet->buffer + dag_record_size;
516        size = rlen - dag_record_size;
517
518        if (size >= LIBTRACE_PACKET_BUFSIZE) {
519                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
520                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
521                                size);
522                return -1;
523        }
524
525        /* Unknown/corrupt */
526        if ((((dag_record_t *)packet->buffer)->type & 0x7f) >= TYPE_RAW_LINK) {
527                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
528                                "Corrupt or Unknown ERF type");
529                return -1;
530        }
531       
532        /* read in the rest of the packet */
533        if ((numbytes=wandio_read(libtrace->io,
534                                        buffer2,
535                                        (size_t)size)) != (int)size) {
536                if (numbytes==-1) {
537                        trace_set_err(libtrace,errno, "read(%s)", 
538                                        libtrace->uridata);
539                        return -1;
540                }
541                trace_set_err(libtrace,EIO,
542                                "Truncated packet (wanted %d, got %d)", 
543                                size, numbytes);
544                /* Failed to read the full packet?  must be EOF */
545                return -1;
546        }
547
548        if (numbytes < (int)size) {
549                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record");
550                return -1;
551        }
552       
553        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
554                                TRACE_RT_DATA_ERF, flags))
555                return -1;
556       
557        return rlen;
558}
559
560static int erf_dump_packet(libtrace_out_t *libtrace,
561                dag_record_t *erfptr, unsigned int pad, void *buffer) {
562        int numbytes = 0;
563        int size;
564
565        if ((numbytes = 
566                wandio_wwrite(OUTPUT->file, 
567                                erfptr,
568                                (size_t)(dag_record_size + pad))) 
569                        != (int)(dag_record_size+pad)) {
570                trace_set_err_out(libtrace,errno,
571                                "write(%s)",libtrace->uridata);
572                return -1;
573        }
574
575        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
576        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
577        if (numbytes != size) {
578                trace_set_err_out(libtrace,errno,
579                                "write(%s)",libtrace->uridata);
580                return -1;
581        }
582        return numbytes + pad + dag_record_size;
583}
584
585static int erf_start_output(libtrace_out_t *libtrace)
586{
587        OUTPUT->file = trace_open_file_out(libtrace,
588                        OUT_OPTIONS.compress_type,
589                        OUT_OPTIONS.level,
590                        OUT_OPTIONS.fileflag);
591
592        if (!OUTPUT->file) {
593                return -1;
594        }
595        return 0;
596}
597
598static bool find_compatible_linktype(libtrace_out_t *libtrace,
599                                libtrace_packet_t *packet)
600{
601        /* Keep trying to simplify the packet until we can find
602         * something we can do with it */
603        do {
604                char type=libtrace_to_erf_type(trace_get_link_type(packet));
605
606                /* Success */
607                if (type != (char)-1)
608                        return true;
609
610                if (!demote_packet(packet)) {
611                        trace_set_err_out(libtrace,
612                                        TRACE_ERR_NO_CONVERSION,
613                                        "No erf type for packet (%i)",
614                                        trace_get_link_type(packet));
615                        return false;
616                }
617
618        } while(1);
619
620        return true;
621}
622               
623static int erf_write_packet(libtrace_out_t *libtrace, 
624                libtrace_packet_t *packet) 
625{
626        int numbytes = 0;
627        unsigned int pad = 0;
628        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
629        void *payload = packet->payload;
630
631        assert(OUTPUT->file);
632
633        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
634                return 0;
635
636        if (!packet->header) {
637                return -1;
638        }
639       
640        pad = erf_get_padding(packet);
641
642        /* If we've had an rxerror, we have no payload to write - fix
643         * rlen to be the correct length
644         */
645        /* I Think this is bogus, we should somehow figure out
646         * a way to write out the payload even if it is gibberish -- Perry */
647        if (payload == NULL) {
648                dag_hdr->rlen = htons(dag_record_size + pad);
649               
650        } 
651       
652        if (packet->type == TRACE_RT_DATA_ERF) {
653                        numbytes = erf_dump_packet(libtrace,
654                                (dag_record_t *)packet->header,
655                                pad,
656                                payload
657                                );
658        } else {
659                dag_record_t erfhdr;
660                int rlen;
661                int framing;
662                /* convert format - build up a new erf header */
663                /* Timestamp */
664                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
665
666                /* Flags. Can't do this */
667                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
668                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
669                        erfhdr.flags.iface = trace_get_direction(packet);
670
671                if (!find_compatible_linktype(libtrace,packet))
672                        return -1;
673
674                payload=packet->payload;
675                pad = erf_get_padding(packet);
676
677                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
678
679                /* Packet length (rlen includes format overhead) */
680                assert(trace_get_capture_length(packet)>0 
681                                && trace_get_capture_length(packet)<=65536);
682                assert(trace_get_framing_length(packet)<=65536);
683               
684                if (erfhdr.type == TYPE_ETH)
685                        framing = dag_record_size + 2;
686                else
687                        framing = dag_record_size;
688               
689                rlen = trace_get_capture_length(packet) + framing;
690                assert(rlen > 0 && rlen <= 65536);
691                erfhdr.rlen = htons(rlen);
692                /* loss counter. Can't do this */
693                erfhdr.lctr = 0;
694                /* Wire length, does not include padding! */
695                erfhdr.wlen = htons(trace_get_wire_length(packet));
696
697                /* Write it out */
698                numbytes = erf_dump_packet(libtrace,
699                                &erfhdr,
700                                pad,
701                                payload);
702        }
703        return numbytes;
704}
705
706libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
707        dag_record_t *erfptr = 0;
708        erfptr = (dag_record_t *)packet->header;
709        uint8_t type = (erfptr->type & 0x7f);
710        if (type != TYPE_LEGACY) {
711                /* The top-most bit is now used to indicate the presence of
712                 * extension headers :/ */
713                return erf_type_to_libtrace(type);
714        }
715        else {
716                /* Sigh, lets start wildly guessing */
717                if (((char*)packet->payload)[4]==0x45)
718                        return TRACE_TYPE_PPP;
719                return ~0;
720        }
721}
722
723libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
724        dag_record_t *erfptr = 0;
725        erfptr = (dag_record_t *)packet->header;
726        return erfptr->flags.iface;
727}
728
729libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
730        dag_record_t *erfptr = 0;
731        erfptr = (dag_record_t *)packet->header;
732        erfptr->flags.iface = direction;
733        return erfptr->flags.iface;
734}
735
736uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
737        dag_record_t *erfptr = 0;
738        erfptr = (dag_record_t *)packet->header;
739        return bswap_le_to_host64(erfptr->ts);
740}
741
742int erf_get_capture_length(const libtrace_packet_t *packet) {
743        dag_record_t *erfptr = 0;
744        int caplen;
745        if (packet->payload == NULL)
746                return 0; 
747       
748        erfptr = (dag_record_t *)packet->header;
749        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
750        if (ntohs(erfptr->wlen) < caplen)
751                return ntohs(erfptr->wlen);
752
753        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
754}
755
756int erf_get_wire_length(const libtrace_packet_t *packet) {
757        dag_record_t *erfptr = 0;
758        erfptr = (dag_record_t *)packet->header;
759        return ntohs(erfptr->wlen);
760}
761
762size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
763        dag_record_t *erfptr = 0;
764        assert(packet);
765        if(size  > trace_get_capture_length(packet)) {
766                /* Can't make a packet larger */
767                return trace_get_capture_length(packet);
768        }
769        /* Reset cached capture length - otherwise we will both return the
770         * wrong value here and subsequent get_capture_length() calls will
771         * return the wrong value. */
772        packet->capture_length = -1;
773        erfptr = (dag_record_t *)packet->header;
774        erfptr->rlen = htons(size + erf_get_framing_length(packet));
775        return trace_get_capture_length(packet);
776}
777
778static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
779        struct libtrace_eventobj_t event = {0,0,0.0,0};
780       
781        /* If we are being told to replay packets as fast as possible, then
782         * we just need to read and return the next packet in the trace */
783        if (IN_OPTIONS.real_time) {
784                event.size = trace_read_packet(libtrace, packet);
785                if (event.size < 1)
786                        event.type = TRACE_EVENT_TERMINATE;
787                else
788                        event.type = TRACE_EVENT_PACKET;
789                return event;
790               
791        } else {
792                /* Otherwise, use the generic event function */
793                return trace_event_trace(libtrace, packet);
794        }
795       
796}
797
798static uint64_t erf_get_dropped_packets(libtrace_t *trace)
799{
800        if (trace->format_data == NULL)
801                return (uint64_t)-1;
802        return DATA(trace)->drops;
803}
804
805static void erf_help(void) {
806        printf("erf format module: $Revision: 1752 $\n");
807        printf("Supported input URIs:\n");
808        printf("\terf:/path/to/file\t(uncompressed)\n");
809        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
810        printf("\terf:-\t(stdin, either compressed or not)\n");
811        printf("\terf:/path/to/socket\n");
812        printf("\n");
813        printf("\te.g.: erf:/tmp/trace\n");
814        printf("\n");
815        printf("Supported output URIs:\n");
816        printf("\terf:path/to/file\t(uncompressed)\n");
817        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
818        printf("\terf:-\t(stdout, either compressed or not)\n");
819        printf("\n");
820        printf("\te.g.: erf:/tmp/trace\n");
821        printf("\n");
822
823       
824}
825
826static struct libtrace_format_t erfformat = {
827        "erf",
828        "$Id$",
829        TRACE_FORMAT_ERF,
830        NULL,                           /* probe filename */
831        erf_probe_magic,                /* probe magic */
832        erf_init_input,                 /* init_input */       
833        erf_config_input,               /* config_input */
834        erf_start_input,                /* start_input */
835        NULL,                           /* pause_input */
836        erf_init_output,                /* init_output */
837        erf_config_output,              /* config_output */
838        erf_start_output,               /* start_output */
839        erf_fin_input,                  /* fin_input */
840        erf_fin_output,                 /* fin_output */
841        erf_read_packet,                /* read_packet */
842        erf_prepare_packet,             /* prepare_packet */
843        NULL,                           /* fin_packet */
844        erf_write_packet,               /* write_packet */
845        erf_get_link_type,              /* get_link_type */
846        erf_get_direction,              /* get_direction */
847        erf_set_direction,              /* set_direction */
848        erf_get_erf_timestamp,          /* get_erf_timestamp */
849        NULL,                           /* get_timeval */
850        NULL,                           /* get_timespec */
851        NULL,                           /* get_seconds */
852        erf_seek_erf,                   /* seek_erf */
853        NULL,                           /* seek_timeval */
854        NULL,                           /* seek_seconds */
855        erf_get_capture_length,         /* get_capture_length */
856        erf_get_wire_length,            /* get_wire_length */
857        erf_get_framing_length,         /* get_framing_length */
858        erf_set_capture_length,         /* set_capture_length */
859        NULL,                           /* get_received_packets */
860        NULL,                           /* get_filtered_packets */
861        erf_get_dropped_packets,        /* get_dropped_packets */
862        NULL,                           /* get_captured_packets */
863        NULL,                           /* get_fd */
864        erf_event,                      /* trace_event */
865        erf_help,                       /* help */
866        NULL                            /* next pointer */
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        erf_get_dropped_packets,        /* get_dropped_packets */
905        NULL,                           /* get_captured_packets */
906        NULL,                           /* get_fd */
907        erf_event,                      /* trace_event */
908        erf_help,                       /* help */
909        NULL                            /* next pointer */
910};
911
912
913
914void erf_constructor(void) {
915        register_format(&erfformat);
916        register_format(&rawerfformat);
917}
Note: See TracBrowser for help on using the repository browser.