Add a note about using GetSystemTimePreciseAsFileTime.
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #ifdef HAVE_LIBPCAP
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <errno.h>
52 #include <string.h>
53
54 #include <pcap.h>
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 SHB_HARDWARE      2 /* currently not used */
163 #define SHB_OS            3
164 #define SHB_USERAPPL      4
165 #define IDB_NAME          2
166 #define IDB_DESCRIPTION   3
167 #define IDB_IF_SPEED      8
168 #define IDB_TSRESOL       9
169 #define IDB_FILTER       11
170 #define IDB_OS           12
171 #define ISB_STARTTIME     2
172 #define ISB_ENDTIME       3
173 #define ISB_IFRECV        4
174 #define ISB_IFDROP        5
175 #define ISB_FILTERACCEPT  6
176 #define ISB_OSDROP        7
177 #define ISB_USRDELIV      8
178 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
179
180 #define WRITE_DATA(file_pointer, data_pointer, data_length, written_length, error_pointer) \
181 {                                                                                          \
182         do {                                                                               \
183                 size_t nwritten;                                                           \
184                                                                                            \
185                 nwritten = fwrite(data_pointer, 1, data_length, file_pointer);             \
186                 if (nwritten != data_length) {                                             \
187                         if (nwritten == 0 && ferror(file_pointer)) {                       \
188                                 *error_pointer = errno;                                    \
189                         } else {                                                           \
190                                 *error_pointer = 0;                                        \
191                         }                                                                  \
192                         return FALSE;                                                      \
193                 }                                                                          \
194                 written_length += (long)nwritten;                                          \
195         } while (0);                                                                       \
196 }
197
198 /* Returns a FILE * to write to on success, NULL on failure */
199 FILE *
200 libpcap_fdopen(int fd, int *err)
201 {
202         FILE *fp;
203
204         fp = fdopen(fd, "wb");
205         if (fp == NULL) {
206                 *err = errno;
207         }
208         return fp;
209 }
210
211 /* Write the file header to a dump file.
212    Returns TRUE on success, FALSE on failure.
213    Sets "*err" to an error code, or 0 for a short write, on failure*/
214 gboolean
215 libpcap_write_file_header(FILE *fp, int linktype, int snaplen, long *bytes_written, int *err)
216 {
217         struct pcap_hdr file_hdr;
218         size_t nwritten;
219
220         file_hdr.magic = PCAP_MAGIC;
221         /* current "libpcap" format is 2.4 */
222         file_hdr.version_major = 2;
223         file_hdr.version_minor = 4;
224         file_hdr.thiszone = 0;  /* XXX - current offset? */
225         file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
226         file_hdr.snaplen = snaplen;
227         file_hdr.network = linktype;
228         nwritten = fwrite(&file_hdr, 1, sizeof(file_hdr), fp);
229         if (nwritten != sizeof(file_hdr)) {
230                 if (nwritten == 0 && ferror(fp))
231                         *err = errno;
232                 else
233                         *err = 0;       /* short write */
234                 return FALSE;
235         }
236         *bytes_written += sizeof(file_hdr);
237
238         return TRUE;
239 }
240
241 /* Write a record for a packet to a dump file.
242    Returns TRUE on success, FALSE on failure. */
243 gboolean
244 libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
245     long *bytes_written, int *err)
246 {
247         struct pcaprec_hdr rec_hdr;
248         size_t nwritten;
249
250         rec_hdr.ts_sec = phdr->ts.tv_sec;
251         rec_hdr.ts_usec = phdr->ts.tv_usec;
252         rec_hdr.incl_len = phdr->caplen;
253         rec_hdr.orig_len = phdr->len;
254         nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
255         if (nwritten != sizeof rec_hdr) {
256                 if (nwritten == 0 && ferror(fp))
257                         *err = errno;
258                 else
259                         *err = 0;       /* short write */
260                 return FALSE;
261         }
262         *bytes_written += sizeof rec_hdr;
263
264         nwritten = fwrite(pd, 1, phdr->caplen, fp);
265         if (nwritten != phdr->caplen) {
266                 if (nwritten == 0 && ferror(fp))
267                         *err = errno;
268                 else
269                         *err = 0;       /* short write */
270                 return FALSE;
271         }
272         *bytes_written += phdr->caplen;
273         return TRUE;
274 }
275
276 gboolean
277 libpcap_write_session_header_block(FILE *fp,
278                                    const char *comment,
279                                    const char *hw,
280                                    const char *os,
281                                    const char *appname,
282                                    guint64 section_length,
283                                    long *bytes_written,
284                                    int *err)
285 {
286         struct shb shb;
287         struct option option;
288         guint32 block_total_length;
289         const guint32 padding = 0;
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 += sizeof(struct option) +
297                                       (guint16)(ADD_PADDING(strlen(comment) + 1));
298                 have_options = TRUE;
299         }
300         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
301                 block_total_length += sizeof(struct option) +
302                                       (guint16)(ADD_PADDING(strlen(hw) + 1));
303                 have_options = TRUE;
304         }
305         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
306                 block_total_length += sizeof(struct option) +
307                                       (guint16)(ADD_PADDING(strlen(os) + 1));
308                 have_options = TRUE;
309         }
310         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
311                 block_total_length += sizeof(struct option) +
312                                       (guint16)(ADD_PADDING(strlen(appname) + 1));
313                 have_options = TRUE;
314         }
315         /* If we have options add size of end-of-options */
316         if (have_options) {
317                 block_total_length += 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         WRITE_DATA(fp, &shb, sizeof(struct shb), *bytes_written, err);
327
328         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
329                 /* write opt_comment options */
330                 option.type = OPT_COMMENT;
331                 option.value_length = (guint16)(strlen(comment) + 1);
332                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
333                 WRITE_DATA(fp, comment, strlen(comment) + 1, *bytes_written, err);
334                 if ((strlen(comment) + 1) % 4) {
335                         WRITE_DATA(fp, &padding, 4 - (strlen(comment) + 1) % 4, *bytes_written, err);
336                 }
337         }
338         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
339                 /* write shb_hardware options */
340                 option.type = SHB_HARDWARE;
341                 option.value_length = (guint16)(strlen(hw) + 1);
342                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
343                 WRITE_DATA(fp, hw, strlen(hw) + 1, *bytes_written, err);
344                 if ((strlen(hw) + 1) % 4) {
345                         WRITE_DATA(fp, &padding, 4 - (strlen(hw) + 1) % 4, *bytes_written, err);
346                 }
347         }
348         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
349                 /* write shb_os options */
350                 option.type = SHB_OS;
351                 option.value_length = (guint16)(strlen(os) + 1);
352                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
353                 WRITE_DATA(fp, os, strlen(os) + 1, *bytes_written, err);
354                 if ((strlen(os) + 1) % 4) {
355                         WRITE_DATA(fp, &padding, 4 - (strlen(os) + 1) % 4, *bytes_written, err);
356                 }
357         }
358         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
359                 /* write shb_userappl options */
360                 option.type = SHB_USERAPPL;
361                 option.value_length = (guint16)(strlen(appname) + 1);
362                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
363                 WRITE_DATA(fp, appname, strlen(appname) + 1, *bytes_written, err);
364                 if ((strlen(appname) + 1) % 4) {
365                         WRITE_DATA(fp, &padding, 4 - (strlen(appname) + 1) % 4, *bytes_written, err);
366                 }
367         }
368         if (have_options) {
369                 /* write end of options */
370                 option.type = OPT_ENDOFOPT;
371                 option.value_length = 0;
372                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
373         }
374
375         /* write the trailing block total length */
376         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
377         return TRUE;
378 }
379
380 gboolean
381 libpcap_write_interface_description_block(FILE *fp,
382                                           const char *comment, /* OPT_COMMENT        1 */
383                                           const char *name,    /* IDB_NAME           2 */
384                                           const char *descr,   /* IDB_DESCRIPTION    3 */
385                                           const char *filter,  /* IDB_FILTER        11 */
386                                           const char *os,      /* IDB_OS            12 */
387                                           int link_type,
388                                           int snap_len,
389                                           long *bytes_written,
390                                           guint64 if_speed,    /* IDB_IF_SPEED       8 */
391                                           guint8 tsresol,      /* IDB_TSRESOL        9 */
392                                           int *err)
393 {
394         struct idb idb;
395         struct option option;
396         guint32 block_total_length;
397         const guint32 padding = 0;
398         gboolean have_options = FALSE;
399
400         block_total_length = sizeof(struct idb) + sizeof(guint32);
401         /* OPT_COMMENT */
402         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
403                 block_total_length += sizeof(struct option) +
404                                       (guint16)(ADD_PADDING(strlen(comment) + 1));
405                 have_options = TRUE;
406         }
407
408         /* IDB_DESCRIPTION */
409         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
410                 block_total_length += sizeof(struct option) +
411                                       (guint16)(ADD_PADDING(strlen(descr) + 1));
412                 have_options = TRUE;
413         }
414
415         /* IDB_NAME */
416         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
417                 block_total_length += sizeof(struct option) +
418                                       (guint16)(ADD_PADDING(strlen(name) + 1));
419                 have_options = TRUE;
420         }
421
422         /* IDB_FILTER */
423         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
424                 block_total_length += sizeof(struct option) +
425                                       (guint16)(ADD_PADDING(strlen(filter) + 1)+1);
426                 have_options = TRUE;
427         }
428
429         /* IDB_OS */
430         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
431                 block_total_length += sizeof(struct option) +
432                                      (guint16)(ADD_PADDING(strlen(os) + 1));
433                 have_options = TRUE;
434         }
435
436         /* IDB_IF_SPEED       8 */
437         if (if_speed != 0) {
438                 block_total_length += sizeof(struct option) + sizeof(guint64);
439                 have_options = TRUE;
440         }
441
442         /* IDB_TSRESOL        9 */
443         if (tsresol != 0) {
444                 block_total_length += sizeof(struct option) + sizeof(struct option);
445                 have_options = TRUE;
446         }
447
448         /* If we have options add size of end-of-options */
449         if (have_options) {
450                 block_total_length += sizeof(struct option);
451         }
452
453         /* write block header */
454         idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
455         idb.block_total_length = block_total_length;
456         idb.link_type = link_type;
457         idb.reserved = 0;
458         idb.snap_len = snap_len;
459         WRITE_DATA(fp, &idb, sizeof(struct idb), *bytes_written, err);
460
461         /* write comment string if applicable */
462         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
463                 option.type = OPT_COMMENT;
464                 option.value_length = (guint16)(strlen(comment) + 1);
465                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
466                 WRITE_DATA(fp, comment, strlen(comment) + 1, *bytes_written, err);
467                 if ((strlen(comment) + 1) % 4) {
468                         WRITE_DATA(fp, &padding, 4 - (strlen(comment) + 1) % 4 , *bytes_written, err);
469                 }
470         }
471
472         /* write interface name string if applicable */
473         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
474                 option.type = IDB_NAME;
475                 option.value_length = (guint16)(strlen(name) + 1);
476                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
477                 WRITE_DATA(fp, name, strlen(name) + 1, *bytes_written, err);
478                 if ((strlen(name) + 1) % 4) {
479                         WRITE_DATA(fp, &padding, 4 - (strlen(name) + 1) % 4 , *bytes_written, err);
480                 }
481         }
482
483         /* write interface description string if applicable */
484         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
485                 option.type = IDB_DESCRIPTION;
486                 option.value_length = (guint16)(strlen(descr) + 1);
487                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
488                 WRITE_DATA(fp, name, strlen(descr) + 1, *bytes_written, err);
489                 if ((strlen(descr) + 1) % 4) {
490                         WRITE_DATA(fp, &padding, 4 - (strlen(descr) + 1) % 4 , *bytes_written, err);
491                 }
492         }
493
494         /* write filter string if applicable
495          * We only write version 1 of the filter, libpcap string
496          */
497         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
498                 option.type = IDB_FILTER;
499                 option.value_length = (guint16)(strlen(filter) + 1 + 1 );
500                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
501
502                 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
503                 WRITE_DATA(fp, &padding, 1, *bytes_written, err);
504                 WRITE_DATA(fp, filter, strlen(filter) + 1, *bytes_written, err);
505                 if ((strlen(filter) + 2) % 4) {
506                         WRITE_DATA(fp, &padding, 4 - (strlen(filter) + 2) % 4 , *bytes_written, err);
507                 }
508         }
509
510         /* write os string if applicable */
511         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
512                 option.type = IDB_OS;
513                 option.value_length = (guint16)(strlen(os) + 1);
514                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
515                 WRITE_DATA(fp, os, strlen(os) + 1, *bytes_written, err);
516                 if ((strlen(os) + 1) % 4) {
517                         WRITE_DATA(fp, &padding, 4 - (strlen(os) + 1) % 4 , *bytes_written, err);
518                 }
519         }
520
521         /* IDB_IF_SPEED       8 */
522         if (if_speed != 0) {
523                 option.type = IDB_IF_SPEED;
524                 option.value_length = sizeof(guint64);
525                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
526                 WRITE_DATA(fp, &if_speed, sizeof(guint64), *bytes_written, err);
527         }
528
529         /* IDB_TSRESOL        9 */
530         if (tsresol != 0) {
531                 option.type = IDB_TSRESOL;
532                 option.value_length = sizeof(guint8);
533                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
534                 WRITE_DATA(fp, &tsresol, sizeof(guint8), *bytes_written, err);
535                 WRITE_DATA(fp, &padding, 3 , *bytes_written, err);
536         }
537
538         if (have_options) {
539                 /* write end of options */
540                 option.type = OPT_ENDOFOPT;
541                 option.value_length = 0;
542                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
543         }
544
545         /* write the trailing Block Total Length */
546         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
547         return TRUE;
548 }
549
550 /* Write a record for a packet to a dump file.
551    Returns TRUE on success, FALSE on failure. */
552 gboolean
553 libpcap_write_enhanced_packet_block(FILE *fp,
554                                     const struct pcap_pkthdr *phdr,
555                                     guint32 interface_id,
556                                     const u_char *pd,
557                                     long *bytes_written,
558                                     int *err)
559 {
560         struct epb epb;
561         guint32 block_total_length;
562         guint64 timestamp;
563         const guint32 padding = 0;
564
565         block_total_length = sizeof(struct epb) +
566                              ADD_PADDING(phdr->caplen) +
567                              sizeof(guint32);
568         timestamp = (guint64)(phdr->ts.tv_sec) * 1000000 +
569                     (guint64)(phdr->ts.tv_usec);
570         epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
571         epb.block_total_length = block_total_length;
572         epb.interface_id = interface_id;
573         epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
574         epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
575         epb.captured_len = phdr->caplen;
576         epb.packet_len = phdr->len;
577         WRITE_DATA(fp, &epb, sizeof(struct epb), *bytes_written, err);
578         WRITE_DATA(fp, pd, phdr->caplen, *bytes_written, err);
579         if (phdr->caplen % 4) {
580                 WRITE_DATA(fp, &padding, 4 - phdr->caplen % 4, *bytes_written, err);
581         }
582         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
583         return TRUE;
584 }
585
586 gboolean
587 libpcap_write_interface_statistics_block(FILE *fp,
588                                          guint32 interface_id,
589                                          pcap_t *pd,
590                                          long *bytes_written,
591                                          const char *comment,   /* OPT_COMMENT           1 */
592                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
593                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
594                                          int *err)
595 {
596         struct isb isb;
597 #ifdef _WIN32
598         FILETIME now;
599 #else
600         struct timeval now;
601 #endif
602         struct option option;
603         struct pcap_stat stats;
604         guint32 block_total_length;
605         guint64 timestamp;
606         guint64 counter;
607         gboolean stats_retrieved;
608         gboolean have_options = FALSE;
609         const guint32 padding = 0;
610 #ifdef _WIN32
611         /*
612          * Current time, represented as 100-nanosecond intervals since
613          * January 1, 1601, 00:00:00 UTC.
614          *
615          * I think DWORD might be signed, so cast both parts of "now"
616          * to guint32 so that the sign bit doesn't get treated specially.
617          *
618          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
619          * might want to use instead.
620          */
621         GetSystemTimeAsFileTime(&now);
622         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
623                     (guint32)now.dwLowDateTime;
624
625         /*
626          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
627          * intervals.
628          */
629         timestamp /= 10;
630
631         /*
632          * Subtract difference, in microseconds, between January 1, 1601
633          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
634          */
635         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
636 #else
637         /*
638          * Current time, represented as seconds and microseconds since
639          * January 1, 1970, 00:00:00 UTC.
640          */
641         gettimeofday(&now, NULL);
642
643         /*
644          * Convert to delta in microseconds.
645          */
646         timestamp = (guint64)(now.tv_sec) * 1000000 +
647                     (guint64)(now.tv_usec);
648 #endif
649         if (pcap_stats(pd, &stats) < 0) {
650                 stats_retrieved = FALSE;
651                 g_warning("pcap_stats() failed.");
652         } else {
653                 stats_retrieved = TRUE;
654                 have_options = TRUE;
655         }
656         block_total_length = sizeof(struct isb) +
657                              sizeof(guint32);
658         if (stats_retrieved) {
659                 block_total_length += 2 * sizeof(struct option) + 2 * sizeof(guint64); /* ISB_IFRECV + ISB_IFDROP */
660         }
661         /* OPT_COMMENT */
662         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
663                 block_total_length += sizeof(struct option) +
664                                       (guint16)(ADD_PADDING(strlen(comment) + 1));
665                 have_options = TRUE;
666         }
667         if (isb_starttime !=0) {
668                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_STARTTIME */
669                 have_options = TRUE;
670         }
671         if (isb_endtime !=0) {
672                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_ENDTIME */
673                 have_options = TRUE;
674         }
675         /* If we have options add size of end-of-options */
676         if (have_options) {
677                 block_total_length += sizeof(struct option);
678         }
679
680         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
681         isb.block_total_length = block_total_length;
682         isb.interface_id = interface_id;
683         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
684         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
685         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
686
687         /* write comment string if applicable */
688         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
689                 option.type = OPT_COMMENT;
690                 option.value_length = (guint16)(strlen(comment) + 1);
691                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
692                 WRITE_DATA(fp, comment, strlen(comment) + 1, *bytes_written, err);
693                 if ((strlen(comment) + 1) % 4) {
694                         WRITE_DATA(fp, &padding, 4 - (strlen(comment) + 1) % 4 , *bytes_written, err);
695                 }
696         }
697
698         if (isb_starttime !=0) {
699                 option.type = ISB_STARTTIME;
700                 option.value_length = sizeof(guint64);
701                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
702                 WRITE_DATA(fp, &isb_starttime, sizeof(guint64), *bytes_written, err);
703         }
704         if (isb_endtime !=0) {
705                 option.type = ISB_ENDTIME;
706                 option.value_length = sizeof(guint64);
707                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
708                 WRITE_DATA(fp, &isb_endtime, sizeof(guint64), *bytes_written, err);
709         }
710         if (stats_retrieved) {
711                 /* */
712                 option.type = ISB_IFRECV;
713                 option.value_length = sizeof(guint64);
714                 counter = stats.ps_recv;
715                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
716                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
717                 /* */
718                 option.type = ISB_IFDROP;
719                 option.value_length = sizeof(guint64);
720                 counter = stats.ps_drop;
721                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
722                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
723         }
724         if (have_options) {
725                 /* write end of options */
726                 option.type = OPT_ENDOFOPT;
727                 option.value_length = 0;
728                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
729         }
730
731         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
732
733         return TRUE;
734 }
735
736 gboolean
737 libpcap_dump_flush(FILE *pd, int *err)
738 {
739         if (fflush(pd) == EOF) {
740                 if (err != NULL)
741                         *err = errno;
742                 return FALSE;
743         }
744         return TRUE;
745 }
746
747 gboolean
748 libpcap_dump_close(FILE *pd, int *err)
749 {
750         if (fclose(pd) == EOF) {
751                 if (err != NULL)
752                         *err = errno;
753                 return FALSE;
754         }
755         return TRUE;
756 }
757
758 #endif /* HAVE_LIBPCAP */