source: lib/format_erf.c @ f6f3ae5

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

Assertion cleanup

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