source: lib/trace.c @ df338b3

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

Major restructuring of format_pcap

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