source: lib/trace.c @ adb2c4c

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

Remove mutex in the packet path, which limits parallel performance

Packets should be destroyed (or finished) before the format is closed,
however this was never enforced or implemented in the single threaded API.

As such to provide support for old applications that destroy the packet
after the trace we store the packet against the trace. This was a race
and locks were used for safety even when using the parallel API.

Instead of locks we can assume that the parallel API will destroy
packets before the trace is closed. So instead of locks only store
the packet in the single threaded case.

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