nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* pcapio.c
2 * Our own private code for writing libpcap files when capturing.
3 *
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
7 *
8 * 1) earlier versions of libpcap doesn't have it
9 *
10 * and
11 *
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).
16 *
17 * Libpcap's pcap_dump() also doesn't return any error indications.
18 *
19 * Wireshark - Network traffic analyzer
20 * By Gerald Combs <gerald@wireshark.org>
21 * Copyright 1998 Gerald Combs
22 *
23 * Derived from code in the Wiretap Library
24 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
25 *
26 * This program is free software; you can redistribute it and/or
27 * modify it under the terms of the GNU General Public License
28 * as published by the Free Software Foundation; either version 2
29 * of the License, or (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39 */
40  
41 #include <config.h>
42  
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <errno.h>
46 #include <string.h>
47 #ifdef HAVE_SYS_TIME_H
48 #include <sys/time.h>
49 #endif
50 #ifdef _WIN32
51 #include <Windows.h>
52 #endif
53  
54 #include <glib.h>
55  
56 #include "pcapio.h"
57  
58 /* Magic numbers in "libpcap" files.
59  
60 "libpcap" file records are written in the byte order of the host that
61 writes them, and the reader is expected to fix this up.
62  
63 PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
64 is a byte-swapped version of that.
65  
66 PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
67 which uses the same common file format as PCAP_MAGIC, but the
68 timestamps are saved in nanosecond resolution instead of microseconds.
69 PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
70 #define PCAP_MAGIC 0xa1b2c3d4
71 #define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
72 #define PCAP_NSEC_MAGIC 0xa1b23c4d
73 #define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1
74  
75 /* "libpcap" file header. */
76 struct pcap_hdr {
77 guint32 magic; /* magic number */
78 guint16 version_major; /* major version number */
79 guint16 version_minor; /* minor version number */
80 gint32 thiszone; /* GMT to local correction */
81 guint32 sigfigs; /* accuracy of timestamps */
82 guint32 snaplen; /* max length of captured packets, in octets */
83 guint32 network; /* data link type */
84 };
85  
86 /* "libpcap" record header. */
87 struct pcaprec_hdr {
88 guint32 ts_sec; /* timestamp seconds */
89 guint32 ts_usec; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
90 guint32 incl_len; /* number of octets of packet saved in file */
91 guint32 orig_len; /* actual length of packet */
92 };
93  
94 /* Magic numbers in ".pcapng" files.
95 *
96 * .pcapng file records are written in the byte order of the host that
97 * writes them, and the reader is expected to fix this up.
98 * PCAPNG_MAGIC is the magic number, in host byte order;
99 * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that.
100 */
101 #define PCAPNG_MAGIC 0x1A2B3C4D
102 #define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1
103  
104 /* Currently we are only supporting the initial version of
105 the file format. */
106 #define PCAPNG_MAJOR_VERSION 1
107 #define PCAPNG_MINOR_VERSION 0
108  
109 /* Section Header Block without options and trailing Block Total Length */
110 struct shb {
111 guint32 block_type;
112 guint32 block_total_length;
113 guint32 byte_order_magic;
114 guint16 major_version;
115 guint16 minor_version;
116 guint64 section_length;
117 };
118 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
119  
120 /* Interface Description Block without options and trailing Block Total Length */
121 struct idb {
122 guint32 block_type;
123 guint32 block_total_length;
124 guint16 link_type;
125 guint16 reserved;
126 guint32 snap_len;
127 };
128 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
129  
130 /* Interface Statistics Block without actual packet, options, and trailing
131 Block Total Length */
132 struct isb {
133 guint32 block_type;
134 guint32 block_total_length;
135 guint32 interface_id;
136 guint32 timestamp_high;
137 guint32 timestamp_low;
138 };
139 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
140  
141 /* Enhanced Packet Block without actual packet, options, and trailing
142 Block Total Length */
143 struct epb {
144 guint32 block_type;
145 guint32 block_total_length;
146 guint32 interface_id;
147 guint32 timestamp_high;
148 guint32 timestamp_low;
149 guint32 captured_len;
150 guint32 packet_len;
151 };
152 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
153  
154 struct option {
155 guint16 type;
156 guint16 value_length;
157 };
158 #define OPT_ENDOFOPT 0
159 #define OPT_COMMENT 1
160 #define EPB_FLAGS 2
161 #define SHB_HARDWARE 2 /* currently not used */
162 #define SHB_OS 3
163 #define SHB_USERAPPL 4
164 #define IDB_NAME 2
165 #define IDB_DESCRIPTION 3
166 #define IDB_IF_SPEED 8
167 #define IDB_TSRESOL 9
168 #define IDB_FILTER 11
169 #define IDB_OS 12
170 #define ISB_STARTTIME 2
171 #define ISB_ENDTIME 3
172 #define ISB_IFRECV 4
173 #define ISB_IFDROP 5
174 #define ISB_FILTERACCEPT 6
175 #define ISB_OSDROP 7
176 #define ISB_USRDELIV 8
177 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
178  
179 /* Write to capture file */
180 static gboolean
181 write_to_file(FILE* pfile, const guint8* data, size_t data_length,
182 guint64 *bytes_written, int *err)
183 {
184 size_t nwritten;
185  
186 nwritten = fwrite(data, data_length, 1, pfile);
187 if (nwritten != 1) {
188 if (ferror(pfile)) {
189 *err = errno;
190 } else {
191 *err = 0;
192 }
193 return FALSE;
194 }
195  
196 (*bytes_written) += data_length;
197 return TRUE;
198 }
199  
200 /* Writing pcap files */
201  
202 /* Write the file header to a dump file.
203 Returns TRUE on success, FALSE on failure.
204 Sets "*err" to an error code, or 0 for a short write, on failure*/
205 gboolean
206 libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err)
207 {
208 struct pcap_hdr file_hdr;
209  
210 file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;
211 /* current "libpcap" format is 2.4 */
212 file_hdr.version_major = 2;
213 file_hdr.version_minor = 4;
214 file_hdr.thiszone = 0; /* XXX - current offset? */
215 file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
216 file_hdr.snaplen = snaplen;
217 file_hdr.network = linktype;
218  
219 return write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);
220 }
221  
222 /* Write a record for a packet to a dump file.
223 Returns TRUE on success, FALSE on failure. */
224 gboolean
225 libpcap_write_packet(FILE* pfile,
226 time_t sec, guint32 usec,
227 guint32 caplen, guint32 len,
228 const guint8 *pd,
229 guint64 *bytes_written, int *err)
230 {
231 struct pcaprec_hdr rec_hdr;
232  
233 rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */
234 rec_hdr.ts_usec = usec;
235 rec_hdr.incl_len = caplen;
236 rec_hdr.orig_len = len;
237 if (!write_to_file(pfile, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))
238 return FALSE;
239  
240 return write_to_file(pfile, pd, caplen, bytes_written, err);
241 }
242  
243 /* Writing pcap-ng files */
244  
245 static guint32
246 pcapng_count_string_option(const char *option_value)
247 {
248 if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < G_MAXUINT16)) {
249 /* There's a value to write; get its length */
250 return (guint32)(sizeof(struct option) +
251 (guint16)ADD_PADDING(strlen(option_value)));
252 }
253 return 0; /* nothing to write */
254 }
255  
256 static gboolean
257 pcapng_write_string_option(FILE* pfile,
258 guint16 option_type, const char *option_value,
259 guint64 *bytes_written, int *err)
260 {
261 size_t option_value_length;
262 struct option option;
263 const guint32 padding = 0;
264  
265 if (option_value == NULL)
266 return TRUE; /* nothing to write */
267 option_value_length = strlen(option_value);
268 if ((option_value_length > 0) && (option_value_length < G_MAXUINT16)) {
269 /* something to write */
270 option.type = option_type;
271 option.value_length = (guint16)option_value_length;
272  
273 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
274 return FALSE;
275  
276 if (!write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err))
277 return FALSE;
278  
279 if (option_value_length % 4) {
280 if (!write_to_file(pfile, (const guint8*)&padding, 4 - option_value_length % 4, bytes_written, err))
281 return FALSE;
282 }
283 }
284 return TRUE;
285 }
286  
287 gboolean
288 pcapng_write_session_header_block(FILE* pfile,
289 const char *comment,
290 const char *hw,
291 const char *os,
292 const char *appname,
293 guint64 section_length,
294 guint64 *bytes_written,
295 int *err)
296 {
297 struct shb shb;
298 struct option option;
299 guint32 block_total_length;
300 guint32 options_length;
301  
302 /* Size of base header */
303 block_total_length = sizeof(struct shb) +
304 sizeof(guint32);
305 options_length = 0;
306 options_length += pcapng_count_string_option(comment);
307 options_length += pcapng_count_string_option(hw);
308 options_length += pcapng_count_string_option(os);
309 options_length += pcapng_count_string_option(appname);
310 /* If we have options add size of end-of-options */
311 if (options_length != 0) {
312 options_length += (guint32)sizeof(struct option);
313 }
314 block_total_length += options_length;
315  
316 /* write shb header */
317 shb.block_type = SECTION_HEADER_BLOCK_TYPE;
318 shb.block_total_length = block_total_length;
319 shb.byte_order_magic = PCAPNG_MAGIC;
320 shb.major_version = PCAPNG_MAJOR_VERSION;
321 shb.minor_version = PCAPNG_MINOR_VERSION;
322 shb.section_length = section_length;
323  
324 if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
325 return FALSE;
326  
327 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
328 bytes_written, err))
329 return FALSE;
330 if (!pcapng_write_string_option(pfile, SHB_HARDWARE, hw,
331 bytes_written, err))
332 return FALSE;
333 if (!pcapng_write_string_option(pfile, SHB_OS, os,
334 bytes_written, err))
335 return FALSE;
336 if (!pcapng_write_string_option(pfile, SHB_USERAPPL, appname,
337 bytes_written, err))
338 return FALSE;
339 if (options_length != 0) {
340 /* write end of options */
341 option.type = OPT_ENDOFOPT;
342 option.value_length = 0;
343 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
344 return FALSE;
345 }
346  
347 /* write the trailing block total length */
348 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
349 }
350  
351 gboolean
352 pcapng_write_interface_description_block(FILE* pfile,
353 const char *comment, /* OPT_COMMENT 1 */
354 const char *name, /* IDB_NAME 2 */
355 const char *descr, /* IDB_DESCRIPTION 3 */
356 const char *filter, /* IDB_FILTER 11 */
357 const char *os, /* IDB_OS 12 */
358 int link_type,
359 int snap_len,
360 guint64 *bytes_written,
361 guint64 if_speed, /* IDB_IF_SPEED 8 */
362 guint8 tsresol, /* IDB_TSRESOL 9 */
363 int *err)
364 {
365 struct idb idb;
366 struct option option;
367 guint32 block_total_length;
368 guint32 options_length;
369 const guint32 padding = 0;
370  
371 block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32));
372 options_length = 0;
373 /* 01 - OPT_COMMENT */
374 options_length += pcapng_count_string_option(comment);
375  
376 /* 02 - IDB_NAME */
377 options_length += pcapng_count_string_option(name);
378  
379 /* 03 - IDB_DESCRIPTION */
380 options_length += pcapng_count_string_option(descr);
381  
382 /* 08 - IDB_IF_SPEED */
383 if (if_speed != 0) {
384 options_length += (guint32)(sizeof(struct option) +
385 sizeof(guint64));
386 }
387  
388 /* 09 - IDB_TSRESOL */
389 if (tsresol != 0) {
390 options_length += (guint32)(sizeof(struct option) +
391 sizeof(struct option));
392 }
393  
394 /* 11 - IDB_FILTER */
395 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
396 /* No, this isn't a string, it has an extra type byte */
397 options_length += (guint32)(sizeof(struct option) +
398 (guint16)(ADD_PADDING(strlen(filter)+ 1)));
399 }
400  
401 /* 12 - IDB_OS */
402 options_length += pcapng_count_string_option(os);
403  
404 /* If we have options add size of end-of-options */
405 if (options_length != 0) {
406 options_length += (guint32)sizeof(struct option);
407 }
408 block_total_length += options_length;
409  
410 /* write block header */
411 idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
412 idb.block_total_length = block_total_length;
413 idb.link_type = link_type;
414 idb.reserved = 0;
415 idb.snap_len = snap_len;
416 if (!write_to_file(pfile, (const guint8*)&idb, sizeof(struct idb), bytes_written, err))
417 return FALSE;
418  
419 /* 01 - OPT_COMMENT - write comment string if applicable */
420 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
421 bytes_written, err))
422 return FALSE;
423  
424 /* 02 - IDB_NAME - write interface name string if applicable */
425 if (!pcapng_write_string_option(pfile, IDB_NAME, name,
426 bytes_written, err))
427 return FALSE;
428  
429 /* 03 - IDB_DESCRIPTION */
430 /* write interface description string if applicable */
431 if (!pcapng_write_string_option(pfile, IDB_DESCRIPTION, descr,
432 bytes_written, err))
433 return FALSE;
434  
435 /* 08 - IDB_IF_SPEED */
436 if (if_speed != 0) {
437 option.type = IDB_IF_SPEED;
438 option.value_length = sizeof(guint64);
439  
440 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
441 return FALSE;
442  
443 if (!write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))
444 return FALSE;
445 }
446  
447 /* 09 - IDB_TSRESOL */
448 if (tsresol != 0) {
449 option.type = IDB_TSRESOL;
450 option.value_length = sizeof(guint8);
451  
452 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
453 return FALSE;
454  
455 if (!write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))
456 return FALSE;
457  
458 if (!write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err))
459 return FALSE;
460 }
461  
462 /* 11 - IDB_FILTER - write filter string if applicable
463 * We only write version 1 of the filter, pcapng string
464 */
465 if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16 - 1)) {
466 option.type = IDB_FILTER;
467 option.value_length = (guint16)(strlen(filter) + 1 );
468 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
469 return FALSE;
470  
471 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
472 if (!write_to_file(pfile, (const guint8*)&padding, 1, bytes_written, err))
473 return FALSE;
474 if (!write_to_file(pfile, (const guint8*)filter, (int) strlen(filter), bytes_written, err))
475 return FALSE;
476 if ((strlen(filter) + 1) % 4) {
477 if (!write_to_file(pfile, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
478 return FALSE;
479 }
480 }
481  
482 /* 12 - IDB_OS - write os string if applicable */
483 if (!pcapng_write_string_option(pfile, IDB_OS, os,
484 bytes_written, err))
485 return FALSE;
486  
487 if (options_length != 0) {
488 /* write end of options */
489 option.type = OPT_ENDOFOPT;
490 option.value_length = 0;
491 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
492 return FALSE;
493 }
494  
495 /* write the trailing Block Total Length */
496 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
497 }
498  
499 /* Write a record for a packet to a dump file.
500 Returns TRUE on success, FALSE on failure. */
501 gboolean
502 pcapng_write_enhanced_packet_block(FILE* pfile,
503 const char *comment,
504 time_t sec, guint32 usec,
505 guint32 caplen, guint32 len,
506 guint32 interface_id,
507 guint ts_mul,
508 const guint8 *pd,
509 guint32 flags,
510 guint64 *bytes_written,
511 int *err)
512 {
513 struct epb epb;
514 struct option option;
515 guint32 block_total_length;
516 guint64 timestamp;
517 guint32 options_length;
518 const guint32 padding = 0;
519  
520 block_total_length = (guint32)(sizeof(struct epb) +
521 ADD_PADDING(caplen) +
522 sizeof(guint32));
523 options_length = 0;
524 options_length += pcapng_count_string_option(comment);
525 if (flags != 0) {
526 options_length += (guint32)(sizeof(struct option) +
527 sizeof(guint32));
528 }
529 /* If we have options add size of end-of-options */
530 if (options_length != 0) {
531 options_length += (guint32)sizeof(struct option);
532 }
533 block_total_length += options_length;
534 timestamp = (guint64)sec * ts_mul + (guint64)usec;
535 epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
536 epb.block_total_length = block_total_length;
537 epb.interface_id = interface_id;
538 epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
539 epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
540 epb.captured_len = caplen;
541 epb.packet_len = len;
542 if (!write_to_file(pfile, (const guint8*)&epb, sizeof(struct epb), bytes_written, err))
543 return FALSE;
544 if (!write_to_file(pfile, pd, caplen, bytes_written, err))
545 return FALSE;
546 if (caplen % 4) {
547 if (!write_to_file(pfile, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err))
548 return FALSE;
549 }
550 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
551 bytes_written, err))
552 return FALSE;
553 if (flags != 0) {
554 option.type = EPB_FLAGS;
555 option.value_length = sizeof(guint32);
556 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
557 return FALSE;
558 if (!write_to_file(pfile, (const guint8*)&flags, sizeof(guint32), bytes_written, err))
559 return FALSE;
560 }
561 if (options_length != 0) {
562 /* write end of options */
563 option.type = OPT_ENDOFOPT;
564 option.value_length = 0;
565 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
566 return FALSE;
567 }
568  
569 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
570 }
571  
572 gboolean
573 pcapng_write_interface_statistics_block(FILE* pfile,
574 guint32 interface_id,
575 guint64 *bytes_written,
576 const char *comment, /* OPT_COMMENT 1 */
577 guint64 isb_starttime, /* ISB_STARTTIME 2 */
578 guint64 isb_endtime, /* ISB_ENDTIME 3 */
579 guint64 isb_ifrecv, /* ISB_IFRECV 4 */
580 guint64 isb_ifdrop, /* ISB_IFDROP 5 */
581 int *err)
582 {
583 struct isb isb;
584 #ifdef _WIN32
585 FILETIME now;
586 #else
587 struct timeval now;
588 #endif
589 struct option option;
590 guint32 block_total_length;
591 guint32 options_length;
592 guint64 timestamp;
593  
594 #ifdef _WIN32
595 /*
596 * Current time, represented as 100-nanosecond intervals since
597 * January 1, 1601, 00:00:00 UTC.
598 *
599 * I think DWORD might be signed, so cast both parts of "now"
600 * to guint32 so that the sign bit doesn't get treated specially.
601 *
602 * Windows 8 provides GetSystemTimePreciseAsFileTime which we
603 * might want to use instead.
604 */
605 GetSystemTimeAsFileTime(&now);
606 timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
607 (guint32)now.dwLowDateTime;
608  
609 /*
610 * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
611 * intervals.
612 */
613 timestamp /= 10;
614  
615 /*
616 * Subtract difference, in microseconds, between January 1, 1601
617 * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
618 */
619 timestamp -= G_GUINT64_CONSTANT(11644473600000000);
620 #else
621 /*
622 * Current time, represented as seconds and microseconds since
623 * January 1, 1970, 00:00:00 UTC.
624 */
625 gettimeofday(&now, NULL);
626  
627 /*
628 * Convert to delta in microseconds.
629 */
630 timestamp = (guint64)(now.tv_sec) * 1000000 +
631 (guint64)(now.tv_usec);
632 #endif
633 block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));
634 options_length = 0;
635 if (isb_ifrecv != G_MAXUINT64) {
636 options_length += (guint32)(sizeof(struct option) +
637 sizeof(guint64));
638 }
639 if (isb_ifdrop != G_MAXUINT64) {
640 options_length += (guint32)(sizeof(struct option) +
641 sizeof(guint64));
642 }
643 /* OPT_COMMENT */
644 options_length += pcapng_count_string_option(comment);
645 if (isb_starttime !=0) {
646 options_length += (guint32)(sizeof(struct option) +
647 sizeof(guint64)); /* ISB_STARTTIME */
648 }
649 if (isb_endtime !=0) {
650 options_length += (guint32)(sizeof(struct option) +
651 sizeof(guint64)); /* ISB_ENDTIME */
652 }
653 /* If we have options add size of end-of-options */
654 if (options_length != 0) {
655 options_length += (guint32)sizeof(struct option);
656 }
657 block_total_length += options_length;
658  
659 isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
660 isb.block_total_length = block_total_length;
661 isb.interface_id = interface_id;
662 isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
663 isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
664 if (!write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))
665 return FALSE;
666  
667 /* write comment string if applicable */
668 if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
669 bytes_written, err))
670 return FALSE;
671  
672 if (isb_starttime !=0) {
673 guint32 high, low;
674  
675 option.type = ISB_STARTTIME;
676 option.value_length = sizeof(guint64);
677 high = (guint32)((isb_starttime>>32) & 0xffffffff);
678 low = (guint32)(isb_starttime & 0xffffffff);
679 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
680 return FALSE;
681  
682 if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
683 return FALSE;
684  
685 if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
686 return FALSE;
687 }
688 if (isb_endtime !=0) {
689 guint32 high, low;
690  
691 option.type = ISB_ENDTIME;
692 option.value_length = sizeof(guint64);
693 high = (guint32)((isb_endtime>>32) & 0xffffffff);
694 low = (guint32)(isb_endtime & 0xffffffff);
695 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
696 return FALSE;
697  
698 if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
699 return FALSE;
700  
701 if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
702 return FALSE;
703 }
704 if (isb_ifrecv != G_MAXUINT64) {
705 option.type = ISB_IFRECV;
706 option.value_length = sizeof(guint64);
707 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
708 return FALSE;
709  
710 if (!write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))
711 return FALSE;
712 }
713 if (isb_ifdrop != G_MAXUINT64) {
714 option.type = ISB_IFDROP;
715 option.value_length = sizeof(guint64);
716 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
717 return FALSE;
718  
719 if (!write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))
720 return FALSE;
721 }
722 if (options_length != 0) {
723 /* write end of options */
724 option.type = OPT_ENDOFOPT;
725 option.value_length = 0;
726 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
727 return FALSE;
728 }
729  
730 return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
731 }
732  
733 /*
734 * Editor modelines - http://www.wireshark.org/tools/modelines.html
735 *
736 * Local variables:
737 * c-basic-offset: 8
738 * tab-width: 8
739 * indent-tabs-mode: nil
740 * End:
741 *
742 * vi: set shiftwidth=8 tabstop=8 expandtab:
743 * :indentSize=8:tabSize=8:noTabs=true:
744 */