source: lib/format_linux.c @ 6ba84d9

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