kerberos dissect KERBEROS_AD_GSS_API_ETYPE_NEGOTIATION content
[metze/wireshark/wip.git] / wiretap / radcom.c
1 /* radcom.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8
9 #include "config.h"
10
11 #include <errno.h>
12 #include <string.h>
13 #include "wtap-int.h"
14 #include "file_wrappers.h"
15 #include "radcom.h"
16
17 struct frame_date {
18         guint16 year;
19         guint8  month;
20         guint8  day;
21         guint32 sec;            /* seconds since midnight */
22         guint32 usec;
23 };
24
25 struct unaligned_frame_date {
26         char    year[2];
27         char    month;
28         char    day;
29         char    sec[4];         /* seconds since midnight */
30         char    usec[4];
31 };
32
33 /* Found at the beginning of the file. Bytes 2 and 3 (D2:00) seem to be
34  * different in some captures */
35 static const guint8 radcom_magic[8] = {
36         0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
37 };
38
39 static const guint8 encap_magic[4] = {
40         0x00, 0x42, 0x43, 0x09
41 };
42
43 static const guint8 active_time_magic[11] = {
44         'A', 'c', 't', 'i', 'v', 'e', ' ', 'T', 'i', 'm', 'e'
45 };
46
47 /* RADCOM record header - followed by frame data (perhaps including FCS).
48
49    "data_length" appears to be the length of packet data following
50    the record header.  It's 0 in the last record.
51
52    "length" appears to be the amount of captured packet data, and
53    "real_length" might be the actual length of the frame on the wire -
54    in some captures, it's the same as "length", and, in others,
55    it's greater than "length".  In the last record, however, those
56    may have bogus values (or is that some kind of trailer record?).
57
58    "xxx" appears to be all-zero in all but the last record in one
59    capture; if so, perhaps this indicates that the last record is,
60    in fact, a trailer of some sort, and some field in the header
61    is a record type. */
62 struct radcomrec_hdr {
63         char    xxx[4];         /* unknown */
64         char    data_length[2]; /* packet length? */
65         char    xxy[5];         /* unknown */
66         struct unaligned_frame_date date; /* date/time stamp of packet */
67         char    real_length[2]; /* actual length of packet */
68         char    length[2];      /* captured length of packet */
69         char    xxz[2];         /* unknown */
70         char    dce;            /* DCE/DTE flag (and other flags?) */
71         char    xxw[9];         /* unknown */
72 };
73
74 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
75         gint64 *data_offset);
76 static gboolean radcom_seek_read(wtap *wth, gint64 seek_off,
77         wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
78 static gboolean radcom_read_rec(wtap *wth, FILE_T fh, wtap_rec *rec,
79         Buffer *buf, int *err, gchar **err_info);
80
81 wtap_open_return_val radcom_open(wtap *wth, int *err, gchar **err_info)
82 {
83         guint8 r_magic[8], t_magic[11], search_encap[7];
84         struct frame_date start_date;
85 #if 0
86         guint32 sec;
87         struct tm tm;
88 #endif
89
90         /* Read in the string that should be at the start of a RADCOM file */
91         if (!wtap_read_bytes(wth->fh, r_magic, 8, err, err_info)) {
92                 if (*err != WTAP_ERR_SHORT_READ)
93                         return WTAP_OPEN_ERROR;
94                 return WTAP_OPEN_NOT_MINE;
95         }
96
97         /* XXX: bytes 2 and 3 of the "magic" header seem to be different in some
98          * captures. We force them to our standard value so that the test
99          * succeeds (until we find if they have a special meaning, perhaps a
100          * version number ?) */
101         r_magic[1] = 0xD2;
102         r_magic[2] = 0x00;
103         if (memcmp(r_magic, radcom_magic, 8) != 0) {
104                 return WTAP_OPEN_NOT_MINE;
105         }
106
107         /* Look for the "Active Time" string. The "frame_date" structure should
108          * be located 32 bytes before the beginning of this string */
109         if (!wtap_read_bytes(wth->fh, t_magic, 11, err, err_info)) {
110                 if (*err != WTAP_ERR_SHORT_READ)
111                         return WTAP_OPEN_ERROR;
112                 return WTAP_OPEN_NOT_MINE;
113         }
114         while (memcmp(t_magic, active_time_magic, 11) != 0)
115         {
116                 if (file_seek(wth->fh, -10, SEEK_CUR, err) == -1)
117                         return WTAP_OPEN_ERROR;
118                 if (!wtap_read_bytes(wth->fh, t_magic, 11, err, err_info)) {
119                         if (*err != WTAP_ERR_SHORT_READ)
120                                 return WTAP_OPEN_ERROR;
121                         return WTAP_OPEN_NOT_MINE;
122                 }
123         }
124         if (file_seek(wth->fh, -43, SEEK_CUR, err) == -1)
125                 return WTAP_OPEN_ERROR;
126
127         /* Get capture start time */
128         if (!wtap_read_bytes(wth->fh, &start_date, sizeof(struct frame_date),
129             err, err_info)) {
130                 if (*err != WTAP_ERR_SHORT_READ)
131                         return WTAP_OPEN_ERROR;
132                 return WTAP_OPEN_NOT_MINE;
133         }
134
135         /* So what time is this? */
136         if (!wtap_read_bytes(wth->fh, NULL, sizeof(struct frame_date),
137             err, err_info)) {
138                 if (*err != WTAP_ERR_SHORT_READ)
139                         return WTAP_OPEN_ERROR;
140                 return WTAP_OPEN_NOT_MINE;
141         }
142
143         for (;;) {
144                 if (!wtap_read_bytes(wth->fh, search_encap, 4,
145                     err, err_info)) {
146                         if (*err != WTAP_ERR_SHORT_READ)
147                                 return WTAP_OPEN_ERROR;
148                         return WTAP_OPEN_NOT_MINE;
149                 }
150
151                 if (memcmp(encap_magic, search_encap, 4) == 0)
152                         break;
153
154                 /*
155                  * OK, that's not it, go forward 1 byte - reading
156                  * the magic moved us forward 4 bytes, so seeking
157                  * backward 3 bytes moves forward 1 byte - and
158                  * try the 4 bytes at that offset.
159                  */
160                 if (file_seek(wth->fh, -3, SEEK_CUR, err) == -1)
161                         return WTAP_OPEN_ERROR;
162         }
163         if (!wtap_read_bytes(wth->fh, NULL, 12, err, err_info)) {
164                 if (*err != WTAP_ERR_SHORT_READ)
165                         return WTAP_OPEN_ERROR;
166                 return WTAP_OPEN_NOT_MINE;
167         }
168         if (!wtap_read_bytes(wth->fh, search_encap, 4, err, err_info)) {
169                 if (*err != WTAP_ERR_SHORT_READ)
170                         return WTAP_OPEN_ERROR;
171                 return WTAP_OPEN_NOT_MINE;
172         }
173
174         /* This is a radcom file */
175         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_RADCOM;
176         wth->subtype_read = radcom_read;
177         wth->subtype_seek_read = radcom_seek_read;
178         wth->snapshot_length = 0; /* not available in header, only in frame */
179         wth->file_tsprec = WTAP_TSPREC_USEC;
180
181 #if 0
182         tm.tm_year = pletoh16(&start_date.year)-1900;
183         tm.tm_mon = start_date.month-1;
184         tm.tm_mday = start_date.day;
185         sec = pletoh32(&start_date.sec);
186         tm.tm_hour = sec/3600;
187         tm.tm_min = (sec%3600)/60;
188         tm.tm_sec = sec%60;
189         tm.tm_isdst = -1;
190 #endif
191
192         if (memcmp(search_encap, "LAPB", 4) == 0)
193                 wth->file_encap = WTAP_ENCAP_LAPB;
194         else if (memcmp(search_encap, "Ethe", 4) == 0)
195                 wth->file_encap = WTAP_ENCAP_ETHERNET;
196         else if (memcmp(search_encap, "ATM/", 4) == 0)
197                 wth->file_encap = WTAP_ENCAP_ATM_RFC1483;
198         else {
199                 *err = WTAP_ERR_UNSUPPORTED;
200                 *err_info = g_strdup_printf("radcom: network type \"%.4s\" unknown", search_encap);
201                 return WTAP_OPEN_ERROR;
202         }
203
204 #if 0
205         if (!wtap_read_bytes(wth->fh, &next_date, sizeof(struct frame_date),
206             err, err_info))
207                 return WTAP_OPEN_ERROR;
208
209         while (memcmp(&start_date, &next_date, 4)) {
210                 if (file_seek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR, err) == -1)
211                         return WTAP_OPEN_ERROR;
212                 if (!wtap_read_bytes(wth->fh, &next_date, sizeof(struct frame_date),
213                     err, err_info))
214                         return WTAP_OPEN_ERROR;
215         }
216 #endif
217
218         if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
219                 if (!wtap_read_bytes(wth->fh, NULL, 294, err, err_info))
220                         return WTAP_OPEN_ERROR;
221         } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
222                 if (!wtap_read_bytes(wth->fh, NULL, 297, err, err_info))
223                         return WTAP_OPEN_ERROR;
224         } else if (wth->file_encap == WTAP_ENCAP_ATM_RFC1483) {
225                 if (!wtap_read_bytes(wth->fh, NULL, 504, err, err_info))
226                         return WTAP_OPEN_ERROR;
227         }
228
229         return WTAP_OPEN_MINE;
230 }
231
232 /* Read the next packet */
233 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
234                             gint64 *data_offset)
235 {
236         char    fcs[2];
237
238         *data_offset = file_tell(wth->fh);
239
240         /* Read record. */
241         if (!radcom_read_rec(wth, wth->fh, &wth->rec, wth->rec_data,
242             err, err_info)) {
243                 /* Read error or EOF */
244                 return FALSE;
245         }
246
247         if (wth->file_encap == WTAP_ENCAP_LAPB) {
248                 /* Read the FCS.
249                    XXX - should we have some way of indicating the
250                    presence and size of an FCS to our caller?
251                    That'd let us handle other file types as well. */
252                 if (!wtap_read_bytes(wth->fh, &fcs, sizeof fcs, err, err_info))
253                         return FALSE;
254         }
255
256         return TRUE;
257 }
258
259 static gboolean
260 radcom_seek_read(wtap *wth, gint64 seek_off,
261                  wtap_rec *rec, Buffer *buf,
262                  int *err, gchar **err_info)
263 {
264         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
265                 return FALSE;
266
267         /* Read record. */
268         if (!radcom_read_rec(wth, wth->random_fh, rec, buf, err,
269             err_info)) {
270                 /* Read error or EOF */
271                 if (*err == 0) {
272                         /* EOF means "short read" in random-access mode */
273                         *err = WTAP_ERR_SHORT_READ;
274                 }
275                 return FALSE;
276         }
277         return TRUE;
278 }
279
280 static gboolean
281 radcom_read_rec(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
282                 int *err, gchar **err_info)
283 {
284         struct radcomrec_hdr hdr;
285         guint16 data_length, real_length, length;
286         guint32 sec;
287         struct tm tm;
288         guint8  atmhdr[8];
289
290         if (!wtap_read_bytes_or_eof(fh, &hdr, sizeof hdr, err, err_info))
291                 return FALSE;
292
293         data_length = pletoh16(&hdr.data_length);
294         if (data_length == 0) {
295                 /*
296                  * The last record appears to have 0 in its "data_length"
297                  * field, but non-zero values in other fields, so we
298                  * check for that and treat it as an EOF indication.
299                  */
300                 *err = 0;
301                 return FALSE;
302         }
303         length = pletoh16(&hdr.length);
304         real_length = pletoh16(&hdr.real_length);
305         /*
306          * The maximum value of length is 65535, which is less than
307          * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check
308          * it.
309          */
310
311         rec->rec_type = REC_TYPE_PACKET;
312         rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
313
314         tm.tm_year = pletoh16(&hdr.date.year)-1900;
315         tm.tm_mon = (hdr.date.month&0x0f)-1;
316         tm.tm_mday = hdr.date.day;
317         sec = pletoh32(&hdr.date.sec);
318         tm.tm_hour = sec/3600;
319         tm.tm_min = (sec%3600)/60;
320         tm.tm_sec = sec%60;
321         tm.tm_isdst = -1;
322         rec->ts.secs = mktime(&tm);
323         rec->ts.nsecs = pletoh32(&hdr.date.usec) * 1000;
324
325         switch (wth->file_encap) {
326
327         case WTAP_ENCAP_ETHERNET:
328                 /* XXX - is there an FCS? */
329                 rec->rec_header.packet_header.pseudo_header.eth.fcs_len = -1;
330                 break;
331
332         case WTAP_ENCAP_LAPB:
333                 rec->rec_header.packet_header.pseudo_header.dte_dce.flags = (hdr.dce & 0x1) ?
334                     0x00 : FROM_DCE;
335                 length -= 2; /* FCS */
336                 real_length -= 2;
337                 break;
338
339         case WTAP_ENCAP_ATM_RFC1483:
340                 /*
341                  * XXX - is this stuff a pseudo-header?
342                  * The direction appears to be in the "hdr.dce" field.
343                  */
344                 if (!wtap_read_bytes(fh, atmhdr, sizeof atmhdr, err,
345                     err_info))
346                         return FALSE;   /* Read error */
347                 length -= 8;
348                 real_length -= 8;
349                 break;
350         }
351
352         rec->rec_header.packet_header.len = real_length;
353         rec->rec_header.packet_header.caplen = length;
354
355         /*
356          * Read the packet data.
357          */
358         if (!wtap_read_packet_bytes(fh, buf, length, err, err_info))
359                 return FALSE;   /* Read error */
360
361         return TRUE;
362 }
363
364 /*
365  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
366  *
367  * Local variables:
368  * c-basic-offset: 8
369  * tab-width: 8
370  * indent-tabs-mode: t
371  * End:
372  *
373  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
374  * :indentSize=8:tabSize=8:noTabs=false:
375  */