source: lib/format_linux.c @ f0fb38f

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