d75bbee37394b741821ada62c47d2784ff88d92a
[obnox/wireshark/wip.git] / pcapio.c
1 /* pcapio.c
2  * Our own private code for writing libpcap files when capturing.
3  *
4  * We have these because we want a way to open a stream for output given
5  * only a file descriptor.  libpcap 0.9[.x] has "pcap_dump_fopen()", which
6  * provides that, but
7  *
8  *      1) earlier versions of libpcap doesn't have it
9  *
10  * and
11  *
12  *      2) WinPcap doesn't have it, because a file descriptor opened
13  *         by code built for one version of the MSVC++ C library
14  *         can't be used by library routines built for another version
15  *         (e.g., threaded vs. unthreaded).
16  *
17  * Libpcap's pcap_dump() also doesn't return any error indications.
18  *
19  * $Id$
20  *
21  * Wireshark - Network traffic analyzer
22  * By Gerald Combs <gerald@wireshark.org>
23  * Copyright 1998 Gerald Combs
24  *
25  * Derived from code in the Wiretap Library
26  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
27  *
28  * This program is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU General Public License
30  * as published by the Free Software Foundation; either version 2
31  * of the License, or (at your option) any later version.
32  *
33  * This program is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36  * GNU General Public License for more details.
37  *
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #ifdef HAVE_LIBPCAP
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <errno.h>
52 #include <string.h>
53
54 #include <pcap.h>
55
56 #include <glib.h>
57
58 #include "pcapio.h"
59
60 /* Magic numbers in "libpcap" files.
61
62    "libpcap" file records are written in the byte order of the host that
63    writes them, and the reader is expected to fix this up.
64
65    PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
66    is a byte-swapped version of that.
67
68    PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
69    which uses the same common file format as PCAP_MAGIC, but the 
70    timestamps are saved in nanosecond resolution instead of microseconds.
71    PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
72 #define PCAP_MAGIC                      0xa1b2c3d4
73 #define PCAP_SWAPPED_MAGIC              0xd4c3b2a1
74 #define PCAP_NSEC_MAGIC                 0xa1b23c4d
75 #define PCAP_SWAPPED_NSEC_MAGIC         0x4d3cb2a1
76
77 /* "libpcap" file header. */
78 struct pcap_hdr {
79         guint32 magic;          /* magic number */
80         guint16 version_major;  /* major version number */
81         guint16 version_minor;  /* minor version number */
82         gint32  thiszone;       /* GMT to local correction */
83         guint32 sigfigs;        /* accuracy of timestamps */
84         guint32 snaplen;        /* max length of captured packets, in octets */
85         guint32 network;        /* data link type */
86 };
87
88 /* "libpcap" record header. */
89 struct pcaprec_hdr {
90         guint32 ts_sec;         /* timestamp seconds */
91         guint32 ts_usec;        /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
92         guint32 incl_len;       /* number of octets of packet saved in file */
93         guint32 orig_len;       /* actual length of packet */
94 };
95
96 /* Magic numbers in ".pcapng" files.
97  *
98  * .pcapng file records are written in the byte order of the host that
99  * writes them, and the reader is expected to fix this up.
100  * PCAPNG_MAGIC is the magic number, in host byte order;
101  * PCAPNG_SWAPPED_MAGIC is a byte-swapped version of that.
102  */
103 #define PCAPNG_MAGIC         0x1A2B3C4D
104 #define PCAPNG_SWAPPED_MAGIC 0xD4C3B2A1
105
106 /* Currently we are only supporting the initial version of
107    the file format. */
108 #define PCAPNG_MAJOR_VERSION 1
109 #define PCAPNG_MINOR_VERSION 0
110
111 /* Section Header Block without options and trailing Block Total Length */
112 struct shb {
113         guint32 block_type;
114         guint32 block_total_length;
115         guint32 byte_order_magic;
116         guint16 major_version;
117         guint16 minor_version;
118         guint64 section_length;
119 };
120 #define SECTION_HEADER_BLOCK_TYPE 0x0A0D0D0A
121
122 /* Interface Decription Block without options and trailing Block Total Length */
123 struct idb {
124         guint32 block_type;
125         guint32 block_total_length;
126         guint16 link_type;
127         guint16 reserved;
128         guint32 snap_len;
129 };
130 #define INTERFACE_DESCRIPTION_BLOCK_TYPE 0x00000001
131
132 /* Interface Statistics Block without actual packet, options, and trailing
133    Block Total Length */
134 struct isb {
135         guint32 block_type;
136         guint32 block_total_length;
137         guint32 interface_id;
138         guint32 timestamp_high;
139         guint32 timestamp_low;
140 };
141 #define INTERFACE_STATISTICS_BLOCK_TYPE 0x00000005
142
143 /* Enhanced Packet Block without actual packet, options, and trailing
144    Block Total Length */
145 struct epb {
146         guint32 block_type;
147         guint32 block_total_length;
148         guint32 interface_id;
149         guint32 timestamp_high;
150         guint32 timestamp_low;
151         guint32 captured_len;
152         guint32 packet_len;
153 };
154 #define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
155
156 struct option {
157         guint16 type;
158         guint16 value_length;
159 };
160 #define OPT_ENDOFOPT 0
161 #define OPT_COMMENT  1 /* currently not used */
162 #define SHB_HARDWARE 2 /* currently not used */
163 #define SHB_OS       3 /* currently not used */
164 #define SHB_USERAPPL 4
165 #define IDB_NAME     2
166 #define IDB_FILTER  11
167 #define ISB_IFRECV   4
168 #define ISB_IFDROP   5
169 #define ISB_FILTERACCEPT 6
170
171 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
172
173 #define WRITE_DATA(file_pointer, data_pointer, data_length, written_length, error_pointer) \
174 {                                                                                          \
175         do {                                                                               \
176                 size_t nwritten;                                                           \
177                                                                                            \
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;                                    \
182                         } else {                                                           \
183                                 *error_pointer = 0;                                        \
184                         }                                                                  \
185                         fclose(file_pointer);                                              \
186                         return FALSE;                                                      \
187                 }                                                                          \
188                 written_length += nwritten;                                                \
189         } while (0);                                                                       \
190 }
191
192 /* Returns a FILE * to write to on success, NULL on failure */
193 FILE *
194 libpcap_fdopen(int fd, int *err)
195 {
196         FILE *fp;
197
198         fp = fdopen(fd, "wb");
199         if (fp == NULL) {
200                 *err = errno;
201         }
202         return fp;
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(FILE *fp, int linktype, int snaplen, long *bytes_written, int *err)
210 {
211         struct pcap_hdr file_hdr;
212         size_t nwritten;
213
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))
225                         *err = errno;
226                 else
227                         *err = 0;       /* short write */
228                 return FALSE;
229         }
230         *bytes_written += sizeof(file_hdr);
231
232         return TRUE;
233 }
234
235 /* Write a record for a packet to a dump file.
236    Returns TRUE on success, FALSE on failure. */
237 gboolean
238 libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
239     long *bytes_written, int *err)
240 {
241         struct pcaprec_hdr rec_hdr;
242         size_t nwritten;
243
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))
251                         *err = errno;
252                 else
253                         *err = 0;       /* short write */
254                 return FALSE;
255         }
256         *bytes_written += sizeof rec_hdr;
257
258         nwritten = fwrite(pd, 1, phdr->caplen, fp);
259         if (nwritten != phdr->caplen) {
260                 if (nwritten == 0 && ferror(fp))
261                         *err = errno;
262                 else
263                         *err = 0;       /* short write */
264                 return FALSE;
265         }
266         *bytes_written += phdr->caplen;
267         return TRUE;
268 }
269
270 gboolean
271 libpcap_write_session_header_block(FILE *fp,
272                                    char *appname,
273                                    long *bytes_written,
274                                    int *err)
275 {
276         struct shb shb;
277         struct option option;
278         guint32 block_total_length;
279         const guint32 padding = 0;
280         
281         block_total_length = sizeof(struct shb) +
282                              sizeof(struct option) + ADD_PADDING(strlen(appname) + 1) +
283                              sizeof(struct option) +
284                              sizeof(guint32);
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);
300         }
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);
307         return TRUE;
308 }
309
310 gboolean
311 libpcap_write_interface_description_block(FILE *fp,
312                                           char *name,
313                                           char *filter,
314                                           int link_type,
315                                           int snap_len,
316                                           long *bytes_written,
317                                           int *err)
318 {
319         struct idb idb;
320         struct option option;
321         guint32 block_total_length;
322         const guint32 padding = 0;
323
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);
327         }
328         if (strlen(filter) > 0) {
329                 block_total_length += sizeof(struct option) + ADD_PADDING(strlen(filter) + 1);
330         }
331         if ((strlen(name) > 0) || (strlen(filter) > 0)) {
332                 block_total_length += sizeof(struct option);
333         }
334         idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
335         idb.block_total_length = block_total_length;
336         idb.link_type = link_type;
337         idb.reserved = 0;
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);
348                 }
349         }
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);
357                 }
358         }
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);
363         }
364         /* write the trailing Block Total Length */
365         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
366         return TRUE;
367 }
368
369 /* Write a record for a packet to a dump file.
370    Returns TRUE on success, FALSE on failure. */
371 gboolean
372 libpcap_write_enhanced_packet_block(FILE *fp,
373                                     const struct pcap_pkthdr *phdr,
374                                     guint32 interface_id,
375                                     const u_char *pd,
376                                     long *bytes_written,
377                                     int *err)
378 {
379         struct epb epb;
380         guint32 block_total_length;
381         guint64 timestamp;
382         const guint32 padding = 0;
383
384         block_total_length = sizeof(struct epb) +
385                              ADD_PADDING(phdr->caplen) +
386                              sizeof(guint32);
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);
400         }
401         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
402         return TRUE;
403 }
404
405 gboolean
406 libpcap_write_interface_statistics_block(FILE *fp,
407                                          guint32 interface_id,
408                                          pcap_t *pd,
409                                          long *bytes_written,
410                                          int *err)
411 {
412         struct isb isb;
413 #ifndef _WIN32
414         struct timeval now;
415 #endif
416         struct option option;
417         struct pcap_stat stats;
418         guint32 block_total_length;
419         guint64 timestamp;
420         guint64 counter;
421         gboolean stats_retrieved;
422         
423 #ifdef _WIN32
424         timestamp = 0; /* FIXME */
425 #else
426         gettimeofday(&now, NULL);
427         timestamp = (guint64)(now.tv_sec) * 1000000 +
428                     (guint64)(now.tv_usec);
429 #endif
430         if (pcap_stats(pd, &stats) < 0) {
431                 stats_retrieved = FALSE;
432                 g_warning("pcap_stats() failed.");
433         } else {
434                 stats_retrieved = TRUE;
435         }
436         block_total_length = sizeof(struct isb) +
437                              sizeof(guint32);
438         if (stats_retrieved) {
439                 block_total_length += 3 * sizeof(struct option) + 2 * sizeof(guint64);
440         }
441         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
442         isb.block_total_length = block_total_length;
443         isb.interface_id = interface_id;
444         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
445         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
446         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
447         if (stats_retrieved) {
448                 /* */
449                 option.type = ISB_IFRECV;
450                 option.value_length = sizeof(guint64);
451                 counter = stats.ps_recv;
452                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
453                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
454                 /* */
455                 option.type = ISB_IFDROP;
456                 option.value_length = sizeof(guint64);
457                 counter = stats.ps_drop;
458                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
459                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
460                 /* last option */
461                 option.type = OPT_ENDOFOPT;
462                 option.value_length = 0;
463                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
464         }
465         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
466         
467         return TRUE;
468 }
469
470 gboolean
471 libpcap_dump_flush(FILE *pd, int *err)
472 {
473         if (fflush(pd) == EOF) {
474                 if (err != NULL)
475                         *err = errno;
476                 return FALSE;
477         }
478         return TRUE;
479 }
480
481 gboolean
482 libpcap_dump_close(FILE *pd, int *err)
483 {
484         if (fclose(pd) == EOF) {
485                 if (err != NULL)
486                         *err = errno;
487                 return FALSE;
488         }
489         return TRUE;
490 }
491
492 #endif /* HAVE_LIBPCAP */