Code to handle Frame Relay Sniffer captures, from Jeff Foster.
[obnox/wireshark/wip.git] / wiretap / wtap.c
1 /* wtap.c
2  *
3  * $Id: wtap.c,v 1.51 2001/01/08 22:18:22 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 FILE*
34 wtap_file(wtap *wth)
35 {
36         return wth->fh;
37 }
38
39 int
40 wtap_fd(wtap *wth)
41 {
42         return wth->fd;
43 }
44
45 int
46 wtap_file_type(wtap *wth)
47 {
48         return wth->file_type;
49 }
50
51 int
52 wtap_snapshot_length(wtap *wth)
53 {
54         return wth->snapshot_length;
55 }
56
57 int
58 wtap_file_encap(wtap *wth)
59 {
60         return wth->file_encap;
61 }
62
63 /* Table of the encapsulation types we know about. */
64 const static struct encap_type_info {
65         const char *name;
66         const char *short_name;
67 } encap_table[WTAP_NUM_ENCAP_TYPES] = {
68         /* WTAP_ENCAP_UNKNOWN */
69         { "Unknown", NULL },
70
71         /* WTAP_ENCAP_ETHERNET */
72         { "Ethernet", "ether" },
73
74         /* WTAP_ENCAP_TR */
75         { "Token Ring", "tr" },
76
77         /* WTAP_ENCAP_SLIP */
78         { "SLIP", "slip" },
79
80         /* WTAP_ENCAP_PPP */
81         { "PPP", "ppp" },
82
83         /* WTAP_ENCAP_FDDI */
84         { "FDDI", "fddi" },
85
86         /* WTAP_ENCAP_FDDI_BITSWAPPED */
87         { "FDDI with bit-swapped MAC addresses", "fddi-swapped" },
88
89         /* WTAP_ENCAP_RAW_IP */
90         { "Raw IP", "rawip" },
91
92         /* WTAP_ENCAP_ARCNET */
93         { "ARCNET", "arcnet" },
94
95         /* WTAP_ENCAP_ATM_RFC1483 */
96         { "RFC 1483 ATM", "atm-rfc1483" },
97
98         /* WTAP_ENCAP_LINUX_ATM_CLIP */
99         { "Linux ATM CLIP", "linux-atm-clip" },
100
101         /* WTAP_ENCAP_LAPB */
102         { "LAPB", "lapb" },
103
104         /* WTAP_ENCAP_ATM_SNIFFER */
105         { "ATM Sniffer", "atm-sniffer" },
106
107         /* WTAP_ENCAP_NULL */
108         { "NULL", "null" },
109
110         /* WTAP_ENCAP_ASCEND */
111         { "Lucent/Ascend access equipment", "ascend" },
112
113         /* WTAP_ENCAP_LAPD */
114         { "LAPD", "lapd" },
115
116         /* WTAP_ENCAP_V120 */
117         { "V.120", "v120" },
118
119         /* WTAP_ENCAP_PPP_WITH_PHDR */
120         { "PPP with Directional Info", "ppp-with-direction" },
121
122         /* WTAP_ENCAP_IEEE_802_11 */
123         { "IEEE 802.11 Wireless LAN", "ieee-802-11" },
124
125         /* WTAP_ENCAP_SLL */
126         { "Linux cooked-mode capture", "linux-sll" },
127
128         /* WTAP_ENCAP_FRELAY */
129         { "Frame Relay", "frelay" },
130 };
131
132 /* Name that should be somewhat descriptive. */
133 const char
134 *wtap_encap_string(int encap)
135 {
136         if (encap < 0 || encap >= WTAP_NUM_ENCAP_TYPES)
137                 return NULL;
138         else
139                 return encap_table[encap].name;
140 }
141
142 /* Name to use in, say, a command-line flag specifying the type. */
143 const char
144 *wtap_encap_short_string(int encap)
145 {
146         if (encap < 0 || encap >= WTAP_NUM_ENCAP_TYPES)
147                 return NULL;
148         else
149                 return encap_table[encap].short_name;
150 }
151
152 /* Translate a short name to a capture file type. */
153 int
154 wtap_short_string_to_encap(const char *short_name)
155 {
156         int encap;
157
158         for (encap = 0; encap < WTAP_NUM_ENCAP_TYPES; encap++) {
159                 if (encap_table[encap].short_name != NULL &&
160                     strcmp(short_name, encap_table[encap].short_name) == 0)
161                         return encap;
162         }
163         return -1;      /* no such encapsulation type */
164 }
165
166 static const char *wtap_errlist[] = {
167         "The file isn't a plain file",
168         "The file isn't a capture file in a known format",
169         "File contains record data we don't support",
170         NULL,
171         "Files can't be saved in that format",
172         "Files from that network type can't be saved in that format",
173         "That format doesn't support per-packet encapsulations",
174         NULL,
175         NULL,
176         "Less data was read than was expected",
177         "File contains a record that's not valid",
178         "Less data was written than was requested",
179         "Uncompression error: data oddly truncated",
180         "Uncompression error: data would overflow buffer",
181         "Uncompression error: bad LZ77 offset",
182 };
183 #define WTAP_ERRLIST_SIZE       (sizeof wtap_errlist / sizeof wtap_errlist[0])
184
185 const char
186 *wtap_strerror(int err)
187 {
188         static char errbuf[128];
189         int wtap_errlist_index;
190
191         if (err < 0) {
192 #ifdef HAVE_LIBZ
193                 if (err >= WTAP_ERR_ZLIB_MIN && err <= WTAP_ERR_ZLIB_MAX) {
194                         /* Assume it's a zlib error. */
195                         sprintf(errbuf, "Uncompression error: %s",
196                             zError(err - WTAP_ERR_ZLIB));
197                         return errbuf;
198                 }
199 #endif
200                 wtap_errlist_index = -1 - err;
201                 if (wtap_errlist_index >= WTAP_ERRLIST_SIZE) {
202                         sprintf(errbuf, "Error %d", err);
203                         return errbuf;
204                 }
205                 if (wtap_errlist[wtap_errlist_index] == NULL)
206                         return "Unknown reason";
207                 return wtap_errlist[wtap_errlist_index];
208         } else
209                 return strerror(err);
210 }
211
212 /* Close only the sequential side, freeing up memory it uses.
213
214    Note that we do *not* want to call the subtype's close function,
215    as it would free any per-subtype data, and that data may be
216    needed by the random-access side.
217    
218    Instead, if the subtype has a "sequential close" function, we call it,
219    to free up stuff used only by the sequential side. */
220 void
221 wtap_sequential_close(wtap *wth)
222 {
223         if (wth->subtype_sequential_close != NULL)
224                 (*wth->subtype_sequential_close)(wth);
225
226         if (wth->fh != NULL) {
227                 file_close(wth->fh);
228                 wth->fh = NULL;
229         }
230
231         if (wth->frame_buffer) {
232                 buffer_free(wth->frame_buffer);
233                 g_free(wth->frame_buffer);
234                 wth->frame_buffer = NULL;
235         }
236 }
237
238 void
239 wtap_close(wtap *wth)
240 {
241         wtap_sequential_close(wth);
242
243         if (wth->subtype_close != NULL)
244                 (*wth->subtype_close)(wth);
245
246         if (wth->random_fh != NULL)
247                 file_close(wth->random_fh);
248
249         g_free(wth);
250 }
251
252 gboolean
253 wtap_read(wtap *wth, int *err, int *data_offset)
254 {
255         return wth->subtype_read(wth, err, data_offset);
256 }
257
258 struct wtap_pkthdr*
259 wtap_phdr(wtap *wth)
260 {
261         return &wth->phdr;
262 }
263
264 union wtap_pseudo_header*
265 wtap_pseudoheader(wtap *wth)
266 {
267         return &wth->pseudo_header;
268 }
269
270 guint8*
271 wtap_buf_ptr(wtap *wth)
272 {
273         return buffer_start_ptr(wth->frame_buffer);
274 }
275
276 gboolean
277 wtap_loop(wtap *wth, int count, wtap_handler callback, u_char* user, int *err)
278 {
279         int             data_offset, loop = 0;
280
281         /* Start by clearing error flag */
282         *err = 0;
283
284         while ( (wtap_read(wth, err, &data_offset)) ) {
285                 callback(user, &wth->phdr, data_offset,
286                     &wth->pseudo_header, buffer_start_ptr(wth->frame_buffer));
287                 if (count > 0 && ++loop >= count)
288                         break;
289         }
290
291         if (*err == 0)
292                 return TRUE;    /* success */
293         else
294                 return FALSE;   /* failure */
295 }
296
297 int
298 wtap_seek_read(wtap *wth, int seek_off,
299         union wtap_pseudo_header *pseudo_header, guint8 *pd, int len)
300 {
301         return wth->subtype_seek_read(wth, seek_off, pseudo_header, pd, len);
302 }