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"
22 static bool i4btrace_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
23 int *err
, char **err_info
, int64_t *offset
);
24 static bool i4btrace_seek_read(wtap
*wth
, int64_t seek_off
,
25 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
);
26 static bool i4b_read_rec(wtap
*wth
, FILE_T fh
, wtap_rec
*rec
,
27 Buffer
*buf
, int *err
, char **err_info
);
29 static int i4btrace_file_type_subtype
= -1;
31 void register_i4btrace(void);
34 * Byte-swap the header.
36 #define I4B_BYTESWAP_HEADER(hdr) \
38 hdr.length = GUINT32_SWAP_LE_BE(hdr.length); \
39 hdr.unit = GUINT32_SWAP_LE_BE(hdr.unit); \
40 hdr.type = GUINT32_SWAP_LE_BE(hdr.type); \
41 hdr.dir = GUINT32_SWAP_LE_BE(hdr.dir); \
42 hdr.trunc = GUINT32_SWAP_LE_BE(hdr.trunc); \
43 hdr.count = GUINT32_SWAP_LE_BE(hdr.count); \
44 hdr.ts_sec = GUINT32_SWAP_LE_BE(hdr.ts_sec); \
45 hdr.ts_usec = GUINT32_SWAP_LE_BE(hdr.ts_usec); \
49 * Test some fields in the header to see if they make sense.
51 #define I4B_HDR_IS_OK(hdr) \
52 (!(hdr.length < sizeof(hdr) || \
53 hdr.length > 16384 || \
55 hdr.type > TRC_CH_B2 || \
56 hdr.dir > FROM_NT || \
58 hdr.ts_usec >= 1000000))
61 * Number of packets to try reading.
63 #define PACKETS_TO_CHECK 5
65 wtap_open_return_val
i4btrace_open(wtap
*wth
, int *err
, char **err_info
)
68 bool byte_swapped
= false;
71 /* I4B trace files have no magic in the header... Sigh */
72 if (!wtap_read_bytes(wth
->fh
, &hdr
, sizeof(hdr
), err
, err_info
)) {
73 if (*err
!= WTAP_ERR_SHORT_READ
)
74 return WTAP_OPEN_ERROR
;
75 return WTAP_OPEN_NOT_MINE
;
78 /* Silly heuristic... */
79 if (!I4B_HDR_IS_OK(hdr
)) {
81 * OK, try byte-swapping the header fields.
83 I4B_BYTESWAP_HEADER(hdr
);
84 if (!I4B_HDR_IS_OK(hdr
)) {
86 * It doesn't look valid in either byte order.
88 return WTAP_OPEN_NOT_MINE
;
92 * It looks valid byte-swapped, so assume it's a
93 * trace written in the opposite byte order.
99 * Now try to read past the packet bytes; if that fails with
100 * a short read, we don't fail, so that we can report
101 * the file as a truncated I4B file.
103 if (!wtap_read_bytes(wth
->fh
, NULL
, hdr
.length
- (uint32_t)sizeof(hdr
),
105 if (*err
!= WTAP_ERR_SHORT_READ
)
106 return WTAP_OPEN_ERROR
;
109 * Now try reading a few more packets.
111 for (int i
= 1; i
< PACKETS_TO_CHECK
; i
++) {
113 * Read and check the file header; we've already
114 * decided whether this would be a byte-swapped file
115 * or not, so we swap iff we decided it was.
117 if (!wtap_read_bytes_or_eof(wth
->fh
, &hdr
, sizeof(hdr
), err
,
120 /* EOF; no more packets to try. */
123 if (*err
!= WTAP_ERR_SHORT_READ
)
124 return WTAP_OPEN_ERROR
;
125 return WTAP_OPEN_NOT_MINE
;
129 I4B_BYTESWAP_HEADER(hdr
);
130 if (!I4B_HDR_IS_OK(hdr
)) {
132 * It doesn't look valid.
134 return WTAP_OPEN_NOT_MINE
;
138 * Now try to read past the packet bytes; if that
139 * fails with a short read, we don't fail, so that
140 * we can report the file as a truncated I4B file.
142 if (!wtap_read_bytes(wth
->fh
, NULL
,
143 hdr
.length
- (uint32_t)sizeof(hdr
), err
, err_info
)) {
144 if (*err
!= WTAP_ERR_SHORT_READ
)
145 return WTAP_OPEN_ERROR
;
148 * Probably a truncated file, so just quit.
155 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -1)
156 return WTAP_OPEN_ERROR
;
158 /* Get capture start time */
160 wth
->file_type_subtype
= i4btrace_file_type_subtype
;
161 i4btrace
= g_new(i4btrace_t
, 1);
162 wth
->priv
= (void *)i4btrace
;
163 wth
->subtype_read
= i4btrace_read
;
164 wth
->subtype_seek_read
= i4btrace_seek_read
;
165 wth
->snapshot_length
= 0; /* not known */
167 i4btrace
->byte_swapped
= byte_swapped
;
169 wth
->file_encap
= WTAP_ENCAP_ISDN
;
170 wth
->file_tsprec
= WTAP_TSPREC_USEC
;
173 * Add an IDB; we don't know how many interfaces were
174 * involved, so we just say one interface, about which
175 * we only know the link-layer type, snapshot length,
176 * and time stamp resolution.
178 wtap_add_generated_idb(wth
);
180 return WTAP_OPEN_MINE
;
183 /* Read the next packet */
184 static bool i4btrace_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
185 int *err
, char **err_info
, int64_t *data_offset
)
187 *data_offset
= file_tell(wth
->fh
);
189 return i4b_read_rec(wth
, wth
->fh
, rec
, buf
, err
, err_info
);
193 i4btrace_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
,
194 Buffer
*buf
, int *err
, char **err_info
)
196 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
199 if (!i4b_read_rec(wth
, wth
->random_fh
, rec
, buf
, err
, err_info
)) {
200 /* Read error or EOF */
202 /* EOF means "short read" in random-access mode */
203 *err
= WTAP_ERR_SHORT_READ
;
211 i4b_read_rec(wtap
*wth
, FILE_T fh
, wtap_rec
*rec
, Buffer
*buf
,
212 int *err
, char **err_info
)
214 i4btrace_t
*i4btrace
= (i4btrace_t
*)wth
->priv
;
218 if (!wtap_read_bytes_or_eof(fh
, &hdr
, sizeof hdr
, err
, err_info
))
221 if (i4btrace
->byte_swapped
) {
223 * Byte-swap the header.
225 I4B_BYTESWAP_HEADER(hdr
);
228 if (hdr
.length
< sizeof(hdr
)) {
229 *err
= WTAP_ERR_BAD_FILE
; /* record length < header! */
230 *err_info
= ws_strdup_printf("i4btrace: record length %u < header length %lu",
231 hdr
.length
, (unsigned long)sizeof(hdr
));
234 length
= hdr
.length
- (uint32_t)sizeof(hdr
);
235 if (length
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
237 * Probably a corrupt capture file; don't blow up trying
238 * to allocate space for an immensely-large packet.
240 *err
= WTAP_ERR_BAD_FILE
;
241 *err_info
= ws_strdup_printf("i4btrace: File has %u-byte packet, bigger than maximum of %u",
242 length
, WTAP_MAX_PACKET_SIZE_STANDARD
);
246 rec
->rec_type
= REC_TYPE_PACKET
;
247 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
248 rec
->presence_flags
= WTAP_HAS_TS
;
250 rec
->rec_header
.packet_header
.len
= length
;
251 rec
->rec_header
.packet_header
.caplen
= length
;
253 rec
->ts
.secs
= hdr
.ts_sec
;
254 rec
->ts
.nsecs
= hdr
.ts_usec
* 1000;
260 * XXX - what is it? It's probably not WTAP_ENCAP_NULL,
261 * as that means it has a 4-byte AF_ type as the
262 * encapsulation header.
264 rec
->rec_header
.packet_header
.pkt_encap
= WTAP_ENCAP_NULL
;
269 * D channel, so it's LAPD; set "p2p.sent".
271 rec
->rec_header
.packet_header
.pkt_encap
= WTAP_ENCAP_ISDN
;
272 rec
->rec_header
.packet_header
.pseudo_header
.isdn
.channel
= 0;
279 rec
->rec_header
.packet_header
.pkt_encap
= WTAP_ENCAP_ISDN
;
280 rec
->rec_header
.packet_header
.pseudo_header
.isdn
.channel
= 1;
287 rec
->rec_header
.packet_header
.pkt_encap
= WTAP_ENCAP_ISDN
;
288 rec
->rec_header
.packet_header
.pseudo_header
.isdn
.channel
= 2;
292 rec
->rec_header
.packet_header
.pseudo_header
.isdn
.uton
= (hdr
.dir
== FROM_TE
);
295 * Read the packet data.
297 return wtap_read_packet_bytes(fh
, buf
, length
, err
, err_info
);
300 static const struct supported_block_type i4btrace_blocks_supported
[] = {
302 * We support packet blocks, with no comments or other options.
304 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
307 static const struct file_type_subtype_info i4btrace_info
= {
308 "I4B ISDN trace", "i4btrace", NULL
, NULL
,
309 false, BLOCKS_SUPPORTED(i4btrace_blocks_supported
),
313 void register_i4btrace(void)
315 i4btrace_file_type_subtype
= wtap_register_file_type_subtype(&i4btrace_info
);
318 * Register name for backwards compatibility with the
319 * wtap_filetypes table in Lua.
321 wtap_register_backwards_compatibility_lua_name("I4BTRACE",
322 i4btrace_file_type_subtype
);
326 * Editor modelines - https://www.wireshark.org/tools/modelines.html
331 * indent-tabs-mode: t
334 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
335 * :indentSize=8:tabSize=8:noTabs=false: