source: lib/format_pcap.c @ 3073c04

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

code tidyups in format_erf.c
writer functionality for format_pcap and format_wag

  • Property mode set to 100644
File size: 11.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#include "common.h"
32#include "config.h"
33#include "libtrace.h"
34#include "libtrace_int.h"
35#include "format_helper.h"
36
37#ifdef HAVE_INTTYPES_H
38#  include <inttypes.h>
39#else
40#  error "Can't find inttypes.h - this needs to be fixed"
41#endif
42
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <unistd.h>
46#include <assert.h>
47
48
49#if HAVE_PCAP_BPF_H
50#  include <pcap-bpf.h>
51#else
52#  ifdef HAVE_NET_BPF_H
53#    include <net/bpf.h>
54#  endif
55#endif
56
57#if HAVE_PCAP_H
58#  include <pcap.h>
59#  ifdef HAVE_PCAP_INT_H
60#    include <pcap-int.h>
61#  endif
62#endif
63
64#if HAVE_PCAP
65
66static struct libtrace_format_t *pcap_ptr = 0;
67static struct libtrace_format_t *pcapint_ptr = 0;
68
69#define CONNINFO libtrace->format_data->conn_info
70#define INPUT libtrace->format_data->input
71#define OUTPUT libtrace->format_data->output
72struct libtrace_format_data_t {
73        union {
74                char *path;             /**< information for local sockets */
75                char *interface;        /**< intormation for reading of network
76                                             interfaces */
77        } conn_info;
78        /** Information about the current state of the input device */
79        union {
80                pcap_t *pcap;
81        } input;
82};
83
84struct libtrace_format_data_out_t {
85        union {
86                char *path;
87                char *interface;
88        } conn_info;
89        struct {
90                pcap_t *pcap;
91                pcap_dumper_t *dump;
92        } output;
93};
94
95static int linktype_to_dlt(libtrace_linktype_t t) {
96        static int table[] = {
97                -1, /* LEGACY */
98                -1, /* HDLC over POS */
99                DLT_EN10MB, /* Ethernet */
100                -1, /* ATM */
101                DLT_IEEE802_11, /* 802.11 */
102                -1 /* END OF TABLE */
103        };
104        if (t>sizeof(table)/sizeof(*table)) {
105                return -1;
106        }
107        return table[t];
108}
109
110static int pcap_init_input(struct libtrace_t *libtrace) {
111        char errbuf[PCAP_ERRBUF_SIZE];
112        struct stat buf;
113        libtrace->format_data = (struct libtrace_format_data_t *) 
114                malloc(sizeof(struct libtrace_format_data_t));
115        CONNINFO.path = libtrace->uridata;
116
117        libtrace->sourcetype = TRACE;
118        if (!strncmp(CONNINFO.path,"-",1)) {
119                if ((INPUT.pcap = 
120                        pcap_open_offline(CONNINFO.path,
121                                                errbuf)) == NULL) {
122                        fprintf(stderr,"%s\n",errbuf);
123                        return 0;
124                }               
125        } else {
126                if (stat(CONNINFO.path,&buf) == -1) {
127                        perror("stat");
128                        return 0;
129                }
130                if (S_ISCHR(buf.st_mode)) {
131                        if ((INPUT.pcap = 
132                                pcap_open_live(CONNINFO.path,
133                                        4096,
134                                        1,
135                                        1,
136                                        errbuf)) == NULL) {
137                                fprintf(stderr,"%s\n",errbuf);
138                                return 0;
139                        }
140                } else { 
141                        if ((INPUT.pcap = 
142                                pcap_open_offline(CONNINFO.path,
143                                        errbuf)) == NULL) {
144                                fprintf(stderr,"%s\n",errbuf);
145                                return 0;
146                        }
147                }       
148        }
149        //fprintf(stderr,       "Unsupported scheme (%s) for format pcap\n",
150        //              CONNINFO.path);
151        return 1;
152       
153}
154
155static int pcap_init_output(struct libtrace_out_t *libtrace) {
156        char errbuf[PCAP_ERRBUF_SIZE];
157        struct stat buf;
158        libtrace->format_data = (struct libtrace_format_data_out_t *)
159                malloc(sizeof(struct libtrace_format_data_out_t));
160        CONNINFO.path = libtrace->uridata;
161        OUTPUT.pcap = NULL;
162        OUTPUT.dump = NULL;
163}
164
165static int pcapint_init_input(struct libtrace_t *libtrace) {
166        char errbuf[PCAP_ERRBUF_SIZE];
167        libtrace->format_data = (struct libtrace_format_data_t *) 
168                malloc(sizeof(struct libtrace_format_data_t));
169        CONNINFO.path = libtrace->uridata;
170        libtrace->sourcetype = INTERFACE;
171        if ((INPUT.pcap = 
172                        pcap_open_live(CONNINFO.path,
173                        4096,
174                        1,
175                        1,
176                        errbuf)) == NULL) {
177                fprintf(stderr,"%s\n",errbuf);
178                return 0;
179        }
180        return 1;
181}
182
183static int pcap_fin_input(struct libtrace_t *libtrace) {
184        pcap_close(INPUT.pcap);
185        free(libtrace->format_data);
186        return 0;
187}
188
189static int pcap_fin_output(struct libtrace_out_t *libtrace) {
190        pcap_dump_flush(OUTPUT.dump);
191        pcap_dump_close(OUTPUT.dump);
192        return 0;
193}
194
195static void trace_pcap_handler(u_char *user, const struct pcap_pkthdr *pcaphdr, const u_char *pcappkt) {
196        struct libtrace_packet_t *packet = (struct libtrace_packet_t *)user;   
197        void *buffer = packet->buffer;
198        int numbytes = 0;
199       
200        memcpy(buffer,pcaphdr,sizeof(struct pcap_pkthdr));
201        numbytes = pcaphdr->len;
202        memcpy(buffer + sizeof(struct pcap_pkthdr),pcappkt,numbytes);
203
204        packet->size = numbytes + sizeof(struct pcap_pkthdr);
205}
206
207static int pcap_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
208        const u_char *pcappkt;
209        int pcapbytes = 0;
210
211        pcapbytes = pcap_dispatch(INPUT.pcap,
212                                        1, /* number of packets */
213                                        &trace_pcap_handler,
214                                        (u_char *)packet);
215
216        if (pcapbytes <= 0) {
217                return pcapbytes;
218        }
219        return (packet->size - sizeof(struct pcap_pkthdr));
220}
221
222static int pcap_write_packet(struct libtrace_out_t *libtrace, struct libtrace_packet_t *packet) {
223        struct pcap_pkthdr pcap_pkt_hdr;
224        void *link = trace_get_link(packet);
225
226        if (!OUTPUT.pcap) {
227                OUTPUT.pcap = pcap_open_dead(
228                                linktype_to_dlt(trace_get_link_type(packet)),
229                                65536);
230                OUTPUT.dump = pcap_dump_open(OUTPUT.pcap,CONNINFO.path);
231                fflush((FILE *)OUTPUT.dump);
232        }
233        if (packet->trace->format == pcap_ptr || 
234                        packet->trace->format == pcapint_ptr) {
235        //if (!strncasecmp(packet->trace->format->name,"pcap",4)) {
236                // this is a pcap trace anyway
237               
238                pcap_dump((u_char*)OUTPUT.dump,(struct pcap_pkthdr *)packet->buffer,link);
239        } else {
240                pcap_pkt_hdr.ts = trace_get_timeval(packet);
241                pcap_pkt_hdr.caplen = trace_get_capture_length(packet);
242                pcap_pkt_hdr.len = trace_get_wire_length(packet);
243
244                pcap_dump((u_char*)OUTPUT.pcap, &pcap_pkt_hdr, link);
245        }
246        return 0;
247}
248
249static void *pcap_get_link(const struct libtrace_packet_t *packet) {
250        return (void *) (packet->buffer + sizeof(struct pcap_pkthdr));
251}
252
253static libtrace_linktype_t pcap_get_link_type(const struct libtrace_packet_t *packet) {
254        struct pcap_pkthdr *pcapptr = 0;
255        int linktype = 0;
256        pcapptr = (struct pcap_pkthdr *)packet->buffer;
257        linktype = pcap_datalink(packet->trace->format_data->input.pcap);
258        switch(linktype) {
259                case DLT_NULL:
260                        return TRACE_TYPE_NONE;
261                case DLT_EN10MB:
262                        return TRACE_TYPE_ETH;
263                case DLT_ATM_RFC1483:
264                        return TRACE_TYPE_ATM;
265                case DLT_IEEE802_11:
266                        return TRACE_TYPE_80211;
267#ifdef DLT_LINUX_SLL
268                case DLT_LINUX_SLL:
269                        return TRACE_TYPE_LINUX_SLL;
270#endif
271#ifdef DLT_PFLOG
272                case DLT_PFLOG:
273                        return TRACE_TYPE_PFLOG;
274#endif
275        }
276        return -1;
277}
278
279static int8_t pcap_get_direction(const struct libtrace_packet_t *packet) {
280        int8_t direction  = -1;
281        switch(pcap_get_link_type(packet)) {
282                case TRACE_TYPE_LINUX_SLL:
283                {
284                        struct trace_sll_header_t *sll;
285                        sll = trace_get_link(packet);
286                        if (!sll) {
287                                return -1;
288                        }
289                        /* 0 == LINUX_SLL_HOST */
290                        /* the Waikato Capture point defines "packets
291                         * originating locally" (ie, outbound), with a
292                         * direction of 0, and "packets destined locally"
293                         * (ie, inbound), with a direction of 1.
294                         * This is kind-of-opposite to LINUX_SLL.
295                         * We return consistent values here, however
296                         *
297                         * Note that in recent versions of pcap, you can
298                         * use "inbound" and "outbound" on ppp in linux
299                         */
300                        if (ntohs(sll->pkttype == 0)) {
301                                direction = 1;
302                        } else {
303                                direction = 0;
304                        }
305                        break;
306
307                }
308                case TRACE_TYPE_PFLOG:
309                {
310                        struct trace_pflog_header_t *pflog;
311                        pflog = trace_get_link(packet);
312                        if (!pflog) {
313                                return -1;
314                        }
315                        /* enum    { PF_IN=0, PF_OUT=1 }; */
316                        if (ntohs(pflog->dir==0)) {
317
318                                direction = 1;
319                        }
320                        else {
321                                direction = 0;
322                        }
323                        break;
324                }
325                default:
326                        break;
327        }       
328        return direction;
329}
330
331
332static struct timeval pcap_get_timeval(const struct libtrace_packet_t *packet) { 
333        struct pcap_pkthdr *pcapptr = (struct pcap_pkthdr *)packet->buffer;
334        return pcapptr->ts;
335}
336
337
338static int pcap_get_capture_length(const struct libtrace_packet_t *packet) {
339        struct pcap_pkthdr *pcapptr = 0;
340        pcapptr = (struct pcap_pkthdr *)packet->buffer;
341        return pcapptr->caplen;
342}
343
344static int pcap_get_wire_length(const struct libtrace_packet_t *packet) {
345        struct pcap_pkthdr *pcapptr = 0;
346        pcapptr = (struct pcap_pkthdr *)packet->buffer;
347        return ntohs(pcapptr->len);
348}
349
350static size_t pcap_set_capture_length(struct libtrace_packet_t *packet,size_t size) {
351        struct pcap_pkthdr *pcapptr = 0;
352        assert(packet);
353        if (size > packet->size) {
354                // can't make a packet larger
355                return packet->size;
356        }
357        pcapptr = (struct pcap_pkthdr *)packet->buffer;
358        pcapptr->caplen = size + sizeof(struct pcap_pkthdr);
359        packet->size = pcapptr->caplen;
360        return packet->size;
361}
362
363static int pcap_get_fd(struct libtrace_packet_t *packet) {
364        return pcap_fileno(packet->trace->format_data->input.pcap);
365}
366
367static void pcap_help() {
368        printf("pcap format module: $Revision$\n");
369        printf("Supported input URIs:\n");
370        printf("\tpcap:/path/to/file\n");
371        printf("\n");
372        printf("\te.g.: pcap:/tmp/trace.pcap\n");
373        printf("\n");
374        printf("Supported output URIs:\n");
375        printf("\tnone\n");
376        printf("\n");
377}
378
379static void pcapint_help() {
380        printf("pcapint format module: $Revision$\n");
381        printf("Supported input URIs:\n");
382        printf("\tpcapint:interface\n");
383        printf("\n");
384        printf("\te.g.: pcapint:eth0\n");
385        printf("\n");
386        printf("Supported output URIs:\n");
387        printf("\tnone\n");
388        printf("\n");
389}
390
391
392static struct libtrace_format_t pcap = {
393        "pcap",
394        "$Id$",
395        pcap_init_input,                /* init_input */
396        pcap_init_output,               /* init_output */
397        NULL,                           /* config_output */
398        pcap_fin_input,                 /* fin_input */
399        pcap_fin_output,                /* fin_output */
400        pcap_read_packet,               /* read_packet */
401        pcap_write_packet,              /* write_packet */
402        pcap_get_link,                  /* get_link */
403        pcap_get_link_type,             /* get_link_type */
404        pcap_get_direction,             /* get_direction */
405        NULL,                           /* set_direction */
406        NULL,                           /* get_erf_timestamp */
407        pcap_get_timeval,               /* get_timeval */
408        NULL,                           /* get_seconds */
409        pcap_get_capture_length,        /* get_capture_length */
410        pcap_get_wire_length,           /* get_wire_length */
411        pcap_set_capture_length,        /* set_capture_length */
412        NULL,                           /* get_fd */
413        trace_event_trace,              /* trace_event */
414        pcap_help                       /* help */
415};
416
417static struct libtrace_format_t pcapint = {
418        "pcapint",
419        "$Id$",
420        pcapint_init_input,             /* init_input */
421        NULL,                           /* init_output */
422        NULL,                           /* config_output */
423        pcap_fin_input,                 /* fin_input */
424        NULL,                           /* fin_output */
425        pcap_read_packet,               /* read_packet */
426        NULL,                           /* write_packet */
427        pcap_get_link,                  /* get_link */
428        pcap_get_link_type,             /* get_link_type */
429        pcap_get_direction,             /* get_direction */
430        NULL,                           /* set_direction */
431        NULL,                           /* get_erf_timestamp */
432        pcap_get_timeval,               /* get_timeval */
433        NULL,                           /* get_seconds */
434        pcap_get_capture_length,        /* get_capture_length */
435        pcap_get_wire_length,           /* get_wire_length */
436        pcap_set_capture_length,        /* set_capture_length */
437        pcap_get_fd,                    /* get_fd */
438        trace_event_device,             /* trace_event */
439        pcapint_help                    /* help */
440};
441
442//pcap_ptr = &pcap;
443//pcapint_ptr = &pcapint;
444
445void __attribute__((constructor)) pcap_constructor() {
446        pcap_ptr = &pcap;
447        pcapint_ptr = &pcapint;
448        register_format(pcap_ptr);
449        register_format(pcapint_ptr);
450}
451
452
453#endif
Note: See TracBrowser for help on using the repository browser.