Changeset 238d50a


Ignore:
Timestamp:
02/08/10 16:43:43 (11 years ago)
Author:
Shane Alcock <salcock@…>
Branches:
4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
Children:
d026488
Parents:
5511c14
Message:
  • Updated licensing and documentation for several format modules and the format_helper code
Location:
lib
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • lib/format_helper.c

    r3fc7948 r238d50a  
    22 * This file is part of libtrace
    33 *
    4  * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
     4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
     5 * New Zealand.
     6 *
    57 * Authors: Daniel Lawson
    6  *          Perry Lorier
     8 *          Perry Lorier
     9 *          Shane Alcock
    710 *         
    811 * All rights reserved.
     
    6467#  include <sys/ioctl.h>
    6568
     69/* Generic event function for live capture devices / interfaces */
    6670struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace,
    6771                                        struct libtrace_packet_t *packet) {
     
    127131#endif
    128132
     133/* Generic event function for trace files */
    129134struct libtrace_eventobj_t trace_event_trace(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
    130135        struct libtrace_eventobj_t event = {0,0,0.0,0};
     
    138143
    139144        if (!trace->event.packet) {
     145                /* There is no packet event waiting for us, so create a new
     146                 * libtrace packet in the event structure and read the next
     147                 * packet into that.
     148                 *
     149                 * If a SLEEP event is reported this time around, the read
     150                 * packet can therefore be saved until the next time this
     151                 * function is called. */
     152
    140153                trace->event.packet = trace_create_packet();
    141154                trace->event.psize=
    142155                        trace_read_packet(trace,trace->event.packet);
    143156                if (trace->event.psize<1) {
    144                         /* return here, the test for
    145                          * event.size will sort out the error
    146                          */
     157                        /* Return here, the test for event.size will sort out
     158                         * the error  */
    147159                        if (trace_is_err(trace)) {
    148160                                trace_perror(trace, "read packet");
     
    155167        }
    156168
     169        /* The goal here is to replicate the inter-packet gaps that are
     170         * present in the trace. */
     171
    157172        ts=trace_get_seconds(trace->event.packet);
    158173
    159         /* Get the adjusted current time */
     174        /* Get the current walltime */
    160175#ifdef WIN32
    161176        _ftime64(&tstruct);
     
    170185       
    171186        if (fabs(trace->event.tdelta)>1e-9) {
    172                 /* adjust for trace delta */
     187                /* Subtract the tdelta from the walltime to get a suitable
     188                 * "relative" time */
    173189                now -= trace->event.tdelta;
    174190
    175                 /* if the trace timestamp is still in the
    176                  * future, return a SLEEP event,
    177                  * otherwise fire the packet
    178                  */
     191                /* If the trace timestamp is still in the future, return a
     192                 * SLEEP event, otherwise return the packet */
    179193                if (ts > now) {
    180194                        event.seconds = ts -
     
    184198                }
    185199        } else {
    186                 /* work out the difference between the
    187                  * start of trace replay, and the first
    188                  * packet in the trace
     200                /* Work out the difference between the walltime at the start
     201                 * of the trace replay and the timestamp of the first packet
     202                 * in the trace. This will be used to convert the walltime
     203                 * into a timeline that is relative to the timestamps in the
     204                 * trace file.
    189205                 */
    190206                trace->event.tdelta = now - ts;
     
    195211       
    196212        /* XXX: Could we do this more efficiently? */
     213
    197214        /* We do a lot of freeing and creating of packet buffers with this
    198215         * method, but at least it works unlike what was here previously */
     
    200217                free(packet->buffer);
    201218        }
    202                
     219       
     220        /* The packet that we had read earlier is now ready to be returned
     221         * to the user - switch all the pointers etc. over */   
    203222        packet->type = trace->event.packet->type;
    204223        packet->trace = trace->event.packet->trace;
     
    232251#endif
    233252
    234 /* open a file or stdin using gzip compression if necessary (and supported)
    235  * @internal
    236  */
     253/* Open a file for reading using the new Libtrace IO system */
    237254io_t *trace_open_file(libtrace_t *trace)
    238255{
     
    244261}
    245262
    246 /* Create a file or write to stdout using compression if requested
    247  * @internal
    248  */
     263/* Open a file for writing using the new Libtrace IO system */
    249264iow_t *trace_open_file_out(libtrace_out_t *trace,int level, int fileflag)
    250265{
     
    256271
    257272
    258 /** Update the libtrace error
     273/** Sets the error status for an input trace
    259274 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
    260275 * @param msg a plaintext error message
     
    279294}
    280295
    281 /** Update the libtrace for output traces error
     296/** Sets the error status for an output trace
    282297 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
    283298 * @param msg a plaintext error message
     
    302317}
    303318
     319/* Byte swapping functions for various inttypes */
    304320uint64_t byteswap64(uint64_t num)
    305321{
  • lib/format_legacy.c

    r1aa4bf7 r238d50a  
    22 * This file is part of libtrace
    33 *
    4  * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
     4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
     5 * New Zealand.
     6 *
    57 * Authors: Daniel Lawson
    6  *          Perry Lorier
     8 *          Perry Lorier
     9 *          Shane Alcock
    710 *         
    811 * All rights reserved.
     
    2831 *
    2932 */
     33
    3034#define _GNU_SOURCE
    3135
     
    5155#endif
    5256
     57/* The format module deals with legacy DAG formats from older revisions of the
     58 * DAG hardware and software. Aside from a few minor differences, the legacy
     59 * formats are very similar so we can deal with them using the same callback
     60 * functions for the most part.
     61 *
     62 * These formats are intended for reading old ERF traces such as the earlier
     63 * Auckland traces.
     64 *
     65 * We definitely do not support writing using these formats - one should
     66 * convert packets to regular ERF instead before writing.
     67 */
     68
     69/* Several formats are covered in this source file:
     70 *
     71 * Legacy Ethernet:     as seen in Auckland VI
     72 * Legacy ATM:          as seen in Auckland II and IV
     73 * Legacy PoS:          as seen in Leipzig I and II
     74 * Legacy NZIX:         as seen in NZIX I
     75 */
    5376
    5477/* Catch undefined O_LARGEFILE on *BSD etc */
     
    6386#define DATA(x) ((struct legacy_format_data_t *)x->format_data)
    6487
     88/* Legacy NZIX timestamps are all relative to the start of the trace, so we
     89 * have to remember all sorts of stuff so that we can convert them into a
     90 * useful timestamp */
     91
    6592struct legacy_format_data_t {
    66         time_t starttime;       /* Used for legacy_nzix */
    67         uint64_t ts_high;       /* Used for legacy_nzix */
    68         uint32_t ts_old;        /* Used for legacy_nzix */
     93        time_t starttime;       /* Time that the trace file was started */
     94        uint64_t ts_high;       /* The timestamp of the last packet */
     95        uint32_t ts_old;        /* The timestamp of the last packet as
     96                                   reported in the NZIX header */
    6997};
    7098
     
    104132}
    105133
     134/* Takes a trace file name and determines the time that the capture began.
     135 *
     136 * NZIX only features relative timestamps so the trace file name is the only
     137 * indication we have of where the relative timestamping begins from
     138 */
    106139static time_t trtime(char *s) {
    107140        /* XXX: this function may not be particularly portable to
     
    143176
    144177        legacy_init_format_data(libtrace);     
     178       
     179        /* Check that the filename appears to contain a suitable timestamp.
     180         * Without it, we have no way of determining the actual timestamps
     181         * for each packet */
    145182        if((retval = regcomp(&reg, "[0-9]{8}-[0-9]{6}", REG_EXTENDED)) != 0) {
    146183                trace_set_err(libtrace, errno, "Failed to compile regex");
     
    155192}
    156193
     194/* All of the formats can be started in exactly the same way */
    157195static int erf_start_input(libtrace_t *libtrace)
    158196{
     
    291329        }
    292330
    293         /* lets move the padding so that it's in the framing header */
     331        /* Lets move the padding so that it's in the framing header */
    294332        data_ptr = ((char *)buffer) + 12;
    295333        memmove(data_ptr + 2, data_ptr, 26);
     
    392430        hdr_ts = legacy->ts;
    393431
    394         /* seems we only need 30 bits to represent our timestamp */
     432        /* Seems we only need 30 bits to represent our timestamp */
    395433        hdr_ts >>=2;
    396         /* try a sequence number wrap-around comparison */
     434       
     435        /* Try a sequence number wrap-around comparison */
    397436        if (ts_cmp(hdr_ts, old_ts) > (UINT32_MAX / 2) )
    398                 new_ts += (1LL << 30); /* wraparound */
    399         new_ts &= ~((1LL << 30) -1);    /* mask lower 30 bits */
    400         new_ts += hdr_ts;               /* packet ts is the new 30 bits */
     437                new_ts += (1LL << 30); /* Wraparound */
     438        new_ts &= ~((1LL << 30) -1);    /* Mask lower 30 bits */
     439        new_ts += hdr_ts;               /* Packet ts is the new 30 bits */
    401440        DATA(packet->trace)->ts_old = hdr_ts;
    402441
  • lib/format_linux.c

    r7fa118f r238d50a  
    22 * This file is part of libtrace
    33 *
    4  * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
     4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
     5 * New Zealand.
     6 *
    57 * Authors: Daniel Lawson
    6  *          Perry Lorier
     8 *          Perry Lorier
     9 *          Shane Alcock
    710 *         
    811 * All rights reserved.
     
    2831 *
    2932 */
     33
    3034
    3135#include "libtrace.h"
     
    5458#include <assert.h>
    5559
     60/* This format module deals with using the Linux Native capture format.
     61 *
     62 * Linux Native is a LIVE capture format.
     63 *
     64 * This format also supports writing which will write packets out to the
     65 * network as a form of packet replay. This should not be confused with the
     66 * RT protocol which is intended to transfer captured packet records between
     67 * RT-speaking programs.
     68 */
     69
    5670/* Declared in linux/if_arp.h but not in net/if_arp.h sigh */
    5771#ifndef ARPHRD_NONE
     
    6680typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t;
    6781
    68 struct libtrace_format_data_t {
     82struct linux_format_data_t {
     83        /* The file descriptor being used for the capture */
    6984        int fd;
     85        /* The snap length for the capture */
    7086        int snaplen;
     87        /* Flag indicating whether the interface should be placed in
     88         * promiscuous mode */
    7189        int promisc;
     90        /* The timestamp format used by the capture */
    7291        timestamptype_t timestamptype;
     92        /* A BPF filter that is applied to every captured packet */
    7393        libtrace_filter_t *filter;
     94        /* Statistics for the capture process, e.g. dropped packet counts */
    7495        struct tpacket_stats stats;
     96        /* Flag indicating whether the statistics are current or not */
    7597        int stats_valid;
    7698};
    7799
    78100
    79 /* Note that this structure is passed over the wire in rt encapsulation, and thus we need to be
    80  * careful with data sizes.  timeval's and timespec's change their size on 32/64 machines
     101/* Note that this structure is passed over the wire in rt encapsulation, and
     102 * thus we need to be careful with data sizes.  timeval's and timespec's
     103 * can also change their size on 32/64 machines.
    81104 */
     105
     106/* Format header for encapsulating packets captured using linux native */
    82107struct libtrace_linuxnative_header {
     108        /* Timestamp of the packet, as a timeval */
    83109        struct {
    84110                uint32_t tv_sec;
    85111                uint32_t tv_usec;
    86112        } tv;
     113        /* Timestamp of the packet, as a timespec */
    87114        struct {
    88115                uint32_t tv_sec;
    89116                uint32_t tv_nsec;
    90117        } ts;
     118        /* The timestamp format used by the process that captured this packet */
    91119        uint8_t timestamptype;
     120        /* Wire length */
    92121        uint32_t wirelen;
     122        /* Capture length */
    93123        uint32_t caplen;
     124        /* The linux native header itself */
    94125        struct sockaddr_ll hdr;
    95126};
    96127
    97 struct libtrace_linuxnative_format_data_t {
     128struct linux_output_format_data_t {
     129        /* The file descriptor used to write the packets */
    98130        int fd;
    99131};
    100132
    101 #define FORMAT(x) ((struct libtrace_format_data_t*)(x))
    102 #define DATAOUT(x) ((struct libtrace_linuxnative_format_data_t*)((x)->format_data))
     133#define FORMAT(x) ((struct linux_format_data_t*)(x))
     134#define DATAOUT(x) ((struct linux_output_format_data_t*)((x)->format_data))
    103135
    104136static int linuxnative_probe_filename(const char *filename)
     
    110142static int linuxnative_init_input(libtrace_t *libtrace)
    111143{
    112         libtrace->format_data = (struct libtrace_format_data_t *)
    113                 malloc(sizeof(struct libtrace_format_data_t));
     144        libtrace->format_data = (struct linux_format_data_t *)
     145                malloc(sizeof(struct linux_format_data_t));
    114146        FORMAT(libtrace->format_data)->fd = -1;
    115147        FORMAT(libtrace->format_data)->promisc = -1;
     
    123155static int linuxnative_init_output(libtrace_out_t *libtrace)
    124156{
    125         libtrace->format_data = (struct libtrace_linuxnative_format_data_t*)
    126                 malloc(sizeof(struct libtrace_linuxnative_format_data_t));
     157        libtrace->format_data = (struct linux_output_format_data_t*)
     158                malloc(sizeof(struct linux_output_format_data_t));
    127159        DATAOUT(libtrace)->fd = -1;
    128160
     
    136168        memset(&addr,0,sizeof(addr));
    137169        libtrace_filter_t *filter = FORMAT(libtrace->format_data)->filter;
     170       
     171        /* Create a raw socket for reading packets on */
    138172        FORMAT(libtrace->format_data)->fd =
    139173                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
     
    143177                return -1;
    144178        }
     179
     180        /* Bind to the capture interface */
    145181        addr.sll_family = AF_PACKET;
    146182        addr.sll_protocol = htons(ETH_P_ALL);
     
    175211                        FORMAT(libtrace->format_data)->promisc=0;
    176212        }
    177                                
     213       
     214        /* Enable promiscuous mode, if requested */                     
    178215        if (FORMAT(libtrace->format_data)->promisc) {
    179216                struct packet_mreq mreq;
     
    190227                }
    191228        }
     229
     230        /* Set the timestamp option on the socket - aim for the most detailed
     231         * clock resolution possible */
    192232#ifdef SO_TIMESTAMPNS
    193233        if (setsockopt(FORMAT(libtrace->format_data)->fd,
     
    281321}
    282322
     323/* Compiles a libtrace BPF filter for use with a linux native socket */
    283324static int linuxnative_configure_bpf(libtrace_t *libtrace,
    284325                libtrace_filter_t *filter) {
     
    361402                        break;
    362403                case TRACE_OPTION_EVENT_REALTIME:
     404                        /* Live captures are always going to be in trace time */
    363405                        break;
    364406                /* Avoid default: so that future options will cause a warning
     
    434476                        (int)FORMAT(libtrace->format_data)->snaplen);
    435477
     478        /* Prepare the msghdr and iovec for the kernel to write the
     479         * captured packet into. The msghdr will point to the part of our
     480         * buffer reserved for sll header, while the iovec will point at
     481         * the buffer following the sll header. */
     482
    436483        msghdr.msg_name = &hdr->hdr;
    437484        msghdr.msg_namelen = sizeof(struct sockaddr_ll);
     
    455502
    456503        hdr->caplen=LIBTRACE_MIN(snaplen,hdr->wirelen);
     504
     505        /* Extract the timestamps from the msghdr and store them in our
     506         * linux native encapsulation, so that we can preserve the formatting
     507         * across multiple architectures */
    457508
    458509        for (cmsg = CMSG_FIRSTHDR(&msghdr);
     
    479530        }
    480531
    481         /* Did we not get given a timestamp? */
     532        /* Did we not get given a timestamp? Try to get one from the
     533         * file descriptor directly */
    482534        if (cmsg == NULL) {
    483535                struct timeval tv;
     
    493545        }
    494546
     547        /* Buffer contains all of our packet (including our custom header) so
     548         * we just need to get prepare_packet to set all our packet pointers
     549         * appropriately */
     550       
    495551        if (linuxnative_prepare_packet(libtrace, packet, packet->buffer,
    496552                                packet->type, flags))
     
    513569        memcpy(hdr.sll_addr,packet->payload,(size_t)ntohs(hdr.sll_halen));
    514570
     571        /* This is pretty easy, just send the payload using sendto() (after
     572         * setting up the sll header properly, of course) */
    515573        return sendto(DATAOUT(trace)->fd,
    516574                        packet->payload,
     
    524582        int linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
    525583                                ->hdr.sll_hatype);
     584        /* Convert the ARPHRD type into an appropriate libtrace link type */
     585
    526586        switch (linktype) {
    527587                case ARPHRD_ETHER:
     
    657717}
    658718
    659 /* Number of packets that past filtering */
     719/* Number of packets that passed filtering */
    660720static uint64_t linuxnative_get_captured_packets(libtrace_t *trace) {
    661721        if (trace->format_data == NULL)
     
    710770        printf("linuxnative format module: $Revision$\n");
    711771        printf("Supported input URIs:\n");
    712         printf("\tint:\n");
     772        printf("\tint:eth0\n");
    713773        printf("\n");
    714774        printf("Supported output URIs:\n");
    715         printf("\tnone\n");
     775        printf("\tint:eth0\n");
    716776        printf("\n");
    717777        return;
  • lib/format_pcap.c

    rdb03808 r238d50a  
    22 * This file is part of libtrace
    33 *
    4  * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
     4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
     5 * New Zealand.
     6 *
    57 * Authors: Daniel Lawson
    6  *          Perry Lorier
     8 *          Perry Lorier
     9 *          Shane Alcock
    710 *         
    811 * All rights reserved.
     
    4952#endif
    5053
     54/* This format module deals with traces captured using the PCAP library. This
     55 * format module handles both captures from a live interface and from PCAP
     56 * files.
     57 *
     58 * However, the PCAP file support featured in this code is superceded by our
     59 * own implementation of the PCAP file format, called pcapfile. See
     60 * format_pcapfile.c for more information.
     61 *
     62 * Both the live and trace formats support writing, provided your PCAP library
     63 * also supports it.
     64 *
     65 */
     66
     67/* Formats implemented in this module:
     68 *      pcap - deals with PCAP trace files
     69 *      pcapint - deals with live PCAP interfaces
     70 */
     71
    5172#ifdef HAVE_LIBPCAP
    5273static struct libtrace_format_t pcap;
     
    5980#define OUTPUT DATAOUT(libtrace)->output
    6081struct pcap_format_data_t {
    61         /** Information about the current state of the input device */
     82        /** Information about the current state of the input trace */
    6283        union {
    63                 pcap_t *pcap;
     84                /* The PCAP input source */
     85                pcap_t *pcap;
    6486        } input;
     87        /* A filter to be applied to all packets read from the source */
    6588        libtrace_filter_t *filter;
     89        /* The snap length to be applied to all captured packets (live only) */
    6690        int snaplen;
     91        /* Whether the capture interface should be set to promiscuous mode
     92         * (live only) */
    6793        int promisc;
    6894};
    6995
    7096struct pcap_format_data_out_t {
     97        /* Information about the current state of the output trace */
    7198        union {
    7299                struct {
    73                         pcap_t *pcap;
     100                        /* The PCAP output device or trace */
     101                        pcap_t *pcap;   
     102                        /* The PCAP dumper */
    74103                        pcap_dumper_t *dump;
    75104                } trace;
     
    93122
    94123
    95         /* if the file is already open */
     124        /* Check if the file is already open */
    96125        if (INPUT.pcap)
    97126                return 0; /* success */
    98127
     128        /* Open the trace file for reading */
    99129        if ((INPUT.pcap =
    100130                pcap_open_offline(libtrace->uridata,
     
    104134                return -1;
    105135        }
     136
     137        /* If a filter has been configured, compile and apply it */
    106138        if (DATA(libtrace)->filter) {
    107139                if (DATA(libtrace)->filter->flag == 0) {
     
    135167                         */
    136168                case TRACE_OPTION_PROMISC:
    137                         /* can't do promisc on a trace! fall thru */
     169                        /* Can't do promisc on a trace! */
    138170                case TRACE_OPTION_META_FREQ:
    139171                        /* No meta data for this format */
    140172                case TRACE_OPTION_EVENT_REALTIME:
     173                        /* We do not support this option for PCAP traces */
    141174                default:
    142175                        return -1;
     
    210243static int pcapint_start_input(libtrace_t *libtrace) {
    211244        char errbuf[PCAP_ERRBUF_SIZE];
     245       
     246        /* Open the live device */
    212247        if ((INPUT.pcap =
    213248                        pcap_open_live(libtrace->uridata,
     
    367402        link = trace_get_packet_buffer(packet,&linktype,&remaining);
    368403
     404        /* We may have to convert this packet into a suitable PCAP packet */
     405
    369406        /* If this packet cannot be converted to a pcap linktype then
    370407         * pop off the top header until it can be converted
     
    406443        }
    407444
     445        /* Check if the packet was captured using one of the PCAP formats */
    408446        if (packet->trace->format == &pcap ||
    409447                        packet->trace->format == &pcapint) {
     448                /* Yes - this means we can write it straight out */
    410449                pcap_dump((u_char*)OUTPUT.trace.dump,
    411450                                (struct pcap_pkthdr *)packet->header,
    412451                                packet->payload);
    413452        } else {
     453                /* No - need to fill in a PCAP header with the appropriate
     454                 * values */
     455
    414456                /* Leave the manual copy as it is, as it gets around
    415457                 * some OS's having different structures in pcap_pkt_hdr
     
    468510
    469511static libtrace_linktype_t pcap_get_link_type(const libtrace_packet_t *packet) {
    470         /* pcap doesn't store linktype in the framing header so we need
    471          * rt to do it for us
     512        /* PCAP doesn't store linktype in the framing header so we need
     513         * RT to do it for us
    472514         */
    473515        int linktype = rt_to_pcap_linktype(packet->type);
     
    477519static libtrace_direction_t pcap_set_direction(libtrace_packet_t *packet,
    478520                libtrace_direction_t dir) {
     521       
     522        /* PCAP doesn't have a direction field in the header, so we need to
     523         * promote to Linux SLL to tag it properly */
    479524        libtrace_sll_header_t *sll;
    480525        promote_packet(packet);
    481526        sll=packet->payload;
     527       
    482528        /* sll->pkttype should be in the endianness of the host that the
    483          * trace was taken on.  this is impossible to achieve
    484          * so we assume host endianness
     529         * trace was taken on.  This is impossible to achieve so we assume
     530         * host endianness
    485531         */
    486532        if(dir==TRACE_DIR_OUTGOING)
     
    494540        libtrace_direction_t direction  = -1;
    495541        switch(pcap_get_link_type(packet)) {
     542                /* Only packets encapsulated in Linux SLL or PFLOG have any
     543                 * direction information */
     544
    496545                case TRACE_TYPE_LINUX_SLL:
    497546                {
     
    598647        assert(packet);
    599648        if (size > trace_get_capture_length(packet)) {
    600                 /* can't make a packet larger */
     649                /* Can't make a packet larger */
    601650                return trace_get_capture_length(packet);
    602651        }
  • lib/format_pcapfile.c

    rb5a23b3 r238d50a  
    22 * This file is part of libtrace
    33 *
    4  * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
     4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
     5 * New Zealand.
     6 *
    57 * Authors: Daniel Lawson
    6  *          Perry Lorier
     8 *          Perry Lorier
     9 *          Shane Alcock
    710 *         
    811 * All rights reserved.
     
    4346#include <fcntl.h>
    4447#include <stdbool.h>
     48
     49/* This format module implements our own, more efficient, version of the PCAP
     50 * file format. This should always be used in preference to the "pcap" format
     51 * provided in format_pcap.c.
     52 *
     53 * This is a trace file format and does not implement any live interface
     54 * capture. This is covered by "pcapint" in format_pcap.c.
     55 *
     56 * This format supports both reading and writing, regardless of the version
     57 * of your PCAP library.
     58 */
    4559
    4660#define DATA(x) ((struct pcapfile_format_data_t*)((x)->format_data))
     
    6074struct pcapfile_format_data_t {
    6175        struct {
     76                /* Indicates whether the event API should replicate the pauses
     77                 * between packets */
    6278                int real_time;
    6379        } options;
     80
     81        /* The PCAP meta-header that should be written at the start of each
     82         * trace */
    6483        pcapfile_header_t header;
     84        /* Indicates whether the input trace is started */
    6585        bool started;
    6686};
     
    114134}
    115135
     136
    116137static uint16_t swaps(libtrace_t *libtrace, uint16_t num)
    117138{
    118         /* to deal with open_dead traces that might try and use this
     139        /* To deal with open_dead traces that might try and use this
    119140         * if we don't have any per trace data, assume host byte order
    120141         */
    121142        if (!DATA(libtrace))
    122143                return num;
     144       
     145        /* We can use the PCAP magic number to determine the byte order */
    123146        if (DATA(libtrace)->header.magic_number == 0xd4c3b2a1)
    124147                return byteswap16(num);
     
    129152static uint32_t swapl(libtrace_t *libtrace, uint32_t num)
    130153{
    131         /* to deal with open_dead traces that might try and use this
     154        /* To deal with open_dead traces that might try and use this
    132155         * if we don't have any per trace data, assume host byte order
    133156         */
    134157        if (!DATA(libtrace))
    135158                return num;
     159       
     160        /* We can use the PCAP magic number to determine the byte order */
    136161        if (DATA(libtrace)->header.magic_number == 0xd4c3b2a1)
    137162                return byteswap32(num);
     
    162187                        return -1;
    163188               
    164                 if (swapl(libtrace,DATA(libtrace)->header.magic_number) != 0xa1b2c3d4) {
    165                         trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"Not a pcap tracefile\n");
     189                if (swapl(libtrace,DATA(libtrace)->header.magic_number) !=
     190                                        0xa1b2c3d4) {
     191                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
     192                                        "Not a pcap tracefile\n");
    166193                        return -1; /* Not a pcap file */
    167194                }
     
    169196                if (swaps(libtrace,DATA(libtrace)->header.version_major)!=2
    170197                        && swaps(libtrace,DATA(libtrace)->header.version_minor)!=4) {
    171                         trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"Unknown pcap tracefile version %d.%d\n",
     198                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
     199                                        "Unknown pcap tracefile version %d.%d\n",
    172200                                        swaps(libtrace,
    173201                                                DATA(libtrace)->header.version_major),
     
    184212static int pcapfile_start_output(libtrace_out_t *libtrace UNUSED)
    185213{
     214        /* We can't open the output file until we've seen the first packet.
     215         * This is because we need to know the DLT to set the "network"
     216         * value in the meta-header */
     217       
    186218        return 0;
    187219}
     
    199231                case TRACE_OPTION_PROMISC:
    200232                case TRACE_OPTION_FILTER:
    201                         /* all these are either unsupported or handled
     233                        /* All these are either unsupported or handled
    202234                         * by trace_config */
    203235                        break;
     
    401433        hdr.caplen = trace_get_capture_length(packet);
    402434        assert(hdr.caplen < LIBTRACE_PACKET_BUFSIZE);
    403         /* PCAP doesn't include the FCS, we do */
     435        /* PCAP doesn't include the FCS in its wire length value, but we do */
    404436        if (linktype==TRACE_TYPE_ETH)
    405437                if (trace_get_wire_length(packet) >= 4) {
     
    415447
    416448
     449        /* Write the packet header */
    417450        numbytes=wandio_wwrite(DATAOUT(out)->file,
    418451                        &hdr, sizeof(hdr));
     
    421454                return -1;
    422455
     456        /* Write the rest of the packet now */
    423457        ret=wandio_wwrite(DATAOUT(out)->file,
    424458                        ptr,
     
    434468                const libtrace_packet_t *packet)
    435469{
    436 #if 0
    437         return pcap_linktype_to_libtrace(
    438                         swapl(packet->trace,
    439                                 DATA(packet->trace)->header.network
    440                              )
    441                         );
    442 #endif
    443470        return pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type));
    444471}
     
    448475        libtrace_direction_t direction  = -1;
    449476        switch(pcapfile_get_link_type(packet)) {
     477                /* We can only get the direction for PCAP packets that have
     478                 * been encapsulated in Linux SLL or PFLOG */
    450479                case TRACE_TYPE_LINUX_SLL:
    451480                {
     
    561590        assert(packet);
    562591        if (size > trace_get_capture_length(packet)) {
    563                 /* can't make a packet larger */
     592                /* Can't make a packet larger */
    564593                return trace_get_capture_length(packet);
    565594        }
     
    575604        libtrace_eventobj_t event = {0,0,0.0,0};
    576605       
     606        /* If we are being told to replay packets as fast as possible, then
     607         * we just need to read and return the next packet in the trace */
     608
    577609        if (IN_OPTIONS.real_time) {
    578610                event.size = pcapfile_read_packet(libtrace, packet);
Note: See TracChangeset for help on using the changeset viewer.