source: lib/format_pcapng.c @ e17bad6

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

Fix some obvious copy paste errors in pcapng

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