source: lib/trace.c @ 5e3f16c

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5e3f16c was 5e3f16c, checked in by Richard Sanger <rsanger@…>, 4 years ago

Fix for issue #39 - ring and int pstop() fails on older kernels when using threads

The problem here is that on old kernels without PACKET_FANOUT support
(added in v3.1) will only include the single threaded versions of int
and ring. When used with multiple threads the libtrace API will
fallback to using read rather than pread which does not check message
queues.

To fix this issue, in any format without pread support:

  • We check for new messages with each loop around read_packet as we fill the burst
  • Within read_packet we update the halt to include the pausing state
  • Use a seperate lock to the main lock when reading a burst of packets, otherwise trace_ppause has to wait for a burst to read.

This is not 100% perfect as a single packet might still need to be received
before a generic message can be received.
A proper fix in the future would be to move all format internals purely to the
parallel API.

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