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