source: lib/format_bpf.c @ 95ca714

cachetimestampsdeveloprc-4.0.4ringdecrementfixringperformance
Last change on this file since 95ca714 was 32ee9b2, checked in by Shane Alcock <salcock@…>, 3 years ago

Add new trace_flush_output() to public API

Can be used to force a libtrace output to dump any buffered output
to disk immediately.

Note that if the file is compressed or the output trace format
requires a trailer, the flushed file will still not be properly
readable afterwards as this will not result in any trailers
being written. You'll still have to close the file for that.

Mainly this is useful for ensuring that output file sizes grow
over time in situations where the amount of output is relatively
small, rather than staying stuck at 0 bytes until we either reach
1MB of output or the file is closed. For instance, you could have
a timer that calls trace_flush_output() every 30 seconds so that
the output file size will grow if any packets were written in the
last 30 seconds.

  • Property mode set to 100644
File size: 20.2 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26#include "libtrace.h"
27#include "libtrace_int.h"
28#include "format_helper.h"
29#include "config.h"
30#include "stdlib.h"
31
32#ifdef HAVE_INTTYPES_H
33#  include <inttypes.h>
34#else
35# error "Can't find inttypes.h"
36#endif
37
38#include <sys/socket.h>
39
40#include <sys/types.h>
41#include <sys/time.h>
42#include <sys/ioctl.h>
43
44#include <string.h>
45#include <net/if.h>
46#include <sys/ioctl.h>
47#include <errno.h>
48#include <fcntl.h>
49#include <unistd.h>
50
51/* This format deals with the BSD Native capture format, perhaps better
52 * known as BPF, which is the equivalent of the Linux Native format for
53 * *BSD systems.
54 *
55 * This is a LIVE capture format - we're always dealing with reading from an
56 * interface.
57 *
58 * This format does not support writing, but BPF packet records can be easily
59 * converted to PCAP or ERF.
60 */ 
61
62struct lt_bpf_timeval {
63        uint32_t tv_sec;
64        uint32_t tv_usec;
65};
66
67struct libtrace_bpf_hdr {
68        struct lt_bpf_timeval bh_tstamp;        /* timestamp */
69        uint32_t bh_caplen;             /* capture length */
70        uint32_t bh_datalen;            /* wire length */
71        uint16_t bh_hdrlen;             /* header length (incl padding) */
72};
73
74#ifndef BPF_TIMEVAL
75#define BPF_TIMEVAL timeval
76#endif
77
78struct local_bpf_hdr {
79        struct BPF_TIMEVAL bh_tstamp;
80        uint32_t bh_caplen;
81        uint32_t bh_datalen;
82        uint16_t bh_hdrlen;
83};
84
85#define BPFHDR(x) ((struct libtrace_bpf_hdr *)((x)->header))
86
87#if HAVE_DECL_BIOCSETIF
88/* "Global" data that is stored for each BPF input trace */
89struct libtrace_format_data_t {
90        /* The file descriptor that is being captured from */
91        int fd; 
92        /* The snap length for the capture */
93        int snaplen;
94        /* A boolean flag indicating whether the capture interface should be
95         * in promiscuous mode */ 
96        int promisc;
97        /* A buffer to write captured data into */
98        void *buffer;
99        /* The current read location in the capture buffer */
100        void *bufptr;
101        /* The total size of the capture buffer */
102        unsigned int buffersize;
103        /* The amount of space remaining before the capture buffer is full */
104        int remaining;
105        /* The linktype of the capture interface */ 
106        unsigned int linktype;
107        /* Statistics about how many packets have been dropped, received etc. */
108        struct bpf_stat stats;
109        /* A boolean flag indicating whether the statistics are up-to-date */
110        int stats_valid;
111        /* Bucket data structure for safely storing buffers of packets */
112        libtrace_bucket_t *bucket;
113};
114
115#define FORMATIN(x) ((struct libtrace_format_data_t*)((x->format_data)))
116
117
118/* Attempts to determine if a given filename could refer to a BPF interface */
119static int bpf_probe_filename(const char *filename)
120{
121        return (if_nametoindex(filename) != 0);
122}
123
124/* Initialises a BPF input trace */
125static int bpf_init_input(libtrace_t *libtrace) 
126{
127        libtrace->format_data = (struct libtrace_format_data_t *)
128                malloc(sizeof(struct libtrace_format_data_t));
129       
130        /* Throw some default values into the format data */
131        FORMATIN(libtrace)->fd = -1;
132        FORMATIN(libtrace)->promisc = 0;
133        FORMATIN(libtrace)->snaplen = 65536;
134        FORMATIN(libtrace)->stats_valid = 0;
135        FORMATIN(libtrace)->bucket = libtrace_bucket_init();
136
137        return 0;
138}
139
140/* Starts a BPF input trace */
141static int bpf_start_input(libtrace_t *libtrace)
142{
143        int bpfid=0;
144        struct bpf_version bv;
145        struct ifreq ifr;
146        unsigned int v;
147
148        /* Find and open a bpf device */
149        do {
150                char buffer[64];
151                snprintf(buffer,sizeof(buffer),"/dev/bpf%d", bpfid);
152                bpfid++;
153               
154                FORMATIN(libtrace)->fd = open(buffer, O_RDONLY);
155        } while(FORMATIN(libtrace)->fd == -1 && errno == EBUSY);
156
157        if (FORMATIN(libtrace)->fd == -1) {
158                trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
159                                "No free bpf devices");
160                return -1;
161        }
162
163        /* Check the BPF Version is ok */
164        if (ioctl(FORMATIN(libtrace)->fd, BIOCVERSION, &bv) == -1) {
165                trace_set_err(libtrace,errno,
166                                "Failed to read the bpf version");
167                close(FORMATIN(libtrace)->fd);
168                return -1;
169        }
170
171        if (bv.bv_major != BPF_MAJOR_VERSION) {
172                trace_set_err(libtrace,errno, 
173                        "Unknown kernel BPF version (%d.%d, libtrace requires at least %d.%d)",
174                        bv.bv_major,
175                        bv.bv_minor,
176                        BPF_MAJOR_VERSION,
177                        BPF_MINOR_VERSION);
178                close(FORMATIN(libtrace)->fd);
179                return -1;
180        }
181
182        if (bv.bv_minor < BPF_MINOR_VERSION) {
183                trace_set_err(libtrace,errno, "Kernel version too old (%d.%d, libtrace requires at least %d.%d)",
184                        bv.bv_major,
185                        bv.bv_minor,
186                        BPF_MAJOR_VERSION,
187                        BPF_MINOR_VERSION);
188                close(FORMATIN(libtrace)->fd);
189                return -1;
190        }
191
192        /* We assume the default kernel buffer size is sufficient. */
193        if (ioctl(FORMATIN(libtrace)->fd, BIOCGBLEN,
194                        &FORMATIN(libtrace)->buffersize)==-1) {
195                trace_set_err(libtrace,errno,"Failed to find buffer length");
196                close(FORMATIN(libtrace)->fd);
197                return -1;
198        }
199
200        FORMATIN(libtrace)->buffer = NULL;
201        FORMATIN(libtrace)->bufptr = NULL;
202        FORMATIN(libtrace)->remaining = 0;
203
204        /* Attach to the device */
205        strncpy(ifr.ifr_name, libtrace->uridata, sizeof(ifr.ifr_name));
206        if (ioctl(FORMATIN(libtrace)->fd, BIOCSETIF, &ifr) == -1) {
207                trace_set_err(libtrace,errno,"Failed to attach");
208                close(FORMATIN(libtrace)->fd);
209                return -1;
210        }
211
212        /* Set the link type */
213        if (ioctl(FORMATIN(libtrace)->fd, BIOCGDLT,
214                         &FORMATIN(libtrace)->linktype) == -1) {
215                trace_set_err(libtrace,errno,"Failed to retrieve link type");
216                close(FORMATIN(libtrace)->fd);
217                return -1;
218        }
219       
220        /* TODO: If BIOCGDLTLIST exists then we should perhaps do something
221         *       with it.  We don't have the same concept of multiple DLT's
222         *       as pcap does.  We grab the rawest possible thing and then
223         *       decode packets by understanding the protocols.  So perhaps
224         *       we should setup a rating of DLT's that we'll prefer in order.
225         *       For example we should try and get 802.11 frames rather than
226         *       802.3 frames.  The general rule should be "whatever actually
227         *       went over the air", although of course if we don't support
228         *       what went over the air we should fall back to something we
229         *       /do/ support.
230         */
231       
232        /* Using timeouts seems sucky.  We'll always use immediate mode.  We
233         * pray the kernel is smart enough that if a another packet arrives
234         * while we're processing this one that it will buffer them into it's
235         * kernel buffer so we can receive packets later. (It'll need to do this
236         * to deal with us spending time processing the last 'n' packets anyway)
237         */
238       
239        v=1;
240        if (ioctl(FORMATIN(libtrace)->fd, BIOCIMMEDIATE, &v) == -1) {
241                trace_set_err(libtrace,errno,"Failed to set immediate mode");
242                close(FORMATIN(libtrace)->fd);
243                return -1;
244        }
245
246        /* Set promiscous mode, if the user has asked us to do so */
247        if (FORMATIN(libtrace)->promisc) {
248                if (ioctl(FORMATIN(libtrace)->fd, BIOCPROMISC, NULL) == -1) {
249                        trace_set_err(libtrace,errno,
250                                "Failed to set promisc mode");
251                        close(FORMATIN(libtrace)->fd);
252                        return -1;
253
254                }
255        }
256
257        FORMATIN(libtrace)->stats_valid = 0;
258
259        /* TODO: we should always set a bpf filter for snapping */
260
261        /* We're done! */
262        return 0;
263}
264
265/* Gets a count of the number of packets received on the BPF interface */
266static uint64_t bpf_get_received_packets(libtrace_t *trace)
267{
268        if (trace->format_data == NULL)
269                return (uint64_t)-1;
270
271        if (FORMATIN(trace)->fd == -1) {
272                /* Almost certainly a 'dead' trace so there is no socket
273                 * for us to query */
274                return (uint64_t) -1;
275        }
276        /* If we're called with stats_valid == 0, or we're called again
277         * then refresh the stats.  Don't refresh the stats if we're called
278         * immediately after get_dropped_packets
279         */
280        if ((FORMATIN(trace)->stats_valid & 1)
281                || (FORMATIN(trace)->stats_valid == 0)) {
282                ioctl(FORMATIN(trace)->fd, BIOCGSTATS, &FORMATIN(trace)->stats);
283                FORMATIN(trace)->stats_valid |= 1;
284        }
285
286        return FORMATIN(trace)->stats.bs_recv;
287}
288
289/* Gets a count of the number of packets dropped on the BPF interface */
290static uint64_t bpf_get_dropped_packets(libtrace_t *trace)
291{
292        if (trace->format_data == NULL)
293                return (uint64_t)-1;
294
295        if (FORMATIN(trace)->fd == -1) {
296                /* Almost certainly a 'dead' trace so there is no socket
297                 * for us to query */
298                return (uint64_t) -1;
299        }
300        /* If we're called with stats_valid == 0, or we're called again
301         * then refresh the stats.  Don't refresh the stats if we're called
302         * immediately after get_received_packets
303         */
304        if ((FORMATIN(trace)->stats_valid & 2) 
305                || (FORMATIN(trace)->stats_valid == 0)) {
306                ioctl(FORMATIN(trace)->fd, BIOCGSTATS, &FORMATIN(trace)->stats);
307                FORMATIN(trace)->stats_valid |= 2;
308        }
309
310        return FORMATIN(trace)->stats.bs_drop;
311}
312
313static void bpf_get_statistics(libtrace_t *trace, libtrace_stat_t *stat) {
314        uint64_t dropped = bpf_get_dropped_packets(trace);
315        uint64_t received = bpf_get_received_packets(trace);
316
317        if (dropped != (uint64_t)-1) {
318                stat->dropped_valid = 1;
319                stat->dropped = dropped;
320        }
321
322        if (received != (uint64_t) -1) {
323                stat->received_valid = 1;
324                stat->received = received;
325        }
326
327}
328
329/* Pauses a BPF input trace */
330static int bpf_pause_input(libtrace_t *libtrace)
331{
332        close(FORMATIN(libtrace)->fd);
333        FORMATIN(libtrace)->fd=-1;
334
335        return 0;
336}
337
338/* Closes a BPF input trace */
339static int bpf_fin_input(libtrace_t *libtrace) 
340{
341        libtrace_bucket_destroy(FORMATIN(libtrace)->bucket);
342        free(libtrace->format_data);
343        return 0;
344}
345
346/* Configures a BPF input trace */
347static int bpf_config_input(libtrace_t *libtrace,
348                trace_option_t option,
349                void *data)
350{
351        switch(option) {
352                case TRACE_OPTION_SNAPLEN:
353                        FORMATIN(libtrace)->snaplen=*(int*)data;
354                        return 0;
355                case TRACE_OPTION_PROMISC:
356                        FORMATIN(libtrace)->promisc=*(int*)data;
357                        return 0;
358                case TRACE_OPTION_FILTER:
359                        /* We don't support bpf filters in any special way
360                         * so return an error and let libtrace deal with
361                         * emulating it
362                         */
363                        break;
364                case TRACE_OPTION_META_FREQ:
365                        /* No meta-data for this format */
366                        break;
367                case TRACE_OPTION_EVENT_REALTIME:
368                        /* Captures are always realtime */
369                        break;
370                case TRACE_OPTION_HASHER:
371                        /* TODO investigate hashing in BSD? */
372                        break;
373
374                /* Avoid default: so that future options will cause a warning
375                 * here to remind us to implement it, or flag it as
376                 * unimplementable
377                 */
378        }
379        return -1;
380}
381
382#endif  /* HAVE_DECL_BIOCSETIF */
383
384/* Converts a buffer containing a recently read BPF packet record into a
385 * libtrace packet */
386static int bpf_prepare_packet(libtrace_t *libtrace UNUSED, 
387                libtrace_packet_t *packet,
388                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
389       
390        struct local_bpf_hdr orig;
391        struct local_bpf_hdr *ptr;
392        struct libtrace_bpf_hdr *replace;
393
394        /* If the packet previously owned a buffer that is not the buffer
395         * that contains the new packet data, we're going to need to free the
396         * old one to avoid memory leaks */
397        if (packet->buffer != buffer &&
398                        packet->buf_control == TRACE_CTRL_PACKET) {
399                free(packet->buffer);
400        }
401
402        /* Set the buffer owner appropriately */
403        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
404                packet->buf_control = TRACE_CTRL_PACKET;
405        } else
406                packet->buf_control = TRACE_CTRL_EXTERNAL;
407
408        /* Update the packet pointers and type appropriately */
409        packet->buffer = buffer;
410        packet->header = buffer;
411        packet->type = rt_type;
412
413        /* FreeBSD is stupid and uses a timeval in the bpf header
414         * structure. This means that sometimes our timestamp consumes
415         * 8 bytes and sometimes it consumes 16 bytes.
416         *
417         * Let's try to standardise our header a bit, hopefully without
418         * overwriting anything else important */
419
420        if (sizeof(struct BPF_TIMEVAL) != sizeof(struct lt_bpf_timeval)) {     
421               
422                ptr = ((struct local_bpf_hdr *)(packet->header));
423                replace = ((struct libtrace_bpf_hdr *)(packet->header));
424                memcpy(&orig, ptr, sizeof(struct local_bpf_hdr));
425
426                replace->bh_tstamp.tv_sec = (uint32_t) (orig.bh_tstamp.tv_sec & 0xffffffff);
427                replace->bh_tstamp.tv_usec = (uint32_t) (orig.bh_tstamp.tv_usec & 0xffffffff);
428                replace->bh_caplen = orig.bh_caplen;
429                replace->bh_datalen = orig.bh_datalen;
430                replace->bh_hdrlen = orig.bh_hdrlen;
431
432
433        }
434
435        /* Find the payload */
436        /* TODO: Pcap deals with a padded FDDI linktype here */
437        packet->payload=(char *)buffer + BPFHDR(packet)->bh_hdrlen;
438
439        return 0;
440}
441
442#if HAVE_DECL_BIOCSETIF
443
444/* Reads the next packet record from a BPF interface and writes it into a
445 * libtrace packet */   
446static int bpf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) 
447{
448        uint32_t flags = 0;
449        fd_set readfds;
450        struct timeval tout;
451        int ret;
452
453        packet->type = bpf_linktype_to_rt(FORMATIN(libtrace)->linktype);
454
455        if (FORMATIN(libtrace)->remaining <= 0) {
456                FORMATIN(libtrace)->buffer = malloc(FORMATIN(libtrace)->buffersize);
457                libtrace_create_new_bucket(FORMATIN(libtrace)->bucket, FORMATIN(libtrace)->buffer);
458        }
459
460        while (FORMATIN(libtrace)->remaining <= 0) {
461
462                tout.tv_sec = 0;
463                tout.tv_usec = 500000;
464                FD_ZERO(&readfds);
465                FD_SET(FORMATIN(libtrace)->fd, &readfds);
466
467                ret = select(FORMATIN(libtrace)->fd + 1, &readfds, NULL,
468                                NULL, &tout);
469                if (ret < 0 && errno != EINTR) {
470                        trace_set_err(libtrace, errno, "select");
471                        return -1;
472                } else if (ret < 0) {
473                        continue;
474                }
475
476                if (FD_ISSET(FORMATIN(libtrace)->fd, &readfds)) {
477                        /* Packets are available, read into buffer */
478                        ret=read(FORMATIN(libtrace)->fd,
479                                FORMATIN(libtrace)->buffer,
480                                FORMATIN(libtrace)->buffersize);
481
482                        if (ret == -1) {
483                                trace_set_err(libtrace,errno,"Failed to read");
484                                return -1;
485                        }
486
487                        if (ret == 0) {
488                                /* EOF */
489                                return 0;
490                        }
491
492                        FORMATIN(libtrace)->remaining=ret;
493                        FORMATIN(libtrace)->bufptr=
494                                        FORMATIN(libtrace)->buffer;
495                        break;
496                }
497
498                /* Timed out -- check if we should halt */
499                if ((ret=is_halted(libtrace)) != -1)
500                        return ret;
501        }
502       
503        /* We do NOT want anything trying to free the memory the packet is
504         * stored in */
505        flags |= TRACE_PREP_DO_NOT_OWN_BUFFER;
506
507        if (packet->buffer && packet->buf_control == TRACE_CTRL_PACKET)
508                free(packet->buffer);
509
510        /* Update 'packet' to point to the first packet in our capture
511         * buffer */
512        if (bpf_prepare_packet(libtrace, packet, FORMATIN(libtrace)->bufptr,
513                        packet->type, flags)) {
514                return -1;
515        }
516
517        packet->internalid = libtrace_push_into_bucket(FORMATIN(libtrace)->bucket);
518        packet->srcbucket = FORMATIN(libtrace)->bucket;
519
520        /* Skip past the packet record we're going to return, making sure
521         * that we deal with padding correctly */
522        FORMATIN(libtrace)->bufptr+=
523                BPF_WORDALIGN(BPFHDR(packet)->bh_hdrlen
524                +BPFHDR(packet)->bh_caplen);
525        FORMATIN(libtrace)->remaining-=
526                BPF_WORDALIGN(BPFHDR(packet)->bh_hdrlen
527                +BPFHDR(packet)->bh_caplen);
528
529        return BPFHDR(packet)->bh_datalen+BPFHDR(packet)->bh_hdrlen;
530}
531
532#endif  /* HAVE_DECL_BIOCSETIF */
533
534/* Returns the linktype for the interface that we are capturing from */
535static libtrace_linktype_t bpf_get_link_type(const libtrace_packet_t *packet) {
536        /* Convert the linktype that we recorded when we started the trace
537         * into a suitable libtrace linktype */
538        return pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type));
539}
540
541/* Returns the direction for a given BPF packet record */
542static libtrace_direction_t bpf_get_direction(const libtrace_packet_t *packet UNUSED) {
543        /* BPF sadly can't do direction tagging */
544        return ~0;
545}
546
547/* Returns the timestamp for a given BPF packet record, in the form of a
548 * struct timeval */
549static struct timeval bpf_get_timeval(const libtrace_packet_t *packet) 
550{
551        struct timeval tv;
552        /* OpenBSD uses a bpf_timeval rather than a timeval so we must copy
553         * each timeval element individually rather than doing a structure
554         * assignment */
555        tv.tv_sec = BPFHDR(packet)->bh_tstamp.tv_sec;
556        tv.tv_usec = BPFHDR(packet)->bh_tstamp.tv_usec;
557
558        return tv;
559}
560
561/* Returns the capture length for a given BPF packet record */
562static int bpf_get_capture_length(const libtrace_packet_t *packet)
563{
564        /* BPF doesn't include the FCS in its caplen field, but libtrace
565         * does so we need to add this extra 4 bytes */
566        return BPFHDR(packet)->bh_caplen+4;
567}
568
569/* Returns the wire length for a given BPF packet record */
570static int bpf_get_wire_length(const libtrace_packet_t *packet) 
571{
572
573        /* BPF doesn't include the FCS in its datalen field, but libtrace
574         * does so we need to add this extra 4 bytes */
575        return BPFHDR(packet)->bh_datalen+4;
576}
577
578/* Returns the framing length for a given BPF packet record */
579static int bpf_get_framing_length(UNUSED
580                const libtrace_packet_t *packet) 
581{
582        return BPFHDR(packet)->bh_hdrlen;
583}
584
585#if HAVE_DECL_BIOCSETIF
586/* Returns the file descriptor that the capture interface is operating on */
587static int bpf_get_fd(const libtrace_t *trace) {
588        return FORMATIN(trace)->fd;
589}
590
591/* Prints some slightly useful help text for the BPF capture format */
592static void bpf_help() {
593        printf("bpf format module: $Revision: 1782 $\n");
594        printf("Supported input URIs:\n");
595        printf("\tbpf:\n");
596        printf("\n");
597        return;
598}
599static struct libtrace_format_t bpf = {
600        "bpf",
601        "$Id$",
602        TRACE_FORMAT_BPF,
603        bpf_probe_filename,     /* probe filename */
604        NULL,                   /* probe magic */
605        bpf_init_input,         /* init_input */
606        bpf_config_input,       /* config_input */
607        bpf_start_input,        /* start_input */
608        bpf_pause_input,        /* pause_input */
609        NULL,                   /* init_output */
610        NULL,                   /* config_output */
611        NULL,                   /* start_ouput */
612        bpf_fin_input,          /* fin_input */
613        NULL,                   /* fin_output */
614        bpf_read_packet,        /* read_packet */
615        bpf_prepare_packet,     /* prepare_packet */
616        NULL,                   /* fin_packet */
617        NULL,                   /* write_packet */
618        bpf_get_link_type,      /* get_link_type */
619        bpf_get_direction,      /* get_direction */
620        NULL,                   /* set_direction */
621        NULL,                   /* get_erf_timestamp */
622        bpf_get_timeval,        /* get_timeval */
623        NULL,                   /* get_timespec */
624        NULL,                   /* get_seconds */
625        NULL,                   /* seek_erf */
626        NULL,                   /* seek_timeval */
627        NULL,                   /* seek_seconds */
628        bpf_get_capture_length, /* get_capture_length */
629        bpf_get_wire_length,    /* get_wire_length */
630        bpf_get_framing_length, /* get_framing_length */
631        NULL,                   /* set_capture_length */
632        NULL,                   /* get_received_packets */
633        NULL,                   /* get_filtered_packets */
634        NULL,                   /* get_dropped_packets */
635        bpf_get_statistics,     /* get_statistics */
636        bpf_get_fd,             /* get_fd */
637        trace_event_device,     /* trace_event */
638        bpf_help,               /* help */
639        NULL,                   /* next pointer */
640        NON_PARALLEL(true)
641};
642#else   /* HAVE_DECL_BIOCSETIF */
643/* Prints some slightly useful help text for the BPF capture format */
644static void bpf_help() {
645        printf("bpf format module: $Revision: 1782 $\n");
646        printf("Not supported on this host\n");
647        return;
648}
649static struct libtrace_format_t bpf = {
650        "bpf",
651        "$Id$",
652        TRACE_FORMAT_BPF,
653        NULL,                   /* probe filename */
654        NULL,                   /* probe magic */
655        NULL,                   /* init_input */
656        NULL,                   /* config_input */
657        NULL,                   /* start_input */
658        NULL,                   /* pause_input */
659        NULL,                   /* init_output */
660        NULL,                   /* config_output */
661        NULL,                   /* start_ouput */
662        NULL,                   /* fin_input */
663        NULL,                   /* fin_output */
664        NULL,                   /* read_packet */
665        bpf_prepare_packet,     /* prepare_packet */
666        NULL,                   /* fin_packet */
667        NULL,                   /* write_packet */
668        NULL,                   /* flush_output */
669        bpf_get_link_type,      /* get_link_type */
670        bpf_get_direction,      /* get_direction */
671        NULL,                   /* set_direction */
672        NULL,                   /* get_erf_timestamp */
673        bpf_get_timeval,        /* get_timeval */
674        NULL,                   /* get_timespec */
675        NULL,                   /* get_seconds */
676        NULL,                   /* seek_erf */
677        NULL,                   /* seek_timeval */
678        NULL,                   /* seek_seconds */
679        bpf_get_capture_length, /* get_capture_length */
680        bpf_get_wire_length,    /* get_wire_length */
681        bpf_get_framing_length, /* get_framing_length */
682        NULL,                   /* set_capture_length */
683        NULL,                   /* get_received_packets */
684        NULL,                   /* get_filtered_packets */
685        NULL,                   /* get_dropped_packets */
686        NULL,                   /* get_statistics */
687        NULL,                   /* get_fd */
688        NULL,                   /* trace_event */
689        bpf_help,               /* help */
690        NULL,                   /* next pointer */
691        NON_PARALLEL(true)
692};
693#endif  /* HAVE_DECL_BIOCSETIF */
694
695void bpf_constructor() {
696        register_format(&bpf);
697}
Note: See TracBrowser for help on using the repository browser.