source: lib/format_linux.c @ b4c3f61

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since b4c3f61 was b4c3f61, checked in by Shane Alcock <salcock@…>, 9 years ago
  • Removed erroneous '_' in all the #ifdefs I just added to format_linux.c :/
  • Removed silly testing output from format_linux.c
  • Simplified queue increment in the ring output code so that it doesn't produce warnings
  • Property mode set to 100644
File size: 48.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *          Richard Sanger
11 *         
12 * All rights reserved.
13 *
14 * This code has been developed by the University of Waikato WAND
15 * research group. For further information please see http://www.wand.net.nz/
16 *
17 * libtrace is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * libtrace is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with libtrace; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30 *
31 * $Id$
32 *
33 */
34
35/* This format module deals with using the Linux Native capture format.
36 *
37 * Linux Native is a LIVE capture format.
38 *
39 * This format also supports writing which will write packets out to the
40 * network as a form of packet replay. This should not be confused with the
41 * RT protocol which is intended to transfer captured packet records between
42 * RT-speaking programs.
43 */
44
45#include "config.h"
46#include "libtrace.h"
47#include "libtrace_int.h"
48#include "format_helper.h"
49#include "libtrace_arphrd.h"
50#include <stdlib.h>
51#include <errno.h>
52#include <unistd.h>
53#include <string.h>
54#include <assert.h>
55
56#ifdef HAVE_INTTYPES_H
57#  include <inttypes.h>
58#else
59# error "Can't find inttypes.h"
60#endif
61
62#ifdef HAVE_NETPACKET_PACKET_H
63
64#include <sys/socket.h>
65#include <netpacket/packet.h>
66#include <net/ethernet.h>
67#include <net/if_arp.h>
68
69#include <net/if.h>
70#include <sys/ioctl.h>
71#include <poll.h>
72#include <sys/mman.h>
73
74/* MAX_ORDER is defined in linux/mmzone.h. 10 is default for 2.4 kernel.
75 * max_order will be decreased by one if the ring buffer fails to allocate.
76 * Used to get correct sized buffers from the kernel.
77 */
78#define MAX_ORDER 10
79static unsigned int max_order = MAX_ORDER;
80
81/* Cached page size, the page size shoudn't be changing */
82static int pagesize = 0;
83
84/* Number of frames in the ring used by both TX and TR rings. More frames
85 * hopefully means less packet loss, especially if traffic comes in bursts.
86 */
87#define CONF_RING_FRAMES        0x100
88
89/* The maximum frames allowed to be waiting in the TX_RING before the kernel is
90 * notified to write them out. Make sure this is less than CONF_RING_FRAMES.
91 * Performance doesn't seem to increase any more when setting this above 10.
92 */
93#define TX_MAX_QUEUE            10
94
95/* Get current frame in the ring buffer*/
96#define GET_CURRENT_BUFFER(libtrace) ((void *) FORMAT(libtrace->format_data)->rx_ring + \
97        (FORMAT(libtrace->format_data)->rxring_offset * FORMAT(libtrace->format_data)->req.tp_frame_size))
98
99
100#else   /* HAVE_NETPACKET_PACKET_H */
101/* Need to know what a sockaddr_ll looks like */
102struct sockaddr_ll {
103        uint16_t sll_family;
104        uint16_t sll_protocol;
105        int32_t  sll_ifindex;
106        uint16_t sll_hatype;
107        uint8_t  sll_pkttype;
108        uint8_t  sll_halen;
109        uint8_t  sll_addr[8];
110};
111
112/* Packet types.  */
113
114#define PACKET_HOST             0               /* To us.  */
115#define PACKET_BROADCAST        1               /* To all.  */
116#define PACKET_MULTICAST        2               /* To group.  */
117#define PACKET_OTHERHOST        3               /* To someone else.  */
118#define PACKET_OUTGOING         4               /* Originated by us . */
119#define PACKET_LOOPBACK         5
120#define PACKET_FASTROUTE        6
121
122/* Packet socket options.  */
123
124#define PACKET_ADD_MEMBERSHIP           1
125#define PACKET_DROP_MEMBERSHIP          2
126#define PACKET_RECV_OUTPUT              3
127#define PACKET_RX_RING                  5
128#define PACKET_STATISTICS               6
129
130
131#endif /* HAVE_NETPACKET_PACKET_H */
132
133struct tpacket_stats {
134        unsigned int tp_packets;
135        unsigned int tp_drops;
136};
137
138typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t;
139
140/* linux/if_packet.h defines. They are here rather than including the header
141 * this means that we can interpret a ring frame on a kernel that doesn't
142 * support the format directly.
143 */
144#define PACKET_RX_RING  5
145#define PACKET_VERSION  10
146#define PACKET_HDRLEN   11
147#define PACKET_TX_RING  13
148#define TP_STATUS_USER  0x1
149#define TP_STATUS_SEND_REQUEST  0x1
150#define TP_STATUS_AVAILABLE     0x0
151#define TO_TP_HDR(x)    ((struct tpacket2_hdr *) (x))
152#define TPACKET_ALIGNMENT       16
153#define TPACKET_ALIGN(x)        (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
154#define TPACKET2_HDRLEN         (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
155
156enum tpacket_versions {
157        TPACKET_V1,
158        TPACKET_V2
159};
160
161struct tpacket2_hdr {
162        /* Frame status - in use by kernel or libtrace etc. */
163        uint32_t        tp_status;
164        /* Wire length */
165        uint32_t        tp_len;
166        /* Captured length */
167        uint32_t        tp_snaplen;
168        /* Offset in bytes from frame start to the mac (link layer) header */
169        uint16_t        tp_mac;
170        /* Offset in bytes from frame start to the net (network layer) header */
171        uint16_t        tp_net;
172        /* Timestamp */
173        uint32_t        tp_sec;
174        uint32_t        tp_nsec;
175        /* Not used VLAN tag control information */
176        uint16_t        tp_vlan_tci;
177        uint16_t        tp_padding;
178};
179
180struct tpacket_req {
181        unsigned int tp_block_size;  /* Minimal size of contiguous block */
182        unsigned int tp_block_nr;    /* Number of blocks */
183        unsigned int tp_frame_size;  /* Size of frame */
184        unsigned int tp_frame_nr;    /* Total number of frames */
185};
186
187struct linux_format_data_t {
188        /* The file descriptor being used for the capture */
189        int fd;
190        /* The snap length for the capture */
191        int snaplen;
192        /* Flag indicating whether the interface should be placed in
193         * promiscuous mode */
194        int promisc;
195        /* The timestamp format used by the capture */ 
196        timestamptype_t timestamptype;
197        /* A BPF filter that is applied to every captured packet */
198        libtrace_filter_t *filter;
199        /* Statistics for the capture process, e.g. dropped packet counts */
200        struct tpacket_stats stats;
201        /* Flag indicating whether the statistics are current or not */
202        int stats_valid;
203        /* The rx ring mmap location*/
204        char * rx_ring;
205        /* The current frame number within the rx ring */       
206        int rxring_offset;
207        /* The format this trace is using linuxring or linuxnative */
208        libtrace_rt_types_t format;
209        /* The current ring buffer layout */
210        struct tpacket_req req;
211};
212
213
214/* Note that this structure is passed over the wire in rt encapsulation, and
215 * thus we need to be careful with data sizes.  timeval's and timespec's
216 * can also change their size on 32/64 machines.
217 */
218
219/* Format header for encapsulating packets captured using linux native */
220struct libtrace_linuxnative_header {
221        /* Timestamp of the packet, as a timeval */
222        struct {
223                uint32_t tv_sec;
224                uint32_t tv_usec;
225        } tv;
226        /* Timestamp of the packet, as a timespec */
227        struct {
228                uint32_t tv_sec;
229                uint32_t tv_nsec;
230        } ts;
231        /* The timestamp format used by the process that captured this packet */
232        uint8_t timestamptype;
233        /* Wire length */
234        uint32_t wirelen;
235        /* Capture length */
236        uint32_t caplen;
237        /* The linux native header itself */
238        struct sockaddr_ll hdr;
239};
240
241struct linux_output_format_data_t {
242        /* The file descriptor used to write the packets */
243        int fd;
244        /* The tx ring mmap location */
245        char * tx_ring;
246        /* The current frame number within the tx ring */       
247        int txring_offset;
248        /* The current ring buffer layout */
249        struct tpacket_req req;
250        /* Our sockaddr structure, here so we can cache the interface number */
251        struct sockaddr_ll sock_hdr;
252        /* The (maximum) number of packets that haven't been written */
253        int queue;
254        /* The format this trace is using linuxring or linuxnative */
255        libtrace_rt_types_t format;
256};
257
258/* Get the sockaddr_ll structure from a frame */
259#define GET_SOCKADDR_HDR(x)  ((struct sockaddr_ll *) (((char *) (x))\
260        + TPACKET_ALIGN(sizeof(struct tpacket2_hdr))))
261
262#define TPACKET_HDRLEN TPACKET2_HDRLEN
263
264#define FORMAT(x) ((struct linux_format_data_t*)(x))
265#define DATAOUT(x) ((struct linux_output_format_data_t*)((x)->format_data))
266
267/* Get the start of the captured data. I'm not sure if tp_mac (link layer) is
268 * always guaranteed. If it's not there then just use tp_net.
269 */
270#define TP_TRACE_START(mac, net, hdrend) \
271        ((mac) > (hdrend) && (mac) < (net) ? (mac) : (net))
272
273
274#ifdef HAVE_NETPACKET_PACKET_H
275
276/*
277 * Try figure out the best sizes for the ring buffer. Ensure that:
278 * - max(Block_size) == page_size << max_order
279 * - Frame_size == page_size << x (so that block_size%frame_size == 0)
280 *   This means that there will be no wasted space between blocks
281 * - Frame_size < block_size
282 * - Frame_size is as close as possible to LIBTRACE_PACKET_BUFSIZE, but not
283 *   bigger
284 * - Frame_nr = Block_nr * (frames per block)
285 * - CONF_RING_FRAMES is used a minimum number of frames to hold
286 * - Calculates based on max_order and buf_min
287 */
288static void calculate_buffers(struct tpacket_req * req, int fd, char * uri){
289       
290        struct ifreq ifr;
291        unsigned mtu = LIBTRACE_PACKET_BUFSIZE;
292        pagesize = getpagesize();
293
294        /* Don't bother trying to set frame size above mtu linux will drop
295         * these anyway
296         */
297        strcpy(ifr.ifr_name, uri);
298        if (ioctl(fd, SIOCGIFMTU, (caddr_t) &ifr) >= 0) 
299                mtu = ifr.ifr_mtu;
300        if(mtu > LIBTRACE_PACKET_BUFSIZE)
301                mtu = LIBTRACE_PACKET_BUFSIZE;
302
303        /* Calculate frame size */
304        req->tp_frame_size = pagesize;
305        while(req->tp_frame_size < mtu && req->tp_frame_size < LIBTRACE_PACKET_BUFSIZE){
306                req->tp_frame_size <<= 1;
307        }
308        if(req->tp_frame_size > LIBTRACE_PACKET_BUFSIZE)
309                req->tp_frame_size >>= 1;
310
311        /* Calculate block size */
312        req->tp_block_size = pagesize << max_order;
313        do{
314                req->tp_block_size >>= 1;
315        } while((CONF_RING_FRAMES * req->tp_frame_size) <= req->tp_block_size);
316        req->tp_block_size <<= 1;
317       
318        /* Calculate number of blocks */
319        req->tp_block_nr = (CONF_RING_FRAMES * req->tp_frame_size) 
320                        / req->tp_block_size;
321        if((CONF_RING_FRAMES * req->tp_frame_size) % req->tp_block_size != 0)
322                req->tp_block_nr++;
323
324        /* Calculate packets such that we use all the space we have to allocated */
325        req->tp_frame_nr = req->tp_block_nr * 
326                        (req->tp_block_size / req->tp_frame_size);
327
328        /*printf("MaxO 0x%x BS 0x%x BN 0x%x FS 0x%x FN 0x%x\n",
329                max_order,
330                req->tp_block_size,
331                req->tp_block_nr,
332                req->tp_frame_size,
333                req->tp_frame_nr);*/
334       
335        /* In case we have some silly values*/
336        assert(req->tp_block_size);
337        assert(req->tp_block_nr);
338        assert(req->tp_frame_size);
339        assert(req->tp_frame_nr);
340        assert(req->tp_block_size % req->tp_frame_size == 0);
341}
342
343
344static int linuxnative_probe_filename(const char *filename)
345{
346        /* Is this an interface? */
347        return (if_nametoindex(filename) != 0);
348}
349
350static inline void init_input(libtrace_t *libtrace){
351        libtrace->format_data = (struct linux_format_data_t *)
352                malloc(sizeof(struct linux_format_data_t));
353        FORMAT(libtrace->format_data)->fd = -1;
354        FORMAT(libtrace->format_data)->promisc = -1;
355        FORMAT(libtrace->format_data)->snaplen = LIBTRACE_PACKET_BUFSIZE;
356        FORMAT(libtrace->format_data)->filter = NULL;
357        FORMAT(libtrace->format_data)->stats_valid = 0;
358        FORMAT(libtrace->format_data)->rx_ring = NULL;
359        FORMAT(libtrace->format_data)->rxring_offset = 0;
360}
361static int linuxring_init_input(libtrace_t *libtrace) 
362{       
363        init_input(libtrace);
364        FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_RING;
365        return 0;
366}
367static int linuxnative_init_input(libtrace_t *libtrace) 
368{
369        init_input(libtrace);
370        FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_NATIVE;
371        return 0;
372}
373
374static inline void init_output(libtrace_out_t *libtrace)
375{
376        libtrace->format_data = (struct linux_output_format_data_t*)
377                malloc(sizeof(struct linux_output_format_data_t));
378        DATAOUT(libtrace)->fd = -1;
379        DATAOUT(libtrace)->tx_ring = NULL;
380        DATAOUT(libtrace)->txring_offset = 0;
381        DATAOUT(libtrace)->queue = 0;
382}
383static int linuxnative_init_output(libtrace_out_t *libtrace)
384{
385        init_output(libtrace);
386        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_NATIVE;
387        return 0;
388}
389static int linuxring_init_output(libtrace_out_t *libtrace)
390{
391        init_output(libtrace);
392        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_RING;
393        return 0;
394}
395
396static int linuxnative_start_input(libtrace_t *libtrace)
397{
398        struct sockaddr_ll addr;
399        int one = 1;
400        memset(&addr,0,sizeof(addr));
401        libtrace_filter_t *filter = FORMAT(libtrace->format_data)->filter;
402       
403        /* Create a raw socket for reading packets on */
404        FORMAT(libtrace->format_data)->fd = 
405                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
406        if (FORMAT(libtrace->format_data)->fd==-1) {
407                trace_set_err(libtrace, errno, "Could not create raw socket");
408                free(libtrace->format_data);
409                libtrace->format_data = NULL;
410                return -1;
411        }
412
413        /* Bind to the capture interface */
414        addr.sll_family = AF_PACKET;
415        addr.sll_protocol = htons(ETH_P_ALL);
416        if (strlen(libtrace->uridata)) {
417                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
418                if (addr.sll_ifindex == 0) {
419                        close(FORMAT(libtrace->format_data)->fd);
420                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to find interface %s", libtrace->uridata);
421                        free(libtrace->format_data);
422                        libtrace->format_data = NULL;
423                        return -1;
424                }
425        }
426        else {
427                addr.sll_ifindex = 0;
428        }
429        if (bind(FORMAT(libtrace->format_data)->fd,
430                                (struct sockaddr*)&addr,
431                                (socklen_t)sizeof(addr))==-1) {
432                free(libtrace->format_data);
433                libtrace->format_data = NULL;
434                trace_set_err(libtrace, errno, "Failed to bind to interface %s", libtrace->uridata);
435                return -1;
436        }
437
438        /* If promisc hasn't been specified, set it to "true" if we're
439         * capturing on one interface, or "false" if we're capturing on
440         * all interfaces.
441         */ 
442        if (FORMAT(libtrace->format_data)->promisc==-1) {
443                if (addr.sll_ifindex!=0)
444                        FORMAT(libtrace->format_data)->promisc=1;
445                else
446                        FORMAT(libtrace->format_data)->promisc=0;
447        }
448       
449        /* Enable promiscuous mode, if requested */                     
450        if (FORMAT(libtrace->format_data)->promisc) {
451                struct packet_mreq mreq;
452                socklen_t socklen = sizeof(mreq);
453                memset(&mreq,0,sizeof(mreq));
454                mreq.mr_ifindex = addr.sll_ifindex;
455                mreq.mr_type = PACKET_MR_PROMISC;
456                if (setsockopt(FORMAT(libtrace->format_data)->fd,
457                                SOL_PACKET,
458                                PACKET_ADD_MEMBERSHIP,
459                                &mreq,
460                                socklen)==-1) {
461                        perror("setsockopt(PROMISC)");
462                }
463        }
464
465        /* Set the timestamp option on the socket - aim for the most detailed
466         * clock resolution possible */
467#ifdef SO_TIMESTAMPNS
468        if (setsockopt(FORMAT(libtrace->format_data)->fd,
469                        SOL_SOCKET,
470                        SO_TIMESTAMPNS,
471                        &one,
472                        (socklen_t)sizeof(one))!=-1) {
473                FORMAT(libtrace->format_data)->timestamptype = TS_TIMESPEC;
474        }
475        else
476        /* DANGER: This is a dangling else to only do the next setsockopt() if we fail the first! */
477#endif
478        if (setsockopt(FORMAT(libtrace->format_data)->fd,
479                        SOL_SOCKET,
480                        SO_TIMESTAMP,
481                        &one,
482                        (socklen_t)sizeof(one))!=-1) {
483                FORMAT(libtrace->format_data)->timestamptype = TS_TIMEVAL;
484        }
485        else 
486                FORMAT(libtrace->format_data)->timestamptype = TS_NONE;
487
488        /* Push BPF filter into the kernel. At this stage we can safely assume
489         * that the filterstring has been compiled, or the filter was supplied
490         * pre-compiled.
491         */
492        if (filter != NULL) {
493                assert(filter->flag == 1);
494                if (setsockopt(FORMAT(libtrace->format_data)->fd,
495                                        SOL_SOCKET,
496                                        SO_ATTACH_FILTER,
497                                        &filter->filter,
498                                        sizeof(filter->filter)) == -1) {
499                        perror("setsockopt(SO_ATTACH_FILTER)");
500                } else { 
501                        /* The socket accepted the filter, so we need to
502                         * consume any buffered packets that were received
503                         * between opening the socket and applying the filter.
504                         */
505                        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
506                        while(recv(FORMAT(libtrace->format_data)->fd,
507                                        buf,
508                                        (size_t) LIBTRACE_PACKET_BUFSIZE,
509                                        MSG_DONTWAIT) != -1) { }
510                        free(buf);
511                }
512        }
513
514        FORMAT(libtrace->format_data)->stats_valid=0;
515                                       
516        return 0;
517}
518static inline int socket_to_packetmmap(char * uridata, int ring_type, 
519                                        int fd, 
520                                        struct tpacket_req * req,
521                                        char ** ring_location){
522        socklen_t len;
523        int val;
524
525        /* Switch to TPACKET header version 2, we only try support v2 because v1 had problems */
526        val = TPACKET_V2;
527        len = sizeof(val);
528        if(getsockopt(fd, 
529                        SOL_PACKET, 
530                        PACKET_HDRLEN, 
531                        &val, 
532                        &len) == -1){
533                return -1;
534        }
535
536        val = TPACKET_V2;
537        if (setsockopt(fd, 
538                        SOL_PACKET, 
539                        PACKET_VERSION, 
540                        &val, 
541                        sizeof(val)) == -1){
542                return -1;
543        }
544
545        /* Try switch to a ring buffer. If it fails we assume the the kernel 
546         * cannot allocate a block of that size, so decrease max_block and retry.
547         */
548        while(1) {     
549                if (max_order <= 0) {
550                        return -1;
551                }
552                calculate_buffers(req, fd, uridata);
553                if (setsockopt(fd, 
554                                SOL_PACKET, 
555                                ring_type, 
556                                req, 
557                                sizeof(struct tpacket_req)) == -1) {
558                        if(errno == ENOMEM){
559                                max_order--;
560                        } else {
561                                return -1;
562                        }
563
564                } else break;
565        }
566       
567        /* Map the ring buffer into userspace */
568        *ring_location = mmap(NULL, 
569                                        req->tp_block_size * req->tp_block_nr, 
570                                        PROT_READ | PROT_WRITE, 
571                                        MAP_SHARED, 
572                                        fd, 0);
573        if(*ring_location == MAP_FAILED){
574                return -1;
575        }
576        return 0;
577}
578static int linuxring_start_input(libtrace_t *libtrace){
579       
580
581        /* We set the socket up the same and then convert it to PACKET_MMAP */
582        if(linuxnative_start_input(libtrace) != 0)
583                return -1;
584
585        /* Make it a packetmmap */
586        if(socket_to_packetmmap(libtrace->uridata, PACKET_RX_RING, FORMAT(libtrace->format_data)->fd,
587                 &FORMAT(libtrace->format_data)->req, &FORMAT(libtrace->format_data)->rx_ring) != 0){
588                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, 
589                        "TPACKET2 not supported or ring buffer is too large");
590                close(DATAOUT(libtrace)->fd);
591                free(libtrace->format_data);
592                return -1;
593        }
594               
595        return 0;
596}
597
598static int linuxnative_start_output(libtrace_out_t *libtrace)
599{
600        DATAOUT(libtrace)->fd = socket(PF_PACKET, SOCK_RAW, 0);
601        if (DATAOUT(libtrace)->fd==-1) {
602                free(DATAOUT(libtrace));
603                return -1;
604        }       
605
606        return 0;
607}
608
609static int linuxring_start_output(libtrace_out_t *libtrace)
610{
611        /* We set the socket up the same and then convert it to PACKET_MMAP */
612        if(linuxnative_start_output(libtrace) != 0)
613                return -1;
614
615        /* Make it a packetmmap */
616        if(socket_to_packetmmap(libtrace->uridata, PACKET_TX_RING, DATAOUT(libtrace)->fd,
617                 &DATAOUT(libtrace)->req, &DATAOUT(libtrace)->tx_ring) != 0){
618                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, 
619                        "TPACKET2 not supported or ring buffer is too large");
620                close(DATAOUT(libtrace)->fd);
621                free(libtrace->format_data);
622                return -1;
623        }
624       
625        DATAOUT(libtrace)->sock_hdr.sll_family = AF_PACKET;
626        DATAOUT(libtrace)->sock_hdr.sll_protocol = 0;
627        DATAOUT(libtrace)->sock_hdr.sll_ifindex = 
628                                        if_nametoindex(libtrace->uridata);
629        DATAOUT(libtrace)->sock_hdr.sll_hatype = 0;
630        DATAOUT(libtrace)->sock_hdr.sll_pkttype = 0;
631        DATAOUT(libtrace)->sock_hdr.sll_halen = 0;
632        DATAOUT(libtrace)->queue = 0;   
633
634        return 0;
635}
636
637static int linuxnative_pause_input(libtrace_t *libtrace)
638{
639        close(FORMAT(libtrace->format_data)->fd);
640        FORMAT(libtrace->format_data)->fd=-1;
641
642        return 0;
643}
644static int linuxring_pause_input(libtrace_t *libtrace)
645{
646        munmap(FORMAT(libtrace->format_data)->rx_ring, 
647                FORMAT(libtrace->format_data)->req.tp_block_size *
648                        FORMAT(libtrace->format_data)->req.tp_block_nr);
649        FORMAT(libtrace->format_data)->rx_ring = NULL;
650        return linuxnative_pause_input(libtrace);
651}
652
653static int linuxnative_fin_input(libtrace_t *libtrace) 
654{
655        if (libtrace->format_data) {
656                if (FORMAT(libtrace->format_data)->filter != NULL)
657                        free(FORMAT(libtrace->format_data)->filter);
658                free(libtrace->format_data);
659        }
660       
661        return 0;
662}
663
664static int linuxnative_fin_output(libtrace_out_t *libtrace)
665{
666        close(DATAOUT(libtrace)->fd);
667        DATAOUT(libtrace)->fd=-1;
668        free(libtrace->format_data);
669        return 0;
670}
671static int linuxring_fin_output(libtrace_out_t *libtrace)
672{
673        /* Make sure any remaining frames get sent */
674        sendto(DATAOUT(libtrace)->fd, 
675                NULL, 
676                0, 
677                0, 
678                (void *) &DATAOUT(libtrace)->sock_hdr, 
679                sizeof(DATAOUT(libtrace)->sock_hdr));
680
681        /* Unmap our data area */
682        munmap(DATAOUT(libtrace)->tx_ring,
683                DATAOUT(libtrace)->req.tp_block_size * 
684                        DATAOUT(libtrace)->req.tp_block_nr);
685
686        return linuxnative_fin_output(libtrace);
687}
688
689/* Compiles a libtrace BPF filter for use with a linux native socket */
690static int linuxnative_configure_bpf(libtrace_t *libtrace, 
691                libtrace_filter_t *filter) {
692#ifdef HAVE_LIBPCAP
693        struct ifreq ifr;
694        unsigned int arphrd;
695        libtrace_dlt_t dlt;
696        libtrace_filter_t *f;
697        int sock;
698        pcap_t *pcap;
699
700        /* Take a copy of the filter object as it was passed in */
701        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
702        memcpy(f, filter, sizeof(libtrace_filter_t));
703       
704        /* If we are passed a filter with "flag" set to zero, then we must
705         * compile the filterstring before continuing. This involves
706         * determining the linktype, passing the filterstring to libpcap to
707         * compile, and saving the result for trace_start() to push into the
708         * kernel.
709         * If flag is set to one, then the filter was probably generated using
710         * trace_create_filter_from_bytecode() and so we don't need to do
711         * anything (we've just copied it above).
712         */
713        if (f->flag == 0) {
714                sock = socket(PF_INET, SOCK_STREAM, 0);
715                memset(&ifr, 0, sizeof(struct ifreq));
716                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE);
717                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
718                        perror("Can't get HWADDR for interface");
719                        return -1;
720                }
721                close(sock);
722
723                arphrd = ifr.ifr_hwaddr.sa_family;
724                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
725
726                pcap = pcap_open_dead(dlt, 
727                                FORMAT(libtrace->format_data)->snaplen);
728
729                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
730                        perror("PCAP failed to compile the filterstring");
731                        return -1;
732                }
733
734                pcap_close(pcap);
735               
736                /* Set the "flag" to indicate that the filterstring has been
737                 * compiled
738                 */
739                f->flag = 1;
740        }
741       
742        if (FORMAT(libtrace->format_data)->filter != NULL)
743                free(FORMAT(libtrace->format_data)->filter);
744       
745        FORMAT(libtrace->format_data)->filter = f;
746       
747        return 0;
748#else
749        return -1
750#endif
751}
752static int linuxnative_config_input(libtrace_t *libtrace,
753                trace_option_t option,
754                void *data)
755{
756        switch(option) {
757                case TRACE_OPTION_SNAPLEN:
758                        FORMAT(libtrace->format_data)->snaplen=*(int*)data;
759                        return 0;
760                case TRACE_OPTION_PROMISC:
761                        FORMAT(libtrace->format_data)->promisc=*(int*)data;
762                        return 0;
763                case TRACE_OPTION_FILTER:
764                        return linuxnative_configure_bpf(libtrace, 
765                                        (libtrace_filter_t *) data);
766                case TRACE_OPTION_META_FREQ:
767                        /* No meta-data for this format */
768                        break;
769                case TRACE_OPTION_EVENT_REALTIME:
770                        /* Live captures are always going to be in trace time */
771                        break;
772                /* Avoid default: so that future options will cause a warning
773                 * here to remind us to implement it, or flag it as
774                 * unimplementable
775                 */
776        }
777       
778        /* Don't set an error - trace_config will try to deal with the
779         * option and will set an error if it fails */
780        return -1;
781}
782#endif /* HAVE_NETPACKET_PACKET_H */
783
784static int linuxnative_prepare_packet(libtrace_t *libtrace UNUSED, 
785                libtrace_packet_t *packet, void *buffer, 
786                libtrace_rt_types_t rt_type, uint32_t flags) {
787
788        if (packet->buffer != buffer &&
789                        packet->buf_control == TRACE_CTRL_PACKET) {
790                free(packet->buffer);
791        }
792
793        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
794                packet->buf_control = TRACE_CTRL_PACKET;
795        } else
796                packet->buf_control = TRACE_CTRL_EXTERNAL;
797
798
799        packet->buffer = buffer;
800        packet->header = buffer;
801        packet->payload = (char *)buffer + 
802                sizeof(struct libtrace_linuxnative_header);
803        packet->type = rt_type;
804
805        /*
806        if (libtrace->format_data == NULL) {
807                if (linuxnative_init_input(libtrace))
808                        return -1;
809        }
810        */
811        return 0;
812       
813}
814
815static int linuxring_prepare_packet(libtrace_t *libtrace UNUSED, 
816                libtrace_packet_t *packet, void *buffer, 
817                libtrace_rt_types_t rt_type, uint32_t flags) {
818
819        if (packet->buffer != buffer &&
820                        packet->buf_control == TRACE_CTRL_PACKET) {
821                free(packet->buffer);
822        }
823
824        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
825                packet->buf_control = TRACE_CTRL_PACKET;
826        } else
827                packet->buf_control = TRACE_CTRL_EXTERNAL;
828
829
830        packet->buffer = buffer;
831        packet->header = buffer;
832        packet->payload = (char *)buffer + 
833                                        TP_TRACE_START(
834                                        TO_TP_HDR(packet->header)->tp_mac, 
835                                        TO_TP_HDR(packet->header)->tp_net, 
836                                        TPACKET2_HDRLEN);
837        packet->type = rt_type;
838
839        /*
840        if (libtrace->format_data == NULL) {
841                if (linuxnative_init_input(libtrace))
842                        return -1;
843        }
844        */
845        return 0;
846       
847}
848
849#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
850
851/* 20 isn't enough on x86_64 */
852#define CMSG_BUF_SIZE 128
853
854#ifdef HAVE_NETPACKET_PACKET_H
855static int linuxnative_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) 
856{
857        struct libtrace_linuxnative_header *hdr;
858        struct msghdr msghdr;
859        struct iovec iovec;
860        unsigned char controlbuf[CMSG_BUF_SIZE];
861        struct cmsghdr *cmsg;
862        int snaplen;
863        uint32_t flags = 0;
864       
865        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
866                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
867                if (!packet->buffer) {
868                        perror("Cannot allocate buffer");
869                }
870        }
871
872        flags |= TRACE_PREP_OWN_BUFFER;
873       
874        packet->type = TRACE_RT_DATA_LINUX_NATIVE;
875
876        hdr=(struct libtrace_linuxnative_header*)packet->buffer;
877        snaplen=LIBTRACE_MIN(
878                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*hdr),
879                        (int)FORMAT(libtrace->format_data)->snaplen);
880
881        /* Prepare the msghdr and iovec for the kernel to write the
882         * captured packet into. The msghdr will point to the part of our
883         * buffer reserved for sll header, while the iovec will point at
884         * the buffer following the sll header. */
885
886        msghdr.msg_name = &hdr->hdr;
887        msghdr.msg_namelen = sizeof(struct sockaddr_ll);
888
889        msghdr.msg_iov = &iovec;
890        msghdr.msg_iovlen = 1;
891
892        msghdr.msg_control = &controlbuf;
893        msghdr.msg_controllen = CMSG_BUF_SIZE;
894        msghdr.msg_flags = 0;
895
896        iovec.iov_base = (void*)(packet->buffer+sizeof(*hdr));
897        iovec.iov_len = snaplen;
898
899        hdr->wirelen = recvmsg(FORMAT(libtrace->format_data)->fd, &msghdr, 0);
900
901        if (hdr->wirelen==~0U) {
902                trace_set_err(libtrace,errno,"recvmsg");
903                return -1;
904        }
905
906        hdr->caplen=LIBTRACE_MIN((unsigned int)snaplen,(unsigned int)hdr->wirelen);
907
908        /* Extract the timestamps from the msghdr and store them in our
909         * linux native encapsulation, so that we can preserve the formatting
910         * across multiple architectures */
911
912        for (cmsg = CMSG_FIRSTHDR(&msghdr);
913                        cmsg != NULL;
914                        cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
915                if (cmsg->cmsg_level == SOL_SOCKET
916                        && cmsg->cmsg_type == SO_TIMESTAMP
917                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timeval))) {
918                       
919                        struct timeval *tv;
920                        tv = (struct timeval *)CMSG_DATA(cmsg);
921                       
922                       
923                        hdr->tv.tv_sec = tv->tv_sec;
924                        hdr->tv.tv_usec = tv->tv_usec;
925                        hdr->timestamptype = TS_TIMEVAL;
926                        break;
927                } 
928#ifdef SO_TIMESTAMPNS
929                else if (cmsg->cmsg_level == SOL_SOCKET
930                        && cmsg->cmsg_type == SO_TIMESTAMPNS
931                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timespec))) {
932
933                        struct timespec *tv;
934                        tv = (struct timespec *)CMSG_DATA(cmsg);
935
936                        hdr->ts.tv_sec = tv->tv_sec;
937                        hdr->ts.tv_nsec = tv->tv_nsec;
938                        hdr->timestamptype = TS_TIMESPEC;
939                        break;
940                }
941#endif
942        }
943
944        /* Did we not get given a timestamp? Try to get one from the
945         * file descriptor directly */
946        if (cmsg == NULL) {
947                struct timeval tv;
948                if (ioctl(FORMAT(libtrace->format_data)->fd, 
949                                  SIOCGSTAMP,&tv)==0) {
950                        hdr->tv.tv_sec = tv.tv_sec;
951                        hdr->tv.tv_usec = tv.tv_usec;
952                        hdr->timestamptype = TS_TIMEVAL;
953                }
954                else {
955                        hdr->timestamptype = TS_NONE;
956                }
957        }
958
959        /* Buffer contains all of our packet (including our custom header) so
960         * we just need to get prepare_packet to set all our packet pointers
961         * appropriately */
962       
963        if (linuxnative_prepare_packet(libtrace, packet, packet->buffer,
964                                packet->type, flags))
965                return -1;
966       
967        return hdr->wirelen+sizeof(*hdr);
968}
969
970#define LIBTRACE_BETWEEN(test,a,b) ((test) >= (a) && (test) < (b))
971static int linuxring_get_capture_length(const libtrace_packet_t *packet);
972static int linuxring_get_framing_length(const libtrace_packet_t *packet);
973
974/* Release a frame back to the kernel or free() if it's a malloc'd buffer
975 */
976inline static void ring_release_frame(libtrace_t *libtrace, libtrace_packet_t *packet ){
977        /* Free the old packet */
978        if(packet->buffer == NULL)
979                return;
980
981        if(packet->buf_control == TRACE_CTRL_PACKET){
982                free(packet->buffer);
983                packet->buffer = NULL;
984        }
985        if(packet->buf_control == TRACE_CTRL_EXTERNAL) {
986                struct linux_format_data_t *ftd = FORMAT(libtrace->format_data);
987               
988                /* Check it's within our buffer first */
989                if(LIBTRACE_BETWEEN((char *) packet->buffer, 
990                                (char *) ftd->rx_ring,
991                                ftd->rx_ring
992                                + ftd->req.tp_block_size * ftd->req.tp_block_nr)){
993                        TO_TP_HDR(packet->buffer)->tp_status = 0;
994                        packet->buffer = NULL;
995                }
996        }
997}
998
999static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
1000
1001        struct tpacket2_hdr *header;
1002        struct pollfd pollset; 
1003        int ret;
1004       
1005        ring_release_frame(libtrace, packet);
1006       
1007        packet->buf_control = TRACE_CTRL_EXTERNAL;
1008        packet->type = TRACE_RT_DATA_LINUX_RING;
1009       
1010        /* Fetch the current frame */
1011        header = GET_CURRENT_BUFFER(libtrace);
1012        assert((((unsigned long) header) & (pagesize - 1)) == 0);
1013
1014        /* TP_STATUS_USER means that we can use the frame.
1015         * When a slot does not have this flag set, the frame is not
1016         * ready for consumption.
1017         */
1018        while (!(header->tp_status & TP_STATUS_USER)) {
1019                pollset.fd = FORMAT(libtrace->format_data)->fd;
1020                pollset.events = POLLIN;
1021                pollset.revents = 0;
1022                /* Wait for more data */
1023                ret = poll(&pollset, 1, -1);
1024                if (ret < 0) {
1025                        if (errno != EINTR)
1026                        trace_set_err(libtrace,errno,"poll()");
1027                        return -1;
1028                }
1029        }
1030
1031        packet->buffer = header;
1032
1033        /* Move to next buffer */
1034        FORMAT(libtrace->format_data)->rxring_offset++;
1035        FORMAT(libtrace->format_data)->rxring_offset %= FORMAT(libtrace->format_data)->req.tp_frame_nr;
1036
1037        /* We just need to get prepare_packet to set all our packet pointers
1038         * appropriately */
1039        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
1040                                packet->type, 0))
1041                return -1;
1042        return  linuxring_get_framing_length(packet) + 
1043                                linuxring_get_capture_length(packet);
1044
1045}
1046
1047/* Non-blocking read */
1048static libtrace_eventobj_t linuxring_event(libtrace_t *libtrace, libtrace_packet_t *packet) {
1049        struct tpacket2_hdr *header;
1050        libtrace_eventobj_t event = {0,0,0.0,0};
1051
1052        /* We must free the old packet, otherwise select() will instantly return
1053         */
1054        ring_release_frame(libtrace, packet);
1055
1056        /* Fetch the current frame */
1057        header = GET_CURRENT_BUFFER(libtrace);
1058        if(header->tp_status & TP_STATUS_USER){
1059                /* We have a frame waiting */
1060                event.size = linuxring_read_packet(libtrace, packet);
1061                event.type = TRACE_EVENT_PACKET;
1062        } else {
1063                /* Ok we don't have a packet waiting */
1064                event.type = TRACE_EVENT_IOWAIT;
1065                event.fd = FORMAT(libtrace->format_data)->fd;
1066        }
1067
1068        return event;
1069}
1070
1071
1072static int linuxnative_write_packet(libtrace_out_t *trace, 
1073                libtrace_packet_t *packet) 
1074{
1075        struct sockaddr_ll hdr;
1076
1077        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
1078                return 0;
1079
1080        hdr.sll_family = AF_PACKET;
1081        hdr.sll_protocol = 0;
1082        hdr.sll_ifindex = if_nametoindex(trace->uridata);
1083        hdr.sll_hatype = 0;
1084        hdr.sll_pkttype = 0;
1085        hdr.sll_halen = htons(6); /* FIXME */
1086        memcpy(hdr.sll_addr,packet->payload,(size_t)ntohs(hdr.sll_halen));
1087
1088        /* This is pretty easy, just send the payload using sendto() (after
1089         * setting up the sll header properly, of course) */
1090        return sendto(DATAOUT(trace)->fd,
1091                        packet->payload,
1092                        trace_get_capture_length(packet),
1093                        0,
1094                        (struct sockaddr*)&hdr, (socklen_t)sizeof(hdr));
1095
1096}
1097static int linuxring_write_packet(libtrace_out_t *trace, 
1098                libtrace_packet_t *packet)
1099{
1100        struct tpacket2_hdr *header;
1101        struct pollfd pollset;
1102        struct socket_addr;
1103        int ret; 
1104        unsigned max_size;
1105        void * off;
1106
1107        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
1108                return 0;
1109
1110        max_size = DATAOUT(trace)->req.tp_frame_size - 
1111                 - TPACKET_HDRLEN + sizeof(struct sockaddr_ll);
1112
1113        header = (void *) DATAOUT(trace)->tx_ring + 
1114        (DATAOUT(trace)->txring_offset * DATAOUT(trace)->req.tp_frame_size);
1115
1116        while(header->tp_status != TP_STATUS_AVAILABLE){
1117                /* if none available: wait on more data */
1118                pollset.fd = DATAOUT(trace)->fd;
1119                pollset.events = POLLOUT;
1120                pollset.revents = 0;
1121                ret = poll(&pollset, 1, 1000);
1122                if (ret < 0 && errno != EINTR) {
1123                        perror("poll");
1124                        return -1;
1125                }
1126                if(ret == 0) 
1127                        /* Timeout something has gone wrong - maybe the queue is
1128                         * to large so try issue another send command
1129                         */
1130                        sendto(DATAOUT(trace)->fd, 
1131                                NULL, 
1132                                0, 
1133                                0, 
1134                                (void *) &DATAOUT(trace)->sock_hdr, 
1135                                sizeof(DATAOUT(trace)->sock_hdr));
1136        }
1137       
1138        header->tp_len = trace_get_capture_length(packet);
1139
1140        /* We cannot write the whole packet so just write part of it */
1141        if (header->tp_len > max_size)
1142                header->tp_len = max_size;
1143
1144        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
1145        off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll));
1146        memcpy(off, 
1147                (char *) packet->payload, 
1148                header->tp_len);
1149       
1150        /* 'Send it' and increase ring pointer to the next frame */
1151        header->tp_status = TP_STATUS_SEND_REQUEST;
1152        DATAOUT(trace)->txring_offset = (DATAOUT(trace)->txring_offset + 1) % 
1153                                                DATAOUT(trace)->req.tp_frame_nr;
1154
1155        /* Notify kernel there are frames to send */
1156        DATAOUT(trace)->queue ++;
1157        DATAOUT(trace)->queue %= TX_MAX_QUEUE;
1158        if(DATAOUT(trace)->queue == 0){
1159                sendto(DATAOUT(trace)->fd, 
1160                        NULL, 
1161                        0, 
1162                        MSG_DONTWAIT, 
1163                        (void *) &DATAOUT(trace)->sock_hdr, 
1164                        sizeof(DATAOUT(trace)->sock_hdr));
1165        }
1166        return header->tp_len;
1167
1168}
1169#endif /* HAVE_NETPACKET_PACKET_H */
1170
1171static inline libtrace_linktype_t get_libtrace_link_type(uint16_t linktype){
1172        /* Convert the ARPHRD type into an appropriate libtrace link type */
1173        switch (linktype) {
1174                case LIBTRACE_ARPHRD_ETHER:
1175                case LIBTRACE_ARPHRD_LOOPBACK:
1176                        return TRACE_TYPE_ETH;
1177                case LIBTRACE_ARPHRD_PPP:
1178                        return TRACE_TYPE_NONE;
1179                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
1180                        return TRACE_TYPE_80211_RADIO;
1181                case LIBTRACE_ARPHRD_IEEE80211:
1182                        return TRACE_TYPE_80211;
1183                case LIBTRACE_ARPHRD_SIT:
1184                case LIBTRACE_ARPHRD_NONE:
1185                        return TRACE_TYPE_NONE;
1186                default: /* shrug, beyond me! */
1187                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
1188                        return (libtrace_linktype_t)~0U;
1189        }
1190}
1191static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
1192        uint16_t linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
1193                                ->hdr.sll_hatype);
1194        return get_libtrace_link_type(linktype);
1195}
1196static libtrace_linktype_t linuxring_get_link_type(const struct libtrace_packet_t *packet) {
1197        uint16_t linktype= GET_SOCKADDR_HDR(packet->buffer)->sll_hatype;
1198        return get_libtrace_link_type(linktype);
1199}
1200
1201static inline libtrace_direction_t get_libtrace_direction(uint8_t pkttype){
1202        switch (pkttype) {
1203                case PACKET_OUTGOING:
1204                case PACKET_LOOPBACK:
1205                        return TRACE_DIR_OUTGOING;
1206                default:
1207                        return TRACE_DIR_INCOMING;
1208        }
1209}
1210static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
1211        return get_libtrace_direction(((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype);
1212}
1213static libtrace_direction_t linuxring_get_direction(const struct libtrace_packet_t *packet) {
1214        return get_libtrace_direction(GET_SOCKADDR_HDR(packet->buffer)->sll_pkttype);
1215}
1216
1217static libtrace_direction_t set_direction(struct sockaddr_ll * skadr, libtrace_direction_t direction){
1218        switch (direction) {
1219                case TRACE_DIR_OUTGOING:
1220                        skadr->sll_pkttype = PACKET_OUTGOING;
1221                        return TRACE_DIR_OUTGOING;
1222                case TRACE_DIR_INCOMING:
1223                        skadr->sll_pkttype = PACKET_HOST;
1224                        return TRACE_DIR_INCOMING;
1225                default:
1226                        return -1;
1227        }
1228}
1229static libtrace_direction_t linuxnative_set_direction(
1230                libtrace_packet_t *packet,
1231                libtrace_direction_t direction) {
1232        return set_direction(&((struct libtrace_linuxnative_header*)(packet->buffer))->hdr, direction);
1233}
1234static libtrace_direction_t linuxring_set_direction(
1235                libtrace_packet_t *packet,
1236                libtrace_direction_t direction) {
1237        return set_direction(GET_SOCKADDR_HDR(packet->buffer), direction);
1238}
1239
1240static struct timespec linuxnative_get_timespec(const libtrace_packet_t *packet) 
1241{
1242        struct libtrace_linuxnative_header *hdr = 
1243                (struct libtrace_linuxnative_header*) packet->buffer;
1244        /* We have to upconvert from timeval to timespec */
1245        if (hdr->timestamptype == TS_TIMEVAL) {
1246                struct timespec ts;
1247                ts.tv_sec = hdr->tv.tv_sec;
1248                ts.tv_nsec = hdr->tv.tv_usec*1000;
1249                return ts;
1250        }
1251        else {
1252                struct timespec ts;
1253                ts.tv_sec = hdr->ts.tv_sec;
1254                ts.tv_nsec = hdr->ts.tv_nsec;
1255                return ts;
1256        }
1257}
1258static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet) 
1259{
1260        struct timespec ts;
1261        ts.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
1262        ts.tv_nsec = TO_TP_HDR(packet->buffer)->tp_nsec;
1263        return ts;
1264}
1265
1266
1267static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet) 
1268{
1269        struct libtrace_linuxnative_header *hdr = 
1270                (struct libtrace_linuxnative_header*) packet->buffer;
1271        /* We have to downconvert from timespec to timeval */
1272        if (hdr->timestamptype == TS_TIMESPEC) {
1273                struct timeval tv;
1274                tv.tv_sec = hdr->ts.tv_sec;
1275                tv.tv_usec = hdr->ts.tv_nsec/1000;
1276                return tv;
1277        }
1278        else {
1279                struct timeval tv;
1280                tv.tv_sec = hdr->tv.tv_sec;
1281                tv.tv_usec = hdr->tv.tv_usec;
1282                return tv;
1283        }
1284}
1285static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet) 
1286{
1287        struct timeval tv;
1288        tv.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
1289        tv.tv_usec = TO_TP_HDR(packet->buffer)->tp_nsec / 1000;
1290        return tv;
1291}
1292
1293static int linuxnative_get_capture_length(const libtrace_packet_t *packet)
1294{
1295        return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen;
1296}
1297
1298static int linuxring_get_capture_length(const libtrace_packet_t *packet)
1299{
1300        return TO_TP_HDR(packet->buffer)->tp_snaplen;
1301}
1302
1303static int linuxnative_get_wire_length(const libtrace_packet_t *packet) 
1304{
1305
1306        int wirelen = ((struct libtrace_linuxnative_header*)(packet->buffer))->wirelen;
1307
1308        /* Include the missing FCS */
1309        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
1310                wirelen += 4;
1311
1312        return wirelen;
1313}
1314
1315static int linuxring_get_wire_length(const libtrace_packet_t *packet) 
1316{
1317        int wirelen = TO_TP_HDR(packet->buffer)->tp_len;
1318
1319        /* Include the missing FCS */
1320        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
1321                wirelen += 4;
1322
1323        return wirelen;
1324}
1325
1326static int linuxnative_get_framing_length(UNUSED
1327                const libtrace_packet_t *packet) 
1328{
1329        return sizeof(struct libtrace_linuxnative_header);
1330}
1331
1332static int linuxring_get_framing_length(const libtrace_packet_t *packet)
1333{       
1334        /*
1335         * Need to make frame_length + capture_length = compelete capture length
1336         * so include alligment whitespace. So reverse calculate from packet.
1337         */
1338        return (char *) packet->payload - (char *) packet->buffer;
1339}
1340
1341static size_t linuxnative_set_capture_length(libtrace_packet_t *packet, 
1342                size_t size) {
1343
1344        struct libtrace_linuxnative_header *linux_hdr = NULL;
1345        assert(packet);
1346        if (size > trace_get_capture_length(packet)) {
1347                /* We should avoid making a packet larger */
1348                return trace_get_capture_length(packet);
1349        }
1350       
1351        /* Reset the cached capture length */
1352        packet->capture_length = -1;
1353
1354        linux_hdr = (struct libtrace_linuxnative_header *)packet->header;
1355        linux_hdr->caplen = size;
1356        return trace_get_capture_length(packet);
1357}
1358
1359static size_t linuxring_set_capture_length(libtrace_packet_t *packet, 
1360                size_t size) {
1361        assert(packet);
1362        if (size > trace_get_capture_length(packet)) {
1363                /* We should avoid making a packet larger */
1364                return trace_get_capture_length(packet);
1365        }
1366       
1367        /* Reset the cached capture length */
1368        packet->capture_length = -1;
1369
1370        TO_TP_HDR(packet->buffer)->tp_len = size;
1371
1372        return trace_get_capture_length(packet);
1373}
1374
1375static int linuxnative_get_fd(const libtrace_t *trace) {
1376        if (trace->format_data == NULL)
1377                return -1;
1378        return FORMAT(trace->format_data)->fd;
1379}
1380
1381/* Linux doesn't keep track how many packets were seen before filtering
1382 * so we can't tell how many packets were filtered.  Bugger.  So annoying.
1383 *
1384 * Since we tell libtrace that we do support filtering, if we don't declare
1385 * this here as failing, libtrace will happily report for us that it didn't
1386 * filter any packets, so don't lie -- return that we don't know.
1387 */
1388static uint64_t linuxnative_get_filtered_packets(libtrace_t *trace UNUSED) {
1389        return UINT64_MAX;
1390}
1391
1392/* Number of packets that passed filtering */
1393static uint64_t linuxnative_get_captured_packets(libtrace_t *trace) {
1394        if (trace->format_data == NULL)
1395                return UINT64_MAX;
1396        if (FORMAT(trace->format_data)->fd == -1) {
1397                /* This is probably a 'dead' trace so obviously we can't query
1398                 * the socket for capture counts, can we? */
1399                return UINT64_MAX;
1400        }
1401
1402#ifdef HAVE_NETPACKET_PACKET_H 
1403        if ((FORMAT(trace->format_data)->stats_valid & 1) 
1404                        || FORMAT(trace->format_data)->stats_valid == 0) {
1405                socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
1406                getsockopt(FORMAT(trace->format_data)->fd, 
1407                                SOL_PACKET,
1408                                PACKET_STATISTICS,
1409                                &FORMAT(trace->format_data)->stats,
1410                                &len);
1411                FORMAT(trace->format_data)->stats_valid |= 1;
1412        }
1413
1414        return FORMAT(trace->format_data)->stats.tp_packets;
1415#else
1416        return UINT64_MAX;
1417#endif
1418}
1419
1420/* Number of packets that got past filtering and were then dropped because
1421 * of lack of space
1422 */
1423static uint64_t linuxnative_get_dropped_packets(libtrace_t *trace) {
1424        if (trace->format_data == NULL)
1425                return UINT64_MAX;
1426        if (FORMAT(trace->format_data)->fd == -1) {
1427                /* This is probably a 'dead' trace so obviously we can't query
1428                 * the socket for drop counts, can we? */
1429                return UINT64_MAX;
1430        }
1431       
1432#ifdef HAVE_NETPACKET_PACKET_H 
1433        if ((FORMAT(trace->format_data)->stats_valid & 2)
1434                        || (FORMAT(trace->format_data)->stats_valid==0)) {
1435                socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
1436                getsockopt(FORMAT(trace->format_data)->fd, 
1437                                SOL_PACKET,
1438                                PACKET_STATISTICS,
1439                                &FORMAT(trace->format_data)->stats,
1440                                &len);
1441                FORMAT(trace->format_data)->stats_valid |= 2;
1442        }
1443
1444        return FORMAT(trace->format_data)->stats.tp_drops;
1445#else
1446        return UINT64_MAX;
1447#endif
1448}
1449
1450#ifdef HAVE_NETPACKET_PACKET_H
1451static void linuxnative_help(void) {
1452        printf("linuxnative format module: $Revision$\n");
1453        printf("Supported input URIs:\n");
1454        printf("\tint:eth0\n");
1455        printf("\n");
1456        printf("Supported output URIs:\n");
1457        printf("\tint:eth0\n");
1458        printf("\n");
1459        return;
1460}
1461
1462static void linuxring_help(void) {
1463        printf("linuxring format module: $Revision$\n");
1464        printf("Supported input URIs:\n");
1465        printf("\tring:eth0\n");
1466        printf("\n");
1467        printf("Supported output URIs:\n");
1468        printf("\tring:eth0\n");
1469        printf("\n");
1470        return;
1471}
1472
1473static struct libtrace_format_t linuxnative = {
1474        "int",
1475        "$Id$",
1476        TRACE_FORMAT_LINUX_NATIVE,
1477        linuxnative_probe_filename,     /* probe filename */
1478        NULL,                           /* probe magic */
1479        linuxnative_init_input,         /* init_input */
1480        linuxnative_config_input,       /* config_input */
1481        linuxnative_start_input,        /* start_input */
1482        linuxnative_pause_input,        /* pause_input */
1483        linuxnative_init_output,        /* init_output */
1484        NULL,                           /* config_output */
1485        linuxnative_start_output,       /* start_ouput */
1486        linuxnative_fin_input,          /* fin_input */
1487        linuxnative_fin_output,         /* fin_output */
1488        linuxnative_read_packet,        /* read_packet */
1489        linuxnative_prepare_packet,     /* prepare_packet */
1490        NULL,                           /* fin_packet */
1491        linuxnative_write_packet,       /* write_packet */
1492        linuxnative_get_link_type,      /* get_link_type */
1493        linuxnative_get_direction,      /* get_direction */
1494        linuxnative_set_direction,      /* set_direction */
1495        NULL,                           /* get_erf_timestamp */
1496        linuxnative_get_timeval,        /* get_timeval */
1497        linuxnative_get_timespec,       /* get_timespec */
1498        NULL,                           /* get_seconds */
1499        NULL,                           /* seek_erf */
1500        NULL,                           /* seek_timeval */
1501        NULL,                           /* seek_seconds */
1502        linuxnative_get_capture_length, /* get_capture_length */
1503        linuxnative_get_wire_length,    /* get_wire_length */
1504        linuxnative_get_framing_length, /* get_framing_length */
1505        linuxnative_set_capture_length, /* set_capture_length */
1506        NULL,                           /* get_received_packets */
1507        linuxnative_get_filtered_packets,/* get_filtered_packets */
1508        linuxnative_get_dropped_packets,/* get_dropped_packets */
1509        linuxnative_get_captured_packets,/* get_captured_packets */
1510        linuxnative_get_fd,             /* get_fd */
1511        NULL,                           /* trace_event */
1512        linuxnative_help,               /* help */
1513        NULL
1514};
1515
1516static struct libtrace_format_t linuxring = {
1517        "ring",
1518        "$Id$",
1519        TRACE_FORMAT_LINUX_RING,
1520        linuxnative_probe_filename,     /* probe filename */
1521        NULL,                           /* probe magic */
1522        linuxring_init_input,           /* init_input */
1523        linuxnative_config_input,       /* config_input */
1524        linuxring_start_input,  /* start_input */
1525        linuxring_pause_input,  /* pause_input */
1526        linuxring_init_output,  /* init_output */
1527        NULL,                           /* config_output */
1528        linuxring_start_output, /* start_ouput */
1529        linuxnative_fin_input,          /* fin_input */
1530        linuxring_fin_output,           /* fin_output */
1531        linuxring_read_packet,  /* read_packet */
1532        linuxring_prepare_packet,       /* prepare_packet */
1533        NULL,                           /* fin_packet */
1534        linuxring_write_packet, /* write_packet */
1535        linuxring_get_link_type,        /* get_link_type */
1536        linuxring_get_direction,        /* get_direction */
1537        linuxring_set_direction,        /* set_direction */
1538        NULL,                           /* get_erf_timestamp */
1539        linuxring_get_timeval,  /* get_timeval */
1540        linuxring_get_timespec, /* get_timespec */
1541        NULL,                           /* get_seconds */
1542        NULL,                           /* seek_erf */
1543        NULL,                           /* seek_timeval */
1544        NULL,                           /* seek_seconds */
1545        linuxring_get_capture_length,   /* get_capture_length */
1546        linuxring_get_wire_length,      /* get_wire_length */
1547        linuxring_get_framing_length,   /* get_framing_length */
1548        linuxring_set_capture_length,   /* set_capture_length */
1549        NULL,                           /* get_received_packets */
1550        linuxnative_get_filtered_packets,/* get_filtered_packets */
1551        linuxnative_get_dropped_packets,/* get_dropped_packets */
1552        linuxnative_get_captured_packets,/* get_captured_packets */
1553        linuxnative_get_fd,             /* get_fd */
1554        linuxring_event,                /* trace_event */
1555        linuxring_help,         /* help */
1556        NULL
1557};
1558#else
1559static void linuxnative_help(void) {
1560        printf("linuxnative format module: $Revision$\n");
1561        printf("Not supported on this host\n");
1562}
1563static void linuxring_help(void) {
1564        printf("linuxring format module: $Revision$\n");
1565        printf("Not supported on this host\n");
1566}
1567
1568static struct libtrace_format_t linuxnative = {
1569        "int",
1570        "$Id$",
1571        TRACE_FORMAT_LINUX_NATIVE,
1572        NULL,                           /* probe filename */
1573        NULL,                           /* probe magic */
1574        NULL,                           /* init_input */
1575        NULL,                           /* config_input */
1576        NULL,                           /* start_input */
1577        NULL,                           /* pause_input */
1578        NULL,                           /* init_output */
1579        NULL,                           /* config_output */
1580        NULL,                           /* start_ouput */
1581        NULL,                           /* fin_input */
1582        NULL,                           /* fin_output */
1583        NULL,                           /* read_packet */
1584        linuxnative_prepare_packet,     /* prepare_packet */
1585        NULL,                           /* fin_packet */
1586        NULL,                           /* write_packet */
1587        linuxnative_get_link_type,      /* get_link_type */
1588        linuxnative_get_direction,      /* get_direction */
1589        linuxnative_set_direction,      /* set_direction */
1590        NULL,                           /* get_erf_timestamp */
1591        linuxnative_get_timeval,        /* get_timeval */
1592        linuxnative_get_timespec,       /* get_timespec */
1593        NULL,                           /* get_seconds */
1594        NULL,                           /* seek_erf */
1595        NULL,                           /* seek_timeval */
1596        NULL,                           /* seek_seconds */
1597        linuxnative_get_capture_length, /* get_capture_length */
1598        linuxnative_get_wire_length,    /* get_wire_length */
1599        linuxnative_get_framing_length, /* get_framing_length */
1600        linuxnative_set_capture_length, /* set_capture_length */
1601        NULL,                           /* get_received_packets */
1602        linuxnative_get_filtered_packets,/* get_filtered_packets */
1603        linuxnative_get_dropped_packets,/* get_dropped_packets */
1604        linuxnative_get_captured_packets,/* get_captured_packets */
1605        linuxnative_get_fd,             /* get_fd */
1606        trace_event_device,             /* trace_event */
1607        linuxnative_help,               /* help */
1608        NULL
1609};
1610
1611static struct libtrace_format_t linuxring = {
1612        "ring",
1613        "$Id$",
1614        TRACE_FORMAT_LINUX_RING,
1615        NULL,                           /* probe filename */
1616        NULL,                           /* probe magic */
1617        NULL,                           /* init_input */
1618        NULL,                           /* config_input */
1619        NULL,                           /* start_input */
1620        NULL,                           /* pause_input */
1621        NULL,                           /* init_output */
1622        NULL,                           /* config_output */
1623        NULL,                           /* start_ouput */
1624        NULL,                           /* fin_input */
1625        NULL,                           /* fin_output */
1626        NULL,                           /* read_packet */
1627        linuxring_prepare_packet,       /* prepare_packet */
1628        NULL,                           /* fin_packet */
1629        NULL,                           /* write_packet */
1630        linuxring_get_link_type,        /* get_link_type */
1631        linuxring_get_direction,        /* get_direction */
1632        linuxring_set_direction,        /* set_direction */
1633        NULL,                           /* get_erf_timestamp */
1634        linuxring_get_timeval,          /* get_timeval */
1635        linuxring_get_timespec,         /* get_timespec */
1636        NULL,                           /* get_seconds */
1637        NULL,                           /* seek_erf */
1638        NULL,                           /* seek_timeval */
1639        NULL,                           /* seek_seconds */
1640        linuxring_get_capture_length,   /* get_capture_length */
1641        linuxring_get_wire_length,      /* get_wire_length */
1642        linuxring_get_framing_length,   /* get_framing_length */
1643        linuxring_set_capture_length,   /* set_capture_length */
1644        NULL,                           /* get_received_packets */
1645        linuxnative_get_filtered_packets,/* get_filtered_packets */
1646        linuxnative_get_dropped_packets,/* get_dropped_packets */
1647        linuxnative_get_captured_packets,/* get_captured_packets */
1648        linuxnative_get_fd,             /* get_fd */
1649        NULL,                           /* trace_event */
1650        linuxring_help,                 /* help */
1651        NULL
1652};
1653
1654#endif /* HAVE_NETPACKET_PACKET_H */
1655
1656
1657void linuxnative_constructor(void) {
1658        register_format(&linuxnative);
1659        register_format(&linuxring);
1660}
Note: See TracBrowser for help on using the repository browser.