Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-bvlc.c
Warning:line 727, column 3
Value stored to 'offset' 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 packet-bvlc.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-22/lib/clang/22 -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 CARES_NO_DEPRECATED -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-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../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=gnu17 -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 -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-06-20-100349-3567-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-bvlc.c
1/* packet-bvlc.c
2 * Routines for BACnet/IP (BVLL, BVLC) dissection
3 * Copyright 2001, Hartmut Mueller <[email protected]>, FH Dortmund
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <[email protected]>
7 * Copyright 1998 Gerald Combs
8 *
9 * Copied from README.developer,v 1.23
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 */
13
14#include "config.h"
15
16#include <epan/packet.h>
17#include <epan/tfs.h>
18
19#include "packet-bacnet.h"
20#include "packet-bacapp.h"
21
22void proto_register_bvlc(void);
23void proto_reg_handoff_bvlc(void);
24
25#define BVLC_UDP_PORT0xBAC0 0xBAC0
26
27/* Network Layer Wrapper Control Information */
28#define BAC_WRAPPER_CONTROL_NET0x80 0x80
29#define BAC_WRAPPER_MSG_ENCRYPED0x40 0x40
30#define BAC_WRAPPER_RESERVED0x20 0x20
31#define BAC_WRAPPER_AUTHD_PRESENT0x10 0x10
32#define BAC_WRAPPER_DO_NOT_UNWRAP0x08 0x08
33#define BAC_WRAPPER_DO_NOT_DECRPT0x04 0x04
34#define BAC_WRAPPER_NO_TRUST_SRC0x02 0x02
35#define BAC_WRAPPER_SECURE_BY_RTR0x01 0x01
36
37static int proto_bvlc;
38static int proto_bscvlc;
39static int hf_bvlc_type;
40static int hf_bvlc_function;
41static int hf_bvlc_ipv6_function;
42static int hf_bvlc_length;
43static int hf_bvlc_result_ip4;
44static int hf_bvlc_result_ip6;
45static int hf_bvlc_bdt_ip;
46static int hf_bvlc_bdt_mask;
47static int hf_bvlc_bdt_port;
48static int hf_bvlc_reg_ttl;
49static int hf_bvlc_fdt_ip;
50static int hf_bvlc_fdt_ipv6;
51static int hf_bvlc_fdt_port;
52static int hf_bvlc_fdt_ttl;
53static int hf_bvlc_fdt_timeout;
54static int hf_bvlc_fwd_ip;
55static int hf_bvlc_fwd_port;
56static int hf_bvlc_virt_source;
57static int hf_bvlc_virt_dest;
58static int hf_bvlc_orig_source_addr;
59static int hf_bvlc_orig_source_port;
60static int hf_bscvlc_control;
61static int hf_bscvlc_control_data_option;
62static int hf_bscvlc_control_destination_option;
63static int hf_bscvlc_control_destination_address;
64static int hf_bscvlc_control_origin_address;
65static int hf_bscvlc_control_reserved;
66static int hf_bscvlc_header;
67static int hf_bscvlc_header_marker;
68static int hf_bscvlc_header_length;
69static int hf_bscvlc_header_data;
70static int hf_bscvlc_header_opt_type;
71static int hf_bscvlc_header_opt_data;
72static int hf_bscvlc_header_opt_must_understand;
73static int hf_bscvlc_header_opt_more;
74static int hf_bscvlc_vendor_id;
75static int hf_bscvlc_proprietary_opt_type;
76static int hf_bscvlc_proprietary_data;
77static int hf_bscvlc_hub_conn_state;
78static int hf_bscvlc_accept_conns;
79static int hf_bscvlc_max_bvlc_length;
80static int hf_bscvlc_max_npdu_length;
81static int hf_bscvlc_function;
82static int hf_bscvlc_result;
83static int hf_bscvlc_error_class;
84static int hf_bscvlc_error_code;
85static int hf_bscvlc_result_data;
86static int hf_bscvlc_uris;
87static int hf_bscvlc_msg_id;
88static int hf_bscvlc_orig_vmac;
89static int hf_bscvlc_dest_vmac;
90static int hf_bscvlc_connect_vmac;
91static int hf_bscvlc_connect_uuid;
92static int hf_bscvlc_identity_device_id;
93static int hf_bscvlc_hello_opt;
94static int hf_bscvlc_hello_opt_identity_relay;
95
96static dissector_table_t bvlc_dissector_table;
97static dissector_table_t bscvlc_dissector_table;
98static dissector_table_t bvlc_ipv6_dissector_table;
99static dissector_handle_t bvlc_handle;
100static dissector_handle_t bscvlc_handle;
101
102static const value_string bvlc_function_names[] = {
103 { 0x00, "BVLC-Result" },
104 { 0x01, "Write-Broadcast-Distribution-Table" },
105 { 0x02, "Read-Broadcast-Distribution-Table" },
106 { 0x03, "Read-Broadcast-Distribution-Table-Ack" },
107 { 0x04, "Forwarded-NPDU" },
108 { 0x05, "Register-Foreign-Device" },
109 { 0x06, "Read-Foreign-Device-Table" },
110 { 0x07, "Read-Foreign-Device-Table-Ack" },
111 { 0x08, "Delete-Foreign-Device-Table-Entry" },
112 { 0x09, "Distribute-Broadcast-To-Network" },
113 { 0x0a, "Original-Unicast-NPDU" },
114 { 0x0b, "Original-Broadcast-NPDU" },
115 { 0x0c, "Secured-BVLL" },
116 { 0, NULL((void*)0) }
117};
118
119static const value_string bscvlc_function_names[] = {
120 { 0x00, "BVLC-Result" },
121 { 0x01, "Encapsulated-NPDU" },
122 { 0x02, "Address-Resolution" },
123 { 0x03, "Address-Resolution-ACK" },
124 { 0x04, "Advertisement" },
125 { 0x05, "Advertisement-Solicitation" },
126 { 0x06, "Connect-Request" },
127 { 0x07, "Connect-Accept" },
128 { 0x08, "Disconnect-Request" },
129 { 0x09, "Disconnect-ACK" },
130 { 0x0A, "Heartbeat-Request" },
131 { 0x0B, "Heartbeat-ACK" },
132 { 0x0C, "Proprietary-Message" },
133 { 0, NULL((void*)0) }
134};
135
136static const value_string bvlc_result_names[] = {
137 { 0x00, "Successful completion" },
138 { 0x10, "Write-Broadcast-Distribution-Table NAK" },
139 { 0x20, "Read-Broadcast-Distribution-Table NAK" },
140 { 0x30, "Register-Foreign-Device NAK" },
141 { 0x40, "Read-Foreign-Device-Table NAK" },
142 { 0x50, "Delete-Foreign-Device-Table-Entry NAK" },
143 { 0x60, "Distribute-Broadcast-To-Network NAK" },
144 { 0, NULL((void*)0) }
145};
146
147static const value_string bscvlc_result_names[] = {
148 { 0x00, "Successful completion (ACK)" },
149 { 0x01, "Completion failed (NAK)" },
150 { 0, NULL((void*)0) }
151};
152
153static const value_string bvlc_ipv6_function_names[] = {
154 { 0x00, "BVLC-Result", },
155 { 0x01, "Original-Unicast-NPDU", },
156 { 0x02, "Original-Broadcast-NPDU", },
157 { 0x03, "Address-Resolution", },
158 { 0x04, "Forwarded-Address-Resolution", },
159 { 0x05, "Address-Resolution-ACK", },
160 { 0x06, "Virtual-Address-Resolution", },
161 { 0x07, "Virtual-Address-Resolution-ACK", },
162 { 0x08, "Forwarded-NPDU", },
163 { 0x09, "Register-Foreign-Device", },
164 { 0x0A, "Delete-Foreign-Device-Table-Entry", },
165 { 0x0B, "Secure-BVLL", },
166 { 0x0C, "Distribute-Broadcast-To-Network", },
167 { 0, NULL((void*)0) }
168};
169
170static const value_string bvlc_ipv6_result_names[] = {
171 { 0x00, "Successful completion" },
172 { 0x30, "Address-Resolution NAK" },
173 { 0x60, "Virtual-Address-Resolution NAK" },
174 { 0x90, "Register-Foreign-Device NAK" },
175 { 0xA0, "Delete-Foreign-Device-Table-Entry NAK" },
176 { 0xC0, "Distribute-Broadcast-To-Network NAK" },
177 { 0, NULL((void*)0) }
178};
179
180static const value_string bscvlc_header_type_names[] = {
181 { 0x01, "Secure Path" },
182 { 0x02, "Hello" },
183 { 0x03, "Identity" },
184 { 0x04, "Hint" },
185 { 0x05, "Token" },
186 { 0x1F, "Proprietary Header Option" },
187 { 0, NULL((void*)0) }
188};
189
190static const value_string bscvlc_hub_conn_state_names[] = {
191 { 0x00, "No hub connection" },
192 { 0x01, "Connected to primary hub" },
193 { 0x02, "Connected to failover hub" },
194 { 0, NULL((void*)0) }
195};
196
197static const value_string bscvlc_hub_accept_conns_names[] = {
198 { 0x00, "The node does not support accepting direct connections" },
199 { 0x01, "The node supports accepting direct connections" },
200 { 0, NULL((void*)0) }
201};
202
203static int ett_bvlc;
204static int ett_bscvlc;
205static int ett_bscvlc_ctrl;
206static int ett_bscvlc_hdr;
207static int ett_bdt;
208static int ett_fdt;
209
210#define BACNET_IP_ANNEX_J0x81 0x81
211#define BACNET_IPV6_ANNEX_U0x82 0x82
212
213static const value_string bvlc_types[] = {
214 { BACNET_IP_ANNEX_J0x81, "BACnet/IP (Annex J)" },
215 { BACNET_IPV6_ANNEX_U0x82, "BACnet/IPV6 (Annex U)" },
216 { 0, NULL((void*)0) }
217};
218
219#define BSCVLC_CONTROL_DATA_OPTION0x01 0x01
220#define BSCVLC_CONTROL_DEST_OPTION0x02 0x02
221#define BSCVLC_CONTROL_DEST_ADDRESS0x04 0x04
222#define BSCVLC_CONTROL_ORIG_ADDRESS0x08 0x08
223#define BSCVLC_CONTROL_RESERVED0xF0 0xF0
224
225static const true_false_string control_data_option_set_high = {
226 "Data Options field is present.",
227 "Data Options field is absent."
228};
229
230static const true_false_string control_destination_option_set_high = {
231 "Destination Options field is present.",
232 "Destination Options field is absent."
233};
234
235static const true_false_string control_destination_address_set_high = {
236 "Destination Virtual Address is present.",
237 "Destination Virtual Address is absent."
238};
239
240static const true_false_string control_orig_address_set_high = {
241 "Originating Virtual Address is present.",
242 "Originating Virtual Address is absent."
243};
244
245static const true_false_string control_reserved_set_high = {
246 "Shall be zero, but is not.",
247 "Shall be zero and is zero."
248};
249
250/* BSCVLC Header option bits */
251#define BSCVLC_HDR_MORE_OPTIONS_FOLLOW0x80 0x80
252#define BSCVLC_HDR_MUST_UNDERSTAND0x40 0x40
253#define BSCVLC_HDR_EVERY_SEGMENT0x40 0x40
254#define BSCVLC_HDR_DATA_PRESENT0x20 0x20
255#define BSCVLC_HDR_OPTION_TYPE_MASK0x1F 0x1F
256
257/* BSCVLC Header options and their bits */
258#define BSCVLC_HDR_OPT_SECURE_PATH0x01 0x01 /* only data option */
259#define BSCVLC_HDR_OPT_HELLO0x02 0x02 /* only destination option */
260#define BSCVLC_HDR_OPT_HELLO_BIT_IDENT_RELAY0x01 0x01 /* only with the connect request */
261#define BSCVLC_HDR_OPT_IDENTITY0x03 0x03 /* only data option */
262#define BSCVLC_HDR_OPT_HINT0x04 0x04 /* only data option */
263#define BSCVLC_HDR_OPT_TOKEN0x05 0x05 /* only data option */
264#define BSCVLC_HDR_OPT_PROPRIETARY0x1F 0x1F /* data or destination option */
265
266
267static const true_false_string header_opt_data_set_high = {
268 "The 'Header Length' and 'Header Data' fields are present.",
269 "The 'Header Length' and 'Header Data' fields are absent."
270};
271
272static const true_false_string header_opt_must_understand_set_high = {
273 "This header option must be understood for consuming the message.",
274 "This header option can be ignored if not understood."
275};
276
277static const true_false_string header_opt_more_set_high = {
278 "Another header option follows in the current header option list.",
279 "This is the last header option in the current header option list."
280};
281
282#define BSCVLC_HELLO_IDENTITY_RELAY0x01 0x01
283
284static const true_false_string hello_opt_identity_relay_set_high = {
285 "Identity relay is allowed.",
286 "Identity relay is forbidden."
287};
288
289static int * const bscvlc_hello1_opt_flags[] = {
290 &hf_bscvlc_hello_opt_identity_relay,
291 NULL((void*)0)
292};
293
294static const value_string
295BACnetErrorClass [] = {
296 { 0, "device" },
297 { 1, "object" },
298 { 2, "property" },
299 { 3, "resources" },
300 { 4, "security" },
301 { 5, "services" },
302 { 6, "vt" },
303 { 7, "communication" },
304 { 0, NULL((void*)0) }
305/* Enumerated values 0-63 are reserved for definition by ASHRAE.
306 Enumerated values64-65535 may be used by others subject to
307 the procedures and constraints described in Clause 23. */
308};
309
310static const value_string
311BACnetErrorCode[] = {
312 { 0, "other"},
313 { 1, "authentication-failed"},
314 { 2, "configuration-in-progress"},
315 { 3, "device-busy"},
316 { 4, "dynamic-creation-not-supported"},
317 { 5, "file-access-denied"},
318 { 6, "incompatible-security-levels"},
319 { 7, "inconsistent-parameters"},
320 { 8, "inconsistent-selection-criterion"},
321 { 9, "invalid-data-type"},
322 { 10, "invalid-file-access-method"},
323 { 11, "invalid-file-start-position"},
324 { 12, "invalid-operator-name"},
325 { 13, "invalid-parameter-data-type"},
326 { 14, "invalid-time-stamp"},
327 { 15, "key-generation-error"},
328 { 16, "missing-required-parameter"},
329 { 17, "no-objects-of-specified-type"},
330 { 18, "no-space-for-object"},
331 { 19, "no-space-to-add-list-element"},
332 { 20, "no-space-to-write-property"},
333 { 21, "no-vt-sessions-available"},
334 { 22, "property-is-not-a-list"},
335 { 23, "object-deletion-not-permitted"},
336 { 24, "object-identifier-already-exists"},
337 { 25, "operational-problem"},
338 { 26, "password-failure"},
339 { 27, "read-access-denied"},
340 { 28, "security-not-supported"},
341 { 29, "service-request-denied"},
342 { 30, "timeout"},
343 { 31, "unknown-object"},
344 { 32, "unknown-property"},
345 { 33, "removed enumeration"},
346 { 34, "unknown-vt-class"},
347 { 35, "unknown-vt-session"},
348 { 36, "unsupported-object-type"},
349 { 37, "value-out-of-range"},
350 { 38, "vt-session-already-closed"},
351 { 39, "vt-session-termination-failure"},
352 { 40, "write-access-denied"},
353 { 41, "character-set-not-supported"},
354 { 42, "invalid-array-index"},
355 { 43, "cov-subscription-failed"},
356 { 44, "not-cov-property"},
357 { 45, "optional-functionality-not-supported"},
358 { 46, "invalid-configuration-data"},
359 { 47, "datatype-not-supported"},
360 { 48, "duplicate-name"},
361 { 49, "duplicate-object-id"},
362 { 50, "property-is-not-an-array"},
363 { 51, "abort - buffer - overflow" },
364 { 52, "abort - invalid - apdu - in - this - state" },
365 { 53, "abort - preempted - by - higher - priority - task" },
366 { 54, "abort - segmentation - not - supported" },
367 { 55, "abort - proprietary" },
368 { 56, "abort - other" },
369 { 57, "reject - invalid - tag" },
370 { 58, "reject - network - down" },
371 { 59, "reject - buffer - overflow" },
372 { 60, "reject - inconsistent - parameters" },
373 { 61, "reject - invalid - parameter - data - type" },
374 { 62, "reject - invalid - tag" },
375 { 63, "reject - missing - required - parameter" },
376 { 64, "reject - parameter - out - of - range" },
377 { 65, "reject - too - many - arguments" },
378 { 66, "reject - undefined - enumeration" },
379 { 67, "reject - unrecognized - service" },
380 { 68, "reject - proprietary" },
381 { 69, "reject - other" },
382 { 70, "unknown - device" },
383 { 71, "unknown - route" },
384 { 72, "value - not - initialized" },
385 { 73, "invalid-event-state"},
386 { 74, "no-alarm-configured"},
387 { 75, "log-buffer-full"},
388 { 76, "logged-value-purged"},
389 { 77, "no-property-specified"},
390 { 78, "not-configured-for-triggered-logging"},
391 { 79, "unknown-subscription"},
392 { 80, "parameter-out-of-range"},
393 { 81, "list-element-not-found"},
394 { 82, "busy"},
395 { 83, "communication-disabled"},
396 { 84, "success"},
397 { 85, "access-denied"},
398 { 86, "bad-destination-address"},
399 { 87, "bad-destination-device-id"},
400 { 88, "bad-signature"},
401 { 89, "bad-source-address"},
402 { 90, "bad-timestamp"},
403 { 91, "cannot-use-key"},
404 { 92, "cannot-verify-message-id"},
405 { 93, "correct-key-revision"},
406 { 94, "destination-device-id-required"},
407 { 95, "duplicate-message"},
408 { 96, "encryption-not-configured"},
409 { 97, "encryption-required"},
410 { 98, "incorrect-key"},
411 { 99, "invalid-key-data"},
412 { 100, "key-update-in-progress"},
413 { 101, "malformed-message"},
414 { 102, "not-key-server"},
415 { 103, "security-not-configured"},
416 { 104, "source-security-required"},
417 { 105, "too-many-keys"},
418 { 106, "unknown-authentication-type"},
419 { 107, "unknown-key"},
420 { 108, "unknown-key-revision"},
421 { 109, "unknown-source-message"},
422 { 110, "not-router-to-dnet"},
423 { 111, "router-busy"},
424 { 112, "unknown-network-message"},
425 { 113, "message-too-long"},
426 { 114, "security-error"},
427 { 115, "addressing-error"},
428 { 116, "write-bdt-failed"},
429 { 117, "read-bdt-failed"},
430 { 118, "register-foreign-device-failed"},
431 { 119, "read-fdt-failed"},
432 { 120, "delete-fdt-entry-failed"},
433 { 121, "distribute-broadcast-failed"},
434 { 122, "unknown-file-size"},
435 { 123, "abort-apdu-too-long"},
436 { 124, "abort-application-exceeded-reply-time"},
437 { 125, "abort-out-of-resources"},
438 { 126, "abort-tsm-timeout"},
439 { 127, "abort-window-size-out-of-range"},
440 { 128, "file-full"},
441 { 129, "inconsistent-configuration"},
442 { 130, "inconsistent-object-type"},
443 { 131, "internal-error"},
444 { 132, "not-configured"},
445 { 133, "out-of-memory"},
446 { 134, "value-too-long"},
447 { 135, "abort-insufficient-security"},
448 { 136, "abort-security-error"},
449 { 137, "duplicate-entry"},
450 { 138, "invalid-value-in-this-state"},
451 { 139, "invalid-operation-in-this-state"},
452 { 140, "list-item-not-numbered"},
453 { 141, "list-item-not-timestamped"},
454 { 142, "invalid-data-encoding"},
455 { 143, "bvlc-function-unknown"},
456 { 144, "bvlc-proprietary-function-unknown"},
457 { 145, "header-encoding-error"},
458 { 146, "header-not-understood"},
459 { 147, "message-incomplete"},
460 { 148, "not-a-bacnet-sc-hub"},
461 { 149, "payload-expected"},
462 { 150, "unexpected-data"},
463 { 151, "node-duplicate-vmac"},
464 { 152, "http-unexpected-response-code"},
465 { 153, "http-no-upgrade"},
466 { 154, "http-resource-not-local"},
467 { 155, "http-proxy-authentication-failed"},
468 { 156, "http-response-timeout"},
469 { 157, "http-response-syntax-error"},
470 { 158, "http-response-value-error"},
471 { 159, "http-response-missing-header"},
472 { 160, "http-websocket-header-error"},
473 { 161, "http-upgrade-required"},
474 { 162, "http-upgrade-error"},
475 { 163, "http-temporary-unavailable"},
476 { 164, "http-not-a-server"},
477 { 165, "http-error"},
478 { 166, "websocket-scheme-not-supported"},
479 { 167, "websocket-unknown-control-message"},
480 { 168, "websocket-close-error"},
481 { 169, "websocket-closed-by-peer"},
482 { 170, "websocket-endpoint-leaves"},
483 { 171, "websocket-protocol-error"},
484 { 172, "websocket-data-not-accepted"},
485 { 173, "websocket-closed-abnormally"},
486 { 174, "websocket-data-inconsistent"},
487 { 175, "websocket-data-against-policy"},
488 { 176, "websocket-frame-too-long"},
489 { 177, "websocket-extension-missing"},
490 { 178, "websocket-request-unavailable"},
491 { 179, "websocket-error"},
492 { 180, "tls-client-certificate-error"},
493 { 181, "tls-server-certificate-error"},
494 { 182, "tls-client-authentication-failed"},
495 { 183, "tls-server-authentication-failed"},
496 { 184, "tls-client-certificate-expired"},
497 { 185, "tls-server-certificate-expired"},
498 { 186, "tls-client-certificate-revoked"},
499 { 187, "tls-server-certificate-revoked"},
500 { 188, "tls-error"},
501 { 189, "dns-unavailable"},
502 { 190, "dns-name-resolution-failed"},
503 { 191, "dns-resolver-failure"},
504 { 192, "dns-error"},
505 { 193, "tcp-connect-timeout"},
506 { 194, "tcp-connection-refused"},
507 { 195, "tcp-closed-by-local"},
508 { 196, "tcp-closed-other"},
509 { 197, "tcp-error"},
510 { 198, "ip-address-not-reachable"},
511 { 199, "ip-error"},
512 { 200, "certificate-expired"},
513 { 201, "certificate-invalid"},
514 { 202, "certificate-malformed"},
515 { 203, "certificate-revoked"},
516 { 204, "unknown-key"},
517 { 205, "referenced-port-in-error"},
518 { 206, "not-enabled"},
519 { 207, "adjust-scope-required"},
520 { 208, "auth-scope-required"},
521 { 209, "bind-scope-required"},
522 { 210, "config-scope-required"},
523 { 211, "control-scope-required"},
524 { 212, "extended-scope-required"},
525 { 213, "incorrect-client"},
526 { 214, "install-scope-required"},
527 { 215, "insufficient-scope"},
528 { 216, "no-default-scope"},
529 { 217, "no-policy"},
530 { 218, "revoked-token"},
531 { 219, "override-scope-required"},
532 { 220, "inactive-token"},
533 { 221, "unknown-audience"},
534 { 222, "unknown-client"},
535 { 223, "unknown-scope"},
536 { 224, "view-scope-required"},
537 { 225, "incorrect-audience"},
538 { 226, "incorrect-client-origin"},
539 { 227, "invalid-array-size"},
540 { 228, "incorrect-issuer"},
541 { 229, "invalid-token"},
542 { 0, NULL((void*)0)}
543/* Enumerated values 0-255 are reserved for definition by ASHRAE.
544 Enumerated values 256-65535 may be used by others subject to the
545 procedures and constraints described in Clause 23. */
546};
547static value_string_ext BACnetErrorCode_ext = VALUE_STRING_EXT_INIT(BACnetErrorCode){ _try_val_to_str_ext_init, 0, (sizeof (BACnetErrorCode) / sizeof
((BACnetErrorCode)[0]))-1, BACnetErrorCode, "BACnetErrorCode"
, ((void*)0) }
;
548
549
550
551static int * const bscvlc_control_flags[] = {
552 &hf_bscvlc_control_data_option,
553 &hf_bscvlc_control_destination_option,
554 &hf_bscvlc_control_destination_address,
555 &hf_bscvlc_control_origin_address,
556 &hf_bscvlc_control_reserved,
557 NULL((void*)0)
558};
559
560static int * const bscvlc_header_flags[] = {
561 &hf_bscvlc_header_opt_type,
562 &hf_bscvlc_header_opt_data,
563 &hf_bscvlc_header_opt_must_understand,
564 &hf_bscvlc_header_opt_more,
565 NULL((void*)0)
566};
567
568static int
569// NOLINTNEXTLINE(misc-no-recursion)
570dissect_ipv4_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
571{
572
573 proto_item *ti;
574 proto_item *ti_bdt;
575 proto_item *ti_fdt;
576 proto_tree *bvlc_tree;
577 proto_tree *bdt_tree; /* Broadcast Distribution Table */
578 proto_tree *fdt_tree; /* Foreign Device Table */
579
580 unsigned offset;
581 bool_Bool sec_decrypted;
582 uint8_t bvlc_type;
583 uint8_t bvlc_function;
584 uint16_t bvlc_length;
585 uint16_t packet_length;
586 unsigned npdu_length;
587 unsigned length_remaining;
588 tvbuff_t *next_tvb;
589
590 offset = 0;
591
592 bvlc_type = tvb_get_uint8(tvb, offset);
593 bvlc_function = tvb_get_uint8(tvb, offset + 1);
594 packet_length = tvb_get_ntohs(tvb, offset + 2);
595 length_remaining = tvb_reported_length_remaining(tvb, offset);
596
597 if (bvlc_function > 0x08) {
598 /* We have a constant header length of BVLC of 4 in every
599 * BVLC-packet forewarding an NPDU. Beware: Changes in the
600 * BACnet-IP-standard may break this.
601 */
602 bvlc_length = 4;
603 } else if (bvlc_function == 0x04) {
604 /* 4 Bytes + 6 Bytes for B/IP Address of Originating Device */
605 bvlc_length = 10;
606 } else {
607 /* BVLC-packets with function below 0x09 contain
608 * routing-level data (e.g. Broadcast Distribution)
609 * but no NPDU for BACnet, so bvlc_length goes up to the end
610 * of the captured frame.
611 */
612 bvlc_length = packet_length;
613 }
614
615 if (bvlc_length < 4 || bvlc_length > packet_length) {
616 return 0; /* reject */
617 }
618
619 /* Put the BVLC Type in the info column */
620 col_append_fstr(pinfo->cinfo, COL_INFO, " BVLC Function %s ",
621 val_to_str_const(bvlc_function, bvlc_function_names, "unknown"));
622
623 ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0, bvlc_length, ENC_NA0x00000000);
624 bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
625 proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1,
626 bvlc_type);
627 offset++;
628 proto_tree_add_uint(bvlc_tree, hf_bvlc_function, tvb,
629 offset, 1, bvlc_function);
630 offset++;
631 if (length_remaining != packet_length)
632 proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
633 2, bvlc_length,
634 "%d of %d bytes (invalid length - expected %d bytes)",
635 bvlc_length, packet_length, length_remaining);
636 else
637 proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
638 2, bvlc_length, "%d of %d bytes BACnet packet length",
639 bvlc_length, packet_length);
640 offset += 2;
641 switch (bvlc_function) {
642 case 0x00: /* BVLC-Result */
643 /* I don't know why the result code is encoded in 4 nibbles,
644 * but only using one: 0x00r0. Shifting left 4 bits.
645 */
646 /* We should bitmask the result correctly when we have a
647 * packet to dissect, see README.developer, 1.6.2, FID */
648 proto_tree_add_item(bvlc_tree, hf_bvlc_result_ip4, tvb,
649 offset, 2, ENC_BIG_ENDIAN0x00000000);
650 /*offset += 2;*/
651 break;
652 case 0x01: /* Write-Broadcast-Distribution-Table */
653 case 0x03: /* Read-Broadcast-Distribution-Table-Ack */
654 /* List of BDT Entries: N*10-octet */
655 ti_bdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
656 offset, bvlc_length-4, ENC_NA0x00000000);
657 bdt_tree = proto_item_add_subtree(ti_bdt, ett_bdt);
658 /* List of BDT Entries: N*10-octet */
659 while ((bvlc_length - offset) > 9) {
660 proto_tree_add_item(bdt_tree, hf_bvlc_bdt_ip,
661 tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
662 offset += 4;
663 proto_tree_add_item(bdt_tree, hf_bvlc_bdt_port,
664 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
665 offset += 2;
666 proto_tree_add_item(bdt_tree,
667 hf_bvlc_bdt_mask, tvb, offset, 4,
668 ENC_NA0x00000000);
669 offset += 4;
670 }
671 /* We check this if we get a BDT-packet somewhere */
672 break;
673 case 0x02: /* Read-Broadcast-Distribution-Table */
674 /* nothing to do here */
675 break;
676 case 0x05: /* Register-Foreign-Device */
677 /* Time-to-Live 2-octets T, Time-to-Live T, in seconds */
678 proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl,
679 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
680 /*offset += 2;*/
681 break;
682 case 0x06: /* Read-Foreign-Device-Table */
683 /* nothing to do here */
684 break;
685 case 0x07: /* Read-Foreign-Device-Table-Ack */
686 /* List of FDT Entries: N*10-octet */
687 /* N indicates the number of entries in the FDT whose
688 * contents are being returned. Each returned entry
689 * consists of the 6-octet B/IP address of the registrant;
690 * the 2-octet Time-to-Live value supplied at the time of
691 * registration; and a 2-octet value representing the
692 * number of seconds remaining before the BBMD will purge
693 * the registrant's FDT entry if no re-registration occurs.
694 */
695 ti_fdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
696 offset, bvlc_length -4, ENC_NA0x00000000);
697 fdt_tree = proto_item_add_subtree(ti_fdt, ett_fdt);
698 /* List of FDT Entries: N*10-octet */
699 while ((bvlc_length - offset) > 9) {
700 proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ip,
701 tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
702 offset += 4;
703 proto_tree_add_item(fdt_tree, hf_bvlc_fdt_port,
704 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
705 offset += 2;
706 proto_tree_add_item(fdt_tree,
707 hf_bvlc_fdt_ttl, tvb, offset, 2,
708 ENC_BIG_ENDIAN0x00000000);
709 offset += 2;
710 proto_tree_add_item(fdt_tree,
711 hf_bvlc_fdt_timeout, tvb, offset, 2,
712 ENC_BIG_ENDIAN0x00000000);
713 offset += 2;
714 }
715 /* We check this if we get a FDT-packet somewhere */
716 break;
717 case 0x08: /* Delete-Foreign-Device-Table-Entry */
718 /* FDT Entry: 6-octets */
719 proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ip,
720 tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
721 offset += 4;
722 proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port,
723 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
724 /*offset += 2;*/
725 break;
726 case 0x0C: /* Secure-BVLL */
727 offset = bacnet_dissect_sec_wrapper(tvb, pinfo, tree, offset, NULL((void*)0), &sec_decrypted);
Value stored to 'offset' is never read
728 if (!sec_decrypted) {
729 call_data_dissector(tvb, pinfo, tree);
730 return tvb_captured_length(tvb);
731 }
732 increment_dissection_depth(pinfo);
733 dissect_ipv4_bvlc(tvb, pinfo, tree, data);
734 decrement_dissection_depth(pinfo);
735 break;
736 /* We check this if we get a FDT-packet somewhere */
737 case 0x04: /* Forwarded-NPDU
738 * Why is this 0x04? It would have been a better
739 * idea to append all forewarded NPDUs at the
740 * end of the function table in the B/IP-standard!
741 */
742 /* proto_tree_add_bytes_format(); */
743 proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_ip,
744 tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
745 offset += 4;
746 proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_port,
747 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
748 /*offset += 2;*/
749 break;
750 default:
751 /* Distribute-Broadcast-To-Network
752 * Original-Unicast-NPDU
753 * Original-Broadcast-NPDU
754 * Going to the next dissector...
755 */
756 break;
757 }
758
759 /* Ok, no routing information BVLC packet. Dissect as
760 * BACnet NPDU
761 */
762 npdu_length = packet_length - bvlc_length;
763 next_tvb = tvb_new_subset_length(tvb, bvlc_length, npdu_length);
764 /* Code from Guy Harris */
765 if (!dissector_try_uint(bvlc_dissector_table,
766 bvlc_function, next_tvb, pinfo, tree)) {
767 /* Unknown function - dissect the payload as data */
768 call_data_dissector(next_tvb, pinfo, tree);
769 }
770 return tvb_reported_length(tvb);
771}
772
773static int
774// NOLINTNEXTLINE(misc-no-recursion)
775dissect_ipv6_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
776{
777 proto_item *ti;
778 proto_tree *bvlc_tree;
779
780 unsigned offset;
781 bool_Bool sec_decrypted;
782 uint8_t bvlc_type;
783 uint8_t bvlc_function;
784 uint16_t bvlc_length = 0;
785 uint16_t packet_length;
786 unsigned npdu_length;
787 unsigned length_remaining;
788 tvbuff_t *next_tvb;
789
790 offset = 0;
791
792 bvlc_type = tvb_get_uint8(tvb, offset);
793 bvlc_function = tvb_get_uint8(tvb, offset + 1);
794 packet_length = tvb_get_ntohs(tvb, offset + 2);
795 length_remaining = tvb_reported_length_remaining(tvb, offset);
796
797 switch (bvlc_function) {
798 case 0x00:
799 case 0x09:
800 bvlc_length = 9;
801 break;
802 case 0x01:
803 bvlc_length = 10;
804 break;
805 case 0x02:
806 case 0x06:
807 case 0x0C:
808 bvlc_length = 7;
809 break;
810 case 0x03:
811 case 0x05:
812 case 0x07:
813 bvlc_length = 10;
814 break;
815 case 0x04:
816 bvlc_length = 28;
817 break;
818 case 0x08:
819 case 0x0A:
820 bvlc_length = 25;
821 break;
822 case 0x0B:
823 bvlc_length = 4;
824 break;
825 default:
826 break;
827 }
828
829 if (bvlc_length > packet_length) {
830 return 0; /* reject */
831 }
832
833 /* Put the BVLC Type in the info column */
834 col_append_fstr(pinfo->cinfo, COL_INFO, " BVLC Function %s ",
835 val_to_str_const(bvlc_function, bvlc_ipv6_function_names, "unknown"));
836
837 ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0,
838 bvlc_length, ENC_NA0x00000000);
839 bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
840 /* add the BVLC type */
841 proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1,
842 bvlc_type);
843 offset++;
844 /* add the BVLC function */
845 proto_tree_add_uint(bvlc_tree, hf_bvlc_ipv6_function, tvb,
846 offset, 1, bvlc_function);
847 offset++;
848 /* add the length information */
849 if (length_remaining != packet_length)
850 proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
851 2, bvlc_length,
852 "%d of %d bytes (invalid length - expected %d bytes)",
853 bvlc_length, packet_length, length_remaining);
854 else
855 proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
856 2, bvlc_length,
857 "%d of %d bytes BACnet packet length",
858 bvlc_length, packet_length);
859 offset += 2;
860
861 /* add the optional present virtual source address */
862 if (bvlc_function != 0x0B) {
863 proto_tree_add_item(bvlc_tree, hf_bvlc_virt_source, tvb, offset,
864 3, ENC_BIG_ENDIAN0x00000000);
865 offset += 3;
866 }
867
868 /* handle additional function parameters */
869 switch (bvlc_function) {
870 case 0x00: /* BVLC-Result */
871 proto_tree_add_item(bvlc_tree, hf_bvlc_result_ip6, tvb,
872 offset, 2, ENC_BIG_ENDIAN0x00000000);
873 offset += 2;
874 break;
875 case 0x01: /* Original-Unicast-NPDU */
876 case 0x03: /* Address-Resolution */
877 case 0x05: /* Address-Resolution-ACK */
878 case 0x07: /* Virtual-Address-Resolution-ACK */
879 proto_tree_add_item(bvlc_tree, hf_bvlc_virt_dest, tvb, offset,
880 3, ENC_BIG_ENDIAN0x00000000);
881 offset += 3;
882 break;
883 case 0x04: /* Forwarded-Address-Resolution */
884 proto_tree_add_item(bvlc_tree, hf_bvlc_virt_dest, tvb, offset,
885 3, ENC_BIG_ENDIAN0x00000000);
886 offset += 3;
887 proto_tree_add_item(bvlc_tree, hf_bvlc_orig_source_addr,
888 tvb, offset, 16, ENC_NA0x00000000);
889 offset += 16;
890 proto_tree_add_item(bvlc_tree, hf_bvlc_orig_source_port,
891 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
892 offset += 2;
893 break;
894 case 0x08: /* Forwarded-NPDU */
895 proto_tree_add_item(bvlc_tree, hf_bvlc_orig_source_addr,
896 tvb, offset, 16, ENC_NA0x00000000);
897 offset += 16;
898 proto_tree_add_item(bvlc_tree, hf_bvlc_orig_source_port,
899 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
900 offset += 2;
901 break;
902 case 0x06: /* Virtual-Address-Resolution */
903 break;
904 case 0x09: /* Register-Foreign-Device */
905 proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl,
906 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
907 offset += 2;
908 break;
909 case 0x0A: /* Delete-Foreign-Device-Table-Entry */
910 proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ipv6,
911 tvb, offset, 16, ENC_NA0x00000000);
912 offset += 16;
913 proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port,
914 tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
915 offset += 2;
916 break;
917 case 0x0B: /* Secure-BVLL */
918 offset = bacnet_dissect_sec_wrapper(tvb, pinfo, tree, offset, NULL((void*)0), &sec_decrypted);
919 if (!sec_decrypted) {
920 call_data_dissector(tvb, pinfo, tree);
921 return tvb_captured_length(tvb);
922 }
923 increment_dissection_depth(pinfo);
924 dissect_ipv6_bvlc(tvb, pinfo, tree, data);
925 decrement_dissection_depth(pinfo);
926 break;
927 case 0x02: /* Original-Broadcast-NPDU */
928 case 0x0c: /* Distribute-Broadcast-To-Network */
929 default:
930 /*
931 * Going to the next dissector...
932 */
933 break;
934 }
935
936 /* Ok, no routing information BVLC packet. Dissect as
937 * BACnet NPDU
938 */
939 npdu_length = packet_length - offset;
940 next_tvb = tvb_new_subset_length(tvb, offset, npdu_length);
941 /* Code from Guy Harris */
942 if ( ! dissector_try_uint(bvlc_ipv6_dissector_table,
943 bvlc_function, next_tvb, pinfo, tree)) {
944 /* Unknown function - dissect the payload as data */
945 call_data_dissector(next_tvb, pinfo, tree);
946 }
947
948 return tvb_reported_length(tvb);
949}
950
951static int
952dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
953{
954 uint8_t bvlc_type;
955 unsigned ret = 0;
956
957 bvlc_type = tvb_get_uint8(tvb, 0);
958
959 /*
960 * Simple sanity check - make sure the type is one we know about.
961 */
962 if (try_val_to_str(bvlc_type, bvlc_types) == NULL((void*)0))
963 return 0;
964
965 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BVLC");
966 col_set_str(pinfo->cinfo, COL_INFO, "BACnet Virtual Link Control");
967
968 switch (bvlc_type)
969 {
970 case BACNET_IP_ANNEX_J0x81:
971 ret = dissect_ipv4_bvlc(tvb, pinfo, tree, data);
972 break;
973 case BACNET_IPV6_ANNEX_U0x82:
974 ret = dissect_ipv6_bvlc(tvb, pinfo, tree, data);
975 break;
976 }
977
978 return ret;
979}
980
981static int
982dissect_bscvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)))
983{
984 proto_item *ti;
985 proto_tree *bvlc_tree;
986 tvbuff_t *next_tvb;
987 int offset;
988 int start;
989 int bvlc_length;
990 int packet_length;
991 int npdu_length = 0;
992 uint8_t bvlc_function;
993 uint8_t bvlc_control;
994 uint8_t bvlc_result;
995 uint8_t hdr_byte;
996 uint8_t option;
997 unsigned bvlc_message_id;
998 bool_Bool bMustSegment;
999 bool_Bool bMoreFlag;
1000 bool_Bool bDataFlag;
1001 const char *pszUnderstand;
1002 const char *pszOption;
1003 proto_tree *subtree;
1004
1005 /* Calculate length of BSCVLC block to get remaining payload length */
1006 offset = 0;
1007
1008 packet_length = tvb_reported_length_remaining(tvb, offset);
1009 if(packet_length < 4)
1010 return 0; /* reject */
1011
1012 /* Fix part of the header first */
1013 bvlc_function = tvb_get_uint8(tvb, offset++);
1014 bvlc_control = tvb_get_uint8(tvb, offset++);
1015 bvlc_message_id = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN0x00000000);
1016 offset += 2;
1017
1018 /* Variable part of the header next */
1019 bvlc_length = offset;
1020
1021 if ((bvlc_control & BSCVLC_CONTROL_ORIG_ADDRESS0x08) != 0)
1022 bvlc_length += 6;
1023
1024 if ((bvlc_control & BSCVLC_CONTROL_DEST_ADDRESS0x04) != 0)
1025 bvlc_length += 6;
1026
1027 if ((bvlc_control & BSCVLC_CONTROL_DEST_OPTION0x02) != 0)
1028 {
1029 bMoreFlag = true1;
1030
1031 while(tvb_reported_length_remaining(tvb, bvlc_length) > 0 &&
1032 (hdr_byte = tvb_get_uint8(tvb, bvlc_length)) != 0 && bMoreFlag)
1033 {
1034 /* get flags and type... */
1035 bMoreFlag = (hdr_byte & BSCVLC_HDR_MORE_OPTIONS_FOLLOW0x80);
1036 bDataFlag = (hdr_byte & BSCVLC_HDR_DATA_PRESENT0x20);
1037 bvlc_length++;
1038
1039 if(bDataFlag)
1040 {
1041 npdu_length = (int)(tvb_get_uint8(tvb, bvlc_length++) << 8);
1042 npdu_length += (int)tvb_get_uint8(tvb, bvlc_length++);
1043 bvlc_length += npdu_length;
1044 }
1045 }
1046 }
1047
1048 if ((bvlc_control & BSCVLC_CONTROL_DATA_OPTION0x01) != 0)
1049 {
1050 bMoreFlag = true1;
1051
1052 while(tvb_reported_length_remaining(tvb, bvlc_length) > 0 &&
1053 (hdr_byte = tvb_get_uint8(tvb, bvlc_length)) != 0 && bMoreFlag)
1054 {
1055 /* get flags and type... */
1056 bMoreFlag= (hdr_byte & BSCVLC_HDR_MORE_OPTIONS_FOLLOW0x80);
1057 bDataFlag= (hdr_byte & BSCVLC_HDR_DATA_PRESENT0x20);
1058 bvlc_length++;
1059
1060 if(bDataFlag)
1061 {
1062 npdu_length = (int)(tvb_get_uint8(tvb, bvlc_length++) << 8);
1063 npdu_length += (int)tvb_get_uint8(tvb, bvlc_length++);
1064 bvlc_length += npdu_length;
1065 }
1066 }
1067 }
1068
1069 /* Now add the BSCVLC payload size for specified function */
1070 switch (bvlc_function)
1071 {
1072 case 0x00: /* BVLC-Result */
1073 case 0x03: /* Address-Resolution-ACK */
1074 case 0x0C: /* Proprietary-Message */
1075 /* complete packet length because of optional present variable length error data
1076 but no length encoded for it in the structure of this frame */
1077 bvlc_length = packet_length;
1078 break;
1079 case 0x02: /* Address-Resolution */
1080 case 0x05: /* Advertisement-Solicitation */
1081 case 0x08: /* Disconnect-Request */
1082 case 0x09: /* Disconnect-ACK */
1083 case 0x0A: /* Heartbeat-Request */
1084 case 0x0B: /* Heartbeat-ACK */
1085 /* No additional payload here */
1086 break;
1087 case 0x04: /* Advertisement */
1088 bvlc_length += 6;
1089 break;
1090 case 0x06: /* Connect-Request */
1091 case 0x07: /* Connect-Accept */
1092 bvlc_length += 26;
1093 break;
1094 case 0x01: /* Encapsulated-NPDU */
1095 default:
1096 /* The additional payload will be decoded elsewhere */
1097 break;
1098 }
1099
1100 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSCVLC");
1101 col_set_str(pinfo->cinfo, COL_INFO, "BACnet Secure Connect Virtual Link Control");
1102
1103 /* Put the BSCVLC Type and Message ID in the info column */
1104 col_append_fstr(pinfo->cinfo, COL_INFO, " BSCVLC Function %s Message-ID %u",
1105 val_to_str_const(bvlc_function, bscvlc_function_names, "unknown"), bvlc_message_id);
1106
1107 /* Fill the tree... */
1108 offset = 0;
1109 ti = proto_tree_add_item(tree, proto_bscvlc, tvb, 0, bvlc_length, ENC_NA0x00000000);
1110 bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
1111
1112 proto_tree_add_uint(bvlc_tree, hf_bscvlc_function, tvb,
1113 offset, 1, bvlc_function);
1114 offset++;
1115 proto_tree_add_bitmask(bvlc_tree, tvb, offset, hf_bscvlc_control,
1116 ett_bscvlc_ctrl, bscvlc_control_flags, ENC_NA0x00000000);
1117 offset ++;
1118 proto_tree_add_uint(bvlc_tree, hf_bscvlc_msg_id, tvb,
1119 offset, 2, bvlc_message_id);
1120 offset += 2;
1121
1122 if ((bvlc_control & BSCVLC_CONTROL_ORIG_ADDRESS0x08) != 0)
1123 {
1124 col_append_fstr(pinfo->cinfo, COL_INFO, " SMAC %s", tvb_bytes_to_str(pinfo->pool, tvb, offset, 6));
1125
1126 proto_tree_add_item(bvlc_tree, hf_bscvlc_orig_vmac, tvb, offset, 6, ENC_NA0x00000000);
1127 offset += 6;
1128 }
1129
1130 if ((bvlc_control & BSCVLC_CONTROL_DEST_ADDRESS0x04) != 0)
1131 {
1132 col_append_fstr(pinfo->cinfo, COL_INFO, " DMAC %s", tvb_bytes_to_str(pinfo->pool, tvb, offset, 6));
1133
1134 proto_tree_add_item(bvlc_tree, hf_bscvlc_dest_vmac, tvb, offset, 6, ENC_NA0x00000000);
1135 offset += 6;
1136 }
1137
1138 if ((bvlc_control & BSCVLC_CONTROL_DEST_OPTION0x02) != 0)
1139 {
1140 bMoreFlag = true1;
1141
1142 while(tvb_reported_length_remaining(tvb, offset) > 0 &&
1143 (hdr_byte = tvb_get_uint8(tvb, offset)) != 0 && bMoreFlag)
1144 {
1145 /* get flags and type... */
1146 option = (hdr_byte & BSCVLC_HDR_OPTION_TYPE_MASK0x1F);
1147 bMustSegment = (hdr_byte & BSCVLC_HDR_MUST_UNDERSTAND0x40);
1148 bMoreFlag = (hdr_byte & BSCVLC_HDR_MORE_OPTIONS_FOLLOW0x80);
1149 bDataFlag = (hdr_byte & BSCVLC_HDR_DATA_PRESENT0x20);
1150 start = offset;
1151
1152 offset++;
1153
1154 if(bDataFlag)
1155 {
1156 npdu_length = (int)(tvb_get_uint8(tvb, offset++) << 8);
1157 npdu_length += (int)tvb_get_uint8(tvb, offset++);
1158 offset += npdu_length;
1159 }
1160
1161 if(bMustSegment)
1162 pszUnderstand = "must understand";
1163 else
1164 pszUnderstand = "optional";
1165
1166 switch(option)
1167 {
1168 case BSCVLC_HDR_OPT_SECURE_PATH0x01:
1169 pszOption = "secure path";
1170 break;
1171 case BSCVLC_HDR_OPT_HELLO0x02:
1172 pszOption = "hello";
1173 break;
1174 case BSCVLC_HDR_OPT_IDENTITY0x03:
1175 pszOption = "identity";
1176 break;
1177 case BSCVLC_HDR_OPT_HINT0x04:
1178 pszOption = "hint";
1179 break;
1180 case BSCVLC_HDR_OPT_TOKEN0x05:
1181 pszOption = "token";
1182 break;
1183 case BSCVLC_HDR_OPT_PROPRIETARY0x1F:
1184 pszOption = "proprietary";
1185 break;
1186 default:
1187 pszOption = "reserved by ASHREA";
1188 break;
1189 }
1190
1191 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, start, offset - start,
1192 ett_bscvlc_hdr, NULL((void*)0), "Destination %s option %s", pszUnderstand, pszOption);
1193 proto_tree_add_bitmask_value(subtree, tvb, start, hf_bscvlc_header,
1194 ett_bscvlc_hdr, bscvlc_header_flags, hdr_byte);
1195
1196 if(bDataFlag)
1197 {
1198 proto_tree_add_item(subtree, hf_bscvlc_header_length, tvb, start + 1, 2, ENC_BIG_ENDIAN0x00000000);
1199 switch(option)
1200 {
1201 case BSCVLC_HDR_OPT_HELLO0x02:
1202 proto_tree_add_bitmask_value(subtree, tvb, start + 3, hf_bscvlc_hello_opt,
1203 ett_bscvlc_hdr, bscvlc_hello1_opt_flags, tvb_get_uint8(tvb, start + 3));
1204 break;
1205 case BSCVLC_HDR_OPT_IDENTITY0x03:
1206 proto_tree_add_item(subtree, hf_bscvlc_identity_device_id, tvb, start + 3, 3, ENC_BIG_ENDIAN0x00000000);
1207 break;
1208 case BSCVLC_HDR_OPT_HINT0x04:
1209 bacnet_dissect_scope(tvb_new_subset_length(tvb, start, npdu_length + 3), pinfo, subtree, 3, "scope: ");
1210 break;
1211 case BSCVLC_HDR_OPT_TOKEN0x05:
1212 bacnet_dissect_token(tvb_new_subset_length(tvb, start, npdu_length + 3), pinfo, subtree, 3, "token: ");
1213 break;
1214 default:
1215 proto_tree_add_item(subtree, hf_bscvlc_header_data, tvb, start + 3, npdu_length, ENC_NA0x00000000);
1216 break;
1217 }
1218 }
1219 }
1220 }
1221
1222 if ((bvlc_control & BSCVLC_CONTROL_DATA_OPTION0x01) != 0)
1223 {
1224 bMoreFlag = true1;
1225
1226 while(tvb_reported_length_remaining(tvb, offset) > 0 &&
1227 (hdr_byte = tvb_get_uint8(tvb, offset)) != 0 && bMoreFlag)
1228 {
1229 /* get flags and type... */
1230 option = (hdr_byte & BSCVLC_HDR_OPTION_TYPE_MASK0x1F);
1231 bMustSegment = (hdr_byte & BSCVLC_HDR_EVERY_SEGMENT0x40);
1232 bMoreFlag = (hdr_byte & BSCVLC_HDR_MORE_OPTIONS_FOLLOW0x80);
1233 bDataFlag = (hdr_byte & BSCVLC_HDR_DATA_PRESENT0x20);
1234 start = offset;
1235
1236 offset++;
1237
1238 if(bDataFlag)
1239 {
1240 npdu_length = (int)(tvb_get_uint8(tvb, offset++) << 8);
1241 npdu_length += (int)tvb_get_uint8(tvb, offset++);
1242 offset += npdu_length;
1243 }
1244
1245 if(bMustSegment)
1246 pszUnderstand = "must understand";
1247 else
1248 pszUnderstand = "optional";
1249
1250 switch(option)
1251 {
1252 case BSCVLC_HDR_OPT_SECURE_PATH0x01:
1253 pszOption = "secure path";
1254 break;
1255 case BSCVLC_HDR_OPT_HELLO0x02:
1256 pszOption = "hello";
1257 break;
1258 case BSCVLC_HDR_OPT_IDENTITY0x03:
1259 pszOption = "identity";
1260 break;
1261 case BSCVLC_HDR_OPT_HINT0x04:
1262 pszOption = "hint";
1263 break;
1264 case BSCVLC_HDR_OPT_TOKEN0x05:
1265 pszOption = "token";
1266 break;
1267 case BSCVLC_HDR_OPT_PROPRIETARY0x1F:
1268 pszOption = "proprietary";
1269 break;
1270 default:
1271 pszOption = "reserved by ASHREA";
1272 break;
1273 }
1274
1275 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, start, offset - start,
1276 ett_bscvlc_hdr, NULL((void*)0), "Data %s option %s", pszUnderstand, pszOption);
1277 proto_tree_add_bitmask_value(subtree, tvb, start, hf_bscvlc_header,
1278 ett_bscvlc_hdr, bscvlc_header_flags, hdr_byte);
1279
1280 if(bDataFlag)
1281 {
1282 proto_tree_add_item(subtree, hf_bscvlc_header_length, tvb, start + 1, 2, ENC_BIG_ENDIAN0x00000000);
1283 switch(option)
1284 {
1285 case BSCVLC_HDR_OPT_HELLO0x02:
1286 proto_tree_add_bitmask_value(subtree, tvb, start + 3, hf_bscvlc_hello_opt,
1287 ett_bscvlc_hdr, bscvlc_hello1_opt_flags, tvb_get_uint8(tvb, start + 3));
1288 break;
1289 case BSCVLC_HDR_OPT_IDENTITY0x03:
1290 proto_tree_add_item(subtree, hf_bscvlc_identity_device_id, tvb, start + 3, 3, ENC_BIG_ENDIAN0x00000000);
1291 break;
1292 case BSCVLC_HDR_OPT_HINT0x04:
1293 bacnet_dissect_scope(tvb_new_subset_length(tvb, start, npdu_length + 3), pinfo, subtree, 3, "scope: ");
1294 break;
1295 case BSCVLC_HDR_OPT_TOKEN0x05:
1296 bacnet_dissect_token(tvb_new_subset_length(tvb, start, npdu_length + 3), pinfo, subtree, 3, "token: ");
1297 break;
1298 default:
1299 proto_tree_add_item(subtree, hf_bscvlc_header_data, tvb, start + 3, npdu_length, ENC_NA0x00000000);
1300 break;
1301 }
1302 }
1303 }
1304 }
1305
1306 switch (bvlc_function)
1307 {
1308 case 0x02: /* Address-Resolution */
1309 case 0x05: /* Advertisement-Solicitation */
1310 case 0x08: /* Disconnect-Request */
1311 case 0x09: /* Disconnect-ACK */
1312 case 0x0A: /* Heartbeat-Request */
1313 case 0x0B: /* Heartbeat-ACK */
1314 break;
1315 case 0x00: /* BVLC-Result */
1316 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset,
1317 ett_bscvlc_hdr, NULL((void*)0), "%s", "BVLC-Result");
1318 proto_tree_add_item(subtree, hf_bscvlc_function, tvb,
1319 offset, 1, ENC_NA0x00000000);
1320 offset++;
1321 proto_tree_add_item(subtree, hf_bscvlc_result, tvb,
1322 offset, 1, ENC_NA0x00000000);
1323 bvlc_result = tvb_get_uint8(tvb, offset);
1324 offset++;
1325
1326 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1327 val_to_str_const(bvlc_result, bscvlc_result_names, "unknown"));
1328
1329 if(bvlc_result)
1330 {
1331 proto_tree_add_item(subtree, hf_bscvlc_header_marker, tvb,
1332 offset, 1, ENC_NA0x00000000);
1333 offset++;
1334 proto_tree_add_item(subtree, hf_bscvlc_error_class, tvb,
1335 offset, 2, ENC_BIG_ENDIAN0x00000000);
1336 offset += 2;
1337 proto_tree_add_item(subtree, hf_bscvlc_error_code, tvb,
1338 offset, 2, ENC_BIG_ENDIAN0x00000000);
1339 offset += 2;
1340 proto_tree_add_item(subtree, hf_bscvlc_result_data, tvb,
1341 offset, packet_length - offset, ENC_NA0x00000000);
1342 }
1343 /* Force and of packet */
1344 offset = packet_length;
1345 break;
1346 case 0x03: /* Address-Resolution-ACK */
1347 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset,
1348 ett_bscvlc_hdr, NULL((void*)0), "%s", "Address-Resolution-ACK");
1349 proto_tree_add_item(subtree, hf_bscvlc_uris, tvb,
1350 offset, packet_length - offset, ENC_NA0x00000000);
1351 /* Force and of packet */
1352 offset = packet_length;
1353 break;
1354 case 0x04: /* Advertisement */
1355 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset,
1356 ett_bscvlc_hdr, NULL((void*)0), "%s", "Advertisement");
1357 proto_tree_add_item(subtree, hf_bscvlc_hub_conn_state, tvb,
1358 offset, 1, ENC_NA0x00000000);
1359 offset++;
1360 proto_tree_add_item(subtree, hf_bscvlc_accept_conns, tvb,
1361 offset, 1, ENC_NA0x00000000);
1362 offset++;
1363 proto_tree_add_item(subtree, hf_bscvlc_max_bvlc_length, tvb,
1364 offset, 2, ENC_BIG_ENDIAN0x00000000);
1365 offset += 2;
1366 proto_tree_add_item(subtree, hf_bscvlc_max_npdu_length, tvb,
1367 offset, 2, ENC_BIG_ENDIAN0x00000000);
1368 offset += 2;
1369 break;
1370 case 0x06: /* Connect-Request */
1371 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset,
1372 ett_bscvlc_hdr, NULL((void*)0), "%s", "Connect-Request");
1373 proto_tree_add_item(subtree, hf_bscvlc_connect_vmac, tvb,
1374 offset, 6, ENC_NA0x00000000);
1375 offset += 6;
1376 proto_tree_add_item(subtree, hf_bscvlc_connect_uuid, tvb,
1377 offset, 16, ENC_NA0x00000000);
1378 offset += 16;
1379 proto_tree_add_item(subtree, hf_bscvlc_max_bvlc_length, tvb,
1380 offset, 2, ENC_BIG_ENDIAN0x00000000);
1381 offset += 2;
1382 proto_tree_add_item(subtree, hf_bscvlc_max_npdu_length, tvb,
1383 offset, 2, ENC_BIG_ENDIAN0x00000000);
1384 offset += 2;
1385 break;
1386 case 0x07: /* Connect-Accept */
1387 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset,
1388 ett_bscvlc_hdr, NULL((void*)0), "%s", "Connect-Accept");
1389 proto_tree_add_item(subtree, hf_bscvlc_connect_vmac, tvb,
1390 offset, 6, ENC_NA0x00000000);
1391 offset += 6;
1392 proto_tree_add_item(subtree, hf_bscvlc_connect_uuid, tvb,
1393 offset, 16, ENC_NA0x00000000);
1394 offset += 16;
1395 proto_tree_add_item(subtree, hf_bscvlc_max_bvlc_length, tvb,
1396 offset, 2, ENC_BIG_ENDIAN0x00000000);
1397 offset += 2;
1398 proto_tree_add_item(subtree, hf_bscvlc_max_npdu_length, tvb,
1399 offset, 2, ENC_BIG_ENDIAN0x00000000);
1400 offset += 2;
1401 break;
1402 case 0x0C: /* Proprietary-Message */
1403 subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset,
1404 ett_bscvlc_hdr, NULL((void*)0), "%s", "Proprietary-Message");
1405 proto_tree_add_item(subtree, hf_bscvlc_vendor_id, tvb,
1406 offset, 2, ENC_BIG_ENDIAN0x00000000);
1407 offset += 2;
1408 proto_tree_add_item(subtree, hf_bscvlc_proprietary_opt_type, tvb,
1409 offset, 1, ENC_NA0x00000000);
1410 offset++;
1411 proto_tree_add_item(subtree, hf_bscvlc_proprietary_data, tvb,
1412 offset, packet_length - offset, ENC_NA0x00000000);
1413 /* Force and of packet */
1414 offset = packet_length;
1415 break;
1416 case 0x01: /* Encapsulated-NPDU */
1417 default:
1418 /* Here we assume additional payload belongs to upper layers and will be decoded later */
1419 break;
1420 }
1421
1422 /* Let the remaining frame to be decoded elsewhere */
1423 npdu_length = packet_length - offset;
1424 next_tvb = tvb_new_subset_length(tvb, offset, npdu_length);
1425 /* Code from Guy Harris */
1426 if (!dissector_try_uint(bscvlc_dissector_table,
1427 bvlc_function, next_tvb, pinfo, tree)) {
1428 /* Unknown function - dissect the payload as data */
1429 call_data_dissector(next_tvb, pinfo, tree);
1430 }
1431
1432 return tvb_reported_length(tvb);
1433}
1434
1435void
1436proto_register_bvlc(void)
1437{
1438 static hf_register_info hf[] = {
1439 { &hf_bvlc_type,
1440 { "Type", "bvlc.type",
1441 FT_UINT8, BASE_HEX, VALS(bvlc_types)((0 ? (const struct _value_string*)0 : ((bvlc_types)))), 0,
1442 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1443 },
1444 { &hf_bvlc_function,
1445 { "Function", "bvlc.function",
1446 FT_UINT8, BASE_HEX, VALS(bvlc_function_names)((0 ? (const struct _value_string*)0 : ((bvlc_function_names)
)))
, 0,
1447 "BVLC Function", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1448 },
1449 { &hf_bvlc_ipv6_function,
1450 { "Function", "bvlc.function_ipv6",
1451 FT_UINT8, BASE_HEX, VALS(bvlc_ipv6_function_names)((0 ? (const struct _value_string*)0 : ((bvlc_ipv6_function_names
))))
, 0,
1452 "BVLC Function IPV6", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1453 },
1454 { &hf_bvlc_length,
1455 { "BVLC-Length", "bvlc.length",
1456 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1457 "Length of BVLC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1458 },
1459 { &hf_bvlc_virt_source,
1460 { "BVLC-Virtual-Source", "bvlc.virtual_source",
1461 FT_UINT24, BASE_DEC_HEX, NULL((void*)0), 0,
1462 "Virtual source address of BVLC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1463 },
1464 { &hf_bvlc_virt_dest,
1465 { "BVLC-Virtual-Destination", "bvlc.virtual_dest",
1466 FT_UINT24, BASE_DEC_HEX, NULL((void*)0), 0,
1467 "Virtual destination address of BVLC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1468 },
1469 { &hf_bvlc_result_ip4,
1470 { "Result", "bvlc.result",
1471 FT_UINT16, BASE_HEX, VALS(bvlc_result_names)((0 ? (const struct _value_string*)0 : ((bvlc_result_names)))
)
, 0,
1472 "Result Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1473 },
1474 { &hf_bvlc_result_ip6,
1475 { "Result", "bvlc.result",
1476 FT_UINT16, BASE_HEX, VALS(bvlc_ipv6_result_names)((0 ? (const struct _value_string*)0 : ((bvlc_ipv6_result_names
))))
, 0,
1477 "Result Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1478 },
1479 { &hf_bvlc_bdt_ip,
1480 { "IP", "bvlc.bdt_ip",
1481 FT_IPv4, BASE_NONE, NULL((void*)0), 0,
1482 "BDT IP", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1483 },
1484 { &hf_bvlc_bdt_port,
1485 { "Port", "bvlc.bdt_port",
1486 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1487 "BDT Port", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1488 },
1489 { &hf_bvlc_bdt_mask,
1490 { "Mask", "bvlc.bdt_mask",
1491 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1492 "BDT Broadcast Distribution Mask", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1493 },
1494 { &hf_bvlc_reg_ttl,
1495 { "TTL", "bvlc.reg_ttl",
1496 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1497 "Foreign Device Time To Live", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1498 },
1499 { &hf_bvlc_fdt_ip,
1500 { "IP", "bvlc.fdt_ip",
1501 FT_IPv4, BASE_NONE, NULL((void*)0), 0,
1502 "FDT IP", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1503 },
1504 { &hf_bvlc_fdt_ipv6,
1505 { "IP", "bvlc.fdt_ipv6",
1506 FT_IPv6, BASE_NONE, NULL((void*)0), 0,
1507 "FDT IP", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1508 },
1509 { &hf_bvlc_fdt_port,
1510 { "Port", "bvlc.fdt_port",
1511 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1512 "FDT Port", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1513 },
1514 { &hf_bvlc_fdt_ttl,
1515 { "TTL", "bvlc.fdt_ttl",
1516 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1517 "Foreign Device Time To Live", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1518 },
1519 { &hf_bvlc_fdt_timeout,
1520 { "Timeout", "bvlc.fdt_timeout",
1521 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1522 "Foreign Device Timeout (seconds)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1523 },
1524 { &hf_bvlc_fwd_ip,
1525 { "IP", "bvlc.fwd_ip",
1526 FT_IPv4, BASE_NONE, NULL((void*)0), 0,
1527 "FWD IP", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1528 },
1529 { &hf_bvlc_fwd_port,
1530 { "Port", "bvlc.fwd_port",
1531 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1532 "FWD Port", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1533 },
1534 { &hf_bvlc_orig_source_addr,
1535 { "IP", "bvlc.orig_source_addr",
1536 FT_IPv6, BASE_NONE, NULL((void*)0), 0,
1537 "ORIG IP", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1538 },
1539 { &hf_bvlc_orig_source_port,
1540 { "Port", "bvlc.orig_source_port",
1541 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1542 "ORIG Port", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1543 },
1544 };
1545
1546 static int *ett[] = {
1547 &ett_bvlc,
1548 &ett_bdt,
1549 &ett_fdt,
1550 };
1551
1552 static hf_register_info bsc_hf[] = {
1553 { &hf_bscvlc_control,
1554 { "Control", "bscvlc.control",
1555 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1556 "BSCVLC Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1557 },
1558 { &hf_bscvlc_control_data_option,
1559 { "Data Option", "bscvlc.control_data_option",
1560 FT_BOOLEAN, 8, TFS(&control_data_option_set_high)((0 ? (const struct true_false_string*)0 : ((&control_data_option_set_high
))))
,
1561 BSCVLC_CONTROL_DATA_OPTION0x01, "BSCVLC Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1562 },
1563 { &hf_bscvlc_control_destination_option,
1564 { "Destination Option", "bscvlc.control_dest_option",
1565 FT_BOOLEAN, 8, TFS(&control_destination_option_set_high)((0 ? (const struct true_false_string*)0 : ((&control_destination_option_set_high
))))
,
1566 BSCVLC_CONTROL_DEST_OPTION0x02, "BSCVLC Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1567 },
1568 { &hf_bscvlc_control_destination_address,
1569 { "Destination Address","bscvlc.control_dest_address",
1570 FT_BOOLEAN, 8, TFS(&control_destination_address_set_high)((0 ? (const struct true_false_string*)0 : ((&control_destination_address_set_high
))))
,
1571 BSCVLC_CONTROL_DEST_ADDRESS0x04, "BSCVLC Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1572 },
1573 { &hf_bscvlc_control_origin_address,
1574 { "Origin Address", "bscvlc.control_orig_address",
1575 FT_BOOLEAN, 8, TFS(&control_orig_address_set_high)((0 ? (const struct true_false_string*)0 : ((&control_orig_address_set_high
))))
,
1576 BSCVLC_CONTROL_ORIG_ADDRESS0x08, "BSCVLC Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1577 },
1578 { &hf_bscvlc_control_reserved,
1579 { "Reserved", "bscvlc.control_reserved",
1580 FT_BOOLEAN, 8, TFS(&control_reserved_set_high)((0 ? (const struct true_false_string*)0 : ((&control_reserved_set_high
))))
,
1581 BSCVLC_CONTROL_RESERVED0xF0, "BSCVLC Control", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1582 },
1583 { &hf_bscvlc_header,
1584 { "Header Data Length", "bscvlc.header",
1585 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1586 "BSCVLC Header Control Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1587 },
1588 { &hf_bscvlc_header_marker,
1589 { "Header Error Marker","bscvlc.header_error_marker",
1590 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1591 "BSCVLC Header Error Marker", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1592 },
1593 { &hf_bscvlc_header_length,
1594 { "Header Data Length", "bscvlc.header_length",
1595 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1596 "BSCVLC Header Data Length", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1597 },
1598 { &hf_bscvlc_header_data,
1599 { "Header Data", "bscvlc.header_data",
1600 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1601 "BSCVLC Header Option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1602 },
1603 { &hf_bscvlc_header_opt_type,
1604 { "Header Type", "bscvlc.header_type",
1605 FT_UINT8, BASE_HEX, VALS(bscvlc_header_type_names)((0 ? (const struct _value_string*)0 : ((bscvlc_header_type_names
))))
,
1606 BSCVLC_HDR_OPTION_TYPE_MASK0x1F, "BSCVLC Header Option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1607 },
1608 { &hf_bscvlc_header_opt_data,
1609 { "Header Data", "bscvlc.header_data_present",
1610 FT_BOOLEAN, 8, TFS(&header_opt_data_set_high)((0 ? (const struct true_false_string*)0 : ((&header_opt_data_set_high
))))
,
1611 BSCVLC_HDR_DATA_PRESENT0x20, "BSCVLC Header Option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1612 },
1613 { &hf_bscvlc_header_opt_must_understand,
1614 { "Header Must Understand","bscvlc.header_understand",
1615 FT_BOOLEAN, 8, TFS(&header_opt_must_understand_set_high)((0 ? (const struct true_false_string*)0 : ((&header_opt_must_understand_set_high
))))
,
1616 BSCVLC_HDR_MUST_UNDERSTAND0x40, "BSCVLC Header Option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1617 },
1618 { &hf_bscvlc_header_opt_more,
1619 { "Header More", "bscvlc.header_more",
1620 FT_BOOLEAN, 8, TFS(&header_opt_more_set_high)((0 ? (const struct true_false_string*)0 : ((&header_opt_more_set_high
))))
,
1621 BSCVLC_HDR_MORE_OPTIONS_FOLLOW0x80, "BSCVLC Header Option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1622 },
1623 { &hf_bscvlc_vendor_id,
1624 { "Vendor ID", "bscvlc.vendor_id",
1625 FT_UINT16, BASE_HEX, NULL((void*)0), 0,
1626 "BSCVLC Vendor ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1627 },
1628 { &hf_bscvlc_proprietary_opt_type,
1629 { "Proprietary Type", "bscvlc.proprietary_type",
1630 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1631 "BSCVLC Proprietary Type", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1632 },
1633 { &hf_bscvlc_proprietary_data,
1634 { "Proprietary Data", "bscvlc.proprietary_data",
1635 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1636 "BSCVLC Proprietary Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1637 },
1638 { &hf_bscvlc_hub_conn_state,
1639 { "Hub Connection Status","bscvlc.hub_conn_state",
1640 FT_UINT8, BASE_HEX, VALS(bscvlc_hub_conn_state_names)((0 ? (const struct _value_string*)0 : ((bscvlc_hub_conn_state_names
))))
, 0,
1641 "BSCVLC Hub Connection Status", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1642 },
1643 { &hf_bscvlc_accept_conns,
1644 { "Hub Accepts Connections","bscvlc.accept_conns",
1645 FT_UINT8, BASE_HEX, VALS(bscvlc_hub_accept_conns_names)((0 ? (const struct _value_string*)0 : ((bscvlc_hub_accept_conns_names
))))
, 0,
1646 "BSCVLC Accepts Connections", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1647 },
1648 { &hf_bscvlc_max_bvlc_length,
1649 { "Max. BVLC Length", "bscvlc.max_bvlc_length",
1650 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1651 "Max Supported BVLC Length", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1652 },
1653 { &hf_bscvlc_max_npdu_length,
1654 { "Max. NPDU Length", "bscvlc.max_npdu_length",
1655 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1656 "Max Supported NPDU Length", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1657 },
1658 { &hf_bscvlc_function,
1659 { "Function", "bscvlc.function",
1660 FT_UINT8, BASE_HEX, VALS(bscvlc_function_names)((0 ? (const struct _value_string*)0 : ((bscvlc_function_names
))))
, 0,
1661 "BSCVLC Function", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1662 },
1663 { &hf_bscvlc_result,
1664 { "Result", "bscvlc.result",
1665 FT_UINT8, BASE_HEX, VALS(bscvlc_result_names)((0 ? (const struct _value_string*)0 : ((bscvlc_result_names)
)))
, 0,
1666 "Result Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1667 },
1668 { &hf_bscvlc_error_class,
1669 { "Error Class", "bscvlc.error_class",
1670 FT_UINT32, BASE_DEC, VALS(BACnetErrorClass)((0 ? (const struct _value_string*)0 : ((BACnetErrorClass)))), 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1671 },
1672 { &hf_bscvlc_error_code,
1673 { "Error Code", "bscvlc.error_code",
1674 FT_UINT32, BASE_DEC|BASE_EXT_STRING0x00000200, &BACnetErrorCode_ext, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1675 },
1676 { &hf_bscvlc_result_data,
1677 { "Result Data", "bscvlc.result_data",
1678 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1679 "BSCVLC Result Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1680 },
1681 { &hf_bscvlc_uris,
1682 { "URI's", "bscvlc.uris",
1683 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1684 "BSCVLC Address URI's", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1685 },
1686 { &hf_bscvlc_msg_id,
1687 { "Message ID", "bscvlc.msgid",
1688 FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1689 "BSCVLC Message ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1690 },
1691 { &hf_bscvlc_orig_vmac,
1692 { "SVMAC", "bscvlc.orig_virtual_address",
1693 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1694 "ORIG VMAC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1695 },
1696 { &hf_bscvlc_dest_vmac,
1697 { "DVMAC", "bscvlc.dest_virtual_address",
1698 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1699 "DEST VMAC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1700 },
1701 { &hf_bscvlc_connect_vmac,
1702 { "Connecting VMAC", "bscvlc.connect_virtual_address",
1703 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1704 "BSCVLC Connecting VMAC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1705 },
1706 { &hf_bscvlc_connect_uuid,
1707 { "Connecting UUID", "bscvlc.connect_uuid",
1708 FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1709 "BSCVLC Connecting UUID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1710 },
1711 { &hf_bscvlc_identity_device_id,
1712 { "Identity Device ID", "bscvlc.identity_device_id",
1713 FT_UINT24, BASE_DEC, NULL((void*)0), 0,
1714 "BSCVLC Identity Device ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1715 },
1716 { &hf_bscvlc_hello_opt,
1717 { "Hello option", "bscvlc.hello_opt",
1718 FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1719 "BSCVLC Hello option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1720 },
1721 { &hf_bscvlc_hello_opt_identity_relay,
1722 { "Hello Identity Relay","bscvlc.hello_opt_identity_relay",
1723 FT_BOOLEAN, 8, TFS(&hello_opt_identity_relay_set_high)((0 ? (const struct true_false_string*)0 : ((&hello_opt_identity_relay_set_high
))))
,
1724 BSCVLC_HELLO_IDENTITY_RELAY0x01, "BSCVLC Hello Option", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1725 },
1726 };
1727
1728 static int *bsc_ett[] = {
1729 &ett_bscvlc,
1730 &ett_bscvlc_ctrl,
1731 &ett_bscvlc_hdr
1732 };
1733
1734 proto_bvlc = proto_register_protocol("BACnet Virtual Link Control", "BVLC", "bvlc");
1735
1736 proto_register_field_array(proto_bvlc, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1737 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1738
1739 bvlc_handle = register_dissector("bvlc", dissect_bvlc, proto_bvlc);
1740
1741 bvlc_dissector_table = register_dissector_table("bvlc.function", "BVLC Function", proto_bvlc, FT_UINT8, BASE_HEX);
1742 bvlc_ipv6_dissector_table = register_dissector_table("bvlc.function_ipv6", "BVLC Function IPV6", proto_bvlc, FT_UINT8, BASE_HEX);
1743
1744 proto_bscvlc = proto_register_protocol("BACnet Secure Connect Virtual Link Control", "BSCVLC", "bscvlc");
1745
1746 proto_register_field_array(proto_bscvlc, bsc_hf, array_length(bsc_hf)(sizeof (bsc_hf) / sizeof (bsc_hf)[0]));
1747 proto_register_subtree_array(bsc_ett, array_length(bsc_ett)(sizeof (bsc_ett) / sizeof (bsc_ett)[0]));
1748
1749 bscvlc_handle = register_dissector("bscvlc", dissect_bscvlc, proto_bscvlc);
1750
1751 bscvlc_dissector_table = register_dissector_table("bscvlc.function", "BSCVLC Function", proto_bscvlc, FT_UINT8, BASE_HEX);
1752}
1753
1754void
1755proto_reg_handoff_bvlc(void)
1756{
1757 dissector_add_uint_with_preference("udp.port", BVLC_UDP_PORT0xBAC0, bvlc_handle);
1758 dissector_add_string("ws.protocol", "hub.bsc.bacnet.org", bscvlc_handle);
1759 dissector_add_string("ws.protocol", "dc.bsc.bacnet.org", bscvlc_handle);
1760}
1761
1762/*
1763 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1764 *
1765 * Local variables:
1766 * c-basic-offset: 8
1767 * tab-width: 8
1768 * indent-tabs-mode: t
1769 * End:
1770 *
1771 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1772 * :indentSize=8:tabSize=8:noTabs=false:
1773 */