source: lib/format_erf.c @ 78f750e

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

Added definition of rt protocol to libtrace.
Rtclients will now skip over packets that contain no useful message body
rt_protocol.h will be installed with other header files.

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