source: lib/format_pcapng.c @ 2c457ec

cachetimestampsdevelopdpdk-ndagetsiliverc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 2c457ec was 2c457ec, checked in by Robert A Zeh <razeh@…>, 3 years ago

Add TRACE_ERR_WANDIO_FAILED for wandio error reporting.

Passing an errcode of 0 to trace_set_err triggers the assertion at
format_helper.c:290, making the error unrecoverable for the calling
code. This happens when the wandio layer encounters an error while
errno is still 0 (for example, an incomplete pcap packet).

To make the error recoverable, pass in TRACE_ERR_WANDIO_FAILED instead
of errno.

  • Property mode set to 100644
File size: 49.3 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#include "common.h"
27#include "config.h"
28#include "libtrace.h"
29#include "libtrace_int.h"
30#include "format_helper.h"
31
32#include <sys/stat.h>
33#include <assert.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <stdbool.h>
40#include <math.h>
41
42#define PCAPNG_SECTION_TYPE 0x0A0D0D0A
43#define PCAPNG_INTERFACE_TYPE 0x00000001
44#define PCAPNG_OLD_PACKET_TYPE 0x00000002
45#define PCAPNG_SIMPLE_PACKET_TYPE 0x00000003
46#define PCAPNG_NAME_RESOLUTION_TYPE 0x00000004
47#define PCAPNG_INTERFACE_STATS_TYPE 0x00000005
48#define PCAPNG_ENHANCED_PACKET_TYPE 0x00000006
49#define PCAPNG_CUSTOM_TYPE 0x00000BAD
50#define PCAPNG_CUSTOM_NONCOPY_TYPE 0x40000BAD
51
52#define PACKET_IS_ENHANCED (pcapng_get_record_type(packet) == PCAPNG_ENHANCED_PACKET_TYPE)
53
54#define PACKET_IS_SIMPLE (pcapng_get_record_type(packet) == PCAPNG_SIMPLE_PACKET_TYPE)
55
56#define PACKET_IS_OLD (pcapng_get_record_type(packet) == PCAPNG_OLD_PACKET_TYPE)
57
58
59#define PCAPNG_IFOPT_TSRESOL 9
60
61#define PCAPNG_PKTOPT_DROPCOUNT 4
62
63#define PCAPNG_STATOPT_START 2
64#define PCAPNG_STATOPT_END 3
65#define PCAPNG_STATOPT_IFRECV 4
66#define PCAPNG_STATOPT_IFDROP 5
67#define PCAPNG_STATOPT_FILTERACCEPT 6
68#define PCAPNG_STATOPT_OSDROP 7
69#define PCAPNG_STATOPT_USRDELIV 8
70
71typedef struct pcagng_section_header_t {
72        uint32_t blocktype;
73        uint32_t blocklen;
74        uint32_t ordering;
75        uint16_t majorversion;
76        uint16_t minorversion;
77        uint64_t sectionlen;
78} pcapng_sec_t;
79
80typedef struct pcapng_interface_header_t {
81        uint32_t blocktype;
82        uint32_t blocklen;
83        uint16_t linktype;
84        uint16_t reserved;
85        uint32_t snaplen;
86} pcapng_int_t;
87
88typedef struct pcapng_nrb_header_t {
89        uint32_t blocktype;
90        uint32_t blocklen;
91} pcapng_nrb_t;
92
93typedef struct pcapng_enhanced_packet_t {
94        uint32_t blocktype;
95        uint32_t blocklen;
96        uint32_t interfaceid;
97        uint32_t timestamp_high;
98        uint32_t timestamp_low;
99        uint32_t caplen;
100        uint32_t wlen;
101} pcapng_epkt_t;
102
103typedef struct pcapng_simple_packet_t {
104        uint32_t blocktype;
105        uint32_t blocklen;
106        uint32_t wlen;
107} pcapng_spkt_t;
108
109typedef struct pcapng_old_packet_t {
110        uint32_t blocktype;
111        uint32_t blocklen;
112        uint16_t interfaceid;
113        uint16_t drops;
114        uint32_t timestamp_high;
115        uint32_t timestamp_low;
116        uint32_t caplen;
117        uint32_t wlen;
118} pcapng_opkt_t;
119
120typedef struct pcapng_stats_header_t {
121        uint32_t blocktype;
122        uint32_t blocklen;
123        uint32_t interfaceid;
124        uint32_t timestamp_high;
125        uint32_t timestamp_low;
126} pcapng_stats_t;
127
128typedef struct pcapng_custom_header_t {
129        uint32_t blocktype;
130        uint32_t blocklen;
131        uint32_t pen;
132} pcapng_custom_t;
133
134typedef struct pcapng_interface_t pcapng_interface_t;
135
136struct pcapng_interface_t {
137
138        uint16_t id;
139        libtrace_dlt_t linktype;
140        uint32_t snaplen;
141        uint32_t tsresol;
142
143        uint64_t received;
144        uint64_t dropped;       /* as reported by interface stats */
145        uint64_t dropcounter;   /* as reported by packet records */
146        uint64_t accepted;
147        uint64_t osdropped;
148        uint64_t laststats;
149
150};
151
152struct pcapng_format_data_t {
153        bool started;
154        bool realtime;
155
156        /* Section data */
157        bool byteswapped;
158
159        /* Interface data */
160        pcapng_interface_t **interfaces;
161        uint16_t allocatedinterfaces;
162        uint16_t nextintid;
163};
164
165struct pcapng_optheader {
166        uint16_t optcode;
167        uint16_t optlen;
168};
169
170struct pcapng_peeker {
171        uint32_t blocktype;
172        uint32_t blocklen;
173};
174
175
176#define DATA(x) ((struct pcapng_format_data_t *)((x)->format_data))
177
178static pcapng_interface_t *lookup_interface(libtrace_t *libtrace,
179                uint32_t intid) {
180
181
182        if (intid >= DATA(libtrace)->nextintid) {
183                return NULL;
184        }
185
186        return DATA(libtrace)->interfaces[intid];
187
188}
189
190static inline uint32_t pcapng_get_record_type(const libtrace_packet_t *packet) {
191
192        uint32_t *btype = (uint32_t *)packet->header;
193
194        if (DATA(packet->trace)->byteswapped)
195                return byteswap32(*btype);
196        return *btype;
197}
198
199static int pcapng_probe_magic(io_t *io) {
200
201        pcapng_sec_t sechdr;
202        int len;
203
204        len = wandio_peek(io, &sechdr, sizeof(sechdr));
205        if (len < (int)sizeof(sechdr)) {
206                return 0;
207        }
208
209        if (sechdr.blocktype == PCAPNG_SECTION_TYPE) {
210                return 1;
211        }
212        return 0;
213}
214
215
216static int pcapng_init_input(libtrace_t *libtrace) {
217        libtrace->format_data = malloc(sizeof(struct pcapng_format_data_t));
218        if (libtrace->format_data == NULL) {
219                trace_set_err(libtrace, ENOMEM, "Out of memory!");
220                return -1;
221        }
222
223        DATA(libtrace)->started = false;
224        DATA(libtrace)->realtime = false;
225        DATA(libtrace)->byteswapped = true;
226        DATA(libtrace)->interfaces = (pcapng_interface_t **)calloc(10, \
227                        sizeof(pcapng_interface_t));
228        DATA(libtrace)->allocatedinterfaces = 10;
229        DATA(libtrace)->nextintid = 0;
230
231        return 0;
232}
233
234static int pcapng_start_input(libtrace_t *libtrace) {
235
236        if (!libtrace->io) {
237                libtrace->io = trace_open_file(libtrace);
238        }
239
240        if (!libtrace->io)
241                return -1;
242
243        return 0;
244}
245
246static int pcapng_config_input(libtrace_t *libtrace, trace_option_t option,
247                void *data) {
248
249        switch(option) {
250                case TRACE_OPTION_EVENT_REALTIME:
251                        if (*(int *)data != 0) {
252                                DATA(libtrace)->realtime = true;
253                        } else {
254                                DATA(libtrace)->realtime = false;
255                        }
256                        return 0;
257                case TRACE_OPTION_META_FREQ:
258                case TRACE_OPTION_SNAPLEN:
259                case TRACE_OPTION_PROMISC:
260                case TRACE_OPTION_FILTER:
261                case TRACE_OPTION_HASHER:
262                        break;
263        }
264
265        trace_set_err(libtrace, TRACE_ERR_UNKNOWN_OPTION, "Unknown option %i",
266                        option);
267        return -1;
268}
269
270static int pcapng_fin_input(libtrace_t *libtrace) {
271
272        int i = 0;
273
274        for (i = 0; i < DATA(libtrace)->allocatedinterfaces; i++) {
275                free(DATA(libtrace)->interfaces[i]);
276        }
277
278        free(DATA(libtrace)->interfaces);
279
280        if (libtrace->io) {
281                wandio_destroy(libtrace->io);
282        }
283        free(libtrace->format_data);
284        return 0;
285}
286
287static char *pcapng_parse_next_option(libtrace_t *libtrace, char **pktbuf,
288                uint16_t *code, uint16_t *length) {
289
290        struct pcapng_optheader *opthdr = (struct pcapng_optheader *)*pktbuf;
291        int to_skip;
292        int padding = 0;
293        char *optval;
294
295        if (DATA(libtrace)->byteswapped) {
296                *code = byteswap16(opthdr->optcode);
297                *length = byteswap16(opthdr->optlen);
298        } else {
299                *code = opthdr->optcode;
300                *length = opthdr->optlen;
301        }
302
303        optval = *pktbuf + sizeof(struct pcapng_optheader);
304
305        if ((*length % 4) > 0) {
306                padding = (4 - (*length % 4));
307        } else {
308                padding = 0;
309        }
310
311        to_skip = (*length) + padding;
312        *pktbuf = optval + to_skip;
313
314        return optval;
315}
316
317static inline int skip_block(libtrace_t *libtrace, uint32_t toread) {
318        int err;
319
320        while (toread > 0) {
321                char buf[4096];
322                int nextread;
323
324                if (toread < 4096) {
325                        nextread = toread;
326                } else {
327                        nextread = 4096;
328                }
329
330                err = wandio_read(libtrace->io, buf, nextread);
331                if (err < 0) {
332                        trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED,
333                                "Reading section header options");
334                        return -1;
335                }
336                if (err == 0) {
337                        return 0;
338                }
339                toread -= err;
340        }
341
342        return 1;
343
344}
345
346static inline int pcapng_read_body(libtrace_t *libtrace, char *body,
347                uint32_t to_read) {
348
349        int err;
350
351        err = wandio_read(libtrace->io, body, to_read);
352        if (err < 0) {
353                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED,
354                        "Failed to read pcapng interface options");
355                return err;
356        }
357
358        if (err == 0) {
359                return err;
360        }
361
362        if (err < (int)to_read) {
363                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
364                        "Incomplete pcapng interface header block");
365                return -1;
366        }
367
368        return to_read;
369}
370
371static int pcapng_get_framing_length(const libtrace_packet_t *packet) {
372
373        switch(pcapng_get_record_type(packet)) {
374                case PCAPNG_SECTION_TYPE:
375                        return sizeof(pcapng_sec_t);
376                case PCAPNG_INTERFACE_TYPE:
377                        return sizeof(pcapng_int_t);
378                case PCAPNG_ENHANCED_PACKET_TYPE:
379                        return sizeof(pcapng_epkt_t);
380                case PCAPNG_SIMPLE_PACKET_TYPE:
381                        return sizeof(pcapng_spkt_t);
382                case PCAPNG_OLD_PACKET_TYPE:
383                        return sizeof(pcapng_opkt_t);
384                case PCAPNG_INTERFACE_STATS_TYPE:
385                        return sizeof(pcapng_stats_t);
386                case PCAPNG_NAME_RESOLUTION_TYPE:
387                        return sizeof(pcapng_nrb_t);
388                case PCAPNG_CUSTOM_TYPE:
389                case PCAPNG_CUSTOM_NONCOPY_TYPE:
390                        return sizeof(pcapng_custom_t);
391        }
392
393        /* If we get here, we aren't a valid pcapng packet */
394        trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET,
395                        "Invalid RT type for pcapng packet: %u",
396                        packet->type);
397        return -1;
398
399}
400
401static int pcapng_prepare_packet(libtrace_t *libtrace,
402                libtrace_packet_t *packet, void *buffer,
403                libtrace_rt_types_t rt_type, uint32_t flags) {
404
405        int hdrlen;
406
407        if (packet->buffer != buffer &&
408                        packet->buf_control == TRACE_CTRL_PACKET) {
409                free(packet->buffer);
410        }
411
412        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
413                packet->buf_control = TRACE_CTRL_PACKET;
414        } else {
415                packet->buf_control = TRACE_CTRL_EXTERNAL;
416        }
417
418        packet->type = rt_type;
419        packet->buffer = buffer;
420        packet->header = buffer;
421
422        hdrlen = pcapng_get_framing_length(packet);
423        if (hdrlen < 0) {
424                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
425                                "X Invalid RT type for pcapng packet: %u",
426                                packet->type);
427                return -1;
428        }
429        packet->payload = ((char *)packet->buffer) + hdrlen;
430
431        return 0;
432}
433
434static int pcapng_read_section(libtrace_t *libtrace,
435                libtrace_packet_t *packet, uint32_t flags) {
436
437        pcapng_sec_t *sechdr;
438        int err;
439        uint32_t to_read;
440        char *bodyptr = NULL;
441
442        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_sec_t));
443        sechdr = (pcapng_sec_t *)packet->buffer;
444
445        if (err < 0) {
446                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED,
447                        "Reading pcapng section header block");
448                return -1;
449        }
450
451        if (err == 0) {
452                return 0;
453        }
454
455        if (err < (int)(sizeof(sechdr))) {
456                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
457                        "Incomplete pcapng section header block");
458                return -1;
459        }
460
461        assert(sechdr->blocktype == PCAPNG_SECTION_TYPE);
462
463        if (sechdr->ordering == 0x1A2B3C4D) {
464                DATA(libtrace)->byteswapped = false;
465        } else if (sechdr->ordering == 0x4D3C2B1A) {
466                DATA(libtrace)->byteswapped = true;
467        } else {
468                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
469                                "Parsing pcapng section header block");
470                return -1;
471        }
472
473
474        if (DATA(libtrace)->byteswapped) {
475                if (byteswap16(sechdr->majorversion) != 1 && byteswap16(sechdr->minorversion) != 0) {
476                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
477                                "Parsing pcapng version numbers");
478                        return -1;
479                }
480                to_read = byteswap32(sechdr->blocklen) - sizeof(pcapng_sec_t);
481        } else {
482                if (sechdr->majorversion != 1 && sechdr->minorversion != 0) {
483                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
484                                "Parsing pcapng version numbers");
485                        return -1;
486                }
487                to_read = sechdr->blocklen - sizeof(pcapng_sec_t);
488        }
489
490        /* Read all of the options etc. -- we don't need them for now, but
491         * we have to skip forward to the next useful header. */
492        bodyptr = packet->buffer + sizeof(pcapng_sec_t);
493        err = pcapng_read_body(libtrace, bodyptr, to_read);
494        if (err <= 0) {
495                return err;
496        }
497
498        packet->type = TRACE_RT_PCAPNG_META;
499        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
500                        packet->type, flags)) {
501                return -1;
502        }
503
504        return 1;
505}
506
507static int pcapng_read_interface(libtrace_t *libtrace,
508                libtrace_packet_t *packet, uint32_t flags) {
509
510        pcapng_int_t *inthdr;
511        int err;
512        uint32_t to_read;
513        pcapng_interface_t *newint;
514        uint16_t optcode, optlen;
515        char *optval = NULL;
516        char *bodyptr = NULL;
517
518        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_int_t));
519
520        if (err < 0) {
521                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED,
522                        "Reading pcapng interface header block");
523                return -1;
524        }
525
526        if (err == 0) {
527                return 0;
528        }
529
530        if (err < (int)sizeof(inthdr)) {
531                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
532                        "Incomplete pcapng interface header block");
533                return -1;
534        }
535        inthdr = (pcapng_int_t *)packet->buffer;
536
537        newint = (pcapng_interface_t *)malloc(sizeof(pcapng_interface_t));
538
539        newint->id = DATA(libtrace)->nextintid;
540
541        newint->received = 0;
542        newint->dropped = 0;
543        newint->dropcounter = 0;
544        newint->accepted = 0;
545        newint->osdropped = 0;
546        newint->laststats = 0;
547        newint->tsresol = 1000000;
548
549        if (DATA(libtrace)->byteswapped) {
550                assert(byteswap32(inthdr->blocktype) == PCAPNG_INTERFACE_TYPE);
551                newint->snaplen = byteswap32(inthdr->snaplen);
552                newint->linktype = byteswap16(inthdr->linktype);
553                to_read = byteswap32(inthdr->blocklen) - sizeof(pcapng_int_t);
554        } else {
555                assert(inthdr->blocktype == PCAPNG_INTERFACE_TYPE);
556                newint->snaplen = inthdr->snaplen;
557                newint->linktype = inthdr->linktype;
558                to_read = inthdr->blocklen - sizeof(pcapng_int_t);
559        }
560
561        if (DATA(libtrace)->nextintid == DATA(libtrace)->allocatedinterfaces) {
562                DATA(libtrace)->allocatedinterfaces += 10;
563                DATA(libtrace)->interfaces = (pcapng_interface_t **)realloc(
564                        DATA(libtrace)->interfaces,
565                        DATA(libtrace)->allocatedinterfaces * sizeof(
566                                pcapng_interface_t *));
567
568                /* Could memset the new memory to zero, if required */
569        }
570
571        DATA(libtrace)->interfaces[newint->id] = newint;
572        DATA(libtrace)->nextintid += 1;
573
574        bodyptr = packet->buffer + sizeof(pcapng_int_t);
575        err = pcapng_read_body(libtrace, bodyptr, to_read);
576        if (err <= 0) {
577                return err;
578        }
579
580        packet->type = TRACE_RT_PCAPNG_META;
581
582        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
583                        packet->type, flags)) {
584                return -1;
585        }
586
587        do {
588                optval = pcapng_parse_next_option(libtrace, &bodyptr,
589                                &optcode, &optlen);
590                if (optval == NULL) {
591                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
592                                "Failed to read options for pcapng interface");
593                        return -1;
594                }
595
596                if (optcode == PCAPNG_IFOPT_TSRESOL) {
597                        uint8_t *resol = (uint8_t *)optval;
598
599                        if ((*resol & 0x80) != 0) {
600                                newint->tsresol = pow(2, *resol & 0x7f);
601
602                        } else {
603                                newint->tsresol = pow(10, *resol & 0x7f);
604                        }
605                }
606
607        } while (optcode != 0);
608
609        return 1;
610
611}
612
613static int pcapng_read_nrb(libtrace_t *libtrace, libtrace_packet_t *packet,
614                uint32_t flags) {
615
616        /* Just read the NR records and pass them off to the caller. If
617         * they want to do anything with them, they can parse the records
618         * themselves.
619         */
620        pcapng_nrb_t *hdr = NULL;
621        int err;
622        uint32_t to_read;
623        char *bodyptr;
624
625        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_nrb_t));
626
627        if (err < 0) {
628                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "reading pcapng name resolution block");
629                return -1;
630        }
631
632        if (err == 0) {
633                return 0;
634        }
635
636        if (err < (int)sizeof(pcapng_nrb_t)) {
637                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
638                                "Incomplete pcapng name resolution block");
639                return -1;
640        }
641
642        hdr = (pcapng_nrb_t *)packet->buffer;
643
644        /* Read the rest of the packet into the buffer */
645        if (DATA(libtrace)->byteswapped) {
646                assert(byteswap32(hdr->blocktype) == PCAPNG_NAME_RESOLUTION_TYPE);
647                to_read = byteswap32(hdr->blocklen) - sizeof(pcapng_nrb_t);
648        } else {
649                assert(hdr->blocktype == PCAPNG_NAME_RESOLUTION_TYPE);
650                to_read = hdr->blocklen - sizeof(pcapng_nrb_t);
651        }
652
653        bodyptr = packet->buffer + sizeof(pcapng_nrb_t);
654        err = pcapng_read_body(libtrace, bodyptr, to_read);
655        if (err <= 0) {
656                return err;
657        }
658
659        packet->type = TRACE_RT_PCAPNG_META;
660        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
661                        packet->type, flags)) {
662                return -1;
663        }
664
665        return sizeof(pcapng_nrb_t) + to_read;
666
667}
668
669static int pcapng_read_custom(libtrace_t *libtrace, libtrace_packet_t *packet,
670                uint32_t flags) {
671
672        /* Just read the custom records and pass them off to the caller. If
673         * they want to do anything with them, they can parse the records
674         * themselves.
675         */
676        pcapng_custom_t *hdr = NULL;
677        int err;
678        uint32_t to_read;
679        char *bodyptr;
680
681        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_custom_t));
682
683        if (err < 0) {
684                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "reading pcapng custom block");
685                return -1;
686        }
687
688        if (err == 0) {
689                return 0;
690        }
691
692        if (err < (int)sizeof(pcapng_custom_t)) {
693                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
694                                "Incomplete pcapng custom block");
695                return -1;
696        }
697
698        hdr = (pcapng_custom_t *)packet->buffer;
699
700        /* Read the rest of the packet into the buffer */
701        if (DATA(libtrace)->byteswapped) {
702                assert(byteswap32(hdr->blocktype) == PCAPNG_CUSTOM_TYPE ||
703                        byteswap32(hdr->blocktype) == PCAPNG_CUSTOM_NONCOPY_TYPE);
704                to_read = byteswap32(hdr->blocklen) - sizeof(pcapng_custom_t);
705        } else {
706                assert(hdr->blocktype == PCAPNG_NAME_RESOLUTION_TYPE ||
707                        hdr->blocktype == PCAPNG_CUSTOM_NONCOPY_TYPE);
708                to_read = hdr->blocklen - sizeof(pcapng_custom_t);
709        }
710
711        bodyptr = packet->buffer + sizeof(pcapng_custom_t);
712        err = pcapng_read_body(libtrace, bodyptr, to_read);
713        if (err <= 0) {
714                return err;
715        }
716
717        packet->type = TRACE_RT_PCAPNG_META;
718        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
719                        packet->type, flags)) {
720                return -1;
721        }
722
723        return sizeof(pcapng_custom_t) + to_read;
724
725}
726
727static int pcapng_read_stats(libtrace_t *libtrace, libtrace_packet_t *packet,
728                uint32_t flags) {
729        pcapng_stats_t *hdr = NULL;
730        int err;
731        uint32_t to_read;
732        uint32_t ifaceid;
733        uint64_t timestamp;
734        pcapng_interface_t *interface;
735        uint16_t optcode, optlen;
736        char *optval;
737        char *bodyptr;
738
739        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_stats_t));
740
741        if (err < 0) {
742                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "reading pcapng interface stats");
743                return -1;
744        }
745
746        if (err == 0) {
747                return 0;
748        }
749
750        if (err < (int)sizeof(pcapng_stats_t)) {
751                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
752                                "Incomplete pcapng interface stats header");
753                return -1;
754        }
755
756        hdr = (pcapng_stats_t *)packet->buffer;
757
758        /* Read the rest of the packet into the buffer */
759        if (DATA(libtrace)->byteswapped) {
760                assert(byteswap32(hdr->blocktype) == PCAPNG_INTERFACE_STATS_TYPE);
761                to_read = byteswap32(hdr->blocklen) - sizeof(pcapng_stats_t);
762                ifaceid = byteswap32(hdr->interfaceid);
763                timestamp = ((uint64_t)(byteswap32(hdr->timestamp_high)) << 32) + byteswap32(hdr->timestamp_low);
764        } else {
765                assert(hdr->blocktype == PCAPNG_INTERFACE_STATS_TYPE);
766                to_read = hdr->blocklen - sizeof(pcapng_stats_t);
767                ifaceid = hdr->interfaceid;
768                timestamp = ((uint64_t)(hdr->timestamp_high) << 32) +
769                                hdr->timestamp_low;
770        }
771
772        bodyptr = packet->buffer + sizeof(pcapng_stats_t);
773        err = pcapng_read_body(libtrace, bodyptr, to_read);
774        if (err <= 0) {
775                return err;
776        }
777
778        /* Set packet type based on interface linktype */
779        interface = lookup_interface(libtrace, ifaceid);
780        if (interface == NULL) {
781                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unknown pcapng interface id: %u", ifaceid);
782                return -1;
783        }
784        packet->type = TRACE_RT_PCAPNG_META;
785
786        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
787                        packet->type, flags)) {
788                return -1;
789        }
790
791        if (timestamp < interface->laststats) {
792                return sizeof(pcapng_stats_t) + to_read;
793        }
794
795        /* All of the stats are stored as options */
796        bodyptr = packet->payload;
797
798        do {
799                optval = pcapng_parse_next_option(packet->trace, &bodyptr,
800                                &optcode, &optlen);
801                if (optval == NULL) {
802                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
803                                "Failed to read options for pcapng enhanced packet");
804                        return -1;
805                }
806
807                if (optcode == PCAPNG_STATOPT_IFRECV) {
808                        uint64_t *recvd = (uint64_t *)optval;
809                        if (DATA(packet->trace)->byteswapped) {
810                                interface->received = byteswap64(*recvd);
811                        } else {
812                                interface->received = *recvd;
813                        }
814                }
815
816                if (optcode == PCAPNG_STATOPT_IFDROP) {
817                        uint64_t *drops = (uint64_t *)optval;
818                        if (DATA(packet->trace)->byteswapped) {
819                                interface->dropped = byteswap64(*drops);
820                        } else {
821                                interface->dropped = *drops;
822                        }
823                }
824
825                if (optcode == PCAPNG_STATOPT_OSDROP) {
826                        uint64_t *drops = (uint64_t *)optval;
827                        if (DATA(packet->trace)->byteswapped) {
828                                interface->osdropped = byteswap64(*drops);
829                        } else {
830                                interface->osdropped = *drops;
831                        }
832                }
833
834                if (optcode == PCAPNG_STATOPT_FILTERACCEPT) {
835                        uint64_t *accepts = (uint64_t *)optval;
836                        if (DATA(packet->trace)->byteswapped) {
837                                interface->accepted = byteswap64(*accepts);
838                        } else {
839                                interface->accepted = *accepts;
840                        }
841                }
842
843        } while (optcode != 0);
844        interface->laststats = timestamp;
845
846        return sizeof(pcapng_stats_t) + to_read;
847
848}
849
850static int pcapng_read_simple(libtrace_t *libtrace, libtrace_packet_t *packet,
851                uint32_t flags) {
852
853        int err;
854        uint32_t to_read;
855        uint32_t caplen;
856        pcapng_spkt_t *hdr = NULL;
857        pcapng_interface_t *interface;
858        char *bodyptr;
859
860        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_spkt_t));
861
862        if (err < 0) {
863                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "reading pcapng simple packet");
864                return -1;
865        }
866
867        if (err == 0) {
868                return 0;
869        }
870
871        if (err < (int)sizeof(pcapng_spkt_t)) {
872                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
873                                "Incomplete pcapng simple packet header");
874                return -1;
875        }
876
877        hdr = (pcapng_spkt_t *)packet->buffer;
878
879        /* Read the rest of the packet into the buffer */
880        if (DATA(libtrace)->byteswapped) {
881                assert(byteswap32(hdr->blocktype) == PCAPNG_SIMPLE_PACKET_TYPE);
882                to_read = byteswap32(hdr->blocklen) - sizeof(pcapng_spkt_t);
883                caplen = to_read - 4;   /* account for trailing length field */
884        } else {
885                assert(hdr->blocktype == PCAPNG_SIMPLE_PACKET_TYPE);
886                to_read = hdr->blocklen - sizeof(pcapng_spkt_t);
887                caplen = to_read - 4; /* account for trailing length field */
888        }
889
890        bodyptr = packet->buffer + sizeof(pcapng_spkt_t);
891        err = pcapng_read_body(libtrace, bodyptr, to_read);
892        if (err <= 0) {
893                return err;
894        }
895
896        /* Set packet type based on interface linktype.
897         * Assume interface 0, since we have no interface field */
898        interface = lookup_interface(libtrace, 0);
899        if (interface == NULL) {
900                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unknown pcapng interface id: %u", 0);
901                return -1;
902        }
903        packet->type = pcapng_linktype_to_rt(interface->linktype);
904
905        /* May as well cache the capture length now, since we've
906         * already got it in the right byte order */
907        packet->capture_length = caplen;
908
909        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
910                        packet->type, flags)) {
911                return -1;
912        }
913        return sizeof(pcapng_spkt_t) + to_read;
914
915}
916
917static int pcapng_read_enhanced(libtrace_t *libtrace, libtrace_packet_t *packet,
918                uint32_t flags) {
919        pcapng_epkt_t *hdr = NULL;
920        int err;
921        uint32_t to_read;
922        uint32_t caplen;
923        uint32_t ifaceid;
924        pcapng_interface_t *interface;
925        uint16_t optcode, optlen;
926        char *optval;
927        char *bodyptr;
928
929        err = wandio_read(libtrace->io, packet->buffer, sizeof(pcapng_epkt_t));
930
931        if (err < 0) {
932                trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "reading pcapng enhanced packet");
933                return -1;
934        }
935
936        if (err == 0) {
937                return 0;
938        }
939
940        if (err < (int)sizeof(pcapng_epkt_t)) {
941                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
942                                "Incomplete pcapng enhanced packet header");
943                return -1;
944        }
945
946        hdr = (pcapng_epkt_t *)packet->buffer;
947
948        /* Read the rest of the packet into the buffer */
949        if (DATA(libtrace)->byteswapped) {
950                assert(byteswap32(hdr->blocktype) == PCAPNG_ENHANCED_PACKET_TYPE);
951                caplen = byteswap32(hdr->caplen);
952                to_read = byteswap32(hdr->blocklen) - sizeof(pcapng_epkt_t);
953                ifaceid = byteswap32(hdr->interfaceid);
954        } else {
955                assert(hdr->blocktype == PCAPNG_ENHANCED_PACKET_TYPE);
956                caplen = hdr->caplen;
957                to_read = hdr->blocklen - sizeof(pcapng_epkt_t);
958                ifaceid = hdr->interfaceid;
959        }
960
961        bodyptr = packet->buffer + sizeof(pcapng_epkt_t);
962        err = pcapng_read_body(libtrace, bodyptr, to_read);
963        if (err <= 0) {
964                return err;
965        }
966
967        /* Set packet type based on interface linktype */
968        interface = lookup_interface(libtrace, ifaceid);
969        if (interface == NULL) {
970                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unknown pcapng interface id: %u", ifaceid);
971                return -1;
972        }
973        packet->type = pcapng_linktype_to_rt(interface->linktype);
974
975        /* May as well cache the capture length now, since we've
976         * already got it in the right byte order */
977        packet->capture_length = caplen;
978
979        if (pcapng_prepare_packet(libtrace, packet, packet->buffer,
980                        packet->type, flags)) {
981                return -1;
982        }
983
984        /* Make sure to parse any useful options */
985        if ((caplen % 4) == 0) {
986                bodyptr = packet->payload + caplen;
987        } else {
988                bodyptr = packet->payload + caplen + (4 - (caplen % 4));
989        }
990
991        do {
992                optval = pcapng_parse_next_option(packet->trace, &bodyptr,
993                                &optcode, &optlen);
994                if (optval == NULL) {
995                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
996                                "Failed to read options for pcapng enhanced packet");
997                        return -1;
998                }
999
1000                if (optcode == PCAPNG_PKTOPT_DROPCOUNT) {
1001                        uint64_t *drops = (uint64_t *)optval;
1002                        if (DATA(packet->trace)->byteswapped) {
1003                                interface->dropcounter += byteswap64(*drops);
1004                        } else {
1005                                interface->dropcounter += *drops;
1006                        }
1007                }
1008
1009        } while (optcode != 0);
1010        return sizeof(pcapng_epkt_t) + to_read;
1011
1012}
1013
1014static int pcapng_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
1015{
1016        struct pcapng_peeker peeker;
1017        int err = 0;
1018        uint32_t flags = 0;
1019        uint32_t to_read;
1020        uint32_t btype = 0;
1021        int gotpacket = 0;
1022
1023        /* Peek to get next block type */
1024        assert(libtrace->format_data);
1025        assert(libtrace->io);
1026
1027        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
1028                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
1029        }
1030
1031        flags |= TRACE_PREP_OWN_BUFFER;
1032
1033        while (!gotpacket) {
1034
1035                if ((err=is_halted(libtrace)) != -1) {
1036                        return err;
1037                }
1038
1039                err = wandio_peek(libtrace->io, &peeker, sizeof(peeker));
1040                if (err < 0) {
1041                        trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "reading pcapng packet");
1042                        return -1;
1043                }
1044
1045                if (err == 0) {
1046                        return 0;
1047                }
1048
1049                if (err < (int)sizeof(struct pcapng_peeker)) {
1050                        trace_set_err(libtrace, TRACE_ERR_WANDIO_FAILED, "Incomplete pcapng block");
1051                        return -1;
1052                }
1053
1054                if (DATA(libtrace)->byteswapped) {
1055                        btype = byteswap32(peeker.blocktype);
1056                } else {
1057                        btype = peeker.blocktype;
1058                }
1059
1060                switch (btype) {
1061                        /* Section Header */
1062                        case PCAPNG_SECTION_TYPE:
1063                                err = pcapng_read_section(libtrace, packet, flags);
1064                                gotpacket = 1;
1065                                break;
1066
1067                        /* Interface Header */
1068                        case PCAPNG_INTERFACE_TYPE:
1069                                err = pcapng_read_interface(libtrace, packet, flags);
1070                                gotpacket = 1;
1071                                break;
1072
1073
1074                        case PCAPNG_ENHANCED_PACKET_TYPE:
1075                                err = pcapng_read_enhanced(libtrace, packet,
1076                                                flags);
1077                                gotpacket = 1;
1078                                break;
1079
1080                        case PCAPNG_SIMPLE_PACKET_TYPE:
1081                                err = pcapng_read_simple(libtrace, packet, flags);
1082                                gotpacket = 1;
1083                                break;
1084
1085                        case PCAPNG_INTERFACE_STATS_TYPE:
1086                                err = pcapng_read_stats(libtrace, packet, flags);
1087                                gotpacket = 1;
1088                                break;
1089
1090                        case PCAPNG_NAME_RESOLUTION_TYPE:
1091                                err = pcapng_read_nrb(libtrace, packet, flags);
1092                                gotpacket = 1;
1093                                break;
1094
1095                        case PCAPNG_CUSTOM_TYPE:
1096                        case PCAPNG_CUSTOM_NONCOPY_TYPE:
1097                                err = pcapng_read_custom(libtrace, packet, flags);
1098                                gotpacket = 1;
1099                                break;
1100
1101
1102                        case PCAPNG_OLD_PACKET_TYPE:
1103                                /* TODO */
1104
1105                        /* Everything else -- don't care, skip it */
1106                        default:
1107                                if (DATA(libtrace)->byteswapped) {
1108                                        to_read = byteswap32(peeker.blocklen);
1109                                } else {
1110                                        to_read = peeker.blocklen;
1111                                }
1112                                err = skip_block(libtrace, to_read);
1113                                break;
1114                }
1115        }
1116
1117        if (err <= 0) {
1118                return err;
1119        }
1120
1121        if (DATA(libtrace)->byteswapped)
1122                return byteswap32(peeker.blocklen);
1123        return peeker.blocklen;
1124
1125}
1126
1127static libtrace_linktype_t pcapng_get_link_type(const libtrace_packet_t *packet)
1128{
1129
1130        return pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type));
1131
1132}
1133
1134static libtrace_direction_t pcapng_get_direction(const libtrace_packet_t
1135                *packet) {
1136
1137        /* Defined in format_helper.c */
1138        return pcap_get_direction(packet);
1139}
1140
1141static struct timespec pcapng_get_timespec(const libtrace_packet_t *packet) {
1142
1143        struct timespec ts;
1144        uint64_t timestamp = 0;
1145        uint32_t interfaceid = 0;
1146        pcapng_interface_t *interface;
1147
1148        assert(packet->header);
1149
1150        ts.tv_sec = 0;
1151        ts.tv_nsec = 0;
1152
1153        /* No timestamps in simple packets :( */
1154        if (PACKET_IS_SIMPLE) {
1155                return ts;
1156        }
1157
1158        if (PACKET_IS_ENHANCED) {
1159                pcapng_epkt_t *ehdr = (pcapng_epkt_t *)packet->header;
1160
1161                if (DATA(packet->trace)->byteswapped) {
1162                        timestamp = ((uint64_t)(byteswap32(ehdr->timestamp_high)) << 32) + byteswap32(ehdr->timestamp_low);
1163                        interfaceid = byteswap32(ehdr->interfaceid);
1164                } else {
1165                        timestamp = ((uint64_t)(ehdr->timestamp_high) << 32) +
1166                                        ehdr->timestamp_low;
1167                        interfaceid = ehdr->interfaceid;
1168                }
1169        } else if (PACKET_IS_OLD) {
1170                pcapng_opkt_t *ohdr = (pcapng_opkt_t *)packet->header;
1171
1172                if (DATA(packet->trace)->byteswapped) {
1173                        timestamp = ((uint64_t)(byteswap32(ohdr->timestamp_high)) << 32) + byteswap32(ohdr->timestamp_low);
1174                        interfaceid = byteswap16(ohdr->interfaceid);
1175                } else {
1176                        timestamp = ((uint64_t)(ohdr->timestamp_high) << 32) +
1177                                        ohdr->timestamp_low;
1178                        interfaceid = ohdr->interfaceid;
1179                }
1180
1181        }
1182
1183        if (timestamp == 0)
1184                return ts;
1185
1186
1187        interface = lookup_interface(packet->trace, interfaceid);
1188        if (interface == NULL) {
1189                trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET,
1190                                "Bad interface %u on pcapng packet",
1191                                interfaceid);
1192                return ts;
1193        }
1194
1195        ts.tv_sec = (timestamp / interface->tsresol);
1196        ts.tv_nsec = (uint64_t)(timestamp - (ts.tv_sec * interface->tsresol)) / interface->tsresol * 1000000000;
1197
1198        return ts;
1199
1200}
1201
1202static inline int pcapng_get_wlen_header(const libtrace_packet_t *packet) {
1203
1204        if (PACKET_IS_ENHANCED) {
1205                pcapng_epkt_t *ehdr = (pcapng_epkt_t *)packet->header;
1206
1207                if (DATA(packet->trace)->byteswapped) {
1208                        return byteswap32(ehdr->wlen);
1209                } else {
1210                        return ehdr->wlen;
1211                }
1212        } else if (PACKET_IS_SIMPLE) {
1213                pcapng_spkt_t *shdr = (pcapng_spkt_t *)packet->header;
1214
1215                if (DATA(packet->trace)->byteswapped) {
1216                        return byteswap32(shdr->wlen);
1217                } else {
1218                        return shdr->wlen;
1219                }
1220        } else if (PACKET_IS_OLD) {
1221                pcapng_opkt_t *ohdr = (pcapng_opkt_t *)packet->header;
1222
1223                if (DATA(packet->trace)->byteswapped) {
1224                        return byteswap32(ohdr->wlen);
1225                } else {
1226                        return ohdr->wlen;
1227                }
1228        }
1229
1230        /* If we get here, we aren't a valid pcapng packet */
1231        trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET,
1232                        "Invalid RT type for pcapng packet: %u",
1233                        packet->type);
1234        return -1;
1235}
1236
1237static int pcapng_get_wire_length(const libtrace_packet_t *packet) {
1238
1239        /* First, get the wire length from the packet header */
1240        int baselen = pcapng_get_wlen_header(packet);
1241
1242        if (baselen == -1)
1243                return -1;
1244
1245        /* Then, account for the vagaries of different DLTs */
1246        if (rt_to_pcap_linktype(packet->type) == TRACE_DLT_EN10MB) {
1247                /* Include the missing FCS */
1248                baselen += 4;
1249        } else if (rt_to_pcap_linktype(packet->type) ==
1250                        TRACE_DLT_IEEE802_11_RADIO) {
1251                /* If the packet is Radiotap and the flags field indicates
1252                 * that the FCS is not included in the 802.11 frame, then
1253                 * we need to add 4 to the wire-length to account for it.
1254                 */
1255                uint8_t flags;
1256                void *link;
1257                libtrace_linktype_t linktype;
1258                link = trace_get_packet_buffer(packet, &linktype, NULL);
1259                trace_get_wireless_flags(link, linktype, &flags);
1260                if ((flags & TRACE_RADIOTAP_F_FCS) == 0) {
1261                        baselen += 4;
1262                }
1263        } else if (rt_to_pcap_linktype(packet->type) == TRACE_DLT_LINUX_SLL) {
1264                libtrace_sll_header_t *sll;
1265                sll = (libtrace_sll_header_t *)packet->payload;
1266
1267                /* Account for FCS when dealing with Ethernet packets that are
1268                 * encapsulated in Linux SLL. This should fix the problem
1269                 * where the wire lengths differ if we convert the packet to
1270                 * ERF */
1271                if (ntohs(sll->protocol) == TRACE_ETHERTYPE_LOOPBACK) {
1272                        baselen += 4;
1273                }
1274        }
1275
1276        return baselen;
1277}
1278
1279static int pcapng_get_capture_length(const libtrace_packet_t *packet) {
1280
1281        if (PACKET_IS_ENHANCED) {
1282                pcapng_epkt_t *ehdr = (pcapng_epkt_t *)packet->header;
1283
1284                if (DATA(packet->trace)->byteswapped) {
1285                        return byteswap32(ehdr->caplen);
1286                } else {
1287                        return ehdr->caplen;
1288                }
1289        } else if (PACKET_IS_SIMPLE) {
1290                pcapng_spkt_t *shdr = (pcapng_spkt_t *)packet->header;
1291
1292                /* Have to calculate this one by removing all the headers.
1293                 * Don't forget the extra length field at the end!
1294                 */
1295                if (DATA(packet->trace)->byteswapped) {
1296                        return byteswap32(shdr->blocklen) -
1297                                        sizeof(pcapng_spkt_t) - 4;
1298                } else {
1299                        return shdr->blocklen - sizeof(pcapng_spkt_t) - 4;
1300                }
1301        } else if (PACKET_IS_OLD) {
1302                pcapng_opkt_t *ohdr = (pcapng_opkt_t *)packet->header;
1303
1304                if (DATA(packet->trace)->byteswapped) {
1305                        return byteswap32(ohdr->caplen);
1306                } else {
1307                        return ohdr->caplen;
1308                }
1309        }
1310
1311        /* If we get here, we aren't a valid pcapng packet */
1312        trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET,
1313                        "Invalid RT type for pcapng packet: %u",
1314                        packet->type);
1315        return -1;
1316}
1317
1318static size_t pcapng_set_capture_length(libtrace_packet_t *packet,
1319                size_t size) {
1320        uint32_t current;
1321        char *copyto, *copyfrom;
1322        uint32_t tocopy;
1323
1324        if (!(PACKET_IS_SIMPLE) && !(PACKET_IS_ENHANCED)) {
1325                return 0;
1326        }
1327
1328        current = pcapng_get_capture_length(packet);
1329
1330        if (current <= size)
1331                return current;
1332
1333        copyto = (char *)packet->payload + size;
1334        copyfrom = (char *)packet->payload + current;
1335
1336        /* Need to make sure we keep the options and trailing length... */
1337
1338        if (PACKET_IS_SIMPLE) {
1339                tocopy = 4;
1340        } else {
1341                pcapng_epkt_t *ehdr = (pcapng_epkt_t *)packet->header;
1342                if (DATA(packet->trace)->byteswapped) {
1343                        tocopy =  byteswap32(ehdr->blocklen) -
1344                                        sizeof(pcapng_epkt_t) - current;
1345                } else {
1346                        tocopy = ehdr->blocklen - sizeof(pcapng_epkt_t) -
1347                                        current;
1348                }
1349        }
1350
1351        memmove(copyto, copyfrom, tocopy);
1352
1353        if (PACKET_IS_SIMPLE) {
1354                pcapng_spkt_t *shdr = (pcapng_spkt_t *)packet->header;
1355
1356                if (DATA(packet->trace)->byteswapped) {
1357                        shdr->blocklen = byteswap32(size + sizeof(pcapng_spkt_t) + tocopy);
1358                } else {
1359                        shdr->blocklen = size + sizeof(pcapng_spkt_t) + tocopy;
1360                }
1361        }
1362
1363        if (PACKET_IS_ENHANCED) {
1364                pcapng_epkt_t *ehdr = (pcapng_epkt_t *)packet->header;
1365
1366                if (DATA(packet->trace)->byteswapped) {
1367                        ehdr->blocklen = byteswap32(size + sizeof(pcapng_epkt_t) + tocopy);
1368                        ehdr->caplen = byteswap32(size);
1369                } else {
1370                        ehdr->blocklen = size + sizeof(pcapng_epkt_t) + tocopy;
1371                        ehdr->caplen = size;
1372                }
1373        }
1374        packet->capture_length = -1;
1375        return trace_get_capture_length(packet);
1376}
1377
1378
1379static struct libtrace_eventobj_t pcapng_event(libtrace_t *libtrace,
1380                libtrace_packet_t *packet) {
1381
1382        libtrace_eventobj_t event = {0,0,0.0,0};
1383
1384        if (DATA(libtrace)->realtime) {
1385                event.size = trace_read_packet(libtrace, packet);
1386                if (event.size < 1) {
1387                        event.type = TRACE_EVENT_TERMINATE;
1388                } else {
1389                        event.type = TRACE_EVENT_PACKET;
1390                }
1391        } else {
1392                event = trace_event_trace(libtrace, packet);
1393        }
1394
1395        return event;
1396}
1397
1398static void pcapng_get_statistics(libtrace_t *trace, libtrace_stat_t *stat) {
1399
1400        int i = 0;
1401        uint64_t drops = 0;
1402        uint64_t accepted = 0;
1403        uint64_t osdrops = 0;
1404        uint64_t received = 0;
1405
1406        if (!trace->format_data) {
1407                return;
1408        }
1409
1410        /* Add up all known interface stats */
1411        for (i = 0; i < DATA(trace)->nextintid; i++) {
1412                pcapng_interface_t *interface;
1413
1414                interface = lookup_interface(trace, i);
1415                if (interface == NULL) {
1416                        continue;
1417                }
1418
1419                received += interface->received;
1420                osdrops += interface->osdropped;
1421                accepted += interface->accepted;
1422                drops += interface->dropped;
1423
1424        }
1425
1426        stat->dropped = drops + osdrops;
1427        stat->dropped_valid = 1;
1428
1429        stat->received = received;
1430        stat->received_valid = 1;
1431
1432        stat->filtered = received - accepted;
1433        stat->filtered_valid = 1;
1434
1435        stat->captured = accepted;
1436        stat->captured_valid = 1;
1437
1438
1439}
1440
1441static void pcapng_help(void) {
1442        printf("pcapng format module: \n");
1443        printf("Supported input URIs:\n");
1444        printf("\tpcapng:/path/to/file\n");
1445        printf("\tpcapng:/path/to/file.gz\n");
1446        printf("\n");
1447        printf("\te.g.: pcapng:/tmp/trace.pcap\n");
1448        printf("\n");
1449}
1450
1451static struct libtrace_format_t pcapng = {
1452        "pcapng",
1453        "$Id$",
1454        TRACE_FORMAT_PCAPNG,
1455        NULL,                           /* probe filename */
1456        pcapng_probe_magic,             /* probe magic */
1457        pcapng_init_input,              /* init_input */
1458        pcapng_config_input,            /* config_input */
1459        pcapng_start_input,             /* start_input */
1460        NULL,                           /* pause_input */
1461        NULL,                           /* init_output */
1462        NULL,                           /* config_output */
1463        NULL,                           /* start_output */
1464        pcapng_fin_input,               /* fin_input */
1465        NULL,                           /* fin_output */
1466        pcapng_read_packet,             /* read_packet */
1467        pcapng_prepare_packet,          /* prepare_packet */
1468        NULL,                           /* fin_packet */
1469        NULL,                           /* write_packet */
1470        pcapng_get_link_type,           /* get_link_type */
1471        pcapng_get_direction,           /* get_direction */
1472        NULL,                           /* set_direction */
1473        NULL,                           /* get_erf_timestamp */
1474        NULL,                           /* get_timeval */
1475        pcapng_get_timespec,            /* get_timespec */
1476        NULL,                           /* get_seconds */
1477        NULL,                           /* seek_erf */
1478        NULL,                           /* seek_timeval */
1479        NULL,                           /* seek_seconds */
1480        pcapng_get_capture_length,      /* get_capture_length */
1481        pcapng_get_wire_length,         /* get_wire_length */
1482        pcapng_get_framing_length,      /* get_framing_length */
1483        pcapng_set_capture_length,      /* set_capture_length */
1484        NULL,                           /* get_received_packets */
1485        NULL,                           /* get_filtered_packets */
1486        NULL,                           /* get_dropped_packets */
1487        pcapng_get_statistics,          /* get_statistics */
1488        NULL,                           /* get_fd */
1489        pcapng_event,                   /* trace_event */
1490        pcapng_help,                    /* help */
1491        NULL,                           /* next pointer */
1492        NON_PARALLEL(false)
1493};
1494
1495void pcapng_constructor(void) {
1496        register_format(&pcapng);
1497}
1498
Note: See TracBrowser for help on using the repository browser.