63475d73b065812783aa2dcaaeb50b8ff41fb6a4
[obnox/wireshark/wip.git] / wiretap / wtap.c
1 /* wtap.c
2  *
3  * $Id: wtap.c,v 1.53 2001/07/05 00:34:42 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@xiexie.org>
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 const static 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
129 /* Name that should be somewhat descriptive. */
130 const char
131 *wtap_encap_string(int encap)
132 {
133         if (encap < 0 || encap >= WTAP_NUM_ENCAP_TYPES)
134                 return NULL;
135         else
136                 return encap_table[encap].name;
137 }
138
139 /* Name to use in, say, a command-line flag specifying the type. */
140 const char
141 *wtap_encap_short_string(int encap)
142 {
143         if (encap < 0 || encap >= WTAP_NUM_ENCAP_TYPES)
144                 return NULL;
145         else
146                 return encap_table[encap].short_name;
147 }
148
149 /* Translate a short name to a capture file type. */
150 int
151 wtap_short_string_to_encap(const char *short_name)
152 {
153         int encap;
154
155         for (encap = 0; encap < WTAP_NUM_ENCAP_TYPES; encap++) {
156                 if (encap_table[encap].short_name != NULL &&
157                     strcmp(short_name, encap_table[encap].short_name) == 0)
158                         return encap;
159         }
160         return -1;      /* no such encapsulation type */
161 }
162
163 static const char *wtap_errlist[] = {
164         "The file isn't a plain file",
165         "The file isn't a capture file in a known format",
166         "File contains record data we don't support",
167         NULL,
168         "Files can't be saved in that format",
169         "Files from that network type can't be saved in that format",
170         "That format doesn't support per-packet encapsulations",
171         NULL,
172         NULL,
173         "Less data was read than was expected",
174         "File contains a record that's not valid",
175         "Less data was written than was requested",
176         "Uncompression error: data oddly truncated",
177         "Uncompression error: data would overflow buffer",
178         "Uncompression error: bad LZ77 offset",
179 };
180 #define WTAP_ERRLIST_SIZE       (sizeof wtap_errlist / sizeof wtap_errlist[0])
181
182 const char
183 *wtap_strerror(int err)
184 {
185         static char errbuf[128];
186         int wtap_errlist_index;
187
188         if (err < 0) {
189 #ifdef HAVE_LIBZ
190                 if (err >= WTAP_ERR_ZLIB_MIN && err <= WTAP_ERR_ZLIB_MAX) {
191                         /* Assume it's a zlib error. */
192                         sprintf(errbuf, "Uncompression error: %s",
193                             zError(err - WTAP_ERR_ZLIB));
194                         return errbuf;
195                 }
196 #endif
197                 wtap_errlist_index = -1 - err;
198                 if (wtap_errlist_index >= WTAP_ERRLIST_SIZE) {
199                         sprintf(errbuf, "Error %d", err);
200                         return errbuf;
201                 }
202                 if (wtap_errlist[wtap_errlist_index] == NULL)
203                         return "Unknown reason";
204                 return wtap_errlist[wtap_errlist_index];
205         } else
206                 return strerror(err);
207 }
208
209 /* Close only the sequential side, freeing up memory it uses.
210
211    Note that we do *not* want to call the subtype's close function,
212    as it would free any per-subtype data, and that data may be
213    needed by the random-access side.
214    
215    Instead, if the subtype has a "sequential close" function, we call it,
216    to free up stuff used only by the sequential side. */
217 void
218 wtap_sequential_close(wtap *wth)
219 {
220         if (wth->subtype_sequential_close != NULL)
221                 (*wth->subtype_sequential_close)(wth);
222
223         if (wth->fh != NULL) {
224                 file_close(wth->fh);
225                 wth->fh = NULL;
226         }
227
228         if (wth->frame_buffer) {
229                 buffer_free(wth->frame_buffer);
230                 g_free(wth->frame_buffer);
231                 wth->frame_buffer = NULL;
232         }
233 }
234
235 void
236 wtap_close(wtap *wth)
237 {
238         wtap_sequential_close(wth);
239
240         if (wth->subtype_close != NULL)
241                 (*wth->subtype_close)(wth);
242
243         if (wth->random_fh != NULL)
244                 file_close(wth->random_fh);
245
246         g_free(wth);
247 }
248
249 gboolean
250 wtap_read(wtap *wth, int *err, int *data_offset)
251 {
252         return wth->subtype_read(wth, err, data_offset);
253 }
254
255 struct wtap_pkthdr*
256 wtap_phdr(wtap *wth)
257 {
258         return &wth->phdr;
259 }
260
261 union wtap_pseudo_header*
262 wtap_pseudoheader(wtap *wth)
263 {
264         return &wth->pseudo_header;
265 }
266
267 guint8*
268 wtap_buf_ptr(wtap *wth)
269 {
270         return buffer_start_ptr(wth->frame_buffer);
271 }
272
273 gboolean
274 wtap_loop(wtap *wth, int count, wtap_handler callback, u_char* user, int *err)
275 {
276         int             data_offset, loop = 0;
277
278         /* Start by clearing error flag */
279         *err = 0;
280
281         while ( (wtap_read(wth, err, &data_offset)) ) {
282                 callback(user, &wth->phdr, data_offset,
283                     &wth->pseudo_header, buffer_start_ptr(wth->frame_buffer));
284                 if (count > 0 && ++loop >= count)
285                         break;
286         }
287
288         if (*err == 0)
289                 return TRUE;    /* success */
290         else
291                 return FALSE;   /* failure */
292 }
293
294 int
295 wtap_seek_read(wtap *wth, int seek_off,
296         union wtap_pseudo_header *pseudo_header, guint8 *pd, int len)
297 {
298         return wth->subtype_seek_read(wth, seek_off, pseudo_header, pd, len);
299 }