source: lib/format_erf.c @ db03808

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

Rearrange internal structure representations to allow for better use of padding/alignment on 64bit.

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