source: lib/format_linux.c @ 63af502

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 63af502 was 63af502, checked in by Shane Alcock <salcock@…>, 7 years ago

int: and ring: now respect trace_interrupt

Calling trace_interrupt() will now cause the read_packet functions
for these formats to exit, even if there are no packets available to
read.

Previously, the read_packet call would hang until a packet arrived
and then exit, which essentially meant tools like tracesplit would
hang forever if there were no packets.

  • Property mode set to 100644
File size: 52.2 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 shouldn'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 + TPACKET_ALIGN(TPACKET_HDRLEN);
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        FORMAT(libtrace->format_data)->max_order = MAX_ORDER;
369}
370static int linuxring_init_input(libtrace_t *libtrace) 
371{       
372        init_input(libtrace);
373        FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_RING;
374        return 0;
375}
376static int linuxnative_init_input(libtrace_t *libtrace) 
377{
378        init_input(libtrace);
379        FORMAT(libtrace->format_data)->format = TRACE_FORMAT_LINUX_NATIVE;
380        return 0;
381}
382
383static inline void init_output(libtrace_out_t *libtrace)
384{
385        libtrace->format_data = (struct linux_output_format_data_t*)
386                malloc(sizeof(struct linux_output_format_data_t));
387        DATAOUT(libtrace)->fd = -1;
388        DATAOUT(libtrace)->tx_ring = NULL;
389        DATAOUT(libtrace)->txring_offset = 0;
390        DATAOUT(libtrace)->queue = 0;
391        DATAOUT(libtrace)->max_order = MAX_ORDER;
392}
393static int linuxnative_init_output(libtrace_out_t *libtrace)
394{
395        init_output(libtrace);
396        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_NATIVE;
397        return 0;
398}
399static int linuxring_init_output(libtrace_out_t *libtrace)
400{
401        init_output(libtrace);
402        DATAOUT(libtrace)->format = TRACE_FORMAT_LINUX_RING;
403        return 0;
404}
405
406static int linuxnative_start_input(libtrace_t *libtrace)
407{
408        struct sockaddr_ll addr;
409        int one = 1;
410        memset(&addr,0,sizeof(addr));
411        libtrace_filter_t *filter = FORMAT(libtrace->format_data)->filter;
412       
413        /* Create a raw socket for reading packets on */
414        FORMAT(libtrace->format_data)->fd = 
415                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
416        if (FORMAT(libtrace->format_data)->fd==-1) {
417                trace_set_err(libtrace, errno, "Could not create raw socket");
418                free(libtrace->format_data);
419                libtrace->format_data = NULL;
420                return -1;
421        }
422
423        /* Bind to the capture interface */
424        addr.sll_family = AF_PACKET;
425        addr.sll_protocol = htons(ETH_P_ALL);
426        if (strlen(libtrace->uridata)) {
427                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
428                if (addr.sll_ifindex == 0) {
429                        close(FORMAT(libtrace->format_data)->fd);
430                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to find interface %s", libtrace->uridata);
431                        free(libtrace->format_data);
432                        libtrace->format_data = NULL;
433                        return -1;
434                }
435        }
436        else {
437                addr.sll_ifindex = 0;
438        }
439        if (bind(FORMAT(libtrace->format_data)->fd,
440                                (struct sockaddr*)&addr,
441                                (socklen_t)sizeof(addr))==-1) {
442                free(libtrace->format_data);
443                libtrace->format_data = NULL;
444                trace_set_err(libtrace, errno, "Failed to bind to interface %s", libtrace->uridata);
445                return -1;
446        }
447
448        /* If promisc hasn't been specified, set it to "true" if we're
449         * capturing on one interface, or "false" if we're capturing on
450         * all interfaces.
451         */ 
452        if (FORMAT(libtrace->format_data)->promisc==-1) {
453                if (addr.sll_ifindex!=0)
454                        FORMAT(libtrace->format_data)->promisc=1;
455                else
456                        FORMAT(libtrace->format_data)->promisc=0;
457        }
458       
459        /* Enable promiscuous mode, if requested */                     
460        if (FORMAT(libtrace->format_data)->promisc) {
461                struct packet_mreq mreq;
462                socklen_t socklen = sizeof(mreq);
463                memset(&mreq,0,sizeof(mreq));
464                mreq.mr_ifindex = addr.sll_ifindex;
465                mreq.mr_type = PACKET_MR_PROMISC;
466                if (setsockopt(FORMAT(libtrace->format_data)->fd,
467                                SOL_PACKET,
468                                PACKET_ADD_MEMBERSHIP,
469                                &mreq,
470                                socklen)==-1) {
471                        perror("setsockopt(PROMISC)");
472                }
473        }
474
475        /* Set the timestamp option on the socket - aim for the most detailed
476         * clock resolution possible */
477#ifdef SO_TIMESTAMPNS
478        if (setsockopt(FORMAT(libtrace->format_data)->fd,
479                        SOL_SOCKET,
480                        SO_TIMESTAMPNS,
481                        &one,
482                        (socklen_t)sizeof(one))!=-1) {
483                FORMAT(libtrace->format_data)->timestamptype = TS_TIMESPEC;
484        }
485        else
486        /* DANGER: This is a dangling else to only do the next setsockopt() if we fail the first! */
487#endif
488        if (setsockopt(FORMAT(libtrace->format_data)->fd,
489                        SOL_SOCKET,
490                        SO_TIMESTAMP,
491                        &one,
492                        (socklen_t)sizeof(one))!=-1) {
493                FORMAT(libtrace->format_data)->timestamptype = TS_TIMEVAL;
494        }
495        else 
496                FORMAT(libtrace->format_data)->timestamptype = TS_NONE;
497
498        /* Push BPF filter into the kernel. At this stage we can safely assume
499         * that the filterstring has been compiled, or the filter was supplied
500         * pre-compiled.
501         */
502        if (filter != NULL) {
503                /* Check if the filter was successfully compiled. If not,
504                 * it is probably a bad filter and we should return an error
505                 * before the caller tries to read any packets */
506                if (filter->flag == 0) {
507                        return -1;
508                }
509               
510                if (setsockopt(FORMAT(libtrace->format_data)->fd,
511                                        SOL_SOCKET,
512                                        SO_ATTACH_FILTER,
513                                        &filter->filter,
514                                        sizeof(filter->filter)) == -1) {
515                        perror("setsockopt(SO_ATTACH_FILTER)");
516                } else { 
517                        /* The socket accepted the filter, so we need to
518                         * consume any buffered packets that were received
519                         * between opening the socket and applying the filter.
520                         */
521                        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
522                        while(recv(FORMAT(libtrace->format_data)->fd,
523                                        buf,
524                                        (size_t) LIBTRACE_PACKET_BUFSIZE,
525                                        MSG_DONTWAIT) != -1) { }
526                        free(buf);
527                }
528        }
529
530        FORMAT(libtrace->format_data)->stats_valid=0;
531                                       
532        return 0;
533}
534static inline int socket_to_packetmmap( char * uridata, int ring_type, 
535                                        int fd, 
536                                        struct tpacket_req * req,
537                                        char ** ring_location,
538                                        uint32_t *max_order,
539                                        char *error){
540        int val;
541
542        /* Switch to TPACKET header version 2, we only try support v2 because v1 had problems */
543
544        val = TPACKET_V2;
545        if (setsockopt(fd, 
546                        SOL_PACKET, 
547                        PACKET_VERSION, 
548                        &val, 
549                        sizeof(val)) == -1){
550                strncpy(error, "TPACKET2 not supported", 2048);
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                        strncpy(error,"Cannot allocate enough memory for ring buffer", 2048);
560                        return -1;
561                }
562                calculate_buffers(req, fd, uridata, *max_order);
563                if (setsockopt(fd, 
564                                SOL_PACKET, 
565                                ring_type, 
566                                req, 
567                                sizeof(struct tpacket_req)) == -1) {
568                        if(errno == ENOMEM){
569                                (*max_order)--;
570                        } else {
571                                strncpy(error, "Error setting the ring buffer size", 2048);
572                                return -1;
573                        }
574
575                } else break;
576        }
577       
578        /* Map the ring buffer into userspace */
579        *ring_location = mmap(NULL, 
580                                        req->tp_block_size * req->tp_block_nr, 
581                                        PROT_READ | PROT_WRITE, 
582                                        MAP_SHARED, 
583                                        fd, 0);
584        if(*ring_location == MAP_FAILED){
585                strncpy(error, "Failed to map memory for ring buffer", 2048);
586                return -1;
587        }
588        return 0;
589}
590static int linuxring_start_input(libtrace_t *libtrace){
591
592        char error[2048];       
593
594        /* We set the socket up the same and then convert it to PACKET_MMAP */
595        if(linuxnative_start_input(libtrace) != 0)
596                return -1;
597
598        strncpy(error, "No known error", 2048);
599
600        /* Make it a packetmmap */
601        if(socket_to_packetmmap(libtrace->uridata, PACKET_RX_RING, 
602                        FORMAT(libtrace->format_data)->fd,
603                        &FORMAT(libtrace->format_data)->req, 
604                        &FORMAT(libtrace->format_data)->rx_ring,
605                        &FORMAT(libtrace->format_data)->max_order,
606                        error) != 0){
607                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Initialisation of packet MMAP failed: %s", error);
608                close(DATAOUT(libtrace)->fd);
609                free(libtrace->format_data);
610                libtrace->format_data = NULL;
611                return -1;
612        }
613
614        return 0;
615}
616
617static int linuxnative_start_output(libtrace_out_t *libtrace)
618{
619        DATAOUT(libtrace)->fd = socket(PF_PACKET, SOCK_RAW, 0);
620        if (DATAOUT(libtrace)->fd==-1) {
621                free(DATAOUT(libtrace));
622                return -1;
623        }       
624
625        return 0;
626}
627
628static int linuxring_start_output(libtrace_out_t *libtrace)
629{
630        char error[2048];       
631        /* We set the socket up the same and then convert it to PACKET_MMAP */
632        if(linuxnative_start_output(libtrace) != 0)
633                return -1;
634
635        /* Make it a packetmmap */
636        if(socket_to_packetmmap(libtrace->uridata, PACKET_TX_RING, 
637                        DATAOUT(libtrace)->fd,
638                        &DATAOUT(libtrace)->req, 
639                        &DATAOUT(libtrace)->tx_ring,
640                        &DATAOUT(libtrace)->max_order,
641                        error) != 0){
642                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, "Initialisation of packet MMAP failed: %s", error);
643                close(DATAOUT(libtrace)->fd);
644                free(libtrace->format_data);
645                libtrace->format_data = NULL;
646                return -1;
647        }
648       
649        DATAOUT(libtrace)->sock_hdr.sll_family = AF_PACKET;
650        DATAOUT(libtrace)->sock_hdr.sll_protocol = 0;
651        DATAOUT(libtrace)->sock_hdr.sll_ifindex = 
652                                        if_nametoindex(libtrace->uridata);
653        DATAOUT(libtrace)->sock_hdr.sll_hatype = 0;
654        DATAOUT(libtrace)->sock_hdr.sll_pkttype = 0;
655        DATAOUT(libtrace)->sock_hdr.sll_halen = 0;
656        DATAOUT(libtrace)->queue = 0;   
657
658        return 0;
659}
660
661static int linuxnative_pause_input(libtrace_t *libtrace)
662{
663        close(FORMAT(libtrace->format_data)->fd);
664        FORMAT(libtrace->format_data)->fd=-1;
665
666        return 0;
667}
668static int linuxring_pause_input(libtrace_t *libtrace)
669{
670        munmap(FORMAT(libtrace->format_data)->rx_ring, 
671                FORMAT(libtrace->format_data)->req.tp_block_size *
672                        FORMAT(libtrace->format_data)->req.tp_block_nr);
673        FORMAT(libtrace->format_data)->rx_ring = NULL;
674        return linuxnative_pause_input(libtrace);
675}
676
677static int linuxnative_fin_input(libtrace_t *libtrace) 
678{
679        if (libtrace->format_data) {
680                if (FORMAT(libtrace->format_data)->filter != NULL)
681                        free(FORMAT(libtrace->format_data)->filter);
682                free(libtrace->format_data);
683        }
684       
685        return 0;
686}
687
688static int linuxnative_fin_output(libtrace_out_t *libtrace)
689{
690        close(DATAOUT(libtrace)->fd);
691        DATAOUT(libtrace)->fd=-1;
692        free(libtrace->format_data);
693        return 0;
694}
695static int linuxring_fin_output(libtrace_out_t *libtrace)
696{
697        /* Make sure any remaining frames get sent */
698        sendto(DATAOUT(libtrace)->fd, 
699                NULL, 
700                0, 
701                0, 
702                (void *) &DATAOUT(libtrace)->sock_hdr, 
703                sizeof(DATAOUT(libtrace)->sock_hdr));
704
705        /* Unmap our data area */
706        munmap(DATAOUT(libtrace)->tx_ring,
707                DATAOUT(libtrace)->req.tp_block_size * 
708                        DATAOUT(libtrace)->req.tp_block_nr);
709
710        return linuxnative_fin_output(libtrace);
711}
712
713/* Compiles a libtrace BPF filter for use with a linux native socket */
714static int linuxnative_configure_bpf(libtrace_t *libtrace, 
715                libtrace_filter_t *filter) {
716#ifdef HAVE_LIBPCAP
717        struct ifreq ifr;
718        unsigned int arphrd;
719        libtrace_dlt_t dlt;
720        libtrace_filter_t *f;
721        int sock;
722        pcap_t *pcap;
723
724        /* Take a copy of the filter object as it was passed in */
725        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
726        memcpy(f, filter, sizeof(libtrace_filter_t));
727       
728        /* If we are passed a filter with "flag" set to zero, then we must
729         * compile the filterstring before continuing. This involves
730         * determining the linktype, passing the filterstring to libpcap to
731         * compile, and saving the result for trace_start() to push into the
732         * kernel.
733         * If flag is set to one, then the filter was probably generated using
734         * trace_create_filter_from_bytecode() and so we don't need to do
735         * anything (we've just copied it above).
736         */
737        if (f->flag == 0) {
738                sock = socket(PF_INET, SOCK_STREAM, 0);
739                memset(&ifr, 0, sizeof(struct ifreq));
740                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE);
741                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
742                        perror("Can't get HWADDR for interface");
743                        return -1;
744                }
745                close(sock);
746
747                arphrd = ifr.ifr_hwaddr.sa_family;
748                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
749
750                pcap = pcap_open_dead(dlt, 
751                                FORMAT(libtrace->format_data)->snaplen);
752
753                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
754                        /* Filter didn't compile, set flag to 0 so we can
755                         * detect this when trace_start() is called and
756                         * produce a useful error
757                         */
758                        f->flag = 0;
759                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, 
760                                        "Failed to compile BPF filter (%s): %s",
761                                        f->filterstring, pcap_geterr(pcap));
762                } else {
763                        /* Set the "flag" to indicate that the filterstring
764                         * has been compiled
765                         */
766                        f->flag = 1;
767                }
768
769                pcap_close(pcap);
770               
771        }
772       
773        if (FORMAT(libtrace->format_data)->filter != NULL)
774                free(FORMAT(libtrace->format_data)->filter);
775       
776        FORMAT(libtrace->format_data)->filter = f;
777       
778        return 0;
779#else
780        return -1
781#endif
782}
783static int linuxnative_config_input(libtrace_t *libtrace,
784                trace_option_t option,
785                void *data)
786{
787        switch(option) {
788                case TRACE_OPTION_SNAPLEN:
789                        FORMAT(libtrace->format_data)->snaplen=*(int*)data;
790                        return 0;
791                case TRACE_OPTION_PROMISC:
792                        FORMAT(libtrace->format_data)->promisc=*(int*)data;
793                        return 0;
794                case TRACE_OPTION_FILTER:
795                        return linuxnative_configure_bpf(libtrace, 
796                                        (libtrace_filter_t *) data);
797                case TRACE_OPTION_META_FREQ:
798                        /* No meta-data for this format */
799                        break;
800                case TRACE_OPTION_EVENT_REALTIME:
801                        /* Live captures are always going to be in trace time */
802                        break;
803                /* Avoid default: so that future options will cause a warning
804                 * here to remind us to implement it, or flag it as
805                 * unimplementable
806                 */
807        }
808       
809        /* Don't set an error - trace_config will try to deal with the
810         * option and will set an error if it fails */
811        return -1;
812}
813#endif /* HAVE_NETPACKET_PACKET_H */
814
815static int linuxnative_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                sizeof(struct libtrace_linuxnative_header);
834        packet->type = rt_type;
835
836        /*
837        if (libtrace->format_data == NULL) {
838                if (linuxnative_init_input(libtrace))
839                        return -1;
840        }
841        */
842        return 0;
843       
844}
845
846static int linuxring_prepare_packet(libtrace_t *libtrace UNUSED, 
847                libtrace_packet_t *packet, void *buffer, 
848                libtrace_rt_types_t rt_type, uint32_t flags) {
849
850        if (packet->buffer != buffer &&
851                        packet->buf_control == TRACE_CTRL_PACKET) {
852                free(packet->buffer);
853        }
854
855        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
856                packet->buf_control = TRACE_CTRL_PACKET;
857        } else
858                packet->buf_control = TRACE_CTRL_EXTERNAL;
859
860
861        packet->buffer = buffer;
862        packet->header = buffer;
863        packet->payload = (char *)buffer + 
864                                        TP_TRACE_START(
865                                        TO_TP_HDR(packet->header)->tp_mac, 
866                                        TO_TP_HDR(packet->header)->tp_net, 
867                                        TPACKET_HDRLEN);
868        packet->type = rt_type;
869
870        /*
871        if (libtrace->format_data == NULL) {
872                if (linuxnative_init_input(libtrace))
873                        return -1;
874        }
875        */
876        return 0;
877       
878}
879
880#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
881
882/* 20 isn't enough on x86_64 */
883#define CMSG_BUF_SIZE 128
884
885#ifdef HAVE_NETPACKET_PACKET_H
886static int linuxnative_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) 
887{
888        struct libtrace_linuxnative_header *hdr;
889        struct msghdr msghdr;
890        struct iovec iovec;
891        unsigned char controlbuf[CMSG_BUF_SIZE];
892        struct cmsghdr *cmsg;
893        int snaplen;
894        uint32_t flags = 0;
895        fd_set readfds;
896        struct timeval tout;
897        int ret;
898       
899        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
900                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
901                if (!packet->buffer) {
902                        perror("Cannot allocate buffer");
903                }
904        }
905
906        flags |= TRACE_PREP_OWN_BUFFER;
907       
908        packet->type = TRACE_RT_DATA_LINUX_NATIVE;
909
910        hdr=(struct libtrace_linuxnative_header*)packet->buffer;
911        snaplen=LIBTRACE_MIN(
912                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*hdr),
913                        (int)FORMAT(libtrace->format_data)->snaplen);
914
915        /* Prepare the msghdr and iovec for the kernel to write the
916         * captured packet into. The msghdr will point to the part of our
917         * buffer reserved for sll header, while the iovec will point at
918         * the buffer following the sll header. */
919
920        msghdr.msg_name = &hdr->hdr;
921        msghdr.msg_namelen = sizeof(struct sockaddr_ll);
922
923        msghdr.msg_iov = &iovec;
924        msghdr.msg_iovlen = 1;
925
926        msghdr.msg_control = &controlbuf;
927        msghdr.msg_controllen = CMSG_BUF_SIZE;
928        msghdr.msg_flags = 0;
929
930        iovec.iov_base = (void*)(packet->buffer+sizeof(*hdr));
931        iovec.iov_len = snaplen;
932
933        /* Use select to allow us to time out occasionally to check if someone
934         * has hit Ctrl-C or otherwise wants us to stop reading and return
935         * so they can exit their program.
936         */
937
938        while (1) {
939                tout.tv_sec = 0;
940                tout.tv_usec = 500000;
941                FD_ZERO(&readfds);
942                FD_SET(FORMAT(libtrace->format_data)->fd, &readfds);
943
944                ret = select(FORMAT(libtrace->format_data)->fd + 1, &readfds,
945                                NULL, NULL, &tout);
946                if (ret < 0 && errno != EINTR) {
947                        trace_set_err(libtrace, errno, "select");
948                        return -1;
949                } else if (ret < 0) {
950                        continue;
951                } 
952               
953                if (FD_ISSET(FORMAT(libtrace->format_data)->fd, &readfds)) {
954                        /* There's something available for us to read */
955                        break;
956                }
957
958               
959                /* If we get here, we timed out -- check if we should halt */
960                if (libtrace_halt)
961                        return 0;
962        }
963
964        hdr->wirelen = recvmsg(FORMAT(libtrace->format_data)->fd, &msghdr, MSG_TRUNC);
965
966        if (hdr->wirelen==~0U) {
967                trace_set_err(libtrace,errno,"recvmsg");
968                return -1;
969        }
970
971        hdr->caplen=LIBTRACE_MIN((unsigned int)snaplen,(unsigned int)hdr->wirelen);
972
973        /* Extract the timestamps from the msghdr and store them in our
974         * linux native encapsulation, so that we can preserve the formatting
975         * across multiple architectures */
976
977        for (cmsg = CMSG_FIRSTHDR(&msghdr);
978                        cmsg != NULL;
979                        cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
980                if (cmsg->cmsg_level == SOL_SOCKET
981                        && cmsg->cmsg_type == SO_TIMESTAMP
982                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timeval))) {
983                       
984                        struct timeval *tv;
985                        tv = (struct timeval *)CMSG_DATA(cmsg);
986                       
987                       
988                        hdr->tv.tv_sec = tv->tv_sec;
989                        hdr->tv.tv_usec = tv->tv_usec;
990                        hdr->timestamptype = TS_TIMEVAL;
991                        break;
992                } 
993#ifdef SO_TIMESTAMPNS
994                else if (cmsg->cmsg_level == SOL_SOCKET
995                        && cmsg->cmsg_type == SO_TIMESTAMPNS
996                        && cmsg->cmsg_len <= CMSG_LEN(sizeof(struct timespec))) {
997
998                        struct timespec *tv;
999                        tv = (struct timespec *)CMSG_DATA(cmsg);
1000
1001                        hdr->ts.tv_sec = tv->tv_sec;
1002                        hdr->ts.tv_nsec = tv->tv_nsec;
1003                        hdr->timestamptype = TS_TIMESPEC;
1004                        break;
1005                }
1006#endif
1007        }
1008
1009        /* Did we not get given a timestamp? Try to get one from the
1010         * file descriptor directly */
1011        if (cmsg == NULL) {
1012                struct timeval tv;
1013                if (ioctl(FORMAT(libtrace->format_data)->fd, 
1014                                  SIOCGSTAMP,&tv)==0) {
1015                        hdr->tv.tv_sec = tv.tv_sec;
1016                        hdr->tv.tv_usec = tv.tv_usec;
1017                        hdr->timestamptype = TS_TIMEVAL;
1018                }
1019                else {
1020                        hdr->timestamptype = TS_NONE;
1021                }
1022        }
1023
1024        /* Buffer contains all of our packet (including our custom header) so
1025         * we just need to get prepare_packet to set all our packet pointers
1026         * appropriately */
1027       
1028        if (linuxnative_prepare_packet(libtrace, packet, packet->buffer,
1029                                packet->type, flags))
1030                return -1;
1031       
1032        return hdr->wirelen+sizeof(*hdr);
1033}
1034
1035#define LIBTRACE_BETWEEN(test,a,b) ((test) >= (a) && (test) < (b))
1036static int linuxring_get_capture_length(const libtrace_packet_t *packet);
1037static int linuxring_get_framing_length(const libtrace_packet_t *packet);
1038
1039/* Release a frame back to the kernel or free() if it's a malloc'd buffer
1040 */
1041inline static void ring_release_frame(libtrace_t *libtrace, libtrace_packet_t *packet ){
1042        /* Free the old packet */
1043        if(packet->buffer == NULL)
1044                return;
1045
1046        if(packet->buf_control == TRACE_CTRL_PACKET){
1047                free(packet->buffer);
1048                packet->buffer = NULL;
1049        }
1050        if(packet->buf_control == TRACE_CTRL_EXTERNAL) {
1051                struct linux_format_data_t *ftd = FORMAT(libtrace->format_data);
1052               
1053                /* Check it's within our buffer first */
1054                if(LIBTRACE_BETWEEN((char *) packet->buffer, 
1055                                (char *) ftd->rx_ring,
1056                                ftd->rx_ring
1057                                + ftd->req.tp_block_size * ftd->req.tp_block_nr)){
1058                        TO_TP_HDR(packet->buffer)->tp_status = 0;
1059                        packet->buffer = NULL;
1060                }
1061        }
1062}
1063
1064static int linuxring_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
1065
1066        struct tpacket2_hdr *header;
1067        struct pollfd pollset; 
1068        int ret;
1069        unsigned int snaplen;
1070       
1071        ring_release_frame(libtrace, packet);
1072       
1073        packet->buf_control = TRACE_CTRL_EXTERNAL;
1074        packet->type = TRACE_RT_DATA_LINUX_RING;
1075       
1076        /* Fetch the current frame */
1077        header = GET_CURRENT_BUFFER(libtrace);
1078        assert((((unsigned long) header) & (pagesize - 1)) == 0);
1079
1080        while (1) {
1081                pollset.fd = FORMAT(libtrace->format_data)->fd;
1082                pollset.events = POLLIN;
1083                pollset.revents = 0;
1084                /* Wait for more data */
1085                ret = poll(&pollset, 1, 500);
1086                if (ret < 0) {
1087                        if (errno != EINTR)
1088                                trace_set_err(libtrace,errno,"poll()");
1089                        return -1;
1090                } else if (ret == 0) {
1091                        /* Poll timed out - check if we should exit */
1092                        if (libtrace_halt)
1093                                return 0;
1094                        continue;
1095                }
1096
1097                /* TP_STATUS_USER means that we can use the frame.
1098                 * When a slot does not have this flag set, the frame is not
1099                 * ready for consumption.
1100                 */
1101                if (header->tp_status & TP_STATUS_USER)
1102                        break;
1103        }
1104
1105        packet->buffer = header;
1106
1107        /* If a snaplen was configured, automatically truncate the packet to
1108         * the desired length.
1109         */
1110        snaplen=LIBTRACE_MIN(
1111                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*header),
1112                        (int)FORMAT(libtrace->format_data)->snaplen);
1113       
1114        TO_TP_HDR(packet->buffer)->tp_snaplen = LIBTRACE_MIN((unsigned int)snaplen, TO_TP_HDR(packet->buffer)->tp_len);
1115
1116        /* Move to next buffer */
1117        FORMAT(libtrace->format_data)->rxring_offset++;
1118        FORMAT(libtrace->format_data)->rxring_offset %= FORMAT(libtrace->format_data)->req.tp_frame_nr;
1119
1120        /* We just need to get prepare_packet to set all our packet pointers
1121         * appropriately */
1122        if (linuxring_prepare_packet(libtrace, packet, packet->buffer,
1123                                packet->type, 0))
1124                return -1;
1125        return  linuxring_get_framing_length(packet) + 
1126                                linuxring_get_capture_length(packet);
1127
1128}
1129
1130/* Non-blocking read */
1131static libtrace_eventobj_t linuxring_event(libtrace_t *libtrace, libtrace_packet_t *packet) {
1132        struct tpacket2_hdr *header;
1133        libtrace_eventobj_t event = {0,0,0.0,0};
1134
1135        /* We must free the old packet, otherwise select() will instantly return
1136         */
1137        ring_release_frame(libtrace, packet);
1138
1139        /* Fetch the current frame */
1140        header = GET_CURRENT_BUFFER(libtrace);
1141        if(header->tp_status & TP_STATUS_USER){
1142                /* We have a frame waiting */
1143                event.size = trace_read_packet(libtrace, packet);
1144                event.type = TRACE_EVENT_PACKET;
1145        } else {
1146                /* Ok we don't have a packet waiting */
1147                event.type = TRACE_EVENT_IOWAIT;
1148                event.fd = FORMAT(libtrace->format_data)->fd;
1149        }
1150
1151        return event;
1152}
1153
1154
1155static int linuxnative_write_packet(libtrace_out_t *trace, 
1156                libtrace_packet_t *packet) 
1157{
1158        struct sockaddr_ll hdr;
1159        int ret = 0;
1160
1161        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
1162                return 0;
1163
1164        hdr.sll_family = AF_PACKET;
1165        hdr.sll_protocol = 0;
1166        hdr.sll_ifindex = if_nametoindex(trace->uridata);
1167        hdr.sll_hatype = 0;
1168        hdr.sll_pkttype = 0;
1169        hdr.sll_halen = htons(6); /* FIXME */
1170        memcpy(hdr.sll_addr,packet->payload,(size_t)ntohs(hdr.sll_halen));
1171
1172        /* This is pretty easy, just send the payload using sendto() (after
1173         * setting up the sll header properly, of course) */
1174        ret = sendto(DATAOUT(trace)->fd,
1175                        packet->payload,
1176                        trace_get_capture_length(packet),
1177                        0,
1178                        (struct sockaddr*)&hdr, (socklen_t)sizeof(hdr));
1179
1180        if (ret < 0) {
1181                trace_set_err_out(trace, errno, "sendto failed");
1182        }
1183
1184        return ret;
1185
1186}
1187static int linuxring_write_packet(libtrace_out_t *trace, 
1188                libtrace_packet_t *packet)
1189{
1190        struct tpacket2_hdr *header;
1191        struct pollfd pollset;
1192        struct socket_addr;
1193        int ret; 
1194        unsigned max_size;
1195        void * off;
1196
1197        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
1198                return 0;
1199
1200        max_size = DATAOUT(trace)->req.tp_frame_size - 
1201                 - TPACKET_HDRLEN + sizeof(struct sockaddr_ll);
1202
1203        header = (void *) DATAOUT(trace)->tx_ring + 
1204        (DATAOUT(trace)->txring_offset * DATAOUT(trace)->req.tp_frame_size);
1205
1206        while(header->tp_status != TP_STATUS_AVAILABLE){
1207                /* if none available: wait on more data */
1208                pollset.fd = DATAOUT(trace)->fd;
1209                pollset.events = POLLOUT;
1210                pollset.revents = 0;
1211                ret = poll(&pollset, 1, 1000);
1212                if (ret < 0 && errno != EINTR) {
1213                        perror("poll");
1214                        return -1;
1215                }
1216                if(ret == 0) 
1217                        /* Timeout something has gone wrong - maybe the queue is
1218                         * to large so try issue another send command
1219                         */
1220                        ret = sendto(DATAOUT(trace)->fd, 
1221                                NULL, 
1222                                0, 
1223                                0, 
1224                                (void *) &DATAOUT(trace)->sock_hdr, 
1225                                sizeof(DATAOUT(trace)->sock_hdr));
1226                        if (ret < 0) {
1227                                trace_set_err_out(trace, errno, 
1228                                                "sendto after timeout failed");
1229                                return -1;
1230                        }
1231        }
1232       
1233        header->tp_len = trace_get_capture_length(packet);
1234
1235        /* We cannot write the whole packet so just write part of it */
1236        if (header->tp_len > max_size)
1237                header->tp_len = max_size;
1238
1239        /* Fill packet - no sockaddr_ll in header when writing to the TX_RING */
1240        off = ((void *) header) + (TPACKET_HDRLEN - sizeof(struct sockaddr_ll));
1241        memcpy(off, 
1242                (char *) packet->payload, 
1243                header->tp_len);
1244       
1245        /* 'Send it' and increase ring pointer to the next frame */
1246        header->tp_status = TP_STATUS_SEND_REQUEST;
1247        DATAOUT(trace)->txring_offset = (DATAOUT(trace)->txring_offset + 1) % 
1248                                                DATAOUT(trace)->req.tp_frame_nr;
1249
1250        /* Notify kernel there are frames to send */
1251        DATAOUT(trace)->queue ++;
1252        DATAOUT(trace)->queue %= TX_MAX_QUEUE;
1253        if(DATAOUT(trace)->queue == 0){
1254                ret = sendto(DATAOUT(trace)->fd, 
1255                                NULL, 
1256                                0, 
1257                                MSG_DONTWAIT, 
1258                                (void *) &DATAOUT(trace)->sock_hdr, 
1259                                sizeof(DATAOUT(trace)->sock_hdr));
1260                if (ret < 0) {
1261                        trace_set_err_out(trace, errno, "sendto failed");
1262                        return -1;
1263                }
1264        }
1265        return header->tp_len;
1266
1267}
1268#endif /* HAVE_NETPACKET_PACKET_H */
1269
1270static inline libtrace_linktype_t get_libtrace_link_type(uint16_t linktype){
1271        /* Convert the ARPHRD type into an appropriate libtrace link type */
1272        switch (linktype) {
1273                case LIBTRACE_ARPHRD_ETHER:
1274                case LIBTRACE_ARPHRD_LOOPBACK:
1275                        return TRACE_TYPE_ETH;
1276                case LIBTRACE_ARPHRD_PPP:
1277                        return TRACE_TYPE_NONE;
1278                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
1279                        return TRACE_TYPE_80211_RADIO;
1280                case LIBTRACE_ARPHRD_IEEE80211:
1281                        return TRACE_TYPE_80211;
1282                case LIBTRACE_ARPHRD_SIT:
1283                case LIBTRACE_ARPHRD_NONE:
1284                        return TRACE_TYPE_NONE;
1285                default: /* shrug, beyond me! */
1286                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
1287                        return (libtrace_linktype_t)~0U;
1288        }
1289}
1290static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
1291        uint16_t linktype=(((struct libtrace_linuxnative_header*)(packet->buffer))
1292                                ->hdr.sll_hatype);
1293        return get_libtrace_link_type(linktype);
1294}
1295static libtrace_linktype_t linuxring_get_link_type(const struct libtrace_packet_t *packet) {
1296        uint16_t linktype= GET_SOCKADDR_HDR(packet->buffer)->sll_hatype;
1297        return get_libtrace_link_type(linktype);
1298}
1299
1300static inline libtrace_direction_t get_libtrace_direction(uint8_t pkttype){
1301        switch (pkttype) {
1302                case PACKET_OUTGOING:
1303                case PACKET_LOOPBACK:
1304                        return TRACE_DIR_OUTGOING;
1305                case PACKET_OTHERHOST:
1306                        return TRACE_DIR_OTHER;
1307                default:
1308                        return TRACE_DIR_INCOMING;
1309        }
1310}
1311static libtrace_direction_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
1312        return get_libtrace_direction(((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype);
1313}
1314static libtrace_direction_t linuxring_get_direction(const struct libtrace_packet_t *packet) {
1315        return get_libtrace_direction(GET_SOCKADDR_HDR(packet->buffer)->sll_pkttype);
1316}
1317
1318static libtrace_direction_t set_direction(struct sockaddr_ll * skadr, libtrace_direction_t direction){
1319        switch (direction) {
1320                case TRACE_DIR_OUTGOING:
1321                        skadr->sll_pkttype = PACKET_OUTGOING;
1322                        return TRACE_DIR_OUTGOING;
1323                case TRACE_DIR_INCOMING:
1324                        skadr->sll_pkttype = PACKET_HOST;
1325                        return TRACE_DIR_INCOMING;
1326                case TRACE_DIR_OTHER:
1327                        skadr->sll_pkttype = PACKET_OTHERHOST;
1328                        return TRACE_DIR_OTHER;
1329                default:
1330                        return -1;
1331        }
1332}
1333static libtrace_direction_t linuxnative_set_direction(
1334                libtrace_packet_t *packet,
1335                libtrace_direction_t direction) {
1336        return set_direction(&((struct libtrace_linuxnative_header*)(packet->buffer))->hdr, direction);
1337}
1338static libtrace_direction_t linuxring_set_direction(
1339                libtrace_packet_t *packet,
1340                libtrace_direction_t direction) {
1341        return set_direction(GET_SOCKADDR_HDR(packet->buffer), direction);
1342}
1343
1344static struct timespec linuxnative_get_timespec(const libtrace_packet_t *packet) 
1345{
1346        struct libtrace_linuxnative_header *hdr = 
1347                (struct libtrace_linuxnative_header*) packet->buffer;
1348        /* We have to upconvert from timeval to timespec */
1349        if (hdr->timestamptype == TS_TIMEVAL) {
1350                struct timespec ts;
1351                ts.tv_sec = hdr->tv.tv_sec;
1352                ts.tv_nsec = hdr->tv.tv_usec*1000;
1353                return ts;
1354        }
1355        else {
1356                struct timespec ts;
1357                ts.tv_sec = hdr->ts.tv_sec;
1358                ts.tv_nsec = hdr->ts.tv_nsec;
1359                return ts;
1360        }
1361}
1362static struct timespec linuxring_get_timespec(const libtrace_packet_t *packet) 
1363{
1364        struct timespec ts;
1365        ts.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
1366        ts.tv_nsec = TO_TP_HDR(packet->buffer)->tp_nsec;
1367        return ts;
1368}
1369
1370
1371static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet) 
1372{
1373        struct libtrace_linuxnative_header *hdr = 
1374                (struct libtrace_linuxnative_header*) packet->buffer;
1375        /* We have to downconvert from timespec to timeval */
1376        if (hdr->timestamptype == TS_TIMESPEC) {
1377                struct timeval tv;
1378                tv.tv_sec = hdr->ts.tv_sec;
1379                tv.tv_usec = hdr->ts.tv_nsec/1000;
1380                return tv;
1381        }
1382        else {
1383                struct timeval tv;
1384                tv.tv_sec = hdr->tv.tv_sec;
1385                tv.tv_usec = hdr->tv.tv_usec;
1386                return tv;
1387        }
1388}
1389static struct timeval linuxring_get_timeval(const libtrace_packet_t *packet) 
1390{
1391        struct timeval tv;
1392        tv.tv_sec = TO_TP_HDR(packet->buffer)->tp_sec;
1393        tv.tv_usec = TO_TP_HDR(packet->buffer)->tp_nsec / 1000;
1394        return tv;
1395}
1396
1397static int linuxnative_get_capture_length(const libtrace_packet_t *packet)
1398{
1399        return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen;
1400}
1401
1402static int linuxring_get_capture_length(const libtrace_packet_t *packet)
1403{
1404        return TO_TP_HDR(packet->buffer)->tp_snaplen;
1405}
1406
1407static int linuxnative_get_wire_length(const libtrace_packet_t *packet) 
1408{
1409
1410        int wirelen = ((struct libtrace_linuxnative_header*)(packet->buffer))->wirelen;
1411
1412        /* Include the missing FCS */
1413        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
1414                wirelen += 4;
1415
1416        return wirelen;
1417}
1418
1419static int linuxring_get_wire_length(const libtrace_packet_t *packet) 
1420{
1421        int wirelen = TO_TP_HDR(packet->buffer)->tp_len;
1422
1423        /* Include the missing FCS */
1424        if (trace_get_link_type(packet) == TRACE_TYPE_ETH)
1425                wirelen += 4;
1426
1427        return wirelen;
1428}
1429
1430static int linuxnative_get_framing_length(UNUSED
1431                const libtrace_packet_t *packet) 
1432{
1433        return sizeof(struct libtrace_linuxnative_header);
1434}
1435
1436static int linuxring_get_framing_length(const libtrace_packet_t *packet)
1437{       
1438        /*
1439         * Need to make frame_length + capture_length = complete capture length
1440         * so include alligment whitespace. So reverse calculate from packet.
1441         */
1442        return (char *) packet->payload - (char *) packet->buffer;
1443}
1444
1445static size_t linuxnative_set_capture_length(libtrace_packet_t *packet, 
1446                size_t size) {
1447
1448        struct libtrace_linuxnative_header *linux_hdr = NULL;
1449        assert(packet);
1450        if (size > trace_get_capture_length(packet)) {
1451                /* We should avoid making a packet larger */
1452                return trace_get_capture_length(packet);
1453        }
1454       
1455        /* Reset the cached capture length */
1456        packet->capture_length = -1;
1457
1458        linux_hdr = (struct libtrace_linuxnative_header *)packet->header;
1459        linux_hdr->caplen = size;
1460        return trace_get_capture_length(packet);
1461}
1462
1463static size_t linuxring_set_capture_length(libtrace_packet_t *packet, 
1464                size_t size) {
1465        assert(packet);
1466        if (size > trace_get_capture_length(packet)) {
1467                /* We should avoid making a packet larger */
1468                return trace_get_capture_length(packet);
1469        }
1470       
1471        /* Reset the cached capture length */
1472        packet->capture_length = -1;
1473
1474        TO_TP_HDR(packet->buffer)->tp_snaplen = size;
1475
1476        return trace_get_capture_length(packet);
1477}
1478
1479static int linuxnative_get_fd(const libtrace_t *trace) {
1480        if (trace->format_data == NULL)
1481                return -1;
1482        return FORMAT(trace->format_data)->fd;
1483}
1484
1485/* Linux doesn't keep track how many packets were seen before filtering
1486 * so we can't tell how many packets were filtered.  Bugger.  So annoying.
1487 *
1488 * Since we tell libtrace that we do support filtering, if we don't declare
1489 * this here as failing, libtrace will happily report for us that it didn't
1490 * filter any packets, so don't lie -- return that we don't know.
1491 */
1492static uint64_t linuxnative_get_filtered_packets(libtrace_t *trace UNUSED) {
1493        return UINT64_MAX;
1494}
1495
1496/* Number of packets that passed filtering */
1497static uint64_t linuxnative_get_captured_packets(libtrace_t *trace) {
1498        if (trace->format_data == NULL)
1499                return UINT64_MAX;
1500        if (FORMAT(trace->format_data)->fd == -1) {
1501                /* This is probably a 'dead' trace so obviously we can't query
1502                 * the socket for capture counts, can we? */
1503                return UINT64_MAX;
1504        }
1505
1506#ifdef HAVE_NETPACKET_PACKET_H 
1507        if ((FORMAT(trace->format_data)->stats_valid & 1) 
1508                        || FORMAT(trace->format_data)->stats_valid == 0) {
1509                socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
1510                getsockopt(FORMAT(trace->format_data)->fd, 
1511                                SOL_PACKET,
1512                                PACKET_STATISTICS,
1513                                &FORMAT(trace->format_data)->stats,
1514                                &len);
1515                FORMAT(trace->format_data)->stats_valid |= 1;
1516        }
1517
1518        return FORMAT(trace->format_data)->stats.tp_packets;
1519#else
1520        return UINT64_MAX;
1521#endif
1522}
1523
1524/* Number of packets that got past filtering and were then dropped because
1525 * of lack of space
1526 */
1527static uint64_t linuxnative_get_dropped_packets(libtrace_t *trace) {
1528        if (trace->format_data == NULL)
1529                return UINT64_MAX;
1530        if (FORMAT(trace->format_data)->fd == -1) {
1531                /* This is probably a 'dead' trace so obviously we can't query
1532                 * the socket for drop counts, can we? */
1533                return UINT64_MAX;
1534        }
1535       
1536#ifdef HAVE_NETPACKET_PACKET_H 
1537        if ((FORMAT(trace->format_data)->stats_valid & 2)
1538                        || (FORMAT(trace->format_data)->stats_valid==0)) {
1539                socklen_t len = sizeof(FORMAT(trace->format_data)->stats);
1540                getsockopt(FORMAT(trace->format_data)->fd, 
1541                                SOL_PACKET,
1542                                PACKET_STATISTICS,
1543                                &FORMAT(trace->format_data)->stats,
1544                                &len);
1545                FORMAT(trace->format_data)->stats_valid |= 2;
1546        }
1547
1548        return FORMAT(trace->format_data)->stats.tp_drops;
1549#else
1550        return UINT64_MAX;
1551#endif
1552}
1553
1554#ifdef HAVE_NETPACKET_PACKET_H
1555static void linuxnative_help(void) {
1556        printf("linuxnative format module: $Revision: 1793 $\n");
1557        printf("Supported input URIs:\n");
1558        printf("\tint:eth0\n");
1559        printf("\n");
1560        printf("Supported output URIs:\n");
1561        printf("\tint:eth0\n");
1562        printf("\n");
1563        return;
1564}
1565
1566static void linuxring_help(void) {
1567        printf("linuxring format module: $Revision: 1793 $\n");
1568        printf("Supported input URIs:\n");
1569        printf("\tring:eth0\n");
1570        printf("\n");
1571        printf("Supported output URIs:\n");
1572        printf("\tring:eth0\n");
1573        printf("\n");
1574        return;
1575}
1576
1577static struct libtrace_format_t linuxnative = {
1578        "int",
1579        "$Id$",
1580        TRACE_FORMAT_LINUX_NATIVE,
1581        linuxnative_probe_filename,     /* probe filename */
1582        NULL,                           /* probe magic */
1583        linuxnative_init_input,         /* init_input */
1584        linuxnative_config_input,       /* config_input */
1585        linuxnative_start_input,        /* start_input */
1586        linuxnative_pause_input,        /* pause_input */
1587        linuxnative_init_output,        /* init_output */
1588        NULL,                           /* config_output */
1589        linuxnative_start_output,       /* start_ouput */
1590        linuxnative_fin_input,          /* fin_input */
1591        linuxnative_fin_output,         /* fin_output */
1592        linuxnative_read_packet,        /* read_packet */
1593        linuxnative_prepare_packet,     /* prepare_packet */
1594        NULL,                           /* fin_packet */
1595        linuxnative_write_packet,       /* write_packet */
1596        linuxnative_get_link_type,      /* get_link_type */
1597        linuxnative_get_direction,      /* get_direction */
1598        linuxnative_set_direction,      /* set_direction */
1599        NULL,                           /* get_erf_timestamp */
1600        linuxnative_get_timeval,        /* get_timeval */
1601        linuxnative_get_timespec,       /* get_timespec */
1602        NULL,                           /* get_seconds */
1603        NULL,                           /* seek_erf */
1604        NULL,                           /* seek_timeval */
1605        NULL,                           /* seek_seconds */
1606        linuxnative_get_capture_length, /* get_capture_length */
1607        linuxnative_get_wire_length,    /* get_wire_length */
1608        linuxnative_get_framing_length, /* get_framing_length */
1609        linuxnative_set_capture_length, /* set_capture_length */
1610        NULL,                           /* get_received_packets */
1611        linuxnative_get_filtered_packets,/* get_filtered_packets */
1612        linuxnative_get_dropped_packets,/* get_dropped_packets */
1613        linuxnative_get_captured_packets,/* get_captured_packets */
1614        linuxnative_get_fd,             /* get_fd */
1615        trace_event_device,             /* trace_event */
1616        linuxnative_help,               /* help */
1617        NULL
1618};
1619
1620static struct libtrace_format_t linuxring = {
1621        "ring",
1622        "$Id$",
1623        TRACE_FORMAT_LINUX_RING,
1624        linuxnative_probe_filename,     /* probe filename */
1625        NULL,                           /* probe magic */
1626        linuxring_init_input,           /* init_input */
1627        linuxnative_config_input,       /* config_input */
1628        linuxring_start_input,  /* start_input */
1629        linuxring_pause_input,  /* pause_input */
1630        linuxring_init_output,  /* init_output */
1631        NULL,                           /* config_output */
1632        linuxring_start_output, /* start_ouput */
1633        linuxnative_fin_input,          /* fin_input */
1634        linuxring_fin_output,           /* fin_output */
1635        linuxring_read_packet,  /* read_packet */
1636        linuxring_prepare_packet,       /* prepare_packet */
1637        NULL,                           /* fin_packet */
1638        linuxring_write_packet, /* write_packet */
1639        linuxring_get_link_type,        /* get_link_type */
1640        linuxring_get_direction,        /* get_direction */
1641        linuxring_set_direction,        /* set_direction */
1642        NULL,                           /* get_erf_timestamp */
1643        linuxring_get_timeval,  /* get_timeval */
1644        linuxring_get_timespec, /* get_timespec */
1645        NULL,                           /* get_seconds */
1646        NULL,                           /* seek_erf */
1647        NULL,                           /* seek_timeval */
1648        NULL,                           /* seek_seconds */
1649        linuxring_get_capture_length,   /* get_capture_length */
1650        linuxring_get_wire_length,      /* get_wire_length */
1651        linuxring_get_framing_length,   /* get_framing_length */
1652        linuxring_set_capture_length,   /* set_capture_length */
1653        NULL,                           /* get_received_packets */
1654        linuxnative_get_filtered_packets,/* get_filtered_packets */
1655        linuxnative_get_dropped_packets,/* get_dropped_packets */
1656        linuxnative_get_captured_packets,/* get_captured_packets */
1657        linuxnative_get_fd,             /* get_fd */
1658        linuxring_event,                /* trace_event */
1659        linuxring_help,         /* help */
1660        NULL
1661};
1662#else
1663static void linuxnative_help(void) {
1664        printf("linuxnative format module: $Revision: 1793 $\n");
1665        printf("Not supported on this host\n");
1666}
1667static void linuxring_help(void) {
1668        printf("linuxring format module: $Revision: 1793 $\n");
1669        printf("Not supported on this host\n");
1670}
1671
1672static struct libtrace_format_t linuxnative = {
1673        "int",
1674        "$Id$",
1675        TRACE_FORMAT_LINUX_NATIVE,
1676        NULL,                           /* probe filename */
1677        NULL,                           /* probe magic */
1678        NULL,                           /* init_input */
1679        NULL,                           /* config_input */
1680        NULL,                           /* start_input */
1681        NULL,                           /* pause_input */
1682        NULL,                           /* init_output */
1683        NULL,                           /* config_output */
1684        NULL,                           /* start_ouput */
1685        NULL,                           /* fin_input */
1686        NULL,                           /* fin_output */
1687        NULL,                           /* read_packet */
1688        linuxnative_prepare_packet,     /* prepare_packet */
1689        NULL,                           /* fin_packet */
1690        NULL,                           /* write_packet */
1691        linuxnative_get_link_type,      /* get_link_type */
1692        linuxnative_get_direction,      /* get_direction */
1693        linuxnative_set_direction,      /* set_direction */
1694        NULL,                           /* get_erf_timestamp */
1695        linuxnative_get_timeval,        /* get_timeval */
1696        linuxnative_get_timespec,       /* get_timespec */
1697        NULL,                           /* get_seconds */
1698        NULL,                           /* seek_erf */
1699        NULL,                           /* seek_timeval */
1700        NULL,                           /* seek_seconds */
1701        linuxnative_get_capture_length, /* get_capture_length */
1702        linuxnative_get_wire_length,    /* get_wire_length */
1703        linuxnative_get_framing_length, /* get_framing_length */
1704        linuxnative_set_capture_length, /* set_capture_length */
1705        NULL,                           /* get_received_packets */
1706        linuxnative_get_filtered_packets,/* get_filtered_packets */
1707        linuxnative_get_dropped_packets,/* get_dropped_packets */
1708        linuxnative_get_captured_packets,/* get_captured_packets */
1709        linuxnative_get_fd,             /* get_fd */
1710        trace_event_device,             /* trace_event */
1711        linuxnative_help,               /* help */
1712        NULL
1713};
1714
1715static struct libtrace_format_t linuxring = {
1716        "ring",
1717        "$Id$",
1718        TRACE_FORMAT_LINUX_RING,
1719        NULL,                           /* probe filename */
1720        NULL,                           /* probe magic */
1721        NULL,                           /* init_input */
1722        NULL,                           /* config_input */
1723        NULL,                           /* start_input */
1724        NULL,                           /* pause_input */
1725        NULL,                           /* init_output */
1726        NULL,                           /* config_output */
1727        NULL,                           /* start_ouput */
1728        NULL,                           /* fin_input */
1729        NULL,                           /* fin_output */
1730        NULL,                           /* read_packet */
1731        linuxring_prepare_packet,       /* prepare_packet */
1732        NULL,                           /* fin_packet */
1733        NULL,                           /* write_packet */
1734        linuxring_get_link_type,        /* get_link_type */
1735        linuxring_get_direction,        /* get_direction */
1736        linuxring_set_direction,        /* set_direction */
1737        NULL,                           /* get_erf_timestamp */
1738        linuxring_get_timeval,          /* get_timeval */
1739        linuxring_get_timespec,         /* get_timespec */
1740        NULL,                           /* get_seconds */
1741        NULL,                           /* seek_erf */
1742        NULL,                           /* seek_timeval */
1743        NULL,                           /* seek_seconds */
1744        linuxring_get_capture_length,   /* get_capture_length */
1745        linuxring_get_wire_length,      /* get_wire_length */
1746        linuxring_get_framing_length,   /* get_framing_length */
1747        linuxring_set_capture_length,   /* set_capture_length */
1748        NULL,                           /* get_received_packets */
1749        linuxnative_get_filtered_packets,/* get_filtered_packets */
1750        linuxnative_get_dropped_packets,/* get_dropped_packets */
1751        linuxnative_get_captured_packets,/* get_captured_packets */
1752        linuxnative_get_fd,             /* get_fd */
1753        NULL,                           /* trace_event */
1754        linuxring_help,                 /* help */
1755        NULL
1756};
1757
1758#endif /* HAVE_NETPACKET_PACKET_H */
1759
1760
1761void linuxnative_constructor(void) {
1762        /* TODO: once we're happy with ring:, it would be a good idea to
1763         * swap the order of these calls so that ring: is preferred over
1764         * int: if the user just gives an interface name as an input without
1765         * explicitly choosing a format.
1766         */
1767        register_format(&linuxnative);
1768        register_format(&linuxring);
1769}
Note: See TracBrowser for help on using the repository browser.