source: lib/format_pcapng.c @ e9da777

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

Refactor pcapng to read an entire block when possible

Remove much of the duplicated read logic in pcapng. Most blocks were
processed by reading the header, and then reading the variable length
portions such as a packet or options.

Instead, this is all replaced with a single top level read which reads
the entire block. This simplifies logic and makes it easier to check
for out of bounds reads/writes. This also adds additional
sanity checks, such as checking the caplen actually matches with the
data supplied.

The one exception to this refactor are 'section' blocks which contain the
magic to determine endianness. So we don't know the endianess of a block
length until we read a 'section'.

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