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