source: lib/format_erf.c @ a605bbe

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

Ripout the old rtclient: code. The only implementation of a server was
within WAND which has been decomissioned and replaced with the newer rt:
protocol.

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