source: lib/format_erf.c @ 92a37b0

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

DAG 2.5 includes a function for getting the next record so let's use that instead of doing a lot of arithmetic with various offsets.
Fixed bug where trace_event_dag was returning an incorrect event type in certain situations.
We now only call one of dag_detach_stream and dag_stop_stream to prevent memory corruption.

  • Property mode set to 100644
File size: 25.8 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                        return -1;
204                case TRACE_OPTION_PROMISC:
205                        /* DAG already operates in a promisc fashion */
206                        return -1;
207                case TRACE_OPTION_FILTER:
208                        return -1;
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        /*
411        if (dag_detach_stream(INPUT.fd, DAG.dagstream) < 0) {
412                trace_set_err(libtrace, errno, "Could not detach DAG stream");
413                return -1;
414        }
415        */
416#endif
417        return 0; /* success */
418}
419
420static int dag_fin_input(libtrace_t *libtrace) {
421        /* dag pause input implicitly called to cleanup before this */
422       
423        dag_close(INPUT.fd);
424        if (DUCK.dummy_duck)
425                trace_destroy_dead(DUCK.dummy_duck);
426        free(libtrace->format_data);
427        return 0; /* success */
428}
429#endif
430
431static int erf_fin_input(libtrace_t *libtrace) {
432        if (INPUT.file)
433                libtrace_io_close(INPUT.file);
434        free(libtrace->format_data);
435        return 0;
436}
437
438static int erf_fin_output(libtrace_out_t *libtrace) {
439        libtrace_io_close(OUTPUT.file);
440        free(libtrace->format_data);
441        return 0;
442}
443 
444#ifdef HAVE_DAG
445#ifdef DAG_VERSION_2_4
446static int dag_get_duckinfo(libtrace_t *libtrace, 
447                                libtrace_packet_t *packet) {
448        dag_inf lt_dag_inf;
449       
450        if (packet->buf_control == TRACE_CTRL_EXTERNAL || 
451                        !packet->buffer) {
452                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
453                packet->buf_control = TRACE_CTRL_PACKET;
454                if (!packet->buffer) {
455                        trace_set_err(libtrace, errno,
456                                        "Cannot allocate packet buffer");
457                        return -1;
458                }
459        }
460       
461        packet->header = 0;
462        packet->payload = packet->buffer;
463       
464        if ((ioctl(INPUT.fd, DAG_IOINF, &lt_dag_inf) < 0)) {
465                trace_set_err(libtrace, errno,
466                                "Error using DAG_IOINF");
467                return -1;
468        }
469        if (!IsDUCK(&lt_dag_inf)) {
470                printf("WARNING: %s does not have modern clock support - No DUCK information will be gathered\n", libtrace->uridata);
471                return 0;
472        }
473
474        if ((ioctl(INPUT.fd, DAG_IOGETDUCK, (duck_inf *)packet->payload) 
475                                < 0)) {
476                trace_set_err(libtrace, errno, "Error using DAG_IOGETDUCK");
477                return -1;
478        }
479
480        packet->type = TRACE_RT_DUCK_2_4;
481        if (!DUCK.dummy_duck) 
482                DUCK.dummy_duck = trace_create_dead("duck:dummy");
483        packet->trace = DUCK.dummy_duck;
484        return sizeof(duck_inf);
485}       
486#else
487static int dag_get_duckinfo(libtrace_t *libtrace, 
488                                libtrace_packet_t *packet) {
489        daginf_t lt_dag_inf;
490       
491        if (packet->buf_control == TRACE_CTRL_EXTERNAL || 
492                        !packet->buffer) {
493                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
494                packet->buf_control = TRACE_CTRL_PACKET;
495                if (!packet->buffer) {
496                        trace_set_err(libtrace, errno,
497                                        "Cannot allocate packet buffer");
498                        return -1;
499                }
500        }
501       
502        packet->header = 0;
503        packet->payload = packet->buffer;
504       
505        /* No need to check if we can get DUCK or not - we're modern
506         * enough */
507        if ((ioctl(INPUT.fd, DAGIOCDUCK, (duckinf_t *)packet->payload) 
508                                < 0)) {
509                trace_set_err(libtrace, errno, "Error using DAGIOCDUCK");
510                return -1;
511        }
512
513        packet->type = TRACE_RT_DUCK_2_5;
514        if (!DUCK.dummy_duck) 
515                DUCK.dummy_duck = trace_create_dead("rt:localhost:3434");
516        packet->trace = DUCK.dummy_duck;       
517        return sizeof(duckinf_t);
518}       
519#endif
520
521static int dag_read(libtrace_t *libtrace, int block_flag) {
522
523        if (DAG.diff != 0) 
524                return DAG.diff;
525
526        DAG.bottom = DAG.top;
527
528        DAG.top = dag_offset(
529                        INPUT.fd,
530                        &(DAG.bottom),
531                        block_flag);
532
533        DAG.diff = DAG.top - DAG.bottom;
534
535        DAG.offset = 0;
536        return DAG.diff;
537}
538
539/* FIXME: dag_read_packet shouldn't update the pointers, dag_fin_packet
540 * should do that.
541 */
542static int dag_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
543        int numbytes;
544        int size;
545        struct timeval tv;
546        dag_record_t *erfptr;
547        char *next_record = NULL;       
548
549        if (DUCK.last_pkt - DUCK.last_duck > DUCK.duck_freq && 
550                        DUCK.duck_freq != 0) {
551                size = dag_get_duckinfo(libtrace, packet);
552                DUCK.last_duck = DUCK.last_pkt;
553                if (size != 0) {
554                        return size;
555                }
556                /* No DUCK support, so don't waste our time anymore */
557                DUCK.duck_freq = 0;
558        }
559       
560        if (packet->buf_control == TRACE_CTRL_PACKET) {
561                packet->buf_control = TRACE_CTRL_EXTERNAL;
562                free(packet->buffer);
563                packet->buffer = 0;
564        }
565       
566        packet->type = TRACE_RT_DATA_ERF;
567#ifdef DAG_VERSION_2_4
568        if ((numbytes = dag_read(libtrace,0)) < 0) 
569                return numbytes;
570        assert(numbytes>0);
571
572        /*DAG always gives us whole packets */
573        erfptr = (dag_record_t *) ((char *)DAG.buf + 
574                        (DAG.bottom + DAG.offset));
575#else
576        next_record = (char *)dag_rx_stream_next_record(INPUT.fd, 0);
577        erfptr = (dag_record_t *)next_record;
578#endif
579        size = ntohs(erfptr->rlen);
580        assert( size >= dag_record_size );
581        assert( size < LIBTRACE_PACKET_BUFSIZE);
582       
583        packet->buffer = erfptr;
584        packet->header = erfptr;
585        if (((dag_record_t *)packet->buffer)->flags.rxerror == 1) {
586                /* rxerror means the payload is corrupt - drop it
587                 * by tweaking rlen */
588                packet->payload = NULL;
589                erfptr->rlen = htons(erf_get_framing_length(packet));
590        } else {
591                packet->payload = (char*)packet->buffer
592                        + erf_get_framing_length(packet);
593        }
594
595#ifdef DAG_VERSION_2_4
596        DAG.offset += size;
597        DAG.diff -= size;
598#endif
599        tv = trace_get_timeval(packet);
600        DUCK.last_pkt = tv.tv_sec;
601       
602        return packet->payload ? size : erf_get_framing_length(packet);
603}
604       
605static int dag_start_input(libtrace_t *libtrace) {
606#ifdef DAG_VERSION_2_4
607        if(dag_start(INPUT.fd) < 0) {
608                trace_set_err(libtrace,errno,"Cannot start DAG %s",
609                                libtrace->uridata);
610                return -1;
611        }
612#else
613        if (dag_attach_stream(INPUT.fd, DAG.dagstream, 0, 0) < 0) {
614                trace_set_err(libtrace, errno, "Cannot attach DAG stream");
615                return -1;
616        }
617        if (dag_start_stream(INPUT.fd, DAG.dagstream) < 0) {
618                trace_set_err(libtrace, errno, "Cannot start DAG stream");
619                return -1;
620        }
621#endif
622        /* dags appear to have a bug where if you call dag_start after
623         * calling dag_stop, and at least one packet has arrived, bad things
624         * happen.  flush the memory hole
625         */
626        while(dag_read(libtrace,DAGF_NONBLOCK)!=0)
627                DAG.diff=0;
628        return 0;
629}
630#endif
631
632static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
633        int numbytes;
634        unsigned int size;
635        void *buffer2 = packet->buffer;
636        unsigned int rlen;
637
638        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
639                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
640                packet->buf_control = TRACE_CTRL_PACKET;
641                if (!packet->buffer) {
642                        trace_set_err(libtrace, errno, 
643                                        "Cannot allocate memory");
644                        return -1;
645                }
646        }
647
648       
649       
650        packet->header = packet->buffer;
651        packet->type = TRACE_RT_DATA_ERF;
652
653        if ((numbytes=libtrace_io_read(INPUT.file,
654                                        packet->buffer,
655                                        dag_record_size)) == -1) {
656                trace_set_err(libtrace,errno,"read(%s)",
657                                libtrace->uridata);
658                return -1;
659        }
660        /* EOF */
661        if (numbytes == 0) {
662                return 0;
663        }
664
665        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
666        buffer2 = (char*)packet->buffer + dag_record_size;
667        size = rlen - dag_record_size;
668
669        assert(size < LIBTRACE_PACKET_BUFSIZE);
670
671        /* Unknown/corrupt */
672        assert(((dag_record_t *)packet->buffer)->type < 10);
673       
674        /* read in the rest of the packet */
675        if ((numbytes=libtrace_io_read(INPUT.file,
676                                        buffer2,
677                                        size)) != (int)size) {
678                if (numbytes==-1) {
679                        trace_set_err(libtrace,errno, "read(%s)", libtrace->uridata);
680                        return -1;
681                }
682                trace_set_err(libtrace,EIO,"Truncated packet (wanted %d, got %d)", size, numbytes);
683                /* Failed to read the full packet?  must be EOF */
684                return -1;
685        }
686        if (((dag_record_t *)packet->buffer)->flags.rxerror == 1) {
687                packet->payload = NULL;
688        } else {
689                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
690        }
691        return rlen;
692}
693
694static int erf_dump_packet(libtrace_out_t *libtrace,
695                dag_record_t *erfptr, unsigned int pad, void *buffer) {
696        int numbytes = 0;
697        int size;
698
699        if ((numbytes = 
700                libtrace_io_write(OUTPUT.file, erfptr, dag_record_size + pad)) 
701                        != (int)dag_record_size+pad) {
702                trace_set_err_out(libtrace,errno,
703                                "write(%s)",libtrace->uridata);
704                return -1;
705        }
706
707        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
708        numbytes=libtrace_io_write(OUTPUT.file, buffer, size);
709        if (numbytes != size) {
710                trace_set_err_out(libtrace,errno,
711                                "write(%s)",libtrace->uridata);
712                return -1;
713        }
714        return numbytes + pad + dag_record_size;
715}
716
717static int erf_start_output(libtrace_out_t *libtrace)
718{
719        OUTPUT.file = trace_open_file_out(libtrace,
720                        OPTIONS.erf.level,
721                        OPTIONS.erf.fileflag);
722        if (!OUTPUT.file) {
723                return -1;
724        }
725        return 0;
726}
727
728static bool find_compatible_linktype(libtrace_out_t *libtrace,
729                                libtrace_packet_t *packet)
730{
731        /* Keep trying to simplify the packet until we can find
732         * something we can do with it */
733        do {
734                char type=libtrace_to_erf_type(trace_get_link_type(packet));
735
736                /* Success */
737                if (type != (char)-1)
738                        return true;
739
740                if (!demote_packet(packet)) {
741                        trace_set_err_out(libtrace,
742                                        TRACE_ERR_NO_CONVERSION,
743                                        "No erf type for packet (%i)",
744                                        trace_get_link_type(packet));
745                        return false;
746                }
747
748        } while(1);
749
750        return true;
751}
752               
753static int erf_write_packet(libtrace_out_t *libtrace, 
754                libtrace_packet_t *packet) 
755{
756        int numbytes = 0;
757        int pad = 0;
758        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
759        void *payload = packet->payload;
760
761        assert(OUTPUT.file);
762
763        if (!packet->header) {
764                /*trace_set_err_output(libtrace, TRACE_ERR_BAD_PACKET,
765                                "Packet has no header - probably an RT packet");
766                */
767                return -1;
768        }
769       
770        pad = erf_get_padding(packet);
771
772        /* If we've had an rxerror, we have no payload to write - fix
773         * rlen to be the correct length
774         */
775        /* I Think this is bogus, we should somehow figure out
776         * a way to write out the payload even if it is gibberish -- Perry */
777        if (payload == NULL) {
778                dag_hdr->rlen = htons(dag_record_size + pad);
779               
780        } 
781       
782        if (packet->trace->format == &erf 
783#ifdef HAVE_DAG
784                        || packet->trace->format == &dag
785#endif
786                        ) {
787                numbytes = erf_dump_packet(libtrace,
788                                (dag_record_t *)packet->header,
789                                pad,
790                                payload
791                                );
792        } else {
793                dag_record_t erfhdr;
794                /* convert format - build up a new erf header */
795                /* Timestamp */
796                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
797
798                /* Flags. Can't do this */
799                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
800                if (trace_get_direction(packet)!=~0U)
801                        erfhdr.flags.iface = trace_get_direction(packet);
802
803                if (!find_compatible_linktype(libtrace,packet))
804                        return -1;
805
806                payload=packet->payload;
807                pad = erf_get_padding(packet);
808
809                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
810
811                /* Packet length (rlen includes format overhead) */
812                assert(trace_get_capture_length(packet)>0 
813                                && trace_get_capture_length(packet)<=65536);
814                assert(erf_get_framing_length(packet)>0 
815                                && trace_get_framing_length(packet)<=65536);
816                assert(
817                        trace_get_capture_length(packet)+erf_get_framing_length(packet)>0
818                      &&trace_get_capture_length(packet)+erf_get_framing_length(packet)<=65536);
819                erfhdr.rlen = htons(trace_get_capture_length(packet) 
820                        + erf_get_framing_length(packet));
821                /* loss counter. Can't do this */
822                erfhdr.lctr = 0;
823                /* Wire length, does not include padding! */
824                erfhdr.wlen = htons(trace_get_wire_length(packet));
825
826                /* Write it out */
827                numbytes = erf_dump_packet(libtrace,
828                                &erfhdr,
829                                pad,
830                                payload);
831        }
832        return numbytes;
833}
834
835static libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
836        dag_record_t *erfptr = 0;
837        erfptr = (dag_record_t *)packet->header;
838        return erf_type_to_libtrace(erfptr->type);
839}
840
841static libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
842        dag_record_t *erfptr = 0;
843        erfptr = (dag_record_t *)packet->header;
844        return erfptr->flags.iface;
845}
846
847static libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
848        dag_record_t *erfptr = 0;
849        erfptr = (dag_record_t *)packet->header;
850        erfptr->flags.iface = direction;
851        return erfptr->flags.iface;
852}
853
854static uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
855        dag_record_t *erfptr = 0;
856        erfptr = (dag_record_t *)packet->header;
857        return bswap_le_to_host64(erfptr->ts);
858}
859
860static int erf_get_capture_length(const libtrace_packet_t *packet) {
861        dag_record_t *erfptr = 0;
862        int caplen;
863        if (packet->payload == NULL)
864                return 0; 
865       
866        erfptr = (dag_record_t *)packet->header;
867        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
868        if (ntohs(erfptr->wlen) < caplen)
869                return ntohs(erfptr->wlen);
870
871        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
872}
873
874static int erf_get_wire_length(const libtrace_packet_t *packet) {
875        dag_record_t *erfptr = 0;
876        erfptr = (dag_record_t *)packet->header;
877        return ntohs(erfptr->wlen);
878}
879
880static size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
881        dag_record_t *erfptr = 0;
882        assert(packet);
883        if(size  > trace_get_capture_length(packet)) {
884                /* can't make a packet larger */
885                return trace_get_capture_length(packet);
886        }
887        erfptr = (dag_record_t *)packet->header;
888        erfptr->rlen = htons(size + erf_get_framing_length(packet));
889        return trace_get_capture_length(packet);
890}
891
892#ifdef HAVE_DAG
893static libtrace_eventobj_t trace_event_dag(libtrace_t *trace, 
894                                        libtrace_packet_t *packet) {
895        libtrace_eventobj_t event = {0,0,0.0,0};
896        int dag_fd;
897        int data;
898
899        if (trace->format->get_fd) {
900                dag_fd = trace->format->get_fd(trace);
901        } else {
902                dag_fd = 0;
903        }
904       
905        data = dag_read(trace, DAGF_NONBLOCK);
906
907        if (data > 0) {
908                event.size = dag_read_packet(trace,packet);
909                DATA(trace)->dag.diff -= event.size;
910                if (trace->filter) {
911                        if (trace_apply_filter(trace->filter, packet)) {
912                                event.type = TRACE_EVENT_PACKET;
913                        } else {
914                                event.type = TRACE_EVENT_SLEEP;
915                                event.seconds = 0.000001;
916                                return event;
917                        }
918                } else {
919                        event.type = TRACE_EVENT_PACKET;
920                }
921                if (trace->snaplen > 0) {
922                        trace_set_capture_length(packet, trace->snaplen);
923                }
924
925                return event;
926        }
927        event.type = TRACE_EVENT_SLEEP;
928        event.seconds = 0.0001;
929        return event;
930}
931#endif
932
933#ifdef HAVE_DAG
934static void dag_help(void) {
935        printf("dag format module: $Revision$\n");
936        printf("Supported input URIs:\n");
937        printf("\tdag:/dev/dagn\n");
938        printf("\n");
939        printf("\te.g.: dag:/dev/dag0\n");
940        printf("\n");
941        printf("Supported output URIs:\n");
942        printf("\tnone\n");
943        printf("\n");
944}
945#endif
946
947static void erf_help(void) {
948        printf("erf format module: $Revision$\n");
949        printf("Supported input URIs:\n");
950        printf("\terf:/path/to/file\t(uncompressed)\n");
951        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
952        printf("\terf:-\t(stdin, either compressed or not)\n");
953        printf("\terf:/path/to/socket\n");
954        printf("\n");
955        printf("\te.g.: erf:/tmp/trace\n");
956        printf("\n");
957        printf("Supported output URIs:\n");
958        printf("\terf:path/to/file\t(uncompressed)\n");
959        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
960        printf("\terf:-\t(stdout, either compressed or not)\n");
961        printf("\n");
962        printf("\te.g.: erf:/tmp/trace\n");
963        printf("\n");
964        printf("Supported output options:\n");
965        printf("\t-z\tSpecify the gzip compression, ranging from 0 (uncompressed) to 9 - defaults to 1\n");
966        printf("\n");
967
968       
969}
970
971static struct libtrace_format_t erf = {
972        "erf",
973        "$Id$",
974        TRACE_FORMAT_ERF,
975        erf_init_input,                 /* init_input */       
976        NULL,                           /* config_input */
977        erf_start_input,                /* start_input */
978        NULL,                           /* pause_input */
979        erf_init_output,                /* init_output */
980        erf_config_output,              /* config_output */
981        erf_start_output,               /* start_output */
982        erf_fin_input,                  /* fin_input */
983        erf_fin_output,                 /* fin_output */
984        erf_read_packet,                /* read_packet */
985        NULL,                           /* fin_packet */
986        erf_write_packet,               /* write_packet */
987        erf_get_link_type,              /* get_link_type */
988        erf_get_direction,              /* get_direction */
989        erf_set_direction,              /* set_direction */
990        erf_get_erf_timestamp,          /* get_erf_timestamp */
991        NULL,                           /* get_timeval */
992        NULL,                           /* get_seconds */
993        erf_seek_erf,                   /* seek_erf */
994        NULL,                           /* seek_timeval */
995        NULL,                           /* seek_seconds */
996        erf_get_capture_length,         /* get_capture_length */
997        erf_get_wire_length,            /* get_wire_length */
998        erf_get_framing_length,         /* get_framing_length */
999        erf_set_capture_length,         /* set_capture_length */
1000        NULL,                           /* get_fd */
1001        trace_event_trace,              /* trace_event */
1002        erf_help,                       /* help */
1003        NULL                            /* next pointer */
1004};
1005
1006#ifdef HAVE_DAG
1007static struct libtrace_format_t dag = {
1008        "dag",
1009        "$Id$",
1010        TRACE_FORMAT_ERF,
1011        dag_init_input,                 /* init_input */       
1012        dag_config_input,               /* config_input */
1013        dag_start_input,                /* start_input */
1014        dag_pause_input,                /* pause_input */
1015        NULL,                           /* init_output */
1016        NULL,                           /* config_output */
1017        NULL,                           /* start_output */
1018        dag_fin_input,                  /* fin_input */
1019        NULL,                           /* fin_output */
1020        dag_read_packet,                /* read_packet */
1021        NULL,                           /* fin_packet */
1022        NULL,                           /* write_packet */
1023        erf_get_link_type,              /* get_link_type */
1024        erf_get_direction,              /* get_direction */
1025        erf_set_direction,              /* set_direction */
1026        erf_get_erf_timestamp,          /* get_erf_timestamp */
1027        NULL,                           /* get_timeval */
1028        NULL,                           /* get_seconds */
1029        NULL,                           /* seek_erf */
1030        NULL,                           /* seek_timeval */
1031        NULL,                           /* seek_seconds */
1032        erf_get_capture_length,         /* get_capture_length */
1033        erf_get_wire_length,            /* get_wire_length */
1034        erf_get_framing_length,         /* get_framing_length */
1035        erf_set_capture_length,         /* set_capture_length */
1036        NULL,                           /* get_fd */
1037        trace_event_dag,                /* trace_event */
1038        dag_help,                       /* help */
1039        NULL                            /* next pointer */
1040};
1041#endif
1042
1043void erf_constructor(void) {
1044        register_format(&erf);
1045#ifdef HAVE_DAG
1046        register_format(&dag);
1047#endif
1048}
Note: See TracBrowser for help on using the repository browser.