Coverage Report

Created: 2025-02-15 06:25

/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
 */