source: lib/format_linux_common.c @ e4f27d1

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

Move the ring sizes to the stream structures, it's possible rings could end up different sizes.
Other than that their are many operation related to reading packets which rely upon it and
it seems more natural to include this against the stream.

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