4 * Copyright (c) 1999 by Bert Driehuis <driehuis@playbeing.org>
6 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "file_wrappers.h"
16 #include "i4b_trace.h"
20 gboolean byte_swapped;
23 static gboolean i4btrace_read(wtap *wth, int *err, gchar **err_info,
25 static gboolean i4btrace_seek_read(wtap *wth, gint64 seek_off,
26 wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
27 static int i4b_read_rec(wtap *wth, FILE_T fh, wtap_rec *rec,
28 Buffer *buf, int *err, gchar **err_info);
31 * Test some fields in the header to see if they make sense.
33 #define I4B_HDR_IS_OK(hdr) \
34 (!((unsigned int)hdr.length < 3 || (unsigned int)hdr.length > 16384 || \
35 (unsigned int)hdr.unit > 4 || (unsigned int)hdr.type > 4 || \
36 (unsigned int)hdr.dir > 2 || (unsigned int)hdr.trunc > 2048))
38 wtap_open_return_val i4btrace_open(wtap *wth, int *err, gchar **err_info)
41 gboolean byte_swapped = FALSE;
44 /* I4B trace files have no magic in the header... Sigh */
45 if (!wtap_read_bytes(wth->fh, &hdr, sizeof(hdr), err, err_info)) {
46 if (*err != WTAP_ERR_SHORT_READ)
47 return WTAP_OPEN_ERROR;
48 return WTAP_OPEN_NOT_MINE;
51 /* Silly heuristic... */
52 if (!I4B_HDR_IS_OK(hdr)) {
54 * OK, try byte-swapping the header fields.
56 hdr.length = GUINT32_SWAP_LE_BE(hdr.length);
57 hdr.unit = GUINT32_SWAP_LE_BE(hdr.unit);
58 hdr.type = GUINT32_SWAP_LE_BE(hdr.type);
59 hdr.dir = GUINT32_SWAP_LE_BE(hdr.dir);
60 hdr.trunc = GUINT32_SWAP_LE_BE(hdr.trunc);
61 if (!I4B_HDR_IS_OK(hdr)) {
63 * It doesn't look valid in either byte order.
65 return WTAP_OPEN_NOT_MINE;
69 * It looks valid byte-swapped, so assume it's a
70 * trace written in the opposite byte order.
75 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
76 return WTAP_OPEN_ERROR;
78 /* Get capture start time */
80 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_I4BTRACE;
81 i4btrace = (i4btrace_t *)g_malloc(sizeof(i4btrace_t));
82 wth->priv = (void *)i4btrace;
83 wth->subtype_read = i4btrace_read;
84 wth->subtype_seek_read = i4btrace_seek_read;
85 wth->snapshot_length = 0; /* not known */
87 i4btrace->byte_swapped = byte_swapped;
89 wth->file_encap = WTAP_ENCAP_ISDN;
90 wth->file_tsprec = WTAP_TSPREC_USEC;
92 return WTAP_OPEN_MINE;
95 /* Read the next packet */
96 static gboolean i4btrace_read(wtap *wth, int *err, gchar **err_info,
99 *data_offset = file_tell(wth->fh);
101 return i4b_read_rec(wth, wth->fh, &wth->rec, wth->rec_data,
106 i4btrace_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec,
107 Buffer *buf, int *err, gchar **err_info)
109 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
112 if (!i4b_read_rec(wth, wth->random_fh, rec, buf, err, err_info)) {
113 /* Read error or EOF */
115 /* EOF means "short read" in random-access mode */
116 *err = WTAP_ERR_SHORT_READ;
124 i4b_read_rec(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
125 int *err, gchar **err_info)
127 i4btrace_t *i4btrace = (i4btrace_t *)wth->priv;
131 if (!wtap_read_bytes_or_eof(fh, &hdr, sizeof hdr, err, err_info))
134 if (i4btrace->byte_swapped) {
136 * Byte-swap the header.
138 hdr.length = GUINT32_SWAP_LE_BE(hdr.length);
139 hdr.unit = GUINT32_SWAP_LE_BE(hdr.unit);
140 hdr.type = GUINT32_SWAP_LE_BE(hdr.type);
141 hdr.dir = GUINT32_SWAP_LE_BE(hdr.dir);
142 hdr.trunc = GUINT32_SWAP_LE_BE(hdr.trunc);
143 hdr.count = GUINT32_SWAP_LE_BE(hdr.count);
144 hdr.ts_sec = GUINT32_SWAP_LE_BE(hdr.ts_sec);
145 hdr.ts_usec = GUINT32_SWAP_LE_BE(hdr.ts_usec);
148 if (hdr.length < sizeof(hdr)) {
149 *err = WTAP_ERR_BAD_FILE; /* record length < header! */
150 *err_info = g_strdup_printf("i4btrace: record length %u < header length %lu",
151 hdr.length, (unsigned long)sizeof(hdr));
154 length = hdr.length - (guint32)sizeof(hdr);
155 if (length > WTAP_MAX_PACKET_SIZE_STANDARD) {
157 * Probably a corrupt capture file; don't blow up trying
158 * to allocate space for an immensely-large packet.
160 *err = WTAP_ERR_BAD_FILE;
161 *err_info = g_strdup_printf("i4btrace: File has %u-byte packet, bigger than maximum of %u",
162 length, WTAP_MAX_PACKET_SIZE_STANDARD);
166 rec->rec_type = REC_TYPE_PACKET;
167 rec->presence_flags = WTAP_HAS_TS;
169 rec->rec_header.packet_header.len = length;
170 rec->rec_header.packet_header.caplen = length;
172 rec->ts.secs = hdr.ts_sec;
173 rec->ts.nsecs = hdr.ts_usec * 1000;
179 * XXX - what is it? It's probably not WTAP_ENCAP_NULL,
180 * as that means it has a 4-byte AF_ type as the
181 * encapsulation header.
183 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NULL;
188 * D channel, so it's LAPD; set "p2p.sent".
190 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_ISDN;
191 rec->rec_header.packet_header.pseudo_header.isdn.channel = 0;
198 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_ISDN;
199 rec->rec_header.packet_header.pseudo_header.isdn.channel = 1;
206 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_ISDN;
207 rec->rec_header.packet_header.pseudo_header.isdn.channel = 2;
211 rec->rec_header.packet_header.pseudo_header.isdn.uton = (hdr.dir == FROM_TE);
214 * Read the packet data.
216 return wtap_read_packet_bytes(fh, buf, length, err, err_info);
220 * Editor modelines - http://www.wireshark.org/tools/modelines.html
225 * indent-tabs-mode: t
228 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
229 * :indentSize=8:tabSize=8:noTabs=false: