source: lib/format_erf.c @ 35e0869

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 35e0869 was 35e0869, checked in by Perry Lorier <perry@…>, 15 years ago

Fix signedness warning

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