4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * Support for candump log file format
7 * Copyright (c) 2019 by Maksim Salau <maksim.salau@gmail.com>
9 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <file_wrappers.h>
17 #include <wsutil/exported_pdu_tlvs.h>
21 #include "candump_priv.h"
23 static bool candump_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
24 int *err
, char **err_info
,
25 int64_t *data_offset
);
26 static bool candump_seek_read(wtap
*wth
, int64_t seek_off
,
27 wtap_rec
*rec
, Buffer
*buf
,
28 int *err
, char **err_info
);
30 static int candump_file_type_subtype
= -1;
32 void register_candump(void);
35 * This is written by the candump utility on Linux.
39 candump_gen_packet(wtap_rec
*rec
, Buffer
*buf
, const msg_t
*msg
, int *err
,
42 /* Generate Exported PDU tags for the packet info */
47 canfd_frame_t canfd_frame
= {0};
50 * There's a maximum of CANFD_MAX_DLEN bytes in a CAN-FD frame.
52 if (msg
->data
.length
> CANFD_MAX_DLEN
) {
53 *err
= WTAP_ERR_BAD_FILE
;
54 if (err_info
!= NULL
) {
55 *err_info
= ws_strdup_printf("candump: File has %u-byte CAN FD packet, bigger than maximum of %u",
56 msg
->data
.length
, CANFD_MAX_DLEN
);
61 canfd_frame
.can_id
= g_htonl(msg
->id
);
62 canfd_frame
.flags
= msg
->flags
| CANFD_FDF
;
63 canfd_frame
.len
= msg
->data
.length
;
64 memcpy(canfd_frame
.data
, msg
->data
.data
, msg
->data
.length
);
66 ws_buffer_append(buf
, (uint8_t *)&canfd_frame
, sizeof(canfd_frame
));
70 can_frame_t can_frame
= {0};
73 * There's a maximum of CAN_MAX_DLEN bytes in a CAN frame.
75 if (msg
->data
.length
> CAN_MAX_DLEN
) {
76 *err
= WTAP_ERR_BAD_FILE
;
77 if (err_info
!= NULL
) {
78 *err_info
= ws_strdup_printf("candump: File has %u-byte CAN packet, bigger than maximum of %u",
79 msg
->data
.length
, CAN_MAX_DLEN
);
84 can_frame
.can_id
= g_htonl(msg
->id
);
85 can_frame
.can_dlc
= msg
->data
.length
;
86 memcpy(can_frame
.data
, msg
->data
.data
, msg
->data
.length
);
88 ws_buffer_append(buf
, (uint8_t *)&can_frame
, sizeof(can_frame
));
91 rec
->rec_type
= REC_TYPE_PACKET
;
92 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
93 rec
->presence_flags
= WTAP_HAS_TS
;
95 rec
->tsprec
= WTAP_TSPREC_USEC
;
97 rec
->rec_header
.packet_header
.caplen
= (uint32_t)ws_buffer_length(buf
);
98 rec
->rec_header
.packet_header
.len
= (uint32_t)ws_buffer_length(buf
);
104 candump_parse(FILE_T fh
, msg_t
*msg
, int64_t *offset
, int *err
, char **err_info
)
106 candump_state_t state
= {0};
111 candump_debug_printf("%s: Trying candump file decoder\n", G_STRFUNC
);
121 seek_off
= file_tell(fh
);
123 candump_debug_printf("%s: Starting parser at offset %" PRIi64
"\n", G_STRFUNC
, seek_off
);
125 state
.file_bytes_read
= 0;
126 ok
= run_candump_parser(&state
, err
, err_info
);
128 /* Rewind the file to the offset we have finished parsing */
129 if (file_seek(fh
, seek_off
+ state
.file_bytes_read
, SEEK_SET
, err
) == -1)
133 *err_info
= g_strdup(g_strerror(errno
));
137 while (ok
&& !state
.is_msg_valid
);
143 candump_debug_printf("%s: Success\n", G_STRFUNC
);
156 candump_open(wtap
*wth
, int *err
, char **err_info
)
158 if (!candump_parse(wth
->fh
, NULL
, NULL
, err
, err_info
))
165 return WTAP_OPEN_NOT_MINE
;
169 candump_debug_printf("%s: This is our file\n", G_STRFUNC
);
172 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -1)
175 *err_info
= g_strdup(g_strerror(errno
));
177 return WTAP_OPEN_ERROR
;
181 wth
->file_type_subtype
= candump_file_type_subtype
;
182 wth
->file_encap
= WTAP_ENCAP_SOCKETCAN
;
183 wth
->file_tsprec
= WTAP_TSPREC_USEC
;
184 wth
->subtype_read
= candump_read
;
185 wth
->subtype_seek_read
= candump_seek_read
;
187 return WTAP_OPEN_MINE
;
191 candump_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
,
192 int64_t *data_offset
)
197 candump_debug_printf("%s: Try reading at offset %" PRIi64
"\n", G_STRFUNC
, file_tell(wth
->fh
));
200 if (!candump_parse(wth
->fh
, &msg
, data_offset
, err
, err_info
))
204 candump_debug_printf("%s: Stopped at offset %" PRIi64
"\n", G_STRFUNC
, file_tell(wth
->fh
));
207 return candump_gen_packet(rec
, buf
, &msg
, err
, err_info
);
211 candump_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
,
212 Buffer
*buf
, int *err
, char **err_info
)
217 candump_debug_printf("%s: Read at offset %" PRIi64
"\n", G_STRFUNC
, seek_off
);
220 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
223 *err_info
= g_strdup(g_strerror(errno
));
228 if (!candump_parse(wth
->random_fh
, &msg
, NULL
, err
, err_info
))
231 return candump_gen_packet(rec
, buf
, &msg
, err
, err_info
);
234 static const struct supported_block_type candump_blocks_supported
[] = {
236 * We support packet blocks, with no comments or other options.
238 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
241 static const struct file_type_subtype_info candump_info
= {
242 "Linux candump file", "candump", NULL
, NULL
,
243 false, BLOCKS_SUPPORTED(candump_blocks_supported
),
247 void register_candump(void)
249 candump_file_type_subtype
= wtap_register_file_type_subtype(&candump_info
);
253 * Editor modelines - https://www.wireshark.org/tools/modelines.html
258 * indent-tabs-mode: nil
261 * vi: set shiftwidth=4 tabstop=8 expandtab:
262 * :indentSize=4:tabSize=8:noTabs=true: