source: lib/trace.c @ 418c78d

develop
Last change on this file since 418c78d was 509ee47, checked in by Shane Alcock <salcock@…>, 2 years ago

Add option to allow users to specify a constant ERF framing length.

This can be useful for situations where

a) the input uses ERF (or some derivative thereof)
b) the link type and ERF record type are constant for the

duration of the capture

c) performance is critical

This option allows users to simply tell libtrace what the ERF
framing length on every packet is going to be, so libtrace
doesn't have to repeatedly derive the framing length for each
packet it processes. At high packet rates, the time taken to
do this calculation can really add up and it makes no sense
to risk dropping packets because you're busy calculating a value
that is always a single constant value.

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