source: lib/format_linux.c @ 1aa4bf7

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

Support using timespec's for dealing with traces

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