source: lib/format_erf.c @ 254c926

develop
Last change on this file since 254c926 was 254c926, checked in by Jacob Van Walraven <jcv9@…>, 21 months ago

Cleanup some duplicate code, Added datatype/option_name for libtrace_meta_t structure

  • Property mode set to 100644
File size: 40.4 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26
27#define _GNU_SOURCE
28
29#include "config.h"
30#include "common.h"
31#include "libtrace.h"
32#include "libtrace_int.h"
33#include "format_helper.h"
34#include "format_erf.h"
35#include "wandio.h"
36
37#include <errno.h>
38#include <fcntl.h>
39#include <stdio.h>
40#include <string.h>
41#include <stdlib.h>
42
43
44#ifdef WIN32
45#  include <io.h>
46#  include <share.h>
47#  define PATH_MAX _MAX_PATH
48#else
49#  include <netdb.h>
50#  ifndef PATH_MAX
51#       define PATH_MAX 4096
52#  endif
53#  include <sys/ioctl.h>
54#endif
55
56/* This format module deals with reading and writing ERF traces. ERF is the
57 * trace format developed by Endace for use by DAG hardware capture cards.
58 *
59 * ERF is not a live capture format.
60 *
61 */
62
63#define ERF_META_TYPE 27
64
65static struct libtrace_format_t erfformat;
66
67#define DATA(x) ((struct erf_format_data_t *)x->format_data)
68#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
69
70#define IN_OPTIONS DATA(libtrace)->options
71#define OUTPUT DATAOUT(libtrace)
72#define OUT_OPTIONS DATAOUT(libtrace)->options
73
74/* "Global" data that is stored for each ERF input trace */
75struct erf_format_data_t {
76       
77        /* Index used for seeking within a trace */
78        struct {
79                /* The index itself */
80                io_t *index;
81                /* The offset of the index */
82                off_t index_len;
83                /* Indicates the existence of an index */
84                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
85        } seek;
86
87        /* Number of packets that were dropped during the capture */
88        uint64_t drops;
89
90        bool discard_meta;
91
92        /* Config options for the input trace */
93        struct {
94                /* Flag indicating whether the event API should replicate the
95                 * time gaps between each packet or return a PACKET event for
96                 * each packet */
97                int real_time;
98        } options;
99};
100
101/* "Global" data that is stored for each ERF output trace */
102struct erf_format_data_out_t {
103
104        /* Config options for the output trace */
105        struct {
106                /* Compression level for the output file */
107                int level;
108                /* Compression type */
109                int compress_type;
110                /* File flags used to open the file, e.g. O_CREATE */
111                int fileflag;
112        } options;
113
114        /* The output file itself */
115        iow_t *file;
116       
117};
118
119typedef struct erf_index_t {
120        uint64_t timestamp;
121        uint64_t offset; 
122} erf_index_t;
123
124static bool erf_can_write(libtrace_packet_t *packet) {
125        /* Get the linktype */
126        libtrace_linktype_t ltype = trace_get_link_type(packet);
127
128        if (ltype == TRACE_TYPE_PCAPNG_META
129                || ltype == TRACE_TYPE_NONDATA) {
130
131                return false;
132        }
133
134        return true;
135}
136
137/* Ethernet packets have a 2 byte padding before the packet
138 * so that the IP header is aligned on a 32 bit boundary.
139 */
140static inline int erf_get_padding(const libtrace_packet_t *packet)
141{
142        dag_record_t *erfptr = (dag_record_t *)packet->header;
143
144        switch(packet->trace->format->type) {
145                case TRACE_FORMAT_ERF:
146                case TRACE_FORMAT_NDAG:
147                case TRACE_FORMAT_RAWERF:
148                case TRACE_FORMAT_DPDK_NDAG:
149                        switch((erfptr->type & 0x7f)) {
150                                case TYPE_ETH:
151                                case TYPE_COLOR_ETH:
152                                case TYPE_DSM_COLOR_ETH:
153                                case TYPE_COLOR_HASH_ETH:
154                                        return 2;
155                                default:
156                                        return 0;
157                        }
158                        break;
159                default:
160                        switch(trace_get_link_type(packet)) {
161                                case TRACE_TYPE_ETH:    return 2;
162                                default:                return 0;
163                        }
164                        break;
165        }
166        return 0;
167}
168
169int erf_is_color_type(uint8_t erf_type)
170{
171        switch(erf_type & 0x7f) {
172                case TYPE_COLOR_HDLC_POS:
173                case TYPE_DSM_COLOR_HDLC_POS:
174                case TYPE_COLOR_ETH:
175                case TYPE_DSM_COLOR_ETH:
176                case TYPE_COLOR_HASH_POS:
177                case TYPE_COLOR_HASH_ETH:
178                        return 1;
179        }
180
181        return 0;
182}
183
184int erf_get_framing_length(const libtrace_packet_t *packet)
185{
186        uint16_t extsize = 0;
187        dag_record_t *erfptr = NULL;
188        uint64_t *exthdr = NULL;
189        uint8_t *firstbyte;
190
191        erfptr = (dag_record_t *)packet->header;
192        if ((erfptr->type & 0x80) == 0x80) {
193                /* Extension headers are present */
194                exthdr = (uint64_t *)((char *)packet->header + dag_record_size);
195                extsize += 8;
196
197                firstbyte = (uint8_t *)exthdr;
198                while ((*firstbyte & 0x80) == 0x80) {
199                        extsize += 8;
200                        exthdr ++;
201                        firstbyte = (uint8_t *)exthdr;
202                        if (extsize > ntohs(erfptr->rlen)) {
203                                trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET, "Extension size is greater than dag record record length in erf_get_framing_length()");
204                                return -1;
205                        }
206                }
207        }
208        return dag_record_size + extsize + erf_get_padding(packet);
209}
210
211/* Attempts to determine whether a given trace file is using the ERF format
212 *
213 * Returns 1 if the trace is probably ERF, 0 otherwise
214 */
215static int erf_probe_magic(io_t *io)
216{
217        char buffer[4096];
218        int len;
219        dag_record_t *erf;
220        len = wandio_peek(io, buffer, sizeof(buffer));
221        if (len < (int)dag_record_size) {
222                return 0; /* False */
223        }
224        erf = (dag_record_t *) buffer;
225        /* If the record is too short */
226        if (ntohs(erf->rlen) < dag_record_size) {
227                return 0;
228        }
229        /* There aren't any erf traces before 1995-01-01 */
230        if (bswap_le_to_host64(erf->ts) < 0x2f0539b000000000ULL) {
231                return 0;
232        }
233        /* And not pcap! */
234        if (bswap_le_to_host64(erf->ts) >>32 == 0xa1b2c3d4) {
235                return 0;
236        }
237        /* And not the other pcap! */
238        if (bswap_le_to_host64(erf->ts) >>32 == 0xd4c3b2a1) {
239                return 0;
240        }
241        /* Is this a proper typed packet */
242        if ((erf->type & 0x7f) > ERF_TYPE_MAX) {
243                return 0;
244        }
245        /* We should put some more tests in here. */
246        /* Yeah, this is probably ERF */
247        return 1;
248}
249
250static int erf_init_input(libtrace_t *libtrace) {
251        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
252
253        if (!libtrace->format_data) {
254                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory for "
255                        "format data inside erf_init_input()");
256                return -1;
257        }
258
259        IN_OPTIONS.real_time = 0;
260        DATA(libtrace)->drops = 0;
261
262        DATA(libtrace)->discard_meta = 0;
263
264        return 0; /* success */
265}
266
267static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
268                void *value) {
269
270        switch (option) {
271                case TRACE_OPTION_EVENT_REALTIME:
272                        IN_OPTIONS.real_time = *(int *)value;
273                        return 0;
274                case TRACE_OPTION_CONSTANT_ERF_FRAMING:
275                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
276                                        "Setting constant framing length is not supported for %s:", libtrace->format->name);
277                        return -1;
278                case TRACE_OPTION_SNAPLEN:
279                case TRACE_OPTION_PROMISC:
280                case TRACE_OPTION_FILTER:
281                case TRACE_OPTION_META_FREQ:
282                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
283                                        "Unsupported option");
284                        return -1;
285                case TRACE_OPTION_DISCARD_META:
286                        if (*(int *)value > 0) {
287                                DATA(libtrace)->discard_meta = true;
288                        } else {
289                                DATA(libtrace)->discard_meta = false;
290                        }
291                        return 0;
292                default:
293                        /* Unknown option */
294                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
295                                        "Unknown option");
296                        return -1;
297        }
298}
299
300static int erf_start_input(libtrace_t *libtrace) 
301{
302        if (libtrace->io)
303                return 0; /* Success -- already done. */
304
305        libtrace->io = trace_open_file(libtrace);
306
307        if (!libtrace->io)
308                return -1;
309
310        DATA(libtrace)->drops = 0;
311        return 0; /* success */
312}
313
314/* Raw ERF is a special case -- we want to force libwandio to treat the file
315 * as uncompressed so we can't just use trace_open_file() */
316static int rawerf_start_input(libtrace_t *libtrace)
317{
318        if (libtrace->io)
319                return 0; 
320
321        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
322
323        if (!libtrace->io) {
324                if (errno != 0) {
325                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
326                }
327                return -1;
328        }
329
330        DATA(libtrace)->drops = 0;
331
332        return 0; /* success */
333}
334
335/* Binary search through the index to find the closest point before
336 * the packet.  Consider in future having a btree index perhaps?
337 */
338static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
339{
340        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
341        size_t min_off = 0;
342        off_t current;
343        erf_index_t record;
344        do {
345                current=(max_off+min_off)>>2;
346
347                wandio_seek(DATA(libtrace)->seek.index,
348                                (int64_t)(current*sizeof(record)),
349                                SEEK_SET);
350                wandio_read(DATA(libtrace)->seek.index,
351                                &record,sizeof(record));
352                if (record.timestamp < erfts) {
353                        min_off=current;
354                }
355                if (record.timestamp > erfts) {
356                        max_off=current;
357                }
358                if (record.timestamp == erfts)
359                        break;
360        } while(min_off<max_off);
361
362        /* If we've passed it, seek backwards.  This loop shouldn't
363         * execute more than twice.
364         */
365        do {
366                wandio_seek(DATA(libtrace)->seek.index,
367                                (int64_t)(current*sizeof(record)),SEEK_SET);
368                wandio_read(DATA(libtrace)->seek.index,
369                                &record,sizeof(record));
370                current--;
371        } while(record.timestamp>erfts);
372
373        /* We've found our location in the trace, now use it. */
374        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
375
376        return 0; /* success */
377}
378
379/* There is no index.  Seek through the entire trace from the start, nice
380 * and slowly.
381 */
382static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
383{
384        if (libtrace->io) {
385                wandio_destroy(libtrace->io);
386        }
387        libtrace->io = trace_open_file(libtrace);
388        if (!libtrace->io)
389                return -1;
390        return 0;
391}
392
393/* Seek within an ERF trace based on an ERF timestamp */
394static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
395{
396        libtrace_packet_t *packet;
397        off_t off = 0;
398
399        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
400                char buffer[PATH_MAX];
401                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
402                DATA(libtrace)->seek.index=wandio_create(buffer);
403                if (DATA(libtrace)->seek.index) {
404                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
405                }
406                else {
407                        DATA(libtrace)->seek.exists=INDEX_NONE;
408                }
409        }
410
411        /* If theres an index, use it to find the nearest packet that isn't
412         * after the time we're looking for.  If there is no index we need
413         * to seek slowly through the trace from the beginning.  Sigh.
414         */
415        switch(DATA(libtrace)->seek.exists) {
416                case INDEX_EXISTS:
417                        erf_fast_seek_start(libtrace,erfts);
418                        break;
419                case INDEX_NONE:
420                        erf_slow_seek_start(libtrace,erfts);
421                        break;
422                case INDEX_UNKNOWN:
423                        trace_set_err(libtrace, TRACE_ERR_SEEK_ERF, "Cannot seek to erf timestamp with unknown index in erf_seek_erf()");
424                        return -1;
425                        break;
426        }
427
428        /* Now seek forward looking for the correct timestamp */
429        packet=trace_create_packet();
430        do {
431                trace_read_packet(libtrace,packet);
432                if (trace_get_erf_timestamp(packet)==erfts)
433                        break;
434                off=wandio_tell(libtrace->io);
435        } while(trace_get_erf_timestamp(packet)<erfts);
436
437        wandio_seek(libtrace->io,off,SEEK_SET);
438
439        return 0;
440}
441
442static int erf_init_output(libtrace_out_t *libtrace) {
443        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
444
445        if (!libtrace->format_data) {
446                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory for "
447                        "format data inside erf_init_output()");
448                return -1;
449        }
450
451        OUT_OPTIONS.level = 0;
452        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
453        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
454        OUTPUT->file = 0;
455
456        return 0;
457}
458
459static int erf_config_output(libtrace_out_t *libtrace, 
460                trace_option_output_t option, void *value) {
461
462        switch (option) {
463                case TRACE_OPTION_OUTPUT_COMPRESS:
464                        OUT_OPTIONS.level = *(int*)value;
465                        return 0;
466                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
467                        OUT_OPTIONS.compress_type = *(int*)value;
468                        return 0;
469                case TRACE_OPTION_OUTPUT_FILEFLAGS:
470                        OUT_OPTIONS.fileflag = *(int*)value;
471                        return 0;
472                default:
473                        /* Unknown option */
474                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
475                                        "Unknown option");
476                        return -1;
477        }
478}
479
480
481
482static int erf_fin_input(libtrace_t *libtrace) {
483        if (libtrace->io)
484                wandio_destroy(libtrace->io);
485        free(libtrace->format_data);
486        return 0;
487}
488
489static int erf_fin_output(libtrace_out_t *libtrace) {
490        if (OUTPUT->file)
491                wandio_wdestroy(OUTPUT->file);
492        free(libtrace->format_data);
493        return 0;
494}
495 
496static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
497                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
498       
499        dag_record_t *erfptr;
500
501        if (packet->buffer != buffer && 
502                packet->buf_control == TRACE_CTRL_PACKET) {
503                free(packet->buffer);
504        }
505
506        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
507                packet->buf_control = TRACE_CTRL_PACKET;
508        } else
509                packet->buf_control = TRACE_CTRL_EXTERNAL;
510
511        packet->type = rt_type;
512        packet->buffer = buffer;
513        packet->header = buffer;
514        erfptr = (dag_record_t *)packet->buffer;
515        if (erfptr->flags.rxerror == 1) {
516                packet->payload = NULL;
517        } else {
518                packet->payload = ((char*)packet->buffer) + trace_get_framing_length(packet);
519        }
520
521        if (erfptr->rlen == 0) {
522                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "ERF packet has an invalid record "
523                        "length: zero, in erf_prepare_packet()\n");
524                return -1;
525        }
526
527        if (libtrace->format_data == NULL) {
528                /* Allocates the format_data structure */
529                if (erf_init_input(libtrace)) 
530                        return -1;
531        }
532
533        /* Check for loss */
534        if (erf_is_color_type(erfptr->type)) {
535                /* No idea how we get this yet */
536
537        } else if (erfptr->lctr) {
538                DATA(libtrace)->drops += ntohs(erfptr->lctr);
539        }
540
541        return 0;
542}
543
544static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
545        int numbytes;
546        unsigned int size;
547        void *buffer2 = packet->buffer;
548        unsigned int rlen;
549        uint32_t flags = 0;
550        libtrace_rt_types_t linktype;
551        int gotpacket = 0;
552
553        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
554                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
555                if (!packet->buffer) {
556                        trace_set_err(libtrace, errno, "Cannot allocate memory");
557                        return -1;
558                }
559        }
560
561        flags |= TRACE_PREP_OWN_BUFFER;
562
563        while (!gotpacket) {
564
565                if ((numbytes=wandio_read(libtrace->io, packet->buffer,
566                        (size_t)dag_record_size)) == -1) {
567
568                        trace_set_err(libtrace,errno,"reading ERF file");
569                        return -1;
570                }
571
572                /* EOF */
573                if (numbytes == 0) {
574                        return 0;
575                }
576
577                if (numbytes < (int)dag_record_size) {
578                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header");
579                        return -1;
580                }
581
582                rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
583                buffer2 = (char*)packet->buffer + dag_record_size;
584                size = rlen - dag_record_size;
585
586                if (size >= LIBTRACE_PACKET_BUFSIZE) {
587                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
588                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
589                                size);
590                        return -1;
591                }
592
593                /* Unknown/corrupt */
594                if ((((dag_record_t *)packet->buffer)->type & 0x7f) > ERF_TYPE_MAX) {
595                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
596                                "Corrupt or Unknown ERF type");
597                        return -1;
598                }
599
600                /* read in the rest of the packet */
601                if ((numbytes=wandio_read(libtrace->io, buffer2,
602                        (size_t)size)) != (int)size) {
603
604                        if (numbytes==-1) {
605                                trace_set_err(libtrace,errno, "read(%s)", 
606                                        libtrace->uridata);
607                                return -1;
608                        }
609
610                        trace_set_err(libtrace,EIO,
611                                "Truncated packet (wanted %d, got %d)", size, numbytes);
612
613                        /* Failed to read the full packet?  must be EOF */
614                        return -1;
615                }
616
617                if (numbytes < (int)size) {
618                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record");
619                        return -1;
620                }
621
622                /* If a provenance packet make sure correct rt linktype is set.
623                 * Only bits 0-6 are used for the type */
624                if ((((dag_record_t *)packet->buffer)->type & 127) == ERF_META_TYPE) {
625                        linktype = TRACE_RT_ERF_META;
626                } else { linktype = TRACE_RT_DATA_ERF; }
627
628                /* If this is a meta packet and TRACE_OPTION_DISCARD_META is set
629                 * ignore this packet and get another */
630                if ((linktype == TRACE_RT_ERF_META && !DATA(libtrace)->discard_meta) ||
631                        linktype == TRACE_RT_DATA_ERF) {
632                        gotpacket = 1;
633
634                        if (erf_prepare_packet(libtrace, packet, packet->buffer, linktype, flags)) {
635                                return -1;
636                        }
637                }
638        }
639
640        return rlen;
641}
642
643static int erf_dump_packet(libtrace_out_t *libtrace,
644                dag_record_t *erfptr, int framinglen, void *buffer,
645                int caplen) {
646        int numbytes = 0;
647
648        if (caplen + framinglen != ntohs(erfptr->rlen))
649                erfptr->rlen = htons(caplen + framinglen);
650
651        if ((numbytes = 
652                wandio_wwrite(OUTPUT->file, 
653                                erfptr,
654                                (size_t)(framinglen))) 
655                        != (int)(framinglen)) {
656                trace_set_err_out(libtrace,errno,
657                                "write(%s)",libtrace->uridata);
658                return -1;
659        }
660
661        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)caplen);
662        if (numbytes != caplen) {
663                trace_set_err_out(libtrace,errno,
664                                "write(%s)",libtrace->uridata);
665                return -1;
666        }
667        return numbytes + framinglen;
668}
669
670static int erf_flush_output(libtrace_out_t *libtrace) {
671        return wandio_wflush(OUTPUT->file);
672}
673
674static int erf_start_output(libtrace_out_t *libtrace)
675{
676        OUTPUT->file = trace_open_file_out(libtrace,
677                        OUT_OPTIONS.compress_type,
678                        OUT_OPTIONS.level,
679                        OUT_OPTIONS.fileflag);
680
681        if (!OUTPUT->file) {
682                return -1;
683        }
684        return 0;
685}
686
687static bool find_compatible_linktype(libtrace_out_t *libtrace,
688                                libtrace_packet_t *packet)
689{
690        /* Keep trying to simplify the packet until we can find
691         * something we can do with it */
692        do {
693                char type=libtrace_to_erf_type(trace_get_link_type(packet));
694
695                /* Success */
696                if (type != (char)-1)
697                        return true;
698
699                if (!demote_packet(packet)) {
700                        trace_set_err_out(libtrace,
701                                        TRACE_ERR_NO_CONVERSION,
702                                        "No erf type for packet (%i)",
703                                        trace_get_link_type(packet));
704                        return false;
705                }
706
707        } while(1);
708
709        return true;
710}
711               
712static int erf_write_packet(libtrace_out_t *libtrace, 
713                libtrace_packet_t *packet) 
714{
715
716        /* Check erf can write this type of packet */
717        if (!erf_can_write(packet)) {
718                return 0;
719        }
720
721        int numbytes = 0;
722        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
723        void *payload = packet->payload;
724
725        if (!OUTPUT->file) {
726                trace_set_err_out(libtrace, TRACE_ERR_BAD_IO, "Attempted to write ERF packets to a "
727                        "closed file, must call trace_create_output() before calling trace_write_output()");
728                return -1;
729        }
730
731        if (!packet->header) {
732                return -1;
733        }
734       
735
736        /* If we've had an rxerror, we have no payload to write - fix
737         * rlen to be the correct length
738         */
739        /* I Think this is bogus, we should somehow figure out
740         * a way to write out the payload even if it is gibberish -- Perry */
741        if (payload == NULL) {
742                unsigned int pad = 0;
743                pad = erf_get_padding(packet);
744                dag_hdr->rlen = htons(dag_record_size + pad);
745               
746        } 
747       
748        if (packet->type == TRACE_RT_DATA_ERF) {
749                        numbytes = erf_dump_packet(libtrace,
750                                (dag_record_t *)packet->header,
751                                trace_get_framing_length(packet),
752                                payload,
753                                trace_get_capture_length(packet)
754                                );
755        } else {
756                dag_record_t erfhdr;
757                int rlen;
758                int framing;
759                /* convert format - build up a new erf header */
760                /* Timestamp */
761                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
762
763                /* Flags. Can't do this */
764                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
765                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
766                        erfhdr.flags.iface = trace_get_direction(packet);
767
768                if (!find_compatible_linktype(libtrace,packet))
769                        return -1;
770
771                payload=packet->payload;
772
773                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
774
775                /* Packet length (rlen includes format overhead) */
776                if (trace_get_capture_length(packet) <= 0
777                        || trace_get_capture_length(packet) > 65536) {
778                        trace_set_err_out(libtrace, TRACE_ERR_BAD_PACKET,
779                                "Capture length is out of range in erf_write_packet()");
780                        return -1;
781                }
782                if (trace_get_framing_length(packet) > 65536) {
783                        trace_set_err_out(libtrace, TRACE_ERR_BAD_PACKET,
784                                "Framing length is to large in erf_write_packet()");
785                        return -1;
786                }
787
788                if (erfhdr.type == TYPE_ETH)
789                        framing = dag_record_size + 2;
790                else
791                        framing = dag_record_size;
792
793                rlen = trace_get_capture_length(packet) + framing;
794                if (rlen <= 0 || rlen > 65536) {
795                        trace_set_err_out(libtrace, TRACE_ERR_BAD_PACKET,
796                                "Capture + framing length is out of range in erf_write_packet()");
797                        return -1;
798                }
799                erfhdr.rlen = htons(rlen);
800                /* loss counter. Can't do this */
801                erfhdr.lctr = 0;
802                /* Wire length, does not include padding! */
803                erfhdr.wlen = htons(trace_get_wire_length(packet));
804
805                /* Write it out */
806                numbytes = erf_dump_packet(libtrace,
807                                &erfhdr,
808                                framing,
809                                payload,
810                                trace_get_capture_length(packet));
811        }
812        return numbytes;
813}
814
815libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
816        dag_record_t *erfptr = 0;
817        erfptr = (dag_record_t *)packet->header;
818        uint8_t type = (erfptr->type & 0x7f);
819        if (type != TYPE_LEGACY) {
820                /* The top-most bit is now used to indicate the presence of
821                 * extension headers :/ */
822                return erf_type_to_libtrace(type);
823        }
824        else {
825                /* Sigh, lets start wildly guessing */
826                if (((char*)packet->payload)[4]==0x45)
827                        return TRACE_TYPE_PPP;
828                return ~0;
829        }
830}
831
832libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
833        dag_record_t *erfptr = 0;
834        erfptr = (dag_record_t *)packet->header;
835        return erfptr->flags.iface;
836}
837
838libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
839        dag_record_t *erfptr = 0;
840        erfptr = (dag_record_t *)packet->header;
841        erfptr->flags.iface = direction;
842        return erfptr->flags.iface;
843}
844
845uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
846        dag_record_t *erfptr = 0;
847        erfptr = (dag_record_t *)packet->header;
848        return bswap_le_to_host64(erfptr->ts);
849}
850
851int erf_get_capture_length(const libtrace_packet_t *packet) {
852        dag_record_t *erfptr = 0;
853        int caplen;
854        size_t framinglen;
855        uint16_t wlen, rlen;
856
857        if (packet->payload == NULL)
858                return 0;
859
860        erfptr = (dag_record_t *)packet->header;
861        framinglen = trace_get_framing_length(packet);
862        rlen = ntohs(erfptr->rlen);
863        wlen = ntohs(erfptr->wlen);
864
865        caplen = rlen - framinglen;
866        if (wlen < caplen)
867                return wlen;
868
869        return caplen;
870}
871
872int erf_get_wire_length(const libtrace_packet_t *packet) {
873        dag_record_t *erfptr = 0;
874        erfptr = (dag_record_t *)packet->header;
875
876        if ((erfptr->type & 0x7f) == TYPE_META)
877                return 0;
878
879        return ntohs(erfptr->wlen);
880}
881
882size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
883        dag_record_t *erfptr = 0;
884        uint16_t wlen;
885
886        if (!packet) {
887                fprintf(stderr, "NULL packet passed to erf_set_capture_length()\n");
888                return ~0U;
889        }
890        erfptr = (dag_record_t *)packet->header;
891
892        if(size > trace_get_capture_length(packet) || (erfptr->type & 0x7f) == TYPE_META) {
893                /* Can't make a packet larger */
894                return trace_get_capture_length(packet);
895        }
896
897        /* Reset cached capture length - otherwise we will both return the
898         * wrong value here and subsequent get_capture_length() calls will
899         * return the wrong value. */
900        packet->cached.capture_length = -1;
901        erfptr->rlen = htons(size + trace_get_framing_length(packet));
902        wlen = ntohs(erfptr->wlen);
903
904        if (wlen < size) {
905                return wlen;
906        }
907
908        return size;
909}
910
911static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
912        struct libtrace_eventobj_t event = {0,0,0.0,0};
913       
914        /* If we are being told to replay packets as fast as possible, then
915         * we just need to read and return the next packet in the trace */
916        if (IN_OPTIONS.real_time) {
917                event.size = trace_read_packet(libtrace, packet);
918                if (event.size < 1)
919                        event.type = TRACE_EVENT_TERMINATE;
920                else
921                        event.type = TRACE_EVENT_PACKET;
922                return event;
923               
924        } else {
925                /* Otherwise, use the generic event function */
926                return trace_event_trace(libtrace, packet);
927        }
928       
929}
930
931static void erf_get_statistics(libtrace_t *trace, libtrace_stat_t *stat) {
932
933        if (trace->format_data) {
934                stat->dropped_valid = 1;
935                stat->dropped = DATA(trace)->drops;
936        }
937}
938
939static char *erf_get_option_name(uint32_t option) {
940        switch(option) {
941                case (ERF_PROV_COMMENT): return "Comment";
942                case (ERF_PROV_FCS_LEN): return "FCS Length";
943                case (ERF_PROV_MASK_CIDR): return "Subnet CIDR";
944                case (ERF_PROV_NAME): return "Interface Name";
945                case (ERF_PROV_DESCR): return "Interface Description";
946                case (ERF_PROV_APP_NAME): return "Application Name";
947                case (ERF_PROV_HOSTNAME): return "Hostname";
948                case (ERF_PROV_OS): return "Operating System";
949                case (ERF_PROV_MODEL): return "Model";
950                case (ERF_PROV_FW_VERSION): return "Firmware Version";
951                case (ERF_PROV_SERIAL_NO): return "Serial Number";
952                case (ERF_PROV_ORG_NAME): return "Organisation Name";
953                case (ERF_PROV_SNAPLEN): return "Snap length";
954                case (ERF_PROV_CARD_NUM): return "DAG Card Number";
955                case (ERF_PROV_MODULE_NUM): return "DAG Module Number";
956                case (ERF_PROV_LOC_NAME): return "Capture Location";
957                case (ERF_PROV_FLOW_HASH_MODE): return "Flow Hash Mode";
958                case (ERF_PROV_TUNNELING_MODE): return "Tunneling Mode";
959                case (ERF_PROV_LOC_DESCR): return "Location Description";
960                case (ERF_PROV_MEM): return "Stream Buffer Memory";
961                case (ERF_PROV_DEV_NAME): return "DAG Device Name";
962                case (ERF_PROV_DEV_PATH): return "DAG Device Path";
963                case (ERF_PROV_APP_VERSION): return "Capture Application Version";
964                case (ERF_PROV_CPU): return "CPU";
965                case (ERF_PROV_CPU_PHYS_CORES): return "CPU Cores";
966                case (ERF_PROV_CPU_NUMA_NODES): return "CPU NUMA Nodes";
967                case (ERF_PROV_DAG_VERSION): return "DAG Software Version";
968                case (ERF_PROV_IF_NUM): return "Number";
969                case (ERF_PROV_IF_SPEED): return "Speed";
970                case (ERF_PROV_IF_IPV4): return "IPv4";
971                case (ERF_PROV_IF_IPV6): return "IPv6";
972                case (ERF_PROV_IF_MAC): return "MAC";
973                case (ERF_PROV_IF_SFP_TYPE): return "Transceiver Type";
974                case (ERF_PROV_IF_LINK_STATUS): return "Link Status";
975                case (ERF_PROV_IF_PHY_MODE): return "PHY Mode";
976                case (ERF_PROV_IF_PORT_TYPE): return "Port Type";
977                case (ERF_PROV_IF_RX_LATENCY): return "Latency";
978                case (ERF_PROV_IF_RX_POWER): return "Optical RX Power";
979                case (ERF_PROV_IF_TX_POWER): return "Optical TX Power";
980                case (ERF_PROV_CLK_SOURCE): return "CLK Source";
981                case (ERF_PROV_CLK_STATE): return "CLK State";
982                case (ERF_PROV_CLK_THRESHOLD): return "CLK Threshold";
983                case (ERF_PROV_CLK_CORRECTION): return "CLK Correction";
984                case (ERF_PROV_CLK_FAILURES): return "CLK Failures";
985                case (ERF_PROV_CLK_RESYNCS): return "CLK Resyncs";
986                case (ERF_PROV_CLK_PHASE_ERROR): return "CLK Phase Errors";
987                case (ERF_PROV_CLK_INPUT_PULSES): return "CLK Input Pulses";
988                case (ERF_PROV_CLK_REJECTED_PULSES): return "CLK Rejected Pulses";
989                case (ERF_PROV_CLK_PHC_INDEX): return "CLK PHC Index";
990                case (ERF_PROV_CLK_PHC_OFFSET): return "CLK PHC Offset";
991                case (ERF_PROV_CLK_TIMEBASE): return "CLK Timebase";
992                case (ERF_PROV_CLK_DESCR): return "CLK Description";
993                case (ERF_PROV_CLK_OUT_SOURCE): return "CLK Output Source" ;
994                case (ERF_PROV_CLK_LINK_MODE): return "CLK Link Mode";
995                case (ERF_PROV_PTP_DOMAIN_NUM): return "PTP Domain Number";
996                case (ERF_PROV_PTP_STEPS_REMOVED): return "PTP Steps removed";
997                case (ERF_PROV_CLK_PORT_PROTO): return "CLK Port Protocol";
998                default:
999                        return "Unknown";
1000        }
1001        return "duno";
1002}
1003
1004static libtrace_meta_datatype_t erf_get_datatype(uint32_t option) {
1005        switch(option) {
1006                case (ERF_PROV_COMMENT): return TRACE_META_STRING;
1007                case (ERF_PROV_FCS_LEN): return TRACE_META_UINT32;
1008                case (ERF_PROV_MASK_CIDR): return TRACE_META_UINT32;
1009                case (ERF_PROV_NAME): return TRACE_META_STRING;
1010                case (ERF_PROV_DESCR): return TRACE_META_STRING;
1011                case (ERF_PROV_APP_NAME): return TRACE_META_STRING;
1012                case (ERF_PROV_HOSTNAME): return TRACE_META_STRING;
1013                case (ERF_PROV_OS): return TRACE_META_STRING;
1014                case (ERF_PROV_MODEL): return TRACE_META_STRING;
1015                case (ERF_PROV_FW_VERSION): return TRACE_META_STRING;
1016                case (ERF_PROV_SERIAL_NO): return TRACE_META_STRING;
1017                case (ERF_PROV_ORG_NAME): return TRACE_META_STRING;
1018                case (ERF_PROV_SNAPLEN): return TRACE_META_UINT32;
1019                case (ERF_PROV_CARD_NUM): return TRACE_META_UINT32;
1020                case (ERF_PROV_MODULE_NUM): return TRACE_META_UINT32;
1021                case (ERF_PROV_LOC_NAME): return TRACE_META_STRING;
1022                case (ERF_PROV_FLOW_HASH_MODE): return TRACE_META_UINT32;
1023                case (ERF_PROV_TUNNELING_MODE): return TRACE_META_UINT32;
1024                case (ERF_PROV_LOC_DESCR): return TRACE_META_STRING;
1025                case (ERF_PROV_MEM): return TRACE_META_UINT64;
1026                case (ERF_PROV_DEV_NAME): return TRACE_META_STRING;
1027                case (ERF_PROV_DEV_PATH): return TRACE_META_STRING;
1028                case (ERF_PROV_APP_VERSION): return TRACE_META_STRING;
1029                case (ERF_PROV_CPU): return TRACE_META_STRING;
1030                case (ERF_PROV_CPU_PHYS_CORES): return TRACE_META_UINT32;
1031                case (ERF_PROV_CPU_NUMA_NODES): return TRACE_META_UINT32;
1032                case (ERF_PROV_DAG_VERSION): return TRACE_META_STRING;
1033                case (ERF_PROV_IF_NUM): return TRACE_META_UINT32;
1034                case (ERF_PROV_IF_SPEED): return TRACE_META_UINT64;
1035                case (ERF_PROV_IF_IPV4): return TRACE_META_IPV4;
1036                case (ERF_PROV_IF_IPV6): return TRACE_META_IPV6;
1037                case (ERF_PROV_IF_MAC): return TRACE_META_MAC;
1038                case (ERF_PROV_IF_SFP_TYPE): return TRACE_META_STRING;
1039                case (ERF_PROV_IF_LINK_STATUS): return TRACE_META_UINT32;
1040                case (ERF_PROV_IF_PHY_MODE): return TRACE_META_STRING;
1041                case (ERF_PROV_IF_PORT_TYPE): return TRACE_META_UINT32;
1042                /* this is a ts_rel, need to double check */
1043                case (ERF_PROV_IF_RX_LATENCY): return TRACE_META_UINT64;
1044                case (ERF_PROV_IF_RX_POWER): return TRACE_META_UINT32;
1045                case (ERF_PROV_IF_TX_POWER): return TRACE_META_UINT32;
1046                case (ERF_PROV_CLK_SOURCE): return TRACE_META_UINT32;
1047                case (ERF_PROV_CLK_STATE): return TRACE_META_UINT32;
1048                /* this is a ts_rel, need to double check */
1049                case (ERF_PROV_CLK_THRESHOLD): return TRACE_META_UINT64;
1050                /* this is a ts_rel, need to double check */
1051                case (ERF_PROV_CLK_CORRECTION): return TRACE_META_UINT64;
1052                case (ERF_PROV_CLK_FAILURES): return TRACE_META_UINT32;
1053                case (ERF_PROV_CLK_RESYNCS): return TRACE_META_UINT32;
1054                /* this is a ts_rel, need to double check */
1055                case (ERF_PROV_CLK_PHASE_ERROR): return TRACE_META_UINT64;
1056                case (ERF_PROV_CLK_INPUT_PULSES): return TRACE_META_UINT32;
1057                case (ERF_PROV_CLK_REJECTED_PULSES): return TRACE_META_UINT32;
1058                case (ERF_PROV_CLK_PHC_INDEX): return TRACE_META_UINT32;
1059                /* this is a ts_rel, need to double check */
1060                case (ERF_PROV_CLK_PHC_OFFSET): return TRACE_META_UINT64;
1061                case (ERF_PROV_CLK_TIMEBASE): return TRACE_META_STRING;
1062                case (ERF_PROV_CLK_DESCR): return TRACE_META_STRING;
1063                case (ERF_PROV_CLK_OUT_SOURCE): return TRACE_META_UINT32;
1064                case (ERF_PROV_CLK_LINK_MODE): return TRACE_META_UINT32;
1065                case (ERF_PROV_PTP_DOMAIN_NUM): return TRACE_META_UINT32;
1066                case (ERF_PROV_PTP_STEPS_REMOVED): return TRACE_META_UINT32;
1067                case (ERF_PROV_CLK_PORT_PROTO): return TRACE_META_UINT32;
1068                default:
1069                        return TRACE_META_UNKNOWN;
1070        }
1071}
1072
1073/* An ERF provenance packet can contain multiple sections of the same type per packet,
1074 * Need to think of a way to handle this currently the first found is returned*/
1075void *erf_get_meta_section(libtrace_packet_t *packet, uint32_t section) {
1076
1077        void *ptr;
1078        dag_record_t *hdr;
1079        dag_sec_t *sec;
1080        uint16_t tmp;
1081        uint16_t remaining;
1082        uint16_t curr_sec = 0;
1083        int in_section = 0;
1084
1085        if (packet->buffer == NULL) { return NULL; }
1086
1087        hdr = (dag_record_t *)packet->buffer;
1088        ptr = packet->payload;
1089
1090        /* ensure this packet is a meta packet */
1091        if ((hdr->type & 127) != 27) { return NULL; }
1092        /* set remaining to size of packet minus header length */
1093        remaining = ntohs(hdr->rlen) - 24;
1094
1095        /* setup structure to hold the result */
1096        libtrace_meta_t *result = malloc(sizeof(libtrace_meta_t));
1097        result->section = section;
1098        result->num = 0;
1099
1100        while (remaining > sizeof(dag_sec_t) && curr_sec != 0xFFFF) {
1101
1102                /* Get the current section/option header */
1103                sec = (dag_sec_t *)ptr;
1104
1105                if (ntohs(sec->type) == ERF_PROV_SECTION_CAPTURE
1106                        || ntohs(sec->type) == ERF_PROV_SECTION_HOST
1107                        || ntohs(sec->type) == ERF_PROV_SECTION_MODULE
1108                        || ntohs(sec->type) == ERF_PROV_SECTION_INTERFACE) {
1109
1110                        if (in_section == 0) {
1111                                curr_sec = ntohs(sec->type);
1112                        } else {
1113                                /* Used to indicate section end */
1114                                curr_sec = 0xFFFF;
1115                        }
1116                }
1117
1118                /* If the current section the requested one and this is not
1119                 * a section header */
1120                if (section == curr_sec &&
1121                        ntohs(sec->type) != ERF_PROV_SECTION_CAPTURE
1122                        && ntohs(sec->type) != ERF_PROV_SECTION_HOST
1123                        && ntohs(sec->type) != ERF_PROV_SECTION_MODULE
1124                        && ntohs(sec->type) != ERF_PROV_SECTION_INTERFACE) {
1125
1126                        /* Indicate a section has been found */
1127                        in_section = 1;
1128
1129                        result->num += 1;
1130                        if (result->num == 1) {
1131                                result->items = malloc(sizeof(libtrace_meta_item_t));
1132                        } else {
1133                                result->items = realloc(result->items,
1134                                        result->num*sizeof(libtrace_meta_item_t));
1135                        }
1136                        result->items[result->num-1].option = ntohs(sec->type);
1137                        result->items[result->num-1].option_name =
1138                                erf_get_option_name(ntohs(sec->type));
1139
1140                        result->items[result->num-1].len = ntohs(sec->len);
1141                        result->items[result->num-1].datatype =
1142                                erf_get_datatype(ntohs(sec->type));
1143
1144                        /* If the datatype is a string allow for a null terminator */
1145                        if (result->items[result->num-1].datatype == TRACE_META_STRING) {
1146                                result->items[result->num-1].data =
1147                                        calloc(1, ntohs(sec->len)+1);
1148                                ((char *)result->items[result->num-1].data)[ntohs(sec->len)] = '\0';
1149                                /* and copy the utf8 string */
1150                                memcpy(result->items[result->num-1].data,
1151                                        ptr+sizeof(struct dag_opthdr), ntohs(sec->len));
1152                        } else {
1153                                result->items[result->num-1].data =
1154                                        calloc(1, ntohs(sec->len));
1155                                /* depending on the datatype we need to ensure the data is
1156                                 * in host byte ordering */
1157                                if (result->items[result->num-1].datatype == TRACE_META_UINT32
1158                                        || result->items[result->num-1].datatype == TRACE_META_IPV4) {
1159                                        uint32_t t = *(uint32_t *)(ptr+sizeof(struct dag_opthdr));
1160                                        t = ntohl(t);
1161                                        memcpy(result->items[result->num-1].data,
1162                                                &t, sizeof(uint32_t));
1163                                } else if(result->items[result->num-1].datatype == TRACE_META_UINT64) {
1164                                        uint64_t t = *(uint64_t *)(ptr+sizeof(struct dag_opthdr));
1165                                        t = bswap_be_to_host64(t);
1166                                        memcpy(result->items[result->num-1].data,
1167                                                &t, sizeof(uint64_t));
1168                                } else {
1169                                        memcpy(result->items[result->num-1].data,
1170                                                ptr+sizeof(struct dag_opthdr), ntohs(sec->len));
1171                                }
1172
1173                        }
1174
1175                }
1176
1177                /* Update remaining and ptr. Also account for any padding */
1178                if ((ntohs(sec->len) % 4) != 0) {
1179                        tmp = ntohs(sec->len) + (4 - (ntohs(sec->len) % 4)) + sizeof(dag_sec_t);
1180                } else {
1181                        tmp = ntohs(sec->len) + sizeof(dag_sec_t);
1182                }
1183                remaining -= tmp;
1184                ptr += tmp;
1185        }
1186
1187        /* If the result structure has result matches were found */
1188        if (result->num > 0) {
1189                return (void *)result;
1190        } else {
1191                free(result);
1192                return NULL;
1193        }
1194}
1195
1196static void erf_help(void) {
1197        printf("erf format module: $Revision: 1752 $\n");
1198        printf("Supported input URIs:\n");
1199        printf("\terf:/path/to/file\t(uncompressed)\n");
1200        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
1201        printf("\terf:-\t(stdin, either compressed or not)\n");
1202        printf("\terf:/path/to/socket\n");
1203        printf("\n");
1204        printf("\te.g.: erf:/tmp/trace\n");
1205        printf("\n");
1206        printf("Supported output URIs:\n");
1207        printf("\terf:path/to/file\t(uncompressed)\n");
1208        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
1209        printf("\terf:-\t(stdout, either compressed or not)\n");
1210        printf("\n");
1211        printf("\te.g.: erf:/tmp/trace\n");
1212        printf("\n");
1213
1214
1215}
1216
1217static struct libtrace_format_t erfformat = {
1218        "erf",
1219        "$Id$",
1220        TRACE_FORMAT_ERF,
1221        NULL,                           /* probe filename */
1222        erf_probe_magic,                /* probe magic */
1223        erf_init_input,                 /* init_input */
1224        erf_config_input,               /* config_input */
1225        erf_start_input,                /* start_input */
1226        NULL,                           /* pause_input */
1227        erf_init_output,                /* init_output */
1228        erf_config_output,              /* config_output */
1229        erf_start_output,               /* start_output */
1230        erf_fin_input,                  /* fin_input */
1231        erf_fin_output,                 /* fin_output */
1232        erf_read_packet,                /* read_packet */
1233        erf_prepare_packet,             /* prepare_packet */
1234        NULL,                           /* fin_packet */
1235        erf_write_packet,               /* write_packet */
1236        erf_flush_output,               /* flush_output */
1237        erf_get_link_type,              /* get_link_type */
1238        erf_get_direction,              /* get_direction */
1239        erf_set_direction,              /* set_direction */
1240        erf_get_erf_timestamp,          /* get_erf_timestamp */
1241        NULL,                           /* get_timeval */
1242        NULL,                           /* get_timespec */
1243        NULL,                           /* get_seconds */
1244        erf_get_meta_section,           /* get_meta_section */
1245        erf_seek_erf,                   /* seek_erf */
1246        NULL,                           /* seek_timeval */
1247        NULL,                           /* seek_seconds */
1248        erf_get_capture_length,         /* get_capture_length */
1249        erf_get_wire_length,            /* get_wire_length */
1250        erf_get_framing_length,         /* get_framing_length */
1251        erf_set_capture_length,         /* set_capture_length */
1252        NULL,                           /* get_received_packets */
1253        NULL,                           /* get_filtered_packets */
1254        NULL,                           /* get_dropped_packets */
1255        erf_get_statistics,             /* get_statistics */
1256        NULL,                           /* get_fd */
1257        erf_event,                      /* trace_event */
1258        erf_help,                       /* help */
1259        NULL,                           /* next pointer */
1260        NON_PARALLEL(false)
1261};
1262
1263static struct libtrace_format_t rawerfformat = {
1264        "rawerf",
1265        "$Id$",
1266        TRACE_FORMAT_RAWERF,
1267        NULL,                           /* probe filename */
1268        NULL,           /* probe magic */
1269        erf_init_input,                 /* init_input */
1270        erf_config_input,               /* config_input */
1271        rawerf_start_input,             /* start_input */
1272        NULL,                           /* pause_input */
1273        erf_init_output,                /* init_output */
1274        erf_config_output,              /* config_output */
1275        erf_start_output,               /* start_output */
1276        erf_fin_input,                  /* fin_input */
1277        erf_fin_output,                 /* fin_output */
1278        erf_read_packet,                /* read_packet */
1279        erf_prepare_packet,             /* prepare_packet */
1280        NULL,                           /* fin_packet */
1281        erf_write_packet,               /* write_packet */
1282        erf_flush_output,               /* flush_output */
1283        erf_get_link_type,              /* get_link_type */
1284        erf_get_direction,              /* get_direction */
1285        erf_set_direction,              /* set_direction */
1286        erf_get_erf_timestamp,          /* get_erf_timestamp */
1287        NULL,                           /* get_timeval */
1288        NULL,                           /* get_timespec */
1289        NULL,                           /* get_seconds */
1290        erf_get_meta_section,           /* get_meta_section */
1291        erf_seek_erf,                   /* seek_erf */
1292        NULL,                           /* seek_timeval */
1293        NULL,                           /* seek_seconds */
1294        erf_get_capture_length,         /* get_capture_length */
1295        erf_get_wire_length,            /* get_wire_length */
1296        erf_get_framing_length,         /* get_framing_length */
1297        erf_set_capture_length,         /* set_capture_length */
1298        NULL,                           /* get_received_packets */
1299        NULL,                           /* get_filtered_packets */
1300        NULL,                           /* get_dropped_packets */
1301        erf_get_statistics,             /* get_statistics */
1302        NULL,                           /* get_fd */
1303        erf_event,                      /* trace_event */
1304        erf_help,                       /* help */
1305        NULL,                           /* next pointer */
1306        NON_PARALLEL(false)
1307};
1308
1309
1310
1311void erf_constructor(void) {
1312        register_format(&erfformat);
1313        register_format(&rawerfformat);
1314}
Note: See TracBrowser for help on using the repository browser.