2 * Our own private code for writing libpcap files when capturing.
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
8 * 1) earlier versions of libpcap doesn't have it
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).
17 * Libpcap's pcap_dump() also doesn't return any error indications.
21 * Wireshark - Network traffic analyzer
22 * By Gerald Combs <gerald@wireshark.org>
23 * Copyright 1998 Gerald Combs
25 * Derived from code in the Wiretap Library
26 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
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.
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.
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.
60 /* Magic numbers in "libpcap" files.
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.
65 PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
66 is a byte-swapped version of that.
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
77 /* "libpcap" file header. */
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 */
88 /* "libpcap" record header. */
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 */
96 /* Magic numbers in ".pcapng" files.
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.
103 #define PCAPNG_MAGIC 0x1A2B3C4D
104 #define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1
106 /* Currently we are only supporting the initial version of
108 #define PCAPNG_MAJOR_VERSION 1
109 #define PCAPNG_MINOR_VERSION 0
111 /* Section Header Block without options and trailing Block Total Length */
114 guint32 block_total_length;
115 guint32 byte_order_magic;
116 guint16 major_version;
117 guint16 minor_version;
118 guint64 section_length;
120 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
122 /* Interface Decription Block without options and trailing Block Total Length */
125 guint32 block_total_length;
130 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
132 /* Interface Statistics Block without actual packet, options, and trailing
133 Block Total Length */
136 guint32 block_total_length;
137 guint32 interface_id;
138 guint32 timestamp_high;
139 guint32 timestamp_low;
141 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
143 /* Enhanced Packet Block without actual packet, options, and trailing
144 Block Total Length */
147 guint32 block_total_length;
148 guint32 interface_id;
149 guint32 timestamp_high;
150 guint32 timestamp_low;
151 guint32 captured_len;
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
158 guint16 value_length;
160 #define OPT_ENDOFOPT 0
161 #define OPT_COMMENT 1 /* currently not used */
162 #define SHB_HARDWARE 2 /* currently not used */
163 #define SHB_OS 3 /* currently not used */
164 #define SHB_USERAPPL 4
166 #define IDB_FILTER 11
169 #define ISB_FILTERACCEPT 6
171 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
173 #define WRITE_DATA(file_pointer, data_pointer, data_length, written_length, error_pointer) \
178 nwritten = fwrite(data_pointer, 1, data_length, file_pointer); \
179 if (nwritten != data_length) { \
180 if (nwritten == 0 && ferror(file_pointer)) { \
181 *error_pointer = errno; \
183 *error_pointer = 0; \
185 fclose(file_pointer); \
188 written_length += nwritten; \
192 /* Returns a FILE * to write to on success, NULL on failure */
194 libpcap_fdopen(int fd, int *err)
198 fp = fdopen(fd, "wb");
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*/
209 libpcap_write_file_header(FILE *fp, int linktype, int snaplen, long *bytes_written, int *err)
211 struct pcap_hdr file_hdr;
214 file_hdr.magic = PCAP_MAGIC;
215 /* current "libpcap" format is 2.4 */
216 file_hdr.version_major = 2;
217 file_hdr.version_minor = 4;
218 file_hdr.thiszone = 0; /* XXX - current offset? */
219 file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
220 file_hdr.snaplen = snaplen;
221 file_hdr.network = linktype;
222 nwritten = fwrite(&file_hdr, 1, sizeof(file_hdr), fp);
223 if (nwritten != sizeof(file_hdr)) {
224 if (nwritten == 0 && ferror(fp))
227 *err = 0; /* short write */
230 *bytes_written += sizeof(file_hdr);
235 /* Write a record for a packet to a dump file.
236 Returns TRUE on success, FALSE on failure. */
238 libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
239 long *bytes_written, int *err)
241 struct pcaprec_hdr rec_hdr;
244 rec_hdr.ts_sec = phdr->ts.tv_sec;
245 rec_hdr.ts_usec = phdr->ts.tv_usec;
246 rec_hdr.incl_len = phdr->caplen;
247 rec_hdr.orig_len = phdr->len;
248 nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
249 if (nwritten != sizeof rec_hdr) {
250 if (nwritten == 0 && ferror(fp))
253 *err = 0; /* short write */
256 *bytes_written += sizeof rec_hdr;
258 nwritten = fwrite(pd, 1, phdr->caplen, fp);
259 if (nwritten != phdr->caplen) {
260 if (nwritten == 0 && ferror(fp))
263 *err = 0; /* short write */
266 *bytes_written += phdr->caplen;
271 libpcap_write_session_header_block(FILE *fp,
277 struct option option;
278 guint32 block_total_length;
279 const guint32 padding = 0;
281 block_total_length = sizeof(struct shb) +
282 sizeof(struct option) + ADD_PADDING(strlen(appname) + 1) +
283 sizeof(struct option) +
285 /* write shb header */
286 shb.block_type = SECTION_HEADER_BLOCK_TYPE;
287 shb.block_total_length = block_total_length;
288 shb.byte_order_magic = PCAPNG_MAGIC;
289 shb.major_version = PCAPNG_MAJOR_VERSION;
290 shb.minor_version = PCAPNG_MINOR_VERSION;
291 shb.section_length = -1;
292 WRITE_DATA(fp, &shb, sizeof(struct shb), *bytes_written, err);
293 /* write shb_userappl options */
294 option.type = SHB_USERAPPL;
295 option.value_length = strlen(appname) + 1;
296 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
297 WRITE_DATA(fp, appname, strlen(appname) + 1, *bytes_written, err);
298 if ((strlen(appname) + 1) % 4) {
299 WRITE_DATA(fp, &padding, 4 - (strlen(appname) + 1) % 4, *bytes_written, err);
301 /* write last option */
302 option.type = OPT_ENDOFOPT;
303 option.value_length = 0;
304 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
305 /* write the trailing block total length */
306 WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
311 libpcap_write_interface_description_block(FILE *fp,
320 struct option option;
321 guint32 block_total_length;
322 const guint32 padding = 0;
324 block_total_length = sizeof(struct idb) + sizeof(guint32);
325 if (strlen(name) > 0) {
326 block_total_length += sizeof(struct option) + ADD_PADDING(strlen(name) + 1);
328 if (strlen(filter) > 0) {
329 block_total_length += sizeof(struct option) + ADD_PADDING(strlen(filter) + 1);
331 if ((strlen(name) > 0) || (strlen(filter) > 0)) {
332 block_total_length += sizeof(struct option);
334 idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
335 idb.block_total_length = block_total_length;
336 idb.link_type = link_type;
338 idb.snap_len = snap_len;
339 WRITE_DATA(fp, &idb, sizeof(struct idb), *bytes_written, err);
340 /* write the options */
341 if (strlen(name) > 0) {
342 option.type = IDB_NAME;
343 option.value_length = strlen(name) + 1;
344 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
345 WRITE_DATA(fp, name, strlen(name) + 1, *bytes_written, err);
346 if ((strlen(name) + 1) % 4) {
347 WRITE_DATA(fp, &padding, 4 - (strlen(name) + 1) % 4 , *bytes_written, err);
350 if (strlen(filter) > 0) {
351 option.type = IDB_FILTER;
352 option.value_length = strlen(filter) + 1;
353 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
354 WRITE_DATA(fp, filter, strlen(filter) + 1, *bytes_written, err);
355 if ((strlen(filter) + 1) % 4) {
356 WRITE_DATA(fp, &padding, 4 - (strlen(filter) + 1) % 4 , *bytes_written, err);
359 if ((strlen(name) > 0) || (strlen(filter) > 0)) {
360 option.type = OPT_ENDOFOPT;
361 option.value_length = 0;
362 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
364 /* write the trailing Block Total Length */
365 WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
369 /* Write a record for a packet to a dump file.
370 Returns TRUE on success, FALSE on failure. */
372 libpcap_write_enhanced_packet_block(FILE *fp,
373 const struct pcap_pkthdr *phdr,
374 guint32 interface_id,
380 guint32 block_total_length;
382 const guint32 padding = 0;
384 block_total_length = sizeof(struct epb) +
385 ADD_PADDING(phdr->caplen) +
387 timestamp = (guint64)(phdr->ts.tv_sec) * 1000000 +
388 (guint64)(phdr->ts.tv_usec);
389 epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
390 epb.block_total_length = block_total_length;
391 epb.interface_id = interface_id;
392 epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
393 epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
394 epb.captured_len = phdr->caplen;
395 epb.packet_len = phdr->len;
396 WRITE_DATA(fp, &epb, sizeof(struct epb), *bytes_written, err);
397 WRITE_DATA(fp, pd, phdr->caplen, *bytes_written, err);
398 if (phdr->caplen % 4) {
399 WRITE_DATA(fp, &padding, 4 - phdr->caplen % 4, *bytes_written, err);
401 WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
406 libpcap_write_interface_statistics_block(FILE *fp,
407 guint32 interface_id,
414 struct option option;
415 struct pcap_stat stats;
416 guint32 block_total_length;
419 gboolean stats_retrieved;
421 gettimeofday(&now, NULL);
422 timestamp = (guint64)(now.tv_sec) * 1000000 +
423 (guint64)(now.tv_usec);
424 if (pcap_stats(pd, &stats) < 0) {
425 stats_retrieved = FALSE;
426 g_warning("pcap_stats() failed.");
428 stats_retrieved = TRUE;
430 block_total_length = sizeof(struct isb) +
432 if (stats_retrieved) {
433 block_total_length += 3 * sizeof(struct option) + 2 * sizeof(guint64);
435 isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
436 isb.block_total_length = block_total_length;
437 isb.interface_id = interface_id;
438 isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
439 isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
440 WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
441 if (stats_retrieved) {
443 option.type = ISB_IFRECV;
444 option.value_length = sizeof(guint64);
445 counter = stats.ps_recv;
446 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
447 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
449 option.type = ISB_IFDROP;
450 option.value_length = sizeof(guint64);
451 counter = stats.ps_drop;
452 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
453 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
455 option.type = OPT_ENDOFOPT;
456 option.value_length = 0;
457 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
459 WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
465 libpcap_dump_flush(FILE *pd, int *err)
467 if (fflush(pd) == EOF) {
476 libpcap_dump_close(FILE *pd, int *err)
478 if (fclose(pd) == EOF) {
486 #endif /* HAVE_LIBPCAP */