source: lib/trace.c @ dc27de3

cachetimestampsdevelopetsiliverc-4.0.4ringdecrementfixringperformance
Last change on this file since dc27de3 was dc27de3, checked in by Richard Sanger <rsanger@…>, 4 years ago

Only destroy previously opened message queues

Fixes issue #68

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