source: lib/format_linux_common.c @ 509ee47

develop
Last change on this file since 509ee47 was 509ee47, checked in by Shane Alcock <salcock@…>, 23 months ago

Add option to allow users to specify a constant ERF framing length.

This can be useful for situations where

a) the input uses ERF (or some derivative thereof)
b) the link type and ERF record type are constant for the

duration of the capture

c) performance is critical

This option allows users to simply tell libtrace what the ERF
framing length on every packet is going to be, so libtrace
doesn't have to repeatedly derive the framing length for each
packet it processes. At high packet rates, the time taken to
do this calculation can really add up and it makes no sense
to risk dropping packets because you're busy calculating a value
that is always a single constant value.

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