source: lib/trace.c @ 78f750e

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 78f750e was f04e489, checked in by Daniel Lawson <dlawson@…>, 16 years ago

fixed the legacyatm legacypos and legacyeth formats to correctly calculate the framing offset then use that to step into the link layer properly.
Added headers to deal with the link layers.

updated tracedump to be correct now.

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