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 doesn'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.
21 * Wireshark - Network traffic analyzer
22 * By Gerald Combs <gerald@wireshark.org>
23 * Copyright 1998 Gerald Combs
25 * Derived from code in the Wiretap Library
26 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
28 * This program is free software; you can redistribute it and/or
29 * modify it under the terms of the GNU General Public License
30 * as published by the Free Software Foundation; either version 2
31 * of the License, or (at your option) any later version.
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
49 #ifdef HAVE_SYS_TIME_H
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 guint32 magic; /* magic number */
80 guint16 version_major; /* major version number */
81 guint16 version_minor; /* minor version number */
82 gint32 thiszone; /* GMT to local correction */
83 guint32 sigfigs; /* accuracy of timestamps */
84 guint32 snaplen; /* max length of captured packets, in octets */
85 guint32 network; /* data link type */
88 /* "libpcap" record header. */
90 guint32 ts_sec; /* timestamp seconds */
91 guint32 ts_usec; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
92 guint32 incl_len; /* number of octets of packet saved in file */
93 guint32 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 0xD4C3B2A1
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 guint32 block_total_length;
115 guint32 byte_order_magic;
116 guint16 major_version;
117 guint16 minor_version;
118 guint64 section_length;
120 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
122 /* Interface Decription Block without options and trailing Block Total Length */
125 guint32 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 guint32 block_total_length;
137 guint32 interface_id;
138 guint32 timestamp_high;
139 guint32 timestamp_low;
141 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
143 /* Enhanced Packet Block without actual packet, options, and trailing
144 Block Total Length */
147 guint32 block_total_length;
148 guint32 interface_id;
149 guint32 timestamp_high;
150 guint32 timestamp_low;
151 guint32 captured_len;
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
158 guint16 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 ISB_STARTTIME 2
173 #define ISB_ENDTIME 3
176 #define ISB_FILTERACCEPT 6
178 #define ISB_USRDELIV 8
179 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
181 /* Write libcap to file. write_data_info will be a FILE* */
182 gboolean libpcap_write_to_file(void* write_data_info,
185 guint64 *bytes_written,
189 FILE* pFile = (FILE*)write_data_info;
191 nwritten = fwrite(data, data_length, 1, pFile);
201 (*bytes_written) += data_length;
205 /* Write the file header to a dump file.
206 Returns TRUE on success, FALSE on failure.
207 Sets "*err" to an error code, or 0 for a short write, on failure*/
209 libpcap_write_file_header(libpcap_write_t write_func, void* write_data_info, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err)
211 struct pcap_hdr file_hdr;
213 file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;
214 /* current "libpcap" format is 2.4 */
215 file_hdr.version_major = 2;
216 file_hdr.version_minor = 4;
217 file_hdr.thiszone = 0; /* XXX - current offset? */
218 file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
219 file_hdr.snaplen = snaplen;
220 file_hdr.network = linktype;
222 return write_func(write_data_info, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);
225 /* Write a record for a packet to a dump file.
226 Returns TRUE on success, FALSE on failure. */
228 libpcap_write_packet(libpcap_write_t write_func, void* write_data_info,
229 time_t sec, guint32 usec,
230 guint32 caplen, guint32 len,
232 guint64 *bytes_written, int *err)
234 struct pcaprec_hdr rec_hdr;
236 rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */
237 rec_hdr.ts_usec = usec;
238 rec_hdr.incl_len = caplen;
239 rec_hdr.orig_len = len;
240 if (!write_func(write_data_info, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))
243 return write_func(write_data_info, pd, caplen, bytes_written, err);
247 libpcap_write_session_header_block(libpcap_write_t write_func, void* write_data_info,
252 guint64 section_length,
253 guint64 *bytes_written,
257 struct option option;
258 guint32 block_total_length;
259 const guint32 padding = 0;
260 gboolean have_options = FALSE;
262 /* Size of base header */
263 block_total_length = sizeof(struct shb) +
265 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
266 block_total_length += (guint32)(sizeof(struct option) +
267 (guint16)ADD_PADDING(strlen(comment)));
270 if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
271 block_total_length += (guint32)(sizeof(struct option) +
272 (guint16)ADD_PADDING(strlen(hw)));
275 if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
276 block_total_length += (guint32)(sizeof(struct option) +
277 (guint16)ADD_PADDING(strlen(os)));
280 if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
281 block_total_length += (guint32)(sizeof(struct option) +
282 (guint16)ADD_PADDING(strlen(appname)));
285 /* If we have options add size of end-of-options */
287 block_total_length += (guint32)sizeof(struct option);
289 /* write shb header */
290 shb.block_type = SECTION_HEADER_BLOCK_TYPE;
291 shb.block_total_length = block_total_length;
292 shb.byte_order_magic = PCAPNG_MAGIC;
293 shb.major_version = PCAPNG_MAJOR_VERSION;
294 shb.minor_version = PCAPNG_MINOR_VERSION;
295 shb.section_length = section_length;
297 if (!write_func(write_data_info, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
300 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
301 /* write opt_comment options */
302 option.type = OPT_COMMENT;
303 option.value_length = (guint16)strlen(comment);
305 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
308 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
311 if (strlen(comment) % 4) {
312 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
316 if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
317 /* write shb_hardware options */
318 option.type = SHB_HARDWARE;
319 option.value_length = (guint16)strlen(hw);
321 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
324 if (!write_func(write_data_info, (const guint8*)hw, (int) strlen(hw), bytes_written, err))
327 if ((strlen(hw) + 1) % 4) {
328 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(hw) % 4, bytes_written, err))
332 if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
333 /* write shb_os options */
334 option.type = SHB_OS;
335 option.value_length = (guint16)strlen(os);
337 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
340 if (!write_func(write_data_info, (const guint8*)os, (int) strlen(os), bytes_written, err))
343 if (strlen(os) % 4) {
344 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(os) % 4, bytes_written, err))
348 if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
349 /* write shb_userappl options */
350 option.type = SHB_USERAPPL;
351 option.value_length = (guint16)strlen(appname);
353 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
356 if (!write_func(write_data_info, (const guint8*)appname, (int) strlen(appname), bytes_written, err))
359 if (strlen(appname) % 4) {
360 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(appname) % 4, bytes_written, err))
365 /* write end of options */
366 option.type = OPT_ENDOFOPT;
367 option.value_length = 0;
368 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
372 /* write the trailing block total length */
373 return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
377 libpcap_write_interface_description_block(libpcap_write_t write_func, void* write_data_info,
378 const char *comment, /* OPT_COMMENT 1 */
379 const char *name, /* IDB_NAME 2 */
380 const char *descr, /* IDB_DESCRIPTION 3 */
381 const char *filter, /* IDB_FILTER 11 */
382 const char *os, /* IDB_OS 12 */
385 guint64 *bytes_written,
386 guint64 if_speed, /* IDB_IF_SPEED 8 */
387 guint8 tsresol, /* IDB_TSRESOL 9 */
391 struct option option;
392 guint32 block_total_length;
393 const guint32 padding = 0;
394 gboolean have_options = FALSE;
396 block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32));
397 /* 01 - OPT_COMMENT */
398 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
399 block_total_length += (guint32)(sizeof(struct option) +
400 (guint16)ADD_PADDING(strlen(comment)));
405 if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
406 block_total_length += (guint32)(sizeof(struct option) +
407 (guint16)ADD_PADDING(strlen(name)));
411 /* 03 - IDB_DESCRIPTION */
412 if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
413 block_total_length += (guint32)(sizeof(struct option) +
414 (guint16)ADD_PADDING(strlen(descr)));
418 /* 08 - IDB_IF_SPEED */
420 block_total_length += (guint32)(sizeof(struct option) +
425 /* 09 - IDB_TSRESOL */
427 block_total_length += (guint32)(sizeof(struct option) +
428 sizeof(struct option));
432 /* 11 - IDB_FILTER */
433 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
434 block_total_length += (guint32)(sizeof(struct option) +
435 (guint16)(ADD_PADDING(strlen(filter)+ 1)));
440 if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
441 block_total_length += (guint32)(sizeof(struct option) +
442 (guint16)ADD_PADDING(strlen(os)));
446 /* If we have options add size of end-of-options */
448 block_total_length += (guint32)sizeof(struct option);
451 /* write block header */
452 idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
453 idb.block_total_length = block_total_length;
454 idb.link_type = link_type;
456 idb.snap_len = snap_len;
457 if (!write_func(write_data_info, (const guint8*)&idb, sizeof(struct idb), bytes_written, err))
460 /* 01 - OPT_COMMENT - write comment string if applicable */
461 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
462 option.type = OPT_COMMENT;
463 option.value_length = (guint16)strlen(comment);
465 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
468 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
471 if (strlen(comment) % 4) {
472 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
477 /* 02 - IDB_NAME - write interface name string if applicable */
478 if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
479 option.type = IDB_NAME;
480 option.value_length = (guint16)strlen(name);
482 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
485 if (!write_func(write_data_info, (const guint8*)name, (int) strlen(name), bytes_written, err))
488 if (strlen(name) % 4) {
489 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(name) % 4, bytes_written, err))
494 /* 03 - IDB_DESCRIPTION */
495 /* write interface description string if applicable */
496 if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
497 option.type = IDB_DESCRIPTION;
498 option.value_length = (guint16)strlen(descr);
500 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
503 if (!write_func(write_data_info, (const guint8*)descr, (int) strlen(descr), bytes_written, err))
506 if (strlen(descr) % 4) {
507 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(descr) % 4, bytes_written, err))
512 /* 08 - IDB_IF_SPEED */
514 option.type = IDB_IF_SPEED;
515 option.value_length = sizeof(guint64);
517 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
520 if (!write_func(write_data_info, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))
524 /* 09 - IDB_TSRESOL */
526 option.type = IDB_TSRESOL;
527 option.value_length = sizeof(guint8);
529 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
532 if (!write_func(write_data_info, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))
535 if (!write_func(write_data_info, (const guint8*)&padding, 3, bytes_written, err))
539 /* 11 - IDB_FILTER - write filter string if applicable
540 * We only write version 1 of the filter, libpcap string
542 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
543 option.type = IDB_FILTER;
544 option.value_length = (guint16)(strlen(filter) + 1 );
545 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
548 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
549 if (!write_func(write_data_info, (const guint8*)&padding, 1, bytes_written, err))
551 if (!write_func(write_data_info, (const guint8*)filter, (int) strlen(filter), bytes_written, err))
553 if ((strlen(filter) + 1) % 4) {
554 if (!write_func(write_data_info, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
559 /* 12 - IDB_OS - write os string if applicable */
560 if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
561 option.type = IDB_OS;
562 option.value_length = (guint16)strlen(os);
563 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
565 if (!write_func(write_data_info, (const guint8*)os, (int) strlen(os), bytes_written, err))
567 if (strlen(os) % 4) {
568 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(os) % 4, bytes_written, err))
574 /* write end of options */
575 option.type = OPT_ENDOFOPT;
576 option.value_length = 0;
577 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
581 /* write the trailing Block Total Length */
582 return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
585 /* Write a record for a packet to a dump file.
586 Returns TRUE on success, FALSE on failure. */
588 libpcap_write_enhanced_packet_block(libpcap_write_t write_func, void* write_data_info,
590 time_t sec, guint32 usec,
591 guint32 caplen, guint32 len,
592 guint32 interface_id,
596 guint64 *bytes_written,
600 struct option option;
601 guint32 block_total_length;
603 gboolean have_options = FALSE;
604 const guint32 padding = 0;
606 block_total_length = (guint32)(sizeof(struct epb) +
607 ADD_PADDING(caplen) +
609 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
610 block_total_length += (guint32)(sizeof(struct option) +
611 (guint16)ADD_PADDING(strlen(comment)));
615 block_total_length += (guint32)(sizeof(struct option) +
619 /* If we have options add size of end-of-options */
621 block_total_length += (guint32)sizeof(struct option);
623 timestamp = (guint64)sec * ts_mul + (guint64)usec;
624 epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
625 epb.block_total_length = block_total_length;
626 epb.interface_id = interface_id;
627 epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
628 epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
629 epb.captured_len = caplen;
630 epb.packet_len = len;
631 if (!write_func(write_data_info, (const guint8*)&epb, sizeof(struct epb), bytes_written, err))
633 if (!write_func(write_data_info, pd, caplen, bytes_written, err))
636 if (!write_func(write_data_info, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err))
639 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
640 option.type = OPT_COMMENT;
641 option.value_length = (guint16)strlen(comment);
643 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
646 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
649 if (strlen(comment) % 4) {
650 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
655 option.type = EPB_FLAGS;
656 option.value_length = sizeof(guint32);
657 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
659 if (!write_func(write_data_info, (const guint8*)&flags, sizeof(guint32), bytes_written, err))
661 option.type = OPT_ENDOFOPT;
662 option.value_length = 0;
663 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
667 return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
671 libpcap_write_interface_statistics_block(libpcap_write_t write_func, void* write_data_info,
672 guint32 interface_id,
673 guint64 *bytes_written,
674 const char *comment, /* OPT_COMMENT 1 */
675 guint64 isb_starttime, /* ISB_STARTTIME 2 */
676 guint64 isb_endtime, /* ISB_ENDTIME 3 */
677 guint64 isb_ifrecv, /* ISB_IFRECV 4 */
678 guint64 isb_ifdrop, /* ISB_IFDROP 5 */
687 struct option option;
688 guint32 block_total_length;
690 gboolean have_options = FALSE;
691 const guint32 padding = 0;
694 * Current time, represented as 100-nanosecond intervals since
695 * January 1, 1601, 00:00:00 UTC.
697 * I think DWORD might be signed, so cast both parts of "now"
698 * to guint32 so that the sign bit doesn't get treated specially.
700 * Windows 8 provides GetSystemTimePreciseAsFileTime which we
701 * might want to use instead.
703 GetSystemTimeAsFileTime(&now);
704 timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
705 (guint32)now.dwLowDateTime;
708 * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
714 * Subtract difference, in microseconds, between January 1, 1601
715 * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
717 timestamp -= G_GINT64_CONSTANT(11644473600000000U);
720 * Current time, represented as seconds and microseconds since
721 * January 1, 1970, 00:00:00 UTC.
723 gettimeofday(&now, NULL);
726 * Convert to delta in microseconds.
728 timestamp = (guint64)(now.tv_sec) * 1000000 +
729 (guint64)(now.tv_usec);
731 block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));
732 if (isb_ifrecv != G_MAXUINT64) {
733 block_total_length += (guint32)(sizeof(struct option) +
737 if (isb_ifdrop != G_MAXUINT64) {
738 block_total_length += (guint32)(sizeof(struct option) +
743 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
744 block_total_length += (guint32)(sizeof(struct option) +
745 (guint16)ADD_PADDING(strlen(comment)));
748 if (isb_starttime !=0) {
749 block_total_length += (guint32)(sizeof(struct option) +
750 sizeof(guint64)); /* ISB_STARTTIME */
753 if (isb_endtime !=0) {
754 block_total_length += (guint32)(sizeof(struct option) +
755 sizeof(guint64)); /* ISB_ENDTIME */
758 /* If we have options add size of end-of-options */
760 block_total_length += (guint32)sizeof(struct option);
763 isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
764 isb.block_total_length = block_total_length;
765 isb.interface_id = interface_id;
766 isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
767 isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
768 if (!write_func(write_data_info, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))
771 /* write comment string if applicable */
772 if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
773 option.type = OPT_COMMENT;
774 option.value_length = (guint16)strlen(comment);
775 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
778 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
781 if (strlen(comment) % 4) {
782 if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
787 if (isb_starttime !=0) {
790 option.type = ISB_STARTTIME;
791 option.value_length = sizeof(guint64);
792 high = (guint32)((isb_starttime>>32) & 0xffffffff);
793 low = (guint32)(isb_starttime & 0xffffffff);
794 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
797 if (!write_func(write_data_info, (const guint8*)&high, sizeof(guint32), bytes_written, err))
800 if (!write_func(write_data_info, (const guint8*)&low, sizeof(guint32), bytes_written, err))
803 if (isb_endtime !=0) {
806 option.type = ISB_ENDTIME;
807 option.value_length = sizeof(guint64);
808 high = (guint32)((isb_endtime>>32) & 0xffffffff);
809 low = (guint32)(isb_endtime & 0xffffffff);
810 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
813 if (!write_func(write_data_info, (const guint8*)&high, sizeof(guint32), bytes_written, err))
816 if (!write_func(write_data_info, (const guint8*)&low, sizeof(guint32), bytes_written, err))
819 if (isb_ifrecv != G_MAXUINT64) {
820 option.type = ISB_IFRECV;
821 option.value_length = sizeof(guint64);
822 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
825 if (!write_func(write_data_info, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))
828 if (isb_ifdrop != G_MAXUINT64) {
829 option.type = ISB_IFDROP;
830 option.value_length = sizeof(guint64);
831 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
834 if (!write_func(write_data_info, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))
838 /* write end of options */
839 option.type = OPT_ENDOFOPT;
840 option.value_length = 0;
841 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
845 return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
849 * Editor modelines - http://www.wireshark.org/tools/modelines.html
854 * indent-tabs-mode: nil
857 * vi: set shiftwidth=4 tabstop=8 expandtab:
858 * :indentSize=4:tabSize=8:noTabs=true: