source: lib/trace.c @ ea75ec2

cachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since ea75ec2 was ea75ec2, checked in by Shane Alcock <salcock@…>, 4 years ago

Add new format for receiving and parsing nDAG records

Also added new statistic: missing_records -- this tracks records
that have gone missing between the original capture device and
the current processing host (i.e. lost on the network between the
two). Useful for nDAG as there is a distinction between packets
dropped by the DAG and packets that were not received by the nDAG
client.

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