From Nick Lowe:
[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                                          pcap_t *pd,
592                                          long *bytes_written,
593                                          const char *comment,   /* OPT_COMMENT           1 */
594                                          guint64 isb_starttime, /* ISB_STARTTIME         2 */
595                                          guint64 isb_endtime,   /* ISB_ENDTIME           3 */
596                                          int *err)
597 {
598         struct isb isb;
599 #ifdef _WIN32
600         FILETIME now;
601 #else
602         struct timeval now;
603 #endif
604         struct option option;
605         struct pcap_stat stats;
606         guint32 block_total_length;
607         guint64 timestamp;
608         guint64 counter;
609         gboolean stats_retrieved;
610         gboolean have_options = FALSE;
611         const guint32 padding = 0;
612 #ifdef _WIN32
613         /*
614          * Current time, represented as 100-nanosecond intervals since
615          * January 1, 1601, 00:00:00 UTC.
616          *
617          * I think DWORD might be signed, so cast both parts of "now"
618          * to guint32 so that the sign bit doesn't get treated specially.
619          *
620          * Windows 8 provides GetSystemTimePreciseAsFileTime which we
621          * might want to use instead.
622          */
623         GetSystemTimeAsFileTime(&now);
624         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
625                     (guint32)now.dwLowDateTime;
626
627         /*
628          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
629          * intervals.
630          */
631         timestamp /= 10;
632
633         /*
634          * Subtract difference, in microseconds, between January 1, 1601
635          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
636          */
637         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
638 #else
639         /*
640          * Current time, represented as seconds and microseconds since
641          * January 1, 1970, 00:00:00 UTC.
642          */
643         gettimeofday(&now, NULL);
644
645         /*
646          * Convert to delta in microseconds.
647          */
648         timestamp = (guint64)(now.tv_sec) * 1000000 +
649                     (guint64)(now.tv_usec);
650 #endif
651         if (pcap_stats(pd, &stats) < 0) {
652                 stats_retrieved = FALSE;
653                 g_warning("pcap_stats() failed.");
654         } else {
655                 stats_retrieved = TRUE;
656                 have_options = TRUE;
657         }
658         block_total_length = sizeof(struct isb) +
659                              sizeof(guint32);
660         if (stats_retrieved) {
661                 block_total_length += 2 * sizeof(struct option) + 2 * sizeof(guint64); /* ISB_IFRECV + ISB_IFDROP */
662         }
663         /* OPT_COMMENT */
664         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
665                 block_total_length += sizeof(struct option) +
666                                       (guint16)ADD_PADDING(strlen(comment));
667                 have_options = TRUE;
668         }
669         if (isb_starttime !=0) {
670                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_STARTTIME */
671                 have_options = TRUE;
672         }
673         if (isb_endtime !=0) {
674                 block_total_length += sizeof(struct option) + sizeof(guint64); /* ISB_ENDTIME */
675                 have_options = TRUE;
676         }
677         /* If we have options add size of end-of-options */
678         if (have_options) {
679                 block_total_length += sizeof(struct option);
680         }
681
682         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
683         isb.block_total_length = block_total_length;
684         isb.interface_id = interface_id;
685         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
686         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
687         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
688
689         /* write comment string if applicable */
690         if ((comment != NULL) && (strlen(comment) > 0) && (strlen(comment) < G_MAXUINT16)) {
691                 option.type = OPT_COMMENT;
692                 option.value_length = (guint16)strlen(comment);
693                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
694                 WRITE_DATA(fp, comment, strlen(comment), *bytes_written, err);
695                 if (strlen(comment) % 4) {
696                         WRITE_DATA(fp, &padding, 4 - strlen(comment) % 4 , *bytes_written, err);
697                 }
698         }
699
700         if (isb_starttime !=0) {
701                 option.type = ISB_STARTTIME;
702                 option.value_length = sizeof(guint64);
703                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
704                 WRITE_DATA(fp, &isb_starttime, sizeof(guint64), *bytes_written, err);
705         }
706         if (isb_endtime !=0) {
707                 option.type = ISB_ENDTIME;
708                 option.value_length = sizeof(guint64);
709                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
710                 WRITE_DATA(fp, &isb_endtime, sizeof(guint64), *bytes_written, err);
711         }
712         if (stats_retrieved) {
713                 /* */
714                 option.type = ISB_IFRECV;
715                 option.value_length = sizeof(guint64);
716                 counter = stats.ps_recv;
717                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
718                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
719                 /* */
720                 option.type = ISB_IFDROP;
721                 option.value_length = sizeof(guint64);
722                 counter = stats.ps_drop;
723                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
724                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
725         }
726         if (have_options) {
727                 /* write end of options */
728                 option.type = OPT_ENDOFOPT;
729                 option.value_length = 0;
730                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
731         }
732
733         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
734
735         return TRUE;
736 }
737
738 gboolean
739 libpcap_dump_flush(FILE *pd, int *err)
740 {
741         if (fflush(pd) == EOF) {
742                 if (err != NULL)
743                         *err = errno;
744                 return FALSE;
745         }
746         return TRUE;
747 }
748
749 gboolean
750 libpcap_dump_close(FILE *pd, int *err)
751 {
752         if (fclose(pd) == EOF) {
753                 if (err != NULL)
754                         *err = errno;
755                 return FALSE;
756         }
757         return TRUE;
758 }
759
760 #endif /* HAVE_LIBPCAP */
761
762 /*
763  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
764  *
765  * Local variables:
766  * c-basic-offset: 4
767  * tab-width: 8
768  * indent-tabs-mode: nil
769  * End:
770  *
771  * vi: set shiftwidth=4 tabstop=8 expandtab:
772  * :indentSize=4:tabSize=8:noTabs=true:
773  */