source: lib/trace.c @ 548a9c2

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

Split erf up into init/start functions
Add "errno" outputs to trace_set_err
Add support for SNAPLEN/FILTER config options

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