source: lib/trace.c @ bad6a93

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

trace_get_vlan_payload_from_ethernet is now available to libtrace users.
Fixed error where erf wire length was having padding subtracted from it - wire length doesn't include padding.
erf can also attach padding to the end of packets - get_capture_length now returns the minimum of the record length - padding and the wire length.
Added support for RT_LOSTCONN - also other zero sized rt packets shouldn't cause TRACE_EVENT_TERMINATE anymore
rt header information is no longer stored statically when doing a non-blocking read
The packet->buffer for rt packets is now regarded as external, so now trace_destroy_packet shouldn't cause a segfault

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