Olivier Abad's fix to the problem where some capture files appeared to
[obnox/wireshark/wip.git] / wiretap / radcom.c
1 /* radcom.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
5  * 
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <time.h>
28 #include "wtap.h"
29 #include "buffer.h"
30 #include "radcom.h"
31
32 struct frame_date {
33         guint16 year;
34         guint8  month;
35         guint8  day;
36         guint32 sec;            /* seconds since midnight */
37         guint32 usec;
38 };
39
40 static char radcom_magic[8] = {
41         0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
42 };
43
44 static int radcom_read(wtap *wth, int *err);
45
46 int radcom_open(wtap *wth, int *err)
47 {
48         int bytes_read;
49         char magic[8];
50         struct frame_date start_date;
51         guint32 sec;
52         struct tm tm;
53         char byte;
54         char encap_magic[7] = {0x54, 0x43, 0x50, 0x00, 0x42, 0x43, 0x09};
55         char search_encap[7];
56
57         /* Read in the string that should be at the start of a RADCOM file */
58         fseek(wth->fh, 0, SEEK_SET);
59         errno = WTAP_ERR_CANT_READ;
60         bytes_read = fread(magic, 1, 8, wth->fh);
61         if (bytes_read != 8) {
62                 if (ferror(wth->fh)) {
63                         *err = errno;
64                         return -1;
65                 }
66                 return 0;
67         }
68
69         if (memcmp(magic, radcom_magic, 8)) {
70                 return 0;
71         }
72
73         fseek(wth->fh, 0x8B, SEEK_SET);
74         wth->data_offset = 0x8B;
75         errno = WTAP_ERR_CANT_READ;
76         bytes_read = fread(&byte, 1, 1, wth->fh);
77         if (bytes_read != 1) {
78                 if (ferror(wth->fh)) {
79                         *err = errno;
80                         return -1;
81                 }
82                 return 0;
83         }
84         wth->data_offset += 1;
85         while (byte) {
86                 errno = WTAP_ERR_CANT_READ;
87                 bytes_read = fread(&byte, 1, 1, wth->fh);
88                 if (bytes_read != 1) {
89                         if (ferror(wth->fh)) {
90                                 *err = errno;
91                                 return -1;
92                         }
93                         return 0;
94                 }
95                 wth->data_offset += 1;
96         }
97         fseek(wth->fh, 1, SEEK_CUR);
98         wth->data_offset += 1;
99
100         /* Get capture start time */
101         errno = WTAP_ERR_CANT_READ;
102         bytes_read = fread(&start_date, 1, sizeof(struct frame_date), wth->fh);
103         if (bytes_read != sizeof(struct frame_date)) {
104                 if (ferror(wth->fh)) {
105                         *err = errno;
106                         return -1;
107                 }
108                 return 0;
109         }
110         wth->data_offset += sizeof(struct frame_date);
111
112         /* This is a radcom file */
113         wth->file_type = WTAP_FILE_RADCOM;
114         wth->capture.radcom = g_malloc(sizeof(radcom_t));
115         wth->subtype_read = radcom_read;
116         wth->snapshot_length = 16384;   /* not available in header, only in frame */
117
118         tm.tm_year = pletohs(&start_date.year)-1900;
119         tm.tm_mon = start_date.month-1;
120         tm.tm_mday = start_date.day;
121         sec = pletohl(&start_date.sec);
122         tm.tm_hour = sec/3600;
123         tm.tm_min = (sec%3600)/60;
124         tm.tm_sec = sec%60;
125         tm.tm_isdst = -1;
126         wth->capture.radcom->start = mktime(&tm);
127
128         fseek(wth->fh, sizeof(struct frame_date), SEEK_CUR);
129         wth->data_offset += sizeof(struct frame_date);
130
131         errno = WTAP_ERR_CANT_READ;
132         bytes_read = fread(search_encap, 1, 7, wth->fh);
133         if (bytes_read != 7) {
134                 goto read_error;
135         }
136         wth->data_offset += 7;
137         while (memcmp(encap_magic, search_encap, 7)) {
138                 fseek(wth->fh, -6, SEEK_CUR);
139                 wth->data_offset -= 6;
140                 errno = WTAP_ERR_CANT_READ;
141                 bytes_read = fread(search_encap, 1, 7, wth->fh);
142                 if (bytes_read != 7) {
143                         goto read_error;
144                 }
145                 wth->data_offset += 7;
146         }
147         fseek(wth->fh, 12, SEEK_CUR);
148         wth->data_offset += 12;
149         errno = WTAP_ERR_CANT_READ;
150         bytes_read = fread(search_encap, 1, 4, wth->fh);
151         if (bytes_read != 4) {
152                 goto read_error;
153         }
154         wth->data_offset += 4;
155         if (!memcmp(search_encap, "LAPB", 4))
156                 wth->file_encap = WTAP_ENCAP_LAPB;
157         else if (!memcmp(search_encap, "Ethe", 4))
158                 wth->file_encap = WTAP_ENCAP_ETHERNET;
159         else {
160                 g_message("pcap: network type \"%.4s\" unknown", search_encap);
161                 *err = WTAP_ERR_UNSUPPORTED;
162                 return -1;
163         }
164
165         /*bytes_read = fread(&next_date, 1, sizeof(struct frame_date), wth->fh);
166         errno = WTAP_ERR_CANT_READ;
167         if (bytes_read != sizeof(struct frame_date)) {
168                 goto read_error;
169         }
170
171         while (memcmp(&start_date, &next_date, 4)) {
172                 fseek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR);
173                 errno = WTAP_ERR_CANT_READ;
174                 bytes_read = fread(&next_date, 1, sizeof(struct frame_date),
175                                    wth->fh);
176                 if (bytes_read != sizeof(struct frame_date)) {
177                         goto read_error;
178                 }
179         }*/
180
181         if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
182                 fseek(wth->fh, 294, SEEK_CUR);
183                 wth->data_offset += 294;
184         } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
185                 fseek(wth->fh, 297, SEEK_CUR);
186                 wth->data_offset += 297;
187         }
188
189         return 1;
190
191 read_error:
192         if (ferror(wth->fh)) {
193                 *err = errno;
194                 free(wth->capture.radcom);
195                 return -1;
196         }
197         free(wth->capture.radcom);
198         return 0;
199 }
200
201 /* Read the next packet */
202 static int radcom_read(wtap *wth, int *err)
203 {
204         int     bytes_read;
205         guint16 length;
206         struct frame_date date;
207         guint32 sec;
208         int     data_offset;
209         struct tm tm;
210         char dce;
211
212         fseek(wth->fh, 4, SEEK_CUR);
213         wth->data_offset += 4;
214
215         /*
216          * Read the frame size
217          */
218         errno = WTAP_ERR_CANT_READ;
219         bytes_read = fread(&length, 1, 2, wth->fh);
220         if (bytes_read != 2) {
221                 if (ferror(wth->fh)) {
222                         *err = errno;
223                         return -1;
224                 }
225                 if (bytes_read != 0) {
226                         *err = WTAP_ERR_SHORT_READ;
227                         return -1;
228                 }
229                 return 0;
230         }
231         wth->data_offset += 2;
232         length = pletohs(&length);
233         if (length == 0) return 0;
234
235         if (wth->file_encap == WTAP_ENCAP_LAPB)
236                 length -= 2; /* FCS */
237
238         wth->phdr.len = length;
239         wth->phdr.caplen = length;
240
241         fseek(wth->fh, 5, SEEK_CUR);
242         wth->data_offset += 5;
243         errno = WTAP_ERR_CANT_READ;
244         bytes_read = fread(&date, 1, sizeof(struct frame_date), wth->fh);
245         if (bytes_read != sizeof(struct frame_date)) {
246                 if (ferror(wth->fh))
247                         *err = errno;
248                 else
249                         *err = WTAP_ERR_SHORT_READ;
250                 return -1;
251         }
252         wth->data_offset += sizeof(struct frame_date);
253
254         tm.tm_year = pletohs(&date.year)-1900;
255         tm.tm_mon = date.month-1;
256         tm.tm_mday = date.day;
257         sec = pletohl(&date.sec);
258         tm.tm_hour = sec/3600;
259         tm.tm_min = (sec%3600)/60;
260         tm.tm_sec = sec%60;
261         tm.tm_isdst = -1;
262         wth->phdr.ts.tv_sec = mktime(&tm);
263         wth->phdr.ts.tv_usec = pletohl(&date.usec);
264
265         fseek(wth->fh, 6, SEEK_CUR);
266         wth->data_offset += 6;
267         errno = WTAP_ERR_CANT_READ;
268         bytes_read = fread(&dce, 1, 1, wth->fh);
269         if (bytes_read != 1) {
270                 if (ferror(wth->fh))
271                         *err = errno;
272                 else
273                         *err = WTAP_ERR_SHORT_READ;
274                 return -1;
275         }
276         wth->data_offset += 1;
277         wth->phdr.pseudo_header.x25.flags = (dce & 0x1) ? 0x00 : 0x80;
278
279         fseek(wth->fh, 9, SEEK_CUR);
280         wth->data_offset += 9;
281
282         /*
283          * Read the packet data.
284          */
285         buffer_assure_space(wth->frame_buffer, length);
286         data_offset = wth->data_offset;
287         errno = WTAP_ERR_CANT_READ;
288         bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
289                         length, wth->fh);
290
291         if (bytes_read != length) {
292                 if (ferror(wth->fh))
293                         *err = errno;
294                 else
295                         *err = WTAP_ERR_SHORT_READ;
296                 return -1;
297         }
298         wth->data_offset += length;
299
300         wth->phdr.pkt_encap = wth->file_encap;
301
302         if (wth->file_encap == WTAP_ENCAP_LAPB) {
303                 fseek(wth->fh, 2, SEEK_CUR); /* FCS */
304                 wth->data_offset += 2;
305         }
306
307         return data_offset;
308 }