source: lib/format_linux.c @ 89404f5

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 89404f5 was 89404f5, checked in by Perry Lorier <perry@…>, 14 years ago

deal with IP with no L2 captures.

  • Property mode set to 100644
File size: 18.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31#include "libtrace.h"
32#include "libtrace_int.h"
33#include "format_helper.h"
34#include "config.h"
35#include "stdlib.h"
36
37#ifdef HAVE_INTTYPES_H
38#  include <inttypes.h>
39#else
40# error "Can't find inttypes.h"
41#endif
42
43#include <sys/socket.h>
44#include <netpacket/packet.h>
45#include <net/ethernet.h>
46#include <net/if_arp.h>
47
48#include <string.h>
49#include <net/if.h>
50#include <sys/ioctl.h>
51#include <errno.h>
52
53#include <assert.h>
54
55/* Declared in linux/if_arp.h but not in net/if_arp.h sigh */
56#ifndef ARPHRD_NONE
57#define ARPHRD_NONE 0xfffe
58#endif
59
60struct tpacket_stats {
61        unsigned int tp_packets;
62        unsigned int tp_drops;
63};
64
65struct libtrace_format_data_t {
66        int fd;
67        int snaplen;
68        int promisc;
69        libtrace_filter_t *filter;
70        struct tpacket_stats stats;
71        int stats_valid;
72};
73
74struct libtrace_linuxnative_header {
75        struct timeval ts;
76        int wirelen;
77        int caplen;
78        struct sockaddr_ll hdr;
79};
80
81struct libtrace_linuxnative_format_data_t {
82        int fd;
83};
84
85#define FORMAT(x) ((struct libtrace_format_data_t*)(x))
86#define DATAOUT(x) ((struct libtrace_linuxnative_format_data_t*)((x)->format_data))
87
88static int linuxnative_init_input(libtrace_t *libtrace) 
89{
90        libtrace->format_data = (struct libtrace_format_data_t *)
91                malloc(sizeof(struct libtrace_format_data_t));
92        FORMAT(libtrace->format_data)->fd = -1;
93        FORMAT(libtrace->format_data)->promisc = -1;
94        FORMAT(libtrace->format_data)->snaplen = LIBTRACE_PACKET_BUFSIZE;
95        FORMAT(libtrace->format_data)->filter = NULL;
96        FORMAT(libtrace->format_data)->stats_valid = 0;
97
98        return 0;
99}
100
101static int linuxnative_init_output(libtrace_out_t *libtrace)
102{
103        libtrace->format_data = (struct libtrace_linuxnative_format_data_t*)
104                malloc(sizeof(struct libtrace_linuxnative_format_data_t));
105        DATAOUT(libtrace)->fd = -1;
106
107        return 0;
108}
109
110static int linuxnative_start_input(libtrace_t *libtrace)
111{
112        struct sockaddr_ll addr;
113        int one = 1;
114        memset(&addr,0,sizeof(addr));
115        libtrace_filter_t *filter = FORMAT(libtrace->format_data)->filter;
116        FORMAT(libtrace->format_data)->fd = 
117                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
118        if (FORMAT(libtrace->format_data)->fd==-1) {
119                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Could not create raw socket");
120                free(libtrace->format_data);
121                return -1;
122        }
123        addr.sll_family = AF_PACKET;
124        addr.sll_protocol = htons(ETH_P_ALL);
125        if (strlen(libtrace->uridata)) {
126                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
127                if (addr.sll_ifindex == 0) {
128                        close(FORMAT(libtrace->format_data)->fd);
129                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to find interface %s", libtrace->uridata);
130                        free(libtrace->format_data);
131                        return -1;
132                }
133        }
134        else {
135                addr.sll_ifindex = 0;
136        }
137        if (bind(FORMAT(libtrace->format_data)->fd,
138                                (struct sockaddr*)&addr,
139                                (socklen_t)sizeof(addr))==-1) {
140                free(libtrace->format_data);
141                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to bind to interface %s", libtrace->uridata);
142                return -1;
143        }
144
145        /* If promisc hasn't been specified, set it to "true" if we're
146         * capturing on one interface, or "false" if we're capturing on
147         * all interfaces.
148         */ 
149        if (FORMAT(libtrace->format_data)->promisc==-1) {
150                if (addr.sll_ifindex!=0)
151                        FORMAT(libtrace->format_data)->promisc=1;
152                else
153                        FORMAT(libtrace->format_data)->promisc=0;
154        }
155                               
156        if (FORMAT(libtrace->format_data)->promisc) {
157                struct packet_mreq mreq;
158                socklen_t socklen = sizeof(mreq);
159                memset(&mreq,0,sizeof(mreq));
160                mreq.mr_ifindex = addr.sll_ifindex;
161                mreq.mr_type = PACKET_MR_PROMISC;
162                if (setsockopt(FORMAT(libtrace->format_data)->fd,
163                                SOL_PACKET,
164                                PACKET_ADD_MEMBERSHIP,
165                                &mreq,
166                                socklen)==-1) {
167                        perror("setsockopt(PROMISC)");
168                }
169        }
170
171        if (setsockopt(FORMAT(libtrace->format_data)->fd,
172                        SOL_SOCKET,
173                        SO_TIMESTAMP,
174                        &one,
175                        (socklen_t)sizeof(one))==-1) {
176                perror("setsockopt(SO_TIMESTAMP)");
177        }
178
179        /* Push BPF filter into the kernel. At this stage we can safely assume
180         * that the filterstring has been compiled, or the filter was supplied
181         * pre-compiled.
182         */
183        if (filter != NULL) {
184                assert(filter->flag == 1);
185                if (setsockopt(FORMAT(libtrace->format_data)->fd,
186                                        SOL_SOCKET,
187                                        SO_ATTACH_FILTER,
188                                        &filter->filter,
189                                        sizeof(filter->filter)) == -1) {
190                        perror("setsockopt(SO_ATTACH_FILTER)");
191                } else { 
192                        /* The socket accepted the filter, so we need to
193                         * consume any buffered packets that were received
194                         * between opening the socket and applying the filter.
195                         */
196                        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
197                        while(recv(FORMAT(libtrace->format_data)->fd,
198                                        buf,
199                                        (size_t) LIBTRACE_PACKET_BUFSIZE,
200                                        MSG_DONTWAIT) != -1) { }
201                        free(buf);
202                }
203        }
204
205        FORMAT(libtrace->format_data)->stats_valid=0;
206                                       
207        return 0;
208}
209
210static int linuxnative_start_output(libtrace_out_t *libtrace)
211{
212        FORMAT(libtrace->format_data)->fd = 
213                                socket(PF_PACKET, SOCK_RAW, 0);
214        if (FORMAT(libtrace->format_data)->fd==-1) {
215                free(libtrace->format_data);
216                return -1;
217        }
218        FORMAT(libtrace->format_data)->stats_valid=0;
219
220        return 0;
221}
222
223static int linuxnative_pause_input(libtrace_t *libtrace)
224{
225        close(FORMAT(libtrace->format_data)->fd);
226        FORMAT(libtrace->format_data)->fd=-1;
227
228        return 0;
229}
230
231static int linuxnative_fin_input(libtrace_t *libtrace) 
232{
233        if (FORMAT(libtrace->format_data)->filter != NULL)
234                free(FORMAT(libtrace->format_data)->filter);
235        free(libtrace->format_data);
236       
237        return 0;
238}
239
240static int linuxnative_fin_output(libtrace_out_t *libtrace)
241{
242        close(DATAOUT(libtrace)->fd);
243        DATAOUT(libtrace)->fd=-1;
244        free(libtrace->format_data);
245        return 0;
246}
247
248static int linuxnative_configure_bpf(libtrace_t *libtrace, 
249                libtrace_filter_t *filter) {
250#ifdef HAVE_LIBPCAP
251        struct ifreq ifr;
252        unsigned int arphrd;
253        libtrace_dlt_t dlt;
254        libtrace_filter_t *f;
255        int sock;
256        pcap_t *pcap;
257
258        /* Take a copy of the filter object as it was passed in */
259        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
260        memcpy(f, filter, sizeof(libtrace_filter_t));
261       
262        /* If we are passed a filter with "flag" set to zero, then we must
263         * compile the filterstring before continuing. This involves
264         * determining the linktype, passing the filterstring to libpcap to
265         * compile, and saving the result for trace_start() to push into the
266         * kernel.
267         * If flag is set to one, then the filter was probably generated using
268         * trace_create_filter_from_bytecode() and so we don't need to do
269         * anything (we've just copied it above).
270         */
271        if (f->flag == 0) {
272                sock = socket(PF_INET, SOCK_STREAM, 0);
273                memset(&ifr, 0, sizeof(struct ifreq));
274                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE);
275                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
276                        perror("Can't get HWADDR for interface");
277                        return -1;
278                }
279                close(sock);
280
281                arphrd = ifr.ifr_hwaddr.sa_family;
282                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
283
284                pcap = pcap_open_dead(dlt, 
285                                FORMAT(libtrace->format_data)->snaplen);
286
287                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
288                        perror("PCAP failed to compile the filterstring");
289                        return -1;
290                }
291
292                pcap_close(pcap);
293               
294                /* Set the "flag" to indicate that the filterstring has been
295                 * compiled
296                 */
297                f->flag = 1;
298        }
299       
300        if (FORMAT(libtrace->format_data)->filter != NULL)
301                free(FORMAT(libtrace->format_data)->filter);
302       
303        FORMAT(libtrace->format_data)->filter = f;
304       
305        return 0;
306#else
307        return -1
308#endif
309}
310static int linuxnative_config_input(libtrace_t *libtrace,
311                trace_option_t option,
312                void *data)
313{
314        switch(option) {
315                case TRACE_OPTION_SNAPLEN:
316                        FORMAT(libtrace->format_data)->snaplen=*(int*)data;
317                        return 0;
318                case TRACE_OPTION_PROMISC:
319                        FORMAT(libtrace->format_data)->promisc=*(int*)data;
320                        return 0;
321                case TRACE_OPTION_FILTER:
322                        return linuxnative_configure_bpf(libtrace, 
323                                        (libtrace_filter_t *) data);
324                case TRACE_OPTION_META_FREQ:
325                        /* No meta-data for this format */
326                        break;
327                case TRACE_OPTION_EVENT_REALTIME:
328                        break;
329                /* Avoid default: so that future options will cause a warning
330                 * here to remind us to implement it, or flag it as
331                 * unimplementable
332                 */
333        }
334       
335        /* Don't set an error - trace_config will try to deal with the
336         * option and will set an error if it fails */
337        return -1;
338}
339
340static int linuxnative_prepare_packet(libtrace_t *libtrace, 
341                libtrace_packet_t *packet, void *buffer, 
342                libtrace_rt_types_t rt_type, uint32_t flags) {
343
344        if (packet->buffer != buffer &&
345                        packet->buf_control == TRACE_CTRL_PACKET) {
346                free(packet->buffer);
347        }
348
349        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
350                packet->buf_control = TRACE_CTRL_PACKET;
351        } else
352                packet->buf_control = TRACE_CTRL_EXTERNAL;
353
354
355        packet->buffer = buffer;
356        packet->header = buffer;
357        packet->payload = (char *)buffer + 
358                sizeof(struct libtrace_linuxnative_header);
359        packet->type = rt_type;
360
361        if (libtrace->format_data == NULL) {
362                if (linuxnative_init_input(libtrace))
363                        return -1;
364        }
365        return 0;
366       
367}
368
369#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
370
371/* 20 isn't enough on x86_64 */
372#define CMSG_BUF_SIZE 128
373static int linuxnative_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) 
374{
375        struct libtrace_linuxnative_header *hdr;
376        struct msghdr msghdr;
377        struct iovec iovec;
378        unsigned char controlbuf[CMSG_BUF_SIZE];
379        struct cmsghdr *cmsg;
380        socklen_t socklen;
381        int snaplen;
382        uint32_t flags = 0;
383       
384        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
385                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
386                if (!packet->buffer) {
387                        perror("Cannot allocate buffer");
388                }
389        }
390
391        flags |= TRACE_PREP_OWN_BUFFER;
392       
393        packet->type = TRACE_RT_DATA_LINUX_NATIVE;
394
395        hdr=(struct libtrace_linuxnative_header*)packet->buffer;
396        socklen=sizeof(hdr->hdr);
397        snaplen=LIBTRACE_MIN(
398                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*hdr),
399                        (int)FORMAT(libtrace->format_data)->snaplen);
400
401        msghdr.msg_name = &hdr->hdr;
402        msghdr.msg_namelen = sizeof(struct sockaddr_ll);
403
404        msghdr.msg_iov = &iovec;
405        msghdr.msg_iovlen = 1;
406
407        msghdr.msg_control = &controlbuf;
408        msghdr.msg_controllen = CMSG_BUF_SIZE;
409        msghdr.msg_flags = 0;
410
411        iovec.iov_base = (void*)packet->buffer;
412        iovec.iov_len = snaplen;
413
414        hdr->wirelen = recvmsg(FORMAT(libtrace->format_data)->fd, &msghdr, 0);
415
416        if (hdr->wirelen==-1) {
417                trace_set_err(libtrace,errno,"recvmsg");
418                return -1;
419        }
420
421        hdr->caplen=LIBTRACE_MIN(snaplen,hdr->wirelen);
422
423        for (cmsg = CMSG_FIRSTHDR(&msghdr);
424                        cmsg != NULL;
425                        cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
426                if (cmsg->cmsg_level == SOL_SOCKET
427                        && cmsg->cmsg_type == SO_TIMESTAMP
428                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timeval))) {
429                        memcpy(&hdr->ts, CMSG_DATA(cmsg),
430                                        sizeof(struct timeval));
431                        break;
432                }
433        }
434
435        if (cmsg == NULL && ioctl(FORMAT(libtrace->format_data)->fd,
436                                SIOCGSTAMP,&hdr->ts)==-1)
437                perror("ioctl(SIOCGSTAMP)");
438
439        if (linuxnative_prepare_packet(libtrace, packet, packet->buffer,
440                                packet->type, flags))
441                return -1;
442       
443        return hdr->wirelen+sizeof(*hdr);
444}
445
446static int linuxnative_write_packet(libtrace_out_t *trace, 
447                libtrace_packet_t *packet) 
448{
449        struct sockaddr_ll hdr;
450
451        hdr.sll_family = AF_PACKET;
452        hdr.sll_protocol = 0;
453        hdr.sll_ifindex = if_nametoindex(trace->uridata);
454        hdr.sll_hatype = 0;
455        hdr.sll_pkttype = 0;
456        hdr.sll_halen = htons(6); /* FIXME */
457        memcpy(hdr.sll_addr,packet->payload,(size_t)hdr.sll_halen);
458
459        return sendto(DATAOUT(trace)->fd,
460                        packet->payload,
461                        trace_get_capture_length(packet),
462                        0,
463                        (struct sockaddr*)&hdr, (socklen_t)sizeof(hdr));
464
465}
466
467static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
468        int linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
469                                ->hdr.sll_hatype);
470        switch (linktype) {
471                case ARPHRD_ETHER:
472                        return TRACE_TYPE_ETH;
473                case ARPHRD_PPP:
474                        return TRACE_TYPE_NONE;
475                case ARPHRD_80211_RADIOTAP:
476                        return TRACE_TYPE_80211_RADIO;
477                case ARPHRD_IEEE80211:
478                        return TRACE_TYPE_80211;
479                case ARPHRD_SIT:
480                case ARPHRD_NONE:
481                        return TRACE_TYPE_NONE;
482                default: /* shrug, beyond me! */
483                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
484                        return (libtrace_linktype_t)~0U;
485        }
486}
487
488static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
489        switch (((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype) {
490                case PACKET_OUTGOING:
491                case PACKET_LOOPBACK:
492                        return TRACE_DIR_OUTGOING;
493                default:
494                        return TRACE_DIR_INCOMING;
495        }
496}
497
498static libtrace_direction_t linuxnative_set_direction(
499                libtrace_packet_t *packet,
500                libtrace_direction_t direction) {
501
502        switch (direction) {
503                case TRACE_DIR_OUTGOING:
504                        ((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype = PACKET_OUTGOING;
505                        return TRACE_DIR_OUTGOING;
506                case TRACE_DIR_INCOMING:
507                        ((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype = PACKET_HOST;
508                        return TRACE_DIR_INCOMING;
509                default:
510                        return -1;
511        }
512}
513
514static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet) 
515{
516        return ((struct libtrace_linuxnative_header*)(packet->buffer))->ts;
517}
518
519static int linuxnative_get_capture_length(const libtrace_packet_t *packet)
520{
521        return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen;
522}
523
524static int linuxnative_get_wire_length(const libtrace_packet_t *packet) 
525{
526        return ((struct libtrace_linuxnative_header*)(packet->buffer))->wirelen;
527}
528
529static int linuxnative_get_framing_length(UNUSED
530                const libtrace_packet_t *packet) 
531{
532        return sizeof(struct libtrace_linuxnative_header);
533}
534
535static int linuxnative_get_fd(const libtrace_t *trace) {
536        if (trace->format_data == NULL)
537                return -1;
538        return FORMAT(trace->format_data)->fd;
539}
540
541/* Linux doesn't keep track how many packets were seen before filtering
542 * so we can't tell how many packets were filtered.  Bugger.  So annoying.
543 *
544 * Since we tell libtrace that we do support filtering, if we don't declare
545 * this here as failing, libtrace will happily report for us that it didn't
546 * filter any packets, so don't lie -- return that we don't know.
547 */
548static uint64_t linuxnative_get_filtered_packets(libtrace_t *trace) {
549        return UINT64_MAX;
550}
551
552/* Number of packets that past filtering */
553static uint64_t linuxnative_get_captured_packets(libtrace_t *trace) {
554        if (trace->format_data == NULL)
555                return UINT64_MAX;
556        if (FORMAT(trace->format_data)->fd == -1) {
557                /* This is probably a 'dead' trace so obviously we can't query
558                 * the socket for capture counts, can we? */
559                return UINT64_MAX;
560        }
561       
562        if ((FORMAT(trace->format_data)->stats_valid & 1) 
563                        || FORMAT(trace->format_data)->stats_valid == 0) {
564                socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
565                getsockopt(FORMAT(trace->format_data)->fd, 
566                                SOL_PACKET,
567                                PACKET_STATISTICS,
568                                &FORMAT(trace->format_data)->stats,
569                                &len);
570                FORMAT(trace->format_data)->stats_valid |= 1;
571        }
572
573        return FORMAT(trace->format_data)->stats.tp_packets;
574}
575
576/* Number of packets that got past filtering and were then dropped because
577 * of lack of space
578 */
579static uint64_t linuxnative_get_dropped_packets(libtrace_t *trace) {
580        if (trace->format_data == NULL)
581                return UINT64_MAX;
582        if (FORMAT(trace->format_data)->fd == -1) {
583                /* This is probably a 'dead' trace so obviously we can't query
584                 * the socket for drop counts, can we? */
585                return UINT64_MAX;
586        }
587       
588        if ((FORMAT(trace->format_data)->stats_valid & 2)
589                        || (FORMAT(trace->format_data)->stats_valid==0)) {
590                socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
591                getsockopt(FORMAT(trace->format_data)->fd, 
592                                SOL_PACKET,
593                                PACKET_STATISTICS,
594                                &FORMAT(trace->format_data)->stats,
595                                &len);
596                FORMAT(trace->format_data)->stats_valid |= 2;
597        }
598
599        return FORMAT(trace->format_data)->stats.tp_drops;
600}
601
602static void linuxnative_help(void) {
603        printf("linuxnative format module: $Revision$\n");
604        printf("Supported input URIs:\n");
605        printf("\tint:\n");
606        printf("\n");
607        printf("Supported output URIs:\n");
608        printf("\tnone\n");
609        printf("\n");
610        return;
611}
612static struct libtrace_format_t linuxnative = {
613        "int",
614        "$Id$",
615        TRACE_FORMAT_LINUX_NATIVE,
616        linuxnative_init_input,         /* init_input */
617        linuxnative_config_input,       /* config_input */
618        linuxnative_start_input,        /* start_input */
619        linuxnative_pause_input,        /* pause_input */
620        linuxnative_init_output,        /* init_output */
621        NULL,                           /* config_output */
622        linuxnative_start_output,       /* start_ouput */
623        linuxnative_fin_input,          /* fin_input */
624        linuxnative_fin_output,         /* fin_output */
625        linuxnative_read_packet,        /* read_packet */
626        linuxnative_prepare_packet,     /* prepare_packet */
627        NULL,                           /* fin_packet */
628        linuxnative_write_packet,       /* write_packet */
629        linuxnative_get_link_type,      /* get_link_type */
630        linuxnative_get_direction,      /* get_direction */
631        linuxnative_set_direction,      /* set_direction */
632        NULL,                           /* get_erf_timestamp */
633        linuxnative_get_timeval,        /* get_timeval */
634        NULL,                           /* get_seconds */
635        NULL,                           /* seek_erf */
636        NULL,                           /* seek_timeval */
637        NULL,                           /* seek_seconds */
638        linuxnative_get_capture_length, /* get_capture_length */
639        linuxnative_get_wire_length,    /* get_wire_length */
640        linuxnative_get_framing_length, /* get_framing_length */
641        NULL,                           /* set_capture_length */
642        NULL,                           /* get_received_packets */
643        linuxnative_get_filtered_packets,/* get_filtered_packets */
644        linuxnative_get_dropped_packets,/* get_dropped_packets */
645        linuxnative_get_captured_packets,/* get_captured_packets */
646        linuxnative_get_fd,             /* get_fd */
647        trace_event_device,             /* trace_event */
648        linuxnative_help,               /* help */
649        NULL
650};
651
652void linuxnative_constructor(void) {
653        register_format(&linuxnative);
654}
Note: See TracBrowser for help on using the repository browser.