source: lib/trace.c @ c1205bd

cachetimestampsdevelopetsiliverc-4.0.4ringdecrementfixringperformance
Last change on this file since c1205bd was c1205bd, checked in by Shane Alcock <salcock@…>, 4 years ago

Add packet reference counting API

This API allows users to keep track of references to libtrace
packet structures that are not being released by the per packet
processing threads, e.g. those passed to the reporter or to
any user-created pthreads.

If you only have one reference to a packet at any given time,
you won't need this API. However, if you have multiple
concurrent references, this API will allow you to ensure that the
packet is correctly freed only once all references have been
finished with.

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