We always write to a FILE *, so:
[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 libpcap_write_to_file(FILE* pfile,
184                       const guint8* data,
185                       size_t data_length,
186                       guint64 *bytes_written,
187                       int *err)
188 {
189         size_t nwritten;
190
191         nwritten = fwrite(data, data_length, 1, pfile);
192         if (nwritten != 1) {
193                 if (ferror(pfile)) {
194                         *err = errno;
195                 } else {
196                         *err = 0;
197                 }
198                 return FALSE;
199         }
200
201         (*bytes_written) += data_length;
202         return TRUE;
203 }
204
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*/
208 gboolean
209 libpcap_write_file_header(FILE* pfile, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err)
210 {
211         struct pcap_hdr file_hdr;
212
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;
221
222         return libpcap_write_to_file(pfile, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);
223 }
224
225 /* Write a record for a packet to a dump file.
226    Returns TRUE on success, FALSE on failure. */
227 gboolean
228 libpcap_write_packet(FILE* pfile,
229                      time_t sec, guint32 usec,
230                      guint32 caplen, guint32 len,
231                      const guint8 *pd,
232                      guint64 *bytes_written, int *err)
233 {
234         struct pcaprec_hdr rec_hdr;
235
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 (!libpcap_write_to_file(pfile, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))
241                 return FALSE;
242
243         return libpcap_write_to_file(pfile, pd, caplen, bytes_written, err);
244 }
245
246 static gboolean
247 write_string_option(FILE* pfile,
248                     guint16 option_type, const char *option_value,
249                     guint64 *bytes_written, int *err)
250 {
251         size_t option_value_length;
252         struct option option;
253         const guint32 padding = 0;
254
255         if (option_value == NULL)
256                 return TRUE; /* nothing to write */
257         option_value_length = strlen(option_value);
258         if ((option_value_length > 0) && (option_value_length < G_MAXUINT16)) {
259                 /* something to write */
260                 option.type = option_type;
261                 option.value_length = (guint16)option_value_length;
262
263                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
264                         return FALSE;
265
266                 if (!libpcap_write_to_file(pfile, (const guint8*)option_value, (int) option_value_length, bytes_written, err))
267                         return FALSE;
268
269                 if (option_value_length % 4) {
270                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - option_value_length % 4, bytes_written, err))
271                                 return FALSE;
272                 }
273         }
274         return TRUE;
275 }
276
277 gboolean
278 libpcap_write_session_header_block(FILE* pfile,
279                                    const char *comment,
280                                    const char *hw,
281                                    const char *os,
282                                    const char *appname,
283                                    guint64 section_length,
284                                    guint64 *bytes_written,
285                                    int *err)
286 {
287         struct shb shb;
288         struct option option;
289         guint32 block_total_length;
290         gboolean have_options = FALSE;
291
292         /* Size of base header */
293         block_total_length = sizeof(struct shb) +
294                              sizeof(guint32);
295         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
296                 block_total_length += (guint32)(sizeof(struct option) +
297                                                 (guint16)ADD_PADDING(strlen(comment)));
298                 have_options = TRUE;
299         }
300         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
301                 block_total_length += (guint32)(sizeof(struct option) +
302                                                 (guint16)ADD_PADDING(strlen(hw)));
303                 have_options = TRUE;
304         }
305         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
306                 block_total_length += (guint32)(sizeof(struct option) +
307                                                 (guint16)ADD_PADDING(strlen(os)));
308                 have_options = TRUE;
309         }
310         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
311                 block_total_length += (guint32)(sizeof(struct option) +
312                                                 (guint16)ADD_PADDING(strlen(appname)));
313                 have_options = TRUE;
314         }
315         /* If we have options add size of end-of-options */
316         if (have_options) {
317                 block_total_length += (guint32)sizeof(struct option);
318         }
319         /* write shb header */
320         shb.block_type = SECTION_HEADER_BLOCK_TYPE;
321         shb.block_total_length = block_total_length;
322         shb.byte_order_magic = PCAPNG_MAGIC;
323         shb.major_version = PCAPNG_MAJOR_VERSION;
324         shb.minor_version = PCAPNG_MINOR_VERSION;
325         shb.section_length = section_length;
326
327         if (!libpcap_write_to_file(pfile, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
328                 return FALSE;
329
330         if (!write_string_option(pfile, OPT_COMMENT, comment,
331                                  bytes_written, err))
332                 return FALSE;
333         if (!write_string_option(pfile, SHB_HARDWARE, hw,
334                                  bytes_written, err))
335                 return FALSE;
336         if (!write_string_option(pfile, SHB_OS, os,
337                                  bytes_written, err))
338                 return FALSE;
339         if (!write_string_option(pfile, SHB_USERAPPL, appname,
340                                  bytes_written, err))
341                 return FALSE;
342         if (have_options) {
343                 /* write end of options */
344                 option.type = OPT_ENDOFOPT;
345                 option.value_length = 0;
346                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
347                         return FALSE;
348         }
349
350         /* write the trailing block total length */
351         return libpcap_write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
352 }
353
354 gboolean
355 libpcap_write_interface_description_block(FILE* pfile,
356                                           const char *comment, /* OPT_COMMENT        1 */
357                                           const char *name,    /* IDB_NAME           2 */
358                                           const char *descr,   /* IDB_DESCRIPTION    3 */
359                                           const char *filter,  /* IDB_FILTER        11 */
360                                           const char *os,      /* IDB_OS            12 */
361                                           int link_type,
362                                           int snap_len,
363                                           guint64 *bytes_written,
364                                           guint64 if_speed,    /* IDB_IF_SPEED       8 */
365                                           guint8 tsresol,      /* IDB_TSRESOL        9 */
366                                           int *err)
367 {
368         struct idb idb;
369         struct option option;
370         guint32 block_total_length;
371         const guint32 padding = 0;
372         gboolean have_options = FALSE;
373
374         block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32));
375         /* 01 - OPT_COMMENT */
376         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
377                 block_total_length += (guint32)(sizeof(struct option) +
378                                                 (guint16)ADD_PADDING(strlen(comment)));
379                 have_options = TRUE;
380         }
381
382         /* 02 - IDB_NAME */
383         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
384                 block_total_length += (guint32)(sizeof(struct option) +
385                                                 (guint16)ADD_PADDING(strlen(name)));
386                 have_options = TRUE;
387         }
388
389         /* 03 - IDB_DESCRIPTION */
390         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
391                 block_total_length += (guint32)(sizeof(struct option) +
392                                                 (guint16)ADD_PADDING(strlen(descr)));
393                 have_options = TRUE;
394         }
395
396         /* 08 - IDB_IF_SPEED */
397         if (if_speed != 0) {
398                 block_total_length += (guint32)(sizeof(struct option) +
399                                                 sizeof(guint64));
400                 have_options = TRUE;
401         }
402
403         /* 09 - IDB_TSRESOL */
404         if (tsresol != 0) {
405                 block_total_length += (guint32)(sizeof(struct option) +
406                                                 sizeof(struct option));
407                 have_options = TRUE;
408         }
409
410         /* 11 - IDB_FILTER */
411         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
412                 block_total_length += (guint32)(sizeof(struct option) +
413                                                 (guint16)(ADD_PADDING(strlen(filter)+ 1)));
414                 have_options = TRUE;
415         }
416
417         /* 12 - IDB_OS */
418         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
419                 block_total_length += (guint32)(sizeof(struct option) +
420                                                 (guint16)ADD_PADDING(strlen(os)));
421                 have_options = TRUE;
422         }
423
424         /* If we have options add size of end-of-options */
425         if (have_options) {
426                 block_total_length += (guint32)sizeof(struct option);
427         }
428
429         /* write block header */
430         idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
431         idb.block_total_length = block_total_length;
432         idb.link_type = link_type;
433         idb.reserved = 0;
434         idb.snap_len = snap_len;
435         if (!libpcap_write_to_file(pfile, (const guint8*)&idb, sizeof(struct idb), bytes_written, err))
436                 return FALSE;
437
438         /* 01 - OPT_COMMENT - write comment string if applicable */
439         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
440                 option.type = OPT_COMMENT;
441                 option.value_length = (guint16)strlen(comment);
442
443                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
444                         return FALSE;
445
446                 if (!libpcap_write_to_file(pfile, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
447                         return FALSE;
448
449                 if (strlen(comment) % 4) {
450                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
451                                 return FALSE;
452                 }
453         }
454
455         /* 02 - IDB_NAME - write interface name string if applicable */
456         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
457                 option.type = IDB_NAME;
458                 option.value_length = (guint16)strlen(name);
459
460                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
461                         return FALSE;
462
463                 if (!libpcap_write_to_file(pfile, (const guint8*)name, (int) strlen(name), bytes_written, err))
464                         return FALSE;
465
466                 if (strlen(name) % 4) {
467                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - strlen(name) % 4, bytes_written, err))
468                                 return FALSE;
469                 }
470         }
471
472         /* 03 - IDB_DESCRIPTION */
473         /* write interface description string if applicable */
474         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
475                 option.type = IDB_DESCRIPTION;
476                 option.value_length = (guint16)strlen(descr);
477
478                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
479                         return FALSE;
480
481                 if (!libpcap_write_to_file(pfile, (const guint8*)descr, (int) strlen(descr), bytes_written, err))
482                         return FALSE;
483
484                 if (strlen(descr) % 4) {
485                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - strlen(descr) % 4, bytes_written, err))
486                                 return FALSE;
487                 }
488         }
489
490         /* 08 - IDB_IF_SPEED */
491         if (if_speed != 0) {
492                 option.type = IDB_IF_SPEED;
493                 option.value_length = sizeof(guint64);
494
495                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
496                         return FALSE;
497
498                 if (!libpcap_write_to_file(pfile, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))
499                         return FALSE;
500         }
501
502         /* 09 - IDB_TSRESOL */
503         if (tsresol != 0) {
504                 option.type = IDB_TSRESOL;
505                 option.value_length = sizeof(guint8);
506
507                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
508                         return FALSE;
509
510                 if (!libpcap_write_to_file(pfile, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))
511                         return FALSE;
512
513                 if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 3, bytes_written, err))
514                         return FALSE;
515         }
516
517         /* 11 - IDB_FILTER - write filter string if applicable
518          * We only write version 1 of the filter, libpcap string
519          */
520         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
521                 option.type = IDB_FILTER;
522                 option.value_length = (guint16)(strlen(filter) + 1 );
523                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
524                         return FALSE;
525
526                 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
527                 if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 1, bytes_written, err))
528                         return FALSE;
529                 if (!libpcap_write_to_file(pfile, (const guint8*)filter, (int) strlen(filter), bytes_written, err))
530                         return FALSE;
531                 if ((strlen(filter) + 1) % 4) {
532                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
533                                 return FALSE;
534                 }
535         }
536
537         /* 12 - IDB_OS - write os string if applicable */
538         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
539                 option.type = IDB_OS;
540                 option.value_length = (guint16)strlen(os);
541                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
542                         return FALSE;
543                 if (!libpcap_write_to_file(pfile, (const guint8*)os, (int) strlen(os), bytes_written, err))
544                         return FALSE;
545                 if (strlen(os) % 4) {
546                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - strlen(os) % 4, bytes_written, err))
547                                 return FALSE;
548                 }
549         }
550
551         if (have_options) {
552                 /* write end of options */
553                 option.type = OPT_ENDOFOPT;
554                 option.value_length = 0;
555                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
556                         return FALSE;
557         }
558
559         /* write the trailing Block Total Length */
560         return libpcap_write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
561 }
562
563 /* Write a record for a packet to a dump file.
564    Returns TRUE on success, FALSE on failure. */
565 gboolean
566 libpcap_write_enhanced_packet_block(FILE* pfile,
567                                     const char *comment,
568                                     time_t sec, guint32 usec,
569                                     guint32 caplen, guint32 len,
570                                     guint32 interface_id,
571                                     guint ts_mul,
572                                     const guint8 *pd,
573                                     guint32 flags,
574                                     guint64 *bytes_written,
575                                     int *err)
576 {
577         struct epb epb;
578         struct option option;
579         guint32 block_total_length;
580         guint64 timestamp;
581         gboolean have_options = FALSE;
582         const guint32 padding = 0;
583
584         block_total_length = (guint32)(sizeof(struct epb) +
585                                        ADD_PADDING(caplen) +
586                                        sizeof(guint32));
587         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
588                 block_total_length += (guint32)(sizeof(struct option) +
589                                                 (guint16)ADD_PADDING(strlen(comment)));
590                 have_options = TRUE;
591         }
592         if (flags != 0) {
593                 block_total_length += (guint32)(sizeof(struct option) +
594                                                 sizeof(guint32));
595                 have_options = TRUE;
596         }
597         /* If we have options add size of end-of-options */
598         if (have_options) {
599                 block_total_length += (guint32)sizeof(struct option);
600         }
601         timestamp = (guint64)sec * ts_mul + (guint64)usec;
602         epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
603         epb.block_total_length = block_total_length;
604         epb.interface_id = interface_id;
605         epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
606         epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
607         epb.captured_len = caplen;
608         epb.packet_len = len;
609         if (!libpcap_write_to_file(pfile, (const guint8*)&epb, sizeof(struct epb), bytes_written, err))
610                 return FALSE;
611         if (!libpcap_write_to_file(pfile, pd, caplen, bytes_written, err))
612                 return FALSE;
613         if (caplen % 4) {
614                 if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err))
615                         return FALSE;
616         }
617         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
618                 option.type = OPT_COMMENT;
619                 option.value_length = (guint16)strlen(comment);
620
621                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
622                         return FALSE;
623
624                 if (!libpcap_write_to_file(pfile, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
625                         return FALSE;
626
627                 if (strlen(comment) % 4) {
628                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
629                                 return FALSE;
630                 }
631         }
632         if (flags != 0) {
633                 option.type = EPB_FLAGS;
634                 option.value_length = sizeof(guint32);
635                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
636                         return FALSE;
637                 if (!libpcap_write_to_file(pfile, (const guint8*)&flags, sizeof(guint32), bytes_written, err))
638                         return FALSE;
639                 option.type = OPT_ENDOFOPT;
640                 option.value_length = 0;
641                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
642                         return FALSE;
643        }
644
645        return libpcap_write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
646 }
647
648 gboolean
649 libpcap_write_interface_statistics_block(FILE* pfile,
650                                          guint32 interface_id,
651                                          guint64 *bytes_written,
652                                          const char *comment,   /* OPT_COMMENT           1 */
653                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
654                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
655                                          guint64 isb_ifrecv,    /* ISB_IFRECV            4 */
656                                          guint64 isb_ifdrop,    /* ISB_IFDROP            5 */
657                                          int *err)
658 {
659         struct isb isb;
660 #ifdef _WIN32
661         FILETIME now;
662 #else
663         struct timeval now;
664 #endif
665         struct option option;
666         guint32 block_total_length;
667         guint64 timestamp;
668         gboolean have_options = FALSE;
669         const guint32 padding = 0;
670 #ifdef _WIN32
671         /*
672          * Current time, represented as 100-nanosecond intervals since
673          * January 1, 1601, 00:00:00 UTC.
674          *
675          * I think DWORD might be signed, so cast both parts of "now"
676          * to guint32 so that the sign bit doesn't get treated specially.
677          *
678          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
679          * might want to use instead.
680          */
681         GetSystemTimeAsFileTime(&now);
682         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
683                     (guint32)now.dwLowDateTime;
684
685         /*
686          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
687          * intervals.
688          */
689         timestamp /= 10;
690
691         /*
692          * Subtract difference, in microseconds, between January 1, 1601
693          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
694          */
695         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
696 #else
697         /*
698          * Current time, represented as seconds and microseconds since
699          * January 1, 1970, 00:00:00 UTC.
700          */
701         gettimeofday(&now, NULL);
702
703         /*
704          * Convert to delta in microseconds.
705          */
706         timestamp = (guint64)(now.tv_sec) * 1000000 +
707                     (guint64)(now.tv_usec);
708 #endif
709         block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));
710         if (isb_ifrecv != G_MAXUINT64) {
711                 block_total_length += (guint32)(sizeof(struct option) +
712                                                 sizeof(guint64));
713                 have_options = TRUE;
714         }
715         if (isb_ifdrop != G_MAXUINT64) {
716                 block_total_length += (guint32)(sizeof(struct option) +
717                                                 sizeof(guint64));
718                 have_options = TRUE;
719         }
720         /* OPT_COMMENT */
721         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
722                 block_total_length += (guint32)(sizeof(struct option) +
723                                       (guint16)ADD_PADDING(strlen(comment)));
724                 have_options = TRUE;
725         }
726         if (isb_starttime !=0) {
727                 block_total_length += (guint32)(sizeof(struct option) +
728                                       sizeof(guint64)); /* ISB_STARTTIME */
729                 have_options = TRUE;
730         }
731         if (isb_endtime !=0) {
732                 block_total_length += (guint32)(sizeof(struct option) +
733                                       sizeof(guint64)); /* ISB_ENDTIME */
734                 have_options = TRUE;
735         }
736         /* If we have options add size of end-of-options */
737         if (have_options) {
738                 block_total_length += (guint32)sizeof(struct option);
739         }
740
741         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
742         isb.block_total_length = block_total_length;
743         isb.interface_id = interface_id;
744         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
745         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
746         if (!libpcap_write_to_file(pfile, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))
747                 return FALSE;
748
749         /* write comment string if applicable */
750         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
751                 option.type = OPT_COMMENT;
752                 option.value_length = (guint16)strlen(comment);
753                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
754                         return FALSE;
755
756                 if (!libpcap_write_to_file(pfile, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
757                         return FALSE;
758
759                 if (strlen(comment) % 4) {
760                         if (!libpcap_write_to_file(pfile, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
761                                 return FALSE;
762                 }
763         }
764
765         if (isb_starttime !=0) {
766                 guint32 high, low;
767
768                 option.type = ISB_STARTTIME;
769                 option.value_length = sizeof(guint64);
770                 high = (guint32)((isb_starttime>>32) & 0xffffffff);
771                 low = (guint32)(isb_starttime & 0xffffffff);
772                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
773                         return FALSE;
774
775                 if (!libpcap_write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
776                         return FALSE;
777
778                 if (!libpcap_write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
779                         return FALSE;
780         }
781         if (isb_endtime !=0) {
782                 guint32 high, low;
783
784                 option.type = ISB_ENDTIME;
785                 option.value_length = sizeof(guint64);
786                 high = (guint32)((isb_endtime>>32) & 0xffffffff);
787                 low = (guint32)(isb_endtime & 0xffffffff);
788                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
789                         return FALSE;
790
791                 if (!libpcap_write_to_file(pfile, (const guint8*)&high, sizeof(guint32), bytes_written, err))
792                         return FALSE;
793
794                 if (!libpcap_write_to_file(pfile, (const guint8*)&low, sizeof(guint32), bytes_written, err))
795                         return FALSE;
796         }
797         if (isb_ifrecv != G_MAXUINT64) {
798                 option.type = ISB_IFRECV;
799                 option.value_length = sizeof(guint64);
800                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
801                         return FALSE;
802
803                 if (!libpcap_write_to_file(pfile, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))
804                         return FALSE;
805         }
806         if (isb_ifdrop != G_MAXUINT64) {
807                 option.type = ISB_IFDROP;
808                 option.value_length = sizeof(guint64);
809                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
810                         return FALSE;
811
812                 if (!libpcap_write_to_file(pfile, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))
813                         return FALSE;
814         }
815         if (have_options) {
816                 /* write end of options */
817                 option.type = OPT_ENDOFOPT;
818                 option.value_length = 0;
819                 if (!libpcap_write_to_file(pfile, (const guint8*)&option, sizeof(struct option), bytes_written, err))
820                         return FALSE;
821         }
822
823         return libpcap_write_to_file(pfile, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
824 }
825
826 /*
827  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
828  *
829  * Local variables:
830  * c-basic-offset: 4
831  * tab-width: 8
832  * indent-tabs-mode: nil
833  * End:
834  *
835  * vi: set shiftwidth=4 tabstop=8 expandtab:
836  * :indentSize=4:tabSize=8:noTabs=true:
837  */