Fix for bug 6356:
[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                         return FALSE;                                                      \
186                 }                                                                          \
187                 written_length += (long)nwritten;                                          \
188         } while (0);                                                                       \
189 }
190
191 /* Returns a FILE * to write to on success, NULL on failure */
192 FILE *
193 libpcap_fdopen(int fd, int *err)
194 {
195         FILE *fp;
196
197         fp = fdopen(fd, "wb");
198         if (fp == NULL) {
199                 *err = errno;
200         }
201         return fp;
202 }
203
204 /* Write the file header to a dump file.
205    Returns TRUE on success, FALSE on failure.
206    Sets "*err" to an error code, or 0 for a short write, on failure*/
207 gboolean
208 libpcap_write_file_header(FILE *fp, int linktype, int snaplen, long *bytes_written, int *err)
209 {
210         struct pcap_hdr file_hdr;
211         size_t nwritten;
212
213         file_hdr.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         nwritten = fwrite(&file_hdr, 1, sizeof(file_hdr), fp);
222         if (nwritten != sizeof(file_hdr)) {
223                 if (nwritten == 0 && ferror(fp))
224                         *err = errno;
225                 else
226                         *err = 0;       /* short write */
227                 return FALSE;
228         }
229         *bytes_written += sizeof(file_hdr);
230
231         return TRUE;
232 }
233
234 /* Write a record for a packet to a dump file.
235    Returns TRUE on success, FALSE on failure. */
236 gboolean
237 libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
238     long *bytes_written, int *err)
239 {
240         struct pcaprec_hdr rec_hdr;
241         size_t nwritten;
242
243         rec_hdr.ts_sec = phdr->ts.tv_sec;
244         rec_hdr.ts_usec = phdr->ts.tv_usec;
245         rec_hdr.incl_len = phdr->caplen;
246         rec_hdr.orig_len = phdr->len;
247         nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
248         if (nwritten != sizeof rec_hdr) {
249                 if (nwritten == 0 && ferror(fp))
250                         *err = errno;
251                 else
252                         *err = 0;       /* short write */
253                 return FALSE;
254         }
255         *bytes_written += sizeof rec_hdr;
256
257         nwritten = fwrite(pd, 1, phdr->caplen, fp);
258         if (nwritten != phdr->caplen) {
259                 if (nwritten == 0 && ferror(fp))
260                         *err = errno;
261                 else
262                         *err = 0;       /* short write */
263                 return FALSE;
264         }
265         *bytes_written += phdr->caplen;
266         return TRUE;
267 }
268
269 gboolean
270 libpcap_write_session_header_block(FILE *fp,
271                                    const char *appname,
272                                    long *bytes_written,
273                                    int *err)
274 {
275         struct shb shb;
276         struct option option;
277         guint32 block_total_length;
278         const guint32 padding = 0;
279
280         block_total_length = sizeof(struct shb) +
281                              sizeof(guint32);
282         if ((strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
283                 block_total_length += 2 * sizeof(struct option) +
284                                       (guint16)(ADD_PADDING(strlen(appname) + 1));
285         }
286         /* write shb header */
287         shb.block_type = SECTION_HEADER_BLOCK_TYPE;
288         shb.block_total_length = block_total_length;
289         shb.byte_order_magic = PCAPNG_MAGIC;
290         shb.major_version = PCAPNG_MAJOR_VERSION;
291         shb.minor_version = PCAPNG_MINOR_VERSION;
292         shb.section_length = -1;
293         WRITE_DATA(fp, &shb, sizeof(struct shb), *bytes_written, err);
294
295         if ((strlen(appname) > 0) && (strlen(appname) < G_MAXUINT16)) {
296                 /* write shb_userappl options */
297                 option.type = SHB_USERAPPL;
298                 option.value_length = (guint16)(strlen(appname) + 1);
299                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
300                 WRITE_DATA(fp, appname, strlen(appname) + 1, *bytes_written, err);
301                 if ((strlen(appname) + 1) % 4) {
302                         WRITE_DATA(fp, &padding, 4 - (strlen(appname) + 1) % 4, *bytes_written, err);
303                 }
304                 /* write last option */
305                 option.type = OPT_ENDOFOPT;
306                 option.value_length = 0;
307                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
308         }
309         /* write the trailing block total length */
310         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
311         return TRUE;
312 }
313
314 gboolean
315 libpcap_write_interface_description_block(FILE *fp,
316                                           const char *name,
317                                           const char *filter,
318                                           int link_type,
319                                           int snap_len,
320                                           long *bytes_written,
321                                           int *err)
322 {
323         struct idb idb;
324         struct option option;
325         guint32 block_total_length;
326         const guint32 padding = 0;
327
328         block_total_length = sizeof(struct idb) + sizeof(guint32);
329         if ((strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
330                 block_total_length += sizeof(struct option) +
331                                       (guint16)(ADD_PADDING(strlen(name) + 1));
332         }
333         if ((strlen(filter) > 0) && (strlen(name) < G_MAXUINT16)) {
334                 block_total_length += sizeof(struct option) +
335                                       (guint16)(ADD_PADDING(strlen(filter) + 1));
336         }
337         if (((strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) ||
338             ((strlen(filter) > 0) && (strlen(name) < G_MAXUINT16))) {
339                 block_total_length += sizeof(struct option);
340         }
341         /* write block header */
342         idb.block_type = INTERFACE_DESCRIPTION_BLOCK_TYPE;
343         idb.block_total_length = block_total_length;
344         idb.link_type = link_type;
345         idb.reserved = 0;
346         idb.snap_len = snap_len;
347         WRITE_DATA(fp, &idb, sizeof(struct idb), *bytes_written, err);
348         /* write interface name string if applicable */
349         if ((strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) {
350                 option.type = IDB_NAME;
351                 option.value_length = (guint16)(strlen(name) + 1);
352                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
353                 WRITE_DATA(fp, name, strlen(name) + 1, *bytes_written, err);
354                 if ((strlen(name) + 1) % 4) {
355                         WRITE_DATA(fp, &padding, 4 - (strlen(name) + 1) % 4 , *bytes_written, err);
356                 }
357         }
358         /* write filter string if applicable */
359         if ((strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16)) {
360                 option.type = IDB_FILTER;
361                 option.value_length = (guint16)(strlen(filter) + 1);
362                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
363                 WRITE_DATA(fp, filter, strlen(filter) + 1, *bytes_written, err);
364                 if ((strlen(filter) + 1) % 4) {
365                         WRITE_DATA(fp, &padding, 4 - (strlen(filter) + 1) % 4 , *bytes_written, err);
366                 }
367         }
368         /* write endofopt option if there were any options */
369         if (((strlen(name) > 0) && (strlen(name) < G_MAXUINT16)) ||
370             ((strlen(filter) > 0) && (strlen(filter) < G_MAXUINT16))) {
371                 option.type = OPT_ENDOFOPT;
372                 option.value_length = 0;
373                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
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 /* Write a record for a packet to a dump file.
381    Returns TRUE on success, FALSE on failure. */
382 gboolean
383 libpcap_write_enhanced_packet_block(FILE *fp,
384                                     const struct pcap_pkthdr *phdr,
385                                     guint32 interface_id,
386                                     const u_char *pd,
387                                     long *bytes_written,
388                                     int *err)
389 {
390         struct epb epb;
391         guint32 block_total_length;
392         guint64 timestamp;
393         const guint32 padding = 0;
394
395         block_total_length = sizeof(struct epb) +
396                              ADD_PADDING(phdr->caplen) +
397                              sizeof(guint32);
398         timestamp = (guint64)(phdr->ts.tv_sec) * 1000000 +
399                     (guint64)(phdr->ts.tv_usec);
400         epb.block_type = ENHANCED_PACKET_BLOCK_TYPE;
401         epb.block_total_length = block_total_length;
402         epb.interface_id = interface_id;
403         epb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
404         epb.timestamp_low = (guint32)(timestamp & 0xffffffff);
405         epb.captured_len = phdr->caplen;
406         epb.packet_len = phdr->len;
407         WRITE_DATA(fp, &epb, sizeof(struct epb), *bytes_written, err);
408         WRITE_DATA(fp, pd, phdr->caplen, *bytes_written, err);
409         if (phdr->caplen % 4) {
410                 WRITE_DATA(fp, &padding, 4 - phdr->caplen % 4, *bytes_written, err);
411         }
412         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
413         return TRUE;
414 }
415
416 gboolean
417 libpcap_write_interface_statistics_block(FILE *fp,
418                                          guint32 interface_id,
419                                          pcap_t *pd,
420                                          long *bytes_written,
421                                          int *err)
422 {
423         struct isb isb;
424 #ifdef _WIN32
425         FILETIME now;
426 #else
427         struct timeval now;
428 #endif
429         struct option option;
430         struct pcap_stat stats;
431         guint32 block_total_length;
432         guint64 timestamp;
433         guint64 counter;
434         gboolean stats_retrieved;
435
436 #ifdef _WIN32
437         /*
438          * Current time, represented as 100-nanosecond intervals since
439          * January 1, 1601, 00:00:00 UTC.
440          *
441          * I think DWORD might be signed, so cast both parts of "now"
442          * to guint32 so that the sign bit doesn't get treated specially.
443          */
444         GetSystemTimeAsFileTime(&now);
445         timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) +
446                     (guint32)now.dwLowDateTime;
447
448         /*
449          * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond,
450          * intervals.
451          */
452         timestamp /= 10;
453
454         /*
455          * Subtract difference, in microseconds, between January 1, 1601
456          * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC.
457          */
458         timestamp -= G_GINT64_CONSTANT(11644473600000000U);
459 #else
460         /*
461          * Current time, represented as seconds and microseconds since
462          * January 1, 1970, 00:00:00 UTC.
463          */
464         gettimeofday(&now, NULL);
465
466         /*
467          * Convert to delta in microseconds.
468          */
469         timestamp = (guint64)(now.tv_sec) * 1000000 +
470                     (guint64)(now.tv_usec);
471 #endif
472         if (pcap_stats(pd, &stats) < 0) {
473                 stats_retrieved = FALSE;
474                 g_warning("pcap_stats() failed.");
475         } else {
476                 stats_retrieved = TRUE;
477         }
478         block_total_length = sizeof(struct isb) +
479                              sizeof(guint32);
480         if (stats_retrieved) {
481                 block_total_length += 3 * sizeof(struct option) + 2 * sizeof(guint64);
482         }
483         isb.block_type = INTERFACE_STATISTICS_BLOCK_TYPE;
484         isb.block_total_length = block_total_length;
485         isb.interface_id = interface_id;
486         isb.timestamp_high = (guint32)((timestamp>>32) & 0xffffffff);
487         isb.timestamp_low = (guint32)(timestamp & 0xffffffff);
488         WRITE_DATA(fp, &isb, sizeof(struct isb), *bytes_written, err);
489         if (stats_retrieved) {
490                 /* */
491                 option.type = ISB_IFRECV;
492                 option.value_length = sizeof(guint64);
493                 counter = stats.ps_recv;
494                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
495                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
496                 /* */
497                 option.type = ISB_IFDROP;
498                 option.value_length = sizeof(guint64);
499                 counter = stats.ps_drop;
500                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
501                 WRITE_DATA(fp, &counter, sizeof(guint64), *bytes_written, err);
502                 /* last option */
503                 option.type = OPT_ENDOFOPT;
504                 option.value_length = 0;
505                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
506         }
507         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
508
509         return TRUE;
510 }
511
512 gboolean
513 libpcap_dump_flush(FILE *pd, int *err)
514 {
515         if (fflush(pd) == EOF) {
516                 if (err != NULL)
517                         *err = errno;
518                 return FALSE;
519         }
520         return TRUE;
521 }
522
523 gboolean
524 libpcap_dump_close(FILE *pd, int *err)
525 {
526         if (fclose(pd) == EOF) {
527                 if (err != NULL)
528                         *err = errno;
529                 return FALSE;
530         }
531         return TRUE;
532 }
533
534 #endif /* HAVE_LIBPCAP */