source: lib/trace.c @ 858ce90

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

Refactoring the packet loop

Removes the pread type selection function and replaces it with a
function pointer created when the format is started.

Tidies the per packet loop, removes duplicate code and rewrites
tracetime-delaying so that a message can be processed while waiting
for the delay to return within a batch of packets.

In this case if a pause message is encountered we will first
notify the trace that we are pausing. Then send any remaining
packets from the batch without delay, and then properly pause. The resume
message is sent to the per packet thread before normal packet
flow continues.

This still is WIP and contains alot of debugging code. The error
path still needs to be better implemented

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