source: lib/trace.c @ d0941cc

develop
Last change on this file since d0941cc was d0941cc, checked in by Shane Alcock <salcock@…>, 22 months ago

Fix potential underflow when calculating wire length of pcap packets.

Only subtract four bytes from the wire length if we have at least
four bytes of wlen to subtract it from.

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