source: lib/trace.c @ d242ea8

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

Some of tracesummary's bpf filters were incorrect - however the new correct filters don't work so well with the output format so that will need fixing at some point
Improved error reporting for bpf filters
tracestats will now ignore a filter that fails and print a single warning. It also no longer increments the counter for filters that fail.

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