source: lib/format_pcapfile.c @ 962aad3

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 962aad3 was 962aad3, checked in by Shane Alcock <salcock@…>, 11 years ago
  • Fixed bug where the capture length could exceed the wire length if we write full payload PCAP traces. Apparently Snort doesn't like this and will discard every packet :(
  • Property mode set to 100644
File size: 17.8 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34#include "common.h"
35#include "config.h"
36#include "libtrace.h"
37#include "libtrace_int.h"
38#include "format_helper.h"
39
40#include <sys/stat.h>
41#include <assert.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <stdbool.h>
48
49/* This format module implements our own, more efficient, version of the PCAP
50 * file format. This should always be used in preference to the "pcap" format
51 * provided in format_pcap.c.
52 *
53 * This is a trace file format and does not implement any live interface
54 * capture. This is covered by "pcapint" in format_pcap.c.
55 *
56 * This format supports both reading and writing, regardless of the version
57 * of your PCAP library.
58 */
59
60#define DATA(x) ((struct pcapfile_format_data_t*)((x)->format_data))
61#define DATAOUT(x) ((struct pcapfile_format_data_out_t*)((x)->format_data))
62#define IN_OPTIONS DATA(libtrace)->options
63
64typedef struct pcapfile_header_t {
65                uint32_t magic_number;   /* magic number */
66                uint16_t version_major;  /* major version number */
67                uint16_t version_minor;  /* minor version number */
68                int32_t  thiszone;       /* GMT to local correction */
69                uint32_t sigfigs;        /* timestamp accuracy */
70                uint32_t snaplen;        /* aka "wirelen" */
71                uint32_t network;        /* data link type */
72} pcapfile_header_t; 
73
74struct pcapfile_format_data_t {
75        struct {
76                /* Indicates whether the event API should replicate the pauses
77                 * between packets */
78                int real_time;
79        } options;
80
81        /* The PCAP meta-header that should be written at the start of each
82         * trace */
83        pcapfile_header_t header;
84        /* Indicates whether the input trace is started */
85        bool started;
86};
87
88struct pcapfile_format_data_out_t {
89        iow_t *file;
90        int level;
91        int flag;
92
93};
94
95static int pcapfile_probe_magic(io_t *io)
96{
97        pcapfile_header_t header;
98        int len;
99        len = wandio_peek(io, &header, sizeof(header));
100        /* Is this long enough? */
101        if (len < (int)sizeof(header)) {
102                return 0;
103        }
104        /* Pcap magic? */
105        if (header.magic_number == 0xa1b2c3d4 || header.magic_number == 0xd4c3b2a1) {
106                return 1;
107        }
108        /* Nope, not pcap */
109        return 0;
110}
111
112static int pcapfile_init_input(libtrace_t *libtrace) {
113        libtrace->format_data = malloc(sizeof(struct pcapfile_format_data_t));
114
115        if (libtrace->format_data == NULL) {
116                trace_set_err(libtrace,ENOMEM,"Out of memory");
117                return -1;
118        }
119
120        IN_OPTIONS.real_time = 0;
121        DATA(libtrace)->started = false;
122        return 0;
123}
124
125static int pcapfile_init_output(libtrace_out_t *libtrace) {
126        libtrace->format_data = 
127                malloc(sizeof(struct pcapfile_format_data_out_t));
128
129        DATAOUT(libtrace)->file=NULL;
130        DATAOUT(libtrace)->level=0;
131        DATAOUT(libtrace)->flag=O_CREAT|O_WRONLY;
132
133        return 0;
134}
135
136
137static uint16_t swaps(libtrace_t *libtrace, uint16_t num)
138{
139        /* To deal with open_dead traces that might try and use this
140         * if we don't have any per trace data, assume host byte order
141         */
142        if (!DATA(libtrace))
143                return num;
144       
145        /* We can use the PCAP magic number to determine the byte order */
146        if (DATA(libtrace)->header.magic_number == 0xd4c3b2a1)
147                return byteswap16(num);
148
149        return num;
150}
151
152static uint32_t swapl(libtrace_t *libtrace, uint32_t num)
153{
154        /* To deal with open_dead traces that might try and use this
155         * if we don't have any per trace data, assume host byte order
156         */
157        if (!DATA(libtrace))
158                return num;
159       
160        /* We can use the PCAP magic number to determine the byte order */
161        if (DATA(libtrace)->header.magic_number == 0xd4c3b2a1)
162                return byteswap32(num);
163
164        return num;
165}
166
167
168static int pcapfile_start_input(libtrace_t *libtrace) 
169{
170        int err;
171
172        if (!libtrace->io) {
173                libtrace->io=trace_open_file(libtrace);
174                DATA(libtrace)->started=false;
175        }
176
177        if (!DATA(libtrace)->started) {
178
179                if (!libtrace->io)
180                        return -1;
181
182                err=wandio_read(libtrace->io,
183                                &DATA(libtrace)->header,
184                                sizeof(DATA(libtrace)->header));
185
186                if (err<1)
187                        return -1;
188               
189                if (swapl(libtrace,DATA(libtrace)->header.magic_number) != 
190                                        0xa1b2c3d4) {
191                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
192                                        "Not a pcap tracefile\n");
193                        return -1; /* Not a pcap file */
194                }
195
196                if (swaps(libtrace,DATA(libtrace)->header.version_major)!=2
197                        && swaps(libtrace,DATA(libtrace)->header.version_minor)!=4) {
198                        trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,
199                                        "Unknown pcap tracefile version %d.%d\n",
200                                        swaps(libtrace,
201                                                DATA(libtrace)->header.version_major),
202                                        swaps(libtrace,
203                                                DATA(libtrace)->header.version_minor));
204                        return -1;
205                }
206
207        }
208
209        return 0;
210}
211
212static int pcapfile_start_output(libtrace_out_t *libtrace UNUSED)
213{
214        /* We can't open the output file until we've seen the first packet.
215         * This is because we need to know the DLT to set the "network"
216         * value in the meta-header */
217       
218        return 0;
219}
220
221static int pcapfile_config_input(libtrace_t *libtrace,
222                trace_option_t option,
223                void *data)
224{
225        switch(option) {
226                case TRACE_OPTION_EVENT_REALTIME:
227                        IN_OPTIONS.real_time = *(int *)data;
228                        return 0;
229                case TRACE_OPTION_META_FREQ:
230                case TRACE_OPTION_SNAPLEN:
231                case TRACE_OPTION_PROMISC:
232                case TRACE_OPTION_FILTER:
233                        /* All these are either unsupported or handled
234                         * by trace_config */
235                        break;
236        }
237       
238        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
239                        "Unknown option %i", option);
240        return -1;
241}
242
243static int pcapfile_fin_input(libtrace_t *libtrace) 
244{
245        if (libtrace->io)
246                wandio_destroy(libtrace->io);
247        free(libtrace->format_data);
248        return 0; /* success */
249}
250
251static int pcapfile_fin_output(libtrace_out_t *libtrace)
252{
253        if (DATAOUT(libtrace)->file)
254                wandio_wdestroy(DATAOUT(libtrace)->file);
255        free(libtrace->format_data);
256        libtrace->format_data=NULL;
257        return 0; /* success */
258}
259
260static int pcapfile_config_output(libtrace_out_t *libtrace,
261                trace_option_output_t option,
262                void *value)
263{
264        switch (option) {
265                case TRACE_OPTION_OUTPUT_COMPRESS:
266                        DATAOUT(libtrace)->level = *(int*)value;
267                        return 0;
268                case TRACE_OPTION_OUTPUT_FILEFLAGS:
269                        DATAOUT(libtrace)->flag = *(int*)value;
270                        return 0;
271                default:
272                        /* Unknown option */
273                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
274                                        "Unknown option");
275                        return -1;
276        }
277        return -1;
278}
279
280static int pcapfile_prepare_packet(libtrace_t *libtrace, 
281                libtrace_packet_t *packet, void *buffer, 
282                libtrace_rt_types_t rt_type, uint32_t flags) {
283
284        if (packet->buffer != buffer && 
285                        packet->buf_control == TRACE_CTRL_PACKET) {
286                free(packet->buffer);
287        }
288
289        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
290                packet->buf_control = TRACE_CTRL_PACKET;
291        } else
292                packet->buf_control = TRACE_CTRL_EXTERNAL;
293       
294       
295        packet->buffer = buffer;
296        packet->header = buffer;
297        packet->payload = (char*)packet->buffer
298                + sizeof(libtrace_pcapfile_pkt_hdr_t);
299        packet->type = rt_type; 
300
301        if (libtrace->format_data == NULL) {
302                if (pcapfile_init_input(libtrace))
303                        return -1;
304        }
305       
306        return 0;
307}
308
309static int pcapfile_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet)
310{
311        int err;
312        uint32_t flags = 0;
313        size_t bytes_to_read = 0;
314
315        assert(libtrace->format_data);
316
317        packet->type = pcap_linktype_to_rt(swapl(libtrace,
318                                DATA(libtrace)->header.network));
319
320        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
321                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
322        }
323
324        flags |= TRACE_PREP_OWN_BUFFER;
325       
326        err=wandio_read(libtrace->io,
327                        packet->buffer,
328                        sizeof(libtrace_pcapfile_pkt_hdr_t));
329
330        if (err<0) {
331                trace_set_err(libtrace,errno,"reading packet");
332                return -1;
333        }
334        if (err==0) {
335                /* EOF */
336                return 0;
337        }
338
339        bytes_to_read = swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen);
340
341        assert(bytes_to_read < LIBTRACE_PACKET_BUFSIZE);
342
343        /* If there is no payload to read, do not ask wandio_read to try and
344         * read zero bytes - we'll just get back a zero that we will
345         * misinterpret as EOF! */
346        if (bytes_to_read == 0) {
347                packet->header = packet->buffer;
348                return sizeof(libtrace_pcapfile_pkt_hdr_t);
349        }
350
351        err=wandio_read(libtrace->io,
352                        (char*)packet->buffer+sizeof(libtrace_pcapfile_pkt_hdr_t),
353                        (size_t)swapl(libtrace,((libtrace_pcapfile_pkt_hdr_t*)packet->buffer)->caplen)
354                        );
355
356       
357        if (err<0) {
358                trace_set_err(libtrace,errno,"reading packet");
359                return -1;
360        }
361        if (err==0) {
362                return 0;
363        }
364
365        if (pcapfile_prepare_packet(libtrace, packet, packet->buffer,
366                                packet->type, flags)) {
367                return -1;
368        }
369       
370        return sizeof(libtrace_pcapfile_pkt_hdr_t) + bytes_to_read;
371}
372
373static int pcapfile_write_packet(libtrace_out_t *out,
374                libtrace_packet_t *packet)
375{
376        struct libtrace_pcapfile_pkt_hdr_t hdr;
377        struct timeval tv = trace_get_timeval(packet);
378        int numbytes;
379        int ret;
380        void *ptr;
381        uint32_t remaining;
382        libtrace_linktype_t linktype;
383
384        ptr = trace_get_packet_buffer(packet,&linktype,&remaining);
385       
386        /* Silently discard RT metadata packets and packets with an
387         * unknown linktype. */
388        if (linktype == TRACE_TYPE_METADATA || linktype == ~0U) {
389                return 0;
390        }
391
392        /* If this packet cannot be converted to a pcap linktype then
393         * pop off the top header until it can be converted
394         */
395        while (libtrace_to_pcap_linktype(linktype)==~0U) {
396                if (!demote_packet(packet)) {
397                        trace_set_err_out(out, 
398                                TRACE_ERR_NO_CONVERSION,
399                                "pcap does not support this format");
400                        return -1;
401                }
402
403                ptr = trace_get_packet_buffer(packet,&linktype,&remaining);
404        }
405
406
407        /* Now we know the link type write out a header if we've not done
408         * so already
409         */
410        if (!DATAOUT(out)->file) {
411                struct pcapfile_header_t pcaphdr;
412
413                DATAOUT(out)->file=trace_open_file_out(out,
414                                DATAOUT(out)->level,
415                                DATAOUT(out)->flag);
416                if (!DATAOUT(out)->file)
417                        return -1;
418
419                pcaphdr.magic_number = 0xa1b2c3d4;
420                pcaphdr.version_major = 2;
421                pcaphdr.version_minor = 4;
422                pcaphdr.thiszone = 0;
423                pcaphdr.sigfigs = 0;
424                pcaphdr.snaplen = 65536;
425                pcaphdr.network = 
426                        libtrace_to_pcap_linktype(linktype);
427
428                wandio_wwrite(DATAOUT(out)->file, 
429                                &pcaphdr, sizeof(pcaphdr));
430        }
431
432        hdr.ts_sec = tv.tv_sec;
433        hdr.ts_usec = tv.tv_usec;
434        hdr.caplen = trace_get_capture_length(packet);
435        assert(hdr.caplen < LIBTRACE_PACKET_BUFSIZE);
436        /* PCAP doesn't include the FCS in its wire length value, but we do */
437        if (linktype==TRACE_TYPE_ETH) {
438                if (trace_get_wire_length(packet) >= 4) {
439                        hdr.wirelen = trace_get_wire_length(packet)-4;
440
441                }
442                else {
443                        hdr.wirelen = 0;
444                }
445        }
446        else
447                hdr.wirelen = trace_get_wire_length(packet);
448
449        assert(hdr.wirelen < LIBTRACE_PACKET_BUFSIZE);
450
451        /* Ensure we have a valid capture length, especially if we're going
452         * to "remove" the FCS from the wire length */
453        if (hdr.caplen > hdr.wirelen)
454                hdr.caplen = hdr.wirelen;
455
456        /* Write the packet header */
457        numbytes=wandio_wwrite(DATAOUT(out)->file,
458                        &hdr, sizeof(hdr));
459
460        if (numbytes!=sizeof(hdr)) 
461                return -1;
462
463        /* Write the rest of the packet now */
464        ret=wandio_wwrite(DATAOUT(out)->file,
465                        ptr,
466                        hdr.caplen);
467
468        if (ret!=(int)hdr.caplen)
469                return -1;
470
471        return numbytes+ret;
472}
473
474static libtrace_linktype_t pcapfile_get_link_type(
475                const libtrace_packet_t *packet) 
476{
477        return pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type));
478}
479
480static libtrace_direction_t pcapfile_get_direction(const libtrace_packet_t *packet) 
481{
482        libtrace_direction_t direction  = -1;
483        switch(pcapfile_get_link_type(packet)) {
484                /* We can only get the direction for PCAP packets that have
485                 * been encapsulated in Linux SLL or PFLOG */
486                case TRACE_TYPE_LINUX_SLL:
487                {
488                        libtrace_sll_header_t *sll;
489                        libtrace_linktype_t linktype;
490
491                        sll = (libtrace_sll_header_t*)trace_get_packet_buffer(
492                                        packet,
493                                        &linktype,
494                                        NULL);
495                        if (!sll) {
496                                trace_set_err(packet->trace,
497                                        TRACE_ERR_BAD_PACKET,
498                                                "Bad or missing packet");
499                                return -1;
500                        }
501                        /* 0 == LINUX_SLL_HOST */
502                        /* the Waikato Capture point defines "packets
503                         * originating locally" (ie, outbound), with a
504                         * direction of 0, and "packets destined locally"
505                         * (ie, inbound), with a direction of 1.
506                         * This is kind-of-opposite to LINUX_SLL.
507                         * We return consistent values here, however
508                         *
509                         * Note that in recent versions of pcap, you can
510                         * use "inbound" and "outbound" on ppp in linux
511                         */
512                        if (ntohs(sll->pkttype == 0)) {
513                                direction = TRACE_DIR_INCOMING;
514                        } else {
515                                direction = TRACE_DIR_OUTGOING;
516                        }
517                        break;
518
519                }
520                case TRACE_TYPE_PFLOG:
521                {
522                        libtrace_pflog_header_t *pflog;
523                        libtrace_linktype_t linktype;
524
525                        pflog=(libtrace_pflog_header_t*)trace_get_packet_buffer(
526                                        packet,&linktype,NULL);
527                        if (!pflog) {
528                                trace_set_err(packet->trace,
529                                                TRACE_ERR_BAD_PACKET,
530                                                "Bad or missing packet");
531                                return -1;
532                        }
533                        /* enum    { PF_IN=0, PF_OUT=1 }; */
534                        if (ntohs(pflog->dir==0)) {
535
536                                direction = TRACE_DIR_INCOMING;
537                        }
538                        else {
539                                direction = TRACE_DIR_OUTGOING;
540                        }
541                        break;
542                }
543                default:
544                        break;
545        }       
546        return direction;
547}
548
549
550static struct timeval pcapfile_get_timeval(
551                const libtrace_packet_t *packet) 
552{
553        libtrace_pcapfile_pkt_hdr_t *hdr;
554        struct timeval ts;
555       
556        assert(packet->header);
557       
558        hdr = (libtrace_pcapfile_pkt_hdr_t*)packet->header;
559        ts.tv_sec = swapl(packet->trace,hdr->ts_sec);
560        ts.tv_usec = swapl(packet->trace,hdr->ts_usec);
561        return ts;
562}
563
564
565static int pcapfile_get_capture_length(const libtrace_packet_t *packet) {
566        libtrace_pcapfile_pkt_hdr_t *pcapptr; 
567
568        assert(packet->header);
569        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
570
571        return swapl(packet->trace,pcapptr->caplen);
572}
573
574static int pcapfile_get_wire_length(const libtrace_packet_t *packet) {
575        libtrace_pcapfile_pkt_hdr_t *pcapptr;
576         
577        assert(packet->header); 
578
579        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
580        if (packet->type==pcap_linktype_to_rt(TRACE_DLT_EN10MB))
581                /* Include the missing FCS */
582                return swapl(packet->trace,pcapptr->wirelen)+4; 
583        else if (packet->type==pcap_linktype_to_rt(TRACE_DLT_IEEE802_11_RADIO)){
584                /* If the packet is Radiotap and the flags field indicates
585                 * that the FCS is not included in the 802.11 frame, then
586                 * we need to add 4 to the wire-length to account for it.
587                 */
588                uint8_t flags;
589                void *link;
590                libtrace_linktype_t linktype;
591                link = trace_get_packet_buffer(packet, &linktype, NULL);
592                trace_get_wireless_flags(link, linktype, &flags);
593                if ((flags & TRACE_RADIOTAP_F_FCS) == 0)
594                        return swapl(packet->trace,pcapptr->wirelen)+4;
595        }
596        return swapl(packet->trace,pcapptr->wirelen);
597}
598
599static int pcapfile_get_framing_length(const libtrace_packet_t *packet UNUSED) {
600        return sizeof(libtrace_pcapfile_pkt_hdr_t);
601}
602
603static size_t pcapfile_set_capture_length(libtrace_packet_t *packet,size_t size) {
604        libtrace_pcapfile_pkt_hdr_t *pcapptr = 0;
605        assert(packet);
606        assert(packet->header);
607        if (size > trace_get_capture_length(packet)) {
608                /* Can't make a packet larger */
609                return trace_get_capture_length(packet);
610        }
611        /* Reset the cached capture length */
612        packet->capture_length = -1;
613        pcapptr = (libtrace_pcapfile_pkt_hdr_t *)packet->header;
614        pcapptr->caplen = swapl(packet->trace,(uint32_t)size);
615        return trace_get_capture_length(packet);
616}
617
618static struct libtrace_eventobj_t pcapfile_event(libtrace_t *libtrace, libtrace_packet_t *packet) {
619       
620        libtrace_eventobj_t event = {0,0,0.0,0};
621       
622        /* If we are being told to replay packets as fast as possible, then
623         * we just need to read and return the next packet in the trace */
624
625        if (IN_OPTIONS.real_time) {
626                event.size = pcapfile_read_packet(libtrace, packet);
627                if (event.size < 1)
628                        event.type = TRACE_EVENT_TERMINATE;
629                else
630                        event.type = TRACE_EVENT_PACKET;
631                return event;
632        } else {
633                return trace_event_trace(libtrace, packet);
634        }
635}
636
637static void pcapfile_help(void) {
638        printf("pcapfile format module: $Revision$\n");
639        printf("Supported input URIs:\n");
640        printf("\tpcapfile:/path/to/file\n");
641        printf("\tpcapfile:/path/to/file.gz\n");
642        printf("\n");
643        printf("\te.g.: pcapfile:/tmp/trace.pcap\n");
644        printf("\n");
645}
646
647static struct libtrace_format_t pcapfile = {
648        "pcapfile",
649        "$Id$",
650        TRACE_FORMAT_PCAPFILE,
651        NULL,                           /* probe filename */
652        pcapfile_probe_magic,           /* probe magic */
653        pcapfile_init_input,            /* init_input */
654        pcapfile_config_input,          /* config_input */
655        pcapfile_start_input,           /* start_input */
656        NULL,                           /* pause_input */
657        pcapfile_init_output,           /* init_output */
658        pcapfile_config_output,         /* config_output */
659        pcapfile_start_output,          /* start_output */
660        pcapfile_fin_input,             /* fin_input */
661        pcapfile_fin_output,            /* fin_output */
662        pcapfile_read_packet,           /* read_packet */
663        pcapfile_prepare_packet,        /* prepare_packet */
664        NULL,                           /* fin_packet */
665        pcapfile_write_packet,          /* write_packet */
666        pcapfile_get_link_type,         /* get_link_type */
667        pcapfile_get_direction,         /* get_direction */
668        NULL,                           /* set_direction */
669        NULL,                           /* get_erf_timestamp */
670        pcapfile_get_timeval,           /* get_timeval */
671        NULL,                           /* get_timespec */
672        NULL,                           /* get_seconds */
673        NULL,                           /* seek_erf */
674        NULL,                           /* seek_timeval */
675        NULL,                           /* seek_seconds */
676        pcapfile_get_capture_length,    /* get_capture_length */
677        pcapfile_get_wire_length,       /* get_wire_length */
678        pcapfile_get_framing_length,    /* get_framing_length */
679        pcapfile_set_capture_length,    /* set_capture_length */
680        NULL,                           /* get_received_packets */
681        NULL,                           /* get_filtered_packets */
682        NULL,                           /* get_dropped_packets */
683        NULL,                           /* get_captured_packets */
684        NULL,                           /* get_fd */
685        pcapfile_event,         /* trace_event */
686        pcapfile_help,                  /* help */
687        NULL                            /* next pointer */
688};
689
690
691void pcapfile_constructor(void) {
692        register_format(&pcapfile);
693}
694
695
Note: See TracBrowser for help on using the repository browser.