source: lib/format_pcapfile.c @ 747c501

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

Fix support for writing on interfaces

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