source: lib/format_linux_common.c @ 5cdb37d

develop
Last change on this file since 5cdb37d was 5cdb37d, checked in by GitHub <noreply@…>, 3 years ago

Merge pull request #101 from jacobvw/meta-api

Meta API

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