source: lib/format_linux.c @ cdcaef6

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