Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / writecap / pcapio.c
blobb681902d8e07ff29dbf039a61db9da2fb64f398d
1 /* pcapio.c
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
6 * provides that, but
8 * 1) earlier versions of libpcap doesn't have it
10 * and
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
29 #include <config.h>
31 #include <stdbool.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <errno.h>
36 #include <string.h>
37 #ifdef HAVE_SYS_TIME_H
38 #include <sys/time.h>
39 #endif
40 #ifdef _WIN32
41 #include <windows.h>
42 #endif
44 #include <glib.h>
46 #include <wsutil/epochs.h>
47 #include <wsutil/file_util.h>
49 #include "pcapio.h"
50 #include <wiretap/file_wrappers.h>
52 typedef void* WFILE_T;
54 struct pcapio_writer {
55 WFILE_T fh;
56 char* io_buffer;
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. */
78 struct pcap_hdr {
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. */
89 struct pcaprec_hdr {
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
107 the file format. */
108 #define PCAPNG_MAJOR_VERSION 1
109 #define PCAPNG_MINOR_VERSION 0
111 /* Section Header Block without options and trailing Block Total Length */
112 struct shb {
113 uint32_t block_type;
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 */
123 struct idb {
124 uint32_t block_type;
125 uint32_t block_total_length;
126 uint16_t link_type;
127 uint16_t reserved;
128 uint32_t snap_len;
130 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
132 /* Interface Statistics Block without actual packet, options, and trailing
133 Block Total Length */
134 struct isb {
135 uint32_t block_type;
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 */
145 struct epb {
146 uint32_t block_type;
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;
152 uint32_t packet_len;
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
156 struct ws_option {
157 uint16_t type;
158 uint16_t value_length;
160 #define OPT_ENDOFOPT 0
161 #define OPT_COMMENT 1
162 #define EPB_FLAGS 2
163 #define SHB_HARDWARE 2 /* currently not used */
164 #define SHB_OS 3
165 #define SHB_USERAPPL 4
166 #define IDB_NAME 2
167 #define IDB_DESCRIPTION 3
168 #define IDB_IF_SPEED 8
169 #define IDB_TSRESOL 9
170 #define IDB_FILTER 11
171 #define IDB_OS 12
172 #define IDB_HARDWARE 15
173 #define ISB_STARTTIME 2
174 #define ISB_ENDTIME 3
175 #define ISB_IFRECV 4
176 #define ISB_IFDROP 5
177 #define ISB_FILTERACCEPT 6
178 #define ISB_OSDROP 7
179 #define ISB_USRDELIV 8
180 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
182 static WFILE_T
183 writecap_file_open(pcapio_writer* pfile, const char *filename)
185 WFILE_T fh;
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 */
195 default:
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.
200 if (fh != NULL) {
201 size_t buffsize = IO_BUF_SIZE;
202 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
203 ws_statb64 statb;
205 if (ws_stat64(filename, &statb) == 0) {
206 if (statb.st_blksize > IO_BUF_SIZE) {
207 buffsize = statb.st_blksize;
210 #endif
211 pfile->io_buffer = (char *)g_malloc(buffsize);
212 setvbuf(fh, pfile->io_buffer, _IOFBF, buffsize);
213 //ws_debug("buffsize %zu", buffsize);
215 return fh;
219 static WFILE_T
220 writecap_file_fdopen(pcapio_writer* pfile, int fd)
222 WFILE_T fh;
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 */
232 default:
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.
237 if (fh != NULL) {
238 size_t buffsize = IO_BUF_SIZE;
239 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
240 ws_statb64 statb;
242 if (ws_fstat64(fd, &statb) == 0) {
243 if (statb.st_blksize > IO_BUF_SIZE) {
244 buffsize = statb.st_blksize;
247 #endif
248 pfile->io_buffer = (char *)g_malloc(buffsize);
249 setvbuf(fh, pfile->io_buffer, _IOFBF, buffsize);
250 //ws_debug("buffsize %zu", buffsize);
252 return fh;
256 pcapio_writer*
257 writecap_fopen(const char *filename, wtap_compression_type ctype, int *err)
259 pcapio_writer* pfile;
260 *err = 0;
262 pfile = g_new0(struct pcapio_writer, 1);
263 if (pfile == NULL) {
264 *err = errno;
265 return NULL;
267 pfile->ctype = ctype;
268 errno = WTAP_ERR_CANT_OPEN;
269 void* fh = writecap_file_open(pfile, filename);
270 if (fh == NULL) {
271 *err = errno;
272 g_free(pfile);
273 return NULL;
276 pfile->fh = fh;
277 return pfile;
280 pcapio_writer*
281 writecap_fdopen(int fd, wtap_compression_type ctype, int *err)
283 pcapio_writer* pfile;
284 *err = 0;
286 pfile = g_new0(struct pcapio_writer, 1);
287 if (pfile == NULL) {
288 *err = errno;
289 return NULL;
291 pfile->ctype = ctype;
292 errno = WTAP_ERR_CANT_OPEN;
293 WFILE_T fh = writecap_file_fdopen(pfile, fd);
294 if (fh == NULL) {
295 *err = errno;
296 g_free(pfile);
297 return NULL;
300 pfile->fh = fh;
301 return pfile;
304 pcapio_writer*
305 writecap_open_stdout(wtap_compression_type ctype, int *err)
307 int new_fd;
308 pcapio_writer* pfile;
310 new_fd = ws_dup(1);
311 if (new_fd == -1) {
312 *err = errno;
313 return NULL;
315 #ifdef _WIN32
317 * Put the new descriptor into binary mode.
319 * XXX - even if the file format we're writing is a text
320 * format?
322 if (_setmode(new_fd, O_BINARY) == -1) {
323 /* "Should not happen" */
324 *err = errno;
325 ws_close(new_fd);
326 return NULL;
328 #endif
330 pfile = writecap_fdopen(new_fd, ctype, err);
331 if (pfile == NULL) {
332 /* Failed; close the new fd */
333 ws_close(new_fd);
334 return NULL;
336 return pfile;
339 bool
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) {
346 if (err) {
347 *err = gzwfile_geterr((GZWFILE_T)pfile->fh);
349 return false;
351 break;
352 #endif
353 #ifdef HAVE_LZ4FRAME_H
354 case WTAP_LZ4_COMPRESSED:
355 if (lz4wfile_flush((LZ4WFILE_T)pfile->fh) == -1) {
356 if (err) {
357 *err = lz4wfile_geterr((LZ4WFILE_T)pfile->fh);
359 return false;
361 break;
362 #endif /* HAVE_LZ4FRAME_H */
363 default:
364 if (fflush((FILE*)pfile->fh) == EOF) {
365 if (err) {
366 *err = errno;
368 return false;
371 return true;
374 bool
375 writecap_close(pcapio_writer* pfile, int *errp)
377 int err = 0;
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);
384 break;
385 #endif
386 #ifdef HAVE_LZ4FRAME_H
387 case WTAP_LZ4_COMPRESSED:
388 err = lz4wfile_close(pfile->fh);
389 break;
390 #endif /* HAVE_LZ4FRAME_H */
391 default:
392 if (fclose(pfile->fh) == EOF) {
393 err = errno;
397 g_free(pfile->io_buffer);
398 g_free(pfile);
399 if (errp) {
400 *errp = err;
402 return err == 0;
405 /* Write to capture file */
406 static bool
407 write_to_file(pcapio_writer* pfile, const uint8_t* data, size_t data_length,
408 uint64_t *bytes_written, int *err)
410 size_t nwritten;
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.
419 if (nwritten == 0) {
420 *err = gzwfile_geterr(pfile->fh);
421 return false;
423 break;
424 #endif
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.
431 if (nwritten == 0) {
432 *err = lz4wfile_geterr(pfile->fh);
433 return false;
435 break;
436 #endif /* HAVE_LZ4FRAME_H */
437 default:
438 nwritten = fwrite(data, data_length, 1, pfile->fh);
439 if (nwritten != 1) {
440 if (ferror(pfile->fh)) {
441 *err = errno;
442 } else {
443 *err = WTAP_ERR_SHORT_WRITE;
445 return false;
447 break;
450 (*bytes_written) += data_length;
451 return true;
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*/
459 bool
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. */
478 bool
479 libpcap_write_packet(pcapio_writer* pfile,
480 time_t sec, uint32_t usec,
481 uint32_t caplen, uint32_t len,
482 const uint8_t *pd,
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))
492 return false;
494 return write_to_file(pfile, pd, caplen, bytes_written, err);
497 /* Writing pcapng files */
499 static uint32_t
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 */
510 static bool
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))
528 return false;
530 if (!write_to_file(pfile, (const uint8_t*)option_value, (int) option_value_length, bytes_written, err))
531 return false;
533 if (option_value_length % 4) {
534 if (!write_to_file(pfile, (const uint8_t*)&padding, 4 - option_value_length % 4, bytes_written, err))
535 return false;
538 return true;
541 /* Write a pre-formatted pcapng block directly to the output file */
542 bool
543 pcapng_write_block(pcapio_writer* pfile,
544 const uint8_t *data,
545 uint32_t length,
546 uint64_t *bytes_written,
547 int *err)
549 uint32_t block_length, end_length;
550 /* Check
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)) {
559 *err = EINVAL;
560 return false;
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) {
565 *err = EBADMSG;
566 return false;
568 return write_to_file(pfile, data, length, bytes_written, err);
571 bool
572 pcapng_write_section_header_block(pcapio_writer* pfile,
573 GPtrArray *comments,
574 const char *hw,
575 const char *os,
576 const char *appname,
577 uint64_t section_length,
578 uint64_t *bytes_written,
579 int *err)
581 struct shb shb;
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);
588 options_length = 0;
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))
612 return false;
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),
618 bytes_written, err))
619 return false;
622 if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw,
623 bytes_written, err))
624 return false;
625 if (!pcapng_write_string_option(pfile, SHB_OS, os,
626 bytes_written, err))
627 return false;
628 if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname,
629 bytes_written, err))
630 return false;
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))
636 return false;
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);
643 bool
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 */
651 int link_type,
652 int snap_len,
653 uint64_t *bytes_written,
654 uint64_t if_speed, /* IDB_IF_SPEED 8 */
655 uint8_t tsresol, /* IDB_TSRESOL 9 */
656 int *err)
658 struct idb idb;
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));
665 options_length = 0;
666 /* 01 - OPT_COMMENT */
667 options_length += pcapng_count_string_option(comment);
669 /* 02 - IDB_NAME */
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 */
676 if (if_speed != 0) {
677 options_length += (uint32_t)(sizeof(struct ws_option) +
678 sizeof(uint64_t));
681 /* 09 - IDB_TSRESOL */
682 if (tsresol != 0) {
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)));
694 /* 12 - IDB_OS */
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;
710 idb.reserved = 0;
711 idb.snap_len = snap_len;
712 if (!write_to_file(pfile, (const uint8_t*)&idb, sizeof(struct idb), bytes_written, err))
713 return false;
715 /* 01 - OPT_COMMENT - write comment string if applicable */
716 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
717 bytes_written, err))
718 return false;
720 /* 02 - IDB_NAME - write interface name string if applicable */
721 if (!pcapng_write_string_option(pfile, IDB_NAME, name,
722 bytes_written, err))
723 return false;
725 /* 03 - IDB_DESCRIPTION */
726 /* write interface description string if applicable */
727 if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr,
728 bytes_written, err))
729 return false;
731 /* 08 - IDB_IF_SPEED */
732 if (if_speed != 0) {
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))
737 return false;
739 if (!write_to_file(pfile, (const uint8_t*)&if_speed, sizeof(uint64_t), bytes_written, err))
740 return false;
743 /* 09 - IDB_TSRESOL */
744 if (tsresol != 0) {
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))
749 return false;
751 if (!write_to_file(pfile, (const uint8_t*)&tsresol, sizeof(uint8_t), bytes_written, err))
752 return false;
754 if (!write_to_file(pfile, (const uint8_t*)&padding, 3, bytes_written, err))
755 return false;
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))
766 return false;
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))
770 return false;
771 if (!write_to_file(pfile, (const uint8_t*)filter, (int) strlen(filter), bytes_written, err))
772 return false;
773 if ((strlen(filter) + 1) % 4) {
774 if (!write_to_file(pfile, (const uint8_t*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
775 return false;
779 /* 12 - IDB_OS - write os string if applicable */
780 if (!pcapng_write_string_option(pfile, IDB_OS, os,
781 bytes_written, err))
782 return false;
784 /* 15 - IDB_HARDWARE - write hardware string if applicable */
785 if (!pcapng_write_string_option(pfile, IDB_HARDWARE, hardware,
786 bytes_written, err))
787 return false;
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))
794 return false;
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. */
803 bool
804 pcapng_write_enhanced_packet_block(pcapio_writer* pfile,
805 const char *comment,
806 time_t sec, uint32_t usec,
807 uint32_t caplen, uint32_t len,
808 uint32_t interface_id,
809 unsigned ts_mul,
810 const uint8_t *pd,
811 uint32_t flags,
812 uint64_t *bytes_written,
813 int *err)
815 struct epb epb;
816 struct ws_option option;
817 uint32_t block_total_length;
818 uint64_t timestamp;
819 uint32_t options_length;
820 const uint32_t padding = 0;
821 uint8_t buff[8];
822 uint8_t i;
823 uint8_t pad_len = 0;
825 block_total_length = (uint32_t)(sizeof(struct epb) +
826 ADD_PADDING(caplen) +
827 sizeof(uint32_t));
828 options_length = 0;
829 options_length += pcapng_count_string_option(comment);
830 if (flags != 0) {
831 options_length += (uint32_t)(sizeof(struct ws_option) +
832 sizeof(uint32_t));
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))
848 return false;
849 if (!write_to_file(pfile, pd, caplen, bytes_written, err))
850 return false;
851 /* Use more efficient write in case of no "extras" */
852 if(caplen % 4) {
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++) {
862 buff[i] = 0;
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);
869 if (pad_len) {
870 if (!write_to_file(pfile, (const uint8_t*)&padding, pad_len, bytes_written, err))
871 return false;
873 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
874 bytes_written, err))
875 return false;
876 if (flags != 0) {
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))
880 return false;
881 if (!write_to_file(pfile, (const uint8_t*)&flags, sizeof(uint32_t), bytes_written, err))
882 return false;
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))
889 return false;
892 return write_to_file(pfile, (const uint8_t*)&block_total_length, sizeof(uint32_t), bytes_written, err);
895 bool
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 */
904 int *err)
906 struct isb isb;
907 #ifdef _WIN32
908 FILETIME now;
909 #else
910 struct timeval now;
911 #endif
912 struct ws_option option;
913 uint32_t block_total_length;
914 uint32_t options_length;
915 uint64_t timestamp;
917 #ifdef _WIN32
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,
934 * intervals.
936 timestamp /= 10;
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;
943 #else
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);
955 #endif
956 block_total_length = (uint32_t)(sizeof(struct isb) + sizeof(uint32_t));
957 options_length = 0;
958 if (isb_ifrecv != UINT64_MAX) {
959 options_length += (uint32_t)(sizeof(struct ws_option) +
960 sizeof(uint64_t));
962 if (isb_ifdrop != UINT64_MAX) {
963 options_length += (uint32_t)(sizeof(struct ws_option) +
964 sizeof(uint64_t));
966 /* OPT_COMMENT */
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))
988 return false;
990 /* write comment string if applicable */
991 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
992 bytes_written, err))
993 return false;
995 if (isb_starttime !=0) {
996 uint32_t high, low;
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))
1003 return false;
1005 if (!write_to_file(pfile, (const uint8_t*)&high, sizeof(uint32_t), bytes_written, err))
1006 return false;
1008 if (!write_to_file(pfile, (const uint8_t*)&low, sizeof(uint32_t), bytes_written, err))
1009 return false;
1011 if (isb_endtime !=0) {
1012 uint32_t high, low;
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))
1019 return false;
1021 if (!write_to_file(pfile, (const uint8_t*)&high, sizeof(uint32_t), bytes_written, err))
1022 return false;
1024 if (!write_to_file(pfile, (const uint8_t*)&low, sizeof(uint32_t), bytes_written, err))
1025 return false;
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))
1031 return false;
1033 if (!write_to_file(pfile, (const uint8_t*)&isb_ifrecv, sizeof(uint64_t), bytes_written, err))
1034 return false;
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))
1040 return false;
1042 if (!write_to_file(pfile, (const uint8_t*)&isb_ifdrop, sizeof(uint64_t), bytes_written, err))
1043 return false;
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))
1050 return false;
1053 return write_to_file(pfile, (const uint8_t*)&block_total_length, sizeof(uint32_t), bytes_written, err);