### Bug Summary

File: | epan/dissectors/packet-tpncp.c
Warning: | line 435, column 10 File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

### Annotated Source Code

Press '?' to see keyboard shortcuts

Show analyzer invocation
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 packet-tpncp.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 /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -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-01-12-100401-3603-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-tpncp.c

Keyboard shortcuts:

- Use 'j/k' keys for keyboard navigation
- Use 'Shift+S' to show/hide relevant lines
- Use '?' to toggle this window

Close
Show only relevant lines Show control flow arrows

1 | /* packet-tpncp.c
2 | * Routines for Audiocodes TrunkPack Network Control Protocol (TPNCP) dissection
3 | *
4 | * Copyright (c) 2007 by Valery Sigalov <valery.sigalov@audiocodes.com>
5 | *
6 | * Wireshark - Network traffic analyzer
7 | * By Gerald Combs <gerald@wireshark.com>
8 | * Copyright 1998 Gerald Combs
9 | *
10 | * SPDX-License-Identifier: GPL-2.0-or-later
11 | */
12 |
13 | /*---------------------------------------------------------------------------*/
14 |
15 | #define WS_LOG_DOMAIN"TPNCP" "TPNCP"
16 | #include "config.h"
17 |
18 | #include <epan/packet.h>
19 | #include <epan/exceptions.h>
20 | #include <epan/expert.h>
21 | #include <epan/prefs.h>
22 | #include <wsutil/filesystem.h>
23 | #include <wsutil/file_util.h>
24 | #include <wsutil/report_message.h>
25 | #include <wsutil/strtoi.h>
26 | #include <epan/wmem_scopes.h>
27 | #include "packet-acdr.h"
28 | #include "packet-tcp.h"
29 |
30 | /*---------------------------------------------------------------------------*/
31 |
32 | #define BASE_TPNCP_PORT2424 2424
33 | #define HA_PORT_TPNCP_TRUNKPACK2442 2442
34 | #define TCP_PORT_TPNCP_TRUNKPACK2424 BASE_TPNCP_PORT2424
35 | #define UDP_PORT_TPNCP_TRUNKPACK2424 BASE_TPNCP_PORT2424
36 | #define TCP_PORT_TPNCP_HOST2424 BASE_TPNCP_PORT2424
37 | #define UDP_PORT_TPNCP_HOST2424 BASE_TPNCP_PORT2424
38 |
39 | #define MAX_TPNCP_DB_ENTRY_LEN3000 3000
40 |
41 | /*---------------------------------------------------------------------------*/
42 |
43 | void proto_register_tpncp(void);
44 | void proto_reg_handoff_tpncp(void);
45 |
46 | enum SpecialFieldType {
47 | TPNCP_NORMAL,
48 | TPNCP_ADDRESS_FAMILY,
49 | TPNCP_IP_ADDR,
50 | TPNCP_OPEN_CHANNEL_START,
51 | TPNCP_SECURITY_START,
52 | TPNCP_SECURITY_OFFSET,
53 | RTP_STATE_START,
54 | RTP_STATE_OFFSET,
55 | RTP_STATE_END,
56 | TPNCP_CHANNEL_CONFIGURATION
57 | };
58 |
59 | /* The linked list for storing information about specific data fields. */
60 | typedef struct tpncp_data_field_info
61 | {
62 | char *name;
63 | int descr;
64 | int ipv6_descr;
65 | int array_dim;
66 | enum SpecialFieldType special_type;
67 | unsigned char size;
68 | unsigned char sign;
69 | int since;
70 | struct tpncp_data_field_info *p_next;
71 | } tpncp_data_field_info;
72 |
73 | /*---------------------------------------------------------------------------
74 | * Desegmentation of TPNCP over TCP */
75 | static bool_Bool tpncp_desegment = true1;
76 |
77 | /* Database for storing information about all TPNCP events. */
78 | static tpncp_data_field_info **tpncp_events_info_db;
79 | unsigned tpncp_events_info_len;
80 |
81 | /* Database for storing information about all TPNCP commands. */
82 | static tpncp_data_field_info **tpncp_commands_info_db;
83 | unsigned tpncp_commands_info_len;
84 |
85 | /* Global variables for bitfields representation. */
86 | /* TPNCP packet header fields. */
87 | static int proto_tpncp;
88 | static int hf_tpncp_version;
89 | static int hf_tpncp_length;
90 | static int hf_tpncp_seq_number;
91 | static int hf_tpncp_length_ext;
92 | static int hf_tpncp_reserved;
93 | static int hf_tpncp_command_id;
94 | static int hf_tpncp_event_id;
95 | static int hf_tpncp_cid;
96 |
97 | static expert_field ei_tpncp_unknown_data;
98 |
99 | /* TPNCP fields defining a subtree. */
100 | static int ett_tpncp;
101 | static int ett_tpncp_body;
102 |
103 | static bool_Bool global_tpncp_load_db;
104 | static const char *tpncp_dat_path = NULL((void*)0);
105 |
106 | static dissector_handle_t tpncp_handle;
107 | static dissector_handle_t tpncp_tcp_handle;
108 |
109 | /* TODO: Runtime value_string_ext arrays should be used*/
110 | static value_string *tpncp_commands_id_vals;
111 | static value_string *tpncp_events_id_vals;
112 | static value_string **tpncp_enums_id_vals;
113 | static char **tpncp_enums_name_vals;
114 |
115 | static int hf_size;
116 | static int hf_allocated;
117 | static hf_register_info *hf;
118 |
119 | static bool_Bool db_initialized;
120 |
121 | /*---------------------------------------------------------------------------*/
122 |
123 | enum AddressFamily {
124 | TPNCP_IPV4 = 2,
125 | TPNCP_IPV6 = 10,
126 | TPNCP_IPV6_PSOS = 28
127 | };
128 |
129 | static void
130 | dissect_tpncp_data(unsigned data_id, packet_info *pinfo, tvbuff_t *tvb, proto_tree *ltree,
131 | int *offset, tpncp_data_field_info **data_fields_info, int ver, unsigned encoding)
132 | {
133 | int g_str_len;
134 | tpncp_data_field_info *field = NULL((void*)0);
135 | int bitindex = encoding == ENC_LITTLE_ENDIAN0x80000000 ? 7 : 0;
136 | enum AddressFamily address_family = TPNCP_IPV4;
137 | int open_channel_start = -1, security_offset = 0, rtp_state_offset = 0;
138 | int channel_b_offset = 0, rtp_tx_state_offset = 0, rtp_state_size = 0;
139 | const int initial_offset = *offset;
140 |
141 | for (field = data_fields_info[data_id]; field; field = field->p_next) {
142 | if (field->since > 0 && field->since > ver)
143 | continue;
144 | switch (field->special_type) {
145 | case TPNCP_OPEN_CHANNEL_START:
146 | open_channel_start = *offset;
147 | break;
148 | case TPNCP_SECURITY_OFFSET: {
149 | const uint32_t sec_offset = tvb_get_uint32(tvb, *offset, encoding);
150 | if (sec_offset > 0 && open_channel_start >= 0)
151 | security_offset = open_channel_start + sec_offset;
152 | break;
153 | }
154 | case TPNCP_SECURITY_START:
155 | *offset = security_offset;
156 | open_channel_start = -1;
157 | security_offset = 0;
158 | break;
159 | case RTP_STATE_OFFSET:
160 | rtp_state_offset = tvb_get_int32(tvb, *offset, encoding);
161 | if (rtp_state_offset > 0)
162 | rtp_state_offset += initial_offset + 4; /* The offset starts after CID */
163 | break;
164 | case RTP_STATE_START:
165 | *offset = rtp_state_offset;
166 | rtp_state_offset = 0;
167 | if (rtp_tx_state_offset == 0) {
168 | rtp_state_size = (tvb_reported_length_remaining(tvb, *offset) - 4) / 2;
169 | rtp_tx_state_offset = *offset + rtp_state_size;
170 | } else {
171 | *offset = rtp_tx_state_offset;
172 | rtp_tx_state_offset += rtp_state_size;
173 | }
174 | break;
175 | case RTP_STATE_END:
176 | rtp_tx_state_offset = 0;
177 | break;
178 | case TPNCP_CHANNEL_CONFIGURATION:
179 | if (channel_b_offset == 0) {
180 | int channel_configuration_size = tvb_reported_length_remaining(tvb, *offset) / 2;
181 | channel_b_offset = *offset + channel_configuration_size;
182 | } else {
183 | *offset = channel_b_offset;
184 | channel_b_offset = 0;
185 | }
186 | break;
187 | case TPNCP_ADDRESS_FAMILY:
188 | address_family = (enum AddressFamily)tvb_get_uint32(tvb, *offset, encoding);
189 | // fall-through
190 | default:
191 | if (open_channel_start != -1 && security_offset > 0 && *offset >= security_offset)
192 | continue;
193 | if (rtp_state_offset > 0 && *offset >= rtp_state_offset)
194 | continue;
195 | if (rtp_tx_state_offset > 0 && *offset >= rtp_tx_state_offset)
196 | continue;
197 | if (channel_b_offset > 0 && *offset >= channel_b_offset)
198 | continue;
199 | break;
200 | }
201 | switch (field->size) {
202 | case 1: case 2: case 3: case 4:
203 | case 5: case 6: case 7: case 8:
204 | /* add char array */
205 | if ((g_str_len = field->array_dim)) {
206 | g_str_len = MIN(g_str_len, tvb_reported_length_remaining(tvb, *offset))(((g_str_len) < (tvb_reported_length_remaining(tvb, *offset ))) ? (g_str_len) : (tvb_reported_length_remaining(tvb, *offset )));
207 | proto_tree_add_item(ltree, field->descr, tvb, *offset, g_str_len, ENC_NA0x00000000 | ENC_ASCII0x00000000);
208 | (*offset) += g_str_len;
209 | } else { /* add single char */
210 | /* Output only the numeric value for 8-bit fields, considering sign, with no extra formatting. */
211 | if (field->size == 8) {
212 | uint8_t g_uchar = tvb_get_uint8(tvb, *offset);
213 | if (field->sign)
214 | proto_tree_add_uint(ltree, field->descr, tvb, *offset, 1, g_uchar);
215 | else
216 | proto_tree_add_int(ltree, field->descr, tvb, *offset, 1, (int8_t)g_uchar);
217 | (*offset)++;
218 | } else { /* unsigned bitfield <8 */
219 | unsigned bit_offset;
220 |
221 | /*
222 | * tpncp.dat always lists bitfields in little-endian (LSB-first) order, regardless of encoding.
223 | * Wireshark's proto_tree_add_bits_item with ENC_LITTLE_ENDIAN matches this order.
224 | *
225 | * Therefore, we always use ENC_LITTLE_ENDIAN for bitfield extraction, regardless of the packet encoding.
226 | *
227 | * bit_offset is simply (*offset) * 8 + bitindex, and bitindex increments by field->size.
228 | */
229 | bit_offset = (*offset) * 8 + bitindex;
230 | proto_tree_add_bits_item(ltree, field->descr, tvb, bit_offset, field->size, ENC_LITTLE_ENDIAN0x80000000);
231 |
232 | bitindex += field->size;
233 | (*offset) += bitindex / 8;
234 | bitindex %= 8;
235 | }
236 | }
237 | break;
238 | case 16:
239 | proto_tree_add_item(ltree, field->descr, tvb, *offset, 2, encoding);
240 | (*offset) += 2;
241 | break;
242 | case 32:
243 | proto_tree_add_item(ltree, field->descr, tvb, *offset, 4, encoding);
244 | (*offset) += 4;
245 | break;
246 | case 64:
247 | proto_tree_add_item(ltree, field->descr, tvb, *offset, 8, encoding);
248 | (*offset) += 8;
249 | break;
250 | case 128:
251 | if (field->special_type == TPNCP_IP_ADDR) {
252 | if (address_family == TPNCP_IPV6 || address_family == TPNCP_IPV6_PSOS)
253 | proto_tree_add_item(ltree, field->ipv6_descr, tvb, *offset, 16, encoding);
254 | else
255 | proto_tree_add_item(ltree, field->descr, tvb, *offset, 4, encoding);
256 | address_family = TPNCP_IPV4;
257 | }
258 | (*offset) += 16;
259 | break;
260 | default:
261 | break;
262 | }
263 | if (tvb_reported_length_remaining(tvb, *offset) <= 0)
264 | break;
265 | }
266 | if ((g_str_len = tvb_reported_length_remaining(tvb, *offset)) > 0) {
267 | expert_add_info_format(pinfo, ltree, &ei_tpncp_unknown_data, "TPNCP Unknown Data");
268 | (*offset) += g_str_len;
269 | }
270 | }
271 |
272 | /*---------------------------------------------------------------------------*/
273 | static int
274 | dissect_tpncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
275 | {
276 | proto_item *item = NULL((void*)0);
277 | proto_tree *tpncp_tree = NULL((void*)0), *event_tree, *command_tree;
278 | int offset = 0, cid = -1;
279 | unsigned id;
280 | unsigned seq_number, len, ver;
281 | unsigned len_ext, reserved, encoding;
282 | uint32_t fullLength;
283 |
284 | if (!db_initialized)
285 | return 0;
286 |
287 | encoding = tvb_get_ntohs(tvb, 8) == 0 ? ENC_BIG_ENDIAN0x00000000 : ENC_LITTLE_ENDIAN0x80000000;
288 |
289 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPNCP");
290 |
291 | item = proto_tree_add_item(tree, proto_tpncp, tvb, 0, -1, ENC_NA0x00000000);
292 | tpncp_tree = proto_item_add_subtree(item, ett_tpncp);
293 |
294 | proto_tree_add_item_ret_uint(tpncp_tree, hf_tpncp_version, tvb, 0, 2, encoding, &ver);
295 | proto_tree_add_item_ret_uint(tpncp_tree, hf_tpncp_length, tvb, 2, 2, encoding, &len);
296 | proto_tree_add_item_ret_uint(tpncp_tree, hf_tpncp_seq_number, tvb, 4, 2, encoding, &seq_number);
297 | proto_tree_add_item_ret_uint(tpncp_tree, hf_tpncp_length_ext, tvb, 6, 1, encoding, &len_ext);
298 | proto_tree_add_item_ret_uint(tpncp_tree, hf_tpncp_reserved, tvb, 7, 1, encoding, &reserved);
299 | fullLength = 0xffff * len_ext + len;
300 |
301 | id = tvb_get_uint32(tvb, 8, encoding);
302 | if (len > 8)
303 | cid = tvb_get_int32(tvb, 12, encoding);
304 | if (pinfo->srcport == UDP_PORT_TPNCP_TRUNKPACK2424 ||
305 | pinfo->srcport == HA_PORT_TPNCP_TRUNKPACK2442) {
306 | if (try_val_to_str(id, tpncp_events_id_vals)) {
307 | proto_tree_add_uint(tpncp_tree, hf_tpncp_event_id, tvb, 8, 4, id);
308 | if (len > 8)
309 | proto_tree_add_int(tpncp_tree, hf_tpncp_cid, tvb, 12, 4, cid);
310 | offset += 16;
311 | if (id < tpncp_events_info_len && tpncp_events_info_db[id] != NULL((void*)0) && len > 12) {
312 | event_tree = proto_tree_add_subtree_format(
313 | tree, tvb, offset, -1, ett_tpncp_body, NULL((void*)0),
314 | "TPNCP Event: %s (%d)",
315 | val_to_str_const(id, tpncp_events_id_vals, "Unknown"), id);
316 | dissect_tpncp_data(id, pinfo, tvb, event_tree, &offset, tpncp_events_info_db,
317 | ver, encoding);
318 | }
319 | }
320 | col_add_fstr(pinfo->cinfo, COL_INFO,
321 | "EvID=%s(%d), SeqNo=%d, CID=%d, Len=%d, Ver=%d",
322 | val_to_str_const(id, tpncp_events_id_vals, "Unknown"),
323 | id, seq_number, cid, fullLength, ver);
324 | } else {
325 | if (try_val_to_str(id, tpncp_commands_id_vals)) {
326 | proto_tree_add_uint(tpncp_tree, hf_tpncp_command_id, tvb, 8, 4, id);
327 | offset += 12;
328 | if (id < tpncp_commands_info_len && tpncp_commands_info_db[id] != NULL((void*)0) && len > 8) {
329 | command_tree = proto_tree_add_subtree_format(
330 | tree, tvb, offset, -1, ett_tpncp_body, NULL((void*)0),
331 | "TPNCP Command: %s (%d)",
332 | val_to_str_const(id, tpncp_commands_id_vals, "Unknown"), id);
333 | dissect_tpncp_data(id, pinfo, tvb, command_tree, &offset, tpncp_commands_info_db,
334 | ver, encoding);
335 | }
336 | }
337 | col_add_fstr(pinfo->cinfo, COL_INFO,
338 | "CmdID=%s(%d), SeqNo=%d, CID=%d, Len=%d, Ver=%d",
339 | val_to_str_const(id, tpncp_commands_id_vals, "Unknown"),
340 | id, seq_number, cid, fullLength, ver);
341 | }
342 |
343 | return tvb_reported_length(tvb);
344 | }
345 |
346 | /*---------------------------------------------------------------------------*/
347 |
348 | static unsigned
349 | get_tpncp_pdu_len(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
350 | {
351 | uint32_t plen;
352 |
353 | /* Get the length of the TPNCP packet. */
354 | plen = tvb_get_ntohs(tvb, offset + 2) + 0xffff * tvb_get_uint8(tvb, offset + 6);
355 |
356 | /* Length does not include the version+length field. */
357 | plen += 4;
358 |
359 | return plen;
360 | }
361 |
362 | /*---------------------------------------------------------------------------*/
363 |
364 | static int
365 | dissect_tpncp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
366 | {
367 | if (!db_initialized)
368 | return 0;
369 |
370 | if (pinfo->can_desegment)
371 | /* If desegmentation is enabled (TCP preferences) use the desegmentation API. */
372 | tcp_dissect_pdus(tvb, pinfo, tree, tpncp_desegment, 4, get_tpncp_pdu_len,
373 | dissect_tpncp, data);
374 | else
375 | /* Otherwise use the regular dissector (might not give correct dissection). */
376 | dissect_tpncp(tvb, pinfo, tree, data);
377 |
378 | return tvb_reported_length(tvb);
379 | }
380 |
381 | static int
382 | dissect_acdr_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
383 | {
384 | int res = 0;
385 | acdr_dissector_data_t *acdr_data = (acdr_dissector_data_t *) data;
386 | uint32_t orig_port = pinfo->srcport;
387 |
388 | if (acdr_data == NULL((void*)0))
389 | return 0;
390 |
391 | // only on version 2+ events are sent with TPNCP header that enables using tpncp parser
392 | if (acdr_data->version <= 1)
393 | return 0;
394 |
395 | // the TPNCP dissector uses the following statement to
396 | // differentiate command from event:
397 | // if (pinfo->srcport == UDP_PORT_TPNCP_TRUNKPACK) -> Event
398 | // so for proper dissection we want to imitate this behaviour
399 | pinfo->srcport = UDP_PORT_TPNCP_TRUNKPACK2424;
400 | res = dissect_tpncp(tvb, pinfo, tree, NULL((void*)0));
401 | pinfo->srcport = orig_port;
402 | return res;
403 | }
404 |
405 | static int
406 | dissect_acdr_tpncp_by_tracepoint(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
407 | {
408 | acdr_dissector_data_t *acdr_data = (acdr_dissector_data_t *) data;
409 | uint32_t orig_port = pinfo->srcport;
410 | int res = 0;
411 |
412 | if (acdr_data == NULL((void*)0))
413 | return 0;
414 |
415 | // the TPNCP dissector uses the following statement to
416 | // differentiate command from event:
417 | // if (pinfo->srcport == UDP_PORT_TPNCP_TRUNKPACK) -> Event
418 | // so for proper dissection we want to imitate this behaviour
419 |
420 | if (acdr_data->trace_point == Host2Net) // event
421 | pinfo->srcport = UDP_PORT_TPNCP_TRUNKPACK2424;
422 | else // Net2Host ->command
423 | pinfo->srcport = UDP_PORT_TPNCP_TRUNKPACK2424 + 1;
424 |
425 | res = dissect_tpncp(tvb, pinfo, tree, NULL((void*)0));
426 | pinfo->srcport = orig_port;
427 | return res;
428 | }
429 |
430 | /*---------------------------------------------------------------------------*/
431 |
432 | static bool_Bool
433 | fgetline(char *buffer, int size, FILE *file)
434 | {
435 | if (!fgets(buffer, size, file))
11 | ← | Assuming this stream operation fails | →
12 | ← | Taking true branch | →
18 | ← | File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
436 | return 0;
437 | size_t last = strlen(buffer);
438 | if (buffer[last - 1] == '\n')
439 | buffer[last - 1] = 0;
440 | return 1;
441 | }
442 |
443 | static int
444 | fill_tpncp_id_vals(value_string **strings, FILE *file)
445 | {
446 | wmem_array_t *vs_arr;
447 | char *line_in_file;
448 |
449 | if (file
8.1 | 'file' is not equal to NULL
15.1 | 'file' is not equal to NULL
== NULL((void*)0)) return -1;
9 | ← | Taking false branch | →
16 | ← | Taking false branch | →
450 |
451 | line_in_file = (char *) g_malloc(MAX_TPNCP_DB_ENTRY_LEN3000);
452 | vs_arr = wmem_array_new(NULL((void*)0), sizeof **strings);
453 |
454 | while (fgetline(line_in_file, MAX_TPNCP_DB_ENTRY_LEN3000, file) && !feof(file)) {
10 | ← | Calling 'fgetline' | →
13 | ← | Returning from 'fgetline' | →
17 | ← | Calling 'fgetline' | →
455 | int tpncp_id = 0;
456 | char tpncp_name[256];
457 |
458 | if (!strncmp(line_in_file, "#####", 5))
459 | break;
460 | if (sscanf(line_in_file, "%255s %d", tpncp_name, &tpncp_id) == 2) {
461 | value_string const string = {
462 | .value = (uint32_t)tpncp_id,
463 | .strptr = wmem_strdup(wmem_epan_scope(), tpncp_name)
464 | };
465 | wmem_array_append_one(vs_arr, string)wmem_array_append((vs_arr), &(string), 1);
466 | }
467 | }
468 |
469 | wmem_array_set_null_terminator(vs_arr);
470 | *strings = wmem_array_finalize(vs_arr);
471 | g_free(line_in_file);
472 |
473 | return 0;
474 | }
475 |
476 | /*---------------------------------------------------------------------------*/
477 |
478 | static int
479 | fill_enums_id_vals(char ***enum_names, value_string ***enum_value_strings, FILE *file)
480 | {
481 | wmem_array_t *enum_name_arr, *enum_vs_arr, *enum_vs = NULL((void*)0);
482 | char *line_in_file;
483 | char enum_type[256];
484 |
485 | line_in_file = (char *) g_malloc(MAX_TPNCP_DB_ENTRY_LEN3000);
486 | enum_type[0] = '\0';
487 |
488 | enum_name_arr = wmem_array_new(NULL((void*)0), sizeof **enum_names);
489 | enum_vs_arr = wmem_array_new(NULL((void*)0), sizeof **enum_value_strings);
490 |
491 | while (fgetline(line_in_file, MAX_TPNCP_DB_ENTRY_LEN3000, file)) {
492 | char enum_name[256], enum_str[256];
493 | int enum_id;
494 |
495 | if (!strncmp(line_in_file, "#####", 5))
496 | break;
497 | if (sscanf(line_in_file, "%255s %255s %d", enum_name, enum_str, &enum_id) == 3) {
498 | if (strcmp(enum_type, enum_name) != 0) {
499 | /* New record. */
500 | if (enum_vs != NULL((void*)0)) {
501 | /* The previous enum_vs is now complete. */
502 | wmem_array_set_null_terminator(enum_vs);
503 | value_string *new_enum_vs = wmem_array_finalize(enum_vs);
504 | wmem_array_append_one(enum_vs_arr, new_enum_vs)wmem_array_append((enum_vs_arr), &(new_enum_vs), 1);
505 | }
506 | enum_vs = wmem_array_sized_new(NULL((void*)0), sizeof ***enum_value_strings, 10);
507 |
508 | char *enum_name_alloc = wmem_strdup(wmem_epan_scope(), enum_name);
509 | wmem_array_append_one(enum_name_arr, enum_name_alloc)wmem_array_append((enum_name_arr), &(enum_name_alloc), 1);
510 | g_strlcpy(enum_type, enum_name, sizeof enum_type);
511 | }
512 | value_string const vs = {
513 | .value = enum_id,
514 | .strptr = wmem_strdup(wmem_epan_scope(), enum_str)
515 | };
516 | wmem_array_append_one(enum_vs, vs)wmem_array_append((enum_vs), &(vs), 1);
517 | }
518 | }
519 |
520 | if (enum_vs != NULL((void*)0)) {
521 | /* The final enum_vs is now complete. */
522 | wmem_array_set_null_terminator(enum_vs);
523 | value_string *new_enum_vs = wmem_array_finalize(enum_vs);
524 | wmem_array_append_one(enum_vs_arr, new_enum_vs)wmem_array_append((enum_vs_arr), &(new_enum_vs), 1);
525 | }
526 |
527 | wmem_array_set_null_terminator(enum_name_arr);
528 | *enum_names = (char **)wmem_array_finalize(enum_name_arr);
529 |
530 | wmem_array_set_null_terminator(enum_vs_arr);
531 | *enum_value_strings = (value_string **)wmem_array_finalize(enum_vs_arr);
532 | g_free(line_in_file);
533 |
534 | return 0;
535 | }
536 |
537 | /*---------------------------------------------------------------------------*/
538 |
539 | static int
540 | get_enum_name_val(const char *enum_name)
541 | {
542 | int enum_val = 0;
543 |
544 | while (tpncp_enums_name_vals[enum_val]) {
545 | if (!strcmp(enum_name, tpncp_enums_name_vals[enum_val]))
546 | return enum_val;
547 | enum_val++;
548 | }
549 |
550 | return -1;
551 | }
552 |
553 | /*---------------------------------------------------------------------------*/
554 |
555 | static bool_Bool add_hf(hf_register_info *hf_entr)
556 | {
557 | if (hf_size >= hf_allocated) {
558 | void *newbuf;
559 | hf_allocated += 1024;
560 | newbuf = wmem_realloc(wmem_epan_scope(), hf, hf_allocated * sizeof (hf_register_info));
561 | if (!newbuf)
562 | return false0;
563 | hf = (hf_register_info *) newbuf;
564 | }
565 | memcpy(hf + hf_size, hf_entr, sizeof (hf_register_info));
566 | hf_size++;
567 | return true1;
568 | }
569 |
570 | static int
571 | init_tpncp_data_fields_info(tpncp_data_field_info ***data_fields_info, unsigned *data_fields_len, FILE *file)
572 | {
573 | static bool_Bool was_registered = false0;
574 | char tpncp_db_entry[MAX_TPNCP_DB_ENTRY_LEN3000];
575 | char entry_copy[MAX_TPNCP_DB_ENTRY_LEN3000];
576 | const char *name = NULL((void*)0), *tmp = NULL((void*)0);
577 | int enum_val, data_id, current_data_id = -1, array_dim;
578 | unsigned char size;
579 | enum SpecialFieldType special_type;
580 | bool_Bool sign, is_address_family;
581 | unsigned idx, since, ip_addr_field;
582 | tpncp_data_field_info *field = NULL((void*)0);
583 | hf_register_info hf_entr;
584 | wmem_array_t *data_fields_info_arr;
585 |
586 | hf_register_info hf_tpncp[] = {
587 | {
588 | &hf_tpncp_version,
589 | {
590 | "Version",
591 | "tpncp.version",
592 | FT_UINT16,
593 | BASE_DEC,
594 | NULL((void*)0),
595 | 0x0,
596 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
597 | }
598 | },
599 | {
600 | &hf_tpncp_length,
601 | {
602 | "Length",
603 | "tpncp.length",
604 | FT_UINT16,
605 | BASE_DEC,
606 | NULL((void*)0),
607 | 0x0,
608 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
609 | }
610 | },
611 | {
612 | &hf_tpncp_seq_number,
613 | {
614 | "Sequence number",
615 | "tpncp.seq_number",
616 | FT_UINT16,
617 | BASE_DEC,
618 | NULL((void*)0),
619 | 0x0,
620 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
621 | }
622 | },
623 | {
624 | &hf_tpncp_length_ext,
625 | {
626 | "Length Extension",
627 | "tpncp.lengthextension",
628 | FT_UINT8,
629 | BASE_DEC,
630 | NULL((void*)0),
631 | 0x0,
632 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
633 | }
634 | },
635 | {
636 | &hf_tpncp_reserved,
637 | {
638 | "Reserved",
639 | "tpncp.reserved",
640 | FT_UINT8,
641 | BASE_DEC,
642 | NULL((void*)0),
643 | 0x0,
644 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
645 | }
646 | },
647 | {
648 | &hf_tpncp_command_id,
649 | {
650 | "Command ID",
651 | "tpncp.command_id",
652 | FT_UINT32,
653 | BASE_DEC,
654 | VALS(tpncp_commands_id_vals)((0 ? (const struct _value_string*)0 : ((tpncp_commands_id_vals )))),
655 | 0x0,
656 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
657 | }
658 | },
659 | {
660 | &hf_tpncp_event_id,
661 | {
662 | "Event ID",
663 | "tpncp.event_id",
664 | FT_UINT32,
665 | BASE_DEC,
666 | VALS(tpncp_events_id_vals)((0 ? (const struct _value_string*)0 : ((tpncp_events_id_vals )))),
667 | 0x0,
668 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
669 | }
670 | },
671 | {
672 | &hf_tpncp_cid,
673 | {
674 | "Channel ID",
675 | "tpncp.channel_id",
676 | FT_INT32,
677 | BASE_DEC,
678 | NULL((void*)0),
679 | 0x0,
680 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)
681 | }
682 | }
683 | };
684 |
685 | /* Register common fields of hf_register_info structure. */
686 | hf_entr.hfinfo.type = FT_NONE;
687 | hf_entr.hfinfo.strings = NULL((void*)0);
688 | hf_entr.hfinfo.bitmask = 0x0;
689 | hf_entr.hfinfo.blurb = NULL((void*)0);
690 | HFILL_INIT(hf_entr)(hf_entr).hfinfo.id = -1; (hf_entr).hfinfo.parent = 0; (hf_entr ).hfinfo.ref_type = HF_REF_TYPE_NONE; (hf_entr).hfinfo.same_name_prev_id = -1; (hf_entr).hfinfo.same_name_next = ((void*)0);;
691 |
692 | if (!was_registered) {
693 | void *newbuf;
694 |
695 | /* Register non-standard data should be done only once. */
696 | hf_allocated = hf_size + (int) array_length(hf_tpncp)(sizeof (hf_tpncp) / sizeof (hf_tpncp)[0]);
697 | newbuf = wmem_realloc(wmem_epan_scope(), hf, hf_allocated * sizeof (hf_register_info));
698 | if (!newbuf)
699 | return -1;
700 | hf = (hf_register_info *) newbuf;
701 | for (idx = 0; idx < array_length(hf_tpncp)(sizeof (hf_tpncp) / sizeof (hf_tpncp)[0]); idx++) {
702 | memcpy(hf + hf_size, hf_tpncp + idx, sizeof (hf_register_info));
703 | hf_size++;
704 | }
705 | was_registered = true1;
706 | }
707 |
708 | is_address_family = false0;
709 | ip_addr_field = 0;
710 |
711 | data_fields_info_arr = wmem_array_new(NULL((void*)0), sizeof **data_fields_info);
712 |
713 | /* Register standard data. */
714 | while (fgetline(tpncp_db_entry, MAX_TPNCP_DB_ENTRY_LEN3000, file)) {
715 | special_type = TPNCP_NORMAL;
716 | since = 0;
717 | snprintf(entry_copy, MAX_TPNCP_DB_ENTRY_LEN3000, "%s", tpncp_db_entry);
718 | if (!strncmp(tpncp_db_entry, "#####", 5))
719 | break;
720 |
721 | /* Default to decimal display type */
722 | hf_entr.hfinfo.display = BASE_DEC;
723 | if ((tmp = strtok(tpncp_db_entry, " ")) == NULL((void*)0)) {
724 | report_failure(
725 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
726 | entry_copy);
727 | continue;
728 | }
729 | data_id = (int) g_ascii_strtoll(tmp, NULL((void*)0), 10);
730 | if ((name = strtok(NULL((void*)0), " ")) == NULL((void*)0)) {
731 | report_failure(
732 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
733 | entry_copy);
734 | continue;
735 | }
736 |
737 | /* We happen to have a line without a name (57 0 32 0 0 primitive). Consider unnamed. */
738 | if (g_ascii_isdigit(*name)((g_ascii_table[(guchar) (*name)] & G_ASCII_DIGIT) != 0)) {
739 | tmp = name;
740 | name = "unnamed";
741 | } else {
742 | if ((tmp = strtok(NULL((void*)0), " ")) == NULL((void*)0)) {
743 | report_failure(
744 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
745 | entry_copy);
746 | continue;
747 | }
748 | }
749 | if (name[0] == 'c' && !strcmp(name, "cmd_rev_lsb"))
750 | special_type = TPNCP_OPEN_CHANNEL_START;
751 | else if (name[0] == 'r' && !strcmp(name, "rtp_authentication_algorithm"))
752 | special_type = TPNCP_SECURITY_START;
753 | else if (name[0] == 's' && !strcmp(name, "security_cmd_offset"))
754 | special_type = TPNCP_SECURITY_OFFSET;
755 | else if (data_id != 1611 && name[0] == 's' && !strcmp(name, "ssrc"))
756 | special_type = RTP_STATE_START;
757 | else if (name[0] == 'r' && !strcmp(name, "rtp_tx_state_ssrc"))
758 | special_type = RTP_STATE_START;
759 | else if (name[0] == 'r' && !strcmp(name, "rtp_state_offset"))
760 | special_type = RTP_STATE_OFFSET;
761 | else if (name[0] == 's' && !strcmp(name, "state_update_time_stamp"))
762 | special_type = RTP_STATE_END;
763 | else if (data_id == 1611 && name[0] == 'c' && strstr(name, "configuration_type_updated"))
764 | special_type = TPNCP_CHANNEL_CONFIGURATION;
765 | else if ((data_id == 4 && strstr(name, "secondary_rtp_seq_num")) ||
766 | (data_id == 1611 && strstr(name, "dtls_remote_fingerprint_alg"))) {
767 | since = 7401;
768 | }
769 | sign = !!((bool_Bool) g_ascii_strtoll(tmp, NULL((void*)0), 10));
770 | if ((tmp = strtok(NULL((void*)0), " ")) == NULL((void*)0)) {
771 | report_failure(
772 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
773 | entry_copy);
774 | continue;
775 | }
776 | size = (unsigned char) g_ascii_strtoll(tmp, NULL((void*)0), 10);
777 | if ((tmp = strtok(NULL((void*)0), " ")) == NULL((void*)0)) {
778 | report_failure(
779 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
780 | entry_copy);
781 | continue;
782 | }
783 | array_dim = (int) g_ascii_strtoll(tmp, NULL((void*)0), 10);
784 | if ((tmp = strtok(NULL((void*)0), " ")) == NULL((void*)0)) {
785 | report_failure(
786 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
787 | entry_copy);
788 | continue;
789 | }
790 | if (sign && g_ascii_strtoll(tmp, NULL((void*)0), 10))
791 | special_type = TPNCP_IP_ADDR;
792 | if ((tmp = strtok(NULL((void*)0), "\n")) == NULL((void*)0)) {
793 | report_failure(
794 | "ERROR! Badly formed data base entry: %s - corresponding field's registration is skipped.",
795 | entry_copy);
796 | continue;
797 | }
798 |
799 | if (ip_addr_field > 0) {
800 | // ip address that comes after address family has 4 fields: ip_addr_0, ip_addr_1, 2 and 3
801 | // On these cases, ignore 1, 2 and 3 and enlarge the field size of 0 to 128
802 | char *seq = (char*)name + strlen(name) - 2;
803 | --ip_addr_field;
804 | if (seq > name && *seq == '_') {
805 | if (seq[1] >= '1' && seq[1] <= '3')
806 | continue;
807 | // relates to the *previous* field
808 | if (is_address_family) {
809 | *seq = 0;
810 | size = 128;
811 | special_type = TPNCP_IP_ADDR;
812 | } else {
813 | report_warning("Bad address form. Field name: %s", name);
814 | ip_addr_field = 0;
815 | }
816 | }
817 | }
818 |
819 | is_address_family = false0;
820 | if (current_data_id != data_id) { /* new data */
821 | tpncp_data_field_info **fp;
822 |
823 | while (wmem_array_get_count(data_fields_info_arr) <= (unsigned)data_id) {
824 | static const tpncp_data_field_info **empty = NULL((void*)0);
825 | wmem_array_append_one(data_fields_info_arr, empty)wmem_array_append((data_fields_info_arr), &(empty), 1);
826 | }
827 | fp = (tpncp_data_field_info **)wmem_array_index(data_fields_info_arr, data_id);
828 | if (*fp != NULL((void*)0)) {
829 | report_failure(
830 | "ERROR! The data_id %d already registered. Cannot register two identical events/command",
831 | data_id);
832 | continue;
833 | }
834 | field = wmem_new0(wmem_epan_scope(), tpncp_data_field_info)((tpncp_data_field_info*)wmem_alloc0((wmem_epan_scope()), sizeof (tpncp_data_field_info)));
835 | *fp = field;
836 | current_data_id = data_id;
837 | } else {
838 | field->p_next = wmem_new(wmem_epan_scope(), tpncp_data_field_info)((tpncp_data_field_info*)wmem_alloc((wmem_epan_scope()), sizeof (tpncp_data_field_info)));
839 | if (!field->p_next)
840 | return (-1);
841 | field = field->p_next;
842 | field->p_next = NULL((void*)0);
843 | }
844 |
845 | /* Register specific fields of hf_register_info structure. */
846 | if (strcmp(tmp, "primitive")) {
847 | enum_val = get_enum_name_val(tmp);
848 | if (enum_val == -1) {
849 | hf_entr.hfinfo.strings = NULL((void*)0);
850 | } else {
851 | if (special_type == TPNCP_IP_ADDR)
852 | special_type = TPNCP_NORMAL;
853 | hf_entr.hfinfo.strings = VALS(tpncp_enums_id_vals[enum_val])((0 ? (const struct _value_string*)0 : ((tpncp_enums_id_vals[ enum_val]))));
854 | if (!strcmp(tmp, "AddressFamily")) {
855 | is_address_family = true1;
856 | ip_addr_field = 4;
857 | }
858 | }
859 | } else {
860 | hf_entr.hfinfo.strings = NULL((void*)0);
861 | }
862 | field->descr = -1;
863 | field->ipv6_descr = -1;
864 | hf_entr.p_id = &field->descr;
865 | field->name = wmem_strdup_printf(wmem_epan_scope(), "tpncp.%s", name);
866 | hf_entr.hfinfo.name = field->name;
867 | hf_entr.hfinfo.abbrev = field->name;
868 | switch (size) {
869 | case 1:
870 | hf_entr.hfinfo.type = FT_BOOLEAN;
871 | break;
872 | case 2: case 3: case 4:
873 | case 5: case 6: case 7: case 8:
874 | if (array_dim) {
875 | hf_entr.hfinfo.type = FT_STRING;
876 | hf_entr.hfinfo.display = BASE_NONE;
877 | } else {
878 | hf_entr.hfinfo.type = (sign) ? FT_UINT8 : FT_INT8;
879 | }
880 | break;
881 | case 16:
882 | hf_entr.hfinfo.type = (sign) ? FT_UINT16 : FT_INT16;
883 | break;
884 | case 32:
885 | if (special_type == TPNCP_IP_ADDR) {
886 | hf_entr.hfinfo.display = BASE_NONE;
887 | hf_entr.hfinfo.type = FT_IPv4;
888 | } else {
889 | hf_entr.hfinfo.type = (sign) ? FT_UINT32 : FT_INT32;
890 | }
891 | break;
892 | case 64:
893 | hf_entr.hfinfo.type = (sign) ? FT_UINT64 : FT_INT64;
894 | break;
895 | case 128:
896 | if (special_type == TPNCP_IP_ADDR) {
897 | hf_entr.hfinfo.display = BASE_NONE;
898 | hf_entr.hfinfo.type = FT_IPv4;
899 | if (!add_hf(&hf_entr))
900 | return -1;
901 | hf_entr.p_id = &field->ipv6_descr;
902 | hf_entr.hfinfo.type = FT_IPv6;
903 | }
904 | break;
905 | default:
906 | break;
907 | }
908 |
909 | /* Register initialized hf_register_info in global database. */
910 | if (!add_hf(&hf_entr))
911 | return -1;
912 | field->sign = sign;
913 | field->size = size;
914 | field->array_dim = array_dim;
915 | field->special_type = is_address_family ? TPNCP_ADDRESS_FAMILY : special_type;
916 | field->since = since;
917 | }
918 |
919 | *data_fields_len = wmem_array_get_count(data_fields_info_arr);
920 | *data_fields_info = (tpncp_data_field_info **)wmem_array_finalize(data_fields_info_arr);
921 |
922 | return 0;
923 | }
924 |
925 | /*---------------------------------------------------------------------------*/
926 |
927 | static FILE *
928 | open_tpncp_dat(void)
929 | {
930 | char *path_buf = NULL((void*)0);
931 | const char *tpncp_dat_file_path = tpncp_dat_path;
932 | FILE *res;
933 | if (!*tpncp_dat_file_path) {
934 | tpncp_dat_file_path = path_buf = g_build_path(
935 | G_DIR_SEPARATOR_S"/", get_datafile_dir(epan_get_environment_prefix()), "tpncp", "tpncp.dat", NULL((void*)0));
936 | }
937 | res = ws_fopenfopen(tpncp_dat_file_path, "r");
938 | g_free(path_buf);
939 | return res;
940 | }
941 |
942 | static int
943 | init_tpncp_db(void)
944 | {
945 | /* Open file with TPNCP data. */
946 | FILE *file = open_tpncp_dat();
947 | if (!file
6.1 | 'file' is non-null
) {
7 | ← | Taking false branch | →
948 | return (-1);
949 | }
950 | fill_tpncp_id_vals(&tpncp_events_id_vals, file);
8 | ← | Calling 'fill_tpncp_id_vals' | →
14 | ← | Returning from 'fill_tpncp_id_vals' | →
951 | fill_tpncp_id_vals(&tpncp_commands_id_vals, file);
15 | ← | Calling 'fill_tpncp_id_vals' | →
952 | fill_enums_id_vals(&tpncp_enums_name_vals, &tpncp_enums_id_vals, file);
953 | init_tpncp_data_fields_info(&tpncp_events_info_db, &tpncp_events_info_len, file);
954 | init_tpncp_data_fields_info(&tpncp_commands_info_db, &tpncp_commands_info_len, file);
955 |
956 | fclose(file);
957 | return 0;
958 | }
959 |
960 | /*---------------------------------------------------------------------------*/
961 |
962 | void
963 | proto_reg_handoff_tpncp(void)
964 | {
965 | static bool_Bool initialized = false0;
966 |
967 | if (proto_tpncp <= 0) return;
1 | Assuming 'proto_tpncp' is > 0 | →
2 | ← | Taking false branch | →
968 |
969 | if (!initialized
2.1 | 'initialized' is false
) {
3 | ← | Taking true branch | →
970 | dissector_add_uint_with_preference("udp.port", UDP_PORT_TPNCP_TRUNKPACK2424, tpncp_handle);
971 | dissector_add_uint_with_preference("tcp.port", TCP_PORT_TPNCP_TRUNKPACK2424, tpncp_tcp_handle);
972 | dissector_add_uint("acdr.media_type", ACDR_PCIIF_COMMAND, tpncp_handle);
973 | dissector_add_uint("acdr.media_type", ACDR_COMMAND, tpncp_handle);
974 | dissector_add_uint("acdr.media_type", ACDR_Event, create_dissector_handle(dissect_acdr_event, proto_tpncp));
975 | dissector_add_uint("acdr.media_type", ACDR_TPNCP,
976 | create_dissector_handle(dissect_acdr_tpncp_by_tracepoint, proto_tpncp));
977 | dissector_add_uint("acdr.tls_application", TLS_APP_TPNCP, tpncp_handle);
978 | initialized = true1;
979 | }
980 |
981 | if (!global_tpncp_load_db)
4 | ← | Assuming 'global_tpncp_load_db' is true | →
982 | return;
983 |
984 | /* If we weren't able to load the database (and thus the hf_ entries)
985 | * do not attach to any ports (if we did then we'd get a "dissector bug"
986 | * assertions every time a packet is handed to us and we tried to use the
987 | * hf_ entry).
988 |
989 | */
990 | if (hf_allocated == 0 && init_tpncp_db() == -1) {
5 | ← | Assuming 'hf_allocated' is equal to 0 | →
6 | ← | Calling 'init_tpncp_db' | →
991 | report_failure("tpncp: Could not load tpncp.dat file, tpncp dissector will not work");
992 | return;
993 | }
994 |
995 | if (db_initialized)
996 | return;
997 |
998 | /* Rather than duplicating large quantities of code from
999 | * proto_register_field_array() and friends to sanitize the tpncp.dat file
1000 | * when we read it, just catch any exceptions we get while registering and
1001 | * take them as a hint that the file is corrupt. Then move on, so that at
1002 | * least the rest of the protocol dissectors will still work.
1003 | */
1004 | TRY{ except_t *volatile exc; volatile int except_state = 0; static const except_id_t catch_spec[] = { { 1, 0 } }; { struct except_stacknode except_sn; struct except_catch except_ch; except_setup_try(& except_sn, &except_ch, catch_spec, 1); if (_setjmp (except_ch .except_jmp)) *(&exc) = &except_ch.except_obj; else * (&exc) = 0; if(except_state & 1) except_state |= 2; except_state &= ~1; if (except_state == 0 && exc == 0) {
1005 | int idx;
1006 | /* The function proto_register_field_array does not work with dynamic
1007 | * arrays, so pass dynamic array elements one-by-one in the loop.
1008 | */
1009 | for (idx = 0; idx < hf_size; idx++)
1010 | proto_register_field_array(proto_tpncp, &hf[idx], 1);
1011 | }
1012 |
1013 | CATCH_ALLif (except_state == 0 && exc != 0 && (except_state |=1)) {
1014 | report_failure("Corrupt tpncp.dat file, tpncp dissector will not work.");
1015 | }
1016 |
1017 | ENDTRYif(!(except_state&1) && exc != 0) except_rethrow( exc); except_free(except_ch.except_obj.except_dyndata); except_pop (); };};
1018 | db_initialized = true1;
1019 | }
1020 |
1021 | /*---------------------------------------------------------------------------*/
1022 |
1023 | void
1024 | proto_register_tpncp(void)
1025 | {
1026 | module_t *tpncp_module;
1027 | expert_module_t* expert_tpncp;
1028 | static int *ett[] = {
1029 | &ett_tpncp,
1030 | &ett_tpncp_body
1031 | };
1032 |
1033 | static ei_register_info ei[] = {
1034 | { &ei_tpncp_unknown_data, { "tpncp.unknown_data", PI_UNDECODED0x05000000, PI_WARN0x00600000, "Unknown data", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}} } },
1035 | };
1036 |
1037 | /* this dissector reads hf entries from a database
1038 | * a boolean preference defines whether the database is loaded or not
1039 | * we initialize the hf array in the handoff function when we have
1040 | * access to the preference's value */
1041 |
1042 | proto_tpncp = proto_register_protocol("TPNCP (TrunkPack Network Control Protocol)",
1043 | "TPNCP", "tpncp");
1044 |
1045 | tpncp_handle = register_dissector("tpncp", dissect_tpncp, proto_tpncp);
1046 | tpncp_tcp_handle = register_dissector("tpncp.tcp", dissect_tpncp_tcp, proto_tpncp);
1047 |
1048 | tpncp_module = prefs_register_protocol(proto_tpncp, proto_reg_handoff_tpncp);
1049 |
1050 | proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1051 |
1052 | expert_tpncp = expert_register_protocol(proto_tpncp);
1053 | expert_register_field_array(expert_tpncp, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1054 |
1055 | /* See https://gitlab.com/wireshark/wireshark/-/issues/9569 for some discussion on this as well */
1056 | prefs_register_bool_preference(tpncp_module, "load_db",
1057 | "Whether to load DB or not; if DB not loaded dissector is passive",
1058 | "Whether to load the Database or not; not loading the DB"
1059 | " disables the protocol; Wireshark has to be restarted for the"
1060 | " setting to take effect.",
1061 | &global_tpncp_load_db);
1062 | prefs_register_filename_preference(tpncp_module, "dat_file",
1063 | "TPNCP data file (tpncp.dat)",
1064 | "Path to tpncp.dat. If empty, the file shipped with Wireshark will be used.\n"
1065 | "Changing the path requires a Wireshark restart to take effect.",
1066 | &tpncp_dat_path, false0);
1067 | }
1068 |
1069 | /*
1070 | * Editor modelines
1071 | *
1072 | * Local Variables:
1073 | * c-basic-offset: 4
1074 | * tab-width: 8
1075 | * indent-tabs-mode: nil
1076 | * End:
1077 | *
1078 | * ex: set shiftwidth=4 tabstop=8 expandtab:
1079 | * :indentSize=4:tabSize=8:noTabs=true:
1080 | */