source: lib/trace.c @ 5ab626a

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5ab626a was 5ab626a, checked in by Richard Sanger <rsangerarj@…>, 7 years ago

Deprecate trace_get_filtered/accepted/recevied/dropped() in favour of a single function

Adds the single trace_get_statistics function. This allows the structure to be filled
at a point in time, rather than making multiple calls to the library during which state
might have changed.

This has been designed such that the structure can be added to in the future without
breaking old code.

The old internal get_captured_packets was removed from the formats as it was never used.
Eventually we should completely remove get_filtered and received from the formats and replace
them with get_statistics.

In additon some extra fields have added, such as error and captured and the pre-existing
fields are better defined.

The linux formats have been updated to use this new API, which combined with reading
/proc/net/dev returns a full set of statistics.

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