source: lib/format_erf.c @ dd2eaee

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

Add new pcapfile: uri for natively reading pcap files (without libpcap)
Add initialiser so we don't need to rely on gccisms for initialisation

  • Property mode set to 100644
File size: 24.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2004 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 "parse_cmd.h"
38
39#include <assert.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45
46#ifdef WIN32
47#  include <io.h>
48#  include <share.h>
49#  define PATH_MAX _MAX_PATH
50#  define snprintf sprintf_s
51#else
52#  include <netdb.h>
53#endif
54
55
56#define COLLECTOR_PORT 3435
57
58static struct libtrace_format_t erf;
59static struct libtrace_format_t rtclient;
60#if HAVE_DAG
61static struct libtrace_format_t dag;
62#endif
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 CONNINFO DATA(libtrace)->conn_info
68#define INPUT DATA(libtrace)->input
69#define OUTPUT DATAOUT(libtrace)->output
70#if HAVE_DAG
71#define DAG DATA(libtrace)->dag
72#endif
73#define OPTIONS DATAOUT(libtrace)->options
74struct erf_format_data_t {
75        union {
76                struct {
77                        char *hostname;
78                        short port;
79                } rt;
80        } conn_info;
81       
82        union {
83                int fd;
84                libtrace_io_t *file;
85        } input;
86
87        struct {
88                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
89                libtrace_io_t *index;
90                off_t index_len;
91        } seek;
92
93#if HAVE_DAG
94        struct {
95                void *buf; 
96                unsigned bottom;
97                unsigned top;
98                unsigned diff;
99                unsigned curr;
100                unsigned offset;
101        } dag;
102#endif
103};
104
105struct erf_format_data_out_t {
106        union {
107                struct {
108                        char *hostname;
109                        short port;
110                } rt;
111                char *path;
112        } conn_info;
113
114        union {
115                struct {
116                        int level;
117                        int fileflag;
118                } erf;
119               
120        } options;
121       
122        union {
123                int fd;
124                struct rtserver_t * rtserver;
125                libtrace_io_t *file;
126        } output;
127};
128
129/** Structure holding status information for a packet */
130typedef struct libtrace_packet_status {
131        uint8_t type;
132        uint8_t reserved;
133        uint16_t message;
134} libtrace_packet_status_t;
135
136typedef struct erf_index_t {
137        uint64_t timestamp;
138        uint64_t offset; 
139} erf_index_t;
140
141#ifdef HAVE_DAG
142static int dag_init_input(struct libtrace_t *libtrace) {
143        struct stat buf;
144
145        libtrace->format_data = (struct erf_format_data_t *)
146                malloc(sizeof(struct erf_format_data_t));
147        if (stat(libtrace->uridata, &buf) == -1) {
148                trace_set_err(libtrace,errno,"stat(%s)",libtrace->uridata);
149                return -1;
150        } 
151        if (S_ISCHR(buf.st_mode)) {
152                /* DEVICE */
153                if((INPUT.fd = dag_open(libtrace->uridata)) < 0) {
154                        trace_set_err(libtrace,errno,"Cannot open DAG %s",
155                                        libtrace->uridata);
156                        return -1;
157                }
158                if((DAG.buf = (void *)dag_mmap(INPUT.fd)) == MAP_FAILED) {
159                        trace_set_err(libtrace,errno,"Cannot mmap DAG %s",
160                                        libtrace->uridata);
161                        return -1;
162                }
163        } else {
164                trace_set_err(libtrace,errno,"Not a valid dag device: %s",
165                                libtrace->uridata);
166                return -1;
167        }
168        return 0;
169}
170
171#endif
172
173/* Dag erf ether packets have a 2 byte padding before the packet
174 * so that the ip header is aligned on a 32 bit boundary.
175 */
176static int erf_get_padding(const libtrace_packet_t *packet)
177{
178        dag_record_t *erfptr = (dag_record_t *)packet->header;
179        switch(erfptr->type) {
180                case TYPE_ETH:          return 2;
181                default:                return 0;
182        }
183}
184
185static int erf_get_framing_length(const libtrace_packet_t *packet)
186{
187        return dag_record_size + erf_get_padding(packet);
188}
189
190
191static int erf_init_input(libtrace_t *libtrace) 
192{
193        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
194       
195        INPUT.file = 0;
196
197        return 0; /* success */
198}
199
200static int erf_start_input(libtrace_t *libtrace)
201{
202        if (INPUT.file)
203                return 0; /* success */
204
205        INPUT.file = trace_open_file(libtrace);
206
207        if (!INPUT.file)
208                return -1;
209
210        return 0; /* success */
211}
212
213/* Binary search through the index to find the closest point before
214 * the packet.  Consider in future having a btree index perhaps?
215 */
216static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
217{
218        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
219        size_t min_off = 0;
220        off_t current;
221        erf_index_t record;
222        do {
223                current=(max_off+min_off)>>2;
224
225                libtrace_io_seek(DATA(libtrace)->seek.index,
226                                current*sizeof(record),
227                                SEEK_SET);
228                libtrace_io_read(DATA(libtrace)->seek.index,
229                                &record,sizeof(record));
230                if (record.timestamp < erfts) {
231                        min_off=current;
232                }
233                if (record.timestamp > erfts) {
234                        max_off=current;
235                }
236                if (record.timestamp == erfts)
237                        break;
238        } while(min_off<max_off);
239
240        /* If we've passed it, seek backwards.  This loop shouldn't
241         * execute more than twice.
242         */
243        do {
244                libtrace_io_seek(DATA(libtrace)->seek.index,
245                                current*sizeof(record),SEEK_SET);
246                libtrace_io_read(DATA(libtrace)->seek.index,
247                                &record,sizeof(record));
248                current--;
249        } while(record.timestamp>erfts);
250
251        /* We've found our location in the trace, now use it. */
252        libtrace_io_seek(INPUT.file,record.offset,SEEK_SET);
253
254        return 0; /* success */
255}
256
257/* There is no index.  Seek through the entire trace from the start, nice
258 * and slowly.
259 */
260static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts)
261{
262        if (INPUT.file) {
263                libtrace_io_close(INPUT.file);
264        }
265        INPUT.file = trace_open_file(libtrace);
266        if (!INPUT.file)
267                return -1;
268        return 0;
269}
270
271static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
272{
273        libtrace_packet_t *packet;
274        off_t off = 0;
275
276        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
277                char buffer[PATH_MAX];
278                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
279                DATA(libtrace)->seek.index=libtrace_io_open(buffer,"r");
280                if (DATA(libtrace)->seek.index) {
281                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
282                }
283                else {
284                        DATA(libtrace)->seek.exists=INDEX_NONE;
285                }
286        }
287
288        /* If theres an index, use it to find the nearest packet that isn't
289         * after the time we're looking for.  If there is no index we need
290         * to seek slowly through the trace from the beginning.  Sigh.
291         */
292        switch(DATA(libtrace)->seek.exists) {
293                case INDEX_EXISTS:
294                        erf_fast_seek_start(libtrace,erfts);
295                        break;
296                case INDEX_NONE:
297                        erf_slow_seek_start(libtrace,erfts);
298                        break;
299                case INDEX_UNKNOWN:
300                        assert(0);
301                        break;
302        }
303
304        /* Now seek forward looking for the correct timestamp */
305        packet=trace_create_packet();
306        do {
307                trace_read_packet(libtrace,packet);
308                if (trace_get_erf_timestamp(packet)==erfts)
309                        break;
310                off=libtrace_io_tell(INPUT.file);
311        } while(trace_get_erf_timestamp(packet)<erfts);
312
313        libtrace_io_seek(INPUT.file,off,SEEK_SET);
314
315        return 0;
316}
317
318static int rtclient_init_input(libtrace_t *libtrace) {
319        char *scan;
320        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
321
322        if (strlen(libtrace->uridata) == 0) {
323                CONNINFO.rt.hostname = 
324                        strdup("localhost");
325                CONNINFO.rt.port = 
326                        COLLECTOR_PORT;
327        } else {
328                if ((scan = strchr(libtrace->uridata,':')) == NULL) {
329                        CONNINFO.rt.hostname = 
330                                strdup(libtrace->uridata);
331                        CONNINFO.rt.port =
332                                COLLECTOR_PORT;
333                } else {
334                        CONNINFO.rt.hostname = 
335                                (char *)strndup(libtrace->uridata,
336                                                (scan - libtrace->uridata));
337                        CONNINFO.rt.port = 
338                                atoi(++scan);
339                }
340        }
341
342        return 0; /* success */
343}
344
345static int rtclient_start_input(libtrace_t *libtrace)
346{
347        struct hostent *he;
348        struct sockaddr_in remote;
349        if ((he=gethostbyname(CONNINFO.rt.hostname)) == NULL) { 
350                trace_set_err(libtrace,errno,"failed to resolve %s",
351                                CONNINFO.rt.hostname);
352                return -1;
353        } 
354        if ((INPUT.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
355                trace_set_err(libtrace,errno,"socket(AF_INET,SOCK_STREAM)");
356                return -1;
357        }
358
359        remote.sin_family = AF_INET;   
360        remote.sin_port = htons(CONNINFO.rt.port);
361        remote.sin_addr = *((struct in_addr *)he->h_addr);
362        memset(&(remote.sin_zero), 0, 8);
363
364        if (connect(INPUT.fd, (struct sockaddr *)&remote,
365                                sizeof(struct sockaddr)) == -1) {
366                trace_set_err(libtrace,errno,"connect(%s)",
367                                CONNINFO.rt.hostname);
368                return -1;
369        }
370        return 0; /* success */
371}
372
373static int rtclient_pause_input(libtrace_t *libtrace)
374{
375        close(INPUT.fd);
376        return 0; /* success */
377}
378
379static int erf_init_output(libtrace_out_t *libtrace) {
380        libtrace->format_data = calloc(1,sizeof(struct erf_format_data_out_t));
381
382        OPTIONS.erf.level = 0;
383        OPTIONS.erf.fileflag = O_CREAT | O_WRONLY;
384        OUTPUT.file = 0;
385
386        return 0;
387}
388
389static int erf_config_output(libtrace_out_t *libtrace, trace_option_output_t option,
390                void *value) {
391
392        switch (option) {
393                case TRACE_OPTION_OUTPUT_COMPRESS:
394                        OPTIONS.erf.level = *(int*)value;
395                        return 0;
396                case TRACE_OPTION_OUTPUT_FILEFLAGS:
397                        OPTIONS.erf.fileflag = *(int*)value;
398                        return 0;
399                default:
400                        /* Unknown option */
401                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
402                                        "Unknown option");
403                        return -1;
404        }
405}
406
407
408#ifdef HAVE_DAG
409static int dag_pause_input(libtrace_t *libtrace) {
410        dag_stop(INPUT.fd);
411        return 0; /* success */
412}
413
414static int dag_fin_input(libtrace_t *libtrace) {
415        /* dag pause input implicitly called to cleanup before this */
416        dag_close(INPUT.fd);
417        free(libtrace->format_data);
418        return 0; /* success */
419}
420#endif
421
422static int rtclient_fin_input(libtrace_t *libtrace) {
423        free(CONNINFO.rt.hostname);
424        close(INPUT.fd);
425        free(libtrace->format_data);
426        return 0;
427}
428
429static int erf_fin_input(libtrace_t *libtrace) {
430        libtrace_io_close(INPUT.file);
431        free(libtrace->format_data);
432        return 0;
433}
434
435static int erf_fin_output(libtrace_out_t *libtrace) {
436        libtrace_io_close(OUTPUT.file);
437        free(libtrace->format_data);
438        return 0;
439}
440 
441#if HAVE_DAG
442static int dag_read(libtrace_t *libtrace, int block_flag) {
443
444        if (DAG.diff != 0) 
445                return DAG.diff;
446
447        DAG.bottom = DAG.top;
448
449        DAG.top = dag_offset(
450                        INPUT.fd,
451                        &(DAG.bottom),
452                        block_flag);
453
454        DAG.diff = DAG.top - DAG.bottom;
455
456        DAG.offset = 0;
457        return DAG.diff;
458}
459
460/* FIXME: dag_read_packet shouldn't update the pointers, dag_fin_packet
461 * should do that.
462 */
463static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
464        int numbytes;
465        int size;
466        dag_record_t *erfptr;
467
468        if (packet->buf_control == TRACE_CTRL_PACKET) {
469                packet->buf_control = TRACE_CTRL_EXTERNAL;
470                free(packet->buffer);
471                packet->buffer = 0;
472        }
473       
474        packet->type = RT_DATA_ERF;
475       
476        if ((numbytes = dag_read(libtrace,0)) < 0) 
477                return numbytes;
478        assert(numbytes>0);
479
480        /*DAG always gives us whole packets */
481        erfptr = (dag_record_t *) ((char *)DAG.buf + 
482                        (DAG.bottom + DAG.offset));
483        size = ntohs(erfptr->rlen);
484
485        assert( size >= dag_record_size );
486        assert( size < LIBTRACE_PACKET_BUFSIZE);
487       
488        packet->buffer = erfptr;
489        packet->header = erfptr;
490        if (((dag_record_t *)packet->buffer)->flags.rxerror == 1) {
491                packet->payload = NULL;
492        } else {
493                packet->payload = (char*)packet->buffer
494                        + erf_get_framing_length(packet);
495        }
496
497        DAG.offset += size;
498        DAG.diff -= size;
499
500        return (size);
501}
502
503static int dag_start_input(libtrace_t *libtrace) {
504        if(dag_start(INPUT.fd) < 0) {
505                trace_set_err(libtrace,errno,"Cannot start DAG %s",
506                                libtrace->uridata);
507                return -1;
508        }
509        /* dags appear to have a bug where if you call dag_start after
510         * calling dag_stop, and at least one packet has arrived, bad things
511         * happen.  flush the memory hole
512         */
513        while(dag_read(libtrace,1)!=0)
514                DAG.diff=0;
515        return 0;
516}
517#endif
518
519static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
520        int numbytes;
521        int size;
522        void *buffer2 = packet->buffer;
523        int rlen;
524
525        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
526                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
527                packet->buf_control = TRACE_CTRL_PACKET;
528        }
529
530        packet->header = packet->buffer;
531        packet->type = RT_DATA_ERF;
532
533        if ((numbytes=libtrace_io_read(INPUT.file,
534                                        packet->buffer,
535                                        dag_record_size)) == -1) {
536                trace_set_err(libtrace,errno,"read(%s)",
537                                libtrace->uridata);
538                return -1;
539        }
540        if (numbytes == 0) {
541                return 0;
542        }
543
544        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
545        buffer2 = (char*)packet->buffer + dag_record_size;
546        size = rlen - dag_record_size;
547        assert(size < LIBTRACE_PACKET_BUFSIZE);
548
549       
550        /* Unknown/corrupt */
551        assert(((dag_record_t *)packet->buffer)->type < 10);
552       
553        /* read in the rest of the packet */
554        if ((numbytes=libtrace_io_read(INPUT.file,
555                                        buffer2,
556                                        size)) != size) {
557                trace_set_err(libtrace,errno, "read(%s)", libtrace->uridata);
558                return -1;
559        }
560        if (((dag_record_t *)packet->buffer)->flags.rxerror == 1) {
561                packet->payload = NULL;
562        } else {
563                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
564        }
565        return rlen;
566}
567
568static int rtclient_read(libtrace_t *libtrace, void *buffer, size_t len) {
569        int numbytes;
570
571        while(1) {
572#ifndef MSG_NOSIGNAL
573#  define MSG_NOSIGNAL 0
574#endif
575                if ((numbytes = recv(INPUT.fd,
576                                                buffer,
577                                                len,
578                                                MSG_NOSIGNAL)) == -1) {
579                        if (errno == EINTR) {
580                                /*ignore EINTR in case
581                                 *a caller is using signals
582                                 */
583                                continue;
584                        }
585                        trace_set_err(libtrace,errno,"recv(%s)",
586                                        libtrace->uridata);
587                        return -1;
588                }
589                break;
590
591        }
592        return numbytes;
593}
594
595static int rtclient_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
596        int numbytes = 0;
597        char buf[RP_BUFSIZE];
598        int read_required = 0;
599       
600        void *buffer = 0;
601
602        if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) {
603                packet->buf_control = TRACE_CTRL_PACKET;
604                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
605        }
606
607        buffer = packet->buffer;
608        packet->header = packet->buffer;
609       
610        packet->type = RT_DATA_ERF;
611
612       
613        do {
614                libtrace_packet_status_t status;
615                int size;
616                if (tracefifo_out_available(libtrace->fifo) == 0 
617                                || read_required) {
618                        if ((numbytes = rtclient_read(
619                                        libtrace,buf,RP_BUFSIZE))<=0) {
620                                return numbytes;
621                        }
622                        tracefifo_write(libtrace->fifo,buf,numbytes);
623                        read_required = 0;
624                }
625                /* Read status byte */
626                if (tracefifo_out_read(libtrace->fifo,
627                                &status, sizeof(uint32_t)) == 0) {
628                        read_required = 1;
629                        continue;
630                }
631                tracefifo_out_update(libtrace->fifo,sizeof(uint32_t));
632                /* Read in packet size */
633                if (tracefifo_out_read(libtrace->fifo,
634                                &size, sizeof(uint32_t)) == 0) {
635                        tracefifo_out_reset(libtrace->fifo);
636                        read_required = 1;
637                        continue;
638                }
639                tracefifo_out_update(libtrace->fifo, sizeof(uint32_t));
640               
641                if (status.type == 2 /* RT_MSG */) {
642                        /* Need to skip this packet as it is a message packet */
643                        tracefifo_out_update(libtrace->fifo, size);
644                        tracefifo_ack_update(libtrace->fifo, size + 
645                                        sizeof(uint32_t) + 
646                                        sizeof(libtrace_packet_status_t));
647                        continue;
648                }
649               
650                /* read in the full packet */
651                if ((numbytes = tracefifo_out_read(libtrace->fifo, 
652                                                buffer, size)) == 0) {
653                        tracefifo_out_reset(libtrace->fifo);
654                        read_required = 1;
655                        continue;
656                }
657
658                /* got in our whole packet, so... */
659                tracefifo_out_update(libtrace->fifo,size);
660
661                tracefifo_ack_update(libtrace->fifo,size + 
662                                sizeof(uint32_t) + 
663                                sizeof(libtrace_packet_status_t));
664
665                if (((dag_record_t *)buffer)->flags.rxerror == 1) {
666                        packet->payload = NULL;
667                } else {
668                        packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
669                }
670                return numbytes;
671        } while(1);
672}
673
674static int erf_dump_packet(libtrace_out_t *libtrace,
675                dag_record_t *erfptr, int pad, void *buffer, size_t size) {
676        int numbytes = 0;
677        assert(size<=65536);
678
679        if ((numbytes = libtrace_io_write(OUTPUT.file, erfptr, dag_record_size + pad)) != dag_record_size+pad) {
680                trace_set_err_out(libtrace,errno,
681                                "write(%s)",libtrace->uridata);
682                return -1;
683        }
684
685        if ((numbytes=libtrace_io_write(OUTPUT.file, buffer, size)) != size) {
686                trace_set_err_out(libtrace,errno,
687                                "write(%s)",libtrace->uridata);
688                return -1;
689        }
690
691        return numbytes + pad + dag_record_size;
692}
693
694static int erf_start_output(libtrace_out_t *libtrace)
695{
696        OUTPUT.file = trace_open_file_out(libtrace,
697                        OPTIONS.erf.level,
698                        OPTIONS.erf.fileflag);
699        if (!OUTPUT.file) {
700                return -1;
701        }
702        return 0;
703}
704               
705static int erf_write_packet(libtrace_out_t *libtrace, 
706                const libtrace_packet_t *packet) 
707{
708        int numbytes = 0;
709        int pad = 0;
710        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
711        void *payload = packet->payload;
712
713        assert(OUTPUT.file);
714
715        pad = erf_get_padding(packet);
716
717        /* If we've had an rxerror, we have no payload to write - fix rlen to
718         * be the correct length */
719        if (payload == NULL) {
720                dag_hdr->rlen = htons(dag_record_size + pad);
721        } 
722       
723        if (packet->trace->format == &erf 
724#if HAVE_DAG
725                        || packet->trace->format == &dag
726#endif
727                        ) {
728                numbytes = erf_dump_packet(libtrace,
729                                (dag_record_t *)packet->header,
730                                pad,
731                                payload,
732                                trace_get_capture_length(packet)
733                                );
734        } else {
735                dag_record_t erfhdr;
736                int type;
737                /* convert format - build up a new erf header */
738                /* Timestamp */
739                erfhdr.ts = trace_get_erf_timestamp(packet);
740                type=libtrace_to_erf_type(trace_get_link_type(packet));
741                if (type==(char)-1) {
742                        trace_set_err_out(libtrace,TRACE_ERR_BAD_PACKET,
743                                        "No erf type for packet");
744                        return -1;
745                }
746                erfhdr.type = type;
747                /* Flags. Can't do this */
748                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
749                /* Packet length (rlen includes format overhead) */
750                erfhdr.rlen = trace_get_capture_length(packet) 
751                        + erf_get_framing_length(packet);
752                /* loss counter. Can't do this */
753                erfhdr.lctr = 0;
754                /* Wire length */
755                erfhdr.wlen = trace_get_wire_length(packet);
756
757                /* Write it out */
758                numbytes = erf_dump_packet(libtrace,
759                                &erfhdr,
760                                pad,
761                                payload,
762                                trace_get_capture_length(packet));
763        }
764        return numbytes;
765}
766
767static libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
768        dag_record_t *erfptr = 0;
769        erfptr = (dag_record_t *)packet->header;
770        return erf_type_to_libtrace(erfptr->type);
771}
772
773static int8_t erf_get_direction(const libtrace_packet_t *packet) {
774        dag_record_t *erfptr = 0;
775        erfptr = (dag_record_t *)packet->header;
776        return erfptr->flags.iface;
777}
778
779static int8_t erf_set_direction(const libtrace_packet_t *packet, int8_t direction) {
780        dag_record_t *erfptr = 0;
781        erfptr = (dag_record_t *)packet->header;
782        erfptr->flags.iface = direction;
783        return erfptr->flags.iface;
784}
785
786static uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
787        dag_record_t *erfptr = 0;
788        erfptr = (dag_record_t *)packet->header;
789        return erfptr->ts;
790}
791
792static int erf_get_capture_length(const libtrace_packet_t *packet) {
793        dag_record_t *erfptr = 0;
794        erfptr = (dag_record_t *)packet->header;
795        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
796}
797
798static int erf_get_wire_length(const libtrace_packet_t *packet) {
799        dag_record_t *erfptr = 0;
800        erfptr = (dag_record_t *)packet->header;
801        return ntohs(erfptr->wlen);
802}
803
804static size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
805        dag_record_t *erfptr = 0;
806        assert(packet);
807        if(size  > trace_get_capture_length(packet)) {
808                /* can't make a packet larger */
809                return trace_get_capture_length(packet);
810        }
811        erfptr = (dag_record_t *)packet->header;
812        erfptr->rlen = htons(size + erf_get_framing_length(packet));
813        return trace_get_capture_length(packet);
814}
815
816static int rtclient_get_fd(const libtrace_t *libtrace) {
817        return INPUT.fd;
818}
819
820#ifdef HAVE_DAG
821libtrace_eventobj_t trace_event_dag(libtrace_t *trace, libtrace_packet_t *packet) {
822        libtrace_eventobj_t event = {0,0,0.0,0};
823        int dag_fd;
824        int data;
825
826        if (trace->format->get_fd) {
827                dag_fd = trace->format->get_fd(trace);
828        } else {
829                dag_fd = 0;
830        }
831       
832        data = dag_read(trace, DAGF_NONBLOCK);
833
834        if (data > 0) {
835                event.size = trace_read_packet(trace,packet);
836                event.type = TRACE_EVENT_PACKET;
837                return event;
838        }
839        event.type = TRACE_EVENT_SLEEP;
840        event.seconds = 0.0001;
841        return event;
842}
843#endif
844
845#if HAVE_DAG
846static void dag_help() {
847        printf("dag format module: $Revision$\n");
848        printf("Supported input URIs:\n");
849        printf("\tdag:/dev/dagn\n");
850        printf("\n");
851        printf("\te.g.: dag:/dev/dag0\n");
852        printf("\n");
853        printf("Supported output URIs:\n");
854        printf("\tnone\n");
855        printf("\n");
856}
857#endif
858
859static void erf_help() {
860        printf("erf format module: $Revision$\n");
861        printf("Supported input URIs:\n");
862        printf("\terf:/path/to/file\t(uncompressed)\n");
863        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
864        printf("\terf:-\t(stdin, either compressed or not)\n");
865        printf("\terf:/path/to/socket\n");
866        printf("\n");
867        printf("\te.g.: erf:/tmp/trace\n");
868        printf("\n");
869        printf("Supported output URIs:\n");
870        printf("\terf:path/to/file\t(uncompressed)\n");
871        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
872        printf("\terf:-\t(stdout, either compressed or not)\n");
873        printf("\n");
874        printf("\te.g.: erf:/tmp/trace\n");
875        printf("\n");
876        printf("Supported output options:\n");
877        printf("\t-z\tSpecify the gzip compression, ranging from 0 (uncompressed) to 9 - defaults to 1\n");
878        printf("\n");
879
880       
881}
882
883static void rtclient_help() {
884        printf("rtclient format module: $Revision$\n");
885        printf("DEPRECATED - use rt module instead\n");
886        printf("Supported input URIs:\n");
887        printf("\trtclient:host:port\n");
888        printf("\n");
889        printf("\te.g.:rtclient:localhost:3435\n");
890        printf("\n");
891        printf("Supported output URIs:\n");
892        printf("\tnone\n");
893        printf("\n");
894}       
895
896static struct libtrace_format_t erf = {
897        "erf",
898        "$Id$",
899        TRACE_FORMAT_ERF,
900        erf_init_input,                 /* init_input */       
901        NULL,                           /* config_input */
902        erf_start_input,                /* start_input */
903        NULL,                           /* pause_input */
904        erf_init_output,                /* init_output */
905        erf_config_output,              /* config_output */
906        erf_start_output,               /* start_output */
907        erf_fin_input,                  /* fin_input */
908        erf_fin_output,                 /* fin_output */
909        erf_read_packet,                /* read_packet */
910        NULL,                           /* fin_packet */
911        erf_write_packet,               /* write_packet */
912        erf_get_link_type,              /* get_link_type */
913        erf_get_direction,              /* get_direction */
914        erf_set_direction,              /* set_direction */
915        erf_get_erf_timestamp,          /* get_erf_timestamp */
916        NULL,                           /* get_timeval */
917        NULL,                           /* get_seconds */
918        erf_seek_erf,                   /* seek_erf */
919        NULL,                           /* seek_timeval */
920        NULL,                           /* seek_seconds */
921        erf_get_capture_length,         /* get_capture_length */
922        erf_get_wire_length,            /* get_wire_length */
923        erf_get_framing_length,         /* get_framing_length */
924        erf_set_capture_length,         /* set_capture_length */
925        NULL,                           /* get_fd */
926        trace_event_trace,              /* trace_event */
927        erf_help,                       /* help */
928        NULL                            /* next pointer */
929};
930
931#ifdef HAVE_DAG
932static struct libtrace_format_t dag = {
933        "dag",
934        "$Id$",
935        TRACE_FORMAT_ERF,
936        dag_init_input,                 /* init_input */       
937        NULL,                           /* config_input */
938        dag_start_input,                /* start_input */
939        dag_pause_input,                /* pause_input */
940        NULL,                           /* init_output */
941        NULL,                           /* config_output */
942        NULL,                           /* start_output */
943        dag_fin_input,                  /* fin_input */
944        NULL,                           /* fin_output */
945        dag_read_packet,                /* read_packet */
946        NULL,                           /* fin_packet */
947        NULL,                           /* write_packet */
948        erf_get_link_type,              /* get_link_type */
949        erf_get_direction,              /* get_direction */
950        erf_set_direction,              /* set_direction */
951        erf_get_erf_timestamp,          /* get_erf_timestamp */
952        NULL,                           /* get_timeval */
953        NULL,                           /* get_seconds */
954        NULL,                           /* seek_erf */
955        NULL,                           /* seek_timeval */
956        NULL,                           /* seek_seconds */
957        erf_get_capture_length,         /* get_capture_length */
958        erf_get_wire_length,            /* get_wire_length */
959        erf_get_framing_length,         /* get_framing_length */
960        erf_set_capture_length,         /* set_capture_length */
961        NULL,                           /* get_fd */
962        trace_event_dag,                /* trace_event */
963        dag_help,                       /* help */
964        NULL                            /* next pointer */
965};
966#endif
967
968static struct libtrace_format_t rtclient = {
969        "rtclient",
970        "$Id$",
971        TRACE_FORMAT_ERF,
972        rtclient_init_input,            /* init_input */       
973        NULL,                           /* config_input */
974        rtclient_start_input,           /* start_input */
975        rtclient_pause_input,           /* pause_input */
976        NULL,                           /* init_output */
977        NULL,                           /* config_output */
978        NULL,                           /* start_output */
979        rtclient_fin_input,             /* fin_input */
980        NULL,                           /* fin_output */
981        rtclient_read_packet,           /* read_packet */
982        NULL,                           /* fin_packet */
983        NULL,                           /* write_packet */
984        erf_get_link_type,              /* get_link_type */
985        erf_get_direction,              /* get_direction */
986        erf_set_direction,              /* set_direction */
987        erf_get_erf_timestamp,          /* get_erf_timestamp */
988        NULL,                           /* get_timeval */
989        NULL,                           /* get_seconds */
990        NULL,                           /* seek_erf */
991        NULL,                           /* seek_timeval */
992        NULL,                           /* seek_seconds */
993        erf_get_capture_length,         /* get_capture_length */
994        erf_get_wire_length,            /* get_wire_length */
995        erf_get_framing_length,         /* get_framing_length */
996        erf_set_capture_length,         /* set_capture_length */
997        rtclient_get_fd,                /* get_fd */
998        trace_event_device,             /* trace_event */
999        rtclient_help,                  /* help */
1000        NULL                            /* next pointer */
1001};
1002
1003void CONSTRUCTOR erf_constructor() {
1004        register_format(&rtclient);
1005        register_format(&erf);
1006#ifdef HAVE_DAG
1007        register_format(&dag);
1008#endif
1009}
Note: See TracBrowser for help on using the repository browser.