source: lib/format_bpf.c @ 322c516

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

Deprecate trace_get_filtered/accepted/recevied/dropped() in favour of a single function

Adds the single trace_get_statistics function. This allows the structure to be filled
at a point in time, rather than making multiple calls to the library during which state
might have changed.

This has been designed such that the structure can be added to in the future without
breaking old code.

The old internal get_captured_packets was removed from the formats as it was never used.
Eventually we should completely remove get_filtered and received from the formats and replace
them with get_statistics.

In additon some extra fields have added, such as error and captured and the pre-existing
fields are better defined.

The linux formats have been updated to use this new API, which combined with reading
/proc/net/dev returns a full set of statistics.

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