source: lib/format_erf.c @ c66068d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c66068d was c66068d, checked in by Perry Lorier <perry@…>, 13 years ago

Rewrite the libtrace io subsystem to use the new wandio abstraction layer.

  • Property mode set to 100644
File size: 18.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30#define _GNU_SOURCE
31
32#include "config.h"
33#include "common.h"
34#include "libtrace.h"
35#include "libtrace_int.h"
36#include "format_helper.h"
37#include "format_erf.h"
38#include "wandio.h"
39
40#include <assert.h>
41#include <errno.h>
42#include <fcntl.h>
43#include <stdio.h>
44#include <string.h>
45#include <stdlib.h>
46
47#ifdef WIN32
48#  include <io.h>
49#  include <share.h>
50#  define PATH_MAX _MAX_PATH
51#else
52#  include <netdb.h>
53#  ifndef PATH_MAX
54#       define PATH_MAX 4096
55#  endif
56#  include <sys/ioctl.h>
57#endif
58
59
60#define COLLECTOR_PORT 3435
61
62static struct libtrace_format_t erfformat;
63
64#define DATA(x) ((struct erf_format_data_t *)x->format_data)
65#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
66
67#define INPUT DATA(libtrace)->input
68#define IN_OPTIONS DATA(libtrace)->options
69#define OUTPUT DATAOUT(libtrace)->output
70#define OUT_OPTIONS DATAOUT(libtrace)->options
71struct erf_format_data_t {
72       
73        union {
74                int fd;
75                io_t *file;
76        } input;
77
78       
79        struct {
80                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
81                io_t *index;
82                off_t index_len;
83        } seek;
84
85        struct {
86                int real_time;
87        } options;
88        uint64_t drops;
89};
90
91struct erf_format_data_out_t {
92        union {
93                struct {
94                        int level;
95                        int fileflag;
96                } erf;
97               
98        } options;
99       
100        union {
101                int fd;
102                struct rtserver_t * rtserver;
103                iow_t *file;
104        } output;
105};
106
107/** Structure holding status information for a packet */
108typedef struct libtrace_packet_status {
109        uint8_t type;
110        uint8_t reserved;
111        uint16_t message;
112} libtrace_packet_status_t;
113
114typedef struct erf_index_t {
115        uint64_t timestamp;
116        uint64_t offset; 
117} erf_index_t;
118
119
120/* Dag erf ether packets have a 2 byte padding before the packet
121 * so that the ip header is aligned on a 32 bit boundary.
122 */
123static int erf_get_padding(const libtrace_packet_t *packet)
124{
125        if (packet->trace->format->type==TRACE_FORMAT_ERF) {
126                dag_record_t *erfptr = (dag_record_t *)packet->header;
127                switch(erfptr->type) {
128                        case TYPE_ETH:         
129                        case TYPE_DSM_COLOR_ETH:
130                                return 2;
131                        default:                return 0;
132                }
133        }
134        else {
135                switch(trace_get_link_type(packet)) {
136                        case TRACE_TYPE_ETH:    return 2;
137                        default:                return 0;
138                }
139        }
140}
141
142int erf_get_framing_length(const libtrace_packet_t *packet)
143{
144        return dag_record_size + erf_get_padding(packet);
145}
146
147
148static int erf_init_input(libtrace_t *libtrace) 
149{
150        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
151       
152        INPUT.file = 0;
153        IN_OPTIONS.real_time = 0;
154        DATA(libtrace)->drops = 0;
155       
156        return 0; /* success */
157}
158
159static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
160                void *value) {
161
162        switch (option) {
163                case TRACE_OPTION_EVENT_REALTIME:
164                        IN_OPTIONS.real_time = *(int *)value;
165                        return 0;
166                case TRACE_OPTION_SNAPLEN:
167                case TRACE_OPTION_PROMISC:
168                case TRACE_OPTION_FILTER:
169                case TRACE_OPTION_META_FREQ:
170                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
171                                        "Unsupported option");
172                        return -1;
173                default:
174                        /* Unknown option */
175                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
176                                        "Unknown option");
177                        return -1;
178        }
179}
180
181static int erf_start_input(libtrace_t *libtrace)
182{
183        if (INPUT.file)
184                return 0; /* success */
185
186        INPUT.file = trace_open_file(libtrace);
187
188        if (!INPUT.file)
189                return -1;
190
191        DATA(libtrace)->drops = 0;
192
193        return 0; /* success */
194}
195
196/* Binary search through the index to find the closest point before
197 * the packet.  Consider in future having a btree index perhaps?
198 */
199static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
200{
201        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
202        size_t min_off = 0;
203        off_t current;
204        erf_index_t record;
205        do {
206                current=(max_off+min_off)>>2;
207
208                wandio_seek(DATA(libtrace)->seek.index,
209                                (int64_t)(current*sizeof(record)),
210                                SEEK_SET);
211                wandio_read(DATA(libtrace)->seek.index,
212                                &record,sizeof(record));
213                if (record.timestamp < erfts) {
214                        min_off=current;
215                }
216                if (record.timestamp > erfts) {
217                        max_off=current;
218                }
219                if (record.timestamp == erfts)
220                        break;
221        } while(min_off<max_off);
222
223        /* If we've passed it, seek backwards.  This loop shouldn't
224         * execute more than twice.
225         */
226        do {
227                wandio_seek(DATA(libtrace)->seek.index,
228                                (int64_t)(current*sizeof(record)),SEEK_SET);
229                wandio_read(DATA(libtrace)->seek.index,
230                                &record,sizeof(record));
231                current--;
232        } while(record.timestamp>erfts);
233
234        /* We've found our location in the trace, now use it. */
235        wandio_seek(INPUT.file,(int64_t) record.offset,SEEK_SET);
236
237        return 0; /* success */
238}
239
240/* There is no index.  Seek through the entire trace from the start, nice
241 * and slowly.
242 */
243static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
244{
245        if (INPUT.file) {
246                wandio_destroy(INPUT.file);
247        }
248        INPUT.file = trace_open_file(libtrace);
249        if (!INPUT.file)
250                return -1;
251        return 0;
252}
253
254static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
255{
256        libtrace_packet_t *packet;
257        off_t off = 0;
258
259        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
260                char buffer[PATH_MAX];
261                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
262                DATA(libtrace)->seek.index=wandio_create(buffer);
263                if (DATA(libtrace)->seek.index) {
264                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
265                }
266                else {
267                        DATA(libtrace)->seek.exists=INDEX_NONE;
268                }
269        }
270
271        /* If theres an index, use it to find the nearest packet that isn't
272         * after the time we're looking for.  If there is no index we need
273         * to seek slowly through the trace from the beginning.  Sigh.
274         */
275        switch(DATA(libtrace)->seek.exists) {
276                case INDEX_EXISTS:
277                        erf_fast_seek_start(libtrace,erfts);
278                        break;
279                case INDEX_NONE:
280                        erf_slow_seek_start(libtrace,erfts);
281                        break;
282                case INDEX_UNKNOWN:
283                        assert(0);
284                        break;
285        }
286
287        /* Now seek forward looking for the correct timestamp */
288        packet=trace_create_packet();
289        do {
290                trace_read_packet(libtrace,packet);
291                if (trace_get_erf_timestamp(packet)==erfts)
292                        break;
293                off=wandio_tell(INPUT.file);
294        } while(trace_get_erf_timestamp(packet)<erfts);
295
296        wandio_seek(INPUT.file,off,SEEK_SET);
297
298        return 0;
299}
300
301static int erf_init_output(libtrace_out_t *libtrace) {
302        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
303
304        OUT_OPTIONS.erf.level = 0;
305        OUT_OPTIONS.erf.fileflag = O_CREAT | O_WRONLY;
306        OUTPUT.file = 0;
307
308        return 0;
309}
310
311static int erf_config_output(libtrace_out_t *libtrace, trace_option_output_t option,
312                void *value) {
313
314        switch (option) {
315                case TRACE_OPTION_OUTPUT_COMPRESS:
316                        OUT_OPTIONS.erf.level = *(int*)value;
317                        return 0;
318                case TRACE_OPTION_OUTPUT_FILEFLAGS:
319                        OUT_OPTIONS.erf.fileflag = *(int*)value;
320                        return 0;
321                default:
322                        /* Unknown option */
323                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
324                                        "Unknown option");
325                        return -1;
326        }
327}
328
329
330
331static int erf_fin_input(libtrace_t *libtrace) {
332        if (INPUT.file)
333                wandio_destroy(INPUT.file);
334        free(libtrace->format_data);
335        return 0;
336}
337
338static int erf_fin_output(libtrace_out_t *libtrace) {
339        if (OUTPUT.file)
340                wandio_wdestroy(OUTPUT.file);
341        free(libtrace->format_data);
342        return 0;
343}
344 
345static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
346                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
347       
348        dag_record_t *erfptr;
349       
350        if (packet->buffer != buffer && 
351                packet->buf_control == TRACE_CTRL_PACKET) {
352                free(packet->buffer);
353        }
354
355        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
356                packet->buf_control = TRACE_CTRL_PACKET;
357        } else
358                packet->buf_control = TRACE_CTRL_EXTERNAL;
359       
360       
361        packet->type = rt_type;
362        packet->buffer = buffer;
363        packet->header = buffer;
364        erfptr = (dag_record_t *)packet->buffer;
365        if (erfptr->flags.rxerror == 1) {
366                packet->payload = NULL;
367                /* XXX: Do we want to do this? We never used to do this
368                 
369                erfptr->rlen = htons(erf_get_framing_length(packet));
370                */
371        } else {
372                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
373        }
374       
375        if (libtrace->format_data == NULL) {
376                /* Allocates the format_data structure */
377                if (erf_init_input(libtrace)) 
378                        return -1;
379        }
380
381        /* Check for loss */
382        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
383                /* No idea how we get this yet */
384
385        } else {
386                DATA(libtrace)->drops += ntohs(erfptr->lctr);
387        }
388
389        return 0;
390}
391
392static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
393        int numbytes;
394        unsigned int size;
395        void *buffer2 = packet->buffer;
396        unsigned int rlen;
397        uint32_t flags = 0;
398       
399       
400        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
401                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
402                if (!packet->buffer) {
403                        trace_set_err(libtrace, errno, 
404                                        "Cannot allocate memory");
405                        return -1;
406                }
407        }
408
409        flags |= TRACE_PREP_OWN_BUFFER; 
410       
411        if ((numbytes=wandio_read(INPUT.file,
412                                        packet->buffer,
413                                        (size_t)dag_record_size)) == -1) {
414                trace_set_err(libtrace,errno,"read(%s)",
415                                libtrace->uridata);
416                return -1;
417        }
418        /* EOF */
419        if (numbytes == 0) {
420                return 0;
421        }
422
423        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
424        buffer2 = (char*)packet->buffer + dag_record_size;
425        size = rlen - dag_record_size;
426
427        if (size >= LIBTRACE_PACKET_BUFSIZE) {
428                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Packet size %u larger than supported by libtrace - packet is probably corrupt", size);
429                return -1;
430        }
431
432        /* Unknown/corrupt */
433        if (((dag_record_t *)packet->buffer)->type >= TYPE_AAL2) {
434                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Corrupt or Unknown ERF type");
435                return -1;
436        }
437       
438        /* read in the rest of the packet */
439        if ((numbytes=wandio_read(INPUT.file,
440                                        buffer2,
441                                        (size_t)size)) != (int)size) {
442                if (numbytes==-1) {
443                        trace_set_err(libtrace,errno, "read(%s)", libtrace->uridata);
444                        return -1;
445                }
446                trace_set_err(libtrace,EIO,"Truncated packet (wanted %d, got %d)", size, numbytes);
447                /* Failed to read the full packet?  must be EOF */
448                return -1;
449        }
450       
451        if (erf_prepare_packet(libtrace, packet, packet->buffer, TRACE_RT_DATA_ERF, flags))
452                return -1;
453       
454        return rlen;
455}
456
457static int erf_dump_packet(libtrace_out_t *libtrace,
458                dag_record_t *erfptr, unsigned int pad, void *buffer) {
459        int numbytes = 0;
460        int size;
461
462        if ((numbytes = 
463                wandio_wwrite(OUTPUT.file, 
464                                erfptr,
465                                (size_t)(dag_record_size + pad))) 
466                        != (int)(dag_record_size+pad)) {
467                trace_set_err_out(libtrace,errno,
468                                "write(%s)",libtrace->uridata);
469                return -1;
470        }
471
472        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
473        numbytes=wandio_wwrite(OUTPUT.file, buffer, (size_t)size);
474        if (numbytes != size) {
475                trace_set_err_out(libtrace,errno,
476                                "write(%s)",libtrace->uridata);
477                return -1;
478        }
479        return numbytes + pad + dag_record_size;
480}
481
482static int erf_start_output(libtrace_out_t *libtrace)
483{
484        OUTPUT.file = trace_open_file_out(libtrace,
485                        OUT_OPTIONS.erf.level,
486                        OUT_OPTIONS.erf.fileflag);
487        if (!OUTPUT.file) {
488                return -1;
489        }
490        return 0;
491}
492
493static bool find_compatible_linktype(libtrace_out_t *libtrace,
494                                libtrace_packet_t *packet)
495{
496        /* Keep trying to simplify the packet until we can find
497         * something we can do with it */
498        do {
499                char type=libtrace_to_erf_type(trace_get_link_type(packet));
500
501                /* Success */
502                if (type != (char)-1)
503                        return true;
504
505                if (!demote_packet(packet)) {
506                        trace_set_err_out(libtrace,
507                                        TRACE_ERR_NO_CONVERSION,
508                                        "No erf type for packet (%i)",
509                                        trace_get_link_type(packet));
510                        return false;
511                }
512
513        } while(1);
514
515        return true;
516}
517               
518static int erf_write_packet(libtrace_out_t *libtrace, 
519                libtrace_packet_t *packet) 
520{
521        int numbytes = 0;
522        unsigned int pad = 0;
523        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
524        void *payload = packet->payload;
525
526        assert(OUTPUT.file);
527
528        if (!packet->header) {
529                /*trace_set_err_output(libtrace, TRACE_ERR_BAD_PACKET,
530                                "Packet has no header - probably an RT packet");
531                */
532                return -1;
533        }
534       
535        pad = erf_get_padding(packet);
536
537        /* If we've had an rxerror, we have no payload to write - fix
538         * rlen to be the correct length
539         */
540        /* I Think this is bogus, we should somehow figure out
541         * a way to write out the payload even if it is gibberish -- Perry */
542        if (payload == NULL) {
543                dag_hdr->rlen = htons(dag_record_size + pad);
544               
545        } 
546       
547        if (packet->type == TRACE_RT_DATA_ERF) {
548                        numbytes = erf_dump_packet(libtrace,
549                                (dag_record_t *)packet->header,
550                                pad,
551                                payload
552                                );
553        } else {
554                dag_record_t erfhdr;
555                /* convert format - build up a new erf header */
556                /* Timestamp */
557                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
558
559                /* Flags. Can't do this */
560                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
561                if (trace_get_direction(packet)!=~0U)
562                        erfhdr.flags.iface = trace_get_direction(packet);
563
564                if (!find_compatible_linktype(libtrace,packet))
565                        return -1;
566
567                payload=packet->payload;
568                pad = erf_get_padding(packet);
569
570                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
571
572                /* Packet length (rlen includes format overhead) */
573                assert(trace_get_capture_length(packet)>0 
574                                && trace_get_capture_length(packet)<=65536);
575                assert(erf_get_framing_length(packet)>0 
576                                && trace_get_framing_length(packet)<=65536);
577                assert(
578                        trace_get_capture_length(packet)+erf_get_framing_length(packet)>0
579                      &&trace_get_capture_length(packet)+erf_get_framing_length(packet)<=65536);
580                erfhdr.rlen = htons(trace_get_capture_length(packet) 
581                        + erf_get_framing_length(packet));
582                /* loss counter. Can't do this */
583                erfhdr.lctr = 0;
584                /* Wire length, does not include padding! */
585                erfhdr.wlen = htons(trace_get_wire_length(packet));
586
587                /* Write it out */
588                numbytes = erf_dump_packet(libtrace,
589                                &erfhdr,
590                                pad,
591                                payload);
592        }
593        return numbytes;
594}
595
596libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
597        dag_record_t *erfptr = 0;
598        erfptr = (dag_record_t *)packet->header;
599        if (erfptr->type != TYPE_LEGACY)
600                return erf_type_to_libtrace(erfptr->type);
601        else {
602                /* Sigh, lets start wildly guessing */
603                if (((char*)packet->payload)[4]==0x45)
604                        return TRACE_TYPE_PPP;
605                return ~0;
606        }
607}
608
609libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
610        dag_record_t *erfptr = 0;
611        erfptr = (dag_record_t *)packet->header;
612        return erfptr->flags.iface;
613}
614
615libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
616        dag_record_t *erfptr = 0;
617        erfptr = (dag_record_t *)packet->header;
618        erfptr->flags.iface = direction;
619        return erfptr->flags.iface;
620}
621
622uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
623        dag_record_t *erfptr = 0;
624        erfptr = (dag_record_t *)packet->header;
625        return bswap_le_to_host64(erfptr->ts);
626}
627
628int erf_get_capture_length(const libtrace_packet_t *packet) {
629        dag_record_t *erfptr = 0;
630        int caplen;
631        if (packet->payload == NULL)
632                return 0; 
633       
634        erfptr = (dag_record_t *)packet->header;
635        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
636        if (ntohs(erfptr->wlen) < caplen)
637                return ntohs(erfptr->wlen);
638
639        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
640}
641
642int erf_get_wire_length(const libtrace_packet_t *packet) {
643        dag_record_t *erfptr = 0;
644        erfptr = (dag_record_t *)packet->header;
645        return ntohs(erfptr->wlen);
646}
647
648size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
649        dag_record_t *erfptr = 0;
650        assert(packet);
651        if(size  > trace_get_capture_length(packet)) {
652                /* can't make a packet larger */
653                return trace_get_capture_length(packet);
654        }
655        /* Reset cached capture length - otherwise we will both return the
656         * wrong value here and subsequent get_capture_length() calls will
657         * return the wrong value. */
658        packet->capture_length = -1;
659        erfptr = (dag_record_t *)packet->header;
660        erfptr->rlen = htons(size + erf_get_framing_length(packet));
661        return trace_get_capture_length(packet);
662}
663
664static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
665        struct libtrace_eventobj_t event = {0,0,0.0,0};
666       
667        if (IN_OPTIONS.real_time) {
668                event.size = erf_read_packet(libtrace, packet);
669                if (event.size < 1)
670                        event.type = TRACE_EVENT_TERMINATE;
671                else
672                        event.type = TRACE_EVENT_PACKET;
673                return event;
674               
675        } else {
676                return trace_event_trace(libtrace, packet);
677        }
678       
679}
680
681static uint64_t erf_get_dropped_packets(libtrace_t *trace)
682{
683        if (trace->format_data == NULL)
684                return (uint64_t)-1;
685        return DATA(trace)->drops;
686}
687
688static void erf_help(void) {
689        printf("erf format module: $Revision$\n");
690        printf("Supported input URIs:\n");
691        printf("\terf:/path/to/file\t(uncompressed)\n");
692        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
693        printf("\terf:-\t(stdin, either compressed or not)\n");
694        printf("\terf:/path/to/socket\n");
695        printf("\n");
696        printf("\te.g.: erf:/tmp/trace\n");
697        printf("\n");
698        printf("Supported output URIs:\n");
699        printf("\terf:path/to/file\t(uncompressed)\n");
700        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
701        printf("\terf:-\t(stdout, either compressed or not)\n");
702        printf("\n");
703        printf("\te.g.: erf:/tmp/trace\n");
704        printf("\n");
705        printf("Supported output options:\n");
706        printf("\t-z\tSpecify the gzip compression, ranging from 0 (uncompressed) to 9 - defaults to 1\n");
707        printf("\n");
708
709       
710}
711
712static struct libtrace_format_t erfformat = {
713        "erf",
714        "$Id$",
715        TRACE_FORMAT_ERF,
716        erf_init_input,                 /* init_input */       
717        erf_config_input,               /* config_input */
718        erf_start_input,                /* start_input */
719        NULL,                           /* pause_input */
720        erf_init_output,                /* init_output */
721        erf_config_output,              /* config_output */
722        erf_start_output,               /* start_output */
723        erf_fin_input,                  /* fin_input */
724        erf_fin_output,                 /* fin_output */
725        erf_read_packet,                /* read_packet */
726        erf_prepare_packet,             /* prepare_packet */
727        NULL,                           /* fin_packet */
728        erf_write_packet,               /* write_packet */
729        erf_get_link_type,              /* get_link_type */
730        erf_get_direction,              /* get_direction */
731        erf_set_direction,              /* set_direction */
732        erf_get_erf_timestamp,          /* get_erf_timestamp */
733        NULL,                           /* get_timeval */
734        NULL,                           /* get_seconds */
735        erf_seek_erf,                   /* seek_erf */
736        NULL,                           /* seek_timeval */
737        NULL,                           /* seek_seconds */
738        erf_get_capture_length,         /* get_capture_length */
739        erf_get_wire_length,            /* get_wire_length */
740        erf_get_framing_length,         /* get_framing_length */
741        erf_set_capture_length,         /* set_capture_length */
742        NULL,                           /* get_received_packets */
743        NULL,                           /* get_filtered_packets */
744        erf_get_dropped_packets,        /* get_dropped_packets */
745        NULL,                           /* get_captured_packets */
746        NULL,                           /* get_fd */
747        erf_event,                      /* trace_event */
748        erf_help,                       /* help */
749        NULL                            /* next pointer */
750};
751
752
753void erf_constructor(void) {
754        register_format(&erfformat);
755}
Note: See TracBrowser for help on using the repository browser.