source: lib/trace.c @ 771ab22

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 771ab22 was 035f8a7, checked in by Dan Collins <dan@…>, 6 years ago

Massive refactor that involves moving ring out into its own file.

format_linux is pretty unmaintainable the way it is, so this branch covers
trying to fix that. Ring is basically a subclass of native, so we use OOP
techniques to reduce code duplication. Putting ring in its own file makes
maintaining the code a lot easier as there is less code to read.

The ring format has been spun off, we just need to finish tidying the
native format (stripping out ring, FORMAT(x) turns to FORMAT_DATA etc).
There's bound to be errors in getting it going, but it should be fairly
smooth sailing.

Finally, work was started in moving from the old format design to the
new format design where threaded or not there is a list holding the
per_stream format data.

  • Property mode set to 100644
File size: 58.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#define _GNU_SOURCE
36#include "common.h"
37#include "config.h"
38#include <assert.h>
39#include <errno.h>
40#include <fcntl.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <sys/stat.h>
45#include <sys/types.h>
46#ifndef WIN32
47#include <sys/socket.h>
48#endif
49#include <stdarg.h>
50#include <sys/param.h>
51
52#ifdef HAVE_LIMITS_H
53#  include <limits.h>
54#endif
55
56#ifdef HAVE_SYS_LIMITS_H
57#  include <sys/limits.h>
58#endif
59
60#ifdef HAVE_NET_IF_ARP_H
61#  include <net/if_arp.h>
62#endif
63
64#ifdef HAVE_NET_IF_H
65#  include <net/if.h>
66#endif
67
68#ifdef HAVE_NETINET_IN_H
69#  include <netinet/in.h>
70#endif
71
72#ifdef HAVE_NET_ETHERNET_H
73#  include <net/ethernet.h>
74#endif
75
76#ifdef HAVE_NETINET_IF_ETHER_H
77#  include <netinet/if_ether.h>
78#endif
79
80#include <time.h>
81#ifdef WIN32
82#include <sys/timeb.h>
83#endif
84
85#include "libtrace.h"
86#include "libtrace_int.h"
87
88#ifdef HAVE_PCAP_BPF_H
89#  include <pcap-bpf.h>
90#else
91#  ifdef HAVE_NET_BPF_H
92#    include <net/bpf.h>
93#  endif
94#endif
95
96
97#include "libtrace_int.h"
98#include "format_helper.h"
99#include "rt_protocol.h"
100
101#include <pthread.h>
102#include <signal.h>
103
104#define MAXOPTS 1024
105
106/* This file contains much of the implementation of the libtrace API itself. */
107
108static struct libtrace_format_t *formats_list = NULL;
109
110volatile int libtrace_halt = 0;
111
112/* Set once pstart is called used for backwards compatibility reasons */
113int libtrace_parallel = 0;
114
115/* strncpy is not assured to copy the final \0, so we
116 * will use our own one that does
117 */
118static void xstrncpy(char *dest, const char *src, size_t n)
119{
120        strncpy(dest,src,n);
121        dest[n]='\0';
122}
123 
124static char *xstrndup(const char *src,size_t n)
125{       
126        char *ret=(char*)malloc(n+1);
127        if (ret==NULL) {
128                fprintf(stderr,"Out of memory");
129                exit(EXIT_FAILURE);
130        }
131        xstrncpy(ret,src,n);
132        return ret;
133}
134
135
136/* call all the constructors if they haven't yet all been called */
137static void trace_init(void)
138{
139        if (!formats_list) {
140                duck_constructor();
141                erf_constructor();
142                tsh_constructor();
143                legacy_constructor();
144                atmhdr_constructor();
145                linuxring_constructor();
146                linuxnative_constructor();
147#ifdef HAVE_LIBPCAP
148                pcap_constructor();
149#endif
150                bpf_constructor();
151                pcapfile_constructor();
152                rt_constructor();
153#ifdef HAVE_DAG
154                dag_constructor();
155#endif
156#ifdef HAVE_DPDK
157        dpdk_constructor();
158#endif
159        }
160}
161
162/* Prints help information for libtrace
163 *
164 * Function prints out some basic help information regarding libtrace,
165 * and then prints out the help() function registered with each input module
166 */
167DLLEXPORT void trace_help(void) {
168        struct libtrace_format_t *tmp;
169        trace_init();
170        printf("libtrace %s\n\n",PACKAGE_VERSION);
171        printf("Following this are a list of the format modules supported in this build of libtrace\n\n");
172        for(tmp=formats_list;tmp;tmp=tmp->next) {
173                if (tmp->help)
174                        tmp->help();
175        }
176}
177
178#define URI_PROTO_LINE 16U
179
180/* Try to guess which format module is appropriate for a given trace file or
181 * device */
182static void guess_format(libtrace_t *libtrace, const char *filename)
183{
184        struct libtrace_format_t *tmp;
185       
186        /* Try and guess based on filename */
187        for(tmp = formats_list; tmp; tmp=tmp->next) {
188                if (tmp->probe_filename && tmp->probe_filename(filename)) {
189                        libtrace->format = tmp;
190                        libtrace->uridata = strdup(filename);
191                        return;
192                }
193        }
194
195        libtrace->io = wandio_create(filename);
196        if (!libtrace->io)
197                return;
198
199        /* Try and guess based on file magic */
200        for(tmp = formats_list; tmp; tmp=tmp->next) {
201                if (tmp->probe_magic && tmp->probe_magic(libtrace->io)) {
202                        libtrace->format = tmp;
203                        libtrace->uridata = strdup(filename);
204                        return;
205                }
206        }
207       
208        /* Oh well */
209        return;
210}
211
212/* Creates an input trace from a URI
213 *
214 * @params char * containing a valid libtrace URI
215 * @returns opaque pointer to a libtrace_t
216 *
217 * Some valid URI's are:
218 *  erf:/path/to/erf/file
219 *  erf:/path/to/erf/file.gz
220 *  erf:-                       (stdin)
221 *  dag:/dev/dagcard
222 *  pcapint:pcapinterface               (eg: pcapint:eth0)
223 *  pcapfile:/path/to/pcap/file
224 *  pcapfile:-
225 *  int:interface                       (eg: int:eth0) only on Linux
226 *  rt:hostname
227 *  rt:hostname:port
228 *
229 * If an error occured when attempting to open a trace, NULL is returned
230 * and an error is output to stdout.
231 */
232DLLEXPORT libtrace_t *trace_create(const char *uri) {
233        libtrace_t *libtrace = 
234                        (libtrace_t *)malloc(sizeof(libtrace_t));
235        char *scan = 0;
236        const char *uridata = 0;                 
237
238        trace_init();
239
240        assert(uri && "Passing NULL to trace_create makes me a very sad program");
241
242        if (!libtrace) {
243                /* Out of memory */
244                return NULL;
245        }
246       
247        libtrace->err.err_num = TRACE_ERR_NOERROR;
248        libtrace->format=NULL;
249       
250        libtrace->event.tdelta = 0.0;
251        libtrace->event.packet = NULL;
252        libtrace->event.psize = 0;
253        libtrace->event.trace_last_ts = 0.0;
254        libtrace->event.waiting = false;
255        libtrace->filter = NULL;
256        libtrace->snaplen = 0;
257        libtrace->started=false;
258        libtrace->uridata = NULL;
259        libtrace->io = NULL;
260        libtrace->filtered_packets = 0;
261        libtrace->accepted_packets = 0;
262       
263        /* Parallel inits */
264        ASSERT_RET(pthread_mutex_init(&libtrace->libtrace_lock, NULL), == 0);
265        ASSERT_RET(pthread_cond_init(&libtrace->perpkt_cond, NULL), == 0);
266        libtrace->state = STATE_NEW;
267        libtrace->perpkt_queue_full = false;
268        libtrace->global_blob = NULL;
269        libtrace->per_pkt = NULL;
270        libtrace->reporter = NULL;
271        libtrace->hasher = NULL;
272        libtrace_zero_ocache(&libtrace->packet_freelist);
273        libtrace_zero_thread(&libtrace->hasher_thread);
274        libtrace_zero_thread(&libtrace->reporter_thread);
275        libtrace_zero_thread(&libtrace->keepalive_thread);
276        libtrace->reporter_thread.type = THREAD_EMPTY;
277        libtrace->perpkt_thread_count = 0;
278        libtrace->perpkt_threads = NULL;
279        libtrace->tracetime = 0;
280        libtrace->first_packets.first = 0;
281        libtrace->first_packets.count = 0;
282        libtrace->first_packets.packets = NULL;
283        libtrace->dropped_packets = UINT64_MAX;
284        libtrace->received_packets = UINT64_MAX;
285        ZERO_USER_CONFIG(libtrace->config);
286
287        /* Parse the URI to determine what sort of trace we are dealing with */
288        if ((uridata = trace_parse_uri(uri, &scan)) == 0) {
289                /* Could not parse the URI nicely */
290                guess_format(libtrace,uri);
291                if (!libtrace->format) {
292                        trace_set_err(libtrace,TRACE_ERR_BAD_FORMAT,"Unable to guess format (%s)",uri);
293                        return libtrace;
294                }
295        }
296        else {
297                struct libtrace_format_t *tmp;
298
299                /* Find a format that matches the first part of the URI */
300                for (tmp=formats_list;tmp;tmp=tmp->next) {
301                        if (strlen(scan) == strlen(tmp->name) &&
302                                        strncasecmp(scan, tmp->name, strlen(scan)) == 0
303                                        ) {
304                                libtrace->format=tmp;
305                                break;
306                        }
307                }
308
309                if (libtrace->format == 0) {
310                        trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT,
311                                        "Unknown format (%s)",scan);
312                        return libtrace;
313                }
314
315                libtrace->uridata = strdup(uridata);
316        }
317        /* libtrace->format now contains the type of uri
318         * libtrace->uridata contains the appropriate data for this
319         */
320       
321        /* Call the init_input function for the matching capture format */ 
322        if (libtrace->format->init_input) {
323                int err=libtrace->format->init_input(libtrace);
324                assert (err==-1 || err==0);
325                if (err==-1) {
326                        /* init_input should call trace_set_err to set
327                         * the error message
328                         */
329                        return libtrace;
330                }
331        } else {
332                trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,
333                                "Format does not support input (%s)",scan);
334                return libtrace;
335        }
336       
337        if (scan)
338                free(scan);
339        libtrace->err.err_num=TRACE_ERR_NOERROR;
340        libtrace->err.problem[0]='\0';
341        return libtrace;
342}
343
344/* Creates a "dummy" trace file that has only the format type set.
345 *
346 * @returns opaque pointer to a (sparsely initialised) libtrace_t
347 *
348 * IMPORTANT: Do not attempt to call trace_read_packet or other such functions
349 * with the dummy trace. Its intended purpose is to act as a packet->trace for
350 * libtrace_packet_t's that are not associated with a libtrace_t structure.
351 */
352DLLEXPORT libtrace_t * trace_create_dead (const char *uri) {
353        libtrace_t *libtrace = (libtrace_t *) malloc(sizeof(libtrace_t));
354        char *scan = (char *)calloc(sizeof(char),URI_PROTO_LINE);
355        char *uridata;
356        struct libtrace_format_t *tmp;
357
358        trace_init();
359       
360        libtrace->err.err_num = TRACE_ERR_NOERROR;
361
362        if((uridata = strchr(uri,':')) == NULL) {
363                xstrncpy(scan, uri, strlen(uri));
364        } else {
365                xstrncpy(scan,uri, (size_t)(uridata - uri));
366        }
367       
368        libtrace->err.err_num = TRACE_ERR_NOERROR;
369        libtrace->format=NULL;
370       
371        libtrace->event.tdelta = 0.0;
372        libtrace->event.packet = NULL;
373        libtrace->event.psize = 0;
374        libtrace->event.trace_last_ts = 0.0;
375        libtrace->filter = NULL;
376        libtrace->snaplen = 0;
377        libtrace->started=false;
378        libtrace->uridata = NULL;
379        libtrace->io = NULL;
380        libtrace->filtered_packets = 0;
381       
382        /* Parallel inits */
383        ASSERT_RET(pthread_mutex_init(&libtrace->libtrace_lock, NULL), == 0);
384        ASSERT_RET(pthread_cond_init(&libtrace->perpkt_cond, NULL), == 0);
385        libtrace->state = STATE_NEW; // TODO MAYBE DEAD
386        libtrace->perpkt_queue_full = false;
387        libtrace->global_blob = NULL;
388        libtrace->per_pkt = NULL;
389        libtrace->reporter = NULL;
390        libtrace->hasher = NULL;
391        libtrace_zero_ocache(&libtrace->packet_freelist);
392        libtrace_zero_thread(&libtrace->hasher_thread);
393        libtrace_zero_thread(&libtrace->reporter_thread);
394        libtrace_zero_thread(&libtrace->keepalive_thread);
395        libtrace->reporter_thread.type = THREAD_EMPTY;
396        libtrace->perpkt_thread_count = 0;
397        libtrace->perpkt_threads = NULL;
398        libtrace->tracetime = 0;
399        ZERO_USER_CONFIG(libtrace->config);
400       
401        for(tmp=formats_list;tmp;tmp=tmp->next) {
402                if (strlen(scan) == strlen(tmp->name) &&
403                                !strncasecmp(scan,
404                                        tmp->name,
405                                        strlen(scan))) {
406                                libtrace->format=tmp;
407                                break;
408                                }
409        }
410        if (libtrace->format == 0) {
411                trace_set_err(libtrace,TRACE_ERR_BAD_FORMAT,
412                                "Unknown format (%s)",scan);
413        }
414
415        libtrace->format_data = NULL;
416        free(scan);
417        return libtrace;
418
419}
420
421/* Creates an output trace from a URI.
422 *
423 * @param uri   the uri string describing the output format and destination
424 * @returns opaque pointer to a libtrace_output_t
425 *
426 *  If an error occured when attempting to open the output trace, NULL is
427 *  returned and trace_errno is set.
428 */
429       
430DLLEXPORT libtrace_out_t *trace_create_output(const char *uri) {
431        libtrace_out_t *libtrace = 
432                        (libtrace_out_t*)malloc(sizeof(libtrace_out_t));
433       
434        char *scan = 0;
435        const char *uridata = 0;
436        struct libtrace_format_t *tmp;
437
438        trace_init();
439
440        libtrace->err.err_num = TRACE_ERR_NOERROR;
441        strcpy(libtrace->err.problem,"Error message set\n");
442        libtrace->format = NULL;
443        libtrace->uridata = NULL;
444       
445        /* Parse the URI to determine what capture format we want to write */
446
447        if ((uridata = trace_parse_uri(uri, &scan)) == 0) {
448                trace_set_err_out(libtrace,TRACE_ERR_BAD_FORMAT,
449                                "Bad uri format (%s)",uri);
450                return libtrace;
451        }
452       
453        /* Attempt to find the format in the list of supported formats */
454        for(tmp=formats_list;tmp;tmp=tmp->next) {
455                if (strlen(scan) == strlen(tmp->name) &&
456                                !strncasecmp(scan,
457                                        tmp->name,
458                                        strlen(scan))) {
459                                libtrace->format=tmp;
460                                break;
461                                }
462        }
463        free(scan);
464
465        if (libtrace->format == NULL) {
466                trace_set_err_out(libtrace,TRACE_ERR_BAD_FORMAT,
467                                "Unknown output format (%s)",scan);
468                return libtrace;
469        }
470        libtrace->uridata = strdup(uridata);
471
472        /* libtrace->format now contains the type of uri
473         * libtrace->uridata contains the appropriate data for this
474         */
475
476        if (libtrace->format->init_output) {
477                /* 0 on success, -1 on failure */
478                switch(libtrace->format->init_output(libtrace)) {
479                        case -1: /* failure */
480                                return libtrace;
481                        case 0: /* success */
482                                break;
483                        default:
484                                assert(!"Internal error: init_output() should return -1 for failure, or 0 for success");
485                }
486        } else {
487                trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
488                                "Format does not support writing (%s)",scan);
489                return libtrace;
490        }
491
492
493        libtrace->started=false;
494        return libtrace;
495}
496
497/* Start an input trace
498 * @param libtrace      the input trace to start
499 * @returns 0 on success
500 *
501 * This does the work associated with actually starting up
502 * the trace.  it may fail.
503 */
504DLLEXPORT int trace_start(libtrace_t *libtrace)
505{
506        assert(libtrace);
507        if (trace_is_err(libtrace))
508                return -1;
509        if (libtrace->format->start_input) {
510                int ret=libtrace->format->start_input(libtrace);
511                if (ret < 0) {
512                        return ret;
513                }
514        }
515
516        libtrace->started=true;
517        return 0;
518}
519
520/* Start an output trace */
521DLLEXPORT int trace_start_output(libtrace_out_t *libtrace) 
522{
523        assert(libtrace);
524        if (libtrace->format->start_output) {
525                int ret=libtrace->format->start_output(libtrace);
526                if (ret < 0) {
527                        return ret;
528                }
529        }
530
531        libtrace->started=true;
532        return 0;
533}
534
535DLLEXPORT int trace_pause(libtrace_t *libtrace)
536{
537        assert(libtrace);
538        if (!libtrace->started) {
539                trace_set_err(libtrace,TRACE_ERR_BAD_STATE, "You must call trace_start() before calling trace_pause()");
540                return -1;
541        }
542        if (libtrace->format->pause_input)
543                libtrace->format->pause_input(libtrace);
544        libtrace->started=false;
545        return 0;
546}
547
548DLLEXPORT int trace_config(libtrace_t *libtrace,
549                trace_option_t option,
550                void *value)
551{
552        int ret;
553
554        if (trace_is_err(libtrace)) {
555                return -1;
556        }
557       
558        /* If the capture format supports configuration, try using their
559         * native configuration first */
560        if (libtrace->format->config_input) {
561                ret=libtrace->format->config_input(libtrace,option,value);
562                if (ret==0)
563                        return 0;
564        }
565
566        /* If we get here, either the native configuration failed or the
567         * format did not support configuration. However, libtrace can
568         * deal with some options itself, so give that a go */
569        switch(option) {
570                case TRACE_OPTION_SNAPLEN:
571                        /* Clear the error if there was one */
572                        if (trace_is_err(libtrace)) {
573                                trace_get_err(libtrace);
574                        }
575                        if (*(int*)value<0 
576                                || *(int*)value>LIBTRACE_PACKET_BUFSIZE) {
577                                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,
578                                        "Invalid snap length");
579                        }
580                        libtrace->snaplen=*(int*)value;
581                        return 0;
582                case TRACE_OPTION_FILTER:
583                        /* Clear the error if there was one */
584                        if (trace_is_err(libtrace)) {
585                                trace_get_err(libtrace);
586                        }
587                        libtrace->filter=(libtrace_filter_t *)value;
588                        return 0;
589                case TRACE_OPTION_PROMISC:
590                        if (!trace_is_err(libtrace)) {
591                                trace_set_err(libtrace,TRACE_ERR_OPTION_UNAVAIL,
592                                                "Promisc mode is not supported by this format module");
593                        }
594                        return -1;
595                case TRACE_OPTION_META_FREQ:
596                        if (!trace_is_err(libtrace)) {
597                                trace_set_err(libtrace, 
598                                                TRACE_ERR_OPTION_UNAVAIL,
599                                                "This format does not support meta-data gathering");
600                        }
601                        return -1;
602                case TRACE_OPTION_EVENT_REALTIME:
603                        if (!trace_is_err(libtrace)) {
604                                trace_set_err(libtrace, 
605                                                TRACE_ERR_OPTION_UNAVAIL,
606                                                "This format does not support realtime events");
607                        }
608                        return -1;
609                       
610        }
611        if (!trace_is_err(libtrace)) {
612                trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
613                        "Unknown option %i", option);
614        }
615        return -1;
616}
617
618DLLEXPORT int trace_config_output(libtrace_out_t *libtrace, 
619                trace_option_output_t option,
620                void *value) {
621       
622        /* Unlike the input options, libtrace does not natively support any of
623         * the output options - the format module must be able to deal with
624         * them. */
625        if (libtrace->format->config_output) {
626                return libtrace->format->config_output(libtrace, option, value);
627        }
628        return -1;
629}
630
631/* Close an input trace file, freeing up any resources it may have been using
632 *
633 */
634DLLEXPORT void trace_destroy(libtrace_t *libtrace) {
635        int i;
636        assert(libtrace);
637
638        ASSERT_RET(pthread_mutex_destroy(&libtrace->libtrace_lock), == 0);
639        ASSERT_RET(pthread_cond_destroy(&libtrace->perpkt_cond), == 0);
640
641        /* destroy any packets that are still around */
642        if (libtrace->state != STATE_NEW && libtrace->first_packets.packets) {
643                for (i = 0; i < libtrace->perpkt_thread_count; ++i) {
644                        if(libtrace->first_packets.packets[i].packet) {
645                                trace_destroy_packet(libtrace->first_packets.packets[i].packet);
646                        }
647                }
648                free(libtrace->first_packets.packets);
649                ASSERT_RET(pthread_spin_destroy(&libtrace->first_packets.lock), == 0);
650        }
651
652        if (libtrace->format) {
653                if (libtrace->started && libtrace->format->pause_input)
654                        libtrace->format->pause_input(libtrace);
655                if (libtrace->format->fin_input)
656                        libtrace->format->fin_input(libtrace);
657        }
658        /* Need to free things! */
659        if (libtrace->uridata)
660                free(libtrace->uridata);
661       
662        /* Empty any packet memory */
663        if (libtrace->state != STATE_NEW) {
664                // This has all of our packets
665                libtrace_ocache_destroy(&libtrace->packet_freelist);
666                if (libtrace->combiner.destroy)
667                        libtrace->combiner.destroy(libtrace, &libtrace->combiner);
668                free(libtrace->perpkt_threads);
669                libtrace->perpkt_threads = NULL;
670                libtrace->perpkt_thread_count = 0;
671        }
672       
673        if (libtrace->event.packet) {
674                /* Don't use trace_destroy_packet here - there is almost
675                 * certainly going to be another libtrace_packet_t that is
676                 * pointing to the buffer for this packet, so we don't want
677                 * to free it. Rather, it will get freed when the user calls
678                 * trace_destroy_packet on the libtrace_packet_t that they
679                 * own.
680                 *
681                 * All we need to do then is free our packet structure itself.
682                 */
683                 free(libtrace->event.packet);
684        }
685        free(libtrace);
686}
687
688
689DLLEXPORT void trace_destroy_dead(libtrace_t *libtrace) {
690        assert(libtrace);
691
692        ASSERT_RET(pthread_mutex_destroy(&libtrace->libtrace_lock), == 0);
693        ASSERT_RET(pthread_cond_destroy(&libtrace->perpkt_cond), == 0);
694
695        /* Don't call pause_input or fin_input, because we should never have
696         * used this trace to do any reading anyway. Do make sure we free
697         * any format_data that has been created, though. */
698        if (libtrace->format_data)
699                free(libtrace->format_data);
700        free(libtrace);
701}
702/* Close an output trace file, freeing up any resources it may have been using
703 *
704 * @param libtrace      the output trace file to be destroyed
705 */
706DLLEXPORT void trace_destroy_output(libtrace_out_t *libtrace) 
707{
708        assert(libtrace);
709        if (libtrace->format && libtrace->format->fin_output)
710                libtrace->format->fin_output(libtrace);
711        if (libtrace->uridata)
712                free(libtrace->uridata);
713        free(libtrace);
714}
715
716DLLEXPORT libtrace_packet_t *trace_create_packet(void)
717{
718        libtrace_packet_t *packet =
719                (libtrace_packet_t*)calloc((size_t)1,sizeof(libtrace_packet_t));
720
721        packet->buf_control=TRACE_CTRL_PACKET;
722        trace_clear_cache(packet);
723        return packet;
724}
725
726DLLEXPORT libtrace_packet_t *trace_copy_packet(const libtrace_packet_t *packet) {
727        libtrace_packet_t *dest = 
728                (libtrace_packet_t *)malloc(sizeof(libtrace_packet_t));
729        if (!dest) {
730                printf("Out of memory constructing packet\n");
731                abort();
732        }
733        dest->trace=packet->trace;
734        dest->buffer=malloc(65536);
735        if (!dest->buffer) {
736                printf("Out of memory allocating buffer memory\n");
737                abort();
738        }
739        dest->header=dest->buffer;
740        dest->payload=(void*)
741                ((char*)dest->buffer+trace_get_framing_length(packet));
742        dest->type=packet->type;
743        dest->buf_control=TRACE_CTRL_PACKET;
744        dest->order = packet->order;
745        dest->hash = packet->hash;
746        dest->error = packet->error;
747        /* Reset the cache - better to recalculate than try to convert
748         * the values over to the new packet */
749        trace_clear_cache(dest);       
750        /* Ooooh nasty memcpys! This is why we want to avoid copying packets
751         * as much as possible */
752        memcpy(dest->header,packet->header,trace_get_framing_length(packet));
753        memcpy(dest->payload,packet->payload,trace_get_capture_length(packet));
754
755        return dest;
756}
757
758/** Destroy a packet object
759 */
760DLLEXPORT void trace_destroy_packet(libtrace_packet_t *packet) {
761        /* Free any resources possibly associated with the packet */
762        if (libtrace_parallel && packet->trace && packet->trace->format->fin_packet) {
763                packet->trace->format->fin_packet(packet);
764        }
765       
766        if (packet->buf_control == TRACE_CTRL_PACKET && packet->buffer) {
767                free(packet->buffer);
768        }
769        packet->buf_control=(buf_control_t)'\0'; 
770                                /* A "bad" value to force an assert
771                                 * if this packet is ever reused
772                                 */
773        free(packet);
774}
775
776/**
777 * Removes any possible data stored againt the trace and releases any data.
778 * This will not destroy a reusable good malloc'd buffer (TRACE_CTRL_PACKET)
779 * use trace_destroy_packet() for those diabolical purposes.
780 */
781void trace_fin_packet(libtrace_packet_t *packet) {
782        if (packet)
783        {
784                if (packet->trace && packet->trace->format->fin_packet) {
785                        packet->trace->format->fin_packet(packet);
786                        //gettimeofday(&tv, NULL);
787                        //printf ("%d.%06d DESTROYED #%"PRIu64"\n", tv.tv_sec, tv.tv_usec, trace_packet_get(packet));
788                }
789
790                // No matter what we remove the header and link pointers
791                packet->trace = NULL;
792                packet->header = NULL;
793                packet->payload = NULL;
794
795                if (packet->buf_control != TRACE_CTRL_PACKET)
796                {
797                        packet->buffer = NULL;
798                }
799
800                trace_clear_cache(packet);
801                packet->hash = 0;
802                packet->order = 0;
803        }
804}
805
806/* Read one packet from the trace into buffer. Note that this function will
807 * block until a packet is read (or EOF is reached).
808 *
809 * @param libtrace      the libtrace opaque pointer
810 * @param packet        the packet opaque pointer
811 * @returns 0 on EOF, negative value on error
812 *
813 */
814DLLEXPORT int trace_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
815
816        assert(libtrace && "You called trace_read_packet() with a NULL libtrace parameter!\n");
817        if (trace_is_err(libtrace))
818                return -1;
819        if (!libtrace->started) {
820                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"You must call libtrace_start() before trace_read_packet()\n");
821                return -1;
822        }
823        if (!(packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
824                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
825                return -1;
826        }
827        assert(packet);
828
829        if (libtrace->format->read_packet) {
830                do {
831                        size_t ret;
832                        int filtret;
833                        /* Finalise the packet, freeing any resources the format module
834                         * may have allocated it and zeroing all data associated with it.
835                         */
836                        trace_fin_packet(packet);
837                        /* Store the trace we are reading from into the packet opaque
838                         * structure */
839                        packet->trace = libtrace;
840                        ret=libtrace->format->read_packet(libtrace,packet);
841                        if (ret==(size_t)-1 || ret==0) {
842                                return ret;
843                        }
844                        if (libtrace->filter) {
845                                /* If the filter doesn't match, read another
846                                 * packet
847                                 */
848                                filtret = trace_apply_filter(libtrace->filter, packet);
849                                if (filtret == -1) {
850                                        /* Error compiling filter, probably */
851                                        return ~0U;
852                                }
853                               
854                                if (filtret == 0) {
855                                        ++libtrace->filtered_packets;
856                                        continue;
857                                }
858                        }
859                        if (libtrace->snaplen>0) {
860                                /* Snap the packet */
861                                trace_set_capture_length(packet,
862                                                libtrace->snaplen);
863                        }
864                        trace_packet_set_order(packet, libtrace->accepted_packets);
865                        ++libtrace->accepted_packets;
866                        return ret;
867                } while(1);
868        }
869        trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,"This format does not support reading packets\n");
870        return ~0U;
871}
872
873/* Converts the provided buffer into a libtrace packet of the given type.
874 *
875 * Unlike trace_construct_packet, the buffer is expected to begin with the
876 * appropriate capture format header for the format type that the packet is
877 * being converted to. This also allows for a packet to be converted into
878 * just about capture format that is supported by libtrace, provided the
879 * format header is present in the buffer.
880 *
881 * This function is primarily used to convert packets received via the RT
882 * protocol back into their original capture format. The RT header encapsulates
883 * the original capture format header, so after removing it the packet must
884 * have it's header and payload pointers updated and the packet format and type
885 * changed, amongst other things.
886 *
887 * Intended only for internal use at this point - this function is not
888 * available through the external libtrace API.
889 */
890int trace_prepare_packet(libtrace_t *trace, libtrace_packet_t *packet,
891                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
892
893        assert(packet);
894        assert(trace);
895       
896        /* XXX Proper error handling?? */
897        if (buffer == NULL)
898                return -1;
899
900        if (!(packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
901                trace_set_err(trace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
902                return -1;
903        }
904       
905        packet->trace = trace;
906       
907        /* Clear packet cache */
908        trace_clear_cache(packet);
909
910        if (trace->format->prepare_packet) {
911                return trace->format->prepare_packet(trace, packet,
912                                buffer, rt_type, flags);
913        }
914        trace_set_err(trace, TRACE_ERR_UNSUPPORTED, 
915                        "This format does not support preparing packets\n");
916        return -1;
917
918}
919
920/* Writes a packet to the specified output trace
921 *
922 * @param libtrace      describes the output format, destination, etc.
923 * @param packet        the packet to be written out
924 * @returns the number of bytes written, -1 if write failed
925 */
926DLLEXPORT int trace_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
927        assert(libtrace);
928        assert(packet);
929        /* Verify the packet is valid */
930        if (!libtrace->started) {
931                trace_set_err_out(libtrace,TRACE_ERR_BAD_STATE,
932                        "Trace is not started before trace_write_packet");
933                return -1;
934        }
935
936        if (libtrace->format->write_packet) {
937                return libtrace->format->write_packet(libtrace, packet);
938        }
939        trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
940                "This format does not support writing packets");
941        return -1;
942}
943
944/* Get a pointer to the first byte of the packet payload */
945DLLEXPORT void *trace_get_packet_buffer(const libtrace_packet_t *packet,
946                libtrace_linktype_t *linktype, uint32_t *remaining) {
947        int cap_len;
948        int wire_len;
949
950        assert(packet != NULL);
951        if (linktype) *linktype = trace_get_link_type(packet);
952        if (remaining) {
953                /* I think we should choose the minimum of the capture and
954                 * wire lengths to be the "remaining" value. If the packet has
955                 * been padded to increase the capture length, we don't want
956                 * to allow subsequent protocol decoders to consider the
957                 * padding as part of the packet.
958                 *
959                 * For example, in Auck 4 there is a trace where the IP header
960                 * length is incorrect (24 bytes) followed by a 20 byte TCP
961                 * header. Total IP length is 40 bytes. As a result, the
962                 * legacyatm padding gets treated as the "missing" bytes of
963                 * the TCP header, which isn't the greatest. We're probably
964                 * better off returning an incomplete TCP header in that case.
965                 */
966               
967                cap_len = trace_get_capture_length(packet);
968                wire_len = trace_get_wire_length(packet);
969
970                assert(cap_len >= 0);
971
972                /* There is the odd corrupt packet, e.g. in IPLS II, that have
973                 * massively negative wire lens. We could assert fail here on
974                 * them, but we could at least try the capture length instead.
975                 *
976                 * You may still run into problems if you try to write that
977                 * packet, but at least reading should work OK.
978                 */
979                if (wire_len < 0)
980                        *remaining = cap_len;
981                else if (wire_len < cap_len)
982                        *remaining = wire_len;
983                else
984                        *remaining = cap_len;
985                /* *remaining = trace_get_capture_length(packet); */
986        }
987        return (void *) packet->payload;
988}
989
990
991/* Get a pointer to the first byte of the packet payload
992 *
993 * DEPRECATED - use trace_get_packet_buffer() instead */
994DLLEXPORT void *trace_get_link(const libtrace_packet_t *packet) {
995        return (void *)packet->payload;
996}
997
998/* Get the current time in DAG time format
999 * @param packet        a pointer to a libtrace_packet structure
1000 * @returns a 64 bit timestamp in DAG ERF format (upper 32 bits are the seconds
1001 * past 1970-01-01, the lower 32bits are partial seconds)
1002 */ 
1003DLLEXPORT uint64_t trace_get_erf_timestamp(const libtrace_packet_t *packet) {
1004        if (packet->trace->format->get_erf_timestamp) {
1005                /* timestamp -> timestamp */
1006                return packet->trace->format->get_erf_timestamp(packet);
1007        } else if (packet->trace->format->get_timespec) {
1008                /* timespec -> timestamp */
1009                struct timespec ts;
1010                ts = packet->trace->format->get_timespec(packet);
1011                return ((((uint64_t)ts.tv_sec) << 32) +
1012                                (((uint64_t)ts.tv_nsec << 32)/1000000000));
1013        } else if (packet->trace->format->get_timeval) {
1014                /* timeval -> timestamp */
1015                struct timeval tv;
1016                tv = packet->trace->format->get_timeval(packet);
1017                return ((((uint64_t)tv.tv_sec) << 32) +
1018                                (((uint64_t)tv.tv_usec << 32)/1000000));
1019        } else if (packet->trace->format->get_seconds) {
1020                /* seconds -> timestamp */
1021                double seconds = packet->trace->format->get_seconds(packet);
1022                return (((uint64_t)seconds)<<32)
1023                          + (uint64_t)((seconds-(uint64_t)seconds)*UINT_MAX);
1024        }
1025        else {
1026                return (uint64_t)0;
1027        }
1028                     
1029}
1030
1031/* Get the current time in struct timeval
1032 * @param packet        a pointer to a libtrace_packet structure
1033 *
1034 * @returns time that this packet was seen in a struct timeval
1035 * @author Daniel Lawson
1036 * @author Perry Lorier
1037 */ 
1038DLLEXPORT struct timeval trace_get_timeval(const libtrace_packet_t *packet) {
1039        struct timeval tv;
1040        uint64_t ts = 0;
1041        if (packet->trace->format->get_timeval) {
1042                /* timeval -> timeval */
1043                tv = packet->trace->format->get_timeval(packet);
1044        } else if (packet->trace->format->get_erf_timestamp) {
1045                /* timestamp -> timeval */
1046                ts = packet->trace->format->get_erf_timestamp(packet);
1047                tv.tv_sec = ts >> 32;
1048                tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1049                if (tv.tv_usec >= 1000000) {
1050                        tv.tv_usec -= 1000000;
1051                        tv.tv_sec += 1;
1052                }
1053        } else if (packet->trace->format->get_timespec) {
1054                struct timespec ts = packet->trace->format->get_timespec(packet);
1055                tv.tv_sec = ts.tv_sec;
1056                tv.tv_usec = ts.tv_nsec/1000;
1057        } else if (packet->trace->format->get_seconds) {
1058                /* seconds -> timeval */
1059                double seconds = packet->trace->format->get_seconds(packet);
1060                tv.tv_sec = (uint32_t)seconds;
1061                tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1062        }
1063        else {
1064                tv.tv_sec=-1;
1065                tv.tv_usec=-1;
1066        }
1067
1068    return tv;
1069}
1070
1071DLLEXPORT struct timespec trace_get_timespec(const libtrace_packet_t *packet) {
1072        struct timespec ts;
1073
1074        if (packet->trace->format->get_timespec) {
1075                return packet->trace->format->get_timespec(packet);
1076        } else if (packet->trace->format->get_erf_timestamp) {
1077                /* timestamp -> timeval */
1078                uint64_t erfts = packet->trace->format->get_erf_timestamp(packet);
1079                ts.tv_sec = erfts >> 32;
1080                ts.tv_nsec = ((erfts&0xFFFFFFFF)*1000000000)>>32;
1081                if (ts.tv_nsec >= 1000000000) {
1082                        ts.tv_nsec -= 1000000000;
1083                        ts.tv_sec += 1;
1084                }
1085                return ts;
1086        } else if (packet->trace->format->get_timeval) {
1087                /* timeval -> timespec */
1088                struct timeval tv = packet->trace->format->get_timeval(packet);
1089                ts.tv_sec = tv.tv_sec;
1090                ts.tv_nsec = tv.tv_usec*1000;
1091                return ts;
1092        } else if (packet->trace->format->get_seconds) {
1093                /* seconds -> timespec */
1094                double seconds = packet->trace->format->get_seconds(packet);
1095                ts.tv_sec = (uint32_t)seconds;
1096                ts.tv_nsec = (long)(((seconds - ts.tv_sec) * 1000000000)/UINT_MAX);
1097                return ts;
1098        }
1099        else {
1100                ts.tv_sec=-1;
1101                ts.tv_nsec=-1;
1102                return ts;
1103        }
1104}
1105
1106
1107/* Get the current time in floating point seconds
1108 * @param packet        a pointer to a libtrace_packet structure
1109 * @returns time that this packet was seen in 64bit floating point seconds
1110 */ 
1111DLLEXPORT double trace_get_seconds(const libtrace_packet_t *packet) {
1112        double seconds = 0.0;
1113
1114        if (packet->trace->format->get_seconds) {
1115                /* seconds->seconds */
1116                seconds = packet->trace->format->get_seconds(packet);
1117        } else if (packet->trace->format->get_erf_timestamp) {
1118                /* timestamp -> seconds */
1119                uint64_t ts = 0;
1120                ts = packet->trace->format->get_erf_timestamp(packet);
1121                seconds =  (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1122        } else if (packet->trace->format->get_timespec) {
1123                /* timespec -> seconds */
1124                struct timespec ts;
1125                ts = packet->trace->format->get_timespec(packet);
1126                seconds = ts.tv_sec + ((ts.tv_nsec * 1.0) / 1000000000);
1127        } else if (packet->trace->format->get_timeval) {
1128                /* timeval -> seconds */
1129                struct timeval tv;
1130                tv = packet->trace->format->get_timeval(packet);
1131                seconds = tv.tv_sec + ((tv.tv_usec * 1.0) / 1000000);
1132        }
1133
1134        return seconds;
1135}
1136
1137DLLEXPORT size_t trace_get_capture_length(const libtrace_packet_t *packet) 
1138{
1139        /* Cache the capture length */
1140        if (packet->capture_length == -1) {
1141                if (!packet->trace->format->get_capture_length)
1142                        return ~0U;
1143                /* Cast away constness because this is "just" a cache */
1144                ((libtrace_packet_t*)packet)->capture_length = 
1145                        packet->trace->format->get_capture_length(packet);
1146        }
1147
1148        assert(packet->capture_length < LIBTRACE_PACKET_BUFSIZE);
1149
1150        return packet->capture_length;
1151}
1152       
1153/* Get the size of the packet as it was seen on the wire.
1154 * @param packet        a pointer to a libtrace_packet structure
1155 *
1156 * @returns the size of the packet as it was on the wire.
1157 * @note Due to the trace being a header capture, or anonymisation this may
1158 * not be the same as the Capture Len.
1159 */ 
1160DLLEXPORT size_t trace_get_wire_length(const libtrace_packet_t *packet){
1161       
1162        if (packet->wire_length == -1) {
1163                if (!packet->trace->format->get_wire_length) 
1164                        return ~0U;
1165                ((libtrace_packet_t *)packet)->wire_length = 
1166                        packet->trace->format->get_wire_length(packet);
1167        }
1168
1169        assert(packet->wire_length < LIBTRACE_PACKET_BUFSIZE);
1170        return packet->wire_length;
1171
1172}
1173
1174/* Get the length of the capture framing headers.
1175 * @param packet        the packet opaque pointer
1176 * @returns the size of the packet as it was on the wire.
1177 * @note this length corresponds to the difference between the size of a
1178 * captured packet in memory, and the captured length of the packet
1179 */ 
1180DLLEXPORT SIMPLE_FUNCTION
1181size_t trace_get_framing_length(const libtrace_packet_t *packet) {
1182        if (packet->trace->format->get_framing_length) {
1183                return packet->trace->format->get_framing_length(packet);
1184        }
1185        return ~0U;
1186}
1187
1188
1189/* Get the type of the link layer
1190 * @param packet        a pointer to a libtrace_packet structure
1191 * @returns libtrace_linktype_t
1192 */
1193DLLEXPORT libtrace_linktype_t trace_get_link_type(const libtrace_packet_t *packet ) {
1194
1195        if (packet->link_type == 0) {
1196                if (!packet->trace->format->get_link_type)
1197                        return TRACE_TYPE_UNKNOWN;
1198                ((libtrace_packet_t *)packet)->link_type =
1199                        packet->trace->format->get_link_type(packet);
1200        }
1201
1202        return packet->link_type;
1203}
1204
1205/* process a libtrace event
1206 * @param trace the libtrace opaque pointer
1207 * @param packet the libtrace_packet opaque pointer
1208 * @returns
1209 *  TRACE_EVENT_IOWAIT  Waiting on I/O on fd
1210 *  TRACE_EVENT_SLEEP   Next event in seconds
1211 *  TRACE_EVENT_PACKET  Packet arrived in buffer with size size
1212 *  TRACE_EVENT_TERMINATE Trace terminated (perhaps with an error condition)
1213 * FIXME currently keeps a copy of the packet inside the trace pointer,
1214 * which in turn is stored inside the new packet object...
1215 */
1216DLLEXPORT libtrace_eventobj_t trace_event(libtrace_t *trace, 
1217                libtrace_packet_t *packet) {
1218        libtrace_eventobj_t event = {TRACE_EVENT_IOWAIT,0,0.0,0};
1219
1220        if (!trace) {
1221                fprintf(stderr,"You called trace_event() with a NULL trace object!\n");
1222        }
1223        assert(trace);
1224        assert(packet);
1225
1226        /* Clear the packet cache */
1227        trace_clear_cache(packet);
1228       
1229        /* Store the trace we are reading from into the packet opaque
1230         * structure */
1231        packet->trace = trace;
1232
1233        if (packet->trace->format->trace_event) {
1234                /* Note: incrementing accepted, filtered etc. packet
1235                 * counters is handled by the format-specific
1236                 * function so don't increment them here.
1237                 */
1238                event=packet->trace->format->trace_event(trace,packet);
1239                }
1240        return event;
1241
1242}
1243
1244/** Setup a BPF filter based on pre-compiled byte-code.
1245 * @param bf_insns      A pointer to the start of the byte-code
1246 * @param bf_len        The number of BPF instructions
1247 * @returns             an opaque pointer to a libtrace_filter_t object
1248 * @note                The supplied byte-code is not checked for correctness.
1249 * @author              Scott Raynel
1250 */
1251DLLEXPORT libtrace_filter_t *
1252trace_create_filter_from_bytecode(void *bf_insns, unsigned int bf_len)
1253{
1254#ifndef HAVE_BPF_FILTER
1255        fprintf(stderr, "This version of libtrace does not have BPF support\n");
1256        return NULL;
1257#else
1258        struct libtrace_filter_t *filter = (struct libtrace_filter_t *)
1259                malloc(sizeof(struct libtrace_filter_t));
1260        filter->filter.bf_insns = (struct bpf_insn *)
1261                malloc(sizeof(struct bpf_insn) * bf_len);
1262       
1263        memcpy(filter->filter.bf_insns, bf_insns,
1264                        bf_len * sizeof(struct bpf_insn));
1265       
1266        filter->filter.bf_len = bf_len;
1267        filter->filterstring = NULL;
1268        filter->jitfilter = NULL;
1269        /* "flag" indicates that the filter member is valid */
1270        filter->flag = 1; 
1271       
1272        return filter;
1273#endif
1274}
1275
1276/* Create a BPF filter
1277 * @param filterstring a char * containing the bpf filter string
1278 * @returns opaque pointer pointer to a libtrace_filter_t object
1279 */
1280DLLEXPORT libtrace_filter_t *trace_create_filter(const char *filterstring) {
1281#ifdef HAVE_BPF_FILTER
1282        libtrace_filter_t *filter = (libtrace_filter_t*)
1283                                malloc(sizeof(libtrace_filter_t));
1284        filter->filterstring = strdup(filterstring);
1285        filter->jitfilter = NULL;
1286        filter->flag = 0;
1287        return filter;
1288#else
1289        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1290        return NULL;
1291#endif
1292}
1293
1294DLLEXPORT void trace_destroy_filter(libtrace_filter_t *filter)
1295{
1296#ifdef HAVE_BPF_FILTER
1297        free(filter->filterstring);
1298        if (filter->flag)
1299                pcap_freecode(&filter->filter);
1300#ifdef HAVE_LLVM
1301        if (filter->jitfilter) 
1302                destroy_program(filter->jitfilter);
1303#endif
1304        free(filter);
1305#else
1306
1307#endif
1308}
1309
1310/* Compile a bpf filter, now we know the link type for the trace that we're
1311 * applying it to.
1312 *
1313 * @internal
1314 *
1315 * @returns -1 on error, 0 on success
1316 */
1317static int trace_bpf_compile(libtrace_filter_t *filter,
1318                const libtrace_packet_t *packet,
1319                void *linkptr, 
1320                libtrace_linktype_t linktype    ) {
1321#ifdef HAVE_BPF_FILTER
1322        /* It just so happens that the underlying libs used by pthread arn't
1323         * thread safe, namely lex/flex thingys, so single threaded compile
1324         * multi threaded running should be safe.
1325         */
1326        static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1327        assert(filter);
1328
1329        /* If this isn't a real packet, then fail */
1330        if (!linkptr) {
1331                trace_set_err(packet->trace,
1332                                TRACE_ERR_BAD_FILTER,"Packet has no payload");
1333                return -1;
1334        }
1335       
1336        if (filter->filterstring && ! filter->flag) {
1337                pcap_t *pcap = NULL;
1338                if (linktype==(libtrace_linktype_t)-1) {
1339                        trace_set_err(packet->trace,
1340                                        TRACE_ERR_BAD_FILTER,
1341                                        "Packet has an unknown linktype");
1342                        return -1;
1343                }
1344                if (libtrace_to_pcap_dlt(linktype) == TRACE_DLT_ERROR) {
1345                        trace_set_err(packet->trace,TRACE_ERR_BAD_FILTER,
1346                                        "Unknown pcap equivalent linktype");
1347                        return -1;
1348                }
1349                assert (pthread_mutex_lock(&mutex) == 0);
1350                /* Make sure not one bet us to this */
1351                if (filter->flag) {
1352                        printf("Someone bet us to compile the filter\n");
1353                        assert (pthread_mutex_unlock(&mutex) == 0);
1354                        return 1;
1355                }
1356                pcap=(pcap_t *)pcap_open_dead(
1357                                (int)libtrace_to_pcap_dlt(linktype),
1358                                1500U);
1359                /* build filter */
1360                assert(pcap);
1361                if (pcap_compile( pcap, &filter->filter, filter->filterstring, 
1362                                        1, 0)) {
1363                        trace_set_err(packet->trace,TRACE_ERR_BAD_FILTER,
1364                                        "Unable to compile the filter \"%s\": %s", 
1365                                        filter->filterstring,
1366                                        pcap_geterr(pcap));
1367                        pcap_close(pcap);
1368                        assert (pthread_mutex_unlock(&mutex) == 0);
1369                        return -1;
1370                }
1371                pcap_close(pcap);
1372                filter->flag=1;
1373                assert (pthread_mutex_unlock(&mutex) == 0);
1374        }
1375        return 0;
1376#else
1377        assert(!"Internal bug: This should never be called when BPF not enabled");
1378        trace_set_err(packet->trace,TRACE_ERR_OPTION_UNAVAIL,
1379                                "Feature unavailable");
1380        return -1;
1381#endif
1382}
1383
1384DLLEXPORT int trace_apply_filter(libtrace_filter_t *filter,
1385                        const libtrace_packet_t *packet) {
1386#ifdef HAVE_BPF_FILTER
1387        void *linkptr = 0;
1388        uint32_t clen = 0;
1389        bool free_packet_needed = false;
1390        int ret;
1391        libtrace_linktype_t linktype;
1392        libtrace_packet_t *packet_copy = (libtrace_packet_t*)packet;
1393#ifdef HAVE_LLVM
1394        static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1395#endif
1396
1397        assert(filter);
1398        assert(packet);
1399
1400        /* Match all non-data packets as we probably want them to pass
1401         * through to the caller */
1402        linktype = trace_get_link_type(packet);
1403
1404        if (linktype == TRACE_TYPE_NONDATA)
1405                return 1;       
1406
1407        if (libtrace_to_pcap_dlt(linktype)==TRACE_DLT_ERROR) {
1408               
1409                /* If we cannot get a suitable DLT for the packet, it may
1410                 * be because the packet is encapsulated in a link type that
1411                 * does not correspond to a DLT. Therefore, we should try
1412                 * popping off headers until we either can find a suitable
1413                 * link type or we can't do any more sensible decapsulation. */
1414               
1415                /* Copy the packet, as we don't want to trash the one we
1416                 * were passed in */
1417                packet_copy=trace_copy_packet(packet);
1418                free_packet_needed=true;
1419
1420                while (libtrace_to_pcap_dlt(linktype) == TRACE_DLT_ERROR) {
1421                        if (!demote_packet(packet_copy)) {
1422                                trace_set_err(packet->trace, 
1423                                                TRACE_ERR_NO_CONVERSION,
1424                                                "pcap does not support this format");
1425                                if (free_packet_needed) {
1426                                        trace_destroy_packet(packet_copy);
1427                                }
1428                                return -1;
1429                        }
1430                        linktype = trace_get_link_type(packet_copy);
1431                }
1432
1433        }
1434       
1435        linkptr = trace_get_packet_buffer(packet_copy,NULL,&clen);
1436        if (!linkptr) {
1437                if (free_packet_needed) {
1438                        trace_destroy_packet(packet_copy);
1439                }
1440                return 0;
1441        }
1442
1443        /* We need to compile the filter now, because before we didn't know
1444         * what the link type was
1445         */
1446        // Note internal mutex locking used here
1447        if (trace_bpf_compile(filter,packet_copy,linkptr,linktype)==-1) {
1448                if (free_packet_needed) {
1449                        trace_destroy_packet(packet_copy);
1450                }
1451                return -1;
1452        }
1453
1454        /* If we're jitting, we may need to JIT the BPF code now too */
1455#if HAVE_LLVM
1456        if (!filter->jitfilter) {
1457                ASSERT_RET(pthread_mutex_lock(&mutex), == 0);
1458                /* Again double check here like the bpf filter */
1459                if(filter->jitfilter) 
1460                        printf("Someone bet us to compile the JIT thingy\n");
1461                else
1462                /* Looking at compile_program source this appears to be thread safe
1463                 * however if this gets called twice we will leak this memory :(
1464                 * as such lock here anyways */
1465                        filter->jitfilter = compile_program(filter->filter.bf_insns, filter->filter.bf_len);
1466                ASSERT_RET(pthread_mutex_unlock(&mutex), == 0);
1467        }
1468#endif
1469
1470        assert(filter->flag);
1471        /* Now execute the filter */
1472#if HAVE_LLVM
1473        ret=filter->jitfilter->bpf_run((unsigned char *)linkptr, clen);
1474#else
1475        ret=bpf_filter(filter->filter.bf_insns,(u_char*)linkptr,(unsigned int)clen,(unsigned int)clen);
1476#endif
1477
1478        /* If we copied the packet earlier, make sure that we free it */
1479        if (free_packet_needed) {
1480                trace_destroy_packet(packet_copy);
1481        }
1482        return ret;
1483#else
1484        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1485        return 0;
1486#endif
1487}
1488
1489/* Set the direction flag, if it has one
1490 * @param packet the packet opaque pointer
1491 * @param direction the new direction (0,1,2,3)
1492 * @returns a signed value containing the direction flag, or -1 if this is not supported
1493 */
1494DLLEXPORT libtrace_direction_t trace_set_direction(libtrace_packet_t *packet, 
1495                libtrace_direction_t direction) 
1496{
1497        assert(packet);
1498        if (packet->trace->format->set_direction) {
1499                return packet->trace->format->set_direction(packet,direction);
1500        }
1501        return (libtrace_direction_t)~0U;
1502}
1503
1504/* Get the direction flag, if it has one
1505 * @param packet a pointer to a libtrace_packet structure
1506 * @returns a signed value containing the direction flag, or -1 if this is not supported
1507 * The direction is defined as 0 for packets originating locally (ie, outbound)
1508 * and 1 for packets originating remotely (ie, inbound).
1509 * Other values are possible, which might be overloaded to mean special things
1510 * for a special trace.
1511 */
1512DLLEXPORT libtrace_direction_t trace_get_direction(const libtrace_packet_t *packet) 
1513{
1514        assert(packet);
1515        if (packet->trace->format->get_direction) {
1516                return packet->trace->format->get_direction(packet);
1517        }
1518        return (libtrace_direction_t)~0U;
1519}
1520
1521#define ROOT_SERVER(x) ((x) < 512)
1522#define ROOT_CLIENT(x) ((512 <= (x)) && ((x) < 1024))
1523#define NONROOT_SERVER(x) ((x) >= 5000)
1524#define NONROOT_CLIENT(x) ((1024 <= (x)) && ((x) < 5000))
1525#define DYNAMIC(x) ((49152 < (x)) && ((x) < 65535))
1526#define SERVER(x) ROOT_SERVER(x) || NONROOT_SERVER(x)
1527#define CLIENT(x) ROOT_CLIENT(x) || NONROOT_CLIENT(x)
1528
1529/* Attempt to deduce the 'server' port
1530 * @param protocol the IP protocol (eg, 6 or 17 for TCP or UDP)
1531 * @param source the TCP or UDP source port
1532 * @param dest the TCP or UDP destination port
1533 * @returns a hint as to which port is the server port
1534 */
1535DLLEXPORT int8_t trace_get_server_port(UNUSED uint8_t protocol, 
1536                uint16_t source, uint16_t dest) 
1537{
1538        /*
1539         * * If the ports are equal, return DEST
1540         * * Check for well-known ports in the given protocol
1541         * * Root server ports: 0 - 511
1542         * * Root client ports: 512 - 1023
1543         * * non-root client ports: 1024 - 4999
1544         * * non-root server ports: 5000+
1545         * * Check for static ranges: 1024 - 49151
1546         * * Check for dynamic ranges: 49152 - 65535
1547         * * flip a coin.
1548         */
1549       
1550        /* equal */
1551        if (source == dest)
1552                return USE_DEST;
1553
1554        /* root server port, 0 - 511 */
1555        if (ROOT_SERVER(source) && ROOT_SERVER(dest)) {
1556                if (source < dest)
1557                        return USE_SOURCE;
1558                return USE_DEST;
1559        }
1560
1561        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1562                return USE_SOURCE;
1563        if (!ROOT_SERVER(source) && ROOT_SERVER(dest))
1564                return USE_DEST;
1565
1566        /* non-root server */
1567        if (NONROOT_SERVER(source) && NONROOT_SERVER(dest)) {
1568                if (source < dest)
1569                        return USE_SOURCE;
1570                return USE_DEST;
1571        }
1572        if (NONROOT_SERVER(source) && !NONROOT_SERVER(dest))
1573                return USE_SOURCE;
1574        if (!NONROOT_SERVER(source) && NONROOT_SERVER(dest))
1575                return USE_DEST;
1576
1577        /* root client */
1578        if (ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1579                if (source < dest)
1580                        return USE_SOURCE;
1581                return USE_DEST;
1582        }
1583        if (ROOT_CLIENT(source) && !ROOT_CLIENT(dest)) {
1584                /* prefer root-client over nonroot-client */
1585                if (NONROOT_CLIENT(dest))
1586                        return USE_SOURCE;
1587                return USE_DEST;
1588        }
1589        if (!ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1590                /* prefer root-client over nonroot-client */
1591                if (NONROOT_CLIENT(source))
1592                        return USE_DEST;
1593                return USE_SOURCE;
1594        }
1595       
1596        /* nonroot client */
1597        if (NONROOT_CLIENT(source) && NONROOT_CLIENT(dest)) {
1598                if (source < dest) 
1599                        return USE_SOURCE;
1600                return USE_DEST;
1601        }
1602        if (NONROOT_CLIENT(source) && !NONROOT_CLIENT(dest))
1603                return USE_DEST;
1604        if (!NONROOT_CLIENT(source) && NONROOT_CLIENT(dest))
1605                return USE_SOURCE;
1606
1607        /* dynamic range */
1608        if (DYNAMIC(source) && DYNAMIC(dest)) {
1609                if (source < dest)
1610                        return USE_SOURCE;
1611                return USE_DEST;
1612        }
1613        if (DYNAMIC(source) && !DYNAMIC(dest))
1614                return USE_DEST;
1615        if (!DYNAMIC(source) && DYNAMIC(dest))
1616                return USE_SOURCE;
1617        /*
1618        if (SERVER(source) && CLIENT(dest))
1619                return USE_SOURCE;
1620       
1621        if (SERVER(dest) && CLIENT(source))
1622                return USE_DEST;
1623        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1624                return USE_SOURCE;
1625        if (ROOT_SERVER(dest) && !ROOT_SERVER(source))
1626                return USE_DEST;
1627        */
1628        /* failing that test... */
1629        if (source < dest) {
1630                return USE_SOURCE;
1631        } 
1632        return USE_DEST;
1633       
1634}
1635
1636/* Truncate the packet at the suggested length
1637 * @param packet        the packet opaque pointer
1638 * @param size          the new length of the packet
1639 * @returns the new size of the packet
1640 * @note size and the return size refer to the network-level payload of the
1641 * packet, and do not include any capture headers. For example, to truncate a
1642 * packet after the IP header, set size to sizeof(ethernet_header) +
1643 * sizeof(ip_header)
1644 * @note If the original network-level payload is smaller than size, then the
1645 * original size is returned and the packet is left unchanged.
1646 */
1647DLLEXPORT size_t trace_set_capture_length(libtrace_packet_t *packet, size_t size) {
1648        assert(packet);
1649
1650        if (packet->trace->format->set_capture_length) {
1651                packet->capture_length = packet->trace->format->set_capture_length(packet,size);
1652                return packet->capture_length;
1653        }
1654
1655        return ~0U;
1656}
1657
1658/* Splits a URI into two components - the format component which is seen before
1659 * the ':', and the uridata which follows the ':'.
1660 *
1661 * Returns a pointer to the URI data, but updates the format parameter to
1662 * point to a copy of the format component.
1663 */
1664
1665DLLEXPORT const char * trace_parse_uri(const char *uri, char **format) {
1666        const char *uridata = 0;
1667       
1668        if((uridata = strchr(uri,':')) == NULL) {
1669                /* Badly formed URI - needs a : */
1670                return 0;
1671        }
1672
1673        if ((unsigned)(uridata - uri) > URI_PROTO_LINE) {
1674                /* Badly formed URI - uri type is too long */
1675                return 0;
1676        }
1677
1678        /* NOTE: this is allocated memory - it should be freed by the caller
1679         * once they are done with it */
1680        *format=xstrndup(uri, (size_t)(uridata - uri));
1681
1682        /* Push uridata past the delimiter */
1683        uridata++;
1684       
1685        return uridata;
1686}
1687
1688enum base_format_t trace_get_format(libtrace_packet_t *packet) 
1689{
1690        assert(packet);
1691
1692        return packet->trace->format->type;
1693}
1694       
1695DLLEXPORT libtrace_err_t trace_get_err(libtrace_t *trace)
1696{
1697        libtrace_err_t err = trace->err;
1698        trace->err.err_num = 0; /* "OK" */
1699        trace->err.problem[0]='\0';
1700        return err;
1701}
1702
1703DLLEXPORT bool trace_is_err(libtrace_t *trace)
1704{
1705        return trace->err.err_num != 0;
1706}
1707
1708/* Prints the input error status to standard error and clears the error state */
1709DLLEXPORT void trace_perror(libtrace_t *trace,const char *msg,...)
1710{
1711        char buf[256];
1712        va_list va;
1713        va_start(va,msg);
1714        vsnprintf(buf,sizeof(buf),msg,va);
1715        va_end(va);
1716        if(trace->err.err_num) {
1717                if (trace->uridata) {
1718                        fprintf(stderr,"%s(%s): %s\n",
1719                                        buf,trace->uridata,trace->err.problem);
1720                } else {
1721                        fprintf(stderr,"%s: %s\n", buf, trace->err.problem);
1722                }
1723        } else {
1724                if (trace->uridata) {
1725                        fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1726                } else {
1727                        fprintf(stderr,"%s: No error\n", buf);
1728                }
1729        }
1730        trace->err.err_num = 0; /* "OK" */
1731        trace->err.problem[0]='\0';
1732}
1733
1734DLLEXPORT libtrace_err_t trace_get_err_output(libtrace_out_t *trace)
1735{
1736        libtrace_err_t err = trace->err;
1737        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1738        trace->err.problem[0]='\0';
1739        return err;
1740}
1741
1742DLLEXPORT bool trace_is_err_output(libtrace_out_t *trace)
1743{
1744        return trace->err.err_num != 0;
1745}
1746
1747/* Prints the output error status to standard error and clears the error state
1748 */
1749DLLEXPORT void trace_perror_output(libtrace_out_t *trace,const char *msg,...)
1750{
1751        char buf[256];
1752        va_list va;
1753        va_start(va,msg);
1754        vsnprintf(buf,sizeof(buf),msg,va);
1755        va_end(va);
1756        if(trace->err.err_num) {
1757                fprintf(stderr,"%s(%s): %s\n",
1758                                buf,
1759                                trace->uridata?trace->uridata:"no uri",
1760                                trace->err.problem);
1761        } else {
1762                fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1763        }
1764        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1765        trace->err.problem[0]='\0';
1766}
1767
1768DLLEXPORT int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts)
1769{
1770        if (trace->format->seek_erf) {
1771                return trace->format->seek_erf(trace,ts);
1772        }
1773        else {
1774                if (trace->format->seek_timeval) {
1775                        struct timeval tv;
1776#if __BYTE_ORDER == __BIG_ENDIAN
1777                        tv.tv_sec = ts & 0xFFFFFFFF;
1778                        tv.tv_usec = ((ts >> 32) * 1000000) & 0xFFFFFFFF;
1779#elif __BYTE_ORDER == __LITTLE_ENDIAN
1780                        tv.tv_sec = ts >> 32;
1781                        tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1782#else
1783#error "What on earth are you running this on?"
1784#endif
1785                        if (tv.tv_usec >= 1000000) {
1786                                tv.tv_usec -= 1000000;
1787                                tv.tv_sec += 1;
1788                        }
1789                        return trace->format->seek_timeval(trace,tv);
1790                }
1791                if (trace->format->seek_seconds) {
1792                        double seconds = 
1793                                (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1794                        return trace->format->seek_seconds(trace,seconds);
1795                }
1796                trace_set_err(trace,
1797                                TRACE_ERR_OPTION_UNAVAIL,
1798                                "Feature unimplemented");
1799                return -1;
1800        }
1801}
1802
1803DLLEXPORT int trace_seek_seconds(libtrace_t *trace, double seconds)
1804{
1805        if (trace->format->seek_seconds) {
1806                return trace->format->seek_seconds(trace,seconds);
1807        }
1808        else {
1809                if (trace->format->seek_timeval) {
1810                        struct timeval tv;
1811                        tv.tv_sec = (uint32_t)seconds;
1812                        tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1813                        return trace->format->seek_timeval(trace,tv);
1814                }
1815                if (trace->format->seek_erf) {
1816                        uint64_t timestamp = 
1817                                ((uint64_t)((uint32_t)seconds) << 32) + \
1818                            (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
1819                        return trace->format->seek_erf(trace,timestamp);
1820                }
1821                trace_set_err(trace,
1822                                TRACE_ERR_OPTION_UNAVAIL,
1823                                "Feature unimplemented");
1824                return -1;
1825        }
1826}
1827
1828DLLEXPORT int trace_seek_timeval(libtrace_t *trace, struct timeval tv)
1829{
1830        if (trace->format->seek_timeval) {
1831                return trace->format->seek_timeval(trace,tv);
1832        }
1833        else {
1834                if (trace->format->seek_erf) {
1835                        uint64_t timestamp = ((((uint64_t)tv.tv_sec) << 32) + \
1836                                (((uint64_t)tv.tv_usec * UINT_MAX)/1000000));
1837                        return trace->format->seek_erf(trace,timestamp);
1838                }
1839                if (trace->format->seek_seconds) {
1840                        double seconds = tv.tv_sec + ((tv.tv_usec * 1.0)/1000000);
1841                        return trace->format->seek_seconds(trace,seconds);
1842                }
1843                trace_set_err(trace,
1844                                TRACE_ERR_OPTION_UNAVAIL,
1845                                "Feature unimplemented");
1846                return -1;
1847        }
1848}
1849
1850/* Converts a binary ethernet MAC address into a printable string */
1851DLLEXPORT char *trace_ether_ntoa(const uint8_t *addr, char *buf)
1852{
1853        static char staticbuf[18]={0,};
1854        if (!buf)
1855                buf=staticbuf;
1856        snprintf(buf,(size_t)18,"%02x:%02x:%02x:%02x:%02x:%02x",
1857                        addr[0],addr[1],addr[2],
1858                        addr[3],addr[4],addr[5]);
1859        return buf;
1860}
1861
1862/* Converts a printable ethernet MAC address into a binary format */
1863DLLEXPORT uint8_t *trace_ether_aton(const char *buf, uint8_t *addr)
1864{
1865        uint8_t *buf2 = addr;
1866        unsigned int tmp[6];
1867        static uint8_t staticaddr[6];
1868        if (!buf2)
1869                buf2=staticaddr;
1870        sscanf(buf,"%x:%x:%x:%x:%x:%x",
1871                        &tmp[0],&tmp[1],&tmp[2],
1872                        &tmp[3],&tmp[4],&tmp[5]);
1873        buf2[0]=tmp[0]; buf2[1]=tmp[1]; buf2[2]=tmp[2];
1874        buf2[3]=tmp[3]; buf2[4]=tmp[4]; buf2[5]=tmp[5];
1875        return buf2;
1876}
1877
1878
1879/* Creates a libtrace packet from scratch using the contents of the provided
1880 * buffer as the packet payload.
1881 *
1882 * Unlike trace_prepare_packet(), the buffer should not contain any capture
1883 * format headers; instead this function will add the PCAP header to the
1884 * packet record. This also means only PCAP packets can be constructed using
1885 * this function.
1886 *
1887 */
1888DLLEXPORT
1889void trace_construct_packet(libtrace_packet_t *packet,
1890                libtrace_linktype_t linktype,
1891                const void *data,
1892                uint16_t len)
1893{
1894        size_t size;
1895        static libtrace_t *deadtrace=NULL;
1896        libtrace_pcapfile_pkt_hdr_t hdr;
1897#ifdef WIN32
1898        struct _timeb tstruct;
1899#else
1900        struct timeval tv;
1901#endif
1902
1903        /* We need a trace to attach the constructed packet to (and it needs
1904         * to be PCAP) */
1905        if (NULL == deadtrace) 
1906                deadtrace=trace_create_dead("pcapfile");
1907
1908        /* Fill in the new PCAP header */
1909#ifdef WIN32
1910        _ftime(&tstruct);
1911        hdr.ts_sec=tstruct.time;
1912        hdr.ts_usec=tstruct.millitm * 1000;
1913#else
1914        gettimeofday(&tv,NULL);
1915        hdr.ts_sec=tv.tv_sec;
1916        hdr.ts_usec=tv.tv_usec;
1917#endif
1918
1919        hdr.caplen=len;
1920        hdr.wirelen=len;
1921
1922        /* Now fill in the libtrace packet itself */
1923        packet->trace=deadtrace;
1924        size=len+sizeof(hdr);
1925        if (packet->buf_control==TRACE_CTRL_PACKET) {
1926                packet->buffer=realloc(packet->buffer,size);
1927        }
1928        else {
1929                packet->buffer=malloc(size);
1930        }
1931        packet->buf_control=TRACE_CTRL_PACKET;
1932        packet->header=packet->buffer;
1933        packet->payload=(void*)((char*)packet->buffer+sizeof(hdr));
1934       
1935        /* Ugh, memcpy - sadly necessary */
1936        memcpy(packet->header,&hdr,sizeof(hdr));
1937        memcpy(packet->payload,data,(size_t)len);
1938        packet->type=pcap_linktype_to_rt(libtrace_to_pcap_linktype(linktype));
1939
1940        trace_clear_cache(packet);
1941}
1942
1943
1944uint64_t trace_get_received_packets(libtrace_t *trace)
1945{
1946        assert(trace);
1947        uint64_t ret;
1948
1949        if (trace->format->get_received_packets) {
1950                if ((ret = trace->format->get_received_packets(trace)) != UINT64_MAX)
1951                        return ret;
1952        }
1953        // Read this cached value taken before the trace was closed
1954        return trace->received_packets;
1955}
1956
1957uint64_t trace_get_filtered_packets(libtrace_t *trace)
1958{
1959        assert(trace);
1960        if (trace->format->get_filtered_packets) {
1961                return trace->format->get_filtered_packets(trace)+
1962                        trace->filtered_packets;
1963        }
1964        return trace->filtered_packets;
1965}
1966
1967uint64_t trace_get_dropped_packets(libtrace_t *trace)
1968{
1969        assert(trace);
1970        uint64_t ret;
1971
1972        if (trace->format->get_dropped_packets) {
1973                if ((ret = trace->format->get_dropped_packets(trace)) != UINT64_MAX)
1974                        return ret;
1975        }
1976        // Read this cached value taken before the trace was closed
1977        return trace->dropped_packets;
1978}
1979
1980uint64_t trace_get_accepted_packets(libtrace_t *trace)
1981{
1982        assert(trace);
1983        int i = 0;
1984        uint64_t ret = trace->accepted_packets;
1985        for (i = 0; i < trace->perpkt_thread_count; i++) {
1986                ret += trace->perpkt_threads[i].accepted_packets;
1987        }
1988        return ret;
1989}
1990
1991void trace_clear_cache(libtrace_packet_t *packet) {
1992
1993        packet->l2_header = NULL;
1994        packet->l3_header = NULL;
1995        packet->l4_header = NULL;
1996        packet->link_type = 0;
1997        packet->l3_ethertype = 0;
1998        packet->transport_proto = 0;
1999        packet->capture_length = -1;
2000        packet->wire_length = -1;
2001        packet->payload_length = -1;
2002        packet->l2_remaining = 0;
2003        packet->l3_remaining = 0;
2004        packet->l4_remaining = 0;
2005
2006}
2007
2008void trace_interrupt(void) {
2009        libtrace_halt = 1;
2010}
2011
2012void register_format(struct libtrace_format_t *f) {
2013        assert(f->next==NULL); /* Can't register a format twice */
2014        f->next=formats_list;
2015        formats_list=f;
2016
2017        /* Now, verify that the format has at least the minimum functionality.
2018         *
2019         * This #if can be changed to a 1 to output warnings about inconsistent
2020         * functions being provided by format modules.  This generally is very
2021         * noisy, as almost all modules don't implement one or more functions
2022         * for various reasons.  This is very useful when checking a new
2023         * format module is sane.
2024         */ 
2025#if 0
2026        if (f->init_input) {
2027#define REQUIRE(x) \
2028                if (!f->x) \
2029                        fprintf(stderr,"%s: Input format should provide " #x "\n",f->name)
2030                REQUIRE(read_packet);
2031                REQUIRE(start_input);
2032                REQUIRE(fin_input);
2033                REQUIRE(get_link_type);
2034                REQUIRE(get_capture_length);
2035                REQUIRE(get_wire_length);
2036                REQUIRE(get_framing_length);
2037                REQUIRE(trace_event);
2038                if (!f->get_erf_timestamp
2039                        && !f->get_seconds
2040                        && !f->get_timeval) {
2041                        fprintf(stderr,"%s: A trace format capable of input, should provide at least one of\n"
2042"get_erf_timestamp, get_seconds or trace_timeval\n",f->name);
2043                }
2044                if (f->trace_event!=trace_event_trace) {
2045                        /* Theres nothing that a trace file could optimise with
2046                         * config_input
2047                         */
2048                        REQUIRE(pause_input);
2049                        REQUIRE(config_input);
2050                        REQUIRE(get_fd);
2051                }
2052                else {
2053                        if (f->get_fd) {
2054                                fprintf(stderr,"%s: Unnecessary get_fd\n",
2055                                                f->name);
2056                        }
2057                }
2058#undef REQUIRE
2059        }
2060        else {
2061#define REQUIRE(x) \
2062                if (f->x) \
2063                        fprintf(stderr,"%s: Non Input format shouldn't need " #x "\n",f->name)
2064                REQUIRE(read_packet);
2065                REQUIRE(start_input);
2066                REQUIRE(pause_input);
2067                REQUIRE(fin_input);
2068                REQUIRE(get_link_type);
2069                REQUIRE(get_capture_length);
2070                REQUIRE(get_wire_length);
2071                REQUIRE(get_framing_length);
2072                REQUIRE(trace_event);
2073                REQUIRE(get_seconds);
2074                REQUIRE(get_timeval);
2075                REQUIRE(get_erf_timestamp);
2076#undef REQUIRE
2077        }
2078        if (f->init_output) {
2079#define REQUIRE(x) \
2080                if (!f->x) \
2081                        fprintf(stderr,"%s: Output format should provide " #x "\n",f->name)
2082                REQUIRE(write_packet);
2083                REQUIRE(start_output);
2084                REQUIRE(config_output);
2085                REQUIRE(fin_output);
2086#undef REQUIRE
2087        }
2088        else {
2089#define REQUIRE(x) \
2090                if (f->x) \
2091                        fprintf(stderr,"%s: Non Output format shouldn't need " #x "\n",f->name)
2092                REQUIRE(write_packet);
2093                REQUIRE(start_output);
2094                REQUIRE(config_output);
2095                REQUIRE(fin_output);
2096#undef REQUIRE
2097        }
2098#endif
2099}
2100
Note: See TracBrowser for help on using the repository browser.