source: lib/format_pcap.c @ a6c77b0

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since a6c77b0 was a6c77b0, checked in by Richard Sanger <rsangerarj@…>, 7 years ago

Stop the pcap format appearing to accept setting directions which it doesn't support instead return an error.
This also removes the overhead of promoting the packet to include an additional header with this data in this case.
Note pcap supports IN/OUT just not OTHER and UNKNOWN.

  • Property mode set to 100644
File size: 23.2 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34#include "common.h"
35#include "config.h"
36#include "libtrace.h"
37#include "libtrace_int.h"
38#include "format_helper.h"
39
40#include <sys/stat.h>
41#include <assert.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <errno.h>
46
47#ifdef HAVE_PCAP_H
48#  include <pcap.h>
49#  ifdef HAVE_PCAP_INT_H
50#    include <pcap-int.h>
51#  endif
52#endif
53
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
72#ifdef HAVE_LIBPCAP
73static struct libtrace_format_t pcap;
74static struct libtrace_format_t pcapint;
75
76#define DATA(x) ((struct pcap_format_data_t*)((x)->format_data))
77#define DATAOUT(x) ((struct pcap_format_data_out_t*)((x)->format_data))
78
79#define INPUT DATA(libtrace)->input
80#define OUTPUT DATAOUT(libtrace)->output
81struct pcap_format_data_t {
82        /** Information about the current state of the input trace */
83        union {
84                /* The PCAP input source */
85                pcap_t *pcap;
86        } input;
87        /* A filter to be applied to all packets read from the source */
88        libtrace_filter_t *filter;
89        /* The snap length to be applied to all captured packets (live only) */
90        int snaplen;
91        /* Whether the capture interface should be set to promiscuous mode
92         * (live only) */
93        int promisc;
94};
95
96struct pcap_format_data_out_t {
97        /* Information about the current state of the output trace */
98        union {
99                struct {
100                        /* The PCAP output device or trace */
101                        pcap_t *pcap;   
102                        /* The PCAP dumper */
103                        pcap_dumper_t *dump;
104                } trace;
105
106        } output;
107};
108
109static int pcap_init_input(libtrace_t *libtrace) {
110        libtrace->format_data = malloc(sizeof(struct pcap_format_data_t));
111
112        INPUT.pcap = NULL;
113        DATA(libtrace)->filter = NULL;
114        DATA(libtrace)->snaplen = LIBTRACE_PACKET_BUFSIZE;
115        DATA(libtrace)->promisc = 0;
116
117        return 0;
118}
119
120static int pcap_start_input(libtrace_t *libtrace) {
121        char errbuf[PCAP_ERRBUF_SIZE];
122
123
124        /* Check if the file is already open */
125        if (INPUT.pcap)
126                return 0; /* success */
127
128        /* Open the trace file for reading */
129        if ((INPUT.pcap = 
130                pcap_open_offline(libtrace->uridata,
131                        errbuf)) == NULL) {
132                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
133                                errbuf);
134                return -1;
135        }
136
137        /* If a filter has been configured, compile and apply it */
138        if (DATA(libtrace)->filter) {
139                if (DATA(libtrace)->filter->flag == 0) {
140                        pcap_compile(INPUT.pcap, 
141                                        &DATA(libtrace)->filter->filter,
142                                        DATA(libtrace)->filter->filterstring, 
143                                        1, 0);
144                        DATA(libtrace)->filter->flag = 1;
145                }
146                if (pcap_setfilter(INPUT.pcap,&DATA(libtrace)->filter->filter) 
147                                == -1) {
148                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
149                                        pcap_geterr(INPUT.pcap));
150                        return -1;
151                }
152        }
153        return 0;
154}
155
156static int pcap_config_input(libtrace_t *libtrace,
157                trace_option_t option,
158                void *data)
159{
160        switch(option) {
161                case TRACE_OPTION_FILTER:
162                        DATA(libtrace)->filter=data;
163                        return 0;
164                case TRACE_OPTION_SNAPLEN:
165                        /* Snapping isn't supported directly, so fall thru
166                         * and let libtrace deal with it
167                         */
168                case TRACE_OPTION_PROMISC:
169                        /* Can't do promisc on a trace! */
170                case TRACE_OPTION_META_FREQ:
171                        /* No meta data for this format */
172                case TRACE_OPTION_EVENT_REALTIME:
173                        /* We do not support this option for PCAP traces */
174                default:
175                        return -1;
176        }
177        assert(0);
178}
179
180static int pcap_init_output(libtrace_out_t *libtrace) {
181        libtrace->format_data = malloc(sizeof(struct pcap_format_data_out_t));
182        OUTPUT.trace.pcap = NULL;
183        OUTPUT.trace.dump = NULL;
184        return 0;
185}
186
187static int pcapint_init_output(libtrace_out_t *libtrace) {
188#ifdef HAVE_PCAP_INJECT
189        libtrace->format_data = malloc(sizeof(struct pcap_format_data_out_t));
190        OUTPUT.trace.pcap = NULL;
191        OUTPUT.trace.dump = NULL;
192        return 0;
193#else
194#ifdef HAVE_PCAP_SENDPACKET
195        libtrace->format_data = malloc(sizeof(struct pcap_format_data_out_t));
196        OUTPUT.trace.pcap = NULL;
197        OUTPUT.trace.dump = NULL;
198        return 0;
199#else
200        trace_set_err_out(libtrace,TRACE_ERR_UNSUPPORTED,
201                        "writing not supported by this version of pcap");
202        return -1;
203#endif
204#endif
205}
206
207static int pcapint_init_input(libtrace_t *libtrace) {
208        libtrace->format_data = malloc(sizeof(struct pcap_format_data_t));
209        DATA(libtrace)->filter = NULL;
210        DATA(libtrace)->snaplen = LIBTRACE_PACKET_BUFSIZE;
211        DATA(libtrace)->promisc = 0;
212        return 0; /* success */
213}
214
215static int pcapint_config_input(libtrace_t *libtrace,
216                trace_option_t option,
217                void *data)
218{
219        switch(option) {
220                case TRACE_OPTION_FILTER:
221                        DATA(libtrace)->filter=(libtrace_filter_t*)data;
222                        return 0;
223                case TRACE_OPTION_SNAPLEN:
224                        DATA(libtrace)->snaplen=*(int*)data;
225                        return 0;
226                case TRACE_OPTION_PROMISC:
227                        DATA(libtrace)->promisc=*(int*)data;
228                        return 0;
229                case TRACE_OPTION_META_FREQ:
230                        /* No meta-data for this format */
231                case TRACE_OPTION_EVENT_REALTIME:
232                        /* live interface is always real-time! */
233                default:
234                        /* Don't set an error here - trace_config will try
235                         * to handle the option when we return. If it can't
236                         * deal with it, then it will do the necessary
237                         * error-setting. */
238                        return -1;
239        }
240        assert(0);
241}
242
243static int pcapint_start_input(libtrace_t *libtrace) {
244        char errbuf[PCAP_ERRBUF_SIZE];
245
246#ifdef HAVE_PCAP_CREATE
247        int ret = 0;
248       
249        if ((INPUT.pcap = pcap_create(libtrace->uridata, errbuf)) == NULL) {
250                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
251                return -1; /* failure */
252        }
253        if ((pcap_set_snaplen(INPUT.pcap, DATA(libtrace)->snaplen) == 
254                                PCAP_ERROR_ACTIVATED)) {
255                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
256                return -1; /* failure */
257        }
258
259        if ((pcap_set_promisc(INPUT.pcap, DATA(libtrace)->promisc) == 
260                                PCAP_ERROR_ACTIVATED)) {
261                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
262                return -1; /* failure */
263        }
264       
265        if ((pcap_set_timeout(INPUT.pcap, 1) == PCAP_ERROR_ACTIVATED)) {
266                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
267                return -1; /* failure */
268        }
269
270        if ((ret = pcap_activate(INPUT.pcap)) != 0) {
271                if (ret == PCAP_WARNING_PROMISC_NOTSUP) {
272                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,"Promiscuous mode unsupported");
273                        return -1;
274                }
275                if (ret == PCAP_WARNING) {
276                        pcap_perror(INPUT.pcap, "Pcap Warning:");
277                } else {
278                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
279                                        pcap_geterr(INPUT.pcap));
280                        return -1;
281                }
282        }
283                         
284#else   
285
286        /* Open the live device */
287        if ((INPUT.pcap = 
288                        pcap_open_live(libtrace->uridata,
289                        DATA(libtrace)->snaplen,
290                        DATA(libtrace)->promisc,
291                        1,
292                        errbuf)) == NULL) {
293                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf);
294                return -1; /* failure */
295        }
296#endif
297        /* Set a filter if one is defined */
298        if (DATA(libtrace)->filter) {
299                if (DATA(libtrace)->filter->flag == 0) {
300                        pcap_compile(INPUT.pcap, 
301                                        &DATA(libtrace)->filter->filter,
302                                        DATA(libtrace)->filter->filterstring, 
303                                        1, 0);
304                        DATA(libtrace)->filter->flag = 1;
305                }
306                if (pcap_setfilter(INPUT.pcap,&DATA(libtrace)->filter->filter)
307                        == -1) {
308                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",
309                                        pcap_geterr(INPUT.pcap));
310                        return -1; /* failure */
311                }
312        }
313#ifdef HAVE_PCAP_SETNONBLOCK
314        pcap_setnonblock(INPUT.pcap,0,errbuf);
315#endif
316        return 0; /* success */
317}
318
319static int pcap_pause_input(libtrace_t *libtrace)
320{
321        pcap_close(INPUT.pcap);
322        INPUT.pcap=NULL;
323        return 0; /* success */
324}
325
326
327static int pcap_fin_input(libtrace_t *libtrace) 
328{
329        free(libtrace->format_data);
330        return 0; /* success */
331}
332
333static int pcap_fin_output(libtrace_out_t *libtrace) 
334{
335        if (OUTPUT.trace.dump) {
336                pcap_dump_flush(OUTPUT.trace.dump);
337                pcap_dump_close(OUTPUT.trace.dump);
338        }
339        pcap_close(OUTPUT.trace.pcap);
340        free(libtrace->format_data);
341        return 0;
342}
343
344static int pcapint_fin_output(libtrace_out_t *libtrace)
345{
346        pcap_close(OUTPUT.trace.pcap);
347        free(libtrace->format_data);
348        return 0;
349}
350
351static int pcap_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
352                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
353       
354        if (packet->buffer != buffer &&
355                        packet->buf_control == TRACE_CTRL_PACKET) {
356                        free(packet->buffer);
357        }
358
359        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
360                packet->buf_control = TRACE_CTRL_PACKET;
361        } else
362                packet->buf_control = TRACE_CTRL_EXTERNAL;
363       
364       
365        packet->buffer = buffer;
366        packet->header = buffer;
367        packet->type = rt_type;
368
369        /* Assuming header and payload are sequential in the buffer -
370         * regular pcap often doesn't work like this though, so hopefully
371         * we're not called by something that is reading genuine pcap! */
372        packet->payload = (char *)packet->header + sizeof(struct pcap_pkthdr);
373
374        if (libtrace->format_data == NULL) {
375                if (pcap_init_input(libtrace))
376                        return -1;
377        }
378        return 0;
379}
380
381static int pcap_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
382        int ret = 0;
383        int linktype;
384        uint32_t flags = 0;
385       
386        assert(libtrace->format_data);
387        linktype = pcap_datalink(DATA(libtrace)->input.pcap);
388        packet->type = pcap_linktype_to_rt(linktype);
389
390        /* If we're using the replacement pcap_next_ex() we need to
391         * make sure we have a buffer to *shudder* memcpy into
392         */
393        if (!packet->buffer) {
394                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
395                if (!packet->buffer) {
396                        trace_set_err(libtrace, errno, 
397                                        "Cannot allocate memory");
398                        return -1;
399                }
400                packet->header = packet->buffer;
401                packet->payload = (char *)packet->buffer+sizeof(struct pcap_pkthdr);
402                       
403        }
404
405        flags |= TRACE_PREP_OWN_BUFFER;
406       
407        for(;;) {
408               
409                struct pcap_pkthdr *pcap_hdr = NULL;
410                u_char *pcap_payload = NULL;
411
412                ret = pcap_next_ex(INPUT.pcap, &pcap_hdr, 
413                                (const u_char **)&pcap_payload);
414               
415                packet->header = pcap_hdr;
416                packet->payload = pcap_payload;
417
418                switch(ret) {
419                        case 1: break; /* no error */
420                        case 0:
421                                if (libtrace_halt)
422                                        return 0;
423                                continue; /* timeout expired */
424                        case -1:
425                                trace_set_err(libtrace,TRACE_ERR_BAD_PACKET,
426                                                "%s",pcap_geterr(INPUT.pcap));
427                                return -1; /* Error */
428                        case -2:
429                                return 0; /* EOF */
430                }
431
432                /*
433                 * pcap is nasty in that the header and payload aren't
434                 * necessarily located sequentially in memory, but most
435                 * sensible uses of pcap_prepare_packet will involve a
436                 * buffer where header and payload are sequential.
437                 *
438                 * Basically, don't call pcap_prepare_packet here!
439                 *
440                if (pcap_prepare_packet(libtrace, packet, packet->buffer,
441                                packet->type, flags)) {
442                        return -1;
443                }
444                */
445                return ((struct pcap_pkthdr*)packet->header)->len
446                        +sizeof(struct pcap_pkthdr);
447        }
448}
449
450static int pcap_write_packet(libtrace_out_t *libtrace, 
451                libtrace_packet_t *packet) 
452{
453        struct pcap_pkthdr pcap_pkt_hdr;
454        void *link;
455        libtrace_linktype_t linktype;
456        uint32_t remaining;
457
458        link = trace_get_packet_buffer(packet,&linktype,&remaining);
459
460        /* We may have to convert this packet into a suitable PCAP packet */
461
462        /* If this packet cannot be converted to a pcap linktype then
463         * pop off the top header until it can be converted
464         */
465        while (libtrace_to_pcap_linktype(linktype)==TRACE_DLT_ERROR) {
466                if (!demote_packet(packet)) {
467                        trace_set_err_out(libtrace, 
468                                TRACE_ERR_NO_CONVERSION,
469                                "pcap does not support this format");
470                        return -1;
471                }
472
473                link = trace_get_packet_buffer(packet,&linktype,&remaining);
474        }
475
476
477        if (!OUTPUT.trace.pcap) {
478                int linktype=libtrace_to_pcap_dlt(trace_get_link_type(packet));
479                OUTPUT.trace.pcap = pcap_open_dead(linktype,65536);
480                if (!OUTPUT.trace.pcap) {
481                        trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED,
482                                        "Failed to open dead trace: %s\n",
483                                        pcap_geterr(OUTPUT.trace.pcap));
484                }
485                OUTPUT.trace.dump = pcap_dump_open(OUTPUT.trace.pcap,
486                                libtrace->uridata);
487                if (!OUTPUT.trace.dump) {
488                        char *errmsg = pcap_geterr(OUTPUT.trace.pcap);
489                        trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED,"Failed to open output file: %s\n",
490                                        errmsg ? errmsg : "Unknown error");
491                        return -1;
492                }
493        }
494
495        /* Corrupt packet, or other "non data" packet, so skip it */
496        if (link == NULL) {
497                /* Return "success", but nothing written */
498                return 0;
499        }
500
501        /* Check if the packet was captured using one of the PCAP formats */
502        if (packet->trace->format == &pcap || 
503                        packet->trace->format == &pcapint) {
504                /* Yes - this means we can write it straight out */
505                pcap_dump((u_char*)OUTPUT.trace.dump,
506                                (struct pcap_pkthdr *)packet->header,
507                                packet->payload);
508        } else {
509                /* No - need to fill in a PCAP header with the appropriate
510                 * values */
511
512                /* Leave the manual copy as it is, as it gets around
513                 * some OS's having different structures in pcap_pkt_hdr
514                 */
515                struct timeval ts = trace_get_timeval(packet);
516                pcap_pkt_hdr.ts.tv_sec = ts.tv_sec;
517                pcap_pkt_hdr.ts.tv_usec = ts.tv_usec;
518                pcap_pkt_hdr.caplen = remaining;
519                /* trace_get_wire_length includes FCS, while pcap doesn't */
520                if (trace_get_link_type(packet)==TRACE_TYPE_ETH)
521                        if (trace_get_wire_length(packet) >= 4) { 
522                                pcap_pkt_hdr.len = 
523                                        trace_get_wire_length(packet)-4;
524                        }
525                        else {
526                                pcap_pkt_hdr.len = 0;
527                        }
528                else
529                        pcap_pkt_hdr.len = trace_get_wire_length(packet);
530
531                assert(pcap_pkt_hdr.caplen<65536);
532                assert(pcap_pkt_hdr.len<65536);
533
534                pcap_dump((u_char*)OUTPUT.trace.dump, &pcap_pkt_hdr, packet->payload);
535        }
536        return 0;
537}
538
539static int pcapint_write_packet(libtrace_out_t *libtrace,
540                libtrace_packet_t *packet) 
541{
542        int err;
543
544        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
545                return 0;
546
547        if (!OUTPUT.trace.pcap) {
548                OUTPUT.trace.pcap = (pcap_t *)pcap_open_live(
549                        libtrace->uridata,65536,0,0,NULL);
550        }
551#ifdef HAVE_PCAP_INJECT
552        err=pcap_inject(OUTPUT.trace.pcap,
553                        packet->payload,
554                        trace_get_capture_length(packet));
555        if (err!=(int)trace_get_capture_length(packet))
556                err=-1;
557#else
558#ifdef HAVE_PCAP_SENDPACKET
559        err=pcap_sendpacket(OUTPUT.trace.pcap,
560                        packet->payload,
561                        trace_get_capture_length(packet));
562#else
563    trace_set_err(packet->trace,TRACE_ERR_UNSUPPORTED,"writing is not supported on this platform");
564        return -1;
565#endif
566#endif
567        return err;
568}
569
570static libtrace_linktype_t pcap_get_link_type(const libtrace_packet_t *packet) {
571        /* PCAP doesn't store linktype in the framing header so we need
572         * RT to do it for us
573         */
574        int linktype = rt_to_pcap_linktype(packet->type);
575        return pcap_linktype_to_libtrace(linktype);
576}
577
578static libtrace_direction_t pcap_set_direction(libtrace_packet_t *packet,
579                libtrace_direction_t dir) {
580
581        /* We only support tagging with IN or OUT return error for any others */
582        if(!(dir == TRACE_DIR_OUTGOING || dir == TRACE_DIR_INCOMING))
583                return -1;
584
585        /* PCAP doesn't have a direction field in the header, so we need to
586         * promote to Linux SLL to tag it properly */
587        libtrace_sll_header_t *sll;
588        promote_packet(packet);
589        sll=packet->payload;
590       
591        /* sll->pkttype should be in the endianness of the host that the
592         * trace was taken on.  This is impossible to achieve so we assume
593         * host endianness
594         */
595        if(dir==TRACE_DIR_OUTGOING)
596                sll->pkttype=TRACE_SLL_OUTGOING;
597        else
598                sll->pkttype=TRACE_SLL_HOST;
599        return dir;
600}
601
602static libtrace_direction_t pcap_get_direction(const libtrace_packet_t *packet) {
603        libtrace_direction_t direction  = -1;
604        switch(pcap_get_link_type(packet)) {
605                /* Only packets encapsulated in Linux SLL or PFLOG have any
606                 * direction information */
607
608                case TRACE_TYPE_LINUX_SLL:
609                {
610                        libtrace_sll_header_t *sll;
611                        sll = trace_get_packet_buffer(packet, NULL, NULL);
612                        /* TODO: should check remaining>=sizeof(*sll) */
613                        if (!sll) {
614                                trace_set_err(packet->trace,
615                                        TRACE_ERR_BAD_PACKET,
616                                                "Bad or missing packet");
617                                return -1;
618                        }
619                        /* 0 == LINUX_SLL_HOST */
620                        /* the Waikato Capture point defines "packets
621                         * originating locally" (ie, outbound), with a
622                         * direction of 0, and "packets destined locally"
623                         * (ie, inbound), with a direction of 1.
624                         * This is kind-of-opposite to LINUX_SLL.
625                         * We return consistent values here, however
626                         *
627                         * Note that in recent versions of pcap, you can
628                         * use "inbound" and "outbound" on ppp in linux
629                         */
630                        if (sll->pkttype == TRACE_SLL_OUTGOING) {
631                                direction = TRACE_DIR_OUTGOING;
632                        } else {
633                                direction = TRACE_DIR_INCOMING;
634                        }
635                        break;
636
637                }
638                case TRACE_TYPE_PFLOG:
639                {
640                        libtrace_pflog_header_t *pflog;
641                        pflog = trace_get_packet_buffer(packet, NULL, NULL);
642                        /* TODO: should check remaining >= sizeof(*pflog) */
643                        if (!pflog) {
644                                trace_set_err(packet->trace,
645                                                TRACE_ERR_BAD_PACKET,
646                                                "Bad or missing packet");
647                                return -1;
648                        }
649                        /* enum    { PF_IN=0, PF_OUT=1 }; */
650                        if (ntohs(pflog->dir==0)) {
651
652                                direction = TRACE_DIR_INCOMING;
653                        }
654                        else {
655                                direction = TRACE_DIR_OUTGOING;
656                        }
657                        break;
658                }
659                default:
660                        break;
661        }       
662        return direction;
663}
664
665
666static struct timeval pcap_get_timeval(const libtrace_packet_t *packet) {
667        struct pcap_pkthdr *pcapptr = (struct pcap_pkthdr *)packet->header;
668        struct timeval ts;
669        ts.tv_sec = pcapptr->ts.tv_sec;
670        ts.tv_usec = pcapptr->ts.tv_usec;
671        return ts;
672}
673
674
675static int pcap_get_capture_length(const libtrace_packet_t *packet) {
676        struct pcap_pkthdr *pcapptr = 0;
677        pcapptr = (struct pcap_pkthdr *)packet->header;
678        assert(pcapptr->caplen<=65536);
679
680        return pcapptr->caplen;
681}
682
683static int pcap_get_wire_length(const libtrace_packet_t *packet) {
684        struct pcap_pkthdr *pcapptr = 0;
685        pcapptr = (struct pcap_pkthdr *)packet->header;
686        if (packet->type==pcap_linktype_to_rt(TRACE_DLT_EN10MB))
687                return pcapptr->len+4; /* Include the missing FCS */
688        else if (packet->type==pcap_linktype_to_rt(TRACE_DLT_IEEE802_11_RADIO)) {
689                libtrace_linktype_t linktype;
690                void *link = trace_get_packet_buffer(packet,&linktype,NULL);
691                /* If the packet is Radiotap and the flags field indicates
692                 * that the FCS is not included in the 802.11 frame, then
693                 * we need to add 4 to the wire-length to account for it.
694                 */
695                uint8_t flags;
696                trace_get_wireless_flags(link, 
697                                linktype, &flags);
698                if ((flags & TRACE_RADIOTAP_F_FCS) == 0)
699                        return pcapptr->len + 4;
700        }
701        return pcapptr->len;
702}
703
704static int pcap_get_framing_length(UNUSED const libtrace_packet_t *packet) {
705        return sizeof(struct pcap_pkthdr);
706}
707
708static size_t pcap_set_capture_length(libtrace_packet_t *packet,size_t size) {
709        struct pcap_pkthdr *pcapptr = 0;
710        assert(packet);
711        if (size > trace_get_capture_length(packet)) {
712                /* Can't make a packet larger */
713                return trace_get_capture_length(packet);
714        }
715        /* Reset the cached capture length */
716        packet->capture_length = -1;
717        pcapptr = (struct pcap_pkthdr *)packet->header;
718        pcapptr->caplen = size;
719        return trace_get_capture_length(packet);
720}
721
722static int pcap_get_fd(const libtrace_t *trace) {
723
724        assert(trace->format_data);
725        return pcap_fileno(DATA(trace)->input.pcap);
726}
727
728static uint64_t pcap_get_dropped_packets(libtrace_t *trace)
729{
730        struct pcap_stat stats;
731        if (pcap_stats(DATA(trace)->input.pcap,&stats)==-1) {
732                char *errmsg = pcap_geterr(DATA(trace)->input.pcap);
733                trace_set_err(trace,TRACE_ERR_UNSUPPORTED,
734                                "Failed to retreive stats: %s\n",
735                                errmsg ? errmsg : "Unknown pcap error");
736                return ~0;
737        }
738
739        return stats.ps_drop;
740}
741
742static void pcap_help(void) {
743        printf("pcap format module: $Revision: 1729 $\n");
744        printf("Supported input URIs:\n");
745        printf("\tpcap:/path/to/file\n");
746        printf("\n");
747        printf("\te.g.: pcap:/tmp/trace.pcap\n");
748        printf("\n");
749        printf("Supported output URIs:\n");
750        printf("\tnone\n");
751        printf("\n");
752}
753
754static void pcapint_help(void) {
755        printf("pcapint format module: $Revision: 1729 $\n");
756        printf("Supported input URIs:\n");
757        printf("\tpcapint:interface\n");
758        printf("\n");
759        printf("\te.g.: pcapint:eth0\n");
760        printf("\n");
761        printf("Supported output URIs:\n");
762        printf("\tnone\n");
763        printf("\n");
764}
765
766
767static struct libtrace_format_t pcap = {
768        "pcap",
769        "$Id$",
770        TRACE_FORMAT_PCAP,
771        NULL,                           /* probe filename */
772        NULL,                           /* probe magic */
773        pcap_init_input,                /* init_input */
774        pcap_config_input,              /* config_input */
775        pcap_start_input,               /* start_input */
776        NULL,                           /* pause_input */
777        pcap_init_output,               /* init_output */
778        NULL,                           /* config_output */
779        NULL,                           /* start_output */
780        pcap_fin_input,                 /* fin_input */
781        pcap_fin_output,                /* fin_output */
782        pcap_read_packet,               /* read_packet */
783        pcap_prepare_packet,            /* prepare_packet */
784        NULL,                           /* fin_packet */
785        pcap_write_packet,              /* write_packet */
786        pcap_get_link_type,             /* get_link_type */
787        pcap_get_direction,             /* get_direction */
788        pcap_set_direction,             /* set_direction */
789        NULL,                           /* get_erf_timestamp */
790        pcap_get_timeval,               /* get_timeval */
791        NULL,                           /* get_seconds */
792        NULL,                           /* get_timespec */
793        NULL,                           /* seek_erf */
794        NULL,                           /* seek_timeval */
795        NULL,                           /* seek_seconds */
796        pcap_get_capture_length,        /* get_capture_length */
797        pcap_get_wire_length,           /* get_wire_length */
798        pcap_get_framing_length,        /* get_framing_length */
799        pcap_set_capture_length,        /* set_capture_length */
800        NULL,                           /* get_received_packets */
801        NULL,                           /* get_filtered_packets */
802        NULL,                           /* get_dropped_packets */
803        NULL,                           /* get_captured_packets */
804        NULL,                           /* get_fd */
805        trace_event_trace,              /* trace_event */
806        pcap_help,                      /* help */
807        NULL                            /* next pointer */
808};
809
810static struct libtrace_format_t pcapint = {
811        "pcapint",
812        "$Id$",
813        TRACE_FORMAT_PCAP,
814        NULL,                           /* probe filename */
815        NULL,                           /* probe magic */
816        pcapint_init_input,             /* init_input */
817        pcapint_config_input,           /* config_input */
818        pcapint_start_input,            /* start_input */
819        pcap_pause_input,               /* pause_input */
820        pcapint_init_output,            /* init_output */
821        NULL,                           /* config_output */
822        NULL,                           /* start_output */
823        pcap_fin_input,                 /* fin_input */
824        pcapint_fin_output,             /* fin_output */
825        pcap_read_packet,               /* read_packet */
826        pcap_prepare_packet,            /* prepare_packet */
827        NULL,                           /* fin_packet */
828        pcapint_write_packet,           /* write_packet */
829        pcap_get_link_type,             /* get_link_type */
830        pcap_get_direction,             /* get_direction */
831        pcap_set_direction,             /* set_direction */
832        NULL,                           /* get_erf_timestamp */
833        pcap_get_timeval,               /* get_timeval */
834        NULL,                           /* get_seconds */
835        NULL,                           /* get_timespec */
836        NULL,                           /* seek_erf */
837        NULL,                           /* seek_timeval */
838        NULL,                           /* seek_seconds */
839        pcap_get_capture_length,        /* get_capture_length */
840        pcap_get_wire_length,           /* get_wire_length */
841        pcap_get_framing_length,        /* get_framing_length */
842        pcap_set_capture_length,        /* set_capture_length */
843        NULL,                           /* get_received_packets */
844        NULL,                           /* get_filtered_packets */
845        pcap_get_dropped_packets,       /* get_dropped_packets */
846        NULL,                           /* get_captured_packets */
847        pcap_get_fd,                    /* get_fd */
848        trace_event_device,             /* trace_event */
849        pcapint_help,                   /* help */
850        NULL                            /* next pointer */
851};
852
853void pcap_constructor(void) {
854        register_format(&pcap);
855        register_format(&pcapint);
856}
857
858
859#endif
Note: See TracBrowser for help on using the repository browser.