source: lib/trace.c @ df87f00

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

First bits of code for an ETSI live format

Will probably remove the dependencies on the ASN.1 stuff
soon, but chucking it all in for now just so everything will
compile nicely.

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