Revert "TODO tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm \@VALUEREF\@"
[wireshark-sm.git] / writecap / pcapio.c
blobbdfb87ad82ab20e1d5b1c01b64d37b20cad39435
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>
48 #include "pcapio.h"
50 /* Magic numbers in "libpcap" files.
52 "libpcap" file records are written in the byte order of the host that
53 writes them, and the reader is expected to fix this up.
55 PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
56 is a byte-swapped version of that.
58 PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
59 which uses the same common file format as PCAP_MAGIC, but the
60 timestamps are saved in nanosecond resolution instead of microseconds.
61 PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
62 #define PCAP_MAGIC 0xa1b2c3d4
63 #define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
64 #define PCAP_NSEC_MAGIC 0xa1b23c4d
65 #define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1
67 /* "libpcap" file header. */
68 struct pcap_hdr {
69 uint32_t magic; /* magic number */
70 uint16_t version_major; /* major version number */
71 uint16_t version_minor; /* minor version number */
72 int32_t thiszone; /* GMT to local correction */
73 uint32_t sigfigs; /* accuracy of timestamps */
74 uint32_t snaplen; /* max length of captured packets, in octets */
75 uint32_t network; /* data link type */
78 /* "libpcap" record header. */
79 struct pcaprec_hdr {
80 uint32_t ts_sec; /* timestamp seconds */
81 uint32_t ts_usec; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
82 uint32_t incl_len; /* number of octets of packet saved in file */
83 uint32_t orig_len; /* actual length of packet */
86 /* Magic numbers in ".pcapng" files.
88 * .pcapng file records are written in the byte order of the host that
89 * writes them, and the reader is expected to fix this up.
90 * PCAPNG_MAGIC is the magic number, in host byte order;
91 * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that.
93 #define PCAPNG_MAGIC 0x1A2B3C4D
94 #define PCAPNG_SWAPPED_MAGIC 0x4D3C2B1A
96 /* Currently we are only supporting the initial version of
97 the file format. */
98 #define PCAPNG_MAJOR_VERSION 1
99 #define PCAPNG_MINOR_VERSION 0
101 /* Section Header Block without options and trailing Block Total Length */
102 struct shb {
103 uint32_t block_type;
104 uint32_t block_total_length;
105 uint32_t byte_order_magic;
106 uint16_t major_version;
107 uint16_t minor_version;
108 uint64_t section_length;
110 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
112 /* Interface Description Block without options and trailing Block Total Length */
113 struct idb {
114 uint32_t block_type;
115 uint32_t block_total_length;
116 uint16_t link_type;
117 uint16_t reserved;
118 uint32_t snap_len;
120 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
122 /* Interface Statistics Block without actual packet, options, and trailing
123 Block Total Length */
124 struct isb {
125 uint32_t block_type;
126 uint32_t block_total_length;
127 uint32_t interface_id;
128 uint32_t timestamp_high;
129 uint32_t timestamp_low;
131 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
133 /* Enhanced Packet Block without actual packet, options, and trailing
134 Block Total Length */
135 struct epb {
136 uint32_t block_type;
137 uint32_t block_total_length;
138 uint32_t interface_id;
139 uint32_t timestamp_high;
140 uint32_t timestamp_low;
141 uint32_t captured_len;
142 uint32_t packet_len;
144 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
146 struct ws_option {
147 uint16_t type;
148 uint16_t value_length;
150 #define OPT_ENDOFOPT 0
151 #define OPT_COMMENT 1
152 #define EPB_FLAGS 2
153 #define SHB_HARDWARE 2 /* currently not used */
154 #define SHB_OS 3
155 #define SHB_USERAPPL 4
156 #define IDB_NAME 2
157 #define IDB_DESCRIPTION 3
158 #define IDB_IF_SPEED 8
159 #define IDB_TSRESOL 9
160 #define IDB_FILTER 11
161 #define IDB_OS 12
162 #define IDB_HARDWARE 15
163 #define ISB_STARTTIME 2
164 #define ISB_ENDTIME 3
165 #define ISB_IFRECV 4
166 #define ISB_IFDROP 5
167 #define ISB_FILTERACCEPT 6
168 #define ISB_OSDROP 7
169 #define ISB_USRDELIV 8
170 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
172 /* Write to capture file */
173 static bool
174 write_to_file(FILE* pfile, const uint8_t* data, size_t data_length,
175 uint64_t *bytes_written, int *err)
177 size_t nwritten;
179 nwritten = fwrite(data, data_length, 1, pfile);
180 if (nwritten != 1) {
181 if (ferror(pfile)) {
182 *err = errno;
183 } else {
184 *err = 0;
186 return false;
189 (*bytes_written) += data_length;
190 return true;
193 /* Writing pcap files */
195 /* Write the file header to a dump file.
196 Returns true on success, false on failure.
197 Sets "*err" to an error code, or 0 for a short write, on failure*/
198 bool
199 libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, bool ts_nsecs, uint64_t *bytes_written, int *err)
201 struct pcap_hdr file_hdr;
203 file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;
204 /* current "libpcap" format is 2.4 */
205 file_hdr.version_major = 2;
206 file_hdr.version_minor = 4;
207 file_hdr.thiszone = 0; /* XXX - current offset? */
208 file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
209 file_hdr.snaplen = snaplen;
210 file_hdr.network = linktype;
212 return write_to_file(pfile, (const uint8_t*)&file_hdr, sizeof(file_hdr), bytes_written, err);
215 /* Write a record for a packet to a dump file.
216 Returns true on success, false on failure. */
217 bool
218 libpcap_write_packet(FILE* pfile,
219 time_t sec, uint32_t usec,
220 uint32_t caplen, uint32_t len,
221 const uint8_t *pd,
222 uint64_t *bytes_written, int *err)
224 struct pcaprec_hdr rec_hdr;
226 rec_hdr.ts_sec = (uint32_t)sec; /* Y2.038K issue in pcap format.... */
227 rec_hdr.ts_usec = usec;
228 rec_hdr.incl_len = caplen;
229 rec_hdr.orig_len = len;
230 if (!write_to_file(pfile, (const uint8_t*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))
231 return false;
233 return write_to_file(pfile, pd, caplen, bytes_written, err);
236 /* Writing pcapng files */
238 static uint32_t
239 pcapng_count_string_option(const char *option_value)
241 if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < UINT16_MAX)) {
242 /* There's a value to write; get its length */
243 return (uint32_t)(sizeof(struct ws_option) +
244 (uint16_t)ADD_PADDING(strlen(option_value)));
246 return 0; /* nothing to write */
249 static bool
250 pcapng_write_string_option(FILE* pfile,
251 uint16_t option_type, const char *option_value,
252 uint64_t *bytes_written, int *err)
254 size_t option_value_length;
255 struct ws_option option;
256 const uint32_t padding = 0;
258 if (option_value == NULL)
259 return true; /* nothing to write */
260 option_value_length = strlen(option_value);
261 if ((option_value_length > 0) && (option_value_length < UINT16_MAX)) {
262 /* something to write */
263 option.type = option_type;
264 option.value_length = (uint16_t)option_value_length;
266 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
267 return false;
269 if (!write_to_file(pfile, (const uint8_t*)option_value, (int) option_value_length, bytes_written, err))
270 return false;
272 if (option_value_length % 4) {
273 if (!write_to_file(pfile, (const uint8_t*)&padding, 4 - option_value_length % 4, bytes_written, err))
274 return false;
277 return true;
280 /* Write a pre-formatted pcapng block directly to the output file */
281 bool
282 pcapng_write_block(FILE* pfile,
283 const uint8_t *data,
284 uint32_t length,
285 uint64_t *bytes_written,
286 int *err)
288 uint32_t block_length, end_length;
289 /* Check
290 * - length and data are aligned to 4 bytes
291 * - block_total_length field is the same at the start and end of the block
293 * The block_total_length is not checked against the provided length but
294 * getting the trailing block_total_length from the length argument gives
295 * us an implicit check of correctness without needing to do an endian swap
297 if (((length & 3) != 0) || (((intptr_t)data & 3) != 0)) {
298 *err = EINVAL;
299 return false;
301 block_length = *(const uint32_t *) (data+sizeof(uint32_t));
302 end_length = *(const uint32_t *) (data+length-sizeof(uint32_t));
303 if (block_length != end_length) {
304 *err = EBADMSG;
305 return false;
307 return write_to_file(pfile, data, length, bytes_written, err);
310 bool
311 pcapng_write_section_header_block(FILE* pfile,
312 GPtrArray *comments,
313 const char *hw,
314 const char *os,
315 const char *appname,
316 uint64_t section_length,
317 uint64_t *bytes_written,
318 int *err)
320 struct shb shb;
321 struct ws_option option;
322 uint32_t block_total_length;
323 uint32_t options_length;
325 /* Size of base header */
326 block_total_length = sizeof(struct shb) +
327 sizeof(uint32_t);
328 options_length = 0;
329 if (comments != NULL) {
330 for (unsigned i = 0; i < comments->len; i++) {
331 options_length += pcapng_count_string_option((char *)g_ptr_array_index(comments, i));
334 options_length += pcapng_count_string_option(hw);
335 options_length += pcapng_count_string_option(os);
336 options_length += pcapng_count_string_option(appname);
337 /* If we have options add size of end-of-options */
338 if (options_length != 0) {
339 options_length += (uint32_t)sizeof(struct ws_option);
341 block_total_length += options_length;
343 /* write shb header */
344 shb.block_type = SECTION_HEADER_BLOCK_TYPE;
345 shb.block_total_length = block_total_length;
346 shb.byte_order_magic = PCAPNG_MAGIC;
347 shb.major_version = PCAPNG_MAJOR_VERSION;
348 shb.minor_version = PCAPNG_MINOR_VERSION;
349 shb.section_length = section_length;
351 if (!write_to_file(pfile, (const uint8_t*)&shb, sizeof(struct shb), bytes_written, err))
352 return false;
354 if (comments != NULL) {
355 for (unsigned i = 0; i < comments->len; i++) {
356 if (!pcapng_write_string_option(pfile, OPT_COMMENT,
357 (char *)g_ptr_array_index(comments, i),
358 bytes_written, err))
359 return false;
362 if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw,
363 bytes_written, err))
364 return false;
365 if (!pcapng_write_string_option(pfile, SHB_OS, os,
366 bytes_written, err))
367 return false;
368 if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname,
369 bytes_written, err))
370 return false;
371 if (options_length != 0) {
372 /* write end of options */
373 option.type = OPT_ENDOFOPT;
374 option.value_length = 0;
375 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
376 return false;
379 /* write the trailing block total length */
380 return write_to_file(pfile, (const uint8_t*)&block_total_length, sizeof(uint32_t), bytes_written, err);
383 bool
384 pcapng_write_interface_description_block(FILE* pfile,
385 const char *comment, /* OPT_COMMENT 1 */
386 const char *name, /* IDB_NAME 2 */
387 const char *descr, /* IDB_DESCRIPTION 3 */
388 const char *filter, /* IDB_FILTER 11 */
389 const char *os, /* IDB_OS 12 */
390 const char *hardware, /* IDB_HARDWARE 15 */
391 int link_type,
392 int snap_len,
393 uint64_t *bytes_written,
394 uint64_t if_speed, /* IDB_IF_SPEED 8 */
395 uint8_t tsresol, /* IDB_TSRESOL 9 */
396 int *err)
398 struct idb idb;
399 struct ws_option option;
400 uint32_t block_total_length;
401 uint32_t options_length;
402 const uint32_t padding = 0;
404 block_total_length = (uint32_t)(sizeof(struct idb) + sizeof(uint32_t));
405 options_length = 0;
406 /* 01 - OPT_COMMENT */
407 options_length += pcapng_count_string_option(comment);
409 /* 02 - IDB_NAME */
410 options_length += pcapng_count_string_option(name);
412 /* 03 - IDB_DESCRIPTION */
413 options_length += pcapng_count_string_option(descr);
415 /* 08 - IDB_IF_SPEED */
416 if (if_speed != 0) {
417 options_length += (uint32_t)(sizeof(struct ws_option) +
418 sizeof(uint64_t));
421 /* 09 - IDB_TSRESOL */
422 if (tsresol != 0) {
423 options_length += (uint32_t)(sizeof(struct ws_option) +
424 sizeof(struct ws_option));
427 /* 11 - IDB_FILTER */
428 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < UINT16_MAX - 1)) {
429 /* No, this isn't a string, it has an extra type byte */
430 options_length += (uint32_t)(sizeof(struct ws_option) +
431 (uint16_t)(ADD_PADDING(strlen(filter)+ 1)));
434 /* 12 - IDB_OS */
435 options_length += pcapng_count_string_option(os);
437 /* 15 - IDB_HARDWARE */
438 options_length += pcapng_count_string_option(hardware);
440 /* If we have options add size of end-of-options */
441 if (options_length != 0) {
442 options_length += (uint32_t)sizeof(struct ws_option);
444 block_total_length += options_length;
446 /* write block header */
447 idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
448 idb.block_total_length = block_total_length;
449 idb.link_type = link_type;
450 idb.reserved = 0;
451 idb.snap_len = snap_len;
452 if (!write_to_file(pfile, (const uint8_t*)&idb, sizeof(struct idb), bytes_written, err))
453 return false;
455 /* 01 - OPT_COMMENT - write comment string if applicable */
456 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
457 bytes_written, err))
458 return false;
460 /* 02 - IDB_NAME - write interface name string if applicable */
461 if (!pcapng_write_string_option(pfile, IDB_NAME, name,
462 bytes_written, err))
463 return false;
465 /* 03 - IDB_DESCRIPTION */
466 /* write interface description string if applicable */
467 if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr,
468 bytes_written, err))
469 return false;
471 /* 08 - IDB_IF_SPEED */
472 if (if_speed != 0) {
473 option.type = IDB_IF_SPEED;
474 option.value_length = sizeof(uint64_t);
476 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
477 return false;
479 if (!write_to_file(pfile, (const uint8_t*)&if_speed, sizeof(uint64_t), bytes_written, err))
480 return false;
483 /* 09 - IDB_TSRESOL */
484 if (tsresol != 0) {
485 option.type = IDB_TSRESOL;
486 option.value_length = sizeof(uint8_t);
488 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
489 return false;
491 if (!write_to_file(pfile, (const uint8_t*)&tsresol, sizeof(uint8_t), bytes_written, err))
492 return false;
494 if (!write_to_file(pfile, (const uint8_t*)&padding, 3, bytes_written, err))
495 return false;
498 /* 11 - IDB_FILTER - write filter string if applicable
499 * We write out the libpcap filter expression, not the
500 * generated BPF code.
502 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < UINT16_MAX - 1)) {
503 option.type = IDB_FILTER;
504 option.value_length = (uint16_t)(strlen(filter) + 1 );
505 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
506 return false;
508 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
509 if (!write_to_file(pfile, (const uint8_t*)&padding, 1, bytes_written, err))
510 return false;
511 if (!write_to_file(pfile, (const uint8_t*)filter, (int) strlen(filter), bytes_written, err))
512 return false;
513 if ((strlen(filter) + 1) % 4) {
514 if (!write_to_file(pfile, (const uint8_t*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
515 return false;
519 /* 12 - IDB_OS - write os string if applicable */
520 if (!pcapng_write_string_option(pfile, IDB_OS, os,
521 bytes_written, err))
522 return false;
524 /* 15 - IDB_HARDWARE - write hardware string if applicable */
525 if (!pcapng_write_string_option(pfile, IDB_HARDWARE, hardware,
526 bytes_written, err))
527 return false;
529 if (options_length != 0) {
530 /* write end of options */
531 option.type = OPT_ENDOFOPT;
532 option.value_length = 0;
533 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
534 return false;
537 /* write the trailing Block Total Length */
538 return write_to_file(pfile, (const uint8_t*)&block_total_length, sizeof(uint32_t), bytes_written, err);
541 /* Write a record for a packet to a dump file.
542 Returns true on success, false on failure. */
543 bool
544 pcapng_write_enhanced_packet_block(FILE* pfile,
545 const char *comment,
546 time_t sec, uint32_t usec,
547 uint32_t caplen, uint32_t len,
548 uint32_t interface_id,
549 unsigned ts_mul,
550 const uint8_t *pd,
551 uint32_t flags,
552 uint64_t *bytes_written,
553 int *err)
555 struct epb epb;
556 struct ws_option option;
557 uint32_t block_total_length;
558 uint64_t timestamp;
559 uint32_t options_length;
560 const uint32_t padding = 0;
561 uint8_t buff[8];
562 uint8_t i;
563 uint8_t pad_len = 0;
565 block_total_length = (uint32_t)(sizeof(struct epb) +
566 ADD_PADDING(caplen) +
567 sizeof(uint32_t));
568 options_length = 0;
569 options_length += pcapng_count_string_option(comment);
570 if (flags != 0) {
571 options_length += (uint32_t)(sizeof(struct ws_option) +
572 sizeof(uint32_t));
574 /* If we have options add size of end-of-options */
575 if (options_length != 0) {
576 options_length += (uint32_t)sizeof(struct ws_option);
578 block_total_length += options_length;
579 timestamp = (uint64_t)sec * ts_mul + (uint64_t)usec;
580 epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
581 epb.block_total_length = block_total_length;
582 epb.interface_id = interface_id;
583 epb.timestamp_high = (uint32_t)((timestamp>>32) & 0xffffffff);
584 epb.timestamp_low = (uint32_t)(timestamp & 0xffffffff);
585 epb.captured_len = caplen;
586 epb.packet_len = len;
587 if (!write_to_file(pfile, (const uint8_t*)&epb, sizeof(struct epb), bytes_written, err))
588 return false;
589 if (!write_to_file(pfile, pd, caplen, bytes_written, err))
590 return false;
591 /* Use more efficient write in case of no "extras" */
592 if(caplen % 4) {
593 pad_len = 4 - (caplen % 4);
596 * If we have no options to write, just write out the padding and
597 * the block total length with one fwrite() call.
599 if(!comment && flags == 0 && options_length==0){
600 /* Put padding in the buffer */
601 for (i = 0; i < pad_len; i++) {
602 buff[i] = 0;
604 /* Write the total length */
605 memcpy(&buff[i], &block_total_length, sizeof(uint32_t));
606 i += sizeof(uint32_t);
607 return write_to_file(pfile, (const uint8_t*)&buff, i, bytes_written, err);
609 if (pad_len) {
610 if (!write_to_file(pfile, (const uint8_t*)&padding, pad_len, bytes_written, err))
611 return false;
613 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
614 bytes_written, err))
615 return false;
616 if (flags != 0) {
617 option.type = EPB_FLAGS;
618 option.value_length = sizeof(uint32_t);
619 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
620 return false;
621 if (!write_to_file(pfile, (const uint8_t*)&flags, sizeof(uint32_t), bytes_written, err))
622 return false;
624 if (options_length != 0) {
625 /* write end of options */
626 option.type = OPT_ENDOFOPT;
627 option.value_length = 0;
628 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
629 return false;
632 return write_to_file(pfile, (const uint8_t*)&block_total_length, sizeof(uint32_t), bytes_written, err);
635 bool
636 pcapng_write_interface_statistics_block(FILE* pfile,
637 uint32_t interface_id,
638 uint64_t *bytes_written,
639 const char *comment, /* OPT_COMMENT 1 */
640 uint64_t isb_starttime, /* ISB_STARTTIME 2 */
641 uint64_t isb_endtime, /* ISB_ENDTIME 3 */
642 uint64_t isb_ifrecv, /* ISB_IFRECV 4 */
643 uint64_t isb_ifdrop, /* ISB_IFDROP 5 */
644 int *err)
646 struct isb isb;
647 #ifdef _WIN32
648 FILETIME now;
649 #else
650 struct timeval now;
651 #endif
652 struct ws_option option;
653 uint32_t block_total_length;
654 uint32_t options_length;
655 uint64_t timestamp;
657 #ifdef _WIN32
659 * Current time, represented as 100-nanosecond intervals since
660 * January 1, 1601, 00:00:00 UTC.
662 * I think DWORD might be signed, so cast both parts of "now"
663 * to uint32_t so that the sign bit doesn't get treated specially.
665 * Windows 8 provides GetSystemTimePreciseAsFileTime which we
666 * might want to use instead.
668 GetSystemTimeAsFileTime(&now);
669 timestamp = (((uint64_t)(uint32_t)now.dwHighDateTime) << 32) +
670 (uint32_t)now.dwLowDateTime;
673 * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
674 * intervals.
676 timestamp /= 10;
679 * Subtract difference, in microseconds, between January 1, 1601
680 * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
682 timestamp -= EPOCH_DELTA_1601_01_01_00_00_00_UTC*1000000;
683 #else
685 * Current time, represented as seconds and microseconds since
686 * January 1, 1970, 00:00:00 UTC.
688 gettimeofday(&now, NULL);
691 * Convert to delta in microseconds.
693 timestamp = (uint64_t)(now.tv_sec) * 1000000 +
694 (uint64_t)(now.tv_usec);
695 #endif
696 block_total_length = (uint32_t)(sizeof(struct isb) + sizeof(uint32_t));
697 options_length = 0;
698 if (isb_ifrecv != UINT64_MAX) {
699 options_length += (uint32_t)(sizeof(struct ws_option) +
700 sizeof(uint64_t));
702 if (isb_ifdrop != UINT64_MAX) {
703 options_length += (uint32_t)(sizeof(struct ws_option) +
704 sizeof(uint64_t));
706 /* OPT_COMMENT */
707 options_length += pcapng_count_string_option(comment);
708 if (isb_starttime !=0) {
709 options_length += (uint32_t)(sizeof(struct ws_option) +
710 sizeof(uint64_t)); /* ISB_STARTTIME */
712 if (isb_endtime !=0) {
713 options_length += (uint32_t)(sizeof(struct ws_option) +
714 sizeof(uint64_t)); /* ISB_ENDTIME */
716 /* If we have options add size of end-of-options */
717 if (options_length != 0) {
718 options_length += (uint32_t)sizeof(struct ws_option);
720 block_total_length += options_length;
722 isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
723 isb.block_total_length = block_total_length;
724 isb.interface_id = interface_id;
725 isb.timestamp_high = (uint32_t)((timestamp>>32) & 0xffffffff);
726 isb.timestamp_low = (uint32_t)(timestamp & 0xffffffff);
727 if (!write_to_file(pfile, (const uint8_t*)&isb, sizeof(struct isb), bytes_written, err))
728 return false;
730 /* write comment string if applicable */
731 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
732 bytes_written, err))
733 return false;
735 if (isb_starttime !=0) {
736 uint32_t high, low;
738 option.type = ISB_STARTTIME;
739 option.value_length = sizeof(uint64_t);
740 high = (uint32_t)((isb_starttime>>32) & 0xffffffff);
741 low = (uint32_t)(isb_starttime & 0xffffffff);
742 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
743 return false;
745 if (!write_to_file(pfile, (const uint8_t*)&high, sizeof(uint32_t), bytes_written, err))
746 return false;
748 if (!write_to_file(pfile, (const uint8_t*)&low, sizeof(uint32_t), bytes_written, err))
749 return false;
751 if (isb_endtime !=0) {
752 uint32_t high, low;
754 option.type = ISB_ENDTIME;
755 option.value_length = sizeof(uint64_t);
756 high = (uint32_t)((isb_endtime>>32) & 0xffffffff);
757 low = (uint32_t)(isb_endtime & 0xffffffff);
758 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
759 return false;
761 if (!write_to_file(pfile, (const uint8_t*)&high, sizeof(uint32_t), bytes_written, err))
762 return false;
764 if (!write_to_file(pfile, (const uint8_t*)&low, sizeof(uint32_t), bytes_written, err))
765 return false;
767 if (isb_ifrecv != UINT64_MAX) {
768 option.type = ISB_IFRECV;
769 option.value_length = sizeof(uint64_t);
770 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
771 return false;
773 if (!write_to_file(pfile, (const uint8_t*)&isb_ifrecv, sizeof(uint64_t), bytes_written, err))
774 return false;
776 if (isb_ifdrop != UINT64_MAX) {
777 option.type = ISB_IFDROP;
778 option.value_length = sizeof(uint64_t);
779 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
780 return false;
782 if (!write_to_file(pfile, (const uint8_t*)&isb_ifdrop, sizeof(uint64_t), bytes_written, err))
783 return false;
785 if (options_length != 0) {
786 /* write end of options */
787 option.type = OPT_ENDOFOPT;
788 option.value_length = 0;
789 if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
790 return false;
793 return write_to_file(pfile, (const uint8_t*)&block_total_length, sizeof(uint32_t), bytes_written, err);
797 * Editor modelines - https://www.wireshark.org/tools/modelines.html
799 * Local variables:
800 * c-basic-offset: 8
801 * tab-width: 8
802 * indent-tabs-mode: nil
803 * End:
805 * vi: set shiftwidth=8 tabstop=8 expandtab:
806 * :indentSize=8:tabSize=8:noTabs=true: