source: lib/format_erf.c @ 803ea87

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

Removed rt_protocol entirely as it was becoming a real nuisance.
Critical rt_protocol components have been moved to libtrace.h

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