source: lib/trace.c @ abc8e94

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

Fix a security flaw
Tidy up some code

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