constify some args of libpcap_write_enhanced_packet_block()
[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         struct timeval now;
414         struct option option;
415         struct pcap_stat stats;
416         guint32 block_total_length;
417         guint64 timestamp;
418         guint64 counter;
419         gboolean stats_retrieved;
420         
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.");
427         } else {
428                 stats_retrieved = TRUE;
429         }
430         block_total_length = sizeof(struct isb) +
431                              sizeof(guint32);
432         if (stats_retrieved) {
433                 block_total_length += 3 * sizeof(struct option) + 2 * sizeof(guint64);
434         }
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) {
442                 /* */
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);
448                 /* */
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);
454                 /* last option */
455                 option.type = OPT_ENDOFOPT;
456                 option.value_length = 0;
457                 WRITE_DATA(fp, &option, sizeof(struct option), *bytes_written, err);
458         }
459         WRITE_DATA(fp, &block_total_length, sizeof(guint32), *bytes_written, err);
460         
461         return TRUE;
462 }
463
464 gboolean
465 libpcap_dump_flush(FILE *pd, int *err)
466 {
467         if (fflush(pd) == EOF) {
468                 if (err != NULL)
469                         *err = errno;
470                 return FALSE;
471         }
472         return TRUE;
473 }
474
475 gboolean
476 libpcap_dump_close(FILE *pd, int *err)
477 {
478         if (fclose(pd) == EOF) {
479                 if (err != NULL)
480                         *err = errno;
481                 return FALSE;
482         }
483         return TRUE;
484 }
485
486 #endif /* HAVE_LIBPCAP */