source: lib/trace.c @ fd4482d

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

Make sure trace_create_packet() doesn't segfault

If allocating memory for the new packet fails, we now return NULL
instead of carrying on and trying to initialise the packet fields.

This has always been the intended behaviour (see some of the examples
for cases where we check if packet is NULL after calling trace_create_packet())
but I guess nobody actually implemented it...

  • Property mode set to 100644
File size: 53.7 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
107volatile int 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 the
296                         * 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        if (packet == NULL)
641                return NULL;
642
643        packet->buf_control=TRACE_CTRL_PACKET;
644        trace_clear_cache(packet);
645        return packet;
646}
647
648DLLEXPORT libtrace_packet_t *trace_copy_packet(const libtrace_packet_t *packet) {
649        libtrace_packet_t *dest =
650                (libtrace_packet_t *)malloc(sizeof(libtrace_packet_t));
651        if (!dest) {
652                printf("Out of memory constructing packet\n");
653                abort();
654        }
655        dest->trace=packet->trace;
656        dest->buffer=malloc(65536);
657        if (!dest->buffer) {
658                printf("Out of memory allocating buffer memory\n");
659                abort();
660        }
661        dest->header=dest->buffer;
662        dest->payload=(void*)
663                ((char*)dest->buffer+trace_get_framing_length(packet));
664        dest->type=packet->type;
665        dest->buf_control=TRACE_CTRL_PACKET;
666        /* Reset the cache - better to recalculate than try to convert
667         * the values over to the new packet */
668        trace_clear_cache(dest);
669        /* Ooooh nasty memcpys! This is why we want to avoid copying packets
670         * as much as possible */
671        memcpy(dest->header,packet->header,trace_get_framing_length(packet));
672        memcpy(dest->payload,packet->payload,trace_get_capture_length(packet));
673
674        return dest;
675}
676
677/** Destroy a packet object
678 */
679DLLEXPORT void trace_destroy_packet(libtrace_packet_t *packet) {
680        if (packet->buf_control == TRACE_CTRL_PACKET && packet->buffer) {
681                free(packet->buffer);
682        }
683        packet->buf_control=(buf_control_t)'\0';
684                                /* A "bad" value to force an assert
685                                 * if this packet is ever reused
686                                 */
687        free(packet);
688}
689
690/* Read one packet from the trace into buffer. Note that this function will
691 * block until a packet is read (or EOF is reached).
692 *
693 * @param libtrace      the libtrace opaque pointer
694 * @param packet        the packet opaque pointer
695 * @returns 0 on EOF, negative value on error
696 *
697 */
698DLLEXPORT int trace_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
699
700        assert(libtrace && "You called trace_read_packet() with a NULL libtrace parameter!\n");
701        if (trace_is_err(libtrace))
702                return -1;
703        if (!libtrace->started) {
704                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"You must call libtrace_start() before trace_read_packet()\n");
705                return -1;
706        }
707        if (!(packet->buf_control==TRACE_CTRL_PACKET
708                    || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
709                trace_set_err(libtrace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
710                return -1;
711        }
712        assert(packet);
713
714        /* Store the trace we are reading from into the packet opaque
715         * structure */
716        packet->trace = libtrace;
717
718        /* Finalise the packet, freeing any resources the format module
719         * may have allocated it
720         */
721        if (libtrace->format->fin_packet) {
722                libtrace->format->fin_packet(packet);
723        }
724
725
726        if (libtrace->format->read_packet) {
727                do {
728                        size_t ret;
729                        int filtret;
730                        /* Clear the packet cache */
731                        trace_clear_cache(packet);
732                        ret=libtrace->format->read_packet(libtrace,packet);
733                        if (ret==(size_t)-1 || ret==0) {
734                                return ret;
735                        }
736                        if (libtrace->filter) {
737                                /* If the filter doesn't match, read another
738                                 * packet
739                                 */
740                                filtret = trace_apply_filter(libtrace->filter, packet);
741                                if (filtret == -1) {
742                                        /* Error compiling filter, probably */
743                                        return ~0U;
744                                }
745
746                                if (filtret == 0) {
747                                        ++libtrace->filtered_packets;
748                                        continue;
749                                }
750                        }
751                        if (libtrace->snaplen>0) {
752                                /* Snap the packet */
753                                trace_set_capture_length(packet,
754                                                libtrace->snaplen);
755                        }
756                        ++libtrace->accepted_packets;
757                        return ret;
758                } while(1);
759        }
760        trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,"This format does not support reading packets\n");
761        return ~0U;
762}
763
764/* Converts the provided buffer into a libtrace packet of the given type.
765 *
766 * Unlike trace_construct_packet, the buffer is expected to begin with the
767 * appropriate capture format header for the format type that the packet is
768 * being converted to. This also allows for a packet to be converted into
769 * just about capture format that is supported by libtrace, provided the
770 * format header is present in the buffer.
771 *
772 * This function is primarily used to convert packets received via the RT
773 * protocol back into their original capture format. The RT header encapsulates
774 * the original capture format header, so after removing it the packet must
775 * have it's header and payload pointers updated and the packet format and type
776 * changed, amongst other things.
777 *
778 * Intended only for internal use at this point - this function is not
779 * available through the external libtrace API.
780 */
781int trace_prepare_packet(libtrace_t *trace, libtrace_packet_t *packet,
782                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
783
784        assert(packet);
785        assert(trace);
786
787        /* XXX Proper error handling?? */
788        if (buffer == NULL)
789                return -1;
790
791        if (!(packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)) {
792                trace_set_err(trace,TRACE_ERR_BAD_STATE,"Packet passed to trace_read_packet() is invalid\n");
793                return -1;
794        }
795
796        packet->trace = trace;
797
798        /* Clear packet cache */
799        trace_clear_cache(packet);
800
801        if (trace->format->prepare_packet) {
802                return trace->format->prepare_packet(trace, packet,
803                                buffer, rt_type, flags);
804        }
805        trace_set_err(trace, TRACE_ERR_UNSUPPORTED,
806                        "This format does not support preparing packets\n");
807        return -1;
808
809}
810
811/* Writes a packet to the specified output trace
812 *
813 * @param libtrace      describes the output format, destination, etc.
814 * @param packet        the packet to be written out
815 * @returns the number of bytes written, -1 if write failed
816 */
817DLLEXPORT int trace_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
818        assert(libtrace);
819        assert(packet);
820        /* Verify the packet is valid */
821        if (!libtrace->started) {
822                trace_set_err_out(libtrace,TRACE_ERR_BAD_STATE,
823                        "Trace is not started before trace_write_packet");
824                return -1;
825        }
826
827        if (libtrace->format->write_packet) {
828                return libtrace->format->write_packet(libtrace, packet);
829        }
830        trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
831                "This format does not support writing packets");
832        return -1;
833}
834
835/* Get a pointer to the first byte of the packet payload */
836DLLEXPORT void *trace_get_packet_buffer(const libtrace_packet_t *packet,
837                libtrace_linktype_t *linktype, uint32_t *remaining) {
838        int cap_len;
839        int wire_len;
840
841        assert(packet != NULL);
842        if (linktype) *linktype = trace_get_link_type(packet);
843        if (remaining) {
844                /* I think we should choose the minimum of the capture and
845                 * wire lengths to be the "remaining" value. If the packet has
846                 * been padded to increase the capture length, we don't want
847                 * to allow subsequent protocol decoders to consider the
848                 * padding as part of the packet.
849                 *
850                 * For example, in Auck 4 there is a trace where the IP header
851                 * length is incorrect (24 bytes) followed by a 20 byte TCP
852                 * header. Total IP length is 40 bytes. As a result, the
853                 * legacyatm padding gets treated as the "missing" bytes of
854                 * the TCP header, which isn't the greatest. We're probably
855                 * better off returning an incomplete TCP header in that case.
856                 */
857
858                cap_len = trace_get_capture_length(packet);
859                wire_len = trace_get_wire_length(packet);
860
861                assert(cap_len >= 0);
862
863                /* There is the odd corrupt packet, e.g. in IPLS II, that have
864                 * massively negative wire lens. We could assert fail here on
865                 * them, but we could at least try the capture length instead.
866                 *
867                 * You may still run into problems if you try to write that
868                 * packet, but at least reading should work OK.
869                 */
870                if (wire_len < 0)
871                        *remaining = cap_len;
872                else if (wire_len < cap_len)
873                        *remaining = wire_len;
874                else
875                        *remaining = cap_len;
876                /* *remaining = trace_get_capture_length(packet); */
877        }
878        return (void *) packet->payload;
879}
880
881
882/* Get a pointer to the first byte of the packet payload
883 *
884 * DEPRECATED - use trace_get_packet_buffer() instead */
885DLLEXPORT void *trace_get_link(const libtrace_packet_t *packet) {
886        return (void *)packet->payload;
887}
888
889/* Get the current time in DAG time format
890 * @param packet        a pointer to a libtrace_packet structure
891 * @returns a 64 bit timestamp in DAG ERF format (upper 32 bits are the seconds
892 * past 1970-01-01, the lower 32bits are partial seconds)
893 */
894DLLEXPORT uint64_t trace_get_erf_timestamp(const libtrace_packet_t *packet) {
895        if (packet->trace->format->get_erf_timestamp) {
896                /* timestamp -> timestamp */
897                return packet->trace->format->get_erf_timestamp(packet);
898        } else if (packet->trace->format->get_timespec) {
899                /* timespec -> timestamp */
900                struct timespec ts;
901                ts = packet->trace->format->get_timespec(packet);
902                return ((((uint64_t)ts.tv_sec) << 32) +
903                                (((uint64_t)ts.tv_nsec << 32)/1000000000));
904        } else if (packet->trace->format->get_timeval) {
905                /* timeval -> timestamp */
906                struct timeval tv;
907                tv = packet->trace->format->get_timeval(packet);
908                return ((((uint64_t)tv.tv_sec) << 32) +
909                                (((uint64_t)tv.tv_usec << 32)/1000000));
910        } else if (packet->trace->format->get_seconds) {
911                /* seconds -> timestamp */
912                double seconds = packet->trace->format->get_seconds(packet);
913                return (((uint64_t)seconds)<<32)
914                          + (uint64_t)((seconds-(uint64_t)seconds)*UINT_MAX);
915        }
916        else {
917                return (uint64_t)0;
918        }
919}
920
921/* Get the current time in struct timeval
922 * @param packet        a pointer to a libtrace_packet structure
923 *
924 * @returns time that this packet was seen in a struct timeval
925 * @author Daniel Lawson
926 * @author Perry Lorier
927 */
928DLLEXPORT struct timeval trace_get_timeval(const libtrace_packet_t *packet) {
929        struct timeval tv;
930        uint64_t ts = 0;
931        if (packet->trace->format->get_timeval) {
932                /* timeval -> timeval */
933                tv = packet->trace->format->get_timeval(packet);
934        } else if (packet->trace->format->get_erf_timestamp) {
935                /* timestamp -> timeval */
936                ts = packet->trace->format->get_erf_timestamp(packet);
937                tv.tv_sec = ts >> 32;
938                tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
939                if (tv.tv_usec >= 1000000) {
940                        tv.tv_usec -= 1000000;
941                        tv.tv_sec += 1;
942                }
943        } else if (packet->trace->format->get_timespec) {
944                struct timespec ts = packet->trace->format->get_timespec(packet);
945                tv.tv_sec = ts.tv_sec;
946                tv.tv_usec = ts.tv_nsec/1000;
947        } else if (packet->trace->format->get_seconds) {
948                /* seconds -> timeval */
949                double seconds = packet->trace->format->get_seconds(packet);
950                tv.tv_sec = (uint32_t)seconds;
951                tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
952        }
953        else {
954                tv.tv_sec=-1;
955                tv.tv_usec=-1;
956        }
957
958        return tv;
959}
960
961DLLEXPORT struct timespec trace_get_timespec(const libtrace_packet_t *packet) {
962        struct timespec ts;
963
964        if (packet->trace->format->get_timespec) {
965                return packet->trace->format->get_timespec(packet);
966        } else if (packet->trace->format->get_erf_timestamp) {
967                /* timestamp -> timeval */
968                uint64_t erfts = packet->trace->format->get_erf_timestamp(packet);
969                ts.tv_sec = erfts >> 32;
970                ts.tv_nsec = ((erfts&0xFFFFFFFF)*1000000000)>>32;
971                if (ts.tv_nsec >= 1000000000) {
972                        ts.tv_nsec -= 1000000000;
973                        ts.tv_sec += 1;
974                }
975                return ts;
976        } else if (packet->trace->format->get_timeval) {
977                /* timeval -> timespec */
978                struct timeval tv = packet->trace->format->get_timeval(packet);
979                ts.tv_sec = tv.tv_sec;
980                ts.tv_nsec = tv.tv_usec*1000;
981                return ts;
982        } else if (packet->trace->format->get_seconds) {
983                /* seconds -> timespec */
984                double seconds = packet->trace->format->get_seconds(packet);
985                ts.tv_sec = (uint32_t)seconds;
986                ts.tv_nsec = (long)(((seconds - ts.tv_sec) * 1000000000)/UINT_MAX);
987                return ts;
988        }
989        else {
990                ts.tv_sec=-1;
991                ts.tv_nsec=-1;
992                return ts;
993        }
994}
995
996
997/* Get the current time in floating point seconds
998 * @param packet        a pointer to a libtrace_packet structure
999 * @returns time that this packet was seen in 64bit floating point seconds
1000 */
1001DLLEXPORT double trace_get_seconds(const libtrace_packet_t *packet) {
1002        double seconds = 0.0;
1003
1004        if (packet->trace->format->get_seconds) {
1005                /* seconds->seconds */
1006                seconds = packet->trace->format->get_seconds(packet);
1007        } else if (packet->trace->format->get_erf_timestamp) {
1008                /* timestamp -> seconds */
1009                uint64_t ts = 0;
1010                ts = packet->trace->format->get_erf_timestamp(packet);
1011                seconds =  (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1012        } else if (packet->trace->format->get_timespec) {
1013                /* timespec -> seconds */
1014                struct timespec ts;
1015                ts = packet->trace->format->get_timespec(packet);
1016                seconds = ts.tv_sec + ((ts.tv_nsec * 1.0) / 1000000000);
1017        } else if (packet->trace->format->get_timeval) {
1018                /* timeval -> seconds */
1019                struct timeval tv;
1020                tv = packet->trace->format->get_timeval(packet);
1021                seconds = tv.tv_sec + ((tv.tv_usec * 1.0) / 1000000);
1022        }
1023
1024        return seconds;
1025}
1026
1027DLLEXPORT size_t trace_get_capture_length(const libtrace_packet_t *packet)
1028{
1029        /* Cache the capture length */
1030        if (packet->capture_length == -1) {
1031                if (!packet->trace->format->get_capture_length)
1032                        return ~0U;
1033                /* Cast away constness because this is "just" a cache */
1034                ((libtrace_packet_t*)packet)->capture_length =
1035                        packet->trace->format->get_capture_length(packet);
1036        }
1037
1038        assert(packet->capture_length < LIBTRACE_PACKET_BUFSIZE);
1039
1040        return packet->capture_length;
1041}
1042
1043/* Get the size of the packet as it was seen on the wire.
1044 * @param packet        a pointer to a libtrace_packet structure
1045 *
1046 * @returns the size of the packet as it was on the wire.
1047 * @note Due to the trace being a header capture, or anonymisation this may
1048 * not be the same as the Capture Len.
1049 */
1050DLLEXPORT size_t trace_get_wire_length(const libtrace_packet_t *packet){
1051
1052        if (packet->wire_length == -1) {
1053                if (!packet->trace->format->get_wire_length)
1054                        return ~0U;
1055                ((libtrace_packet_t *)packet)->wire_length =
1056                        packet->trace->format->get_wire_length(packet);
1057        }
1058
1059        assert(packet->wire_length < LIBTRACE_PACKET_BUFSIZE);
1060        return packet->wire_length;
1061
1062}
1063
1064/* Get the length of the capture framing headers.
1065 * @param packet        the packet opaque pointer
1066 * @returns the size of the packet as it was on the wire.
1067 * @note this length corresponds to the difference between the size of a
1068 * captured packet in memory, and the captured length of the packet
1069 */
1070DLLEXPORT SIMPLE_FUNCTION
1071size_t trace_get_framing_length(const libtrace_packet_t *packet) {
1072        if (packet->trace->format->get_framing_length) {
1073                return packet->trace->format->get_framing_length(packet);
1074        }
1075        return ~0U;
1076}
1077
1078
1079/* Get the type of the link layer
1080 * @param packet        a pointer to a libtrace_packet structure
1081 * @returns libtrace_linktype_t
1082 */
1083DLLEXPORT libtrace_linktype_t trace_get_link_type(const libtrace_packet_t *packet ) {
1084
1085        if (packet->link_type == 0) {
1086                if (!packet->trace->format->get_link_type)
1087                        return TRACE_TYPE_UNKNOWN;
1088                ((libtrace_packet_t *)packet)->link_type =
1089                        packet->trace->format->get_link_type(packet);
1090        }
1091
1092        return packet->link_type;
1093}
1094
1095/* process a libtrace event
1096 * @param trace the libtrace opaque pointer
1097 * @param packet the libtrace_packet opaque pointer
1098 * @returns
1099 *  TRACE_EVENT_IOWAIT  Waiting on I/O on fd
1100 *  TRACE_EVENT_SLEEP   Next event in seconds
1101 *  TRACE_EVENT_PACKET  Packet arrived in buffer with size size
1102 *  TRACE_EVENT_TERMINATE Trace terminated (perhaps with an error condition)
1103 * FIXME currently keeps a copy of the packet inside the trace pointer,
1104 * which in turn is stored inside the new packet object...
1105 */
1106DLLEXPORT libtrace_eventobj_t trace_event(libtrace_t *trace,
1107                libtrace_packet_t *packet) {
1108        libtrace_eventobj_t event = {TRACE_EVENT_IOWAIT,0,0.0,0};
1109
1110        if (!trace) {
1111                fprintf(stderr,"You called trace_event() with a NULL trace object!\n");
1112        }
1113        assert(trace);
1114        assert(packet);
1115
1116        /* Clear the packet cache */
1117        trace_clear_cache(packet);
1118
1119        /* Store the trace we are reading from into the packet opaque
1120         * structure */
1121        packet->trace = trace;
1122
1123        if (packet->trace->format->trace_event) {
1124                /* Note: incrementing accepted, filtered etc. packet
1125                 * counters is handled by the format-specific
1126                 * function so don't increment them here.
1127                 */
1128                event=packet->trace->format->trace_event(trace,packet);
1129        }
1130        return event;
1131
1132}
1133
1134/** Setup a BPF filter based on pre-compiled byte-code.
1135 * @param bf_insns      A pointer to the start of the byte-code
1136 * @param bf_len        The number of BPF instructions
1137 * @returns             an opaque pointer to a libtrace_filter_t object
1138 * @note                The supplied byte-code is not checked for correctness.
1139 * @author              Scott Raynel
1140 */
1141DLLEXPORT libtrace_filter_t *
1142trace_create_filter_from_bytecode(void *bf_insns, unsigned int bf_len)
1143{
1144#ifndef HAVE_BPF_FILTER
1145        fprintf(stderr, "This version of libtrace does not have BPF support\n");
1146        return NULL;
1147#else
1148        struct libtrace_filter_t *filter = (struct libtrace_filter_t *)
1149                malloc(sizeof(struct libtrace_filter_t));
1150        filter->filter.bf_insns = (struct bpf_insn *)
1151                malloc(sizeof(struct bpf_insn) * bf_len);
1152
1153        memcpy(filter->filter.bf_insns, bf_insns,
1154                        bf_len * sizeof(struct bpf_insn));
1155
1156        filter->filter.bf_len = bf_len;
1157        filter->filterstring = NULL;
1158        filter->jitfilter = NULL;
1159        /* "flag" indicates that the filter member is valid */
1160        filter->flag = 1;
1161
1162        return filter;
1163#endif
1164}
1165
1166/* Create a BPF filter
1167 * @param filterstring a char * containing the bpf filter string
1168 * @returns opaque pointer pointer to a libtrace_filter_t object
1169 */
1170DLLEXPORT libtrace_filter_t *trace_create_filter(const char *filterstring) {
1171#ifdef HAVE_BPF_FILTER
1172        libtrace_filter_t *filter = (libtrace_filter_t*)
1173                                malloc(sizeof(libtrace_filter_t));
1174        filter->filterstring = strdup(filterstring);
1175        filter->jitfilter = NULL;
1176        filter->flag = 0;
1177        return filter;
1178#else
1179        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1180        return NULL;
1181#endif
1182}
1183
1184DLLEXPORT void trace_destroy_filter(libtrace_filter_t *filter)
1185{
1186#ifdef HAVE_BPF_FILTER
1187        free(filter->filterstring);
1188        if (filter->flag)
1189                pcap_freecode(&filter->filter);
1190#ifdef HAVE_LLVM
1191        if (filter->jitfilter)
1192                destroy_program(filter->jitfilter);
1193#endif
1194        free(filter);
1195#else
1196
1197#endif
1198}
1199
1200/* Compile a bpf filter, now we know the link type for the trace that we're
1201 * applying it to.
1202 *
1203 * @internal
1204 *
1205 * @returns -1 on error, 0 on success
1206 */
1207static int trace_bpf_compile(libtrace_filter_t *filter,
1208                const libtrace_packet_t *packet,
1209                void *linkptr,
1210                libtrace_linktype_t linktype    ) {
1211#ifdef HAVE_BPF_FILTER
1212        assert(filter);
1213
1214        /* If this isn't a real packet, then fail */
1215        if (!linkptr) {
1216                trace_set_err(packet->trace,
1217                                TRACE_ERR_BAD_FILTER,"Packet has no payload");
1218                return -1;
1219        }
1220
1221        if (filter->filterstring && ! filter->flag) {
1222                pcap_t *pcap = NULL;
1223                if (linktype==(libtrace_linktype_t)-1) {
1224                        trace_set_err(packet->trace,
1225                                        TRACE_ERR_BAD_FILTER,
1226                                        "Packet has an unknown linktype");
1227                        return -1;
1228                }
1229                if (libtrace_to_pcap_dlt(linktype) == TRACE_DLT_ERROR) {
1230                        trace_set_err(packet->trace,TRACE_ERR_BAD_FILTER,
1231                                        "Unknown pcap equivalent linktype");
1232                        return -1;
1233                }
1234                pcap=(pcap_t *)pcap_open_dead(
1235                                (int)libtrace_to_pcap_dlt(linktype),
1236                                1500U);
1237                /* build filter */
1238                assert(pcap);
1239                if (pcap_compile( pcap, &filter->filter, filter->filterstring,
1240                                        1, 0)) {
1241                        trace_set_err(packet->trace,TRACE_ERR_BAD_FILTER,
1242                                        "Unable to compile the filter \"%s\": %s",
1243                                        filter->filterstring,
1244                                        pcap_geterr(pcap));
1245                        pcap_close(pcap);
1246                        return -1;
1247                }
1248                pcap_close(pcap);
1249                filter->flag=1;
1250        }
1251        return 0;
1252#else
1253        assert(!"Internal bug: This should never be called when BPF not enabled");
1254        trace_set_err(packet->trace,TRACE_ERR_OPTION_UNAVAIL,
1255                                "Feature unavailable");
1256        return -1;
1257#endif
1258}
1259
1260DLLEXPORT int trace_apply_filter(libtrace_filter_t *filter,
1261                        const libtrace_packet_t *packet) {
1262#ifdef HAVE_BPF_FILTER
1263        void *linkptr = 0;
1264        uint32_t clen = 0;
1265        bool free_packet_needed = false;
1266        int ret;
1267        libtrace_linktype_t linktype;
1268        libtrace_packet_t *packet_copy = (libtrace_packet_t*)packet;
1269
1270        assert(filter);
1271        assert(packet);
1272
1273        /* Match all non-data packets as we probably want them to pass
1274         * through to the caller */
1275        linktype = trace_get_link_type(packet);
1276
1277        if (linktype == TRACE_TYPE_NONDATA)
1278                return 1;
1279
1280        if (libtrace_to_pcap_dlt(linktype)==TRACE_DLT_ERROR) {
1281
1282                /* If we cannot get a suitable DLT for the packet, it may
1283                 * be because the packet is encapsulated in a link type that
1284                 * does not correspond to a DLT. Therefore, we should try
1285                 * popping off headers until we either can find a suitable
1286                 * link type or we can't do any more sensible decapsulation. */
1287
1288                /* Copy the packet, as we don't want to trash the one we
1289                 * were passed in */
1290                packet_copy=trace_copy_packet(packet);
1291                free_packet_needed=true;
1292
1293                while (libtrace_to_pcap_dlt(linktype) == TRACE_DLT_ERROR) {
1294                        if (!demote_packet(packet_copy)) {
1295                                trace_set_err(packet->trace,
1296                                                TRACE_ERR_NO_CONVERSION,
1297                                                "pcap does not support this format");
1298                                if (free_packet_needed) {
1299                                        trace_destroy_packet(packet_copy);
1300                                }
1301                                return -1;
1302                        }
1303                        linktype = trace_get_link_type(packet_copy);
1304                }
1305
1306        }
1307
1308        linkptr = trace_get_packet_buffer(packet_copy,NULL,&clen);
1309        if (!linkptr) {
1310                if (free_packet_needed) {
1311                        trace_destroy_packet(packet_copy);
1312                }
1313                return 0;
1314        }
1315
1316        /* We need to compile the filter now, because before we didn't know
1317         * what the link type was
1318         */
1319        if (trace_bpf_compile(filter,packet_copy,linkptr,linktype)==-1) {
1320                if (free_packet_needed) {
1321                        trace_destroy_packet(packet_copy);
1322                }
1323                return -1;
1324        }
1325
1326        /* If we're jitting, we may need to JIT the BPF code now too */
1327#if HAVE_LLVM
1328        if (!filter->jitfilter) {
1329                filter->jitfilter = compile_program(filter->filter.bf_insns, filter->filter.bf_len);
1330        }
1331#endif
1332
1333        assert(filter->flag);
1334        /* Now execute the filter */
1335#if HAVE_LLVM
1336        ret=filter->jitfilter->bpf_run((unsigned char *)linkptr, clen);
1337#else
1338        ret=bpf_filter(filter->filter.bf_insns,(u_char*)linkptr,(unsigned int)clen,(unsigned int)clen);
1339#endif
1340
1341        /* If we copied the packet earlier, make sure that we free it */
1342        if (free_packet_needed) {
1343                trace_destroy_packet(packet_copy);
1344        }
1345        return ret;
1346#else
1347        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1348        return 0;
1349#endif
1350}
1351
1352/* Set the direction flag, if it has one
1353 * @param packet the packet opaque pointer
1354 * @param direction the new direction (0,1,2,3)
1355 * @returns a signed value containing the direction flag, or -1 if this is not supported
1356 */
1357DLLEXPORT libtrace_direction_t trace_set_direction(libtrace_packet_t *packet,
1358                libtrace_direction_t direction)
1359{
1360        assert(packet);
1361        if (packet->trace->format->set_direction) {
1362                return packet->trace->format->set_direction(packet,direction);
1363        }
1364        return (libtrace_direction_t)~0U;
1365}
1366
1367/* Get the direction flag, if it has one
1368 * @param packet a pointer to a libtrace_packet structure
1369 * @returns a signed value containing the direction flag, or -1 if this is not supported
1370 * The direction is defined as 0 for packets originating locally (ie, outbound)
1371 * and 1 for packets originating remotely (ie, inbound).
1372 * Other values are possible, which might be overloaded to mean special things
1373 * for a special trace.
1374 */
1375DLLEXPORT libtrace_direction_t trace_get_direction(const libtrace_packet_t *packet)
1376{
1377        assert(packet);
1378        if (packet->trace->format->get_direction) {
1379                return packet->trace->format->get_direction(packet);
1380        }
1381        return (libtrace_direction_t)~0U;
1382}
1383
1384#define ROOT_SERVER(x) ((x) < 512)
1385#define ROOT_CLIENT(x) ((512 <= (x)) && ((x) < 1024))
1386#define NONROOT_SERVER(x) ((x) >= 5000)
1387#define NONROOT_CLIENT(x) ((1024 <= (x)) && ((x) < 5000))
1388#define DYNAMIC(x) ((49152 < (x)) && ((x) < 65535))
1389#define SERVER(x) ROOT_SERVER(x) || NONROOT_SERVER(x)
1390#define CLIENT(x) ROOT_CLIENT(x) || NONROOT_CLIENT(x)
1391
1392/* Attempt to deduce the 'server' port
1393 * @param protocol the IP protocol (eg, 6 or 17 for TCP or UDP)
1394 * @param source the TCP or UDP source port
1395 * @param dest the TCP or UDP destination port
1396 * @returns a hint as to which port is the server port
1397 */
1398DLLEXPORT int8_t trace_get_server_port(UNUSED uint8_t protocol,
1399                uint16_t source, uint16_t dest)
1400{
1401        /*
1402         * * If the ports are equal, return DEST
1403         * * Check for well-known ports in the given protocol
1404         * * Root server ports: 0 - 511
1405         * * Root client ports: 512 - 1023
1406         * * non-root client ports: 1024 - 4999
1407         * * non-root server ports: 5000+
1408         * * Check for static ranges: 1024 - 49151
1409         * * Check for dynamic ranges: 49152 - 65535
1410         * * flip a coin.
1411         */
1412
1413        /* equal */
1414        if (source == dest)
1415                return USE_DEST;
1416
1417        /* root server port, 0 - 511 */
1418        if (ROOT_SERVER(source) && ROOT_SERVER(dest)) {
1419                if (source < dest)
1420                        return USE_SOURCE;
1421                return USE_DEST;
1422        }
1423
1424        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1425                return USE_SOURCE;
1426        if (!ROOT_SERVER(source) && ROOT_SERVER(dest))
1427                return USE_DEST;
1428
1429        /* non-root server */
1430        if (NONROOT_SERVER(source) && NONROOT_SERVER(dest)) {
1431                if (source < dest)
1432                        return USE_SOURCE;
1433                return USE_DEST;
1434        }
1435        if (NONROOT_SERVER(source) && !NONROOT_SERVER(dest))
1436                return USE_SOURCE;
1437        if (!NONROOT_SERVER(source) && NONROOT_SERVER(dest))
1438                return USE_DEST;
1439
1440        /* root client */
1441        if (ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1442                if (source < dest)
1443                        return USE_SOURCE;
1444                return USE_DEST;
1445        }
1446        if (ROOT_CLIENT(source) && !ROOT_CLIENT(dest)) {
1447                /* prefer root-client over nonroot-client */
1448                if (NONROOT_CLIENT(dest))
1449                        return USE_SOURCE;
1450                return USE_DEST;
1451        }
1452        if (!ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1453                /* prefer root-client over nonroot-client */
1454                if (NONROOT_CLIENT(source))
1455                        return USE_DEST;
1456                return USE_SOURCE;
1457        }
1458
1459        /* nonroot client */
1460        if (NONROOT_CLIENT(source) && NONROOT_CLIENT(dest)) {
1461                if (source < dest)
1462                        return USE_SOURCE;
1463                return USE_DEST;
1464        }
1465        if (NONROOT_CLIENT(source) && !NONROOT_CLIENT(dest))
1466                return USE_DEST;
1467        if (!NONROOT_CLIENT(source) && NONROOT_CLIENT(dest))
1468                return USE_SOURCE;
1469
1470        /* dynamic range */
1471        if (DYNAMIC(source) && DYNAMIC(dest)) {
1472                if (source < dest)
1473                        return USE_SOURCE;
1474                return USE_DEST;
1475        }
1476        if (DYNAMIC(source) && !DYNAMIC(dest))
1477                return USE_DEST;
1478        if (!DYNAMIC(source) && DYNAMIC(dest))
1479                return USE_SOURCE;
1480        /*
1481        if (SERVER(source) && CLIENT(dest))
1482                return USE_SOURCE;
1483
1484        if (SERVER(dest) && CLIENT(source))
1485                return USE_DEST;
1486        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1487                return USE_SOURCE;
1488        if (ROOT_SERVER(dest) && !ROOT_SERVER(source))
1489                return USE_DEST;
1490        */
1491        /* failing that test... */
1492        if (source < dest) {
1493                return USE_SOURCE;
1494        }
1495        return USE_DEST;
1496
1497}
1498
1499/* Truncate the packet at the suggested length
1500 * @param packet        the packet opaque pointer
1501 * @param size          the new length of the packet
1502 * @returns the new size of the packet
1503 * @note size and the return size refer to the network-level payload of the
1504 * packet, and do not include any capture headers. For example, to truncate a
1505 * packet after the IP header, set size to sizeof(ethernet_header) +
1506 * sizeof(ip_header)
1507 * @note If the original network-level payload is smaller than size, then the
1508 * original size is returned and the packet is left unchanged.
1509 */
1510DLLEXPORT size_t trace_set_capture_length(libtrace_packet_t *packet, size_t size) {
1511        assert(packet);
1512
1513        if (packet->trace->format->set_capture_length) {
1514                packet->capture_length = packet->trace->format->set_capture_length(packet,size);
1515                return packet->capture_length;
1516        }
1517
1518        return ~0U;
1519}
1520
1521/* Splits a URI into two components - the format component which is seen before
1522 * the ':', and the uridata which follows the ':'.
1523 *
1524 * Returns a pointer to the URI data, but updates the format parameter to
1525 * point to a copy of the format component.
1526 */
1527
1528DLLEXPORT const char * trace_parse_uri(const char *uri, char **format) {
1529        const char *uridata = 0;
1530
1531        if((uridata = strchr(uri,':')) == NULL) {
1532                /* Badly formed URI - needs a : */
1533                return 0;
1534        }
1535
1536        if ((unsigned)(uridata - uri) > URI_PROTO_LINE) {
1537                /* Badly formed URI - uri type is too long */
1538                return 0;
1539        }
1540
1541        /* NOTE: this is allocated memory - it should be freed by the caller
1542         * once they are done with it */
1543        *format=xstrndup(uri, (size_t)(uridata - uri));
1544
1545        /* Push uridata past the delimiter */
1546        uridata++;
1547
1548        return uridata;
1549}
1550
1551enum base_format_t trace_get_format(libtrace_packet_t *packet)
1552{
1553        assert(packet);
1554
1555        return packet->trace->format->type;
1556}
1557
1558DLLEXPORT libtrace_err_t trace_get_err(libtrace_t *trace)
1559{
1560        libtrace_err_t err = trace->err;
1561        trace->err.err_num = 0; /* "OK" */
1562        trace->err.problem[0]='\0';
1563        return err;
1564}
1565
1566DLLEXPORT bool trace_is_err(libtrace_t *trace)
1567{
1568        return trace->err.err_num != 0;
1569}
1570
1571/* Prints the input error status to standard error and clears the error state */
1572DLLEXPORT void trace_perror(libtrace_t *trace,const char *msg,...)
1573{
1574        char buf[256];
1575        va_list va;
1576        va_start(va,msg);
1577        vsnprintf(buf,sizeof(buf),msg,va);
1578        va_end(va);
1579        if(trace->err.err_num) {
1580                if (trace->uridata) {
1581                        fprintf(stderr,"%s(%s): %s\n",
1582                                        buf,trace->uridata,trace->err.problem);
1583                } else {
1584                        fprintf(stderr,"%s: %s\n", buf, trace->err.problem);
1585                }
1586        } else {
1587                if (trace->uridata) {
1588                        fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1589                } else {
1590                        fprintf(stderr,"%s: No error\n", buf);
1591                }
1592        }
1593        trace->err.err_num = 0; /* "OK" */
1594        trace->err.problem[0]='\0';
1595}
1596
1597DLLEXPORT libtrace_err_t trace_get_err_output(libtrace_out_t *trace)
1598{
1599        libtrace_err_t err = trace->err;
1600        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1601        trace->err.problem[0]='\0';
1602        return err;
1603}
1604
1605DLLEXPORT bool trace_is_err_output(libtrace_out_t *trace)
1606{
1607        return trace->err.err_num != 0;
1608}
1609
1610/* Prints the output error status to standard error and clears the error state
1611 */
1612DLLEXPORT void trace_perror_output(libtrace_out_t *trace,const char *msg,...)
1613{
1614        char buf[256];
1615        va_list va;
1616        va_start(va,msg);
1617        vsnprintf(buf,sizeof(buf),msg,va);
1618        va_end(va);
1619        if(trace->err.err_num) {
1620                fprintf(stderr,"%s(%s): %s\n",
1621                                buf,
1622                                trace->uridata?trace->uridata:"no uri",
1623                                trace->err.problem);
1624        } else {
1625                fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1626        }
1627        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1628        trace->err.problem[0]='\0';
1629}
1630
1631DLLEXPORT int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts)
1632{
1633        if (trace->format->seek_erf) {
1634                return trace->format->seek_erf(trace,ts);
1635        }
1636        else {
1637                if (trace->format->seek_timeval) {
1638                        struct timeval tv;
1639#if __BYTE_ORDER == __BIG_ENDIAN
1640                        tv.tv_sec = ts & 0xFFFFFFFF;
1641                        tv.tv_usec = ((ts >> 32) * 1000000) & 0xFFFFFFFF;
1642#elif __BYTE_ORDER == __LITTLE_ENDIAN
1643                        tv.tv_sec = ts >> 32;
1644                        tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1645#else
1646#error "What on earth are you running this on?"
1647#endif
1648                        if (tv.tv_usec >= 1000000) {
1649                                tv.tv_usec -= 1000000;
1650                                tv.tv_sec += 1;
1651                        }
1652                        return trace->format->seek_timeval(trace,tv);
1653                }
1654                if (trace->format->seek_seconds) {
1655                        double seconds =
1656                                (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1657                        return trace->format->seek_seconds(trace,seconds);
1658                }
1659                trace_set_err(trace,
1660                                TRACE_ERR_OPTION_UNAVAIL,
1661                                "Feature unimplemented");
1662                return -1;
1663        }
1664}
1665
1666DLLEXPORT int trace_seek_seconds(libtrace_t *trace, double seconds)
1667{
1668        if (trace->format->seek_seconds) {
1669                return trace->format->seek_seconds(trace,seconds);
1670        }
1671        else {
1672                if (trace->format->seek_timeval) {
1673                        struct timeval tv;
1674                        tv.tv_sec = (uint32_t)seconds;
1675                        tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1676                        return trace->format->seek_timeval(trace,tv);
1677                }
1678                if (trace->format->seek_erf) {
1679                        uint64_t timestamp =
1680                                ((uint64_t)((uint32_t)seconds) << 32) + \
1681                            (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
1682                        return trace->format->seek_erf(trace,timestamp);
1683                }
1684                trace_set_err(trace,
1685                                TRACE_ERR_OPTION_UNAVAIL,
1686                                "Feature unimplemented");
1687                return -1;
1688        }
1689}
1690
1691DLLEXPORT int trace_seek_timeval(libtrace_t *trace, struct timeval tv)
1692{
1693        if (trace->format->seek_timeval) {
1694                return trace->format->seek_timeval(trace,tv);
1695        }
1696        else {
1697                if (trace->format->seek_erf) {
1698                        uint64_t timestamp = ((((uint64_t)tv.tv_sec) << 32) + \
1699                                (((uint64_t)tv.tv_usec * UINT_MAX)/1000000));
1700                        return trace->format->seek_erf(trace,timestamp);
1701                }
1702                if (trace->format->seek_seconds) {
1703                        double seconds = tv.tv_sec + ((tv.tv_usec * 1.0)/1000000);
1704                        return trace->format->seek_seconds(trace,seconds);
1705                }
1706                trace_set_err(trace,
1707                                TRACE_ERR_OPTION_UNAVAIL,
1708                                "Feature unimplemented");
1709                return -1;
1710        }
1711}
1712
1713/* Converts a binary ethernet MAC address into a printable string */
1714DLLEXPORT char *trace_ether_ntoa(const uint8_t *addr, char *buf)
1715{
1716        static char staticbuf[18]={0,};
1717        if (!buf)
1718                buf=staticbuf;
1719        snprintf(buf,(size_t)18,"%02x:%02x:%02x:%02x:%02x:%02x",
1720                        addr[0],addr[1],addr[2],
1721                        addr[3],addr[4],addr[5]);
1722        return buf;
1723}
1724
1725/* Converts a printable ethernet MAC address into a binary format */
1726DLLEXPORT uint8_t *trace_ether_aton(const char *buf, uint8_t *addr)
1727{
1728        uint8_t *buf2 = addr;
1729        unsigned int tmp[6];
1730        static uint8_t staticaddr[6];
1731        if (!buf2)
1732                buf2=staticaddr;
1733        sscanf(buf,"%x:%x:%x:%x:%x:%x",
1734                        &tmp[0],&tmp[1],&tmp[2],
1735                        &tmp[3],&tmp[4],&tmp[5]);
1736        buf2[0]=tmp[0]; buf2[1]=tmp[1]; buf2[2]=tmp[2];
1737        buf2[3]=tmp[3]; buf2[4]=tmp[4]; buf2[5]=tmp[5];
1738        return buf2;
1739}
1740
1741
1742/* Creates a libtrace packet from scratch using the contents of the provided
1743 * buffer as the packet payload.
1744 *
1745 * Unlike trace_prepare_packet(), the buffer should not contain any capture
1746 * format headers; instead this function will add the PCAP header to the
1747 * packet record. This also means only PCAP packets can be constructed using
1748 * this function.
1749 *
1750 */
1751DLLEXPORT
1752void trace_construct_packet(libtrace_packet_t *packet,
1753                libtrace_linktype_t linktype,
1754                const void *data,
1755                uint16_t len)
1756{
1757        size_t size;
1758        static libtrace_t *deadtrace=NULL;
1759        libtrace_pcapfile_pkt_hdr_t hdr;
1760#ifdef WIN32
1761        struct _timeb tstruct;
1762#else
1763        struct timeval tv;
1764#endif
1765
1766        /* We need a trace to attach the constructed packet to (and it needs
1767         * to be PCAP) */
1768        if (NULL == deadtrace)
1769                deadtrace=trace_create_dead("pcapfile");
1770
1771        /* Fill in the new PCAP header */
1772#ifdef WIN32
1773        _ftime(&tstruct);
1774        hdr.ts_sec=tstruct.time;
1775        hdr.ts_usec=tstruct.millitm * 1000;
1776#else
1777        gettimeofday(&tv,NULL);
1778        hdr.ts_sec=tv.tv_sec;
1779        hdr.ts_usec=tv.tv_usec;
1780#endif
1781
1782        hdr.caplen=len;
1783        hdr.wirelen=len;
1784
1785        /* Now fill in the libtrace packet itself */
1786        assert(deadtrace);
1787        packet->trace=deadtrace;
1788        size=len+sizeof(hdr);
1789        if (size < LIBTRACE_PACKET_BUFSIZE)
1790            size = LIBTRACE_PACKET_BUFSIZE;
1791        if (packet->buf_control==TRACE_CTRL_PACKET) {
1792            packet->buffer = realloc(packet->buffer, size);
1793        }
1794        else {
1795                packet->buffer = malloc(size);
1796        }
1797        packet->buf_control=TRACE_CTRL_PACKET;
1798        packet->header=packet->buffer;
1799        packet->payload=(void*)((char*)packet->buffer+sizeof(hdr));
1800
1801        /* Ugh, memmove - sadly necessary, also beware that we might be
1802         * moving data around within this packet, so ordering is important.
1803         */
1804        memmove(packet->payload, data, (size_t)len);
1805        memmove(packet->header, &hdr, sizeof(hdr));
1806        packet->type=pcap_linktype_to_rt(libtrace_to_pcap_linktype(linktype));
1807
1808        trace_clear_cache(packet);
1809}
1810
1811
1812uint64_t trace_get_received_packets(libtrace_t *trace)
1813{
1814        assert(trace);
1815        if (trace->format->get_received_packets) {
1816                return trace->format->get_received_packets(trace);
1817        }
1818        return (uint64_t)-1;
1819}
1820
1821uint64_t trace_get_filtered_packets(libtrace_t *trace)
1822{
1823        assert(trace);
1824        if (trace->format->get_filtered_packets) {
1825                return trace->format->get_filtered_packets(trace)+
1826                        trace->filtered_packets;
1827        }
1828        return trace->filtered_packets;
1829}
1830
1831uint64_t trace_get_dropped_packets(libtrace_t *trace)
1832{
1833        assert(trace);
1834        if (trace->format->get_dropped_packets) {
1835                return trace->format->get_dropped_packets(trace);
1836        }
1837        return (uint64_t)-1;
1838}
1839
1840uint64_t trace_get_accepted_packets(libtrace_t *trace)
1841{
1842        assert(trace);
1843        return trace->accepted_packets;
1844}
1845
1846void trace_clear_cache(libtrace_packet_t *packet) {
1847
1848        packet->l2_header = NULL;
1849        packet->l3_header = NULL;
1850        packet->l4_header = NULL;
1851        packet->link_type = 0;
1852        packet->l3_ethertype = 0;
1853        packet->transport_proto = 0;
1854        packet->capture_length = -1;
1855        packet->wire_length = -1;
1856        packet->payload_length = -1;
1857        packet->l2_remaining = 0;
1858        packet->l3_remaining = 0;
1859        packet->l4_remaining = 0;
1860
1861}
1862
1863void trace_interrupt(void) {
1864        libtrace_halt = 1;
1865}
1866
1867void register_format(struct libtrace_format_t *f) {
1868        assert(f->next==NULL); /* Can't register a format twice */
1869        f->next=formats_list;
1870        formats_list=f;
1871
1872        /* Now, verify that the format has at least the minimum functionality.
1873         *
1874         * This #if can be changed to a 1 to output warnings about inconsistent
1875         * functions being provided by format modules.  This generally is very
1876         * noisy, as almost all modules don't implement one or more functions
1877         * for various reasons.  This is very useful when checking a new
1878         * format module is sane.
1879         */
1880#if 0
1881        if (f->init_input) {
1882#define REQUIRE(x) \
1883                if (!f->x) \
1884                        fprintf(stderr,"%s: Input format should provide " #x "\n",f->name)
1885                REQUIRE(read_packet);
1886                REQUIRE(start_input);
1887                REQUIRE(fin_input);
1888                REQUIRE(get_link_type);
1889                REQUIRE(get_capture_length);
1890                REQUIRE(get_wire_length);
1891                REQUIRE(get_framing_length);
1892                REQUIRE(trace_event);
1893                if (!f->get_erf_timestamp
1894                        && !f->get_seconds
1895                        && !f->get_timeval) {
1896                        fprintf(stderr,"%s: A trace format capable of input, should provide at least one of\n"
1897"get_erf_timestamp, get_seconds or trace_timeval\n",f->name);
1898                }
1899                if (f->trace_event!=trace_event_trace) {
1900                        /* Theres nothing that a trace file could optimise with
1901                         * config_input
1902                         */
1903                        REQUIRE(pause_input);
1904                        REQUIRE(config_input);
1905                        REQUIRE(get_fd);
1906                }
1907                else {
1908                        if (f->get_fd) {
1909                                fprintf(stderr,"%s: Unnecessary get_fd\n",
1910                                                f->name);
1911                        }
1912                }
1913#undef REQUIRE
1914        }
1915        else {
1916#define REQUIRE(x) \
1917                if (f->x) \
1918                        fprintf(stderr,"%s: Non Input format shouldn't need " #x "\n",f->name)
1919                REQUIRE(read_packet);
1920                REQUIRE(start_input);
1921                REQUIRE(pause_input);
1922                REQUIRE(fin_input);
1923                REQUIRE(get_link_type);
1924                REQUIRE(get_capture_length);
1925                REQUIRE(get_wire_length);
1926                REQUIRE(get_framing_length);
1927                REQUIRE(trace_event);
1928                REQUIRE(get_seconds);
1929                REQUIRE(get_timeval);
1930                REQUIRE(get_erf_timestamp);
1931#undef REQUIRE
1932        }
1933        if (f->init_output) {
1934#define REQUIRE(x) \
1935                if (!f->x) \
1936                        fprintf(stderr,"%s: Output format should provide " #x "\n",f->name)
1937                REQUIRE(write_packet);
1938                REQUIRE(start_output);
1939                REQUIRE(config_output);
1940                REQUIRE(fin_output);
1941#undef REQUIRE
1942        }
1943        else {
1944#define REQUIRE(x) \
1945                if (f->x) \
1946                        fprintf(stderr,"%s: Non Output format shouldn't need " #x "\n",f->name)
1947                REQUIRE(write_packet);
1948                REQUIRE(start_output);
1949                REQUIRE(config_output);
1950                REQUIRE(fin_output);
1951#undef REQUIRE
1952        }
1953#endif
1954}
1955
Note: See TracBrowser for help on using the repository browser.