source: lib/trace.c @ e375e0f

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

Fix bug where libtrace-created hasher_data was leaked.

If trace_set_hasher was called with a null hasher, libtrace
would malloc memory for storing hasher_data. However, that
memory was never freed, since we had no way of telling whether
that memory had been externally allocated and passed in to
trace_set_hasher or if the memory had been allocated by libtrace.

Added a flag to the libtrace_t structure that records who owns
hasher_data and will now free it during trace_destroy if the
memory was allocated by libtrace.

  • Property mode set to 100644
File size: 69.1 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                libtrace_message_queue_destroy(&libtrace->hasher_thread.messages);
729                libtrace_message_queue_destroy(&libtrace->keepalive_thread.messages);
730                libtrace_message_queue_destroy(&libtrace->reporter_thread.messages);
731
732
733                if (libtrace->combiner.destroy && libtrace->reporter_cbs)
734                        libtrace->combiner.destroy(libtrace, &libtrace->combiner);
735                free(libtrace->perpkt_threads);
736                libtrace->perpkt_threads = NULL;
737                libtrace->perpkt_thread_count = 0;
738
739        }
740
741        if (libtrace->hasher_owner == HASH_OWNED_LIBTRACE) {
742                if (libtrace->hasher_data) {
743                        free(libtrace->hasher_data);
744                }
745        }
746
747
748        if (libtrace->perpkt_cbs)
749                trace_destroy_callback_set(libtrace->perpkt_cbs);
750        if (libtrace->reporter_cbs)
751                trace_destroy_callback_set(libtrace->reporter_cbs);
752
753        if (libtrace->event.packet) {
754                /* Don't use trace_destroy_packet here - there is almost
755                 * certainly going to be another libtrace_packet_t that is
756                 * pointing to the buffer for this packet, so we don't want
757                 * to free it. Rather, it will get freed when the user calls
758                 * trace_destroy_packet on the libtrace_packet_t that they
759                 * own.
760                 *
761                 * All we need to do then is free our packet structure itself.
762                 */
763                 free(libtrace->event.packet);
764        }
765
766        free(libtrace);
767}
768
769
770DLLEXPORT void trace_destroy_dead(libtrace_t *libtrace) {
771        assert(libtrace);
772
773        ASSERT_RET(pthread_mutex_destroy(&libtrace->libtrace_lock), == 0);
774        ASSERT_RET(pthread_mutex_destroy(&libtrace->read_packet_lock), == 0);
775        ASSERT_RET(pthread_cond_destroy(&libtrace->perpkt_cond), == 0);
776
777        /* Don't call pause_input or fin_input, because we should never have
778         * used this trace to do any reading anyway. Do make sure we free
779         * any format_data that has been created, though. */
780        if (libtrace->format_data)
781                free(libtrace->format_data);
782        free(libtrace);
783}
784/* Close an output trace file, freeing up any resources it may have been using
785 *
786 * @param libtrace      the output trace file to be destroyed
787 */
788DLLEXPORT void trace_destroy_output(libtrace_out_t *libtrace)
789{
790        assert(libtrace);
791        if (libtrace->format && libtrace->format->fin_output)
792                libtrace->format->fin_output(libtrace);
793        if (libtrace->uridata)
794                free(libtrace->uridata);
795        free(libtrace);
796}
797
798DLLEXPORT libtrace_packet_t *trace_create_packet(void)
799{
800        libtrace_packet_t *packet =
801                (libtrace_packet_t*)calloc((size_t)1,sizeof(libtrace_packet_t));
802
803        if (packet == NULL)
804                return NULL;
805
806        packet->buf_control=TRACE_CTRL_PACKET;
807        trace_clear_cache(packet);
808        return packet;
809}
810
811DLLEXPORT libtrace_packet_t *trace_copy_packet(const libtrace_packet_t *packet) {
812        libtrace_packet_t *dest = 
813                (libtrace_packet_t *)calloc((size_t)1, sizeof(libtrace_packet_t));
814        if (!dest) {
815                printf("Out of memory constructing packet\n");
816                abort();
817        }
818        dest->trace=packet->trace;
819        dest->buffer=malloc(65536);
820        if (!dest->buffer) {
821                printf("Out of memory allocating buffer memory\n");
822                abort();
823        }
824        dest->header=dest->buffer;
825        dest->payload=(void*)
826                ((char*)dest->buffer+trace_get_framing_length(packet));
827        dest->type=packet->type;
828        dest->buf_control=TRACE_CTRL_PACKET;
829        dest->order = packet->order;
830        dest->hash = packet->hash;
831        dest->error = packet->error;
832        /* Reset the cache - better to recalculate than try to convert
833         * the values over to the new packet */
834        trace_clear_cache(dest);
835        /* Ooooh nasty memcpys! This is why we want to avoid copying packets
836         * as much as possible */
837        memcpy(dest->header,packet->header,trace_get_framing_length(packet));
838        memcpy(dest->payload,packet->payload,trace_get_capture_length(packet));
839
840        return dest;
841}
842
843/** Destroy a packet object
844 */
845DLLEXPORT void trace_destroy_packet(libtrace_packet_t *packet) {
846        /* Free any resources possibly associated with the packet */
847        if (libtrace_parallel && packet->trace && packet->trace->format->fin_packet) {
848                packet->trace->format->fin_packet(packet);
849        }
850        if (!libtrace_parallel && packet->trace &&
851             packet->trace->last_packet == packet) {
852                packet->trace->last_packet = NULL;
853        }
854       
855        if (packet->buf_control == TRACE_CTRL_PACKET && packet->buffer) {
856                free(packet->buffer);
857        }
858        packet->buf_control=(buf_control_t)'\0';
859                                /* A "bad" value to force an assert
860                                 * if this packet is ever reused
861                                 */
862        free(packet);
863}
864
865/**
866 * Removes any possible data stored againt the trace and releases any data.
867 * This will not destroy a reusable good malloc'd buffer (TRACE_CTRL_PACKET)
868 * use trace_destroy_packet() for those diabolical purposes.
869 */
870void trace_fin_packet(libtrace_packet_t *packet) {
871        if (packet)
872        {
873                if (packet->trace && packet->trace->format->fin_packet) {
874                        packet->trace->format->fin_packet(packet);
875                }
876
877                if (packet->srcbucket && packet->internalid != 0) {
878                        libtrace_bucket_t *b = (libtrace_bucket_t *)packet->srcbucket;
879                        libtrace_release_bucket_id(b, packet->internalid);
880                }
881
882                if (packet->trace) {
883                        if (!libtrace_parallel && packet->trace->last_packet == packet)
884                                packet->trace->last_packet = NULL;
885                }
886
887                // No matter what we remove the header and link pointers
888                packet->trace = NULL;
889                packet->header = NULL;
890                packet->payload = NULL;
891
892                if (packet->buf_control != TRACE_CTRL_PACKET)
893                {
894                        packet->buffer = NULL;
895                }
896
897                trace_clear_cache(packet);
898                packet->hash = 0;
899                packet->order = 0;
900                packet->srcbucket = NULL;
901        }
902}
903
904/* Read one packet from the trace into buffer. Note that this function will
905 * block until a packet is read (or EOF is reached).
906 *
907 * @param libtrace      the libtrace opaque pointer
908 * @param packet        the packet opaque pointer
909 * @returns 0 on EOF, negative value on error
910 *
911 */
912DLLEXPORT int trace_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
913
914        assert(libtrace && "You called trace_read_packet() with a NULL libtrace parameter!\n");
915        if (trace_is_err(libtrace))
916                return -1;
917        if (!libtrace->started) {
918                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"You must call libtrace_start() before trace_read_packet()\n");
919                return -1;
920        }
921        if (!(packet->buf_control==TRACE_CTRL_PACKET
922                    || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
923                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
924                return -1;
925        }
926        assert(packet);
927
928        if (libtrace->format->read_packet) {
929                /* Finalise the packet, freeing any resources the format module
930                 * may have allocated it and zeroing all data associated with it.
931                 */
932                if (packet->trace == libtrace) {
933                        trace_fin_packet(packet);
934                }
935                do {
936                        size_t ret;
937                        int filtret;
938                        if ((ret=is_halted(libtrace)) != (size_t)-1)
939                                return ret;
940                        /* Store the trace we are reading from into the packet opaque
941                         * structure */
942                        packet->trace = libtrace;
943                        ret=libtrace->format->read_packet(libtrace,packet);
944                        if (ret==(size_t)READ_MESSAGE ||
945                            ret==(size_t)-1 || ret==0) {
946                                packet->trace = NULL;
947                                return ret;
948                        }
949                        if (libtrace->filter) {
950                                /* If the filter doesn't match, read another
951                                 * packet
952                                 */
953                                filtret = trace_apply_filter(libtrace->filter, packet);
954                                if (filtret == -1) {
955                                        /* Error compiling filter, probably */
956                                        return ~0U;
957                                }
958
959                                if (filtret == 0) {
960                                        ++libtrace->filtered_packets;
961                                        trace_fin_packet(packet);
962                                        continue;
963                                }
964                        }
965                        if (libtrace->snaplen>0) {
966                                /* Snap the packet */
967                                trace_set_capture_length(packet,
968                                                libtrace->snaplen);
969                        }
970                        if (!IS_LIBTRACE_META_PACKET(packet)) {
971                                ++libtrace->accepted_packets;
972                        }
973                        trace_packet_set_order(packet, libtrace->sequence_number);
974                        ++libtrace->sequence_number;
975                        if (!libtrace_parallel && packet->trace == libtrace)
976                                libtrace->last_packet = packet;
977
978                        return ret;
979                } while(1);
980        }
981        trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,"This format does not support reading packets\n");
982        return ~0U;
983}
984
985/* Converts the provided buffer into a libtrace packet of the given type.
986 *
987 * Unlike trace_construct_packet, the buffer is expected to begin with the
988 * appropriate capture format header for the format type that the packet is
989 * being converted to. This also allows for a packet to be converted into
990 * just about capture format that is supported by libtrace, provided the
991 * format header is present in the buffer.
992 *
993 * This function is primarily used to convert packets received via the RT
994 * protocol back into their original capture format. The RT header encapsulates
995 * the original capture format header, so after removing it the packet must
996 * have it's header and payload pointers updated and the packet format and type
997 * changed, amongst other things.
998 *
999 * Intended only for internal use at this point - this function is not
1000 * available through the external libtrace API.
1001 */
1002int trace_prepare_packet(libtrace_t *trace, libtrace_packet_t *packet,
1003                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
1004
1005        assert(packet);
1006        assert(trace);
1007
1008        /* XXX Proper error handling?? */
1009        if (buffer == NULL)
1010                return -1;
1011
1012        if (!(packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
1013                trace_set_err(trace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
1014                return -1;
1015        }
1016
1017        packet->trace = trace;
1018        if (!libtrace_parallel)
1019                trace->last_packet = packet;
1020        /* Clear packet cache */
1021        trace_clear_cache(packet);
1022
1023        if (trace->format->prepare_packet) {
1024                return trace->format->prepare_packet(trace, packet,
1025                                buffer, rt_type, flags);
1026        }
1027        trace_set_err(trace, TRACE_ERR_UNSUPPORTED,
1028                        "This format does not support preparing packets\n");
1029        return -1;
1030
1031}
1032
1033/* Writes a packet to the specified output trace
1034 *
1035 * @param libtrace      describes the output format, destination, etc.
1036 * @param packet        the packet to be written out
1037 * @returns the number of bytes written, -1 if write failed
1038 */
1039DLLEXPORT int trace_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
1040        assert(libtrace);
1041        assert(packet);
1042        /* Verify the packet is valid */
1043        if (!libtrace->started) {
1044                trace_set_err_out(libtrace,TRACE_ERR_BAD_STATE,
1045                        "Trace is not started before trace_write_packet");
1046                return -1;
1047        }
1048
1049        /* Don't try to convert meta-packets across formats */
1050        if (strcmp(libtrace->format->name, packet->trace->format->name) != 0 &&
1051                        IS_LIBTRACE_META_PACKET(packet)) {
1052                return 0;
1053        }
1054
1055        if (libtrace->format->write_packet) {
1056                return libtrace->format->write_packet(libtrace, packet);
1057        }
1058        trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
1059                "This format does not support writing packets");
1060        return -1;
1061}
1062
1063/* Get a pointer to the first byte of the packet payload */
1064DLLEXPORT void *trace_get_packet_buffer(const libtrace_packet_t *packet,
1065                libtrace_linktype_t *linktype, uint32_t *remaining) {
1066        int cap_len;
1067        int wire_len;
1068
1069        assert(packet != NULL);
1070        if (linktype) *linktype = trace_get_link_type(packet);
1071        if (remaining) {
1072                /* I think we should choose the minimum of the capture and
1073                 * wire lengths to be the "remaining" value. If the packet has
1074                 * been padded to increase the capture length, we don't want
1075                 * to allow subsequent protocol decoders to consider the
1076                 * padding as part of the packet.
1077                 *
1078                 * For example, in Auck 4 there is a trace where the IP header
1079                 * length is incorrect (24 bytes) followed by a 20 byte TCP
1080                 * header. Total IP length is 40 bytes. As a result, the
1081                 * legacyatm padding gets treated as the "missing" bytes of
1082                 * the TCP header, which isn't the greatest. We're probably
1083                 * better off returning an incomplete TCP header in that case.
1084                 */
1085
1086                cap_len = trace_get_capture_length(packet);
1087                wire_len = trace_get_wire_length(packet);
1088
1089                assert(cap_len >= 0);
1090
1091                /* There is the odd corrupt packet, e.g. in IPLS II, that have
1092                 * massively negative wire lens. We could assert fail here on
1093                 * them, but we could at least try the capture length instead.
1094                 *
1095                 * You may still run into problems if you try to write that
1096                 * packet, but at least reading should work OK.
1097                 */
1098                if (wire_len < 0)
1099                        *remaining = cap_len;
1100                else if (wire_len < cap_len)
1101                        *remaining = wire_len;
1102                else
1103                        *remaining = cap_len;
1104                /* *remaining = trace_get_capture_length(packet); */
1105        }
1106        return (void *) packet->payload;
1107}
1108
1109
1110/* Get a pointer to the first byte of the packet payload
1111 *
1112 * DEPRECATED - use trace_get_packet_buffer() instead */
1113DLLEXPORT void *trace_get_link(const libtrace_packet_t *packet) {
1114        return (void *)packet->payload;
1115}
1116
1117/* Get the current time in DAG time format
1118 * @param packet        a pointer to a libtrace_packet structure
1119 * @returns a 64 bit timestamp in DAG ERF format (upper 32 bits are the seconds
1120 * past 1970-01-01, the lower 32bits are partial seconds)
1121 */
1122DLLEXPORT uint64_t trace_get_erf_timestamp(const libtrace_packet_t *packet) {
1123        if (packet->trace->format->get_erf_timestamp) {
1124                /* timestamp -> timestamp */
1125                return packet->trace->format->get_erf_timestamp(packet);
1126        } else if (packet->trace->format->get_timespec) {
1127                /* timespec -> timestamp */
1128                struct timespec ts;
1129                ts = packet->trace->format->get_timespec(packet);
1130                return ((((uint64_t)ts.tv_sec) << 32) +
1131                                (((uint64_t)ts.tv_nsec << 32)/1000000000));
1132        } else if (packet->trace->format->get_timeval) {
1133                /* timeval -> timestamp */
1134                struct timeval tv;
1135                tv = packet->trace->format->get_timeval(packet);
1136                return ((((uint64_t)tv.tv_sec) << 32) +
1137                                (((uint64_t)tv.tv_usec << 32)/1000000));
1138        } else if (packet->trace->format->get_seconds) {
1139                /* seconds -> timestamp */
1140                double seconds = packet->trace->format->get_seconds(packet);
1141                return (((uint64_t)seconds)<<32)
1142                          + (uint64_t)((seconds-(uint64_t)seconds)*UINT_MAX);
1143        }
1144        else {
1145                return (uint64_t)0;
1146        }
1147}
1148
1149/* Get the current time in struct timeval
1150 * @param packet        a pointer to a libtrace_packet structure
1151 *
1152 * @returns time that this packet was seen in a struct timeval
1153 * @author Daniel Lawson
1154 * @author Perry Lorier
1155 */
1156DLLEXPORT struct timeval trace_get_timeval(const libtrace_packet_t *packet) {
1157        struct timeval tv;
1158        uint64_t ts = 0;
1159        if (packet->trace->format->get_timeval) {
1160                /* timeval -> timeval */
1161                tv = packet->trace->format->get_timeval(packet);
1162        } else if (packet->trace->format->get_erf_timestamp) {
1163                /* timestamp -> timeval */
1164                ts = packet->trace->format->get_erf_timestamp(packet);
1165                tv.tv_sec = ts >> 32;
1166                tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1167                if (tv.tv_usec >= 1000000) {
1168                        tv.tv_usec -= 1000000;
1169                        tv.tv_sec += 1;
1170                }
1171        } else if (packet->trace->format->get_timespec) {
1172                struct timespec ts = packet->trace->format->get_timespec(packet);
1173                tv.tv_sec = ts.tv_sec;
1174                tv.tv_usec = ts.tv_nsec/1000;
1175        } else if (packet->trace->format->get_seconds) {
1176                /* seconds -> timeval */
1177                double seconds = packet->trace->format->get_seconds(packet);
1178                tv.tv_sec = (uint32_t)seconds;
1179                tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1180        }
1181        else {
1182                tv.tv_sec=-1;
1183                tv.tv_usec=-1;
1184        }
1185
1186    return tv;
1187}
1188
1189DLLEXPORT struct timespec trace_get_timespec(const libtrace_packet_t *packet) {
1190        struct timespec ts;
1191
1192        if (packet->trace->format->get_timespec) {
1193                return packet->trace->format->get_timespec(packet);
1194        } else if (packet->trace->format->get_erf_timestamp) {
1195                /* timestamp -> timeval */
1196                uint64_t erfts = packet->trace->format->get_erf_timestamp(packet);
1197                ts.tv_sec = erfts >> 32;
1198                ts.tv_nsec = ((erfts&0xFFFFFFFF)*1000000000)>>32;
1199                if (ts.tv_nsec >= 1000000000) {
1200                        ts.tv_nsec -= 1000000000;
1201                        ts.tv_sec += 1;
1202                }
1203                return ts;
1204        } else if (packet->trace->format->get_timeval) {
1205                /* timeval -> timespec */
1206                struct timeval tv = packet->trace->format->get_timeval(packet);
1207                ts.tv_sec = tv.tv_sec;
1208                ts.tv_nsec = tv.tv_usec*1000;
1209                return ts;
1210        } else if (packet->trace->format->get_seconds) {
1211                /* seconds -> timespec */
1212                double seconds = packet->trace->format->get_seconds(packet);
1213                ts.tv_sec = (uint32_t)seconds;
1214                ts.tv_nsec = (long)(((seconds - ts.tv_sec) * 1000000000)/UINT_MAX);
1215                return ts;
1216        }
1217        else {
1218                ts.tv_sec=-1;
1219                ts.tv_nsec=-1;
1220                return ts;
1221        }
1222}
1223
1224
1225/* Get the current time in floating point seconds
1226 * @param packet        a pointer to a libtrace_packet structure
1227 * @returns time that this packet was seen in 64bit floating point seconds
1228 */
1229DLLEXPORT double trace_get_seconds(const libtrace_packet_t *packet) {
1230        double seconds = 0.0;
1231
1232        if (packet->trace->format->get_seconds) {
1233                /* seconds->seconds */
1234                seconds = packet->trace->format->get_seconds(packet);
1235        } else if (packet->trace->format->get_erf_timestamp) {
1236                /* timestamp -> seconds */
1237                uint64_t ts = 0;
1238                ts = packet->trace->format->get_erf_timestamp(packet);
1239                seconds =  (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1240        } else if (packet->trace->format->get_timespec) {
1241                /* timespec -> seconds */
1242                struct timespec ts;
1243                ts = packet->trace->format->get_timespec(packet);
1244                seconds = ts.tv_sec + ((ts.tv_nsec * 1.0) / 1000000000);
1245        } else if (packet->trace->format->get_timeval) {
1246                /* timeval -> seconds */
1247                struct timeval tv;
1248                tv = packet->trace->format->get_timeval(packet);
1249                seconds = tv.tv_sec + ((tv.tv_usec * 1.0) / 1000000);
1250        }
1251
1252        return seconds;
1253}
1254
1255DLLEXPORT size_t trace_get_capture_length(const libtrace_packet_t *packet)
1256{
1257        /* Cache the capture length */
1258        if (packet->capture_length == -1) {
1259                if (!packet->trace->format->get_capture_length)
1260                        return ~0U;
1261                /* Cast away constness because this is "just" a cache */
1262                ((libtrace_packet_t*)packet)->capture_length =
1263                        packet->trace->format->get_capture_length(packet);
1264        }
1265
1266        assert(packet->capture_length < LIBTRACE_PACKET_BUFSIZE);
1267
1268        return packet->capture_length;
1269}
1270
1271/* Get the size of the packet as it was seen on the wire.
1272 * @param packet        a pointer to a libtrace_packet structure
1273 *
1274 * @returns the size of the packet as it was on the wire.
1275 * @note Due to the trace being a header capture, or anonymisation this may
1276 * not be the same as the Capture Len.
1277 */
1278DLLEXPORT size_t trace_get_wire_length(const libtrace_packet_t *packet){
1279
1280        if (packet->wire_length == -1) {
1281                if (!packet->trace->format->get_wire_length)
1282                        return ~0U;
1283                ((libtrace_packet_t *)packet)->wire_length =
1284                        packet->trace->format->get_wire_length(packet);
1285        }
1286
1287        assert(packet->wire_length < LIBTRACE_PACKET_BUFSIZE);
1288        return packet->wire_length;
1289
1290}
1291
1292/* Get the length of the capture framing headers.
1293 * @param packet        the packet opaque pointer
1294 * @returns the size of the packet as it was on the wire.
1295 * @note this length corresponds to the difference between the size of a
1296 * captured packet in memory, and the captured length of the packet
1297 */
1298DLLEXPORT SIMPLE_FUNCTION
1299size_t trace_get_framing_length(const libtrace_packet_t *packet) {
1300        if (packet->trace->format->get_framing_length) {
1301                return packet->trace->format->get_framing_length(packet);
1302        }
1303        return ~0U;
1304}
1305
1306
1307/* Get the type of the link layer
1308 * @param packet        a pointer to a libtrace_packet structure
1309 * @returns libtrace_linktype_t
1310 */
1311DLLEXPORT libtrace_linktype_t trace_get_link_type(const libtrace_packet_t *packet ) {
1312
1313        if (packet->link_type == 0) {
1314                if (!packet->trace->format->get_link_type)
1315                        return TRACE_TYPE_UNKNOWN;
1316                ((libtrace_packet_t *)packet)->link_type =
1317                        packet->trace->format->get_link_type(packet);
1318        }
1319
1320        return packet->link_type;
1321}
1322
1323/* process a libtrace event
1324 * @param trace the libtrace opaque pointer
1325 * @param packet the libtrace_packet opaque pointer
1326 * @returns
1327 *  TRACE_EVENT_IOWAIT  Waiting on I/O on fd
1328 *  TRACE_EVENT_SLEEP   Next event in seconds
1329 *  TRACE_EVENT_PACKET  Packet arrived in buffer with size size
1330 *  TRACE_EVENT_TERMINATE Trace terminated (perhaps with an error condition)
1331 * FIXME currently keeps a copy of the packet inside the trace pointer,
1332 * which in turn is stored inside the new packet object...
1333 */
1334DLLEXPORT libtrace_eventobj_t trace_event(libtrace_t *trace,
1335                libtrace_packet_t *packet) {
1336        libtrace_eventobj_t event = {TRACE_EVENT_IOWAIT,0,0.0,0};
1337
1338        if (!trace) {
1339                fprintf(stderr,"You called trace_event() with a NULL trace object!\n");
1340        }
1341        assert(trace);
1342        assert(packet);
1343
1344        /* Free the last packet */
1345        trace_fin_packet(packet);
1346        /* Store the trace we are reading from into the packet opaque
1347         * structure */
1348        packet->trace = trace;
1349
1350        if (packet->trace->format->trace_event) {
1351                /* Note: incrementing accepted, filtered etc. packet
1352                 * counters is handled by the format-specific
1353                 * function so don't increment them here.
1354                 */
1355                event=packet->trace->format->trace_event(trace,packet);
1356                }
1357        return event;
1358
1359}
1360
1361/** Setup a BPF filter based on pre-compiled byte-code.
1362 * @param bf_insns      A pointer to the start of the byte-code
1363 * @param bf_len        The number of BPF instructions
1364 * @returns             an opaque pointer to a libtrace_filter_t object
1365 * @note                The supplied byte-code is not checked for correctness.
1366 * @author              Scott Raynel
1367 */
1368DLLEXPORT libtrace_filter_t *
1369trace_create_filter_from_bytecode(void *bf_insns, unsigned int bf_len)
1370{
1371#ifndef HAVE_BPF
1372        fprintf(stderr, "This version of libtrace does not have BPF support\n");
1373        return NULL;
1374#else
1375        struct libtrace_filter_t *filter = (struct libtrace_filter_t *)
1376                malloc(sizeof(struct libtrace_filter_t));
1377        filter->filter.bf_insns = (struct bpf_insn *)
1378                malloc(sizeof(struct bpf_insn) * bf_len);
1379
1380        memcpy(filter->filter.bf_insns, bf_insns,
1381                        bf_len * sizeof(struct bpf_insn));
1382
1383        filter->filter.bf_len = bf_len;
1384        filter->filterstring = NULL;
1385        filter->jitfilter = NULL;
1386        /* "flag" indicates that the filter member is valid */
1387        filter->flag = 1;
1388
1389        return filter;
1390#endif
1391}
1392
1393/* Create a BPF filter
1394 * @param filterstring a char * containing the bpf filter string
1395 * @returns opaque pointer pointer to a libtrace_filter_t object
1396 */
1397DLLEXPORT libtrace_filter_t *trace_create_filter(const char *filterstring) {
1398#ifdef HAVE_BPF
1399        libtrace_filter_t *filter = (libtrace_filter_t*)
1400                                malloc(sizeof(libtrace_filter_t));
1401        filter->filterstring = strdup(filterstring);
1402        filter->jitfilter = NULL;
1403        filter->flag = 0;
1404        return filter;
1405#else
1406        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1407        return NULL;
1408#endif
1409}
1410
1411DLLEXPORT void trace_destroy_filter(libtrace_filter_t *filter)
1412{
1413#ifdef HAVE_BPF
1414        free(filter->filterstring);
1415        if (filter->flag)
1416                pcap_freecode(&filter->filter);
1417#ifdef HAVE_LLVM
1418        if (filter->jitfilter)
1419                destroy_program(filter->jitfilter);
1420#endif
1421        free(filter);
1422#else
1423
1424#endif
1425}
1426
1427/* Compile a bpf filter, now we know the link type for the trace that we're
1428 * applying it to.
1429 *
1430 * @internal
1431 *
1432 * @returns -1 on error, 0 on success
1433 */
1434static int trace_bpf_compile(libtrace_filter_t *filter,
1435                const libtrace_packet_t *packet,
1436                void *linkptr,
1437                libtrace_linktype_t linktype    ) {
1438#ifdef HAVE_BPF
1439        /* It just so happens that the underlying libs used by pthread arn't
1440         * thread safe, namely lex/flex thingys, so single threaded compile
1441         * multi threaded running should be safe.
1442         */
1443        static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1444        assert(filter);
1445
1446        /* If this isn't a real packet, then fail */
1447        if (!linkptr) {
1448                trace_set_err(packet->trace,
1449                                TRACE_ERR_BAD_FILTER,"Packet has no payload");
1450                return -1;
1451        }
1452
1453        if (filter->filterstring && ! filter->flag) {
1454                pcap_t *pcap = NULL;
1455                if (linktype==(libtrace_linktype_t)-1) {
1456                        trace_set_err(packet->trace,
1457                                        TRACE_ERR_BAD_FILTER,
1458                                        "Packet has an unknown linktype");
1459                        return -1;
1460                }
1461                if (libtrace_to_pcap_dlt(linktype) == TRACE_DLT_ERROR) {
1462                        trace_set_err(packet->trace,TRACE_ERR_BAD_FILTER,
1463                                        "Unknown pcap equivalent linktype");
1464                        return -1;
1465                }
1466                assert (pthread_mutex_lock(&mutex) == 0);
1467                /* Make sure not one bet us to this */
1468                if (filter->flag) {
1469                        assert (pthread_mutex_unlock(&mutex) == 0);
1470                        return 1;
1471                }
1472                pcap=(pcap_t *)pcap_open_dead(
1473                                (int)libtrace_to_pcap_dlt(linktype),
1474                                1500U);
1475                /* build filter */
1476                assert(pcap);
1477                if (pcap_compile( pcap, &filter->filter, filter->filterstring,
1478                                        1, 0)) {
1479                        trace_set_err(packet->trace,TRACE_ERR_BAD_FILTER,
1480                                        "Unable to compile the filter \"%s\": %s",
1481                                        filter->filterstring,
1482                                        pcap_geterr(pcap));
1483                        pcap_close(pcap);
1484                        assert (pthread_mutex_unlock(&mutex) == 0);
1485                        return -1;
1486                }
1487                pcap_close(pcap);
1488                filter->flag=1;
1489                assert (pthread_mutex_unlock(&mutex) == 0);
1490        }
1491        return 0;
1492#else
1493        assert(!"Internal bug: This should never be called when BPF not enabled");
1494        trace_set_err(packet->trace,TRACE_ERR_OPTION_UNAVAIL,
1495                                "Feature unavailable");
1496        return -1;
1497#endif
1498}
1499
1500DLLEXPORT int trace_apply_filter(libtrace_filter_t *filter,
1501                        const libtrace_packet_t *packet) {
1502#ifdef HAVE_BPF
1503        void *linkptr = 0;
1504        uint32_t clen = 0;
1505        bool free_packet_needed = false;
1506        int ret;
1507        libtrace_linktype_t linktype;
1508        libtrace_packet_t *packet_copy = (libtrace_packet_t*)packet;
1509#ifdef HAVE_LLVM
1510        static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1511#endif
1512
1513        assert(filter);
1514        assert(packet);
1515
1516        /* Match all non-data packets as we probably want them to pass
1517         * through to the caller */
1518        linktype = trace_get_link_type(packet);
1519
1520        if (linktype == TRACE_TYPE_NONDATA || linktype == TRACE_TYPE_ERF_META)
1521                return 1;
1522
1523        if (libtrace_to_pcap_dlt(linktype)==TRACE_DLT_ERROR) {
1524
1525                /* If we cannot get a suitable DLT for the packet, it may
1526                 * be because the packet is encapsulated in a link type that
1527                 * does not correspond to a DLT. Therefore, we should try
1528                 * popping off headers until we either can find a suitable
1529                 * link type or we can't do any more sensible decapsulation. */
1530
1531                /* Copy the packet, as we don't want to trash the one we
1532                 * were passed in */
1533                packet_copy=trace_copy_packet(packet);
1534                free_packet_needed=true;
1535
1536                while (libtrace_to_pcap_dlt(linktype) == TRACE_DLT_ERROR) {
1537                        if (!demote_packet(packet_copy)) {
1538                                trace_set_err(packet->trace,
1539                                                TRACE_ERR_NO_CONVERSION,
1540                                                "pcap does not support this format");
1541                                if (free_packet_needed) {
1542                                        trace_destroy_packet(packet_copy);
1543                                }
1544                                return -1;
1545                        }
1546                        linktype = trace_get_link_type(packet_copy);
1547                }
1548
1549        }
1550
1551        linkptr = trace_get_packet_buffer(packet_copy,NULL,&clen);
1552        if (!linkptr) {
1553                if (free_packet_needed) {
1554                        trace_destroy_packet(packet_copy);
1555                }
1556                return 0;
1557        }
1558
1559        /* We need to compile the filter now, because before we didn't know
1560         * what the link type was
1561         */
1562        // Note internal mutex locking used here
1563        if (trace_bpf_compile(filter,packet_copy,linkptr,linktype)==-1) {
1564                if (free_packet_needed) {
1565                        trace_destroy_packet(packet_copy);
1566                }
1567                return -1;
1568        }
1569
1570        /* If we're jitting, we may need to JIT the BPF code now too */
1571#if HAVE_LLVM
1572        if (!filter->jitfilter) {
1573                ASSERT_RET(pthread_mutex_lock(&mutex), == 0);
1574                /* Again double check here like the bpf filter */
1575                if(!filter->jitfilter)
1576                /* Looking at compile_program source this appears to be thread safe
1577                 * however if this gets called twice we will leak this memory :(
1578                 * as such lock here anyways */
1579                        filter->jitfilter = compile_program(filter->filter.bf_insns, filter->filter.bf_len);
1580                ASSERT_RET(pthread_mutex_unlock(&mutex), == 0);
1581        }
1582#endif
1583
1584        assert(filter->flag);
1585        /* Now execute the filter */
1586#if HAVE_LLVM
1587        ret=filter->jitfilter->bpf_run((unsigned char *)linkptr, clen);
1588#else
1589        ret=bpf_filter(filter->filter.bf_insns,(u_char*)linkptr,(unsigned int)clen,(unsigned int)clen);
1590#endif
1591
1592        /* If we copied the packet earlier, make sure that we free it */
1593        if (free_packet_needed) {
1594                trace_destroy_packet(packet_copy);
1595        }
1596        return ret;
1597#else
1598        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1599        return 0;
1600#endif
1601}
1602
1603/* Set the direction flag, if it has one
1604 * @param packet the packet opaque pointer
1605 * @param direction the new direction (0,1,2,3)
1606 * @returns a signed value containing the direction flag, or -1 if this is not supported
1607 */
1608DLLEXPORT libtrace_direction_t trace_set_direction(libtrace_packet_t *packet,
1609                libtrace_direction_t direction)
1610{
1611        assert(packet);
1612        if (packet->trace->format->set_direction) {
1613                return packet->trace->format->set_direction(packet,direction);
1614        }
1615        return (libtrace_direction_t)~0U;
1616}
1617
1618/* Get the direction flag, if it has one
1619 * @param packet a pointer to a libtrace_packet structure
1620 * @returns a signed value containing the direction flag, or -1 if this is not supported
1621 * The direction is defined as 0 for packets originating locally (ie, outbound)
1622 * and 1 for packets originating remotely (ie, inbound).
1623 * Other values are possible, which might be overloaded to mean special things
1624 * for a special trace.
1625 */
1626DLLEXPORT libtrace_direction_t trace_get_direction(const libtrace_packet_t *packet)
1627{
1628        assert(packet);
1629        if (packet->trace->format->get_direction) {
1630                return packet->trace->format->get_direction(packet);
1631        }
1632        return (libtrace_direction_t)~0U;
1633}
1634
1635#define ROOT_SERVER(x) ((x) < 512)
1636#define ROOT_CLIENT(x) ((512 <= (x)) && ((x) < 1024))
1637#define NONROOT_SERVER(x) ((x) >= 5000)
1638#define NONROOT_CLIENT(x) ((1024 <= (x)) && ((x) < 5000))
1639#define DYNAMIC(x) ((49152 < (x)) && ((x) < 65535))
1640#define SERVER(x) ROOT_SERVER(x) || NONROOT_SERVER(x)
1641#define CLIENT(x) ROOT_CLIENT(x) || NONROOT_CLIENT(x)
1642
1643/* Attempt to deduce the 'server' port
1644 * @param protocol the IP protocol (eg, 6 or 17 for TCP or UDP)
1645 * @param source the TCP or UDP source port
1646 * @param dest the TCP or UDP destination port
1647 * @returns a hint as to which port is the server port
1648 */
1649DLLEXPORT int8_t trace_get_server_port(UNUSED uint8_t protocol,
1650                uint16_t source, uint16_t dest)
1651{
1652        /*
1653         * * If the ports are equal, return DEST
1654         * * Check for well-known ports in the given protocol
1655         * * Root server ports: 0 - 511
1656         * * Root client ports: 512 - 1023
1657         * * non-root client ports: 1024 - 4999
1658         * * non-root server ports: 5000+
1659         * * Check for static ranges: 1024 - 49151
1660         * * Check for dynamic ranges: 49152 - 65535
1661         * * flip a coin.
1662         */
1663
1664        /* equal */
1665        if (source == dest)
1666                return USE_DEST;
1667
1668        /* root server port, 0 - 511 */
1669        if (ROOT_SERVER(source) && ROOT_SERVER(dest)) {
1670                if (source < dest)
1671                        return USE_SOURCE;
1672                return USE_DEST;
1673        }
1674
1675        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1676                return USE_SOURCE;
1677        if (!ROOT_SERVER(source) && ROOT_SERVER(dest))
1678                return USE_DEST;
1679
1680        /* non-root server */
1681        if (NONROOT_SERVER(source) && NONROOT_SERVER(dest)) {
1682                if (source < dest)
1683                        return USE_SOURCE;
1684                return USE_DEST;
1685        }
1686        if (NONROOT_SERVER(source) && !NONROOT_SERVER(dest))
1687                return USE_SOURCE;
1688        if (!NONROOT_SERVER(source) && NONROOT_SERVER(dest))
1689                return USE_DEST;
1690
1691        /* root client */
1692        if (ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1693                if (source < dest)
1694                        return USE_SOURCE;
1695                return USE_DEST;
1696        }
1697        if (ROOT_CLIENT(source) && !ROOT_CLIENT(dest)) {
1698                /* prefer root-client over nonroot-client */
1699                if (NONROOT_CLIENT(dest))
1700                        return USE_SOURCE;
1701                return USE_DEST;
1702        }
1703        if (!ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1704                /* prefer root-client over nonroot-client */
1705                if (NONROOT_CLIENT(source))
1706                        return USE_DEST;
1707                return USE_SOURCE;
1708        }
1709
1710        /* nonroot client */
1711        if (NONROOT_CLIENT(source) && NONROOT_CLIENT(dest)) {
1712                if (source < dest)
1713                        return USE_SOURCE;
1714                return USE_DEST;
1715        }
1716        if (NONROOT_CLIENT(source) && !NONROOT_CLIENT(dest))
1717                return USE_DEST;
1718        if (!NONROOT_CLIENT(source) && NONROOT_CLIENT(dest))
1719                return USE_SOURCE;
1720
1721        /* dynamic range */
1722        if (DYNAMIC(source) && DYNAMIC(dest)) {
1723                if (source < dest)
1724                        return USE_SOURCE;
1725                return USE_DEST;
1726        }
1727        if (DYNAMIC(source) && !DYNAMIC(dest))
1728                return USE_DEST;
1729        if (!DYNAMIC(source) && DYNAMIC(dest))
1730                return USE_SOURCE;
1731        /*
1732        if (SERVER(source) && CLIENT(dest))
1733                return USE_SOURCE;
1734
1735        if (SERVER(dest) && CLIENT(source))
1736                return USE_DEST;
1737        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1738                return USE_SOURCE;
1739        if (ROOT_SERVER(dest) && !ROOT_SERVER(source))
1740                return USE_DEST;
1741        */
1742        /* failing that test... */
1743        if (source < dest) {
1744                return USE_SOURCE;
1745        }
1746        return USE_DEST;
1747
1748}
1749
1750/* Truncate the packet at the suggested length
1751 * @param packet        the packet opaque pointer
1752 * @param size          the new length of the packet
1753 * @returns the new size of the packet
1754 * @note size and the return size refer to the network-level payload of the
1755 * packet, and do not include any capture headers. For example, to truncate a
1756 * packet after the IP header, set size to sizeof(ethernet_header) +
1757 * sizeof(ip_header)
1758 * @note If the original network-level payload is smaller than size, then the
1759 * original size is returned and the packet is left unchanged.
1760 */
1761DLLEXPORT size_t trace_set_capture_length(libtrace_packet_t *packet, size_t size) {
1762        assert(packet);
1763
1764        if (packet->trace->format->set_capture_length) {
1765                packet->capture_length = packet->trace->format->set_capture_length(packet,size);
1766                return packet->capture_length;
1767        }
1768
1769        return ~0U;
1770}
1771
1772/* Splits a URI into two components - the format component which is seen before
1773 * the ':', and the uridata which follows the ':'.
1774 *
1775 * Returns a pointer to the URI data, but updates the format parameter to
1776 * point to a copy of the format component.
1777 */
1778
1779DLLEXPORT const char * trace_parse_uri(const char *uri, char **format) {
1780        const char *uridata = 0;
1781
1782        if((uridata = strchr(uri,':')) == NULL) {
1783                /* Badly formed URI - needs a : */
1784                return 0;
1785        }
1786
1787        if ((unsigned)(uridata - uri) > URI_PROTO_LINE) {
1788                /* Badly formed URI - uri type is too long */
1789                return 0;
1790        }
1791
1792        /* NOTE: this is allocated memory - it should be freed by the caller
1793         * once they are done with it */
1794        *format=xstrndup(uri, (size_t)(uridata - uri));
1795
1796        /* Push uridata past the delimiter */
1797        uridata++;
1798
1799        return uridata;
1800}
1801
1802enum base_format_t trace_get_format(libtrace_packet_t *packet)
1803{
1804        assert(packet);
1805
1806        return packet->trace->format->type;
1807}
1808
1809DLLEXPORT libtrace_err_t trace_get_err(libtrace_t *trace)
1810{
1811        libtrace_err_t err = trace->err;
1812        trace->err.err_num = 0; /* "OK" */
1813        trace->err.problem[0]='\0';
1814        return err;
1815}
1816
1817DLLEXPORT bool trace_is_err(libtrace_t *trace)
1818{
1819        return trace->err.err_num != 0;
1820}
1821
1822/* Prints the input error status to standard error and clears the error state */
1823DLLEXPORT void trace_perror(libtrace_t *trace,const char *msg,...)
1824{
1825        char buf[256];
1826        va_list va;
1827        va_start(va,msg);
1828        vsnprintf(buf,sizeof(buf),msg,va);
1829        va_end(va);
1830        if(trace->err.err_num) {
1831                if (trace->uridata) {
1832                        fprintf(stderr,"%s(%s): %s\n",
1833                                        buf,trace->uridata,trace->err.problem);
1834                } else {
1835                        fprintf(stderr,"%s: %s\n", buf, trace->err.problem);
1836                }
1837        } else {
1838                if (trace->uridata) {
1839                        fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1840                } else {
1841                        fprintf(stderr,"%s: No error\n", buf);
1842                }
1843        }
1844        trace->err.err_num = 0; /* "OK" */
1845        trace->err.problem[0]='\0';
1846}
1847
1848DLLEXPORT libtrace_err_t trace_get_err_output(libtrace_out_t *trace)
1849{
1850        libtrace_err_t err = trace->err;
1851        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1852        trace->err.problem[0]='\0';
1853        return err;
1854}
1855
1856DLLEXPORT bool trace_is_err_output(libtrace_out_t *trace)
1857{
1858        return trace->err.err_num != 0;
1859}
1860
1861/* Prints the output error status to standard error and clears the error state
1862 */
1863DLLEXPORT void trace_perror_output(libtrace_out_t *trace,const char *msg,...)
1864{
1865        char buf[256];
1866        va_list va;
1867        va_start(va,msg);
1868        vsnprintf(buf,sizeof(buf),msg,va);
1869        va_end(va);
1870        if(trace->err.err_num) {
1871                fprintf(stderr,"%s(%s): %s\n",
1872                                buf,
1873                                trace->uridata?trace->uridata:"no uri",
1874                                trace->err.problem);
1875        } else {
1876                fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1877        }
1878        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1879        trace->err.problem[0]='\0';
1880}
1881
1882DLLEXPORT int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts)
1883{
1884        if (trace->format->seek_erf) {
1885                return trace->format->seek_erf(trace,ts);
1886        }
1887        else {
1888                if (trace->format->seek_timeval) {
1889                        struct timeval tv;
1890#if __BYTE_ORDER == __BIG_ENDIAN
1891                        tv.tv_sec = ts & 0xFFFFFFFF;
1892                        tv.tv_usec = ((ts >> 32) * 1000000) & 0xFFFFFFFF;
1893#elif __BYTE_ORDER == __LITTLE_ENDIAN
1894                        tv.tv_sec = ts >> 32;
1895                        tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1896#else
1897#error "What on earth are you running this on?"
1898#endif
1899                        if (tv.tv_usec >= 1000000) {
1900                                tv.tv_usec -= 1000000;
1901                                tv.tv_sec += 1;
1902                        }
1903                        return trace->format->seek_timeval(trace,tv);
1904                }
1905                if (trace->format->seek_seconds) {
1906                        double seconds =
1907                                (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1908                        return trace->format->seek_seconds(trace,seconds);
1909                }
1910                trace_set_err(trace,
1911                                TRACE_ERR_OPTION_UNAVAIL,
1912                                "Feature unimplemented");
1913                return -1;
1914        }
1915}
1916
1917DLLEXPORT int trace_seek_seconds(libtrace_t *trace, double seconds)
1918{
1919        if (trace->format->seek_seconds) {
1920                return trace->format->seek_seconds(trace,seconds);
1921        }
1922        else {
1923                if (trace->format->seek_timeval) {
1924                        struct timeval tv;
1925                        tv.tv_sec = (uint32_t)seconds;
1926                        tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1927                        return trace->format->seek_timeval(trace,tv);
1928                }
1929                if (trace->format->seek_erf) {
1930                        uint64_t timestamp =
1931                                ((uint64_t)((uint32_t)seconds) << 32) + \
1932                            (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
1933                        return trace->format->seek_erf(trace,timestamp);
1934                }
1935                trace_set_err(trace,
1936                                TRACE_ERR_OPTION_UNAVAIL,
1937                                "Feature unimplemented");
1938                return -1;
1939        }
1940}
1941
1942DLLEXPORT int trace_seek_timeval(libtrace_t *trace, struct timeval tv)
1943{
1944        if (trace->format->seek_timeval) {
1945                return trace->format->seek_timeval(trace,tv);
1946        }
1947        else {
1948                if (trace->format->seek_erf) {
1949                        uint64_t timestamp = ((((uint64_t)tv.tv_sec) << 32) + \
1950                                (((uint64_t)tv.tv_usec * UINT_MAX)/1000000));
1951                        return trace->format->seek_erf(trace,timestamp);
1952                }
1953                if (trace->format->seek_seconds) {
1954                        double seconds = tv.tv_sec + ((tv.tv_usec * 1.0)/1000000);
1955                        return trace->format->seek_seconds(trace,seconds);
1956                }
1957                trace_set_err(trace,
1958                                TRACE_ERR_OPTION_UNAVAIL,
1959                                "Feature unimplemented");
1960                return -1;
1961        }
1962}
1963
1964/* Converts a binary ethernet MAC address into a printable string */
1965DLLEXPORT char *trace_ether_ntoa(const uint8_t *addr, char *buf)
1966{
1967        static char staticbuf[18]={0,};
1968        if (!buf)
1969                buf=staticbuf;
1970        snprintf(buf,(size_t)18,"%02x:%02x:%02x:%02x:%02x:%02x",
1971                        addr[0],addr[1],addr[2],
1972                        addr[3],addr[4],addr[5]);
1973        return buf;
1974}
1975
1976/* Converts a printable ethernet MAC address into a binary format */
1977DLLEXPORT uint8_t *trace_ether_aton(const char *buf, uint8_t *addr)
1978{
1979        uint8_t *buf2 = addr;
1980        unsigned int tmp[6];
1981        static uint8_t staticaddr[6];
1982        if (!buf2)
1983                buf2=staticaddr;
1984        sscanf(buf,"%x:%x:%x:%x:%x:%x",
1985                        &tmp[0],&tmp[1],&tmp[2],
1986                        &tmp[3],&tmp[4],&tmp[5]);
1987        buf2[0]=tmp[0]; buf2[1]=tmp[1]; buf2[2]=tmp[2];
1988        buf2[3]=tmp[3]; buf2[4]=tmp[4]; buf2[5]=tmp[5];
1989        return buf2;
1990}
1991
1992
1993/* Creates a libtrace packet from scratch using the contents of the provided
1994 * buffer as the packet payload.
1995 *
1996 * Unlike trace_prepare_packet(), the buffer should not contain any capture
1997 * format headers; instead this function will add the PCAP header to the
1998 * packet record. This also means only PCAP packets can be constructed using
1999 * this function.
2000 *
2001 */
2002DLLEXPORT
2003void trace_construct_packet(libtrace_packet_t *packet,
2004                libtrace_linktype_t linktype,
2005                const void *data,
2006                uint16_t len)
2007{
2008        size_t size;
2009        static libtrace_t *deadtrace=NULL;
2010        libtrace_pcapfile_pkt_hdr_t hdr;
2011#ifdef WIN32
2012        struct _timeb tstruct;
2013#else
2014        struct timeval tv;
2015#endif
2016
2017        /* We need a trace to attach the constructed packet to (and it needs
2018         * to be PCAP) */
2019        if (NULL == deadtrace)
2020                deadtrace=trace_create_dead("pcapfile");
2021
2022        /* Fill in the new PCAP header */
2023#ifdef WIN32
2024        _ftime(&tstruct);
2025        hdr.ts_sec=tstruct.time;
2026        hdr.ts_usec=tstruct.millitm * 1000;
2027#else
2028        gettimeofday(&tv,NULL);
2029        hdr.ts_sec=tv.tv_sec;
2030        hdr.ts_usec=tv.tv_usec;
2031#endif
2032
2033        hdr.caplen=len;
2034        hdr.wirelen=len;
2035
2036        /* Now fill in the libtrace packet itself */
2037        assert(deadtrace);
2038        packet->trace=deadtrace;
2039        size=len+sizeof(hdr);
2040        if (size < LIBTRACE_PACKET_BUFSIZE)
2041            size = LIBTRACE_PACKET_BUFSIZE;
2042        if (packet->buf_control==TRACE_CTRL_PACKET) {
2043            packet->buffer = realloc(packet->buffer, size);
2044        }
2045        else {
2046                packet->buffer = malloc(size);
2047        }
2048        packet->buf_control=TRACE_CTRL_PACKET;
2049        packet->header=packet->buffer;
2050        packet->payload=(void*)((char*)packet->buffer+sizeof(hdr));
2051
2052        /* Ugh, memmove - sadly necessary, also beware that we might be
2053         * moving data around within this packet, so ordering is important.
2054         */
2055        memmove(packet->payload, data, (size_t)len);
2056        memmove(packet->header, &hdr, sizeof(hdr));
2057        packet->type=pcap_linktype_to_rt(libtrace_to_pcap_linktype(linktype));
2058
2059        trace_clear_cache(packet);
2060}
2061
2062
2063uint64_t trace_get_received_packets(libtrace_t *trace)
2064{
2065        assert(trace);
2066        uint64_t ret;
2067
2068        if (trace->format->get_received_packets) {
2069                if ((ret = trace->format->get_received_packets(trace)) != UINT64_MAX)
2070                        return ret;
2071        } else if (trace->format->get_statistics) {
2072                struct libtrace_stat_t stat;
2073                stat.magic = LIBTRACE_STAT_MAGIC;
2074                trace_get_statistics(trace, &stat);
2075                if (stat.received_valid)
2076                        return stat.received;
2077        }
2078
2079        // Read the cached value taken before the trace was paused/closed
2080        if(trace->stats && trace->stats->received_valid)
2081                return trace->stats->received;
2082        else
2083                return UINT64_MAX;
2084}
2085
2086uint64_t trace_get_filtered_packets(libtrace_t *trace)
2087{
2088        assert(trace);
2089        int i = 0;
2090        uint64_t lib_filtered = trace->filtered_packets;
2091        for (i = 0; i < trace->perpkt_thread_count; i++) {
2092                lib_filtered += trace->perpkt_threads[i].filtered_packets;
2093        }
2094        if (trace->format->get_filtered_packets) {
2095                uint64_t trace_filtered = trace->format->get_filtered_packets(trace);
2096                if (trace_filtered == UINT64_MAX)
2097                        return UINT64_MAX;
2098                else
2099                        return trace_filtered + lib_filtered;
2100        } else if (trace->format->get_statistics) {
2101                struct libtrace_stat_t stat;
2102                stat.magic = LIBTRACE_STAT_MAGIC;
2103                trace_get_statistics(trace, &stat);
2104                if (stat.filtered_valid)
2105                        return lib_filtered + stat.filtered;
2106                else
2107                        return UINT64_MAX;
2108        }
2109
2110        // Read the cached value taken before the trace was paused/closed
2111        if(trace->stats && trace->stats->filtered_valid)
2112                return trace->stats->filtered + lib_filtered;
2113        else
2114                return lib_filtered;
2115}
2116
2117uint64_t trace_get_dropped_packets(libtrace_t *trace)
2118{
2119        assert(trace);
2120        uint64_t ret;
2121
2122        if (trace->format->get_dropped_packets) {
2123                if ((ret = trace->format->get_dropped_packets(trace)) != UINT64_MAX)
2124                        return ret;
2125        } else if (trace->format->get_statistics) {
2126                struct libtrace_stat_t stat;
2127                stat.magic = LIBTRACE_STAT_MAGIC;
2128                trace_get_statistics(trace, &stat);
2129                if (stat.dropped_valid)
2130                        return stat.dropped;
2131        }
2132
2133        // Read the cached value taken before the trace was paused/closed
2134        if(trace->stats && trace->stats->dropped_valid)
2135                return trace->stats->dropped;
2136        else
2137                return UINT64_MAX;
2138}
2139
2140uint64_t trace_get_accepted_packets(libtrace_t *trace)
2141{
2142        assert(trace);
2143        int i = 0;
2144        uint64_t ret = 0;
2145        /* We always add to a thread's accepted count before dispatching the
2146         * packet to the user. However if the underlying trace is single
2147         * threaded it will also be increasing the global count. So if we
2148         * find perpkt ignore the global count.
2149         */
2150        for (i = 0; i < trace->perpkt_thread_count; i++) {
2151                ret += trace->perpkt_threads[i].accepted_packets;
2152        }
2153        return ret ? ret : trace->accepted_packets;
2154}
2155
2156libtrace_stat_t *trace_get_statistics(libtrace_t *trace, libtrace_stat_t *stat)
2157{
2158        uint64_t ret = 0;
2159        int i;
2160        assert(trace);
2161        if (stat == NULL) {
2162                if (trace->stats == NULL)
2163                        trace->stats = trace_create_statistics();
2164                stat = trace->stats;
2165        }
2166        assert(stat->magic == LIBTRACE_STAT_MAGIC && "Please use"
2167               "trace_create_statistics() to allocate statistics");
2168
2169        /* If the trace has paused or finished get the cached results */
2170        if (trace->state == STATE_PAUSED ||
2171            trace->state == STATE_FINISHED ||
2172            trace->state == STATE_FINISHING ||
2173            trace->state == STATE_JOINED) {
2174                if (trace->stats && trace->stats != stat)
2175                        *stat = *trace->stats;
2176                return stat;
2177        }
2178
2179        stat->reserved1 = 0;
2180        stat->reserved2 = 0;
2181#define X(x) stat->x ##_valid = 0;
2182        LIBTRACE_STAT_FIELDS;
2183#undef X
2184        /* Both accepted and filtered are stored against in the library */
2185
2186        /* We always add to a thread's accepted count before dispatching the
2187         * packet to the user. However if the underlying trace is single
2188         * threaded it will also be increasing the global count. So if we
2189         * find perpkt ignore the global count.
2190         */
2191        for (i = 0; i < trace->perpkt_thread_count; i++) {
2192                ret += trace->perpkt_threads[i].accepted_packets;
2193        }
2194
2195        stat->accepted_valid = 1;
2196        stat->accepted = ret ? ret : trace->accepted_packets;
2197
2198        stat->filtered_valid = 1;
2199        stat->filtered = trace->filtered_packets;
2200        for (i = 0; i < trace->perpkt_thread_count; i++) {
2201                stat->filtered += trace->perpkt_threads[i].filtered_packets;
2202        }
2203
2204        if (trace->format->get_statistics) {
2205                trace->format->get_statistics(trace, stat);
2206        }
2207        return stat;
2208}
2209
2210void trace_get_thread_statistics(libtrace_t *trace, libtrace_thread_t *t,
2211                                 libtrace_stat_t *stat)
2212{
2213        assert(trace && stat);
2214        assert(stat->magic == LIBTRACE_STAT_MAGIC && "Please use"
2215               "trace_create_statistics() to allocate statistics");
2216        stat->reserved1 = 0;
2217        stat->reserved2 = 0;
2218#define X(x) stat->x ##_valid= 0;
2219        LIBTRACE_STAT_FIELDS;
2220#undef X
2221        stat->accepted_valid = 1;
2222        stat->accepted = t->accepted_packets;
2223        stat->filtered_valid = 1;
2224        stat->filtered = t->filtered_packets;
2225        if (!trace_has_dedicated_hasher(trace) && trace->format->get_thread_statistics) {
2226                trace->format->get_thread_statistics(trace, t, stat);
2227        }
2228        return;
2229}
2230
2231libtrace_stat_t *trace_create_statistics(void) {
2232        libtrace_stat_t *ret;
2233        ret = malloc(sizeof(libtrace_stat_t));
2234        if (ret) {
2235                memset(ret, 0, sizeof(libtrace_stat_t));
2236                ret->magic = LIBTRACE_STAT_MAGIC;
2237        }
2238        return ret;
2239}
2240
2241void trace_clear_statistics(libtrace_stat_t *s) {
2242        memset(s, 0, sizeof(libtrace_stat_t));
2243        s->magic = LIBTRACE_STAT_MAGIC;
2244}
2245
2246void trace_subtract_statistics(const libtrace_stat_t *a, const libtrace_stat_t *b,
2247                         libtrace_stat_t *c) {
2248        assert(a->magic == LIBTRACE_STAT_MAGIC && "Please use"
2249               "trace_create_statistics() to allocate statistics");
2250        assert(b->magic == LIBTRACE_STAT_MAGIC && "Please use"
2251               "trace_create_statistics() to allocate statistics");
2252        assert(c->magic == LIBTRACE_STAT_MAGIC && "Please use"
2253               "trace_create_statistics() to allocate statistics");
2254
2255#define X(x) \
2256        if (a->x ##_valid && b->x ##_valid) { \
2257                c->x ##_valid = 1; \
2258                c->x = a->x - b->x; \
2259        } else {\
2260                c->x ##_valid = 0;\
2261        }
2262        LIBTRACE_STAT_FIELDS
2263#undef X
2264}
2265
2266void trace_add_statistics(const libtrace_stat_t *a, const libtrace_stat_t *b,
2267                         libtrace_stat_t *c) {
2268        assert(a->magic == LIBTRACE_STAT_MAGIC && "Please use"
2269               "trace_create_statistics() to allocate statistics");
2270        assert(b->magic == LIBTRACE_STAT_MAGIC && "Please use"
2271               "trace_create_statistics() to allocate statistics");
2272        assert(c->magic == LIBTRACE_STAT_MAGIC && "Please use"
2273               "trace_create_statistics() to allocate statistics");
2274
2275#define X(x) \
2276        if (a->x ##_valid&& b->x ##_valid) { \
2277                c->x ##_valid = 1; \
2278                c->x = a->x + b->x; \
2279        } else {\
2280                c->x ##_valid = 0;\
2281        }
2282        LIBTRACE_STAT_FIELDS
2283#undef X
2284}
2285
2286int trace_print_statistics(const libtrace_stat_t *s, FILE *f, const char *format) {
2287        assert(s->magic == LIBTRACE_STAT_MAGIC && "Please use"
2288               "trace_create_statistics() to allocate statistics");
2289        if (format == NULL)
2290                format = "%s: %"PRIu64"\n";
2291#define xstr(s) str(s)
2292#define str(s) #s
2293#define X(x) \
2294        if (s->x ##_valid) { \
2295                if (fprintf(f, format, xstr(x), s->x) < 0) \
2296                        return -1; \
2297        }
2298        LIBTRACE_STAT_FIELDS
2299#undef X
2300        return 0;
2301}
2302
2303
2304void trace_clear_cache(libtrace_packet_t *packet) {
2305
2306        packet->l2_header = NULL;
2307        packet->l3_header = NULL;
2308        packet->l4_header = NULL;
2309        packet->link_type = 0;
2310        packet->l3_ethertype = 0;
2311        packet->transport_proto = 0;
2312        packet->capture_length = -1;
2313        packet->wire_length = -1;
2314        packet->payload_length = -1;
2315        packet->l2_remaining = 0;
2316        packet->l3_remaining = 0;
2317        packet->l4_remaining = 0;
2318
2319}
2320
2321void trace_interrupt(void) {
2322        libtrace_halt = 1;
2323}
2324
2325void register_format(struct libtrace_format_t *f) {
2326        assert(f->next==NULL); /* Can't register a format twice */
2327        f->next=formats_list;
2328        formats_list=f;
2329
2330        /* Now, verify that the format has at least the minimum functionality.
2331         *
2332         * This #if can be changed to a 1 to output warnings about inconsistent
2333         * functions being provided by format modules.  This generally is very
2334         * noisy, as almost all modules don't implement one or more functions
2335         * for various reasons.  This is very useful when checking a new
2336         * format module is sane.
2337         */
2338#if 0
2339        if (f->init_input) {
2340#define REQUIRE(x) \
2341                if (!f->x) \
2342                        fprintf(stderr,"%s: Input format should provide " #x "\n",f->name)
2343                REQUIRE(read_packet);
2344                REQUIRE(start_input);
2345                REQUIRE(fin_input);
2346                REQUIRE(get_link_type);
2347                REQUIRE(get_capture_length);
2348                REQUIRE(get_wire_length);
2349                REQUIRE(get_framing_length);
2350                REQUIRE(trace_event);
2351                if (!f->get_erf_timestamp
2352                        && !f->get_seconds
2353                        && !f->get_timeval) {
2354                        fprintf(stderr,"%s: A trace format capable of input, should provide at least one of\n"
2355"get_erf_timestamp, get_seconds or trace_timeval\n",f->name);
2356                }
2357                if (f->trace_event!=trace_event_trace) {
2358                        /* Theres nothing that a trace file could optimise with
2359                         * config_input
2360                         */
2361                        REQUIRE(pause_input);
2362                        REQUIRE(config_input);
2363                        REQUIRE(get_fd);
2364                }
2365                else {
2366                        if (f->get_fd) {
2367                                fprintf(stderr,"%s: Unnecessary get_fd\n",
2368                                                f->name);
2369                        }
2370                }
2371#undef REQUIRE
2372        }
2373        else {
2374#define REQUIRE(x) \
2375                if (f->x) \
2376                        fprintf(stderr,"%s: Non Input format shouldn't need " #x "\n",f->name)
2377                REQUIRE(read_packet);
2378                REQUIRE(start_input);
2379                REQUIRE(pause_input);
2380                REQUIRE(fin_input);
2381                REQUIRE(get_link_type);
2382                REQUIRE(get_capture_length);
2383                REQUIRE(get_wire_length);
2384                REQUIRE(get_framing_length);
2385                REQUIRE(trace_event);
2386                REQUIRE(get_seconds);
2387                REQUIRE(get_timeval);
2388                REQUIRE(get_erf_timestamp);
2389#undef REQUIRE
2390        }
2391        if (f->init_output) {
2392#define REQUIRE(x) \
2393                if (!f->x) \
2394                        fprintf(stderr,"%s: Output format should provide " #x "\n",f->name)
2395                REQUIRE(write_packet);
2396                REQUIRE(start_output);
2397                REQUIRE(config_output);
2398                REQUIRE(fin_output);
2399#undef REQUIRE
2400        }
2401        else {
2402#define REQUIRE(x) \
2403                if (f->x) \
2404                        fprintf(stderr,"%s: Non Output format shouldn't need " #x "\n",f->name)
2405                REQUIRE(write_packet);
2406                REQUIRE(start_output);
2407                REQUIRE(config_output);
2408                REQUIRE(fin_output);
2409#undef REQUIRE
2410        }
2411#endif
2412}
2413
Note: See TracBrowser for help on using the repository browser.