source: lib/format_erf.c @ 5baec88

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

Added append option to erf output

erf output doesn't open the output file until the first packet is to be
written

Added non-blocking dag read function

  • Property mode set to 100644
File size: 30.5 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#ifdef HAVE_INTTYPES_H
40#  include <inttypes.h>
41#else
42#  error "Can't find inttypes.h - this needs to be fixed"
43#endif
44
45#ifdef HAVE_STDDEF_H
46#  include <stddef.h>
47#else
48# error "Can't find stddef.h - do you define ptrdiff_t elsewhere?"
49#endif
50#include <sys/types.h>
51#include <sys/socket.h>
52#include <sys/un.h>
53#include <sys/mman.h>
54#include <sys/stat.h>
55#include <unistd.h>
56#include <assert.h>
57#include <errno.h>
58#include <netdb.h>
59#include <fcntl.h>
60#include <getopt.h>
61#include <stdio.h>
62#include <string.h>
63#include <stdlib.h>
64
65
66#define COLLECTOR_PORT 3435
67
68/* Catch undefined O_LARGEFILE on *BSD etc */
69#ifndef O_LARGEFILE
70#  define O_LARGEFILE 0
71#endif
72
73static struct libtrace_format_t erf;
74static struct libtrace_format_t rtclient;
75#if HAVE_DAG
76static struct libtrace_format_t dag;
77#endif
78static struct libtrace_format_t legacypos;
79static struct libtrace_format_t legacyeth;
80static struct libtrace_format_t legacyatm;
81
82#define CONNINFO libtrace->format_data->conn_info
83#define INPUT libtrace->format_data->input
84#define OUTPUT libtrace->format_data->output
85#if HAVE_DAG
86#define DAG libtrace->format_data->dag
87#endif
88#define OPTIONS libtrace->format_data->options
89struct libtrace_format_data_t {
90        union {
91                struct {
92                        char *hostname;
93                        short port;
94                } rt;
95                char *path;             
96        } conn_info;
97       
98        union {
99                int fd;
100#if HAVE_ZLIB
101                gzFile *file;
102#else   
103                //FILE  *file;
104                int file;
105#endif
106        } input;
107
108#if HAVE_DAG
109        struct {
110                void *buf; 
111                unsigned bottom;
112                unsigned top;
113                unsigned diff;
114                unsigned curr;
115                unsigned offset;
116        } dag;
117#endif
118};
119
120struct libtrace_format_data_out_t {
121        union {
122                struct {
123                        char *hostname;
124                        short port;
125                } rt;
126                char *path;
127        } conn_info;
128
129
130
131        union {
132                struct {
133                        int level;
134                        int append;
135                } erf;
136               
137        } options;
138       
139        union {
140                int fd;
141                struct rtserver_t * rtserver;
142#if HAVE_ZLIB
143                gzFile *file;
144#else
145                //FILE *file;
146                int file;
147#endif
148        } output;
149};
150
151#ifdef HAVE_DAG
152static int dag_init_input(struct libtrace_t *libtrace) {
153        struct stat buf;
154        libtrace->format_data = (struct libtrace_format_data_t *)
155                malloc(sizeof(struct libtrace_format_data_t));
156
157        CONNINFO.path = libtrace->uridata;
158        if (stat(CONNINFO.path,&buf) == -1) {
159                perror("stat");
160                return 0;
161        } 
162        if (S_ISCHR(buf.st_mode)) {
163                // DEVICE
164                libtrace->sourcetype = DEVICE;
165                if((INPUT.fd = dag_open(CONNINFO.path)) < 0) {
166                        fprintf(stderr,"Cannot open DAG %s: %m\n", 
167                                        CONNINFO.path,errno);
168                        exit(0);
169                }
170                if((DAG.buf = (void *)dag_mmap(INPUT.fd)) == MAP_FAILED) {
171                        fprintf(stderr,"Cannot mmap DAG %s: %m\n", 
172                                        CONNINFO.path,errno);
173                        exit(0);
174                }
175                if(dag_start(INPUT.fd) < 0) {
176                        fprintf(stderr,"Cannot start DAG %s: %m\n", 
177                                        CONNINFO.path,errno);
178                        exit(0);
179                }
180        } else {
181                fprintf(stderr,"%s isn't a valid char device, exiting\n",
182                                CONNINFO.path);
183                return 0;
184        }
185        return 1;
186}
187#endif
188
189/* Dag erf ether packets have a 2 byte padding before the packet
190 * so that the ip header is aligned on a 32 bit boundary.
191 */
192static int erf_get_padding(const struct libtrace_packet_t *packet)
193{
194        switch(trace_get_link_type(packet)) {
195                case TRACE_TYPE_ETH:    return 2;
196                default:                return 0;
197        }
198}
199
200static int erf_get_framing_length(const struct libtrace_packet_t *packet)
201{
202        return dag_record_size + erf_get_padding(packet);
203}
204
205static int legacyeth_get_framing_length(const struct libtrace_packet_t *packet UNUSED) 
206{
207        return sizeof(legacy_ether_t);
208}
209
210static int legacypos_get_framing_length(const struct libtrace_packet_t *packet UNUSED) 
211{
212        return sizeof(legacy_pos_t);
213}
214
215static int legacyatm_get_framing_length(const struct libtrace_packet_t *packet UNUSED) 
216{
217        return sizeof(legacy_cell_t);
218}
219
220static int erf_init_input(struct libtrace_t *libtrace) {
221        struct stat buf;
222        struct sockaddr_un unix_sock;
223        libtrace->format_data = (struct libtrace_format_data_t *)
224                malloc(sizeof(struct libtrace_format_data_t));
225
226        CONNINFO.path = libtrace->uridata;
227        if (!strncmp(CONNINFO.path,"-",1)) {
228                // STDIN
229                libtrace->sourcetype = STDIN;
230                INPUT.file = LIBTRACE_FDOPEN(fileno(stdin), "r");
231               
232
233        } else {
234                if (stat(CONNINFO.path,&buf) == -1 ) {
235                        perror("stat");
236                        return 0;
237                }
238                if (S_ISSOCK(buf.st_mode)) {
239                        libtrace->sourcetype = SOCKET;
240                        if ((INPUT.fd = socket(
241                                        AF_UNIX, SOCK_STREAM, 0)) == -1) {
242                                perror("socket");
243                                return 0;
244                        }
245                        unix_sock.sun_family = AF_UNIX;
246                        bzero(unix_sock.sun_path,108);
247                        snprintf(unix_sock.sun_path,
248                                        108,"%s"
249                                        ,CONNINFO.path);
250
251                        if (connect(INPUT.fd, 
252                                        (struct sockaddr *)&unix_sock,
253                                        sizeof(struct sockaddr)) == -1) {
254                                perror("connect (unix)");
255                                return 0;
256                        }
257                } else { 
258
259                        libtrace->sourcetype = TRACE;
260
261                        // we use an FDOPEN call to reopen an FD
262                        // returned from open(), so that we can set
263                        // O_LARGEFILE. This gets around gzopen not
264                        // letting you do this...
265                        INPUT.file = LIBTRACE_FDOPEN(open(
266                                                CONNINFO.path,
267                                                O_LARGEFILE),"r");
268                }
269        }
270        return 1;
271}
272
273static int rtclient_init_input(struct libtrace_t *libtrace) {
274        char *scan;
275        char *uridata = libtrace->uridata;
276        struct hostent *he;
277        struct sockaddr_in remote;
278        libtrace->format_data = (struct libtrace_format_data_t *)
279                malloc(sizeof(struct libtrace_format_data_t));
280
281        libtrace->sourcetype = RT;
282
283        if (strlen(uridata) == 0) {
284                CONNINFO.rt.hostname = 
285                        strdup("localhost");
286                CONNINFO.rt.port = 
287                        COLLECTOR_PORT;
288        } else {
289                if ((scan = strchr(uridata,':')) == NULL) {
290                        CONNINFO.rt.hostname = 
291                                strdup(uridata);
292                        CONNINFO.rt.port =
293                                COLLECTOR_PORT;
294                } else {
295                        CONNINFO.rt.hostname = 
296                                (char *)strndup(uridata,
297                                                (scan - uridata));
298                        CONNINFO.rt.port = 
299                                atoi(++scan);
300                }
301        }
302       
303        if ((he=gethostbyname(CONNINFO.rt.hostname)) == NULL) { 
304                perror("gethostbyname");
305                return 0;
306        } 
307        if ((INPUT.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
308                perror("socket");
309                return 0;
310        }
311
312        remote.sin_family = AF_INET;   
313        remote.sin_port = htons(CONNINFO.rt.port);
314        remote.sin_addr = *((struct in_addr *)he->h_addr);
315        bzero(&(remote.sin_zero), 8);
316
317        if (connect(INPUT.fd, (struct sockaddr *)&remote,
318                                sizeof(struct sockaddr)) == -1) {
319                perror("connect (inet)");
320                return 0;
321        }
322        return 1;
323}
324
325static int erf_init_output(struct libtrace_out_t *libtrace) {
326        int fd;
327        libtrace->format_data = (struct libtrace_format_data_out_t *)
328                calloc(1,sizeof(struct libtrace_format_data_out_t));
329
330        OPTIONS.erf.level = 0;
331        OPTIONS.erf.append = 0;
332        OUTPUT.file = 0;
333
334        return 1;
335}
336
337static int erf_open_output(struct libtrace_out_t *libtrace) {
338        char *filemode;
339        int trunc_flag = O_TRUNC;
340        int fd;
341
342#if HAVE_ZLIB
343        asprintf(&filemode,"wb%d",OPTIONS.erf.level);
344#else
345        asprintf(&filemode,"w");
346#endif
347
348        if (OPTIONS.erf.append) {
349                trunc_flag = O_APPEND;
350        }               
351
352        if (!strncmp(libtrace->uridata,"-",1)) {
353                // STDOUT
354                OUTPUT.file = LIBTRACE_FDOPEN(fileno(stdout),filemode);
355        }
356        else {
357                // TRACE
358                fd = open(libtrace->uridata, O_CREAT | O_LARGEFILE | O_WRONLY | trunc_flag, 
359                                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
360                if (fd <= 0) {
361                        return 0;
362                }
363                OUTPUT.file = LIBTRACE_FDOPEN(fd,filemode);
364
365        }
366        free(filemode);
367        return 1;
368}
369
370static int erf_config_output(struct libtrace_out_t *libtrace, int argc, char *argv[]) {
371        int opt;
372        int level = OPTIONS.erf.level;
373        optind = 1;
374
375
376        while ((opt = getopt(argc, argv, "z:a")) != EOF) {
377                switch (opt) {
378                        case 'z':
379                                level = atoi(optarg);
380                                break;
381                        case 'a':
382                                OPTIONS.erf.append = 1;
383                                break;
384                        default:
385                                printf("Bad argument to erf: %s\n", optarg);
386                                // maybe spit out some help here
387                                return -1;
388                }
389        }
390       
391        return 0;
392
393}
394
395
396#ifdef HAVE_DAG
397static int dag_fin_input(struct libtrace_t *libtrace) {
398        dag_stop(INPUT.fd);
399}
400#endif
401
402static int erf_fin_input(struct libtrace_t *libtrace) {
403        LIBTRACE_CLOSE(INPUT.file);
404        free(libtrace->format_data);
405        return 0;
406}
407
408static int rtclient_fin_input(struct libtrace_t *libtrace) {
409        close(INPUT.fd);
410        return 0;
411}
412
413static int erf_fin_output(struct libtrace_out_t *libtrace) {
414        LIBTRACE_CLOSE(OUTPUT.file);
415        free(libtrace->format_data);
416
417        return 0;
418}
419 
420#if HAVE_DAG
421static int dag_read(struct libtrace_t *libtrace, void *buffer, size_t len, int block_flag) {
422        int numbytes;
423        static short lctr = 0;
424        struct dag_record_t *erfptr = 0;
425        int rlen;
426
427        if (buffer == 0)
428                buffer = malloc(len);
429       
430        DAG.bottom = DAG.top;
431        DAG.top = dag_offset(
432                        INPUT.fd,
433                        &(DAG.bottom),
434                        block_flag);
435        DAG.diff = DAG.top -
436                DAG.bottom;
437
438        numbytes=DAG.diff;
439        DAG.offset = 0;
440        return numbytes;
441}
442#endif
443
444#if HAVE_DAG
445static int dag_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
446        int numbytes;
447        int size;
448        char buf[RP_BUFSIZE];
449        dag_record_t *erfptr;
450        void *buffer = packet->buffer;
451        void *buffer2 = buffer;
452        int rlen;
453
454        if (packet->buf_control == PACKET) {
455                packet->buf_control = EXTERNAL;
456                free(packet->buffer);
457                packet->buffer = 0;
458        }
459   
460        if (DAG.diff == 0) {
461                if ((numbytes = dag_read(libtrace,buf,RP_BUFSIZE, 0)) <= 0) 
462                        return numbytes;
463        }
464
465        //DAG always gives us whole packets
466        erfptr = (dag_record_t *) ((void *)DAG.buf + 
467                        (DAG.bottom + DAG.offset));
468        size = ntohs(erfptr->rlen);
469
470        if ( size  > LIBTRACE_PACKET_BUFSIZE) {
471                assert( size < LIBTRACE_PACKET_BUFSIZE);
472        }
473       
474        packet->buffer = erfptr;
475        packet->header = erfptr;
476        if (((dag_record_t *)buffer)->flags.rxerror == 1) {
477                packet->payload = NULL;
478        } else {
479                packet->payload = packet->buffer + erf_get_framing_length(packet);
480        }
481
482       
483        packet->status.type = RT_DATA;
484        packet->status.message = 0;
485        packet->size = size;
486        DAG.offset += size;
487        DAG.diff -= size;
488
489        assert(DAG.diff >= 0);
490
491        return (size);
492}
493
494
495// Lots of repeated code in here - could easily be tidied up
496static int dag_read_packet_nb(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
497        int numbytes;
498        int size;
499        char buf[RP_BUFSIZE];
500        dag_record_t *erfptr;
501        void *buffer = packet->buffer;
502        void *buffer2 = buffer;
503        int rlen;
504
505        if (packet->buf_control == PACKET) {
506                packet->buf_control = EXTERNAL;
507                free(packet->buffer);
508                packet->buffer = 0;
509        }
510
511        if (DAG.diff == 0) {
512                if ((numbytes = dag_read(libtrace,buf,RP_BUFSIZE, DAGF_NONBLOCK)) <= 0)
513                        return numbytes;
514        }
515
516        //DAG always gives us whole packets
517        erfptr = (dag_record_t *) ((void *)DAG.buf +
518                        (DAG.bottom + DAG.offset));
519        size = ntohs(erfptr->rlen);
520
521        if ( size  > LIBTRACE_PACKET_BUFSIZE) {
522                assert( size < LIBTRACE_PACKET_BUFSIZE);
523        }
524
525        packet->buffer = erfptr;
526        packet->header = erfptr;
527        if (((dag_record_t *)buffer)->flags.rxerror == 1) {
528                packet->payload = NULL;
529        } else {
530                packet->payload = packet->buffer + erf_get_framing_length(packet);
531        }
532
533
534        packet->status.type = RT_DATA;
535        packet->status.message = 0;
536        packet->size = size;
537        DAG.offset += size;
538        DAG.diff -= size;
539
540        assert(DAG.diff >= 0);
541
542        return (size);
543}
544
545#endif
546
547static int legacy_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
548        int numbytes;
549        void *buffer = packet->buffer;
550       
551        if ((numbytes=LIBTRACE_READ(INPUT.file,
552                                        buffer,
553                                        64)) == -1) {
554                perror("libtrace_read");
555                return -1;
556        }
557        packet->status.type = RT_DATA;
558        packet->status.message = 0;
559        packet->size = 64;
560       
561        packet->header = packet->buffer;
562        packet->payload = packet->buffer + 
563                packet->trace->format->get_framing_length(packet);
564       
565        return 64;
566       
567}
568static int erf_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
569        int numbytes;
570        int size;
571        void *buffer = packet->buffer;
572        void *buffer2 = buffer;
573        int rlen;
574        if (packet->buf_control == EXTERNAL) {
575                packet->buf_control = PACKET;
576                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
577        }
578        buffer = packet->buffer;
579        packet->header = packet->buffer;
580
581
582        if ((numbytes=LIBTRACE_READ(INPUT.file,
583                                        buffer,
584                                        dag_record_size)) == -1) {
585                perror("libtrace_read");
586                return -1;
587        }
588        if (numbytes == 0) {
589                return 0;
590        }
591
592        rlen = ntohs(((dag_record_t *)buffer)->rlen);
593        buffer2 = buffer + dag_record_size;
594        size = rlen - dag_record_size;
595        assert(size < LIBTRACE_PACKET_BUFSIZE);
596       
597        /* If your trace is legacy, or corrupt, then this assert may fire. */
598        /* turns out some older traces have fixed snaplens, which are padded
599         * with 00's if the packet is smaller, so this doesn't work.  Sigh.
600        assert(ntohs(((dag_record_t *)buffer)->rlen) <=
601                        ntohs(((dag_record_t*)buffer)->wlen)+erf_get_framing_length(packet));
602        */
603        /* Unknown/corrupt */
604        assert(((dag_record_t *)buffer)->type < 10);
605       
606        // read in the rest of the packet
607        if ((numbytes=LIBTRACE_READ(INPUT.file,
608                                        buffer2,
609                                        size)) != size) {
610                perror("libtrace_read");
611                return -1;
612        }
613        packet->status.type = RT_DATA;
614        packet->status.message = 0;
615        packet->size = rlen;
616        if (((dag_record_t *)buffer)->flags.rxerror == 1) {
617                packet->payload = NULL;
618        } else {
619                packet->payload = packet->buffer + erf_get_framing_length(packet);
620        }
621        return rlen;
622}
623
624static int rtclient_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
625        int numbytes;
626
627        if (buffer == 0)
628                buffer = malloc(len);
629        while(1) {
630#ifndef MSG_NOSIGNAL
631#  define MSG_NOSIGNAL 0
632#endif
633                if ((numbytes = recv(INPUT.fd,
634                                                buffer,
635                                                len,
636                                                MSG_NOSIGNAL)) == -1) {
637                        if (errno == EINTR) {
638                                //ignore EINTR in case
639                                // a caller is using signals
640                                continue;
641                        }
642                        perror("recv");
643                        return -1;
644                }
645                break;
646
647        }
648        return numbytes;
649}
650
651static int rtclient_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
652        int numbytes = 0;
653        char buf[RP_BUFSIZE];
654        int read_required = 0;
655       
656        void *buffer = 0;
657
658        packet->trace = libtrace;
659
660        if (packet->buf_control == EXTERNAL) {
661                packet->buf_control = PACKET;
662                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
663        }
664
665        buffer = packet->buffer;
666        packet->header = packet->buffer;
667
668       
669        do {
670                if (tracefifo_out_available(libtrace->fifo) == 0 || read_required) {
671                        if ((numbytes = rtclient_read(
672                                        libtrace,buf,RP_BUFSIZE))<=0) {
673                                return numbytes;
674                        }
675                        tracefifo_write(libtrace->fifo,buf,numbytes);
676                        read_required = 0;
677                }
678                // Read status byte
679                if (tracefifo_out_read(libtrace->fifo,
680                                &packet->status, sizeof(uint32_t)) == 0) {
681                        read_required = 1;
682                        continue;
683                }
684                tracefifo_out_update(libtrace->fifo,sizeof(uint32_t));
685                // Read in packet size
686                if (tracefifo_out_read(libtrace->fifo,
687                                &packet->size, sizeof(uint32_t)) == 0) {
688                        tracefifo_out_reset(libtrace->fifo);
689                        read_required = 1;
690                        continue;
691                }
692                tracefifo_out_update(libtrace->fifo, sizeof(uint32_t));
693               
694                /*
695                // read in the ERF header
696                if ((numbytes = tracefifo_out_read(libtrace->fifo, buffer,
697                                                dag_record_size)) == 0) {
698                        tracefifo_out_reset(libtrace->fifo);
699                        read_required = 1;
700                        continue;
701                }
702                */
703                if (packet->status.type == RT_MSG) {
704                        // Need to skip this packet as it is a message packet
705                        tracefifo_out_update(libtrace->fifo, packet->size);
706                        tracefifo_ack_update(libtrace->fifo, packet->size + 
707                                        sizeof(uint32_t) + 
708                                        sizeof(libtrace_packet_status_t));
709                        continue;
710                }
711               
712                //size = ntohs(((dag_record_t *)buffer)->rlen);
713               
714                // read in the full packet
715                if ((numbytes = tracefifo_out_read(libtrace->fifo, 
716                                                buffer, packet->size)) == 0) {
717                        tracefifo_out_reset(libtrace->fifo);
718                        read_required = 1;
719                        continue;
720                }
721
722                // got in our whole packet, so...
723                tracefifo_out_update(libtrace->fifo,packet->size);
724
725                tracefifo_ack_update(libtrace->fifo,packet->size + 
726                                sizeof(uint32_t) + 
727                                sizeof(libtrace_packet_status_t));
728
729                //packet->size = numbytes;
730                if (((dag_record_t *)buffer)->flags.rxerror == 1) {
731                        packet->payload = NULL;
732                } else {
733                        packet->payload = packet->buffer + erf_get_framing_length(packet);
734                }
735                return numbytes;
736        } while(1);
737}
738
739static int erf_dump_packet(struct libtrace_out_t *libtrace, dag_record_t *erfptr, int pad, void *buffer, size_t size) {
740        int numbytes = 0;
741        if ((numbytes = LIBTRACE_WRITE(OUTPUT.file, erfptr, dag_record_size + pad)) == 0) {
742                perror("libtrace_write");
743                return -1;
744        }
745
746        if (buffer) {
747                if ((numbytes = LIBTRACE_WRITE(OUTPUT.file, buffer, size)) == 0) {
748                        perror("libtrace_write");
749                        return -1;
750                }
751       
752                return numbytes + pad + dag_record_size;
753        }
754        return numbytes;
755}
756               
757static int erf_write_packet(struct libtrace_out_t *libtrace, const struct libtrace_packet_t *packet) {
758        int numbytes = 0;
759        dag_record_t erfhdr;
760        int pad = 0;
761        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
762        void *payload = packet->payload;
763
764        /* Because of configuration, we don't actually open the output file
765           until we get the first packet. Not ideal, but it'll do for now */
766        if (!OUTPUT.file) {
767                if (erf_open_output(libtrace) <= 0) { 
768                        perror("erf_open_output");
769                        return -1;
770                }
771        }
772
773        pad = erf_get_padding(packet);
774
775        /* If we've had an rxerror, we have no payload to write - fix rlen to
776         * be the correct length */
777        if (payload == NULL) {
778                dag_hdr->rlen = htons(dag_record_size + pad);
779        } 
780       
781        if (packet->trace->format == &erf || 
782#if HAVE_DAG
783                        packet->trace->format == &dag ||
784#endif
785                        packet->trace->format == &rtclient ) {
786                numbytes = erf_dump_packet(libtrace,
787                                (dag_record_t *)packet->buffer,
788                                pad,
789                                payload,
790                                packet->size - 
791                                        (dag_record_size + pad)); 
792        } else {
793                // convert format - build up a new erf header
794                // Timestamp
795                erfhdr.ts = trace_get_erf_timestamp(packet);
796                // Flags. Can't do this
797                memset(&erfhdr.flags,1,1);
798                // Packet length (rlen includes format overhead)
799                erfhdr.rlen = trace_get_capture_length(packet) + erf_get_framing_length(packet);
800                // loss counter. Can't do this
801                erfhdr.lctr = 0;
802                // Wire length
803                erfhdr.wlen = trace_get_wire_length(packet);
804               
805                // Write it out
806                numbytes = erf_dump_packet(libtrace,
807                                &erfhdr,
808                                pad,
809                                payload,
810                                trace_get_capture_length(packet));
811        }
812        return numbytes;
813}
814
815static void *legacypos_get_link(const struct libtrace_packet_t *packet) {
816        return (void *)packet->payload;
817}
818
819static libtrace_linktype_t legacypos_get_link_type(const struct libtrace_packet_t *packet UNUSED) {
820        return TRACE_TYPE_LEGACY_POS;
821}
822
823static void *legacyatm_get_link(const struct libtrace_packet_t *packet) {
824        return (void *)packet->payload;
825}
826
827static libtrace_linktype_t legacyatm_get_link_type(const struct libtrace_packet_t *packet UNUSED) {
828        return TRACE_TYPE_LEGACY_ATM;
829}
830
831static void *legacyeth_get_link(const struct libtrace_packet_t *packet) {
832        return (void *)packet->payload;
833}
834
835static libtrace_linktype_t legacyeth_get_link_type(const struct libtrace_packet_t *packet UNUSED) {
836        return TRACE_TYPE_LEGACY_ETH;
837}
838
839
840
841static void *erf_get_link(const struct libtrace_packet_t *packet) {
842        return (void *)packet->payload;
843}
844
845static libtrace_linktype_t erf_get_link_type(const struct libtrace_packet_t *packet) {
846        dag_record_t *erfptr = 0;
847        erfptr = (dag_record_t *)packet->header;
848        switch (erfptr->type) {
849                case TYPE_LEGACY:       return TRACE_TYPE_LEGACY;
850                case TYPE_ETH:          return TRACE_TYPE_ETH;
851                case TYPE_ATM:          return TRACE_TYPE_ATM;
852                default: 
853                               fprintf(stderr,"Unknown erf type %02x\n",erfptr->type);
854                               assert(0);
855        }
856        return erfptr->type;
857}
858
859static int8_t erf_get_direction(const struct libtrace_packet_t *packet) {
860        dag_record_t *erfptr = 0;
861        erfptr = (dag_record_t *)packet->header;
862        return erfptr->flags.iface;
863}
864
865static int8_t erf_set_direction(const struct libtrace_packet_t *packet, int8_t direction) {
866        dag_record_t *erfptr = 0;
867        erfptr = (dag_record_t *)packet->header;
868        erfptr->flags.iface = direction;
869        return erfptr->flags.iface;
870}
871
872static uint64_t erf_get_erf_timestamp(const struct libtrace_packet_t *packet) {
873        dag_record_t *erfptr = 0;
874        erfptr = (dag_record_t *)packet->header;
875        return erfptr->ts;
876}
877
878static int legacy_get_capture_length(const struct libtrace_packet_t *packet __attribute__((unused))) {
879        return 64;
880}
881
882static int legacypos_get_wire_length(const struct libtrace_packet_t *packet) {
883        legacy_pos_t *lpos = (legacy_pos_t *)packet->header;
884        return ntohs(lpos->wlen);
885}
886
887static int legacyatm_get_wire_length(const struct libtrace_packet_t *packet UNUSED) {
888        return 53;
889}
890
891static int legacyeth_get_wire_length(const struct libtrace_packet_t *packet) {
892        legacy_ether_t *leth = (legacy_ether_t *)packet->header;
893        return ntohs(leth->wlen);
894}
895static int erf_get_capture_length(const struct libtrace_packet_t *packet) {
896        dag_record_t *erfptr = 0;
897        erfptr = (dag_record_t *)packet->header;
898        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
899}
900
901static int erf_get_wire_length(const struct libtrace_packet_t *packet) {
902        dag_record_t *erfptr = 0;
903        erfptr = (dag_record_t *)packet->header;
904        return ntohs(erfptr->wlen);
905}
906
907static size_t erf_set_capture_length(struct libtrace_packet_t *packet, size_t size) {
908        dag_record_t *erfptr = 0;
909        assert(packet);
910        if((size + erf_get_framing_length(packet)) > packet->size) {
911                // can't make a packet larger
912                return (packet->size - erf_get_framing_length(packet));
913        }
914        erfptr = (dag_record_t *)packet->header;
915        erfptr->rlen = htons(size + erf_get_framing_length(packet));
916        packet->size = size + erf_get_framing_length(packet);
917        return packet->size;
918}
919
920static int rtclient_get_fd(const struct libtrace_packet_t *packet) {
921        return packet->trace->format_data->input.fd;
922}
923
924static int erf_get_fd(const struct libtrace_packet_t *packet) {
925        return packet->trace->format_data->input.fd;
926}
927
928#if HAVE_DAG
929static void dag_help() {
930        printf("dag format module: $Revision$\n");
931        printf("Supported input URIs:\n");
932        printf("\tdag:/dev/dagn\n");
933        printf("\n");
934        printf("\te.g.: dag:/dev/dag0\n");
935        printf("\n");
936        printf("Supported output URIs:\n");
937        printf("\tnone\n");
938        printf("\n");
939}
940#endif
941
942static void legacypos_help() {
943        printf("legacypos format module: $Revision$\n");
944        printf("Supported input URIs:\n");
945        printf("\tlegacypos:/path/to/file\t(uncompressed)\n");
946        printf("\tlegacypos:/path/to/file.gz\t(gzip-compressed)\n");
947        printf("\tlegacypos:-\t(stdin, either compressed or not)\n");
948        printf("\n");
949        printf("\te.g.: legacypos:/tmp/trace.gz\n");
950        printf("\n");
951}
952
953static void legacyatm_help() {
954        printf("legacyatm format module: $Revision$\n");
955        printf("Supported input URIs:\n");
956        printf("\tlegacyatm:/path/to/file\t(uncompressed)\n");
957        printf("\tlegacyatm:/path/to/file.gz\t(gzip-compressed)\n");
958        printf("\tlegacyatm:-\t(stdin, either compressed or not)\n");
959        printf("\n");
960        printf("\te.g.: legacyatm:/tmp/trace.gz\n");
961        printf("\n");
962}
963
964static void legacyeth_help() {
965        printf("legacyeth format module: $Revision$\n");
966        printf("Supported input URIs:\n");
967        printf("\tlegacyeth:/path/to/file\t(uncompressed)\n");
968        printf("\tlegacyeth:/path/to/file.gz\t(gzip-compressed)\n");
969        printf("\tlegacyeth:-\t(stdin, either compressed or not)\n");
970        printf("\n");
971        printf("\te.g.: legacyeth:/tmp/trace.gz\n");
972        printf("\n");
973}
974
975static void erf_help() {
976        printf("erf format module: $Revision$\n");
977        printf("Supported input URIs:\n");
978        printf("\terf:/path/to/file\t(uncompressed)\n");
979        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
980        printf("\terf:-\t(stdin, either compressed or not)\n");
981        printf("\terf:/path/to/socket\n");
982        printf("\n");
983        printf("\te.g.: erf:/tmp/trace\n");
984        printf("\n");
985        printf("Supported output URIs:\n");
986        printf("\terf:path/to/file\t(uncompressed)\n");
987        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
988        printf("\terf:-\t(stdout, either compressed or not)\n");
989        printf("\n");
990        printf("\te.g.: erf:/tmp/trace\n");
991        printf("\n");
992        printf("Supported output options:\n");
993        printf("\t-z\tSpecify the gzip compression, ranging from 0 (uncompressed) to 9 - defaults to 1\n");
994        printf("\n");
995
996       
997}
998
999static void rtclient_help() {
1000        printf("rtclient format module\n");
1001        printf("Supported input URIs:\n");
1002        printf("\trtclient:hostname:port\n");
1003        printf("\trtclient:hostname (connects on default port)\n");
1004        printf("\n");
1005        printf("\te.g.: rtclient:localhost\n");
1006        printf("\te.g.: rtclient:localhost:32500\n");
1007        printf("\n");
1008        printf("Supported output URIs:\n");
1009        printf("\trtclient: \t(will output on default port on all available IP addresses) \n");
1010        printf("\trtclient:hostname:port\n");
1011        printf("\trtclient:port\n");
1012        printf("\n");
1013        printf("\te.g.: rtclient:32500\n");
1014        printf("\te.g.: rtclient:\n");
1015        printf("\n");
1016
1017}
1018
1019static struct libtrace_format_t legacyatm = {
1020        "legacyatm",
1021        "$Id$",
1022        "legacyatm",
1023        erf_init_input,                 /* init_input */       
1024        NULL,                           /* init_output */
1025        NULL,                           /* config_output */
1026        erf_fin_input,                  /* fin_input */
1027        NULL,                           /* fin_output */
1028        legacy_read_packet,             /* read_packet */
1029        NULL,                           /* write_packet */
1030        legacyatm_get_link,             /* get_link */
1031        legacyatm_get_link_type,        /* get_link_type */
1032        NULL,                           /* get_direction */
1033        NULL,                           /* set_direction */
1034        erf_get_erf_timestamp,          /* get_erf_timestamp */
1035        NULL,                           /* get_timeval */
1036        NULL,                           /* get_seconds */
1037        legacy_get_capture_length,      /* get_capture_length */
1038        legacyatm_get_wire_length,      /* get_wire_length */
1039        legacyatm_get_framing_length,   /* get_framing_length */
1040        NULL,                           /* set_capture_length */
1041        NULL,                           /* get_fd */
1042        trace_event_trace,              /* trace_event */
1043        legacyatm_help                  /* help */
1044};
1045
1046static struct libtrace_format_t legacyeth = {
1047        "legacyeth",
1048        "$Id$",
1049        "legacyeth",
1050        erf_init_input,                 /* init_input */       
1051        NULL,                           /* init_output */
1052        NULL,                           /* config_output */
1053        erf_fin_input,                  /* fin_input */
1054        NULL,                           /* fin_output */
1055        legacy_read_packet,             /* read_packet */
1056        NULL,                           /* write_packet */
1057        legacyeth_get_link,             /* get_link */
1058        legacyeth_get_link_type,        /* get_link_type */
1059        NULL,                           /* get_direction */
1060        NULL,                           /* set_direction */
1061        erf_get_erf_timestamp,          /* get_erf_timestamp */
1062        NULL,                           /* get_timeval */
1063        NULL,                           /* get_seconds */
1064        legacy_get_capture_length,      /* get_capture_length */
1065        legacyeth_get_wire_length,      /* get_wire_length */
1066        legacyeth_get_framing_length,   /* get_framing_length */
1067        NULL,                           /* set_capture_length */
1068        NULL,                           /* get_fd */
1069        trace_event_trace,              /* trace_event */
1070        legacyeth_help                  /* help */
1071};
1072
1073static struct libtrace_format_t legacypos = {
1074        "legacypos",
1075        "$Id$",
1076        "legacypos",
1077        erf_init_input,                 /* init_input */       
1078        NULL,                           /* init_output */
1079        NULL,                           /* config_output */
1080        erf_fin_input,                  /* fin_input */
1081        NULL,                           /* fin_output */
1082        legacy_read_packet,             /* read_packet */
1083        NULL,                           /* write_packet */
1084        legacypos_get_link,             /* get_link */
1085        legacypos_get_link_type,        /* get_link_type */
1086        NULL,                           /* get_direction */
1087        NULL,                           /* set_direction */
1088        erf_get_erf_timestamp,          /* get_erf_timestamp */
1089        NULL,                           /* get_timeval */
1090        NULL,                           /* get_seconds */
1091        legacy_get_capture_length,      /* get_capture_length */
1092        legacypos_get_wire_length,      /* get_wire_length */
1093        legacypos_get_framing_length,   /* get_framing_length */
1094        NULL,                           /* set_capture_length */
1095        NULL,                           /* get_fd */
1096        trace_event_trace,              /* trace_event */
1097        legacypos_help                  /* help */
1098};
1099
1100       
1101static struct libtrace_format_t erf = {
1102        "erf",
1103        "$Id$",
1104        "erf",
1105        erf_init_input,                 /* init_input */       
1106        erf_init_output,                /* init_output */
1107        erf_config_output,              /* config_output */
1108        erf_fin_input,                  /* fin_input */
1109        erf_fin_output,                 /* fin_output */
1110        erf_read_packet,                /* read_packet */
1111        erf_write_packet,               /* write_packet */
1112        erf_get_link,                   /* get_link */
1113        erf_get_link_type,              /* get_link_type */
1114        erf_get_direction,              /* get_direction */
1115        erf_set_direction,              /* set_direction */
1116        erf_get_erf_timestamp,          /* get_erf_timestamp */
1117        NULL,                           /* get_timeval */
1118        NULL,                           /* get_seconds */
1119        erf_get_capture_length,         /* get_capture_length */
1120        erf_get_wire_length,            /* get_wire_length */
1121        erf_get_framing_length,         /* get_framing_length */
1122        erf_set_capture_length,         /* set_capture_length */
1123        erf_get_fd,                     /* get_fd */
1124        trace_event_trace,              /* trace_event */
1125        erf_help                        /* help */
1126};
1127
1128#ifdef HAVE_DAG
1129static struct libtrace_format_t dag = {
1130        "dag",
1131        "$Id$",
1132        "erf",
1133        dag_init_input,                 /* init_input */       
1134        NULL,                           /* init_output */
1135        NULL,                           /* config_output */
1136        dag_fin_input,                  /* fin_input */
1137        NULL,                           /* fin_output */
1138        dag_read_packet,                /* read_packet */
1139        NULL,                           /* write_packet */
1140        erf_get_link,                   /* get_link */
1141        erf_get_link_type,              /* get_link_type */
1142        erf_get_direction,              /* get_direction */
1143        erf_set_direction,              /* set_direction */
1144        erf_get_erf_timestamp,          /* get_erf_timestamp */
1145        NULL,                           /* get_timeval */
1146        NULL,                           /* get_seconds */
1147        erf_get_capture_length,         /* get_capture_length */
1148        erf_get_wire_length,            /* get_wire_length */
1149        erf_get_framing_length,         /* get_framing_length */
1150        erf_set_capture_length,         /* set_capture_length */
1151        NULL,                           /* get_fd */
1152        trace_event_trace,              /* trace_event */
1153        dag_help                        /* help */
1154};
1155#endif
1156
1157static struct libtrace_format_t rtclient = {
1158        "rtclient",
1159        "$Id$",
1160        "erf",
1161        rtclient_init_input,            /* init_input */       
1162        NULL,                           /* init_output */
1163        NULL,                           /* config_output */
1164        rtclient_fin_input,             /* fin_input */
1165        NULL,                           /* fin_output */
1166        rtclient_read_packet,           /* read_packet */
1167        NULL,                           /* write_packet */
1168        erf_get_link,                   /* get_link */
1169        erf_get_link_type,              /* get_link_type */
1170        erf_get_direction,              /* get_direction */
1171        erf_set_direction,              /* set_direction */
1172        erf_get_erf_timestamp,          /* get_erf_timestamp */
1173        NULL,                           /* get_timeval */
1174        NULL,                           /* get_seconds */
1175        erf_get_capture_length,         /* get_capture_length */
1176        erf_get_wire_length,            /* get_wire_length */
1177        erf_get_framing_length,         /* get_framing_length */
1178        erf_set_capture_length,         /* set_capture_length */
1179        rtclient_get_fd,                /* get_fd */
1180        trace_event_device,             /* trace_event */
1181        rtclient_help                   /* help */
1182};
1183
1184void __attribute__((constructor)) erf_constructor() {
1185        register_format(&erf);
1186#ifdef HAVE_DAG
1187        register_format(&dag);
1188#endif
1189        register_format(&rtclient);
1190        register_format(&legacypos);
1191        register_format(&legacyeth);
1192        register_format(&legacyatm);
1193}
Note: See TracBrowser for help on using the repository browser.