source: lib/format_pcapfile.c @ 5d233a5

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

Convert pcapfile over to using byteswap{16,32}.
Fix typos in previous commit

  • Property mode set to 100644
File size: 9.9 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#include "common.h"
32#include "config.h"
33#include "libtrace.h"
34#include "libtrace_int.h"
35#include "format_helper.h"
36
37#include <sys/stat.h>
38#include <assert.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <errno.h>
43
44#define DATA(x) ((struct pcapfile_format_data_t*)((x)->format_data))
45
46typedef struct pcapfile_header_t {
47                uint32_t magic_number;   /* magic number */
48                uint16_t version_major;  /* major version number */
49                uint16_t version_minor;  /* minor version number */
50                int32_t  thiszone;       /* GMT to local correction */
51                uint32_t sigfigs;        /* timestamp accuracy */
52                uint32_t snaplen;        /* aka "wirelen" */
53                uint32_t network;        /* data link type */
54} pcapfile_header_t; 
55
56struct pcapfile_format_data_t {
57        libtrace_io_t *file;
58        pcapfile_header_t header;
59};
60
61struct pcapfile_format_data_out_t {
62        libtrace_io_t *file;
63
64};
65
66static int pcapfile_init_input(libtrace_t *libtrace) {
67        libtrace->format_data = malloc(sizeof(struct pcapfile_format_data_t));
68
69        DATA(libtrace)->file=NULL;
70
71        return 0;
72}
73
74static uint16_t swaps(libtrace_t *libtrace, uint16_t num)
75{
76        /* to deal with open_dead traces that might try and use this
77         * if we don't have any per trace data, assume host byte order
78         */
79        if (!DATA(libtrace))
80                return num;
81        if (DATA(libtrace)->header.magic_number == 0xd4c3b2a1)
82                return byteswap16(num);
83
84        return num;
85}
86
87static uint32_t swapl(libtrace_t *libtrace, uint32_t num)
88{
89        /* to deal with open_dead traces that might try and use this
90         * if we don't have any per trace data, assume host byte order
91         */
92        if (!DATA(libtrace))
93                return num;
94        if (DATA(libtrace)->header.magic_number == 0xd4c3b2a1)
95                return byteswap32(num);
96
97        return num;
98}
99
100
101static int pcapfile_start_input(libtrace_t *libtrace) 
102{
103        int err;
104
105        if (!DATA(libtrace)->file) {
106                DATA(libtrace)->file=trace_open_file(libtrace);
107
108                if (!DATA(libtrace)->file)
109                        return -1;
110
111                err=libtrace_io_read(DATA(libtrace)->file,
112                                &DATA(libtrace)->header,
113                                sizeof(DATA(libtrace)->header));
114
115                if (err<1)
116                        return -1;
117               
118                if (swapl(libtrace,DATA(libtrace)->header.magic_number) != 0xa1b2c3d4) {
119                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"Not a pcap tracefile\n");
120                        return -1; /* Not a pcap file */
121                }
122
123                if (swaps(libtrace,DATA(libtrace)->header.version_major)!=2
124                        && swaps(libtrace,DATA(libtrace)->header.version_minor)!=4) {
125                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"Unknown pcap tracefile version %d.%d\n",
126                                        swaps(libtrace,
127                                                DATA(libtrace)->header.version_major),
128                                        swaps(libtrace,
129                                                DATA(libtrace)->header.version_minor));
130                        return -1;
131                }
132
133        }
134
135        return 0;
136}
137
138static int pcapfile_config_input(libtrace_t *libtrace,
139                trace_option_t option,
140                void *data)
141{
142        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
143                        "Unknown option %i", option);
144        return -1;
145}
146
147static int pcapfile_fin_input(libtrace_t *libtrace) 
148{
149        libtrace_io_close(DATA(libtrace)->file);
150        free(libtrace->format_data);
151        return 0; /* success */
152}
153
154static int pcapfile_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
155{
156        int err;
157
158        assert(libtrace->format_data);
159
160        packet->type = pcap_dlt_to_rt(swapl(libtrace,
161                                DATA(libtrace)->header.network));
162
163        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
164                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
165                packet->buf_control = TRACE_CTRL_PACKET;
166        }
167
168        err=libtrace_io_read(DATA(libtrace)->file,
169                        packet->buffer,
170                        sizeof(libtrace_pcapfile_pkt_hdr_t));
171
172        if (err<0) {
173                trace_set_err(libtrace,errno,"reading packet");
174                return -1;
175        }
176        if (err==0) {
177                /* EOF */
178                return 0;
179        }
180
181        packet->header = packet->buffer;
182
183
184        err=libtrace_io_read(DATA(libtrace)->file,
185                        (char*)packet->buffer+sizeof(libtrace_pcapfile_pkt_hdr_t),
186                        swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen)
187                        );
188
189       
190        if (err<0) {
191                trace_set_err(libtrace,errno,"reading packet");
192                return -1;
193        }
194        if (err==0) {
195                return 0;
196        }
197
198        packet->payload = (char*)packet->buffer
199                + sizeof(libtrace_pcapfile_pkt_hdr_t);
200       
201        return sizeof(libtrace_pcapfile_pkt_hdr_t)
202                +swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen);
203}
204
205#if 0
206static void pcapfile_write_packet(libtrace_out_t *out,
207                const libtrace_packet_t *packet)
208{
209        struct pcapfile_pkt_hdr_t hdr;
210
211        tv = trace_get_timeval(packet);
212        hdr.ts_sec = tv.tv_sec;
213        hdr.ts_usec = tv.tv_usec;
214        hdr.caplen = trace_get_capture_length(packet);
215        hdr.wirelen = trace_get_wire_length(packet);
216
217        write(fd,&hdr,sizeof(hdr));
218        write(fd,packet->payload,hdr.caplen);
219       
220}
221#endif
222
223
224static libtrace_linktype_t pcapfile_get_link_type(
225                const libtrace_packet_t *packet) 
226{
227#if 0
228        return pcap_dlt_to_libtrace(
229                        swapl(packet->trace,
230                                DATA(packet->trace)->header.network
231                             )
232                        );
233#endif
234        return pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type));
235}
236
237static libtrace_direction_t pcapfile_get_direction(const libtrace_packet_t *packet) 
238{
239        libtrace_direction_t direction  = -1;
240        switch(pcapfile_get_link_type(packet)) {
241                case TRACE_TYPE_LINUX_SLL:
242                {
243                        libtrace_sll_header_t *sll;
244                        sll = trace_get_link(packet);
245                        if (!sll) {
246                                trace_set_err(packet->trace,
247                                        TRACE_ERR_BAD_PACKET,
248                                                "Bad or missing packet");
249                                return -1;
250                        }
251                        /* 0 == LINUX_SLL_HOST */
252                        /* the Waikato Capture point defines "packets
253                         * originating locally" (ie, outbound), with a
254                         * direction of 0, and "packets destined locally"
255                         * (ie, inbound), with a direction of 1.
256                         * This is kind-of-opposite to LINUX_SLL.
257                         * We return consistent values here, however
258                         *
259                         * Note that in recent versions of pcap, you can
260                         * use "inbound" and "outbound" on ppp in linux
261                         */
262                        if (ntohs(sll->pkttype == 0)) {
263                                direction = TRACE_DIR_INCOMING;
264                        } else {
265                                direction = TRACE_DIR_OUTGOING;
266                        }
267                        break;
268
269                }
270                case TRACE_TYPE_PFLOG:
271                {
272                        libtrace_pflog_header_t *pflog;
273                        pflog = trace_get_link(packet);
274                        if (!pflog) {
275                                trace_set_err(packet->trace,
276                                                TRACE_ERR_BAD_PACKET,
277                                                "Bad or missing packet");
278                                return -1;
279                        }
280                        /* enum    { PF_IN=0, PF_OUT=1 }; */
281                        if (ntohs(pflog->dir==0)) {
282
283                                direction = TRACE_DIR_INCOMING;
284                        }
285                        else {
286                                direction = TRACE_DIR_OUTGOING;
287                        }
288                        break;
289                }
290                default:
291                        break;
292        }       
293        return direction;
294}
295
296
297static struct timeval pcapfile_get_timeval(
298                const libtrace_packet_t *packet) 
299{
300        libtrace_pcapfile_pkt_hdr_t *hdr =
301                (libtrace_pcapfile_pkt_hdr_t*)packet->header;
302        struct timeval ts;
303        ts.tv_sec = swapl(packet->trace,hdr->ts_sec);
304        ts.tv_usec = swapl(packet->trace,hdr->ts_usec);
305        return ts;
306}
307
308
309static int pcapfile_get_capture_length(const libtrace_packet_t *packet) {
310        libtrace_pcapfile_pkt_hdr_t *pcapptr
311                = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
312
313        return swapl(packet->trace,pcapptr->caplen);
314}
315
316static int pcapfile_get_wire_length(const libtrace_packet_t *packet) {
317        libtrace_pcapfile_pkt_hdr_t *pcapptr
318                = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
319        if (packet->type==pcap_dlt_to_rt(TRACE_DLT_EN10MB))
320                /* Include the missing FCS */
321                return swapl(packet->trace,pcapptr->wirelen)+4; 
322        else
323                return swapl(packet->trace,pcapptr->wirelen);
324}
325
326static int pcapfile_get_framing_length(const libtrace_packet_t *packet UNUSED) {
327        return sizeof(libtrace_pcapfile_pkt_hdr_t);
328}
329
330static size_t pcapfile_set_capture_length(libtrace_packet_t *packet,size_t size) {
331        libtrace_pcapfile_pkt_hdr_t *pcapptr = 0;
332        assert(packet);
333        if (size > trace_get_capture_length(packet)) {
334                /* can't make a packet larger */
335                return trace_get_capture_length(packet);
336        }
337        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
338        pcapptr->caplen = swapl(packet->trace,size);
339        return trace_get_capture_length(packet);
340}
341
342static void pcapfile_help() {
343        printf("pcapfile format module: $Revision$\n");
344        printf("Supported input URIs:\n");
345        printf("\tpcapfile:/path/to/file\n");
346        printf("\tpcapfile:/path/to/file.gz\n");
347        printf("\n");
348        printf("\te.g.: pcapfile:/tmp/trace.pcap\n");
349        printf("\n");
350}
351
352static struct libtrace_format_t pcapfile = {
353        "pcapfile",
354        "$Id$",
355        TRACE_FORMAT_PCAPFILE,
356        pcapfile_init_input,            /* init_input */
357        pcapfile_config_input,          /* config_input */
358        pcapfile_start_input,           /* start_input */
359        NULL,                           /* pause_input */
360        NULL,                   /* init_output */
361        NULL,                           /* config_output */
362        NULL,                           /* start_output */
363        pcapfile_fin_input,             /* fin_input */
364        NULL,                           /* fin_output */
365        pcapfile_read_packet,           /* read_packet */
366        NULL,                           /* fin_packet */
367        NULL,                           /* write_packet */
368        pcapfile_get_link_type,         /* get_link_type */
369        pcapfile_get_direction,         /* get_direction */
370        NULL,                           /* set_direction */
371        NULL,                           /* get_erf_timestamp */
372        pcapfile_get_timeval,           /* get_timeval */
373        NULL,                           /* get_seconds */
374        NULL,                           /* seek_erf */
375        NULL,                           /* seek_timeval */
376        NULL,                           /* seek_seconds */
377        pcapfile_get_capture_length,    /* get_capture_length */
378        pcapfile_get_wire_length,       /* get_wire_length */
379        pcapfile_get_framing_length,    /* get_framing_length */
380        pcapfile_set_capture_length,    /* set_capture_length */
381        NULL,                           /* get_fd */
382        trace_event_trace,              /* trace_event */
383        pcapfile_help,                  /* help */
384        NULL                            /* next pointer */
385};
386
387
388void pcapfile_constructor() {
389        register_format(&pcapfile);
390}
391
392
Note: See TracBrowser for help on using the repository browser.