source: lib/trace.c @ 73dd29f

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 73dd29f was 73dd29f, checked in by Perry Lorier <perry@…>, 14 years ago

Sooo, pcap has two types of DLT's "pure" DLT's that are platform dependant,
and "linktype" DLT's that are portable and are what are written to pcap files.

Instead of fudging the two concepts together so much, attempt to disintangle
this mess without exposing too much of the god awful mess to the end user.

  • Property mode set to 100644
File size: 39.3 KB
RevLine 
[a79ddbe]1/*
2 * This file is part of libtrace
3 *
[d5a27e8]4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
[a79ddbe]5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
[9580a74]31
[fba4ca0]32/* @file
[2c060e3]33 *
34 * @brief Trace file processing library
35 *
36 * @author Daniel Lawson
37 * @author Perry Lorier
38 *
[68667ee]39 * @internal
[2c060e3]40 */
41#define _GNU_SOURCE
[6c05d2c]42#include "common.h"
[60fc8aa]43#include "config.h"
[2c060e3]44#include <assert.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <sys/stat.h>
51#include <sys/types.h>
[6ed6c4a]52#ifndef WIN32
[77285d9]53#include <sys/socket.h>
[6ed6c4a]54#endif
[3d4d52d]55#include <stdarg.h>
[e5d3718]56
57#ifdef HAVE_LIMITS_H
58#  include <limits.h>
59#endif
60
[1f3696b]61#ifdef HAVE_SYS_LIMITS_H
62#  include <sys/limits.h>
63#endif
[e5d3718]64
[808a478]65#ifdef HAVE_NET_IF_ARP_H
66#  include <net/if_arp.h>
67#endif
68
69#ifdef HAVE_NET_IF_H
70#  include <net/if.h>
71#endif
72
73#ifdef HAVE_NETINET_IN_H
74#  include <netinet/in.h>
75#endif
76
77#ifdef HAVE_NET_ETHERNET_H
78#  include <net/ethernet.h>
79#endif
80
81#ifdef HAVE_NETINET_IF_ETHER_H
82#  include <netinet/if_ether.h>
83#endif
84
[2c060e3]85#include <time.h>
[6ed6c4a]86#ifdef WIN32
87#include <sys/timeb.h>
88#endif
[dfef05d]89
[2c060e3]90#include "libtrace.h"
[9e2a109]91#include "libtrace_int.h"
[2c060e3]92
[e5c2bc4]93#ifdef HAVE_PCAP_BPF_H
[6c05d2c]94#  include <pcap-bpf.h>
95#else
96#  ifdef HAVE_NET_BPF_H
97#    include <net/bpf.h>
98#  endif
99#endif
[2137b49]100
[e5c2bc4]101
[9e2a109]102#include "libtrace_int.h"
[72bfe20]103#include "format_helper.h"
[6dbc47a]104#include "rt_protocol.h"
[2c060e3]105
[91ebc50]106#define MAXOPTS 1024
107
[c5a22ec]108
[4dfa44e]109static struct libtrace_format_t *formats_list = NULL;
[a6badc2]110
[6f75b9d]111/* strncpy is not assured to copy the final \0, so we
112 * will use our own one that does
113 */
114static void xstrncpy(char *dest, const char *src, size_t n)
115{
116        strncpy(dest,src,n);
117        dest[n]='\0';
118}
119 
120static char *xstrndup(const char *src,size_t n)
121{       
[e502f76]122        char *ret=(char*)malloc(n+1);
[d694056]123        if (ret==NULL) {
124                fprintf(stderr,"Out of memory");
125                exit(EXIT_FAILURE);
126        }
[6f75b9d]127        xstrncpy(ret,src,n);
128        return ret;
129}
130
[9e2a109]131void register_format(struct libtrace_format_t *f) {
[eeab9832]132        assert(f->next==NULL);
133        f->next=formats_list;
134        formats_list=f;
[411f3c7]135        /* Now, verify things
136         * This #if can be changed to a 1 to output warnings about inconsistant
137         * functions being provided by format modules.  This generally is very
138         * noisy, as almost all modules don't implement one or more functions
139         * for various reasons.  This is very useful when checking a new
140         * format module is sane.
141         */ 
[4927e86]142#if 0
[411f3c7]143        if (f->init_input) {
[d5879cc]144#define REQUIRE(x) \
[411f3c7]145                if (!f->x) \
146                        fprintf(stderr,"%s: Input format should provide " #x "\n",f->name)
[d5879cc]147                REQUIRE(read_packet);
148                REQUIRE(start_input);
149                REQUIRE(fin_input);
150                REQUIRE(get_link_type);
151                REQUIRE(get_capture_length);
152                REQUIRE(get_wire_length);
153                REQUIRE(get_framing_length);
154                REQUIRE(trace_event);
[411f3c7]155                if (!f->get_erf_timestamp
156                        && !f->get_seconds
157                        && !f->get_timeval) {
[d5879cc]158                        fprintf(stderr,"%s: A trace format capable of input, should provide at least one of\n"
[411f3c7]159"get_erf_timestamp, get_seconds or trace_timeval\n",f->name);
[d5879cc]160                }
[411f3c7]161                if (f->trace_event!=trace_event_trace) {
162                        /* Theres nothing that a trace file could optimise with
163                         * config_input
164                         */
165                        REQUIRE(pause_input);
166                        REQUIRE(config_input);
[4aa4615]167                        REQUIRE(get_fd);
168                }
169                else {
[411f3c7]170                        if (f->get_fd) {
[4aa4615]171                                fprintf(stderr,"%s: Unnecessary get_fd\n",
[411f3c7]172                                                f->name);
[4aa4615]173                        }
174                }
[d5879cc]175#undef REQUIRE
176        }
177        else {
178#define REQUIRE(x) \
[411f3c7]179                if (f->x) \
180                        fprintf(stderr,"%s: Non Input format shouldn't need " #x "\n",f->name)
[d5879cc]181                REQUIRE(read_packet);
182                REQUIRE(start_input);
183                REQUIRE(pause_input);
184                REQUIRE(fin_input);
185                REQUIRE(get_link_type);
186                REQUIRE(get_capture_length);
187                REQUIRE(get_wire_length);
188                REQUIRE(get_framing_length);
189                REQUIRE(trace_event);
[4aa4615]190                REQUIRE(get_seconds);
191                REQUIRE(get_timeval);
192                REQUIRE(get_erf_timestamp);
[d5879cc]193#undef REQUIRE
194        }
[411f3c7]195        if (f->init_output) {
[d5879cc]196#define REQUIRE(x) \
[411f3c7]197                if (!f->x) \
198                        fprintf(stderr,"%s: Output format should provide " #x "\n",f->name)
[d5879cc]199                REQUIRE(write_packet);
200                REQUIRE(start_output);
201                REQUIRE(config_output);
202                REQUIRE(fin_output);
203#undef REQUIRE
204        }
205        else {
206#define REQUIRE(x) \
[411f3c7]207                if (f->x) \
208                        fprintf(stderr,"%s: Non Output format shouldn't need " #x "\n",f->name)
[d5879cc]209                REQUIRE(write_packet);
210                REQUIRE(start_output);
211                REQUIRE(config_output);
212                REQUIRE(fin_output);
213#undef REQUIRE
214        }
[4aa4615]215#endif
[4dedc28]216}
[8dd1830]217
[dd2eaee]218/* call all the constructors if they haven't yet all been called */
[33d83d4]219static void trace_init(void)
[dd2eaee]220{
221        if (!formats_list) {
[cd7eec7]222                duck_constructor();
[dd2eaee]223                erf_constructor();
[e01a738]224                tsh_constructor();
[dd2eaee]225                legacy_constructor();
[7b2a39b]226#ifdef HAVE_NETPACKET_PACKET_H
[dd2eaee]227                linuxnative_constructor();
[7b2a39b]228#endif
[e5c2bc4]229#ifdef HAVE_LIBPCAP
[dd2eaee]230                pcap_constructor();
231#endif
[4bd8a5b]232#ifdef HAVE_BIOCSETIF
[755e794]233                bpf_constructor();
234#endif
[dd2eaee]235                pcapfile_constructor();
236                rt_constructor();
237                wag_constructor();
[5e85c23]238#ifdef HAVE_DAG
239                dag_constructor();
240#endif
[dd2eaee]241        }
242}
243
[fba4ca0]244/* Prints help information for libtrace
[40ba6ad]245 *
246 * Function prints out some basic help information regarding libtrace,
247 * and then prints out the help() function registered with each input module
248 */
[e1868fb]249DLLEXPORT void trace_help(void) {
[eeab9832]250        struct libtrace_format_t *tmp;
[dd2eaee]251        trace_init();
[47de0aa]252        printf("libtrace %s\n\n",PACKAGE_VERSION);
253        printf("Following this are a list of the format modules supported in this build of libtrace\n\n");
[eeab9832]254        for(tmp=formats_list;tmp;tmp=tmp->next) {
255                if (tmp->help)
256                        tmp->help();
[40ba6ad]257        }
258}
259
[4bd8a5b]260#define URI_PROTO_LINE 16U
[2c060e3]261
[dd2eaee]262
[fba4ca0]263/* Create a trace file from a URI
264 *
265 * @params char * containing a valid libtrace URI
[2c060e3]266 * @returns opaque pointer to a libtrace_t
267 *
268 * Valid URI's are:
[277442c]269 *  erf:/path/to/erf/file
270 *  erf:/path/to/erf/file.gz
271 *  erf:/path/to/rtclient/socket
272 *  erf:-                       (stdin)
[fba4ca0]273 *  dag:/dev/dagcard
[476df56]274 *  pcapint:pcapinterface               (eg: pcapint:eth0)
[277442c]275 *  pcap:/path/to/pcap/file
276 *  pcap:-
277 *  rtclient:hostname
278 *  rtclient:hostname:port
279 *  wag:-
280 *  wag:/path/to/wag/file
281 *  wag:/path/to/wag/file.gz
282 *  wag:/path/to/wag/socket
283 *
284 * If an error occured when attempting to open a trace, NULL is returned
285 * and an error is output to stdout.
[2c060e3]286 */
[e6d963c]287DLLEXPORT libtrace_t *trace_create(const char *uri) {
288        libtrace_t *libtrace = 
289                        (libtrace_t *)malloc(sizeof(libtrace_t));
[de8c420b]290        char *scan = 0;
[6f75b9d]291        const char *uridata = 0;                 
[eeab9832]292        struct libtrace_format_t *tmp;
[0c222cc]293
[dd2eaee]294        trace_init();
295
[0c222cc]296        assert(uri && "Passing NULL to trace_create makes me a very sad program");
[d694056]297
298        if (!libtrace) {
299                /* Out of memory */
300                return NULL;
301        }
[a114d8b5]302       
[eea0f87]303        libtrace->err.err_num = TRACE_ERR_NOERROR;
[0ea3526]304        libtrace->format=NULL;
[9e2a109]305       
[7068467]306        /* parse the URI to determine what sort of event we are dealing with */
[de8c420b]307        if ((uridata = trace_parse_uri(uri, &scan)) == 0) {
[4aa4615]308                trace_set_err(libtrace,TRACE_ERR_BAD_FORMAT,"Bad uri format (%s)",uri);
[0ea3526]309                return libtrace;
[de8c420b]310        }
311       
[9e2a109]312        libtrace->event.tdelta = 0.0;
[b9aa767]313        libtrace->event.packet = NULL;
314        libtrace->event.psize = 0;
315        libtrace->event.trace_last_ts = 0.0;
[880aa58]316        libtrace->filter = NULL;
317        libtrace->snaplen = 0;
[d8f02df]318        libtrace->started=false;
[9e2a109]319
[eeab9832]320        for (tmp=formats_list;tmp;tmp=tmp->next) {
321                if (strlen(scan) == strlen(tmp->name) &&
322                                strncasecmp(scan, tmp->name, strlen(scan)) == 0
323                                ) {
324                        libtrace->format=tmp;
[6f75b9d]325                        break;
326                }
[9e2a109]327        }
328        if (libtrace->format == 0) {
[0ea3526]329                trace_set_err(libtrace, TRACE_ERR_BAD_FORMAT,
[880aa58]330                                "Unknown format (%s)",scan);
[eeab9832]331                return libtrace;
[9e2a109]332        }
333
334        libtrace->uridata = strdup(uridata);
[7068467]335        /* libtrace->format now contains the type of uri
336         * libtrace->uridata contains the appropriate data for this
337         */
[9e2a109]338       
339        if (libtrace->format->init_input) {
[d5879cc]340                int err=libtrace->format->init_input(libtrace);
341                assert (err==-1 || err==0);
342                if (err==-1) {
[880aa58]343                        /* init_input should call trace_set_err to set
344                         * the error message
345                         */
[0ea3526]346                        return libtrace;
[ffc8c8d]347                }
[9e2a109]348        } else {
[91db67b]349                trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,
[880aa58]350                                "Format does not support input (%s)",scan);
[0ea3526]351                return libtrace;
[9e2a109]352        }
353       
354
[ae8196e]355        free(scan);
[ae66bde]356        libtrace->err.err_num=TRACE_ERR_NOERROR;
357        libtrace->err.problem[0]='\0';
[2c060e3]358        return libtrace;
359}
360
[fba4ca0]361/* Creates a "dummy" trace file that has only the format type set.
362 *
363 * @returns opaque pointer to a (sparsely initialised) libtrace_t
364 *
[880aa58]365 * IMPORTANT: Do not attempt to call trace_read_packet or other such functions
366 * with the dummy trace. Its intended purpose is to act as a packet->trace for
367 * libtrace_packet_t's that are not associated with a libtrace_t structure.
[fba4ca0]368 */
[e6d963c]369DLLEXPORT libtrace_t * trace_create_dead (const char *uri) {
370        libtrace_t *libtrace = (libtrace_t *) malloc(sizeof(libtrace_t));
[67a14d4]371        char *scan = (char *)calloc(sizeof(char),URI_PROTO_LINE);
[084d95a]372        char *uridata;
[eeab9832]373        struct libtrace_format_t *tmp;
[0453ca8]374
375        trace_init();
[084d95a]376       
[eea0f87]377        libtrace->err.err_num = TRACE_ERR_NOERROR;
[084d95a]378
379        if((uridata = strchr(uri,':')) == NULL) {
[6f75b9d]380                xstrncpy(scan, uri, strlen(uri));
[084d95a]381        } else {
[4bd8a5b]382                xstrncpy(scan,uri, (size_t)(uridata - uri));
[084d95a]383        }
384       
385        libtrace->format = 0;   
386       
[eeab9832]387        for(tmp=formats_list;tmp;tmp=tmp->next) {
388                if (strlen(scan) == strlen(tmp->name) &&
[084d95a]389                                !strncasecmp(scan,
[eeab9832]390                                        tmp->name,
[084d95a]391                                        strlen(scan))) {
[eeab9832]392                                libtrace->format=tmp;
[084d95a]393                                break;
394                                }
395        }
396        if (libtrace->format == 0) {
[0ea3526]397                trace_set_err(libtrace,TRACE_ERR_BAD_FORMAT,
[880aa58]398                                "Unknown format (%s)",scan);
[084d95a]399        }
[7ac9705]400
401        libtrace->format_data = NULL;
[ae8196e]402        free(scan);
[084d95a]403        return libtrace;
404
405}
[fba4ca0]406
[b69afb1]407/* Creates a trace output file from a URI.
[5eae97a]408 *
[fba4ca0]409 * @param uri   the uri string describing the output format and destination
[880aa58]410 * @returns opaque pointer to a libtrace_output_t
[fba4ca0]411 *
[880aa58]412 *  If an error occured when attempting to open the output trace, NULL is
413 *  returned and trace_errno is set.
[fba4ca0]414 */
415       
[39e141f]416DLLEXPORT libtrace_out_t *trace_create_output(const char *uri) {
[67a14d4]417        libtrace_out_t *libtrace = 
[e6d963c]418                        (libtrace_out_t*)malloc(sizeof(libtrace_out_t));
[5eae97a]419       
[de8c420b]420        char *scan = 0;
[6f75b9d]421        const char *uridata = 0;
[eeab9832]422        struct libtrace_format_t *tmp;
[df2dff9]423
[dd2eaee]424        trace_init();
425
[eea0f87]426        libtrace->err.err_num = TRACE_ERR_NOERROR;
[d97bbb2]427        strcpy(libtrace->err.problem,"Error message set\n");
[eea0f87]428       
[7068467]429        /* parse the URI to determine what sort of event we are dealing with */
[df2dff9]430
[de8c420b]431        if ((uridata = trace_parse_uri(uri, &scan)) == 0) {
[eeab9832]432                trace_set_err_out(libtrace,TRACE_ERR_BAD_FORMAT,
433                                "Bad uri format (%s)",uri);
[0ea3526]434                return libtrace;
[de8c420b]435        }
436       
[eeab9832]437        libtrace->format = NULL;
438        for(tmp=formats_list;tmp;tmp=tmp->next) {
439                if (strlen(scan) == strlen(tmp->name) &&
[df2dff9]440                                !strncasecmp(scan,
[eeab9832]441                                        tmp->name,
[df2dff9]442                                        strlen(scan))) {
[eeab9832]443                                libtrace->format=tmp;
[df2dff9]444                                break;
445                                }
446        }
[eeab9832]447        if (libtrace->format == NULL) {
[0ea3526]448                trace_set_err_out(libtrace,TRACE_ERR_BAD_FORMAT,
[880aa58]449                                "Unknown output format (%s)",scan);
[eeab9832]450                return libtrace;
[df2dff9]451        }
452        libtrace->uridata = strdup(uridata);
453
454
[7068467]455        /* libtrace->format now contains the type of uri
456         * libtrace->uridata contains the appropriate data for this
457         */
[df2dff9]458
459        if (libtrace->format->init_output) {
[fe76c55]460                /* 0 on success, -1 on failure */
461                switch(libtrace->format->init_output(libtrace)) {
462                        case -1: /* failure */
[eeab9832]463                                return libtrace;
[fe76c55]464                        case 0: /* success */
465                                break;
466                        default:
467                                assert(!"init_output() should return -1 for failure, or 0 for success");
[ffc8c8d]468                }
[df2dff9]469        } else {
[91db67b]470                trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
[880aa58]471                                "Format does not support writing (%s)",scan);
[0ea3526]472                return libtrace;
[df2dff9]473        }
474
475
[ae8196e]476        free(scan);
[0a6638f]477        libtrace->started=false;
[91ebc50]478        return libtrace;
479}
[5eae97a]480
[37195b4]481/* Start a trace
482 * @param libtrace      the input trace to start
483 * @returns 0 on success
484 *
485 * This does the work associated with actually starting up
486 * the trace.  it may fail.
487 */
[e6d963c]488DLLEXPORT int trace_start(libtrace_t *libtrace)
[37195b4]489{
[df338b3]490        assert(libtrace);
[ef8358e]491        assert(!trace_is_err(libtrace) && "Please use trace_is_err to check for errors after calling trace_create!");
[37195b4]492        if (libtrace->format->start_input) {
493                int ret=libtrace->format->start_input(libtrace);
[49babe0]494                if (ret < 0) {
[37195b4]495                        return ret;
496                }
497        }
498
499        libtrace->started=true;
500        return 0;
501}
502
[39e141f]503DLLEXPORT int trace_start_output(libtrace_out_t *libtrace) 
[0a6638f]504{
505        assert(libtrace);
506        if (libtrace->format->start_output) {
507                int ret=libtrace->format->start_output(libtrace);
508                if (ret < 0) {
509                        return ret;
510                }
511        }
512
[eeab9832]513        libtrace->started=true;
[0a6638f]514        return 0;
515}
516
[39e141f]517DLLEXPORT int trace_pause(libtrace_t *libtrace)
[1fbd938]518{
519        assert(libtrace);
520        assert(libtrace->started && "BUG: Called trace_pause without calling trace_start first");
521        if (libtrace->format->pause_input)
522                libtrace->format->pause_input(libtrace);
523        libtrace->started=false;
524        return 0;
525}
526
[39e141f]527DLLEXPORT int trace_config(libtrace_t *libtrace,
[65a5900]528                trace_option_t option,
529                void *value)
530{
531        int ret;
[205809b]532        libtrace_err_t err;
533       
534        assert(!trace_is_err(libtrace) && "Please use trace_is_err to check for errors after calling trace_create!");
535       
[65a5900]536        if (libtrace->format->config_input) {
537                ret=libtrace->format->config_input(libtrace,option,value);
538                if (ret==0)
539                        return 0;
540        }
541        switch(option) {
542                case TRACE_OPTION_SNAPLEN:
[205809b]543                        /* Clear the error if there was one */
544                        if (trace_is_err(libtrace)) {
545                                err = trace_get_err(libtrace);
546                        }
[65a5900]547                        libtrace->snaplen=*(int*)value;
[67a14d4]548                        return 0;
[65a5900]549                case TRACE_OPTION_FILTER:
[205809b]550                        /* Clear the error if there was one */
551                        if (trace_is_err(libtrace)) {
552                                err = trace_get_err(libtrace);
553                        }
[e6d963c]554                        libtrace->filter=(libtrace_filter_t *)value;
[67a14d4]555                        return 0;
[65a5900]556                case TRACE_OPTION_PROMISC:
[205809b]557                        if (!trace_is_err(libtrace)) {
558                                trace_set_err(libtrace,TRACE_ERR_OPTION_UNAVAIL,
559                                                "Promisc mode is not supported by this format module");
560                        }
[65a5900]561                        return -1;
[cd7eec7]562                case TRACE_META_FREQ:
[205809b]563                        if (!trace_is_err(libtrace)) {
564                                trace_set_err(libtrace, 
565                                                TRACE_ERR_OPTION_UNAVAIL,
566                                                "This format does not support meta-data gathering");
567                        }
[cd7eec7]568                        return -1;
[65a5900]569        }
[205809b]570        if (!trace_is_err(libtrace)) {
571                trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
572                        "Unknown option %i", option);
573        }
[67a14d4]574        return -1;
[65a5900]575}
576
[fba4ca0]577/* Parses an output options string and calls the appropriate function to deal with output options.
[ef55d05]578 *
579 * @param libtrace      the output trace object to apply the options to
580 * @param options       the options string
581 * @returns -1 if option configuration failed, 0 otherwise
582 *
583 * @author Shane Alcock
584 */
[e6d963c]585DLLEXPORT int trace_config_output(libtrace_out_t *libtrace, 
[7068467]586                trace_option_output_t option,
587                void *value) {
[9c6aa95]588        if (libtrace->format->config_output) {
[7068467]589                return libtrace->format->config_output(libtrace, option, value);
[9c6aa95]590        }
591        return -1;
[5eae97a]592}
593
[fba4ca0]594/* Close a trace file, freeing up any resources it may have been using
[2c060e3]595 *
596 */
[e6d963c]597DLLEXPORT void trace_destroy(libtrace_t *libtrace) {
[2c060e3]598        assert(libtrace);
[4e65f42]599        if (libtrace->format) {
600                if (libtrace->started && libtrace->format->pause_input)
601                        libtrace->format->pause_input(libtrace);
602                libtrace->format->fin_input(libtrace);
603        }
[7068467]604        /* need to free things! */
[4e65f42]605        if (libtrace->uridata)
606                free(libtrace->uridata);
[2c060e3]607        free(libtrace);
608}
609
[084d95a]610
[e6d963c]611DLLEXPORT void trace_destroy_dead(libtrace_t *libtrace) {
[084d95a]612        assert(libtrace);
613        free(libtrace);
614}
[fba4ca0]615/* Close an output trace file, freeing up any resources it may have been using
[5eae97a]616 *
617 * @param libtrace      the output trace file to be destroyed
618 *
619 * @author Shane Alcock
620 * */
[33d83d4]621DLLEXPORT void trace_destroy_output(libtrace_out_t *libtrace) 
622{
[5eae97a]623        assert(libtrace);
[1fc2f6a]624        libtrace->format->fin_output(libtrace);
[a114d8b5]625        free(libtrace->uridata);
[5eae97a]626        free(libtrace);
627}
628
[33d83d4]629DLLEXPORT libtrace_packet_t *trace_create_packet(void) 
630{
[67a14d4]631        libtrace_packet_t *packet = 
[4bd8a5b]632                (libtrace_packet_t*)calloc((size_t)1,sizeof(libtrace_packet_t));
[c1db742]633        packet->buf_control=TRACE_CTRL_PACKET;
[14d8a63]634        return packet;
635}
636
[39e141f]637DLLEXPORT libtrace_packet_t *trace_copy_packet(const libtrace_packet_t *packet) {
[67a14d4]638        libtrace_packet_t *dest = 
639                (libtrace_packet_t *)malloc(sizeof(libtrace_packet_t));
[91c9552]640        dest->trace=packet->trace;
641        dest->buffer=malloc(
642                        trace_get_framing_length(packet)
643                        +trace_get_capture_length(packet));
644        dest->header=dest->buffer;
645        dest->payload=(void*)
646                ((char*)dest->buffer+trace_get_framing_length(packet));
647        dest->type=packet->type;
648        dest->buf_control=TRACE_CTRL_PACKET;
649        memcpy(dest->header,packet->header,trace_get_framing_length(packet));
650        memcpy(dest->payload,packet->payload,trace_get_capture_length(packet));
[d8f02df]651
652        return dest;
[91c9552]653}
654
[14d8a63]655/** Destroy a packet object
656 *
657 * sideeffect: sets packet to NULL
658 */
[e2aebe7]659DLLEXPORT void trace_destroy_packet(libtrace_packet_t *packet) {
660        if (packet->buf_control == TRACE_CTRL_PACKET) {
661                free(packet->buffer);
662        }
[85a79b0]663        packet->buf_control=(buf_control_t)'\0'; 
664                                /* an "bad" value to force an assert
665                                 * if this packet is ever reused
666                                 */
[e2aebe7]667        free(packet);
[14d8a63]668}       
669
[fba4ca0]670/* Read one packet from the trace into buffer
[2c060e3]671 *
[2137b49]672 * @param libtrace      the libtrace opaque pointer
673 * @param packet        the packet opaque pointer
[fba4ca0]674 * @returns 0 on EOF, negative value on error
[2c060e3]675 *
676 */
[39e141f]677DLLEXPORT int trace_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
[2137b49]678
[37195b4]679        assert(libtrace && "You called trace_read_packet() with a NULL libtrace parameter!\n");
680        assert(libtrace->started && "BUG: You must call libtrace_start() before trace_read_packet()\n");
681        assert(packet);
[c1db742]682        assert((packet->buf_control==TRACE_CTRL_PACKET || packet->buf_control==TRACE_CTRL_EXTERNAL)&&
[0a6638f]683                "BUG: You must allocate a packet using packet_create()");
[2137b49]684     
685        /* Store the trace we are reading from into the packet opaque
686         * structure */
687        packet->trace = libtrace;
[afd0b73]688
[4dedc28]689        if (libtrace->format->read_packet) {
[880aa58]690                do {
[a7d1914]691                        size_t ret;
692                        ret=libtrace->format->read_packet(libtrace,packet);
693                        if (ret==(size_t)-1 || ret==0) {
694                                return ret;
[222d8f5]695                        }
[880aa58]696                        if (libtrace->filter) {
697                                /* If the filter doesn't match, read another
698                                 * packet
699                                 */
[e2aebe7]700                                if (!trace_apply_filter(libtrace->filter,packet)){
[880aa58]701                                        continue;
702                                }
703                        }
704                        if (libtrace->snaplen>0) {
705                                /* Snap the packet */
706                                trace_set_capture_length(packet,
707                                                libtrace->snaplen);
708                        }
[a7d1914]709                        return ret;
[880aa58]710                } while(1);
[a22c979]711        }
[91db67b]712        trace_set_err(libtrace,TRACE_ERR_UNSUPPORTED,"This format does not support reading packets\n");
[85a79b0]713        return ~0U;
[2c060e3]714}
715
[fba4ca0]716/* Writes a packet to the specified output
[5eae97a]717 *
718 * @param libtrace      describes the output format, destination, etc.
719 * @param packet        the packet to be written out
720 * @returns the number of bytes written, -1 if write failed
721 *
722 * @author Shane Alcock
723 * */
[3a169d7]724DLLEXPORT int trace_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) {
[5eae97a]725        assert(libtrace);
726        assert(packet); 
[a8a9355]727        /* Verify the packet is valid */
[eeab9832]728        assert(libtrace->started);
[5eae97a]729
[1fc2f6a]730        if (libtrace->format->write_packet) {
731                return libtrace->format->write_packet(libtrace, packet);
[5eae97a]732        }
[8a1fb3c]733        trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
734                "This format does not support writing packets");
[9c6aa95]735        return -1;
[5eae97a]736}
[2c060e3]737
[e6d963c]738DLLEXPORT void *trace_get_link(const libtrace_packet_t *packet) {
[14d8a63]739        return (void *)packet->payload;
[2c060e3]740}
741
[fba4ca0]742/* Get the current time in DAG time format
[850630f]743 * @param packet        a pointer to a libtrace_packet structure
[2c060e3]744 * @returns a 64 bit timestamp in DAG ERF format (upper 32 bits are the seconds
745 * past 1970-01-01, the lower 32bits are partial seconds)
746 * @author Daniel Lawson
747 */ 
[39e141f]748DLLEXPORT uint64_t trace_get_erf_timestamp(const libtrace_packet_t *packet) {
[2c060e3]749        uint64_t timestamp = 0;
[ca87bcd]750        double seconds = 0.0;
[4dedc28]751        struct timeval ts;
752
753        if (packet->trace->format->get_erf_timestamp) {
[7068467]754                /* timestamp -> timestamp */
[4dedc28]755                timestamp = packet->trace->format->get_erf_timestamp(packet);
756        } else if (packet->trace->format->get_timeval) {
[7068467]757                /* timeval -> timestamp */
[4dedc28]758                ts = packet->trace->format->get_timeval(packet);
759                timestamp = ((((uint64_t)ts.tv_sec) << 32) + \
760                                (((uint64_t)ts.tv_usec * UINT_MAX)/1000000));
[ca87bcd]761        } else if (packet->trace->format->get_seconds) {
[7068467]762                /* seconds -> timestamp */
[ca87bcd]763                seconds = packet->trace->format->get_seconds(packet);
[1974620]764                timestamp = ((uint64_t)((uint32_t)seconds) << 32) + \
[67a14d4]765                      (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
[ca87bcd]766        }
[4dedc28]767        return timestamp;
[2c060e3]768}
769
[fba4ca0]770/* Get the current time in struct timeval
[850630f]771 * @param packet        a pointer to a libtrace_packet structure
772 *
[2c060e3]773 * @returns time that this packet was seen in a struct timeval
774 * @author Daniel Lawson
775 * @author Perry Lorier
776 */ 
[39e141f]777DLLEXPORT struct timeval trace_get_timeval(const libtrace_packet_t *packet) {
[2c060e3]778        struct timeval tv;
[4dedc28]779        uint64_t ts = 0;
[e01bfa8]780        double seconds = 0.0;
[4dedc28]781        if (packet->trace->format->get_timeval) {
[7068467]782                /* timeval -> timeval */
[4dedc28]783                tv = packet->trace->format->get_timeval(packet);
784        } else if (packet->trace->format->get_erf_timestamp) {
[7068467]785                /* timestamp -> timeval */
[4dedc28]786                ts = packet->trace->format->get_erf_timestamp(packet);
[8dd1830]787#if __BYTE_ORDER == __BIG_ENDIAN
[4dedc28]788                tv.tv_sec = ts & 0xFFFFFFFF;
[8dd1830]789#elif __BYTE_ORDER == __LITTLE_ENDIAN
[4dedc28]790                tv.tv_sec = ts >> 32;
[8dd1830]791#else
792#error "What on earth are you running this on?"
793#endif
[2e223eca]794                tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
[4dedc28]795                if (tv.tv_usec >= 1000000) {
796                        tv.tv_usec -= 1000000;
797                        tv.tv_sec += 1;
798                }
[ca87bcd]799        } else if (packet->trace->format->get_seconds) {
[7068467]800                /* seconds -> timeval */
[ca87bcd]801                seconds = packet->trace->format->get_seconds(packet);
802                tv.tv_sec = (uint32_t)seconds;
803                tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
[4dedc28]804        }
[302714f]805        else {
806                tv.tv_sec=-1;
807                tv.tv_usec=-1;
808        }
[4dedc28]809
[2c060e3]810        return tv;
811}
812
[fba4ca0]813/* Get the current time in floating point seconds
[850630f]814 * @param packet        a pointer to a libtrace_packet structure
[2c060e3]815 * @returns time that this packet was seen in 64bit floating point seconds
816 * @author Perry Lorier
817 */ 
[e6d963c]818DLLEXPORT double trace_get_seconds(const libtrace_packet_t *packet) {
[9c6aa95]819        double seconds = 0.0;
820        uint64_t ts = 0;
[ca87bcd]821        struct timeval tv;
[a8a9355]822
[4dedc28]823        if (packet->trace->format->get_seconds) {
[7068467]824                /* seconds->seconds */
[4dedc28]825                seconds = packet->trace->format->get_seconds(packet);
826        } else if (packet->trace->format->get_erf_timestamp) {
[7068467]827                /* timestamp -> seconds */
[4dedc28]828                ts = packet->trace->format->get_erf_timestamp(packet);
829                seconds =  (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
[ca87bcd]830        } else if (packet->trace->format->get_timeval) {
[7068467]831                /* timeval -> seconds */
[ca87bcd]832                tv = packet->trace->format->get_timeval(packet);
[b51edf5]833                seconds = tv.tv_sec + ((tv.tv_usec * 1.0) / 1000000);
[ca87bcd]834        }
835
[4dedc28]836        return seconds;
[2c060e3]837}
838
[a7d1914]839DLLEXPORT size_t trace_get_capture_length(const libtrace_packet_t *packet) 
840{
[4dedc28]841        if (packet->trace->format->get_capture_length) {
842                return packet->trace->format->get_capture_length(packet);
[2c060e3]843        }
[85a79b0]844        return ~0U;
[2c060e3]845}
846       
[fba4ca0]847/* Get the size of the packet as it was seen on the wire.
[850630f]848 * @param packet        a pointer to a libtrace_packet structure
849 *
[2c060e3]850 * @returns the size of the packet as it was on the wire.
851 * @author Perry Lorier
852 * @author Daniel Lawson
853 * @note Due to the trace being a header capture, or anonymisation this may
854 * not be the same as the Capture Len.
855 */ 
[39e141f]856DLLEXPORT size_t trace_get_wire_length(const libtrace_packet_t *packet){
[4dedc28]857        if (packet->trace->format->get_wire_length) {
858                return packet->trace->format->get_wire_length(packet);
[2c060e3]859        }
[85a79b0]860        return ~0U;
[2c060e3]861
862}
863
[7c8eacf]864/* Get the length of the capture framing headers.
865 * @param packet        the packet opaque pointer
866 * @returns the size of the packet as it was on the wire.
867 * @author Perry Lorier
868 * @author Daniel Lawson
869 * @note this length corresponds to the difference between the size of a
870 * captured packet in memory, and the captured length of the packet
871 */ 
[39e141f]872DLLEXPORT SIMPLE_FUNCTION
[d8f02df]873size_t trace_get_framing_length(const libtrace_packet_t *packet) {
[7c8eacf]874        if (packet->trace->format->get_framing_length) {
875                return packet->trace->format->get_framing_length(packet);
876        }
[85a79b0]877        return ~0U;
[7c8eacf]878}
879
880
[fba4ca0]881/* Get the type of the link layer
[850630f]882 * @param packet        a pointer to a libtrace_packet structure
[2c060e3]883 * @returns libtrace_linktype_t
884 * @author Perry Lorier
885 * @author Daniel Lawson
886 */
[39e141f]887DLLEXPORT libtrace_linktype_t trace_get_link_type(const libtrace_packet_t *packet ) {
[4dedc28]888        if (packet->trace->format->get_link_type) {
889                return packet->trace->format->get_link_type(packet);
[2c060e3]890        }
[67a14d4]891        return (libtrace_linktype_t)-1;
[2c060e3]892}
893
[fba4ca0]894/* process a libtrace event
[ef36351d]895 * @param trace the libtrace opaque pointer
896 * @param packet the libtrace_packet opaque pointer
[2c060e3]897 * @returns
[68667ee]898 *  TRACE_EVENT_IOWAIT  Waiting on I/O on fd
899 *  TRACE_EVENT_SLEEP   Next event in seconds
900 *  TRACE_EVENT_PACKET  Packet arrived in buffer with size size
[7bb7dda]901 *  TRACE_EVENT_TERMINATE Trace terminated (perhaps with an error condition)
[2137b49]902 * FIXME currently keeps a copy of the packet inside the trace pointer,
903 * which in turn is stored inside the new packet object...
[277442c]904 * @author Perry Lorier
[2c060e3]905 */
[e6d963c]906DLLEXPORT libtrace_eventobj_t trace_event(libtrace_t *trace, 
907                libtrace_packet_t *packet) {
908        libtrace_eventobj_t event = {TRACE_EVENT_IOWAIT,0,0.0,0};
[4fd12ac]909
910        if (!trace) {
911                fprintf(stderr,"You called trace_event() with a NULL trace object!\n");
912        }
913        assert(trace);
914        assert(packet);
915
916        /* Store the trace we are reading from into the packet opaque
917         * structure */
918        packet->trace = trace;
919
[72bfe20]920        if (packet->trace->format->trace_event) {
921                return packet->trace->format->trace_event(trace,packet);
922        } else {
923                return event;
[2c060e3]924        }
[72bfe20]925
[2c060e3]926}
[c681e86]927
[fba4ca0]928/* setup a BPF filter
[c681e86]929 * @param filterstring a char * containing the bpf filter string
[c5a22ec]930 * @returns opaque pointer pointer to a libtrace_filter_t object
[c681e86]931 * @author Daniel Lawson
932 */
[e2aebe7]933DLLEXPORT libtrace_filter_t *trace_create_filter(const char *filterstring) {
[e5c2bc4]934#ifdef HAVE_BPF
[e6d963c]935        libtrace_filter_t *filter = (libtrace_filter_t*)
936                                malloc(sizeof(libtrace_filter_t));
[c5a22ec]937        filter->filterstring = strdup(filterstring);
[df338b3]938        filter->flag = 0;
[c5a22ec]939        return filter;
[9580a74]940#else
941        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
[516a90d]942        return NULL;
[9580a74]943#endif
[c681e86]944}
945
[e2aebe7]946DLLEXPORT void trace_destroy_filter(libtrace_filter_t *filter)
[747c501]947{
[e5c2bc4]948#ifdef HAVE_BPF
[747c501]949        free(filter->filterstring);
950        if (filter->flag)
951                pcap_freecode(&filter->filter);
952        free(filter);
[516a90d]953#else
954
955#endif
[747c501]956}
957
[df338b3]958/* compile a bpf filter, now we know what trace it's on
959 * @internal
960 *
961 * @returns -1 on error, 0 on success
962 */
963int trace_bpf_compile(libtrace_filter_t *filter,
964                const libtrace_packet_t *packet ) {
[e5c2bc4]965#ifdef HAVE_BPF
[df338b3]966        void *linkptr = 0;
967        assert(filter);
968
969        /* If this isn't a real packet, then fail */
970        linkptr = trace_get_link(packet);
971        if (!linkptr) {
[0ea3526]972                trace_set_err(packet->trace,
973                                TRACE_ERR_BAD_PACKET,"Packet has no payload");
[df338b3]974                return -1;
975        }
976       
977        if (filter->filterstring && ! filter->flag) {
[d242ea8]978                pcap_t *pcap = NULL;
[d5879cc]979                libtrace_linktype_t linktype=trace_get_link_type(packet);
980                if (linktype==(libtrace_linktype_t)-1) {
[302714f]981                        trace_set_err(packet->trace,
982                                        TRACE_ERR_BAD_PACKET,
[d5879cc]983                                        "Packet has an unknown linktype");
984                        return -1;
985                }
[c806cb3]986                if (libtrace_to_pcap_dlt(linktype) == ~1U) {
[d5879cc]987                        trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET,
[d242ea8]988                                        "Unknown pcap equivalent linktype");
[d5879cc]989                        return -1;
990                }
[df338b3]991                pcap=(pcap_t *)pcap_open_dead(
[4bd8a5b]992                                (int)libtrace_to_pcap_dlt(linktype),
993                                1500U);
[df338b3]994                /* build filter */
[d242ea8]995                assert(pcap);
[df338b3]996                if (pcap_compile( pcap, &filter->filter, filter->filterstring, 
997                                        1, 0)) {
[0ea3526]998                        trace_set_err(packet->trace,TRACE_ERR_BAD_PACKET,
[d242ea8]999                                        "Unable to compile the filter \"%s\": %s", 
1000                                        filter->filterstring,
1001                                        pcap_geterr(pcap));
1002                        pcap_close(pcap);
[df338b3]1003                        return -1;
1004                }
1005                pcap_close(pcap);
1006                filter->flag=1;
1007        }
1008        return 0;
1009#else
1010        assert(!"This should never be called when BPF not enabled");
[abc8e94]1011        trace_set_err(packet->trace,TRACE_ERR_OPTION_UNAVAIL,
1012                                "Feature unavailable");
1013        return -1;
[df338b3]1014#endif
1015}
1016
[e2aebe7]1017DLLEXPORT int trace_apply_filter(libtrace_filter_t *filter,
[e6d963c]1018                        const libtrace_packet_t *packet) {
[e5c2bc4]1019#ifdef HAVE_BPF
[2137b49]1020        void *linkptr = 0;
[33d83d4]1021        unsigned int clen = 0;
[76eeca0]1022        bool free_packet_needed = false;
1023        int ret;
[778d459]1024        libtrace_packet_t *packet_copy = (libtrace_packet_t*)packet;
[33d83d4]1025
[c5a22ec]1026        assert(filter);
[2137b49]1027        assert(packet);
[1352066]1028
[33d83d4]1029        if (libtrace_to_pcap_dlt(trace_get_link_type(packet))==~0U) {
[1352066]1030                /* Copy the packet, as we don't want to trash the one we
1031                 * were passed in
1032                 */
[7ca2c7d]1033                packet_copy=trace_copy_packet(packet);
[76eeca0]1034                free_packet_needed=true;
[7ca2c7d]1035                while (libtrace_to_pcap_dlt(trace_get_link_type(packet_copy))==
[33d83d4]1036                                ~0U) {
[7ca2c7d]1037                        if (!demote_packet(packet_copy)) {
[33d83d4]1038                                trace_set_err(packet->trace, 
[1352066]1039                                                TRACE_ERR_NO_CONVERSION,
1040                                                "pcap does not support this format");
[76eeca0]1041                                if (free_packet_needed) {
[7ca2c7d]1042                                        trace_destroy_packet(packet_copy);
[76eeca0]1043                                }
[1352066]1044                                return -1;
1045                        }
1046                }
1047        }
[b86f8d3]1048       
[7ca2c7d]1049        linkptr = trace_get_link(packet_copy);
[76eeca0]1050        if (!linkptr) {
1051                if (free_packet_needed) {
[7ca2c7d]1052                        trace_destroy_packet(packet_copy);
[76eeca0]1053                }
1054                return 0;
1055        }
1056
1057        /* We need to compile it now, because before we didn't know what the
1058         * link type was
1059         */
[7ca2c7d]1060        if (trace_bpf_compile(filter,packet_copy)==-1) {
[76eeca0]1061                if (free_packet_needed) {
[7ca2c7d]1062                        trace_destroy_packet(packet_copy);
[76eeca0]1063                }
1064                return -1;
1065        }
1066
[7ca2c7d]1067        clen = trace_get_capture_length(packet_copy);
[c681e86]1068
[df338b3]1069        assert(filter->flag);
[76eeca0]1070        ret=bpf_filter(filter->filter.bf_insns,(u_char*)linkptr,clen,clen);
1071        if (free_packet_needed) {
[7ca2c7d]1072                trace_destroy_packet(packet_copy);
[76eeca0]1073        }
1074        return ret;
[9580a74]1075#else
1076        fprintf(stderr,"This version of libtrace does not have bpf filter support\n");
1077        return 0;
1078#endif
[c681e86]1079}
1080
[fba4ca0]1081/* Set the direction flag, if it has one
[80a2e99]1082 * @param packet the packet opaque pointer
1083 * @param direction the new direction (0,1,2,3)
1084 * @returns a signed value containing the direction flag, or -1 if this is not supported
1085 */
[c37ab9f]1086DLLEXPORT libtrace_direction_t trace_set_direction(libtrace_packet_t *packet, 
1087                libtrace_direction_t direction) 
1088{
[9a36e6d]1089        assert(packet);
[4dedc28]1090        if (packet->trace->format->set_direction) {
1091                return packet->trace->format->set_direction(packet,direction);
[80a2e99]1092        }
[85a79b0]1093        return (libtrace_direction_t)~0U;
[80a2e99]1094}
1095
[fba4ca0]1096/* Get the direction flag, if it has one
[850630f]1097 * @param packet a pointer to a libtrace_packet structure
[14a9d05]1098 * @returns a signed value containing the direction flag, or -1 if this is not supported
[9075d49]1099 * The direction is defined as 0 for packets originating locally (ie, outbound)
1100 * and 1 for packets originating remotely (ie, inbound).
1101 * Other values are possible, which might be overloaded to mean special things
1102 * for a special trace.
[14a9d05]1103 * @author Daniel Lawson
1104 */
[c37ab9f]1105DLLEXPORT libtrace_direction_t trace_get_direction(const libtrace_packet_t *packet) 
1106{
[2137b49]1107        assert(packet);
[4dedc28]1108        if (packet->trace->format->get_direction) {
1109                return packet->trace->format->get_direction(packet);
[14a9d05]1110        }
[85a79b0]1111        return (libtrace_direction_t)~0U;
[14a9d05]1112}
[c681e86]1113
[5c25d3a]1114#define ROOT_SERVER(x) ((x) < 512)
1115#define ROOT_CLIENT(x) ((512 <= (x)) && ((x) < 1024))
1116#define NONROOT_SERVER(x) ((x) >= 5000)
1117#define NONROOT_CLIENT(x) ((1024 <= (x)) && ((x) < 5000))
1118#define DYNAMIC(x) ((49152 < (x)) && ((x) < 65535))
[83e0a25]1119#define SERVER(x) ROOT_SERVER(x) || NONROOT_SERVER(x)
[b007afc]1120#define CLIENT(x) ROOT_CLIENT(x) || NONROOT_CLIENT(x)
[83e0a25]1121
[d66fbf0]1122/* Attempt to deduce the 'server' port
[1cea750]1123 * @param protocol the IP protocol (eg, 6 or 17 for TCP or UDP)
1124 * @param source the TCP or UDP source port
1125 * @param dest the TCP or UDP destination port
1126 * @returns a hint as to which port is the server port
1127 */
[85a79b0]1128DLLEXPORT int8_t trace_get_server_port(UNUSED uint8_t protocol, 
1129                uint16_t source, uint16_t dest) 
1130{
[83e0a25]1131        /*
1132         * * If the ports are equal, return DEST
1133         * * Check for well-known ports in the given protocol
1134         * * Root server ports: 0 - 511
1135         * * Root client ports: 512 - 1023
1136         * * non-root client ports: 1024 - 4999
1137         * * non-root server ports: 5000+
1138         * * Check for static ranges: 1024 - 49151
1139         * * Check for dynamic ranges: 49152 - 65535
1140         * * flip a coin.
1141         */
[9c6aa95]1142       
[b007afc]1143        /* equal */
[9c6aa95]1144        if (source == dest)
[b007afc]1145                return USE_DEST;
1146
1147        /* root server port, 0 - 511 */
[5c25d3a]1148        if (ROOT_SERVER(source) && ROOT_SERVER(dest)) {
1149                if (source < dest)
1150                        return USE_SOURCE;
[b007afc]1151                return USE_DEST;
[5c25d3a]1152        }
[b007afc]1153
1154        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
[83e0a25]1155                return USE_SOURCE;
[b007afc]1156        if (!ROOT_SERVER(source) && ROOT_SERVER(dest))
1157                return USE_DEST;
1158
1159        /* non-root server */
[5c25d3a]1160        if (NONROOT_SERVER(source) && NONROOT_SERVER(dest)) {
1161                if (source < dest)
1162                        return USE_SOURCE;
[83e0a25]1163                return USE_DEST;
[5c25d3a]1164        }
[b007afc]1165        if (NONROOT_SERVER(source) && !NONROOT_SERVER(dest))
[83e0a25]1166                return USE_SOURCE;
[b007afc]1167        if (!NONROOT_SERVER(source) && NONROOT_SERVER(dest))
[83e0a25]1168                return USE_DEST;
[b007afc]1169
1170        /* root client */
[5c25d3a]1171        if (ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1172                if (source < dest)
1173                        return USE_SOURCE;
[b007afc]1174                return USE_DEST;
[5c25d3a]1175        }
[f0a2f98]1176        if (ROOT_CLIENT(source) && !ROOT_CLIENT(dest)) {
1177                /* prefer root-client over nonroot-client */
1178                if (NONROOT_CLIENT(dest))
1179                        return USE_SOURCE;
[b007afc]1180                return USE_DEST;
[f0a2f98]1181        }
1182        if (!ROOT_CLIENT(source) && ROOT_CLIENT(dest)) {
1183                /* prefer root-client over nonroot-client */
1184                if (NONROOT_CLIENT(source))
1185                        return USE_DEST;
[b007afc]1186                return USE_SOURCE;
[f0a2f98]1187        }
[83e0a25]1188       
[b007afc]1189        /* nonroot client */
[5c25d3a]1190        if (NONROOT_CLIENT(source) && NONROOT_CLIENT(dest)) {
1191                if (source < dest) 
1192                        return USE_SOURCE;
[b007afc]1193                return USE_DEST;
[5c25d3a]1194        }
[b007afc]1195        if (NONROOT_CLIENT(source) && !NONROOT_CLIENT(dest))
1196                return USE_DEST;
1197        if (!NONROOT_CLIENT(source) && NONROOT_CLIENT(dest))
1198                return USE_SOURCE;
1199
[5c25d3a]1200        /* dynamic range */
[e1868fb]1201        if (DYNAMIC(source) && DYNAMIC(dest)) {
[f9bb6c5]1202                if (source < dest)
1203                        return USE_SOURCE;
[b007afc]1204                return USE_DEST;
[e1868fb]1205        }
[b007afc]1206        if (DYNAMIC(source) && !DYNAMIC(dest))
1207                return USE_DEST;
1208        if (!DYNAMIC(source) && DYNAMIC(dest))
1209                return USE_SOURCE;
1210        /*
1211        if (SERVER(source) && CLIENT(dest))
1212                return USE_SOURCE;
1213       
1214        if (SERVER(dest) && CLIENT(source))
1215                return USE_DEST;
1216        if (ROOT_SERVER(source) && !ROOT_SERVER(dest))
1217                return USE_SOURCE;
1218        if (ROOT_SERVER(dest) && !ROOT_SERVER(source))
1219                return USE_DEST;
1220        */
[7068467]1221        /* failing that test... */
[83e0a25]1222        if (source < dest) {
1223                return USE_SOURCE;
1224        } 
1225        return USE_DEST;
1226       
1227}
[80a2e99]1228
[fba4ca0]1229/* Truncate the packet at the suggested length
[80a2e99]1230 * @param packet        the packet opaque pointer
[850630f]1231 * @param size          the new length of the packet
[fe7b292]1232 * @returns the new size of the packet
[c95b923]1233 * @note size and the return size refer to the network-level payload of the
1234 * packet, and do not include any capture headers. For example, to truncate a
1235 * packet after the IP header, set size to sizeof(ethernet_header) +
1236 * sizeof(ip_header)
1237 * @note If the original network-level payload is smaller than size, then the
1238 * original size is returned and the packet is left unchanged.
[80a2e99]1239 * @author Daniel Lawson
1240 */
[e6d963c]1241DLLEXPORT size_t trace_set_capture_length(libtrace_packet_t *packet, size_t size) {
[80a2e99]1242        assert(packet);
1243
[c95b923]1244        if (packet->trace->format->set_capture_length) {
[2e420ff]1245                return packet->trace->format->set_capture_length(packet,size);
[80a2e99]1246        }
[fe7b292]1247
[85a79b0]1248        return ~0U;
[80a2e99]1249}
1250
[39e141f]1251DLLEXPORT const char * trace_parse_uri(const char *uri, char **format) {
[6f75b9d]1252        const char *uridata = 0;
[de8c420b]1253       
1254        if((uridata = strchr(uri,':')) == NULL) {
[7068467]1255                /* badly formed URI - needs a : */
[de8c420b]1256                return 0;
1257        }
1258
1259        if ((uridata - uri) > URI_PROTO_LINE) {
[7068467]1260                /* badly formed URI - uri type is too long */
[de8c420b]1261                return 0;
1262        }
1263
[4bd8a5b]1264        *format=xstrndup(uri, (size_t)(uridata - uri));
[6f75b9d]1265
[7068467]1266        /* push uridata past the delimiter */
[de8c420b]1267        uridata++;
[ae8196e]1268       
[de8c420b]1269        return uridata;
1270}
[6dbc47a]1271
[e6d963c]1272enum base_format_t trace_get_format(libtrace_packet_t *packet) 
[0ea3526]1273{
[6dbc47a]1274        assert(packet);
1275
1276        return packet->trace->format->type;
1277}
[de8c420b]1278       
[39e141f]1279DLLEXPORT libtrace_err_t trace_get_err(libtrace_t *trace)
[880aa58]1280{
[0ea3526]1281        libtrace_err_t err = trace->err;
1282        trace->err.err_num = 0; /* "OK" */
1283        trace->err.problem[0]='\0';
1284        return err;
1285}
1286
[39e141f]1287DLLEXPORT bool trace_is_err(libtrace_t *trace)
[eeab9832]1288{
1289        return trace->err.err_num != 0;
1290}
1291
[39e141f]1292DLLEXPORT void trace_perror(libtrace_t *trace,const char *msg,...)
[eeab9832]1293{
1294        char buf[256];
1295        va_list va;
1296        va_start(va,msg);
1297        vsnprintf(buf,sizeof(buf),msg,va);
1298        va_end(va);
1299        if(trace->err.err_num) {
1300                fprintf(stderr,"%s(%s): %s\n",
1301                                buf,trace->uridata,trace->err.problem);
1302        } else {
1303                fprintf(stderr,"%s(%s): No error\n",
1304                                buf,trace->uridata);
1305        }
[114b8d6]1306        trace->err.err_num = 0; /* "OK" */
1307        trace->err.problem[0]='\0';
[eeab9832]1308}
1309
[39e141f]1310DLLEXPORT libtrace_err_t trace_get_err_output(libtrace_out_t *trace)
[0ea3526]1311{
1312        libtrace_err_t err = trace->err;
[ae66bde]1313        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
[0ea3526]1314        trace->err.problem[0]='\0';
1315        return err;
[880aa58]1316}
[0d57541]1317
[39e141f]1318DLLEXPORT bool trace_is_err_output(libtrace_out_t *trace)
[eeab9832]1319{
1320        return trace->err.err_num != 0;
1321}
1322
[39e141f]1323DLLEXPORT void trace_perror_output(libtrace_out_t *trace,const char *msg,...)
[eeab9832]1324{
1325        char buf[256];
1326        va_list va;
1327        va_start(va,msg);
1328        vsnprintf(buf,sizeof(buf),msg,va);
1329        va_end(va);
1330        if(trace->err.err_num) {
1331                fprintf(stderr,"%s(%s): %s\n",
1332                                buf,trace->uridata,trace->err.problem);
1333        } else {
1334                fprintf(stderr,"%s(%s): No error\n",buf,trace->uridata);
1335        }
[e4976e1]1336        trace->err.err_num = TRACE_ERR_NOERROR; /* "OK" */
1337        trace->err.problem[0]='\0';
[eeab9832]1338}
1339
[39e141f]1340DLLEXPORT int trace_seek_erf_timestamp(libtrace_t *trace, uint64_t ts)
[0d57541]1341{
1342        if (trace->format->seek_erf) {
1343                return trace->format->seek_erf(trace,ts);
1344        }
1345        else {
[6c248a9]1346                if (trace->format->seek_timeval) {
1347                        struct timeval tv;
1348#if __BYTE_ORDER == __BIG_ENDIAN
1349                        tv.tv_sec = ts & 0xFFFFFFFF;
1350#elif __BYTE_ORDER == __LITTLE_ENDIAN
1351                        tv.tv_sec = ts >> 32;
1352#else
1353#error "What on earth are you running this on?"
1354#endif
1355                        tv.tv_usec = ((ts&0xFFFFFFFF)*1000000)>>32;
1356                        if (tv.tv_usec >= 1000000) {
1357                                tv.tv_usec -= 1000000;
1358                                tv.tv_sec += 1;
1359                        }
1360                        return trace->format->seek_timeval(trace,tv);
1361                }
1362                if (trace->format->seek_seconds) {
1363                        double seconds = 
1364                                (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX);
1365                        return trace->format->seek_seconds(trace,seconds);
1366                }
1367                trace_set_err(trace,
1368                                TRACE_ERR_OPTION_UNAVAIL,
1369                                "Feature unimplemented");
1370                return -1;
1371        }
1372}
1373
[39e141f]1374DLLEXPORT int trace_seek_seconds(libtrace_t *trace, double seconds)
[6c248a9]1375{
1376        if (trace->format->seek_seconds) {
1377                return trace->format->seek_seconds(trace,seconds);
1378        }
1379        else {
1380                if (trace->format->seek_timeval) {
1381                        struct timeval tv;
1382                        tv.tv_sec = (uint32_t)seconds;
1383                        tv.tv_usec = (uint32_t)(((seconds - tv.tv_sec) * 1000000)/UINT_MAX);
1384                        return trace->format->seek_timeval(trace,tv);
1385                }
1386                if (trace->format->seek_erf) {
1387                        uint64_t timestamp = 
1388                                ((uint64_t)((uint32_t)seconds) << 32) + \
[67a14d4]1389                            (uint64_t)(( seconds - (uint32_t)seconds   ) * UINT_MAX);
[6c248a9]1390                        return trace->format->seek_erf(trace,timestamp);
1391                }
1392                trace_set_err(trace,
1393                                TRACE_ERR_OPTION_UNAVAIL,
1394                                "Feature unimplemented");
1395                return -1;
1396        }
1397}
1398
[39e141f]1399DLLEXPORT int trace_seek_timeval(libtrace_t *trace, struct timeval tv)
[6c248a9]1400{
1401        if (trace->format->seek_timeval) {
1402                return trace->format->seek_timeval(trace,tv);
1403        }
1404        else {
1405                if (trace->format->seek_erf) {
1406                        uint64_t timestamp = ((((uint64_t)tv.tv_sec) << 32) + \
1407                                (((uint64_t)tv.tv_usec * UINT_MAX)/1000000));
1408                        return trace->format->seek_erf(trace,timestamp);
1409                }
1410                if (trace->format->seek_seconds) {
[e4e1635]1411                        double seconds = tv.tv_sec + ((tv.tv_usec * 1.0)/1000000);
[6c248a9]1412                        return trace->format->seek_seconds(trace,seconds);
1413                }
[0d57541]1414                trace_set_err(trace,
1415                                TRACE_ERR_OPTION_UNAVAIL,
1416                                "Feature unimplemented");
1417                return -1;
1418        }
1419}
1420
[39e141f]1421DLLEXPORT char *trace_ether_ntoa(const uint8_t *addr, char *buf)
[752709f]1422{
1423        char *buf2 = buf;
[411f3c7]1424        char staticbuf[18]={0,};
[752709f]1425        if (!buf2)
1426                buf2=staticbuf;
[4bd8a5b]1427        snprintf(buf2,(size_t)18,"%02x:%02x:%02x:%02x:%02x:%02x",
[752709f]1428                        addr[0],addr[1],addr[2],
1429                        addr[3],addr[4],addr[5]);
1430        return buf2;
1431}
1432
[39e141f]1433DLLEXPORT uint8_t *trace_ether_aton(const char *buf, uint8_t *addr)
[752709f]1434{
1435        uint8_t *buf2 = addr;
1436        unsigned int tmp[6];
1437        static uint8_t staticaddr[6];
1438        if (!buf2)
1439                buf2=staticaddr;
1440        sscanf(buf,"%x:%x:%x:%x:%x:%x",
1441                        &tmp[0],&tmp[1],&tmp[2],
1442                        &tmp[3],&tmp[4],&tmp[5]);
1443        buf2[0]=tmp[0]; buf2[1]=tmp[1]; buf2[2]=tmp[2];
1444        buf2[3]=tmp[3]; buf2[4]=tmp[4]; buf2[5]=tmp[5];
1445        return buf2;
1446}
[4af54d1]1447
[c5ebbaa]1448DLLEXPORT
1449void trace_construct_packet(libtrace_packet_t *packet,
1450                libtrace_linktype_t linktype,
1451                const void *data,
1452                uint16_t len)
1453{
[a7d1914]1454        size_t size;
[0a62bba]1455        static libtrace_t *deadtrace=NULL;
[c5ebbaa]1456        libtrace_pcapfile_pkt_hdr_t hdr;
[6ed6c4a]1457#ifdef WIN32
1458        struct _timeb tstruct;
1459#else
[c5ebbaa]1460        struct timeval tv;
[6ed6c4a]1461#endif
1462
1463        if (NULL == deadtrace) 
1464                deadtrace=trace_create_dead("pcapfile");
1465
1466#ifdef WIN32
1467        _ftime(&tstruct);
1468        hdr.ts_sec=tstruct.time;
1469        hdr.ts_usec=tstruct.millitm * 1000;
1470#else
[c5ebbaa]1471        gettimeofday(&tv,NULL);
1472        hdr.ts_sec=tv.tv_sec;
1473        hdr.ts_usec=tv.tv_usec;
[6ed6c4a]1474#endif
1475
[c5ebbaa]1476        hdr.caplen=len;
1477        hdr.wirelen=len;
1478
1479        packet->trace=deadtrace;
[a7d1914]1480        size=len+sizeof(hdr);
[c5ebbaa]1481        if (packet->buf_control==TRACE_CTRL_PACKET) {
[a7d1914]1482                packet->buffer=realloc(packet->buffer,size);
[c5ebbaa]1483        }
1484        else {
[a7d1914]1485                packet->buffer=malloc(size);
[c5ebbaa]1486        }
1487        packet->buf_control=TRACE_CTRL_PACKET;
1488        packet->header=packet->buffer;
1489        packet->payload=(void*)((char*)packet->buffer+sizeof(hdr));
1490        memcpy(packet->header,&hdr,sizeof(hdr));
[4bd8a5b]1491        memcpy(packet->payload,data,(size_t)len);
[73dd29f]1492        packet->type=pcap_linktype_to_rt(libtrace_to_pcap_linktype(linktype));
[c5ebbaa]1493}
Note: See TracBrowser for help on using the repository browser.