source: lib/trace.c @ cc9c9de

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

Add new config option for trace_event() -- REPLAY_SPEEDUP

This allows users to specify a "speedup factor" when using
trace_event() to replay trace files, i.e. all inter-packet
gaps will be divided by the speedup factor. This allows traces
to be replayed faster, while still preserving the same relative
gaps between packets.

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