From Josip Medved: Add 3GPP AVP 1506 and 1507
[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_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(hw) + 1) % 4, *bytes_written, err);
336                 }
337         }
338         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
339                 /* write shb_hardware options */
340                 option.type = SHB_HARDWARE;
341                 option.value_length = (guint16)(strlen(hw) + 1);
342                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
343                 WRITE_DATA(fp, hw, strlen(hw) + 1, *bytes_written, err);
344                 if ((strlen(hw) + 1) % 4) {
345                         WRITE_DATA(fp, &padding, 4 - (strlen(hw) + 1) % 4, *bytes_written, err);
346                 }
347         }
348         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
349                 /* write shb_os options */
350                 option.type = SHB_OS;
351                 option.value_length = (guint16)(strlen(os) + 1);
352                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
353                 WRITE_DATA(fp, os, strlen(os) + 1, *bytes_written, err);
354                 if ((strlen(os) + 1) % 4) {
355                         WRITE_DATA(fp, &padding, 4 - (strlen(os) + 1) % 4, *bytes_written, err);
356                 }
357         }
358         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
359                 /* write shb_userappl options */
360                 option.type = SHB_USERAPPL;
361                 option.value_length = (guint16)(strlen(appname) + 1);
362                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
363                 WRITE_DATA(fp, appname, strlen(appname) + 1, *bytes_written, err);
364                 if ((strlen(appname) + 1) % 4) {
365                         WRITE_DATA(fp, &padding, 4 - (strlen(appname) + 1) % 4, *bytes_written, err);
366                 }
367         }
368         if (have_options) {
369                 /* write end of options */
370                 option.type = OPT_ENDOFOPT;
371                 option.value_length = 0;
372                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
373         }
374
375         /* write the trailing block total length */
376         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
377         return TRUE;
378 }
379
380 gboolean
381 libpcap_write_interface_description_block(FILE *fp,
382                                           const char *comment, /* OPT_COMMENT        1 */
383                                           const char *name,    /* IDB_NAME           2 */
384                                           const char *descr,   /* IDB_DESCRIPTION    3 */
385                                           const char *filter,  /* IDB_FILTER        11 */
386                                           const char *os,      /* IDB_OS            12 */
387                                           int link_type,
388                                           int snap_len,
389                                           long *bytes_written,
390                                           guint64 if_speed,    /* IDB_IF_SPEED       8 */
391                                           guint8 tsresol,      /* IDB_TSRESOL        9 */
392                                           int *err)
393 {
394         struct idb idb;
395         struct option option;
396         guint32 block_total_length;
397         const guint32 padding = 0;
398         gboolean have_options = FALSE;
399
400         block_total_length = sizeof(struct idb) + sizeof(guint32);
401         /* OPT_COMMENT */
402         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
403                 block_total_length += sizeof(struct option) +
404                                       (guint16)(ADD_PADDING(strlen(comment) + 1));
405                 have_options = TRUE;
406         }
407
408         /* IDB_DESCRIPTION */
409         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
410                 block_total_length += sizeof(struct option) +
411                                       (guint16)(ADD_PADDING(strlen(descr) + 1));
412                 have_options = TRUE;
413         }
414
415         /* IDB_NAME */
416         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
417                 block_total_length += sizeof(struct option) +
418                                       (guint16)(ADD_PADDING(strlen(name) + 1));
419                 have_options = TRUE;
420         }
421
422         /* IDB_FILTER */
423         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
424                 block_total_length += sizeof(struct option) +
425                                       (guint16)(ADD_PADDING(strlen(filter) + 1));
426                 have_options = TRUE;
427         }
428
429         /* IDB_OS */
430         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
431                 block_total_length += sizeof(struct option) +
432                                      (guint16)(ADD_PADDING(strlen(os) + 1));
433                 have_options = TRUE;
434         }
435
436         /* IDB_IF_SPEED       8 */
437         if (if_speed != 0) {
438                 block_total_length += sizeof(struct option) + sizeof(guint64);
439                 have_options = TRUE;
440         }
441
442         /* IDB_TSRESOL        9 */
443         if (tsresol != 0) {
444                 block_total_length += sizeof(struct option) + sizeof(struct option);
445                 have_options = TRUE;
446         }
447
448         /* If we have options add size of end-of-options */
449         if (have_options) {
450                 block_total_length += sizeof(struct option);
451         }
452
453         /* write block header */
454         idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
455         idb.block_total_length = block_total_length;
456         idb.link_type = link_type;
457         idb.reserved = 0;
458         idb.snap_len = snap_len;
459         WRITE_DATA(fp, &idb, sizeof(struct idb), *bytes_written, err);
460
461         /* write comment string if applicable */
462         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
463                 option.type = OPT_COMMENT;
464                 option.value_length = (guint16)(strlen(comment) + 1);
465                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
466                 WRITE_DATA(fp, comment, strlen(comment) + 1, *bytes_written, err);
467                 if ((strlen(comment) + 1) % 4) {
468                         WRITE_DATA(fp, &padding, 4 - (strlen(comment) + 1) % 4 , *bytes_written, err);
469                 }
470         }
471
472         /* write interface name string if applicable */
473         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
474                 option.type = IDB_NAME;
475                 option.value_length = (guint16)(strlen(name) + 1);
476                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
477                 WRITE_DATA(fp, name, strlen(name) + 1, *bytes_written, err);
478                 if ((strlen(name) + 1) % 4) {
479                         WRITE_DATA(fp, &padding, 4 - (strlen(name) + 1) % 4 , *bytes_written, err);
480                 }
481         }
482
483         /* write interface description string if applicable */
484         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
485                 option.type = IDB_DESCRIPTION;
486                 option.value_length = (guint16)(strlen(descr) + 1);
487                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
488                 WRITE_DATA(fp, name, strlen(descr) + 1, *bytes_written, err);
489                 if ((strlen(descr) + 1) % 4) {
490                         WRITE_DATA(fp, &padding, 4 - (strlen(descr) + 1) % 4 , *bytes_written, err);
491                 }
492         }
493
494         /* write filter string if applicable */
495         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
496                 option.type = IDB_FILTER;
497                 option.value_length = (guint16)(strlen(filter) + 1);
498                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
499                 WRITE_DATA(fp, filter, strlen(filter) + 1, *bytes_written, err);
500                 if ((strlen(filter) + 1) % 4) {
501                         WRITE_DATA(fp, &padding, 4 - (strlen(filter) + 1) % 4 , *bytes_written, err);
502                 }
503         }
504
505         /* write os string if applicable */
506         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
507                 option.type = IDB_OS;
508                 option.value_length = (guint16)(strlen(os) + 1);
509                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
510                 WRITE_DATA(fp, os, strlen(os) + 1, *bytes_written, err);
511                 if ((strlen(os) + 1) % 4) {
512                         WRITE_DATA(fp, &padding, 4 - (strlen(os) + 1) % 4 , *bytes_written, err);
513                 }
514         }
515
516         /* IDB_IF_SPEED       8 */
517         if (if_speed != 0) {
518                 option.type = IDB_IF_SPEED;
519                 option.value_length = sizeof(guint64);
520                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
521                 WRITE_DATA(fp, &if_speed, sizeof(guint64), *bytes_written, err);
522         }
523
524         /* IDB_TSRESOL        9 */
525         if (tsresol != 0) {
526                 option.type = IDB_TSRESOL;
527                 option.value_length = sizeof(guint8);
528                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
529                 WRITE_DATA(fp, &if_speed, sizeof(guint8), *bytes_written, err);
530                 WRITE_DATA(fp, &padding, 3 , *bytes_written, err);
531         }
532
533         if (have_options) {
534                 /* write end of options */
535                 option.type = OPT_ENDOFOPT;
536                 option.value_length = 0;
537                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
538         }
539
540         /* write the trailing Block Total Length */
541         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
542         return TRUE;
543 }
544
545 /* Write a record for a packet to a dump file.
546    Returns TRUE on success, FALSE on failure. */
547 gboolean
548 libpcap_write_enhanced_packet_block(FILE *fp,
549                                     const struct pcap_pkthdr *phdr,
550                                     guint32 interface_id,
551                                     const u_char *pd,
552                                     long *bytes_written,
553                                     int *err)
554 {
555         struct epb epb;
556         guint32 block_total_length;
557         guint64 timestamp;
558         const guint32 padding = 0;
559
560         block_total_length = sizeof(struct epb) +
561                              ADD_PADDING(phdr->caplen) +
562                              sizeof(guint32);
563         timestamp = (guint64)(phdr->ts.tv_sec) * 1000000 +
564                     (guint64)(phdr->ts.tv_usec);
565         epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
566         epb.block_total_length = block_total_length;
567         epb.interface_id = interface_id;
568         epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
569         epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
570         epb.captured_len = phdr->caplen;
571         epb.packet_len = phdr->len;
572         WRITE_DATA(fp, &epb, sizeof(struct epb), *bytes_written, err);
573         WRITE_DATA(fp, pd, phdr->caplen, *bytes_written, err);
574         if (phdr->caplen % 4) {
575                 WRITE_DATA(fp, &padding, 4 - phdr->caplen % 4, *bytes_written, err);
576         }
577         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
578         return TRUE;
579 }
580
581 gboolean
582 libpcap_write_interface_statistics_block(FILE *fp,
583                                          guint32 interface_id,
584                                          pcap_t *pd,
585                                          long *bytes_written,
586                                          const char *comment,   /* OPT_COMMENT           1 */
587                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
588                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
589                                          int *err)
590 {
591         struct isb isb;
592 #ifdef _WIN32
593         FILETIME now;
594 #else
595         struct timeval now;
596 #endif
597         struct option option;
598         struct pcap_stat stats;
599         guint32 block_total_length;
600         guint64 timestamp;
601         guint64 counter;
602         gboolean stats_retrieved;
603         gboolean have_options = FALSE;
604         const guint32 padding = 0;
605 #ifdef _WIN32
606         /*
607          * Current time, represented as 100-nanosecond intervals since
608          * January 1, 1601, 00:00:00 UTC.
609          *
610          * I think DWORD might be signed, so cast both parts of "now"
611          * to guint32 so that the sign bit doesn't get treated specially.
612          */
613         GetSystemTimeAsFileTime(&now);
614         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
615                     (guint32)now.dwLowDateTime;
616
617         /*
618          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
619          * intervals.
620          */
621         timestamp /= 10;
622
623         /*
624          * Subtract difference, in microseconds, between January 1, 1601
625          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
626          */
627         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
628 #else
629         /*
630          * Current time, represented as seconds and microseconds since
631          * January 1, 1970, 00:00:00 UTC.
632          */
633         gettimeofday(&now, NULL);
634
635         /*
636          * Convert to delta in microseconds.
637          */
638         timestamp = (guint64)(now.tv_sec) * 1000000 +
639                     (guint64)(now.tv_usec);
640 #endif
641         if (pcap_stats(pd, &stats) < 0) {
642                 stats_retrieved = FALSE;
643                 g_warning("pcap_stats() failed.");
644         } else {
645                 stats_retrieved = TRUE;
646                 have_options = TRUE;
647         }
648         block_total_length = sizeof(struct isb) +
649                              sizeof(guint32);
650         if (stats_retrieved) {
651                 block_total_length += 2 * sizeof(struct option) + 2 * sizeof(guint64); /* ISB_IFRECV + ISB_IFDROP */
652         }
653         /* OPT_COMMENT */
654         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
655                 block_total_length += sizeof(struct option) +
656                                       (guint16)(ADD_PADDING(strlen(comment) + 1));
657                 have_options = TRUE;
658         }
659         if (isb_starttime !=0) {
660                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_STARTTIME */
661                 have_options = TRUE;
662         }
663         if (isb_endtime !=0) {
664                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_ENDTIME */
665                 have_options = TRUE;
666         }
667         /* If we have options add size of end-of-options */
668         if (have_options) {
669                 block_total_length += sizeof(struct option);
670         }
671
672         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
673         isb.block_total_length = block_total_length;
674         isb.interface_id = interface_id;
675         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
676         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
677         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
678
679         /* write comment string if applicable */
680         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
681                 option.type = OPT_COMMENT;
682                 option.value_length = (guint16)(strlen(comment) + 1);
683                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
684                 WRITE_DATA(fp, comment, strlen(comment) + 1, *bytes_written, err);
685                 if ((strlen(comment) + 1) % 4) {
686                         WRITE_DATA(fp, &padding, 4 - (strlen(comment) + 1) % 4 , *bytes_written, err);
687                 }
688         }
689
690         if (isb_starttime !=0) {
691                 option.type = ISB_STARTTIME;
692                 option.value_length = sizeof(guint64);
693                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
694                 WRITE_DATA(fp, &isb_starttime, sizeof(guint64), *bytes_written, err);
695         }
696         if (isb_endtime !=0) {
697                 option.type = ISB_ENDTIME;
698                 option.value_length = sizeof(guint64);
699                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
700                 WRITE_DATA(fp, &isb_endtime, sizeof(guint64), *bytes_written, err);
701         }
702         if (stats_retrieved) {
703                 /* */
704                 option.type = ISB_IFRECV;
705                 option.value_length = sizeof(guint64);
706                 counter = stats.ps_recv;
707                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
708                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
709                 /* */
710                 option.type = ISB_IFDROP;
711                 option.value_length = sizeof(guint64);
712                 counter = stats.ps_drop;
713                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
714                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
715         }
716         if (have_options) {
717                 /* write end of options */
718                 option.type = OPT_ENDOFOPT;
719                 option.value_length = 0;
720                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
721         }
722
723         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
724
725         return TRUE;
726 }
727
728 gboolean
729 libpcap_dump_flush(FILE *pd, int *err)
730 {
731         if (fflush(pd) == EOF) {
732                 if (err != NULL)
733                         *err = errno;
734                 return FALSE;
735         }
736         return TRUE;
737 }
738
739 gboolean
740 libpcap_dump_close(FILE *pd, int *err)
741 {
742         if (fclose(pd) == EOF) {
743                 if (err != NULL)
744                         *err = errno;
745                 return FALSE;
746         }
747         return TRUE;
748 }
749
750 #endif /* HAVE_LIBPCAP */