source: lib/format_pcapng.c @ 7bb2fd4

cachetimestampsdeveloprc-4.0.4ringdecrementfixringperformance
Last change on this file since 7bb2fd4 was 7bb2fd4, checked in by Richard Sanger <rsanger@…>, 2 years ago

Fix incorrect sizeof()'s checks in pcapng

Fix sizeof()'s which were accidentally checking the pointer size instead of the object.

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