Bug Summary

File:builds/wireshark/wireshark/wiretap/dbs-etherwatch.c
Warning:line 490, column 5
Value stored to 'pd' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dbs-etherwatch.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/libxml2 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D wiretap_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -I /builds/wireshark/wireshark/build/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-04-12-100331-3641-1 -x c /builds/wireshark/wireshark/wiretap/dbs-etherwatch.c
1/* dbs-etherwatch.c
2 *
3 * Wiretap Library
4 * Copyright (c) 2001 by Marc Milgram <[email protected]>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "config.h"
10#include "dbs-etherwatch.h"
11#include "wtap_module.h"
12#include "file_wrappers.h"
13
14#include <stdlib.h>
15#include <string.h>
16
17#include <wsutil/array.h>
18#include <wsutil/pint.h>
19
20/*
21 * DBS Etherwatch (text format)
22 *
23 * Text output from DBS Etherwatch is supported. DBS Etherwatch is available
24 * from: https://web.archive.org/web/20070612033348/http://www.users.bigpond.com/dbsneddon/software.htm.
25*/
26
27/* This module reads the text output of the 'DBS-ETHERTRACE' command in VMS
28 * It was initially based on vms.c.
29 */
30
31/*
32 Example 'ETHERWATCH' output data (with "printable" characters in the
33 "printable characters" section of the output replaced by "." if they have
34 the 8th bit set, so as not to upset compilers that are expecting text
35 in comments to be in a particular character encoding that can't handle
36 those values):
37ETHERWATCH X5-008
3842 names and addresses were loaded
39Reading recorded data from PERSISTENCE
40------------------------------------------------------------------------------
41From 00-D0-C0-D2-4D-60 [MF1] to AA-00-04-00-FC-94 [PSERVB]
42Protocol 08-00 00 00-00-00-00-00, 60 byte buffer at 10-OCT-2001 10:20:45.16
43 [E..<8...........]- 0-[45 00 00 3C 38 93 00 00 1D 06 D2 12 80 93 11 1A]
44 [.........(......]- 16-[80 93 80 D6 02 D2 02 03 00 28 A4 90 00 00 00 00]
45 [................]- 32-[A0 02 FF FF 95 BD 00 00 02 04 05 B4 03 03 04 01]
46 [............ ]- 48-[01 01 08 0A 90 90 E5 14 00 00 00 00]
47------------------------------------------------------------------------------
48From 00-D0-C0-D2-4D-60 [MF1] to AA-00-04-00-FC-94 [PSERVB]
49Protocol 08-00 00 00-00-00-00-00, 50 byte buffer at 10-OCT-2001 10:20:45.17
50 [E..(8......%....]- 0-[45 00 00 28 38 94 00 00 1D 06 D2 25 80 93 11 1A]
51 [.........(..Z.4w]- 16-[80 93 80 D6 02 D2 02 03 00 28 A4 91 5A 1C 34 77]
52 [P.#(.s..........]- 32-[50 10 23 28 C1 73 00 00 02 04 05 B4 03 03 00 00]
53 [.. ]- 48-[02 04]
54
55
56Alternative HEX only output, slightly more efficient and all wireshark needs:
57------------------------------------------------------------------------------
58From 00-D0-C0-D2-4D-60 [MF1] to AA-00-04-00-FC-94 [PSERVB]
59Protocol 08-00 00 00-00-00-00-00, 50 byte buffer at 10-OCT-2001 10:20:45.17
60 0-[45 00 00 28 38 9B 00 00 1D 06 D2 1E 80 93 11 1A 80 93 80 D6]
61 20-[02 D2 02 03 00 28 A4 BF 5A 1C 34 79 50 10 23 28 C1 43 00 00]
62 40-[03 30 30 30 30 30 00 00 03 30]
63 */
64
65/* Magic text to check for DBS-ETHERWATCH-ness of file */
66static const char dbs_etherwatch_hdr_magic[] =
67{ 'E', 'T', 'H', 'E', 'R', 'W', 'A', 'T', 'C', 'H', ' '};
68#define DBS_ETHERWATCH_HDR_MAGIC_SIZE(sizeof (dbs_etherwatch_hdr_magic) / sizeof (dbs_etherwatch_hdr_magic
)[0])
\
69 array_length(dbs_etherwatch_hdr_magic)(sizeof (dbs_etherwatch_hdr_magic) / sizeof (dbs_etherwatch_hdr_magic
)[0])
70
71/* Magic text for start of packet */
72static const char dbs_etherwatch_rec_magic[] =
73{'F', 'r', 'o', 'm', ' '};
74#define DBS_ETHERWATCH_REC_MAGIC_SIZE(sizeof (dbs_etherwatch_rec_magic) / sizeof (dbs_etherwatch_rec_magic
)[0])
\
75 array_length(dbs_etherwatch_rec_magic)(sizeof (dbs_etherwatch_rec_magic) / sizeof (dbs_etherwatch_rec_magic
)[0])
76
77/*
78 * Default packet size - maximum normal Ethernet packet size, without an
79 * FCS.
80 */
81#define DBS_ETHERWATCH_MAX_ETHERNET_PACKET_LEN1514 1514
82
83static bool_Bool dbs_etherwatch_read(wtap *wth, wtap_rec *rec,
84 int *err, char **err_info, int64_t *data_offset);
85static bool_Bool dbs_etherwatch_seek_read(wtap *wth, int64_t seek_off,
86 wtap_rec *rec, int *err, char **err_info);
87static bool_Bool parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
88 int *err, char **err_info);
89static unsigned parse_single_hex_dump_line(char* rec, Buffer *buf,
90 int byte_offset);
91static unsigned parse_hex_dump(char* dump, Buffer *buf, char separator, char end);
92
93static int dbs_etherwatch_file_type_subtype = -1;
94
95void register_dbs_etherwatch(void);
96
97/* Seeks to the beginning of the next packet, and returns the
98 byte offset. Returns -1 on failure, and sets "*err" to the error
99 and "*err_info" to null or an additional error string. */
100static int64_t dbs_etherwatch_seek_next_packet(wtap *wth, int *err,
101 char **err_info)
102{
103 int byte;
104 unsigned int level = 0;
105 int64_t cur_off;
106
107 while ((byte = file_getc(wth->fh)) != EOF(-1)) {
108 if (byte == dbs_etherwatch_rec_magic[level]) {
109 level++;
110 if (level >= DBS_ETHERWATCH_REC_MAGIC_SIZE(sizeof (dbs_etherwatch_rec_magic) / sizeof (dbs_etherwatch_rec_magic
)[0])
) {
111 /* note: we're leaving file pointer right after the magic characters */
112 cur_off = file_tell(wth->fh);
113 if (cur_off == -1) {
114 /* Error. */
115 *err = file_error(wth->fh, err_info);
116 return -1;
117 }
118 return cur_off + 1;
119 }
120 } else {
121 level = 0;
122 }
123 }
124 /* EOF or error. */
125 *err = file_error(wth->fh, err_info);
126 return -1;
127}
128
129#define DBS_ETHERWATCH_HEADER_LINES_TO_CHECK200 200
130#define DBS_ETHERWATCH_LINE_LENGTH240 240
131
132/* Look through the first part of a file to see if this is
133 * a DBS Ethertrace text trace file.
134 *
135 * Returns true if it is, false if it isn't or if we get an I/O error;
136 * if we get an I/O error, "*err" will be set to a non-zero value and
137 * "*err_info" will be set to null or an error string.
138 */
139static bool_Bool dbs_etherwatch_check_file_type(wtap *wth, int *err,
140 char **err_info)
141{
142 char buf[DBS_ETHERWATCH_LINE_LENGTH240];
143 int line, byte;
144 size_t reclen;
145 unsigned int i, level;
146
147 buf[DBS_ETHERWATCH_LINE_LENGTH240-1] = 0;
148
149 for (line = 0; line < DBS_ETHERWATCH_HEADER_LINES_TO_CHECK200; line++) {
150 if (file_gets(buf, DBS_ETHERWATCH_LINE_LENGTH240, wth->fh) == NULL((void*)0)) {
151 /* EOF or error. */
152 *err = file_error(wth->fh, err_info);
153 return false0;
154 }
155
156 reclen = strlen(buf);
157 if (reclen < DBS_ETHERWATCH_HDR_MAGIC_SIZE(sizeof (dbs_etherwatch_hdr_magic) / sizeof (dbs_etherwatch_hdr_magic
)[0])
)
158 continue;
159
160 level = 0;
161 for (i = 0; i < reclen; i++) {
162 byte = buf[i];
163 if (byte == dbs_etherwatch_hdr_magic[level]) {
164 level++;
165 if (level >=
166 DBS_ETHERWATCH_HDR_MAGIC_SIZE(sizeof (dbs_etherwatch_hdr_magic) / sizeof (dbs_etherwatch_hdr_magic
)[0])
) {
167 return true1;
168 }
169 }
170 else
171 level = 0;
172 }
173 }
174 *err = 0;
175 return false0;
176}
177
178
179wtap_open_return_val dbs_etherwatch_open(wtap *wth, int *err, char **err_info)
180{
181 /* Look for DBS ETHERWATCH header */
182 if (!dbs_etherwatch_check_file_type(wth, err, err_info)) {
183 if (*err != 0 && *err != WTAP_ERR_SHORT_READ-12)
184 return WTAP_OPEN_ERROR;
185 return WTAP_OPEN_NOT_MINE;
186 }
187
188 wth->file_encap = WTAP_ENCAP_ETHERNET1;
189 wth->file_type_subtype = dbs_etherwatch_file_type_subtype;
190 wth->snapshot_length = 0; /* not known */
191 wth->subtype_read = dbs_etherwatch_read;
192 wth->subtype_seek_read = dbs_etherwatch_seek_read;
193 wth->file_tsprec = WTAP_TSPREC_10_MSEC2;
194
195 /*
196 * Add an IDB; we don't know how many interfaces were
197 * involved, so we just say one interface, about which
198 * we only know the link-layer type, snapshot length,
199 * and time stamp resolution.
200 */
201 wtap_add_generated_idb(wth);
202
203 return WTAP_OPEN_MINE;
204}
205
206/* Find the next packet and parse it; called from wtap_read(). */
207static bool_Bool dbs_etherwatch_read(wtap *wth, wtap_rec *rec,
208 int *err, char **err_info, int64_t *data_offset)
209{
210 int64_t offset;
211
212 /* Find the next packet */
213 offset = dbs_etherwatch_seek_next_packet(wth, err, err_info);
214 if (offset < 1)
215 return false0;
216 *data_offset = offset;
217
218 /* Parse the packet */
219 return parse_dbs_etherwatch_packet(wth, wth->fh, rec, err, err_info);
220}
221
222/* Used to read packets in random-access fashion */
223static bool_Bool
224dbs_etherwatch_seek_read(wtap *wth, int64_t seek_off,
225 wtap_rec *rec, int *err, char **err_info)
226{
227 if (file_seek(wth->random_fh, seek_off - 1, SEEK_SET0, err) == -1)
228 return false0;
229
230 return parse_dbs_etherwatch_packet(wth, wth->random_fh, rec, err, err_info);
231}
232
233/* Parse a packet */
234/*
235Packet header:
236 1 2 3 4
2370123456789012345678901234567890123456789012345
238From 00-D0-C0-D2-4D-60 [MF1] to AA-00-04-00-FC-94 [PSERVB]
239Protocol 08-00 00 00-00-00-00-00, 50 byte buffer at 10-OCT-2001 10:20:45.17
240*/
241#define MAC_ADDR_LENGTH6 6 /* Length MAC address */
242#define DEST_MAC_PREFIX"] to " "] to " /* Prefix to the dest. MAC address */
243#define PROTOCOL_LENGTH2 2 /* Length protocol */
244#define PROTOCOL_POS9 9 /* Position protocol */
245#define SAP_LENGTH2 2 /* Length DSAP+SSAP */
246#define SAP_POS9 9 /* Position DSAP+SSAP */
247#define CTL_UNNUMB_LENGTH1 1 /* Length unnumbered control field */
248#define CTL_NUMB_LENGTH2 2 /* Length numbered control field */
249#define CTL_POS15 15 /* Position control field */
250#define PID_LENGTH5 5 /* Length PID */
251#define PID_POS18 18 /* Position PID */
252#define LENGTH_POS33 33 /* Position length */
253#define HEX_HDR_SPR'-' '-' /* Separator char header hex values */
254#define HEX_HDR_END' ' ' ' /* End char hdr. hex val. except PID */
255#define HEX_PID_END',' ',' /* End char PID hex value */
256#define IEEE802_LEN_LEN2 2 /* Length of the IEEE 802 len. field */
257/*
258To check whether it is Ethernet II or IEEE 802 we check the values of the
259control field and PID, when they are all 0's we assume it is Ethernet II
260else IEEE 802. In IEEE 802 the DSAP and SSAP are behind protocol, the
261length in the IEEE data we have to construct.
262*/
263#define ETH_II_CHECK_POS15 15
264#define ETH_II_CHECK_STR"00 00-00-00-00-00," "00 00-00-00-00-00,"
265/*
266To check whether it IEEE 802.3 with SNAP we check that both the DSAP & SSAP
267values are 0xAA and the control field 0x03.
268*/
269#define SNAP_CHECK_POS9 9
270#define SNAP_CHECK_STR"AA-AA 03" "AA-AA 03"
271/*
272To check whether the control field is 1 or two octets we check if it is
273unnumbered. Unnumbered has length 1, numbered 2.
274*/
275#define CTL_UNNUMB_MASK0x03 0x03
276#define CTL_UNNUMB_VALUE0x03 0x03
277static bool_Bool
278parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
279 int *err, char **err_info)
280{
281 uint8_t *pd;
282 char line[DBS_ETHERWATCH_LINE_LENGTH240];
283 int num_items_scanned;
284 int pkt_len_signed, csec_signed;
285 unsigned eth_hdr_len, pkt_len, csec;
286 unsigned length_pos, length_from, length;
287 struct tm tm;
288 char mon[4] = "xxx";
289 char *p;
290 static const char months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
291 unsigned count, line_count;
292
293 /* Make sure we have enough room for a regular Ethernet packet */
294 ws_buffer_assure_space(&rec->data, DBS_ETHERWATCH_MAX_ETHERNET_PACKET_LEN1514);
295 pd = ws_buffer_start_ptr(&rec->data);
296
297 eth_hdr_len = 0;
298 memset(&tm, 0, sizeof(tm));
299 /* Our file pointer should be on the first line containing the
300 * summary information for a packet. Read in that line and
301 * extract the useful information
302 */
303 if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH240, fh) == NULL((void*)0)) {
304 *err = file_error(fh, err_info);
305 if (*err == 0) {
306 *err = WTAP_ERR_SHORT_READ-12;
307 }
308 return false0;
309 }
310
311 /* Get the destination address */
312 p = strstr(line, DEST_MAC_PREFIX"] to ");
313 if(!p) {
314 *err = WTAP_ERR_BAD_FILE-13;
315 *err_info = g_strdup("dbs_etherwatch: destination address not found")g_strdup_inline ("dbs_etherwatch: destination address not found"
)
;
316 return false0;
317 }
318 p += strlen(DEST_MAC_PREFIX"] to ");
319 if(parse_hex_dump(p, &rec->data, HEX_HDR_SPR'-', HEX_HDR_END' ')
320 != MAC_ADDR_LENGTH6) {
321 *err = WTAP_ERR_BAD_FILE-13;
322 *err_info = g_strdup("dbs_etherwatch: destination address not valid")g_strdup_inline ("dbs_etherwatch: destination address not valid"
)
;
323 return false0;
324 }
325 eth_hdr_len += MAC_ADDR_LENGTH6;
326
327 /* Get the source address */
328 /*
329 * Since the first part of the line is already skipped in order to find
330 * the start of the record we cannot index, just look for the first
331 * 'HEX' character
332 */
333 p = line;
334 while(!g_ascii_isxdigit(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_XDIGIT) != 0)) {
335 p++;
336 }
337 if(parse_hex_dump(p, &rec->data, HEX_HDR_SPR'-',
338 HEX_HDR_END' ') != MAC_ADDR_LENGTH6) {
339 *err = WTAP_ERR_BAD_FILE-13;
340 *err_info = g_strdup("dbs_etherwatch: source address not valid")g_strdup_inline ("dbs_etherwatch: source address not valid");
341 return false0;
342 }
343 eth_hdr_len += MAC_ADDR_LENGTH6;
344
345 /* Read the next line of the record header */
346 if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH240, fh) == NULL((void*)0)) {
347 *err = file_error(fh, err_info);
348 if (*err == 0) {
349 *err = WTAP_ERR_SHORT_READ-12;
350 }
351 return false0;
352 }
353
354 /* Check the lines is as least as long as the length position */
355 if(strlen(line) < LENGTH_POS33) {
356 *err = WTAP_ERR_BAD_FILE-13;
357 *err_info = g_strdup("dbs_etherwatch: line too short")g_strdup_inline ("dbs_etherwatch: line too short");
358 return false0;
359 }
360
361 /*
362 * %u doesn't fail if the value has a sign; it works like the
363 * strto*() routines.
364 *
365 * Use %d, scan into signed values, and then check whether they're
366 * < 0.
367 */
368 num_items_scanned = sscanf(line + LENGTH_POS33,
369 "%9d byte buffer at %2d-%3s-%4d %2d:%2d:%2d.%9d",
370 &pkt_len_signed,
371 &tm.tm_mday, mon,
372 &tm.tm_year, &tm.tm_hour, &tm.tm_min,
373 &tm.tm_sec, &csec_signed);
374
375 if (num_items_scanned != 8) {
376 *err = WTAP_ERR_BAD_FILE-13;
377 *err_info = g_strdup("dbs_etherwatch: header line not valid")g_strdup_inline ("dbs_etherwatch: header line not valid");
378 return false0;
379 }
380
381 if (pkt_len_signed < 0) {
382 *err = WTAP_ERR_BAD_FILE-13;
383 *err_info = g_strdup("dbs_etherwatch: packet header has a negative packet length")g_strdup_inline ("dbs_etherwatch: packet header has a negative packet length"
)
;
384 return false0;
385 }
386
387 if (csec_signed < 0) {
388 *err = WTAP_ERR_BAD_FILE-13;
389 *err_info = g_strdup("dbs_etherwatch: packet header has a negative microseconds time stamp")g_strdup_inline ("dbs_etherwatch: packet header has a negative microseconds time stamp"
)
;
390 return false0;
391 }
392
393 pkt_len = (unsigned) pkt_len_signed;
394 csec = (unsigned) csec_signed;
395
396 /* Determine whether it is Ethernet II or IEEE 802 */
397 if(strncmp(&line[ETH_II_CHECK_POS15], ETH_II_CHECK_STR"00 00-00-00-00-00,",
398 strlen(ETH_II_CHECK_STR"00 00-00-00-00-00,")) == 0) {
399 /* Ethernet II */
400 /* Get the Protocol */
401 if(parse_hex_dump(&line[PROTOCOL_POS9], &rec->data, HEX_HDR_SPR'-',
402 HEX_HDR_END' ') != PROTOCOL_LENGTH2) {
403 *err = WTAP_ERR_BAD_FILE-13;
404 *err_info = g_strdup("dbs_etherwatch: Ethernet II protocol value not valid")g_strdup_inline ("dbs_etherwatch: Ethernet II protocol value not valid"
)
;
405 return false0;
406 }
407 eth_hdr_len += PROTOCOL_LENGTH2;
408 } else {
409 /* IEEE 802 */
410 /* Remember where to put the length in the header */
411 length_pos = eth_hdr_len;
412 /* Leave room in the header for the length */
413 eth_hdr_len += IEEE802_LEN_LEN2;
414 /* Remember how much of the header should not be added to the length */
415 length_from = eth_hdr_len;
416 /* Get the DSAP + SSAP */
417 if(parse_hex_dump(&line[SAP_POS9], &rec->data, HEX_HDR_SPR'-',
418 HEX_HDR_END' ') != SAP_LENGTH2) {
419 *err = WTAP_ERR_BAD_FILE-13;
420 *err_info = g_strdup("dbs_etherwatch: 802.2 DSAP+SSAP value not valid")g_strdup_inline ("dbs_etherwatch: 802.2 DSAP+SSAP value not valid"
)
;
421 return false0;
422 }
423 eth_hdr_len += SAP_LENGTH2;
424 /* Get the (first part of the) control field */
425 if(parse_hex_dump(&line[CTL_POS15], &rec->data, HEX_HDR_SPR'-',
426 HEX_HDR_END' ') != CTL_UNNUMB_LENGTH1) {
427 *err = WTAP_ERR_BAD_FILE-13;
428 *err_info = g_strdup("dbs_etherwatch: 802.2 control field first part not valid")g_strdup_inline ("dbs_etherwatch: 802.2 control field first part not valid"
)
;
429 return false0;
430 }
431 /* Determine whether the control is numbered, and thus longer */
432 if((pd[eth_hdr_len] & CTL_UNNUMB_MASK0x03) != CTL_UNNUMB_VALUE0x03) {
433 /* Get the rest of the control field, the first octet in the PID */
434 if(parse_hex_dump(&line[PID_POS18], &rec->data, HEX_HDR_END' ',
435 HEX_HDR_SPR'-') != CTL_NUMB_LENGTH2 - CTL_UNNUMB_LENGTH1) {
436 *err = WTAP_ERR_BAD_FILE-13;
437 *err_info = g_strdup("dbs_etherwatch: 802.2 control field second part value not valid")g_strdup_inline ("dbs_etherwatch: 802.2 control field second part value not valid"
)
;
438 return false0;
439 }
440 eth_hdr_len += CTL_NUMB_LENGTH2;
441 } else {
442 eth_hdr_len += CTL_UNNUMB_LENGTH1;
443 }
444 /* Determine whether it is SNAP */
445 if(strncmp(&line[SNAP_CHECK_POS9], SNAP_CHECK_STR"AA-AA 03",
446 strlen(SNAP_CHECK_STR"AA-AA 03")) == 0) {
447 /* Get the PID */
448 if(parse_hex_dump(&line[PID_POS18], &rec->data, HEX_HDR_SPR'-',
449 HEX_PID_END',') != PID_LENGTH5) {
450 *err = WTAP_ERR_BAD_FILE-13;
451 *err_info = g_strdup("dbs_etherwatch: 802.2 PID value not valid")g_strdup_inline ("dbs_etherwatch: 802.2 PID value not valid");
452 return false0;
453 }
454 eth_hdr_len += PID_LENGTH5;
455 }
456 /* Write the length in the header */
457 length = (eth_hdr_len - length_from) + pkt_len;
458 phtonu16(&pd[length_pos], length);
459 }
460
461 wtap_setup_packet_rec(rec, wth->file_encap);
462 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
463 rec->presence_flags = WTAP_HAS_TS0x00000001|WTAP_HAS_CAP_LEN0x00000002;
464
465 p = strstr(months, mon);
466 if (p)
467 tm.tm_mon = (int)(p - months) / 3;
468 tm.tm_year -= 1900;
469
470 tm.tm_isdst = -1;
471 rec->ts.secs = mktime(&tm);
472 rec->ts.nsecs = csec * 10000000;
473 rec->rec_header.packet_header.caplen = eth_hdr_len + pkt_len;
474 rec->rec_header.packet_header.len = eth_hdr_len + pkt_len;
475
476 if (rec->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD262144U) {
477 /*
478 * Probably a corrupt capture file; return an error,
479 * so that our caller doesn't blow up trying to allocate
480 * space for an immensely-large packet.
481 */
482 *err = WTAP_ERR_BAD_FILE-13;
483 *err_info = ws_strdup_printf("dbs_etherwatch: File has %u-byte packet, bigger than maximum of %u",wmem_strdup_printf(((void*)0), "dbs_etherwatch: File has %u-byte packet, bigger than maximum of %u"
, rec->rec_header.packet_header.caplen, 262144U)
484 rec->rec_header.packet_header.caplen, WTAP_MAX_PACKET_SIZE_STANDARD)wmem_strdup_printf(((void*)0), "dbs_etherwatch: File has %u-byte packet, bigger than maximum of %u"
, rec->rec_header.packet_header.caplen, 262144U)
;
485 return false0;
486 }
487
488 /* Make sure we have enough room, even for an oversized Ethernet packet */
489 ws_buffer_assure_space(&rec->data, rec->rec_header.packet_header.caplen);
490 pd = ws_buffer_start_ptr(&rec->data);
Value stored to 'pd' is never read
491
492 /*
493 * We don't have an FCS in this frame.
494 */
495 rec->rec_header.packet_header.pseudo_header.eth.fcs_len = 0;
496
497 /* Parse the hex dump */
498 count = 0;
499 while (count < pkt_len) {
500 if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH240, fh) == NULL((void*)0)) {
501 *err = file_error(fh, err_info);
502 if (*err == 0) {
503 *err = WTAP_ERR_SHORT_READ-12;
504 }
505 return false0;
506 }
507 if (!(line_count = parse_single_hex_dump_line(line,
508 &rec->data, count))) {
509 *err = WTAP_ERR_BAD_FILE-13;
510 *err_info = g_strdup("dbs_etherwatch: packet data value not valid")g_strdup_inline ("dbs_etherwatch: packet data value not valid"
)
;
511 return false0;
512 }
513 count += line_count;
514 if (count > pkt_len) {
515 *err = WTAP_ERR_BAD_FILE-13;
516 *err_info = g_strdup("dbs_etherwatch: packet data value has too many bytes")g_strdup_inline ("dbs_etherwatch: packet data value has too many bytes"
)
;
517 return false0;
518 }
519 }
520 return true1;
521}
522
523/* Parse a hex dump line */
524/*
525/DISPLAY=BOTH output:
526
527 1 2 3 4
5280123456789012345678901234567890123456789012345
529 [E..(8...........]- 0-[45 00 00 28 38 9B 00 00 1D 06 D2 1E 80 93 11 1A]
530 [.........(..Z.4y]- 16-[80 93 80 D6 02 D2 02 03 00 28 A4 BF 5A 1C 34 79]
531 [P.#(.C...00000..]- 32-[50 10 23 28 C1 43 00 00 03 30 30 30 30 30 00 00]
532 [.0 ]- 48-[03 30]
533
534/DISPLAY=HEXADECIMAL output:
535
536 1 2 3 4
5370123456789012345678901234567890123456789012345
538 0-[45 00 00 28 38 9B 00 00 1D 06 D2 1E 80 93 11 1A 80 93 80 D6]
539 20-[02 D2 02 03 00 28 A4 BF 5A 1C 34 79 50 10 23 28 C1 43 00 00]
540 40-[03 30 30 30 30 30 00 00 03 30]
541
542*/
543
544#define TYPE_CHECK_POS2 2 /* Position to check the type of hex dump */
545#define TYPE_CHECK_BOTH'[' '[' /* Value at pos. that indicates BOTH type */
546#define COUNT_POS_BOTH21 21 /* Count position BOTH type */
547#define COUNT_POS_HEX1 1 /* Count position HEX type */
548#define COUNT_SIZE5 5 /* Length counter */
549#define HEX_DUMP_START'[' '[' /* Start char */
550#define HEX_DUMP_SPR' ' ' ' /* Separator char */
551#define HEX_DUMP_END']' ']' /* End char */
552
553/* Take a string representing one line from a hex dump and converts the
554 * text to binary data. We check the printed offset with the offset
555 * we are passed to validate the record. We place the bytes in the buffer
556 * at the specified offset.
557 *
558 * Returns length parsed if a good hex dump, 0 if bad.
559 */
560static unsigned
561parse_single_hex_dump_line(char* rec, Buffer *buf, int byte_offset) {
562
563 int pos, i;
564 int value;
565
566
567 /* Check that the record is as least as long as the check offset */
568 for(i = 0; i < TYPE_CHECK_POS2; i++)
569 {
570 if(rec[i] == '\0') {
571 return 0;
572 }
573 }
574 /* determine the format and thus the counter offset and hex dump length */
575 if(rec[TYPE_CHECK_POS2] == TYPE_CHECK_BOTH'[')
576 {
577 pos = COUNT_POS_BOTH21;
578 }
579 else
580 {
581 pos = COUNT_POS_HEX1;
582 }
583
584 /* Check that the record is as least as long as the start position */
585 while(i < pos)
586 {
587 if(rec[i] == '\0') {
588 return 0;
589 }
590 i++;
591 }
592
593 /* Get the byte_offset directly from the record */
594 value = 0;
595 for(i = 0; i < COUNT_SIZE5; i++) {
596 if(!g_ascii_isspace(rec[pos])((g_ascii_table[(guchar) (rec[pos])] & G_ASCII_SPACE) != 0
)
) {
597 if(g_ascii_isdigit(rec[pos])((g_ascii_table[(guchar) (rec[pos])] & G_ASCII_DIGIT) != 0
)
) {
598 value *= 10;
599 value += rec[pos] - '0';
600 } else {
601 return 0;
602 }
603 }
604 pos++;
605 }
606
607 if (value != byte_offset) {
608 return 0;
609 }
610
611 /* find the start of the hex dump */
612 while(rec[pos] != HEX_DUMP_START'[') {
613 if(rec[pos] == '\0') {
614 return 0;
615 }
616 pos++;
617 }
618 pos++;
619 return parse_hex_dump(&rec[pos], buf, HEX_DUMP_SPR' ', HEX_DUMP_END']');
620}
621
622/* Parse a hex dump */
623static unsigned
624parse_hex_dump(char* dump, Buffer *buf, char separator, char end) {
625 int pos, count;
626
627 /* Parse the hex dump */
628 pos = 0;
629 count = 0;
630 uint8_t *pd = ws_buffer_end_ptr(buf);
631 while(dump[pos] != end) {
632 /* Check the hex value */
633 if(!(g_ascii_isxdigit(dump[pos])((g_ascii_table[(guchar) (dump[pos])] & G_ASCII_XDIGIT) !=
0)
&&
634 g_ascii_isxdigit(dump[pos + 1])((g_ascii_table[(guchar) (dump[pos + 1])] & G_ASCII_XDIGIT
) != 0)
)) {
635 return 0;
636 }
637 /* Get the hex value */
638 if(g_ascii_isdigit(dump[pos])((g_ascii_table[(guchar) (dump[pos])] & G_ASCII_DIGIT) !=
0)
) {
639 pd[count] = (dump[pos] - '0') << 4;
640 } else {
641 pd[count] = (g_ascii_toupper(dump[pos]) - 'A' + 10) << 4;
642 }
643 pos++;
644 if(g_ascii_isdigit(dump[pos])((g_ascii_table[(guchar) (dump[pos])] & G_ASCII_DIGIT) !=
0)
) {
645 pd[count] += dump[pos] - '0';
646 } else {
647 pd[count] += g_ascii_toupper(dump[pos]) - 'A' + 10;
648 }
649 pos++;
650 count++;
651 /* Skip the separator characters */
652 while(dump[pos] == separator) {
653 pos++;
654 }
655 }
656 ws_buffer_increase_length(buf, count);
657 return count;
658}
659
660static const struct supported_block_type dbs_etherwatch_blocks_supported[] = {
661 /*
662 * We support packet blocks, with no comments or other options.
663 */
664 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED0, ((void*)0) }
665};
666
667static const struct file_type_subtype_info dbs_etherwatch_info = {
668 "DBS Etherwatch (VMS)", "etherwatch", "txt", NULL((void*)0),
669 false0, BLOCKS_SUPPORTED(dbs_etherwatch_blocks_supported)(sizeof (dbs_etherwatch_blocks_supported) / sizeof (dbs_etherwatch_blocks_supported
)[0]), dbs_etherwatch_blocks_supported
,
670 NULL((void*)0), NULL((void*)0), NULL((void*)0)
671};
672
673void register_dbs_etherwatch(void)
674{
675 dbs_etherwatch_file_type_subtype = wtap_register_file_type_subtype(&dbs_etherwatch_info);
676
677 /*
678 * Register name for backwards compatibility with the
679 * wtap_filetypes table in Lua.
680 */
681 wtap_register_backwards_compatibility_lua_name("DBS_ETHERWATCH",
682 dbs_etherwatch_file_type_subtype);
683}
684
685/*
686 * Editor modelines - https://www.wireshark.org/tools/modelines.html
687 *
688 * Local variables:
689 * c-basic-offset: 4
690 * tab-width: 8
691 * indent-tabs-mode: nil
692 * End:
693 *
694 * vi: set shiftwidth=4 tabstop=8 expandtab:
695 * :indentSize=4:tabSize=8:noTabs=true:
696 */