dcerpc-netlogon: improve NetrLogonGetCapabilities dissection
[wireshark-sm.git] / wiretap / daintree-sna.c
blob61310f481e6f6140a3a8f78746772b78aa18cd4e
1 /* daintree_sna.c
2 * Routines for opening .dcf capture files created by Daintree's
3 * Sensor Network Analyzer for 802.15.4 radios
4 * Copyright 2009, Exegin Technologies Limited <fff@exegin.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Started with packetlogger.c as a template, but little packetlogger code
11 * remains. Borrowed many snippets from dbs-etherwatch.c, the
12 * daintree_sna_process_hex_data function having the largest chunk.
14 * SPDX-License-Identifier: GPL-2.0-or-later
17 /* This module reads capture files saved by Daintree's Sensor Network Analyzer.
18 * Daintree captures are plain text files with a two line header,
19 * followed by packet records, one per line, with whitespace separated fields
20 * consisting of: packet number, time, bytes of capture data, capture data,
21 * unknown, unknown, signal strength?, unknown, etc, and terminated with CRLF.
24 /* Example capture file:
26 #Format=4
27 # SNA v2.2.0.4 SUS:20090709 ACT:819705
28 1 1233783799.326400 10 030809ffffffff07ffff 42 1 -69 25 2 0 1 32767
29 2 1233783799.477440 5 02000bffff 110 1 -44 25 6 0 1 32767
30 3 1233783799.809920 5 020013ffff 107 1 -45 25 43 0 1 3276
34 #include "config.h"
35 #include "daintree-sna.h"
37 #include <stdlib.h>
38 #include <string.h>
40 #include "wtap-int.h"
41 #include "file_wrappers.h"
43 typedef struct daintree_sna_header {
44 uint32_t len;
45 uint64_t ts;
46 } daintree_sna_header_t;
48 #define DAINTREE_SNA_HEADER_SIZE 2
49 #define FCS_LENGTH 2
51 static const char daintree_magic_text[] = "#Format=";
53 #define DAINTREE_MAGIC_TEXT_SIZE (sizeof daintree_magic_text - 1)
54 #define DAINTREE_MAX_LINE_SIZE 512
55 #define READDATA_BUF_SIZE (DAINTREE_MAX_LINE_SIZE/2)
56 #define READDATA_MAX_FIELD_SIZE "255" /* DAINTREE_MAX_LINE_SIZE/2 -1 */
58 #define COMMENT_LINE daintree_magic_text[0]
60 static bool daintree_sna_read(wtap *wth, wtap_rec *rec,
61 Buffer *buf, int *err, char **err_info, int64_t *data_offset);
63 static bool daintree_sna_seek_read(wtap *wth, int64_t seek_off,
64 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
66 static bool daintree_sna_read_packet(FILE_T fh, wtap_rec *rec,
67 Buffer *buf, int *err, char **err_info);
69 static int daintree_sna_file_type_subtype = -1;
71 void register_daintree_sna(void);
73 /* Open a file and determine if it's a Daintree file */
74 wtap_open_return_val daintree_sna_open(wtap *wth, int *err, char **err_info)
76 char readLine[DAINTREE_MAX_LINE_SIZE];
78 /* get first line of file header */
79 if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) {
80 *err = file_error(wth->fh, err_info);
81 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
82 return WTAP_OPEN_ERROR;
83 return WTAP_OPEN_NOT_MINE;
86 /* check magic text */
87 if (strncmp(readLine, daintree_magic_text, DAINTREE_MAGIC_TEXT_SIZE) != 0)
88 return WTAP_OPEN_NOT_MINE; /* not daintree format */
90 /* read second header line */
91 if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) {
92 *err = file_error(wth->fh, err_info);
93 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
94 return WTAP_OPEN_ERROR;
95 return WTAP_OPEN_NOT_MINE;
97 if (readLine[0] != COMMENT_LINE)
98 return WTAP_OPEN_NOT_MINE; /* daintree files have a two line header */
100 /* set up the pointers to the handlers for this file type */
101 wth->subtype_read = daintree_sna_read;
102 wth->subtype_seek_read = daintree_sna_seek_read;
104 /* set up for file type */
105 wth->file_type_subtype = daintree_sna_file_type_subtype;
106 wth->file_encap = WTAP_ENCAP_IEEE802_15_4_NOFCS;
107 wth->file_tsprec = WTAP_TSPREC_USEC;
108 wth->snapshot_length = 0; /* not available in header */
111 * Add an IDB; we don't know how many interfaces were
112 * involved, so we just say one interface, about which
113 * we only know the link-layer type, snapshot length,
114 * and time stamp resolution.
116 wtap_add_generated_idb(wth);
118 return WTAP_OPEN_MINE; /* it's a Daintree file */
121 /* Read the capture file sequentially
122 * Wireshark scans the file with sequential reads during preview and initial display. */
123 static bool
124 daintree_sna_read(wtap *wth, wtap_rec *rec, Buffer *buf,
125 int *err, char **err_info, int64_t *data_offset)
127 *data_offset = file_tell(wth->fh);
129 /* parse that line and the following packet data */
130 return daintree_sna_read_packet(wth->fh, rec, buf, err, err_info);
133 /* Read the capture file randomly
134 * Wireshark opens the capture file for random access when displaying user-selected packets */
135 static bool
136 daintree_sna_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec,
137 Buffer *buf, int *err, char **err_info)
139 if(file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
140 return false;
142 /* parse that line and the following packet data */
143 return daintree_sna_read_packet(wth->random_fh, rec, buf, err,
144 err_info);
147 /* Read a header line, scan it, and fill in a struct wtap_rec.
148 * Then convert packet data from ASCII hex string to binary in place,
149 * sanity-check its length against what we assume is the packet length field,
150 * and copy it into a Buffer. */
151 static bool
152 daintree_sna_read_packet(FILE_T fh, wtap_rec *rec, Buffer *buf,
153 int *err, char **err_info)
155 uint64_t seconds;
156 int useconds;
157 char readLine[DAINTREE_MAX_LINE_SIZE];
158 char readData[READDATA_BUF_SIZE];
159 unsigned char *str = (unsigned char *)readData;
160 unsigned bytes;
161 uint8_t *p;
163 /* we've only seen file header lines starting with '#', but
164 * if others appear in the file, they are tossed */
165 do {
166 if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, fh) == NULL) {
167 *err = file_error(fh, err_info);
168 return false; /* all done */
170 } while (readLine[0] == COMMENT_LINE);
172 rec->rec_type = REC_TYPE_PACKET;
173 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
174 rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
176 if (sscanf(readLine, "%*s %18" SCNu64 ".%9d %9u %" READDATA_MAX_FIELD_SIZE "s",
177 &seconds, &useconds, &rec->rec_header.packet_header.len, readData) != 4) {
178 *err = WTAP_ERR_BAD_FILE;
179 *err_info = g_strdup("daintree_sna: invalid read record");
180 return false;
183 /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
184 if (rec->rec_header.packet_header.len <= FCS_LENGTH) {
185 *err = WTAP_ERR_BAD_FILE;
186 *err_info = ws_strdup_printf("daintree_sna: packet length <= %u bytes, no frame data present",
187 FCS_LENGTH);
188 return false;
190 rec->rec_header.packet_header.len -= FCS_LENGTH;
192 rec->ts.secs = (time_t) seconds;
193 rec->ts.nsecs = useconds * 1000; /* convert mS to nS */
196 * READDATA_BUF_SIZE is < WTAP_MAX_PACKET_SIZE_STANDARD, and is the maximum
197 * number of bytes of packet data we can generate, so we don't
198 * need to check the packet length.
200 p = str; /* overlay source buffer */
201 bytes = 0;
202 /* convert hex string to uint8_t */
203 while(*str) {
204 /* most significant nibble */
205 if (!g_ascii_isxdigit(*str)) {
206 *err = WTAP_ERR_BAD_FILE;
207 *err_info = g_strdup("daintree_sna: non-hex digit in hex data");
208 return false;
210 if(g_ascii_isdigit(*str)) {
211 *p = (*str - '0') << 4;
212 } else {
213 *p = ((g_ascii_tolower(*str) - 'a') + 10) << 4;
215 str++;
217 /* least significant nibble */
218 if (!g_ascii_isxdigit(*str)) {
219 *err = WTAP_ERR_BAD_FILE;
220 *err_info = g_strdup("daintree_sna: non-hex digit in hex data");
221 return false;
223 if(g_ascii_isdigit(*str)) {
224 *p += *str - '0';
225 } else {
226 *p += (g_ascii_tolower(*str) - 'a') + 10;
228 str++;
230 /* next byte in buffer */
231 p++;
232 bytes++;
235 /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
236 if (bytes <= FCS_LENGTH) {
237 *err = WTAP_ERR_BAD_FILE;
238 *err_info = ws_strdup_printf("daintree_sna: Only %u bytes of packet data",
239 bytes);
240 return false;
242 bytes -= FCS_LENGTH;
243 if (bytes > rec->rec_header.packet_header.len) {
244 *err = WTAP_ERR_BAD_FILE;
245 *err_info = ws_strdup_printf("daintree_sna: capture length (%u) > packet length (%u)",
246 bytes, rec->rec_header.packet_header.len);
247 return false;
250 rec->rec_header.packet_header.caplen = bytes;
252 ws_buffer_assure_space(buf, bytes);
253 memcpy(ws_buffer_start_ptr(buf), readData, bytes);
254 return true;
257 static const struct supported_block_type daintree_sna_blocks_supported[] = {
259 * We support packet blocks, with no comments or other options.
261 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
264 static const struct file_type_subtype_info daintree_sna_info = {
265 "Daintree SNA", "dsna", "dcf", NULL,
266 false, BLOCKS_SUPPORTED(daintree_sna_blocks_supported),
267 NULL, NULL, NULL
270 void register_daintree_sna(void)
272 daintree_sna_file_type_subtype = wtap_register_file_type_subtype(&daintree_sna_info);
275 * Register name for backwards compatibility with the
276 * wtap_filetypes table in Lua.
278 wtap_register_backwards_compatibility_lua_name("DAINTREE_SNA",
279 daintree_sna_file_type_subtype);
283 * Editor modelines - https://www.wireshark.org/tools/modelines.html
285 * Local variables:
286 * c-basic-offset: 8
287 * tab-width: 8
288 * indent-tabs-mode: t
289 * End:
291 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
292 * :indentSize=8:tabSize=8:noTabs=false: