source: lib/format_erf.c @ b3dca4d

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

Don't rely on rlen for determining write sizes for ERF packets

Sometimes rlen is greater than the capture + framing length for a packet, e.g.
in cases where the wlen is less than the rlen. Basing our arithmetic off
rlen can mean that we try to write too much data (especially if the packet
buffer has been sized to perfectly fit the packet according to
trace_get_capture_length and trace_get_framing_length). This will happen
if the ERF packets have been received via RT, for instance.

Also replace use of "dag_record_size + pad" with trace_get_framing_length() in
the same arithmetic, so that our write sizes are correct in the presence of
ERF extension headers.

  • Property mode set to 100644
File size: 23.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#define _GNU_SOURCE
36
37#include "config.h"
38#include "common.h"
39#include "libtrace.h"
40#include "libtrace_int.h"
41#include "format_helper.h"
42#include "format_erf.h"
43#include "wandio.h"
44
45#include <assert.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <stdio.h>
49#include <string.h>
50#include <stdlib.h>
51
52
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, int framinglen, void *buffer,
562                int caplen) {
563        int numbytes = 0;
564        int size;
565
566        if ((numbytes = 
567                wandio_wwrite(OUTPUT->file, 
568                                erfptr,
569                                (size_t)(framinglen))) 
570                        != (int)(framinglen)) {
571                trace_set_err_out(libtrace,errno,
572                                "write(%s)",libtrace->uridata);
573                return -1;
574        }
575
576        size=caplen-(framinglen);
577        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
578        if (numbytes != size) {
579                trace_set_err_out(libtrace,errno,
580                                "write(%s)",libtrace->uridata);
581                return -1;
582        }
583        return numbytes + framinglen;
584}
585
586static int erf_start_output(libtrace_out_t *libtrace)
587{
588        OUTPUT->file = trace_open_file_out(libtrace,
589                        OUT_OPTIONS.compress_type,
590                        OUT_OPTIONS.level,
591                        OUT_OPTIONS.fileflag);
592
593        if (!OUTPUT->file) {
594                return -1;
595        }
596        return 0;
597}
598
599static bool find_compatible_linktype(libtrace_out_t *libtrace,
600                                libtrace_packet_t *packet)
601{
602        /* Keep trying to simplify the packet until we can find
603         * something we can do with it */
604        do {
605                char type=libtrace_to_erf_type(trace_get_link_type(packet));
606
607                /* Success */
608                if (type != (char)-1)
609                        return true;
610
611                if (!demote_packet(packet)) {
612                        trace_set_err_out(libtrace,
613                                        TRACE_ERR_NO_CONVERSION,
614                                        "No erf type for packet (%i)",
615                                        trace_get_link_type(packet));
616                        return false;
617                }
618
619        } while(1);
620
621        return true;
622}
623               
624static int erf_write_packet(libtrace_out_t *libtrace, 
625                libtrace_packet_t *packet) 
626{
627        int numbytes = 0;
628        unsigned int pad = 0;
629        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
630        void *payload = packet->payload;
631
632        assert(OUTPUT->file);
633
634        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
635                return 0;
636
637        if (!packet->header) {
638                return -1;
639        }
640       
641        pad = erf_get_padding(packet);
642
643        /* If we've had an rxerror, we have no payload to write - fix
644         * rlen to be the correct length
645         */
646        /* I Think this is bogus, we should somehow figure out
647         * a way to write out the payload even if it is gibberish -- Perry */
648        if (payload == NULL) {
649                dag_hdr->rlen = htons(dag_record_size + pad);
650               
651        } 
652       
653        if (packet->type == TRACE_RT_DATA_ERF) {
654                        numbytes = erf_dump_packet(libtrace,
655                                (dag_record_t *)packet->header,
656                                trace_get_framing_length(packet),
657                                payload,
658                                trace_get_capture_length(packet)
659                                );
660        } else {
661                dag_record_t erfhdr;
662                int rlen;
663                int framing;
664                /* convert format - build up a new erf header */
665                /* Timestamp */
666                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
667
668                /* Flags. Can't do this */
669                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
670                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
671                        erfhdr.flags.iface = trace_get_direction(packet);
672
673                if (!find_compatible_linktype(libtrace,packet))
674                        return -1;
675
676                payload=packet->payload;
677                pad = erf_get_padding(packet);
678
679                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
680
681                /* Packet length (rlen includes format overhead) */
682                assert(trace_get_capture_length(packet)>0 
683                                && trace_get_capture_length(packet)<=65536);
684                assert(trace_get_framing_length(packet)<=65536);
685               
686                if (erfhdr.type == TYPE_ETH)
687                        framing = dag_record_size + 2;
688                else
689                        framing = dag_record_size;
690               
691                rlen = trace_get_capture_length(packet) + framing;
692                assert(rlen > 0 && rlen <= 65536);
693                erfhdr.rlen = htons(rlen);
694                /* loss counter. Can't do this */
695                erfhdr.lctr = 0;
696                /* Wire length, does not include padding! */
697                erfhdr.wlen = htons(trace_get_wire_length(packet));
698
699                /* Write it out */
700                numbytes = erf_dump_packet(libtrace,
701                                &erfhdr,
702                                framing,
703                                payload,
704                                trace_get_capture_length(packet));
705        }
706        return numbytes;
707}
708
709libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
710        dag_record_t *erfptr = 0;
711        erfptr = (dag_record_t *)packet->header;
712        uint8_t type = (erfptr->type & 0x7f);
713        if (type != TYPE_LEGACY) {
714                /* The top-most bit is now used to indicate the presence of
715                 * extension headers :/ */
716                return erf_type_to_libtrace(type);
717        }
718        else {
719                /* Sigh, lets start wildly guessing */
720                if (((char*)packet->payload)[4]==0x45)
721                        return TRACE_TYPE_PPP;
722                return ~0;
723        }
724}
725
726libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
727        dag_record_t *erfptr = 0;
728        erfptr = (dag_record_t *)packet->header;
729        return erfptr->flags.iface;
730}
731
732libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
733        dag_record_t *erfptr = 0;
734        erfptr = (dag_record_t *)packet->header;
735        erfptr->flags.iface = direction;
736        return erfptr->flags.iface;
737}
738
739uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
740        dag_record_t *erfptr = 0;
741        erfptr = (dag_record_t *)packet->header;
742        return bswap_le_to_host64(erfptr->ts);
743}
744
745int erf_get_capture_length(const libtrace_packet_t *packet) {
746        dag_record_t *erfptr = 0;
747        int caplen;
748        if (packet->payload == NULL)
749                return 0; 
750       
751        erfptr = (dag_record_t *)packet->header;
752        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
753        if (ntohs(erfptr->wlen) < caplen)
754                return ntohs(erfptr->wlen);
755
756        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
757}
758
759int erf_get_wire_length(const libtrace_packet_t *packet) {
760        dag_record_t *erfptr = 0;
761        erfptr = (dag_record_t *)packet->header;
762        return ntohs(erfptr->wlen);
763}
764
765size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
766        dag_record_t *erfptr = 0;
767        assert(packet);
768        if(size  > trace_get_capture_length(packet)) {
769                /* Can't make a packet larger */
770                return trace_get_capture_length(packet);
771        }
772        /* Reset cached capture length - otherwise we will both return the
773         * wrong value here and subsequent get_capture_length() calls will
774         * return the wrong value. */
775        packet->capture_length = -1;
776        erfptr = (dag_record_t *)packet->header;
777        erfptr->rlen = htons(size + erf_get_framing_length(packet));
778        return trace_get_capture_length(packet);
779}
780
781static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
782        struct libtrace_eventobj_t event = {0,0,0.0,0};
783       
784        /* If we are being told to replay packets as fast as possible, then
785         * we just need to read and return the next packet in the trace */
786        if (IN_OPTIONS.real_time) {
787                event.size = trace_read_packet(libtrace, packet);
788                if (event.size < 1)
789                        event.type = TRACE_EVENT_TERMINATE;
790                else
791                        event.type = TRACE_EVENT_PACKET;
792                return event;
793               
794        } else {
795                /* Otherwise, use the generic event function */
796                return trace_event_trace(libtrace, packet);
797        }
798       
799}
800
801static uint64_t erf_get_dropped_packets(libtrace_t *trace)
802{
803        if (trace->format_data == NULL)
804                return (uint64_t)-1;
805        return DATA(trace)->drops;
806}
807
808static void erf_help(void) {
809        printf("erf format module: $Revision: 1752 $\n");
810        printf("Supported input URIs:\n");
811        printf("\terf:/path/to/file\t(uncompressed)\n");
812        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
813        printf("\terf:-\t(stdin, either compressed or not)\n");
814        printf("\terf:/path/to/socket\n");
815        printf("\n");
816        printf("\te.g.: erf:/tmp/trace\n");
817        printf("\n");
818        printf("Supported output URIs:\n");
819        printf("\terf:path/to/file\t(uncompressed)\n");
820        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
821        printf("\terf:-\t(stdout, either compressed or not)\n");
822        printf("\n");
823        printf("\te.g.: erf:/tmp/trace\n");
824        printf("\n");
825
826       
827}
828
829static struct libtrace_format_t erfformat = {
830        "erf",
831        "$Id$",
832        TRACE_FORMAT_ERF,
833        NULL,                           /* probe filename */
834        erf_probe_magic,                /* probe magic */
835        erf_init_input,                 /* init_input */       
836        erf_config_input,               /* config_input */
837        erf_start_input,                /* start_input */
838        NULL,                           /* pause_input */
839        erf_init_output,                /* init_output */
840        erf_config_output,              /* config_output */
841        erf_start_output,               /* start_output */
842        erf_fin_input,                  /* fin_input */
843        erf_fin_output,                 /* fin_output */
844        erf_read_packet,                /* read_packet */
845        erf_prepare_packet,             /* prepare_packet */
846        NULL,                           /* fin_packet */
847        erf_write_packet,               /* write_packet */
848        erf_get_link_type,              /* get_link_type */
849        erf_get_direction,              /* get_direction */
850        erf_set_direction,              /* set_direction */
851        erf_get_erf_timestamp,          /* get_erf_timestamp */
852        NULL,                           /* get_timeval */
853        NULL,                           /* get_timespec */
854        NULL,                           /* get_seconds */
855        erf_seek_erf,                   /* seek_erf */
856        NULL,                           /* seek_timeval */
857        NULL,                           /* seek_seconds */
858        erf_get_capture_length,         /* get_capture_length */
859        erf_get_wire_length,            /* get_wire_length */
860        erf_get_framing_length,         /* get_framing_length */
861        erf_set_capture_length,         /* set_capture_length */
862        NULL,                           /* get_received_packets */
863        NULL,                           /* get_filtered_packets */
864        erf_get_dropped_packets,        /* get_dropped_packets */
865        NULL,                           /* get_statistics */
866        NULL,                           /* get_fd */
867        erf_event,                      /* trace_event */
868        erf_help,                       /* help */
869        NULL,                           /* next pointer */
870        NON_PARALLEL(false)
871};
872
873static struct libtrace_format_t rawerfformat = {
874        "rawerf",
875        "$Id$",
876        TRACE_FORMAT_RAWERF,
877        NULL,                           /* probe filename */
878        NULL,           /* probe magic */
879        erf_init_input,                 /* init_input */       
880        erf_config_input,               /* config_input */
881        rawerf_start_input,             /* start_input */
882        NULL,                           /* pause_input */
883        erf_init_output,                /* init_output */
884        erf_config_output,              /* config_output */
885        erf_start_output,               /* start_output */
886        erf_fin_input,                  /* fin_input */
887        erf_fin_output,                 /* fin_output */
888        erf_read_packet,                /* read_packet */
889        erf_prepare_packet,             /* prepare_packet */
890        NULL,                           /* fin_packet */
891        erf_write_packet,               /* write_packet */
892        erf_get_link_type,              /* get_link_type */
893        erf_get_direction,              /* get_direction */
894        erf_set_direction,              /* set_direction */
895        erf_get_erf_timestamp,          /* get_erf_timestamp */
896        NULL,                           /* get_timeval */
897        NULL,                           /* get_timespec */
898        NULL,                           /* get_seconds */
899        erf_seek_erf,                   /* seek_erf */
900        NULL,                           /* seek_timeval */
901        NULL,                           /* seek_seconds */
902        erf_get_capture_length,         /* get_capture_length */
903        erf_get_wire_length,            /* get_wire_length */
904        erf_get_framing_length,         /* get_framing_length */
905        erf_set_capture_length,         /* set_capture_length */
906        NULL,                           /* get_received_packets */
907        NULL,                           /* get_filtered_packets */
908        erf_get_dropped_packets,        /* get_dropped_packets */
909        NULL,                           /* get_statistics */
910        NULL,                           /* get_fd */
911        erf_event,                      /* trace_event */
912        erf_help,                       /* help */
913        NULL,                           /* next pointer */
914        NON_PARALLEL(false)
915};
916
917
918
919void erf_constructor(void) {
920        register_format(&erfformat);
921        register_format(&rawerfformat);
922}
Note: See TracBrowser for help on using the repository browser.