source: lib/format_erf.c @ a857389

cachetimestampsdevelopetsiliverc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since a857389 was a857389, checked in by Shane Alcock <salcock@…>, 3 years ago

Initial support for ERF provenance records

Update erftypes.h with TYPE_META (27).
Check for ERF_TYPE_MAX rather than some arbitrary type in ERF sanity checks. In Wireshark we recently completely removed these checks as there are only a few types before TYPE_PAD/ERF_TYPE_MAX, but leave them in for now.
Add TRACE_TYPE_ERF_META for provenance record payload.
Continue to use TRACE_RT_DATA_ERF as provenance is a valid ERF record. Note: this means that LIBTRACE_IS_META_PACKET() will currently return FALSE which may confuse some tools. Other places in the code also tend to check for TRACE_TYPE_NONDATA which isn't true here either.
Return zero for wire length of provenance records.
Don't allow snapping them (just return the same value).
Skip provenance records in l2 parsers and trace_get_payload_from_meta().
Return provenance payload for trace_get_packet_meta().

Also add support for a couple of missing ERF_TYPE_ETH_COLOR variants.

  • Property mode set to 100644
File size: 24.6 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       
170        erfptr = (dag_record_t *)packet->header;
171        if ((erfptr->type & 0x80) == 0x80) {
172                /* Extension headers are present */
173                exthdr = (uint64_t *)((char *)packet->header + dag_record_size);
174                extsize += 8;
175
176                while (*exthdr < (1UL << 31)) {
177                        extsize += 8;
178                        exthdr ++;
179                        assert(extsize <= ntohs(erfptr->rlen));
180                }
181        }
182       
183
184        return dag_record_size + extsize + erf_get_padding(packet);
185}
186
187/* Attempts to determine whether a given trace file is using the ERF format
188 *
189 * Returns 1 if the trace is probably ERF, 0 otherwise
190 */
191static int erf_probe_magic(io_t *io)
192{
193        char buffer[4096];
194        int len;
195        dag_record_t *erf;
196        len = wandio_peek(io, buffer, sizeof(buffer));
197        if (len < (int)dag_record_size) {
198                return 0; /* False */
199        }
200        erf = (dag_record_t *) buffer;
201        /* If the record is too short */
202        if (ntohs(erf->rlen) < dag_record_size) {
203                return 0;
204        }
205        /* There aren't any erf traces before 1995-01-01 */
206        if (bswap_le_to_host64(erf->ts) < 0x2f0539b000000000ULL) {
207                return 0;
208        }
209        /* And not pcap! */
210        if (bswap_le_to_host64(erf->ts) >>32 == 0xa1b2c3d4) {
211                return 0;
212        }
213        /* And not the other pcap! */
214        if (bswap_le_to_host64(erf->ts) >>32 == 0xd4c3b2a1) {
215                return 0;
216        }
217        /* Is this a proper typed packet */
218        if ((erf->type & 0x7f) > ERF_TYPE_MAX) {
219                return 0;
220        }
221        /* We should put some more tests in here. */
222        /* Yeah, this is probably ERF */
223        return 1;
224}
225
226static int erf_init_input(libtrace_t *libtrace) 
227{
228        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
229       
230        IN_OPTIONS.real_time = 0;
231        DATA(libtrace)->drops = 0;
232       
233        return 0; /* success */
234}
235
236static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
237                void *value) {
238
239        switch (option) {
240                case TRACE_OPTION_EVENT_REALTIME:
241                        IN_OPTIONS.real_time = *(int *)value;
242                        return 0;
243                case TRACE_OPTION_SNAPLEN:
244                case TRACE_OPTION_PROMISC:
245                case TRACE_OPTION_FILTER:
246                case TRACE_OPTION_META_FREQ:
247                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
248                                        "Unsupported option");
249                        return -1;
250                default:
251                        /* Unknown option */
252                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
253                                        "Unknown option");
254                        return -1;
255        }
256}
257
258static int erf_start_input(libtrace_t *libtrace) 
259{
260        if (libtrace->io)
261                return 0; /* Success -- already done. */
262
263        libtrace->io = trace_open_file(libtrace);
264
265        if (!libtrace->io)
266                return -1;
267
268        DATA(libtrace)->drops = 0;
269        return 0; /* success */
270}
271
272/* Raw ERF is a special case -- we want to force libwandio to treat the file
273 * as uncompressed so we can't just use trace_open_file() */
274static int rawerf_start_input(libtrace_t *libtrace)
275{
276        if (libtrace->io)
277                return 0; 
278
279        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
280
281        if (!libtrace->io) {
282                if (errno != 0) {
283                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
284                }
285                return -1;
286        }
287
288        DATA(libtrace)->drops = 0;
289
290        return 0; /* success */
291}
292
293/* Binary search through the index to find the closest point before
294 * the packet.  Consider in future having a btree index perhaps?
295 */
296static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
297{
298        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
299        size_t min_off = 0;
300        off_t current;
301        erf_index_t record;
302        do {
303                current=(max_off+min_off)>>2;
304
305                wandio_seek(DATA(libtrace)->seek.index,
306                                (int64_t)(current*sizeof(record)),
307                                SEEK_SET);
308                wandio_read(DATA(libtrace)->seek.index,
309                                &record,sizeof(record));
310                if (record.timestamp < erfts) {
311                        min_off=current;
312                }
313                if (record.timestamp > erfts) {
314                        max_off=current;
315                }
316                if (record.timestamp == erfts)
317                        break;
318        } while(min_off<max_off);
319
320        /* If we've passed it, seek backwards.  This loop shouldn't
321         * execute more than twice.
322         */
323        do {
324                wandio_seek(DATA(libtrace)->seek.index,
325                                (int64_t)(current*sizeof(record)),SEEK_SET);
326                wandio_read(DATA(libtrace)->seek.index,
327                                &record,sizeof(record));
328                current--;
329        } while(record.timestamp>erfts);
330
331        /* We've found our location in the trace, now use it. */
332        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
333
334        return 0; /* success */
335}
336
337/* There is no index.  Seek through the entire trace from the start, nice
338 * and slowly.
339 */
340static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
341{
342        if (libtrace->io) {
343                wandio_destroy(libtrace->io);
344        }
345        libtrace->io = trace_open_file(libtrace);
346        if (!libtrace->io)
347                return -1;
348        return 0;
349}
350
351/* Seek within an ERF trace based on an ERF timestamp */
352static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
353{
354        libtrace_packet_t *packet;
355        off_t off = 0;
356
357        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
358                char buffer[PATH_MAX];
359                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
360                DATA(libtrace)->seek.index=wandio_create(buffer);
361                if (DATA(libtrace)->seek.index) {
362                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
363                }
364                else {
365                        DATA(libtrace)->seek.exists=INDEX_NONE;
366                }
367        }
368
369        /* If theres an index, use it to find the nearest packet that isn't
370         * after the time we're looking for.  If there is no index we need
371         * to seek slowly through the trace from the beginning.  Sigh.
372         */
373        switch(DATA(libtrace)->seek.exists) {
374                case INDEX_EXISTS:
375                        erf_fast_seek_start(libtrace,erfts);
376                        break;
377                case INDEX_NONE:
378                        erf_slow_seek_start(libtrace,erfts);
379                        break;
380                case INDEX_UNKNOWN:
381                        assert(0);
382                        break;
383        }
384
385        /* Now seek forward looking for the correct timestamp */
386        packet=trace_create_packet();
387        do {
388                trace_read_packet(libtrace,packet);
389                if (trace_get_erf_timestamp(packet)==erfts)
390                        break;
391                off=wandio_tell(libtrace->io);
392        } while(trace_get_erf_timestamp(packet)<erfts);
393
394        wandio_seek(libtrace->io,off,SEEK_SET);
395
396        return 0;
397}
398
399static int erf_init_output(libtrace_out_t *libtrace) {
400        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
401
402        OUT_OPTIONS.level = 0;
403        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
404        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
405        OUTPUT->file = 0;
406
407        return 0;
408}
409
410static int erf_config_output(libtrace_out_t *libtrace, 
411                trace_option_output_t option, void *value) {
412
413        switch (option) {
414                case TRACE_OPTION_OUTPUT_COMPRESS:
415                        OUT_OPTIONS.level = *(int*)value;
416                        return 0;
417                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
418                        OUT_OPTIONS.compress_type = *(int*)value;
419                        return 0;
420                case TRACE_OPTION_OUTPUT_FILEFLAGS:
421                        OUT_OPTIONS.fileflag = *(int*)value;
422                        return 0;
423                default:
424                        /* Unknown option */
425                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
426                                        "Unknown option");
427                        return -1;
428        }
429}
430
431
432
433static int erf_fin_input(libtrace_t *libtrace) {
434        if (libtrace->io)
435                wandio_destroy(libtrace->io);
436        free(libtrace->format_data);
437        return 0;
438}
439
440static int erf_fin_output(libtrace_out_t *libtrace) {
441        if (OUTPUT->file)
442                wandio_wdestroy(OUTPUT->file);
443        free(libtrace->format_data);
444        return 0;
445}
446 
447static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
448                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
449       
450        dag_record_t *erfptr;
451       
452        if (packet->buffer != buffer && 
453                packet->buf_control == TRACE_CTRL_PACKET) {
454                free(packet->buffer);
455        }
456
457        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
458                packet->buf_control = TRACE_CTRL_PACKET;
459        } else
460                packet->buf_control = TRACE_CTRL_EXTERNAL;
461       
462       
463        packet->type = rt_type;
464        packet->buffer = buffer;
465        packet->header = buffer;
466        erfptr = (dag_record_t *)packet->buffer;
467        if (erfptr->flags.rxerror == 1) {
468                packet->payload = NULL;
469        } else {
470                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
471        }
472
473        assert(erfptr->rlen != 0);
474       
475        if (libtrace->format_data == NULL) {
476                /* Allocates the format_data structure */
477                if (erf_init_input(libtrace)) 
478                        return -1;
479        }
480
481        /* Check for loss */
482        if (erf_is_color_type(erfptr->type)) {
483                /* No idea how we get this yet */
484
485        } else if (erfptr->lctr) {
486                DATA(libtrace)->drops += ntohs(erfptr->lctr);
487        }
488
489        return 0;
490}
491
492static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
493        int numbytes;
494        unsigned int size;
495        void *buffer2 = packet->buffer;
496        unsigned int rlen;
497        uint32_t flags = 0;
498       
499       
500        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
501                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
502                if (!packet->buffer) {
503                        trace_set_err(libtrace, errno, 
504                                        "Cannot allocate memory");
505                        return -1;
506                }
507        }
508
509        flags |= TRACE_PREP_OWN_BUFFER; 
510       
511        if ((numbytes=wandio_read(libtrace->io,
512                                        packet->buffer,
513                                        (size_t)dag_record_size)) == -1) {
514                trace_set_err(libtrace,errno,"reading ERF file");
515                return -1;
516        }
517        /* EOF */
518        if (numbytes == 0) {
519                return 0;
520        }
521
522        if (numbytes < (int)dag_record_size) {
523                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header");
524                return -1;
525        }
526
527        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
528        buffer2 = (char*)packet->buffer + dag_record_size;
529        size = rlen - dag_record_size;
530
531        if (size >= LIBTRACE_PACKET_BUFSIZE) {
532                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
533                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
534                                size);
535                return -1;
536        }
537
538        /* Unknown/corrupt */
539        if ((((dag_record_t *)packet->buffer)->type & 0x7f) > ERF_TYPE_MAX) {
540                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
541                                "Corrupt or Unknown ERF type");
542                return -1;
543        }
544       
545        /* read in the rest of the packet */
546        if ((numbytes=wandio_read(libtrace->io,
547                                        buffer2,
548                                        (size_t)size)) != (int)size) {
549                if (numbytes==-1) {
550                        trace_set_err(libtrace,errno, "read(%s)", 
551                                        libtrace->uridata);
552                        return -1;
553                }
554                trace_set_err(libtrace,EIO,
555                                "Truncated packet (wanted %d, got %d)", 
556                                size, numbytes);
557                /* Failed to read the full packet?  must be EOF */
558                return -1;
559        }
560
561        if (numbytes < (int)size) {
562                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record");
563                return -1;
564        }
565       
566        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
567                                TRACE_RT_DATA_ERF, flags))
568                return -1;
569       
570        return rlen;
571}
572
573static int erf_dump_packet(libtrace_out_t *libtrace,
574                dag_record_t *erfptr, int framinglen, void *buffer,
575                int caplen) {
576        int numbytes = 0;
577
578        if (caplen + framinglen != ntohs(erfptr->rlen))
579                erfptr->rlen = htons(caplen + framinglen);
580
581        if ((numbytes = 
582                wandio_wwrite(OUTPUT->file, 
583                                erfptr,
584                                (size_t)(framinglen))) 
585                        != (int)(framinglen)) {
586                trace_set_err_out(libtrace,errno,
587                                "write(%s)",libtrace->uridata);
588                return -1;
589        }
590
591        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)caplen);
592        if (numbytes != caplen) {
593                trace_set_err_out(libtrace,errno,
594                                "write(%s)",libtrace->uridata);
595                return -1;
596        }
597        return numbytes + framinglen;
598}
599
600static int erf_start_output(libtrace_out_t *libtrace)
601{
602        OUTPUT->file = trace_open_file_out(libtrace,
603                        OUT_OPTIONS.compress_type,
604                        OUT_OPTIONS.level,
605                        OUT_OPTIONS.fileflag);
606
607        if (!OUTPUT->file) {
608                return -1;
609        }
610        return 0;
611}
612
613static bool find_compatible_linktype(libtrace_out_t *libtrace,
614                                libtrace_packet_t *packet)
615{
616        /* Keep trying to simplify the packet until we can find
617         * something we can do with it */
618        do {
619                char type=libtrace_to_erf_type(trace_get_link_type(packet));
620
621                /* Success */
622                if (type != (char)-1)
623                        return true;
624
625                if (!demote_packet(packet)) {
626                        trace_set_err_out(libtrace,
627                                        TRACE_ERR_NO_CONVERSION,
628                                        "No erf type for packet (%i)",
629                                        trace_get_link_type(packet));
630                        return false;
631                }
632
633        } while(1);
634
635        return true;
636}
637               
638static int erf_write_packet(libtrace_out_t *libtrace, 
639                libtrace_packet_t *packet) 
640{
641        int numbytes = 0;
642        unsigned int pad = 0;
643        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
644        void *payload = packet->payload;
645
646        assert(OUTPUT->file);
647
648        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
649                return 0;
650
651        if (!packet->header) {
652                return -1;
653        }
654       
655        pad = erf_get_padding(packet);
656
657        /* If we've had an rxerror, we have no payload to write - fix
658         * rlen to be the correct length
659         */
660        /* I Think this is bogus, we should somehow figure out
661         * a way to write out the payload even if it is gibberish -- Perry */
662        if (payload == NULL) {
663                dag_hdr->rlen = htons(dag_record_size + pad);
664               
665        } 
666       
667        if (packet->type == TRACE_RT_DATA_ERF) {
668                        numbytes = erf_dump_packet(libtrace,
669                                (dag_record_t *)packet->header,
670                                trace_get_framing_length(packet),
671                                payload,
672                                trace_get_capture_length(packet)
673                                );
674        } else {
675                dag_record_t erfhdr;
676                int rlen;
677                int framing;
678                /* convert format - build up a new erf header */
679                /* Timestamp */
680                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
681
682                /* Flags. Can't do this */
683                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
684                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
685                        erfhdr.flags.iface = trace_get_direction(packet);
686
687                if (!find_compatible_linktype(libtrace,packet))
688                        return -1;
689
690                payload=packet->payload;
691                pad = erf_get_padding(packet);
692
693                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
694
695                /* Packet length (rlen includes format overhead) */
696                assert(trace_get_capture_length(packet)>0 
697                                && trace_get_capture_length(packet)<=65536);
698                assert(trace_get_framing_length(packet)<=65536);
699               
700                if (erfhdr.type == TYPE_ETH)
701                        framing = dag_record_size + 2;
702                else
703                        framing = dag_record_size;
704               
705                rlen = trace_get_capture_length(packet) + framing;
706                assert(rlen > 0 && rlen <= 65536);
707                erfhdr.rlen = htons(rlen);
708                /* loss counter. Can't do this */
709                erfhdr.lctr = 0;
710                /* Wire length, does not include padding! */
711                erfhdr.wlen = htons(trace_get_wire_length(packet));
712
713                /* Write it out */
714                numbytes = erf_dump_packet(libtrace,
715                                &erfhdr,
716                                framing,
717                                payload,
718                                trace_get_capture_length(packet));
719        }
720        return numbytes;
721}
722
723libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
724        dag_record_t *erfptr = 0;
725        erfptr = (dag_record_t *)packet->header;
726        uint8_t type = (erfptr->type & 0x7f);
727        if (type != TYPE_LEGACY) {
728                /* The top-most bit is now used to indicate the presence of
729                 * extension headers :/ */
730                return erf_type_to_libtrace(type);
731        }
732        else {
733                /* Sigh, lets start wildly guessing */
734                if (((char*)packet->payload)[4]==0x45)
735                        return TRACE_TYPE_PPP;
736                return ~0;
737        }
738}
739
740libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
741        dag_record_t *erfptr = 0;
742        erfptr = (dag_record_t *)packet->header;
743        return erfptr->flags.iface;
744}
745
746libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
747        dag_record_t *erfptr = 0;
748        erfptr = (dag_record_t *)packet->header;
749        erfptr->flags.iface = direction;
750        return erfptr->flags.iface;
751}
752
753uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
754        dag_record_t *erfptr = 0;
755        erfptr = (dag_record_t *)packet->header;
756        return bswap_le_to_host64(erfptr->ts);
757}
758
759int erf_get_capture_length(const libtrace_packet_t *packet) {
760        dag_record_t *erfptr = 0;
761        int caplen;
762        if (packet->payload == NULL)
763                return 0; 
764       
765        erfptr = (dag_record_t *)packet->header;
766        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
767        if (ntohs(erfptr->wlen) < caplen)
768                return ntohs(erfptr->wlen);
769
770        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
771}
772
773int erf_get_wire_length(const libtrace_packet_t *packet) {
774        dag_record_t *erfptr = 0;
775        erfptr = (dag_record_t *)packet->header;
776
777        if ((erfptr->type & 0x7f) == TYPE_META)
778                return 0;
779
780        return ntohs(erfptr->wlen);
781}
782
783size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
784        dag_record_t *erfptr = 0;
785        assert(packet);
786        erfptr = (dag_record_t *)packet->header;
787
788        if(size > trace_get_capture_length(packet) || (erfptr->type & 0x7f) == TYPE_META) {
789                /* Can't make a packet larger */
790                return trace_get_capture_length(packet);
791        }
792
793        /* Reset cached capture length - otherwise we will both return the
794         * wrong value here and subsequent get_capture_length() calls will
795         * return the wrong value. */
796        packet->capture_length = -1;
797        erfptr->rlen = htons(size + erf_get_framing_length(packet));
798        return trace_get_capture_length(packet);
799}
800
801static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
802        struct libtrace_eventobj_t event = {0,0,0.0,0};
803       
804        /* If we are being told to replay packets as fast as possible, then
805         * we just need to read and return the next packet in the trace */
806        if (IN_OPTIONS.real_time) {
807                event.size = trace_read_packet(libtrace, packet);
808                if (event.size < 1)
809                        event.type = TRACE_EVENT_TERMINATE;
810                else
811                        event.type = TRACE_EVENT_PACKET;
812                return event;
813               
814        } else {
815                /* Otherwise, use the generic event function */
816                return trace_event_trace(libtrace, packet);
817        }
818       
819}
820
821static void erf_get_statistics(libtrace_t *trace, libtrace_stat_t *stat) {
822
823        if (trace->format_data) {
824                stat->dropped_valid = 1;
825                stat->dropped = DATA(trace)->drops;
826        }
827}
828
829static void erf_help(void) {
830        printf("erf format module: $Revision: 1752 $\n");
831        printf("Supported input URIs:\n");
832        printf("\terf:/path/to/file\t(uncompressed)\n");
833        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
834        printf("\terf:-\t(stdin, either compressed or not)\n");
835        printf("\terf:/path/to/socket\n");
836        printf("\n");
837        printf("\te.g.: erf:/tmp/trace\n");
838        printf("\n");
839        printf("Supported output URIs:\n");
840        printf("\terf:path/to/file\t(uncompressed)\n");
841        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
842        printf("\terf:-\t(stdout, either compressed or not)\n");
843        printf("\n");
844        printf("\te.g.: erf:/tmp/trace\n");
845        printf("\n");
846
847       
848}
849
850static struct libtrace_format_t erfformat = {
851        "erf",
852        "$Id$",
853        TRACE_FORMAT_ERF,
854        NULL,                           /* probe filename */
855        erf_probe_magic,                /* probe magic */
856        erf_init_input,                 /* init_input */       
857        erf_config_input,               /* config_input */
858        erf_start_input,                /* start_input */
859        NULL,                           /* pause_input */
860        erf_init_output,                /* init_output */
861        erf_config_output,              /* config_output */
862        erf_start_output,               /* start_output */
863        erf_fin_input,                  /* fin_input */
864        erf_fin_output,                 /* fin_output */
865        erf_read_packet,                /* read_packet */
866        erf_prepare_packet,             /* prepare_packet */
867        NULL,                           /* fin_packet */
868        erf_write_packet,               /* write_packet */
869        erf_get_link_type,              /* get_link_type */
870        erf_get_direction,              /* get_direction */
871        erf_set_direction,              /* set_direction */
872        erf_get_erf_timestamp,          /* get_erf_timestamp */
873        NULL,                           /* get_timeval */
874        NULL,                           /* get_timespec */
875        NULL,                           /* get_seconds */
876        erf_seek_erf,                   /* seek_erf */
877        NULL,                           /* seek_timeval */
878        NULL,                           /* seek_seconds */
879        erf_get_capture_length,         /* get_capture_length */
880        erf_get_wire_length,            /* get_wire_length */
881        erf_get_framing_length,         /* get_framing_length */
882        erf_set_capture_length,         /* set_capture_length */
883        NULL,                           /* get_received_packets */
884        NULL,                           /* get_filtered_packets */
885        NULL,                           /* get_dropped_packets */
886        erf_get_statistics,             /* get_statistics */
887        NULL,                           /* get_fd */
888        erf_event,                      /* trace_event */
889        erf_help,                       /* help */
890        NULL,                           /* next pointer */
891        NON_PARALLEL(false)
892};
893
894static struct libtrace_format_t rawerfformat = {
895        "rawerf",
896        "$Id$",
897        TRACE_FORMAT_RAWERF,
898        NULL,                           /* probe filename */
899        NULL,           /* probe magic */
900        erf_init_input,                 /* init_input */       
901        erf_config_input,               /* config_input */
902        rawerf_start_input,             /* start_input */
903        NULL,                           /* pause_input */
904        erf_init_output,                /* init_output */
905        erf_config_output,              /* config_output */
906        erf_start_output,               /* start_output */
907        erf_fin_input,                  /* fin_input */
908        erf_fin_output,                 /* fin_output */
909        erf_read_packet,                /* read_packet */
910        erf_prepare_packet,             /* prepare_packet */
911        NULL,                           /* fin_packet */
912        erf_write_packet,               /* write_packet */
913        erf_get_link_type,              /* get_link_type */
914        erf_get_direction,              /* get_direction */
915        erf_set_direction,              /* set_direction */
916        erf_get_erf_timestamp,          /* get_erf_timestamp */
917        NULL,                           /* get_timeval */
918        NULL,                           /* get_timespec */
919        NULL,                           /* get_seconds */
920        erf_seek_erf,                   /* seek_erf */
921        NULL,                           /* seek_timeval */
922        NULL,                           /* seek_seconds */
923        erf_get_capture_length,         /* get_capture_length */
924        erf_get_wire_length,            /* get_wire_length */
925        erf_get_framing_length,         /* get_framing_length */
926        erf_set_capture_length,         /* set_capture_length */
927        NULL,                           /* get_received_packets */
928        NULL,                           /* get_filtered_packets */
929        NULL,                           /* get_dropped_packets */
930        erf_get_statistics,             /* get_statistics */
931        NULL,                           /* get_fd */
932        erf_event,                      /* trace_event */
933        erf_help,                       /* help */
934        NULL,                           /* next pointer */
935        NON_PARALLEL(false)
936};
937
938
939
940void erf_constructor(void) {
941        register_format(&erfformat);
942        register_format(&rawerfformat);
943}
Note: See TracBrowser for help on using the repository browser.