source: lib/trace.c @ f6f3ae5

develop
Last change on this file since f6f3ae5 was f6f3ae5, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Assertion cleanup

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