Free the actual struct, not the typedef thereof, because the typedef is actually
[metze/wireshark/wip.git] / pcapio.c
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  * $Id$
20  *
21  * Wireshark - Network traffic analyzer
22  * By Gerald Combs <gerald@wireshark.org>
23  * Copyright 1998 Gerald Combs
24  *
25  * Derived from code in the Wiretap Library
26  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
27  *
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.
32  *
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.
37  *
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.
41  */
42
43 #include "config.h"
44
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
55
56 #include <glib.h>
57
58 #include "pcapio.h"
59
60 /* Magic numbers in "libpcap" files.
61
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.
64
65    PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
66    is a byte-swapped version of that.
67
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
76
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 */
86 };
87
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 */
94 };
95
96 /* Magic numbers in ".pcapng" files.
97  *
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.
102  */
103 #define PCAPNG_MAGIC         0x1A2B3C4D
104 #define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1
105
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
110
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;
119 };
120 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
121
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;
129 };
130 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
131
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;
140 };
141 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
142
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;
153 };
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
155
156 struct option {
157         guint16 type;
158         guint16 value_length;
159 };
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)
180
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)
185 {
186         size_t nwritten;
187
188         nwritten = fwrite(data, data_length, 1, pfile);
189         if (nwritten != 1) {
190                 if (ferror(pfile)) {
191                         *err = errno;
192                 } else {
193                         *err = 0;
194                 }
195                 return FALSE;
196         }
197
198         (*bytes_written) += data_length;
199         return TRUE;
200 }
201
202 /* Writing pcap files */
203
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)
209 {
210         struct pcap_hdr file_hdr;
211
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;
220
221         return write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);
222 }
223
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)
232 {
233         struct pcaprec_hdr rec_hdr;
234
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;
241
242         return write_to_file(pfile, pd, caplen, bytes_written, err);
243 }
244
245 /* Writing pcap-ng files */
246
247 static guint32
248 pcapng_count_string_option(const char *option_value)
249 {
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)));
254         }
255         return 0; /* nothing to write */
256 }
257
258 static gboolean
259 pcapng_write_string_option(FILE* pfile,
260                            guint16 option_type, const char *option_value,
261                            guint64 *bytes_written, int *err)
262 {
263         size_t option_value_length;
264         struct option option;
265         const guint32 padding = 0;
266
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;
274
275                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
276                         return FALSE;
277
278                 if (!write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err))
279                         return FALSE;
280
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;
284                 }
285         }
286         return TRUE;
287 }
288
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)
298 {
299         struct shb shb;
300         struct option option;
301         guint32 block_total_length;
302         guint32 options_length;
303
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);
315         }
316         block_total_length += options_length;
317
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;
325
326         if (!write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
327                 return FALSE;
328
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;
347         }
348
349         /* write the trailing block total length */
350         return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
351 }
352
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)
366 {
367         struct idb idb;
368         struct option option;
369         guint32 block_total_length;
370         guint32 options_length;
371         const guint32 padding = 0;
372
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);
377
378         /* 02 - IDB_NAME */
379         options_length += pcapng_count_string_option(name);
380
381         /* 03 - IDB_DESCRIPTION */
382         options_length += pcapng_count_string_option(descr);
383
384         /* 08 - IDB_IF_SPEED */
385         if (if_speed != 0) {
386                 options_length += (guint32)(sizeof(struct option) +
387                                             sizeof(guint64));
388         }
389
390         /* 09 - IDB_TSRESOL */
391         if (tsresol != 0) {
392                 options_length += (guint32)(sizeof(struct option) +
393                                             sizeof(struct option));
394         }
395
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)));
401         }
402
403         /* 12 - IDB_OS */
404         options_length += pcapng_count_string_option(os);
405
406         /* If we have options add size of end-of-options */
407         if (options_length != 0) {
408                 options_length += (guint32)sizeof(struct option);
409         }
410         block_total_length += options_length;
411
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;
420
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;
425
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;
430
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;
436
437         /* 08 - IDB_IF_SPEED */
438         if (if_speed != 0) {
439                 option.type = IDB_IF_SPEED;
440                 option.value_length = sizeof(guint64);
441
442                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
443                         return FALSE;
444
445                 if (!write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))
446                         return FALSE;
447         }
448
449         /* 09 - IDB_TSRESOL */
450         if (tsresol != 0) {
451                 option.type = IDB_TSRESOL;
452                 option.value_length = sizeof(guint8);
453
454                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
455                         return FALSE;
456
457                 if (!write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))
458                         return FALSE;
459
460                 if (!write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err))
461                         return FALSE;
462         }
463
464         /* 11 - IDB_FILTER - write filter string if applicable
465          * We only write version 1 of the filter, pcapng string
466          */
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;
472
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;
481                 }
482         }
483
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;
488
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;
495         }
496
497         /* write the trailing Block Total Length */
498         return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
499 }
500
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)
514 {
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;
521
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));
530         }
531         /* If we have options add size of end-of-options */
532         if (options_length != 0) {
533                 options_length += (guint32)sizeof(struct option);
534         }
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;
551         }
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;
562                 option.type = OPT_ENDOFOPT;
563                 option.value_length = 0;
564                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
565                         return FALSE;
566         }
567         if (options_length != 0) {
568                 /* write end of options */
569                 option.type = OPT_ENDOFOPT;
570                 option.value_length = 0;
571                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
572                         return FALSE;
573         }
574
575        return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
576 }
577
578 gboolean
579 pcapng_write_interface_statistics_block(FILE* pfile,
580                                         guint32 interface_id,
581                                         guint64 *bytes_written,
582                                         const char *comment,   /* OPT_COMMENT           1 */
583                                         guint64 isb_starttime, /* ISB_STARTTIME         2 */
584                                         guint64 isb_endtime,   /* ISB_ENDTIME           3 */
585                                         guint64 isb_ifrecv,    /* ISB_IFRECV            4 */
586                                         guint64 isb_ifdrop,    /* ISB_IFDROP            5 */
587                                         int *err)
588 {
589         struct isb isb;
590 #ifdef _WIN32
591         FILETIME now;
592 #else
593         struct timeval now;
594 #endif
595         struct option option;
596         guint32 block_total_length;
597         guint32 options_length;
598         guint64 timestamp;
599
600 #ifdef _WIN32
601         /*
602          * Current time, represented as 100-nanosecond intervals since
603          * January 1, 1601, 00:00:00 UTC.
604          *
605          * I think DWORD might be signed, so cast both parts of "now"
606          * to guint32 so that the sign bit doesn't get treated specially.
607          *
608          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
609          * might want to use instead.
610          */
611         GetSystemTimeAsFileTime(&now);
612         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
613                     (guint32)now.dwLowDateTime;
614
615         /*
616          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
617          * intervals.
618          */
619         timestamp /= 10;
620
621         /*
622          * Subtract difference, in microseconds, between January 1, 1601
623          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
624          */
625         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
626 #else
627         /*
628          * Current time, represented as seconds and microseconds since
629          * January 1, 1970, 00:00:00 UTC.
630          */
631         gettimeofday(&now, NULL);
632
633         /*
634          * Convert to delta in microseconds.
635          */
636         timestamp = (guint64)(now.tv_sec) * 1000000 +
637                     (guint64)(now.tv_usec);
638 #endif
639         block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));
640         options_length = 0;
641         if (isb_ifrecv != G_MAXUINT64) {
642                 options_length += (guint32)(sizeof(struct option) +
643                                             sizeof(guint64));
644         }
645         if (isb_ifdrop != G_MAXUINT64) {
646                 options_length += (guint32)(sizeof(struct option) +
647                                             sizeof(guint64));
648         }
649         /* OPT_COMMENT */
650         options_length += pcapng_count_string_option(comment);
651         if (isb_starttime !=0) {
652                 options_length += (guint32)(sizeof(struct option) +
653                                             sizeof(guint64)); /* ISB_STARTTIME */
654         }
655         if (isb_endtime !=0) {
656                 options_length += (guint32)(sizeof(struct option) +
657                                             sizeof(guint64)); /* ISB_ENDTIME */
658         }
659         /* If we have options add size of end-of-options */
660         if (options_length != 0) {
661                 options_length += (guint32)sizeof(struct option);
662         }
663         block_total_length += options_length;
664
665         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
666         isb.block_total_length = block_total_length;
667         isb.interface_id = interface_id;
668         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
669         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
670         if (!write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))
671                 return FALSE;
672
673         /* write comment string if applicable */
674         if (!pcapng_write_string_option(pfile, OPT_COMMENT, comment,
675                                         bytes_written, err))
676                 return FALSE;
677
678         if (isb_starttime !=0) {
679                 guint32 high, low;
680
681                 option.type = ISB_STARTTIME;
682                 option.value_length = sizeof(guint64);
683                 high = (guint32)((isb_starttime>>32) & 0xffffffff);
684                 low = (guint32)(isb_starttime & 0xffffffff);
685                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
686                         return FALSE;
687
688                 if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
689                         return FALSE;
690
691                 if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
692                         return FALSE;
693         }
694         if (isb_endtime !=0) {
695                 guint32 high, low;
696
697                 option.type = ISB_ENDTIME;
698                 option.value_length = sizeof(guint64);
699                 high = (guint32)((isb_endtime>>32) & 0xffffffff);
700                 low = (guint32)(isb_endtime & 0xffffffff);
701                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
702                         return FALSE;
703
704                 if (!write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
705                         return FALSE;
706
707                 if (!write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
708                         return FALSE;
709         }
710         if (isb_ifrecv != G_MAXUINT64) {
711                 option.type = ISB_IFRECV;
712                 option.value_length = sizeof(guint64);
713                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
714                         return FALSE;
715
716                 if (!write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))
717                         return FALSE;
718         }
719         if (isb_ifdrop != G_MAXUINT64) {
720                 option.type = ISB_IFDROP;
721                 option.value_length = sizeof(guint64);
722                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
723                         return FALSE;
724
725                 if (!write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))
726                         return FALSE;
727         }
728         if (options_length != 0) {
729                 /* write end of options */
730                 option.type = OPT_ENDOFOPT;
731                 option.value_length = 0;
732                 if (!write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
733                         return FALSE;
734         }
735
736         return write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
737 }
738
739 /*
740  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
741  *
742  * Local variables:
743  * c-basic-offset: 4
744  * tab-width: 8
745  * indent-tabs-mode: nil
746  * End:
747  *
748  * vi: set shiftwidth=4 tabstop=8 expandtab:
749  * :indentSize=4:tabSize=8:noTabs=true:
750  */