source: lib/trace.c @ 95ca714

cachetimestampsdeveloprc-4.0.4ringdecrementfixringperformance
Last change on this file since 95ca714 was 32ee9b2, checked in by Shane Alcock <salcock@…>, 3 years ago

Add new trace_flush_output() to public API

Can be used to force a libtrace output to dump any buffered output
to disk immediately.

Note that if the file is compressed or the output trace format
requires a trailer, the flushed file will still not be properly
readable afterwards as this will not result in any trailers
being written. You'll still have to close the file for that.

Mainly this is useful for ensuring that output file sizes grow
over time in situations where the amount of output is relatively
small, rather than staying stuck at 0 bytes until we either reach
1MB of output or the file is closed. For instance, you could have
a timer that calls trace_flush_output() every 30 seconds so that
the output file size will grow if any packets were written in the
last 30 seconds.

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