source: lib/format_linux_common.c @ 2725318

develop
Last change on this file since 2725318 was 2725318, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Cleanup some of the assertions

  • 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#include <assert.h>
43
44#ifdef HAVE_INTTYPES_H
45#  include <inttypes.h>
46#else
47# error "Can't find inttypes.h"
48#endif
49
50#include "format_linux_common.h"
51
52unsigned int rand_seedp = 0;
53
54#ifdef HAVE_NETPACKET_PACKET_H
55
56int linuxcommon_probe_filename(const char *filename)
57{
58        /* Is this an interface? */
59        return (if_nametoindex(filename) != 0);
60}
61
62/* Compiles a libtrace BPF filter for use with a linux native socket */
63static int linuxnative_configure_bpf(libtrace_t *libtrace,
64                libtrace_filter_t *filter) {
65#if defined(HAVE_LIBPCAP) && defined(HAVE_BPF)
66        struct ifreq ifr;
67        unsigned int arphrd;
68        libtrace_dlt_t dlt;
69        libtrace_filter_t *f;
70        int sock;
71        pcap_t *pcap;
72
73        /* Take a copy of the filter object as it was passed in */
74        f = (libtrace_filter_t *) malloc(sizeof(libtrace_filter_t));
75        memcpy(f, filter, sizeof(libtrace_filter_t));
76
77        /* If we are passed a filter with "flag" set to zero, then we must
78         * compile the filterstring before continuing. This involves
79         * determining the linktype, passing the filterstring to libpcap to
80         * compile, and saving the result for trace_start() to push into the
81         * kernel.
82         * If flag is set to one, then the filter was probably generated using
83         * trace_create_filter_from_bytecode() and so we don't need to do
84         * anything (we've just copied it above).
85         */
86        if (f->flag == 0) {
87                sock = socket(PF_INET, SOCK_STREAM, 0);
88                memset(&ifr, 0, sizeof(struct ifreq));
89                strncpy(ifr.ifr_name, libtrace->uridata, IF_NAMESIZE - 1);
90                if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
91                        perror("Can't get HWADDR for interface");
92                        return -1;
93                }
94                close(sock);
95
96                arphrd = ifr.ifr_hwaddr.sa_family;
97                dlt = libtrace_to_pcap_dlt(arphrd_type_to_libtrace(arphrd));
98
99                pcap = pcap_open_dead(dlt,
100                                FORMAT_DATA->snaplen);
101
102                if (pcap_compile(pcap, &f->filter, f->filterstring, 0, 0) == -1) {
103                        /* Filter didn't compile, set flag to 0 so we can
104                         * detect this when trace_start() is called and
105                         * produce a useful error
106                         */
107                        f->flag = 0;
108                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
109                                      "Failed to compile BPF filter (%s): %s",
110                                      f->filterstring, pcap_geterr(pcap));
111                } else {
112                        /* Set the "flag" to indicate that the filterstring
113                         * has been compiled
114                         */
115                        f->flag = 1;
116                }
117
118                pcap_close(pcap);
119
120        }
121
122        if (FORMAT_DATA->filter != NULL)
123                free(FORMAT_DATA->filter);
124
125        FORMAT_DATA->filter = f;
126
127        return 0;
128#else
129        return -1;
130#endif
131}
132
133int linuxcommon_config_input(libtrace_t *libtrace,
134                trace_option_t option,
135                void *data)
136{
137        switch(option) {
138                case TRACE_OPTION_SNAPLEN:
139                        FORMAT_DATA->snaplen=*(int*)data;
140                        return 0;
141                case TRACE_OPTION_PROMISC:
142                        FORMAT_DATA->promisc=*(int*)data;
143                        return 0;
144                case TRACE_OPTION_FILTER:
145                        return linuxnative_configure_bpf(libtrace,
146                                        (libtrace_filter_t *) data);
147                case TRACE_OPTION_HASHER:
148                        switch (*((enum hasher_types *)data)) {
149                                case HASHER_BALANCE:
150                                        // Do fanout
151                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
152                                        // Or we could balance to the CPU
153                                        return 0;
154                                case HASHER_BIDIRECTIONAL:
155                                case HASHER_UNIDIRECTIONAL:
156                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_HASH;
157                                        return 0;
158                                case HASHER_CUSTOM:
159                                        return -1;
160                        }
161                        break;
162                case TRACE_OPTION_META_FREQ:
163                        /* No meta-data for this format */
164                        break;
165                case TRACE_OPTION_EVENT_REALTIME:
166                        /* Live captures are always going to be in trace time */
167                        break;
168                case TRACE_OPTION_REPLAY_SPEEDUP:
169                        break;
170                /* Avoid default: so that future options will cause a warning
171                 * here to remind us to implement it, or flag it as
172                 * unimplementable
173                 */
174        }
175
176        /* Don't set an error - trace_config will try to deal with the
177         * option and will set an error if it fails */
178        return -1;
179}
180
181int linuxcommon_init_input(libtrace_t *libtrace)
182{
183        struct linux_per_stream_t stream_data = ZERO_LINUX_STREAM;
184
185        libtrace->format_data = (struct linux_format_data_t *)
186                malloc(sizeof(struct linux_format_data_t));
187
188        /*assert(libtrace->format_data != NULL);*/
189        if (!libtrace->format_data) {
190                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory linuxcommon_init_input()");
191                return -1;
192        }
193
194        FORMAT_DATA->per_stream =
195                libtrace_list_init(sizeof(stream_data));
196
197        /*assert(FORMAT_DATA->per_stream != NULL);*/
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        /*assert(libtrace->format_data != NULL);*/
225        if (!libtrace->format_data) {
226                trace_set_err_out(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory 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.