source: lib/format_pcap.c @ 4dedc28

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

isplit input formats out

  • Property mode set to 100644
File size: 6.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 "format.h"
35#include <inttypes.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <unistd.h>
39#include <assert.h>
40
41
42#if HAVE_PCAP_BPF_H
43#  include <pcap-bpf.h>
44#else
45#  ifdef HAVE_NET_BPF_H
46#    include <net/bpf.h>
47#  endif
48#endif
49
50#if HAVE_PCAP_H
51#  include <pcap.h>
52#  ifdef HAVE_PCAP_INT_H
53#    include <pcap-int.h>
54#  endif
55#endif
56
57static int pcap_init_input(struct libtrace_t *libtrace) {
58        char errbuf[PCAP_ERRBUF_SIZE];
59        struct stat buf;
60        if (!strncmp(libtrace->conn_info.path,"-",1)) {
61                if ((libtrace->input.pcap = 
62                        pcap_open_offline(libtrace->conn_info.path,
63                                                errbuf)) == NULL) {
64                        fprintf(stderr,"%s\n",errbuf);
65                        return 0;
66                }               
67        } else {
68                if (stat(libtrace->conn_info.path,&buf) == -1) {
69                        perror("stat");
70                        return 0;
71                }
72                if (S_ISCHR(buf.st_mode)) {
73                        if ((libtrace->input.pcap = 
74                                pcap_open_live(libtrace->conn_info.path,
75                                        4096,
76                                        1,
77                                        1,
78                                        errbuf)) == NULL) {
79                                fprintf(stderr,"%s\n",errbuf);
80                                return 0;
81                        }
82                } else { 
83                        if ((libtrace->input.pcap = 
84                                pcap_open_offline(libtrace->conn_info.path,
85                                        errbuf)) == NULL) {
86                                fprintf(stderr,"%s\n",errbuf);
87                                return 0;
88                        }
89                }       
90        }
91        fprintf(stderr,
92                        "Unsupported scheme (%s) for format pcap\n",
93                        libtrace->conn_info.path);
94        return 0;
95       
96}
97
98static int pcapint_init_input(struct libtrace_t *libtrace) {
99        char errbuf[PCAP_ERRBUF_SIZE];
100        if ((libtrace->input.pcap = 
101                        pcap_open_live(libtrace->conn_info.path,
102                        4096,
103                        1,
104                        1,
105                        errbuf)) == NULL) {
106                fprintf(stderr,"%s\n",errbuf);
107                return 0;
108        }
109
110}
111
112static int pcap_fin_input(struct libtrace_t *libtrace) {
113        return -1;
114}
115
116static void trace_pcap_handler(u_char *user, const struct pcap_pkthdr *pcaphdr, const u_char *pcappkt) {
117        struct libtrace_packet_t *packet = (struct libtrace_packet_t *)user;   
118        void *buffer = packet->buffer;
119        int numbytes = 0;
120       
121        memcpy(buffer,pcaphdr,sizeof(struct pcap_pkthdr));
122        numbytes = pcaphdr->len;
123        memcpy(buffer + sizeof(struct pcap_pkthdr),pcappkt,numbytes);
124
125        packet->size = numbytes + sizeof(struct pcap_pkthdr);
126
127}
128static int pcap_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
129        const u_char *pcappkt;
130        int pcapbytes = 0;
131
132        while ((pcapbytes = pcap_dispatch(libtrace->input.pcap,
133                                        1, /* number of packets */
134                                        &trace_pcap_handler,
135                                        (u_char *)packet)) == 0);
136
137        if (pcapbytes < 0) {
138                return -1;
139        }
140        return (packet->size - sizeof(struct pcap_pkthdr));
141}
142
143static void *pcap_get_link(const struct libtrace_packet_t *packet) {
144        return (void *) (packet->buffer + sizeof(struct pcap_pkthdr));
145}
146
147static libtrace_linktype_t pcap_get_link_type(const struct libtrace_packet_t *packet) {
148        struct pcap_pkthdr *pcapptr = 0;
149        int linktype = 0;
150        pcapptr = (struct pcap_pkthdr *)packet->buffer;
151        linktype = pcap_datalink(packet->trace->input.pcap);
152        switch(linktype) {
153                case DLT_NULL:
154                        return TRACE_TYPE_NONE;
155                case DLT_EN10MB:
156                        return TRACE_TYPE_ETH;
157                case DLT_ATM_RFC1483:
158                        return TRACE_TYPE_ATM;
159                case DLT_IEEE802_11:
160                        return TRACE_TYPE_80211;
161#ifdef DLT_LINUX_SLL
162                case DLT_LINUX_SLL:
163                        return TRACE_TYPE_LINUX_SLL;
164#endif
165#ifdef DLT_PFLOG
166                case DLT_PFLOG:
167                        return TRACE_TYPE_PFLOG;
168#endif
169        }
170        return -1;
171}
172
173static int8_t pcap_get_direction(const struct libtrace_packet_t *packet) {
174        int8_t direction  = -1;
175        switch(pcap_get_link_type(packet)) {
176                case TRACE_TYPE_LINUX_SLL:
177                {
178                        struct trace_sll_header_t *sll;
179                        sll = trace_get_link(packet);
180                        if (!sll) {
181                                return -1;
182                        }
183                        /* 0 == LINUX_SLL_HOST */
184                        /* the Waikato Capture point defines "packets
185                         * originating locally" (ie, outbound), with a
186                         * direction of 0, and "packets destined locally"
187                         * (ie, inbound), with a direction of 1.
188                         * This is kind-of-opposite to LINUX_SLL.
189                         * We return consistent values here, however
190                         *
191                         * Note that in recent versions of pcap, you can
192                         * use "inbound" and "outbound" on ppp in linux
193                         */
194                        if (ntohs(sll->pkttype == 0)) {
195                                direction = 1;
196                        } else {
197                                direction = 0;
198                        }
199                        break;
200
201                }
202                case TRACE_TYPE_PFLOG:
203                {
204                        struct trace_pflog_header_t *pflog;
205                        pflog = trace_get_link(packet);
206                        if (!pflog) {
207                                return -1;
208                        }
209                        /* enum    { PF_IN=0, PF_OUT=1 }; */
210                        if (ntohs(pflog->dir==0)) {
211
212                                direction = 1;
213                        }
214                        else {
215                                direction = 0;
216                        }
217                        break;
218                }
219                default:
220                        break;
221        }       
222        return direction;
223}
224
225
226static struct timeval pcap_get_timeval(const struct libtrace_packet_t *packet) { 
227        struct pcap_pkthdr *pcapptr = (struct pcap_pkthdr *)packet->buffer;
228        return pcapptr->ts;
229}
230
231
232static int pcap_get_capture_length(const struct libtrace_packet_t *packet) {
233        struct pcap_pkthdr *pcapptr = 0;
234        pcapptr = (struct pcap_pkthdr *)packet->buffer;
235        return pcapptr->caplen;
236}
237
238static int pcap_get_wire_length(const struct libtrace_packet_t *packet) {
239        struct pcap_pkthdr *pcapptr = 0;
240        pcapptr = (struct pcap_pkthdr *)packet->buffer;
241        return ntohs(pcapptr->len);
242}
243
244static size_t pcap_truncate_packet(struct libtrace_packet_t *packet,size_t size) {
245        struct pcap_pkthdr *pcapptr = 0;
246        assert(packet);
247        if (size > packet->size) {
248                // can't make a packet larger
249                return packet->size;
250        }
251        pcapptr = (struct pcap_pkthdr *)packet->buffer;
252        pcapptr->caplen = size + sizeof(struct pcap_pkthdr);
253        packet->size = pcapptr->caplen;
254        return packet->size;
255}
256
257static struct format_t pcap = {
258        "pcap",
259        "$Id$",
260        pcap_init_input,
261        NULL,
262        pcap_fin_input,
263        NULL,
264        pcap_read_packet,
265        NULL,
266        pcap_get_link,
267        pcap_get_link_type,
268        pcap_get_direction,
269        NULL,
270        NULL,
271        pcap_get_timeval,
272        NULL,
273        pcap_get_capture_length,
274        pcap_get_wire_length,
275        pcap_truncate_packet
276};
277
278static struct format_t pcapint = {
279        "pcapint",
280        "$Id$",
281        pcapint_init_input,
282        NULL,
283        pcap_fin_input,
284        NULL,
285        pcap_read_packet,
286        NULL,
287        pcap_get_link,
288        pcap_get_link_type,
289        pcap_get_direction,
290        NULL,
291        NULL,
292        pcap_get_timeval,
293        NULL,
294        pcap_get_capture_length,
295        pcap_get_wire_length,
296        pcap_truncate_packet
297};
298
299void __attribute__((constructor)) pcap_constructor() {
300        register_format(&pcap);
301        register_format(&pcapint);
302}
Note: See TracBrowser for help on using the repository browser.