From LI Hai via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8708 :
[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 #include <stdlib.h>
46 #include <stdio.h>
47 #include <errno.h>
48 #include <string.h>
49 #ifdef HAVE_SYS_TIME_H
50 #include <sys/time.h>
51 #endif
52 #ifdef _WIN32
53 #include <Windows.h>
54 #endif
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 EPB_FLAGS         2
163 #define SHB_HARDWARE      2 /* currently not used */
164 #define SHB_OS            3
165 #define SHB_USERAPPL      4
166 #define IDB_NAME          2
167 #define IDB_DESCRIPTION   3
168 #define IDB_IF_SPEED      8
169 #define IDB_TSRESOL       9
170 #define IDB_FILTER       11
171 #define IDB_OS           12
172 #define ISB_STARTTIME     2
173 #define ISB_ENDTIME       3
174 #define ISB_IFRECV        4
175 #define ISB_IFDROP        5
176 #define ISB_FILTERACCEPT  6
177 #define ISB_OSDROP        7
178 #define ISB_USRDELIV      8
179 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
180
181 /* Write libcap to file.  write_data_info will be a FILE* */
182 gboolean libpcap_write_to_file(void* write_data_info,
183                                const guint8* data,
184                                long data_length,
185                                guint64 *bytes_written,
186                                int *err)
187 {
188         size_t nwritten;
189         FILE* pFile = (FILE*)write_data_info;
190
191         nwritten = fwrite(data, data_length, 1, pFile);
192         if (nwritten != 1) {
193                 if (ferror(pFile)) {
194                         *err = errno;
195                 } else {
196                         *err = 0;
197                 }
198                 return FALSE;
199         }
200
201         (*bytes_written) += data_length;
202         return TRUE;
203 }
204
205 /* Write the file header to a dump file.
206    Returns TRUE on success, FALSE on failure.
207    Sets "*err" to an error code, or 0 for a short write, on failure*/
208 gboolean
209 libpcap_write_file_header(libpcap_write_t write_func, void* write_data_info, int linktype, int snaplen, gboolean ts_nsecs, guint64 *bytes_written, int *err)
210 {
211         struct pcap_hdr file_hdr;
212
213         file_hdr.magic = ts_nsecs ? PCAP_NSEC_MAGIC : PCAP_MAGIC;
214         /* current "libpcap" format is 2.4 */
215         file_hdr.version_major = 2;
216         file_hdr.version_minor = 4;
217         file_hdr.thiszone = 0;  /* XXX - current offset? */
218         file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
219         file_hdr.snaplen = snaplen;
220         file_hdr.network = linktype;
221
222         return write_func(write_data_info, (const guint8*)&file_hdr, sizeof(file_hdr), bytes_written, err);
223 }
224
225 /* Write a record for a packet to a dump file.
226    Returns TRUE on success, FALSE on failure. */
227 gboolean
228 libpcap_write_packet(libpcap_write_t write_func, void* write_data_info,
229                      time_t sec, guint32 usec,
230                      guint32 caplen, guint32 len,
231                      const guint8 *pd,
232                      guint64 *bytes_written, int *err)
233 {
234         struct pcaprec_hdr rec_hdr;
235
236         rec_hdr.ts_sec = (guint32)sec; /* Y2.038K issue in pcap format.... */
237         rec_hdr.ts_usec = usec;
238         rec_hdr.incl_len = caplen;
239         rec_hdr.orig_len = len;
240         if (!write_func(write_data_info, (const guint8*)&rec_hdr, sizeof(rec_hdr), bytes_written, err))
241                 return FALSE;
242
243         return write_func(write_data_info, pd, caplen, bytes_written, err);
244 }
245
246 gboolean
247 libpcap_write_session_header_block(libpcap_write_t write_func, void* write_data_info,
248                                    const char *comment,
249                                    const char *hw,
250                                    const char *os,
251                                    const char *appname,
252                                    guint64 section_length,
253                                    guint64 *bytes_written,
254                                    int *err)
255 {
256         struct shb shb;
257         struct option option;
258         guint32 block_total_length;
259         const guint32 padding = 0;
260         gboolean have_options = FALSE;
261
262         /* Size of base header */
263         block_total_length = sizeof(struct shb) +
264                              sizeof(guint32);
265         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
266                 block_total_length += (guint32)(sizeof(struct option) +
267                                                 (guint16)ADD_PADDING(strlen(comment)));
268                 have_options = TRUE;
269         }
270         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
271                 block_total_length += (guint32)(sizeof(struct option) +
272                                                 (guint16)ADD_PADDING(strlen(hw)));
273                 have_options = TRUE;
274         }
275         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
276                 block_total_length += (guint32)(sizeof(struct option) +
277                                                 (guint16)ADD_PADDING(strlen(os)));
278                 have_options = TRUE;
279         }
280         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
281                 block_total_length += (guint32)(sizeof(struct option) +
282                                                 (guint16)ADD_PADDING(strlen(appname)));
283                 have_options = TRUE;
284         }
285         /* If we have options add size of end-of-options */
286         if (have_options) {
287                 block_total_length += (guint32)sizeof(struct option);
288         }
289         /* write shb header */
290         shb.block_type = SECTION_HEADER_BLOCK_TYPE;
291         shb.block_total_length = block_total_length;
292         shb.byte_order_magic = PCAPNG_MAGIC;
293         shb.major_version = PCAPNG_MAJOR_VERSION;
294         shb.minor_version = PCAPNG_MINOR_VERSION;
295         shb.section_length = section_length;
296
297         if (!write_func(write_data_info, (const guint8*)&shb, sizeof(struct shb), bytes_written, err))
298                 return FALSE;
299
300         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
301                 /* write opt_comment options */
302                 option.type = OPT_COMMENT;
303                 option.value_length = (guint16)strlen(comment);
304
305                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
306                         return FALSE;
307
308                 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
309                         return FALSE;
310
311                 if (strlen(comment) % 4) {
312                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
313                                 return FALSE;
314                 }
315         }
316         if ((hw != NULL) && (strlen(hw) > 0) && (strlen(hw) < G_MAXUINT16)) {
317                 /* write shb_hardware options */
318                 option.type = SHB_HARDWARE;
319                 option.value_length = (guint16)strlen(hw);
320
321                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
322                         return FALSE;
323
324                 if (!write_func(write_data_info, (const guint8*)hw, (int) strlen(hw), bytes_written, err))
325                         return FALSE;
326
327                 if ((strlen(hw) + 1) % 4) {
328                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(hw) % 4, bytes_written, err))
329                                 return FALSE;
330                 }
331         }
332         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
333                 /* write shb_os options */
334                 option.type = SHB_OS;
335                 option.value_length = (guint16)strlen(os);
336
337                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
338                         return FALSE;
339
340                 if (!write_func(write_data_info, (const guint8*)os, (int) strlen(os), bytes_written, err))
341                         return FALSE;
342
343                 if (strlen(os) % 4) {
344                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(os) % 4, bytes_written, err))
345                                 return FALSE;
346                 }
347         }
348         if ((appname != NULL) && (strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
349                 /* write shb_userappl options */
350                 option.type = SHB_USERAPPL;
351                 option.value_length = (guint16)strlen(appname);
352
353                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
354                         return FALSE;
355
356                 if (!write_func(write_data_info, (const guint8*)appname, (int) strlen(appname), bytes_written, err))
357                         return FALSE;
358
359                 if (strlen(appname) % 4) {
360                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(appname) % 4, bytes_written, err))
361                                 return FALSE;
362                 }
363         }
364         if (have_options) {
365                 /* write end of options */
366                 option.type = OPT_ENDOFOPT;
367                 option.value_length = 0;
368                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
369                         return FALSE;
370         }
371
372         /* write the trailing block total length */
373         return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
374 }
375
376 gboolean
377 libpcap_write_interface_description_block(libpcap_write_t write_func, void* write_data_info,
378                                           const char *comment, /* OPT_COMMENT        1 */
379                                           const char *name,    /* IDB_NAME           2 */
380                                           const char *descr,   /* IDB_DESCRIPTION    3 */
381                                           const char *filter,  /* IDB_FILTER        11 */
382                                           const char *os,      /* IDB_OS            12 */
383                                           int link_type,
384                                           int snap_len,
385                                           guint64 *bytes_written,
386                                           guint64 if_speed,    /* IDB_IF_SPEED       8 */
387                                           guint8 tsresol,      /* IDB_TSRESOL        9 */
388                                           int *err)
389 {
390         struct idb idb;
391         struct option option;
392         guint32 block_total_length;
393         const guint32 padding = 0;
394         gboolean have_options = FALSE;
395
396         block_total_length = (guint32)(sizeof(struct idb) + sizeof(guint32));
397         /* 01 - OPT_COMMENT */
398         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
399                 block_total_length += (guint32)(sizeof(struct option) +
400                                                 (guint16)ADD_PADDING(strlen(comment)));
401                 have_options = TRUE;
402         }
403
404         /* 02 - IDB_NAME */
405         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
406                 block_total_length += (guint32)(sizeof(struct option) +
407                                                 (guint16)ADD_PADDING(strlen(name)));
408                 have_options = TRUE;
409         }
410
411         /* 03 - IDB_DESCRIPTION */
412         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
413                 block_total_length += (guint32)(sizeof(struct option) +
414                                                 (guint16)ADD_PADDING(strlen(descr)));
415                 have_options = TRUE;
416         }
417
418         /* 08 - IDB_IF_SPEED */
419         if (if_speed != 0) {
420                 block_total_length += (guint32)(sizeof(struct option) +
421                                                 sizeof(guint64));
422                 have_options = TRUE;
423         }
424
425         /* 09 - IDB_TSRESOL */
426         if (tsresol != 0) {
427                 block_total_length += (guint32)(sizeof(struct option) +
428                                                 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 += (guint32)(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 += (guint32)(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 += (guint32)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         if (!write_func(write_data_info, (const guint8*)&idb, sizeof(struct idb), bytes_written, err))
458                 return FALSE;
459
460         /* 01 - OPT_COMMENT - write comment string if applicable */
461         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
462                 option.type = OPT_COMMENT;
463                 option.value_length = (guint16)strlen(comment);
464
465                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
466                         return FALSE;
467
468                 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
469                         return FALSE;
470
471                 if (strlen(comment) % 4) {
472                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
473                                 return FALSE;
474                 }
475         }
476
477         /* 02 - IDB_NAME - write interface name string if applicable */
478         if ((name != NULL) && (strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
479                 option.type = IDB_NAME;
480                 option.value_length = (guint16)strlen(name);
481
482                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
483                         return FALSE;
484
485                 if (!write_func(write_data_info, (const guint8*)name, (int) strlen(name), bytes_written, err))
486                         return FALSE;
487
488                 if (strlen(name) % 4) {
489                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(name) % 4, bytes_written, err))
490                                 return FALSE;
491                 }
492         }
493
494         /* 03 - IDB_DESCRIPTION */
495         /* write interface description string if applicable */
496         if ((descr != NULL) && (strlen(descr) > 0) && (strlen(descr) < G_MAXUINT16)) {
497                 option.type = IDB_DESCRIPTION;
498                 option.value_length = (guint16)strlen(descr);
499
500                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
501                         return FALSE;
502
503                 if (!write_func(write_data_info, (const guint8*)descr, (int) strlen(descr), bytes_written, err))
504                         return FALSE;
505
506                 if (strlen(descr) % 4) {
507                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(descr) % 4, bytes_written, err))
508                                 return FALSE;
509                 }
510         }
511
512         /* 08 - IDB_IF_SPEED */
513         if (if_speed != 0) {
514                 option.type = IDB_IF_SPEED;
515                 option.value_length = sizeof(guint64);
516
517                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
518                         return FALSE;
519
520                 if (!write_func(write_data_info, (const guint8*)&if_speed, sizeof(guint64), bytes_written, err))
521                         return FALSE;
522         }
523
524         /* 09 - IDB_TSRESOL */
525         if (tsresol != 0) {
526                 option.type = IDB_TSRESOL;
527                 option.value_length = sizeof(guint8);
528
529                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
530                         return FALSE;
531
532                 if (!write_func(write_data_info, (const guint8*)&tsresol, sizeof(guint8), bytes_written, err))
533                         return FALSE;
534
535                 if (!write_func(write_data_info, (const guint8*)&padding, 3, bytes_written, err))
536                         return FALSE;
537         }
538
539         /* 11 - IDB_FILTER - write filter string if applicable
540          * We only write version 1 of the filter, libpcap string
541          */
542         if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
543                 option.type = IDB_FILTER;
544                 option.value_length = (guint16)(strlen(filter) + 1 );
545                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
546                         return FALSE;
547
548                 /* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
549                 if (!write_func(write_data_info, (const guint8*)&padding, 1, bytes_written, err))
550                         return FALSE;
551                 if (!write_func(write_data_info, (const guint8*)filter, (int) strlen(filter), bytes_written, err))
552                         return FALSE;
553                 if ((strlen(filter) + 1) % 4) {
554                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - (strlen(filter) + 1) % 4, bytes_written, err))
555                                 return FALSE;
556                 }
557         }
558
559         /* 12 - IDB_OS - write os string if applicable */
560         if ((os != NULL) && (strlen(os) > 0) && (strlen(os) < G_MAXUINT16)) {
561                 option.type = IDB_OS;
562                 option.value_length = (guint16)strlen(os);
563                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
564                         return FALSE;
565                 if (!write_func(write_data_info, (const guint8*)os, (int) strlen(os), bytes_written, err))
566                         return FALSE;
567                 if (strlen(os) % 4) {
568                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(os) % 4, bytes_written, err))
569                                 return FALSE;
570                 }
571         }
572
573         if (have_options) {
574                 /* write end of options */
575                 option.type = OPT_ENDOFOPT;
576                 option.value_length = 0;
577                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
578                         return FALSE;
579         }
580
581         /* write the trailing Block Total Length */
582         return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
583 }
584
585 /* Write a record for a packet to a dump file.
586    Returns TRUE on success, FALSE on failure. */
587 gboolean
588 libpcap_write_enhanced_packet_block(libpcap_write_t write_func, void* write_data_info,
589                                     const char *comment,
590                                     time_t sec, guint32 usec,
591                                     guint32 caplen, guint32 len,
592                                     guint32 interface_id,
593                                     guint ts_mul,
594                                     const guint8 *pd,
595                                     guint32 flags,
596                                     guint64 *bytes_written,
597                                     int *err)
598 {
599         struct epb epb;
600         struct option option;
601         guint32 block_total_length;
602         guint64 timestamp;
603         gboolean have_options = FALSE;
604         const guint32 padding = 0;
605
606         block_total_length = (guint32)(sizeof(struct epb) +
607                                        ADD_PADDING(caplen) +
608                                        sizeof(guint32));
609         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
610                 block_total_length += (guint32)(sizeof(struct option) +
611                                                 (guint16)ADD_PADDING(strlen(comment)));
612                 have_options = TRUE;
613         }
614         if (flags != 0) {
615                 block_total_length += (guint32)(sizeof(struct option) +
616                                                 sizeof(guint32));
617                 have_options = TRUE;
618         }
619         /* If we have options add size of end-of-options */
620         if (have_options) {
621                 block_total_length += (guint32)sizeof(struct option);
622         }
623         timestamp = (guint64)sec * ts_mul + (guint64)usec;
624         epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
625         epb.block_total_length = block_total_length;
626         epb.interface_id = interface_id;
627         epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
628         epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
629         epb.captured_len = caplen;
630         epb.packet_len = len;
631         if (!write_func(write_data_info, (const guint8*)&epb, sizeof(struct epb), bytes_written, err))
632                 return FALSE;
633         if (!write_func(write_data_info, pd, caplen, bytes_written, err))
634                 return FALSE;
635         if (caplen % 4) {
636                 if (!write_func(write_data_info, (const guint8*)&padding, 4 - caplen % 4, bytes_written, err))
637                         return FALSE;
638         }
639         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
640                 option.type = OPT_COMMENT;
641                 option.value_length = (guint16)strlen(comment);
642
643                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
644                         return FALSE;
645
646                 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
647                         return FALSE;
648
649                 if (strlen(comment) % 4) {
650                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
651                                 return FALSE;
652                 }
653         }
654         if (flags != 0) {
655                 option.type = EPB_FLAGS;
656                 option.value_length = sizeof(guint32);
657                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
658                         return FALSE;
659                 if (!write_func(write_data_info, (const guint8*)&flags, sizeof(guint32), bytes_written, err))
660                         return FALSE;
661                 option.type = OPT_ENDOFOPT;
662                 option.value_length = 0;
663                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
664                         return FALSE;
665        }
666
667        return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
668 }
669
670 gboolean
671 libpcap_write_interface_statistics_block(libpcap_write_t write_func, void* write_data_info,
672                                          guint32 interface_id,
673                                          guint64 *bytes_written,
674                                          const char *comment,   /* OPT_COMMENT           1 */
675                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
676                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
677                                          guint64 isb_ifrecv,    /* ISB_IFRECV            4 */
678                                          guint64 isb_ifdrop,    /* ISB_IFDROP            5 */
679                                          int *err)
680 {
681         struct isb isb;
682 #ifdef _WIN32
683         FILETIME now;
684 #else
685         struct timeval now;
686 #endif
687         struct option option;
688         guint32 block_total_length;
689         guint64 timestamp;
690         gboolean have_options = FALSE;
691         const guint32 padding = 0;
692 #ifdef _WIN32
693         /*
694          * Current time, represented as 100-nanosecond intervals since
695          * January 1, 1601, 00:00:00 UTC.
696          *
697          * I think DWORD might be signed, so cast both parts of "now"
698          * to guint32 so that the sign bit doesn't get treated specially.
699          *
700          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
701          * might want to use instead.
702          */
703         GetSystemTimeAsFileTime(&now);
704         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
705                     (guint32)now.dwLowDateTime;
706
707         /*
708          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
709          * intervals.
710          */
711         timestamp /= 10;
712
713         /*
714          * Subtract difference, in microseconds, between January 1, 1601
715          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
716          */
717         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
718 #else
719         /*
720          * Current time, represented as seconds and microseconds since
721          * January 1, 1970, 00:00:00 UTC.
722          */
723         gettimeofday(&now, NULL);
724
725         /*
726          * Convert to delta in microseconds.
727          */
728         timestamp = (guint64)(now.tv_sec) * 1000000 +
729                     (guint64)(now.tv_usec);
730 #endif
731         block_total_length = (guint32)(sizeof(struct isb) + sizeof(guint32));
732         if (isb_ifrecv != G_MAXUINT64) {
733                 block_total_length += (guint32)(sizeof(struct option) +
734                                                 sizeof(guint64));
735                 have_options = TRUE;
736         }
737         if (isb_ifdrop != G_MAXUINT64) {
738                 block_total_length += (guint32)(sizeof(struct option) +
739                                                 sizeof(guint64));
740                 have_options = TRUE;
741         }
742         /* OPT_COMMENT */
743         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
744                 block_total_length += (guint32)(sizeof(struct option) +
745                                       (guint16)ADD_PADDING(strlen(comment)));
746                 have_options = TRUE;
747         }
748         if (isb_starttime !=0) {
749                 block_total_length += (guint32)(sizeof(struct option) +
750                                       sizeof(guint64)); /* ISB_STARTTIME */
751                 have_options = TRUE;
752         }
753         if (isb_endtime !=0) {
754                 block_total_length += (guint32)(sizeof(struct option) +
755                                       sizeof(guint64)); /* ISB_ENDTIME */
756                 have_options = TRUE;
757         }
758         /* If we have options add size of end-of-options */
759         if (have_options) {
760                 block_total_length += (guint32)sizeof(struct option);
761         }
762
763         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
764         isb.block_total_length = block_total_length;
765         isb.interface_id = interface_id;
766         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
767         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
768         if (!write_func(write_data_info, (const guint8*)&isb, sizeof(struct isb), bytes_written, err))
769                 return FALSE;
770
771         /* write comment string if applicable */
772         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
773                 option.type = OPT_COMMENT;
774                 option.value_length = (guint16)strlen(comment);
775                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
776                         return FALSE;
777
778                 if (!write_func(write_data_info, (const guint8*)comment, (int) strlen(comment), bytes_written, err))
779                         return FALSE;
780
781                 if (strlen(comment) % 4) {
782                         if (!write_func(write_data_info, (const guint8*)&padding, 4 - strlen(comment) % 4, bytes_written, err))
783                                 return FALSE;
784                 }
785         }
786
787         if (isb_starttime !=0) {
788                 guint32 high, low;
789
790                 option.type = ISB_STARTTIME;
791                 option.value_length = sizeof(guint64);
792                 high = (guint32)((isb_starttime>>32) & 0xffffffff);
793                 low = (guint32)(isb_starttime & 0xffffffff);
794                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
795                         return FALSE;
796
797                 if (!write_func(write_data_info, (const guint8*)&high, sizeof(guint32), bytes_written, err))
798                         return FALSE;
799
800                 if (!write_func(write_data_info, (const guint8*)&low, sizeof(guint32), bytes_written, err))
801                         return FALSE;
802         }
803         if (isb_endtime !=0) {
804                 guint32 high, low;
805
806                 option.type = ISB_ENDTIME;
807                 option.value_length = sizeof(guint64);
808                 high = (guint32)((isb_endtime>>32) & 0xffffffff);
809                 low = (guint32)(isb_endtime & 0xffffffff);
810                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
811                         return FALSE;
812
813                 if (!write_func(write_data_info, (const guint8*)&high, sizeof(guint32), bytes_written, err))
814                         return FALSE;
815
816                 if (!write_func(write_data_info, (const guint8*)&low, sizeof(guint32), bytes_written, err))
817                         return FALSE;
818         }
819         if (isb_ifrecv != G_MAXUINT64) {
820                 option.type = ISB_IFRECV;
821                 option.value_length = sizeof(guint64);
822                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
823                         return FALSE;
824
825                 if (!write_func(write_data_info, (const guint8*)&isb_ifrecv, sizeof(guint64), bytes_written, err))
826                         return FALSE;
827         }
828         if (isb_ifdrop != G_MAXUINT64) {
829                 option.type = ISB_IFDROP;
830                 option.value_length = sizeof(guint64);
831                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
832                         return FALSE;
833
834                 if (!write_func(write_data_info, (const guint8*)&isb_ifdrop, sizeof(guint64), bytes_written, err))
835                         return FALSE;
836         }
837         if (have_options) {
838                 /* write end of options */
839                 option.type = OPT_ENDOFOPT;
840                 option.value_length = 0;
841                 if (!write_func(write_data_info, (const guint8*)&option, sizeof(struct option), bytes_written, err))
842                         return FALSE;
843         }
844
845         return write_func(write_data_info, (const guint8*)&block_total_length, sizeof(guint32), bytes_written, err);
846 }
847
848 /*
849  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
850  *
851  * Local variables:
852  * c-basic-offset: 4
853  * tab-width: 8
854  * indent-tabs-mode: nil
855  * End:
856  *
857  * vi: set shiftwidth=4 tabstop=8 expandtab:
858  * :indentSize=4:tabSize=8:noTabs=true:
859  */