source: lib/format_linux_common.c @ 8df87c4

develop
Last change on this file since 8df87c4 was 8df87c4, checked in by Jacob Van Walraven <jcv9@…>, 22 months ago

Instead we should still copy the filter but make sure its freed when copying another, this protects against the user freeing a filter that is in use. Issue #87

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