MSWSP: WIP: dissect_CPMSetBindings()
[wireshark-wip.git] / pcapio.c
blob70bbf98ebf30e12ee7e0107a8087f2d079a54856
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 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.
19 * $Id$
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.
43 #include "config.h"
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <errno.h>
48 #include <string.h>
49 #ifdef HAVE_SYS_TIME_H
50 #include <sys/time.h>
51 #endif
52 #ifdef _WIN32
53 #include <Windows.h>
54 #endif
56 #include <glib.h>
58 #include "pcapio.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. */
78 struct pcap_hdr {
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. */
89 struct pcaprec_hdr {
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
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 guint32 block_type;
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 */
123 struct idb {
124 guint32 block_type;
125 guint32 block_total_length;
126 guint16 link_type;
127 guint16 reserved;
128 guint32 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 guint32 block_type;
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 */
145 struct epb {
146 guint32 block_type;
147 guint32 block_total_length;
148 guint32 interface_id;
149 guint32 timestamp_high;
150 guint32 timestamp_low;
151 guint32 captured_len;
152 guint32 packet_len;
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
156 struct option {
157 guint16 type;
158 guint16 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 ISB_STARTTIME 2
173 #define ISB_ENDTIME 3
174 #define ISB_IFRECV 4
175 #define ISB_IFDROP 5
176 #define ISB_FILTERACCEPT 6
177 #define ISB_OSDROP 7
178 #define ISB_USRDELIV 8
179 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
181 /* Write to capture file */
182 static gboolean
183 write_to_file(FILE* pfile, const guint8* data, size_t data_length,
184 guint64 *bytes_written, int *err)
186 size_t nwritten;
188 nwritten = fwrite(data, data_length, 1, pfile);
189 if (nwritten != 1) {
190 if (ferror(pfile)) {
191 *err = errno;
192 } else {
193 *err = 0;
195 return FALSE;
198 (*bytes_written) += data_length;
199 return TRUE;
202 /* Writing pcap files */
204 /* Write the file header to a dump file.
205 Returns TRUE on success, FALSE on failure.
206 Sets "*err" to an error code, or 0 for a short write, on failure*/
207 gboolean
208 libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err)
210 struct pcap_hdr file_hdr;
212 file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;
213 /* current "libpcap" format is 2.4 */
214 file_hdr.version_major = 2;
215 file_hdr.version_minor = 4;
216 file_hdr.thiszone = 0; /* XXX - current offset? */
217 file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
218 file_hdr.snaplen = snaplen;
219 file_hdr.network = linktype;
221 return write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);
224 /* Write a record for a packet to a dump file.
225 Returns TRUE on success, FALSE on failure. */
226 gboolean
227 libpcap_write_packet(FILE* pfile,
228 time_t sec, guint32 usec,
229 guint32 caplen, guint32 len,
230 const guint8 *pd,
231 guint64 *bytes_written, int *err)
233 struct pcaprec_hdr rec_hdr;
235 rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */
236 rec_hdr.ts_usec = usec;
237 rec_hdr.incl_len = caplen;
238 rec_hdr.orig_len = len;
239 if (!write_to_file(pfile, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))
240 return FALSE;
242 return write_to_file(pfile, pd, caplen, bytes_written, err);
245 /* Writing pcap-ng files */
247 static guint32
248 pcapng_count_string_option(const char *option_value)
250 if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < G_MAXUINT16)) {
251 /* There's a value to write; get its length */
252 return (guint32)(sizeof(struct option) +
253 (guint16)ADD_PADDING(strlen(option_value)));
255 return 0; /* nothing to write */
258 static gboolean
259 pcapng_write_string_option(FILE* pfile,
260 guint16 option_type, const char *option_value,
261 guint64 *bytes_written, int *err)
263 size_t option_value_length;
264 struct option option;
265 const guint32 padding = 0;
267 if (option_value == NULL)
268 return TRUE; /* nothing to write */
269 option_value_length = strlen(option_value);
270 if ((option_value_length > 0) && (option_value_length < G_MAXUINT16)) {
271 /* something to write */
272 option.type = option_type;
273 option.value_length = (guint16)option_value_length;
275 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
276 return FALSE;
278 if (!write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err))
279 return FALSE;
281 if (option_value_length % 4) {
282 if (!write_to_file(pfile, (const guint8*)&padding, 4 - option_value_length % 4, bytes_written, err))
283 return FALSE;
286 return TRUE;
289 gboolean
290 pcapng_write_session_header_block(FILE* pfile,
291 const char *comment,
292 const char *hw,
293 const char *os,
294 const char *appname,
295 guint64 section_length,
296 guint64 *bytes_written,
297 int *err)
299 struct shb shb;
300 struct option option;
301 guint32 block_total_length;
302 guint32 options_length;
304 /* Size of base header */
305 block_total_length = sizeof(struct shb) +
306 sizeof(guint32);
307 options_length = 0;
308 options_length += pcapng_count_string_option(comment);
309 options_length += pcapng_count_string_option(hw);
310 options_length += pcapng_count_string_option(os);
311 options_length += pcapng_count_string_option(appname);
312 /* If we have options add size of end-of-options */
313 if (options_length != 0) {
314 options_length += (guint32)sizeof(struct option);
316 block_total_length += options_length;
318 /* write shb header */
319 shb.block_type = SECTION_HEADER_BLOCK_TYPE;
320 shb.block_total_length = block_total_length;
321 shb.byte_order_magic = PCAPNG_MAGIC;
322 shb.major_version = PCAPNG_MAJOR_VERSION;
323 shb.minor_version = PCAPNG_MINOR_VERSION;
324 shb.section_length = section_length;
326 if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
327 return FALSE;
329 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
330 bytes_written, err))
331 return FALSE;
332 if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw,
333 bytes_written, err))
334 return FALSE;
335 if (!pcapng_write_string_option(pfile, SHB_OS, os,
336 bytes_written, err))
337 return FALSE;
338 if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname,
339 bytes_written, err))
340 return FALSE;
341 if (options_length != 0) {
342 /* write end of options */
343 option.type = OPT_ENDOFOPT;
344 option.value_length = 0;
345 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
346 return FALSE;
349 /* write the trailing block total length */
350 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
353 gboolean
354 pcapng_write_interface_description_block(FILE* pfile,
355 const char *comment, /* OPT_COMMENT 1 */
356 const char *name, /* IDB_NAME 2 */
357 const char *descr, /* IDB_DESCRIPTION 3 */
358 const char *filter, /* IDB_FILTER 11 */
359 const char *os, /* IDB_OS 12 */
360 int link_type,
361 int snap_len,
362 guint64 *bytes_written,
363 guint64 if_speed, /* IDB_IF_SPEED 8 */
364 guint8 tsresol, /* IDB_TSRESOL 9 */
365 int *err)
367 struct idb idb;
368 struct option option;
369 guint32 block_total_length;
370 guint32 options_length;
371 const guint32 padding = 0;
373 block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32));
374 options_length = 0;
375 /* 01 - OPT_COMMENT */
376 options_length += pcapng_count_string_option(comment);
378 /* 02 - IDB_NAME */
379 options_length += pcapng_count_string_option(name);
381 /* 03 - IDB_DESCRIPTION */
382 options_length += pcapng_count_string_option(descr);
384 /* 08 - IDB_IF_SPEED */
385 if (if_speed != 0) {
386 options_length += (guint32)(sizeof(struct option) +
387 sizeof(guint64));
390 /* 09 - IDB_TSRESOL */
391 if (tsresol != 0) {
392 options_length += (guint32)(sizeof(struct option) +
393 sizeof(struct option));
396 /* 11 - IDB_FILTER */
397 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
398 /* No, this isn't a string, it has an extra type byte */
399 options_length += (guint32)(sizeof(struct option) +
400 (guint16)(ADD_PADDING(strlen(filter)+ 1)));
403 /* 12 - IDB_OS */
404 options_length += pcapng_count_string_option(os);
406 /* If we have options add size of end-of-options */
407 if (options_length != 0) {
408 options_length += (guint32)sizeof(struct option);
410 block_total_length += options_length;
412 /* write block header */
413 idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
414 idb.block_total_length = block_total_length;
415 idb.link_type = link_type;
416 idb.reserved = 0;
417 idb.snap_len = snap_len;
418 if (!write_to_file(pfile, (const guint8*)&idb, sizeof(struct idb), bytes_written, err))
419 return FALSE;
421 /* 01 - OPT_COMMENT - write comment string if applicable */
422 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
423 bytes_written, err))
424 return FALSE;
426 /* 02 - IDB_NAME - write interface name string if applicable */
427 if (!pcapng_write_string_option(pfile, IDB_NAME, name,
428 bytes_written, err))
429 return FALSE;
431 /* 03 - IDB_DESCRIPTION */
432 /* write interface description string if applicable */
433 if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr,
434 bytes_written, err))
435 return FALSE;
437 /* 08 - IDB_IF_SPEED */
438 if (if_speed != 0) {
439 option.type = IDB_IF_SPEED;
440 option.value_length = sizeof(guint64);
442 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
443 return FALSE;
445 if (!write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))
446 return FALSE;
449 /* 09 - IDB_TSRESOL */
450 if (tsresol != 0) {
451 option.type = IDB_TSRESOL;
452 option.value_length = sizeof(guint8);
454 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
455 return FALSE;
457 if (!write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))
458 return FALSE;
460 if (!write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err))
461 return FALSE;
464 /* 11 - IDB_FILTER - write filter string if applicable
465 * We only write version 1 of the filter, pcapng string
467 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16 - 1)) {
468 option.type = IDB_FILTER;
469 option.value_length = (guint16)(strlen(filter) + 1 );
470 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
471 return FALSE;
473 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
474 if (!write_to_file(pfile, (const guint8*)&padding, 1, bytes_written, err))
475 return FALSE;
476 if (!write_to_file(pfile, (const guint8*)filter, (int) strlen(filter), bytes_written, err))
477 return FALSE;
478 if ((strlen(filter) + 1) % 4) {
479 if (!write_to_file(pfile, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
480 return FALSE;
484 /* 12 - IDB_OS - write os string if applicable */
485 if (!pcapng_write_string_option(pfile, IDB_OS, os,
486 bytes_written, err))
487 return FALSE;
489 if (options_length != 0) {
490 /* write end of options */
491 option.type = OPT_ENDOFOPT;
492 option.value_length = 0;
493 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
494 return FALSE;
497 /* write the trailing Block Total Length */
498 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
501 /* Write a record for a packet to a dump file.
502 Returns TRUE on success, FALSE on failure. */
503 gboolean
504 pcapng_write_enhanced_packet_block(FILE* pfile,
505 const char *comment,
506 time_t sec, guint32 usec,
507 guint32 caplen, guint32 len,
508 guint32 interface_id,
509 guint ts_mul,
510 const guint8 *pd,
511 guint32 flags,
512 guint64 *bytes_written,
513 int *err)
515 struct epb epb;
516 struct option option;
517 guint32 block_total_length;
518 guint64 timestamp;
519 guint32 options_length;
520 const guint32 padding = 0;
522 block_total_length = (guint32)(sizeof(struct epb) +
523 ADD_PADDING(caplen) +
524 sizeof(guint32));
525 options_length = 0;
526 options_length += pcapng_count_string_option(comment);
527 if (flags != 0) {
528 options_length += (guint32)(sizeof(struct option) +
529 sizeof(guint32));
531 /* If we have options add size of end-of-options */
532 if (options_length != 0) {
533 options_length += (guint32)sizeof(struct option);
535 block_total_length += options_length;
536 timestamp = (guint64)sec * ts_mul + (guint64)usec;
537 epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
538 epb.block_total_length = block_total_length;
539 epb.interface_id = interface_id;
540 epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
541 epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
542 epb.captured_len = caplen;
543 epb.packet_len = len;
544 if (!write_to_file(pfile, (const guint8*)&epb, sizeof(struct epb), bytes_written, err))
545 return FALSE;
546 if (!write_to_file(pfile, pd, caplen, bytes_written, err))
547 return FALSE;
548 if (caplen % 4) {
549 if (!write_to_file(pfile, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err))
550 return FALSE;
552 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
553 bytes_written, err))
554 return FALSE;
555 if (flags != 0) {
556 option.type = EPB_FLAGS;
557 option.value_length = sizeof(guint32);
558 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
559 return FALSE;
560 if (!write_to_file(pfile, (const guint8*)&flags, sizeof(guint32), bytes_written, err))
561 return FALSE;
563 if (options_length != 0) {
564 /* write end of options */
565 option.type = OPT_ENDOFOPT;
566 option.value_length = 0;
567 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
568 return FALSE;
571 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
574 gboolean
575 pcapng_write_interface_statistics_block(FILE* pfile,
576 guint32 interface_id,
577 guint64 *bytes_written,
578 const char *comment, /* OPT_COMMENT 1 */
579 guint64 isb_starttime, /* ISB_STARTTIME 2 */
580 guint64 isb_endtime, /* ISB_ENDTIME 3 */
581 guint64 isb_ifrecv, /* ISB_IFRECV 4 */
582 guint64 isb_ifdrop, /* ISB_IFDROP 5 */
583 int *err)
585 struct isb isb;
586 #ifdef _WIN32
587 FILETIME now;
588 #else
589 struct timeval now;
590 #endif
591 struct option option;
592 guint32 block_total_length;
593 guint32 options_length;
594 guint64 timestamp;
596 #ifdef _WIN32
598 * Current time, represented as 100-nanosecond intervals since
599 * January 1, 1601, 00:00:00 UTC.
601 * I think DWORD might be signed, so cast both parts of "now"
602 * to guint32 so that the sign bit doesn't get treated specially.
604 * Windows 8 provides GetSystemTimePreciseAsFileTime which we
605 * might want to use instead.
607 GetSystemTimeAsFileTime(&now);
608 timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
609 (guint32)now.dwLowDateTime;
612 * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
613 * intervals.
615 timestamp /= 10;
618 * Subtract difference, in microseconds, between January 1, 1601
619 * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
621 timestamp -= G_GINT64_CONSTANT(11644473600000000U);
622 #else
624 * Current time, represented as seconds and microseconds since
625 * January 1, 1970, 00:00:00 UTC.
627 gettimeofday(&now, NULL);
630 * Convert to delta in microseconds.
632 timestamp = (guint64)(now.tv_sec) * 1000000 +
633 (guint64)(now.tv_usec);
634 #endif
635 block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));
636 options_length = 0;
637 if (isb_ifrecv != G_MAXUINT64) {
638 options_length += (guint32)(sizeof(struct option) +
639 sizeof(guint64));
641 if (isb_ifdrop != G_MAXUINT64) {
642 options_length += (guint32)(sizeof(struct option) +
643 sizeof(guint64));
645 /* OPT_COMMENT */
646 options_length += pcapng_count_string_option(comment);
647 if (isb_starttime !=0) {
648 options_length += (guint32)(sizeof(struct option) +
649 sizeof(guint64)); /* ISB_STARTTIME */
651 if (isb_endtime !=0) {
652 options_length += (guint32)(sizeof(struct option) +
653 sizeof(guint64)); /* ISB_ENDTIME */
655 /* If we have options add size of end-of-options */
656 if (options_length != 0) {
657 options_length += (guint32)sizeof(struct option);
659 block_total_length += options_length;
661 isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
662 isb.block_total_length = block_total_length;
663 isb.interface_id = interface_id;
664 isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
665 isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
666 if (!write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))
667 return FALSE;
669 /* write comment string if applicable */
670 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
671 bytes_written, err))
672 return FALSE;
674 if (isb_starttime !=0) {
675 guint32 high, low;
677 option.type = ISB_STARTTIME;
678 option.value_length = sizeof(guint64);
679 high = (guint32)((isb_starttime>>32) & 0xffffffff);
680 low = (guint32)(isb_starttime & 0xffffffff);
681 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
682 return FALSE;
684 if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
685 return FALSE;
687 if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
688 return FALSE;
690 if (isb_endtime !=0) {
691 guint32 high, low;
693 option.type = ISB_ENDTIME;
694 option.value_length = sizeof(guint64);
695 high = (guint32)((isb_endtime>>32) & 0xffffffff);
696 low = (guint32)(isb_endtime & 0xffffffff);
697 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
698 return FALSE;
700 if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
701 return FALSE;
703 if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
704 return FALSE;
706 if (isb_ifrecv != G_MAXUINT64) {
707 option.type = ISB_IFRECV;
708 option.value_length = sizeof(guint64);
709 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
710 return FALSE;
712 if (!write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))
713 return FALSE;
715 if (isb_ifdrop != G_MAXUINT64) {
716 option.type = ISB_IFDROP;
717 option.value_length = sizeof(guint64);
718 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
719 return FALSE;
721 if (!write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))
722 return FALSE;
724 if (options_length != 0) {
725 /* write end of options */
726 option.type = OPT_ENDOFOPT;
727 option.value_length = 0;
728 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
729 return FALSE;
732 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
736 * Editor modelines - http://www.wireshark.org/tools/modelines.html
738 * Local variables:
739 * c-basic-offset: 4
740 * tab-width: 8
741 * indent-tabs-mode: nil
742 * End:
744 * vi: set shiftwidth=4 tabstop=8 expandtab:
745 * :indentSize=4:tabSize=8:noTabs=true: