source: lib/format_erf.c @ 5eeba76

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

Fixed memory leak in trace_event_trace
Wrote an example using the event framework
Removed old event examples
Updated format_pcapfile to use libtrace_direction_t
erf_read_packet now checks that malloc()ing a buffer actually succeeds

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