b9ba2e1558733462544f35406132f0f7148df30f
[obnox/wireshark/wip.git] / wiretap / wtap.c
1 /* wtap.c
2  *
3  * $Id: wtap.c,v 1.61 2002/02/07 20:41:28 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  * 
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  */
23 #include <string.h>
24 #include <errno.h>
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include "wtap-int.h"
30 #include "file_wrappers.h"
31 #include "buffer.h"
32
33 int
34 wtap_fd(wtap *wth)
35 {
36         return wth->fd;
37 }
38
39 int
40 wtap_file_type(wtap *wth)
41 {
42         return wth->file_type;
43 }
44
45 int
46 wtap_snapshot_length(wtap *wth)
47 {
48         return wth->snapshot_length;
49 }
50
51 int
52 wtap_file_encap(wtap *wth)
53 {
54         return wth->file_encap;
55 }
56
57 /* Table of the encapsulation types we know about. */
58 static const struct encap_type_info {
59         const char *name;
60         const char *short_name;
61 } encap_table[WTAP_NUM_ENCAP_TYPES] = {
62         /* WTAP_ENCAP_UNKNOWN */
63         { "Unknown", NULL },
64
65         /* WTAP_ENCAP_ETHERNET */
66         { "Ethernet", "ether" },
67
68         /* WTAP_ENCAP_TR */
69         { "Token Ring", "tr" },
70
71         /* WTAP_ENCAP_SLIP */
72         { "SLIP", "slip" },
73
74         /* WTAP_ENCAP_PPP */
75         { "PPP", "ppp" },
76
77         /* WTAP_ENCAP_FDDI */
78         { "FDDI", "fddi" },
79
80         /* WTAP_ENCAP_FDDI_BITSWAPPED */
81         { "FDDI with bit-swapped MAC addresses", "fddi-swapped" },
82
83         /* WTAP_ENCAP_RAW_IP */
84         { "Raw IP", "rawip" },
85
86         /* WTAP_ENCAP_ARCNET */
87         { "ARCNET", "arcnet" },
88
89         /* WTAP_ENCAP_ATM_RFC1483 */
90         { "RFC 1483 ATM", "atm-rfc1483" },
91
92         /* WTAP_ENCAP_LINUX_ATM_CLIP */
93         { "Linux ATM CLIP", "linux-atm-clip" },
94
95         /* WTAP_ENCAP_LAPB */
96         { "LAPB", "lapb" },
97
98         /* WTAP_ENCAP_ATM_SNIFFER */
99         { "ATM Sniffer", "atm-sniffer" },
100
101         /* WTAP_ENCAP_NULL */
102         { "NULL", "null" },
103
104         /* WTAP_ENCAP_ASCEND */
105         { "Lucent/Ascend access equipment", "ascend" },
106
107         /* WTAP_ENCAP_LAPD */
108         { "LAPD", "lapd" },
109
110         /* WTAP_ENCAP_V120 */
111         { "V.120", "v120" },
112
113         /* WTAP_ENCAP_PPP_WITH_PHDR */
114         { "PPP with Directional Info", "ppp-with-direction" },
115
116         /* WTAP_ENCAP_IEEE_802_11 */
117         { "IEEE 802.11 Wireless LAN", "ieee-802-11" },
118
119         /* WTAP_ENCAP_SLL */
120         { "Linux cooked-mode capture", "linux-sll" },
121
122         /* WTAP_ENCAP_FRELAY */
123         { "Frame Relay", "frelay" },
124
125         /* WTAP_ENCAP_CHDLC */
126         { "Cisco HDLC", "chdlc" },
127
128         /* WTAP_ENCAP_CISCO_IOS */
129         { "Cisco IOS internal", "ios" },
130
131         /* WTAP_ENCAP_LOCALTALK */
132         { "Localtalk", "ltalk" },
133
134         /* WTAP_ENCAP_PRISM_HEADER */
135         { "IEEE 802.11 plus Prism II monitor mode header", "prism" },
136
137         /* WTAP_ENCAP_PFLOG  */
138         { "OpenBSD PF Firewall logs", "pflog" },
139
140         /* WTAP_ENCAP_AIROPEEK  */
141         { "IEEE 802.11 plus AiroPeek header", "airopeek" },
142
143         /* WTAP_ENCAP_HHDLC */
144         { "HiPath HDLC", "hhdlc" },
145 };
146
147 /* Name that should be somewhat descriptive. */
148 const char
149 *wtap_encap_string(int encap)
150 {
151         if (encap < 0 || encap >= WTAP_NUM_ENCAP_TYPES)
152                 return NULL;
153         else
154                 return encap_table[encap].name;
155 }
156
157 /* Name to use in, say, a command-line flag specifying the type. */
158 const char
159 *wtap_encap_short_string(int encap)
160 {
161         if (encap < 0 || encap >= WTAP_NUM_ENCAP_TYPES)
162                 return NULL;
163         else
164                 return encap_table[encap].short_name;
165 }
166
167 /* Translate a short name to a capture file type. */
168 int
169 wtap_short_string_to_encap(const char *short_name)
170 {
171         int encap;
172
173         for (encap = 0; encap < WTAP_NUM_ENCAP_TYPES; encap++) {
174                 if (encap_table[encap].short_name != NULL &&
175                     strcmp(short_name, encap_table[encap].short_name) == 0)
176                         return encap;
177         }
178         return -1;      /* no such encapsulation type */
179 }
180
181 static const char *wtap_errlist[] = {
182         "The file isn't a plain file",
183         "The file isn't a capture file in a known format",
184         "File contains record data we don't support",
185         NULL,
186         "Files can't be saved in that format",
187         "Files from that network type can't be saved in that format",
188         "That format doesn't support per-packet encapsulations",
189         NULL,
190         NULL,
191         "Less data was read than was expected",
192         "File contains a record that's not valid",
193         "Less data was written than was requested",
194         "Uncompression error: data oddly truncated",
195         "Uncompression error: data would overflow buffer",
196         "Uncompression error: bad LZ77 offset",
197 };
198 #define WTAP_ERRLIST_SIZE       (sizeof wtap_errlist / sizeof wtap_errlist[0])
199
200 const char
201 *wtap_strerror(int err)
202 {
203         static char errbuf[128];
204         unsigned int wtap_errlist_index;
205
206         if (err < 0) {
207 #ifdef HAVE_LIBZ
208                 if (err >= WTAP_ERR_ZLIB_MIN && err <= WTAP_ERR_ZLIB_MAX) {
209                         /* Assume it's a zlib error. */
210                         sprintf(errbuf, "Uncompression error: %s",
211                             zError(err - WTAP_ERR_ZLIB));
212                         return errbuf;
213                 }
214 #endif
215                 wtap_errlist_index = -1 - err;
216                 if (wtap_errlist_index >= WTAP_ERRLIST_SIZE) {
217                         sprintf(errbuf, "Error %d", err);
218                         return errbuf;
219                 }
220                 if (wtap_errlist[wtap_errlist_index] == NULL)
221                         return "Unknown reason";
222                 return wtap_errlist[wtap_errlist_index];
223         } else
224                 return strerror(err);
225 }
226
227 /* Close only the sequential side, freeing up memory it uses.
228
229    Note that we do *not* want to call the subtype's close function,
230    as it would free any per-subtype data, and that data may be
231    needed by the random-access side.
232    
233    Instead, if the subtype has a "sequential close" function, we call it,
234    to free up stuff used only by the sequential side. */
235 void
236 wtap_sequential_close(wtap *wth)
237 {
238         if (wth->subtype_sequential_close != NULL)
239                 (*wth->subtype_sequential_close)(wth);
240
241         if (wth->fh != NULL) {
242                 file_close(wth->fh);
243                 wth->fh = NULL;
244         }
245
246         if (wth->frame_buffer) {
247                 buffer_free(wth->frame_buffer);
248                 g_free(wth->frame_buffer);
249                 wth->frame_buffer = NULL;
250         }
251 }
252
253 void
254 wtap_close(wtap *wth)
255 {
256         wtap_sequential_close(wth);
257
258         if (wth->subtype_close != NULL)
259                 (*wth->subtype_close)(wth);
260
261         if (wth->random_fh != NULL)
262                 file_close(wth->random_fh);
263
264         g_free(wth);
265 }
266
267 gboolean
268 wtap_read(wtap *wth, int *err, long *data_offset)
269 {
270         return wth->subtype_read(wth, err, data_offset);
271 }
272
273 struct wtap_pkthdr*
274 wtap_phdr(wtap *wth)
275 {
276         return &wth->phdr;
277 }
278
279 union wtap_pseudo_header*
280 wtap_pseudoheader(wtap *wth)
281 {
282         return &wth->pseudo_header;
283 }
284
285 guint8*
286 wtap_buf_ptr(wtap *wth)
287 {
288         return buffer_start_ptr(wth->frame_buffer);
289 }
290
291 gboolean
292 wtap_loop(wtap *wth, int count, wtap_handler callback, u_char* user, int *err)
293 {
294         long            data_offset;
295         int             loop = 0;
296
297         /* Start by clearing error flag */
298         *err = 0;
299
300         while ( (wtap_read(wth, err, &data_offset)) ) {
301                 callback(user, &wth->phdr, data_offset,
302                     &wth->pseudo_header, buffer_start_ptr(wth->frame_buffer));
303                 if (count > 0 && ++loop >= count)
304                         break;
305         }
306
307         if (*err == 0)
308                 return TRUE;    /* success */
309         else
310                 return FALSE;   /* failure */
311 }
312
313 int
314 wtap_seek_read(wtap *wth, long seek_off,
315         union wtap_pseudo_header *pseudo_header, guint8 *pd, int len)
316 {
317         return wth->subtype_seek_read(wth, seek_off, pseudo_header, pd, len);
318 }