From Jose Pedro Oliveira:
[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         /* 01 - 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         /* 02 - IDB_NAME */
409         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
410                 block_total_length += sizeof(struct option) +
411                                       (guint16)(ADD_PADDING(strlen(name) + 1));
412                 have_options = TRUE;
413         }
414
415         /* 03 - IDB_DESCRIPTION */
416         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
417                 block_total_length += sizeof(struct option) +
418                                       (guint16)(ADD_PADDING(strlen(descr) + 1));
419                 have_options = TRUE;
420         }
421
422         /* 08 - IDB_IF_SPEED */
423         if (if_speed != 0) {
424                 block_total_length += sizeof(struct option) + sizeof(guint64);
425                 have_options = TRUE;
426         }
427
428         /* 09 - IDB_TSRESOL */
429         if (tsresol != 0) {
430                 block_total_length += sizeof(struct option) + sizeof(struct option);
431                 have_options = TRUE;
432         }
433
434         /* 11 - IDB_FILTER */
435         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
436                 block_total_length += sizeof(struct option) +
437                                       (guint16)(ADD_PADDING(strlen(filter) + 1 + 1));
438                 have_options = TRUE;
439         }
440
441         /* 12 - IDB_OS */
442         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
443                 block_total_length += sizeof(struct option) +
444                                      (guint16)(ADD_PADDING(strlen(os) + 1));
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         /* 01 - OPT_COMMENT - 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         /* 02 - IDB_NAME - 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         /* 03 - IDB_DESCRIPTION */
484         /* write interface description string if applicable */
485         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
486                 option.type = IDB_DESCRIPTION;
487                 option.value_length = (guint16)(strlen(descr) + 1);
488                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
489                 WRITE_DATA(fp, name, strlen(descr) + 1, *bytes_written, err);
490                 if ((strlen(descr) + 1) % 4) {
491                         WRITE_DATA(fp, &padding, 4 - (strlen(descr) + 1) % 4 , *bytes_written, err);
492                 }
493         }
494
495         /* 08 - IDB_IF_SPEED */
496         if (if_speed != 0) {
497                 option.type = IDB_IF_SPEED;
498                 option.value_length = sizeof(guint64);
499                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
500                 WRITE_DATA(fp, &if_speed, sizeof(guint64), *bytes_written, err);
501         }
502
503         /* 09 - IDB_TSRESOL */
504         if (tsresol != 0) {
505                 option.type = IDB_TSRESOL;
506                 option.value_length = sizeof(guint8);
507                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
508                 WRITE_DATA(fp, &tsresol, sizeof(guint8), *bytes_written, err);
509                 WRITE_DATA(fp, &padding, 3 , *bytes_written, err);
510         }
511
512         /* 11 - IDB_FILTER - write filter string if applicable
513          * We only write version 1 of the filter, libpcap string
514          */
515         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
516                 option.type = IDB_FILTER;
517                 option.value_length = (guint16)(strlen(filter) + 1 + 1 );
518                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
519
520                 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
521                 WRITE_DATA(fp, &padding, 1, *bytes_written, err);
522                 WRITE_DATA(fp, filter, strlen(filter) + 1, *bytes_written, err);
523                 if ((strlen(filter) + 2) % 4) {
524                         WRITE_DATA(fp, &padding, 4 - (strlen(filter) + 2) % 4 , *bytes_written, err);
525                 }
526         }
527
528         /* 12 - IDB_OS - write os string if applicable */
529         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
530                 option.type = IDB_OS;
531                 option.value_length = (guint16)(strlen(os) + 1);
532                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
533                 WRITE_DATA(fp, os, strlen(os) + 1, *bytes_written, err);
534                 if ((strlen(os) + 1) % 4) {
535                         WRITE_DATA(fp, &padding, 4 - (strlen(os) + 1) % 4 , *bytes_written, err);
536                 }
537         }
538
539         if (have_options) {
540                 /* write end of options */
541                 option.type = OPT_ENDOFOPT;
542                 option.value_length = 0;
543                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
544         }
545
546         /* write the trailing Block Total Length */
547         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
548         return TRUE;
549 }
550
551 /* Write a record for a packet to a dump file.
552    Returns TRUE on success, FALSE on failure. */
553 gboolean
554 libpcap_write_enhanced_packet_block(FILE *fp,
555                                     const struct pcap_pkthdr *phdr,
556                                     guint32 interface_id,
557                                     const u_char *pd,
558                                     long *bytes_written,
559                                     int *err)
560 {
561         struct epb epb;
562         guint32 block_total_length;
563         guint64 timestamp;
564         const guint32 padding = 0;
565
566         block_total_length = sizeof(struct epb) +
567                              ADD_PADDING(phdr->caplen) +
568                              sizeof(guint32);
569         timestamp = (guint64)(phdr->ts.tv_sec) * 1000000 +
570                     (guint64)(phdr->ts.tv_usec);
571         epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
572         epb.block_total_length = block_total_length;
573         epb.interface_id = interface_id;
574         epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
575         epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
576         epb.captured_len = phdr->caplen;
577         epb.packet_len = phdr->len;
578         WRITE_DATA(fp, &epb, sizeof(struct epb), *bytes_written, err);
579         WRITE_DATA(fp, pd, phdr->caplen, *bytes_written, err);
580         if (phdr->caplen % 4) {
581                 WRITE_DATA(fp, &padding, 4 - phdr->caplen % 4, *bytes_written, err);
582         }
583         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
584         return TRUE;
585 }
586
587 gboolean
588 libpcap_write_interface_statistics_block(FILE *fp,
589                                          guint32 interface_id,
590                                          pcap_t *pd,
591                                          long *bytes_written,
592                                          const char *comment,   /* OPT_COMMENT           1 */
593                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
594                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
595                                          int *err)
596 {
597         struct isb isb;
598 #ifdef _WIN32
599         FILETIME now;
600 #else
601         struct timeval now;
602 #endif
603         struct option option;
604         struct pcap_stat stats;
605         guint32 block_total_length;
606         guint64 timestamp;
607         guint64 counter;
608         gboolean stats_retrieved;
609         gboolean have_options = FALSE;
610         const guint32 padding = 0;
611 #ifdef _WIN32
612         /*
613          * Current time, represented as 100-nanosecond intervals since
614          * January 1, 1601, 00:00:00 UTC.
615          *
616          * I think DWORD might be signed, so cast both parts of "now"
617          * to guint32 so that the sign bit doesn't get treated specially.
618          *
619          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
620          * might want to use instead.
621          */
622         GetSystemTimeAsFileTime(&now);
623         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
624                     (guint32)now.dwLowDateTime;
625
626         /*
627          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
628          * intervals.
629          */
630         timestamp /= 10;
631
632         /*
633          * Subtract difference, in microseconds, between January 1, 1601
634          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
635          */
636         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
637 #else
638         /*
639          * Current time, represented as seconds and microseconds since
640          * January 1, 1970, 00:00:00 UTC.
641          */
642         gettimeofday(&now, NULL);
643
644         /*
645          * Convert to delta in microseconds.
646          */
647         timestamp = (guint64)(now.tv_sec) * 1000000 +
648                     (guint64)(now.tv_usec);
649 #endif
650         if (pcap_stats(pd, &stats) < 0) {
651                 stats_retrieved = FALSE;
652                 g_warning("pcap_stats() failed.");
653         } else {
654                 stats_retrieved = TRUE;
655                 have_options = TRUE;
656         }
657         block_total_length = sizeof(struct isb) +
658                              sizeof(guint32);
659         if (stats_retrieved) {
660                 block_total_length += 2 * sizeof(struct option) + 2 * sizeof(guint64); /* ISB_IFRECV + ISB_IFDROP */
661         }
662         /* OPT_COMMENT */
663         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
664                 block_total_length += sizeof(struct option) +
665                                       (guint16)(ADD_PADDING(strlen(comment) + 1));
666                 have_options = TRUE;
667         }
668         if (isb_starttime !=0) {
669                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_STARTTIME */
670                 have_options = TRUE;
671         }
672         if (isb_endtime !=0) {
673                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_ENDTIME */
674                 have_options = TRUE;
675         }
676         /* If we have options add size of end-of-options */
677         if (have_options) {
678                 block_total_length += sizeof(struct option);
679         }
680
681         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
682         isb.block_total_length = block_total_length;
683         isb.interface_id = interface_id;
684         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
685         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
686         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
687
688         /* write comment string if applicable */
689         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
690                 option.type = OPT_COMMENT;
691                 option.value_length = (guint16)(strlen(comment) + 1);
692                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
693                 WRITE_DATA(fp, comment, strlen(comment) + 1, *bytes_written, err);
694                 if ((strlen(comment) + 1) % 4) {
695                         WRITE_DATA(fp, &padding, 4 - (strlen(comment) + 1) % 4 , *bytes_written, err);
696                 }
697         }
698
699         if (isb_starttime !=0) {
700                 option.type = ISB_STARTTIME;
701                 option.value_length = sizeof(guint64);
702                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
703                 WRITE_DATA(fp, &isb_starttime, sizeof(guint64), *bytes_written, err);
704         }
705         if (isb_endtime !=0) {
706                 option.type = ISB_ENDTIME;
707                 option.value_length = sizeof(guint64);
708                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
709                 WRITE_DATA(fp, &isb_endtime, sizeof(guint64), *bytes_written, err);
710         }
711         if (stats_retrieved) {
712                 /* */
713                 option.type = ISB_IFRECV;
714                 option.value_length = sizeof(guint64);
715                 counter = stats.ps_recv;
716                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
717                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
718                 /* */
719                 option.type = ISB_IFDROP;
720                 option.value_length = sizeof(guint64);
721                 counter = stats.ps_drop;
722                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
723                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
724         }
725         if (have_options) {
726                 /* write end of options */
727                 option.type = OPT_ENDOFOPT;
728                 option.value_length = 0;
729                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
730         }
731
732         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
733
734         return TRUE;
735 }
736
737 gboolean
738 libpcap_dump_flush(FILE *pd, int *err)
739 {
740         if (fflush(pd) == EOF) {
741                 if (err != NULL)
742                         *err = errno;
743                 return FALSE;
744         }
745         return TRUE;
746 }
747
748 gboolean
749 libpcap_dump_close(FILE *pd, int *err)
750 {
751         if (fclose(pd) == EOF) {
752                 if (err != NULL)
753                         *err = errno;
754                 return FALSE;
755         }
756         return TRUE;
757 }
758
759 #endif /* HAVE_LIBPCAP */