source: lib/format_erf.c @ 5cdb37d

develop
Last change on this file since 5cdb37d was 5cdb37d, checked in by GitHub <noreply@…>, 21 months ago

Merge pull request #101 from jacobvw/meta-api

Meta API

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