source: lib/format_linux_common.c @ 1407294

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

Remove HASHER_HARDWARE and doc/code tidies

We don't want to expose this option to the user as it was only used internally.
As it happens we can completely remove it if needed.

Remove error handling from start thread and fix gcc warning in start thread.

  • 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        stream->rxring_offset = 0;
229        FORMAT_DATA->dev_stats.if_name[0] = 0;
230}
231
232#define REPEAT_16(x) x x x x x x x x x x x x x x x x
233#define xstr(s) str(s)
234#define str(s) #s
235
236/* These don't typically reset however an interface does exist to reset them */
237static int linuxcommon_get_dev_statisitics(libtrace_t *libtrace, struct linux_dev_stats *stats) {
238        FILE *file;
239        char line[1024];
240        struct linux_dev_stats tmp_stats;
241
242        file = fopen("/proc/net/dev","r");
243        if (file == NULL) {
244                return -1;
245        }
246
247        /* Skip 2 header lines */
248        fgets(line, sizeof(line), file);
249        fgets(line, sizeof(line), file);
250
251        while (!(feof(file)||ferror(file))) {
252                int tot;
253                fgets(line, sizeof(line), file);
254                tot = sscanf(line, " %"xstr(IF_NAMESIZE)"[^:]:" REPEAT_16(" %"SCNd64),
255                             tmp_stats.if_name,
256                             &tmp_stats.rx_bytes,
257                             &tmp_stats.rx_packets,
258                             &tmp_stats.rx_errors,
259                             &tmp_stats.rx_drops,
260                             &tmp_stats.rx_fifo,
261                             &tmp_stats.rx_frame,
262                             &tmp_stats.rx_compressed,
263                             &tmp_stats.rx_multicast,
264                             &tmp_stats.tx_bytes,
265                             &tmp_stats.tx_packets,
266                             &tmp_stats.tx_errors,
267                             &tmp_stats.tx_drops,
268                             &tmp_stats.tx_fifo,
269                             &tmp_stats.tx_colls,
270                             &tmp_stats.tx_carrier,
271                             &tmp_stats.tx_compressed);
272                if (tot != 17)
273                        continue;
274                if (strncmp(tmp_stats.if_name, libtrace->uridata, IF_NAMESIZE) == 0) {
275                        *stats = tmp_stats;
276                        fclose(file);
277                        return 0;
278                }
279        }
280        fclose(file);
281        return -1;
282}
283
284/* Start an input stream
285 * - Opens the file descriptor
286 * - Sets promiscuous correctly
287 * - Sets socket option
288 * - Add BPF filter
289 *
290 * The output is ready for int directly, for ring the conversion to ring still
291 * needs to take place.
292 */
293int linuxcommon_start_input_stream(libtrace_t *libtrace,
294                                   struct linux_per_stream_t *stream)
295{
296        struct sockaddr_ll addr;
297        const int one = 1;
298        memset(&addr,0,sizeof(addr));
299        libtrace_filter_t *filter = FORMAT_DATA->filter;
300
301        /* Create a raw socket for reading packets on */
302        stream->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
303        if (stream->fd==-1) {
304                trace_set_err(libtrace, errno, "Could not create raw socket");
305                return -1;
306        }
307
308        /* Bind to the capture interface */
309        addr.sll_family = AF_PACKET;
310        addr.sll_protocol = htons(ETH_P_ALL);
311        if (strlen(libtrace->uridata)) {
312                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
313                if (addr.sll_ifindex == 0) {
314                        linuxcommon_close_input_stream(libtrace, stream);
315                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
316                                      "Failed to find interface %s",
317                                      libtrace->uridata);
318                        return -1;
319                }
320        } else {
321                addr.sll_ifindex = 0;
322        }
323        if (bind(stream->fd,
324                 (struct sockaddr*)&addr,
325                 (socklen_t)sizeof(addr))==-1) {
326                linuxcommon_close_input_stream(libtrace, stream);
327                trace_set_err(libtrace, errno,
328                              "Failed to bind to interface %s",
329                              libtrace->uridata);
330                return -1;
331        }
332
333        /* If promisc hasn't been specified, set it to "true" if we're
334         * capturing on one interface, or "false" if we're capturing on
335         * all interfaces.
336         */
337        if (FORMAT_DATA->promisc==-1) {
338                if (addr.sll_ifindex!=0)
339                        FORMAT_DATA->promisc=1;
340                else
341                        FORMAT_DATA->promisc=0;
342        }
343
344        /* Enable promiscuous mode, if requested */
345        if (FORMAT_DATA->promisc) {
346                struct packet_mreq mreq;
347                socklen_t socklen = sizeof(mreq);
348                memset(&mreq,0,sizeof(mreq));
349                mreq.mr_ifindex = addr.sll_ifindex;
350                mreq.mr_type = PACKET_MR_PROMISC;
351                if (setsockopt(stream->fd,
352                               SOL_PACKET,
353                               PACKET_ADD_MEMBERSHIP,
354                               &mreq,
355                               socklen)==-1) {
356                        perror("setsockopt(PROMISC)");
357                }
358        }
359
360        /* Set the timestamp option on the socket - aim for the most detailed
361         * clock resolution possible */
362#ifdef SO_TIMESTAMPNS
363        if (setsockopt(stream->fd,
364                       SOL_SOCKET,
365                       SO_TIMESTAMPNS,
366                       &one,
367                       (socklen_t)sizeof(one))!=-1) {
368                FORMAT_DATA->timestamptype = TS_TIMESPEC;
369        }
370        else
371        /* DANGER: This is a dangling else to only do the next setsockopt()
372         * if we fail the first! */
373#endif
374                if (setsockopt(stream->fd,
375                               SOL_SOCKET,
376                               SO_TIMESTAMP,
377                               &one,
378                               (socklen_t)sizeof(one))!=-1) {
379                        FORMAT_DATA->timestamptype = TS_TIMEVAL;
380                }
381                else
382                        FORMAT_DATA->timestamptype = TS_NONE;
383
384        /* Push BPF filter into the kernel. At this stage we can safely assume
385         * that the filterstring has been compiled, or the filter was supplied
386         * pre-compiled.
387         */
388        if (filter != NULL) {
389                /* Check if the filter was successfully compiled. If not,
390                 * it is probably a bad filter and we should return an error
391                 * before the caller tries to read any packets */
392                if (filter->flag == 0) {
393                        linuxcommon_close_input_stream(libtrace, stream);
394                        trace_set_err(libtrace, TRACE_ERR_BAD_FILTER,
395                                      "Cannot attach a bad filter to %s",
396                                      libtrace->uridata);
397                        return -1;
398                }
399
400                if (setsockopt(stream->fd,
401                               SOL_SOCKET,
402                               SO_ATTACH_FILTER,
403                               &filter->filter,
404                               sizeof(filter->filter)) == -1) {
405                        perror("setsockopt(SO_ATTACH_FILTER)");
406                }
407        }
408
409        /* Consume any buffered packets that were received before the socket
410         * was properly setup, including those which missed the filter and
411         * bind()ing to an interface.
412         *
413         * If packet rate is high this could therotically hang forever. 4K
414         * should be a large enough limit.
415         */
416        int count = 0;
417        void *buf = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
418        while(count < 4096 &&
419                recv(stream->fd,
420                   buf,
421                   (size_t)LIBTRACE_PACKET_BUFSIZE,
422                   MSG_DONTWAIT) != -1) { count++; }
423        free(buf);
424
425        /* Mark that the stats are valid and apply an offset */
426        FORMAT_DATA->stats_valid = 1;
427        /* Offset by number we ate for each stream and reset stats after pause */
428        FORMAT_DATA->stats.tp_packets = -count;
429        FORMAT_DATA->stats.tp_drops = 0;
430
431        if (linuxcommon_get_dev_statisitics(libtrace, &FORMAT_DATA->dev_stats) != 0) {
432                /* Mark this as bad */
433                FORMAT_DATA->dev_stats.if_name[0] = 0;
434        }
435
436        return 0;
437}
438
439/**
440 * Converts a socket, either packet_mmap or standard raw socket into a
441 * fanout socket.
442 * NOTE: This means we can read from the socket with multiple queues,
443 * each must be setup (identically) and then this called upon them
444 *
445 * @return 0 success, -1 error
446 */
447inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace,
448                                        struct linux_per_stream_t *stream)
449{
450        int fanout_opt = ((int)FORMAT_DATA->fanout_flags << 16) |
451                         (int)FORMAT_DATA->fanout_group;
452        if (setsockopt(stream->fd, SOL_PACKET, PACKET_FANOUT,
453                        &fanout_opt, sizeof(fanout_opt)) == -1) {
454                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
455                              "Converting the fd to a socket fanout failed %s",
456                              libtrace->uridata);
457                return -1;
458        }
459        return 0;
460}
461
462int linuxcommon_pause_input(libtrace_t *libtrace)
463{
464        size_t i;
465
466        /* Stop and detach each stream */
467        for (i = 0; i < libtrace_list_get_size(FORMAT_DATA->per_stream); ++i) {
468                struct linux_per_stream_t *stream;
469                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
470                linuxcommon_close_input_stream(libtrace, stream);
471        }
472
473        return 0;
474}
475
476int linuxcommon_fin_input(libtrace_t *libtrace)
477{
478        if (libtrace->format_data) {
479                if (FORMAT_DATA->filter != NULL)
480                        free(FORMAT_DATA->filter);
481
482                if (FORMAT_DATA->per_stream)
483                        libtrace_list_deinit(FORMAT_DATA->per_stream);
484
485                free(libtrace->format_data);
486        }
487
488        return 0;
489}
490
491int linuxcommon_pregister_thread(libtrace_t *libtrace,
492                                 libtrace_thread_t *t,
493                                 bool reading) {
494        if (reading) {
495                /* XXX TODO remove this oneday make sure hasher thread still works */
496                struct linux_per_stream_t *stream;
497                stream = libtrace_list_get_index(FORMAT_DATA->per_stream,
498                                                 t->perpkt_num)->data;
499                t->format_data = stream;
500                if (!stream) {
501                        /* This should never happen and indicates an
502                         * internal libtrace bug */
503                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
504                                      "Failed to attached thread %d to a stream",
505                                      t->perpkt_num);
506                        return -1;
507                }
508        }
509        return 0;
510}
511
512int linuxcommon_pconfig_input(libtrace_t *libtrace,
513                              trace_parallel_option_t option,
514                              void *data)
515{
516        switch(option) {
517                case TRACE_OPTION_SET_HASHER:
518                        switch (*((enum hasher_types *)data)) {
519                                case HASHER_BALANCE:
520                                        // Do fanout
521                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_LB;
522                                        // Or we could balance to the CPU
523                                        return 0;
524                                case HASHER_BIDIRECTIONAL:
525                                case HASHER_UNIDIRECTIONAL:
526                                        FORMAT_DATA->fanout_flags = PACKET_FANOUT_HASH;
527                                        return 0;
528                                case HASHER_CUSTOM:
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            FORMAT_DATA->stats_valid &&
600            dev_stats.if_name[0]) {
601                uint64_t filtered = DEV_DIFF(rx_packets) -
602                                    FORMAT_DATA->stats.tp_packets;
603                /* Check the value is sane, due to timing it could be below 0 */
604                if (filtered < UINT64_MAX - 100000) {
605                        stat->filtered += filtered;
606                }
607        }
608
609        /* dropped count == socket dropped + dev dropped */
610        if (FORMAT_DATA->stats_valid) {
611                stat->dropped_valid = 1;
612                stat->dropped = FORMAT_DATA->stats.tp_drops;
613                if (dev_stats.if_name[0]) {
614                        stat->dropped += DEV_DIFF(rx_drops);
615                }
616        }
617
618        /* received count - All good packets even those dropped or filtered */
619        if (dev_stats.if_name[0]) {
620                stat->received_valid = 1;
621                stat->received = DEV_DIFF(rx_packets) + DEV_DIFF(rx_drops);
622        }
623
624        /* captured count - received and but not dropped */
625        if (dev_stats.if_name[0] && FORMAT_DATA->stats_valid) {
626                stat->captured_valid = 1;
627                stat->captured = DEV_DIFF(rx_packets) - FORMAT_DATA->stats.tp_drops;
628        }
629
630        /* errors */
631        if (dev_stats.if_name[0]) {
632                stat->errors_valid = 1;
633                stat->errors = DEV_DIFF(rx_errors);
634        }
635
636}
637
638int linuxcommon_get_fd(const libtrace_t *libtrace) {
639        if (libtrace->format_data == NULL)
640                return -1;
641        return FORMAT_DATA_FIRST->fd;
642}
643
644int linuxcommon_pstart_input(libtrace_t *libtrace,
645                             int (*start_stream)(libtrace_t *, struct linux_per_stream_t*)) {
646        int i = 0;
647        int tot = libtrace->perpkt_thread_count;
648        int iserror = 0;
649        struct linux_per_stream_t empty_stream = ZERO_LINUX_STREAM;
650
651        printf("Calling native pstart packet\n");
652        for (i = 0; i < tot; ++i)
653        {
654                struct linux_per_stream_t *stream;
655                /* Add storage for another stream */
656                if (libtrace_list_get_size(FORMAT_DATA->per_stream) <= (size_t) i)
657                        libtrace_list_push_back(FORMAT_DATA->per_stream, &empty_stream);
658
659                stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
660                if (start_stream(libtrace, stream) != 0) {
661                        iserror = 1;
662                        break;
663                }
664                if (linuxcommon_to_packet_fanout(libtrace, stream) != 0)
665                {
666                        iserror = 1;
667                        close(stream->fd);
668                        stream->fd = -1;
669                        break;
670                }
671        }
672
673        if (iserror) {
674                /* Free those that succeeded */
675                for (i = i - 1; i >= 0; i--) {
676                        struct linux_per_stream_t *stream;
677                        stream = libtrace_list_get_index(FORMAT_DATA->per_stream, i)->data;
678                        linuxcommon_close_input_stream(libtrace, stream);
679                }
680                libtrace_list_deinit(FORMAT_DATA->per_stream);
681                free(libtrace->format_data);
682                libtrace->format_data = NULL;
683                return -1;
684        }
685
686        return 0;
687}
688
689#else /* HAVE_NETPACKET_PACKET_H */
690
691/* No NETPACKET - So this format is not live */
692void linuxcommon_get_statistics(libtrace_t *libtrace UNUSED,
693                                libtrace_stat_t *stat UNUSED) {
694        return;
695}
696
697#endif /* HAVE_NETPACKET_PACKET_H */
698
699
700inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype)
701{
702        switch (pkttype) {
703                case PACKET_OUTGOING:
704                case PACKET_LOOPBACK:
705                        return TRACE_DIR_OUTGOING;
706                case PACKET_OTHERHOST:
707                        return TRACE_DIR_OTHER;
708                default:
709                        return TRACE_DIR_INCOMING;
710        }
711}
712
713inline libtrace_direction_t
714linuxcommon_set_direction(struct sockaddr_ll * skadr,
715                          libtrace_direction_t direction)
716{
717        switch (direction) {
718                case TRACE_DIR_OUTGOING:
719                        skadr->sll_pkttype = PACKET_OUTGOING;
720                        return TRACE_DIR_OUTGOING;
721                case TRACE_DIR_INCOMING:
722                        skadr->sll_pkttype = PACKET_HOST;
723                        return TRACE_DIR_INCOMING;
724                case TRACE_DIR_OTHER:
725                        skadr->sll_pkttype = PACKET_OTHERHOST;
726                        return TRACE_DIR_OTHER;
727                default:
728                        return -1;
729        }
730}
731
732inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype)
733{
734        /* Convert the ARPHRD type into an appropriate libtrace link type */
735        switch (linktype) {
736                case LIBTRACE_ARPHRD_ETHER:
737                case LIBTRACE_ARPHRD_LOOPBACK:
738                        return TRACE_TYPE_ETH;
739                case LIBTRACE_ARPHRD_PPP:
740                        return TRACE_TYPE_NONE;
741                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP:
742                        return TRACE_TYPE_80211_RADIO;
743                case LIBTRACE_ARPHRD_IEEE80211:
744                        return TRACE_TYPE_80211;
745                case LIBTRACE_ARPHRD_SIT:
746                case LIBTRACE_ARPHRD_NONE:
747                        return TRACE_TYPE_NONE;
748                default: /* shrug, beyond me! */
749                        printf("unknown Linux ARPHRD type 0x%04x\n",linktype);
750                        return (libtrace_linktype_t)~0U;
751        }
752}
Note: See TracBrowser for help on using the repository browser.