source: lib/trace.c @ 2fa43fa

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 2fa43fa was 2fa43fa, checked in by Richard Sanger <rsangerarj@…>, 6 years ago

Fixes an issue with old programs reusing a packet over multi traces

Fixes a bug that Shane found. In the case an old libtrace program used
a single packet and cycled over multiple traces. Closing the trace
and then reusing the packet with a new trace will try to finish
the packet which requires the old format to be present.

As such we now keep track of the last packet against the format,
and finish this when the trace is destroyed.

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