source: lib/trace.c @ 7fda5c5

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 7fda5c5 was 7fda5c5, checked in by Shane Alcock <salcock@…>, 7 years ago

Fix bogus filtered packet calc for BPF format

This was essentially counting filtered packets twice,
first by deducting accepted from received, then adding on
the local filtered counter.

Since BPF doesn't do any in-kernel filtering, all we actually
need is libtrace's filtered counter.

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