4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "file_wrappers.h"
16 /* Magic number in Aethra PC108 files. */
19 static const unsigned char aethra_magic
[MAGIC_SIZE
] = {
20 'V', '0', '2', '0', '8'
23 /* Aethra file header. */
25 unsigned char magic
[MAGIC_SIZE
];
26 uint8_t unknown1
[39]; /* 5-43 */
27 unsigned char sw_vers
[60]; /* 44-103 - software version string, not null-terminated */
28 uint8_t unknown2
[118]; /* 104-221 */
29 uint8_t start_sec
; /* 222 - seconds of capture start time */
30 uint8_t start_min
; /* 223 - minutes of capture start time */
31 uint8_t start_hour
; /* 224 - hour of capture start time */
32 uint8_t unknown3
[462]; /* 225-686 */
33 unsigned char xxx_string
[37]; /* 687-723 - null-terminated short comment string? */
34 uint8_t unknown3_5
[4]; /* 724-727 */
35 unsigned char yyy_string
[4504];/* 728-5231 - null-terminated long comment string? */
36 uint8_t start_year
[2]; /* 5232-5233 - year of capture start date */
37 uint8_t start_month
[2]; /* 5234-5235 - month of capture start date */
38 uint8_t unknown4
[2]; /* 5236-5237 */
39 uint8_t start_day
[2]; /* 5238-5239 - day of capture start date */
40 uint8_t unknown5
[8]; /* 5240-5247 */
41 unsigned char com_info
[16]; /* 5248-5263 - COM port and speed, null-padded(?) */
42 uint8_t unknown6
[107]; /* 5264-5370 */
43 unsigned char xxx_vers
[41]; /* 5371-5411 - unknown version string (longer, null-padded?) */
46 /* Aethra record header. Yes, the alignment is weird.
47 All multi-byte fields are little-endian. */
48 struct aethrarec_hdr
{
49 uint8_t rec_size
[2]; /* record length, not counting the length itself */
50 uint8_t rec_type
; /* record type */
51 uint8_t timestamp
[4]; /* milliseconds since start of capture */
52 uint8_t flags
; /* low-order bit: 0 = N->U, 1 = U->N */
58 * As the indications from the device and signalling messages appear not
59 * to have the 8th bit set, and at least some B-channel records do, we
60 * assume, for now, that the 8th bit indicates bearer information.
62 * 0x9F is the record type seen for B31 channel records; that might be
63 * 0x80|31, so, for now, we assume that if the 8th bit is set, the B
64 * channel number is in the low 7 bits.
66 #define AETHRA_BEARER 0x80 /* bearer information */
68 #define AETHRA_DEVICE 0x00 /* indication from the monitoring device */
69 #define AETHRA_ISDN_LINK 0x01 /* information from the ISDN link */
72 * In AETHRA_DEVICE records, the flags field has what appears to
73 * be a record subtype.
75 #define AETHRA_DEVICE_STOP_MONITOR 0x00 /* Stop Monitor */
76 #define AETHRA_DEVICE_START_MONITOR 0x04 /* Start Monitor */
77 #define AETHRA_DEVICE_ACTIVATION 0x05 /* Activation */
78 #define AETHRA_DEVICE_START_CAPTURE 0x5F /* Start Capture */
81 * In AETHRA_ISDN_LINK and bearer channel records, the flags field has
82 * a direction flag and possibly some other bits.
84 * In AETHRA_ISDN_LINK records, at least some of the other bits are
87 * In bearer channel records, there are records with data and
88 * "Constant Value" records with a single byte. Data has a
89 * flags value of 0x14 ORed with the direction flag, and Constant Value
90 * records have a flags value of 0x16 ORed with the direction flag.
91 * There are also records of an unknown type with 0x02, probably
92 * ORed with the direction flag.
94 #define AETHRA_U_TO_N 0x01 /* set for TE->NT */
96 #define AETHRA_ISDN_LINK_SUBTYPE 0xFE
97 #define AETHRA_ISDN_LINK_LAPD 0x00 /* LAPD frame */
98 #define AETHRA_ISDN_LINK_SA_BITS 0x2E /* 2048K PRI Sa bits (G.704 section 2.3.2) */
99 #define AETHRA_ISDN_LINK_ALL_ALARMS_CLEARED 0x30 /* All Alarms Cleared */
105 static bool aethra_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
,
106 char **err_info
, int64_t *data_offset
);
107 static bool aethra_seek_read(wtap
*wth
, int64_t seek_off
,
108 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
);
109 static bool aethra_read_rec_header(wtap
*wth
, FILE_T fh
, struct aethrarec_hdr
*hdr
,
110 wtap_rec
*rec
, int *err
, char **err_info
);
112 static int aethra_file_type_subtype
= -1;
114 void register_aethra(void);
116 wtap_open_return_val
aethra_open(wtap
*wth
, int *err
, char **err_info
)
118 struct aethra_hdr hdr
;
122 /* Read in the string that should be at the start of a "aethra" file */
123 if (!wtap_read_bytes(wth
->fh
, hdr
.magic
, sizeof hdr
.magic
, err
,
125 if (*err
!= WTAP_ERR_SHORT_READ
)
126 return WTAP_OPEN_ERROR
;
127 return WTAP_OPEN_NOT_MINE
;
130 if (memcmp(hdr
.magic
, aethra_magic
, sizeof aethra_magic
) != 0)
131 return WTAP_OPEN_NOT_MINE
;
133 /* Read the rest of the header. */
134 if (!wtap_read_bytes(wth
->fh
, (char *)&hdr
+ sizeof hdr
.magic
,
135 sizeof hdr
- sizeof hdr
.magic
, err
, err_info
))
136 return WTAP_OPEN_ERROR
;
137 wth
->file_type_subtype
= aethra_file_type_subtype
;
138 aethra
= g_new(aethra_t
, 1);
139 wth
->priv
= (void *)aethra
;
140 wth
->subtype_read
= aethra_read
;
141 wth
->subtype_seek_read
= aethra_seek_read
;
144 * Convert the time stamp to a "time_t".
146 tm
.tm_year
= pletoh16(&hdr
.start_year
) - 1900;
147 tm
.tm_mon
= pletoh16(&hdr
.start_month
) - 1;
148 tm
.tm_mday
= pletoh16(&hdr
.start_day
);
149 tm
.tm_hour
= hdr
.start_hour
;
150 tm
.tm_min
= hdr
.start_min
;
151 tm
.tm_sec
= hdr
.start_sec
;
153 aethra
->start
= mktime(&tm
);
156 * We've only seen ISDN files, so, for now, we treat all
159 wth
->file_encap
= WTAP_ENCAP_ISDN
;
160 wth
->snapshot_length
= 0; /* not available in header */
161 wth
->file_tsprec
= WTAP_TSPREC_MSEC
;
164 * Add an IDB; we don't know how many interfaces were
165 * involved, so we just say one interface, about which
166 * we only know the link-layer type, snapshot length,
167 * and time stamp resolution.
169 wtap_add_generated_idb(wth
);
171 return WTAP_OPEN_MINE
;
175 static unsigned packet
;
178 /* Read the next packet */
179 static bool aethra_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
,
180 char **err_info
, int64_t *data_offset
)
182 struct aethrarec_hdr hdr
;
185 * Keep reading until we see an AETHRA_ISDN_LINK with a subtype
186 * of AETHRA_ISDN_LINK_LAPD record or get an end-of-file.
189 *data_offset
= file_tell(wth
->fh
);
191 /* Read record header. */
192 if (!aethra_read_rec_header(wth
, wth
->fh
, &hdr
, rec
, err
, err_info
))
196 * XXX - if this is big, we might waste memory by
197 * growing the buffer to handle it.
199 if (rec
->rec_header
.packet_header
.caplen
!= 0) {
200 if (!wtap_read_packet_bytes(wth
->fh
, buf
,
201 rec
->rec_header
.packet_header
.caplen
, err
, err_info
))
202 return false; /* Read error */
207 switch (hdr
.rec_type
) {
209 case AETHRA_ISDN_LINK
:
211 fprintf(stderr
, "Packet %u: type 0x%02x (AETHRA_ISDN_LINK)\n",
212 packet
, hdr
.rec_type
);
214 switch (hdr
.flags
& AETHRA_ISDN_LINK_SUBTYPE
) {
216 case AETHRA_ISDN_LINK_LAPD
:
218 * The data is a LAPD frame.
221 fprintf(stderr
, " subtype 0x%02x (AETHRA_ISDN_LINK_LAPD)\n", hdr
.flags
& AETHRA_ISDN_LINK_SUBTYPE
);
225 case AETHRA_ISDN_LINK_SA_BITS
:
227 * These records have one data byte, which
228 * has the Sa bits in the lower 5 bits.
230 * XXX - what about stuff other than 2048K
234 fprintf(stderr
, " subtype 0x%02x (AETHRA_ISDN_LINK_SA_BITS)\n", hdr
.flags
& AETHRA_ISDN_LINK_SUBTYPE
);
238 case AETHRA_ISDN_LINK_ALL_ALARMS_CLEARED
:
240 * No data, just an "all alarms cleared"
244 fprintf(stderr
, " subtype 0x%02x (AETHRA_ISDN_LINK_ALL_ALARMS_CLEARED)\n", hdr
.flags
& AETHRA_ISDN_LINK_SUBTYPE
);
250 fprintf(stderr
, " subtype 0x%02x, packet_size %u, direction 0x%02x\n",
251 hdr
.flags
& AETHRA_ISDN_LINK_SUBTYPE
, rec
->rec_header
.packet_header
.caplen
, hdr
.flags
& AETHRA_U_TO_N
);
259 fprintf(stderr
, "Packet %u: type 0x%02x, packet_size %u, flags 0x%02x\n",
260 packet
, hdr
.rec_type
, rec
->rec_header
.packet_header
.caplen
, hdr
.flags
);
271 aethra_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
,
272 Buffer
*buf
, int *err
, char **err_info
)
274 struct aethrarec_hdr hdr
;
276 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
279 if (!aethra_read_rec_header(wth
, wth
->random_fh
, &hdr
, rec
, err
,
282 *err
= WTAP_ERR_SHORT_READ
;
287 * Read the packet data.
289 if (!wtap_read_packet_bytes(wth
->random_fh
, buf
, rec
->rec_header
.packet_header
.caplen
, err
, err_info
))
290 return false; /* failed */
296 aethra_read_rec_header(wtap
*wth
, FILE_T fh
, struct aethrarec_hdr
*hdr
,
297 wtap_rec
*rec
, int *err
, char **err_info
)
299 aethra_t
*aethra
= (aethra_t
*)wth
->priv
;
301 uint32_t packet_size
;
304 /* Read record header. */
305 if (!wtap_read_bytes_or_eof(fh
, hdr
, sizeof *hdr
, err
, err_info
))
308 rec_size
= pletoh16(hdr
->rec_size
);
309 if (rec_size
< (sizeof *hdr
- sizeof hdr
->rec_size
)) {
310 /* The record is shorter than a record header. */
311 *err
= WTAP_ERR_BAD_FILE
;
312 *err_info
= ws_strdup_printf("aethra: File has %u-byte record, less than minimum of %u",
314 (unsigned int)(sizeof *hdr
- sizeof hdr
->rec_size
));
317 if (rec_size
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
319 * Probably a corrupt capture file; return an error,
320 * so that our caller doesn't blow up trying to allocate
321 * space for an immensely-large packet.
323 *err
= WTAP_ERR_BAD_FILE
;
324 *err_info
= ws_strdup_printf("aethra: File has %u-byte packet, bigger than maximum of %u",
325 rec_size
, WTAP_MAX_PACKET_SIZE_STANDARD
);
329 packet_size
= rec_size
- (uint32_t)(sizeof *hdr
- sizeof hdr
->rec_size
);
331 msecs
= pletoh32(hdr
->timestamp
);
332 rec
->rec_type
= REC_TYPE_PACKET
;
333 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
334 rec
->presence_flags
= WTAP_HAS_TS
;
335 rec
->ts
.secs
= aethra
->start
+ (msecs
/ 1000);
336 rec
->ts
.nsecs
= (msecs
% 1000) * 1000000;
337 rec
->rec_header
.packet_header
.caplen
= packet_size
;
338 rec
->rec_header
.packet_header
.len
= packet_size
;
339 rec
->rec_header
.packet_header
.pseudo_header
.isdn
.uton
= (hdr
->flags
& AETHRA_U_TO_N
);
340 rec
->rec_header
.packet_header
.pseudo_header
.isdn
.channel
= 0; /* XXX - D channel */
345 static const struct supported_block_type aethra_blocks_supported
[] = {
347 * We support packet blocks, with no comments or other options.
349 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
352 static const struct file_type_subtype_info aethra_info
= {
353 "Aethra .aps file", "aethra", "aps", NULL
,
354 false, BLOCKS_SUPPORTED(aethra_blocks_supported
),
358 void register_aethra(void)
360 aethra_file_type_subtype
= wtap_register_file_type_subtype(&aethra_info
);
363 * Register name for backwards compatibility with the
364 * wtap_filetypes table in Lua.
366 wtap_register_backwards_compatibility_lua_name("AETHRA",
367 aethra_file_type_subtype
);
371 * Editor modelines - https://www.wireshark.org/tools/modelines.html
376 * indent-tabs-mode: t
379 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
380 * :indentSize=8:tabSize=8:noTabs=false: