source: lib/trace.c @ 4bd8a5b

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

Cleanup a gazillion warnings

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