We always HAVE_CONFIG_H so don't bother checking whether we have it or not.
[metze/wireshark/wip.git] / pcapio.c
1 /* pcapio.c
2  * Our own private code for writing libpcap files when capturing.
3  *
4  * We have these because we want a way to open a stream for output given
5  * only a file descriptor.  libpcap 0.9[.x] has "pcap_dump_fopen()", which
6  * provides that, but
7  *
8  *      1) earlier versions of libpcap doesn't have it
9  *
10  * and
11  *
12  *      2) WinPcap doesn't have it, because a file descriptor opened
13  *         by code built for one version of the MSVC++ C library
14  *         can't be used by library routines built for another version
15  *         (e.g., threaded vs. unthreaded).
16  *
17  * Libpcap's pcap_dump() also doesn't return any error indications.
18  *
19  * $Id$
20  *
21  * Wireshark - Network traffic analyzer
22  * By Gerald Combs <gerald@wireshark.org>
23  * Copyright 1998 Gerald Combs
24  *
25  * Derived from code in the Wiretap Library
26  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
27  *
28  * This program is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU General Public License
30  * as published by the Free Software Foundation; either version 2
31  * of the License, or (at your option) any later version.
32  *
33  * This program is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
41  */
42
43 #include "config.h"
44
45 #ifdef HAVE_LIBPCAP
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <errno.h>
50 #include <string.h>
51
52 #include <pcap.h>
53
54 #include <glib.h>
55
56 #include "pcapio.h"
57
58 /* Magic numbers in "libpcap" files.
59
60    "libpcap" file records are written in the byte order of the host that
61    writes them, and the reader is expected to fix this up.
62
63    PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
64    is a byte-swapped version of that.
65
66    PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
67    which uses the same common file format as PCAP_MAGIC, but the
68    timestamps are saved in nanosecond resolution instead of microseconds.
69    PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
70 #define PCAP_MAGIC                      0xa1b2c3d4
71 #define PCAP_SWAPPED_MAGIC              0xd4c3b2a1
72 #define PCAP_NSEC_MAGIC                 0xa1b23c4d
73 #define PCAP_SWAPPED_NSEC_MAGIC         0x4d3cb2a1
74
75 /* "libpcap" file header. */
76 struct pcap_hdr {
77         guint32 magic;          /* magic number */
78         guint16 version_major;  /* major version number */
79         guint16 version_minor;  /* minor version number */
80         gint32  thiszone;       /* GMT to local correction */
81         guint32 sigfigs;        /* accuracy of timestamps */
82         guint32 snaplen;        /* max length of captured packets, in octets */
83         guint32 network;        /* data link type */
84 };
85
86 /* "libpcap" record header. */
87 struct pcaprec_hdr {
88         guint32 ts_sec;         /* timestamp seconds */
89         guint32 ts_usec;        /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
90         guint32 incl_len;       /* number of octets of packet saved in file */
91         guint32 orig_len;       /* actual length of packet */
92 };
93
94 /* Magic numbers in ".pcapng" files.
95  *
96  * .pcapng file records are written in the byte order of the host that
97  * writes them, and the reader is expected to fix this up.
98  * PCAPNG_MAGIC is the magic number, in host byte order;
99  * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that.
100  */
101 #define PCAPNG_MAGIC         0x1A2B3C4D
102 #define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1
103
104 /* Currently we are only supporting the initial version of
105    the file format. */
106 #define PCAPNG_MAJOR_VERSION 1
107 #define PCAPNG_MINOR_VERSION 0
108
109 /* Section Header Block without options and trailing Block Total Length */
110 struct shb {
111         guint32 block_type;
112         guint32 block_total_length;
113         guint32 byte_order_magic;
114         guint16 major_version;
115         guint16 minor_version;
116         guint64 section_length;
117 };
118 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
119
120 /* Interface Decription Block without options and trailing Block Total Length */
121 struct idb {
122         guint32 block_type;
123         guint32 block_total_length;
124         guint16 link_type;
125         guint16 reserved;
126         guint32 snap_len;
127 };
128 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
129
130 /* Interface Statistics Block without actual packet, options, and trailing
131    Block Total Length */
132 struct isb {
133         guint32 block_type;
134         guint32 block_total_length;
135         guint32 interface_id;
136         guint32 timestamp_high;
137         guint32 timestamp_low;
138 };
139 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
140
141 /* Enhanced Packet Block without actual packet, options, and trailing
142    Block Total Length */
143 struct epb {
144         guint32 block_type;
145         guint32 block_total_length;
146         guint32 interface_id;
147         guint32 timestamp_high;
148         guint32 timestamp_low;
149         guint32 captured_len;
150         guint32 packet_len;
151 };
152 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
153
154 struct option {
155         guint16 type;
156         guint16 value_length;
157 };
158 #define OPT_ENDOFOPT      0
159 #define OPT_COMMENT       1
160 #define SHB_HARDWARE      2 /* currently not used */
161 #define SHB_OS            3
162 #define SHB_USERAPPL      4
163 #define IDB_NAME          2
164 #define IDB_DESCRIPTION   3
165 #define IDB_IF_SPEED      8
166 #define IDB_TSRESOL       9
167 #define IDB_FILTER       11
168 #define IDB_OS           12
169 #define ISB_STARTTIME     2
170 #define ISB_ENDTIME       3
171 #define ISB_IFRECV        4
172 #define ISB_IFDROP        5
173 #define ISB_FILTERACCEPT  6
174 #define ISB_OSDROP        7
175 #define ISB_USRDELIV      8
176 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
177
178 #define WRITE_DATA(file_pointer, data_pointer, data_length, written_length, error_pointer) \
179 {                                                                                          \
180         do {                                                                               \
181                 size_t nwritten;                                                           \
182                                                                                            \
183                 nwritten = fwrite(data_pointer, 1, data_length, file_pointer);             \
184                 if (nwritten != data_length) {                                             \
185                         if (nwritten == 0 && ferror(file_pointer)) {                       \
186                                 *error_pointer = errno;                                    \
187                         } else {                                                           \
188                                 *error_pointer = 0;                                        \
189                         }                                                                  \
190                         return FALSE;                                                      \
191                 }                                                                          \
192                 written_length += (long)nwritten;                                          \
193         } while (0);                                                                       \
194 }
195
196 /* Returns a FILE * to write to on success, NULL on failure */
197 FILE *
198 libpcap_fdopen(int fd, int *err)
199 {
200         FILE *fp;
201
202         fp = fdopen(fd, "wb");
203         if (fp == NULL) {
204                 *err = errno;
205         }
206         return fp;
207 }
208
209 /* Write the file header to a dump file.
210    Returns TRUE on success, FALSE on failure.
211    Sets "*err" to an error code, or 0 for a short write, on failure*/
212 gboolean
213 libpcap_write_file_header(FILE *fp, int linktype, int snaplen, gboolean ts_nsecs, long *bytes_written, int *err)
214 {
215         struct pcap_hdr file_hdr;
216         size_t nwritten;
217
218         file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;
219         /* current "libpcap" format is 2.4 */
220         file_hdr.version_major = 2;
221         file_hdr.version_minor = 4;
222         file_hdr.thiszone = 0;  /* XXX - current offset? */
223         file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
224         file_hdr.snaplen = snaplen;
225         file_hdr.network = linktype;
226         nwritten = fwrite(&file_hdr, 1, sizeof(file_hdr), fp);
227         if (nwritten != sizeof(file_hdr)) {
228                 if (nwritten == 0 && ferror(fp))
229                         *err = errno;
230                 else
231                         *err = 0;       /* short write */
232                 return FALSE;
233         }
234         *bytes_written += sizeof(file_hdr);
235
236         return TRUE;
237 }
238
239 /* Write a record for a packet to a dump file.
240    Returns TRUE on success, FALSE on failure. */
241 gboolean
242 libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
243     long *bytes_written, int *err)
244 {
245         struct pcaprec_hdr rec_hdr;
246         size_t nwritten;
247
248         rec_hdr.ts_sec = phdr->ts.tv_sec;
249         rec_hdr.ts_usec = phdr->ts.tv_usec;
250         rec_hdr.incl_len = phdr->caplen;
251         rec_hdr.orig_len = phdr->len;
252         nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
253         if (nwritten != sizeof rec_hdr) {
254                 if (nwritten == 0 && ferror(fp))
255                         *err = errno;
256                 else
257                         *err = 0;       /* short write */
258                 return FALSE;
259         }
260         *bytes_written += sizeof rec_hdr;
261
262         nwritten = fwrite(pd, 1, phdr->caplen, fp);
263         if (nwritten != phdr->caplen) {
264                 if (nwritten == 0 && ferror(fp))
265                         *err = errno;
266                 else
267                         *err = 0;       /* short write */
268                 return FALSE;
269         }
270         *bytes_written += phdr->caplen;
271         return TRUE;
272 }
273
274 gboolean
275 libpcap_write_session_header_block(FILE *fp,
276                                    const char *comment,
277                                    const char *hw,
278                                    const char *os,
279                                    const char *appname,
280                                    guint64 section_length,
281                                    long *bytes_written,
282                                    int *err)
283 {
284         struct shb shb;
285         struct option option;
286         guint32 block_total_length;
287         const guint32 padding = 0;
288         gboolean have_options = FALSE;
289
290         /* Size of base header */
291         block_total_length = sizeof(struct shb) +
292                              sizeof(guint32);
293         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
294                 block_total_length += sizeof(struct option) +
295                                       (guint16)ADD_PADDING(strlen(comment));
296                 have_options = TRUE;
297         }
298         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
299                 block_total_length += sizeof(struct option) +
300                                       (guint16)ADD_PADDING(strlen(hw));
301                 have_options = TRUE;
302         }
303         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
304                 block_total_length += sizeof(struct option) +
305                                       (guint16)ADD_PADDING(strlen(os));
306                 have_options = TRUE;
307         }
308         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
309                 block_total_length += sizeof(struct option) +
310                                       (guint16)ADD_PADDING(strlen(appname));
311                 have_options = TRUE;
312         }
313         /* If we have options add size of end-of-options */
314         if (have_options) {
315                 block_total_length += sizeof(struct option);
316         }
317         /* write shb header */
318         shb.block_type = SECTION_HEADER_BLOCK_TYPE;
319         shb.block_total_length = block_total_length;
320         shb.byte_order_magic = PCAPNG_MAGIC;
321         shb.major_version = PCAPNG_MAJOR_VERSION;
322         shb.minor_version = PCAPNG_MINOR_VERSION;
323         shb.section_length = section_length;
324         WRITE_DATA(fp, &shb, sizeof(struct shb), *bytes_written, err);
325
326         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
327                 /* write opt_comment options */
328                 option.type = OPT_COMMENT;
329                 option.value_length = (guint16)strlen(comment);
330                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
331                 WRITE_DATA(fp, comment, strlen(comment), *bytes_written, err);
332                 if (strlen(comment) % 4) {
333                         WRITE_DATA(fp, &padding, 4 - strlen(comment) % 4, *bytes_written, err);
334                 }
335         }
336         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
337                 /* write shb_hardware options */
338                 option.type = SHB_HARDWARE;
339                 option.value_length = (guint16)strlen(hw);
340                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
341                 WRITE_DATA(fp, hw, strlen(hw), *bytes_written, err);
342                 if ((strlen(hw) + 1) % 4) {
343                         WRITE_DATA(fp, &padding, 4 - strlen(hw) % 4, *bytes_written, err);
344                 }
345         }
346         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
347                 /* write shb_os options */
348                 option.type = SHB_OS;
349                 option.value_length = (guint16)strlen(os);
350                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
351                 WRITE_DATA(fp, os, strlen(os), *bytes_written, err);
352                 if (strlen(os) % 4) {
353                         WRITE_DATA(fp, &padding, 4 - strlen(os) % 4, *bytes_written, err);
354                 }
355         }
356         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
357                 /* write shb_userappl options */
358                 option.type = SHB_USERAPPL;
359                 option.value_length = (guint16)strlen(appname);
360                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
361                 WRITE_DATA(fp, appname, strlen(appname), *bytes_written, err);
362                 if (strlen(appname) % 4) {
363                         WRITE_DATA(fp, &padding, 4 - strlen(appname) % 4, *bytes_written, err);
364                 }
365         }
366         if (have_options) {
367                 /* write end of options */
368                 option.type = OPT_ENDOFOPT;
369                 option.value_length = 0;
370                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
371         }
372
373         /* write the trailing block total length */
374         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
375         return TRUE;
376 }
377
378 gboolean
379 libpcap_write_interface_description_block(FILE *fp,
380                                           const char *comment, /* OPT_COMMENT        1 */
381                                           const char *name,    /* IDB_NAME           2 */
382                                           const char *descr,   /* IDB_DESCRIPTION    3 */
383                                           const char *filter,  /* IDB_FILTER        11 */
384                                           const char *os,      /* IDB_OS            12 */
385                                           int link_type,
386                                           int snap_len,
387                                           long *bytes_written,
388                                           guint64 if_speed,    /* IDB_IF_SPEED       8 */
389                                           guint8 tsresol,      /* IDB_TSRESOL        9 */
390                                           int *err)
391 {
392         struct idb idb;
393         struct option option;
394         guint32 block_total_length;
395         const guint32 padding = 0;
396         gboolean have_options = FALSE;
397
398         block_total_length = sizeof(struct idb) + sizeof(guint32);
399         /* 01 - OPT_COMMENT */
400         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
401                 block_total_length += sizeof(struct option) +
402                                       (guint16)ADD_PADDING(strlen(comment));
403                 have_options = TRUE;
404         }
405
406         /* 02 - IDB_NAME */
407         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
408                 block_total_length += sizeof(struct option) +
409                                       (guint16)ADD_PADDING(strlen(name));
410                 have_options = TRUE;
411         }
412
413         /* 03 - IDB_DESCRIPTION */
414         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
415                 block_total_length += sizeof(struct option) +
416                                       (guint16)ADD_PADDING(strlen(descr));
417                 have_options = TRUE;
418         }
419
420         /* 08 - IDB_IF_SPEED */
421         if (if_speed != 0) {
422                 block_total_length += sizeof(struct option) + sizeof(guint64);
423                 have_options = TRUE;
424         }
425
426         /* 09 - IDB_TSRESOL */
427         if (tsresol != 0) {
428                 block_total_length += sizeof(struct option) + sizeof(struct option);
429                 have_options = TRUE;
430         }
431
432         /* 11 - IDB_FILTER */
433         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
434                 block_total_length += sizeof(struct option) +
435                                       (guint16)(ADD_PADDING(strlen(filter)+ 1));
436                 have_options = TRUE;
437         }
438
439         /* 12 - IDB_OS */
440         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
441                 block_total_length += sizeof(struct option) +
442                                      (guint16)ADD_PADDING(strlen(os));
443                 have_options = TRUE;
444         }
445
446         /* If we have options add size of end-of-options */
447         if (have_options) {
448                 block_total_length += sizeof(struct option);
449         }
450
451         /* write block header */
452         idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
453         idb.block_total_length = block_total_length;
454         idb.link_type = link_type;
455         idb.reserved = 0;
456         idb.snap_len = snap_len;
457         WRITE_DATA(fp, &idb, sizeof(struct idb), *bytes_written, err);
458
459         /* 01 - OPT_COMMENT - write comment string if applicable */
460         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
461                 option.type = OPT_COMMENT;
462                 option.value_length = (guint16)strlen(comment);
463                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
464                 WRITE_DATA(fp, comment, strlen(comment), *bytes_written, err);
465                 if (strlen(comment) % 4) {
466                         WRITE_DATA(fp, &padding, 4 - strlen(comment) % 4 , *bytes_written, err);
467                 }
468         }
469
470         /* 02 - IDB_NAME - write interface name string if applicable */
471         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
472                 option.type = IDB_NAME;
473                 option.value_length = (guint16)strlen(name);
474                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
475                 WRITE_DATA(fp, name, strlen(name), *bytes_written, err);
476                 if (strlen(name) % 4) {
477                         WRITE_DATA(fp, &padding, 4 - strlen(name) % 4 , *bytes_written, err);
478                 }
479         }
480
481         /* 03 - IDB_DESCRIPTION */
482         /* write interface description string if applicable */
483         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
484                 option.type = IDB_DESCRIPTION;
485                 option.value_length = (guint16)strlen(descr);
486                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
487                 WRITE_DATA(fp, descr, strlen(descr), *bytes_written, err);
488                 if (strlen(descr) % 4) {
489                         WRITE_DATA(fp, &padding, 4 - strlen(descr) % 4 , *bytes_written, err);
490                 }
491         }
492
493         /* 08 - IDB_IF_SPEED */
494         if (if_speed != 0) {
495                 option.type = IDB_IF_SPEED;
496                 option.value_length = sizeof(guint64);
497                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
498                 WRITE_DATA(fp, &if_speed, sizeof(guint64), *bytes_written, err);
499         }
500
501         /* 09 - IDB_TSRESOL */
502         if (tsresol != 0) {
503                 option.type = IDB_TSRESOL;
504                 option.value_length = sizeof(guint8);
505                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
506                 WRITE_DATA(fp, &tsresol, sizeof(guint8), *bytes_written, err);
507                 WRITE_DATA(fp, &padding, 3 , *bytes_written, err);
508         }
509
510         /* 11 - IDB_FILTER - write filter string if applicable
511          * We only write version 1 of the filter, libpcap string
512          */
513         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
514                 option.type = IDB_FILTER;
515                 option.value_length = (guint16)(strlen(filter) + 1 );
516                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
517
518                 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
519                 WRITE_DATA(fp, &padding, 1, *bytes_written, err);
520                 WRITE_DATA(fp, filter, strlen(filter), *bytes_written, err);
521                 if ((strlen(filter) + 1) % 4) {
522                         WRITE_DATA(fp, &padding, 4 - (strlen(filter) + 1) % 4 , *bytes_written, err);
523                 }
524         }
525
526         /* 12 - IDB_OS - write os string if applicable */
527         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
528                 option.type = IDB_OS;
529                 option.value_length = (guint16)strlen(os);
530                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
531                 WRITE_DATA(fp, os, strlen(os), *bytes_written, err);
532                 if (strlen(os) % 4) {
533                         WRITE_DATA(fp, &padding, 4 - strlen(os) % 4 , *bytes_written, err);
534                 }
535         }
536
537         if (have_options) {
538                 /* write end of options */
539                 option.type = OPT_ENDOFOPT;
540                 option.value_length = 0;
541                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
542         }
543
544         /* write the trailing Block Total Length */
545         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
546         return TRUE;
547 }
548
549 /* Write a record for a packet to a dump file.
550    Returns TRUE on success, FALSE on failure. */
551 gboolean
552 libpcap_write_enhanced_packet_block(FILE *fp,
553                                     const struct pcap_pkthdr *phdr,
554                                     guint32 interface_id,
555                                     guint ts_mul,
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) * ts_mul +
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                                          long *bytes_written,
590                                          const char *comment,   /* OPT_COMMENT           1 */
591                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
592                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
593                                          guint64 isb_ifrecv,    /* ISB_IFRECV            4 */
594                                          guint64 isb_ifdrop,    /* ISB_IFDROP            5 */
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         guint32 block_total_length;
605         guint64 timestamp;
606         gboolean have_options = FALSE;
607         const guint32 padding = 0;
608 #ifdef _WIN32
609         /*
610          * Current time, represented as 100-nanosecond intervals since
611          * January 1, 1601, 00:00:00 UTC.
612          *
613          * I think DWORD might be signed, so cast both parts of "now"
614          * to guint32 so that the sign bit doesn't get treated specially.
615          *
616          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
617          * might want to use instead.
618          */
619         GetSystemTimeAsFileTime(&now);
620         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
621                     (guint32)now.dwLowDateTime;
622
623         /*
624          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
625          * intervals.
626          */
627         timestamp /= 10;
628
629         /*
630          * Subtract difference, in microseconds, between January 1, 1601
631          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
632          */
633         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
634 #else
635         /*
636          * Current time, represented as seconds and microseconds since
637          * January 1, 1970, 00:00:00 UTC.
638          */
639         gettimeofday(&now, NULL);
640
641         /*
642          * Convert to delta in microseconds.
643          */
644         timestamp = (guint64)(now.tv_sec) * 1000000 +
645                     (guint64)(now.tv_usec);
646 #endif
647         block_total_length = sizeof(struct isb) + sizeof(guint32);
648         if (isb_ifrecv != G_MAXUINT64) {
649             block_total_length +=  sizeof(struct option) + sizeof(guint64);
650             have_options = TRUE;
651         }
652         if (isb_ifdrop != G_MAXUINT64) {
653             block_total_length +=  sizeof(struct option) + sizeof(guint64);
654             have_options = TRUE;
655         }
656         /* OPT_COMMENT */
657         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
658                 block_total_length += sizeof(struct option) +
659                                       (guint16)ADD_PADDING(strlen(comment));
660                 have_options = TRUE;
661         }
662         if (isb_starttime !=0) {
663                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_STARTTIME */
664                 have_options = TRUE;
665         }
666         if (isb_endtime !=0) {
667                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_ENDTIME */
668                 have_options = TRUE;
669         }
670         /* If we have options add size of end-of-options */
671         if (have_options) {
672                 block_total_length += sizeof(struct option);
673         }
674
675         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
676         isb.block_total_length = block_total_length;
677         isb.interface_id = interface_id;
678         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
679         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
680         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
681
682         /* write comment string if applicable */
683         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
684                 option.type = OPT_COMMENT;
685                 option.value_length = (guint16)strlen(comment);
686                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
687                 WRITE_DATA(fp, comment, strlen(comment), *bytes_written, err);
688                 if (strlen(comment) % 4) {
689                         WRITE_DATA(fp, &padding, 4 - strlen(comment) % 4 , *bytes_written, err);
690                 }
691         }
692
693         if (isb_starttime !=0) {
694                 guint32 high, low;
695
696                 option.type = ISB_STARTTIME;
697                 option.value_length = sizeof(guint64);
698                 high = (guint32)((isb_starttime>>32) & 0xffffffff);
699                 low = (guint32)(isb_starttime & 0xffffffff);
700                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
701                 WRITE_DATA(fp, &high, sizeof(guint32), *bytes_written, err);
702                 WRITE_DATA(fp, &low, sizeof(guint32), *bytes_written, err);
703         }
704         if (isb_endtime !=0) {
705                 guint32 high, low;
706
707                 option.type = ISB_ENDTIME;
708                 option.value_length = sizeof(guint64);
709                 high = (guint32)((isb_endtime>>32) & 0xffffffff);
710                 low = (guint32)(isb_endtime & 0xffffffff);
711                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
712                 WRITE_DATA(fp, &high, sizeof(guint32), *bytes_written, err);
713                 WRITE_DATA(fp, &low, sizeof(guint32), *bytes_written, err);
714         }
715         if (isb_ifrecv != G_MAXUINT64) {
716                 option.type = ISB_IFRECV;
717                 option.value_length = sizeof(guint64);
718                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
719                 WRITE_DATA(fp, &isb_ifrecv, sizeof(guint64), *bytes_written, err);
720         }
721         if (isb_ifdrop != G_MAXUINT64) {
722                 option.type = ISB_IFDROP;
723                 option.value_length = sizeof(guint64);
724                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
725                 WRITE_DATA(fp, &isb_ifdrop, sizeof(guint64), *bytes_written, err);
726         }
727         if (have_options) {
728                 /* write end of options */
729                 option.type = OPT_ENDOFOPT;
730                 option.value_length = 0;
731                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
732         }
733
734         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
735
736         return TRUE;
737 }
738
739 gboolean
740 libpcap_dump_flush(FILE *pd, int *err)
741 {
742         if (fflush(pd) == EOF) {
743                 if (err != NULL)
744                         *err = errno;
745                 return FALSE;
746         }
747         return TRUE;
748 }
749
750 gboolean
751 libpcap_dump_close(FILE *pd, int *err)
752 {
753         if (fclose(pd) == EOF) {
754                 if (err != NULL)
755                         *err = errno;
756                 return FALSE;
757         }
758         return TRUE;
759 }
760
761 #endif /* HAVE_LIBPCAP */
762
763 /*
764  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
765  *
766  * Local variables:
767  * c-basic-offset: 4
768  * tab-width: 8
769  * indent-tabs-mode: nil
770  * End:
771  *
772  * vi: set shiftwidth=4 tabstop=8 expandtab:
773  * :indentSize=4:tabSize=8:noTabs=true:
774  */