Make ringbuffer.[ch] file format agnostic.
[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
53 #include <pcap.h>
54
55 #include <glib.h>
56
57 #include "pcapio.h"
58
59 /* Magic numbers in "libpcap" files.
60
61    "libpcap" file records are written in the byte order of the host that
62    writes them, and the reader is expected to fix this up.
63
64    PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
65    is a byte-swapped version of that.
66
67    PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
68    which uses the same common file format as PCAP_MAGIC, but the 
69    timestamps are saved in nanosecond resolution instead of microseconds.
70    PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
71 #define PCAP_MAGIC                      0xa1b2c3d4
72 #define PCAP_SWAPPED_MAGIC              0xd4c3b2a1
73 #define PCAP_NSEC_MAGIC                 0xa1b23c4d
74 #define PCAP_SWAPPED_NSEC_MAGIC         0x4d3cb2a1
75
76 /* "libpcap" file header. */
77 struct pcap_hdr {
78         guint32 magic;          /* magic number */
79         guint16 version_major;  /* major version number */
80         guint16 version_minor;  /* minor version number */
81         gint32  thiszone;       /* GMT to local correction */
82         guint32 sigfigs;        /* accuracy of timestamps */
83         guint32 snaplen;        /* max length of captured packets, in octets */
84         guint32 network;        /* data link type */
85 };
86
87 /* "libpcap" record header. */
88 struct pcaprec_hdr {
89         guint32 ts_sec;         /* timestamp seconds */
90         guint32 ts_usec;        /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
91         guint32 incl_len;       /* number of octets of packet saved in file */
92         guint32 orig_len;       /* actual length of packet */
93 };
94
95 /* Returns a FILE * to write to on success, NULL on failure */
96 FILE *
97 libpcap_fdopen(int fd, int *err)
98 {
99         FILE *fp;
100
101         fp = fdopen(fd, "wb");
102         if (fp == NULL) {
103                 *err = errno;
104         }
105         return fp;
106 }
107
108 /* Write the file header to a dump file.
109    Returns TRUE on success, FALSE on failure.
110    Sets "*err" to an error code, or 0 for a short write, on failure*/
111 gboolean
112 libpcap_write_file_header(FILE *fp, int linktype, int snaplen, long *bytes_written, int *err)
113 {
114         struct pcap_hdr file_hdr;
115         size_t nwritten;
116
117         file_hdr.magic = PCAP_MAGIC;
118         /* current "libpcap" format is 2.4 */
119         file_hdr.version_major = 2;
120         file_hdr.version_minor = 4;
121         file_hdr.thiszone = 0;  /* XXX - current offset? */
122         file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
123         file_hdr.snaplen = snaplen;
124         file_hdr.network = linktype;
125         nwritten = fwrite(&file_hdr, 1, sizeof(file_hdr), fp);
126         if (nwritten != sizeof(file_hdr)) {
127                 if (nwritten == 0 && ferror(fp))
128                         *err = errno;
129                 else
130                         *err = 0;       /* short write */
131                 return FALSE;
132         }
133         *bytes_written += sizeof(file_hdr);
134
135         return TRUE;
136 }
137
138 /* Write a record for a packet to a dump file.
139    Returns TRUE on success, FALSE on failure. */
140 gboolean
141 libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
142     long *bytes_written, int *err)
143 {
144         struct pcaprec_hdr rec_hdr;
145         size_t nwritten;
146
147         rec_hdr.ts_sec = phdr->ts.tv_sec;
148         rec_hdr.ts_usec = phdr->ts.tv_usec;
149         rec_hdr.incl_len = phdr->caplen;
150         rec_hdr.orig_len = phdr->len;
151         nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
152         if (nwritten != sizeof rec_hdr) {
153                 if (nwritten == 0 && ferror(fp))
154                         *err = errno;
155                 else
156                         *err = 0;       /* short write */
157                 return FALSE;
158         }
159         *bytes_written += sizeof rec_hdr;
160
161         nwritten = fwrite(pd, 1, phdr->caplen, fp);
162         if (nwritten != phdr->caplen) {
163                 if (nwritten == 0 && ferror(fp))
164                         *err = errno;
165                 else
166                         *err = 0;       /* short write */
167                 return FALSE;
168         }
169         *bytes_written += phdr->caplen;
170         return TRUE;
171 }
172
173 gboolean
174 libpcap_dump_flush(FILE *pd, int *err)
175 {
176         if (fflush(pd) == EOF) {
177                 if (err != NULL)
178                         *err = errno;
179                 return FALSE;
180         }
181         return TRUE;
182 }
183
184 gboolean
185 libpcap_dump_close(FILE *pd, int *err)
186 {
187         if (fclose(pd) == EOF) {
188                 if (err != NULL)
189                         *err = errno;
190                 return FALSE;
191         }
192         return TRUE;
193 }
194
195 #endif /* HAVE_LIBPCAP */