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