source: lib/trace.c @ f52bcdd

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since f52bcdd was f0fb38f, checked in by Shane Alcock <salcock@…>, 14 years ago
  • Added prepare_packet functions to all formats, primarily to support translating RT packets into the appropriate format. These functions are all used internally as well, as most formats still need to "prepare" packets that have been read by setting pointers, updating loss counters etc.
  • Also added a trace_prepare_packet function, but this is not made available externally at this stage
  • Added init_format_data functions to some formats to initialise format data structures in cases where the init_trace function does more than just that
  • Refactored rt packet reading code to use the new trace_prepare_packet functionality - also did a lot of tidying of the code
  • Added missing RT type for BPF format
  • Property mode set to 100644
File size: 43.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31
32/* @file
33 *
34 * @brief Trace file processing library
35 *
36 * @author Daniel Lawson
37 * @author Perry Lorier
38 *
39 * @internal
40 */
41#define _GNU_SOURCE
42#include "common.h"
43#include "config.h"
44#include <assert.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <sys/stat.h>
51#include <sys/types.h>
52#ifndef WIN32
53#include <sys/socket.h>
54#endif
55#include <stdarg.h>
56
57#ifdef HAVE_LIMITS_H
58#  include <limits.h>
59#endif
60
61#ifdef HAVE_SYS_LIMITS_H
62#  include <sys/limits.h>
63#endif
64
65#ifdef HAVE_NET_IF_ARP_H
66#  include <net/if_arp.h>
67#endif
68
69#ifdef HAVE_NET_IF_H
70#  include <net/if.h>
71#endif
72
73#ifdef HAVE_NETINET_IN_H
74#  include <netinet/in.h>
75#endif
76
77#ifdef HAVE_NET_ETHERNET_H
78#  include <net/ethernet.h>
79#endif
80
81#ifdef HAVE_NETINET_IF_ETHER_H
82#  include <netinet/if_ether.h>
83#endif
84
85#include <time.h>
86#ifdef WIN32
87#include <sys/timeb.h>
88#endif
89
90#include "libtrace.h"
91#include "libtrace_int.h"
92
93#ifdef HAVE_PCAP_BPF_H
94#  include <pcap-bpf.h>
95#else
96#  ifdef HAVE_NET_BPF_H
97#    include <net/bpf.h>
98#  endif
99#endif
100
101
102#include "libtrace_int.h"
103#include "format_helper.h"
104#include "rt_protocol.h"
105
106#define MAXOPTS 1024
107
108
109static struct libtrace_format_t *formats_list = NULL;
110
111/* strncpy is not assured to copy the final \0, so we
112 * will use our own one that does
113 */
114static void xstrncpy(char *dest, const char *src, size_t n)
115{
116        strncpy(dest,src,n);
117        dest[n]='\0';
118}
119 
120static char *xstrndup(const char *src,size_t n)
121{       
122        char *ret=(char*)malloc(n+1);
123        if (ret==NULL) {
124                fprintf(stderr,"Out of memory");
125                exit(EXIT_FAILURE);
126        }
127        xstrncpy(ret,src,n);
128        return ret;
129}
130
131void register_format(struct libtrace_format_t *f) {
132        assert(f->next==NULL); /* Can't register a format twice */
133        f->next=formats_list;
134        formats_list=f;
135        /* Now, verify things
136         * This #if can be changed to a 1 to output warnings about inconsistant
137         * functions being provided by format modules.  This generally is very
138         * noisy, as almost all modules don't implement one or more functions
139         * for various reasons.  This is very useful when checking a new
140         * format module is sane.
141         */ 
142#if 0
143        if (f->init_input) {
144#define REQUIRE(x) \
145                if (!f->x) \
146                        fprintf(stderr,"%s: Input format should provide " #x "\n",f->name)
147                REQUIRE(read_packet);
148                REQUIRE(start_input);
149                REQUIRE(fin_input);
150                REQUIRE(get_link_type);
151                REQUIRE(get_capture_length);
152                REQUIRE(get_wire_length);
153                REQUIRE(get_framing_length);
154                REQUIRE(trace_event);
155                if (!f->get_erf_timestamp
156                        && !f->get_seconds
157                        && !f->get_timeval) {
158                        fprintf(stderr,"%s: A trace format capable of input, should provide at least one of\n"
159"get_erf_timestamp, get_seconds or trace_timeval\n",f->name);
160                }
161                if (f->trace_event!=trace_event_trace) {
162                        /* Theres nothing that a trace file could optimise with
163                         * config_input
164                         */
165                        REQUIRE(pause_input);
166                        REQUIRE(config_input);
167                        REQUIRE(get_fd);
168                }
169                else {
170                        if (f->get_fd) {
171                                fprintf(stderr,"%s: Unnecessary get_fd\n",
172                                                f->name);
173                        }
174                }
175#undef REQUIRE
176        }
177        else {
178#define REQUIRE(x) \
179                if (f->x) \
180                        fprintf(stderr,"%s: Non Input format shouldn't need " #x "\n",f->name)
181                REQUIRE(read_packet);
182                REQUIRE(start_input);
183                REQUIRE(pause_input);
184                REQUIRE(fin_input);
185                REQUIRE(get_link_type);
186                REQUIRE(get_capture_length);
187                REQUIRE(get_wire_length);
188                REQUIRE(get_framing_length);
189                REQUIRE(trace_event);
190                REQUIRE(get_seconds);
191                REQUIRE(get_timeval);
192                REQUIRE(get_erf_timestamp);
193#undef REQUIRE
194        }
195        if (f->init_output) {
196#define REQUIRE(x) \
197                if (!f->x) \
198                        fprintf(stderr,"%s: Output format should provide " #x "\n",f->name)
199                REQUIRE(write_packet);
200                REQUIRE(start_output);
201                REQUIRE(config_output);
202                REQUIRE(fin_output);
203#undef REQUIRE
204        }
205        else {
206#define REQUIRE(x) \
207                if (f->x) \
208                        fprintf(stderr,"%s: Non Output format shouldn't need " #x "\n",f->name)
209                REQUIRE(write_packet);
210                REQUIRE(start_output);
211                REQUIRE(config_output);
212                REQUIRE(fin_output);
213#undef REQUIRE
214        }
215#endif
216}
217
218/* call all the constructors if they haven't yet all been called */
219static void trace_init(void)
220{
221        if (!formats_list) {
222                duck_constructor();
223                erf_constructor();
224                tsh_constructor();
225                legacy_constructor();
226                atmhdr_constructor();
227#ifdef HAVE_NETPACKET_PACKET_H
228                linuxnative_constructor();
229#endif
230#ifdef HAVE_LIBPCAP
231                pcap_constructor();
232#endif
233#if HAVE_DECL_BIOCSETIF
234                bpf_constructor();
235#endif
236                pcapfile_constructor();
237                rt_constructor();
238#ifdef HAVE_DAG
239                dag_constructor();
240#endif
241        }
242}
243
244/* Prints help information for libtrace
245 *
246 * Function prints out some basic help information regarding libtrace,
247 * and then prints out the help() function registered with each input module
248 */
249DLLEXPORT void trace_help(void) {
250        struct libtrace_format_t *tmp;
251        trace_init();
252        printf("libtrace %s\n\n",PACKAGE_VERSION);
253        printf("Following this are a list of the format modules supported in this build of libtrace\n\n");
254        for(tmp=formats_list;tmp;tmp=tmp->next) {
255                if (tmp->help)
256                        tmp->help();
257        }
258}
259
260#define URI_PROTO_LINE 16U
261
262
263/* Create a trace file from a URI
264 *
265 * @params char * containing a valid libtrace URI
266 * @returns opaque pointer to a libtrace_t
267 *
268 * Valid URI's are:
269 *  erf:/path/to/erf/file
270 *  erf:/path/to/erf/file.gz
271 *  erf:/path/to/rtclient/socket
272 *  erf:-                       (stdin)
273 *  dag:/dev/dagcard
274 *  pcapint:pcapinterface               (eg: pcapint:eth0)
275 *  pcap:/path/to/pcap/file
276 *  pcap:-
277 *  rtclient:hostname
278 *  rtclient:hostname:port
279 *
280 * If an error occured when attempting to open a trace, NULL is returned
281 * and an error is output to stdout.
282 */
283DLLEXPORT libtrace_t *trace_create(const char *uri) {
284        libtrace_t *libtrace = 
285                        (libtrace_t *)malloc(sizeof(libtrace_t));
286        char *scan = 0;
287        const char *uridata = 0;                 
288        struct libtrace_format_t *tmp;
289
290        trace_init();
291
292        assert(uri && "Passing NULL to trace_create makes me a very sad program");
293
294        if (!libtrace) {
295                /* Out of memory */
296                return NULL;
297        }
298       
299        libtrace->err.err_num = TRACE_ERR_NOERROR;
300        libtrace->format=NULL;
301       
302        libtrace->event.tdelta = 0.0;
303        libtrace->event.packet = NULL;
304        libtrace->event.psize = 0;
305        libtrace->event.trace_last_ts = 0.0;
306        libtrace->filter = NULL;
307        libtrace->snaplen = 0;
308        libtrace->started=false;
309
310        /* parse the URI to determine what sort of event we are dealing with */
311        if ((uridata = trace_parse_uri(uri, &scan)) == 0) {
312                trace_set_err(libtrace,TRACE_ERR_BAD_FORMAT,"Bad uri format (%s)",uri);
313                return libtrace;
314        }
315       
316        for (tmp=formats_list;tmp;tmp=tmp->next) {
317                if (strlen(scan) == strlen(tmp->name) &&
318                                strncasecmp(scan, tmp->name, strlen(scan)) == 0
319                                ) {
320                        libtrace->format=tmp;
321                        break;
322                }
323        }
324        if (libtrace->format == 0) {
325                trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT,
326                                "Unknown format (%s)",scan);
327                return libtrace;
328        }
329
330        libtrace->uridata = strdup(uridata);
331        /* libtrace->format now contains the type of uri
332         * libtrace->uridata contains the appropriate data for this
333         */
334       
335        if (libtrace->format->init_input) {
336                int err=libtrace->format->init_input(libtrace);
337                assert (err==-1 || err==0);
338                if (err==-1) {
339                        /* init_input should call trace_set_err to set
340                         * the error message
341                         */
342                        return libtrace;
343                }
344        } else {
345                trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,
346                                "Format does not support input (%s)",scan);
347                return libtrace;
348        }
349       
350
351        free(scan);
352        libtrace->err.err_num=TRACE_ERR_NOERROR;
353        libtrace->err.problem[0]='\0';
354        return libtrace;
355}
356
357/* Creates a "dummy" trace file that has only the format type set.
358 *
359 * @returns opaque pointer to a (sparsely initialised) libtrace_t
360 *
361 * IMPORTANT: Do not attempt to call trace_read_packet or other such functions
362 * with the dummy trace. Its intended purpose is to act as a packet->trace for
363 * libtrace_packet_t's that are not associated with a libtrace_t structure.
364 */
365DLLEXPORT libtrace_t * trace_create_dead (const char *uri) {
366        libtrace_t *libtrace = (libtrace_t *) malloc(sizeof(libtrace_t));
367        char *scan = (char *)calloc(sizeof(char),URI_PROTO_LINE);
368        char *uridata;
369        struct libtrace_format_t *tmp;
370
371        trace_init();
372       
373        libtrace->err.err_num = TRACE_ERR_NOERROR;
374
375        if((uridata = strchr(uri,':')) == NULL) {
376                xstrncpy(scan, uri, strlen(uri));
377        } else {
378                xstrncpy(scan,uri, (size_t)(uridata - uri));
379        }
380       
381        libtrace->format = 0;   
382       
383        for(tmp=formats_list;tmp;tmp=tmp->next) {
384                if (strlen(scan) == strlen(tmp->name) &&
385                                !strncasecmp(scan,
386                                        tmp->name,
387                                        strlen(scan))) {
388                                libtrace->format=tmp;
389                                break;
390                                }
391        }
392        if (libtrace->format == 0) {
393                trace_set_err(libtrace,TRACE_ERR_BAD_FORMAT,
394                                "Unknown format (%s)",scan);
395        }
396
397        libtrace->format_data = NULL;
398        free(scan);
399        return libtrace;
400
401}
402
403/* Creates a trace output file from a URI.
404 *
405 * @param uri   the uri string describing the output format and destination
406 * @returns opaque pointer to a libtrace_output_t
407 *
408 *  If an error occured when attempting to open the output trace, NULL is
409 *  returned and trace_errno is set.
410 */
411       
412DLLEXPORT libtrace_out_t *trace_create_output(const char *uri) {
413        libtrace_out_t *libtrace = 
414                        (libtrace_out_t*)malloc(sizeof(libtrace_out_t));
415       
416        char *scan = 0;
417        const char *uridata = 0;
418        struct libtrace_format_t *tmp;
419
420        trace_init();
421
422        libtrace->err.err_num = TRACE_ERR_NOERROR;
423        strcpy(libtrace->err.problem,"Error message set\n");
424        libtrace->format = NULL;
425        libtrace->uridata = NULL;
426       
427        /* parse the URI to determine what sort of event we are dealing with */
428
429        if ((uridata = trace_parse_uri(uri, &scan)) == 0) {
430                trace_set_err_out(libtrace,TRACE_ERR_BAD_FORMAT,
431                                "Bad uri format (%s)",uri);
432                return libtrace;
433        }
434       
435        for(tmp=formats_list;tmp;tmp=tmp->next) {
436                if (strlen(scan) == strlen(tmp->name) &&
437                                !strncasecmp(scan,
438                                        tmp->name,
439                                        strlen(scan))) {
440                                libtrace->format=tmp;
441                                break;
442                                }
443        }
444        free(scan);
445
446        if (libtrace->format == NULL) {
447                trace_set_err_out(libtrace,TRACE_ERR_BAD_FORMAT,
448                                "Unknown output format (%s)",scan);
449                return libtrace;
450        }
451        libtrace->uridata = strdup(uridata);
452
453        /* libtrace->format now contains the type of uri
454         * libtrace->uridata contains the appropriate data for this
455         */
456
457        if (libtrace->format->init_output) {
458                /* 0 on success, -1 on failure */
459                switch(libtrace->format->init_output(libtrace)) {
460                        case -1: /* failure */
461                                return libtrace;
462                        case 0: /* success */
463                                break;
464                        default:
465                                assert(!"Internal error: init_output() should return -1 for failure, or 0 for success");
466                }
467        } else {
468                trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
469                                "Format does not support writing (%s)",scan);
470                return libtrace;
471        }
472
473
474        libtrace->started=false;
475        return libtrace;
476}
477
478/* Start a trace
479 * @param libtrace      the input trace to start
480 * @returns 0 on success
481 *
482 * This does the work associated with actually starting up
483 * the trace.  it may fail.
484 */
485DLLEXPORT int trace_start(libtrace_t *libtrace)
486{
487        assert(libtrace);
488        if (trace_is_err(libtrace))
489                return -1;
490        if (libtrace->format->start_input) {
491                int ret=libtrace->format->start_input(libtrace);
492                if (ret < 0) {
493                        return ret;
494                }
495        }
496
497        libtrace->started=true;
498        return 0;
499}
500
501DLLEXPORT int trace_start_output(libtrace_out_t *libtrace) 
502{
503        assert(libtrace);
504        if (libtrace->format->start_output) {
505                int ret=libtrace->format->start_output(libtrace);
506                if (ret < 0) {
507                        return ret;
508                }
509        }
510
511        libtrace->started=true;
512        return 0;
513}
514
515DLLEXPORT int trace_pause(libtrace_t *libtrace)
516{
517        assert(libtrace);
518        if (!libtrace->started) {
519                trace_set_err(libtrace,TRACE_ERR_BAD_STATE, "You must call trace_start() before calling trace_pause()");
520                return -1;
521        }
522        if (libtrace->format->pause_input)
523                libtrace->format->pause_input(libtrace);
524        libtrace->started=false;
525        return 0;
526}
527
528DLLEXPORT int trace_config(libtrace_t *libtrace,
529                trace_option_t option,
530                void *value)
531{
532        int ret;
533        libtrace_err_t err;
534
535        if (trace_is_err(libtrace)) {
536                return -1;
537        }
538       
539        if (libtrace->format->config_input) {
540                ret=libtrace->format->config_input(libtrace,option,value);
541                if (ret==0)
542                        return 0;
543        }
544        switch(option) {
545                case TRACE_OPTION_SNAPLEN:
546                        /* Clear the error if there was one */
547                        if (trace_is_err(libtrace)) {
548                                err = trace_get_err(libtrace);
549                        }
550                        libtrace->snaplen=*(int*)value;
551                        return 0;
552                case TRACE_OPTION_FILTER:
553                        /* Clear the error if there was one */
554                        if (trace_is_err(libtrace)) {
555                                err = trace_get_err(libtrace);
556                        }
557                        libtrace->filter=(libtrace_filter_t *)value;
558                        return 0;
559                case TRACE_OPTION_PROMISC:
560                        if (!trace_is_err(libtrace)) {
561                                trace_set_err(libtrace,TRACE_ERR_OPTION_UNAVAIL,
562                                                "Promisc mode is not supported by this format module");
563                        }
564                        return -1;
565                case TRACE_OPTION_META_FREQ:
566                        if (!trace_is_err(libtrace)) {
567                                trace_set_err(libtrace, 
568                                                TRACE_ERR_OPTION_UNAVAIL,
569                                                "This format does not support meta-data gathering");
570                        }
571                        return -1;
572                case TRACE_OPTION_EVENT_REALTIME:
573                        if (!trace_is_err(libtrace)) {
574                                trace_set_err(libtrace, 
575                                                TRACE_ERR_OPTION_UNAVAIL,
576                                                "This format does not support meta-data gathering");
577                        }
578                        return -1;
579                       
580        }
581        if (!trace_is_err(libtrace)) {
582                trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
583                        "Unknown option %i", option);
584        }
585        return -1;
586}
587
588/* Parses an output options string and calls the appropriate function to deal with output options.
589 *
590 * @param libtrace      the output trace object to apply the options to
591 * @param options       the options string
592 * @returns -1 if option configuration failed, 0 otherwise
593 *
594 * @author Shane Alcock
595 */
596DLLEXPORT int trace_config_output(libtrace_out_t *libtrace, 
597                trace_option_output_t option,
598                void *value) {
599        if (libtrace->format->config_output) {
600                return libtrace->format->config_output(libtrace, option, value);
601        }
602        return -1;
603}
604
605/* Close a trace file, freeing up any resources it may have been using
606 *
607 */
608DLLEXPORT void trace_destroy(libtrace_t *libtrace) {
609        assert(libtrace);
610        if (libtrace->format) {
611                if (libtrace->started && libtrace->format->pause_input)
612                        libtrace->format->pause_input(libtrace);
613                libtrace->format->fin_input(libtrace);
614        }
615        /* need to free things! */
616        if (libtrace->uridata)
617                free(libtrace->uridata);
618        free(libtrace);
619}
620
621
622DLLEXPORT void trace_destroy_dead(libtrace_t *libtrace) {
623        assert(libtrace);
624        if (libtrace->format_data)
625                free(libtrace->format_data);
626        free(libtrace);
627}
628/* Close an output trace file, freeing up any resources it may have been using
629 *
630 * @param libtrace      the output trace file to be destroyed
631 *
632 * @author Shane Alcock
633 * */
634DLLEXPORT void trace_destroy_output(libtrace_out_t *libtrace) 
635{
636        assert(libtrace);
637        if (libtrace->format && libtrace->format->fin_output)
638                libtrace->format->fin_output(libtrace);
639        if (libtrace->uridata)
640                free(libtrace->uridata);
641        free(libtrace);
642}
643
644DLLEXPORT libtrace_packet_t *trace_create_packet(void) 
645{
646        libtrace_packet_t *packet = 
647                (libtrace_packet_t*)calloc((size_t)1,sizeof(libtrace_packet_t));
648
649        packet->buf_control=TRACE_CTRL_PACKET;
650        packet->capture_length=-1;
651        return packet;
652}
653
654DLLEXPORT libtrace_packet_t *trace_copy_packet(const libtrace_packet_t *packet) {
655        libtrace_packet_t *dest = 
656                (libtrace_packet_t *)malloc(sizeof(libtrace_packet_t));
657        if (!dest) {
658                printf("out of memory constructing packet\n");
659                abort();
660        }
661        dest->trace=packet->trace;
662        dest->buffer=malloc(65536);
663        if (!dest->buffer) {
664                printf("out of memory allocating buffer memory\n");
665                abort();
666        }
667        dest->header=dest->buffer;
668        dest->payload=(void*)
669                ((char*)dest->buffer+trace_get_framing_length(packet));
670        dest->type=packet->type;
671        dest->buf_control=TRACE_CTRL_PACKET;
672        /* Reset the cache - better to recalculate than try to convert
673         * the values over to the new packet */
674        dest->capture_length = -1;
675        dest->l3_header = NULL;
676        dest->l3_ethertype = 0;
677        memcpy(dest->header,packet->header,trace_get_framing_length(packet));
678        memcpy(dest->payload,packet->payload,trace_get_capture_length(packet));
679
680        return dest;
681}
682
683/** Destroy a packet object
684 *
685 * sideeffect: sets packet to NULL
686 */
687DLLEXPORT void trace_destroy_packet(libtrace_packet_t *packet) {
688        if (packet->buf_control == TRACE_CTRL_PACKET) {
689                free(packet->buffer);
690        }
691        packet->buf_control=(buf_control_t)'\0'; 
692                                /* an "bad" value to force an assert
693                                 * if this packet is ever reused
694                                 */
695        free(packet);
696}       
697
698/* Read one packet from the trace into buffer
699 *
700 * @param libtrace      the libtrace opaque pointer
701 * @param packet        the packet opaque pointer
702 * @returns 0 on EOF, negative value on error
703 *
704 */
705DLLEXPORT int trace_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
706
707        assert(libtrace && "You called trace_read_packet() with a NULL libtrace parameter!\n");
708        if (trace_is_err(libtrace))
709                return -1;
710        if (!libtrace->started) {
711                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"You must call libtrace_start() before trace_read_packet()\n");
712                return -1;
713        }
714        if (!(packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
715                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
716                return -1;
717        }
718        assert(packet);
719     
720        /* Store the trace we are reading from into the packet opaque
721         * structure */
722        packet->trace = libtrace;
723
724        /* Finalise the packet, freeing any resources the format module
725         * may have allocated it
726         */
727        if (libtrace->format->fin_packet) {
728                libtrace->format->fin_packet(packet);
729        }
730
731        /* Clear the packet cache */
732        packet->capture_length = -1;
733        packet->l3_header = NULL;
734        packet->l3_ethertype = 0;
735
736        if (libtrace->format->read_packet) {
737                do {
738                        size_t ret;
739                        ret=libtrace->format->read_packet(libtrace,packet);
740                        if (ret==(size_t)-1 || ret==0) {
741                                return ret;
742                        }
743                        if (libtrace->filter) {
744                                /* If the filter doesn't match, read another
745                                 * packet
746                                 */
747                                if (!trace_apply_filter(libtrace->filter,packet)){
748                                        ++libtrace->filtered_packets;
749                                        continue;
750                                }
751                        }
752                        if (libtrace->snaplen>0) {
753                                /* Snap the packet */
754                                trace_set_capture_length(packet,
755                                                libtrace->snaplen);
756                        }
757                        ++libtrace->accepted_packets;
758                        return ret;
759                } while(1);
760        }
761        trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,"This format does not support reading packets\n");
762        return ~0U;
763}
764
765int trace_prepare_packet(libtrace_t *trace, libtrace_packet_t *packet,
766                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
767
768        assert(packet);
769        assert(trace);
770       
771        /* XXX Proper error handling?? */
772        if (buffer == NULL)
773                return -1;
774
775        if (!(packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
776                trace_set_err(trace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
777                return -1;
778        }
779       
780        packet->trace = trace;
781       
782        /* Clear packet cache */
783        packet->capture_length = -1;
784        packet->l3_header = NULL;
785        packet->l3_ethertype = 0;
786
787        if (trace->format->prepare_packet) {
788                return trace->format->prepare_packet(trace, packet,
789                                buffer, rt_type, flags);
790        }
791        trace_set_err(trace, TRACE_ERR_UNSUPPORTED, 
792                        "This format does not support preparing packets\n");
793        return -1;
794
795}
796
797/* Writes a packet to the specified output
798 *
799 * @param libtrace      describes the output format, destination, etc.
800 * @param packet        the packet to be written out
801 * @returns the number of bytes written, -1 if write failed
802 *
803 * @author Shane Alcock
804 * */
805DLLEXPORT int trace_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
806        assert(libtrace);
807        assert(packet); 
808        /* Verify the packet is valid */
809        if (!libtrace->started) {
810                trace_set_err_out(libtrace,TRACE_ERR_BAD_STATE,
811                        "Trace is not started before trace_write_packet");
812                return -1;
813        }
814
815        if (libtrace->format->write_packet) {
816                return libtrace->format->write_packet(libtrace, packet);
817        }
818        trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
819                "This format does not support writing packets");
820        return -1;
821}
822
823DLLEXPORT void *trace_get_packet_buffer(const libtrace_packet_t *packet,
824                libtrace_linktype_t *linktype, uint32_t *remaining) {
825        assert(packet != NULL);
826        if (linktype) *linktype = trace_get_link_type(packet);
827        if (remaining) *remaining = trace_get_capture_length(packet);
828        return (void *) packet->payload;
829}
830
831DLLEXPORT void *trace_get_link(const libtrace_packet_t *packet) {
832        return (void *)packet->payload;
833}
834
835/* Get the current time in DAG time format
836 * @param packet        a pointer to a libtrace_packet structure
837 * @returns a 64 bit timestamp in DAG ERF format (upper 32 bits are the seconds
838 * past 1970-01-01, the lower 32bits are partial seconds)
839 * @author Daniel Lawson
840 */ 
841DLLEXPORT uint64_t trace_get_erf_timestamp(const libtrace_packet_t *packet) {
842        uint64_t timestamp = 0;
843        double seconds = 0.0;
844        struct timeval ts;
845
846        if (packet->trace->format->get_erf_timestamp) {
847                /* timestamp -> timestamp */
848                timestamp = packet->trace->format->get_erf_timestamp(packet);
849        } else if (packet->trace->format->get_timeval) {
850                /* timeval -> timestamp */
851                ts = packet->trace->format->get_timeval(packet);
852                timestamp = ((((uint64_t)ts.tv_sec) << 32) + \
853                                (((uint64_t)ts.tv_usec * UINT_MAX)/1000000));
854        } else if (packet->trace->format->get_seconds) {
855                /* seconds -> timestamp */
856                seconds = packet->trace->format->get_seconds(packet);
857                timestamp = ((uint64_t)((uint32_t)seconds) << 32) + \
858                      (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
859        }
860        return timestamp;
861}
862
863/* Get the current time in struct timeval
864 * @param packet        a pointer to a libtrace_packet structure
865 *
866 * @returns time that this packet was seen in a struct timeval
867 * @author Daniel Lawson
868 * @author Perry Lorier
869 */ 
870DLLEXPORT struct timeval trace_get_timeval(const libtrace_packet_t *packet) {
871        struct timeval tv;
872        uint64_t ts = 0;
873        double seconds = 0.0;
874        if (packet->trace->format->get_timeval) {
875                /* timeval -> timeval */
876                tv = packet->trace->format->get_timeval(packet);
877        } else if (packet->trace->format->get_erf_timestamp) {
878                /* timestamp -> timeval */
879                ts = packet->trace->format->get_erf_timestamp(packet);
880#if __BYTE_ORDER == __BIG_ENDIAN
881                tv.tv_sec = ts & 0xFFFFFFFF;
882#elif __BYTE_ORDER == __LITTLE_ENDIAN
883                tv.tv_sec = ts >> 32;
884#else
885#error "What on earth are you running this on?"
886#endif
887                tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
888                if (tv.tv_usec >= 1000000) {
889                        tv.tv_usec -= 1000000;
890                        tv.tv_sec += 1;
891                }
892        } else if (packet->trace->format->get_seconds) {
893                /* seconds -> timeval */
894                seconds = packet->trace->format->get_seconds(packet);
895                tv.tv_sec = (uint32_t)seconds;
896                tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
897        }
898        else {
899                tv.tv_sec=-1;
900                tv.tv_usec=-1;
901        }
902
903        return tv;
904}
905
906/* Get the current time in floating point seconds
907 * @param packet        a pointer to a libtrace_packet structure
908 * @returns time that this packet was seen in 64bit floating point seconds
909 * @author Perry Lorier
910 */ 
911DLLEXPORT double trace_get_seconds(const libtrace_packet_t *packet) {
912        double seconds = 0.0;
913        uint64_t ts = 0;
914        struct timeval tv;
915
916        if (packet->trace->format->get_seconds) {
917                /* seconds->seconds */
918                seconds = packet->trace->format->get_seconds(packet);
919        } else if (packet->trace->format->get_erf_timestamp) {
920                /* timestamp -> seconds */
921                ts = packet->trace->format->get_erf_timestamp(packet);
922                seconds =  (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
923        } else if (packet->trace->format->get_timeval) {
924                /* timeval -> seconds */
925                tv = packet->trace->format->get_timeval(packet);
926                seconds = tv.tv_sec + ((tv.tv_usec * 1.0) / 1000000);
927        }
928
929        return seconds;
930}
931
932DLLEXPORT size_t trace_get_capture_length(const libtrace_packet_t *packet) 
933{
934        /* Cache the capture length */
935        if (packet->capture_length == -1) {
936                if (!packet->trace->format->get_capture_length)
937                        return ~0U;
938                /* Cast away constness because this is "just" a cache */
939                ((libtrace_packet_t*)packet)->capture_length = 
940                        packet->trace->format->get_capture_length(packet);
941        }
942
943        return packet->capture_length;
944}
945       
946/* Get the size of the packet as it was seen on the wire.
947 * @param packet        a pointer to a libtrace_packet structure
948 *
949 * @returns the size of the packet as it was on the wire.
950 * @author Perry Lorier
951 * @author Daniel Lawson
952 * @note Due to the trace being a header capture, or anonymisation this may
953 * not be the same as the Capture Len.
954 */ 
955DLLEXPORT size_t trace_get_wire_length(const libtrace_packet_t *packet){
956        if (packet->trace->format->get_wire_length) {
957                return packet->trace->format->get_wire_length(packet);
958        }
959        return ~0U;
960
961}
962
963/* Get the length of the capture framing headers.
964 * @param packet        the packet opaque pointer
965 * @returns the size of the packet as it was on the wire.
966 * @author Perry Lorier
967 * @author Daniel Lawson
968 * @note this length corresponds to the difference between the size of a
969 * captured packet in memory, and the captured length of the packet
970 */ 
971DLLEXPORT SIMPLE_FUNCTION
972size_t trace_get_framing_length(const libtrace_packet_t *packet) {
973        if (packet->trace->format->get_framing_length) {
974                return packet->trace->format->get_framing_length(packet);
975        }
976        return ~0U;
977}
978
979
980/* Get the type of the link layer
981 * @param packet        a pointer to a libtrace_packet structure
982 * @returns libtrace_linktype_t
983 * @author Perry Lorier
984 * @author Daniel Lawson
985 */
986DLLEXPORT libtrace_linktype_t trace_get_link_type(const libtrace_packet_t *packet ) {
987        if (packet->trace->format->get_link_type) {
988                return packet->trace->format->get_link_type(packet);
989        }
990        return (libtrace_linktype_t)-1;
991}
992
993/* process a libtrace event
994 * @param trace the libtrace opaque pointer
995 * @param packet the libtrace_packet opaque pointer
996 * @returns
997 *  TRACE_EVENT_IOWAIT  Waiting on I/O on fd
998 *  TRACE_EVENT_SLEEP   Next event in seconds
999 *  TRACE_EVENT_PACKET  Packet arrived in buffer with size size
1000 *  TRACE_EVENT_TERMINATE Trace terminated (perhaps with an error condition)
1001 * FIXME currently keeps a copy of the packet inside the trace pointer,
1002 * which in turn is stored inside the new packet object...
1003 * @author Perry Lorier
1004 */
1005DLLEXPORT libtrace_eventobj_t trace_event(libtrace_t *trace, 
1006                libtrace_packet_t *packet) {
1007        libtrace_eventobj_t event = {TRACE_EVENT_IOWAIT,0,0.0,0};
1008
1009        if (!trace) {
1010                fprintf(stderr,"You called trace_event() with a NULL trace object!\n");
1011        }
1012        assert(trace);
1013        assert(packet);
1014
1015        /* Clear the packet cache */
1016        packet->capture_length = -1;
1017        packet->l3_header = NULL;
1018        packet->l3_ethertype = 0;
1019       
1020        /* Store the trace we are reading from into the packet opaque
1021         * structure */
1022        packet->trace = trace;
1023
1024        if (packet->trace->format->trace_event) {
1025                event=packet->trace->format->trace_event(trace,packet);
1026                if (event.type == TRACE_EVENT_PACKET) {
1027                        ++trace->accepted_packets;
1028                }
1029        }
1030        return event;
1031
1032}
1033
1034/** Setup a BPF filter based on pre-compiled byte-code.
1035 * @param bf_insns      A pointer to the start of the byte-code
1036 * @param bf_len        The number of BPF instructions
1037 * @returns             an opaque pointer to a libtrace_filter_t object
1038 * @note                The supplied byte-code is not checked for correctness.
1039 * @author              Scott Raynel
1040 */
1041DLLEXPORT libtrace_filter_t *
1042trace_create_filter_from_bytecode(void *bf_insns, unsigned int bf_len)
1043{
1044#ifndef HAVE_BPF_FILTER
1045        fprintf(stderr, "This version of libtrace does not have BPF support\n");
1046        return NULL;
1047#else
1048        struct libtrace_filter_t *filter = (struct libtrace_filter_t *)
1049                malloc(sizeof(struct libtrace_filter_t));
1050        filter->filter.bf_insns = (struct bpf_insn *)
1051                malloc(sizeof(struct bpf_insn) * bf_len);
1052       
1053        memcpy(filter->filter.bf_insns, bf_insns,
1054                        bf_len * sizeof(struct bpf_insn));
1055       
1056        filter->filter.bf_len = bf_len;
1057        filter->filterstring = NULL;
1058        /* "flag" indicates that the filter member is valid */
1059        filter->flag = 1; 
1060       
1061        return filter;
1062#endif
1063}
1064
1065/* setup a BPF filter
1066 * @param filterstring a char * containing the bpf filter string
1067 * @returns opaque pointer pointer to a libtrace_filter_t object
1068 * @author Daniel Lawson
1069 */
1070DLLEXPORT libtrace_filter_t *trace_create_filter(const char *filterstring) {
1071#ifdef HAVE_BPF_FILTER
1072        libtrace_filter_t *filter = (libtrace_filter_t*)
1073                                malloc(sizeof(libtrace_filter_t));
1074        filter->filterstring = strdup(filterstring);
1075        filter->flag = 0;
1076        return filter;
1077#else
1078        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1079        return NULL;
1080#endif
1081}
1082
1083DLLEXPORT void trace_destroy_filter(libtrace_filter_t *filter)
1084{
1085#ifdef HAVE_BPF_FILTER
1086        free(filter->filterstring);
1087        if (filter->flag)
1088                pcap_freecode(&filter->filter);
1089        free(filter);
1090#else
1091
1092#endif
1093}
1094
1095/* compile a bpf filter, now we know what trace it's on
1096 * @internal
1097 *
1098 * @returns -1 on error, 0 on success
1099 */
1100int trace_bpf_compile(libtrace_filter_t *filter,
1101                const libtrace_packet_t *packet ) {
1102#ifdef HAVE_BPF_FILTER
1103        void *linkptr = 0;
1104        libtrace_linktype_t linktype;
1105        assert(filter);
1106
1107        /* If this isn't a real packet, then fail */
1108        linkptr = trace_get_packet_buffer(packet,&linktype,NULL);
1109        if (!linkptr) {
1110                trace_set_err(packet->trace,
1111                                TRACE_ERR_BAD_PACKET,"Packet has no payload");
1112                return -1;
1113        }
1114       
1115        if (filter->filterstring && ! filter->flag) {
1116                pcap_t *pcap = NULL;
1117                if (linktype==(libtrace_linktype_t)-1) {
1118                        trace_set_err(packet->trace,
1119                                        TRACE_ERR_BAD_PACKET,
1120                                        "Packet has an unknown linktype");
1121                        return -1;
1122                }
1123                if (libtrace_to_pcap_dlt(linktype) == ~1U) {
1124                        trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET,
1125                                        "Unknown pcap equivalent linktype");
1126                        return -1;
1127                }
1128                pcap=(pcap_t *)pcap_open_dead(
1129                                (int)libtrace_to_pcap_dlt(linktype),
1130                                1500U);
1131                /* build filter */
1132                assert(pcap);
1133                if (pcap_compile( pcap, &filter->filter, filter->filterstring, 
1134                                        1, 0)) {
1135                        trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET,
1136                                        "Unable to compile the filter \"%s\": %s", 
1137                                        filter->filterstring,
1138                                        pcap_geterr(pcap));
1139                        pcap_close(pcap);
1140                        return -1;
1141                }
1142                pcap_close(pcap);
1143                filter->flag=1;
1144        }
1145        return 0;
1146#else
1147        assert(!"Internal bug: This never be called when BPF not enabled");
1148        trace_set_err(packet->trace,TRACE_ERR_OPTION_UNAVAIL,
1149                                "Feature unavailable");
1150        return -1;
1151#endif
1152}
1153
1154DLLEXPORT int trace_apply_filter(libtrace_filter_t *filter,
1155                        const libtrace_packet_t *packet) {
1156#ifdef HAVE_BPF_FILTER
1157        void *linkptr = 0;
1158        uint32_t clen = 0;
1159        bool free_packet_needed = false;
1160        int ret;
1161        libtrace_packet_t *packet_copy = (libtrace_packet_t*)packet;
1162
1163        assert(filter);
1164        assert(packet);
1165
1166        if (libtrace_to_pcap_dlt(trace_get_link_type(packet))==~0U) {
1167                /* Copy the packet, as we don't want to trash the one we
1168                 * were passed in
1169                 */
1170                packet_copy=trace_copy_packet(packet);
1171                free_packet_needed=true;
1172                while (libtrace_to_pcap_dlt(trace_get_link_type(packet_copy))==
1173                                ~0U) {
1174                        if (!demote_packet(packet_copy)) {
1175                                trace_set_err(packet->trace, 
1176                                                TRACE_ERR_NO_CONVERSION,
1177                                                "pcap does not support this format");
1178                                if (free_packet_needed) {
1179                                        trace_destroy_packet(packet_copy);
1180                                }
1181                                return -1;
1182                        }
1183                }
1184        }
1185       
1186        linkptr = trace_get_packet_buffer(packet_copy,NULL,&clen);
1187        if (!linkptr) {
1188                if (free_packet_needed) {
1189                        trace_destroy_packet(packet_copy);
1190                }
1191                return 0;
1192        }
1193
1194        /* We need to compile it now, because before we didn't know what the
1195         * link type was
1196         */
1197        if (trace_bpf_compile(filter,packet_copy)==-1) {
1198                if (free_packet_needed) {
1199                        trace_destroy_packet(packet_copy);
1200                }
1201                return -1;
1202        }
1203
1204        assert(filter->flag);
1205        ret=bpf_filter(filter->filter.bf_insns,(u_char*)linkptr,(unsigned int)clen,(unsigned int)clen);
1206        if (free_packet_needed) {
1207                trace_destroy_packet(packet_copy);
1208        }
1209        return ret;
1210#else
1211        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1212        return 0;
1213#endif
1214}
1215
1216/* Set the direction flag, if it has one
1217 * @param packet the packet opaque pointer
1218 * @param direction the new direction (0,1,2,3)
1219 * @returns a signed value containing the direction flag, or -1 if this is not supported
1220 */
1221DLLEXPORT libtrace_direction_t trace_set_direction(libtrace_packet_t *packet, 
1222                libtrace_direction_t direction) 
1223{
1224        assert(packet);
1225        if (packet->trace->format->set_direction) {
1226                return packet->trace->format->set_direction(packet,direction);
1227        }
1228        return (libtrace_direction_t)~0U;
1229}
1230
1231/* Get the direction flag, if it has one
1232 * @param packet a pointer to a libtrace_packet structure
1233 * @returns a signed value containing the direction flag, or -1 if this is not supported
1234 * The direction is defined as 0 for packets originating locally (ie, outbound)
1235 * and 1 for packets originating remotely (ie, inbound).
1236 * Other values are possible, which might be overloaded to mean special things
1237 * for a special trace.
1238 * @author Daniel Lawson
1239 */
1240DLLEXPORT libtrace_direction_t trace_get_direction(const libtrace_packet_t *packet) 
1241{
1242        assert(packet);
1243        if (packet->trace->format->get_direction) {
1244                return packet->trace->format->get_direction(packet);
1245        }
1246        return (libtrace_direction_t)~0U;
1247}
1248
1249#define ROOT_SERVER(x) ((x) < 512)
1250#define ROOT_CLIENT(x) ((512 <= (x)) && ((x) < 1024))
1251#define NONROOT_SERVER(x) ((x) >= 5000)
1252#define NONROOT_CLIENT(x) ((1024 <= (x)) && ((x) < 5000))
1253#define DYNAMIC(x) ((49152 < (x)) && ((x) < 65535))
1254#define SERVER(x) ROOT_SERVER(x) || NONROOT_SERVER(x)
1255#define CLIENT(x) ROOT_CLIENT(x) || NONROOT_CLIENT(x)
1256
1257/* Attempt to deduce the 'server' port
1258 * @param protocol the IP protocol (eg, 6 or 17 for TCP or UDP)
1259 * @param source the TCP or UDP source port
1260 * @param dest the TCP or UDP destination port
1261 * @returns a hint as to which port is the server port
1262 */
1263DLLEXPORT int8_t trace_get_server_port(UNUSED uint8_t protocol, 
1264                uint16_t source, uint16_t dest) 
1265{
1266        /*
1267         * * If the ports are equal, return DEST
1268         * * Check for well-known ports in the given protocol
1269         * * Root server ports: 0 - 511
1270         * * Root client ports: 512 - 1023
1271         * * non-root client ports: 1024 - 4999
1272         * * non-root server ports: 5000+
1273         * * Check for static ranges: 1024 - 49151
1274         * * Check for dynamic ranges: 49152 - 65535
1275         * * flip a coin.
1276         */
1277       
1278        /* equal */
1279        if (source == dest)
1280                return USE_DEST;
1281
1282        /* root server port, 0 - 511 */
1283        if (ROOT_SERVER(source) && ROOT_SERVER(dest)) {
1284                if (source < dest)
1285                        return USE_SOURCE;
1286                return USE_DEST;
1287        }
1288
1289        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1290                return USE_SOURCE;
1291        if (!ROOT_SERVER(source) && ROOT_SERVER(dest))
1292                return USE_DEST;
1293
1294        /* non-root server */
1295        if (NONROOT_SERVER(source) && NONROOT_SERVER(dest)) {
1296                if (source < dest)
1297                        return USE_SOURCE;
1298                return USE_DEST;
1299        }
1300        if (NONROOT_SERVER(source) && !NONROOT_SERVER(dest))
1301                return USE_SOURCE;
1302        if (!NONROOT_SERVER(source) && NONROOT_SERVER(dest))
1303                return USE_DEST;
1304
1305        /* root client */
1306        if (ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1307                if (source < dest)
1308                        return USE_SOURCE;
1309                return USE_DEST;
1310        }
1311        if (ROOT_CLIENT(source) && !ROOT_CLIENT(dest)) {
1312                /* prefer root-client over nonroot-client */
1313                if (NONROOT_CLIENT(dest))
1314                        return USE_SOURCE;
1315                return USE_DEST;
1316        }
1317        if (!ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1318                /* prefer root-client over nonroot-client */
1319                if (NONROOT_CLIENT(source))
1320                        return USE_DEST;
1321                return USE_SOURCE;
1322        }
1323       
1324        /* nonroot client */
1325        if (NONROOT_CLIENT(source) && NONROOT_CLIENT(dest)) {
1326                if (source < dest) 
1327                        return USE_SOURCE;
1328                return USE_DEST;
1329        }
1330        if (NONROOT_CLIENT(source) && !NONROOT_CLIENT(dest))
1331                return USE_DEST;
1332        if (!NONROOT_CLIENT(source) && NONROOT_CLIENT(dest))
1333                return USE_SOURCE;
1334
1335        /* dynamic range */
1336        if (DYNAMIC(source) && DYNAMIC(dest)) {
1337                if (source < dest)
1338                        return USE_SOURCE;
1339                return USE_DEST;
1340        }
1341        if (DYNAMIC(source) && !DYNAMIC(dest))
1342                return USE_DEST;
1343        if (!DYNAMIC(source) && DYNAMIC(dest))
1344                return USE_SOURCE;
1345        /*
1346        if (SERVER(source) && CLIENT(dest))
1347                return USE_SOURCE;
1348       
1349        if (SERVER(dest) && CLIENT(source))
1350                return USE_DEST;
1351        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1352                return USE_SOURCE;
1353        if (ROOT_SERVER(dest) && !ROOT_SERVER(source))
1354                return USE_DEST;
1355        */
1356        /* failing that test... */
1357        if (source < dest) {
1358                return USE_SOURCE;
1359        } 
1360        return USE_DEST;
1361       
1362}
1363
1364/* Truncate the packet at the suggested length
1365 * @param packet        the packet opaque pointer
1366 * @param size          the new length of the packet
1367 * @returns the new size of the packet
1368 * @note size and the return size refer to the network-level payload of the
1369 * packet, and do not include any capture headers. For example, to truncate a
1370 * packet after the IP header, set size to sizeof(ethernet_header) +
1371 * sizeof(ip_header)
1372 * @note If the original network-level payload is smaller than size, then the
1373 * original size is returned and the packet is left unchanged.
1374 * @author Daniel Lawson
1375 */
1376DLLEXPORT size_t trace_set_capture_length(libtrace_packet_t *packet, size_t size) {
1377        assert(packet);
1378
1379        if (packet->trace->format->set_capture_length) {
1380                return packet->trace->format->set_capture_length(packet,size);
1381        }
1382
1383        return ~0U;
1384}
1385
1386DLLEXPORT const char * trace_parse_uri(const char *uri, char **format) {
1387        const char *uridata = 0;
1388       
1389        if((uridata = strchr(uri,':')) == NULL) {
1390                /* badly formed URI - needs a : */
1391                return 0;
1392        }
1393
1394        if ((unsigned)(uridata - uri) > URI_PROTO_LINE) {
1395                /* badly formed URI - uri type is too long */
1396                return 0;
1397        }
1398
1399        *format=xstrndup(uri, (size_t)(uridata - uri));
1400
1401        /* push uridata past the delimiter */
1402        uridata++;
1403       
1404        return uridata;
1405}
1406
1407enum base_format_t trace_get_format(libtrace_packet_t *packet) 
1408{
1409        assert(packet);
1410
1411        return packet->trace->format->type;
1412}
1413       
1414DLLEXPORT libtrace_err_t trace_get_err(libtrace_t *trace)
1415{
1416        libtrace_err_t err = trace->err;
1417        trace->err.err_num = 0; /* "OK" */
1418        trace->err.problem[0]='\0';
1419        return err;
1420}
1421
1422DLLEXPORT bool trace_is_err(libtrace_t *trace)
1423{
1424        return trace->err.err_num != 0;
1425}
1426
1427DLLEXPORT void trace_perror(libtrace_t *trace,const char *msg,...)
1428{
1429        char buf[256];
1430        va_list va;
1431        va_start(va,msg);
1432        vsnprintf(buf,sizeof(buf),msg,va);
1433        va_end(va);
1434        if(trace->err.err_num) {
1435                fprintf(stderr,"%s(%s): %s\n",
1436                                buf,trace->uridata,trace->err.problem);
1437        } else {
1438                fprintf(stderr,"%s(%s): No error\n",
1439                                buf,trace->uridata);
1440        }
1441        trace->err.err_num = 0; /* "OK" */
1442        trace->err.problem[0]='\0';
1443}
1444
1445DLLEXPORT libtrace_err_t trace_get_err_output(libtrace_out_t *trace)
1446{
1447        libtrace_err_t err = trace->err;
1448        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1449        trace->err.problem[0]='\0';
1450        return err;
1451}
1452
1453DLLEXPORT bool trace_is_err_output(libtrace_out_t *trace)
1454{
1455        return trace->err.err_num != 0;
1456}
1457
1458DLLEXPORT void trace_perror_output(libtrace_out_t *trace,const char *msg,...)
1459{
1460        char buf[256];
1461        va_list va;
1462        va_start(va,msg);
1463        vsnprintf(buf,sizeof(buf),msg,va);
1464        va_end(va);
1465        if(trace->err.err_num) {
1466                fprintf(stderr,"%s(%s): %s\n",
1467                                buf,
1468                                trace->uridata?trace->uridata:"no uri",
1469                                trace->err.problem);
1470        } else {
1471                fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1472        }
1473        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1474        trace->err.problem[0]='\0';
1475}
1476
1477DLLEXPORT int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts)
1478{
1479        if (trace->format->seek_erf) {
1480                return trace->format->seek_erf(trace,ts);
1481        }
1482        else {
1483                if (trace->format->seek_timeval) {
1484                        struct timeval tv;
1485#if __BYTE_ORDER == __BIG_ENDIAN
1486                        tv.tv_sec = ts & 0xFFFFFFFF;
1487#elif __BYTE_ORDER == __LITTLE_ENDIAN
1488                        tv.tv_sec = ts >> 32;
1489#else
1490#error "What on earth are you running this on?"
1491#endif
1492                        tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1493                        if (tv.tv_usec >= 1000000) {
1494                                tv.tv_usec -= 1000000;
1495                                tv.tv_sec += 1;
1496                        }
1497                        return trace->format->seek_timeval(trace,tv);
1498                }
1499                if (trace->format->seek_seconds) {
1500                        double seconds = 
1501                                (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1502                        return trace->format->seek_seconds(trace,seconds);
1503                }
1504                trace_set_err(trace,
1505                                TRACE_ERR_OPTION_UNAVAIL,
1506                                "Feature unimplemented");
1507                return -1;
1508        }
1509}
1510
1511DLLEXPORT int trace_seek_seconds(libtrace_t *trace, double seconds)
1512{
1513        if (trace->format->seek_seconds) {
1514                return trace->format->seek_seconds(trace,seconds);
1515        }
1516        else {
1517                if (trace->format->seek_timeval) {
1518                        struct timeval tv;
1519                        tv.tv_sec = (uint32_t)seconds;
1520                        tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1521                        return trace->format->seek_timeval(trace,tv);
1522                }
1523                if (trace->format->seek_erf) {
1524                        uint64_t timestamp = 
1525                                ((uint64_t)((uint32_t)seconds) << 32) + \
1526                            (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
1527                        return trace->format->seek_erf(trace,timestamp);
1528                }
1529                trace_set_err(trace,
1530                                TRACE_ERR_OPTION_UNAVAIL,
1531                                "Feature unimplemented");
1532                return -1;
1533        }
1534}
1535
1536DLLEXPORT int trace_seek_timeval(libtrace_t *trace, struct timeval tv)
1537{
1538        if (trace->format->seek_timeval) {
1539                return trace->format->seek_timeval(trace,tv);
1540        }
1541        else {
1542                if (trace->format->seek_erf) {
1543                        uint64_t timestamp = ((((uint64_t)tv.tv_sec) << 32) + \
1544                                (((uint64_t)tv.tv_usec * UINT_MAX)/1000000));
1545                        return trace->format->seek_erf(trace,timestamp);
1546                }
1547                if (trace->format->seek_seconds) {
1548                        double seconds = tv.tv_sec + ((tv.tv_usec * 1.0)/1000000);
1549                        return trace->format->seek_seconds(trace,seconds);
1550                }
1551                trace_set_err(trace,
1552                                TRACE_ERR_OPTION_UNAVAIL,
1553                                "Feature unimplemented");
1554                return -1;
1555        }
1556}
1557
1558DLLEXPORT char *trace_ether_ntoa(const uint8_t *addr, char *buf)
1559{
1560        static char staticbuf[18]={0,};
1561        if (!buf)
1562                buf=staticbuf;
1563        snprintf(buf,(size_t)18,"%02x:%02x:%02x:%02x:%02x:%02x",
1564                        addr[0],addr[1],addr[2],
1565                        addr[3],addr[4],addr[5]);
1566        return buf;
1567}
1568
1569DLLEXPORT uint8_t *trace_ether_aton(const char *buf, uint8_t *addr)
1570{
1571        uint8_t *buf2 = addr;
1572        unsigned int tmp[6];
1573        static uint8_t staticaddr[6];
1574        if (!buf2)
1575                buf2=staticaddr;
1576        sscanf(buf,"%x:%x:%x:%x:%x:%x",
1577                        &tmp[0],&tmp[1],&tmp[2],
1578                        &tmp[3],&tmp[4],&tmp[5]);
1579        buf2[0]=tmp[0]; buf2[1]=tmp[1]; buf2[2]=tmp[2];
1580        buf2[3]=tmp[3]; buf2[4]=tmp[4]; buf2[5]=tmp[5];
1581        return buf2;
1582}
1583
1584DLLEXPORT
1585void trace_construct_packet(libtrace_packet_t *packet,
1586                libtrace_linktype_t linktype,
1587                const void *data,
1588                uint16_t len)
1589{
1590        size_t size;
1591        static libtrace_t *deadtrace=NULL;
1592        libtrace_pcapfile_pkt_hdr_t hdr;
1593#ifdef WIN32
1594        struct _timeb tstruct;
1595#else
1596        struct timeval tv;
1597#endif
1598
1599        if (NULL == deadtrace) 
1600                deadtrace=trace_create_dead("pcapfile");
1601
1602#ifdef WIN32
1603        _ftime(&tstruct);
1604        hdr.ts_sec=tstruct.time;
1605        hdr.ts_usec=tstruct.millitm * 1000;
1606#else
1607        gettimeofday(&tv,NULL);
1608        hdr.ts_sec=tv.tv_sec;
1609        hdr.ts_usec=tv.tv_usec;
1610#endif
1611
1612        hdr.caplen=len;
1613        hdr.wirelen=len;
1614
1615        packet->trace=deadtrace;
1616        size=len+sizeof(hdr);
1617        if (packet->buf_control==TRACE_CTRL_PACKET) {
1618                packet->buffer=realloc(packet->buffer,size);
1619        }
1620        else {
1621                packet->buffer=malloc(size);
1622        }
1623        packet->buf_control=TRACE_CTRL_PACKET;
1624        packet->header=packet->buffer;
1625        packet->payload=(void*)((char*)packet->buffer+sizeof(hdr));
1626        memcpy(packet->header,&hdr,sizeof(hdr));
1627        memcpy(packet->payload,data,(size_t)len);
1628        packet->type=pcap_linktype_to_rt(libtrace_to_pcap_linktype(linktype));
1629}
1630
1631
1632uint64_t trace_get_received_packets(libtrace_t *trace)
1633{
1634        assert(trace);
1635        if (trace->format->get_received_packets) {
1636                return trace->format->get_received_packets(trace);
1637        }
1638        return (uint64_t)-1;
1639}
1640
1641uint64_t trace_get_filtered_packets(libtrace_t *trace)
1642{
1643        assert(trace);
1644        if (trace->format->get_filtered_packets) {
1645                return trace->format->get_filtered_packets(trace)+
1646                        trace->filtered_packets;
1647        }
1648        if (trace->format->get_received_packets
1649                && trace->format->get_dropped_packets) {
1650                return 
1651                        ((trace_get_received_packets(trace)
1652                        -trace_get_accepted_packets(trace))
1653                        -trace_get_dropped_packets(trace))
1654                        +trace->filtered_packets;
1655        }
1656        return trace->filtered_packets;
1657}
1658
1659uint64_t trace_get_dropped_packets(libtrace_t *trace)
1660{
1661        assert(trace);
1662        if (trace->format->get_dropped_packets) {
1663                return trace->format->get_dropped_packets(trace);
1664        }
1665        return (uint64_t)-1;
1666}
1667
1668uint64_t trace_get_accepted_packets(libtrace_t *trace)
1669{
1670        assert(trace);
1671        return trace->accepted_packets;
1672}
1673
Note: See TracBrowser for help on using the repository browser.