2 * Our own private code for writing libpcap files when capturing.
4 * We have these because we want a way to open a stream for output given
5 * only a file descriptor. libpcap 0.9[.x] has "pcap_dump_fopen()", which
8 * 1) earlier versions of libpcap doesn't have it
12 * 2) WinPcap/Npcap don't have it, because a file descriptor opened
13 * by code built for one version of the MSVC++ C library
14 * can't be used by library routines built for another version
15 * (e.g., threaded vs. unthreaded).
17 * Libpcap's pcap_dump() also doesn't return any error indications.
19 * Wireshark - Network traffic analyzer
20 * By Gerald Combs <gerald@wireshark.org>
21 * Copyright 1998 Gerald Combs
23 * Derived from code in the Wiretap Library
24 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
26 * SPDX-License-Identifier: GPL-2.0-or-later
37 #ifdef HAVE_SYS_TIME_H
46 #include <wsutil/epochs.h>
47 #include <wsutil/file_util.h>
50 #include <wiretap/file_wrappers.h>
52 typedef void* WFILE_T
;
54 struct pcapio_writer
{
57 wtap_compression_type ctype
;
60 /* Magic numbers in "libpcap" files.
62 "libpcap" file records are written in the byte order of the host that
63 writes them, and the reader is expected to fix this up.
65 PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
66 is a byte-swapped version of that.
68 PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
69 which uses the same common file format as PCAP_MAGIC, but the
70 timestamps are saved in nanosecond resolution instead of microseconds.
71 PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
72 #define PCAP_MAGIC 0xa1b2c3d4
73 #define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
74 #define PCAP_NSEC_MAGIC 0xa1b23c4d
75 #define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1
77 /* "libpcap" file header. */
79 uint32_t magic
; /* magic number */
80 uint16_t version_major
; /* major version number */
81 uint16_t version_minor
; /* minor version number */
82 int32_t thiszone
; /* GMT to local correction */
83 uint32_t sigfigs
; /* accuracy of timestamps */
84 uint32_t snaplen
; /* max length of captured packets, in octets */
85 uint32_t network
; /* data link type */
88 /* "libpcap" record header. */
90 uint32_t ts_sec
; /* timestamp seconds */
91 uint32_t ts_usec
; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
92 uint32_t incl_len
; /* number of octets of packet saved in file */
93 uint32_t orig_len
; /* actual length of packet */
96 /* Magic numbers in ".pcapng" files.
98 * .pcapng file records are written in the byte order of the host that
99 * writes them, and the reader is expected to fix this up.
100 * PCAPNG_MAGIC is the magic number, in host byte order;
101 * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that.
103 #define PCAPNG_MAGIC 0x1A2B3C4D
104 #define PCAPNG_SWAPPED_MAGIC 0x4D3C2B1A
106 /* Currently we are only supporting the initial version of
108 #define PCAPNG_MAJOR_VERSION 1
109 #define PCAPNG_MINOR_VERSION 0
111 /* Section Header Block without options and trailing Block Total Length */
114 uint32_t block_total_length
;
115 uint32_t byte_order_magic
;
116 uint16_t major_version
;
117 uint16_t minor_version
;
118 uint64_t section_length
;
120 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
122 /* Interface Description Block without options and trailing Block Total Length */
125 uint32_t block_total_length
;
130 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
132 /* Interface Statistics Block without actual packet, options, and trailing
133 Block Total Length */
136 uint32_t block_total_length
;
137 uint32_t interface_id
;
138 uint32_t timestamp_high
;
139 uint32_t timestamp_low
;
141 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
143 /* Enhanced Packet Block without actual packet, options, and trailing
144 Block Total Length */
147 uint32_t block_total_length
;
148 uint32_t interface_id
;
149 uint32_t timestamp_high
;
150 uint32_t timestamp_low
;
151 uint32_t captured_len
;
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
158 uint16_t value_length
;
160 #define OPT_ENDOFOPT 0
161 #define OPT_COMMENT 1
163 #define SHB_HARDWARE 2 /* currently not used */
165 #define SHB_USERAPPL 4
167 #define IDB_DESCRIPTION 3
168 #define IDB_IF_SPEED 8
169 #define IDB_TSRESOL 9
170 #define IDB_FILTER 11
172 #define IDB_HARDWARE 15
173 #define ISB_STARTTIME 2
174 #define ISB_ENDTIME 3
177 #define ISB_FILTERACCEPT 6
179 #define ISB_USRDELIV 8
180 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
183 writecap_file_open(pcapio_writer
* pfile
, const char *filename
)
186 switch (pfile
->ctype
) {
187 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
188 case WTAP_GZIP_COMPRESSED
:
189 return gzwfile_open(filename
);
190 #endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
191 #ifdef HAVE_LZ4FRAME_H
192 case WTAP_LZ4_COMPRESSED
:
193 return lz4wfile_open(filename
);
194 #endif /* HAVE_LZ4FRAME_H */
196 fh
= ws_fopen(filename
, "wb");
197 /* Increase the size of the IO buffer if uncompressed.
198 * Compression has its own buffer that reduces writes.
201 size_t buffsize
= IO_BUF_SIZE
;
202 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
205 if (ws_stat64(filename
, &statb
) == 0) {
206 if (statb
.st_blksize
> IO_BUF_SIZE
) {
207 buffsize
= statb
.st_blksize
;
211 pfile
->io_buffer
= (char *)g_malloc(buffsize
);
212 setvbuf(fh
, pfile
->io_buffer
, _IOFBF
, buffsize
);
213 //ws_debug("buffsize %zu", buffsize);
220 writecap_file_fdopen(pcapio_writer
* pfile
, int fd
)
223 switch (pfile
->ctype
) {
224 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
225 case WTAP_GZIP_COMPRESSED
:
226 return gzwfile_fdopen(fd
);
227 #endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
228 #ifdef HAVE_LZ4FRAME_H
229 case WTAP_LZ4_COMPRESSED
:
230 return lz4wfile_fdopen(fd
);
231 #endif /* HAVE_LZ4FRAME_H */
233 fh
= ws_fdopen(fd
, "wb");
234 /* Increase the size of the IO buffer if uncompressed.
235 * Compression has its own buffer that reduces writes.
238 size_t buffsize
= IO_BUF_SIZE
;
239 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
242 if (ws_fstat64(fd
, &statb
) == 0) {
243 if (statb
.st_blksize
> IO_BUF_SIZE
) {
244 buffsize
= statb
.st_blksize
;
248 pfile
->io_buffer
= (char *)g_malloc(buffsize
);
249 setvbuf(fh
, pfile
->io_buffer
, _IOFBF
, buffsize
);
250 //ws_debug("buffsize %zu", buffsize);
257 writecap_fopen(const char *filename
, wtap_compression_type ctype
, int *err
)
259 pcapio_writer
* pfile
;
262 pfile
= g_new0(struct pcapio_writer
, 1);
267 pfile
->ctype
= ctype
;
268 errno
= WTAP_ERR_CANT_OPEN
;
269 void* fh
= writecap_file_open(pfile
, filename
);
281 writecap_fdopen(int fd
, wtap_compression_type ctype
, int *err
)
283 pcapio_writer
* pfile
;
286 pfile
= g_new0(struct pcapio_writer
, 1);
291 pfile
->ctype
= ctype
;
292 errno
= WTAP_ERR_CANT_OPEN
;
293 WFILE_T fh
= writecap_file_fdopen(pfile
, fd
);
305 writecap_open_stdout(wtap_compression_type ctype
, int *err
)
308 pcapio_writer
* pfile
;
317 * Put the new descriptor into binary mode.
319 * XXX - even if the file format we're writing is a text
322 if (_setmode(new_fd
, O_BINARY
) == -1) {
323 /* "Should not happen" */
330 pfile
= writecap_fdopen(new_fd
, ctype
, err
);
332 /* Failed; close the new fd */
340 writecap_flush(pcapio_writer
* pfile
, int *err
)
342 switch (pfile
->ctype
) {
343 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
344 case WTAP_GZIP_COMPRESSED
:
345 if (gzwfile_flush((GZWFILE_T
)pfile
->fh
) == -1) {
347 *err
= gzwfile_geterr((GZWFILE_T
)pfile
->fh
);
353 #ifdef HAVE_LZ4FRAME_H
354 case WTAP_LZ4_COMPRESSED
:
355 if (lz4wfile_flush((LZ4WFILE_T
)pfile
->fh
) == -1) {
357 *err
= lz4wfile_geterr((LZ4WFILE_T
)pfile
->fh
);
362 #endif /* HAVE_LZ4FRAME_H */
364 if (fflush((FILE*)pfile
->fh
) == EOF
) {
375 writecap_close(pcapio_writer
* pfile
, int *errp
)
379 errno
= WTAP_ERR_CANT_CLOSE
;
380 switch (pfile
->ctype
) {
381 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
382 case WTAP_GZIP_COMPRESSED
:
383 err
= gzwfile_close(pfile
->fh
);
386 #ifdef HAVE_LZ4FRAME_H
387 case WTAP_LZ4_COMPRESSED
:
388 err
= lz4wfile_close(pfile
->fh
);
390 #endif /* HAVE_LZ4FRAME_H */
392 if (fclose(pfile
->fh
) == EOF
) {
397 g_free(pfile
->io_buffer
);
405 /* Write to capture file */
407 write_to_file(pcapio_writer
* pfile
, const uint8_t* data
, size_t data_length
,
408 uint64_t *bytes_written
, int *err
)
412 switch (pfile
->ctype
) {
413 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
414 case WTAP_GZIP_COMPRESSED
:
415 nwritten
= gzwfile_write(pfile
->fh
, data
, (unsigned)data_length
);
417 * gzwfile_write() returns 0 on error.
420 *err
= gzwfile_geterr(pfile
->fh
);
425 #ifdef HAVE_LZ4FRAME_H
426 case WTAP_LZ4_COMPRESSED
:
427 nwritten
= lz4wfile_write(pfile
->fh
, data
, data_length
);
429 * lz4wfile_write() returns 0 on error.
432 *err
= lz4wfile_geterr(pfile
->fh
);
436 #endif /* HAVE_LZ4FRAME_H */
438 nwritten
= fwrite(data
, data_length
, 1, pfile
->fh
);
440 if (ferror(pfile
->fh
)) {
443 *err
= WTAP_ERR_SHORT_WRITE
;
450 (*bytes_written
) += data_length
;
454 /* Writing pcap files */
456 /* Write the file header to a dump file.
457 Returns true on success, false on failure.
458 Sets "*err" to an error code, or 0 for a short write, on failure*/
460 libpcap_write_file_header(pcapio_writer
* pfile
, int linktype
, int snaplen
, bool ts_nsecs
, uint64_t *bytes_written
, int *err
)
462 struct pcap_hdr file_hdr
;
464 file_hdr
.magic
= ts_nsecs
? PCAP_NSEC_MAGIC
: PCAP_MAGIC
;
465 /* current "libpcap" format is 2.4 */
466 file_hdr
.version_major
= 2;
467 file_hdr
.version_minor
= 4;
468 file_hdr
.thiszone
= 0; /* XXX - current offset? */
469 file_hdr
.sigfigs
= 0; /* unknown, but also apparently unused */
470 file_hdr
.snaplen
= snaplen
;
471 file_hdr
.network
= linktype
;
473 return write_to_file(pfile
, (const uint8_t*)&file_hdr
, sizeof(file_hdr
), bytes_written
, err
);
476 /* Write a record for a packet to a dump file.
477 Returns true on success, false on failure. */
479 libpcap_write_packet(pcapio_writer
* pfile
,
480 time_t sec
, uint32_t usec
,
481 uint32_t caplen
, uint32_t len
,
483 uint64_t *bytes_written
, int *err
)
485 struct pcaprec_hdr rec_hdr
;
487 rec_hdr
.ts_sec
= (uint32_t)sec
; /* Y2.038K issue in pcap format.... */
488 rec_hdr
.ts_usec
= usec
;
489 rec_hdr
.incl_len
= caplen
;
490 rec_hdr
.orig_len
= len
;
491 if (!write_to_file(pfile
, (const uint8_t*)&rec_hdr
, sizeof(rec_hdr
), bytes_written
, err
))
494 return write_to_file(pfile
, pd
, caplen
, bytes_written
, err
);
497 /* Writing pcapng files */
500 pcapng_count_string_option(const char *option_value
)
502 if ((option_value
!= NULL
) && (strlen(option_value
) > 0) && (strlen(option_value
) < UINT16_MAX
)) {
503 /* There's a value to write; get its length */
504 return (uint32_t)(sizeof(struct ws_option
) +
505 (uint16_t)ADD_PADDING(strlen(option_value
)));
507 return 0; /* nothing to write */
511 pcapng_write_string_option(pcapio_writer
* pfile
,
512 uint16_t option_type
, const char *option_value
,
513 uint64_t *bytes_written
, int *err
)
515 size_t option_value_length
;
516 struct ws_option option
;
517 const uint32_t padding
= 0;
519 if (option_value
== NULL
)
520 return true; /* nothing to write */
521 option_value_length
= strlen(option_value
);
522 if ((option_value_length
> 0) && (option_value_length
< UINT16_MAX
)) {
523 /* something to write */
524 option
.type
= option_type
;
525 option
.value_length
= (uint16_t)option_value_length
;
527 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
530 if (!write_to_file(pfile
, (const uint8_t*)option_value
, (int) option_value_length
, bytes_written
, err
))
533 if (option_value_length
% 4) {
534 if (!write_to_file(pfile
, (const uint8_t*)&padding
, 4 - option_value_length
% 4, bytes_written
, err
))
541 /* Write a pre-formatted pcapng block directly to the output file */
543 pcapng_write_block(pcapio_writer
* pfile
,
546 uint64_t *bytes_written
,
549 uint32_t block_length
, end_length
;
551 * - length and data are aligned to 4 bytes
552 * - block_total_length field is the same at the start and end of the block
554 * The block_total_length is not checked against the provided length but
555 * getting the trailing block_total_length from the length argument gives
556 * us an implicit check of correctness without needing to do an endian swap
558 if (((length
& 3) != 0) || (((intptr_t)data
& 3) != 0)) {
562 block_length
= *(const uint32_t *) (data
+sizeof(uint32_t));
563 end_length
= *(const uint32_t *) (data
+length
-sizeof(uint32_t));
564 if (block_length
!= end_length
) {
568 return write_to_file(pfile
, data
, length
, bytes_written
, err
);
572 pcapng_write_section_header_block(pcapio_writer
* pfile
,
577 uint64_t section_length
,
578 uint64_t *bytes_written
,
582 struct ws_option option
;
583 uint32_t block_total_length
;
584 uint32_t options_length
;
586 /* Size of base header */
587 block_total_length
= sizeof(struct shb
) + sizeof(uint32_t);
589 if (comments
!= NULL
) {
590 for (unsigned i
= 0; i
< comments
->len
; i
++) {
591 options_length
+= pcapng_count_string_option((char *)g_ptr_array_index(comments
, i
));
594 options_length
+= pcapng_count_string_option(hw
);
595 options_length
+= pcapng_count_string_option(os
);
596 options_length
+= pcapng_count_string_option(appname
);
597 /* If we have options add size of end-of-options */
598 if (options_length
!= 0) {
599 options_length
+= (uint32_t)sizeof(struct ws_option
);
601 block_total_length
+= options_length
;
603 /* write shb header */
604 shb
.block_type
= SECTION_HEADER_BLOCK_TYPE
;
605 shb
.block_total_length
= block_total_length
;
606 shb
.byte_order_magic
= PCAPNG_MAGIC
;
607 shb
.major_version
= PCAPNG_MAJOR_VERSION
;
608 shb
.minor_version
= PCAPNG_MINOR_VERSION
;
609 shb
.section_length
= section_length
;
611 if (!write_to_file(pfile
, (const uint8_t*)&shb
, sizeof(struct shb
), bytes_written
, err
))
614 if (comments
!= NULL
) {
615 for (unsigned i
= 0; i
< comments
->len
; i
++) {
616 if (!pcapng_write_string_option(pfile
, OPT_COMMENT
,
617 (char *)g_ptr_array_index(comments
, i
),
622 if (!pcapng_write_string_option(pfile
, SHB_HARDWARE
, hw
,
625 if (!pcapng_write_string_option(pfile
, SHB_OS
, os
,
628 if (!pcapng_write_string_option(pfile
, SHB_USERAPPL
, appname
,
631 if (options_length
!= 0) {
632 /* write end of options */
633 option
.type
= OPT_ENDOFOPT
;
634 option
.value_length
= 0;
635 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
639 /* write the trailing block total length */
640 return write_to_file(pfile
, (const uint8_t*)&block_total_length
, sizeof(uint32_t), bytes_written
, err
);
644 pcapng_write_interface_description_block(pcapio_writer
* pfile
,
645 const char *comment
, /* OPT_COMMENT 1 */
646 const char *name
, /* IDB_NAME 2 */
647 const char *descr
, /* IDB_DESCRIPTION 3 */
648 const char *filter
, /* IDB_FILTER 11 */
649 const char *os
, /* IDB_OS 12 */
650 const char *hardware
, /* IDB_HARDWARE 15 */
653 uint64_t *bytes_written
,
654 uint64_t if_speed
, /* IDB_IF_SPEED 8 */
655 uint8_t tsresol
, /* IDB_TSRESOL 9 */
659 struct ws_option option
;
660 uint32_t block_total_length
;
661 uint32_t options_length
;
662 const uint32_t padding
= 0;
664 block_total_length
= (uint32_t)(sizeof(struct idb
) + sizeof(uint32_t));
666 /* 01 - OPT_COMMENT */
667 options_length
+= pcapng_count_string_option(comment
);
670 options_length
+= pcapng_count_string_option(name
);
672 /* 03 - IDB_DESCRIPTION */
673 options_length
+= pcapng_count_string_option(descr
);
675 /* 08 - IDB_IF_SPEED */
677 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
681 /* 09 - IDB_TSRESOL */
683 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
684 sizeof(struct ws_option
));
687 /* 11 - IDB_FILTER */
688 if ((filter
!= NULL
) && (strlen(filter
) > 0) && (strlen(filter
) < UINT16_MAX
- 1)) {
689 /* No, this isn't a string, it has an extra type byte */
690 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
691 (uint16_t)(ADD_PADDING(strlen(filter
)+ 1)));
695 options_length
+= pcapng_count_string_option(os
);
697 /* 15 - IDB_HARDWARE */
698 options_length
+= pcapng_count_string_option(hardware
);
700 /* If we have options add size of end-of-options */
701 if (options_length
!= 0) {
702 options_length
+= (uint32_t)sizeof(struct ws_option
);
704 block_total_length
+= options_length
;
706 /* write block header */
707 idb
.block_type
= INTERFACE_DESCRIPTION_BLOCK_TYPE
;
708 idb
.block_total_length
= block_total_length
;
709 idb
.link_type
= link_type
;
711 idb
.snap_len
= snap_len
;
712 if (!write_to_file(pfile
, (const uint8_t*)&idb
, sizeof(struct idb
), bytes_written
, err
))
715 /* 01 - OPT_COMMENT - write comment string if applicable */
716 if (!pcapng_write_string_option(pfile
, OPT_COMMENT
, comment
,
720 /* 02 - IDB_NAME - write interface name string if applicable */
721 if (!pcapng_write_string_option(pfile
, IDB_NAME
, name
,
725 /* 03 - IDB_DESCRIPTION */
726 /* write interface description string if applicable */
727 if (!pcapng_write_string_option(pfile
, IDB_DESCRIPTION
, descr
,
731 /* 08 - IDB_IF_SPEED */
733 option
.type
= IDB_IF_SPEED
;
734 option
.value_length
= sizeof(uint64_t);
736 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
739 if (!write_to_file(pfile
, (const uint8_t*)&if_speed
, sizeof(uint64_t), bytes_written
, err
))
743 /* 09 - IDB_TSRESOL */
745 option
.type
= IDB_TSRESOL
;
746 option
.value_length
= sizeof(uint8_t);
748 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
751 if (!write_to_file(pfile
, (const uint8_t*)&tsresol
, sizeof(uint8_t), bytes_written
, err
))
754 if (!write_to_file(pfile
, (const uint8_t*)&padding
, 3, bytes_written
, err
))
758 /* 11 - IDB_FILTER - write filter string if applicable
759 * We write out the libpcap filter expression, not the
760 * generated BPF code.
762 if ((filter
!= NULL
) && (strlen(filter
) > 0) && (strlen(filter
) < UINT16_MAX
- 1)) {
763 option
.type
= IDB_FILTER
;
764 option
.value_length
= (uint16_t)(strlen(filter
) + 1 );
765 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
768 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
769 if (!write_to_file(pfile
, (const uint8_t*)&padding
, 1, bytes_written
, err
))
771 if (!write_to_file(pfile
, (const uint8_t*)filter
, (int) strlen(filter
), bytes_written
, err
))
773 if ((strlen(filter
) + 1) % 4) {
774 if (!write_to_file(pfile
, (const uint8_t*)&padding
, 4 - (strlen(filter
) + 1) % 4, bytes_written
, err
))
779 /* 12 - IDB_OS - write os string if applicable */
780 if (!pcapng_write_string_option(pfile
, IDB_OS
, os
,
784 /* 15 - IDB_HARDWARE - write hardware string if applicable */
785 if (!pcapng_write_string_option(pfile
, IDB_HARDWARE
, hardware
,
789 if (options_length
!= 0) {
790 /* write end of options */
791 option
.type
= OPT_ENDOFOPT
;
792 option
.value_length
= 0;
793 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
797 /* write the trailing Block Total Length */
798 return write_to_file(pfile
, (const uint8_t*)&block_total_length
, sizeof(uint32_t), bytes_written
, err
);
801 /* Write a record for a packet to a dump file.
802 Returns true on success, false on failure. */
804 pcapng_write_enhanced_packet_block(pcapio_writer
* pfile
,
806 time_t sec
, uint32_t usec
,
807 uint32_t caplen
, uint32_t len
,
808 uint32_t interface_id
,
812 uint64_t *bytes_written
,
816 struct ws_option option
;
817 uint32_t block_total_length
;
819 uint32_t options_length
;
820 const uint32_t padding
= 0;
825 block_total_length
= (uint32_t)(sizeof(struct epb
) +
826 ADD_PADDING(caplen
) +
829 options_length
+= pcapng_count_string_option(comment
);
831 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
834 /* If we have options add size of end-of-options */
835 if (options_length
!= 0) {
836 options_length
+= (uint32_t)sizeof(struct ws_option
);
838 block_total_length
+= options_length
;
839 timestamp
= (uint64_t)sec
* ts_mul
+ (uint64_t)usec
;
840 epb
.block_type
= ENHANCED_PACKET_BLOCK_TYPE
;
841 epb
.block_total_length
= block_total_length
;
842 epb
.interface_id
= interface_id
;
843 epb
.timestamp_high
= (uint32_t)((timestamp
>>32) & 0xffffffff);
844 epb
.timestamp_low
= (uint32_t)(timestamp
& 0xffffffff);
845 epb
.captured_len
= caplen
;
846 epb
.packet_len
= len
;
847 if (!write_to_file(pfile
, (const uint8_t*)&epb
, sizeof(struct epb
), bytes_written
, err
))
849 if (!write_to_file(pfile
, pd
, caplen
, bytes_written
, err
))
851 /* Use more efficient write in case of no "extras" */
853 pad_len
= 4 - (caplen
% 4);
856 * If we have no options to write, just write out the padding and
857 * the block total length with one fwrite() call.
859 if(!comment
&& flags
== 0 && options_length
==0){
860 /* Put padding in the buffer */
861 for (i
= 0; i
< pad_len
; i
++) {
864 /* Write the total length */
865 memcpy(&buff
[i
], &block_total_length
, sizeof(uint32_t));
866 i
+= sizeof(uint32_t);
867 return write_to_file(pfile
, (const uint8_t*)&buff
, i
, bytes_written
, err
);
870 if (!write_to_file(pfile
, (const uint8_t*)&padding
, pad_len
, bytes_written
, err
))
873 if (!pcapng_write_string_option(pfile
, OPT_COMMENT
, comment
,
877 option
.type
= EPB_FLAGS
;
878 option
.value_length
= sizeof(uint32_t);
879 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
881 if (!write_to_file(pfile
, (const uint8_t*)&flags
, sizeof(uint32_t), bytes_written
, err
))
884 if (options_length
!= 0) {
885 /* write end of options */
886 option
.type
= OPT_ENDOFOPT
;
887 option
.value_length
= 0;
888 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
892 return write_to_file(pfile
, (const uint8_t*)&block_total_length
, sizeof(uint32_t), bytes_written
, err
);
896 pcapng_write_interface_statistics_block(pcapio_writer
* pfile
,
897 uint32_t interface_id
,
898 uint64_t *bytes_written
,
899 const char *comment
, /* OPT_COMMENT 1 */
900 uint64_t isb_starttime
, /* ISB_STARTTIME 2 */
901 uint64_t isb_endtime
, /* ISB_ENDTIME 3 */
902 uint64_t isb_ifrecv
, /* ISB_IFRECV 4 */
903 uint64_t isb_ifdrop
, /* ISB_IFDROP 5 */
912 struct ws_option option
;
913 uint32_t block_total_length
;
914 uint32_t options_length
;
919 * Current time, represented as 100-nanosecond intervals since
920 * January 1, 1601, 00:00:00 UTC.
922 * I think DWORD might be signed, so cast both parts of "now"
923 * to uint32_t so that the sign bit doesn't get treated specially.
925 * Windows 8 provides GetSystemTimePreciseAsFileTime which we
926 * might want to use instead.
928 GetSystemTimeAsFileTime(&now
);
929 timestamp
= (((uint64_t)(uint32_t)now
.dwHighDateTime
) << 32) +
930 (uint32_t)now
.dwLowDateTime
;
933 * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
939 * Subtract difference, in microseconds, between January 1, 1601
940 * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
942 timestamp
-= EPOCH_DELTA_1601_01_01_00_00_00_UTC
*1000000;
945 * Current time, represented as seconds and microseconds since
946 * January 1, 1970, 00:00:00 UTC.
948 gettimeofday(&now
, NULL
);
951 * Convert to delta in microseconds.
953 timestamp
= (uint64_t)(now
.tv_sec
) * 1000000 +
954 (uint64_t)(now
.tv_usec
);
956 block_total_length
= (uint32_t)(sizeof(struct isb
) + sizeof(uint32_t));
958 if (isb_ifrecv
!= UINT64_MAX
) {
959 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
962 if (isb_ifdrop
!= UINT64_MAX
) {
963 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
967 options_length
+= pcapng_count_string_option(comment
);
968 if (isb_starttime
!=0) {
969 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
970 sizeof(uint64_t)); /* ISB_STARTTIME */
972 if (isb_endtime
!=0) {
973 options_length
+= (uint32_t)(sizeof(struct ws_option
) +
974 sizeof(uint64_t)); /* ISB_ENDTIME */
976 /* If we have options add size of end-of-options */
977 if (options_length
!= 0) {
978 options_length
+= (uint32_t)sizeof(struct ws_option
);
980 block_total_length
+= options_length
;
982 isb
.block_type
= INTERFACE_STATISTICS_BLOCK_TYPE
;
983 isb
.block_total_length
= block_total_length
;
984 isb
.interface_id
= interface_id
;
985 isb
.timestamp_high
= (uint32_t)((timestamp
>>32) & 0xffffffff);
986 isb
.timestamp_low
= (uint32_t)(timestamp
& 0xffffffff);
987 if (!write_to_file(pfile
, (const uint8_t*)&isb
, sizeof(struct isb
), bytes_written
, err
))
990 /* write comment string if applicable */
991 if (!pcapng_write_string_option(pfile
, OPT_COMMENT
, comment
,
995 if (isb_starttime
!=0) {
998 option
.type
= ISB_STARTTIME
;
999 option
.value_length
= sizeof(uint64_t);
1000 high
= (uint32_t)((isb_starttime
>>32) & 0xffffffff);
1001 low
= (uint32_t)(isb_starttime
& 0xffffffff);
1002 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
1005 if (!write_to_file(pfile
, (const uint8_t*)&high
, sizeof(uint32_t), bytes_written
, err
))
1008 if (!write_to_file(pfile
, (const uint8_t*)&low
, sizeof(uint32_t), bytes_written
, err
))
1011 if (isb_endtime
!=0) {
1014 option
.type
= ISB_ENDTIME
;
1015 option
.value_length
= sizeof(uint64_t);
1016 high
= (uint32_t)((isb_endtime
>>32) & 0xffffffff);
1017 low
= (uint32_t)(isb_endtime
& 0xffffffff);
1018 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
1021 if (!write_to_file(pfile
, (const uint8_t*)&high
, sizeof(uint32_t), bytes_written
, err
))
1024 if (!write_to_file(pfile
, (const uint8_t*)&low
, sizeof(uint32_t), bytes_written
, err
))
1027 if (isb_ifrecv
!= UINT64_MAX
) {
1028 option
.type
= ISB_IFRECV
;
1029 option
.value_length
= sizeof(uint64_t);
1030 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
1033 if (!write_to_file(pfile
, (const uint8_t*)&isb_ifrecv
, sizeof(uint64_t), bytes_written
, err
))
1036 if (isb_ifdrop
!= UINT64_MAX
) {
1037 option
.type
= ISB_IFDROP
;
1038 option
.value_length
= sizeof(uint64_t);
1039 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
1042 if (!write_to_file(pfile
, (const uint8_t*)&isb_ifdrop
, sizeof(uint64_t), bytes_written
, err
))
1045 if (options_length
!= 0) {
1046 /* write end of options */
1047 option
.type
= OPT_ENDOFOPT
;
1048 option
.value_length
= 0;
1049 if (!write_to_file(pfile
, (const uint8_t*)&option
, sizeof(struct ws_option
), bytes_written
, err
))
1053 return write_to_file(pfile
, (const uint8_t*)&block_total_length
, sizeof(uint32_t), bytes_written
, err
);