source: lib/trace.c @ 1fc2f6a

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

Output functions to format_erf.c

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