source: lib/trace.c @ c7e547e

cachetimestampsdevelopdpdk-ndagetsiliverc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since c7e547e was c7e547e, checked in by Shane Alcock <salcock@…>, 3 years ago

Added a dpdkndag format for faster ndag reading

Instead of joining a multicast group and receiving nDAG packets
via the networking stack, this new format uses DPDK to sniff
the multicast direct from the wire. This should save some effort
shuffling the packets back through the kernel's networking stack.

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