source: lib/format_erf.c @ 3fcb8b4

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 3fcb8b4 was 3fcb8b4, checked in by Shane Alcock <salcock@…>, 15 years ago

Added a couple of necessary fixes for FreeBSD compilation - defining PATH_MAX and including unistd.h for ssize_t and off_t
stdbool.h is no longer included if you're compiling as C++ as this causes conflicts under OpenBSD

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