source: lib/format_pcapng.c @ 2725318

develop
Last change on this file since 2725318 was 2725318, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Cleanup some of the assertions

  • 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) {
221                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory pcapng_init_input()");
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.