Added support for Lucent/Ascend packet traces. The MAX and Pipeline router
[obnox/wireshark/wip.git] / wiretap / file.c
1 /* file.c
2  *
3  * $Id: file.c,v 1.20 1999/09/11 04:50:44 gerald Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include "wtap.h"
32 #include "buffer.h"
33 #include "lanalyzer.h"
34 #include "ngsniffer.h"
35 #include "radcom.h"
36 #include "ascend.h"
37 #include "libpcap.h"
38 #include "snoop.h"
39 #include "iptrace.h"
40 #include "netmon.h"
41 #include "netxray.h"
42
43 /* The open_file_* routines should return:
44  *
45  *      -1 on an I/O error;
46  *
47  *      1 if the file they're reading is one of the types it handles;
48  *
49  *      0 if the file they're reading isn't the type they're checking for.
50  *
51  * If the routine handles this type of file, it should set the "file_type"
52  * field in the "struct wtap" to the type of the file.
53  *
54  * XXX - I need to drag my damn ANSI C spec in to figure out how to
55  * declare a "const" array of pointers to functions; putting "const"
56  * right after "static" isn't the right answer, at least according
57  * to GCC, which whines if I do that.
58  */
59
60 static int (*open_routines[])(wtap *, int *) = {
61         libpcap_open,
62         lanalyzer_open,
63         ngsniffer_open,
64         snoop_open,
65         iptrace_open,
66         netmon_open,
67         netxray_open,
68         radcom_open,
69         ascend_open
70 };
71
72 int wtap_def_seek_read (FILE *fh, int seek_off, guint8 *pd, int len)
73 {
74         fseek(fh, seek_off, SEEK_SET);
75         return fread(pd, sizeof(guint8), len, fh);
76 }
77
78 #define N_FILE_TYPES    (sizeof open_routines / sizeof open_routines[0])
79
80 /* Opens a file and prepares a wtap struct */
81 wtap* wtap_open_offline(const char *filename, int *err)
82 {
83         struct stat statb;
84         wtap    *wth;
85         int     i;
86
87         /* First, make sure the file is valid */
88         if (stat(filename, &statb) < 0) {
89                 *err = errno;
90                 return NULL;
91         }
92 #ifndef WIN32
93         if (! S_ISREG(statb.st_mode) && ! S_ISFIFO(statb.st_mode)) {
94                 *err = WTAP_ERR_NOT_REGULAR_FILE;
95                 return NULL;
96         }
97 #endif
98
99         errno = ENOMEM;
100         wth = (wtap*)malloc(sizeof(wtap));
101         if (wth == NULL) {
102                 *err = errno;
103                 return NULL;
104         }
105
106         /* Open the file */
107         errno = WTAP_ERR_CANT_OPEN;
108         if (!(wth->fh = fopen(filename, "rb"))) {
109                 *err = errno;
110                 free(wth);
111                 return NULL;
112         }
113
114         /* initialization */
115         wth->file_encap = WTAP_ENCAP_UNKNOWN;
116         wth->data_offset = 0;
117
118         /* Try all file types */
119         for (i = 0; i < N_FILE_TYPES; i++) {
120                 switch ((*open_routines[i])(wth, err)) {
121
122                 case -1:
123                         /* I/O error - give up */
124                         *err = errno;
125                         fclose(wth->fh);
126                         free(wth);
127                         return NULL;
128
129                 case 0:
130                         /* No I/O error, but not that type of file */
131                         break;
132
133                 case 1:
134                         /* We found the file type */
135                         goto success;
136                 }
137         }
138
139         /* Well, it's not one of the types of file we know about. */
140         fclose(wth->fh);
141         free(wth);
142         *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
143         return NULL;
144
145 success:
146         wth->frame_buffer = g_malloc(sizeof(struct Buffer));
147         buffer_init(wth->frame_buffer, 1500);
148         return wth;
149 }
150
151
152 static wtap_dumper* wtap_dump_open_common(FILE *fh, int filetype,
153     int encap, int snaplen, int *err);
154
155 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
156                                 int snaplen, int *err)
157 {
158         FILE *fh;
159
160         /* In case "fopen()" fails but doesn't set "errno", set "errno"
161            to a generic "the open failed" error. */
162         errno = WTAP_ERR_CANT_OPEN;
163         fh = fopen(filename, "w");
164         if (fh == NULL) {
165                 *err = errno;
166                 return NULL;    /* can't create file */
167         }
168         return wtap_dump_open_common(fh, filetype, encap, snaplen, err);
169 }
170
171 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
172                                 int *err)
173 {
174         FILE *fh;
175
176         /* In case "fopen()" fails but doesn't set "errno", set "errno"
177            to a generic "the open failed" error. */
178         errno = WTAP_ERR_CANT_OPEN;
179         fh = fdopen(fd, "w");
180         if (fh == NULL) {
181                 *err = errno;
182                 return NULL;    /* can't create standard I/O stream */
183         }
184         return wtap_dump_open_common(fh, filetype, encap, snaplen, err);
185 }
186
187 static wtap_dumper* wtap_dump_open_common(FILE *fh, int filetype, int encap,
188                                         int snaplen, int *err)
189 {
190         wtap_dumper *wdh;
191
192         wdh = malloc(sizeof (wtap_dumper));
193         if (wdh == NULL) {
194                 *err = errno;
195                 /* NOTE: this means the FD handed to "wtap_dump_fdopen()"
196                    will be closed if the malloc fails. */
197                 fclose(fh);
198                 return NULL;
199         }
200         wdh->fh = fh;
201         wdh->file_type = filetype;
202         wdh->snaplen = snaplen;
203         wdh->encap = encap;
204
205         switch (filetype) {
206
207         case WTAP_FILE_PCAP:
208                 if (!libpcap_dump_open(wdh, err))
209                         goto fail;
210                 break;
211
212         default:
213                 /* We currently only support dumping "libpcap" files */
214                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
215                 goto fail;
216         }
217         return wdh;
218
219 fail:
220         free(wdh);
221         fclose(fh);
222         return NULL;    /* XXX - provide a reason why we failed */
223 }
224
225 FILE* wtap_dump_file(wtap_dumper *wdh)
226 {
227         return wdh->fh;
228 }
229
230 int wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
231     const u_char *pd, int *err)
232 {
233         return (wdh->subtype_write)(wdh, phdr, pd, err);
234 }
235
236 int wtap_dump_close(wtap_dumper *wdh, int *err)
237 {
238         int ret = 1;
239
240         if (!(wdh->subtype_close)(wdh, err))
241                 ret = 0;
242         errno = WTAP_ERR_CANT_CLOSE;
243         if (fclose(wdh->fh) == EOF) {
244                 if (ret) {
245                         /* The per-format close function succeeded,
246                            but the fclose didn't.  Save the reason
247                            why, if our caller asked for it. */
248                         if (err != NULL)
249                                 *err = errno;
250                 }
251                 ret = 0;
252         }
253         free(wdh);
254         return ret;
255 }
256