3 * $Id: i4btrace.c,v 1.12 2000/11/17 21:00:40 gram Exp $
6 * Copyright (c) 1999 by Bert Driehuis <driehuis@playbeing.org>
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.
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.
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.
31 #include "file_wrappers.h"
33 #include "i4b_trace.h"
35 static gboolean i4btrace_read(wtap *wth, int *err, int *data_offset);
36 static int i4btrace_seek_read(wtap *wth, int seek_off,
37 union wtap_pseudo_header *pseudo_header, u_char *pd, int length);
38 static int i4b_read_rec_header(FILE_T fh, i4b_trace_hdr_t *hdr, int *err);
39 static void i4b_byte_swap_header(wtap *wth, i4b_trace_hdr_t *hdr);
40 static int i4b_read_rec_data(FILE_T fh, u_char *pd, int length, int *err);
41 static void i4b_set_pseudo_header(wtap *wth, i4b_trace_hdr_t *hdr,
42 union wtap_pseudo_header *pseudo_header);
45 * Test some fields in the header to see if they make sense.
47 #define I4B_HDR_IS_OK(hdr) \
48 (!((unsigned)hdr.length < 3 || (unsigned)hdr.unit > 4 || \
49 (unsigned)hdr.type > 4 || (unsigned)hdr.dir > 2 || \
50 (unsigned)hdr.trunc > 2048))
52 int i4btrace_open(wtap *wth, int *err)
56 gboolean byte_swapped = FALSE;
58 /* I4B trace files have no magic in the header... Sigh */
59 file_seek(wth->fh, 0, SEEK_SET);
60 errno = WTAP_ERR_CANT_READ;
61 bytes_read = file_read(&hdr, 1, sizeof(hdr), wth->fh);
62 if (bytes_read != sizeof(hdr)) {
63 *err = file_error(wth->fh);
69 /* Silly heuristic... */
70 if (!I4B_HDR_IS_OK(hdr)) {
72 * OK, try byte-swapping the header fields.
74 hdr.length = BSWAP32(hdr.length);
75 hdr.unit = BSWAP32(hdr.unit);
76 hdr.type = BSWAP32(hdr.type);
77 hdr.dir = BSWAP32(hdr.dir);
78 hdr.trunc = BSWAP32(hdr.trunc);
79 if (!I4B_HDR_IS_OK(hdr)) {
81 * It doesn't look valid in either byte order.
87 * It looks valid byte-swapped, so assume it's a
88 * trace written in the opposite byte order.
93 file_seek(wth->fh, 0, SEEK_SET);
96 /* Get capture start time */
98 wth->file_type = WTAP_FILE_I4BTRACE;
99 wth->capture.i4btrace = g_malloc(sizeof(i4btrace_t));
100 wth->subtype_read = i4btrace_read;
101 wth->subtype_seek_read = i4btrace_seek_read;
102 wth->snapshot_length = 2048; /* actual length set per packet */
104 wth->capture.i4btrace->bchannel_prot[0] = -1;
105 wth->capture.i4btrace->bchannel_prot[1] = -1;
106 wth->capture.i4btrace->byte_swapped = byte_swapped;
108 wth->file_encap = WTAP_ENCAP_PER_PACKET;
113 #define V120SABME "\010\001\177"
115 /* Read the next packet */
116 static gboolean i4btrace_read(wtap *wth, int *err, int *data_offset)
124 /* Read record header. */
125 *data_offset = wth->data_offset;
126 ret = i4b_read_rec_header(wth->fh, &hdr, err);
128 /* Read error or EOF */
131 wth->data_offset += sizeof hdr;
132 i4b_byte_swap_header(wth, &hdr);
133 length = hdr.length - sizeof(hdr);
137 wth->phdr.len = length;
138 wth->phdr.caplen = length;
140 wth->phdr.ts.tv_sec = hdr.time.tv_sec;
141 wth->phdr.ts.tv_usec = hdr.time.tv_usec;
144 * Read the packet data.
146 buffer_assure_space(wth->frame_buffer, length);
147 bufp = buffer_start_ptr(wth->frame_buffer);
148 if (i4b_read_rec_data(wth->fh, bufp, length, err) < 0)
149 return FALSE; /* Read error */
150 wth->data_offset += length;
156 * XXX - what is it? It's probably not WTAP_ENCAP_NULL,
157 * as that means it has a 4-byte AF_ type as the
158 * encapsulation header.
160 wth->phdr.pkt_encap = WTAP_ENCAP_NULL;
165 * D channel, so it's LAPD.
167 wth->phdr.pkt_encap = WTAP_ENCAP_LAPD;
173 * B channel, so it could be any of a number of things.
175 channel = hdr.type - TRC_CH_B1;
177 if (wth->capture.i4btrace->bchannel_prot[channel] == -1) {
179 * We don't know yet whether the datastream is
180 * V.120 or not; this heuristic tries to figure
183 * We cannot glean this from the Q.931 SETUP message,
184 * because no commercial V.120 implementation I've
185 * seen actually sets the V.120 protocol discriminator
186 * (that, or I'm misreading the spec badly).
188 * TODO: reset the flag to -1 (unknown) after a close
189 * on the B channel is detected.
191 if (memcmp(bufp, V120SABME, 3) == 0)
192 wth->capture.i4btrace->bchannel_prot[channel] = 1;
194 wth->capture.i4btrace->bchannel_prot[channel] = 0;
196 if (wth->capture.i4btrace->bchannel_prot[channel] == 1) {
200 wth->phdr.pkt_encap = WTAP_ENCAP_V120;
205 * XXX - what is it? It's probably not
206 * WTAP_ENCAP_NULL, as that means it has a
207 * 4-byte AF_ type as the encapsulation header.
208 * If it's PPP, we should use WTAP_ENCAP_PPP here.
210 wth->phdr.pkt_encap = WTAP_ENCAP_NULL;
215 i4b_set_pseudo_header(wth, &hdr, &wth->pseudo_header);
221 i4btrace_seek_read(wtap *wth, int seek_off,
222 union wtap_pseudo_header *pseudo_header, u_char *pd, int length)
225 int err; /* XXX - return this */
228 file_seek(wth->random_fh, seek_off, SEEK_SET);
230 /* Read record header. */
231 ret = i4b_read_rec_header(wth->random_fh, &hdr, &err);
233 /* Read error or EOF */
236 i4b_byte_swap_header(wth, &hdr);
238 i4b_set_pseudo_header(wth, &hdr, pseudo_header);
241 * Read the packet data.
243 return i4b_read_rec_data(wth->random_fh, pd, length, &err);
247 i4b_read_rec_header(FILE_T fh, i4b_trace_hdr_t *hdr, int *err)
251 errno = WTAP_ERR_CANT_READ;
252 bytes_read = file_read(hdr, 1, sizeof *hdr, fh);
253 if (bytes_read != sizeof *hdr) {
254 *err = file_error(fh);
257 if (bytes_read != 0) {
258 *err = WTAP_ERR_SHORT_READ;
267 i4b_byte_swap_header(wtap *wth, i4b_trace_hdr_t *hdr)
269 if (wth->capture.i4btrace->byte_swapped) {
271 * Byte-swap the header.
273 hdr->length = BSWAP32(hdr->length);
274 hdr->unit = BSWAP32(hdr->unit);
275 hdr->type = BSWAP32(hdr->type);
276 hdr->dir = BSWAP32(hdr->dir);
277 hdr->trunc = BSWAP32(hdr->trunc);
278 hdr->count = BSWAP32(hdr->count);
279 hdr->time.tv_sec = BSWAP32(hdr->time.tv_sec);
280 hdr->time.tv_usec = BSWAP32(hdr->time.tv_usec);
285 i4b_read_rec_data(FILE_T fh, u_char *pd, int length, int *err)
289 errno = WTAP_ERR_CANT_READ;
290 bytes_read = file_read(pd, 1, length, fh);
292 if (bytes_read != length) {
293 *err = file_error(fh);
295 *err = WTAP_ERR_SHORT_READ;
302 i4b_set_pseudo_header(wtap *wth, i4b_trace_hdr_t *hdr,
303 union wtap_pseudo_header *pseudo_header)
311 * D channel, so it's LAPD; set "p2p.sent".
313 pseudo_header->p2p.sent = (hdr->dir == FROM_TE) ? TRUE : FALSE;
319 * B channel, so it could be any of a number of things;
320 * if it's V.120, set "x25.flags".
322 channel = hdr->type - TRC_CH_B1;
324 if (wth->capture.i4btrace->bchannel_prot[channel] == 1) {
328 pseudo_header->x25.flags =
329 (hdr->dir == FROM_TE) ? 0x00 : 0x80;