source: lib/format_erf.c @ 2725318

develop
Last change on this file since 2725318 was 2725318, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Cleanup some of the assertions

  • Property mode set to 100644
File size: 25.4 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26
27#define _GNU_SOURCE
28
29#include "config.h"
30#include "common.h"
31#include "libtrace.h"
32#include "libtrace_int.h"
33#include "format_helper.h"
34#include "format_erf.h"
35#include "wandio.h"
36
37#include <assert.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <stdio.h>
41#include <string.h>
42#include <stdlib.h>
43
44
45#ifdef WIN32
46#  include <io.h>
47#  include <share.h>
48#  define PATH_MAX _MAX_PATH
49#else
50#  include <netdb.h>
51#  ifndef PATH_MAX
52#       define PATH_MAX 4096
53#  endif
54#  include <sys/ioctl.h>
55#endif
56
57/* This format module deals with reading and writing ERF traces. ERF is the
58 * trace format developed by Endace for use by DAG hardware capture cards.
59 *
60 * ERF is not a live capture format.
61 *
62 */
63
64
65static struct libtrace_format_t erfformat;
66
67#define DATA(x) ((struct erf_format_data_t *)x->format_data)
68#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
69
70#define IN_OPTIONS DATA(libtrace)->options
71#define OUTPUT DATAOUT(libtrace)
72#define OUT_OPTIONS DATAOUT(libtrace)->options
73
74/* "Global" data that is stored for each ERF input trace */
75struct erf_format_data_t {
76       
77        /* Index used for seeking within a trace */
78        struct {
79                /* The index itself */
80                io_t *index;
81                /* The offset of the index */
82                off_t index_len;
83                /* Indicates the existence of an index */
84                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
85        } seek;
86
87        /* Number of packets that were dropped during the capture */
88        uint64_t drops;
89
90        /* Config options for the input trace */
91        struct {
92                /* Flag indicating whether the event API should replicate the
93                 * time gaps between each packet or return a PACKET event for
94                 * each packet */
95                int real_time;
96        } options;
97};
98
99/* "Global" data that is stored for each ERF output trace */
100struct erf_format_data_out_t {
101
102        /* Config options for the output trace */
103        struct {
104                /* Compression level for the output file */
105                int level;
106                /* Compression type */
107                int compress_type;
108                /* File flags used to open the file, e.g. O_CREATE */
109                int fileflag;
110        } options;
111
112        /* The output file itself */
113        iow_t *file;
114       
115};
116
117typedef struct erf_index_t {
118        uint64_t timestamp;
119        uint64_t offset; 
120} erf_index_t;
121
122/* Ethernet packets have a 2 byte padding before the packet
123 * so that the IP header is aligned on a 32 bit boundary.
124 */
125static inline int erf_get_padding(const libtrace_packet_t *packet)
126{
127        if (packet->trace->format->type==TRACE_FORMAT_ERF ||
128                        packet->trace->format->type == TRACE_FORMAT_NDAG ||
129                        packet->trace->format->type == TRACE_FORMAT_RAWERF ||
130                        packet->trace->format->type == TRACE_FORMAT_DPDK_NDAG) {
131                dag_record_t *erfptr = (dag_record_t *)packet->header;
132                switch((erfptr->type & 0x7f)) {
133                        case TYPE_ETH:
134                        case TYPE_COLOR_ETH:
135                        case TYPE_DSM_COLOR_ETH:
136                        case TYPE_COLOR_HASH_ETH:
137                                return 2;
138                        default:                return 0;
139                }
140        }
141        else {
142                switch(trace_get_link_type(packet)) {
143                        case TRACE_TYPE_ETH:    return 2;
144                        default:                return 0;
145                }
146        }
147}
148
149int erf_is_color_type(uint8_t erf_type)
150{
151        switch(erf_type & 0x7f) {
152                case TYPE_COLOR_HDLC_POS:
153                case TYPE_DSM_COLOR_HDLC_POS:
154                case TYPE_COLOR_ETH:
155                case TYPE_DSM_COLOR_ETH:
156                case TYPE_COLOR_HASH_POS:
157                case TYPE_COLOR_HASH_ETH:
158                        return 1;
159        }
160
161        return 0;
162}
163
164int erf_get_framing_length(const libtrace_packet_t *packet)
165{
166        uint16_t extsize = 0;
167        dag_record_t *erfptr = NULL;
168        uint64_t *exthdr = NULL;
169        uint8_t *firstbyte;
170
171        erfptr = (dag_record_t *)packet->header;
172        if ((erfptr->type & 0x80) == 0x80) {
173                /* Extension headers are present */
174                exthdr = (uint64_t *)((char *)packet->header + dag_record_size);
175                extsize += 8;
176
177                firstbyte = (uint8_t *)exthdr;
178                while ((*firstbyte & 0x80) == 0x80) {
179                        extsize += 8;
180                        exthdr ++;
181                        firstbyte = (uint8_t *)exthdr;
182                        assert(extsize <= ntohs(erfptr->rlen));
183                }
184        }
185        return dag_record_size + extsize + erf_get_padding(packet);
186}
187
188/* Attempts to determine whether a given trace file is using the ERF format
189 *
190 * Returns 1 if the trace is probably ERF, 0 otherwise
191 */
192static int erf_probe_magic(io_t *io)
193{
194        char buffer[4096];
195        int len;
196        dag_record_t *erf;
197        len = wandio_peek(io, buffer, sizeof(buffer));
198        if (len < (int)dag_record_size) {
199                return 0; /* False */
200        }
201        erf = (dag_record_t *) buffer;
202        /* If the record is too short */
203        if (ntohs(erf->rlen) < dag_record_size) {
204                return 0;
205        }
206        /* There aren't any erf traces before 1995-01-01 */
207        if (bswap_le_to_host64(erf->ts) < 0x2f0539b000000000ULL) {
208                return 0;
209        }
210        /* And not pcap! */
211        if (bswap_le_to_host64(erf->ts) >>32 == 0xa1b2c3d4) {
212                return 0;
213        }
214        /* And not the other pcap! */
215        if (bswap_le_to_host64(erf->ts) >>32 == 0xd4c3b2a1) {
216                return 0;
217        }
218        /* Is this a proper typed packet */
219        if ((erf->type & 0x7f) > ERF_TYPE_MAX) {
220                return 0;
221        }
222        /* We should put some more tests in here. */
223        /* Yeah, this is probably ERF */
224        return 1;
225}
226
227static int erf_init_input(libtrace_t *libtrace) {
228        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
229
230        if (!libtrace->format_data) {
231                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory erf_init_input()");
232                return -1;
233        }
234
235        IN_OPTIONS.real_time = 0;
236        DATA(libtrace)->drops = 0;
237
238        return 0; /* success */
239}
240
241static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
242                void *value) {
243
244        switch (option) {
245                case TRACE_OPTION_EVENT_REALTIME:
246                        IN_OPTIONS.real_time = *(int *)value;
247                        return 0;
248                case TRACE_OPTION_SNAPLEN:
249                case TRACE_OPTION_PROMISC:
250                case TRACE_OPTION_FILTER:
251                case TRACE_OPTION_META_FREQ:
252                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
253                                        "Unsupported option");
254                        return -1;
255                default:
256                        /* Unknown option */
257                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
258                                        "Unknown option");
259                        return -1;
260        }
261}
262
263static int erf_start_input(libtrace_t *libtrace) 
264{
265        if (libtrace->io)
266                return 0; /* Success -- already done. */
267
268        libtrace->io = trace_open_file(libtrace);
269
270        if (!libtrace->io)
271                return -1;
272
273        DATA(libtrace)->drops = 0;
274        return 0; /* success */
275}
276
277/* Raw ERF is a special case -- we want to force libwandio to treat the file
278 * as uncompressed so we can't just use trace_open_file() */
279static int rawerf_start_input(libtrace_t *libtrace)
280{
281        if (libtrace->io)
282                return 0; 
283
284        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
285
286        if (!libtrace->io) {
287                if (errno != 0) {
288                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
289                }
290                return -1;
291        }
292
293        DATA(libtrace)->drops = 0;
294
295        return 0; /* success */
296}
297
298/* Binary search through the index to find the closest point before
299 * the packet.  Consider in future having a btree index perhaps?
300 */
301static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
302{
303        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
304        size_t min_off = 0;
305        off_t current;
306        erf_index_t record;
307        do {
308                current=(max_off+min_off)>>2;
309
310                wandio_seek(DATA(libtrace)->seek.index,
311                                (int64_t)(current*sizeof(record)),
312                                SEEK_SET);
313                wandio_read(DATA(libtrace)->seek.index,
314                                &record,sizeof(record));
315                if (record.timestamp < erfts) {
316                        min_off=current;
317                }
318                if (record.timestamp > erfts) {
319                        max_off=current;
320                }
321                if (record.timestamp == erfts)
322                        break;
323        } while(min_off<max_off);
324
325        /* If we've passed it, seek backwards.  This loop shouldn't
326         * execute more than twice.
327         */
328        do {
329                wandio_seek(DATA(libtrace)->seek.index,
330                                (int64_t)(current*sizeof(record)),SEEK_SET);
331                wandio_read(DATA(libtrace)->seek.index,
332                                &record,sizeof(record));
333                current--;
334        } while(record.timestamp>erfts);
335
336        /* We've found our location in the trace, now use it. */
337        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
338
339        return 0; /* success */
340}
341
342/* There is no index.  Seek through the entire trace from the start, nice
343 * and slowly.
344 */
345static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
346{
347        if (libtrace->io) {
348                wandio_destroy(libtrace->io);
349        }
350        libtrace->io = trace_open_file(libtrace);
351        if (!libtrace->io)
352                return -1;
353        return 0;
354}
355
356/* Seek within an ERF trace based on an ERF timestamp */
357static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
358{
359        libtrace_packet_t *packet;
360        off_t off = 0;
361
362        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
363                char buffer[PATH_MAX];
364                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
365                DATA(libtrace)->seek.index=wandio_create(buffer);
366                if (DATA(libtrace)->seek.index) {
367                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
368                }
369                else {
370                        DATA(libtrace)->seek.exists=INDEX_NONE;
371                }
372        }
373
374        /* If theres an index, use it to find the nearest packet that isn't
375         * after the time we're looking for.  If there is no index we need
376         * to seek slowly through the trace from the beginning.  Sigh.
377         */
378        switch(DATA(libtrace)->seek.exists) {
379                case INDEX_EXISTS:
380                        erf_fast_seek_start(libtrace,erfts);
381                        break;
382                case INDEX_NONE:
383                        erf_slow_seek_start(libtrace,erfts);
384                        break;
385                case INDEX_UNKNOWN:
386                        assert(0);
387                        break;
388        }
389
390        /* Now seek forward looking for the correct timestamp */
391        packet=trace_create_packet();
392        do {
393                trace_read_packet(libtrace,packet);
394                if (trace_get_erf_timestamp(packet)==erfts)
395                        break;
396                off=wandio_tell(libtrace->io);
397        } while(trace_get_erf_timestamp(packet)<erfts);
398
399        wandio_seek(libtrace->io,off,SEEK_SET);
400
401        return 0;
402}
403
404static int erf_init_output(libtrace_out_t *libtrace) {
405        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
406
407        if (!libtrace->format_data) {
408                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory erf_init_output()");
409                return -1;
410        }
411
412        OUT_OPTIONS.level = 0;
413        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
414        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
415        OUTPUT->file = 0;
416
417        return 0;
418}
419
420static int erf_config_output(libtrace_out_t *libtrace, 
421                trace_option_output_t option, void *value) {
422
423        switch (option) {
424                case TRACE_OPTION_OUTPUT_COMPRESS:
425                        OUT_OPTIONS.level = *(int*)value;
426                        return 0;
427                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
428                        OUT_OPTIONS.compress_type = *(int*)value;
429                        return 0;
430                case TRACE_OPTION_OUTPUT_FILEFLAGS:
431                        OUT_OPTIONS.fileflag = *(int*)value;
432                        return 0;
433                default:
434                        /* Unknown option */
435                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
436                                        "Unknown option");
437                        return -1;
438        }
439}
440
441
442
443static int erf_fin_input(libtrace_t *libtrace) {
444        if (libtrace->io)
445                wandio_destroy(libtrace->io);
446        free(libtrace->format_data);
447        return 0;
448}
449
450static int erf_fin_output(libtrace_out_t *libtrace) {
451        if (OUTPUT->file)
452                wandio_wdestroy(OUTPUT->file);
453        free(libtrace->format_data);
454        return 0;
455}
456 
457static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
458                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
459       
460        dag_record_t *erfptr;
461
462        if (packet->buffer != buffer && 
463                packet->buf_control == TRACE_CTRL_PACKET) {
464                free(packet->buffer);
465        }
466
467        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
468                packet->buf_control = TRACE_CTRL_PACKET;
469        } else
470                packet->buf_control = TRACE_CTRL_EXTERNAL;
471       
472       
473        packet->type = rt_type;
474        packet->buffer = buffer;
475        packet->header = buffer;
476        erfptr = (dag_record_t *)packet->buffer;
477        if (erfptr->flags.rxerror == 1) {
478                packet->payload = NULL;
479        } else {
480                packet->payload = ((char*)packet->buffer) + trace_get_framing_length(packet);
481        }
482
483        assert(erfptr->rlen != 0);
484       
485        if (libtrace->format_data == NULL) {
486                /* Allocates the format_data structure */
487                if (erf_init_input(libtrace)) 
488                        return -1;
489        }
490
491        /* Check for loss */
492        if (erf_is_color_type(erfptr->type)) {
493                /* No idea how we get this yet */
494
495        } else if (erfptr->lctr) {
496                DATA(libtrace)->drops += ntohs(erfptr->lctr);
497        }
498
499        return 0;
500}
501
502static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
503        int numbytes;
504        unsigned int size;
505        void *buffer2 = packet->buffer;
506        unsigned int rlen;
507        uint32_t flags = 0;
508       
509       
510        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
511                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
512                if (!packet->buffer) {
513                        trace_set_err(libtrace, errno, 
514                                        "Cannot allocate memory");
515                        return -1;
516                }
517        }
518
519        flags |= TRACE_PREP_OWN_BUFFER; 
520       
521        if ((numbytes=wandio_read(libtrace->io,
522                                        packet->buffer,
523                                        (size_t)dag_record_size)) == -1) {
524                trace_set_err(libtrace,errno,"reading ERF file");
525                return -1;
526        }
527        /* EOF */
528        if (numbytes == 0) {
529                return 0;
530        }
531
532        if (numbytes < (int)dag_record_size) {
533                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header");
534                return -1;
535        }
536
537        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
538        buffer2 = (char*)packet->buffer + dag_record_size;
539        size = rlen - dag_record_size;
540
541        if (size >= LIBTRACE_PACKET_BUFSIZE) {
542                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
543                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
544                                size);
545                return -1;
546        }
547
548        /* Unknown/corrupt */
549        if ((((dag_record_t *)packet->buffer)->type & 0x7f) > ERF_TYPE_MAX) {
550                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
551                                "Corrupt or Unknown ERF type");
552                return -1;
553        }
554       
555        /* read in the rest of the packet */
556        if ((numbytes=wandio_read(libtrace->io,
557                                        buffer2,
558                                        (size_t)size)) != (int)size) {
559                if (numbytes==-1) {
560                        trace_set_err(libtrace,errno, "read(%s)", 
561                                        libtrace->uridata);
562                        return -1;
563                }
564                trace_set_err(libtrace,EIO,
565                                "Truncated packet (wanted %d, got %d)", 
566                                size, numbytes);
567                /* Failed to read the full packet?  must be EOF */
568                return -1;
569        }
570
571        if (numbytes < (int)size) {
572                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record");
573                return -1;
574        }
575       
576        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
577                                TRACE_RT_DATA_ERF, flags))
578                return -1;
579       
580        return rlen;
581}
582
583static int erf_dump_packet(libtrace_out_t *libtrace,
584                dag_record_t *erfptr, int framinglen, void *buffer,
585                int caplen) {
586        int numbytes = 0;
587
588        if (caplen + framinglen != ntohs(erfptr->rlen))
589                erfptr->rlen = htons(caplen + framinglen);
590
591        if ((numbytes = 
592                wandio_wwrite(OUTPUT->file, 
593                                erfptr,
594                                (size_t)(framinglen))) 
595                        != (int)(framinglen)) {
596                trace_set_err_out(libtrace,errno,
597                                "write(%s)",libtrace->uridata);
598                return -1;
599        }
600
601        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)caplen);
602        if (numbytes != caplen) {
603                trace_set_err_out(libtrace,errno,
604                                "write(%s)",libtrace->uridata);
605                return -1;
606        }
607        return numbytes + framinglen;
608}
609
610static int erf_flush_output(libtrace_out_t *libtrace) {
611        return wandio_wflush(OUTPUT->file);
612}
613
614static int erf_start_output(libtrace_out_t *libtrace)
615{
616        OUTPUT->file = trace_open_file_out(libtrace,
617                        OUT_OPTIONS.compress_type,
618                        OUT_OPTIONS.level,
619                        OUT_OPTIONS.fileflag);
620
621        if (!OUTPUT->file) {
622                return -1;
623        }
624        return 0;
625}
626
627static bool find_compatible_linktype(libtrace_out_t *libtrace,
628                                libtrace_packet_t *packet)
629{
630        /* Keep trying to simplify the packet until we can find
631         * something we can do with it */
632        do {
633                char type=libtrace_to_erf_type(trace_get_link_type(packet));
634
635                /* Success */
636                if (type != (char)-1)
637                        return true;
638
639                if (!demote_packet(packet)) {
640                        trace_set_err_out(libtrace,
641                                        TRACE_ERR_NO_CONVERSION,
642                                        "No erf type for packet (%i)",
643                                        trace_get_link_type(packet));
644                        return false;
645                }
646
647        } while(1);
648
649        return true;
650}
651               
652static int erf_write_packet(libtrace_out_t *libtrace, 
653                libtrace_packet_t *packet) 
654{
655        int numbytes = 0;
656        unsigned int pad = 0;
657        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
658        void *payload = packet->payload;
659
660        assert(OUTPUT->file);
661
662        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
663                return 0;
664
665        if (!packet->header) {
666                return -1;
667        }
668       
669        pad = erf_get_padding(packet);
670
671        /* If we've had an rxerror, we have no payload to write - fix
672         * rlen to be the correct length
673         */
674        /* I Think this is bogus, we should somehow figure out
675         * a way to write out the payload even if it is gibberish -- Perry */
676        if (payload == NULL) {
677                dag_hdr->rlen = htons(dag_record_size + pad);
678               
679        } 
680       
681        if (packet->type == TRACE_RT_DATA_ERF) {
682                        numbytes = erf_dump_packet(libtrace,
683                                (dag_record_t *)packet->header,
684                                trace_get_framing_length(packet),
685                                payload,
686                                trace_get_capture_length(packet)
687                                );
688        } else {
689                dag_record_t erfhdr;
690                int rlen;
691                int framing;
692                /* convert format - build up a new erf header */
693                /* Timestamp */
694                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
695
696                /* Flags. Can't do this */
697                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
698                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
699                        erfhdr.flags.iface = trace_get_direction(packet);
700
701                if (!find_compatible_linktype(libtrace,packet))
702                        return -1;
703
704                payload=packet->payload;
705                pad = erf_get_padding(packet);
706
707                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
708
709                /* Packet length (rlen includes format overhead) */
710                assert(trace_get_capture_length(packet)>0 
711                                && trace_get_capture_length(packet)<=65536);
712                assert(trace_get_framing_length(packet)<=65536);
713               
714                if (erfhdr.type == TYPE_ETH)
715                        framing = dag_record_size + 2;
716                else
717                        framing = dag_record_size;
718               
719                rlen = trace_get_capture_length(packet) + framing;
720                assert(rlen > 0 && rlen <= 65536);
721                erfhdr.rlen = htons(rlen);
722                /* loss counter. Can't do this */
723                erfhdr.lctr = 0;
724                /* Wire length, does not include padding! */
725                erfhdr.wlen = htons(trace_get_wire_length(packet));
726
727                /* Write it out */
728                numbytes = erf_dump_packet(libtrace,
729                                &erfhdr,
730                                framing,
731                                payload,
732                                trace_get_capture_length(packet));
733        }
734        return numbytes;
735}
736
737libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
738        dag_record_t *erfptr = 0;
739        erfptr = (dag_record_t *)packet->header;
740        uint8_t type = (erfptr->type & 0x7f);
741        if (type != TYPE_LEGACY) {
742                /* The top-most bit is now used to indicate the presence of
743                 * extension headers :/ */
744                return erf_type_to_libtrace(type);
745        }
746        else {
747                /* Sigh, lets start wildly guessing */
748                if (((char*)packet->payload)[4]==0x45)
749                        return TRACE_TYPE_PPP;
750                return ~0;
751        }
752}
753
754libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
755        dag_record_t *erfptr = 0;
756        erfptr = (dag_record_t *)packet->header;
757        return erfptr->flags.iface;
758}
759
760libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
761        dag_record_t *erfptr = 0;
762        erfptr = (dag_record_t *)packet->header;
763        erfptr->flags.iface = direction;
764        return erfptr->flags.iface;
765}
766
767uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
768        dag_record_t *erfptr = 0;
769        erfptr = (dag_record_t *)packet->header;
770        return bswap_le_to_host64(erfptr->ts);
771}
772
773int erf_get_capture_length(const libtrace_packet_t *packet) {
774        dag_record_t *erfptr = 0;
775        int caplen;
776        size_t framinglen;
777        uint16_t wlen, rlen;
778
779        if (packet->payload == NULL)
780                return 0;
781
782        erfptr = (dag_record_t *)packet->header;
783        framinglen = trace_get_framing_length(packet);
784        rlen = ntohs(erfptr->rlen);
785        wlen = ntohs(erfptr->wlen);
786
787        caplen = rlen - framinglen;
788        if (wlen < caplen)
789                return wlen;
790
791        return caplen;
792}
793
794int erf_get_wire_length(const libtrace_packet_t *packet) {
795        dag_record_t *erfptr = 0;
796        erfptr = (dag_record_t *)packet->header;
797
798        if ((erfptr->type & 0x7f) == TYPE_META)
799                return 0;
800
801        return ntohs(erfptr->wlen);
802}
803
804size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
805        dag_record_t *erfptr = 0;
806        uint16_t wlen;
807
808        assert(packet);
809        erfptr = (dag_record_t *)packet->header;
810
811        if(size > trace_get_capture_length(packet) || (erfptr->type & 0x7f) == TYPE_META) {
812                /* Can't make a packet larger */
813                return trace_get_capture_length(packet);
814        }
815
816        /* Reset cached capture length - otherwise we will both return the
817         * wrong value here and subsequent get_capture_length() calls will
818         * return the wrong value. */
819        packet->capture_length = -1;
820        erfptr->rlen = htons(size + trace_get_framing_length(packet));
821        wlen = ntohs(erfptr->wlen);
822
823        if (wlen < size) {
824                return wlen;
825        }
826
827        return size;
828}
829
830static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
831        struct libtrace_eventobj_t event = {0,0,0.0,0};
832       
833        /* If we are being told to replay packets as fast as possible, then
834         * we just need to read and return the next packet in the trace */
835        if (IN_OPTIONS.real_time) {
836                event.size = trace_read_packet(libtrace, packet);
837                if (event.size < 1)
838                        event.type = TRACE_EVENT_TERMINATE;
839                else
840                        event.type = TRACE_EVENT_PACKET;
841                return event;
842               
843        } else {
844                /* Otherwise, use the generic event function */
845                return trace_event_trace(libtrace, packet);
846        }
847       
848}
849
850static void erf_get_statistics(libtrace_t *trace, libtrace_stat_t *stat) {
851
852        if (trace->format_data) {
853                stat->dropped_valid = 1;
854                stat->dropped = DATA(trace)->drops;
855        }
856}
857
858static void erf_help(void) {
859        printf("erf format module: $Revision: 1752 $\n");
860        printf("Supported input URIs:\n");
861        printf("\terf:/path/to/file\t(uncompressed)\n");
862        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
863        printf("\terf:-\t(stdin, either compressed or not)\n");
864        printf("\terf:/path/to/socket\n");
865        printf("\n");
866        printf("\te.g.: erf:/tmp/trace\n");
867        printf("\n");
868        printf("Supported output URIs:\n");
869        printf("\terf:path/to/file\t(uncompressed)\n");
870        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
871        printf("\terf:-\t(stdout, either compressed or not)\n");
872        printf("\n");
873        printf("\te.g.: erf:/tmp/trace\n");
874        printf("\n");
875
876       
877}
878
879static struct libtrace_format_t erfformat = {
880        "erf",
881        "$Id$",
882        TRACE_FORMAT_ERF,
883        NULL,                           /* probe filename */
884        erf_probe_magic,                /* probe magic */
885        erf_init_input,                 /* init_input */       
886        erf_config_input,               /* config_input */
887        erf_start_input,                /* start_input */
888        NULL,                           /* pause_input */
889        erf_init_output,                /* init_output */
890        erf_config_output,              /* config_output */
891        erf_start_output,               /* start_output */
892        erf_fin_input,                  /* fin_input */
893        erf_fin_output,                 /* fin_output */
894        erf_read_packet,                /* read_packet */
895        erf_prepare_packet,             /* prepare_packet */
896        NULL,                           /* fin_packet */
897        erf_write_packet,               /* write_packet */
898        erf_flush_output,               /* flush_output */
899        erf_get_link_type,              /* get_link_type */
900        erf_get_direction,              /* get_direction */
901        erf_set_direction,              /* set_direction */
902        erf_get_erf_timestamp,          /* get_erf_timestamp */
903        NULL,                           /* get_timeval */
904        NULL,                           /* get_timespec */
905        NULL,                           /* get_seconds */
906        erf_seek_erf,                   /* seek_erf */
907        NULL,                           /* seek_timeval */
908        NULL,                           /* seek_seconds */
909        erf_get_capture_length,         /* get_capture_length */
910        erf_get_wire_length,            /* get_wire_length */
911        erf_get_framing_length,         /* get_framing_length */
912        erf_set_capture_length,         /* set_capture_length */
913        NULL,                           /* get_received_packets */
914        NULL,                           /* get_filtered_packets */
915        NULL,                           /* get_dropped_packets */
916        erf_get_statistics,             /* get_statistics */
917        NULL,                           /* get_fd */
918        erf_event,                      /* trace_event */
919        erf_help,                       /* help */
920        NULL,                           /* next pointer */
921        NON_PARALLEL(false)
922};
923
924static struct libtrace_format_t rawerfformat = {
925        "rawerf",
926        "$Id$",
927        TRACE_FORMAT_RAWERF,
928        NULL,                           /* probe filename */
929        NULL,           /* probe magic */
930        erf_init_input,                 /* init_input */       
931        erf_config_input,               /* config_input */
932        rawerf_start_input,             /* start_input */
933        NULL,                           /* pause_input */
934        erf_init_output,                /* init_output */
935        erf_config_output,              /* config_output */
936        erf_start_output,               /* start_output */
937        erf_fin_input,                  /* fin_input */
938        erf_fin_output,                 /* fin_output */
939        erf_read_packet,                /* read_packet */
940        erf_prepare_packet,             /* prepare_packet */
941        NULL,                           /* fin_packet */
942        erf_write_packet,               /* write_packet */
943        erf_flush_output,               /* flush_output */
944        erf_get_link_type,              /* get_link_type */
945        erf_get_direction,              /* get_direction */
946        erf_set_direction,              /* set_direction */
947        erf_get_erf_timestamp,          /* get_erf_timestamp */
948        NULL,                           /* get_timeval */
949        NULL,                           /* get_timespec */
950        NULL,                           /* get_seconds */
951        erf_seek_erf,                   /* seek_erf */
952        NULL,                           /* seek_timeval */
953        NULL,                           /* seek_seconds */
954        erf_get_capture_length,         /* get_capture_length */
955        erf_get_wire_length,            /* get_wire_length */
956        erf_get_framing_length,         /* get_framing_length */
957        erf_set_capture_length,         /* set_capture_length */
958        NULL,                           /* get_received_packets */
959        NULL,                           /* get_filtered_packets */
960        NULL,                           /* get_dropped_packets */
961        erf_get_statistics,             /* get_statistics */
962        NULL,                           /* get_fd */
963        erf_event,                      /* trace_event */
964        erf_help,                       /* help */
965        NULL,                           /* next pointer */
966        NON_PARALLEL(false)
967};
968
969
970
971void erf_constructor(void) {
972        register_format(&erfformat);
973        register_format(&rawerfformat);
974}
Note: See TracBrowser for help on using the repository browser.