source: lib/format_linux.c @ 7fa118f

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

Keep sizes of framing headers passed over the wire specified

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