source: lib/format_linux_common.c @ 6b98325

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 6b98325 was 6b98325, checked in by Richard Sanger <rsangerarj@…>, 6 years ago

Removes pconfig_input() and replaces trace_config() with trace_set_<option>

  • Removes trace_pconfig completely - only trace_set_hasher is left now in trace_config
  • Rework user configuration so this is no longer modified directly. Now we just apply it directly to a trace.
  • Many minor documentation fixes and additions
  • Property mode set to 100644
File size: 20.8 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 file contains the common functions used by both the ring and int
36 * formats.
37 *
38 * Typically these deal with the socket descriptor or common conversions.
39 */
40
41#include "config.h"
42#include "libtrace.h"
43#include "libtrace_int.h"
44#include "format_helper.h"
45#include "libtrace_arphrd.h"
46#include <stdlib.h>
47#include <errno.h>
48#include <unistd.h>
49#include <string.h>
50#include <assert.h>
51
52#ifdef HAVE_INTTYPES_H
53#  include <inttypes.h>
54#else
55# error "Can't find inttypes.h"
56#endif
57
58#include "format_linux_common.h"
59
60#ifdef HAVE_NETPACKET_PACKET_H
61
62int linuxcommon_probe_filename(const char *filename)
63{
64        /* Is this an interface? */
65        return (if_nametoindex(filename) != 0);
66}
67
68/* Compiles a libtrace BPF filter for use with a linux native socket */
69static int linuxnative_configure_bpf(libtrace_t *libtrace,
70                libtrace_filter_t *filter) {
71#ifdef HAVE_LIBPCAP
72        struct ifreq ifr;
73        unsigned int arphrd;
74        libtrace_dlt_t dlt;
75        libtrace_filter_t *f;
76        int sock;
77        pcap_t *pcap;
78
79        /* Take a copy of the filter object as it was passed in */
80        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
81        memcpy(f, filter, sizeof(libtrace_filter_t));
82
83        /* If we are passed a filter with "flag" set to zero, then we must
84         * compile the filterstring before continuing. This involves
85         * determining the linktype, passing the filterstring to libpcap to
86         * compile, and saving the result for trace_start() to push into the
87         * kernel.
88         * If flag is set to one, then the filter was probably generated using
89         * trace_create_filter_from_bytecode() and so we don't need to do
90         * anything (we've just copied it above).
91         */
92        if (f->flag == 0) {
93                sock = socket(PF_INET, SOCK_STREAM, 0);
94                memset(&ifr, 0, sizeof(struct ifreq));
95                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE);
96                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
97                        perror("Can't get HWADDR for interface");
98                        return -1;
99                }
100                close(sock);
101
102                arphrd = ifr.ifr_hwaddr.sa_family;
103                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
104
105                pcap = pcap_open_dead(dlt,
106                                FORMAT_DATA->snaplen);
107
108                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
109                        /* Filter didn't compile, set flag to 0 so we can
110                         * detect this when trace_start() is called and
111                         * produce a useful error
112                         */
113                        f->flag = 0;
114                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
115                                      "Failed to compile BPF filter (%s): %s",
116                                      f->filterstring, pcap_geterr(pcap));
117                } else {
118                        /* Set the "flag" to indicate that the filterstring
119                         * has been compiled
120                         */
121                        f->flag = 1;
122                }
123
124                pcap_close(pcap);
125
126        }
127
128        if (FORMAT_DATA->filter != NULL)
129                free(FORMAT_DATA->filter);
130
131        FORMAT_DATA->filter = f;
132
133        return 0;
134#else
135        return -1
136#endif
137}
138
139int linuxcommon_config_input(libtrace_t *libtrace,
140                trace_option_t option,
141                void *data)
142{
143        switch(option) {
144                case TRACE_OPTION_SNAPLEN:
145                        FORMAT_DATA->snaplen=*(int*)data;
146                        return 0;
147                case TRACE_OPTION_PROMISC:
148                        FORMAT_DATA->promisc=*(int*)data;
149                        return 0;
150                case TRACE_OPTION_FILTER:
151                        return linuxnative_configure_bpf(libtrace,
152                                        (libtrace_filter_t *) data);
153                case TRACE_OPTION_HASHER:
154                        switch (*((enum hasher_types *)data)) {
155                                case HASHER_BALANCE:
156                                        // Do fanout
157                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
158                                        // Or we could balance to the CPU
159                                        return 0;
160                                case HASHER_BIDIRECTIONAL:
161                                case HASHER_UNIDIRECTIONAL:
162                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_HASH;
163                                        return 0;
164                                case HASHER_CUSTOM:
165                                        return -1;
166                        }
167                        break;
168                case TRACE_OPTION_META_FREQ:
169                        /* No meta-data for this format */
170                        break;
171                case TRACE_OPTION_EVENT_REALTIME:
172                        /* Live captures are always going to be in trace time */
173                        break;
174                /* Avoid default: so that future options will cause a warning
175                 * here to remind us to implement it, or flag it as
176                 * unimplementable
177                 */
178        }
179
180        /* Don't set an error - trace_config will try to deal with the
181         * option and will set an error if it fails */
182        return -1;
183}
184
185int linuxcommon_init_input(libtrace_t *libtrace)
186{
187        struct linux_per_stream_t stream_data = ZERO_LINUX_STREAM;
188
189        libtrace->format_data = (struct linux_format_data_t *)
190                malloc(sizeof(struct linux_format_data_t));
191        assert(libtrace->format_data != NULL);
192
193        FORMAT_DATA->per_stream =
194                libtrace_list_init(sizeof(stream_data));
195        assert(FORMAT_DATA->per_stream != NULL);
196
197        libtrace_list_push_back(FORMAT_DATA->per_stream, &stream_data);
198
199        FORMAT_DATA->promisc = -1;
200        FORMAT_DATA->snaplen = LIBTRACE_PACKET_BUFSIZE;
201        FORMAT_DATA->filter = NULL;
202        FORMAT_DATA->stats_valid = 0;
203        FORMAT_DATA->stats.tp_drops = 0;
204        FORMAT_DATA->stats.tp_packets = 0;
205        FORMAT_DATA->max_order = MAX_ORDER;
206        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
207        /* Some examples use pid for the group however that would limit a single
208         * application to use only int/ring format, instead using rand */
209        FORMAT_DATA->fanout_group = (uint16_t) rand();
210        return 0;
211}
212
213int linuxcommon_init_output(libtrace_out_t *libtrace)
214{
215        libtrace->format_data = (struct linux_format_data_out_t*)
216                malloc(sizeof(struct linux_format_data_out_t));
217        assert(libtrace->format_data != NULL);
218
219        FORMAT_DATA_OUT->fd = -1;
220        FORMAT_DATA_OUT->tx_ring = NULL;
221        FORMAT_DATA_OUT->txring_offset = 0;
222        FORMAT_DATA_OUT->queue = 0;
223        FORMAT_DATA_OUT->max_order = MAX_ORDER;
224        return 0;
225}
226
227/* Close an input stream, this is safe to be called part way through
228 * initilisation as a cleanup function assuming streams were set to
229 * ZERO_LINUX_STREAM to begin with.
230 *
231 * This works correctly with both int and ring
232 */
233void linuxcommon_close_input_stream(libtrace_t *libtrace,
234                                    struct linux_per_stream_t *stream) {
235        if (stream->fd != -1)
236                close(stream->fd);
237        stream->fd = -1;
238        if (stream->rx_ring != MAP_FAILED)
239                munmap(stream->rx_ring,
240                       stream->req.tp_block_size *
241                       stream->req.tp_block_nr);
242        stream->rx_ring = MAP_FAILED;
243        stream->rxring_offset = 0;
244        FORMAT_DATA->dev_stats.if_name[0] = 0;
245}
246
247#define REPEAT_16(x) x x x x x x x x x x x x x x x x
248#define xstr(s) str(s)
249#define str(s) #s
250
251/* These don't typically reset however an interface does exist to reset them */
252static int linuxcommon_get_dev_statisitics(libtrace_t *libtrace, struct linux_dev_stats *stats) {
253        FILE *file;
254        char line[1024];
255        struct linux_dev_stats tmp_stats;
256
257        file = fopen("/proc/net/dev","r");
258        if (file == NULL) {
259                return -1;
260        }
261
262        /* Skip 2 header lines */
263        fgets(line, sizeof(line), file);
264        fgets(line, sizeof(line), file);
265
266        while (!(feof(file)||ferror(file))) {
267                int tot;
268                fgets(line, sizeof(line), file);
269                tot = sscanf(line, " %"xstr(IF_NAMESIZE)"[^:]:" REPEAT_16(" %"SCNd64),
270                             tmp_stats.if_name,
271                             &tmp_stats.rx_bytes,
272                             &tmp_stats.rx_packets,
273                             &tmp_stats.rx_errors,
274                             &tmp_stats.rx_drops,
275                             &tmp_stats.rx_fifo,
276                             &tmp_stats.rx_frame,
277                             &tmp_stats.rx_compressed,
278                             &tmp_stats.rx_multicast,
279                             &tmp_stats.tx_bytes,
280                             &tmp_stats.tx_packets,
281                             &tmp_stats.tx_errors,
282                             &tmp_stats.tx_drops,
283                             &tmp_stats.tx_fifo,
284                             &tmp_stats.tx_colls,
285                             &tmp_stats.tx_carrier,
286                             &tmp_stats.tx_compressed);
287                if (tot != 17)
288                        continue;
289                if (strncmp(tmp_stats.if_name, libtrace->uridata, IF_NAMESIZE) == 0) {
290                        *stats = tmp_stats;
291                        fclose(file);
292                        return 0;
293                }
294        }
295        fclose(file);
296        return -1;
297}
298
299/* Start an input stream
300 * - Opens the file descriptor
301 * - Sets promiscuous correctly
302 * - Sets socket option
303 * - Add BPF filter
304 *
305 * The output is ready for int directly, for ring the conversion to ring still
306 * needs to take place.
307 */
308int linuxcommon_start_input_stream(libtrace_t *libtrace,
309                                   struct linux_per_stream_t *stream)
310{
311        struct sockaddr_ll addr;
312        const int one = 1;
313        memset(&addr,0,sizeof(addr));
314        libtrace_filter_t *filter = FORMAT_DATA->filter;
315
316        /* Create a raw socket for reading packets on */
317        stream->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
318        if (stream->fd==-1) {
319                trace_set_err(libtrace, errno, "Could not create raw socket");
320                return -1;
321        }
322
323        /* Bind to the capture interface */
324        addr.sll_family = AF_PACKET;
325        addr.sll_protocol = htons(ETH_P_ALL);
326        if (strlen(libtrace->uridata)) {
327                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
328                if (addr.sll_ifindex == 0) {
329                        linuxcommon_close_input_stream(libtrace, stream);
330                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
331                                      "Failed to find interface %s",
332                                      libtrace->uridata);
333                        return -1;
334                }
335        } else {
336                addr.sll_ifindex = 0;
337        }
338        if (bind(stream->fd,
339                 (struct sockaddr*)&addr,
340                 (socklen_t)sizeof(addr))==-1) {
341                linuxcommon_close_input_stream(libtrace, stream);
342                trace_set_err(libtrace, errno,
343                              "Failed to bind to interface %s",
344                              libtrace->uridata);
345                return -1;
346        }
347
348        /* If promisc hasn't been specified, set it to "true" if we're
349         * capturing on one interface, or "false" if we're capturing on
350         * all interfaces.
351         */
352        if (FORMAT_DATA->promisc==-1) {
353                if (addr.sll_ifindex!=0)
354                        FORMAT_DATA->promisc=1;
355                else
356                        FORMAT_DATA->promisc=0;
357        }
358
359        /* Enable promiscuous mode, if requested */
360        if (FORMAT_DATA->promisc) {
361                struct packet_mreq mreq;
362                socklen_t socklen = sizeof(mreq);
363                memset(&mreq,0,sizeof(mreq));
364                mreq.mr_ifindex = addr.sll_ifindex;
365                mreq.mr_type = PACKET_MR_PROMISC;
366                if (setsockopt(stream->fd,
367                               SOL_PACKET,
368                               PACKET_ADD_MEMBERSHIP,
369                               &mreq,
370                               socklen)==-1) {
371                        perror("setsockopt(PROMISC)");
372                }
373        }
374
375        /* Set the timestamp option on the socket - aim for the most detailed
376         * clock resolution possible */
377#ifdef SO_TIMESTAMPNS
378        if (setsockopt(stream->fd,
379                       SOL_SOCKET,
380                       SO_TIMESTAMPNS,
381                       &one,
382                       (socklen_t)sizeof(one))!=-1) {
383                FORMAT_DATA->timestamptype = TS_TIMESPEC;
384        }
385        else
386        /* DANGER: This is a dangling else to only do the next setsockopt()
387         * if we fail the first! */
388#endif
389                if (setsockopt(stream->fd,
390                               SOL_SOCKET,
391                               SO_TIMESTAMP,
392                               &one,
393                               (socklen_t)sizeof(one))!=-1) {
394                        FORMAT_DATA->timestamptype = TS_TIMEVAL;
395                }
396                else
397                        FORMAT_DATA->timestamptype = TS_NONE;
398
399        /* Push BPF filter into the kernel. At this stage we can safely assume
400         * that the filterstring has been compiled, or the filter was supplied
401         * pre-compiled.
402         */
403        if (filter != NULL) {
404                /* Check if the filter was successfully compiled. If not,
405                 * it is probably a bad filter and we should return an error
406                 * before the caller tries to read any packets */
407                if (filter->flag == 0) {
408                        linuxcommon_close_input_stream(libtrace, stream);
409                        trace_set_err(libtrace, TRACE_ERR_BAD_FILTER,
410                                      "Cannot attach a bad filter to %s",
411                                      libtrace->uridata);
412                        return -1;
413                }
414
415                if (setsockopt(stream->fd,
416                               SOL_SOCKET,
417                               SO_ATTACH_FILTER,
418                               &filter->filter,
419                               sizeof(filter->filter)) == -1) {
420                        perror("setsockopt(SO_ATTACH_FILTER)");
421                }
422        }
423
424        /* Consume any buffered packets that were received before the socket
425         * was properly setup, including those which missed the filter and
426         * bind()ing to an interface.
427         *
428         * If packet rate is high this could therotically hang forever. 4K
429         * should be a large enough limit.
430         */
431        int count = 0;
432        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
433        while(count < 4096 &&
434                recv(stream->fd,
435                   buf,
436                   (size_t)LIBTRACE_PACKET_BUFSIZE,
437                   MSG_DONTWAIT) != -1) { count++; }
438        free(buf);
439
440        /* Mark that the stats are valid and apply an offset */
441        FORMAT_DATA->stats_valid = 1;
442        /* Offset by number we ate for each stream and reset stats after pause */
443        FORMAT_DATA->stats.tp_packets = -count;
444        FORMAT_DATA->stats.tp_drops = 0;
445
446        if (linuxcommon_get_dev_statisitics(libtrace, &FORMAT_DATA->dev_stats) != 0) {
447                /* Mark this as bad */
448                FORMAT_DATA->dev_stats.if_name[0] = 0;
449        }
450
451        return 0;
452}
453
454/**
455 * Converts a socket, either packet_mmap or standard raw socket into a
456 * fanout socket.
457 * NOTE: This means we can read from the socket with multiple queues,
458 * each must be setup (identically) and then this called upon them
459 *
460 * @return 0 success, -1 error
461 */
462inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace,
463                                        struct linux_per_stream_t *stream)
464{
465        int fanout_opt = ((int)FORMAT_DATA->fanout_flags << 16) |
466                         (int)FORMAT_DATA->fanout_group;
467        if (setsockopt(stream->fd, SOL_PACKET, PACKET_FANOUT,
468                        &fanout_opt, sizeof(fanout_opt)) == -1) {
469                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
470                              "Converting the fd to a socket fanout failed %s",
471                              libtrace->uridata);
472                return -1;
473        }
474        return 0;
475}
476
477int linuxcommon_pause_input(libtrace_t *libtrace)
478{
479        size_t i;
480
481        /* Stop and detach each stream */
482        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
483                struct linux_per_stream_t *stream;
484                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
485                linuxcommon_close_input_stream(libtrace, stream);
486        }
487
488        return 0;
489}
490
491int linuxcommon_fin_input(libtrace_t *libtrace)
492{
493        if (libtrace->format_data) {
494                if (FORMAT_DATA->filter != NULL)
495                        free(FORMAT_DATA->filter);
496
497                if (FORMAT_DATA->per_stream)
498                        libtrace_list_deinit(FORMAT_DATA->per_stream);
499
500                free(libtrace->format_data);
501        }
502
503        return 0;
504}
505
506int linuxcommon_pregister_thread(libtrace_t *libtrace,
507                                 libtrace_thread_t *t,
508                                 bool reading) {
509        if (reading) {
510                /* XXX TODO remove this oneday make sure hasher thread still works */
511                struct linux_per_stream_t *stream;
512                stream = libtrace_list_get_index(FORMAT_DATA->per_stream,
513                                                 t->perpkt_num)->data;
514                t->format_data = stream;
515                if (!stream) {
516                        /* This should never happen and indicates an
517                         * internal libtrace bug */
518                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
519                                      "Failed to attached thread %d to a stream",
520                                      t->perpkt_num);
521                        return -1;
522                }
523        }
524        return 0;
525}
526
527/* These counters reset with each read */
528static void linuxcommon_update_socket_statistics(libtrace_t *libtrace) {
529        struct tpacket_stats stats;
530        size_t i;
531        socklen_t len = sizeof(stats);
532
533        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
534                struct linux_per_stream_t *stream;
535                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
536                if (stream->fd != -1) {
537                        if (getsockopt(stream->fd,
538                                   SOL_PACKET,
539                                   PACKET_STATISTICS,
540                                   &stats,
541                                   &len) == 0) {
542                                if (FORMAT_DATA->stats_valid==0) {
543                                        FORMAT_DATA->stats.tp_drops = stats.tp_drops;
544                                        FORMAT_DATA->stats.tp_packets = stats.tp_packets;
545                                        FORMAT_DATA->stats_valid = 1;
546                                } else {
547                                        FORMAT_DATA->stats.tp_drops += stats.tp_drops;
548                                        FORMAT_DATA->stats.tp_packets += stats.tp_packets;
549                                }
550                        } else {
551                                perror("getsockopt PACKET_STATISTICS failed");
552                        }
553                }
554        }
555}
556
557#define DEV_DIFF(x) (dev_stats.x - FORMAT_DATA->dev_stats.x)
558/* Note these statistics come from two different sources, the socket itself and
559 * the linux device. As such this means it is highly likely that their is some
560 * margin of error in the returned statisitics, we perform basic sanitising so
561 * that these are not too noticable.
562 */
563void linuxcommon_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat) {
564        struct linux_dev_stats dev_stats;
565        if (libtrace->format_data == NULL)
566                return;
567        /* Do we need to consider the case after the trace is closed? */
568        if (FORMAT_DATA_FIRST->fd == -1) {
569                /* This is probably a 'dead' trace so obviously we can't query
570                 * the socket for capture counts, can we? */
571                return;
572        }
573
574        dev_stats.if_name[0] = 0; /* This will be set if we retrive valid stats */
575        /* Do we have starting stats to compare to? */
576        if (FORMAT_DATA->dev_stats.if_name[0] != 0) {
577                linuxcommon_get_dev_statisitics(libtrace, &dev_stats);
578        }
579        linuxcommon_update_socket_statistics(libtrace);
580
581        /* filtered count == dev received - socket received */
582        if (FORMAT_DATA->filter != NULL &&
583            FORMAT_DATA->stats_valid &&
584            dev_stats.if_name[0]) {
585                uint64_t filtered = DEV_DIFF(rx_packets) -
586                                    FORMAT_DATA->stats.tp_packets;
587                /* Check the value is sane, due to timing it could be below 0 */
588                if (filtered < UINT64_MAX - 100000) {
589                        stat->filtered += filtered;
590                }
591        }
592
593        /* dropped count == socket dropped + dev dropped */
594        if (FORMAT_DATA->stats_valid) {
595                stat->dropped_valid = 1;
596                stat->dropped = FORMAT_DATA->stats.tp_drops;
597                if (dev_stats.if_name[0]) {
598                        stat->dropped += DEV_DIFF(rx_drops);
599                }
600        }
601
602        /* received count - All good packets even those dropped or filtered */
603        if (dev_stats.if_name[0]) {
604                stat->received_valid = 1;
605                stat->received = DEV_DIFF(rx_packets) + DEV_DIFF(rx_drops);
606        }
607
608        /* captured count - received and but not dropped */
609        if (dev_stats.if_name[0] && FORMAT_DATA->stats_valid) {
610                stat->captured_valid = 1;
611                stat->captured = DEV_DIFF(rx_packets) - FORMAT_DATA->stats.tp_drops;
612        }
613
614        /* errors */
615        if (dev_stats.if_name[0]) {
616                stat->errors_valid = 1;
617                stat->errors = DEV_DIFF(rx_errors);
618        }
619
620}
621
622int linuxcommon_get_fd(const libtrace_t *libtrace) {
623        if (libtrace->format_data == NULL)
624                return -1;
625        return FORMAT_DATA_FIRST->fd;
626}
627
628int linuxcommon_pstart_input(libtrace_t *libtrace,
629                             int (*start_stream)(libtrace_t *, struct linux_per_stream_t*)) {
630        int i = 0;
631        int tot = libtrace->perpkt_thread_count;
632        int iserror = 0;
633        struct linux_per_stream_t empty_stream = ZERO_LINUX_STREAM;
634
635        printf("Calling native pstart packet\n");
636        for (i = 0; i < tot; ++i)
637        {
638                struct linux_per_stream_t *stream;
639                /* Add storage for another stream */
640                if (libtrace_list_get_size(FORMAT_DATA->per_stream) <= (size_t) i)
641                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty_stream);
642
643                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
644                if (start_stream(libtrace, stream) != 0) {
645                        iserror = 1;
646                        break;
647                }
648                if (linuxcommon_to_packet_fanout(libtrace, stream) != 0)
649                {
650                        iserror = 1;
651                        close(stream->fd);
652                        stream->fd = -1;
653                        break;
654                }
655        }
656
657        if (iserror) {
658                /* Free those that succeeded */
659                for (i = i - 1; i >= 0; i--) {
660                        struct linux_per_stream_t *stream;
661                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
662                        linuxcommon_close_input_stream(libtrace, stream);
663                }
664                libtrace_list_deinit(FORMAT_DATA->per_stream);
665                free(libtrace->format_data);
666                libtrace->format_data = NULL;
667                return -1;
668        }
669
670        return 0;
671}
672
673#else /* HAVE_NETPACKET_PACKET_H */
674
675/* No NETPACKET - So this format is not live */
676void linuxcommon_get_statistics(libtrace_t *libtrace UNUSED,
677                                libtrace_stat_t *stat UNUSED) {
678        return;
679}
680
681#endif /* HAVE_NETPACKET_PACKET_H */
682
683
684inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype)
685{
686        switch (pkttype) {
687                case PACKET_OUTGOING:
688                case PACKET_LOOPBACK:
689                        return TRACE_DIR_OUTGOING;
690                case PACKET_OTHERHOST:
691                        return TRACE_DIR_OTHER;
692                default:
693                        return TRACE_DIR_INCOMING;
694        }
695}
696
697inline libtrace_direction_t
698linuxcommon_set_direction(struct sockaddr_ll * skadr,
699                          libtrace_direction_t direction)
700{
701        switch (direction) {
702                case TRACE_DIR_OUTGOING:
703                        skadr->sll_pkttype = PACKET_OUTGOING;
704                        return TRACE_DIR_OUTGOING;
705                case TRACE_DIR_INCOMING:
706                        skadr->sll_pkttype = PACKET_HOST;
707                        return TRACE_DIR_INCOMING;
708                case TRACE_DIR_OTHER:
709                        skadr->sll_pkttype = PACKET_OTHERHOST;
710                        return TRACE_DIR_OTHER;
711                default:
712                        return -1;
713        }
714}
715
716inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype)
717{
718        /* Convert the ARPHRD type into an appropriate libtrace link type */
719        switch (linktype) {
720                case LIBTRACE_ARPHRD_ETHER:
721                case LIBTRACE_ARPHRD_LOOPBACK:
722                        return TRACE_TYPE_ETH;
723                case LIBTRACE_ARPHRD_PPP:
724                        return TRACE_TYPE_NONE;
725                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
726                        return TRACE_TYPE_80211_RADIO;
727                case LIBTRACE_ARPHRD_IEEE80211:
728                        return TRACE_TYPE_80211;
729                case LIBTRACE_ARPHRD_SIT:
730                case LIBTRACE_ARPHRD_NONE:
731                        return TRACE_TYPE_NONE;
732                default: /* shrug, beyond me! */
733                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
734                        return (libtrace_linktype_t)~0U;
735        }
736}
Note: See TracBrowser for help on using the repository browser.