Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-bacapp.c
Line
Count
Source
1
/* packet-bacapp.c
2
 * Routines for BACnet (APDU) dissection
3
 * Copyright 2001, Hartmut Mueller <hartmut[AT]abmlinux.org>, FH Dortmund
4
 * Enhanced by Steve Karg, 2005, <skarg[AT]users.sourceforge.net>, Atlanta
5
 * Enhanced by Herbert Lischka, 2005, <lischka[AT]kieback-peter.de>, Berlin
6
 * Enhanced by Felix Kraemer, 2010, <sauter-cumulus[AT]de.sauter-bc.com>,
7
 *  Sauter-Cumulus GmbH, Freiburg
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald[AT]wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include <epan/to_str.h>
20
#include <epan/strutil.h>
21
#include <epan/reassemble.h>
22
#include <epan/expert.h>
23
#include <epan/proto_data.h>
24
#include <epan/tfs.h>
25
#include <epan/stats_tree.h>
26
#include "packet-bacapp.h"
27
#include "data-bacnet.h"
28
29
static int bacapp_tap;
30
31
/* formerly bacapp.h  contains definitions and forward declarations */
32
33
/* BACnet PDU Types */
34
13.7k
#define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
35
1.31k
#define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
36
92
#define BACAPP_TYPE_SIMPLE_ACK                                  2
37
1.53k
#define BACAPP_TYPE_COMPLEX_ACK                                 3
38
118
#define BACAPP_TYPE_SEGMENT_ACK                                 4
39
794
#define BACAPP_TYPE_ERROR                                       5
40
60
#define BACAPP_TYPE_REJECT                                      6
41
106
#define BACAPP_TYPE_ABORT                                       7
42
#define MAX_BACAPP_TYPE                                         8
43
44
7.73k
#define BACAPP_SEGMENTED_REQUEST 0x08
45
245
#define BACAPP_MORE_SEGMENTS 0x04
46
#define BACAPP_SEGMENTED_RESPONSE 0x02
47
#define BACAPP_SEGMENT_NAK 0x02
48
#define BACAPP_SENT_BY 0x01
49
50
/**
51
 * dissect_bacapp ::= CHOICE {
52
 *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
53
 *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
54
 *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
55
 *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
56
 *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
57
 *  error-PDU                   [5] BACnet-Error-PDU,
58
 *  reject-PDU                  [6] BACnet-Reject-PDU,
59
 *  abort-PDU                   [7] BACnet-Abort-PDU
60
 * }
61
 * @param tvb the tv buffer of the current data
62
 * @param pinfo the packet info of the current data
63
 * @param tree the tree to append this item to
64
 **/
65
66
/**
67
 * ConfirmedRequest-PDU ::= SEQUENCE {
68
 *  pdu-type                    [0] Unsigned (0..15), -- 0 for this PDU Type
69
 *  segmentedMessage            [1] BOOLEAN,
70
 *  moreFollows                 [2] BOOLEAN,
71
 *  segmented-response-accepted [3] BOOLEAN,
72
 *  reserved                    [4] Unsigned (0..3), -- must be set zero
73
 *  max-segments-accepted       [5] Unsigned (0..7), -- as per 20.1.2.4
74
 *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
75
 *  invokeID                    [6] Unsigned (0..255),
76
 *  sequence-number             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
77
 *  proposed-window-size        [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
78
 *  service-choice              [9] BACnetConfirmedServiceChoice,
79
 *  service-request             [10] BACnet-Confirmed-Service-Request OPTIONAL
80
 * }
81
 * @param tvb the tv buffer of the current data
82
 * @param pinfo the packet info of the current data
83
 * @param tree the tree to append this item to
84
 * @param offset the offset in the tvb
85
 * @return modified offset
86
 */
87
static unsigned
88
fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
89
90
/**
91
 * @param tvb the tv buffer of the current data
92
 * @param pinfo the packet info of the current data
93
 * @param tree the tree to append this item to
94
 * @param offset the offset in the tvb
95
 * @param ack - indicates whether working on request or ack
96
 * @param svc - output variable to return service choice
97
 * @param tt  - output varable to return service choice item
98
 * @return modified offset
99
 */
100
static unsigned
101
fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t ack,
102
                int *svc, proto_item **tt);
103
104
/**
105
 * Unconfirmed-Request-PDU ::= SEQUENCE {
106
 *  pdu-type        [0] Unsigned (0..15), -- 1 for this PDU type
107
 *  reserved        [1] Unsigned (0..15), -- must be set zero
108
 *  service-choice  [2] BACnetUnconfirmedServiceChoice,
109
 *  service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
110
 * }
111
 * @param tvb the tv buffer of the current data
112
 * @param pinfo the packet info of the current data
113
 * @param tree the tree to append this item to
114
 * @param offset the offset in the tvb
115
 * @return modified offset
116
 */
117
static unsigned
118
fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
119
120
/**
121
 * SimpleACK-PDU ::= SEQUENCE {
122
 *  pdu-type            [0] Unsigned (0..15), -- 2 for this PDU type
123
 *  reserved            [1] Unsigned (0..15), -- must be set zero
124
 *  invokeID            [2] Unsigned (0..255),
125
 *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
126
 * }
127
 * @param tvb the tv buffer of the current data
128
 * @param pinfo the packet info of the current data
129
 * @param tree the tree to append this item to
130
 * @param offset the offset in the tvb
131
 * @return modified offset
132
 */
133
static unsigned
134
fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
135
136
/**
137
 * ComplexACK-PDU ::= SEQUENCE {
138
 *  pdu-type                [0] Unsigned (0..15), -- 3 for this PDU Type
139
 *  segmentedMessage        [1] BOOLEAN,
140
 *  moreFollows             [2] BOOLEAN,
141
 *  reserved                [3] Unsigned (0..3), -- must be set zero
142
 *  invokeID                [4] Unsigned (0..255),
143
 *  sequence-number         [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
144
 *  proposed-window-size    [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
145
 *  service-ACK-choice      [7] BACnetConfirmedServiceChoice,
146
 *  service-ACK             [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
147
 * }
148
 * @param tvb the tv buffer of the current data
149
 * @param pinfo the packet info of the current data
150
 * @param tree the tree to append this item to
151
 * @param offset the offset in the tvb
152
 * @return modified offset
153
 */
154
static unsigned
155
fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
156
157
/**
158
 * SegmentACK-PDU ::= SEQUENCE {
159
 *  pdu-type                [0] Unsigned (0..15), -- 4 for this PDU Type
160
 *  reserved                [1] Unsigned (0..3), -- must be set zero
161
 *  negative-ACK            [2] BOOLEAN,
162
 *  server                  [3] BOOLEAN,
163
 *  original-invokeID       [4] Unsigned (0..255),
164
 *  sequence-number         [5] Unsigned (0..255),
165
 *  actual-window-size      [6] Unsigned (0..127)
166
 * }
167
 * @param tvb the tv buffer of the current data
168
 * @param pinfo the packet info of the current data
169
 * @param tree the tree to append this item to
170
 * @param offset the offset in the tvb
171
 * @return modified offset
172
 */
173
static unsigned
174
fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
175
176
/**
177
 * Error-PDU ::= SEQUENCE {
178
 *  pdu-type                [0] Unsigned (0..15), -- 5 for this PDU Type
179
 *  reserved                [1] Unsigned (0..3), -- must be set zero
180
 *  original-invokeID       [2] Unsigned (0..255),
181
 *  error-choice            [3] BACnetConfirmedServiceChoice,
182
 *  error                   [4] BACnet-Error
183
 * }
184
 * @param tvb the tv buffer of the current data
185
 * @param pinfo the packet info of the current data
186
 * @param tree the tree to append this item to
187
 * @param offset the offset in the tvb
188
 * @return modified offset
189
 */
190
static unsigned
191
fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
192
193
/**
194
 * Reject-PDU ::= SEQUENCE {
195
 *  pdu-type                [0] Unsigned (0..15), -- 6 for this PDU Type
196
 *  reserved                [1] Unsigned (0..3), -- must be set zero
197
 *  original-invokeID       [2] Unsigned (0..255),
198
 *  reject-reason           [3] BACnetRejectReason
199
 * }
200
 * @param tvb the tv buffer of the current data
201
 * @param pinfo the packet info of the current data
202
 * @param tree the tree to append this item to
203
 * @param offset the offset in the tvb
204
 * @return modified offset
205
 */
206
static unsigned
207
fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
208
209
/**
210
 * Abort-PDU ::= SEQUENCE {
211
 *  pdu-type                [0] Unsigned (0..15), -- 7 for this PDU Type
212
 *  reserved                [1] Unsigned (0..3), -- must be set zero
213
 *  server                  [2] BOOLEAN,
214
 *  original-invokeID       [3] Unsigned (0..255),
215
 *  abort-reason            [4] BACnetAbortReason
216
 * }
217
 * @param tvb the tv buffer of the current data
218
 * @param pinfo the packet info of the current data
219
 * @param tree the tree to append this item to
220
 * @param offset the offset in the tvb
221
 * @return modified offset
222
 */
223
static unsigned
224
fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
225
226
/**
227
 * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
228
 * @param tvb the tv buffer of the current data
229
 * @param pinfo the packet info of the current data
230
 * @param tree the tree to append this item to
231
 * @param offset the offset in the tvb
232
 * @param label the label of this item
233
 * @return modified offset
234
 */
235
static unsigned
236
fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
237
238
/**
239
 * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
240
 * @param tvb the tv buffer of the current data
241
 * @param pinfo the packet info of the current data
242
 * @param tree the tree to append this item to
243
 * @param offset the offset in the tvb
244
 * @param label the label of this item
245
 * @return modified offset
246
 */
247
static unsigned
248
fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
249
250
/**
251
 * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
252
 * @param tvb the tv buffer of the current data
253
 * @param pinfo the packet info of the current data
254
 * @param tree the tree to append this item to
255
 * @param offset the offset in the tvb
256
 * @param label the label of this item
257
 * @param lvt length of String
258
 * @return modified offset
259
 */
260
static unsigned
261
fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt);
262
263
/**
264
 * 20.2.12, adds the label with Date Value to tree
265
 * @param tvb the tv buffer of the current data
266
 * @param pinfo the packet info of the current data
267
 * @param tree the tree to append this item to
268
 * @param offset the offset in the tvb
269
 * @param label the label of this item
270
 * @return modified offset
271
 */
272
static unsigned
273
fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
274
275
/**
276
 * 20.2.13, adds the label with Time Value to tree
277
 * @param tvb the tv buffer of the current data
278
 * @param pinfo the packet info of the current data
279
 * @param tree the tree to append this item to
280
 * @param offset the offset in the tvb
281
 * @param label the label of this item
282
 * @return modified offset
283
 */
284
static unsigned
285
fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
286
287
/**
288
 * 20.2.14, adds Object Identifier to tree
289
 * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
290
 * @param tvb the tv buffer of the current data
291
 * @param pinfo the packet info of the current data
292
 * @param tree the tree to append this item to
293
 * @param offset the offset in the tvb
294
 * @param hfid the hfid of the item to use (e.g., hf_bacapp_object_identifier
295
 *  or hf_bacapp_device_identifier)
296
 * @return modified offset
297
 */
298
static unsigned
299
fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int hfid);
300
301
/**
302
 * BACnet-Confirmed-Service-Request ::= CHOICE {
303
 * }
304
 * @param tvb the tv buffer of the current data
305
 * @param pinfo the packet info of the current data
306
 * @param tree the tree to append this item to
307
 * @param offset the offset in the tvb
308
 * @param service_choice the service choice
309
 * @return offset
310
 */
311
static unsigned
312
fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
313
314
/**
315
 * BACnet-Confirmed-Service-ACK ::= CHOICE {
316
 * }
317
 * @param tvb the tv buffer of the current data
318
 * @param pinfo the packet info of the current data
319
 * @param tree the tree to append this item to
320
 * @param offset the offset in the tvb
321
 * @param service_choice the service choice
322
 * @return offset
323
 */
324
static unsigned
325
fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
326
327
/**
328
 * AcknowledgeAlarm-Request ::= SEQUENCE {
329
 *  acknowledgingProcessIdentifier [0] Unsigned32,
330
 *  eventObjectIdentifier          [1] BACnetObjectIdentifier,
331
 *  eventStateAcknowledge          [2] BACnetEventState,
332
 *  timeStamp                      [3] BACnetTimeStamp,
333
 *  acknowledgementSource          [4] Character String,
334
 *  timeOfAcknowledgement          [5] BACnetTimeStamp
335
 * }
336
 * @param tvb the tv buffer of the current data
337
 * @param pinfo the packet info of the current data
338
 * @param tree the tree to append this item to
339
 * @param offset the offset in the tvb
340
 * @return modified offset
341
 */
342
static unsigned
343
fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
344
345
/**
346
 * ConfirmedCOVNotification-Request ::= SEQUENCE {
347
 *  subscriberProcessIdentifier [0] Unsigned32,
348
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
349
 *  monitoredObjectIdentifier   [2] BACnetObjectIdentifier,
350
 *  timeRemaining               [3] unsigned,
351
 *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
352
 * }
353
 * @param tvb the tv buffer of the current data
354
 * @param pinfo the packet info of the current data
355
 * @param tree the tree to append this item to
356
 * @param offset the offset in the tvb
357
 * @return modified offset
358
 */
359
static unsigned
360
fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
361
362
/**
363
 * ConfirmedEventNotification-Request ::= SEQUENCE {
364
 *  ProcessIdentifier           [0] Unsigned32,
365
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
366
 *  eventObjectIdentifier       [2] BACnetObjectIdentifier,
367
 *  timeStamp                   [3] BACnetTimeStamp,
368
 *  notificationClass           [4] unsigned,
369
 *  priority                    [5] unsigned8,
370
 *  eventType                   [6] BACnetEventType,
371
 *  messageText                 [7] CharacterString OPTIONAL,
372
 *  notifyType                  [8] BACnetNotifyType,
373
 *  ackRequired                 [9] BOOLEAN OPTIONAL,
374
 *  fromState                  [10] BACnetEventState OPTIONAL,
375
 *  toState                    [11] BACnetEventState,
376
 *  eventValues                [12] BACnetNotificationParameters OPTIONAL
377
 * }
378
 * @param tvb the tv buffer of the current data
379
 * @param pinfo the packet info of the current data
380
 * @param tree the tree to append this item to
381
 * @param offset the offset in the tvb
382
 * @return modified offset
383
 */
384
static unsigned
385
fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, unsigned offset);
386
387
/**
388
 * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
389
 *  objectIdentifier         BACnetObjectIdentifier,
390
 *  alarmState               BACnetEventState,
391
 *  acknowledgedTransitions  BACnetEventTransitionBits
392
 * }
393
 * @param tvb the tv buffer of the current data
394
 * @param pinfo the packet info of the current data
395
 * @param tree the tree to append this item to
396
 * @param offset the offset in the tvb
397
 * @return modified offset
398
 */
399
static unsigned
400
fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
401
402
/**
403
 * GetEnrollmentSummary-Request ::= SEQUENCE {
404
 *  acknowledgmentFilter    [0] ENUMERATED {
405
 *      all       (0),
406
 *      acked     (1),
407
 *      not-acked (2)
408
 *      },
409
 *  enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
410
 *  eventStateFilter        [2] ENUMERATED {
411
 *      offnormal (0),
412
 *      fault     (1),
413
 *      normal    (2),
414
 *      all       (3),
415
 *      active    (4)
416
 *      },
417
 *  eventTypeFilter         [3] BACnetEventType OPTIONAL,
418
 *  priorityFilter          [4] SEQUENCE {
419
 *      minPriority [0] Unsigned8,
420
 *      maxPriority [1] Unsigned8
421
 *      } OPTIONAL,
422
 *  notificationClassFilter [5] Unsigned OPTIONAL
423
 * }
424
 * @param tvb the tv buffer of the current data
425
 * @param pinfo the packet info of the current data
426
 * @param tree the tree to append this item to
427
 * @param offset the offset in the tvb
428
 * @return modified offset
429
 */
430
static unsigned
431
fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
432
433
/**
434
 * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
435
 *  objectIdentifier    BACnetObjectIdentifier,
436
 *  eventType           BACnetEventType,
437
 *  eventState          BACnetEventState,
438
 *  priority            Unsigned8,
439
 *  notificationClass   Unsigned OPTIONAL
440
 * }
441
 * @param tvb the tv buffer of the current data
442
 * @param pinfo the packet info of the current data
443
 * @param tree the tree to append this item to
444
 * @param offset the offset in the tvb
445
 * @return modified offset
446
 */
447
static unsigned
448
fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
449
450
/**
451
 * GetEventInformation-Request ::= SEQUENCE {
452
 *  lastReceivedObjectIdentifier    [0] BACnetObjectIdentifier
453
 * }
454
 * @param tvb the tv buffer of the current data
455
 * @param pinfo the packet info of the current data
456
 * @param tree the tree to append this item to
457
 * @param offset the offset in the tvb
458
 * @return modified offset
459
 */
460
static unsigned
461
fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
462
463
/**
464
 * GetEventInformation-ACK ::= SEQUENCE {
465
 *  listOfEventSummaries [0] listOfEventSummaries,
466
 *  moreEvents           [1] BOOLEAN
467
 * }
468
 * @param tvb the tv buffer of the current data
469
 * @param pinfo the packet info of the current data
470
 * @param tree the tree to append this item to
471
 * @param offset the offset in the tvb
472
 * @return modified offset
473
 */
474
static unsigned
475
fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
476
477
/**
478
 * LifeSafetyOperation-Request ::= SEQUENCE {
479
 *  requestingProcessIdentifier [0] Unsigned32
480
 *  requestingSource            [1] CharacterString
481
 *  request                     [2] BACnetLifeSafetyOperation
482
 *  objectIdentifier            [3] BACnetObjectIdentifier OPTIONAL
483
 * }
484
 * @param tvb the tv buffer of the current data
485
 * @param pinfo the packet info of the current data
486
 * @param tree the tree to append this item to
487
 * @param offset the offset in the tvb
488
 * @return modified offset
489
 */
490
static unsigned
491
fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
492
493
/**
494
 * SubscribeCOV-Request ::= SEQUENCE {
495
 *  subscriberProcessIdentifier [0] Unsigned32
496
 *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
497
 *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
498
 *  lifetime                    [3] Unsigned OPTIONAL
499
 * }
500
 * @param tvb the tv buffer of the current data
501
 * @param pinfo the packet info of the current data
502
 * @param tree the tree to append this item to
503
 * @param offset the offset in the tvb
504
 * @return modified offset
505
 */
506
static unsigned
507
fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
508
509
/**
510
 * SubscribeCOVProperty-Request ::= SEQUENCE {
511
 *  subscriberProcessIdentifier [0] Unsigned32
512
 *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
513
 *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
514
 *  lifetime                    [3] Unsigned OPTIONAL
515
 *  monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
516
 *  covIncrement                [5] Unsigned OPTIONAL
517
 * }
518
 * @param tvb the tv buffer of the current data
519
 * @param pinfo the packet info of the current data
520
 * @param tree the tree to append this item to
521
 * @param offset the offset in the tvb
522
 * @return modified offset
523
 */
524
static unsigned
525
fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
526
527
/**
528
 * AtomicReadFile-Request ::= SEQUENCE {
529
 *  fileIdentifier  BACnetObjectIdentifier,
530
 *  accessMethod    CHOICE {
531
 *      streamAccess    [0] SEQUENCE {
532
 *          fileStartPosition   INTEGER,
533
 *          requestedOctetCount Unsigned
534
 *          },
535
 *      recordAccess    [1] SEQUENCE {
536
 *          fileStartRecord      INTEGER,
537
 *          requestedRecordCount Unsigned
538
 *          }
539
 *      }
540
 * }
541
 * @param tvb the tv buffer of the current data
542
 * @param pinfo the packet info of the current data
543
 * @param tree the tree to append this item to
544
 * @param offset the offset in the tvb
545
 * @return modified offset
546
 */
547
static unsigned
548
fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
549
550
/**
551
 * AtomicWriteFile-ACK ::= SEQUENCE {
552
 *  endOfFile   BOOLEAN,
553
 *  accessMethod    CHOICE {
554
 *      streamAccess    [0] SEQUENCE {
555
 *          fileStartPosition   INTEGER,
556
 *          fileData            OCTET STRING
557
 *          },
558
 *      recordAccess    [1] SEQUENCE {
559
 *          fileStartRecord     INTEGER,
560
 *          returnedRecordCount Unsigned,
561
 *          fileRecordData      SEQUENCE OF OCTET STRING
562
 *          }
563
 *      }
564
 * }
565
 * @param tvb the tv buffer of the current data
566
 * @param pinfo the packet info of the current data
567
 * @param tree the tree to append this item to
568
 * @param offset the offset in the tvb
569
 * @return modified offset
570
 */
571
static unsigned
572
fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
573
574
/**
575
 * AtomicWriteFile-Request ::= SEQUENCE {
576
 *  fileIdentifier  BACnetObjectIdentifier,
577
 *  accessMethod    CHOICE {
578
 *      streamAccess    [0] SEQUENCE {
579
 *          fileStartPosition  INTEGER,
580
 *          fileData           OCTET STRING
581
 *          },
582
 *      recordAccess    [1] SEQUENCE {
583
 *          fileStartRecord    INTEGER,
584
 *          recordCount        Unsigned,
585
 *          fileRecordData     SEQUENCE OF OCTET STRING
586
 *          }
587
 *      }
588
 * }
589
 * @param tvb the tv buffer of the current data
590
 * @param pinfo the packet info of the current data
591
 * @param tree the tree to append this item to
592
 * @param offset the offset in the tvb
593
 * @return modified offset
594
 */
595
static unsigned
596
fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
597
598
/**
599
 * AtomicWriteFile-ACK ::= SEQUENCE {
600
 *      fileStartPosition [0] INTEGER,
601
 *      fileStartRecord   [1] INTEGER,
602
 * }
603
 * @param tvb the tv buffer of the current data
604
 * @param pinfo the packet info of the current data
605
 * @param tree the tree to append this item to
606
 * @param offset the offset in the tvb
607
 * @return modified offset
608
 */
609
static unsigned
610
fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
611
612
/**
613
 * AddListElement-Request ::= SEQUENCE {
614
 *  objectIdentifier   [0] BACnetObjectIdentifier,
615
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
616
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
617
 *  listOfElements     [3] ABSTRACT-SYNTAX.&Type
618
 * }
619
 * @param tvb the tv buffer of the current data
620
 * @param pinfo the packet info of the current data
621
 * @param tree the tree to append this item to
622
 * @param offset the offset in the tvb
623
 * @return modified offset
624
 */
625
static unsigned
626
fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
627
628
/**
629
 * CreateObject-Request ::= SEQUENCE {
630
 *  objectSpecifier     [0] ObjectSpecifier,
631
 *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
632
 * }
633
 * @param tvb the tv buffer of the current data
634
 * @param pinfo the packet info of the current data
635
 * @param subtree the sub tree to append this item to
636
 * @param offset the offset in the tvb
637
 * @return modified offset
638
 */
639
static unsigned
640
fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
641
642
/**
643
 * CreateObject-Request ::= BACnetObjectIdentifier
644
 * @param tvb the tv buffer of the current data
645
 * @param pinfo the packet info of the current data
646
 * @param tree the tree to append this item to
647
 * @param offset the offset in the tvb
648
 * @return modified offset
649
 */
650
static unsigned
651
fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
652
653
/**
654
 * DeleteObject-Request ::= SEQUENCE {
655
 *  ObjectIdentifier    BACnetObjectIdentifier
656
 * }
657
 * @param tvb the tv buffer of the current data
658
 * @param pinfo the packet info of the current data
659
 * @param tree the tree to append this item to
660
 * @param offset the offset in the tvb
661
 * @return modified offset
662
 */
663
static unsigned
664
fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
665
666
/**
667
 * ReadProperty-Request ::= SEQUENCE {
668
 *  objectIdentifier    [0] BACnetObjectIdentifier,
669
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
670
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
671
 * }
672
 * @param tvb the tv buffer of the current data
673
 * @param pinfo the packet info of the current data
674
 * @param tree the tree to append this item to
675
 * @param offset the offset in the tvb
676
 * @return modified offset
677
 */
678
static unsigned
679
fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
680
681
/**
682
 * ReadProperty-ACK ::= SEQUENCE {
683
 *  objectIdentifier   [0] BACnetObjectIdentifier,
684
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
685
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
686
 *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
687
 * }
688
 * @param tvb the tv buffer of the current data
689
 * @param pinfo the packet info of the current data
690
 * @param tree the tree to append this item to
691
 * @param offset the offset in the tvb
692
 * @return modified offset
693
 */
694
static unsigned
695
fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
696
697
/**
698
 * ReadPropertyConditional-Request ::= SEQUENCE {
699
 *  objectSelectionCriteria  [0] objectSelectionCriteria,
700
 *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
701
 * }
702
 * @param tvb the tv buffer of the current data
703
 * @param pinfo the packet info of the current data
704
 * @param subtree the  sub tree to append this item to
705
 * @param offset the offset in the tvb
706
 * @return modified offset
707
 */
708
static unsigned
709
fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
710
711
/**
712
 * ReadPropertyConditional-ACK ::= SEQUENCE {
713
 *  listOfPReadAccessResults    SEQUENCE OF ReadAccessResult OPTIONAL
714
 * }
715
 * @param tvb the tv buffer of the current data
716
 * @param pinfo the packet info of the current data
717
 * @param tree the tree to append this item to
718
 * @param offset the offset in the tvb
719
 * @return modified offset
720
 */
721
static unsigned
722
fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
723
724
/**
725
 * ReadPropertyMultiple-Request ::= SEQUENCE {
726
 *  listOfReadAccessSpecs   SEQUENCE OF ReadAccessSpecification
727
 * }
728
 * @param tvb the tv buffer of the current data
729
 * @param pinfo the packet info of the current data
730
 * @param subtree the sub tree to append this item to
731
 * @param offset the offset in the tvb
732
 * @return offset modified
733
 */
734
static unsigned
735
fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
736
737
/**
738
 * ReadPropertyMultiple-Ack ::= SEQUENCE {
739
 *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
740
 * }
741
 * @param tvb the tv buffer of the current data
742
 * @param pinfo the packet info of the current data
743
 * @param tree the tree to append this item to
744
 * @param offset the offset in the tvb
745
 * @return offset modified
746
 */
747
static unsigned
748
fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
749
750
/**
751
 * ReadRange-Request ::= SEQUENCE {
752
 *  objectIdentifier    [0] BACnetObjectIdentifier,
753
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
754
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
755
 *  range   CHOICE {
756
 *      byPosition  [3] SEQUENCE {
757
 *          referencedIndex Unsigned,
758
 *          count INTEGER
759
 *          },
760
 *      byTime      [4] SEQUENCE {
761
 *          referenceTime BACnetDateTime,
762
 *          count INTEGER
763
 *          },
764
 *      timeRange   [5] SEQUENCE {
765
 *          beginningTime BACnetDateTime,
766
 *          endingTime BACnetDateTime
767
 *          },
768
 *      } OPTIONAL
769
 * }
770
 * @param tvb the tv buffer of the current data
771
 * @param pinfo the packet info of the current data
772
 * @param tree the tree to append this item to
773
 * @param offset the offset in the tvb
774
 * @return modified offset
775
 */
776
static unsigned
777
fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
778
779
/**
780
 * ReadRange-ACK ::= SEQUENCE {
781
 *  objectIdentifier   [0] BACnetObjectIdentifier,
782
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
783
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
784
 *  resultFlags        [3] BACnetResultFlags,
785
 *  itemCount          [4] Unsigned,
786
 *  itemData           [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
787
 * }
788
 * @param tvb the tv buffer of the current data
789
 * @param pinfo the packet info of the current data
790
 * @param tree the tree to append this item to
791
 * @param offset the offset in the tvb
792
 * @return modified offset
793
 */
794
static unsigned
795
fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
796
797
/**
798
 * RemoveListElement-Request ::= SEQUENCE {
799
 *  objectIdentifier    [0] BACnetObjectIdentifier,
800
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
801
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
802
 *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
803
 * }
804
 * @param tvb the tv buffer of the current data
805
 * @param pinfo the packet info of the current data
806
 * @param tree the tree to append this item to
807
 * @param offset the offset in the tvb
808
 * @return modified offset
809
 */
810
static unsigned
811
fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
812
813
/**
814
 * WriteProperty-Request ::= SEQUENCE {
815
 *  objectIdentifier   [0] BACnetObjectIdentifier,
816
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
817
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
818
 *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
819
 *  priority           [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
820
 * }
821
 * @param tvb the tv buffer of the current data
822
 * @param pinfo the packet info of the current data
823
 * @param tree the tree to append this item to
824
 * @param offset the offset in the tvb
825
 * @return modified offset
826
 */
827
static unsigned
828
fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
829
830
/**
831
 * WritePropertyMultiple-Request ::= SEQUENCE {
832
 *  listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
833
 * }
834
 * @param tvb the tv buffer of the current data
835
 * @param pinfo the packet info of the current data
836
 * @param tree the tree to append this item to
837
 * @param offset the offset in the tvb
838
 * @return modified offset
839
 */
840
static unsigned
841
fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
842
843
/**
844
 * DeviceCommunicationControl-Request ::= SEQUENCE {
845
 *  timeDuration    [0] Unsigned16 OPTIONAL,
846
 *  enable-disable  [1] ENUMERATED {
847
 *      enable  (0),
848
 *      disable (1)
849
 *      },
850
 *  password        [2] CharacterString (SIZE(1..20)) OPTIONAL
851
 * }
852
 * @param tvb the tv buffer of the current data
853
 * @param pinfo the packet info of the current data
854
 * @param tree the tree to append this item to
855
 * @param offset the offset in the tvb
856
 * @return modified offset
857
 */
858
static unsigned
859
fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
860
861
/**
862
 * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
863
 *  vendorID          [0] Unsigned,
864
 *  serviceNumber     [1] Unsigned,
865
 *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
866
 * }
867
 * @param tvb the tv buffer of the current data
868
 * @param pinfo the packet info of the current data
869
 * @param tree the tree to append this item to
870
 * @param offset the offset in the tvb
871
 * @return modified offset
872
 */
873
static unsigned
874
fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
875
876
/**
877
 * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
878
 *  vendorID      [0] Unsigned,
879
 *  serviceNumber [1] Unsigned,
880
 *  resultBlock   [2] ABSTRACT-SYNTAX.&Type OPTIONAL
881
 * }
882
 * @param tvb the tv buffer of the current data
883
 * @param pinfo the packet info of the current data
884
 * @param tree the tree to append this item to
885
 * @param offset the offset in the tvb
886
 * @return modified offset
887
 */
888
static unsigned
889
fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
890
891
/**
892
 * ConfirmedTextMessage-Request ::=  SEQUENCE {
893
 *  textMessageSourceDevice [0] BACnetObjectIdentifier,
894
 *  messageClass            [1] CHOICE {
895
 *      numeric   [0] Unsigned,
896
 *      character [1] CharacterString
897
 *      } OPTIONAL,
898
 *  messagePriority         [2] ENUMERATED {
899
 *      normal (0),
900
 *      urgent (1)
901
 *      },
902
 *  message [3] CharacterString
903
 * }
904
 * @param tvb the tv buffer of the current data
905
 * @param pinfo the packet info of the current data
906
 * @param tree the tree to append this item to
907
 * @param offset the offset in the tvb
908
 * @return modified offset
909
 */
910
static unsigned
911
fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
912
913
/**
914
 * ReinitializeDevice-Request ::= SEQUENCE {
915
 *  reinitializedStateOfDevice  [0] ENUMERATED {
916
 *      coldstart    (0),
917
 *      warmstart    (1),
918
 *      startbackup  (2),
919
 *      endbackup    (3),
920
 *      startrestore (4),
921
 *      endrestore   (5),
922
 *      abortrestor  (6)
923
 *      },
924
 *  password                    [1] CharacterString (SIZE(1..20)) OPTIONAL
925
 * }
926
 * @param tvb the tv buffer of the current data
927
 * @param pinfo the packet info of the current data
928
 * @param tree the tree to append this item to
929
 * @param offset the offset in the tvb
930
 * @return modified offset
931
 */
932
static unsigned
933
fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
934
935
/**
936
 * VTOpen-Request ::= SEQUENCE {
937
 *  vtClass BACnetVTClass,
938
 *  localVTSessionIdentifier    Unsigned8
939
 * }
940
 * @param tvb the tv buffer of the current data
941
 * @param pinfo the packet info of the current data
942
 * @param tree the tree to append this item to
943
 * @param offset the offset in the tvb
944
 * @return modified offset
945
 */
946
static unsigned
947
fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
948
949
/**
950
 * VTOpen-ACK ::= SEQUENCE {
951
 *  remoteVTSessionIdentifier   Unsigned8
952
 * }
953
 * @param tvb the tv buffer of the current data
954
 * @param pinfo the packet info of the current data
955
 * @param tree the tree to append this item to
956
 * @param offset the offset in the tvb
957
 * @return modified offset
958
 */
959
static unsigned
960
fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
961
962
/**
963
 * VTClose-Request ::= SEQUENCE {
964
 *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
965
 * }
966
 * @param tvb the tv buffer of the current data
967
 * @param pinfo the packet info of the current data
968
 * @param tree the tree to append this item to
969
 * @param offset the offset in the tvb
970
 * @return modified offset
971
 */
972
static unsigned
973
fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
974
975
/**
976
 * VTData-Request ::= SEQUENCE {
977
 *  vtSessionIdentifier Unsigned8,
978
 *  vtNewData           OCTET STRING,
979
 *  vtDataFlag          Unsigned (0..1)
980
 * }
981
 * @param tvb the tv buffer of the current data
982
 * @param pinfo the packet info of the current data
983
 * @param tree the tree to append this item to
984
 * @param offset the offset in the tvb
985
 * @return modified offset
986
 */
987
static unsigned
988
fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
989
990
/**
991
 * VTData-ACK ::= SEQUENCE {
992
 *  allNewDataAccepted  [0] BOOLEAN,
993
 *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = false
994
 * }
995
 * @param tvb the tv buffer of the current data
996
 * @param pinfo the packet info of the current data
997
 * @param tree the tree to append this item to
998
 * @param offset the offset in the tvb
999
 * @return modified offset
1000
 */
1001
static unsigned
1002
fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1003
1004
/**
1005
 * Authenticate-Request ::= SEQUENCE {
1006
 *  pseudoRandomNumber     [0] Unsigned32,
1007
 *  expectedInvokeID       [1] Unsigned8 OPTIONAL,
1008
 *  operatorName           [2] CharacterString OPTIONAL,
1009
 *  operatorPassword       [3] CharacterString (SIZE(1..20)) OPTIONAL,
1010
 *  startEncypheredSession [4] BOOLEAN OPTIONAL
1011
 * }
1012
 * @param tvb the tv buffer of the current data
1013
 * @param pinfo the packet info of the current data
1014
 * @param tree the tree to append this item to
1015
 * @param offset the offset in the tvb
1016
 * @return modified offset
1017
 */
1018
static unsigned
1019
fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1020
1021
/**
1022
 * Authenticate-ACK ::= SEQUENCE {
1023
 *  modifiedRandomNumber    Unsigned32,
1024
 * }
1025
 * @param tvb the tv buffer of the current data
1026
 * @param pinfo the packet info of the current data
1027
 * @param tree the tree to append this item to
1028
 * @param offset the offset in the tvb
1029
 * @return modified offset
1030
 */
1031
static unsigned
1032
fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1033
1034
/**
1035
 * RequestKey-Request ::= SEQUENCE {
1036
 *  requestingDeviceIdentifier BACnetObjectIdentifier,
1037
 *  requestingDeviceAddress    BACnetAddress,
1038
 *  remoteDeviceIdentifier     BACnetObjectIdentifier,
1039
 *  remoteDeviceAddress        BACnetAddress
1040
 * }
1041
 * @param tvb the tv buffer of the current data
1042
 * @param pinfo the packet info of the current data
1043
 * @param tree the tree to append this item to
1044
 * @param offset the offset in the tvb
1045
 * @return modified offset
1046
 */
1047
static unsigned
1048
fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1049
1050
/**
1051
 * Unconfirmed-Service-Request ::= CHOICE {
1052
 * }
1053
 * @param tvb the tv buffer of the current data
1054
 * @param pinfo the packet info of the current data
1055
 * @param tree the tree to append this item to
1056
 * @param offset the offset in the tvb
1057
 * @param service_choice the service choice
1058
 * @return modified offset
1059
 */
1060
static unsigned
1061
fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
1062
1063
/**
1064
 * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1065
 *  subscriberProcessIdentifier [0] Unsigned32,
1066
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
1067
 *  monitoredObjectIdentifier   [2] BACnetObjectIdentifier,
1068
 *  timeRemaining               [3] unsigned,
1069
 *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
1070
 * }
1071
 * @param tvb the tv buffer of the current data
1072
 * @param pinfo the packet info of the current data
1073
 * @param tree the tree to append this item to
1074
 * @param offset the offset in the tvb
1075
 * @return modified offset
1076
 */
1077
static unsigned
1078
fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1079
1080
/**
1081
 * UnconfirmedEventNotification-Request ::= SEQUENCE {
1082
 *  ProcessIdentifier           [0] Unsigned32,
1083
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
1084
 *  eventObjectIdentifier       [2] BACnetObjectIdentifier,
1085
 *  timeStamp                   [3] BACnetTimeStamp,
1086
 *  notificationClass           [4] unsigned,
1087
 *  priority                    [5] unsigned8,
1088
 *  eventType                   [6] BACnetEventType,
1089
 *  messageText                 [7] CharacterString OPTIONAL,
1090
 *  notifyType                  [8] BACnetNotifyType,
1091
 *  ackRequired                 [9] BOOLEAN OPTIONAL,
1092
 *  fromState                  [10] BACnetEventState OPTIONAL,
1093
 *  toState                    [11] BACnetEventState,
1094
 *  eventValues                [12] BACnetNotificationParameters OPTIONAL
1095
 * }
1096
 * @param tvb the tv buffer of the current data
1097
 * @param pinfo the packet info of the current data
1098
 * @param tree the tree to append this item to
1099
 * @param offset the offset in the tvb
1100
 * @return modified offset
1101
 */
1102
static unsigned
1103
fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1104
1105
/**
1106
 * I-Am-Request ::= SEQUENCE {
1107
 *  aAmDeviceIdentifier BACnetObjectIdentifier,
1108
 *  maxAPDULengthAccepted   Unsigned,
1109
 *  segmentationSupported   BACnetSegmentation,
1110
 *  vendorID    Unsigned
1111
 * }
1112
 * @param tvb the tv buffer of the current data
1113
 * @param pinfo the packet info of the current data
1114
 * @param tree the tree to append this item to
1115
 * @param offset the offset in the tvb
1116
 * @return modified offset
1117
 */
1118
static unsigned
1119
fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1120
1121
1122
/**
1123
 * I-Have-Request ::= SEQUENCE {
1124
 *  deviceIdentifier  BACnetObjectIdentifier,
1125
 *  objectIdentifier  BACnetObjectIdentifier,
1126
 *  objectName        CharacterString
1127
 * }
1128
 * @param tvb the tv buffer of the current data
1129
 * @param pinfo the packet info of the current data
1130
 * @param tree the tree to append this item to
1131
 * @param offset the offset in the tvb
1132
 * @return modified offset
1133
 */
1134
static unsigned
1135
fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1136
1137
/**
1138
 * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1139
 *  vendorID          [0] Unsigned,
1140
 *  serviceNumber     [1] Unsigned,
1141
 *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1142
 * }
1143
 * @param tvb the tv buffer of the current data
1144
 * @param pinfo the packet info of the current data
1145
 * @param tree the tree to append this item to
1146
 * @param offset the offset in the tvb
1147
 * @return modified offset
1148
 */
1149
static unsigned
1150
fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1151
1152
/**
1153
 * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1154
 *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1155
 *  messageClass            [1] CHOICE {
1156
 *      numeric   [0] Unsigned,
1157
 *      character [1] CharacterString
1158
 *      } OPTIONAL,
1159
 *  messagePriority         [2] ENUMERATED {
1160
 *      normal (0),
1161
 *      urgent (1)
1162
 *      },
1163
 *  message                 [3] CharacterString
1164
 * }
1165
 * @param tvb the tv buffer of the current data
1166
 * @param pinfo the packet info of the current data
1167
 * @param tree the tree to append this item to
1168
 * @param offset the offset in the tvb
1169
 * @return modified offset
1170
 */
1171
static unsigned
1172
fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1173
1174
/**
1175
 * TimeSynchronization-Request ::=  SEQUENCE {
1176
 *  BACnetDateTime
1177
 * }
1178
 * @param tvb the tv buffer of the current data
1179
 * @param pinfo the packet info of the current data
1180
 * @param tree the tree to append this item to
1181
 * @param offset the offset in the tvb
1182
 * @return modified offset
1183
 */
1184
static unsigned
1185
fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1186
1187
/**
1188
 * UTCTimeSynchronization-Request ::=  SEQUENCE {
1189
 *  BACnetDateTime
1190
 * }
1191
 * @param tvb the tv buffer of the current data
1192
 * @param pinfo the packet info of the current data
1193
 * @param tree the tree to append this item to
1194
 * @param offset the offset in the tvb
1195
 * @return modified offset
1196
 */
1197
static unsigned
1198
fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1199
1200
/**
1201
 * Who-Has-Request ::=  SEQUENCE {
1202
 *  limits SEQUENCE {
1203
 *      deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303),
1204
 *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1205
 *      } OPTIONAL,
1206
 *  object CHOICE {
1207
 *      objectIdentifier             [2] BACnetObjectIdentifier,
1208
 *      objectName                   [3] CharacterString
1209
 *      }
1210
 * }
1211
 * @param tvb the tv buffer of the current data
1212
 * @param pinfo the packet info of the current data
1213
 * @param tree the tree to append this item to
1214
 * @param offset the offset in the tvb
1215
 * @return modified offset
1216
 */
1217
static unsigned
1218
fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1219
1220
/**
1221
 * Who-Is-Request ::= SEQUENCE {
1222
 *  deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1223
 *  deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1224
 * }
1225
 * @param tvb the tv buffer of the current data
1226
 * @param tree the tree to append this item to
1227
 * @param offset the offset in the tvb
1228
 * @return modified offset
1229
 */
1230
static unsigned
1231
fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1232
1233
/**
1234
 * BACnet-Error ::= CHOICE {
1235
 *  addListElement           [8] ChangeList-Error,
1236
 *  removeListElement        [9] ChangeList-Error,
1237
 *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1238
 *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1239
 *  vtClose                 [22] VTClose-Error,
1240
 *  readRange               [26] ObjectAccessService-Error
1241
 *                          [default] Error
1242
 * }
1243
 * @param tvb the tv buffer of the current data
1244
 * @param pinfo the packet info of the current data
1245
 * @param tree the tree to append this item to
1246
 * @param offset the offset in the tvb
1247
 * @param service the service
1248
 * @return modified offset
1249
 */
1250
static unsigned
1251
fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned service);
1252
1253
/**
1254
 * Dissect a BACnetError in a context tag
1255
 *
1256
 * @param tvb the tv buffer of the current data
1257
 * @param pinfo the packet info of the current data
1258
 * @param tree the tree to append this item to
1259
 * @param offset the offset in the tvb
1260
 * @return modified offset
1261
 */
1262
static unsigned fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1263
1264
/**
1265
 * ChangeList-Error ::= SEQUENCE {
1266
 *    errorType                [0] Error,
1267
 *    firstFailedElementNumber [1] Unsigned
1268
 *    }
1269
 * }
1270
 * @param tvb the tv buffer of the current data
1271
 * @param pinfo the packet info of the current data
1272
 * @param tree the tree to append this item to
1273
 * @param offset the offset in the tvb
1274
 * @return modified offset
1275
 */
1276
static unsigned
1277
fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1278
1279
/**
1280
 * CreateObject-Error ::= SEQUENCE {
1281
 *    errorType                [0] Error,
1282
 *    firstFailedElementNumber [1] Unsigned
1283
 *    }
1284
 * }
1285
 * @param tvb the tv buffer of the current data
1286
 * @param pinfo the packet info of the current data
1287
 * @param tree the tree to append this item to
1288
 * @param offset the offset in the tvb
1289
 * @return modified offset
1290
 */
1291
static unsigned
1292
fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1293
1294
/**
1295
 * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1296
 *    errorType       [0] Error,
1297
 *    vendorID        [1] Unsigned,
1298
 *    serviceNumber   [2] Unsigned,
1299
 *    errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1300
 *    }
1301
 * }
1302
 * @param tvb the tv buffer of the current data
1303
 * @param pinfo the packet info of the current data
1304
 * @param tree the tree to append this item to
1305
 * @param offset the offset in the tvb
1306
 * @return modified offset
1307
 */
1308
static unsigned
1309
fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1310
1311
/**
1312
 * WritePropertyMultiple-Error ::= SEQUENCE {
1313
 *    errorType               [0] Error,
1314
 *    firstFailedWriteAttempt [1] Unsigned
1315
 *    }
1316
 * }
1317
 * @param tvb the tv buffer of the current data
1318
 * @param pinfo the packet info of the current data
1319
 * @param tree the tree to append this item to
1320
 * @param offset the offset in the tvb
1321
 * @return modified offset
1322
 */
1323
static unsigned
1324
fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1325
1326
/**
1327
 * VTClose-Error ::= SEQUENCE {
1328
 *    errorType                  [0] Error,
1329
 *    listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1330
 *    }
1331
 * }
1332
 * @param tvb the tv buffer of the current data
1333
 * @param pinfo the packet info of the current data
1334
 * @param tree the tree to append this item to
1335
 * @param offset the offset in the tvb
1336
 * @return modified offset
1337
 */
1338
static unsigned
1339
fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1340
1341
/**
1342
 * BACnet Application Types chapter 20.2.1
1343
 * @param tvb the tv buffer of the current data
1344
 * @param pinfo the packet info of the current data
1345
 * @param tree the tree to append this item to
1346
 * @param offset the offset in the tvb
1347
 * @param label the label of this item
1348
 * @return modified offset
1349
 */
1350
static unsigned
1351
fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
1352
1353
/**
1354
 * BACnetActionCommand ::= SEQUENCE {
1355
 *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1356
 *  objectIdentifier    [1] BACnetObjectIdentifier,
1357
 *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1358
 *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1359
 *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1360
 *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1361
 *  postDelay           [6] Unsigned OPTIONAL,
1362
 *  quitOnFailure       [7] BOOLEAN,
1363
 *  writeSuccessful     [8] BOOLEAN
1364
 * }
1365
 * @param tvb the tv buffer of the current data
1366
 * @param pinfo the packet info of the current data
1367
 * @param tree the tree to append this item to
1368
 * @param offset the offset in the tvb
1369
 * @param tag_match the tag number
1370
 * @return modified offset
1371
 */
1372
static unsigned
1373
fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_match);
1374
1375
/**
1376
 * BACnetActionList ::= SEQUENCE {
1377
 *  action  [0] SEQUENCE of BACnetActionCommand
1378
 * }
1379
 * @param tvb the tv buffer of the current data
1380
 * @param pinfo the packet info of the current data
1381
 * @param tree the tree to append this item to
1382
 * @param offset the offset in the tvb
1383
 * @return modified offset
1384
 */
1385
static unsigned
1386
fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1387
1388
/** BACnetAddress ::= SEQUENCE {
1389
 *  network-number  Unsigned16, -- A value 0 indicates the local network
1390
 *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1391
 * }
1392
 * @param tvb the tv buffer of the current data
1393
 * @param pinfo the packet info of the current data
1394
 * @param tree the tree to append this item to
1395
 * @param offset the offset in the tvb
1396
 * @return modified offset
1397
 */
1398
static unsigned
1399
fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1400
1401
/**
1402
 * BACnetAddressBinding ::= SEQUENCE {
1403
 *  deviceObjectID  BACnetObjectIdentifier
1404
 *  deviceAddress   BacnetAddress
1405
 * }
1406
 * @param tvb the tv buffer of the current data
1407
 * @param pinfo the packet info of the current data
1408
 * @param tree the tree to append this item to
1409
 * @param offset the offset in the tvb
1410
 * @return modified offset
1411
 */
1412
static unsigned
1413
fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1414
1415
/**
1416
 * BACnetCalendarEntry ::= CHOICE {
1417
 *  date        [0] Date,
1418
 *  dateRange   [1] BACnetDateRange,
1419
 *  weekNDay    [2] BacnetWeekNday
1420
 * }
1421
 * @param tvb the tv buffer of the current data
1422
 * @param pinfo the packet info of the current data
1423
 * @param tree the tree to append this item to
1424
 * @param offset the offset in the tvb
1425
 * @return modified offset
1426
 */
1427
static unsigned
1428
fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1429
1430
/**
1431
 * BACnetClientCOV ::= CHOICE {
1432
 *  real-increment  REAL,
1433
 *  default-increment   NULL
1434
 * }
1435
 * @param tvb the tv buffer of the current data
1436
 * @param tree the tree to append this item to
1437
 * @param offset the offset in the tvb
1438
 * @return modified offset
1439
 */
1440
static unsigned
1441
fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1442
1443
1444
/**
1445
 * BACnetDailySchedule ::= SEQUENCE {
1446
 *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1447
 * }
1448
 * @param tvb the tv buffer of the current data
1449
 * @param pinfo the packet info of the current data
1450
 * @param tree the tree to append this item to
1451
 * @param offset the offset in the tvb
1452
 * @return modified offset
1453
 */
1454
static unsigned
1455
fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1456
1457
/**
1458
 * BACnetHealth ::= SEQUENCE {
1459
 *  timestamp                   [0] BACnetDateTime,
1460
 *  result                      [1] Error,
1461
 *  property                    [2] BACnetPropertyIdentifier OPTIONAL,
1462
 *  details                     [3] CharacterString OPTIONAL
1463
 * }
1464
 * @param tvb the tv buffer of the current data
1465
 * @param pinfo the packet info of the current data
1466
 * @param tree the tree to append this item to
1467
 * @param offset the offset in the tvb
1468
 * @return modified offset
1469
 */
1470
static unsigned
1471
fHealth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1472
1473
/**
1474
 * BACnetSCFailedConnectionRequest ::= SEQUENCE {
1475
 *  timestamp                   [0] BACnetDateTime,
1476
 *  peer-address                [1] BACnetHostNPort,
1477
 *  peer-vmac                   [2] OCTET STRING (SIZE(6))
1478
 *  peer-uuid                   [3] OCTET STRING (SIZE(16))
1479
 *  error                       [4] Error OPTIONAL
1480
 *  error-details               [5] CharacterString OPTIONAL
1481
 * }
1482
 * @param tvb the tv buffer of the current data
1483
 * @param pinfo the packet info of the current data
1484
 * @param tree the tree to append this item to
1485
 * @param offset the offset in the tvb
1486
 * @return modified offset
1487
 */
1488
static unsigned
1489
fSCFailedConnectionRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1490
1491
/**
1492
 * BACnetSCDirectConnection ::= SEQUENCE {
1493
 *  uri                         [0] CharacterString
1494
 *  connection-state            [1] BACnetSCConnectionState,
1495
 *  connect-timestamp           [2] BACnetDateTime,
1496
 *  disconnect-timestamp        [3] BACnetDateTime,
1497
 *  peer-address                [4] BACnetHostNPort,
1498
 *  peer-vmac                   [5] OCTET STRING (SIZE(6))
1499
 *  peer-uuid                   [6] OCTET STRING (SIZE(16))
1500
 *  error                       [7] Error OPTIONAL
1501
 *  error-details               [8] CharacterString OPTIONAL
1502
 * }
1503
 * @param tvb the tv buffer of the current data
1504
 * @param pinfo the packet info of the current data
1505
 * @param tree the tree to append this item to
1506
 * @param offset the offset in the tvb
1507
 * @return modified offset
1508
 */
1509
static unsigned
1510
fSCDirectConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1511
1512
/**
1513
 * BACnetSCHubConnection ::= SEQUENCE {
1514
 *  connection-state            [0] BACnetSCConnectionState,
1515
 *  connect-timestamp           [1] BACnetDateTime,
1516
 *  disconnect-timestamp        [2] BACnetDateTime,
1517
 *  error                       [3] Error OPTIONAL
1518
 *  error-details               [4] CharacterString OPTIONAL
1519
 * }
1520
 * @param tvb the tv buffer of the current data
1521
 * @param pinfo the packet info of the current data
1522
 * @param tree the tree to append this item to
1523
 * @param offset the offset in the tvb
1524
 * @return modified offset
1525
 */
1526
static unsigned
1527
fSCHubConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1528
1529
/**
1530
 * BACnetSCHubFunctionConnection ::= SEQUENCE {
1531
 *  connection-state            [0] BACnetSCConnectionState,
1532
 *  connect-timestamp           [1] BACnetDateTime,
1533
 *  disconnect-timestamp        [2] BACnetDateTime,
1534
 *  peer-address                [3] BACnetHostNPort,
1535
 *  peer-vmac                   [4] OCTET STRING (SIZE(6))
1536
 *  peer-uuid                   [5] OCTET STRING (SIZE(16))
1537
 *  error                       [6] Error OPTIONAL
1538
 *  error-details               [7] CharacterString OPTIONAL
1539
 * }
1540
 * @param tvb the tv buffer of the current data
1541
 * @param pinfo the packet info of the current data
1542
 * @param tree the tree to append this item to
1543
 * @param offset the offset in the tvb
1544
 * @return modified offset
1545
 */
1546
static unsigned
1547
fSCHubFunctionConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1548
1549
/**
1550
 * BACnetWeeklySchedule ::= SEQUENCE {
1551
 *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1552
 * }
1553
 * @param tvb the tv buffer of the current data
1554
 * @param pinfo the packet info of the current data
1555
 * @param tree the tree to append this item to
1556
 * @param offset the offset in the tvb
1557
 * @return modified offset
1558
 */
1559
static unsigned
1560
fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1561
1562
/**
1563
 * BACnetDateRange ::= SEQUENCE {
1564
 *  StartDate   Date,
1565
 *  EndDate     Date
1566
 * }
1567
 * @param tvb the tv buffer of the current data
1568
 * @param pinfo the packet info of the current data
1569
 * @param tree the tree to append this item to
1570
 * @param offset the offset in the tvb
1571
 * @return modified offset
1572
 */
1573
static unsigned
1574
fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1575
1576
/**
1577
 * BACnetDateTime ::= SEQUENCE {
1578
 *  date   Date,
1579
 *  time   Time
1580
 * }
1581
 * @param tvb the tv buffer of the current data
1582
 * @param pinfo the packet info of the current data
1583
 * @param tree the tree to append this item to
1584
 * @param offset the offset in the tvb
1585
 * @param label the label of this item
1586
 * @return modified offset
1587
 */
1588
static unsigned
1589
fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
1590
1591
/**
1592
 * BACnetDestination ::= SEQUENCE {
1593
 *  validDays   BACnetDaysOfWeek,
1594
 *  fromTime    Time,
1595
 *  toTime      Time,
1596
 *  recipient   BACnetRecipient,
1597
 *  processIdentifier   Unsigned32,
1598
 *  issueConfirmedNotifications BOOLEAN,
1599
 *  transitions BACnetEventTransitionBits
1600
 * }
1601
 * @param tvb the tv buffer of the current data
1602
 * @param pinfo the packet info of the current data
1603
 * @param tree the tree to append this item to
1604
 * @param offset the offset in the tvb
1605
 * @return modified offset
1606
 */
1607
static unsigned
1608
fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1609
1610
/**
1611
 * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1612
 *  objectIdentifier    [0] BACnetObjectIdentifier,
1613
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1614
 *  propertyArrayIndex  [2] Unsigned OPTIONAL,
1615
 *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1616
 * }
1617
 * @param tvb the tv buffer of the current data
1618
 * @param pinfo the packet info of the current data
1619
 * @param tree the tree to append this item to
1620
 * @param offset the offset in the tvb
1621
 * @return modified offset
1622
 */
1623
static unsigned
1624
fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1625
1626
/**
1627
 * BACnetObjectPropertyReference ::= SEQUENCE {
1628
 *  objectIdentifier    [0] BACnetObjectIdentifier,
1629
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1630
 *  propertyArrayIndex  [2] Unsigned OPTIONAL,
1631
 * }
1632
 * @param tvb the tv buffer of the current data
1633
 * @param pinfo the packet info of the current data
1634
 * @param tree the tree to append this item to
1635
 * @param offset the offset in the tvb
1636
 * @return modified offset
1637
 */
1638
static unsigned
1639
fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1640
1641
/**
1642
 * BACnetDeviceObjectReference ::= SEQUENCE {
1643
 *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1644
 *  objectIdentifier    [1] BACnetObjectIdentifier
1645
 * }
1646
 * @param tvb the tv buffer of the current data
1647
 * @param pinfo the packet info of the current data
1648
 * @param tree the tree to append this item to
1649
 * @param offset the offset in the tvb
1650
 * @return modified offset
1651
 */
1652
static unsigned
1653
fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1654
1655
/**
1656
 * BACnetEventParameter ::= CHOICE {
1657
 *  change-of-bitstring             [0] SEQUENCE {
1658
 *      time-delay                       [0] Unsigned,
1659
 *      bitmask                          [1] BIT STRING,
1660
 *      list-of-bitstring-values         [2] SEQUENCE OF BIT STRING
1661
 *      },
1662
 *  change-of-state                 [1] SEQUENCE {
1663
 *      time-delay     [0] Unsigned,
1664
 *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1665
 *      },
1666
 *  change-of-value                 [2] SEQUENCE {
1667
 *      time-delay   [0] Unsigned,
1668
 *      cov-criteria [1] CHOICE {
1669
 *          bitmask                       [0] BIT STRING,
1670
 *          referenced-property-increment [1] REAL
1671
 *          }
1672
 *      },
1673
 *  command-failure                 [3] SEQUENCE {
1674
 *      time-delay                       [0] Unsigned,
1675
 *      feedback-property-reference      [1] BACnetDeviceObjectPropertyReference
1676
 *      },
1677
 *  floating-limit                  [4] SEQUENCE {
1678
 *      time-delay                       [0] Unsigned,
1679
 *      setpoint-reference               [1] BACnetDeviceObjectPropertyReference,
1680
 *      low-diff-limit                   [2] REAL,
1681
 *      high-diff-limit                  [3] REAL,
1682
 *      deadband                         [4] REAL
1683
 *      },
1684
 *  out-of-range                    [5] SEQUENCE {
1685
 *      time-delay                       [0] Unsigned,
1686
 *      low-limit                        [1] REAL,
1687
 *      high-limit                       [2] REAL,
1688
 *      deadband                         [3] REAL
1689
 *      },
1690
 *  -- context tag 7 is deprecated
1691
 *  change-of-life-safety           [8] SEQUENCE {
1692
 *      time-delay                       [0] Unsigned,
1693
 *      list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1694
 *      list-of-alarm-values             [2] SEQUENCE OF BACnetLifeSafetyState,
1695
 *      mode-property-reference          [3] BACnetDeviceObjectPropertyReference
1696
 *      },
1697
 *  extended                        [9] SEQUENCE {
1698
 *      vendor-id                        [0] Unsigned16,
1699
 *      extended-event-type              [1] Unsigned,
1700
 *      parameters                       [2] SEQUENCE OF CHOICE {
1701
 *          null        NULL,
1702
 *          real        REAL,
1703
 *          integer     Unsigned,
1704
 *          boolean     BOOLEAN,
1705
 *          double      Double,
1706
 *          octet       OCTET STRING,
1707
 *          bitstring   BIT STRING,
1708
 *          enum        ENUMERATED,
1709
 *          reference   [0] BACnetDeviceObjectPropertyReference
1710
 *          }
1711
 *      },
1712
 *  buffer-ready                    [10] SEQUENCE {
1713
 *      notification-threshold           [0] Unsigned,
1714
 *      previous-notification-count      [1] Unsigned32
1715
 *      },
1716
 * unsigned-range                   [11] SEQUENCE {
1717
 *      time-delay                       [0] Unsigned,
1718
 *      low-limit                        [1] Unsigned,
1719
 *      high-limit                       [2] Unsigned,
1720
 *      }
1721
 * -- context tag 12 is reserved for future addenda
1722
 * access-event                     [13] SEQUENCE {
1723
 *      list-of-access-events            [0] SEQUENCE OF BACnetAccessEvent,
1724
 *      access-event-time-reference      [1] BACnetDeviceObjectPropertyReference
1725
 *      }
1726
 * double-out-of-range              [14] SEQUENCE {
1727
 *      time-delay                       [0] Unsigned,
1728
 *      low-limit                        [1] Double,
1729
 *      high-limit                       [2] Double,
1730
 *      deadband                         [3] Double
1731
 *  }
1732
 *  signed-out-of-range             [15] SEQUENCE {
1733
 *      time-delay                       [0] Unsigned,
1734
 *      low-limit                        [1] INTEGER,
1735
 *      high-limit                       [2] INTEGER,
1736
 *      deadband                         [3] Unsigned
1737
 *  }
1738
 *  unsigned-out-of-range           [16] SEQUENCE {
1739
 *      time-delay                       [0] Unsigned,
1740
 *      low-limit                        [1] Unsigned,
1741
 *      high-limit                       [2] Unsigned,
1742
 *      deadband                         [3] Unsigned
1743
 *   }
1744
 *  change-of-characterstring       [17] SEQUENCE {
1745
 *      time-delay                       [0] Unsigned,
1746
 *      list-of-alarm-values             [1] SEQUENCE OF CharacterString,
1747
 *   }
1748
 *  change-of-status-flags          [18] SEQUENCE {
1749
 *      time-delay                       [0] Unsigned,
1750
 *      selected-flags                   [1] BACnetStatusFlags
1751
 *   }
1752
 * }
1753
 * @param tvb the tv buffer of the current data
1754
 * @param tree the tree to append this item to
1755
 * @param offset the offset in the tvb
1756
 * @return modified offset
1757
 */
1758
static unsigned
1759
fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1760
1761
1762
1763
/**
1764
 * BACnetLogRecord ::= SEQUENCE {
1765
 *  timestamp   [0] BACnetDateTime,
1766
 *  logDatum    [1] CHOICE {
1767
 *      log-status      [0] BACnetLogStatus,
1768
 *      boolean-value   [1] BOOLEAN,
1769
 *      real-value      [2] REAL,
1770
 *      enum-value      [3] ENUMERATED, -- Optionally limited to 32 bits
1771
 *      unsigned-value  [4] Unsigned, -- Optionally limited to 32 bits
1772
 *      signed-value    [5] INTEGER, -- Optionally limited to 32 bits
1773
 *      bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1774
 *      null-value      [7] NULL,
1775
 *      failure         [8] Error,
1776
 *      time-change     [9] REAL,
1777
 *      any-value       [10] ABSTRACT-SYNTAX.&Type -- Optional
1778
 *      }
1779
 *  statusFlags [2] BACnetStatusFlags OPTIONAL
1780
 * }
1781
 * @param tvb the tv buffer of the current data
1782
 * @param pinfo the packet info of the current data
1783
 * @param tree the tree to append this item to
1784
 * @param offset the offset in the tvb
1785
 * @return modified offset
1786
 */
1787
static unsigned
1788
fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1789
1790
/**
1791
 * BACnetEventLogRecord ::= SEQUENCE {
1792
 *  timestamp [0] BACnetDateTime,
1793
 *  logDatum  [1] CHOICE {
1794
 *      log-status   [0] BACnetLogStatus,
1795
 *      notification [1] ConfirmedEventNotification-Request,
1796
 *      time-change  [2] REAL,
1797
 *      }
1798
 * }
1799
 * @param tvb the tv buffer of the current data
1800
 * @param pinfo the packet info of the current data
1801
 * @param tree the tree to append this item to
1802
 * @param offset the offset in the tvb
1803
 * @return modified offset
1804
 */
1805
static unsigned
1806
fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1807
1808
static unsigned
1809
fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1810
1811
/**
1812
 * BACnetNotificationParameters ::= CHOICE {
1813
 *  change-of-bitstring [0] SEQUENCE {
1814
 *      referenced-bitstring [0] BIT STRING,
1815
 *      status-flags         [1] BACnetStatusFlags
1816
 *      },
1817
 *  change-of-state [1] SEQUENCE {
1818
 *      new-state            [0] BACnetPropertyStatus,
1819
 *      status-flags         [1] BACnetStatusFlags
1820
 *      },
1821
 *  change-of-value [2] SEQUENCE {
1822
 *      new-value            [0] CHOICE {
1823
 *          changed-bits        [0] BIT STRING,
1824
 *          changed-value       [1] REAL
1825
 *          },
1826
 *      status-flags         [1] BACnetStatusFlags
1827
 *      },
1828
 *  command-failure [3] SEQUENCE {
1829
 *      command-value        [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1830
 *      status-flags         [1] BACnetStatusFlags
1831
 *      feedback-value       [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1832
 *      },
1833
 *  floating-limit [4]  SEQUENCE {
1834
 *      reference-value      [0] REAL,
1835
 *      status-flags         [1] BACnetStatusFlags
1836
 *      setpoint-value       [2] REAL,
1837
 *      error-limit          [3] REAL
1838
 *      },
1839
 *  out-of-range [5]    SEQUENCE {
1840
 *      exceeding-value      [0] REAL,
1841
 *      status-flags         [1] BACnetStatusFlags
1842
 *      deadband             [2] REAL,
1843
 *      exceeded-limit       [3] REAL
1844
 *      },
1845
 *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1846
 * -- complex tag 7 is deprecated
1847
 *  change-of-life-safety [8]   SEQUENCE {
1848
 *      new-state            [0] BACnetLifeSafetyState,
1849
 *      new-mode             [1] BACnetLifeSafetyState
1850
 *      status-flags         [2] BACnetStatusFlags,
1851
 *      operation-expected   [3] BACnetLifeSafetyOperation
1852
 *      },
1853
 *  extended [9]   SEQUENCE {
1854
 *      vendor-id            [0] Unsigned16,
1855
 *      extended-event-type  [1] Unsigned,
1856
 *      parameters           [2] SEQUENCE OF CHOICE {
1857
 *          null                NULL,
1858
 *          real                REAL,
1859
 *          integer             Unsigned,
1860
 *          boolean             BOOLEAN,
1861
 *          double              Double,
1862
 *          octet               OCTET STRING,
1863
 *          bitstring           BIT STRING,
1864
 *          enum                ENUMERATED,
1865
 *          propertyValue       [0] BACnetDeviceObjectPropertyValue
1866
 *          }
1867
 *      },
1868
 *  buffer-ready [10]    SEQUENCE {
1869
 *      buffer-property      [0] BACnetDeviceObjectPropertyReference,
1870
 *      previous-notification[1] Unsigned32,
1871
 *      current-notification [2] BACneUnsigned32tDateTime
1872
 *      },
1873
 *  unsigned-range [11]    SEQUENCE {
1874
 *      exceeding-value      [0] Unsigned,
1875
 *      status-flags         [1] BACnetStatusFlags,
1876
 *      exceeded-limit       [2] Unsigned
1877
 *      },
1878
 * -- context tag 12 is reserved for future addenda
1879
 *  access-event [13]    SEQUENCE {
1880
 *      access-event          [0] BACnetAccessEvent,
1881
 *      status-flags          [1] BACnetStatusFlags,
1882
 *      access-event-tag      [2] Unsigned,
1883
 *      access-event-time     [3] BACnetTimeStamp,
1884
 *      access-credential     [4] BACnetDeviceObjectReference,
1885
 *      authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1886
 *      },
1887
 *  double-out-of-range [14]    SEQUENCE {
1888
 *      exceeding-value      [0] Double,
1889
 *      status-flags         [1] BACnetStatusFlags
1890
 *      deadband             [2] Double,
1891
 *      exceeded-limit       [3] Double
1892
 *      },
1893
 *  signed-out-of-range [15]    SEQUENCE {
1894
 *      exceeding-value      [0] INTEGER,
1895
 *      status-flags         [1] BACnetStatusFlags
1896
 *      deadband             [2] Unsigned,
1897
 *      exceeded-limit       [3] INTEGER
1898
 *      },
1899
 *  unsigned-out-of-range [16]    SEQUENCE {
1900
 *      exceeding-value      [0] Unsigned,
1901
 *      status-flags         [1] BACnetStatusFlags
1902
 *      deadband             [2] Unsigned,
1903
 *      exceeded-limit       [3] Unsigned
1904
 *      },
1905
 *  change-of-characterstring [17]    SEQUENCE {
1906
 *      changed-value        [0] CharacterString,
1907
 *      status-flags         [1] BACnetStatusFlags
1908
 *      alarm-value          [2] CharacterString
1909
 *      },
1910
 *  change-of-status-flags [18]    SEQUENCE {
1911
 *      present-value        [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1912
 *                              -- depends on referenced property
1913
 *      referenced-flags     [1] BACnetStatusFlags
1914
 *      },
1915
 * }
1916
 * @param tvb the tv buffer of the current data
1917
 * @param pinfo the packet info of the current data
1918
 * @param tree the tree to append this item to
1919
 * @param offset the offset in the tvb
1920
 * @return modified offset
1921
 */
1922
static unsigned
1923
fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1924
1925
/**
1926
 * BACnetObjectPropertyReference ::= SEQUENCE {
1927
 *  objectIdentifier    [0] BACnetObjectIdentifier,
1928
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1929
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
1930
 * }
1931
 * @param tvb the tv buffer of the current data
1932
 * @param pinfo the packet info of the current data
1933
 * @param tree the tree to append this item to
1934
 * @param offset the offset in the tvb
1935
 * @return modified offset
1936
 */
1937
static unsigned
1938
fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1939
1940
#if 0
1941
/**
1942
 * BACnetObjectPropertyValue ::= SEQUENCE {
1943
 *      objectIdentifier   [0] BACnetObjectIdentifier,
1944
 *      propertyIdentifier [1] BACnetPropertyIdentifier,
1945
 *      propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1946
 *                                                -- if omitted with an array the entire array is referenced
1947
 *      value              [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1948
 *      priority           [4] Unsigned (1..16) OPTIONAL
1949
 * }
1950
 * @param tvb the tv buffer of the current data
1951
 * @param tree the tree to append this item to
1952
 * @param offset the offset in the tvb
1953
 * @return modified offset
1954
 */
1955
static unsigned
1956
fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
1957
#endif
1958
1959
/**
1960
 * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1961
 * @param tvb the tv buffer of the current data
1962
 * @param pinfo the packet info of the current data
1963
 * @param tree the tree to append this item to
1964
 * @param offset the offset in the tvb
1965
 * @return modified offset
1966
 */
1967
static unsigned
1968
fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1969
1970
static unsigned
1971
fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset, uint8_t list);
1972
1973
/**
1974
 * BACnetPropertyReference ::= SEQUENCE {
1975
 *  propertyIdentifier  [0] BACnetPropertyIdentifier,
1976
 *  propertyArrayIndex  [1] Unsigned OPTIONAL, -- used only with array datatype
1977
 * }
1978
 * @param tvb the tv buffer of the current data
1979
 * @param pinfo the packet info of the current data
1980
 * @param tree the tree to append this item to
1981
 * @param offset the offset in the tvb
1982
 * @return modified offset
1983
 */
1984
static unsigned
1985
fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t list);
1986
1987
static unsigned
1988
fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1989
1990
static unsigned
1991
fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1992
1993
/**
1994
 * BACnetPropertyValue ::= SEQUENCE {
1995
 *      PropertyIdentifier [0] BACnetPropertyIdentifier,
1996
 *      propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1997
 *                                                -- if omitted with an array the entire array is referenced
1998
 *      value              [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1999
 *      priority           [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
2000
 * }
2001
 * @param tvb the tv buffer of the current data
2002
 * @param pinfo the packet info of the current data
2003
 * @param tree the tree to append this item to
2004
 * @param offset the offset in the tvb
2005
 * @return modified offset
2006
 */
2007
static unsigned
2008
fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2009
2010
static unsigned
2011
fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset);
2012
2013
/**
2014
 * BACnet Application PDUs chapter 21
2015
 * BACnetRecipient::= CHOICE {
2016
 *  device  [0] BACnetObjectIdentifier
2017
 *  address [1] BACnetAddress
2018
 * }
2019
 * @param tvb the tv buffer of the current data
2020
 * @param pinfo the packet info of the current data
2021
 * @param tree the tree to append this item to
2022
 * @param offset the offset in the tvb
2023
 * @return modified offset
2024
 */
2025
static unsigned
2026
fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2027
2028
/**
2029
 * BACnet Application PDUs chapter 21
2030
 * BACnetRecipientProcess::= SEQUENCE {
2031
 *  recipient   [0] BACnetRecipient
2032
 *  processID   [1] Unsigned32
2033
 * }
2034
 * @param tvb the tv buffer of the current data
2035
 * @param pinfo the packet info of the current data
2036
 * @param tree the tree to append this item to
2037
 * @param offset the offset in the tvb
2038
 * @return modified offset
2039
 */
2040
static unsigned
2041
fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2042
2043
static unsigned
2044
fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2045
2046
#if 0
2047
/**
2048
 * BACnetSessionKey ::= SEQUENCE {
2049
 *  sessionKey  OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
2050
 *  peerAddress BACnetAddress
2051
 * }
2052
 * @param tvb the tv buffer of the current data
2053
 * @param tree the tree to append this item to
2054
 * @param offset the offset in the tvb
2055
 * @return modified offset
2056
 * @todo check if checksum is displayed correctly
2057
 */
2058
static unsigned
2059
fSessionKey(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
2060
#endif
2061
2062
/**
2063
 * BACnetSpecialEvent ::= SEQUENCE {
2064
 *  period      CHOICE {
2065
 *      calendarEntry       [0] BACnetCalendarEntry,
2066
 *      calendarReference    [1] BACnetObjectIdentifier
2067
 *      },
2068
 *      listOfTimeValues    [2] SEQUENCE OF BACnetTimeValue,
2069
 *      eventPriority       [3] Unsigned (1..16)
2070
 * }
2071
 * @param tvb the tv buffer of the current data
2072
 * @param pinfo the packet info of the current data
2073
 * @param tree the tree to append this item to
2074
 * @param offset the offset in the tvb
2075
 * @return modified offset
2076
 */
2077
static unsigned
2078
fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2079
2080
/**
2081
 * BACnetTimeStamp ::= CHOICE {
2082
 *  time            [0] Time,
2083
 *  sequenceNumber  [1] Unsigned (0..65535),
2084
 *  dateTime        [2] BACnetDateTime
2085
 * }
2086
 * @param tvb the tv buffer of the current data
2087
 * @param pinfo the packet info of the current data
2088
 * @param tree the tree to append this item to
2089
 * @param offset the offset in the tvb
2090
 * @param label the label of this item
2091
 * @return modified offset
2092
 */
2093
static unsigned
2094
fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2095
2096
static unsigned
2097
fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2098
2099
/**
2100
 * BACnetTimeValue ::= SEQUENCE {
2101
 *  time    Time,
2102
 *  value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2103
 * }
2104
 * @param tvb the tv buffer of the current data
2105
 * @param pinfo the packet info of the current data
2106
 * @param tree the tree to append this item to
2107
 * @param offset the offset in the tvb
2108
 * @return modified offset
2109
 */
2110
static unsigned
2111
fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2112
2113
#if 0
2114
/**
2115
 * BACnetVTSession ::= SEQUENCE {
2116
 *  local-vtSessionID   Unsigned8,
2117
 *  remote-vtSessionID  Unsigned8,
2118
 *  remote-vtAddress    BACnetAddress
2119
 * }
2120
 * @param tvb the tv buffer of the current data
2121
 * @param tree the tree to append this item to
2122
 * @param offset the offset in the tvb
2123
 * @return modified offset
2124
 */
2125
static unsigned
2126
fVTSession(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
2127
#endif
2128
2129
/**
2130
 * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2131
 * -- first octet month (1..12) January = 1, X'FF' = any month
2132
 * -- second octet weekOfMonth where: 1 = days numbered 1-7
2133
 * -- 2 = days numbered 8-14
2134
 * -- 3 = days numbered 15-21
2135
 * -- 4 = days numbered 22-28
2136
 * -- 5 = days numbered 29-31
2137
 * -- 6 = last 7 days of this month
2138
 * -- X'FF' = any week of this month
2139
 * -- third octet dayOfWeek (1..7) where 1 = Monday
2140
 * -- 7 = Sunday
2141
 * -- X'FF' = any day of week
2142
 * @param tvb the tv buffer of the current data
2143
 * @param pinfo the packet info of the current data
2144
 * @param tree the tree to append this item to
2145
 * @param offset the offset in the tvb
2146
 * @return modified offset
2147
 */
2148
static unsigned
2149
fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2150
2151
/**
2152
 * ReadAccessResult ::= SEQUENCE {
2153
 *  objectIdentifier            [0] BACnetObjectIdentifier,
2154
 *  listOfResults               [1] SEQUENCE OF SEQUENCE {
2155
 *      propertyIdentifier      [2] BACnetPropertyIdentifier,
2156
 *      propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2157
 *      readResult  CHOICE {
2158
 *          propertyValue       [4] ABSTRACT-SYNTAX.&Type,
2159
 *          propertyAccessError [5] Error
2160
 *      }
2161
 *  } OPTIONAL
2162
 * }
2163
 * @param tvb the tv buffer of the current data
2164
 * @param pinfo the packet info of the current data
2165
 * @param tree the tree to append this item to
2166
 * @param offset the offset in the tvb
2167
 * @return modified offset
2168
 */
2169
static unsigned
2170
fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2171
2172
/**
2173
 * ReadAccessSpecification ::= SEQUENCE {
2174
 *  objectIdentifier         [0] BACnetObjectIdentifier,
2175
 *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2176
 * }
2177
 * @param tvb the tv buffer of the current data
2178
 * @param pinfo the packet info of the current data
2179
 * @param subtree the subtree to append this item to
2180
 * @param offset the offset in the tvb
2181
 * @return modified offset
2182
 */
2183
static unsigned
2184
fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2185
2186
/**
2187
 * WriteAccessSpecification ::= SEQUENCE {
2188
 *  objectIdentifier [0] BACnetObjectIdentifier,
2189
 *  listOfProperty   [1] SEQUENCE OF BACnetPropertyValue
2190
 * }
2191
 * @param tvb the tv buffer of the current data
2192
 * @param pinfo the packet info of the current data
2193
 * @param subtree the sub tree to append this item to
2194
 * @param offset the offset in the tvb
2195
 * @return modified offset
2196
 */
2197
static unsigned
2198
fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2199
2200
2201
/********************************************************* Helper functions *******************************************/
2202
2203
/**
2204
 * extracts the tag number from the tag header.
2205
 * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2206
 * @param offset the offset in the tvb in actual tvb
2207
 * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2208
 */
2209
static unsigned
2210
fTagNo(tvbuff_t *tvb, unsigned offset);
2211
2212
/**
2213
 * splits Tag Header corresponding to 20.2.1 General Rules For BACnet Tags
2214
 * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2215
 * @param pinfo the packet info of the current data = packet info
2216
 * @param offset the offset in the tvb = offset in actual tvb
2217
 * @return tag_no BACnet 20.2.1.2 Tag Number
2218
 * @return class_tag BACnet 20.2.1.1 Class
2219
 * @return lvt BACnet 20.2.1.3 Length/Value/Type
2220
 * @return offs = length of this header
2221
 */
2222
2223
static unsigned
2224
fTagHeader(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, uint8_t *tag_no, uint8_t* class_tag, uint32_t *lvt);
2225
2226
2227
/**
2228
 * adds processID with max 32Bit unsigned Integer Value to tree
2229
 * @param tvb the tv buffer of the current data
2230
 * @param pinfo the packet info of the current data
2231
 * @param tree the tree to append this item to
2232
 * @param offset the offset in the tvb
2233
 * @return modified offset
2234
 */
2235
static unsigned
2236
fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2237
2238
/**
2239
 * adds present value to the tree
2240
 * @param tvb the tv buffer of the current data
2241
 * @param pinfo the packet info of the current data
2242
 * @param tree the tree to append this item to
2243
 * @param offset the offset in the tvb
2244
 * @param vs enum of string values when applicable
2245
 * @param split_val enum index
2246
 * @param type present value datatype enum
2247
 * @return modified offset
2248
 */
2249
static unsigned
2250
fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const value_string *vs, uint32_t split_val, BacappPresentValueType type);
2251
2252
/**
2253
 * adds event type to the tree
2254
 * @param tvb the tv buffer of the current data
2255
 * @param pinfo the packet info of the current data
2256
 * @param tree the tree to append this item to
2257
 * @param offset the offset in the tvb
2258
 * @return modified offset
2259
 */
2260
static unsigned
2261
fEventType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2262
2263
/**
2264
 * adds notify type to the tree
2265
 * @param tvb the tv buffer of the current data
2266
 * @param pinfo the packet info of the current data
2267
 * @param tree the tree to append this item to
2268
 * @param offset the offset in the tvb
2269
 * @return modified offset
2270
 */
2271
static unsigned
2272
fNotifyType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2273
2274
/**
2275
 * adds next_state with max 32Bit unsigned Integer Value to tree
2276
 * @param tvb the tv buffer of the current data
2277
 * @param pinfo the packet info of the current data
2278
 * @param tree the tree to append this item to
2279
 * @param offset the offset in the tvb
2280
 * @return modified offset
2281
 */
2282
static unsigned
2283
fToState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2284
2285
/**
2286
 * adds from_state with max 32Bit unsigned Integer Value to tree
2287
 * @param tvb the tv buffer of the current data
2288
 * @param pinfo the packet info of the current data
2289
 * @param tree the tree to append this item to
2290
 * @param offset the offset in the tvb
2291
 * @return modified offset
2292
 */
2293
static unsigned
2294
fFromState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2295
2296
/**
2297
 * adds object_name string value to tree
2298
 * @param tvb the tv buffer of the current data
2299
 * @param pinfo the packet info of the current data
2300
 * @param tree the tree to append this item to
2301
 * @param offset the offset in the tvb
2302
 * @return modified offset
2303
 */
2304
static unsigned
2305
fObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2306
2307
/**
2308
 * wrapper function for fCharacterStringBase
2309
 * @param tvb the tv buffer of the current data
2310
 * @param pinfo the packet info of the current data
2311
 * @param tree the tree to append this item to
2312
 * @param offset the offset in the tvb
2313
 * @return modified offset
2314
 */
2315
static unsigned
2316
fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2317
2318
/**
2319
 * adds string value to tree
2320
 * @param tvb the tv buffer of the current data
2321
 * @param pinfo the packet info of the current data
2322
 * @param tree the tree to append this item to
2323
 * @param offset the offset in the tvb
2324
 * @param present_val_dissect exposes string as present_value property
2325
 * @param object_name_dissect exposes string as object_name property
2326
 * @return modified offset
2327
 */
2328
static unsigned
2329
fCharacterStringBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2330
                     bool present_val_dissect, bool object_name_dissect);
2331
2332
/**
2333
 * adds timeSpan with max 32Bit unsigned Integer Value to tree
2334
 * @param tvb the tv buffer of the current data
2335
 * @param pinfo the packet info of the current data
2336
 * @param tree the tree to append this item to
2337
 * @param offset the offset in the tvb
2338
 * @return modified offset
2339
 */
2340
static unsigned
2341
fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2342
2343
/**
2344
 * BACnet Application PDUs chapter 21
2345
 * BACnetPropertyIdentifier::= ENUMERATED {
2346
 *   @see bacapp_property_identifier
2347
 * }
2348
 * @param tvb the tv buffer of the current data
2349
 * @param pinfo the packet info of the current data
2350
 * @param tree the tree to append this item to
2351
 * @param offset the offset in the tvb
2352
 * @return modified offset
2353
 */
2354
static unsigned
2355
fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2356
2357
/**
2358
 * BACnet Application PDUs chapter 21
2359
 * BACnetPropertyArrayIndex::= ENUMERATED {
2360
 *   @see bacapp_property_array_index
2361
 * }
2362
 * @param tvb the tv buffer of the current data
2363
 * @param pinfo the packet info of the current data
2364
 * @param tree the tree to append this item to
2365
 * @param offset the offset in the tvb
2366
 * @return modified offset
2367
 */
2368
static unsigned
2369
fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2370
2371
/**
2372
 * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2373
 *  objectIdentifier        [0] BACnetObjectIdentifier,
2374
 *  eventState              [1] BACnetEventState,
2375
 *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2376
 *  eventTimeStamps         [3] SEQUENCE SIZE (3) OF BACnetTimeStamps,
2377
 *  notifyType              [4] BACnetNotifyType,
2378
 *  eventEnable             [5] BACnetEventTransitionBits,
2379
 *  eventPriorities         [6] SEQUENCE SIZE (3) OF Unsigned
2380
 * }
2381
 * @param tvb the tv buffer of the current data
2382
 * @param pinfo the packet info of the current data
2383
 * @param tree the tree to append this item to
2384
 * @param offset the offset in the tvb
2385
 * @return modified offset
2386
 */
2387
static unsigned
2388
flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2389
2390
/**
2391
 * SelectionCriteria ::= SEQUENCE {
2392
 *  propertyIdentifier [0] BACnetPropertyIdentifier,
2393
 *  propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2394
 *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
2395
 *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
2396
 * }
2397
 * @param tvb the tv buffer of the current data
2398
 * @param pinfo the packet info of the current data
2399
 * @param tree the tree to append this item to
2400
 * @param offset the offset in the tvb
2401
 * @return modified offset
2402
 */
2403
static unsigned
2404
fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2405
2406
/**
2407
 * objectSelectionCriteria ::= SEQUENCE {
2408
 *  selectionLogic          [0] ENUMERATED { bacapp_selectionLogic },
2409
 *  listOfSelectionCriteria [1] SelectionCriteria
2410
 * }
2411
 * @param tvb the tv buffer of the current data
2412
 * @param pinfo the packet info of the current data
2413
 * @param subtree the sub tree to append this item to
2414
 * @param offset the offset in the tvb
2415
 * @return modified offset
2416
 */
2417
static unsigned
2418
fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2419
2420
/**
2421
 * BACnet-Error ::= SEQUENCE {
2422
 *    error-class ENUMERATED {},
2423
 *    error-code  ENUMERATED {}
2424
 *    }
2425
 * }
2426
 * @param tvb the tv buffer of the current data
2427
 * @param pinfo the packet info of the current data
2428
 * @param tree the tree to append this item to
2429
 * @param offset the offset in the tvb
2430
 * @return modified offset
2431
 */
2432
static unsigned
2433
fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2434
2435
/**
2436
 * Adds error-code from BACnet-Error to the tree
2437
 * @param tvb the tv buffer of the current data
2438
 * @param pinfo the packet info of the current data
2439
 * @param tree the tree to append this item to
2440
 * @param offset the offset in the tvb
2441
 * @return modified offset
2442
 */
2443
static unsigned
2444
fErrorCode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2445
2446
/**
2447
 * Adds error-class from BACnet-Error to the tree
2448
 * @param tvb the tv buffer of the current data
2449
 * @param pinfo the packet info of the current data
2450
 * @param tree the tree to append this item to
2451
 * @param offset the offset in the tvb
2452
 * @return modified offset
2453
 */
2454
static unsigned
2455
fErrorClass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2456
2457
/**
2458
 * Generic handler for context tagged values.  Mostly for handling
2459
 * vendor-defined properties and services.
2460
 * @param tvb the tv buffer of the current data
2461
 * @param pinfo the packet info of the current data
2462
 * @param tree the tree to append this item to
2463
 * @param offset the offset in the tvb
2464
 * @return modified offset
2465
 * @todo beautify this ugly construct
2466
 */
2467
static unsigned
2468
fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2469
2470
/**
2471
 * realizes some ABSTRACT-SYNTAX.&Type
2472
 * @param tvb the tv buffer of the current data
2473
 * @param pinfo the packet info of the current data
2474
 * @param tree the tree to append this item to
2475
 * @param offset the offset in the tvb
2476
 * @return modified offset
2477
 * @todo beautify this ugly construct
2478
 */
2479
static unsigned
2480
fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2481
2482
2483
static unsigned
2484
fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2485
    const value_string *src);
2486
2487
static unsigned
2488
fBitStringTagVSBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2489
    const value_string *src, bool present_val_dissect);
2490
2491
static unsigned
2492
fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2493
2494
static unsigned
2495
fEventNotificationSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2496
2497
static unsigned
2498
fLightingCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2499
2500
static unsigned
2501
fColorCommand(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable);
2502
2503
static unsigned
2504
fXyColor(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable);
2505
2506
static unsigned
2507
fTimerStateChangeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2508
2509
static unsigned
2510
fHostNPort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2511
2512
static unsigned
2513
fBDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2514
2515
static unsigned
2516
fFDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2517
2518
static unsigned
2519
fRouterEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2520
2521
static unsigned
2522
fVMACEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2523
2524
static unsigned
2525
fValueSource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2526
2527
static unsigned
2528
fAssignedLandingCalls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2529
2530
static unsigned
2531
fLandingCallStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2532
2533
static unsigned
2534
fLandingDoorStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2535
2536
static unsigned
2537
fCOVMultipleSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2538
2539
static unsigned
2540
fNameValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2541
2542
static unsigned
2543
fNameValueCollection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2544
2545
static unsigned
2546
fAuthenticationFactor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2547
2548
static unsigned
2549
fAuthenticationFactorFormat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2550
2551
static unsigned
2552
fAuthenticationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2553
2554
static unsigned
2555
fAccessRule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2556
2557
static unsigned
2558
fChannelValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2559
2560
static unsigned
2561
fPropertyAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2562
2563
static unsigned
2564
fNetworkSecurityPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2565
2566
static unsigned
2567
fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2568
2569
static unsigned
2570
fAuditLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2571
2572
static unsigned
2573
fStageLimitValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2574
2575
static unsigned
2576
fObjectSelector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2577
2578
static unsigned
2579
fDeviceAddressProxyTableEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2580
2581
static unsigned
2582
fAccessToken(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2583
2584
static unsigned
2585
fAuthorizationConstraint(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2586
2587
static unsigned
2588
fAuthorizationScope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2589
2590
static unsigned
2591
fAuthenticationClient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2592
2593
static unsigned
2594
fAuthorizationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2595
2596
static unsigned
2597
fAuthenticationPeer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2598
2599
static unsigned
2600
fAuthenticationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2601
2602
static unsigned
2603
fAuthorizationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2604
2605
static unsigned
2606
fAuthorizationScopeDescription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2607
2608
static unsigned
2609
fAuthorizationServer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2610
2611
static unsigned
2612
fAuthorizationStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2613
2614
2615
/**
2616
 * register_bacapp
2617
 */
2618
void
2619
proto_register_bacapp(void);
2620
2621
/* <<<< formerly bacapp.h */
2622
2623
/* reassembly table for segmented messages */
2624
static reassembly_table msg_reassembly_table;
2625
2626
/* some necessary forward function prototypes */
2627
static unsigned
2628
fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
2629
    const char *label, const value_string *vs);
2630
2631
static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
2632
static const char ASHRAE_Reserved_Fmt[] = "(%d) Reserved for Use by ASHRAE";
2633
static const char Vendor_Proprietary_Fmt[] = "(%d) Vendor Proprietary Value";
2634
2635
static const value_string
2636
BACnetTypeName[] = {
2637
    { 0, "Confirmed-REQ"},
2638
    { 1, "Unconfirmed-REQ"},
2639
    { 2, "Simple-ACK"},
2640
    { 3, "Complex-ACK"},
2641
    { 4, "Segment-ACK"},
2642
    { 5, "Error"},
2643
    { 6, "Reject"},
2644
    { 7, "Abort"},
2645
    { 0, NULL }
2646
};
2647
2648
static const true_false_string segments_follow = {
2649
    "Segmented Request",
2650
    "Unsegmented Request"
2651
};
2652
2653
static const true_false_string more_follow = {
2654
    "More Segments Follow",
2655
    "No More Segments Follow"
2656
};
2657
2658
static const true_false_string segmented_accept = {
2659
    "Segmented Response accepted",
2660
    "Segmented Response not accepted"
2661
};
2662
2663
static const true_false_string
2664
BACnetTagClass = {
2665
    "Context Specific Tag",
2666
    "Application Tag"
2667
};
2668
2669
static const value_string
2670
BACnetMaxSegmentsAccepted [] = {
2671
    { 0,  "Unspecified"},
2672
    { 1,  "2 segments"},
2673
    { 2,  "4 segments"},
2674
    { 3,  "8 segments"},
2675
    { 4, "16 segments"},
2676
    { 5, "32 segments"},
2677
    { 6, "64 segments"},
2678
    { 7, "Greater than 64 segments"},
2679
    { 0, NULL }
2680
};
2681
2682
static const value_string
2683
BACnetMaxAPDULengthAccepted [] = {
2684
    {  0, "Up to MinimumMessageSize (50 octets)"},
2685
    {  1, "Up to 128 octets"},
2686
    {  2, "Up to 206 octets (fits in a LonTalk frame)"},
2687
    {  3, "Up to 480 octets (fits in an ARCNET frame)"},
2688
    {  4, "Up to 1024 octets"},
2689
    {  5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2690
    {  6, "reserved by ASHRAE"},
2691
    {  7, "reserved by ASHRAE"},
2692
    {  8, "reserved by ASHRAE"},
2693
    {  9, "reserved by ASHRAE"},
2694
    { 10, "reserved by ASHRAE"},
2695
    { 11, "reserved by ASHRAE"},
2696
    { 12, "reserved by ASHRAE"},
2697
    { 13, "reserved by ASHRAE"},
2698
    { 14, "reserved by ASHRAE"},
2699
    { 15, "reserved by ASHRAE"},
2700
    { 0, NULL}
2701
};
2702
2703
static const value_string
2704
BACnetRejectReason [] = {
2705
    { 0, "other"},
2706
    { 1, "buffer-overflow"},
2707
    { 2, "inconsistent-parameters"},
2708
    { 3, "invalid-parameter-data-type"},
2709
    { 4, "invalid-tag"},
2710
    { 5, "missing-required-parameter"},
2711
    { 6, "parameter-out-of-range"},
2712
    { 7, "too-many-arguments"},
2713
    { 8, "undefined-enumeration"},
2714
    { 9, "unrecognized-service"},
2715
    { 0, NULL}
2716
};
2717
2718
static const value_string
2719
BACnetRestartReason [] = {
2720
    { 0, "unknown"},
2721
    { 1, "coldstart"},
2722
    { 2, "warmstart"},
2723
    { 3, "detected-power-lost"},
2724
    { 4, "detected-powered-off"},
2725
    { 5, "hardware-watchdog"},
2726
    { 6, "software-watchdog"},
2727
    { 7, "suspended"},
2728
    { 8, "activate-changes"},
2729
    { 0, NULL}
2730
};
2731
2732
static const value_string
2733
BACnetApplicationTagNumber [] = {
2734
    {  0, "Null"},
2735
    {  1, "Boolean"},
2736
    {  2, "Unsigned Integer"},
2737
    {  3, "Signed Integer (2's complement notation)"},
2738
    {  4, "Real (ANSI/IEE-754 floating point)"},
2739
    {  5, "Double (ANSI/IEE-754 double precision floating point)"},
2740
    {  6, "Octet String"},
2741
    {  7, "Character String"},
2742
    {  8, "Bit String"},
2743
    {  9, "Enumerated"},
2744
    { 10, "Date"},
2745
    { 11, "Time"},
2746
    { 12, "BACnetObjectIdentifier"},
2747
    { 13, "reserved by ASHRAE"},
2748
    { 14, "reserved by ASHRAE"},
2749
    { 15, "reserved by ASHRAE"},
2750
    { 0,  NULL}
2751
};
2752
2753
static const value_string
2754
BACnetAction [] = {
2755
    { 0, "direct"},
2756
    { 1, "reverse"},
2757
    { 0, NULL}
2758
};
2759
2760
static const value_string
2761
BACnetAccessEvent [] = {
2762
    {  0, "none"},
2763
    {  1, "granted"},
2764
    {  2, "muster"},
2765
    {  3, "passback-detected"},
2766
    {  4, "duress"},
2767
    {  5, "trace"},
2768
    {  6, "lockout-max-attempts"},
2769
    {  7, "lockout-other"},
2770
    {  8, "lockout-relinquished"},
2771
    {  9, "lockout-by-higher-priority"},
2772
    { 10, "out-of-service"},
2773
    { 11, "out-of-service-relinquished"},
2774
    { 12, "accompaniment-by"},
2775
    { 13, "authentication-factor-read"},
2776
    { 14, "authorization-delayed"},
2777
    { 15, "verification-required"},
2778
    /* Enumerated values 128-511 are used for events
2779
     * which indicate that access has been denied. */
2780
    { 128, "denied-deny-all"},
2781
    { 129, "denied-unknown-credential"},
2782
    { 130, "denied-authentication-unavailable"},
2783
    { 131, "denied-authentication-factor-timeout"},
2784
    { 132, "denied-incorrect-authentication-factor"},
2785
    { 133, "denied-zone-no-access-rights"},
2786
    { 134, "denied-point-no-access-rights"},
2787
    { 135, "denied-no-access-rights"},
2788
    { 136, "denied-out-of-time-range"},
2789
    { 137, "denied-threat-level"},
2790
    { 138, "denied-passback"},
2791
    { 139, "denied-unexpected-location-usage"},
2792
    { 140, "denied-max-attempts"},
2793
    { 141, "denied-lower-occupancy-limit"},
2794
    { 142, "denied-upper-occupancy-limit"},
2795
    { 143, "denied-authentication-factor-lost"},
2796
    { 144, "denied-authentication-factor-stolen"},
2797
    { 145, "denied-authentication-factor-damaged"},
2798
    { 146, "denied-authentication-factor-destroyed"},
2799
    { 147, "denied-authentication-factor-disabled"},
2800
    { 148, "denied-authentication-factor-error"},
2801
    { 149, "denied-credential-unassigned"},
2802
    { 150, "denied-credential-not-provisioned"},
2803
    { 151, "denied-credential-not-yet-active"},
2804
    { 152, "denied-credential-expired"},
2805
    { 153, "denied-credential-manual-disable"},
2806
    { 154, "denied-credential-lockout"},
2807
    { 155, "denied-credential-max-days"},
2808
    { 156, "denied-credential-max-uses"},
2809
    { 157, "denied-credential-inactivity"},
2810
    { 158, "denied-credential-disabled"},
2811
    { 159, "denied-no-accompaniment"},
2812
    { 160, "denied-incorrect-accompaniment"},
2813
    { 161, "denied-lockout"},
2814
    { 162, "denied-verification-failed"},
2815
    { 163, "denied-verification-timeout"},
2816
    { 164, "denied-other"},
2817
    { 0,  NULL}
2818
/* Enumerated values 0-512 are reserved for definition by ASHRAE.
2819
   Enumerated values 512-65535 may be used by others subject to
2820
   procedures and constraints described in Clause 23. */
2821
};
2822
2823
static const value_string
2824
BACnetAccessZoneOccupancyState[] = {
2825
    { 0, "normal"},
2826
    { 1, "below-lower-limit"},
2827
    { 2, "at-lower-limit"},
2828
    { 3, "at-upper-limit"},
2829
    { 4, "above-upper-limit"},
2830
    { 5, "disabled"},
2831
    { 6, "not-supported"},
2832
    { 0,  NULL}
2833
};
2834
2835
static const value_string
2836
BACnetAccessPassbackMode[] = {
2837
    { 0, "passback-off" },
2838
    { 1, "hard-passback" },
2839
    { 2, "soft-passback" },
2840
    { 0, NULL }
2841
};
2842
2843
static const value_string
2844
BACnetAccessCredentialDisableReason[] = {
2845
    { 0, "disabled" },
2846
    { 1, "disabled-needs-provisioning" },
2847
    { 2, "disabled-unassigned" },
2848
    { 3, "disabled-not-yet-active" },
2849
    { 4, "disabled-expired" },
2850
    { 5, "disabled-lockout" },
2851
    { 6, "disabled-max-days" },
2852
    { 7, "disabled-max-uses" },
2853
    { 8, "disabled-inactivity" },
2854
    { 9, "disabled-manual" },
2855
    { 0, NULL }
2856
};
2857
2858
static const value_string
2859
BACnetAccessUserType[] = {
2860
    { 0, "asset" },
2861
    { 1, "group" },
2862
    { 2, "person" },
2863
    { 0, NULL }
2864
};
2865
2866
static const value_string
2867
BACnetWriteStatus[] = {
2868
    { 0, "idle" },
2869
    { 1, "in-progress" },
2870
    { 2, "successful" },
2871
    { 3, "failed" },
2872
    { 0, NULL }
2873
};
2874
2875
static const value_string
2876
BACnetLightingTransition[] = {
2877
    { 0, "none" },
2878
    { 1, "fade" },
2879
    { 2, "ramp" },
2880
    { 0, NULL }
2881
};
2882
2883
static const value_string
2884
BACnetSecurityLevel[] = {
2885
    { 0, "incapable" },
2886
    { 1, "plain" },
2887
    { 2, "signed" },
2888
    { 3, "encrypted" },
2889
    { 4, "signed-end-to-end" },
2890
    { 5, "encrypted-end-to-end" },
2891
    { 0, NULL }
2892
};
2893
2894
static const value_string
2895
BACnetAccessCredentialDisable[] = {
2896
    { 0, "none" },
2897
    { 1, "disable" },
2898
    { 2, "disable-manual" },
2899
    { 3, "disable-lockout" },
2900
    { 0, NULL }
2901
};
2902
2903
static const value_string
2904
BACnetAuthenticationStatus[] = {
2905
    { 0, "not-ready" },
2906
    { 1, "ready" },
2907
    { 2, "disabled" },
2908
    { 3, "waiting-for-authentication-factor" },
2909
    { 4, "waiting-for-accompaniment" },
2910
    { 5, "waiting-for-verification" },
2911
    { 6, "in-progress" },
2912
    { 0, NULL }
2913
};
2914
2915
static const value_string
2916
BACnetAuthorizationMode[] = {
2917
    { 0, "authorize" },
2918
    { 1, "grant-active" },
2919
    { 2, "deny-all" },
2920
    { 3, "verification-required" },
2921
    { 4, "authorization-delayed" },
2922
    { 5, "none" },
2923
    { 0, NULL }
2924
};
2925
2926
static const value_string
2927
BACnetAuthorizationExemption[] = {
2928
    { 0, "passback" },
2929
    { 1, "occupancy-check" },
2930
    { 2, "access-rights" },
2931
    { 3, "lockout" },
2932
    { 4, "deny" },
2933
    { 5, "verification" },
2934
    { 6, "authorization-delay" },
2935
    { 0, NULL }
2936
};
2937
2938
static const value_string
2939
BACnetLightingInProgress[] = {
2940
    { 0, "idle" },
2941
    { 1, "fade-active" },
2942
    { 2, "ramp-active" },
2943
    { 3, "not-controlled" },
2944
    { 4, "other" },
2945
    { 5, "trim-active" },
2946
    { 0, NULL }
2947
};
2948
2949
static const value_string
2950
BACnetColorOperationInProgress[] = {
2951
    { 0, "idle" },
2952
    { 1, "fade-active" },
2953
    { 2, "ramp-active" },
2954
    { 3, "not-controlled" },
2955
    { 4, "other" },
2956
    { 0, NULL }
2957
};
2958
2959
static const value_string
2960
BACnetColorTransition[] = {
2961
    { 0, "none" },
2962
    { 1, "fade" },
2963
    { 2, "ramp" },
2964
    { 0, NULL }
2965
};
2966
2967
static const value_string
2968
BACnetBinaryLightingPV[] = {
2969
    { 0, "off" },
2970
    { 1, "on" },
2971
    { 2, "warn" },
2972
    { 3, "warn-off" },
2973
    { 4, "warn-relinquish" },
2974
    { 5, "stop" },
2975
    { 6, "toggle" },
2976
    { 0, NULL }
2977
};
2978
2979
static const value_string
2980
BACnetBackupState[] = {
2981
    { 0, "idle"},
2982
    { 1, "preparing-for-backup"},
2983
    { 2, "preparing-for-restore"},
2984
    { 3, "performing-a-backup"},
2985
    { 4, "performing-a-restore"},
2986
    { 5, "backup-failure"},
2987
    { 6, "restore-failure"},
2988
    { 0,  NULL}
2989
};
2990
2991
static const value_string
2992
BACnetAcknowledgedTransitions[] = {
2993
    { 0, "to-offnormal" },
2994
    { 1, "to-fault" },
2995
    { 2, "to-normal" },
2996
    { 0, NULL }
2997
};
2998
2999
static const value_string
3000
BACnetFileAccessMethod [] = {
3001
    { 0, "record-access"},
3002
    { 1, "stream-access"},
3003
    { 0, NULL}
3004
};
3005
3006
/* For some reason, BACnet defines the choice parameter
3007
   in the file read and write services backwards from the
3008
   BACnetFileAccessMethod enumeration.
3009
*/
3010
static const value_string
3011
BACnetFileAccessOption [] = {
3012
    { 0, "stream access"},
3013
    { 1, "record access"},
3014
    { 0, NULL}
3015
};
3016
3017
static const value_string
3018
BACnetFileStartOption [] = {
3019
    { 0, "File Start Position: "},
3020
    { 1, "File Start Record: "},
3021
    { 0, NULL}
3022
};
3023
3024
static const value_string
3025
BacnetFileRequestedCount [] = {
3026
    { 0, "Requested Octet Count: "},
3027
    { 1, "Requested Record Count: "},
3028
    { 0, NULL}
3029
};
3030
3031
static const value_string
3032
BACnetFileWriteInfo [] = {
3033
    { 0, "File Data: "},
3034
    { 1, "Record Count: "},
3035
    { 0, NULL}
3036
};
3037
3038
static const value_string
3039
BACnetAbortReason [] = {
3040
    { 0, "other"},
3041
    { 1, "buffer-overflow"},
3042
    { 2, "invalid-apdu-in-this-state"},
3043
    { 3, "preempted-by-higher-priority-task"},
3044
    { 4, "segmentation-not-supported"},
3045
    { 5, "security-error"},
3046
    { 6, "insufficient-security"},
3047
    { 7, "window-size-out-of-range"},
3048
    { 8, "application-exceeded-reply-time"},
3049
    { 9, "out-of-resources"},
3050
    { 10, "tsm-timeout"},
3051
    { 11, "apdu-too-long"},
3052
    { 0, NULL}
3053
};
3054
3055
static const value_string
3056
BACnetIpMode [] = {
3057
    { 0, "normal"},
3058
    { 1, "foreign"},
3059
    { 2, "bbmd"},
3060
    { 0,  NULL}
3061
};
3062
3063
static const value_string
3064
BACnetNetworkPortCommand [] = {
3065
    { 0, "idle"},
3066
    { 1, "discard-changes"},
3067
    { 2, "renew-fd-registration"},
3068
    { 3, "restart-slave-discovery"},
3069
    { 4, "renew-dhcp"},
3070
    { 5, "restart-autonegotiation"},
3071
    { 6, "disconnect"},
3072
    { 7, "restart-port"},
3073
    { 8, "generate-csr-file"},
3074
    { 9, "validate-changes"},
3075
    { 10, "restart-device-discovery"},
3076
    { 0,  NULL}
3077
};
3078
3079
static const value_string
3080
BACnetNetworkNumberQuality [] = {
3081
    { 0, "unknown"},
3082
    { 1, "learned"},
3083
    { 2, "learned-configured"},
3084
    { 3, "configured"},
3085
    { 0,  NULL}
3086
};
3087
3088
static const value_string
3089
BACnetNetworkType [] = {
3090
    { 0, "ethernet" },
3091
    { 1, "arcnet" },
3092
    { 2, "mstp" },
3093
    { 3, "ptp" },
3094
    { 4, "lontalk" },
3095
    { 5, "bacnet-ipv4" },
3096
    { 6, "zigbee" },
3097
    { 7, "virtual" },
3098
    { 8, "non-bacnet" },
3099
    { 9, "bacnet-ipv6" },
3100
    {10, "serial" },
3101
    {11, "secure-connect" },
3102
    { 0,  NULL}
3103
};
3104
3105
static const value_string
3106
BACnetSCConnectionState [] = {
3107
    { 0, "not-connected" },
3108
    { 1, "connected" },
3109
    { 2, "disconnected-with-errors" },
3110
    { 3, "failed-to-connect" },
3111
    { 0,  NULL}
3112
};
3113
3114
static const value_string
3115
BACnetSCHubConnectorState [] = {
3116
    { 0, "no-hub-connection" },
3117
    { 1, "connected-to-primary" },
3118
    { 2, "connected-to-failover" },
3119
    { 0,  NULL}
3120
};
3121
3122
static const value_string
3123
BACnetLifeSafetyMode [] = {
3124
    {  0, "off"},
3125
    {  1, "on"},
3126
    {  2, "test"},
3127
    {  3, "manned"},
3128
    {  4, "unmanned"},
3129
    {  5, "armed"},
3130
    {  6, "disarmed"},
3131
    {  7, "prearmed"},
3132
    {  8, "slow"},
3133
    {  9, "fast"},
3134
    { 10, "disconnected"},
3135
    { 11, "enabled"},
3136
    { 12, "disabled"},
3137
    { 13, "atomic-release-disabled"},
3138
    { 14, "default"},
3139
    { 15, "activated-oeo-alarm"},
3140
    { 16, "activated-oeo-evacuate"},
3141
    { 17, "activated-oeo-phase1-recall"},
3142
    { 18, "activated-oeo-unavailable"},
3143
    { 19, "deactivated"},
3144
    { 0,  NULL}
3145
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
3146
   Enumerated values 256-65535 may be used by others subject to
3147
   procedures and constraints described in Clause 23. */
3148
};
3149
3150
static const value_string
3151
BACnetLifeSafetyOperation [] = {
3152
    { 0, "none"},
3153
    { 1, "silence"},
3154
    { 2, "silence-audible"},
3155
    { 3, "silence-visual"},
3156
    { 4, "reset"},
3157
    { 5, "reset-alarm"},
3158
    { 6, "reset-fault"},
3159
    { 7, "unsilence"},
3160
    { 8, "unsilence-audible"},
3161
    { 9, "unsilence-visual"},
3162
    { 0, NULL}
3163
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
3164
   Enumerated values 64-65535 may be used by others subject to
3165
   procedures and constraints described in Clause 23. */
3166
};
3167
3168
static const value_string
3169
BACnetLifeSafetyState [] = {
3170
    {  0, "quiet"},
3171
    {  1, "pre-alarm"},
3172
    {  2, "alarm"},
3173
    {  3, "fault"},
3174
    {  4, "fault-pre-alarm"},
3175
    {  5, "fault-alarm"},
3176
    {  6, "not-ready"},
3177
    {  7, "active"},
3178
    {  8, "tamper"},
3179
    {  9, "test-alarm"},
3180
    { 10, "test-active"},
3181
    { 11, "test-fault"},
3182
    { 12, "test-fault-alarm"},
3183
    { 13, "holdup"},
3184
    { 14, "duress"},
3185
    { 15, "tamper-alarm"},
3186
    { 16, "abnormal"},
3187
    { 17, "emergency-power"},
3188
    { 18, "delayed"},
3189
    { 19, "blocked"},
3190
    { 20, "local-alarm"},
3191
    { 21, "general-alarm"},
3192
    { 22, "supervisory"},
3193
    { 23, "test-supervisory"},
3194
    { 24, "non-default-mode"},
3195
    { 25, "oeo-unavailable"},
3196
    { 26, "oeo-alarm"},
3197
    { 27, "oeo-phase1-recall"},
3198
    { 28, "oeo-evacuate"},
3199
    { 29, "oeo-unaffected"},
3200
    { 30, "test-oeo-unavailable"},
3201
    { 31, "test-oeo-alarm"},
3202
    { 32, "test-oeo-phase1-recall"},
3203
    { 33, "test-oeo-evacuate"},
3204
    { 34, "test-oeo-unaffected"},
3205
    { 0,  NULL}
3206
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
3207
   Enumerated values 256-65535 may be used by others subject to
3208
   procedures and constraints described in Clause 23. */
3209
};
3210
3211
static const value_string
3212
BACnetLimitEnable[] = {
3213
    { 0, "low-limit-enable" },
3214
    { 1, "high-limit-enable" },
3215
    { 0, NULL }
3216
};
3217
3218
static const value_string
3219
BACnetTimerState [] = {
3220
    { 0, "idle"},
3221
    { 1, "running"},
3222
    { 2, "expired"},
3223
    { 0, NULL}
3224
};
3225
3226
static const value_string
3227
BACnetTimerTransition [] = {
3228
    { 0, "none"},
3229
    { 1, "idle-to-running"},
3230
    { 2, "running-to-idle"},
3231
    { 3, "running-to-running"},
3232
    { 4, "running-to-expired"},
3233
    { 5, "forced-to-expired"},
3234
    { 6, "expired-to-idle"},
3235
    { 7, "expired-to-running"},
3236
    { 0, NULL}
3237
};
3238
3239
static const value_string
3240
BACnetEscalatorFault [] = {
3241
    { 0, "controller-fault"},
3242
    { 1, "drive-and-motor-fault"},
3243
    { 2, "mechanical-component-fault"},
3244
    { 3, "overspeed-fault"},
3245
    { 4, "power-supply-fault"},
3246
    { 5, "safety-device-fault"},
3247
    { 6, "controller-supply-fault"},
3248
    { 7, "drive-temperature-exceeded"},
3249
    { 8, "comb-plate-fault"},
3250
    { 0, NULL}
3251
};
3252
3253
static const value_string
3254
BACnetEscalatorMode [] = {
3255
    { 0, "unknown"},
3256
    { 1, "stop"},
3257
    { 2, "up"},
3258
    { 3, "down"},
3259
    { 4, "inspection"},
3260
    { 5, "out-of-service"},
3261
    { 0, NULL}
3262
};
3263
3264
static const value_string
3265
BACnetEscalatorOperationDirection [] = {
3266
    { 0, "unknown"},
3267
    { 1, "stopped"},
3268
    { 2, "up-rated-speed"},
3269
    { 3, "up-reduced-speed"},
3270
    { 4, "down-rated-speed"},
3271
    { 5, "down-reduced-speed"},
3272
    { 0, NULL}
3273
};
3274
3275
static const value_string
3276
BACnetLiftCarDirection [] = {
3277
    { 0, "unknown"},
3278
    { 1, "none"},
3279
    { 2, "stopped"},
3280
    { 3, "up"},
3281
    { 4, "down"},
3282
    { 5, "up-and-down"},
3283
    { 0, NULL}
3284
};
3285
3286
static const value_string
3287
BACnetLiftCarDoorCommand [] = {
3288
    { 0, "none"},
3289
    { 1, "open"},
3290
    { 2, "close"},
3291
    { 0, NULL}
3292
};
3293
3294
static const value_string
3295
BACnetLiftCarDriveStatus [] = {
3296
    { 0, "unknown"},
3297
    { 1, "stationary"},
3298
    { 2, "braking"},
3299
    { 3, "accelerate"},
3300
    { 4, "decelerate"},
3301
    { 5, "rated-speed"},
3302
    { 6, "single-floor-jump"},
3303
    { 7, "two-floor-jump"},
3304
    { 8, "three-floor-jump"},
3305
    { 9, "multi-floor-jump"},
3306
    { 0, NULL}
3307
};
3308
3309
static const value_string
3310
BACnetLiftCarMode [] = {
3311
    { 0, "unknown"},
3312
    { 1, "normal"},
3313
    { 2, "vip"},
3314
    { 3, "homing"},
3315
    { 4, "parking"},
3316
    { 5, "attendant-control"},
3317
    { 6, "firefighter-control"},
3318
    { 7, "emergency-power"},
3319
    { 8, "inspection"},
3320
    { 9, "cabinet-recall"},
3321
    { 10, "earthquake-operation"},
3322
    { 11, "fire-operation"},
3323
    { 12, "out-of-service"},
3324
    { 13, "occupant-evacuation"},
3325
    { 0, NULL}
3326
};
3327
3328
static const value_string
3329
BACnetLiftFault [] = {
3330
    { 0, "controller-fault"},
3331
    { 1, "drive-and-motor-fault"},
3332
    { 2, "governor-and-safety-gear-fault"},
3333
    { 3, "lift-shaft-device-fault"},
3334
    { 4, "power-supply-fault"},
3335
    { 5, "safety-interlock-fault"},
3336
    { 6, "door-closing-fault"},
3337
    { 7, "door-opening-fault"},
3338
    { 8, "car-stopped-outside-landing-zone"},
3339
    { 9, "call-button-stuck"},
3340
    { 10, "start-failure"},
3341
    { 11, "controller-supply-fault"},
3342
    { 12, "self-test-failure"},
3343
    { 13, "runtime-limit-exceeded"},
3344
    { 14, "position-lost"},
3345
    { 15, "drive-temperature-exceeded"},
3346
    { 16, "load-measurement-fault"},
3347
    { 0, NULL}
3348
};
3349
3350
static const value_string
3351
BACnetLiftGroupMode [] = {
3352
    { 0, "unknown"},
3353
    { 1, "normal"},
3354
    { 2, "down-peak"},
3355
    { 3, "two-way"},
3356
    { 4, "four-way"},
3357
    { 5, "emergency-power"},
3358
    { 6, "up-peak"},
3359
    { 0, NULL}
3360
};
3361
3362
static const value_string
3363
BACnetProtocolLevel [] = {
3364
    { 0, "physical"},
3365
    { 1, "protocol"},
3366
    { 2, "bacnet-application"},
3367
    { 3, "non-bacnet-application"},
3368
    { 0, NULL}
3369
};
3370
3371
static const value_string
3372
BACnetRelationship [] = {
3373
    { 0, "unknown"},
3374
    { 1, "default"},
3375
    { 2, "contains"},
3376
    { 3, "contained-by"},
3377
    { 4, "uses"},
3378
    { 5, "used-by"},
3379
    { 6, "commands"},
3380
    { 7, "commanded-by"},
3381
    { 8, "adjusts"},
3382
    { 9, "adjusted-by"},
3383
    { 10, "ingress"},
3384
    { 11, "egress"},
3385
    { 12, "supplies-air"},
3386
    { 13, "receives-air"},
3387
    { 14, "supplies-hot-air"},
3388
    { 15, "receives-hot-air"},
3389
    { 16, "supplies-cool-air"},
3390
    { 17, "receives-cool-air"},
3391
    { 18, "supplies-power"},
3392
    { 19, "receives-power"},
3393
    { 20, "supplies-gas"},
3394
    { 21, "receives-gas"},
3395
    { 22, "supplies-water"},
3396
    { 23, "receives-water"},
3397
    { 24, "supplies-hot-water"},
3398
    { 25, "receives-hot-water"},
3399
    { 26, "supplies-cool-water"},
3400
    { 27, "receives-cool-water"},
3401
    { 28, "supplies-steam"},
3402
    { 29, "receives-steam"},
3403
    { 0, NULL}
3404
};
3405
3406
static const value_string
3407
BACnetLightingOperation[] = {
3408
    { 0, "none" },
3409
    { 1, "fade-to" },
3410
    { 2, "ramp-to" },
3411
    { 3, "step-up" },
3412
    { 4, "step-down" },
3413
    { 5, "step-on" },
3414
    { 6, "step-off" },
3415
    { 7, "warn" },
3416
    { 8, "warn-off" },
3417
    { 9, "warn-relinquish" },
3418
    { 10, "stop" },
3419
    { 11, "restore-on" },
3420
    { 12, "default-on" },
3421
    { 13, "toggle-restor" },
3422
    { 14, "toggle-default" },
3423
    { 0, NULL }
3424
};
3425
3426
static const value_string
3427
BACnetColorOperation[] = {
3428
    { 0, "none" },
3429
    { 1, "fade-to-color" },
3430
    { 2, "fade-to-cct" },
3431
    { 3, "ramp-to-cct" },
3432
    { 4, "step-up-cct" },
3433
    { 5, "step-down-cct" },
3434
    { 6, "stop" },
3435
    { 0, NULL }
3436
};
3437
3438
static const value_string
3439
BACnetConfirmedServiceChoice[] = {
3440
    {  0, "acknowledgeAlarm"},
3441
    {  1, "confirmedCOVNotification"},
3442
    {  2, "confirmedEventNotification"},
3443
    {  3, "getAlarmSummary"},
3444
    {  4, "getEnrollmentSummary"},
3445
    {  5, "subscribeCOV"},
3446
    {  6, "atomicReadFile"},
3447
    {  7, "atomicWriteFile"},
3448
    {  8, "addListElement"},
3449
    {  9, "removeListElement"},
3450
    { 10, "createObject"},
3451
    { 11, "deleteObject"},
3452
    { 12, "readProperty"},
3453
    { 13, "readPropertyConditional"},
3454
    { 14, "readPropertyMultiple"},
3455
    { 15, "writeProperty"},
3456
    { 16, "writePropertyMultiple"},
3457
    { 17, "deviceCommunicationControl"},
3458
    { 18, "confirmedPrivateTransfer"},
3459
    { 19, "confirmedTextMessage"},
3460
    { 20, "reinitializeDevice"},
3461
    { 21, "vtOpen"},
3462
    { 22, "vtClose"},
3463
    { 23, "vtData"},
3464
    { 24, "authenticate"},
3465
    { 25, "requestKey"},
3466
    { 26, "readRange"},
3467
    { 27, "lifeSafetyOperation"},
3468
    { 28, "subscribeCOVProperty"},
3469
    { 29, "getEventInformation"},
3470
    { 30, "subscribeCovPropertyMultiple"},
3471
    { 31, "confirmedCovNotificationMultiple"},
3472
    { 32, "confirmedAuditNotification"},
3473
    { 33, "auditLogQuery"},
3474
    { 34, "authRequest" },
3475
    { 0,  NULL}
3476
};
3477
3478
static const value_string
3479
BACnetReliability [] = {
3480
    {  0, "no-fault-detected"},
3481
    {  1, "no-sensor"},
3482
    {  2, "over-range"},
3483
    {  3, "under-range"},
3484
    {  4, "open-loop"},
3485
    {  5, "shorted-loop"},
3486
    {  6, "no-output"},
3487
    {  7, "unreliable-other"},
3488
    {  8, "process-error"},
3489
    {  9, "multi-state-fault"},
3490
    { 10, "configuration-error"},
3491
    { 11, "reserved for a future addendum"},
3492
    { 12, "communication-failure"},
3493
    { 13, "member-fault"},
3494
    { 14, "monitored-object-fault" },
3495
    { 15, "tripped"},
3496
    { 16, "lamp-failure"},
3497
    { 17, "activation-failure"},
3498
    { 18, "renew-dhcp-failure"},
3499
    { 19, "renew-fd-registration-failure"},
3500
    { 20, "restart-auto-negotiation-failure"},
3501
    { 21, "restart-failure"},
3502
    { 22, "proprietary-command-failure"},
3503
    { 23, "faults-listed"},
3504
    { 24, "referenced-object-fault"},
3505
    { 25, "multi-state-out-of-range"},
3506
    { 0,  NULL}
3507
};
3508
3509
static const value_string
3510
BACnetRouterStatus[] = {
3511
    { 0, "available" },
3512
    { 1, "busy" },
3513
    { 2, "disconnected" },
3514
    { 0, NULL }
3515
};
3516
3517
static const value_string
3518
BACnetUnconfirmedServiceChoice [] = {
3519
    { 0, "i-Am"},
3520
    { 1, "i-Have"},
3521
    { 2, "unconfirmedCOVNotification"},
3522
    { 3, "unconfirmedEventNotification"},
3523
    { 4, "unconfirmedPrivateTransfer"},
3524
    { 5, "unconfirmedTextMessage"},
3525
    { 6, "timeSynchronization"},
3526
    { 7, "who-Has"},
3527
    { 8, "who-Is"},
3528
    { 9, "utcTimeSynchronization"},
3529
    { 10, "writeGroup"},
3530
    { 11, "unconfirmedCovNotificationMultiple"},
3531
    { 12, "unconfirmedAuditNotification"},
3532
    { 13, "who-am-I" },
3533
    { 14, "you-are" },
3534
    { 0, NULL}
3535
};
3536
3537
static const value_string
3538
BACnetObjectType [] = {
3539
    {  0, "analog-input"},
3540
    {  1, "analog-output"},
3541
    {  2, "analog-value"},
3542
    {  3, "binary-input"},
3543
    {  4, "binary-output"},
3544
    {  5, "binary-value"},
3545
    {  6, "calendar"},
3546
    {  7, "command"},
3547
    {  8, "device"},
3548
    {  9, "event-enrollment"},
3549
    { 10, "file"},
3550
    { 11, "group"},
3551
    { 12, "loop"},
3552
    { 13, "multi-state-input"},
3553
    { 14, "multi-state-output"},
3554
    { 15, "notification-class"},
3555
    { 16, "program"},
3556
    { 17, "schedule"},
3557
    { 18, "averaging"},
3558
    { 19, "multi-state-value"},
3559
    { 20, "trend-log"},
3560
    { 21, "life-safety-point"},
3561
    { 22, "life-safety-zone"},
3562
    { 23, "accumulator"},
3563
    { 24, "pulse-converter"},
3564
    { 25, "event-log"},
3565
    { 26, "global-group"},
3566
    { 27, "trend-log-multiple"},
3567
    { 28, "load-control"},
3568
    { 29, "structured-view"},
3569
    { 30, "access-door"},     /* 30-37 added with addanda 135-2008j */
3570
    { 31, "timer"},
3571
    { 32, "access-credential"},
3572
    { 33, "access-point"},
3573
    { 34, "access-rights"},
3574
    { 35, "access-user"},
3575
    { 36, "access-zone"},
3576
    { 37, "credential-data-input"},
3577
    { 38, "network-security"},
3578
    { 39, "bitstring-value"},     /* 39-50 added with addenda 135-2008w */
3579
    { 40, "characterstring-value"},
3580
    { 41, "date-pattern-value"},
3581
    { 42, "date-value"},
3582
    { 43, "datetime-pattern-value"},
3583
    { 44, "datetime-value"},
3584
    { 45, "integer-value"},
3585
    { 46, "large-analog-value"},
3586
    { 47, "octetstring-value"},
3587
    { 48, "positive-integer-value"},
3588
    { 49, "time-pattern-value"},
3589
    { 50, "time-value"},
3590
    { 51, "notification-forwarder"},
3591
    { 52, "alert-enrollment"},
3592
    { 53, "channel"},
3593
    { 54, "lighting-output"},
3594
    { 55, "binary-lighting-output"},
3595
    { 56, "network-port"},
3596
    { 57, "elevator-group"},
3597
    { 58, "escalator"},
3598
    { 59, "lift"},
3599
    { 60, "staging"},
3600
    { 61, "audit-log"},
3601
    { 62, "audit-reporter"},
3602
    { 63, "color"},
3603
    { 64, "color-temperature"},
3604
    { 0,  NULL}
3605
/* Enumerated values 0-127 are reserved for definition by ASHRAE.
3606
   Enumerated values 128-1023 may be used by others subject to
3607
   the procedures and constraints described in Clause 23. */
3608
};
3609
static value_string_ext BACnetObjectType_ext = VALUE_STRING_EXT_INIT(BACnetObjectType);
3610
3611
static const value_string
3612
BACnetObjectTypeAbbrev[] = {
3613
    {  0, "AI" },
3614
    {  1, "AO" },
3615
    {  2, "AV" },
3616
    {  3, "BI" },
3617
    {  4, "BO" },
3618
    {  5, "BV" },
3619
    {  6, "CAL" },
3620
    {  7, "CMD" },
3621
    {  8, "DEV" },
3622
    {  9, "EE" },
3623
    { 10, "FV" },
3624
    { 11, "G" },
3625
    { 12, "LP" },
3626
    { 13, "MSI" },
3627
    { 14, "MSO" },
3628
    { 15, "NC" },
3629
    { 16, "PROG" },
3630
    { 17, "SCH" },
3631
    { 18, "AVG" },
3632
    { 19, "MSVV" },
3633
    { 20, "TLV" },
3634
    { 21, "LSP" },
3635
    { 22, "LSZV" },
3636
    { 23, "ACM" },
3637
    { 24, "PC" },
3638
    { 25, "EL" },
3639
    { 26, "GG" },
3640
    { 27, "TLM" },
3641
    { 28, "LCV" },
3642
    { 29, "SV" },
3643
    { 30, "ACD" },
3644
    { 32, "ACC" },
3645
    { 33, "ACP" },
3646
    { 34, "ACR" },
3647
    { 35, "ACU" },
3648
    { 36, "ACZ" },
3649
    { 37, "CDI" },
3650
    { 38, "NS" },
3651
    { 39, "BSV" },
3652
    { 40, "CSV" },
3653
    { 41, "DPV" },
3654
    { 42, "DV" },
3655
    { 43, "DTPV" },
3656
    { 44, "DTV" },
3657
    { 45, "IVV" },
3658
    { 46, "LAV" },
3659
    { 47, "OSV" },
3660
    { 48, "UV" },
3661
    { 49, "TPV" },
3662
    { 50, "TVV" },
3663
    { 51, "NFV" },
3664
    { 52, "AE" },
3665
    { 53, "CH" },
3666
    { 54, "LO" },
3667
    { 55, "BLO" },
3668
    { 56, "NP" },
3669
    { 57, "EG" },
3670
    { 58, "ES" },
3671
    { 59, "L" },
3672
    { 60, "STG" },
3673
    { 61, "ALV" },
3674
    { 62, "AR" },
3675
    { 63, "CO" },
3676
    { 64, "CT" },
3677
    {  0, NULL }
3678
};
3679
3680
static const value_string
3681
BACnetEngineeringUnits [] = {
3682
    {   0, "Sq Meters"},
3683
    {   1, "Sq Feet"},
3684
    {   2, "Milliamperes"},
3685
    {   3, "Amperes"},
3686
    {   4, "Ohms"},
3687
    {   5, "Volts"},
3688
    {   6, "Kilovolts"},
3689
    {   7, "Megavolts"},
3690
    {   8, "Volt Amperes"},
3691
    {   9, "Kilovolt Amperes"},
3692
    {  10, "Megavolt Amperes"},
3693
    {  11, "Volt Amperes Reactive"},
3694
    {  12, "Kilovolt Amperes Reactive"},
3695
    {  13, "Megavolt Amperes Reactive"},
3696
    {  14, "Degrees Phase"},
3697
    {  15, "Power Factor"},
3698
    {  16, "Joules"},
3699
    {  17, "Kilojoules"},
3700
    {  18, "Watt Hours"},
3701
    {  19, "Kilowatt Hours"},
3702
    {  20, "BTUs"},
3703
    {  21, "Therms"},
3704
    {  22, "Ton Hours"},
3705
    {  23, "Joules Per Kg Dry Air"},
3706
    {  24, "BTUs Per Pound Dry Air"},
3707
    {  25, "Cycles Per Hour"},
3708
    {  26, "Cycles Per Minute"},
3709
    {  27, "Hertz"},
3710
    {  28, "Grams Of Water Per Kilogram Dry Air"},
3711
    {  29, "Relative Humidity"},
3712
    {  30, "Millimeters"},
3713
    {  31, "Meters"},
3714
    {  32, "Inches"},
3715
    {  33, "Feed"},
3716
    {  34, "Watts Per Sq Foot"},
3717
    {  35, "Watts Per Sq meter"},
3718
    {  36, "Lumens"},
3719
    {  37, "Lux"},
3720
    {  38, "Foot Candles"},
3721
    {  39, "Kilograms"},
3722
    {  40, "Pounds Mass"},
3723
    {  41, "Tons"},
3724
    {  42, "Kgs per Second"},
3725
    {  43, "Kgs Per Minute"},
3726
    {  44, "Kgs Per Hour"},
3727
    {  45, "Pounds Mass Per Minute"},
3728
    {  46, "Pounds Mass Per Hour"},
3729
    {  47, "Watt"},
3730
    {  48, "Kilowatts"},
3731
    {  49, "Megawatts"},
3732
    {  50, "BTUs Per Hour"},
3733
    {  51, "Horsepower"},
3734
    {  52, "Tons Refrigeration"},
3735
    {  53, "Pascals"},
3736
    {  54, "Kilopascals"},
3737
    {  55, "Bars"},
3738
    {  56, "Pounds Force Per Square Inch"},
3739
    {  57, "Centimeters Of Water"},
3740
    {  58, "Inches Of Water"},
3741
    {  59, "Millimeters Of Mercury"},
3742
    {  60, "Centimeters Of Mercury"},
3743
    {  61, "Inches Of Mercury"},
3744
    {  62, "Degrees Celsius"},
3745
    {  63, "Degrees Kelvin"},
3746
    {  64, "Degrees Fahrenheit"},
3747
    {  65, "Degree Days Celsius"},
3748
    {  66, "Degree Days Fahrenheit"},
3749
    {  67, "Years"},
3750
    {  68, "Months"},
3751
    {  69, "Weeks"},
3752
    {  70, "Days"},
3753
    {  71, "Hours"},
3754
    {  72, "Minutes"},
3755
    {  73, "Seconds"},
3756
    {  74, "Meters Per Second"},
3757
    {  75, "Kilometers Per Hour"},
3758
    {  76, "Feed Per Second"},
3759
    {  77, "Feet Per Minute"},
3760
    {  78, "Miles Per Hour"},
3761
    {  79, "Cubic Feet"},
3762
    {  80, "Cubic Meters"},
3763
    {  81, "Imperial Gallons"},
3764
    {  82, "Liters"},
3765
    {  83, "US Gallons"},
3766
    {  84, "Cubic Feet Per Minute"},
3767
    {  85, "Cubic Meters Per Second"},
3768
    {  86, "Imperial Gallons Per Minute"},
3769
    {  87, "Liters Per Second"},
3770
    {  88, "Liters Per Minute"},
3771
    {  89, "US Gallons Per Minute"},
3772
    {  90, "Degrees Angular"},
3773
    {  91, "Degrees Celsius Per Hour"},
3774
    {  92, "Degrees Celsius Per Minute"},
3775
    {  93, "Degrees Fahrenheit Per Hour"},
3776
    {  94, "Degrees Fahrenheit Per Minute"},
3777
    {  95, "No Units"},
3778
    {  96, "Parts Per Million"},
3779
    {  97, "Parts Per Billion"},
3780
    {  98, "Percent"},
3781
    {  99, "Percent Per Second"},
3782
    { 100, "Per Minute"},
3783
    { 101, "Per Second"},
3784
    { 102, "Psi Per Degree Fahrenheit"},
3785
    { 103, "Radians"},
3786
    { 104, "Revolutions Per Min"},
3787
    { 105, "Currency1"},
3788
    { 106, "Currency2"},
3789
    { 107, "Currency3"},
3790
    { 108, "Currency4"},
3791
    { 109, "Currency5"},
3792
    { 110, "Currency6"},
3793
    { 111, "Currency7"},
3794
    { 112, "Currency8"},
3795
    { 113, "Currency9"},
3796
    { 114, "Currency10"},
3797
    { 115, "Sq Inches"},
3798
    { 116, "Sq Centimeters"},
3799
    { 117, "BTUs Per Pound"},
3800
    { 118, "Centimeters"},
3801
    { 119, "Pounds Mass Per Second"},
3802
    { 120, "Delta Degrees Fahrenheit"},
3803
    { 121, "Delta Degrees Kelvin"},
3804
    { 122, "Kilohms"},
3805
    { 123, "Megohms"},
3806
    { 124, "Millivolts"},
3807
    { 125, "Kilojoules Per Kg"},
3808
    { 126, "Megajoules"},
3809
    { 127, "Joules Per Degree Kelvin"},
3810
    { 128, "Joules Per Kg Degree Kelvin"},
3811
    { 129, "Kilohertz"},
3812
    { 130, "Megahertz"},
3813
    { 131, "Per Hour"},
3814
    { 132, "Milliwatts"},
3815
    { 133, "Hectopascals"},
3816
    { 134, "Millibars"},
3817
    { 135, "Cubic Meters Per Hour"},
3818
    { 136, "Liters Per Hour"},
3819
    { 137, "KWatt Hours Per Square Meter"},
3820
    { 138, "KWatt Hours Per Square Foot"},
3821
    { 139, "Megajoules Per Square Meter"},
3822
    { 140, "Megajoules Per Square Foot"},
3823
    { 141, "Watts Per Sq Meter Degree Kelvin"},
3824
    { 142, "Cubic Feet Per Second"},
3825
    { 143, "Percent Obstruction Per Foot"},
3826
    { 144, "Percent Obstruction Per Meter"},
3827
    { 145, "milliohms"},
3828
    { 146, "megawatt-hours"},
3829
    { 147, "kilo-btus"},
3830
    { 148, "mega-btus"},
3831
    { 149, "kilojoules-per-kilogram-dry-air"},
3832
    { 150, "megajoules-per-kilogram-dry-air"},
3833
    { 151, "kilojoules-per-degree-Kelvin"},
3834
    { 152, "megajoules-per-degree-Kelvin"},
3835
    { 153, "newton"},
3836
    { 154, "grams-per-second"},
3837
    { 155, "grams-per-minute"},
3838
    { 156, "tons-per-hour"},
3839
    { 157, "kilo-btus-per-hour"},
3840
    { 158, "hundredths-seconds"},
3841
    { 159, "milliseconds"},
3842
    { 160, "newton-meters"},
3843
    { 161, "millimeters-per-second"},
3844
    { 162, "millimeters-per-minute"},
3845
    { 163, "meters-per-minute"},
3846
    { 164, "meters-per-hour"},
3847
    { 165, "cubic-meters-per-minute"},
3848
    { 166, "meters-per-second-per-second"},
3849
    { 167, "amperes-per-meter"},
3850
    { 168, "amperes-per-square-meter"},
3851
    { 169, "ampere-square-meters"},
3852
    { 170, "farads"},
3853
    { 171, "henrys"},
3854
    { 172, "ohm-meters"},
3855
    { 173, "siemens"},
3856
    { 174, "siemens-per-meter"},
3857
    { 175, "teslas"},
3858
    { 176, "volts-per-degree-Kelvin"},
3859
    { 177, "volts-per-meter"},
3860
    { 178, "webers"},
3861
    { 179, "candelas"},
3862
    { 180, "candelas-per-square-meter"},
3863
    { 181, "degrees-Kelvin-per-hour"},
3864
    { 182, "degrees-Kelvin-per-minute"},
3865
    { 183, "joule-seconds"},
3866
    { 184, "radians-per-second"},
3867
    { 185, "square-meters-per-Newton"},
3868
    { 186, "kilograms-per-cubic-meter"},
3869
    { 187, "newton-seconds"},
3870
    { 188, "newtons-per-meter"},
3871
    { 189, "watts-per-meter-per-degree-Kelvin"},
3872
    { 190, "micro-siemens"},
3873
    { 191, "cubic-feet-per-hour"},
3874
    { 192, "us-gallons-per-hour"},
3875
    { 193, "kilometers"},
3876
    { 194, "micrometers"},
3877
    { 195, "grams"},
3878
    { 196, "milligrams"},
3879
    { 197, "milliliters"},
3880
    { 198, "milliliters-per-second"},
3881
    { 199, "decibels"},
3882
    { 200, "decibels-millivolt"},
3883
    { 201, "decibels-volt"},
3884
    { 202, "millisiemens"},
3885
    { 203, "watt-hours-reactive"},
3886
    { 204, "kilowatt-hours-reactive"},
3887
    { 205, "megawatt-hours-reactive"},
3888
    { 206, "millimeters-of-water"},
3889
    { 207, "per-mille"},
3890
    { 208, "grams-per-gram"},
3891
    { 209, "kilograms-per-kilogram"},
3892
    { 210, "grams-per-kilogram"},
3893
    { 211, "milligrams-per-gram"},
3894
    { 212, "milligrams-per-kilogram"},
3895
    { 213, "grams-per-milliliter"},
3896
    { 214, "grams-per-liter"},
3897
    { 215, "milligrams-per-liter"},
3898
    { 216, "micrograms-per-liter"},
3899
    { 217, "grams-per-cubic-meter"},
3900
    { 218, "milligrams-per-cubic-meter"},
3901
    { 219, "micrograms-per-cubic-meter"},
3902
    { 220, "nanograms-per-cubic-meter"},
3903
    { 221, "grams-per-cubic-centimeter"},
3904
    { 222, "becquerels"},
3905
    { 223, "kilobecquerels"},
3906
    { 224, "megabecquerels"},
3907
    { 225, "gray"},
3908
    { 226, "milligray"},
3909
    { 227, "microgray"},
3910
    { 228, "sieverts"},
3911
    { 229, "millisieverts"},
3912
    { 230, "microsieverts"},
3913
    { 231, "microsieverts-per-hour"},
3914
    { 232, "decibels-a"},
3915
    { 233, "nephelometric-turbidity-unit"},
3916
    { 234, "pH"},
3917
    { 235, "grams-per-square-meter"},
3918
    { 236, "minutes-per-degree-kelvin"},
3919
    { 237, "ohm-meter-squared-per-meter"},
3920
    { 238, "ampere-seconds"},
3921
    { 239, "volt-ampere-hours"},
3922
    { 240, "kilovolt-ampere-hours"},
3923
    { 241, "megavolt-ampere-hours"},
3924
    { 242, "volt-ampere-hours-reactive"},
3925
    { 243, "kilovolt-ampere-hours-reactive"},
3926
    { 244, "megavolt-ampere-hours-reactive"},
3927
    { 245, "volt-square-hours"},
3928
    { 246, "ampere-square-hours"},
3929
    { 247, "joule-per-hours"},
3930
    { 248, "cubic-feet-per-day"},
3931
    { 249, "cubic-meters-per-day"},
3932
    { 250, "watt-hours-per-cubic-meter"},
3933
    { 251, "joules-per-cubic-meter"},
3934
    { 252, "mole-percent"},
3935
    { 253, "pascal-seconds"},
3936
    { 254, "million-standard-cubic-feet-per-minute"},
3937
    { 255, "unassigned-unit-value-255"},
3938
    { 47808, "standard-cubic-feet-per-day"},
3939
    { 47809, "million-standard-cubic-feet-per-day"},
3940
    { 47810, "thousand-cubic-feet-per-day"},
3941
    { 47811, "thousand-standard-cubic-feet-per-day"},
3942
    { 47812, "pounds-mass-per-day"},
3943
    { 47813, "reserved-unit-47813"},
3944
    { 47814, "millirems"},
3945
    { 47815, "millirems-per-hour"},
3946
    { 47816, "degrees-lovibond"},
3947
    { 47817, "alcohol-by-volume"},
3948
    { 47818, "international-bittering-units"},
3949
    { 47819, "european-bitterness-units"},
3950
    { 47820, "degrees-plato"},
3951
    { 47821, "specific-gravity"},
3952
    { 47822, "european-brewing-convention"},
3953
    { 0,   NULL}
3954
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
3955
   Enumerated values 256-65535 may be used by others subject to
3956
   the procedures and constraints described in Clause 23. */
3957
};
3958
3959
static const value_string
3960
BACnetErrorCode [] = {
3961
    {   0, "other"},
3962
    {   1, "authentication-failed"},
3963
    {   2, "configuration-in-progress"},
3964
    {   3, "device-busy"},
3965
    {   4, "dynamic-creation-not-supported"},
3966
    {   5, "file-access-denied"},
3967
    {   6, "incompatible-security-levels"},
3968
    {   7, "inconsistent-parameters"},
3969
    {   8, "inconsistent-selection-criterion"},
3970
    {   9, "invalid-data-type"},
3971
    {  10, "invalid-file-access-method"},
3972
    {  11, "invalid-file-start-position"},
3973
    {  12, "invalid-operator-name"},
3974
    {  13, "invalid-parameter-data-type"},
3975
    {  14, "invalid-time-stamp"},
3976
    {  15, "key-generation-error"},
3977
    {  16, "missing-required-parameter"},
3978
    {  17, "no-objects-of-specified-type"},
3979
    {  18, "no-space-for-object"},
3980
    {  19, "no-space-to-add-list-element"},
3981
    {  20, "no-space-to-write-property"},
3982
    {  21, "no-vt-sessions-available"},
3983
    {  22, "property-is-not-a-list"},
3984
    {  23, "object-deletion-not-permitted"},
3985
    {  24, "object-identifier-already-exists"},
3986
    {  25, "operational-problem"},
3987
    {  26, "password-failure"},
3988
    {  27, "read-access-denied"},
3989
    {  28, "security-not-supported"},
3990
    {  29, "service-request-denied"},
3991
    {  30, "timeout"},
3992
    {  31, "unknown-object"},
3993
    {  32, "unknown-property"},
3994
    {  33, "removed enumeration"},
3995
    {  34, "unknown-vt-class"},
3996
    {  35, "unknown-vt-session"},
3997
    {  36, "unsupported-object-type"},
3998
    {  37, "value-out-of-range"},
3999
    {  38, "vt-session-already-closed"},
4000
    {  39, "vt-session-termination-failure"},
4001
    {  40, "write-access-denied"},
4002
    {  41, "character-set-not-supported"},
4003
    {  42, "invalid-array-index"},
4004
    {  43, "cov-subscription-failed"},
4005
    {  44, "not-cov-property"},
4006
    {  45, "optional-functionality-not-supported"},
4007
    {  46, "invalid-configuration-data"},
4008
    {  47, "datatype-not-supported"},
4009
    {  48, "duplicate-name"},
4010
    {  49, "duplicate-object-id"},
4011
    {  50, "property-is-not-an-array"},
4012
    {  51, "abort - buffer - overflow" },
4013
    {  52, "abort - invalid - apdu - in - this - state" },
4014
    {  53, "abort - preempted - by - higher - priority - task" },
4015
    {  54, "abort - segmentation - not - supported" },
4016
    {  55, "abort - proprietary" },
4017
    {  56, "abort - other" },
4018
    {  57, "invalid - tag" },
4019
    {  58, "network - down" },
4020
    {  59, "reject - buffer - overflow" },
4021
    {  60, "reject - inconsistent - parameters" },
4022
    {  61, "reject - invalid - parameter - data - type" },
4023
    {  62, "reject - invalid - tag" },
4024
    {  63, "reject - missing - required - parameter" },
4025
    {  64, "reject - parameter - out - of - range" },
4026
    {  65, "reject - too - many - arguments" },
4027
    {  66, "reject - undefined - enumeration" },
4028
    {  67, "reject - unrecognized - service" },
4029
    {  68, "reject - proprietary" },
4030
    {  69, "reject - other" },
4031
    {  70, "unknown - device" },
4032
    {  71, "unknown - route" },
4033
    {  72, "value - not - initialized" },
4034
    {  73, "invalid-event-state"},
4035
    {  74, "no-alarm-configured"},
4036
    {  75, "log-buffer-full"},
4037
    {  76, "logged-value-purged"},
4038
    {  77, "no-property-specified"},
4039
    {  78, "not-configured-for-triggered-logging"},
4040
    {  79, "unknown-subscription"},
4041
    {  80, "parameter-out-of-range"},
4042
    {  81, "list-element-not-found"},
4043
    {  82, "busy"},
4044
    {  83, "communication-disabled"},
4045
    {  84, "success"},
4046
    {  85, "access-denied"},
4047
    {  86, "bad-destination-address"},
4048
    {  87, "bad-destination-device-id"},
4049
    {  88, "bad-signature"},
4050
    {  89, "bad-source-address"},
4051
    {  90, "bad-timestamp"},
4052
    {  91, "cannot-use-key"},
4053
    {  92, "cannot-verify-message-id"},
4054
    {  93, "correct-key-revision"},
4055
    {  94, "destination-device-id-required"},
4056
    {  95, "duplicate-message"},
4057
    {  96, "encryption-not-configured"},
4058
    {  97, "encryption-required"},
4059
    {  98, "incorrect-key"},
4060
    {  99, "invalid-key-data"},
4061
    { 100, "key-update-in-progress"},
4062
    { 101, "malformed-message"},
4063
    { 102, "not-key-server"},
4064
    { 103, "security-not-configured"},
4065
    { 104, "source-security-required"},
4066
    { 105, "too-many-keys"},
4067
    { 106, "unknown-authentication-type"},
4068
    { 107, "unknown-key"},
4069
    { 108, "unknown-key-revision"},
4070
    { 109, "unknown-source-message"},
4071
    { 110, "not-router-to-dnet"},
4072
    { 111, "router-busy"},
4073
    { 112, "unknown-network-message"},
4074
    { 113, "message-too-long"},
4075
    { 114, "security-error"},
4076
    { 115, "addressing-error"},
4077
    { 116, "write-bdt-failed"},
4078
    { 117, "read-bdt-failed"},
4079
    { 118, "register-foreign-device-failed"},
4080
    { 119, "read-fdt-failed"},
4081
    { 120, "delete-fdt-entry-failed"},
4082
    { 121, "distribute-broadcast-failed"},
4083
    { 122, "unknown-file-size"},
4084
    { 123, "abort-apdu-too-long"},
4085
    { 124, "abort-application-exceeded-reply-time"},
4086
    { 125, "abort-out-of-resources"},
4087
    { 126, "abort-tsm-timeout"},
4088
    { 127, "abort-window-size-out-of-range"},
4089
    { 128, "file-full"},
4090
    { 129, "inconsistent-configuration"},
4091
    { 130, "inconsistent-object-type"},
4092
    { 131, "internal-error"},
4093
    { 132, "not-configured"},
4094
    { 133, "out-of-memory"},
4095
    { 134, "value-too-long"},
4096
    { 135, "abort-insufficient-security"},
4097
    { 136, "abort-security-error"},
4098
    { 137, "duplicate-entry"},
4099
    { 138, "invalid-value-in-this-state"},
4100
    { 139, "invalid-operation-in-this-state"},
4101
    { 140, "list-item-not-numbered"},
4102
    { 141, "list-item-not-timestamped"},
4103
    { 142, "invalid-data-encoding"},
4104
    { 143, "bvlc-function-unknown"},
4105
    { 144, "bvlc-proprietary-function-unknown"},
4106
    { 145, "header-encoding-error"},
4107
    { 146, "header-not-understood"},
4108
    { 147, "message-incomplete"},
4109
    { 148, "not-a-bacnet-sc-hub"},
4110
    { 149, "payload-expected"},
4111
    { 150, "unexpected-data"},
4112
    { 151, "node-duplicate-vmac"},
4113
    { 152, "http-unexpected-response-code"},
4114
    { 153, "http-no-upgrade"},
4115
    { 154, "http-resource-not-local"},
4116
    { 155, "http-proxy-authentication-failed"},
4117
    { 156, "http-response-timeout"},
4118
    { 157, "http-response-syntax-error"},
4119
    { 158, "http-response-value-error"},
4120
    { 159, "http-response-missing-header"},
4121
    { 160, "http-websocket-header-error"},
4122
    { 161, "http-upgrade-required"},
4123
    { 162, "http-upgrade-error"},
4124
    { 163, "http-temporary-unavailable"},
4125
    { 164, "http-not-a-server"},
4126
    { 165, "http-error"},
4127
    { 166, "websocket-scheme-not-supported"},
4128
    { 167, "websocket-unknown-control-message"},
4129
    { 168, "websocket-close-error"},
4130
    { 169, "websocket-closed-by-peer"},
4131
    { 170, "websocket-endpoint-leaves"},
4132
    { 171, "websocket-protocol-error"},
4133
    { 172, "websocket-data-not-accepted"},
4134
    { 173, "websocket-closed-abnormally"},
4135
    { 174, "websocket-data-inconsistent"},
4136
    { 175, "websocket-data-against-policy"},
4137
    { 176, "websocket-frame-too-long"},
4138
    { 177, "websocket-extension-missing"},
4139
    { 178, "websocket-request-unavailable"},
4140
    { 179, "websocket-error"},
4141
    { 180, "tls-client-certificate-error"},
4142
    { 181, "tls-server-certificate-error"},
4143
    { 182, "tls-client-authentication-failed"},
4144
    { 183, "tls-server-authentication-failed"},
4145
    { 184, "tls-client-certificate-expired"},
4146
    { 185, "tls-server-certificate-expired"},
4147
    { 186, "tls-client-certificate-revoked"},
4148
    { 187, "tls-server-certificate-revoked"},
4149
    { 188, "tls-error"},
4150
    { 189, "dns-unavailable"},
4151
    { 190, "dns-name-resolution-failed"},
4152
    { 191, "dns-resolver-failure"},
4153
    { 192, "dns-error"},
4154
    { 193, "tcp-connect-timeout"},
4155
    { 194, "tcp-connection-refused"},
4156
    { 195, "tcp-closed-by-local"},
4157
    { 196, "tcp-closed-other"},
4158
    { 197, "tcp-error"},
4159
    { 198, "ip-address-not-reachable"},
4160
    { 199, "ip-error"},
4161
    { 200, "certificate-expired"},
4162
    { 201, "certificate-invalid"},
4163
    { 202, "certificate-malformed"},
4164
    { 203, "certificate-revoked"},
4165
    { 204, "unknown-key"},
4166
    { 205, "referenced-port-in-error"},
4167
    { 206, "not-enabled"},
4168
    { 207, "adjust-scope-required"},
4169
    { 208, "auth-scope-required"},
4170
    { 209, "bind-scope-required"},
4171
    { 210, "config-scope-required"},
4172
    { 211, "control-scope-required"},
4173
    { 212, "extended-scope-required"},
4174
    { 213, "incorrect-client"},
4175
    { 214, "install-scope-required"},
4176
    { 215, "insufficient-scope"},
4177
    { 216, "no-default-scope"},
4178
    { 217, "no-policy"},
4179
    { 218, "revoked-token"},
4180
    { 219, "override-scope-required"},
4181
    { 220, "inactive-token"},
4182
    { 221, "unknown-audience"},
4183
    { 222, "unknown-client"},
4184
    { 223, "unknown-scope"},
4185
    { 224, "view-scope-required"},
4186
    { 225, "incorrect-audience"},
4187
    { 226, "incorrect-client-origin"},
4188
    { 227, "invalid-array-size"},
4189
    { 228, "incorrect-issuer"},
4190
    { 229, "invalid-token"},
4191
    { 0,   NULL}
4192
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
4193
   Enumerated values 256-65535 may be used by others subject to the
4194
   procedures and constraints described in Clause 23. */
4195
};
4196
static value_string_ext BACnetErrorCode_ext = VALUE_STRING_EXT_INIT(BACnetErrorCode);
4197
4198
static const value_string
4199
BACnetPropertyIdentifier [] = {
4200
    {   0, "acked-transition"},
4201
    {   1, "ack-required"},
4202
    {   2, "action"},
4203
    {   3, "action-text"},
4204
    {   4, "active-text"},
4205
    {   5, "active-vt-session"},
4206
    {   6, "alarm-value"},
4207
    {   7, "alarm-values"},
4208
    {   8, "all"},
4209
    {   9, "all-writes-successful"},
4210
    {  10, "apdu-segment-timeout"},
4211
    {  11, "apdu-timeout"},
4212
    {  12, "application-software-version"},
4213
    {  13, "archive"},
4214
    {  14, "bias"},
4215
    {  15, "change-of-state-count"},
4216
    {  16, "change-of-state-time"},
4217
    {  17, "notification-class"},
4218
    {  18, "the property in this place was deleted"},
4219
    {  19, "controlled-variable-reference"},
4220
    {  20, "controlled-variable-units"},
4221
    {  21, "controlled-variable-value"},
4222
    {  22, "cov-increment"},
4223
    {  23, "datelist"},
4224
    {  24, "daylights-savings-status"},
4225
    {  25, "deadband"},
4226
    {  26, "derivative-constant"},
4227
    {  27, "derivative-constant-units"},
4228
    {  28, "description"},
4229
    {  29, "description-of-halt"},
4230
    {  30, "device-address-binding"},
4231
    {  31, "device-type"},
4232
    {  32, "effective-period"},
4233
    {  33, "elapsed-active-time"},
4234
    {  34, "error-limit"},
4235
    {  35, "event-enable"},
4236
    {  36, "event-state"},
4237
    {  37, "event-type"},
4238
    {  38, "exception-schedule"},
4239
    {  39, "fault-values"},
4240
    {  40, "feedback-value"},
4241
    {  41, "file-access-method"},
4242
    {  42, "file-size"},
4243
    {  43, "file-type"},
4244
    {  44, "firmware-revision"},
4245
    {  45, "high-limit"},
4246
    {  46, "inactive-text"},
4247
    {  47, "in-process"},
4248
    {  48, "instance-of"},
4249
    {  49, "integral-constant"},
4250
    {  50, "integral-constant-units"},
4251
    {  51, "issue-confirmed-notifications"},
4252
    {  52, "limit-enable"},
4253
    {  53, "list-of-group-members"},
4254
    {  54, "list-of-object-property-references"},
4255
    {  55, "list-of-session-keys"},
4256
    {  56, "local-date"},
4257
    {  57, "local-time"},
4258
    {  58, "location"},
4259
    {  59, "low-limit"},
4260
    {  60, "manipulated-variable-reference"},
4261
    {  61, "maximum-output"},
4262
    {  62, "max-apdu-length-accepted"},
4263
    {  63, "max-info-frames"},
4264
    {  64, "max-master"},
4265
    {  65, "max-pres-value"},
4266
    {  66, "minimum-off-time"},
4267
    {  67, "minimum-on-time"},
4268
    {  68, "minimum-output"},
4269
    {  69, "min-pres-value"},
4270
    {  70, "model-name"},
4271
    {  71, "modification-date"},
4272
    {  72, "notify-type"},
4273
    {  73, "number-of-APDU-retries"},
4274
    {  74, "number-of-states"},
4275
    {  75, "object-identifier"},
4276
    {  76, "object-list"},
4277
    {  77, "object-name"},
4278
    {  78, "object-property-reference"},
4279
    {  79, "object-type"},
4280
    {  80, "optional"},
4281
    {  81, "out-of-service"},
4282
    {  82, "output-units"},
4283
    {  83, "event-parameters"},
4284
    {  84, "polarity"},
4285
    {  85, "present-value"},
4286
    {  86, "priority"},
4287
    {  87, "priority-array"},
4288
    {  88, "priority-for-writing"},
4289
    {  89, "process-identifier"},
4290
    {  90, "program-change"},
4291
    {  91, "program-location"},
4292
    {  92, "program-state"},
4293
    {  93, "proportional-constant"},
4294
    {  94, "proportional-constant-units"},
4295
    {  95, "protocol-conformance-class"},
4296
    {  96, "protocol-object-types-supported"},
4297
    {  97, "protocol-services-supported"},
4298
    {  98, "protocol-version"},
4299
    {  99, "read-only"},
4300
    { 100, "reason-for-halt"},
4301
    { 101, "recipient"},
4302
    { 102, "recipient-list"},
4303
    { 103, "reliability"},
4304
    { 104, "relinquish-default"},
4305
    { 105, "required"},
4306
    { 106, "resolution"},
4307
    { 107, "segmentation-supported"},
4308
    { 108, "setpoint"},
4309
    { 109, "setpoint-reference"},
4310
    { 110, "state-text"},
4311
    { 111, "status-flags"},
4312
    { 112, "system-status"},
4313
    { 113, "time-delay"},
4314
    { 114, "time-of-active-time-reset"},
4315
    { 115, "time-of-state-count-reset"},
4316
    { 116, "time-synchronization-recipients"},
4317
    { 117, "units"},
4318
    { 118, "update-interval"},
4319
    { 119, "utc-offset"},
4320
    { 120, "vendor-identifier"},
4321
    { 121, "vendor-name"},
4322
    { 122, "vt-class-supported"},
4323
    { 123, "weekly-schedule"},
4324
    { 124, "attempted-samples"},
4325
    { 125, "average-value"},
4326
    { 126, "buffer-size"},
4327
    { 127, "client-cov-increment"},
4328
    { 128, "cov-resubscription-interval"},
4329
    { 129, "current-notify-time"},
4330
    { 130, "event-time-stamp"},
4331
    { 131, "log-buffer"},
4332
    { 132, "log-device-object-property"},
4333
    { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
4334
    { 134, "log-interval"},
4335
    { 135, "maximum-value"},
4336
    { 136, "minimum-value"},
4337
    { 137, "notification-threshold"},
4338
    { 138, "previous-notify-time"},
4339
    { 139, "protocol-revision"},
4340
    { 140, "records-since-notification"},
4341
    { 141, "record-count"},
4342
    { 142, "start-time"},
4343
    { 143, "stop-time"},
4344
    { 144, "stop-when-full"},
4345
    { 145, "total-record-count"},
4346
    { 146, "valid-samples"},
4347
    { 147, "window-interval"},
4348
    { 148, "window-samples"},
4349
    { 149, "maximum-value-time-stamp"},
4350
    { 150, "minimum-value-time-stamp"},
4351
    { 151, "variance-value"},
4352
    { 152, "active-cov-subscriptions"},
4353
    { 153, "backup-failure-timeout"},
4354
    { 154, "configuration-files"},
4355
    { 155, "database-revision"},
4356
    { 156, "direct-reading"},
4357
    { 157, "last-restore-time"},
4358
    { 158, "maintenance-required"},
4359
    { 159, "member-of"},
4360
    { 160, "mode"},
4361
    { 161, "operation-expected"},
4362
    { 162, "setting"},
4363
    { 163, "silenced"},
4364
    { 164, "tracking-value"},
4365
    { 165, "zone-members"},
4366
    { 166, "life-safety-alarm-values"},
4367
    { 167, "max-segments-accepted"},
4368
    { 168, "profile-name"},
4369
    { 169, "auto-slave-discovery"},
4370
    { 170, "manual-slave-address-binding"},
4371
    { 171, "slave-address-binding"},
4372
    { 172, "slave-proxy-enable"},
4373
    { 173, "last-notify-record"},     /* bug 4117 */
4374
    { 174, "schedule-default"},
4375
    { 175, "accepted-modes"},
4376
    { 176, "adjust-value"},
4377
    { 177, "count"},
4378
    { 178, "count-before-change"},
4379
    { 179, "count-change-time"},
4380
    { 180, "cov-period"},
4381
    { 181, "input-reference"},
4382
    { 182, "limit-monitoring-interval"},
4383
    { 183, "logging-object"},
4384
    { 184, "logging-record"},
4385
    { 185, "prescale"},
4386
    { 186, "pulse-rate"},
4387
    { 187, "scale"},
4388
    { 188, "scale-factor"},
4389
    { 189, "update-time"},
4390
    { 190, "value-before-change"},
4391
    { 191, "value-set"},
4392
    { 192, "value-change-time"},
4393
    { 193, "align-intervals"},
4394
    { 194, "group-member-names"},
4395
    { 195, "interval-offset"},
4396
    { 196, "last-restart-reason"},
4397
    { 197, "logging-type"},
4398
    { 198, "member-status-flags"},
4399
    { 199, "notification-period"},
4400
    { 200, "previous-notify-record"},
4401
    { 201, "requested-update-interval"},
4402
    { 202, "restart-notification-recipients"},
4403
    { 203, "time-of-device-restart"},
4404
    { 204, "time-synchronization-interval"},
4405
    { 205, "trigger"},
4406
    { 206, "UTC-time-synchronization-recipients"},
4407
    { 207, "node-subtype"},
4408
    { 208, "node-type"},
4409
    { 209, "structured-object-list"},
4410
    { 210, "subordinate-annotations"},
4411
    { 211, "subordinate-list"},
4412
    { 212, "actual-shed-level"},
4413
    { 213, "duty-window"},
4414
    { 214, "expected-shed-level"},
4415
    { 215, "full-duty-baseline"},
4416
    { 216, "node-subtype"},
4417
    { 217, "node-type"},
4418
    { 218, "requested-shed-level"},
4419
    { 219, "shed-duration"},
4420
    { 220, "shed-level-descriptions"},
4421
    { 221, "shed-levels"},
4422
    { 222, "state-description"},
4423
    /* enumeration values 223-225 are unassigned */
4424
    { 226, "door-alarm-state"},
4425
    { 227, "door-extended-pulse-time"},
4426
    { 228, "door-members"},
4427
    { 229, "door-open-too-long-time"},
4428
    { 230, "door-pulse-time"},
4429
    { 231, "door-status"},
4430
    { 232, "door-unlock-delay-time"},
4431
    { 233, "lock-status"},
4432
    { 234, "masked-alarm-values"},
4433
    { 235, "secured-status"},
4434
    /* enumeration values 236-243 are unassigned */
4435
    { 244, "absentee-limit"},     /* added with addenda 135-2008j */
4436
    { 245, "access-alarm-events"},
4437
    { 246, "access-doors"},
4438
    { 247, "access-event"},
4439
    { 248, "access-event-authentication-factor"},
4440
    { 249, "access-event-credential"},
4441
    { 250, "access-event-time"},
4442
    { 251, "access-transaction-events"},
4443
    { 252, "accompaniment"},
4444
    { 253, "accompaniment-time"},
4445
    { 254, "activation-time"},
4446
    { 255, "active-authentication-policy"},
4447
    { 256, "assigned-access-rights"},
4448
    { 257, "authentication-factors"},
4449
    { 258, "authentication-policy-list"},
4450
    { 259, "authentication-policy-names"},
4451
    { 260, "authentication-status"},
4452
    { 261, "authorization-mode"},
4453
    { 262, "belongs-to"},
4454
    { 263, "credential-disable"},
4455
    { 264, "credential-status"},
4456
    { 265, "credentials"},
4457
    { 266, "credentials-in-zone"},
4458
    { 267, "days-remaining"},
4459
    { 268, "entry-points"},
4460
    { 269, "exit-points"},
4461
    { 270, "expiration-time"},
4462
    { 271, "extended-time-enable"},
4463
    { 272, "failed-attempt-events"},
4464
    { 273, "failed-attempts"},
4465
    { 274, "failed-attempts-time"},
4466
    { 275, "last-access-event"},
4467
    { 276, "last-access-point"},
4468
    { 277, "last-credential-added"},
4469
    { 278, "last-credential-added-time"},
4470
    { 279, "last-credential-removed"},
4471
    { 280, "last-credential-removed-time"},
4472
    { 281, "last-use-time"},
4473
    { 282, "lockout"},
4474
    { 283, "lockout-relinquish-time"},
4475
    { 284, "master-exemption"},
4476
    { 285, "max-failed-attempts"},
4477
    { 286, "members"},
4478
    { 287, "muster-point"},
4479
    { 288, "negative-access-rules"},
4480
    { 289, "number-of-authentication-policies"},
4481
    { 290, "occupancy-count"},
4482
    { 291, "occupancy-count-adjust"},
4483
    { 292, "occupancy-count-enable"},
4484
    { 293, "occupancy-exemption"},
4485
    { 294, "occupancy-lower-limit"},
4486
    { 295, "occupancy-lower-limit-enforced"},
4487
    { 296, "occupancy-state"},
4488
    { 297, "occupancy-upper-limit"},
4489
    { 298, "occupancy-upper-limit-enforced"},
4490
    { 299, "passback-exemption"},
4491
    { 300, "passback-mode"},
4492
    { 301, "passback-timeout"},
4493
    { 302, "positive-access-rules"},
4494
    { 303, "reason-for-disable"},
4495
    { 304, "supported-formats"},
4496
    { 305, "supported-format-classes"},
4497
    { 306, "threat-authority"},
4498
    { 307, "threat-level"},
4499
    { 308, "trace-flag"},
4500
    { 309, "transaction-notification-class"},
4501
    { 310, "user-external-identifier"},
4502
    { 311, "user-information-reference"},
4503
    /* enumeration values 312-316 are unassigned */
4504
    { 317, "user-name"},
4505
    { 318, "user-type"},
4506
    { 319, "uses-remaining"},
4507
    { 320, "zone-from"},
4508
    { 321, "zone-to"},
4509
    { 322, "access-event-tag"},
4510
    { 323, "global-identifier"},
4511
    /* enumeration values 324-325 reserved for future addenda */
4512
    { 326, "verification-time"},
4513
    { 327, "base-device-security-policy"},
4514
    { 328, "distribution-key-revision"},
4515
    { 329, "do-not-hide"},
4516
    { 330, "key-sets"},
4517
    { 331, "last-key-server"},
4518
    { 332, "network-access-security-policies"},
4519
    { 333, "packet-reorder-time"},
4520
    { 334, "security-pdu-timeout"},
4521
    { 335, "security-time-window"},
4522
    { 336, "supported-security-algorithms"},
4523
    { 337, "update-key-set-timeout"},
4524
    { 338, "backup-and-restore-state"},
4525
    { 339, "backup-preparation-time"},
4526
    { 340, "restore-completion-time"},
4527
    { 341, "restore-preparation-time"},
4528
    { 342, "bit-mask"},       /* addenda 135-2008w */
4529
    { 343, "bit-text"},
4530
    { 344, "is-utc"},
4531
    { 345, "group-members"},
4532
    { 346, "group-member-names"},
4533
    { 347, "member-status-flags"},
4534
    { 348, "requested-update-interval"},
4535
    { 349, "covu-period"},
4536
    { 350, "covu-recipients"},
4537
    { 351, "event-message-texts"},
4538
    { 352, "event-message-texts-config"},
4539
    { 353, "event-detection-enable"},
4540
    { 354, "event-algorithm-inhibit"},
4541
    { 355, "event-algorithm-inhibit-ref"},
4542
    { 356, "time-delay-normal"},
4543
    { 357, "reliability-evaluation-inhibit"},
4544
    { 358, "fault-parameters"},
4545
    { 359, "fault-type"},
4546
    { 360, "local-forwarding-only"},
4547
    { 361, "process-identifier-filter"},
4548
    { 362, "subscribed-recipients"},
4549
    { 363, "port-filter"},
4550
    { 364, "authorization-exemptions"},
4551
    { 365, "allow-group-delay-inhibit"},
4552
    { 366, "channel-number"},
4553
    { 367, "control-groups"},
4554
    { 368, "execution-delay"},
4555
    { 369, "last-priority"},
4556
    { 370, "write-status"},
4557
    { 371, "property-list"},
4558
    { 372, "serial-number"},
4559
    { 373, "blink-warn-enable"},
4560
    { 374, "default-fade-time"},
4561
    { 375, "default-ramp-rate"},
4562
    { 376, "default-step-increment"},
4563
    { 377, "egress-time"},
4564
    { 378, "in-progress"},
4565
    { 379, "instantaneous-power"},
4566
    { 380, "lighting-command"},
4567
    { 381, "lighting-command-default-priority"},
4568
    { 382, "max-actual-value"},
4569
    { 383, "min-actual-value"},
4570
    { 384, "power"},
4571
    { 385, "transition"},
4572
    { 386, "egress-active"},
4573
    { 387, "interface-value"},
4574
    { 388, "fault-high-limit"},
4575
    { 389, "fault-low-limit"},
4576
    { 390, "low-diff-limit"},
4577
    { 391, "strike-count"},
4578
    { 392, "time-of-strike-count-reset"},
4579
    { 393, "default-timeout"},
4580
    { 394, "initial-timeout"},
4581
    { 395, "last-state-change"},
4582
    { 396, "state-change-values"},
4583
    { 397, "timer-running"},
4584
    { 398, "timer-state"},
4585
    { 399, "apdu-length"},
4586
    { 400, "bacnet-ip-address"},
4587
    { 401, "bacnet-ip-default-gateway"},
4588
    { 402, "bacnet-ip-dhcp-enable"},
4589
    { 403, "bacnet-ip-dhcp-lease-time"},
4590
    { 404, "bacnet-ip-dhcp-lease-time-remaining"},
4591
    { 405, "bacnet-ip-dhcp-server"},
4592
    { 406, "bacnet-ip-dns-server"},
4593
    { 407, "bacnet-ip-global-address"},
4594
    { 408, "bacnet-ip-mode"},
4595
    { 409, "bacnet-ip-multicast-address"},
4596
    { 410, "bacnet-ip-nat-traversal"},
4597
    { 411, "bacnet-ip-subnet-mask"},
4598
    { 412, "bacnet-ip-udp-port"},
4599
    { 413, "bbmd-accept-fd-registrations"},
4600
    { 414, "bbmd-broadcast-distribution-table"},
4601
    { 415, "bbmd-foreign-device-table"},
4602
    { 416, "changes-pending"},
4603
    { 417, "command"},
4604
    { 418, "fd-bbmd-address"},
4605
    { 419, "fd-subscription-lifetime"},
4606
    { 420, "link-speed"},
4607
    { 421, "link-speeds"},
4608
    { 422, "link-speed-autonegotiate"},
4609
    { 423, "mac-address"},
4610
    { 424, "network-interface-name"},
4611
    { 425, "network-number"},
4612
    { 426, "network-number-quality"},
4613
    { 427, "network-type"},
4614
    { 428, "routing-table"},
4615
    { 429, "virtual-mac-address-table"},
4616
    { 430, "command-time-array"},
4617
    { 431, "current-command-priority"},
4618
    { 432, "last-command-time"},
4619
    { 433, "value-source"},
4620
    { 434, "value-source-array"},
4621
    { 435, "bacnet-ipv6-mode"},
4622
    { 436, "ipv6-address"},
4623
    { 437, "ipv6-prefix-length"},
4624
    { 438, "bacnet-ipv6-udp-port"},
4625
    { 439, "ipv6-default-gateway"},
4626
    { 440, "bacnet-ipv6-multicast-address"},
4627
    { 441, "ipv6-dns-server"},
4628
    { 442, "ipv6-auto-addressing-enable"},
4629
    { 443, "ipv6-dhcp-lease-time"},
4630
    { 444, "ipv6-dhcp-lease-time-remaining"},
4631
    { 445, "ipv6-dhcp-server"},
4632
    { 446, "ipv6-zone-index"},
4633
    { 447, "assigned-landing-calls"},
4634
    { 448, "car-assigned-direction"},
4635
    { 449, "car-door-command"},
4636
    { 450, "car-door-status"},
4637
    { 451, "car-door-text"},
4638
    { 452, "car-door-zone"},
4639
    { 453, "car-drive-status"},
4640
    { 454, "car-load"},
4641
    { 455, "car-load-units"},
4642
    { 456, "car-mode"},
4643
    { 457, "car-moving-direction"},
4644
    { 458, "car-position"},
4645
    { 459, "elevator-group"},
4646
    { 460, "energy-meter"},
4647
    { 461, "energy-meter-ref"},
4648
    { 462, "escalator-mode"},
4649
    { 463, "fault-signals"},
4650
    { 464, "floor-text"},
4651
    { 465, "group-id"},
4652
    { 466, "enumeration value 466 is unassigned"},
4653
    { 467, "group-mode"},
4654
    { 468, "higher-deck"},
4655
    { 469, "installation-id"},
4656
    { 470, "landing-calls"},
4657
    { 471, "landing-call-control"},
4658
    { 472, "landing-door-status"},
4659
    { 473, "lower-deck"},
4660
    { 474, "machine-room-id"},
4661
    { 475, "making-car-call"},
4662
    { 476, "next-stopping-floor"},
4663
    { 477, "operation-direction"},
4664
    { 478, "passenger-alarm"},
4665
    { 479, "power-mode"},
4666
    { 480, "registered-car-call"},
4667
    { 481, "active-cov-multiple-subscriptions"},
4668
    { 482, "protocol-level"},
4669
    { 483, "reference-port"},
4670
    { 484, "deployed-profile-location"},
4671
    { 485, "profile-location"},
4672
    { 486, "tags"},
4673
    { 487, "subordinate-node-types"},
4674
    { 488, "subordinate-tags"},
4675
    { 489, "subordinate-relationship"},
4676
    { 490, "default-subordinate-relationship"},
4677
    { 491, "represents"},
4678
    { 492, "default-present-value"},
4679
    { 493, "present-stage"},
4680
    { 494, "stages"},
4681
    { 495, "stage-names"},
4682
    { 496, "target-references"},
4683
    { 497, "audit-source-reporter"},
4684
    { 498, "audit-level"},
4685
    { 499, "audit-notification-recipient"},
4686
    { 500, "audit-priority-filter"},
4687
    { 501, "auditable-operations"},
4688
    { 502, "delete-on-forward"},
4689
    { 503, "maximum-send-delay"},
4690
    { 504, "monitored-objects"},
4691
    { 505, "send-now"},
4692
    { 506, "floor-number"},
4693
    { 507, "device-uuid"},
4694
    { 508, "additional-reference-ports"},
4695
    { 509, "certificate-signing-request-file"},
4696
    { 510, "command-validation-result"},
4697
    { 511, "issuer-certificate-files"},
4698
    { 4194304, "max-bvlc-length-accepted"},
4699
    { 4194305, "max-npdu-length-accepted"},
4700
    { 4194306, "operational-certificate-file"},
4701
    { 4194307, "current-health"},
4702
    { 4194308, "sc-connect-wait-timeout"},
4703
    { 4194309, "sc-direct-connect-accept-enable"},
4704
    { 4194310, "sc-direct-connect-accept-uris"},
4705
    { 4194311, "ssc-direct-connect-binding"},
4706
    { 4194312, "sc-direct-connect-connection-status"},
4707
    { 4194313, "sc-direct-connect-initiate-enable"},
4708
    { 4194314, "sc-disconnect-wait-timeout"},
4709
    { 4194315, "sc-failed-connection-request"},
4710
    { 4194316, "sc-failover-hub-connection-status"},
4711
    { 4194317, "sc-failover-hub-uri"},
4712
    { 4194318, "sc-hub-connector-state"},
4713
    { 4194319, "sc-hub-function-accept-uris"},
4714
    { 4194320, "sc-hub-function-binding"},
4715
    { 4194321, "sc-hub-function-connection-status"},
4716
    { 4194322, "sc-hub-function-enable"},
4717
    { 4194323, "sc-heartbeat-timeout"},
4718
    { 4194324, "sc-primary-hub-connection-status"},
4719
    { 4194325, "sc-primary-hub-uri"},
4720
    { 4194326, "sc-maximum-reconnect-time"},
4721
    { 4194327, "sc-minimum-reconnect-time"},
4722
    { 4194328, "color-override"},
4723
    { 4194329, "color-reference"},
4724
    { 4194330, "default-color"},
4725
    { 4194331, "default-color-temperature"},
4726
    { 4194332, "override-color-reference"},
4727
    { 4194334, "color-command"},
4728
    { 4194335, "high_end_trim"},
4729
    { 4194336, "low_end_trim"},
4730
    { 4194337, "trim_fade_time"},
4731
    { 4194338, "device-address-proxy-enable"},
4732
    { 4194339, "device-address-proxy-table"},
4733
    { 4194340, "device-address-proxy-timeout"},
4734
    { 4194341, "default-on-value"},
4735
    { 4194342, "last-on-value"},
4736
    { 4194343, "authorization-cache"},
4737
    { 4194344, "authorization-groups"},
4738
    { 4194345, "authorization-policy"},
4739
    { 4194346, "authorization-scope"},
4740
    { 4194347, "authorization-server"},
4741
    { 4194348, "authorization-status"},
4742
    { 4194349, "max-proxied-i-ams-per-second"},
4743
    { 0,   NULL}
4744
/* Enumerated values 0-511 are reserved for definition by ASHRAE.
4745
   Enumerated values 512-4194303 may be used by others subject to
4746
   the procedures and constraints described in Clause 23. */
4747
};
4748
4749
static const value_string
4750
BACnetBinaryPV [] = {
4751
    { 0, "inactive"},
4752
    { 1, "active"},
4753
    { 0, NULL}
4754
};
4755
4756
4757
446
#define ANSI_X3_4      0 /* ANSI X3.4, a/k/a "ASCII"; full UTF-8 since 2010 */
4758
                         /* See, for example, ANSI/ASHRAE Addendum k to ANSI/ASHRAE Standard 135-2008 */
4759
                         /* XXX - I've seen captures using this for ISO 8859-1 */
4760
15.3k
#define IBM_MS_DBCS    1 /* "IBM/Microsoft DBCS"; was there only one such DBCS? */
4761
132
#define JIS_C_6226     2 /* JIS C 6226 */
4762
101
#define ISO_10646_UCS4 3 /* ISO 10646 (UCS-4) - 4-byte Unicode */
4763
90
#define ISO_10646_UCS2 4 /* ISO 10646 (UCS-2) - 2-byte Unicode Basic Multilingual Plane (not UTF-16, presumably) */
4764
50
#define ISO_8859_1     5 /* ISO 8859-1 */
4765
static const value_string
4766
BACnetCharacterSet [] = {
4767
    { ANSI_X3_4,      "ANSI X3.4 / UTF-8 (since 2010)"},
4768
    { IBM_MS_DBCS,    "IBM/Microsoft DBCS"},
4769
    { JIS_C_6226,     "JIS C 6226"},
4770
    { ISO_10646_UCS4, "ISO 10646 (UCS-4)"},
4771
    { ISO_10646_UCS2, "ISO 10646 (UCS-2)"},
4772
    { ISO_8859_1,     "ISO 8859-1"},
4773
    { 0,     NULL}
4774
};
4775
4776
static const value_string
4777
BACnetStatusFlags [] = {
4778
    { 0, "in-alarm"},
4779
    { 1, "fault"},
4780
    { 2, "overridden"},
4781
    { 3, "out-of-service"},
4782
    { 0, NULL}
4783
};
4784
4785
static const value_string
4786
BACnetMessagePriority [] = {
4787
    { 0, "normal"},
4788
    { 1, "urgent"},
4789
    { 0, NULL}
4790
};
4791
4792
static const value_string
4793
BACnetAcknowledgementFilter [] = {
4794
    { 0, "all"},
4795
    { 1, "acked"},
4796
    { 2, "not-acked"},
4797
    { 0, NULL}
4798
};
4799
4800
static const value_string
4801
BACnetResultFlags [] = {
4802
    { 0, "first-item"},
4803
    { 1, "last-item"},
4804
    { 2, "more-items"},
4805
    { 0, NULL}
4806
};
4807
4808
static const value_string
4809
BACnetRelationSpecifier [] = {
4810
    { 0, "equal"},
4811
    { 1, "not-equal"},
4812
    { 2, "less-than"},
4813
    { 3, "greater-than"},
4814
    { 4, "less-than-or-equal"},
4815
    { 5, "greater-than-or-equal"},
4816
    { 0, NULL}
4817
};
4818
4819
static const value_string
4820
BACnetSelectionLogic [] = {
4821
    { 0, "and"},
4822
    { 1, "or"},
4823
    { 2, "all"},
4824
    { 0, NULL}
4825
};
4826
4827
static const value_string
4828
BACnetEventStateFilter [] = {
4829
    { 0, "offnormal"},
4830
    { 1, "fault"},
4831
    { 2, "normal"},
4832
    { 3, "all"},
4833
    { 4, "active"},
4834
    { 0, NULL}
4835
};
4836
4837
static const value_string
4838
BACnetEventTransitionBits [] = {
4839
    { 0, "to-offnormal"},
4840
    { 1, "to-fault"},
4841
    { 2, "to-normal"},
4842
    { 0, NULL}
4843
};
4844
4845
static const value_string
4846
BACnetSegmentation [] = {
4847
    { 0, "segmented-both"},
4848
    { 1, "segmented-transmit"},
4849
    { 2, "segmented-receive"},
4850
    { 3, "no-segmentation"},
4851
    { 0, NULL}
4852
};
4853
4854
static const value_string
4855
BACnetSilencedState [] = {
4856
    { 0, "unsilenced"},
4857
    { 1, "audible-silenced"},
4858
    { 2, "visible-silenced"},
4859
    { 3, "all-silenced"},
4860
    { 0, NULL}
4861
};
4862
4863
static const value_string
4864
BACnetDeviceStatus [] = {
4865
    { 0, "operational"},
4866
    { 1, "operational-read-only"},
4867
    { 2, "download-required"},
4868
    { 3, "download-in-progress"},
4869
    { 4, "non-operational"},
4870
    { 5, "backup-in-progress"},
4871
    { 0, NULL}
4872
};
4873
4874
static const value_string
4875
BACnetEnableDisable [] = {
4876
    { 0, "enable"},
4877
    { 1, "disable"},
4878
    { 2, "disable-initiation"},
4879
    { 0, NULL}
4880
};
4881
4882
static const value_string
4883
months [] = {
4884
    {   1, "January" },
4885
    {   2, "February" },
4886
    {   3, "March" },
4887
    {   4, "April" },
4888
    {   5, "May" },
4889
    {   6, "June" },
4890
    {   7, "July" },
4891
    {   8, "August" },
4892
    {   9, "September" },
4893
    {  10, "October" },
4894
    {  11, "November" },
4895
    {  12, "December" },
4896
    {  13, "odd month" },
4897
    {  14, "even month" },
4898
    { 255, "any month" },
4899
    { 0,   NULL }
4900
};
4901
4902
static const value_string
4903
weekofmonth [] = {
4904
    {   1, "days numbered 1-7" },
4905
    {   2, "days numbered 8-14" },
4906
    {   3, "days numbered 15-21" },
4907
    {   4, "days numbered 22-28" },
4908
    {   5, "days numbered 29-31" },
4909
    {   6, "last 7 days of this month" },
4910
    {   7, "any of 7 days prior to last 7 days of this month" },
4911
    {   8, "any of 7 days prior to last 14 days of this month" },
4912
    {   9, "any of 7 days prior to last 21 days of this month" },
4913
    { 255, "any week of this month" },
4914
    { 0,   NULL }
4915
};
4916
4917
/* note: notification class object recipient-list uses
4918
   different day-of-week enum */
4919
static const value_string
4920
day_of_week [] = {
4921
    {   1, "Monday" },
4922
    {   2, "Tuesday" },
4923
    {   3, "Wednesday" },
4924
    {   4, "Thursday" },
4925
    {   5, "Friday" },
4926
    {   6, "Saturday" },
4927
    {   7, "Sunday" },
4928
    { 255, "any day of week" },
4929
    { 0,   NULL }
4930
};
4931
4932
static const value_string
4933
BACnetErrorClass [] = {
4934
    { 0, "device" },
4935
    { 1, "object" },
4936
    { 2, "property" },
4937
    { 3, "resources" },
4938
    { 4, "security" },
4939
    { 5, "services" },
4940
    { 6, "vt" },
4941
    { 7, "communication" },
4942
    { 0, NULL }
4943
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
4944
   Enumerated values64-65535 may be used by others subject to
4945
   the procedures and constraints described in Clause 23. */
4946
};
4947
4948
static const value_string
4949
BACnetVTClass [] = {
4950
    { 0, "default-terminal" },
4951
    { 1, "ansi-x3-64" },
4952
    { 2, "dec-vt52" },
4953
    { 3, "dec-vt100" },
4954
    { 4, "dec-vt200" },
4955
    { 5, "hp-700-94" },
4956
    { 6, "ibm-3130" },
4957
    { 0, NULL }
4958
};
4959
4960
static const value_string
4961
BACnetEventType [] = {
4962
    {  0, "change-of-bitstring" },
4963
    {  1, "change-of-state" },
4964
    {  2, "change-of-value" },
4965
    {  3, "command-failure" },
4966
    {  4, "floating-limit" },
4967
    {  5, "out-of-range" },
4968
    {  6, "complex-event-type" },
4969
    {  7, "(deprecated)event-buffer-ready" },
4970
    {  8, "change-of-life-safety" },
4971
    {  9, "extended" },
4972
    { 10, "buffer-ready" },
4973
    { 11, "unsigned-range" },
4974
    { 13, "access-event" },
4975
    { 14, "double-out-of-range"},     /* added with addenda 135-2008w */
4976
    { 15, "signed-out-of-range"},
4977
    { 16, "unsigned-out-of-range"},
4978
    { 17, "change-of-characterstring"},
4979
    { 18, "change-of-status-flags"},
4980
    { 19, "change-of-reliability" },
4981
    { 20, "none" },
4982
    { 21, "change-of-discrete-value"},
4983
    { 22, "change-of-timer"},
4984
    { 0,  NULL }
4985
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
4986
   Enumerated values 64-65535 may be used by others subject to
4987
   the procedures and constraints described in Clause 23.
4988
   It is expected that these enumerated values will correspond
4989
   to the use of the complex-event-type CHOICE [6] of the
4990
   BACnetNotificationParameters production. */
4991
};
4992
4993
static const value_string
4994
BACnetEventState [] = {
4995
    { 0, "normal" },
4996
    { 1, "fault" },
4997
    { 2, "offnormal" },
4998
    { 3, "high-limit" },
4999
    { 4, "low-limit" },
5000
    { 5, "life-safety-alarm" },
5001
    { 0, NULL }
5002
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
5003
   Enumerated values 64-65535 may be used by others subject to
5004
   the procedures and constraints described in Clause 23.  */
5005
};
5006
5007
static const value_string
5008
BACnetLogStatus [] = {
5009
    { 0, "log-disabled" },
5010
    { 1, "buffer-purged" },
5011
    { 2, "log-interrupted"},
5012
    { 0, NULL }
5013
};
5014
5015
static const value_string
5016
BACnetMaintenance [] = {
5017
    { 0, "none" },
5018
    { 1, "periodic-test" },
5019
    { 2, "need-service-operational" },
5020
    { 3, "need-service-inoperative" },
5021
    { 0, NULL }
5022
};
5023
5024
static const value_string
5025
BACnetNotifyType [] = {
5026
    { 0, "alarm" },
5027
    { 1, "event" },
5028
    { 2, "ack-notification" },
5029
    { 0, NULL }
5030
};
5031
5032
static const value_string
5033
BACnetServicesSupported [] = {
5034
    {  0, "acknowledgeAlarm"},
5035
    {  1, "confirmedCOVNotification"},
5036
    {  2, "confirmedEventNotification"},
5037
    {  3, "getAlarmSummary"},
5038
    {  4, "getEnrollmentSummary"},
5039
    {  5, "subscribeCOV"},
5040
    {  6, "atomicReadFile"},
5041
    {  7, "atomicWriteFile"},
5042
    {  8, "addListElement"},
5043
    {  9, "removeListElement"},
5044
    { 10, "createObject"},
5045
    { 11, "deleteObject"},
5046
    { 12, "readProperty"},
5047
    { 13, "readPropertyConditional"},
5048
    { 14, "readPropertyMultiple"},
5049
    { 15, "writeProperty"},
5050
    { 16, "writePropertyMultiple"},
5051
    { 17, "deviceCommunicationControl"},
5052
    { 18, "confirmedPrivateTransfer"},
5053
    { 19, "confirmedTextMessage"},
5054
    { 20, "reinitializeDevice"},
5055
    { 21, "vtOpen"},
5056
    { 22, "vtClose"},
5057
    { 23, "vtData"},
5058
    { 24, "authenticate"},
5059
    { 25, "requestKey"},
5060
    { 26, "i-Am"},
5061
    { 27, "i-Have"},
5062
    { 28, "unconfirmedCOVNotification"},
5063
    { 29, "unconfirmedEventNotification"},
5064
    { 30, "unconfirmedPrivateTransfer"},
5065
    { 31, "unconfirmedTextMessage"},
5066
    { 32, "timeSynchronization"},
5067
    { 33, "who-Has"},
5068
    { 34, "who-Is"},
5069
    { 35, "readRange"},
5070
    { 36, "utcTimeSynchronization"},
5071
    { 37, "lifeSafetyOperation"},
5072
    { 38, "subscribeCOVProperty"},
5073
    { 39, "getEventInformation"},
5074
    { 40, "write-group"},
5075
    { 41, "subscribe-cov-property-multiple"},
5076
    { 42, "confirmed-cov-notification-multiple"},
5077
    { 43, "unconfirmed-cov-notification-multiple"},
5078
    { 44, "confirmed-audit-notification"},
5079
    { 45, "audit-log-query"},
5080
    { 46, "unconfirmed-audit-notification"},
5081
    { 47, "who-am-i"},
5082
    { 48, "you-are"},
5083
    { 49, "auth-request"},
5084
    { 0,  NULL}
5085
};
5086
5087
static const value_string
5088
BACnetPropertyStates [] = {
5089
    {  0, "boolean-value"},
5090
    {  1, "binary-value"},
5091
    {  2, "event-type"},
5092
    {  3, "polarity"},
5093
    {  4, "program-change"},
5094
    {  5, "program-state"},
5095
    {  6, "reason-for-halt"},
5096
    {  7, "reliability"},
5097
    {  8, "state"},
5098
    {  9, "system-status"},
5099
    { 10, "units"},
5100
    { 11, "unsigned-value"},
5101
    { 12, "life-safety-mode"},
5102
    { 13, "life-safety-state"},
5103
    { 14, "restart-reason"},
5104
    { 15, "door-alarm-state"},
5105
    { 16, "action"},
5106
    { 17, "door-secured-status"},
5107
    { 18, "door-status"},
5108
    { 19, "door-value"},
5109
    { 20, "file-access-method"},
5110
    { 21, "lock-status"},
5111
    { 22, "life-safety-operation"},
5112
    { 23, "maintenance"},
5113
    { 24, "node-type"},
5114
    { 25, "notify-type"},
5115
    { 26, "security-level"},
5116
    { 27, "shed-state"},
5117
    { 28, "silenced-state"},
5118
    { 29, "unknown-29"},
5119
    { 30, "access-event"},
5120
    { 31, "zone-occupancy-state"},
5121
    { 32, "access-credential-disable-reason"},
5122
    { 33, "access-credential-disable"},
5123
    { 34, "authentication-status"},
5124
    { 35, "unknown-35"},
5125
    { 36, "backup-state"},
5126
    { 37, "write-status"},
5127
    { 38, "lighting-in-progress"},
5128
    { 39, "lighting-operation"},
5129
    { 40, "lighting-transition"},
5130
    { 41, "signed-value"},
5131
    { 42, "unknown-42"},
5132
    { 43, "timer-state"},
5133
    { 44, "timer-transition"},
5134
    { 45, "bacnet-ip-mode"},
5135
    { 46, "network-port-command"},
5136
    { 47, "network-type"},
5137
    { 48, "network-number-quality"},
5138
    { 49, "escalator-operation-direction"},
5139
    { 50, "escalator-fault"},
5140
    { 51, "escalator-mode"},
5141
    { 52, "lift-car-direction"},
5142
    { 53, "lift-car-door-command"},
5143
    { 54, "lift-car-drive-status"},
5144
    { 55, "lift-car-mode"},
5145
    { 56, "lift-group-mode"},
5146
    { 57, "lift-fault"},
5147
    { 58, "protocol-level"},
5148
    { 59, "audit-level"},
5149
    { 60, "audit-operation"},
5150
    { 63, "extended-value"},
5151
    {256, "-- example-one"},
5152
    {257, "-- example-two"},
5153
    {258, "sc-connection-state"},
5154
    {259, "sc-hub-connecto-state"},
5155
    { 0, NULL}
5156
/* Tag values 0-63 are reserved for definition by ASHRAE.
5157
   Tag values of 64-254 may be used by others to accommodate
5158
   vendor specific properties that have discrete or enumerated values,
5159
   subject to the constraints described in Clause 23. */
5160
};
5161
5162
static const value_string
5163
BACnetProgramError [] = {
5164
    { 0, "normal"},
5165
    { 1, "load-failed"},
5166
    { 2, "internal"},
5167
    { 3, "program"},
5168
    { 4, "other"},
5169
    { 0, NULL}
5170
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
5171
   Enumerated values 64-65535 may be used by others subject to
5172
   the procedures and constraints described in Clause 23. */
5173
};
5174
5175
static const value_string
5176
BACnetProgramRequest [] = {
5177
    { 0, "ready"},
5178
    { 1, "load"},
5179
    { 2, "run"},
5180
    { 3, "halt"},
5181
    { 4, "restart"},
5182
    { 5, "unload"},
5183
    { 0, NULL}
5184
};
5185
5186
static const value_string
5187
BACnetProgramState [] = {
5188
    { 0, "idle"},
5189
    { 1, "loading"},
5190
    { 2, "running"},
5191
    { 3, "waiting"},
5192
    { 4, "halted"},
5193
    { 5, "unloading"},
5194
    { 0, NULL}
5195
};
5196
5197
static const value_string
5198
BACnetReinitializedStateOfDevice [] = {
5199
    { 0, "coldstart"},
5200
    { 1, "warmstart"},
5201
    { 2, "start-backup"},
5202
    { 3, "end-backup"},
5203
    { 4, "start-restore"},
5204
    { 5, "end-restore"},
5205
    { 6, "abort-restore"},
5206
    { 7, "activate-changes"},
5207
    { 0, NULL}
5208
};
5209
5210
static const value_string
5211
BACnetPolarity [] = {
5212
    { 0, "normal"},
5213
    { 1, "reverse"},
5214
    { 0, NULL}
5215
};
5216
5217
static const value_string
5218
BACnetTagNames[] = {
5219
    { 5, "Extended Value" },
5220
    { 6, "Opening Tag" },
5221
    { 7, "Closing Tag" },
5222
    { 0, NULL }
5223
};
5224
5225
static const value_string
5226
BACnetReadRangeOptions[] = {
5227
    { 3, "range byPosition" },
5228
    { 4, "range byTime" },
5229
    { 5, "range timeRange" },
5230
    { 6, "range bySequenceNumber" },
5231
    { 7, "range byTime" },
5232
    { 0, NULL }
5233
};
5234
5235
/* Present_Value for Load Control Object */
5236
static const value_string
5237
BACnetShedState[] = {
5238
    { 0, "shed-inactive" },
5239
    { 1, "shed-request-pending" },
5240
    { 2, "shed-compliant" },
5241
    { 3, "shed-non-compliant" },
5242
    { 0, NULL }
5243
};
5244
5245
static const value_string
5246
BACnetFaultType[] = {
5247
  { 0, "none" },
5248
  { 1, "fault-characterstring" },
5249
  { 2, "fault-extended" },
5250
  { 3, "fault-life-safety" },
5251
  { 4, "fault-state" },
5252
  { 5, "fault-status-flags" },
5253
  { 6, "fault-out-of-range" },
5254
  { 7, "fault-listed" },
5255
  { 0, NULL }
5256
};
5257
5258
static const value_string
5259
BACnetNodeType [] = {
5260
    { 0, "unknown" },
5261
    { 1, "system" },
5262
    { 2, "network" },
5263
    { 3, "device" },
5264
    { 4, "organizational" },
5265
    { 5, "area" },
5266
    { 6, "equipment" },
5267
    { 7, "point" },
5268
    { 8, "collection" },
5269
    { 9, "property" },
5270
    { 10, "functional" },
5271
    { 11, "other" },
5272
    { 12, "subsystem" },
5273
    { 13, "building" },
5274
    { 14, "floor" },
5275
    { 15, "section" },
5276
    { 16, "module" },
5277
    { 17, "tree" },
5278
    { 18, "member" },
5279
    { 19, "protocol" },
5280
    { 20, "room" },
5281
    { 21, "zone" },
5282
    { 0, NULL }
5283
};
5284
5285
static const value_string
5286
BACnetLoggingType [] = {
5287
    { 0, "polled" },
5288
    { 1, "cov" },
5289
    { 2, "triggered" },
5290
    { 0, NULL }
5291
};
5292
5293
static const value_string
5294
BACnetDoorStatus [] = {
5295
    { 0, "closed" },
5296
    { 1, "opened" },
5297
    { 2, "unknown" },
5298
    { 3, "door-fault" },
5299
    { 4, "unused" },
5300
    { 5, "none" },
5301
    { 6, "closing" },
5302
    { 7, "opening" },
5303
    { 8, "safety-locked" },
5304
    { 9, "limited-opened" },
5305
    { 0, NULL }
5306
};
5307
5308
static const value_string
5309
BACnetDoorValue[] = {
5310
  { 0, "lock" },
5311
  { 1, "unlock" },
5312
  { 2, "pulse-unlock" },
5313
  { 3, "extended-pulse-unlock" },
5314
  { 0, NULL }
5315
};
5316
5317
static const value_string
5318
BACnetLockStatus [] = {
5319
    { 0, "locked" },
5320
    { 1, "unlocked" },
5321
    { 2, "fault" },
5322
    { 3, "unknown" },
5323
    { 0, NULL }
5324
};
5325
5326
static const value_string
5327
BACnetDoorSecuredStatus [] = {
5328
    { 0, "secured" },
5329
    { 1, "unsecured" },
5330
    { 2, "unknown" },
5331
    { 0, NULL }
5332
};
5333
5334
static const value_string
5335
BACnetDoorAlarmState [] = {
5336
    { 0, "normal" },
5337
    { 1, "alarm" },
5338
    { 2, "door-open-too-long" },
5339
    { 3, "forced-open" },
5340
    { 4, "tamper" },
5341
    { 5, "door-fault" },
5342
    { 6, "lock-down" },
5343
    { 7, "free-access" },
5344
    { 8, "egress-open" },
5345
    { 0, NULL }
5346
};
5347
5348
static const value_string
5349
BACnetSecurityPolicy [] = {
5350
    { 0, "plain-non-trusted"},
5351
    { 1, "plain-trusted"},
5352
    { 2, "signed-trusted"},
5353
    { 3, "encrypted-trusted"},
5354
    { 0, NULL }
5355
};
5356
5357
static const value_string
5358
BACnetAccumulatorStatus [] = {
5359
    { 0, "normal" },
5360
    { 1, "starting" },
5361
    { 2, "recovered" },
5362
    { 3, "abnormal" },
5363
    { 4, "failed" },
5364
    { 0, NULL }
5365
};
5366
5367
static const value_string
5368
BACnetAuditLevel [] = {
5369
    { 0, "none" },
5370
    { 1, "audit-all" },
5371
    { 2, "audit-config" },
5372
    { 3, "default" },
5373
    { 0, NULL }
5374
};
5375
5376
static const value_string
5377
BACnetAuditPriorityFilter [] = {
5378
    { 1, "manual-life-safety" },
5379
    { 2, "automatic-life-safety" },
5380
    { 3, "priority-3" },
5381
    { 4, "priority-4" },
5382
    { 5, "critical-equipment-controls" },
5383
    { 6, "minimum-on-off" },
5384
    { 7, "priority-7" },
5385
    { 8, "manual-operator" },
5386
    { 9, "priority-9" },
5387
    { 10, "priority-10" },
5388
    { 11, "priority-11" },
5389
    { 12, "priority-12" },
5390
    { 13, "priority-13" },
5391
    { 14, "priority-14" },
5392
    { 15, "priority-15" },
5393
    { 16, "priority-16" },
5394
    { 0, NULL }
5395
};
5396
5397
static const value_string
5398
BACnetAuditOperation [] = {
5399
    { 0, "read" },
5400
    { 1, "write" },
5401
    { 2, "create" },
5402
    { 3, "delete" },
5403
    { 4, "life-safety" },
5404
    { 5, "acknowledge-alarm" },
5405
    { 6, "device-disable-comm" },
5406
    { 7, "device-enable-comm" },
5407
    { 8, "device-reset" },
5408
    { 9, "device-backup" },
5409
    { 10, "device-restore" },
5410
    { 11, "subscription" },
5411
    { 12, "notification" },
5412
    { 13, "auditing-failure" },
5413
    { 14, "network-changes" },
5414
    { 15, "general" },
5415
    { 0, NULL }
5416
};
5417
5418
static const value_string
5419
BACnetSuccessFilter [] = {
5420
    { 0, "all" },
5421
    { 1, "successes-only" },
5422
    { 2, "failures-only" },
5423
    { 0, NULL }
5424
};
5425
5426
static const value_string
5427
BACnetAuthorizationScopeStandard [] = {
5428
    { 0, "view" },
5429
    { 1, "adjust" },
5430
    { 2, "control" },
5431
    { 3, "override" },
5432
    { 4, "config" },
5433
    { 5, "bind" },
5434
    { 6, "install" },
5435
    { 7, "auth" },
5436
    { 8, "infrastructure" },
5437
    { 9, "reserved-9" },
5438
    { 10, "reserved-10" },
5439
    { 11, "reserved-11" },
5440
    { 12, "reserved-12" },
5441
    { 13, "reserved-13" },
5442
    { 14, "reserved-14" },
5443
    { 15, "reserved-15" },
5444
    { 16, "reserved-16" },
5445
    { 17, "reserved-17" },
5446
    { 18, "reserved-18" },
5447
    { 19, "reserved-19" },
5448
    { 20, "reserved-20" },
5449
    { 21, "reserved-21" },
5450
    { 22, "reserved-22" },
5451
    { 23, "reserved-23" },
5452
    { 0, NULL }
5453
};
5454
5455
static const value_string
5456
BACnetAuthorizationPosture[] = {
5457
    { 0, "open" },
5458
    { 1, "proprietary" },
5459
    { 2, "configured" },
5460
    { 3, "misconfigured-partial" },
5461
    { 4, "misconfigured-total" },
5462
    { 0, NULL }
5463
};
5464
5465
static const value_string
5466
BACnetAuthenticationDecision[] = {
5467
    { 0, "allow-match" },
5468
    { 1, "deny-mismatch" },
5469
    { 2, "deny-non-relay" },
5470
    { 0, NULL }
5471
};
5472
5473
static const value_string
5474
BACnetAuthorizationDecision[] = {
5475
    { 0, "allow-by-token" },
5476
    { 1, "allow-by-local-polic" },
5477
    { 2, "deny-no-token-or-policy" },
5478
    { 3, "deny-not-before" },
5479
    { 4, "deny-not-after" },
5480
    { 5, "deny-target-device" },
5481
    { 6, "deny-target-group" },
5482
    { 7, "deny-client-device" },
5483
    { 8, "deny-client-method" },
5484
    { 9, "deny-scope" },
5485
    { 10, "deny-issuer" },
5486
    { 11, "deny-revoked" },
5487
    { 12, "deny-signature" },
5488
    { 13, "deny-other" },
5489
    { 0, NULL }
5490
};
5491
5492
static const value_string
5493
BACnetAuthorizationConstraintOrigin[] = {
5494
    { 0, "direct-connect" },
5495
    { 1, "same-network" },
5496
    { 2, "any-network" },
5497
    { 0, NULL }
5498
};
5499
5500
static const value_string
5501
BACnetAuthorizationConstraintAuthentication[] = {
5502
    { 0, "certified" },
5503
    { 1, "secure-path" },
5504
    { 2, "any-method" },
5505
    { 0, NULL }
5506
};
5507
5508
static int proto_bacapp;
5509
static int hf_bacapp_type;
5510
static int hf_bacapp_pduflags;
5511
static int hf_bacapp_SEG;
5512
static int hf_bacapp_MOR;
5513
static int hf_bacapp_SA;
5514
static int hf_bacapp_response_segments;
5515
static int hf_bacapp_max_adpu_size;
5516
static int hf_bacapp_invoke_id;
5517
static int hf_bacapp_object_identifier;
5518
static int hf_bacapp_device_identifier;
5519
static int hf_bacapp_objectType;
5520
static int hf_bacapp_object_name;
5521
static int hf_bacapp_instanceNumber;
5522
static int hf_bacapp_sequence_number;
5523
static int hf_bacapp_window_size;
5524
static int hf_bacapp_service;
5525
static int hf_bacapp_NAK;
5526
static int hf_bacapp_SRV;
5527
static int hf_bacapp_notify_type;
5528
static int hf_bacapp_event_type;
5529
static int hf_bacapp_error_class;
5530
static int hf_bacapp_error_code;
5531
static int hf_Device_Instance_Range_Low_Limit;
5532
static int hf_Device_Instance_Range_High_Limit;
5533
static int hf_BACnetRejectReason;
5534
static int hf_BACnetAbortReason;
5535
static int hf_BACnetApplicationTagNumber;
5536
static int hf_BACnetContextTagNumber;
5537
static int hf_BACnetExtendedTagNumber;
5538
static int hf_BACnetNamedTag;
5539
static int hf_BACnetTagClass;
5540
static int hf_BACnetCharacterSet;
5541
static int hf_BACnetCodePage;
5542
static int hf_bacapp_tag_lvt;
5543
static int hf_bacapp_tag_ProcessId;
5544
static int hf_bacapp_tag_to_state;
5545
static int hf_bacapp_tag_from_state;
5546
static int hf_bacapp_uservice;
5547
static int hf_BACnetPropertyIdentifier;
5548
static int hf_BACnetVendorIdentifier;
5549
static int hf_BACnetRestartReason;
5550
static int hf_bacapp_tag_IPV4;
5551
static int hf_bacapp_tag_IPV6;
5552
static int hf_bacapp_tag_PORT;
5553
static int hf_bacapp_tag_mac_address_broadcast;
5554
static int hf_bacapp_reserved_ashrea;
5555
static int hf_bacapp_unused_bits;
5556
static int hf_bacapp_bit;
5557
static int hf_bacapp_complete_bitstring;
5558
5559
/* present value */
5560
static int hf_bacapp_present_value_null;
5561
static int hf_bacapp_present_value_bool;
5562
static int hf_bacapp_present_value_unsigned;
5563
static int hf_bacapp_present_value_signed;
5564
static int hf_bacapp_present_value_real;
5565
static int hf_bacapp_present_value_double;
5566
static int hf_bacapp_present_value_octet_string;
5567
static int hf_bacapp_present_value_char_string;
5568
static int hf_bacapp_present_value_bit_string;
5569
static int hf_bacapp_present_value_enum_index;
5570
5571
/* some more variables for segmented messages */
5572
static int hf_msg_fragments;
5573
static int hf_msg_fragment;
5574
static int hf_msg_fragment_overlap;
5575
static int hf_msg_fragment_overlap_conflicts;
5576
static int hf_msg_fragment_multiple_tails;
5577
static int hf_msg_fragment_too_long_fragment;
5578
static int hf_msg_fragment_error;
5579
static int hf_msg_fragment_count;
5580
static int hf_msg_reassembled_in;
5581
static int hf_msg_reassembled_length;
5582
5583
static int ett_msg_fragment;
5584
static int ett_msg_fragments;
5585
5586
static int ett_bacapp;
5587
static int ett_bacapp_control;
5588
static int ett_bacapp_tag;
5589
static int ett_bacapp_list;
5590
static int ett_bacapp_value;
5591
static int ett_bacapp_object_identifier;
5592
5593
static expert_field ei_bacapp_bad_length;
5594
static expert_field ei_bacapp_bad_tag;
5595
static expert_field ei_bacapp_opening_tag;
5596
5597
static int32_t propertyIdentifier = -1;
5598
static int32_t propertyArrayIndex = -1;
5599
static uint32_t object_type = 4096;
5600
5601
static uint8_t bacapp_flags;
5602
static uint8_t bacapp_seq;
5603
5604
/* Defined to allow vendor identifier registration of private transfer dissectors */
5605
static dissector_table_t bacapp_dissector_table;
5606
5607
5608
/* Stat: BACnet Packets sorted by IP */
5609
/* XXX - Should probably be passed into functions and not be global */
5610
static bacapp_info_value_t bacinfo;
5611
5612
static const char* st_str_packets_by_ip = "BACnet Packets by IP";
5613
static const char* st_str_packets_by_ip_dst = "By Destination";
5614
static const char* st_str_packets_by_ip_src = "By Source";
5615
static int st_node_packets_by_ip = -1;
5616
static int st_node_packets_by_ip_dst = -1;
5617
static int st_node_packets_by_ip_src = -1;
5618
5619
static void
5620
bacapp_packet_stats_tree_init(stats_tree* st)
5621
0
{
5622
0
    st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
5623
0
    st_node_packets_by_ip_src = stats_tree_create_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, STAT_DT_INT, true);
5624
0
    st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, STAT_DT_INT, true);
5625
0
}
5626
5627
static char *
5628
bacapp_get_address_label(const char *tag, address *addr)
5629
0
{
5630
0
    char *addr_str, *label_str;
5631
5632
0
    addr_str = address_to_str(NULL, addr);
5633
0
    label_str = wmem_strconcat(NULL, tag, addr_str, NULL);
5634
0
    wmem_free(NULL, addr_str);
5635
0
    return label_str;
5636
0
}
5637
5638
static tap_packet_status
5639
bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
5640
0
{
5641
0
    int    packets_for_this_dst;
5642
0
    int    packets_for_this_src;
5643
0
    int    service_for_this_dst;
5644
0
    int    service_for_this_src;
5645
0
    int    src_for_this_dst;
5646
0
    int    dst_for_this_src;
5647
0
    int    objectid_for_this_dst;
5648
0
    int    objectid_for_this_src;
5649
0
    int    instanceid_for_this_dst;
5650
0
    int    instanceid_for_this_src;
5651
0
    char *dststr;
5652
0
    char *srcstr;
5653
0
    const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5654
5655
0
    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5656
0
    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5657
5658
0
    tick_stat_node(st, st_str_packets_by_ip, 0, true);
5659
0
    packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, true);
5660
0
    packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, true);
5661
0
    src_for_this_dst     = tick_stat_node(st, dststr, packets_for_this_dst, true);
5662
0
    dst_for_this_src     = tick_stat_node(st, srcstr, packets_for_this_src, true);
5663
0
    service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, true);
5664
0
    service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, true);
5665
0
    if (binfo->service_type) {
5666
0
        objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, true);
5667
0
        objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, true);
5668
0
        if (binfo->object_ident) {
5669
0
            instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, true);
5670
0
            tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, false);
5671
0
            instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, true);
5672
0
            tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, false);
5673
0
        }
5674
0
    }
5675
5676
0
    wmem_free(NULL, srcstr);
5677
0
    wmem_free(NULL, dststr);
5678
5679
0
    return TAP_PACKET_REDRAW;
5680
0
}
5681
5682
/* Stat: BACnet Packets sorted by Service */
5683
static const char* st_str_packets_by_service = "BACnet Packets by Service";
5684
static int st_node_packets_by_service = -1;
5685
5686
static void
5687
bacapp_service_stats_tree_init(stats_tree* st)
5688
0
{
5689
0
    st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
5690
0
}
5691
5692
static tap_packet_status
5693
bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
5694
0
{
5695
0
    int    servicetype;
5696
0
    int    src, dst;
5697
0
    int    objectid;
5698
5699
0
    char *dststr;
5700
0
    char *srcstr;
5701
5702
0
    const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5703
5704
0
    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5705
0
    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5706
5707
0
    tick_stat_node(st, st_str_packets_by_service, 0, true);
5708
0
    if (binfo->service_type) {
5709
0
        servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, true);
5710
0
        src         = tick_stat_node(st, srcstr, servicetype, true);
5711
0
        dst         = tick_stat_node(st, dststr, src, true);
5712
0
        if (binfo->object_ident) {
5713
0
            objectid = tick_stat_node(st, binfo->object_ident, dst, true);
5714
0
            tick_stat_node(st, binfo->instance_ident, objectid, false);
5715
0
        }
5716
0
    }
5717
5718
0
    wmem_free(NULL, srcstr);
5719
0
    wmem_free(NULL, dststr);
5720
5721
0
    return TAP_PACKET_REDRAW;
5722
0
}
5723
5724
/* Stat: BACnet Packets sorted by Object Type */
5725
static const char* st_str_packets_by_objectid = "BACnet Packets by Object Type";
5726
static int st_node_packets_by_objectid = -1;
5727
5728
static void
5729
bacapp_objectid_stats_tree_init(stats_tree* st)
5730
0
{
5731
0
    st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
5732
0
}
5733
5734
static tap_packet_status
5735
bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
5736
0
{
5737
0
    int    servicetype;
5738
0
    int    src, dst;
5739
0
    int    objectid;
5740
5741
0
    char *dststr;
5742
0
    char *srcstr;
5743
0
    const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5744
5745
0
    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5746
0
    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5747
5748
0
    tick_stat_node(st, st_str_packets_by_objectid, 0, true);
5749
0
    if (binfo->object_ident) {
5750
0
        objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, true);
5751
0
        src = tick_stat_node(st, srcstr, objectid, true);
5752
0
        dst = tick_stat_node(st, dststr, src, true);
5753
0
        if (binfo->service_type) {
5754
0
            servicetype = tick_stat_node(st, binfo->service_type, dst, true);
5755
0
            tick_stat_node(st, binfo->instance_ident, servicetype, false);
5756
0
        }
5757
0
    }
5758
5759
0
    wmem_free(NULL, srcstr);
5760
0
    wmem_free(NULL, dststr);
5761
5762
0
    return TAP_PACKET_REDRAW;
5763
0
}
5764
5765
/* Stat: BACnet Packets sorted by Instance No */
5766
static const char* st_str_packets_by_instanceid  = "BACnet Packets by Instance ID";
5767
static int          st_node_packets_by_instanceid = -1;
5768
5769
static void
5770
bacapp_instanceid_stats_tree_init(stats_tree* st)
5771
0
{
5772
0
    st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
5773
0
}
5774
5775
static tap_packet_status
5776
bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
5777
0
{
5778
0
    int    servicetype;
5779
0
    int    src, dst;
5780
0
    int    instanceid;
5781
5782
0
    char *dststr;
5783
0
    char *srcstr;
5784
0
    const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
5785
5786
0
    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
5787
0
    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
5788
5789
0
    tick_stat_node(st, st_str_packets_by_instanceid, 0, true);
5790
0
    if (binfo->object_ident) {
5791
0
        instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, true);
5792
0
        src = tick_stat_node(st, srcstr, instanceid, true);
5793
0
        dst = tick_stat_node(st, dststr, src, true);
5794
0
        if (binfo->service_type) {
5795
0
            servicetype = tick_stat_node(st, binfo->service_type, dst, true);
5796
0
            tick_stat_node(st, binfo->object_ident, servicetype, false);
5797
0
        }
5798
0
    }
5799
5800
0
    wmem_free(NULL, srcstr);
5801
0
    wmem_free(NULL, dststr);
5802
5803
0
    return TAP_PACKET_REDRAW;
5804
0
}
5805
5806
5807
/* register all BACnet Statistic trees */
5808
static void
5809
register_bacapp_stat_trees(void)
5810
15
{
5811
15
    stats_tree_register("bacapp", "bacapp_ip", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by IP", 0,
5812
15
        bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
5813
15
    stats_tree_register("bacapp", "bacapp_service", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Service", 0,
5814
15
        bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
5815
15
    stats_tree_register("bacapp", "bacapp_objectid", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Object Type", 0,
5816
15
        bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
5817
15
    stats_tree_register("bacapp", "bacapp_instanceid", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Instance ID", 0,
5818
15
        bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
5819
15
}
5820
5821
/* 'data' must be allocated with wmem packet scope */
5822
static int
5823
updateBacnetInfoValue(int whichval, const char *data)
5824
79.4k
{
5825
79.4k
    if (whichval == BACINFO_SERVICE) {
5826
8.91k
        bacinfo.service_type = data;
5827
8.91k
        return 0;
5828
8.91k
    }
5829
70.5k
    if (whichval == BACINFO_INVOKEID) {
5830
8.25k
        bacinfo.invoke_id = data;
5831
8.25k
        return 0;
5832
8.25k
    }
5833
62.2k
    if (whichval == BACINFO_OBJECTID) {
5834
31.1k
        bacinfo.object_ident = data;
5835
31.1k
        return 0;
5836
31.1k
    }
5837
31.1k
    if (whichval == BACINFO_INSTANCEID) {
5838
31.1k
        bacinfo.instance_ident = data;
5839
31.1k
        return 0;
5840
31.1k
    }
5841
0
    return -1;
5842
31.1k
}
5843
5844
static const fragment_items msg_frag_items = {
5845
    /* Fragment subtrees */
5846
    &ett_msg_fragment,
5847
    &ett_msg_fragments,
5848
    /* Fragment fields */
5849
    &hf_msg_fragments,
5850
    &hf_msg_fragment,
5851
    &hf_msg_fragment_overlap,
5852
    &hf_msg_fragment_overlap_conflicts,
5853
    &hf_msg_fragment_multiple_tails,
5854
    &hf_msg_fragment_too_long_fragment,
5855
    &hf_msg_fragment_error,
5856
    &hf_msg_fragment_count,
5857
    /* Reassembled in field */
5858
    &hf_msg_reassembled_in,
5859
    /* Reassembled length field */
5860
    &hf_msg_reassembled_length,
5861
    /* Reassembled data field */
5862
    NULL,
5863
    /* Tag */
5864
    "Message fragments"
5865
};
5866
5867
/* calculate an extended sequence number. The sequence number is an 8-bit
5868
 * counter, and can rollover with very large data length. */
5869
static uint32_t
5870
calculate_extended_seqno(uint32_t prev_seqno, uint8_t raw_seqno)
5871
58
{
5872
58
    uint32_t seqno = (prev_seqno & 0xffffff00) | raw_seqno;
5873
    /* The Window Size must be in a range 1 to 127 (see ANSI/ASHRAE Std
5874
     * 135-2016 5.3), and this guarantees that, e.g., sequence number 128
5875
     * will not be transmitted unless a SegmentACK has been received for
5876
     * sequence number 0, so any subsequent sequence number 0 must actually
5877
     * be sequence number 256 after rollover.
5878
     */
5879
58
    if (seqno + 0x80 < prev_seqno) {
5880
0
        seqno += 0x100;
5881
58
    } else if (prev_seqno + 0x80 < seqno) {
5882
        /* Unlikely, out-of-order packet backwards over the wrap boundary. */
5883
8
        seqno -= 0x100;
5884
8
    }
5885
58
    return seqno;
5886
58
}
5887
5888
#if 0
5889
/* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
5890
/* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
5891
static const unsigned MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
5892
5893
static unsigned
5894
fGetMaxAPDUSize(uint8_t idx)
5895
{
5896
    /* only 16 values are defined, so use & 0x0f */
5897
    /* check the size of the Array, deliver either the entry
5898
       or the first entry if idx is outside of the array (bug 3736 comment#7) */
5899
5900
    if ((idx & 0x0f) >= (int)array_length(MaxAPDUSize))
5901
        return MaxAPDUSize[0];
5902
    else
5903
        return MaxAPDUSize[idx & 0x0f];
5904
}
5905
#endif
5906
5907
/* Used when there are ranges of reserved and proprietary enumerations */
5908
static const char*
5909
val_to_split_str(wmem_allocator_t* scope, uint32_t val, uint32_t split_val, const value_string *vs,
5910
    const char *fmt, const char *split_fmt)
5911
130k
{
5912
130k
    if (val < split_val)
5913
89.9k
        return val_to_str(scope, val, vs, fmt);
5914
40.1k
    else
5915
40.1k
        return val_to_str(scope, val, vs, split_fmt);
5916
130k
}
5917
5918
/* from clause 20.2.1.3.2 Constructed Data */
5919
/* returns true if the extended value is used */
5920
static bool
5921
tag_is_extended_value(uint8_t tag)
5922
1.95M
{
5923
1.95M
    return (tag & 0x07) == 5;
5924
1.95M
}
5925
5926
static bool
5927
tag_is_opening(uint8_t tag)
5928
1.15M
{
5929
1.15M
    return (tag & 0x07) == 6;
5930
1.15M
}
5931
5932
static bool
5933
tag_is_closing(uint8_t tag)
5934
1.49M
{
5935
1.49M
    return (tag & 0x07) == 7;
5936
1.49M
}
5937
5938
/* from clause 20.2.1.1 Class
5939
   class bit shall be one for context specific tags */
5940
/* returns true if the tag is context specific */
5941
static bool
5942
tag_is_context_specific(uint8_t tag)
5943
2.57M
{
5944
2.57M
    return (tag & 0x08) != 0;
5945
2.57M
}
5946
5947
static bool
5948
tag_is_extended_tag_number(uint8_t tag)
5949
2.03M
{
5950
2.03M
    return ((tag & 0xF0) == 0xF0);
5951
2.03M
}
5952
5953
static uint32_t
5954
object_id_type(uint32_t object_identifier)
5955
31.9k
{
5956
31.9k
    return ((object_identifier >> 22) & 0x3FF);
5957
31.9k
}
5958
5959
static uint32_t
5960
object_id_instance(uint32_t object_identifier)
5961
93.4k
{
5962
93.4k
    return (object_identifier & 0x3FFFFF);
5963
93.4k
}
5964
5965
static unsigned
5966
fTagNo(tvbuff_t *tvb, unsigned offset)
5967
106k
{
5968
106k
    return (unsigned)(tvb_get_uint8(tvb, offset) >> 4);
5969
106k
}
5970
5971
static bool
5972
fUnsigned32(tvbuff_t *tvb, unsigned offset, uint32_t lvt, uint32_t *val)
5973
142k
{
5974
142k
    bool valid = true;
5975
5976
142k
    switch (lvt) {
5977
18.6k
    case 1:
5978
18.6k
        *val = tvb_get_uint8(tvb, offset);
5979
18.6k
        break;
5980
11.7k
    case 2:
5981
11.7k
        *val = tvb_get_ntohs(tvb, offset);
5982
11.7k
        break;
5983
7.76k
    case 3:
5984
7.76k
        *val = tvb_get_ntoh24(tvb, offset);
5985
7.76k
        break;
5986
7.41k
    case 4:
5987
7.41k
        *val = tvb_get_ntohl(tvb, offset);
5988
7.41k
        break;
5989
96.7k
    default:
5990
96.7k
        valid = false;
5991
96.7k
        break;
5992
142k
    }
5993
5994
142k
    return valid;
5995
142k
}
5996
5997
static bool
5998
fUnsigned64(tvbuff_t *tvb, unsigned offset, uint32_t lvt, uint64_t *val)
5999
57.9k
{
6000
57.9k
    bool valid = false;
6001
57.9k
    int64_t  value = 0;
6002
57.9k
    uint8_t  data;
6003
6004
57.9k
    if (lvt && (lvt <= 8)) {
6005
20.3k
        valid = true;
6006
78.4k
        for (unsigned i = 0; i < lvt; i++) {
6007
58.0k
            data = tvb_get_uint8(tvb, offset+i);
6008
58.0k
            value = (value << 8) + data;
6009
58.0k
        }
6010
20.3k
        *val = value;
6011
20.3k
    }
6012
6013
57.9k
    return valid;
6014
57.9k
}
6015
6016
/* BACnet Signed Value uses 2's complement notation, but with a twist:
6017
   All signed integers shall be encoded in the smallest number of octets
6018
   possible.  That is, the first octet of any multi-octet encoded value
6019
   shall not be X'00' if the most significant bit (bit 7) of the second
6020
   octet is 0, and the first octet shall not be X'FF' if the most
6021
   significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
6022
static bool
6023
fSigned64(tvbuff_t *tvb, unsigned offset, uint32_t lvt, int64_t *val)
6024
10.2k
{
6025
10.2k
    bool valid = false;
6026
10.2k
    int64_t  value = 0;
6027
10.2k
    uint8_t  data;
6028
10.2k
    uint32_t i;
6029
6030
    /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
6031
10.2k
    if (lvt && (lvt <= 7)) {
6032
4.21k
        valid = true;
6033
4.21k
        data = tvb_get_uint8(tvb, offset);
6034
4.21k
        if ((data & 0x80) != 0)
6035
982
            value = (~UINT64_C(0) << 8) | data;
6036
3.22k
        else
6037
3.22k
            value = data;
6038
12.2k
        for (i = 1; i < lvt; i++) {
6039
8.00k
            data = tvb_get_uint8(tvb, offset+i);
6040
8.00k
            value = ((uint64_t)value << 8) | data;
6041
8.00k
        }
6042
4.21k
        *val = value;
6043
4.21k
    }
6044
6045
10.2k
    return valid;
6046
10.2k
}
6047
6048
static unsigned
6049
fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6050
    unsigned offset, uint8_t *tag_no, uint8_t* tag_info, uint32_t *lvt)
6051
1.47M
{
6052
1.47M
    proto_item *ti = NULL;
6053
1.47M
    uint8_t     tag;
6054
1.47M
    uint8_t     value;
6055
1.47M
    unsigned    tag_len = 1;
6056
1.47M
    unsigned    lvt_len = 1;    /* used for tree display of lvt */
6057
1.47M
    unsigned    lvt_offset;     /* used for tree display of lvt */
6058
6059
1.47M
    lvt_offset = offset;
6060
1.47M
    tag        = tvb_get_uint8(tvb, offset);
6061
1.47M
    *tag_info  = 0;
6062
1.47M
    *lvt       = tag & 0x07;
6063
6064
    /* To solve the problem of lvt values of 6/7 being indeterminate - it */
6065
    /* can mean open/close tag or length of 6/7 after the length is */
6066
    /* computed below - store whole tag info, not just context bit. */
6067
1.47M
    if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
6068
1.47M
    *tag_no = tag >> 4;
6069
1.47M
    if (tag_is_extended_tag_number(tag)) {
6070
47.5k
        *tag_no = tvb_get_uint8(tvb, offset + tag_len++);
6071
47.5k
    }
6072
1.47M
    if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
6073
55.3k
        lvt_offset += tag_len;
6074
55.3k
        value = tvb_get_uint8(tvb, lvt_offset);
6075
55.3k
        tag_len++;
6076
55.3k
        if (value == 254) { /* length is encoded with 16 Bits */
6077
171
            *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
6078
171
            tag_len += 2;
6079
171
            lvt_len += 2;
6080
55.2k
        } else if (value == 255) { /* length is encoded with 32 Bits */
6081
1.55k
            *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
6082
1.55k
            tag_len += 4;
6083
1.55k
            lvt_len += 4;
6084
1.55k
        } else
6085
53.6k
            *lvt = value;
6086
55.3k
    }
6087
6088
1.47M
    if (tree) {
6089
556k
        proto_tree *subtree;
6090
556k
        if (tag_is_opening(tag)) {
6091
49.8k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6092
49.8k
                    ett_bacapp_tag, &ti, "{[%u]", *tag_no );
6093
506k
        } else if (tag_is_closing(tag)) {
6094
30.2k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6095
30.2k
                    ett_bacapp_tag, &ti, "}[%u]", *tag_no );
6096
476k
        } else if (tag_is_context_specific(tag)) {
6097
117k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6098
117k
                    ett_bacapp_tag, &ti,
6099
117k
                    "Context Tag: %u, Length/Value/Type: %u", *tag_no, *lvt);
6100
358k
        } else {
6101
358k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6102
358k
                    ett_bacapp_tag, &ti,
6103
358k
                    "Application Tag: %s, Length/Value/Type: %u",
6104
358k
                    val_to_str(pinfo->pool, *tag_no, BACnetApplicationTagNumber,
6105
358k
                        ASHRAE_Reserved_Fmt),
6106
358k
                    *lvt);
6107
358k
        }
6108
6109
        /* details if needed */
6110
556k
        proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
6111
556k
        if (tag_is_extended_tag_number(tag)) {
6112
17.2k
            proto_tree_add_uint_format(subtree,
6113
17.2k
                                       hf_BACnetContextTagNumber,
6114
17.2k
                                       tvb, offset, 1, tag,
6115
17.2k
                                       "Extended Tag Number");
6116
17.2k
            proto_tree_add_item(subtree,
6117
17.2k
                                hf_BACnetExtendedTagNumber,
6118
17.2k
                                tvb, offset + 1, 1, ENC_BIG_ENDIAN);
6119
538k
        } else {
6120
538k
            if (tag_is_context_specific(tag))
6121
154k
                proto_tree_add_item(subtree,
6122
154k
                                    hf_BACnetContextTagNumber,
6123
154k
                                    tvb, offset, 1, ENC_BIG_ENDIAN);
6124
384k
            else
6125
384k
                proto_tree_add_item(subtree,
6126
384k
                                    hf_BACnetApplicationTagNumber,
6127
384k
                                    tvb, offset, 1, ENC_BIG_ENDIAN);
6128
538k
        }
6129
556k
        if (tag_is_closing(tag) || tag_is_opening(tag))
6130
80.1k
            proto_tree_add_item(subtree,
6131
80.1k
                                hf_BACnetNamedTag,
6132
80.1k
                                tvb, offset, 1, ENC_BIG_ENDIAN);
6133
476k
        else if (tag_is_extended_value(tag)) {
6134
20.6k
            proto_tree_add_item(subtree,
6135
20.6k
                                hf_BACnetNamedTag,
6136
20.6k
                                tvb, offset, 1, ENC_BIG_ENDIAN);
6137
20.6k
            proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
6138
20.6k
                                tvb, lvt_offset, lvt_len, *lvt);
6139
20.6k
        } else
6140
455k
            proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
6141
455k
                                tvb, lvt_offset, lvt_len, *lvt);
6142
556k
    } /* if (tree) */
6143
6144
1.47M
    if (*lvt > tvb_reported_length(tvb)) {
6145
9.25k
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
6146
9.25k
                               "LVT length too long: %d > %d", *lvt,
6147
9.25k
                               tvb_reported_length(tvb));
6148
9.25k
        *lvt = 1;
6149
9.25k
    }
6150
6151
1.47M
    return tag_len;
6152
1.47M
}
6153
6154
static unsigned
6155
fTagHeader(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, uint8_t *tag_no, uint8_t* tag_info,
6156
    uint32_t *lvt)
6157
922k
{
6158
922k
    return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
6159
922k
}
6160
6161
static unsigned
6162
fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6163
24.0k
{
6164
24.0k
    uint8_t     tag_no, tag_info;
6165
24.0k
    uint32_t    lvt;
6166
24.0k
    proto_tree *subtree;
6167
6168
24.0k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "%sNULL", label);
6169
24.0k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6170
6171
24.0k
    return offset + 1;
6172
24.0k
}
6173
6174
static unsigned
6175
fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6176
21.1k
{
6177
21.1k
    uint8_t     tag_no, tag_info;
6178
21.1k
    uint32_t    lvt      = 0;
6179
21.1k
    proto_tree *subtree;
6180
21.1k
    unsigned    bool_len = 1;
6181
6182
21.1k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6183
21.1k
    if (tag_info && lvt == 1) {
6184
478
        lvt = tvb_get_uint8(tvb, offset+1);
6185
478
        ++bool_len;
6186
478
    }
6187
6188
21.1k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, bool_len,
6189
21.1k
                             ett_bacapp_tag, NULL, "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
6190
21.1k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6191
6192
21.1k
    return offset + bool_len;
6193
21.1k
}
6194
6195
static unsigned
6196
fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6197
56.8k
{
6198
56.8k
    uint64_t    val = 0;
6199
56.8k
    uint8_t     tag_no, tag_info;
6200
56.8k
    uint32_t    lvt;
6201
56.8k
    unsigned    tag_len;
6202
56.8k
    proto_tree *subtree;
6203
6204
56.8k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6205
    /* only support up to an 8 byte (64-bit) integer */
6206
56.8k
    if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
6207
19.4k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6208
19.4k
            ett_bacapp_tag, NULL, "%s(Unsigned) %" PRIu64, label, val);
6209
37.3k
    else
6210
37.3k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6211
37.3k
            ett_bacapp_tag, NULL, "%s - %u octets (Unsigned)", label, lvt);
6212
56.8k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6213
6214
56.8k
    return offset+tag_len+lvt;
6215
56.8k
}
6216
6217
static unsigned
6218
fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int hf)
6219
77
{
6220
77
    uint8_t     tag_no, tag_info;
6221
77
    uint32_t    lvt, safe_lvt;
6222
77
    unsigned    tag_len;
6223
77
    proto_item *ti;
6224
77
    proto_tree *subtree;
6225
6226
77
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6227
6228
77
    if (lvt > 4)
6229
20
        safe_lvt = 4;
6230
57
    else
6231
57
        safe_lvt = lvt;
6232
6233
77
    ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
6234
6235
77
    if (lvt != safe_lvt)
6236
20
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
6237
20
                "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
6238
6239
77
    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6240
77
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6241
6242
77
    return offset+tag_len+lvt;
6243
77
}
6244
6245
/* set split_val to zero when not needed */
6246
static unsigned
6247
fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6248
    unsigned offset, const char *label, const value_string *vs, uint32_t split_val)
6249
32.8k
{
6250
32.8k
    uint32_t    val = 0;
6251
32.8k
    uint8_t     tag_no, tag_info;
6252
32.8k
    uint32_t    lvt;
6253
32.8k
    unsigned    tag_len;
6254
32.8k
    proto_tree *subtree;
6255
6256
32.8k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6257
    /* only support up to a 4 byte (32-bit) enumeration */
6258
32.8k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
6259
9.58k
        if (vs)
6260
8.33k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6261
8.33k
                ett_bacapp_tag, NULL, "%s %s (%u)", label,
6262
8.33k
                val_to_split_str(pinfo->pool, val, split_val, vs,
6263
8.33k
                                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt), val);
6264
1.25k
        else
6265
1.25k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6266
1.25k
                ett_bacapp_tag, NULL, "%s %u", label, val);
6267
23.2k
    } else {
6268
23.2k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6269
23.2k
            ett_bacapp_tag, NULL, "%s - %u octets (enumeration)", label, lvt);
6270
23.2k
    }
6271
6272
32.8k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6273
6274
32.8k
    return offset+tag_len+lvt;
6275
32.8k
}
6276
6277
static unsigned
6278
fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6279
        unsigned offset, const char *label, const value_string *vs)
6280
14.2k
{
6281
14.2k
    return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
6282
14.2k
}
6283
6284
static unsigned
6285
fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6286
8.75k
{
6287
8.75k
    int64_t     val = 0;
6288
8.75k
    uint8_t     tag_no, tag_info;
6289
8.75k
    uint32_t    lvt;
6290
8.75k
    unsigned    tag_len;
6291
8.75k
    proto_tree *subtree;
6292
6293
8.75k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6294
8.75k
    if (fSigned64(tvb, offset + tag_len, lvt, &val))
6295
3.33k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6296
3.33k
            ett_bacapp_tag, NULL, "%s(Signed) %" PRId64, label, val);
6297
5.41k
    else
6298
5.41k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6299
5.41k
            ett_bacapp_tag, NULL, "%s - %u octets (Signed)", label, lvt);
6300
8.75k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6301
6302
8.75k
    return offset+tag_len+lvt;
6303
8.75k
}
6304
6305
static unsigned
6306
fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6307
7.06k
{
6308
7.06k
    uint8_t     tag_no, tag_info;
6309
7.06k
    uint32_t    lvt;
6310
7.06k
    unsigned    tag_len;
6311
7.06k
    float       f_val;
6312
7.06k
    proto_tree *subtree;
6313
6314
7.06k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6315
7.06k
    f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
6316
7.06k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 4+tag_len,
6317
7.06k
        ett_bacapp_tag, NULL, "%s%f (Real)", label, f_val);
6318
7.06k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6319
6320
7.06k
    return offset+tag_len+4;
6321
7.06k
}
6322
6323
static unsigned
6324
fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6325
2.00k
{
6326
2.00k
    uint8_t     tag_no, tag_info;
6327
2.00k
    uint32_t    lvt;
6328
2.00k
    unsigned    tag_len;
6329
2.00k
    double      d_val;
6330
2.00k
    proto_tree  *subtree;
6331
6332
2.00k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6333
2.00k
    d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
6334
2.00k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 8+tag_len,
6335
2.00k
        ett_bacapp_tag, NULL, "%s%f (Double)", label, d_val);
6336
2.00k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6337
6338
2.00k
    return offset+tag_len+8;
6339
2.00k
}
6340
6341
static unsigned
6342
fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6343
36.0k
{
6344
36.0k
    uint32_t    val = 0, lvt;
6345
36.0k
    uint8_t     tag_no, tag_info;
6346
36.0k
    proto_item *ti;
6347
36.0k
    proto_tree *subtree;
6348
36.0k
    unsigned    tag_len;
6349
6350
36.0k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6351
36.0k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6352
7.03k
    {
6353
7.03k
        ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
6354
7.03k
            tvb, offset, lvt+tag_len, val);
6355
7.03k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6356
7.03k
    }
6357
29.0k
    else
6358
29.0k
    {
6359
29.0k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6360
29.0k
            ett_bacapp_tag, NULL, "Process Identifier - %u octets (Signed)", lvt);
6361
29.0k
    }
6362
36.0k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6363
36.0k
    offset += tag_len + lvt;
6364
6365
36.0k
    return offset;
6366
36.0k
}
6367
6368
static unsigned
6369
fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const value_string *vs, uint32_t split_val, BacappPresentValueType type)
6370
22.2k
{
6371
    // tag vars
6372
22.2k
    uint32_t    lvt;
6373
22.2k
    uint8_t     tag_no, tag_info;
6374
22.2k
    unsigned    tag_len;
6375
22.2k
    unsigned    curr_offset = offset;
6376
    // tree vars
6377
22.2k
    proto_item *tree_item = NULL;
6378
22.2k
    proto_tree *subtree = NULL;
6379
    // dissection vars
6380
22.2k
    unsigned    bool_len = 1;
6381
22.2k
    uint64_t    unsigned_val = 0;
6382
22.2k
    int64_t     signed_val = 0;
6383
22.2k
    float       float_val;
6384
22.2k
    double      double_val;
6385
22.2k
    uint32_t    enum_index = 0;
6386
22.2k
    uint32_t    object_id;
6387
6388
22.2k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6389
22.2k
    switch(type) {
6390
10.6k
        case BACAPP_PRESENT_VALUE_NULL:
6391
10.6k
            tree_item = proto_tree_add_string(tree, hf_bacapp_present_value_null, tvb, offset, lvt+tag_len, "NULL");
6392
10.6k
            curr_offset += 1;
6393
10.6k
            break;
6394
1.56k
        case BACAPP_PRESENT_VALUE_BOOL:
6395
1.56k
            if (tag_info && lvt == 1) {
6396
0
                lvt = tvb_get_uint8(tvb, offset+1);
6397
0
                bool_len++;
6398
0
            }
6399
1.56k
            tree_item = proto_tree_add_boolean(tree, hf_bacapp_present_value_bool, tvb, offset, bool_len, lvt);
6400
1.56k
            curr_offset += bool_len;
6401
1.56k
            break;
6402
1.16k
        case BACAPP_PRESENT_VALUE_UNSIGNED:
6403
1.16k
            if (fUnsigned64(tvb, offset + tag_len, lvt, &unsigned_val))
6404
662
                tree_item = proto_tree_add_uint64(tree, hf_bacapp_present_value_unsigned, tvb, offset, lvt+tag_len, unsigned_val);
6405
1.16k
            curr_offset += tag_len + lvt;
6406
1.16k
            break;
6407
1.50k
        case BACAPP_PRESENT_VALUE_SIGNED:
6408
1.50k
            if (fSigned64(tvb, offset + tag_len, lvt, &signed_val))
6409
843
                tree_item = proto_tree_add_int64(tree, hf_bacapp_present_value_signed, tvb, offset, lvt+tag_len, signed_val);
6410
1.50k
            curr_offset += tag_len + lvt;
6411
1.50k
            break;
6412
507
        case BACAPP_PRESENT_VALUE_REAL:
6413
507
            float_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
6414
507
            double_val = (double) float_val;
6415
507
            tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_real, tvb, offset, lvt+tag_len, double_val);
6416
507
            curr_offset += tag_len + lvt;
6417
507
            break;
6418
368
        case BACAPP_PRESENT_VALUE_DOUBLE:
6419
368
            double_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
6420
368
            tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_double, tvb, offset, lvt+tag_len, double_val);
6421
368
            curr_offset += tag_len + lvt;
6422
368
            break;
6423
708
        case BACAPP_PRESENT_VALUE_OCTET_STRING:
6424
708
            if (lvt > 0)
6425
451
                tree_item = proto_tree_add_item(tree, hf_bacapp_present_value_octet_string, tvb, offset, lvt+tag_len, ENC_NA);
6426
708
            curr_offset += tag_len + lvt;
6427
708
            break;
6428
360
        case BACAPP_PRESENT_VALUE_CHARACTER_STRING:
6429
360
            curr_offset = fCharacterStringBase(tvb, pinfo, tree, offset, NULL, true, false);
6430
360
            break;
6431
682
        case BACAPP_PRESENT_VALUE_BIT_STRING:
6432
682
            curr_offset = fBitStringTagVSBase(tvb, pinfo, tree, offset, NULL, NULL, true);
6433
682
            break;
6434
2.89k
        case BACAPP_PRESENT_VALUE_ENUM:
6435
2.89k
            if (fUnsigned32(tvb, offset+tag_len, lvt, &enum_index)) {
6436
1.23k
                if (vs) {
6437
983
                    subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len, ett_bacapp_tag, NULL,
6438
983
                        "Present Value (enum value): %s",
6439
983
                        val_to_split_str(pinfo->pool, enum_index,
6440
983
                                         split_val, vs,
6441
983
                                         ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
6442
983
                    proto_tree_add_uint(subtree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, enum_index);
6443
983
                    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6444
983
                } else {
6445
255
                    tree_item = proto_tree_add_uint(tree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, enum_index);
6446
255
                }
6447
1.23k
            }
6448
2.89k
            curr_offset += tag_len + lvt;
6449
2.89k
            break;
6450
575
        case BACAPP_PRESENT_VALUE_DATE:
6451
575
            curr_offset = fDate(tvb, pinfo, tree, offset, "Date: ");
6452
575
            break;
6453
474
        case BACAPP_PRESENT_VALUE_TIME:
6454
474
            curr_offset = fTime(tvb, pinfo, tree, offset, "Time: ");
6455
474
            break;
6456
787
        case BACAPP_PRESENT_VALUE_OBJECT_IDENTIFIER:
6457
787
            object_id   = tvb_get_ntohl(tvb, offset+tag_len);
6458
787
            object_type = object_id_type(object_id);
6459
787
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len + 4, ett_bacapp_tag, NULL,
6460
787
                "Present Value (enum value): %s",
6461
787
                val_to_split_str(pinfo->pool, object_type,
6462
787
                                 128, BACnetObjectType,
6463
787
                                 ASHRAE_Reserved_Fmt,
6464
787
                                 Vendor_Proprietary_Fmt));
6465
787
            proto_tree_add_uint(subtree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, object_type);
6466
787
            fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6467
787
            curr_offset += tag_len + lvt;
6468
787
            break;
6469
0
        default:
6470
0
            curr_offset += tag_len + lvt;
6471
0
            break;
6472
22.2k
    }
6473
6474
22.1k
    if (tree_item != NULL && subtree == NULL) {
6475
15.2k
        subtree = proto_item_add_subtree(tree_item, ett_bacapp_value);
6476
15.2k
        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6477
15.2k
    }
6478
6479
22.1k
    return curr_offset;
6480
22.2k
}
6481
6482
static unsigned
6483
fEventType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6484
3.74k
{
6485
3.74k
    uint32_t    val = 0, lvt;
6486
3.74k
    uint8_t     tag_no, tag_info;
6487
3.74k
    proto_item *ti;
6488
3.74k
    proto_tree *subtree;
6489
3.74k
    unsigned    tag_len;
6490
6491
3.74k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6492
3.74k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6493
2.57k
    {
6494
2.57k
        ti = proto_tree_add_uint(tree, hf_bacapp_event_type,
6495
2.57k
            tvb, offset, lvt+tag_len, val);
6496
2.57k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6497
2.57k
    }
6498
1.16k
    else
6499
1.16k
    {
6500
1.16k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6501
1.16k
            ett_bacapp_tag, NULL, "Event Type - %u octets (Signed)", lvt);
6502
1.16k
    }
6503
3.74k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6504
3.74k
    offset += tag_len + lvt;
6505
6506
3.74k
    return offset;
6507
3.74k
}
6508
6509
static unsigned
6510
fNotifyType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6511
3.74k
{
6512
3.74k
    uint32_t    val = 0, lvt;
6513
3.74k
    uint8_t     tag_no, tag_info;
6514
3.74k
    proto_item *ti;
6515
3.74k
    proto_tree *subtree;
6516
3.74k
    unsigned    tag_len;
6517
6518
3.74k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6519
3.74k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6520
2.10k
    {
6521
2.10k
        ti = proto_tree_add_uint(tree, hf_bacapp_notify_type,
6522
2.10k
            tvb, offset, lvt+tag_len, val);
6523
2.10k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6524
2.10k
    }
6525
1.64k
    else
6526
1.64k
    {
6527
1.64k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6528
1.64k
            ett_bacapp_tag, NULL, "Notify Type - %u octets (Signed)", lvt);
6529
1.64k
    }
6530
3.74k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6531
3.74k
    offset += tag_len + lvt;
6532
6533
3.74k
    return offset;
6534
3.74k
}
6535
6536
static unsigned
6537
fToState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6538
2.20k
{
6539
2.20k
    uint32_t    val = 0, lvt;
6540
2.20k
    uint8_t     tag_no, tag_info;
6541
2.20k
    proto_item *ti;
6542
2.20k
    proto_tree *subtree;
6543
2.20k
    unsigned    tag_len;
6544
6545
2.20k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6546
2.20k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6547
1.10k
    {
6548
1.10k
        ti = proto_tree_add_uint(tree, hf_bacapp_tag_to_state,
6549
1.10k
            tvb, offset, lvt+tag_len, val);
6550
1.10k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6551
1.10k
    }
6552
1.10k
    else
6553
1.10k
    {
6554
1.10k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6555
1.10k
            ett_bacapp_tag, NULL, "To State - %u octets (Signed)", lvt);
6556
1.10k
    }
6557
2.20k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6558
2.20k
    offset += tag_len + lvt;
6559
6560
2.20k
    return offset;
6561
2.20k
}
6562
6563
static unsigned
6564
fFromState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6565
2.80k
{
6566
2.80k
    uint32_t    val = 0, lvt;
6567
2.80k
    uint8_t     tag_no, tag_info;
6568
2.80k
    proto_item *ti;
6569
2.80k
    proto_tree *subtree;
6570
2.80k
    unsigned    tag_len;
6571
6572
2.80k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6573
2.80k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6574
1.61k
    {
6575
1.61k
        ti = proto_tree_add_uint(tree, hf_bacapp_tag_from_state,
6576
1.61k
            tvb, offset, lvt+tag_len, val);
6577
1.61k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6578
1.61k
    }
6579
1.18k
    else
6580
1.18k
    {
6581
1.18k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6582
1.18k
            ett_bacapp_tag, NULL, "From State - %u octets (Signed)", lvt);
6583
1.18k
    }
6584
2.80k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6585
2.80k
    offset += tag_len + lvt;
6586
6587
2.80k
    return offset;
6588
2.80k
}
6589
6590
static unsigned
6591
fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6592
28.8k
{
6593
28.8k
    uint32_t    val = 0, lvt;
6594
28.8k
    uint8_t     tag_no, tag_info;
6595
28.8k
    proto_tree *subtree;
6596
28.8k
    unsigned    tag_len;
6597
6598
28.8k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6599
28.8k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6600
3.52k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6601
3.52k
            ett_bacapp_tag, NULL,
6602
3.52k
            "%s (hh.mm.ss): %d.%02d.%02d%s",
6603
3.52k
            label,
6604
3.52k
            (val / 3600), ((val % 3600) / 60), (val % 60),
6605
3.52k
            val == 0 ? " (indefinite)" : "");
6606
25.3k
    else
6607
25.3k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6608
25.3k
            ett_bacapp_tag, NULL,
6609
25.3k
            "%s - %u octets (Signed)", label, lvt);
6610
28.8k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6611
6612
28.8k
    return offset+tag_len+lvt;
6613
28.8k
}
6614
6615
static unsigned
6616
fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6617
106
{
6618
106
    uint32_t    month, weekOfMonth, dayOfWeek;
6619
106
    uint8_t     tag_no, tag_info;
6620
106
    uint32_t    lvt;
6621
106
    unsigned    tag_len;
6622
106
    proto_tree *subtree;
6623
6624
106
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6625
106
    month = tvb_get_uint8(tvb, offset+tag_len);
6626
106
    weekOfMonth = tvb_get_uint8(tvb, offset+tag_len+1);
6627
106
    dayOfWeek = tvb_get_uint8(tvb, offset+tag_len+2);
6628
106
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6629
106
                 ett_bacapp_tag, NULL, "%s %s, %s",
6630
106
                 val_to_str(pinfo->pool, month, months, "month (%d) not found"),
6631
106
                 val_to_str(pinfo->pool, weekOfMonth, weekofmonth, "week of month (%d) not found"),
6632
106
                 val_to_str(pinfo->pool, dayOfWeek, day_of_week, "day of week (%d) not found"));
6633
106
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6634
6635
106
    return offset+tag_len+lvt;
6636
106
}
6637
6638
static unsigned
6639
fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6640
12.7k
{
6641
12.7k
    uint32_t    year, month, day, weekday;
6642
12.7k
    uint8_t     tag_no, tag_info;
6643
12.7k
    uint32_t    lvt;
6644
12.7k
    unsigned    tag_len;
6645
12.7k
    proto_tree *subtree;
6646
6647
12.7k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6648
12.7k
    year    = tvb_get_uint8(tvb, offset+tag_len);
6649
12.7k
    month   = tvb_get_uint8(tvb, offset+tag_len+1);
6650
12.7k
    day     = tvb_get_uint8(tvb, offset+tag_len+2);
6651
12.7k
    weekday = tvb_get_uint8(tvb, offset+tag_len+3);
6652
12.7k
    if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
6653
68
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6654
68
            ett_bacapp_tag, NULL,
6655
68
            "%sany", label);
6656
68
    }
6657
12.6k
    else if (year != 255) {
6658
12.4k
        year += 1900;
6659
12.4k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6660
12.4k
            ett_bacapp_tag, NULL,
6661
12.4k
            "%s%s %d, %d, (Day of Week = %s)",
6662
12.4k
            label, val_to_str(pinfo->pool, month,
6663
12.4k
                months,
6664
12.4k
                "month (%d) not found"),
6665
12.4k
            day, year, val_to_str(pinfo->pool, weekday,
6666
12.4k
                day_of_week,
6667
12.4k
                "(%d) not found"));
6668
12.4k
    } else {
6669
255
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6670
255
            ett_bacapp_tag, NULL,
6671
255
            "%s%s %d, any year, (Day of Week = %s)",
6672
255
            label, val_to_str(pinfo->pool, month, months, "month (%d) not found"),
6673
255
            day, val_to_str(pinfo->pool, weekday, day_of_week, "(%d) not found"));
6674
255
    }
6675
12.7k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6676
6677
12.7k
    return offset+tag_len+lvt;
6678
12.7k
}
6679
6680
static unsigned
6681
fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6682
15.9k
{
6683
15.9k
    uint32_t    hour, minute, second, msec, lvt;
6684
15.9k
    uint8_t     tag_no, tag_info;
6685
15.9k
    unsigned    tag_len;
6686
15.9k
    proto_tree *subtree;
6687
6688
15.9k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6689
15.9k
    hour    = tvb_get_uint8(tvb, offset+tag_len);
6690
15.9k
    minute  = tvb_get_uint8(tvb, offset+tag_len+1);
6691
15.9k
    second  = tvb_get_uint8(tvb, offset+tag_len+2);
6692
15.9k
    msec    = tvb_get_uint8(tvb, offset+tag_len+3);
6693
15.9k
    if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
6694
63
        subtree = proto_tree_add_subtree_format(tree, tvb, offset,
6695
63
            lvt+tag_len, ett_bacapp_tag, NULL,
6696
63
            "%sany", label);
6697
15.8k
    else
6698
15.8k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6699
15.8k
            ett_bacapp_tag, NULL,
6700
15.8k
            "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
6701
15.8k
            label,
6702
15.8k
            hour > 12 ? hour - 12 : hour,
6703
15.8k
            minute, second, msec,
6704
15.8k
            hour >= 12 ? "P.M." : "A.M.",
6705
15.8k
            hour, minute, second, msec);
6706
15.9k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6707
6708
15.9k
    return offset+tag_len+lvt;
6709
15.9k
}
6710
6711
static unsigned
6712
fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6713
8.76k
{
6714
8.76k
    proto_tree *subtree = tree;
6715
6716
8.76k
    if (label != NULL) {
6717
8.75k
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
6718
8.75k
    }
6719
8.76k
    offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
6720
8.76k
    return fTime(tvb, pinfo, subtree, offset, "Time: ");
6721
8.76k
}
6722
6723
static unsigned
6724
fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6725
4
{
6726
4
    unsigned lastoffset = 0;
6727
4
    uint8_t tag_no, tag_info;
6728
4
    uint32_t lvt;
6729
6730
32
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6731
32
        lastoffset = offset;
6732
32
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6733
32
        if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
6734
4
            return offset;
6735
4
        }
6736
28
        offset = fTime(tvb, pinfo, tree, offset, "Time: ");
6737
28
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
6738
6739
28
        if (offset <= lastoffset) break;    /* exit loop if nothing happens inside */
6740
28
    }
6741
0
    return offset;
6742
4
}
6743
6744
static unsigned
6745
fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6746
1.98k
{
6747
1.98k
    uint8_t tag_no, tag_info;
6748
1.98k
    uint32_t lvt;
6749
6750
1.98k
    switch (fTagNo(tvb, offset)) {
6751
1.55k
    case 0: /* Date */
6752
1.55k
        offset = fDate(tvb, pinfo, tree, offset, "Date: ");
6753
1.55k
        break;
6754
186
    case 1: /* dateRange */
6755
186
        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6756
186
        offset  = fDateRange(tvb, pinfo, tree, offset);
6757
186
        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6758
186
        break;
6759
106
    case 2: /* BACnetWeekNDay */
6760
106
        offset = fWeekNDay(tvb, pinfo, tree, offset);
6761
106
        break;
6762
137
    default:
6763
137
        return offset;
6764
1.98k
    }
6765
6766
1.84k
    return offset;
6767
1.98k
}
6768
6769
static unsigned
6770
fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6771
128
{
6772
128
    uint32_t    lvt     = 0;
6773
128
    proto_tree* subtree = tree;
6774
6775
128
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
6776
128
        subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
6777
6778
128
        offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
6779
128
        offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
6780
128
        offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
6781
128
    }
6782
128
    return offset;
6783
128
}
6784
6785
static unsigned
6786
fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6787
13.7k
{
6788
13.7k
    uint8_t tag_no = 0, tag_info = 0;
6789
13.7k
    uint32_t lvt    = 0;
6790
6791
13.7k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
6792
13.7k
        switch (fTagNo(tvb, offset)) {
6793
5.63k
        case 0: /* time */
6794
5.63k
            offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
6795
5.63k
            break;
6796
901
        case 1: /* sequenceNumber */
6797
901
            offset = fUnsignedTag(tvb, pinfo, tree, offset,
6798
901
                label?label:"sequence number: ");
6799
901
            break;
6800
473
        case 2: /* dateTime */
6801
473
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6802
473
            offset  = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
6803
473
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6804
473
            break;
6805
6.70k
        default:
6806
6.70k
            return offset;
6807
13.7k
        }
6808
13.7k
    }
6809
6810
6.95k
    return offset;
6811
13.7k
}
6812
6813
6814
static unsigned
6815
fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6816
344
{
6817
344
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
6818
344
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
6819
344
    }
6820
344
    return offset;
6821
344
}
6822
6823
static const value_string
6824
BACnetDaysOfWeek [] = {
6825
    { 0, "Monday" },
6826
    { 1, "Tuesday" },
6827
    { 2, "Wednesday" },
6828
    { 3, "Thursday" },
6829
    { 4, "Friday" },
6830
    { 5, "Saturday" },
6831
    { 6, "Sunday" },
6832
    { 0, NULL }
6833
};
6834
6835
static unsigned
6836
fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6837
45
{
6838
45
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
6839
45
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
6840
45
                                             "valid Days: ", BACnetDaysOfWeek);
6841
45
        offset = fTime(tvb, pinfo, tree, offset, "from time: ");
6842
45
        offset = fTime(tvb, pinfo, tree, offset, "to time: ");
6843
45
        offset = fRecipient(tvb, pinfo, tree, offset);
6844
45
        offset = fProcessId(tvb, pinfo, tree, offset);
6845
45
        offset = fApplicationTypes(tvb, pinfo, tree, offset,
6846
45
                                    "issue confirmed notifications: ");
6847
45
        offset = fBitStringTagVS(tvb, pinfo, tree, offset,
6848
45
                                  "transitions: ", BACnetEventTransitionBits);
6849
45
    }
6850
45
    return offset;
6851
45
}
6852
6853
6854
static unsigned
6855
fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt)
6856
3.46k
{
6857
3.46k
    char       *tmp;
6858
3.46k
    unsigned    start   = offset;
6859
3.46k
    uint8_t     tag_no, tag_info;
6860
3.46k
    proto_tree *subtree = tree;
6861
6862
3.46k
    offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6863
6864
3.46k
    if (lvt > 0) {
6865
1.82k
        tmp = tvb_bytes_to_str(pinfo->pool, tvb, offset, lvt);
6866
1.82k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt,
6867
1.82k
                    ett_bacapp_tag, NULL, "%s %s", label, tmp);
6868
1.82k
        offset += lvt;
6869
1.82k
    }
6870
6871
3.46k
    fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6872
6873
3.46k
    return offset;
6874
3.46k
}
6875
6876
static unsigned
6877
fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt)
6878
972
{
6879
972
    unsigned start = offset;
6880
972
    uint8_t tag_no, tag_info;
6881
972
    proto_tree* subtree = tree;
6882
6883
972
    offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6884
6885
    /* just add the label, with the tagHeader information in its subtree */
6886
972
    subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, label);
6887
6888
972
    if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
6889
152
        proto_tree_add_item(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ENC_BIG_ENDIAN);
6890
152
        proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, ENC_BIG_ENDIAN);
6891
820
    } else if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
6892
4
        proto_tree_add_item(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, ENC_NA);
6893
4
        proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, ENC_BIG_ENDIAN);
6894
816
    } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
6895
816
        subtree = proto_tree_add_subtree(tree, tvb, offset, lvt,
6896
816
                ett_bacapp_tag, NULL, tvb_bytes_to_str(pinfo->pool, tvb, offset, lvt));
6897
816
    }
6898
972
    offset += lvt;
6899
6900
972
    fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6901
6902
972
    return offset;
6903
972
}
6904
6905
static unsigned
6906
fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6907
1.80k
{
6908
1.80k
    uint8_t tag_no, tag_info;
6909
1.80k
    uint32_t lvt;
6910
1.80k
    unsigned   offs;
6911
6912
1.80k
    offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
6913
1.80k
    offs   = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6914
1.80k
    if (lvt == 0) {
6915
804
        proto_tree_add_item(tree, hf_bacapp_tag_mac_address_broadcast, tvb, offset, offs, ENC_NA);
6916
804
        offset += offs;
6917
804
    } else
6918
997
        offset  = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
6919
6920
1.80k
    return offset;
6921
1.80k
}
6922
6923
static unsigned
6924
fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6925
257
{
6926
257
    offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
6927
257
    return fAddress(tvb, pinfo, tree, offset);
6928
257
}
6929
6930
static void
6931
format_object_identifier(char *s, uint32_t object_id)
6932
0
{
6933
0
    uint32_t type = object_id_type(object_id);
6934
0
    const char* abbrev = try_val_to_str(type, BACnetObjectTypeAbbrev);
6935
0
    if (abbrev) {
6936
0
        snprintf(s, ITEM_LABEL_LENGTH,
6937
0
                "%s-%u", abbrev, object_id_instance(object_id));
6938
0
    } else {
6939
0
        snprintf(s, ITEM_LABEL_LENGTH,
6940
0
                "[%u]-%u", type, object_id_instance(object_id));
6941
0
    }
6942
0
}
6943
6944
static unsigned
6945
fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int hfid)
6946
31.5k
{
6947
31.5k
    uint8_t     tag_no, tag_info;
6948
31.5k
    uint32_t    lvt;
6949
31.5k
    unsigned    tag_length;
6950
31.5k
    proto_tree *subtree;
6951
31.5k
    uint32_t    object_id;
6952
6953
31.5k
    tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6954
31.5k
    object_id   = tvb_get_ntohl(tvb, offset+tag_length);
6955
31.5k
    object_type = object_id_type(object_id);
6956
31.5k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_length + 4,
6957
31.5k
            ett_bacapp_tag, NULL, "%s: %s, %u", proto_registrar_get_name(hfid),
6958
31.5k
            val_to_split_str(pinfo->pool, object_type,
6959
31.5k
                128,
6960
31.5k
                BACnetObjectType,
6961
31.5k
                ASHRAE_Reserved_Fmt,
6962
31.5k
                Vendor_Proprietary_Fmt),
6963
31.5k
            object_id_instance(object_id));
6964
6965
31.5k
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
6966
31.5k
            val_to_split_str(pinfo->pool, object_type,
6967
31.5k
                128,
6968
31.5k
                BACnetObjectType,
6969
31.5k
                ASHRAE_Reserved_Fmt,
6970
31.5k
                Vendor_Proprietary_Fmt),
6971
31.5k
            object_id_instance(object_id));
6972
6973
    /* update BACnet Statistics */
6974
31.5k
    updateBacnetInfoValue(BACINFO_OBJECTID,
6975
31.5k
                  wmem_strdup(pinfo->pool,
6976
31.5k
                    val_to_split_str(pinfo->pool, object_type, 128,
6977
31.5k
                                     BACnetObjectType, ASHRAE_Reserved_Fmt,
6978
31.5k
                                     Vendor_Proprietary_Fmt)));
6979
31.5k
    updateBacnetInfoValue(BACINFO_INSTANCEID,
6980
31.5k
                  wmem_strdup_printf(pinfo->pool,
6981
31.5k
                    "Instance ID: %u",
6982
31.5k
                    object_id_instance(object_id)));
6983
6984
    /* here are the details of how we arrived at the above text */
6985
31.5k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6986
31.5k
    offset += tag_length;
6987
31.5k
    static int * const object_identifier_fields[] = {
6988
31.5k
        &hf_bacapp_objectType,
6989
31.5k
        &hf_bacapp_instanceNumber,
6990
31.5k
        NULL
6991
31.5k
    };
6992
31.5k
    proto_tree_add_bitmask_with_flags(subtree, tvb, offset, hfid,
6993
31.5k
        ett_bacapp_object_identifier, object_identifier_fields, ENC_BIG_ENDIAN, BMT_NO_APPEND);
6994
31.5k
    offset += 4;
6995
6996
31.5k
    return offset;
6997
31.5k
}
6998
6999
static unsigned
7000
fObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7001
137
{
7002
137
    return fCharacterStringBase(tvb, pinfo, tree, offset, "Object Name", false, true);
7003
137
}
7004
7005
static unsigned
7006
fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7007
4.15k
{
7008
4.15k
    uint8_t tag_no, tag_info;
7009
4.15k
    uint32_t lvt;
7010
7011
4.15k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7012
4.15k
    if (tag_no < 2) {
7013
1.09k
        if (tag_no == 0) { /* device */
7014
981
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
7015
981
        }
7016
109
        else {  /* address */
7017
109
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7018
109
            offset  = fAddress(tvb, pinfo, tree, offset);
7019
109
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7020
109
        }
7021
1.09k
    }
7022
4.15k
    return offset;
7023
4.15k
}
7024
7025
static unsigned
7026
fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7027
407
{
7028
407
    unsigned    lastoffset = 0;
7029
407
    uint8_t     tag_no, tag_info;
7030
407
    uint32_t    lvt;
7031
407
    proto_tree *orgtree    = tree;
7032
407
    proto_tree *subtree;
7033
7034
    /* beginning of new item - indent and label */
7035
407
    tree = proto_tree_add_subtree(orgtree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient Process" );
7036
7037
1.05k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7038
1.05k
        lastoffset = offset;
7039
7040
1.05k
        switch (fTagNo(tvb, offset)) {
7041
657
        case 0: /* recipient */
7042
657
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
7043
657
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
7044
657
            offset  = fRecipient(tvb, pinfo, subtree, offset);
7045
657
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
7046
657
            break;
7047
145
        case 1: /* processId */
7048
145
            offset = fProcessId(tvb, pinfo, tree, offset);
7049
145
            lastoffset = offset;
7050
145
            break;
7051
250
        default:
7052
250
            break;
7053
1.05k
        }
7054
1.04k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7055
1.04k
    }
7056
400
    return offset;
7057
407
}
7058
7059
static unsigned
7060
fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7061
50
{
7062
50
    unsigned    lastoffset = 0;
7063
50
    uint8_t     tag_no, tag_info;
7064
50
    uint32_t    lvt;
7065
50
    proto_tree *subtree;
7066
50
    proto_tree *orgtree    = tree;
7067
50
    unsigned    itemno     = 1;
7068
7069
797
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7070
796
        lastoffset = offset;
7071
796
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7072
796
        if (tag_is_closing(tag_info) ) {
7073
13
            return offset;
7074
13
        }
7075
783
        switch (tag_no) {
7076
7077
117
        case 0: /* recipient */
7078
            /* beginning of new item in list */
7079
117
            tree = proto_tree_add_subtree_format(orgtree, tvb, offset, 1,
7080
117
                ett_bacapp_value, NULL, "Subscription %d",itemno);    /* add tree label and indent */
7081
117
            itemno = itemno + 1;
7082
7083
117
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
7084
117
                ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
7085
117
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
7086
117
            offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
7087
117
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
7088
117
            break;
7089
89
        case 1: /* MonitoredPropertyReference */
7090
89
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
7091
89
                ett_bacapp_value, NULL, "Monitored Property Reference");
7092
89
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7093
89
            offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
7094
89
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7095
89
            break;
7096
263
        case 2: /* IssueConfirmedNotifications - boolean */
7097
263
            offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
7098
263
            break;
7099
180
        case 3: /* TimeRemaining */
7100
180
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
7101
180
            break;
7102
100
        case 4: /* COVIncrement */
7103
100
            offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
7104
100
            break;
7105
33
        default:
7106
33
            break;
7107
783
        }
7108
780
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7109
780
    }
7110
34
    return offset;
7111
50
}
7112
7113
static unsigned
7114
fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7115
333
{
7116
333
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
7117
333
    return fAddress(tvb, pinfo, tree, offset);
7118
333
}
7119
7120
static unsigned
7121
// NOLINTNEXTLINE(misc-no-recursion)
7122
fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_match)
7123
637
{
7124
637
    unsigned    lastoffset = 0, len;
7125
637
    uint8_t     tag_no, tag_info;
7126
637
    uint32_t    lvt;
7127
637
    proto_tree *subtree    = tree;
7128
7129
    /* set the optional global properties to indicate not-used */
7130
637
    propertyArrayIndex = -1;
7131
9.41k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7132
9.33k
        lastoffset = offset;
7133
9.33k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7134
9.33k
        if (tag_is_closing(tag_info) ) {
7135
1.79k
            if (tag_no == tag_match) {
7136
68
                return offset;
7137
68
            }
7138
1.73k
            offset += len;
7139
1.73k
            subtree = tree;
7140
1.73k
            continue;
7141
1.79k
        }
7142
7.53k
        switch (tag_no) {
7143
7144
2.78k
        case 0: /* deviceIdentifier */
7145
2.78k
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_device_identifier);
7146
2.78k
            break;
7147
447
        case 1: /* objectIdentifier */
7148
447
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
7149
447
            break;
7150
510
        case 2: /* propertyIdentifier */
7151
510
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
7152
510
            break;
7153
711
        case 3: /* propertyArrayIndex */
7154
711
            offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
7155
711
            break;
7156
494
        case 4: /* propertyValue */
7157
494
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
7158
494
            break;
7159
328
        case 5: /* priority */
7160
328
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
7161
328
            break;
7162
373
        case 6: /* postDelay */
7163
373
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
7164
373
            break;
7165
685
        case 7: /* quitOnFailure */
7166
685
            offset = fBooleanTag(tvb, pinfo, subtree, offset,
7167
685
                "Quit On Failure: ");
7168
685
            break;
7169
831
        case 8: /* writeSuccessful */
7170
831
            offset = fBooleanTag(tvb, pinfo, subtree, offset,
7171
831
                "Write Successful: ");
7172
831
            break;
7173
371
        default:
7174
371
            return offset;
7175
7.53k
        }
7176
7.08k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7177
7.08k
    }
7178
115
    return offset;
7179
637
}
7180
7181
/* BACnetActionList ::= SEQUENCE{
7182
      action [0] SEQUENCE OF BACnetActionCommand
7183
      }
7184
*/
7185
static unsigned
7186
// NOLINTNEXTLINE(misc-no-recursion)
7187
fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7188
873
{
7189
873
    unsigned    lastoffset = 0, len;
7190
873
    uint8_t     tag_no, tag_info;
7191
873
    uint32_t    lvt;
7192
873
    proto_tree *subtree    = tree;
7193
7194
2.37k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
7195
2.29k
        lastoffset = offset;
7196
2.29k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7197
2.29k
        if (tag_is_closing(tag_info)) {
7198
251
            if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
7199
23
                return offset;
7200
            /* print closing tag of action list too */
7201
228
            fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7202
228
            subtree = tree;
7203
228
            offset += len;
7204
228
            continue;
7205
251
        }
7206
2.04k
        if (tag_is_opening(tag_info)) {
7207
721
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "Action List");
7208
721
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
7209
721
                &tag_no, &tag_info, &lvt);
7210
721
        }
7211
2.04k
        switch (tag_no) {
7212
637
        case 0: /* BACnetActionCommand */
7213
637
            offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
7214
637
            break;
7215
1.40k
        default:
7216
1.40k
            break;
7217
2.04k
        }
7218
1.95k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
7219
1.95k
    }
7220
763
    return offset;
7221
873
}
7222
7223
static unsigned
7224
// NOLINTNEXTLINE(misc-no-recursion)
7225
fPropertyAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7226
633
{
7227
633
  unsigned    lastoffset = 0;
7228
633
  uint8_t     tag_no, tag_info;
7229
633
  uint32_t    lvt;
7230
633
  uint32_t    save_object_type;
7231
633
  uint32_t    save_inner_object_type;
7232
633
  int32_t     save_propertyIdentifier;
7233
7234
  /* save the external entry data because it might get overwritten here */
7235
633
  save_object_type = object_type;
7236
633
  save_propertyIdentifier = propertyIdentifier;
7237
7238
  /* inner object type might get overwritten by device id */
7239
633
  save_inner_object_type = object_type;
7240
7241
2.21k
  while (tvb_reported_length_remaining(tvb, offset) > 0) {
7242
2.16k
    lastoffset = offset;
7243
2.16k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7244
2.16k
    if (tag_is_closing(tag_info)) {
7245
87
        break;
7246
87
    }
7247
7248
2.07k
    switch (tag_no) {
7249
804
    case 0: /* objectIdentifier */
7250
804
        offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
7251
        /* save the local object type because device id might overwrite it */
7252
804
        save_inner_object_type = object_type;
7253
804
        break;
7254
173
    case 1: /* propertyIdentifier */
7255
173
        offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7256
173
        break;
7257
302
    case 2: /* propertyArrayIndex */
7258
302
        offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
7259
302
        break;
7260
88
    case 3: /* deviceIdentifier */
7261
88
        offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
7262
        /* restore the inner object type to decode the right property value */
7263
88
        object_type = save_inner_object_type;
7264
88
        break;
7265
267
    case 4: /* propertyValue */
7266
267
        offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
7267
        /* restore the external values for next loop */
7268
267
        object_type = save_object_type;
7269
267
        propertyIdentifier = save_propertyIdentifier;
7270
267
        break;
7271
53
    case 5: /* propertyAccessError */
7272
53
        if (tag_is_opening(tag_info)) {
7273
1
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7274
1
            offset = fError(tvb, pinfo, tree, offset);
7275
1
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7276
1
        }
7277
52
        else {
7278
52
            expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
7279
52
        }
7280
        /* restore the external values for next loop */
7281
53
        object_type = save_object_type;
7282
53
        propertyIdentifier = save_propertyIdentifier;
7283
53
        break;
7284
390
    default:
7285
390
        break;
7286
2.07k
    }
7287
7288
2.07k
    if (offset <= lastoffset) break;    /* nothing happened, exit loop */
7289
2.07k
  }
7290
7291
  /* restore the external values for next decoding */
7292
630
  object_type = save_object_type;
7293
630
  propertyIdentifier = save_propertyIdentifier;
7294
630
  return offset;
7295
633
}
7296
7297
static unsigned
7298
fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7299
10.0k
{
7300
10.0k
    uint8_t      tag_no, tag_info;
7301
10.0k
    uint32_t     lvt;
7302
10.0k
    unsigned     tag_len;
7303
10.0k
    proto_tree  *subtree;
7304
10.0k
    static const char *label = "Property Identifier";
7305
7306
10.0k
    propertyIdentifier = 0; /* global Variable */
7307
10.0k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7308
    /* can we decode this value? */
7309
10.0k
    if (fUnsigned32(tvb, offset+tag_len, lvt, (uint32_t *)&propertyIdentifier)) {
7310
8.23k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7311
8.23k
            ett_bacapp_tag, NULL,
7312
8.23k
            "%s: %s (%u)", label,
7313
8.23k
            val_to_split_str(pinfo->pool, propertyIdentifier, 512,
7314
8.23k
                             BACnetPropertyIdentifier,
7315
8.23k
                             ASHRAE_Reserved_Fmt,
7316
8.23k
                             Vendor_Proprietary_Fmt), propertyIdentifier);
7317
8.23k
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
7318
8.23k
                val_to_split_str(pinfo->pool, propertyIdentifier, 512,
7319
8.23k
                                 BACnetPropertyIdentifier,
7320
8.23k
                                 ASHRAE_Reserved_Fmt,
7321
8.23k
                                 Vendor_Proprietary_Fmt));
7322
8.23k
    } else {
7323
        /* property identifiers cannot be larger than 22-bits */
7324
1.81k
        return offset;
7325
1.81k
    }
7326
7327
8.23k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7328
8.23k
    proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
7329
8.23k
        offset+tag_len, lvt, ENC_BIG_ENDIAN);
7330
7331
8.23k
    return offset+tag_len+lvt;
7332
10.0k
}
7333
7334
static unsigned
7335
fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7336
3.02k
{
7337
3.02k
    uint8_t     tag_no, tag_info;
7338
3.02k
    uint32_t    lvt;
7339
3.02k
    unsigned    tag_len;
7340
3.02k
    proto_tree *subtree;
7341
7342
3.02k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7343
3.02k
    if (fUnsigned32(tvb, offset + tag_len, lvt, (uint32_t *)&propertyArrayIndex))
7344
1.34k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7345
1.34k
            ett_bacapp_tag, NULL, "property Array Index (Unsigned) %u", propertyArrayIndex);
7346
1.68k
    else
7347
1.68k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7348
1.68k
            ett_bacapp_tag, NULL, "property Array Index - %u octets (Unsigned)", lvt);
7349
3.02k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7350
7351
3.02k
    return offset+tag_len+lvt;
7352
3.02k
}
7353
7354
static unsigned
7355
fChannelValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7356
11.1k
{
7357
11.1k
  uint8_t     tag_no, tag_info;
7358
11.1k
  uint32_t    lvt;
7359
7360
11.1k
  if (tvb_reported_length_remaining(tvb, offset) > 0) {
7361
11.1k
      fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7362
11.1k
      if (tag_is_opening(tag_info) && tag_no == 0) {
7363
199
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7364
199
          offset = fLightingCommand(tvb, pinfo, tree, offset, "lighting-command: ");
7365
199
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7366
10.9k
      } else if (tag_is_opening(tag_info) && tag_no == 1) {
7367
89
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7368
89
          offset = fXyColor(tvb, pinfo, tree, offset, "xy-color: ");
7369
89
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7370
10.9k
      } else if (tag_is_opening(tag_info) && tag_no == 2) {
7371
295
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7372
295
          offset = fColorCommand(tvb, pinfo, tree, offset, "color-command: ");
7373
295
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7374
10.6k
      } else {
7375
10.6k
          if (tag_info) {
7376
2.08k
              offset = fContextTaggedValue(tvb, pinfo, tree, offset, label);
7377
8.53k
          } else {
7378
8.53k
              offset = fApplicationTypes(tvb, pinfo, tree, offset, label);
7379
8.53k
          }
7380
10.6k
      }
7381
11.1k
  }
7382
7383
11.1k
  return offset;
7384
11.1k
}
7385
7386
static unsigned
7387
fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7388
7.26k
{
7389
7.26k
    return fCharacterStringBase(tvb, pinfo, tree, offset, label, false, false);
7390
7.26k
}
7391
7392
static unsigned
7393
fCharacterStringBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, bool present_val_dissect, bool object_name_dissect)
7394
7.75k
{
7395
7.75k
    uint8_t         tag_no, tag_info, character_set;
7396
7.75k
    uint32_t        lvt, l;
7397
7.75k
    unsigned        offs;
7398
7.75k
    const char     *coding;
7399
7.75k
    uint8_t        *out;
7400
7.75k
    proto_tree     *subtree;
7401
7.75k
    unsigned        start = offset;
7402
7403
7.75k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
7404
7405
7.75k
        offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7406
7.75k
        offset += offs;
7407
7408
7.75k
        character_set = tvb_get_uint8(tvb, offset);
7409
7.75k
        offset++;
7410
7.75k
        lvt--;
7411
7412
        /* Account for code page if DBCS */
7413
7.75k
        if (character_set == IBM_MS_DBCS) {
7414
111
            offset += 2;
7415
111
            lvt -= 2;
7416
111
        }
7417
7418
7.80k
        do {
7419
7.80k
            l = MIN(lvt, 256);
7420
            /*
7421
             * XXX - are we guaranteed that these encoding
7422
             * names correspond, on *all* platforms with
7423
             * iconv(), to the encodings we want?
7424
             *
7425
             * Not necessarily. These specify "character sets" but
7426
             * not the encodings. IBM/MS DBCS specifies that it uses
7427
             * some IBM or MS double byte character set, but does not
7428
             * specify the code page - there was a proposal to explicitly
7429
             * add the code page, but that was apparently withdrawn in favor
7430
             * of just deprecating using DBCS, as it never got past a draft
7431
             * (One problem could be that IBM and MS code pages with the
7432
             * same number are slightly different, and then there's non
7433
             * IBM/MS unofficial ones that got used, sometimes conflicting
7434
             * numbers.) Even if we assume that they certainly mean one
7435
             * of the DBCS and not just any non ISO-8859-1 code page, there's
7436
             * all four types of CJK to choose from. -
7437
             * http://www.bacnet.org/Addenda/Add-135-2004k-PPR1-chair-approved.pdf
7438
             * JIS C 6226 (now JIS X 0208)
7439
             * http://www.bacnet.org/Addenda/Add-135-2008k.pdf
7440
             * is a character set, which are supported by several different
7441
             * encodings, the main types being ISO-2022-JP (JIS X 0202,
7442
             * a 7 bit encoding), Shift-JIS (most common), and EUC-JP (UNIX).
7443
             * It is unclear which encoding this refers to.
7444
             *
7445
             * If not (and perhaps even if so), we should
7446
             * perhaps have our own iconv() implementation,
7447
             * with a different name, so that we control the
7448
             * encodings it supports and the names of those
7449
             * encodings.
7450
             *
7451
             * We should also handle that in the general
7452
             * string handling code, rather than making it
7453
             * specific to the BACAPP dissector, as many
7454
             * other dissectors need to handle various
7455
             * character encodings.
7456
             */
7457
            /** this decoding may be not correct for multi-byte characters, Lka */
7458
7.80k
            switch (character_set) {
7459
446
            case ANSI_X3_4:
7460
446
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UTF_8);
7461
446
                coding = "UTF-8";
7462
446
                break;
7463
111
            case IBM_MS_DBCS:
7464
111
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
7465
111
                coding = "IBM MS DBCS";
7466
111
                break;
7467
132
            case JIS_C_6226:
7468
132
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
7469
132
                coding = "JIS C 6226";
7470
132
                break;
7471
101
            case ISO_10646_UCS4:
7472
101
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UCS_4|ENC_BIG_ENDIAN);
7473
101
                coding = "ISO 10646 UCS-4";
7474
101
                break;
7475
90
            case ISO_10646_UCS2:
7476
90
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UCS_2|ENC_BIG_ENDIAN);
7477
90
                coding = "ISO 10646 UCS-2";
7478
90
                break;
7479
50
            case ISO_8859_1:
7480
50
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ISO_8859_1);
7481
50
                coding = "ISO 8859-1";
7482
50
                break;
7483
6.84k
            default:
7484
                /* Assume this is some form of extended ASCII, with one-byte code points for ASCII characters */
7485
6.84k
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
7486
6.84k
                coding = "unknown";
7487
6.84k
                break;
7488
7.80k
            }
7489
7490
7.53k
            if (present_val_dissect) {
7491
351
                subtree = proto_tree_add_subtree(tree, tvb, offset, l, ett_bacapp_tag, NULL, "present-value");
7492
351
                proto_tree_add_string(subtree, hf_bacapp_present_value_char_string, tvb, offset, l, (const char*) out);
7493
7.18k
            } else if (object_name_dissect) {
7494
126
                subtree = proto_tree_add_subtree(tree, tvb, offset, l, ett_bacapp_tag, NULL, label);
7495
126
                proto_tree_add_string(subtree, hf_bacapp_object_name, tvb, offset, l, (const char*) out);
7496
7.05k
            } else {
7497
7.05k
                subtree = proto_tree_add_subtree_format(tree, tvb, offset, l, ett_bacapp_tag, NULL,
7498
7.05k
                                    "%s%s '%s'", label, coding, out);
7499
7.05k
            }
7500
7501
7.53k
            lvt    -= l;
7502
7.53k
            offset += l;
7503
7.53k
        } while (lvt > 0);
7504
7505
7.48k
        fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
7506
7.48k
        proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
7507
7508
7.48k
        if (character_set == IBM_MS_DBCS) {
7509
100
            proto_tree_add_item(subtree, hf_BACnetCodePage, tvb, start+offs+1, 2, ENC_BIG_ENDIAN);
7510
100
        }
7511
        /* XXX - put the string value here */
7512
7.48k
    }
7513
7.48k
    return offset;
7514
7.75k
}
7515
7516
static unsigned
7517
fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
7518
    const value_string *src)
7519
5.88k
{
7520
5.88k
    return fBitStringTagVSBase(tvb, pinfo, tree, offset, label, src, false);
7521
5.88k
}
7522
7523
static unsigned
7524
fBitStringTagVSBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
7525
    const value_string *src, bool present_val_dissect)
7526
6.56k
{
7527
6.56k
    uint8_t         tag_no, tag_info, tmp;
7528
6.56k
    int             j, unused, skip;
7529
6.56k
    unsigned        start = offset;
7530
6.56k
    unsigned        offs;
7531
6.56k
    uint32_t        lvt, i, numberOfBytes;
7532
6.56k
    char            bf_arr[256 + 1];
7533
6.56k
    proto_tree     *subtree = tree;
7534
7535
6.56k
    offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7536
6.56k
    numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
7537
6.56k
    offset += offs;
7538
6.56k
    unused  = tvb_get_uint8(tvb, offset); /* get the unused Bits */
7539
7540
6.56k
    memset(bf_arr, 0, sizeof(bf_arr));
7541
6.56k
    skip = 0;
7542
40.4k
    for (i = 0; i < numberOfBytes; i++) {
7543
33.8k
        tmp = tvb_get_uint8(tvb, (offset)+i + 1);
7544
33.8k
        if (i == numberOfBytes - 1) { skip = unused; }
7545
271k
        for (j = 0; j < 8 - skip; j++) {
7546
238k
            bf_arr[MIN(sizeof(bf_arr) - 2, (i * 8) + j)] = tmp & (1 << (7 - j)) ? 'T' : 'F';
7547
238k
        }
7548
33.8k
    }
7549
7550
6.56k
    if (!present_val_dissect) {
7551
5.62k
        subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
7552
5.62k
                                    ett_bacapp_tag, NULL,
7553
5.62k
                                    "%s(Bit String) (%s)", label, bf_arr);
7554
5.62k
    } else {
7555
943
        subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
7556
943
                                    ett_bacapp_tag, NULL,
7557
943
                                    "present-value (%s)", bf_arr);
7558
943
    }
7559
7560
6.56k
    fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
7561
6.56k
    proto_tree_add_item(subtree, hf_bacapp_unused_bits, tvb, offset, 1, ENC_NA);
7562
6.56k
    memset(bf_arr, 0, sizeof(bf_arr));
7563
6.56k
    skip = 0;
7564
24.5k
    for (i = 0; i < numberOfBytes; i++) {
7565
17.9k
        tmp = tvb_get_uint8(tvb, (offset)+i+1);
7566
17.9k
        if (i == numberOfBytes-1) { skip = unused; }
7567
131k
        for (j = 0; j < 8-skip; j++) {
7568
113k
            if (src != NULL) {
7569
69.4k
                proto_tree_add_boolean_format(subtree, hf_bacapp_bit, tvb, offset+i+1, 1,
7570
69.4k
                                            (tmp & (1 << (7 - j))), "%s = %s",
7571
69.4k
                                            val_to_str(pinfo->pool, (unsigned) (i*8 +j), src, ASHRAE_Reserved_Fmt),
7572
69.4k
                                            (tmp & (1 << (7 - j))) ? "TRUE" : "FALSE");
7573
69.4k
            } else {
7574
43.6k
                bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
7575
43.6k
            }
7576
113k
        }
7577
17.9k
    }
7578
7579
6.56k
    if (src == NULL) {
7580
2.51k
        bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
7581
2.51k
        proto_tree_add_bytes_format(subtree, hf_bacapp_complete_bitstring, tvb, offset, lvt, NULL, "B'%s'", bf_arr);
7582
2.51k
    }
7583
7584
6.56k
    offset += lvt;
7585
7586
6.56k
    return offset;
7587
6.56k
}
7588
7589
static unsigned
7590
fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7591
1.48k
{
7592
1.48k
    return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
7593
1.48k
}
7594
7595
/* handles generic application types, as well as enumerated and enumerations
7596
   with reserved and proprietary ranges (split) */
7597
static unsigned
7598
fApplicationTypesEnumeratedSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
7599
    const char *label, const value_string *src, uint32_t split_val)
7600
47.2k
{
7601
47.2k
    uint8_t tag_no, tag_info;
7602
47.2k
    uint32_t lvt;
7603
47.2k
    unsigned   tag_len;
7604
7605
47.2k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
7606
47.2k
        tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7607
47.2k
        if (!tag_is_context_specific(tag_info)) {
7608
42.4k
            switch (tag_no) {
7609
22.9k
            case 0: /** NULL 20.2.2 */
7610
22.9k
                offset = fNullTag(tvb, pinfo, tree, offset, label);
7611
22.9k
                break;
7612
4.74k
            case 1: /** BOOLEAN 20.2.3 */
7613
4.74k
                offset = fBooleanTag(tvb, pinfo, tree, offset, label);
7614
4.74k
                break;
7615
2.05k
            case 2: /** Unsigned Integer 20.2.4 */
7616
2.05k
                offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
7617
2.05k
                break;
7618
2.22k
            case 3: /** Signed Integer 20.2.5 */
7619
2.22k
                offset = fSignedTag(tvb, pinfo, tree, offset, label);
7620
2.22k
                break;
7621
844
            case 4: /** Real 20.2.6 */
7622
844
                offset = fRealTag(tvb, pinfo, tree, offset, label);
7623
844
                break;
7624
669
            case 5: /** Double 20.2.7 */
7625
669
                offset = fDoubleTag(tvb, pinfo, tree, offset, label);
7626
669
                break;
7627
1.53k
            case 6: /** Octet String 20.2.8 */
7628
1.53k
                offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
7629
1.53k
                break;
7630
880
            case 7: /** Character String 20.2.9 */
7631
880
                offset = fCharacterString(tvb, pinfo, tree, offset, label);
7632
880
                break;
7633
897
            case 8: /** Bit String 20.2.10 */
7634
897
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
7635
897
                break;
7636
940
            case 9: /** Enumerated 20.2.11 */
7637
940
                offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
7638
940
                break;
7639
1.03k
            case 10: /** Date 20.2.12 */
7640
1.03k
                offset = fDate(tvb, pinfo, tree, offset, label);
7641
1.03k
                break;
7642
573
            case 11: /** Time 20.2.13 */
7643
573
                offset = fTime(tvb, pinfo, tree, offset, label);
7644
573
                break;
7645
666
            case 12: /** BACnetObjectIdentifier 20.2.14 */
7646
666
                offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
7647
666
                break;
7648
1.12k
            case 13: /* reserved for ASHRAE */
7649
2.16k
            case 14:
7650
2.17k
            case 15:
7651
2.17k
                proto_tree_add_bytes_format(tree, hf_bacapp_reserved_ashrea, tvb, offset, lvt+tag_len, NULL, "%s'reserved for ASHRAE'", label);
7652
2.17k
                offset += lvt + tag_len;
7653
2.17k
                break;
7654
303
            default:
7655
303
                break;
7656
42.4k
            }
7657
42.4k
        }
7658
47.2k
    }
7659
47.0k
    return offset;
7660
47.2k
}
7661
7662
static unsigned
7663
fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7664
130
{
7665
130
    unsigned lastoffset = 0;
7666
7667
864
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7668
862
        lastoffset = offset;
7669
7670
862
        switch (fTagNo(tvb, offset)) {
7671
532
        case 0: /* percent */
7672
532
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
7673
532
            break;
7674
141
        case 1: /* level */
7675
141
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
7676
141
            break;
7677
62
        case 2: /* amount */
7678
62
            offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
7679
62
            break;
7680
127
        default:
7681
127
            return offset;
7682
862
        }
7683
734
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7684
734
    }
7685
2
    return offset;
7686
130
}
7687
7688
static unsigned
7689
fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
7690
    const char *label, const value_string *vs)
7691
11.6k
{
7692
11.6k
    return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
7693
11.6k
}
7694
7695
static unsigned
7696
fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
7697
    const char *label)
7698
34.6k
{
7699
34.6k
    return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
7700
34.6k
}
7701
7702
static unsigned
7703
fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7704
8.65k
{
7705
8.65k
    uint8_t     tag_no, tag_info;
7706
8.65k
    uint32_t    lvt;
7707
8.65k
    unsigned    tag_len;
7708
8.65k
    proto_tree *subtree;
7709
8.65k
    int         tvb_len;
7710
7711
8.65k
    (void)label;
7712
8.65k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7713
    /* cap the the suggested length in case of bad data */
7714
8.65k
    tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
7715
8.65k
    if ((tvb_len >= 0) && ((uint32_t)tvb_len < lvt)) {
7716
97
        lvt = tvb_len;
7717
97
    }
7718
8.65k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset+tag_len, lvt,
7719
8.65k
        ett_bacapp_tag, NULL, "Context Value (as %u DATA octets)", lvt);
7720
7721
8.65k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7722
7723
8.65k
    return offset + tag_len + lvt;
7724
8.65k
}
7725
/*
7726
BACnetPrescale ::= SEQUENCE {
7727
    multiplier  [0] Unsigned,
7728
moduloDivide    [1] Unsigned
7729
}
7730
*/
7731
static unsigned
7732
fPrescale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7733
15
{
7734
15
    uint8_t tag_no, tag_info;
7735
15
    uint32_t lvt;
7736
15
    unsigned   lastoffset = 0;
7737
7738
20
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7739
20
        lastoffset = offset;
7740
20
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7741
20
        if (tag_is_closing(tag_info) ) {
7742
0
            return offset;
7743
0
            }
7744
20
        switch (tag_no) {
7745
3
        case 0: /* multiplier */
7746
3
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
7747
3
            break;
7748
3
        case 1: /* moduloDivide */
7749
3
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
7750
3
            break;
7751
14
        default:
7752
14
            return offset;
7753
20
        }
7754
5
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7755
5
    }
7756
0
    return offset;
7757
7758
15
}
7759
/*
7760
BACnetScale ::= CHOICE {
7761
    floatScale  [0] REAL,
7762
integerScale    [1] INTEGER
7763
}
7764
*/
7765
static unsigned
7766
fScale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7767
43
{
7768
43
    uint8_t tag_no, tag_info;
7769
43
    uint32_t lvt;
7770
43
    unsigned   lastoffset = 0;
7771
7772
103
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7773
102
        lastoffset = offset;
7774
102
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7775
102
        if (tag_is_closing(tag_info) ) {
7776
1
            return offset;
7777
1
            }
7778
101
        switch (tag_no) {
7779
60
        case 0: /* floatScale */
7780
60
            offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
7781
60
            break;
7782
4
        case 1: /* integerScale */
7783
4
            offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
7784
4
            break;
7785
37
        default:
7786
37
            return offset;
7787
101
        }
7788
60
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7789
60
    }
7790
1
    return offset;
7791
43
}
7792
/*
7793
BACnetAccumulatorRecord ::= SEQUENCE {
7794
    timestamp       [0] BACnetDateTime,
7795
    presentValue        [1] Unsigned,
7796
    accumulatedValue    [2] Unsigned,
7797
    accumulatortStatus  [3] ENUMERATED {
7798
                    normal          (0),
7799
                    starting        (1),
7800
                    recovered       (2),
7801
                    abnormal        (3),
7802
                    failed          (4)
7803
                    }
7804
}
7805
*/
7806
static unsigned
7807
fLoggingRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7808
81
{
7809
81
    uint8_t tag_no, tag_info;
7810
81
    uint32_t lvt;
7811
81
    unsigned   lastoffset = 0;
7812
7813
250
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7814
248
        lastoffset = offset;
7815
248
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7816
248
        if (tag_is_closing(tag_info) ) {
7817
4
            return offset;
7818
4
            }
7819
244
        switch (tag_no) {
7820
97
        case 0: /* timestamp */
7821
97
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7822
97
            offset  = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
7823
97
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7824
97
            break;
7825
38
        case 1: /* presentValue */
7826
38
            offset = fPresentValue(tvb, pinfo, tree, offset, NULL, 0, BACAPP_PRESENT_VALUE_UNSIGNED);
7827
38
            break;
7828
20
        case 2: /* accumulatedValue */
7829
20
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
7830
20
            break;
7831
15
        case 3: /* accumulatorStatus */
7832
15
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
7833
15
            break;
7834
74
        default:
7835
74
            return offset;
7836
244
        }
7837
169
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7838
169
    }
7839
2
    return offset;
7840
81
}
7841
7842
/*
7843
 SEQ OF Any enumeration (current usage is SEQ OF BACnetDoorAlarmState
7844
*/
7845
static unsigned
7846
fSequenceOfEnums(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, const value_string *vs)
7847
29
{
7848
29
    uint8_t tag_no, tag_info;
7849
29
    uint32_t lvt;
7850
29
    unsigned   lastoffset = 0;
7851
7852
172
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7853
170
        lastoffset = offset;
7854
170
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7855
170
        if (tag_is_closing(tag_info) ) {
7856
2
            return offset;
7857
2
            }
7858
168
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
7859
168
        if ( offset <= lastoffset ) break;
7860
168
    }
7861
27
    return offset;
7862
29
}
7863
7864
/*
7865
SEQ OF BACnetDeviceObjectReference (accessed as an array)
7866
}
7867
*/
7868
static unsigned
7869
fDoorMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7870
136
{
7871
136
    uint8_t tag_no, tag_info;
7872
136
    uint32_t lvt;
7873
136
    unsigned   lastoffset = 0;
7874
7875
162
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7876
162
        lastoffset = offset;
7877
162
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7878
162
        if (tag_is_closing(tag_info) ) {
7879
3
            return offset;
7880
3
            }
7881
159
        offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
7882
159
        if (offset <= lastoffset) break;
7883
159
    }
7884
133
    return offset;
7885
136
}
7886
7887
/*
7888
SEQ OF ReadAccessSpecification
7889
*/
7890
static unsigned
7891
fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7892
60
{
7893
60
    uint8_t tag_no, tag_info;
7894
60
    uint32_t lvt;
7895
60
    unsigned   lastoffset = 0;
7896
7897
77
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7898
75
        lastoffset = offset;
7899
75
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7900
75
        if (tag_is_closing(tag_info) ) {
7901
3
            return offset;
7902
3
            }
7903
72
        offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
7904
72
        if ( offset <= lastoffset ) break;
7905
72
    }
7906
57
    return offset;
7907
60
}
7908
7909
static unsigned
7910
// NOLINTNEXTLINE(misc-no-recursion)
7911
fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7912
8.78k
{
7913
8.78k
    uint8_t tag_no, tag_info;
7914
8.78k
    uint32_t lvt;
7915
8.78k
    unsigned   lastoffset = 0, depth = 0;
7916
8.78k
    char    ar[256];
7917
8.78k
    uint32_t save_object_type;
7918
8.78k
    bool do_default_handling;
7919
7920
8.78k
    if (propertyIdentifier >= 0) {
7921
8.77k
        snprintf(ar, sizeof(ar), "%s: ",
7922
8.77k
            val_to_split_str(pinfo->pool, propertyIdentifier, 512,
7923
8.77k
                BACnetPropertyIdentifier,
7924
8.77k
                ASHRAE_Reserved_Fmt,
7925
8.77k
                Vendor_Proprietary_Fmt));
7926
8.77k
    } else {
7927
14
        snprintf(ar, sizeof(ar), "Abstract Type: ");
7928
14
    }
7929
7930
8.78k
    increment_dissection_depth(pinfo);
7931
7932
114k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7933
114k
        lastoffset = offset;
7934
114k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7935
114k
        if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
7936
3.18k
            if (depth <= 0) {
7937
2.33k
                goto cleanup;
7938
2.33k
            }
7939
3.18k
        }
7940
7941
111k
        do_default_handling = false;
7942
7943
        /* Application Tags */
7944
111k
        switch (propertyIdentifier) {
7945
2.61k
        case 0: /* acked-transitions */
7946
2.68k
        case 35: /* event-enable */
7947
2.68k
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
7948
2.68k
            BACnetAcknowledgedTransitions);
7949
2.68k
            break;
7950
2.34k
        case 2: /* action */
7951
                /* loop object is application tagged,
7952
                    command object is context tagged */
7953
2.34k
                if (tag_is_context_specific(tag_info)) {
7954
                    /* BACnetActionList */
7955
873
                    offset = fActionList(tvb, pinfo, tree, offset);
7956
1.47k
                } else {
7957
                    /* BACnetAction */
7958
1.47k
                    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
7959
1.47k
                        BACnetAction);
7960
1.47k
                }
7961
2.34k
                break;
7962
3.00k
        case 7: /* alarm-values*/
7963
3.00k
            switch (object_type) {
7964
14
            case 21: /* life-point */
7965
14
            case 22: /* life-zone */
7966
14
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
7967
14
              break;
7968
0
            case 30: /* access-door */
7969
0
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
7970
0
              break;
7971
16
            case 31: /* timer */
7972
16
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
7973
16
              break;
7974
0
            case 36: /* access-zone */
7975
0
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
7976
0
              break;
7977
0
            case 39: /* bitstring-value */
7978
2.97k
            default:
7979
2.97k
              if (tag_info) {
7980
1.32k
                if (tag_is_opening(tag_info)) {
7981
379
                  ++depth;
7982
379
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7983
379
                }
7984
947
                else if (tag_is_closing(tag_info)) {
7985
127
                  --depth;
7986
127
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7987
127
                }
7988
820
                else {
7989
820
                  offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
7990
820
                }
7991
1.32k
              }
7992
1.65k
              else {
7993
1.65k
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
7994
1.65k
              }
7995
2.97k
              break;
7996
3.00k
            }
7997
2.99k
            break;
7998
2.99k
        case 37: /* event-type */
7999
420
            offset = fEventType(tvb, pinfo, tree, offset);
8000
420
            break;
8001
2.37k
        case 39: /* fault-values */
8002
2.37k
            switch (object_type) {
8003
1
            case 21: /* life-point */
8004
1
            case 22: /* life-zone */
8005
1
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
8006
1
              break;
8007
0
            case 30: /* access-door */
8008
0
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
8009
0
              break;
8010
0
            case 31: /* timer */
8011
0
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
8012
0
              break;
8013
41
            case 36: /* access-zone */
8014
41
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
8015
41
              break;
8016
0
            case 39: /* bitstring-value */
8017
2.33k
            default:
8018
2.33k
              if (tag_info) {
8019
777
                if (tag_is_opening(tag_info)) {
8020
430
                  ++depth;
8021
430
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8022
430
                }
8023
347
                else if (tag_is_closing(tag_info)) {
8024
71
                  --depth;
8025
71
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8026
71
                }
8027
276
                else {
8028
276
                  offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
8029
276
                }
8030
777
              }
8031
1.55k
              else {
8032
1.55k
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8033
1.55k
              }
8034
2.33k
              break;
8035
2.37k
            }
8036
2.37k
            break;
8037
2.37k
        case 30: /* BACnetAddressBinding */
8038
333
        case 331: /* last-key-server */
8039
333
            offset = fAddressBinding(tvb, pinfo, tree, offset);
8040
333
            break;
8041
58
        case 52: /* limit-enable */
8042
58
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLimitEnable);
8043
58
            break;
8044
135
        case 54: /* list of object property reference */
8045
135
            offset = fLOPR(tvb, pinfo, tree, offset);
8046
135
            break;
8047
257
        case 55: /* list-of-session-keys */
8048
257
            offset = fSessionKey(tvb, pinfo, tree, offset);
8049
257
            break;
8050
31
        case 77: /* object-name */
8051
31
            offset = fObjectName(tvb, pinfo, tree, offset);
8052
31
            break;
8053
36
        case 79: /* object-type */
8054
592
        case 96: /* protocol-object-types-supported */
8055
592
            offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
8056
592
                BACnetObjectType, 128);
8057
592
            break;
8058
367
        case 97: /* Protocol-Services-Supported */
8059
367
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8060
367
                BACnetServicesSupported);
8061
367
            break;
8062
45
        case 102: /* recipient-list */
8063
45
            offset = fDestination(tvb, pinfo, tree, offset);
8064
45
            break;
8065
1
        case 107: /* segmentation-supported */
8066
1
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8067
1
                BACnetSegmentation);
8068
1
            break;
8069
3
        case 111: /* Status-Flags */
8070
3
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8071
3
                BACnetStatusFlags);
8072
3
            break;
8073
70
        case 112: /* System-Status */
8074
70
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8075
70
                BACnetDeviceStatus);
8076
70
            break;
8077
62
        case 117: /* units */
8078
66
        case 455: /* car-load-units */
8079
66
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8080
66
                BACnetEngineeringUnits);
8081
66
            break;
8082
427
        case 87:    /* priority-array -- accessed as a BACnetARRAY */
8083
427
            if (propertyArrayIndex == 0) {
8084
                /* BACnetARRAY index 0 refers to the length
8085
                of the array, not the elements of the array */
8086
8
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8087
419
            } else {
8088
419
                offset = fPriorityArray(tvb, pinfo, tree, offset);
8089
419
            }
8090
427
            break;
8091
135
        case 38:    /* exception-schedule */
8092
135
            if (object_type < 128) {
8093
105
                if (propertyArrayIndex == 0) {
8094
                    /* BACnetARRAY index 0 refers to the length
8095
                    of the array, not the elements of the array */
8096
2
                    offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8097
103
                } else {
8098
103
                    offset = fSpecialEvent(tvb, pinfo, tree, offset);
8099
103
                }
8100
105
            }
8101
135
            break;
8102
10
        case 19:  /* controlled-variable-reference */
8103
22
        case 60:  /* manipulated-variable-reference */
8104
27
        case 78:  /* object-property-reference */
8105
41
        case 181: /* input-reference */
8106
41
        case 355: /* event-algorithm-inhibit-reference */
8107
41
            offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
8108
41
            break;
8109
2
        case 132: /* log-device-object-property */
8110
2
            offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
8111
2
            break;
8112
143
        case 109: /* Setpoint-Reference */
8113
            /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
8114
143
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8115
143
            offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
8116
143
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8117
143
            break;
8118
77
        case 123:   /* weekly-schedule -- accessed as a BACnetARRAY */
8119
77
            if (object_type < 128) {
8120
69
                if (propertyArrayIndex == 0) {
8121
                    /* BACnetARRAY index 0 refers to the length
8122
                    of the array, not the elements of the array */
8123
20
                    offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8124
49
                } else {
8125
49
                    offset = fWeeklySchedule(tvb, pinfo, tree, offset);
8126
49
                }
8127
69
            }
8128
77
            break;
8129
344
        case 127:   /* client COV increment */
8130
344
            offset = fClientCOV(tvb, pinfo, tree, offset);
8131
344
            break;
8132
6
        case 131:  /* log-buffer */
8133
6
            if ( object_type == 61 )
8134
0
                offset = fAuditLogRecord(tvb, pinfo, tree, offset);
8135
6
            else if ( object_type == 25 )
8136
0
                offset = fEventLogRecord(tvb, pinfo, tree, offset);
8137
6
            else if ( object_type == 27 )
8138
0
                offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
8139
6
            else
8140
6
                offset = fLogRecord(tvb, pinfo, tree, offset);
8141
6
            break;
8142
2
        case 159: /* member-of */
8143
5
        case 165: /* zone-members */
8144
11
        case 211: /* subordinate-list */
8145
32
        case 246: /* access-doors */
8146
57
        case 249: /* access-event-credential */
8147
68
        case 252: /* accompaniment */
8148
80
        case 265: /* credentials */
8149
84
        case 266: /* credentials-in-zone */
8150
130
        case 277: /* last-credential-added */
8151
152
        case 279: /* last-credential-removed */
8152
154
        case 286: /* members */
8153
165
        case 320: /* zone-from */
8154
180
        case 321: /* zone-to */
8155
265
        case 461: /* energy-meter-ref */
8156
267
        case 491: /* represents */
8157
267
            offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
8158
267
            break;
8159
2.06k
        case 196: /* last-restart-reason */
8160
2.06k
            offset = fRestartReason(tvb, pinfo, tree, offset);
8161
2.06k
            break;
8162
117
        case 212: /* actual-shed-level */
8163
117
        case 214: /* expected-shed-level */
8164
130
        case 218: /* requested-shed-level */
8165
130
            offset = fShedLevel(tvb, pinfo, tree, offset);
8166
130
            break;
8167
50
        case 152: /* active-cov-subscriptions */
8168
50
            offset = fCOVSubscription(tvb, pinfo, tree, offset);
8169
50
            break;
8170
1.98k
        case 23: /* date-list */
8171
1.98k
            offset = fCalendarEntry(tvb, pinfo, tree, offset);
8172
1.98k
            break;
8173
1
        case 116: /* time-synchronization-recipients */
8174
4
        case 206: /* utc-time-synchronization-recipients */
8175
136
        case 202: /* restart-notification-recipients */
8176
136
            offset = fRecipient(tvb, pinfo, tree, offset);
8177
136
            break;
8178
26.3k
        case 83: /* event-parameters */
8179
26.3k
            offset = fEventParameter(tvb, pinfo, tree, offset);
8180
26.3k
            break;
8181
128
        case 130: /* event-time-stamp */
8182
128
            if (propertyArrayIndex == 0) {
8183
                /* BACnetARRAY index 0 refers to the length
8184
                of the array, not the elements of the array */
8185
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8186
128
            } else {
8187
128
                offset = fEventTimeStamps(tvb, pinfo, tree, offset);
8188
128
            }
8189
128
            break;
8190
86
        case 197: /* logging-type */
8191
86
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
8192
86
            break;
8193
39
        case 36: /* event-state */
8194
39
            offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
8195
39
            break;
8196
76
        case 103: /* reliability */
8197
76
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
8198
76
            break;
8199
469
        case 72: /* notify-type */
8200
469
            offset = fNotifyType(tvb, pinfo, tree, offset);
8201
469
            break;
8202
109
        case 208: /* node-type */
8203
109
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
8204
109
            break;
8205
19
        case 231: /* door-status */
8206
137
        case 450: /* car-door-status */
8207
137
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
8208
137
            break;
8209
227
        case 233: /* lock-status */
8210
227
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
8211
227
            break;
8212
256
        case 235: /* secured-status */
8213
256
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
8214
256
            break;
8215
23
        case 158: /* maintenance-required */
8216
23
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
8217
23
            break;
8218
78
        case 92: /* program-state */
8219
78
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
8220
78
            break;
8221
120
        case 90: /* program-change */
8222
120
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
8223
120
            break;
8224
179
        case 100: /* reason-for-halt */
8225
179
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
8226
179
            break;
8227
0
        case 157: /* last-restore-time */
8228
0
            offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8229
0
            break;
8230
105
        case 160: /* mode */
8231
366
        case 175: /* accepted-modes */
8232
366
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
8233
366
            break;
8234
72
        case 163: /* silenced */
8235
72
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
8236
72
            break;
8237
58
        case 161: /* operation-expected */
8238
58
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
8239
58
            break;
8240
2
        case 164: /* tracking-value */
8241
2
            if (object_type == 21 || object_type == 22) /* life-safety-point/zone */
8242
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
8243
2
            else if (object_type == 63) /* color */
8244
0
                offset = fXyColor(tvb, pinfo, tree, offset, ar);
8245
2
            else if (object_type == 64) /* color-temperature */
8246
0
                offset = fUnsignedTag(tvb, pinfo, tree, offset, ar);
8247
2
            else if (object_type == 54) /* lighting-output */
8248
0
                offset = fRealTag(tvb, pinfo, tree, offset, ar);
8249
2
            break;
8250
63
        case 166: /* life-safety-alarm-values */
8251
63
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
8252
63
            break;
8253
697
        case 41: /* file-access-method */
8254
697
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
8255
697
            break;
8256
15
        case 185:  /* prescale */
8257
15
            offset = fPrescale(tvb, pinfo, tree, offset);
8258
15
            break;
8259
43
        case 187:  /* scale */
8260
43
            offset = fScale(tvb, pinfo, tree, offset);
8261
43
            break;
8262
138
        case 189: /* update-time */
8263
138
            if (object_type == 37) /* credential-data-input */
8264
0
                offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8265
138
            else
8266
138
                offset = fDateTime(tvb, pinfo, tree, offset, ar);
8267
138
            break;
8268
81
        case 184: /* logging-record */
8269
81
            offset = fLoggingRecord(tvb, pinfo, tree, offset);
8270
81
            break;
8271
62
        case 203: /* time-of-device-restart */
8272
62
            offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8273
62
            break;
8274
46
        case 226: /* door-alarm-state */
8275
46
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
8276
46
            break;
8277
136
        case 228: /* door-members */
8278
136
            offset = fDoorMembers(tvb, pinfo, tree, offset);
8279
136
            break;
8280
27
        case 234: /* masked-alarm-values */
8281
27
            offset = fSequenceOfEnums(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
8282
27
            break;
8283
4
        case 248: /* access-event-authentication-factor */
8284
4
            offset = fAuthenticationFactor(tvb, pinfo, tree, offset);
8285
4
            break;
8286
363
        case 261: /* authorization-mode */
8287
363
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuthorizationMode);
8288
363
            break;
8289
60
        case 53:  /* list-of-group-members */
8290
60
            save_object_type = object_type;
8291
60
            offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
8292
60
            object_type = save_object_type;
8293
60
            break;
8294
0
        case 296: /* occupancy-state */
8295
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
8296
0
            break;
8297
0
        case 300: /* passback-mode */
8298
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessPassbackMode);
8299
0
            break;
8300
35
        case 303: /* reason-for-disable */
8301
35
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessCredentialDisableReason);
8302
35
            break;
8303
1
        case 318: /* user-type */
8304
1
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessUserType);
8305
1
            break;
8306
21
        case 330: /* key-sets */
8307
21
            offset = fSecurityKeySet(tvb, pinfo, tree, offset);
8308
21
            break;
8309
13
        case 332: /* network-access-security-policies */
8310
13
            offset = fNetworkSecurityPolicy(tvb, pinfo, tree, offset);
8311
13
            break;
8312
0
        case 338: /* backup-and-restore-state */
8313
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetBackupState);
8314
0
            break;
8315
0
        case 370: /* write-status */
8316
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetWriteStatus);
8317
0
            break;
8318
0
        case 385: /* transition */
8319
0
            if (object_type == 54) /* lighting-output */
8320
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLightingTransition);
8321
0
            else if (object_type == 63) /* color */
8322
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorTransition);
8323
0
            else if (object_type == 64) /* color-temperature */
8324
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorTransition);
8325
0
            break;
8326
41
        case 288: /* negative-access-rules */
8327
112
        case 302: /* positive-access-rules */
8328
112
            offset = fAccessRule(tvb, pinfo, tree, offset);
8329
112
            break;
8330
118
        case 304: /* supported-formats */
8331
118
            offset = fAuthenticationFactorFormat(tvb, pinfo, tree, offset);
8332
118
            break;
8333
16
        case 327: /* base-device-security-policy */
8334
16
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSecurityLevel);
8335
16
            break;
8336
2
        case 371: /* property-list */
8337
2
            offset = fSequenceOfEnums(tvb, pinfo, tree, offset, ar, BACnetPropertyIdentifier);
8338
2
            break;
8339
8.55k
        case 358: /* fault-parameters */
8340
8.55k
            offset = fFaultParameter(tvb, pinfo, tree, offset);
8341
8.55k
            break;
8342
0
        case 359: /* fault type */
8343
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFaultType);
8344
0
            break;
8345
92
        case 362: /* subscribed-recipients */
8346
92
            offset = fEventNotificationSubscription(tvb, pinfo, tree, offset);
8347
92
            break;
8348
0
        case 364: /* authorization-exemptions */
8349
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuthorizationExemption);
8350
0
            break;
8351
2
        case 378: /* in-progress */
8352
2
            if (object_type == 54) /* lighting-output */
8353
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLightingInProgress);
8354
2
            else if (object_type == 63) /* color */
8355
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorOperationInProgress);
8356
2
            else if (object_type == 64) /* color-temperature */
8357
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorOperationInProgress);
8358
2
            break;
8359
0
        case 380: /* lighting-command */
8360
0
            offset = fLightingCommand(tvb, pinfo, tree, offset, ar);
8361
0
            break;
8362
210
        case 16:  /* change-of-state-time */
8363
611
        case 71:  /* modification-date */
8364
861
        case 114: /* time-of-active-time-reset */
8365
1.51k
        case 115: /* time-of-state-count-reset */
8366
1.83k
        case 142: /* start-time */
8367
2.08k
        case 143: /* stop-time */
8368
2.17k
        case 149: /* maximum-value-time-stamp */
8369
2.20k
        case 150: /* minimum-value-time-stamp */
8370
2.56k
        case 179: /* count-change-time */
8371
2.99k
        case 192: /* value-change-time */
8372
3.17k
        case 254: /* activation-time */
8373
3.43k
        case 270: /* expiration-time */
8374
3.72k
        case 278: /* last-credential-added-time */
8375
3.72k
        case 280: /* last-credential-removed-time */
8376
3.72k
        case 281: /* last-use-time */
8377
3.72k
        case 392: /* time-of-strike-count-reset */
8378
3.72k
            offset = fDateTime(tvb, pinfo, tree, offset, ar);
8379
3.72k
            break;
8380
131
        case 258: /* authentication-policy-list */
8381
131
            offset = fAuthenticationPolicy(tvb, pinfo, tree, offset);
8382
131
            break;
8383
0
        case 395: /* last-state-change */
8384
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerTransition);
8385
0
            break;
8386
77
        case 396: /* state-change-values */
8387
77
            offset = fTimerStateChangeValue(tvb, pinfo, tree, offset);
8388
77
            break;
8389
11
        case 398: /* timer-state */
8390
11
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
8391
11
            break;
8392
75
        case 407: /* bacnet-ip-global-address */
8393
75
        case 418: /* fd-bbmd-address */
8394
75
            offset = fHostNPort(tvb, pinfo, tree, offset, ar);
8395
75
            break;
8396
0
        case 408: /* bacnet-ip-mode */
8397
0
        case 435: /* bacnet-ipv6-mode */
8398
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetIpMode);
8399
0
            break;
8400
92
        case 414: /* bmd-broadcast-distribution-table */
8401
92
            offset = fBDTEntry(tvb, pinfo, tree, offset, ar);
8402
92
            break;
8403
81
        case 415: /* bbmd-foreign-device-table */
8404
81
            offset = fFDTEntry(tvb, pinfo, tree, offset, ar);
8405
81
            break;
8406
21
        case 417: /* command */
8407
21
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkPortCommand);
8408
21
            break;
8409
0
        case 426: /* network-number-quality */
8410
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkNumberQuality);
8411
0
            break;
8412
0
        case 427: /* network-type */
8413
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkType);
8414
0
            break;
8415
46
        case 428: /* routing-table */
8416
46
            offset = fRouterEntry(tvb, pinfo, tree, offset);
8417
46
            break;
8418
24
        case 429: /* virtual-mac-address-table */
8419
24
            offset = fVMACEntry(tvb, pinfo, tree, offset);
8420
24
            break;
8421
25
        case 430: /* command-time-array */
8422
25
            if (propertyArrayIndex == 0) {
8423
                /* BACnetARRAY index 0 refers to the length
8424
                of the array, not the elements of the array */
8425
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8426
25
            } else {
8427
25
                offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8428
25
            }
8429
25
            break;
8430
0
        case 432: /* last-command-time */
8431
0
            offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8432
0
            break;
8433
605
        case 433: /* value-source */
8434
605
            offset = fValueSource(tvb, pinfo, tree, offset);
8435
605
            break;
8436
0
        case 434: /* value-source-array */
8437
0
            if (propertyArrayIndex == 0) {
8438
                /* BACnetARRAY index 0 refers to the length
8439
                of the array, not the elements of the array */
8440
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8441
0
            } else {
8442
0
                offset = fValueSource(tvb, pinfo, tree, offset);
8443
0
            }
8444
0
            break;
8445
2.71k
        case 447: /* assigned-landing-calls */
8446
2.71k
            offset = fAssignedLandingCalls(tvb, pinfo, tree, offset);
8447
2.71k
            break;
8448
69
        case 448: /* car-assigned-direction */
8449
69
        case 457: /* car-moving-direction */
8450
69
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDirection);
8451
69
            break;
8452
6
        case 449: /* car-door-command */
8453
6
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDoorCommand);
8454
6
            break;
8455
1
        case 453: /* car-drive-status */
8456
1
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDriveStatus);
8457
1
            break;
8458
0
        case 456: /* car-mode */
8459
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarMode);
8460
0
            break;
8461
41
        case 462: /* escalator-mode */
8462
41
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorMode);
8463
41
            break;
8464
0
        case 463: /* fault-signals */
8465
0
            if (propertyArrayIndex == 0) {
8466
                /* BACnetARRAY index 0 refers to the length
8467
                of the array, not the elements of the array */
8468
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8469
0
            } else {
8470
0
                if (object_type == 59) /* lift object */
8471
0
                    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftFault);
8472
0
                else
8473
0
                    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorFault);
8474
0
            }
8475
0
            break;
8476
1
        case 467: /* group-mode */
8477
1
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftGroupMode);
8478
1
            break;
8479
50
        case 470: /* landing-calls */
8480
50
            if (propertyArrayIndex == 0) {
8481
                /* BACnetARRAY index 0 refers to the length
8482
                of the array, not the elements of the array */
8483
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8484
50
            } else {
8485
50
                offset = fLandingCallStatus(tvb, pinfo, tree, offset);
8486
50
            }
8487
50
            break;
8488
128
        case 471: /* landing-call-control */
8489
128
            offset = fLandingCallStatus(tvb, pinfo, tree, offset);
8490
128
            break;
8491
677
        case 472: /* landing-door-status */
8492
677
            if (propertyArrayIndex == 0) {
8493
                /* BACnetARRAY index 0 refers to the length
8494
                of the array, not the elements of the array */
8495
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8496
677
            } else {
8497
677
                offset = fLandingDoorStatus(tvb, pinfo, tree, offset);
8498
677
            }
8499
677
            break;
8500
19
        case 477: /* "operation-direction */
8501
19
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorOperationDirection);
8502
19
            break;
8503
444
        case 481: /* active-cov-multiple-subscriptions */
8504
444
            if (propertyArrayIndex == 0) {
8505
                /* BACnetARRAY index 0 refers to the length
8506
                of the array, not the elements of the array */
8507
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8508
444
            } else {
8509
444
                offset = fCOVMultipleSubscription(tvb, pinfo, tree, offset);
8510
444
            }
8511
444
            break;
8512
258
        case 482: /* protocol-level */
8513
258
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProtocolLevel);
8514
258
            break;
8515
3
        case 486: /* tags */
8516
3
            if (propertyArrayIndex == 0) {
8517
                /* BACnetARRAY index 0 refers to the length
8518
                of the array, not the elements of the array */
8519
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8520
3
            } else {
8521
3
                offset = fNameValue(tvb, pinfo, tree, offset);
8522
3
            }
8523
3
            break;
8524
6
        case 487: /* subordinate-node-types */
8525
6
            if (propertyArrayIndex == 0) {
8526
                /* BACnetARRAY index 0 refers to the length
8527
                of the array, not the elements of the array */
8528
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8529
6
            } else {
8530
6
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
8531
6
            }
8532
6
            break;
8533
1.84k
        case 488: /* subordinate-tags */
8534
1.84k
            if (propertyArrayIndex == 0) {
8535
                /* BACnetARRAY index 0 refers to the length
8536
                of the array, not the elements of the array */
8537
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8538
1.84k
            } else {
8539
1.84k
                offset = fNameValueCollection(tvb, pinfo, tree, offset);
8540
1.84k
            }
8541
1.84k
            break;
8542
157
        case 489: /* subordinate-relationship */
8543
157
            if (propertyArrayIndex == 0) {
8544
                /* BACnetARRAY index 0 refers to the length
8545
                of the array, not the elements of the array */
8546
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8547
157
            } else {
8548
157
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetRelationship);
8549
157
            }
8550
157
            break;
8551
0
        case 490: /* default-subordinate-relationship */
8552
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetRelationship);
8553
0
            break;
8554
3
        case 494: /* stages */
8555
3
            if (propertyArrayIndex == 0) {
8556
                /* BACnetARRAY index 0 refers to the length
8557
                of the array, not the elements of the array */
8558
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8559
3
            } else {
8560
3
                offset = fStageLimitValue(tvb, pinfo, tree, offset);
8561
3
            }
8562
3
            break;
8563
5
        case 498: /* audit-level */
8564
5
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditLevel);
8565
5
            break;
8566
1
        case 500: /* audit-priority-filter */
8567
1
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditPriorityFilter);
8568
1
            break;
8569
0
        case 501: /* auditable-operations */
8570
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditOperation);
8571
0
            break;
8572
0
        case 504: /* monitored-objects */
8573
0
            if (propertyArrayIndex == 0) {
8574
                /* BACnetARRAY index 0 refers to the length
8575
                of the array, not the elements of the array */
8576
0
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8577
0
            } else {
8578
0
                offset = fObjectSelector(tvb, pinfo, tree, offset);
8579
0
            }
8580
0
            break;
8581
74
        case 510:     /* command-validation-result */
8582
75
        case 4194307: /* current-health */
8583
75
            offset = fHealth(tvb, pinfo, tree, offset);
8584
75
            break;
8585
52
        case 4194312: /* sc-direct-connect-connection-status */
8586
52
            offset = fSCDirectConnection(tvb, pinfo, tree, offset);
8587
52
            break;
8588
0
        case 4194315: /* sc-failed-connection-requests */
8589
0
            offset = fSCFailedConnectionRequest(tvb, pinfo, tree, offset);
8590
0
            break;
8591
1
        case 4194316: /* sc-failover-hub-connection-status */
8592
1
        case 4194324: /* sc-primary-hub-connection-status */
8593
1
            offset = fSCHubConnection(tvb, pinfo, tree, offset);
8594
1
            break;
8595
0
        case 4194318: /* sc_hub_connector_state */
8596
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSCHubConnectorState);
8597
0
            break;
8598
47
        case 4194321: /* sc-hub-function-connection-status */
8599
47
            offset = fSCHubFunctionConnection(tvb, pinfo, tree, offset);
8600
47
            break;
8601
0
        case 4194330: /* default-color */
8602
0
            offset = fXyColor(tvb, pinfo, tree, offset, ar);
8603
0
            break;
8604
0
        case 4194334: /* color-command */
8605
0
            offset = fColorCommand(tvb, pinfo, tree, offset, ar);
8606
0
            break;
8607
0
        case 4194339: /* device-address-proxy-table */
8608
0
            offset = fDeviceAddressProxyTableEntry(tvb, pinfo, tree, offset, ar);
8609
0
            break;
8610
1
        case 4194343: /* authorization-cache */
8611
1
            offset = fAccessToken(tvb, pinfo, tree, offset, ar);
8612
1
            break;
8613
1
        case 4194345: /* authorization-policy */
8614
1
            offset = fAuthorizationPolicy(tvb, pinfo, tree, offset, ar);
8615
1
            break;
8616
0
        case 4194346: /* authorization-scope */
8617
0
            offset = fAuthorizationScopeDescription(tvb, pinfo, tree, offset, ar);
8618
0
            break;
8619
0
        case 4194347: /* authorization-server */
8620
0
            offset = fAuthorizationServer(tvb, pinfo, tree, offset, ar);
8621
0
            break;
8622
173
        case 4194348: /* authorization-status */
8623
173
            offset = fAuthorizationStatus(tvb, pinfo, tree, offset, ar);
8624
173
            break;
8625
8626
32.1k
        case 85:  /* present-value */
8627
32.1k
            if ( object_type == 11 )    /* group object handling of present-value */
8628
801
            {
8629
801
                offset = fReadAccessResult(tvb, pinfo, tree, offset);
8630
801
            }
8631
31.3k
            else if (object_type == 30)  /* access-door object */
8632
308
            {
8633
308
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetDoorValue, 0, BACAPP_PRESENT_VALUE_ENUM);
8634
308
            }
8635
31.0k
            else if (object_type == 21)  /* life-point */
8636
533
            {
8637
533
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetLifeSafetyState, 0, BACAPP_PRESENT_VALUE_ENUM);
8638
533
            }
8639
30.5k
            else if (object_type == 22)  /* life-zone */
8640
768
            {
8641
768
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetLifeSafetyState, 0, BACAPP_PRESENT_VALUE_ENUM);
8642
768
            }
8643
29.7k
            else if (object_type == 53) /* channel object */
8644
342
            {
8645
342
                offset = fChannelValue(tvb, pinfo, tree, offset, ar);
8646
342
            }
8647
29.4k
            else if (object_type == 37) /* credential-data-input */
8648
9
            {
8649
9
                offset = fAuthenticationFactor(tvb, pinfo, tree, offset);
8650
9
            }
8651
29.4k
            else if (object_type == 26) /* global-group */
8652
633
            {
8653
633
                offset = fPropertyAccessResult(tvb, pinfo, tree, offset);
8654
633
            }
8655
28.7k
            else if (object_type == 28) /* loac-control */
8656
788
            {
8657
788
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetShedState, 0, BACAPP_PRESENT_VALUE_ENUM);
8658
788
            }
8659
28.0k
            else if (object_type == 43) /* date-time-pattern-value */
8660
508
            {
8661
508
                offset = fDateTime(tvb, pinfo, tree, offset, ar);
8662
508
            }
8663
27.4k
            else if (object_type == 44) /* date-time-value */
8664
563
            {
8665
563
                offset = fDateTime(tvb, pinfo, tree, offset, ar);
8666
563
            }
8667
26.9k
            else if (object_type == 63) /* color */
8668
82
            {
8669
82
                offset = fXyColor(tvb, pinfo, tree, offset, ar);
8670
82
            }
8671
26.8k
            else
8672
26.8k
            {
8673
26.8k
                if (!tag_info) {
8674
19.9k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8675
                    // application tag number above 12 reserved for ASHRAE
8676
19.9k
                    if (!tag_is_context_specific(tag_info) && tag_no <= 12) {
8677
19.7k
                        offset = fPresentValue(tvb, pinfo, tree, offset, NULL, 0, (BacappPresentValueType) tag_no);
8678
19.7k
                    }
8679
19.9k
                } else {
8680
6.90k
                    do_default_handling = true;
8681
6.90k
                }
8682
26.8k
            }
8683
32.1k
            break;
8684
10.0k
        default:
8685
10.0k
            do_default_handling = true;
8686
10.0k
            break;
8687
111k
        }
8688
110k
        if (do_default_handling) {
8689
16.9k
            if (tag_info) {
8690
9.39k
                if (tag_is_opening(tag_info)) {
8691
3.30k
                    ++depth;
8692
3.30k
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8693
6.08k
                } else if (tag_is_closing(tag_info)) {
8694
614
                    --depth;
8695
614
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8696
5.47k
                } else {
8697
5.47k
                    offset  = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
8698
5.47k
                }
8699
9.39k
            } else {
8700
7.51k
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8701
7.51k
            }
8702
16.9k
        }
8703
110k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8704
110k
    }
8705
8706
7.15k
cleanup:
8707
7.15k
    decrement_dissection_depth(pinfo);
8708
7.15k
    return offset;
8709
8.78k
}
8710
8711
static unsigned
8712
// NOLINTNEXTLINE(misc-no-recursion)
8713
fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_info)
8714
3.33k
{
8715
3.33k
    uint8_t tag_no;
8716
3.33k
    uint32_t lvt;
8717
8718
3.33k
    if (tag_is_opening(tag_info)) {
8719
3.22k
        offset += fTagHeaderTree(tvb, pinfo, tree, offset,
8720
3.22k
                                 &tag_no, &tag_info, &lvt);
8721
3.22k
        offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8722
3.22k
        if (tvb_reported_length_remaining(tvb, offset) > 0) {
8723
2.24k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset,
8724
2.24k
                                     &tag_no, &tag_info, &lvt);
8725
2.24k
        }
8726
3.22k
    } else {
8727
110
        proto_tree_add_expert_remaining(tree, pinfo, &ei_bacapp_opening_tag, tvb, offset);
8728
110
        offset = tvb_reported_length(tvb);
8729
110
    }
8730
8731
3.33k
    return offset;
8732
3.33k
}
8733
8734
8735
static unsigned
8736
// NOLINTNEXTLINE(misc-no-recursion)
8737
fPropertyIdentifierValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset)
8738
5.31k
{
8739
5.31k
    unsigned   lastoffset = offset;
8740
5.31k
    uint8_t tag_no, tag_info;
8741
5.31k
    uint32_t lvt;
8742
8743
5.31k
    offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
8744
5.31k
    if (offset > lastoffset) {
8745
2.18k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8746
2.18k
        if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
8747
665
            offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
8748
665
        }
8749
2.18k
    }
8750
5.31k
    return offset;
8751
5.31k
}
8752
8753
static unsigned
8754
// NOLINTNEXTLINE(misc-no-recursion)
8755
fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8756
3.21k
{
8757
3.21k
    unsigned   lastoffset = 0;
8758
3.21k
    uint8_t tag_no, tag_info;
8759
3.21k
    uint32_t lvt;
8760
8761
5.04k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8762
4.83k
        lastoffset = offset;
8763
4.83k
        offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
8764
4.83k
        if (offset > lastoffset) {
8765
            /* detect optional priority
8766
            by looking to see if the next tag is context tag number 3 */
8767
1.68k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8768
1.68k
            if (tag_is_context_specific(tag_info) && (tag_no == 3))
8769
16
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
8770
1.68k
        }
8771
4.83k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8772
4.83k
    }
8773
3.21k
    return offset;
8774
3.21k
}
8775
8776
static unsigned
8777
fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8778
103
{
8779
103
    unsigned    lastoffset = 0, len;
8780
103
    uint8_t     tag_no, tag_info;
8781
103
    uint32_t    lvt;
8782
103
    proto_tree *subtree = tree;
8783
8784
3.88k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8785
3.86k
        lastoffset = offset;
8786
3.86k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8787
3.86k
        if (tag_is_closing(tag_info)) {
8788
777
            offset += len;
8789
777
            subtree = tree;
8790
777
            continue;
8791
777
        }
8792
8793
3.08k
        switch (tag_no) {
8794
1.68k
        case 0: /* ProcessId */
8795
1.68k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
8796
1.68k
            break;
8797
177
        case 1: /* monitored ObjectId */
8798
177
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
8799
177
            break;
8800
403
        case 2: /* issueConfirmedNotifications */
8801
403
            offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
8802
403
            break;
8803
414
        case 3: /* life time */
8804
414
            offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
8805
414
            break;
8806
165
        case 4: /* monitoredPropertyIdentifier */
8807
165
            if (tag_is_opening(tag_info)) {
8808
145
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "monitoredPropertyIdentifier");
8809
145
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8810
145
                offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
8811
145
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8812
145
            } else {
8813
20
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
8814
20
            }
8815
165
            break;
8816
198
        case 5: /* covIncrement */
8817
198
            offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
8818
198
            break;
8819
48
        default:
8820
48
            return offset;
8821
3.08k
        }
8822
3.02k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8823
3.02k
    }
8824
37
    return offset;
8825
103
}
8826
8827
static unsigned
8828
fSubscribeCOVPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8829
118
{
8830
118
    unsigned    lastoffset = 0, len;
8831
118
    uint8_t     tag_no, tag_info;
8832
118
    uint32_t    lvt;
8833
118
    proto_tree *subtree = tree;
8834
118
    proto_tree *subsubtree = tree;
8835
8836
4.98k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8837
4.95k
        lastoffset = offset;
8838
4.95k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8839
4.95k
        if (tag_is_closing(tag_info)) {
8840
1.43k
            offset += len;
8841
1.43k
            subtree = tree;
8842
1.43k
            continue;
8843
1.43k
        }
8844
8845
3.51k
        switch (tag_no) {
8846
1.46k
        case 0: /* ProcessId */
8847
1.46k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
8848
1.46k
            break;
8849
1.13k
        case 1: /* issueConfirmedNotifications */
8850
1.13k
            offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
8851
1.13k
            break;
8852
414
        case 2: /* life time */
8853
414
            offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
8854
414
            break;
8855
381
        case 3: /* notification delay */
8856
381
            offset = fTimeSpan(tvb, pinfo, tree, offset, "notification delay");
8857
381
            break;
8858
63
        case 4: /* list-of-cov-subscription-specifications */
8859
63
            if (tag_is_opening(tag_info)) {
8860
58
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-subscription-specifications: ");
8861
58
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8862
8863
239
                while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8864
239
                    lastoffset = offset;
8865
239
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8866
239
                    if (tag_is_closing(tag_info)) {
8867
41
                        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8868
41
                        offset += len;
8869
41
                        subtree = tree;
8870
41
                        break;
8871
41
                    }
8872
8873
198
                    switch (tag_no) {
8874
143
                    case 0: /* monitored-object-identifier */
8875
143
                        offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
8876
143
                        break;
8877
49
                    case 1: /* list-of-cov-references */
8878
49
                      if (tag_is_opening(tag_info)) {
8879
47
                          subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-references: ");
8880
47
                          offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8881
8882
177
                          while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8883
177
                              lastoffset = offset;
8884
177
                              len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8885
177
                              if (tag_is_closing(tag_info)) {
8886
40
                                  fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8887
40
                                  offset += len;
8888
40
                                  break;
8889
40
                              }
8890
8891
137
                              switch (tag_no) {
8892
66
                              case 0: /* monitored-property */
8893
66
                                  if (tag_is_opening(tag_info)) {
8894
64
                                      offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8895
64
                                      offset = fBACnetPropertyReference(tvb, pinfo, subsubtree, offset, 1);
8896
64
                                      offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8897
64
                                  }
8898
2
                                  else {
8899
2
                                      expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
8900
2
                                  }
8901
66
                                  break;
8902
56
                              case 1: /* cov-increment */
8903
56
                                  offset = fRealTag(tvb, pinfo, subsubtree, offset, "COV Increment: ");
8904
56
                                  break;
8905
10
                              case 2: /* timestamped */
8906
10
                                  offset = fBooleanTag(tvb, pinfo, subsubtree, offset, "timestamped: ");
8907
10
                                  break;
8908
5
                              default:
8909
5
                                  return offset;
8910
137
                            }
8911
132
                            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8912
132
                        }
8913
47
                      }
8914
2
                      else {
8915
2
                          expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
8916
2
                      }
8917
44
                      break;
8918
44
                    default:
8919
6
                      return offset;
8920
198
                    }
8921
185
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8922
185
                }
8923
58
            }
8924
5
            else {
8925
5
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
8926
5
            }
8927
50
            break;
8928
57
        default:
8929
57
            return offset;
8930
3.51k
        }
8931
3.44k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8932
3.44k
    }
8933
46
    return offset;
8934
118
}
8935
8936
static unsigned
8937
fSubscribeCOVPropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8938
113
{
8939
113
    unsigned    lastoffset = 0, len;
8940
113
    uint8_t     tag_no, tag_info;
8941
113
    uint32_t    lvt;
8942
8943
567
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8944
556
        lastoffset = offset;
8945
556
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8946
556
        if (tag_is_closing(tag_info)) {
8947
9
            len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8948
9
            offset += len;
8949
9
            break;
8950
9
        }
8951
8952
547
        switch (tag_no) {
8953
424
        case 0: /* normal error */
8954
424
            if (tag_is_opening(tag_info)) {
8955
3
                offset = fContextTaggedError(tvb, pinfo, tree, offset);
8956
3
            }
8957
421
            else {
8958
421
                offset = fError(tvb, pinfo, tree, offset);
8959
421
            }
8960
424
            break;
8961
98
        case 1: /* first-failed-subscription */
8962
98
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8963
8964
587
            while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8965
582
                lastoffset = offset;
8966
582
                len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8967
582
                if (tag_is_closing(tag_info)) {
8968
28
                    fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8969
28
                    offset += len;
8970
28
                    break;
8971
28
                }
8972
8973
554
                switch (tag_no) {
8974
165
                case 0: /* monitored-object-identifier */
8975
165
                    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
8976
165
                    break;
8977
241
                case 1: /* monitored-property-reference */
8978
241
                    if (tag_is_opening(tag_info)) {
8979
221
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8980
221
                        offset = fBACnetPropertyReference(tvb, pinfo, tree, offset, 1);
8981
221
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8982
221
                    }
8983
20
                    else {
8984
20
                        expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
8985
20
                    }
8986
241
                    break;
8987
106
                case 2: /* error-type */
8988
106
                    offset = fContextTaggedError(tvb, pinfo, tree, offset);
8989
106
                    break;
8990
40
                default:
8991
40
                    return offset;
8992
554
                }
8993
509
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8994
509
            }
8995
53
            break;
8996
53
        default:
8997
25
            return offset;
8998
547
        }
8999
474
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9000
474
    }
9001
40
    return offset;
9002
113
}
9003
9004
static unsigned
9005
fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9006
67
{
9007
67
    return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
9008
67
}
9009
9010
static unsigned
9011
fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9012
59
{
9013
59
    unsigned lastoffset = 0;
9014
9015
1.50k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9016
1.48k
        lastoffset = offset;
9017
9018
1.48k
        switch (fTagNo(tvb, offset)) {
9019
1.05k
        case 0: /* deviceInstanceLowLimit */
9020
1.05k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
9021
1.05k
            break;
9022
184
        case 1: /* deviceInstanceHighLimit */
9023
184
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
9024
184
            break;
9025
103
        case 2: /* BACnetObjectId */
9026
103
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
9027
103
            break;
9028
101
        case 3: /* ObjectName */
9029
101
            offset = fObjectName(tvb, pinfo, tree, offset);
9030
101
            break;
9031
41
        default:
9032
41
            return offset;
9033
1.48k
        }
9034
1.44k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9035
1.44k
    }
9036
12
    return offset;
9037
59
}
9038
9039
9040
static unsigned
9041
fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
9042
269
{
9043
269
    unsigned   lastoffset = 0;
9044
269
    uint8_t tag_no, tag_info;
9045
269
    uint32_t lvt;
9046
9047
269
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9048
269
    if (tag_is_opening(tag_info) && tag_no == 0) {
9049
0
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
9050
0
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9051
0
            lastoffset = offset;
9052
0
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9053
0
            if (tag_is_closing(tag_info)) {
9054
                /* should be closing context tag 0 */
9055
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9056
0
                return offset;
9057
0
            }
9058
9059
0
            offset = fTimeValue(tvb, pinfo, subtree, offset);
9060
0
            if (offset <= lastoffset) break;    /* nothing happened, exit loop */
9061
0
        }
9062
269
    } else if ((tag_no == 0) && (lvt == 0)) {
9063
        /* not sure null (empty array element) is legal */
9064
222
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9065
222
    }
9066
269
    return offset;
9067
269
}
9068
9069
/**
9070
 * BACnetHealth ::= SEQUENCE {
9071
 *  timestamp                   [0] BACnetDateTime,
9072
 *  result                      [1] Error,
9073
 *  property                    [2] BACnetPropertyIdentifier OPTIONAL,
9074
 *  details                     [3] CharacterString OPTIONAL
9075
 * }
9076
 * @param tvb the tv buffer of the current data
9077
 * @param pinfo the packet info of the current data
9078
 * @param tree the tree to append this item to
9079
 * @param offset the offset in the tvb
9080
 * @return modified offset
9081
 */
9082
static unsigned
9083
fHealth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9084
75
{
9085
75
    unsigned   lastoffset = 0;
9086
75
    uint8_t tag_no, tag_info;
9087
75
    uint32_t lvt;
9088
9089
541
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9090
540
        lastoffset = offset;
9091
        /* check the tag.  A closing tag means we are done */
9092
540
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9093
540
        if (tag_is_closing(tag_info)) {
9094
10
            return offset;
9095
10
        }
9096
530
        switch (tag_no) {
9097
287
        case 0: /* timestamp */
9098
287
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9099
287
            offset = fDateTime(tvb, pinfo, tree, offset, "timestamp: ");
9100
287
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9101
287
            break;
9102
120
        case 1: /* result */
9103
120
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9104
120
            offset = fError(tvb, pinfo, tree, offset);
9105
120
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9106
120
            break;
9107
43
        case 2: /* property - OPTIONAL*/
9108
43
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9109
43
            break;
9110
24
        case 3: /* details - OPTIONAL */
9111
24
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9112
24
            break;
9113
56
        default:
9114
56
            return offset;
9115
530
        }
9116
471
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9117
471
    }
9118
6
    return offset;
9119
75
}
9120
9121
/**
9122
 * BACnetSCDirectConnection ::= SEQUENCE {
9123
 *  uri                         [0] CharacterString
9124
 *  connection-state            [1] BACnetSCConnectionState,
9125
 *  connect-timestamp           [2] BACnetDateTime,
9126
 *  disconnect-timestamp        [3] BACnetDateTime,
9127
 *  peer-address                [4] BACnetHostNPort,
9128
 *  peer-vmac                   [5] OCTET STRING (SIZE(6))
9129
 *  peer-uuid                   [6] OCTET STRING (SIZE(16))
9130
 *  error                       [7] Error OPTIONAL
9131
 *  error-details               [8] CharacterString OPTIONAL
9132
 * }
9133
 * @param tvb the tv buffer of the current data
9134
 * @param pinfo the packet info of the current data
9135
 * @param tree the tree to append this item to
9136
 * @param offset the offset in the tvb
9137
 * @return modified offset
9138
 */
9139
static unsigned
9140
fSCDirectConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9141
52
{
9142
52
    unsigned   lastoffset = 0;
9143
52
    uint8_t tag_no, tag_info;
9144
52
    uint32_t lvt;
9145
9146
678
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9147
675
        lastoffset = offset;
9148
        /* check the tag.  A closing tag means we are done */
9149
675
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9150
675
        if (tag_is_closing(tag_info)) {
9151
2
            return offset;
9152
2
        }
9153
673
        switch (tag_no) {
9154
72
        case 0: /* uri */
9155
72
            offset = fCharacterString(tvb, pinfo, tree, offset, "uri: ");
9156
72
            break;
9157
8
        case 1: /* connection-state */
9158
8
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
9159
8
            break;
9160
31
        case 2: /* connect-timestamp */
9161
31
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9162
31
            offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
9163
31
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9164
31
            break;
9165
76
        case 3: /* disconnect-timestamp */
9166
76
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9167
76
            offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
9168
76
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9169
76
            break;
9170
71
        case 4: /* peer-address */
9171
71
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9172
71
            offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
9173
71
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9174
71
            break;
9175
38
        case 5: /* peer-vmac */
9176
38
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
9177
38
            break;
9178
141
        case 6: /* peer-uuid */
9179
141
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
9180
141
            break;
9181
143
        case 7: /* error */
9182
143
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9183
143
            offset = fError(tvb, pinfo, tree, offset);
9184
143
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9185
143
            break;
9186
71
        case 8: /* details - OPTIONAL */
9187
71
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9188
71
            break;
9189
22
        default:
9190
22
            return offset;
9191
673
        }
9192
626
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9193
626
    }
9194
3
    return offset;
9195
52
}
9196
9197
/**
9198
 * BACnetSCFailedConnectionRequest ::= SEQUENCE {
9199
 *  timestamp                   [0] BACnetDateTime,
9200
 *  peer-address                [1] BACnetHostNPort,
9201
 *  peer-vmac                   [2] OCTET STRING (SIZE(6))
9202
 *  peer-uuid                   [3] OCTET STRING (SIZE(16))
9203
 *  error                       [4] Error OPTIONAL
9204
 *  error-details               [5] CharacterString OPTIONAL
9205
 * }
9206
 * @param tvb the tv buffer of the current data
9207
 * @param pinfo the packet info of the current data
9208
 * @param tree the tree to append this item to
9209
 * @param offset the offset in the tvb
9210
 * @return modified offset
9211
 */
9212
static unsigned
9213
fSCFailedConnectionRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9214
0
{
9215
0
    unsigned   lastoffset = 0;
9216
0
    uint8_t tag_no, tag_info;
9217
0
    uint32_t lvt;
9218
9219
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9220
0
        lastoffset = offset;
9221
        /* check the tag.  A closing tag means we are done */
9222
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9223
0
        if (tag_is_closing(tag_info)) {
9224
0
            return offset;
9225
0
        }
9226
0
        switch (tag_no) {
9227
0
        case 0: /* timestamp */
9228
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9229
0
            offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
9230
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9231
0
            break;
9232
0
        case 1: /* peer-address */
9233
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9234
0
            offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
9235
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9236
0
            break;
9237
0
        case 2: /* peer-vmac */
9238
0
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
9239
0
            break;
9240
0
        case 3: /* peer-uuid */
9241
0
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
9242
0
            break;
9243
0
        case 4: /* error */
9244
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9245
0
            offset = fError(tvb, pinfo, tree, offset);
9246
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9247
0
            break;
9248
0
        case 5: /* details - OPTIONAL */
9249
0
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9250
0
            break;
9251
0
        default:
9252
0
            return offset;
9253
0
        }
9254
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9255
0
    }
9256
0
    return offset;
9257
0
}
9258
9259
/**
9260
 * BACnetSCHubConnection ::= SEQUENCE {
9261
 *  connection-state            [0] BACnetSCConnectionState,
9262
 *  connect-timestamp           [1] BACnetDateTime,
9263
 *  disconnect-timestamp        [2] BACnetDateTime,
9264
 *  error                       [3] Error OPTIONAL
9265
 *  error-details               [4] CharacterString OPTIONAL
9266
 * }
9267
 * @param tvb the tv buffer of the current data
9268
 * @param pinfo the packet info of the current data
9269
 * @param tree the tree to append this item to
9270
 * @param offset the offset in the tvb
9271
 * @return modified offset
9272
 */
9273
static unsigned
9274
fSCHubConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9275
1
{
9276
1
    unsigned   lastoffset = 0;
9277
1
    uint8_t tag_no, tag_info;
9278
1
    uint32_t lvt;
9279
9280
1
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9281
1
        lastoffset = offset;
9282
        /* check the tag.  A closing tag means we are done */
9283
1
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9284
1
        if (tag_is_closing(tag_info)) {
9285
0
            return offset;
9286
0
        }
9287
1
        switch (tag_no) {
9288
0
        case 0: /* connection-state */
9289
0
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
9290
0
            break;
9291
0
        case 1: /* connect-timestamp */
9292
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9293
0
            offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
9294
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9295
0
            break;
9296
0
        case 2: /* disconnect-timestamp */
9297
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9298
0
            offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
9299
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9300
0
            break;
9301
0
        case 3: /* error */
9302
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9303
0
            offset = fError(tvb, pinfo, tree, offset);
9304
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9305
0
            break;
9306
0
        case 4: /* details - OPTIONAL */
9307
0
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9308
0
            break;
9309
1
        default:
9310
1
            return offset;
9311
1
        }
9312
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9313
0
    }
9314
0
    return offset;
9315
1
}
9316
9317
/**
9318
 * BACnetSCHubFunctionConnection ::= SEQUENCE {
9319
 *  connection-state            [0] BACnetSCConnectionState,
9320
 *  connect-timestamp           [1] BACnetDateTime,
9321
 *  disconnect-timestamp        [2] BACnetDateTime,
9322
 *  peer-address                [3] BACnetHostNPort,
9323
 *  peer-vmac                   [4] OCTET STRING (SIZE(6))
9324
 *  peer-uuid                   [5] OCTET STRING (SIZE(16))
9325
 *  error                       [6] Error OPTIONAL
9326
 *  error-details               [7] CharacterString OPTIONAL
9327
 * }
9328
 * @param tvb the tv buffer of the current data
9329
 * @param pinfo the packet info of the current data
9330
 * @param tree the tree to append this item to
9331
 * @param offset the offset in the tvb
9332
 * @return modified offset
9333
 */
9334
static unsigned
9335
fSCHubFunctionConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9336
47
{
9337
47
    unsigned   lastoffset = 0;
9338
47
    uint8_t tag_no, tag_info;
9339
47
    uint32_t lvt;
9340
9341
806
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9342
805
        lastoffset = offset;
9343
        /* check the tag.  A closing tag means we are done */
9344
805
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9345
805
        if (tag_is_closing(tag_info)) {
9346
6
            return offset;
9347
6
        }
9348
799
        switch (tag_no) {
9349
266
        case 0: /* connection-state */
9350
266
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
9351
266
            break;
9352
10
        case 1: /* connect-timestamp */
9353
10
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9354
10
            offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
9355
10
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9356
10
            break;
9357
28
        case 2: /* disconnect-timestamp */
9358
28
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9359
28
            offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
9360
28
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9361
28
            break;
9362
62
        case 3: /* peer-address */
9363
62
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9364
62
            offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
9365
62
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9366
62
            break;
9367
38
        case 4: /* peer-vmac */
9368
38
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
9369
38
            break;
9370
125
        case 5: /* peer-uuid */
9371
125
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
9372
125
            break;
9373
102
        case 6: /* error */
9374
102
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9375
102
            offset = fError(tvb, pinfo, tree, offset);
9376
102
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9377
102
            break;
9378
135
        case 7: /* details - OPTIONAL */
9379
135
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9380
135
            break;
9381
33
        default:
9382
33
            return offset;
9383
799
        }
9384
759
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9385
759
    }
9386
1
    return offset;
9387
47
}
9388
9389
static unsigned
9390
fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9391
49
{
9392
49
    unsigned    lastoffset = 0;
9393
49
    uint8_t     tag_no, tag_info;
9394
49
    uint32_t    lvt;
9395
49
    unsigned    i = 1; /* day of week array index */
9396
49
    proto_tree *subtree = tree;
9397
9398
49
    if (propertyArrayIndex > 0) {
9399
        /* BACnetARRAY index 0 refers to the length
9400
        of the array, not the elements of the array.
9401
        BACnetARRAY index -1 is our internal flag that
9402
        the optional index was not used.
9403
        BACnetARRAY refers to this as all elements of the array.
9404
        If the optional index is specified for a BACnetARRAY,
9405
        then that specific array element is referenced. */
9406
10
        i = propertyArrayIndex;
9407
10
    }
9408
271
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9409
271
        lastoffset = offset;
9410
271
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9411
271
        if (tag_is_closing(tag_info)) {
9412
2
            return offset; /* outer encoding will print out closing tag */
9413
2
        }
9414
269
        subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bacapp_value, NULL,
9415
269
                                val_to_str(pinfo->pool, i++, day_of_week, "day of week (%d) not found"));
9416
269
        offset = fDailySchedule(tvb, pinfo, subtree, offset);
9417
269
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9418
269
    }
9419
47
    return offset;
9420
49
}
9421
9422
9423
static unsigned
9424
fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9425
4
{
9426
4
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
9427
0
        return offset;
9428
9429
4
    return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
9430
4
}
9431
9432
static unsigned
9433
fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9434
9
{
9435
9
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
9436
0
        return offset;
9437
9438
9
    return fDateTime(tvb, pinfo, tree, offset, NULL);
9439
9
}
9440
9441
static unsigned
9442
fWriteGroupRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9443
260
{
9444
260
    unsigned    lastoffset = 0, len;
9445
260
    uint8_t     tag_no, tag_info;
9446
260
    uint32_t    lvt;
9447
260
    proto_tree *subtree = tree;
9448
9449
5.52k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9450
5.44k
        lastoffset = offset;
9451
5.44k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9452
5.44k
        if (tag_is_closing(tag_info)) {
9453
1.28k
            offset += len;
9454
1.28k
            subtree = tree;
9455
1.28k
            continue;
9456
1.28k
        }
9457
9458
4.15k
        switch (tag_no) {
9459
2.06k
        case 0: /* group-number */
9460
2.06k
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Group number: ");
9461
2.06k
            break;
9462
263
        case 1: /* write-priority */
9463
263
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9464
263
            break;
9465
296
        case 2: /* change-list */
9466
296
            if (tag_is_opening(tag_info)) {
9467
283
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "change-list: ");
9468
283
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9469
9470
11.9k
                while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9471
11.9k
                    lastoffset = offset;
9472
11.9k
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9473
11.9k
                    if (tag_is_closing(tag_info)) {
9474
129
                        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9475
129
                        offset += len;
9476
129
                        subtree = tree;
9477
129
                        break;
9478
129
                    }
9479
9480
11.7k
                    switch (tag_no) {
9481
5.07k
                    case 0: /* channel */
9482
5.07k
                        if (tag_info && ! tag_is_opening(tag_info)) {
9483
                            /* context tagged */
9484
602
                            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Channel: ");
9485
4.46k
                        } else {
9486
                            /* application tagged */
9487
4.46k
                            offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
9488
4.46k
                        }
9489
5.07k
                        break;
9490
1.95k
                    case 1: /* overriding-priority */
9491
1.95k
                        if (tag_info && ! tag_is_opening(tag_info)) {
9492
                            /* context tagged */
9493
325
                            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Overriding priority: ");
9494
1.63k
                        } else {
9495
                            /* application tagged */
9496
1.63k
                            offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
9497
1.63k
                        }
9498
1.95k
                        break;
9499
4.75k
                    default: /* channel-value (application tagged, or opening/closing context-0 tagged) */
9500
4.75k
                        offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
9501
4.75k
                        break;
9502
11.7k
                    }
9503
11.7k
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9504
11.7k
                }
9505
283
            }
9506
13
            else {
9507
13
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9508
13
            }
9509
213
            break;
9510
1.46k
        case 3: /* inhibit-delay */
9511
1.46k
            offset = fBooleanTag(tvb, pinfo, tree, offset, "Inhibit delay: ");
9512
1.46k
            break;
9513
68
        default:
9514
68
            return offset;
9515
4.15k
        }
9516
4.00k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9517
4.00k
    }
9518
101
    return offset;
9519
260
}
9520
9521
static unsigned
9522
fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9523
186
{
9524
186
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
9525
0
        return offset;
9526
186
    offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
9527
186
    return fDate(tvb, pinfo, tree, offset, "End Date: ");
9528
186
}
9529
9530
static unsigned
9531
fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9532
4.62k
{
9533
4.62k
    uint32_t     val   = 0;
9534
4.62k
    uint8_t      tag_no, tag_info;
9535
4.62k
    uint32_t     lvt;
9536
4.62k
    unsigned     tag_len;
9537
4.62k
    proto_item  *ti;
9538
4.62k
    proto_tree  *subtree;
9539
4.62k
    static const char *label = "Vendor ID";
9540
9541
4.62k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9542
4.62k
    if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
9543
1.61k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9544
1.61k
            ett_bacapp_tag, &ti, "%s: %s (%u)",
9545
1.61k
            label,
9546
1.61k
            val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
9547
1.61k
            val);
9548
3.01k
    else
9549
3.01k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9550
3.01k
            ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
9551
4.62k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9552
9553
4.62k
    if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
9554
3.72k
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
9555
3.72k
                                "Wrong length indicated. Expected 1 or 2, got %u", lvt);
9556
3.72k
        return offset+tag_len+lvt;
9557
3.72k
    }
9558
9559
896
    proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
9560
896
        offset+tag_len, lvt, ENC_BIG_ENDIAN);
9561
9562
896
    return offset+tag_len+lvt;
9563
4.62k
}
9564
9565
static unsigned
9566
fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9567
2.06k
{
9568
2.06k
    uint32_t     val   = 0;
9569
2.06k
    uint8_t      tag_no, tag_info;
9570
2.06k
    uint32_t     lvt;
9571
2.06k
    unsigned     tag_len;
9572
2.06k
    proto_item  *ti;
9573
2.06k
    proto_tree  *subtree;
9574
2.06k
    static const char *label = "Restart Reason";
9575
9576
2.06k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9577
2.06k
    if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
9578
865
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9579
865
            ett_bacapp_tag, &ti, "%s: %s (%u)", label,
9580
865
            val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
9581
1.20k
    else
9582
1.20k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9583
1.20k
            ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
9584
2.06k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9585
9586
2.06k
    if (lvt != 1) {
9587
1.83k
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
9588
1.83k
                                "Wrong length indicated. Expected 1, got %u", lvt);
9589
1.83k
        return offset+tag_len+lvt;
9590
1.83k
    }
9591
9592
237
    proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
9593
237
        offset+tag_len, lvt, ENC_BIG_ENDIAN);
9594
9595
237
    return offset+tag_len+lvt;
9596
2.06k
}
9597
9598
static unsigned
9599
fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9600
73
{
9601
73
    uint8_t      tag_no, tag_info;
9602
73
    uint32_t     lvt;
9603
73
    unsigned     lastoffset = 0;
9604
9605
1.61k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9606
1.59k
        lastoffset = offset;
9607
1.59k
        switch (fTagNo(tvb, offset)) {
9608
437
        case 0: /* textMessageSourceDevice */
9609
437
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
9610
437
            break;
9611
588
        case 1: /* messageClass */
9612
588
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9613
588
            switch (fTagNo(tvb, offset)) {
9614
50
            case 0: /* numeric */
9615
50
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
9616
50
                break;
9617
479
            case 1: /* character */
9618
479
                offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
9619
479
                break;
9620
588
            }
9621
581
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9622
581
            break;
9623
281
        case 2: /* messagePriority */
9624
281
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
9625
281
                BACnetMessagePriority);
9626
281
            break;
9627
255
        case 3: /* message */
9628
255
            offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
9629
255
            break;
9630
38
        default:
9631
38
            return offset;
9632
1.59k
        }
9633
1.54k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9634
1.54k
    }
9635
15
    return offset;
9636
73
}
9637
9638
static unsigned
9639
fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9640
8
{
9641
8
    return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
9642
8
}
9643
9644
static unsigned
9645
fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9646
117
{
9647
117
    unsigned    lastoffset, len;
9648
117
    uint8_t     tag_no, tag_info;
9649
117
    uint32_t    lvt;
9650
117
    proto_tree *subtree = tree;
9651
117
    tvbuff_t   *next_tvb;
9652
117
    unsigned    vendor_identifier = 0;
9653
117
    unsigned    service_number = 0;
9654
9655
117
    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9656
117
    fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
9657
117
    col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
9658
117
    offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
9659
9660
117
    next_tvb = tvb_new_subset_remaining(tvb, offset);
9661
117
    if (dissector_try_uint(bacapp_dissector_table,
9662
117
        vendor_identifier, next_tvb, pinfo, tree)) {
9663
        /* we parsed it so skip over length and we are done */
9664
0
        offset += tvb_reported_length(next_tvb);
9665
0
        return offset;
9666
0
    }
9667
9668
    /* Not handled by vendor dissector */
9669
9670
    /* exit loop if nothing happens inside */
9671
604
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9672
596
        lastoffset = offset;
9673
596
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9674
596
        if (tag_is_closing(tag_info)) {
9675
27
            if (tag_no == 2) { /* Make sure it's the expected tag */
9676
22
                offset += len;
9677
22
                subtree = tree;
9678
22
                continue;
9679
22
            } else {
9680
5
                break; /* End loop if incorrect closing tag */
9681
5
            }
9682
27
        }
9683
569
        switch (tag_no) {
9684
9685
            /* vendorID is now parsed above */
9686
466
        case 1: /* serviceNumber */
9687
466
            fUnsigned32(tvb, offset+len, lvt, &service_number);
9688
466
            col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
9689
466
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
9690
466
            break;
9691
9
        case 2: /*serviceParameters */
9692
9
            if (tag_is_opening(tag_info)) {
9693
4
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
9694
4
                        ett_bacapp_value, NULL, "service Parameters");
9695
4
                propertyIdentifier = -1;
9696
4
                offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9697
5
            } else {
9698
5
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9699
5
            }
9700
9
            break;
9701
94
        default:
9702
94
            return offset;
9703
569
        }
9704
470
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9705
470
    }
9706
9707
18
    return offset;
9708
117
}
9709
9710
static unsigned
9711
fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9712
10
{
9713
10
    return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
9714
10
}
9715
9716
static unsigned
9717
fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9718
3
{
9719
3
    return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
9720
3
}
9721
9722
static unsigned
9723
fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
9724
45
{
9725
45
    unsigned    lastoffset = 0;
9726
45
    uint8_t     tag_no, tag_info;
9727
45
    uint32_t    lvt;
9728
45
    proto_tree *subtree = tree;
9729
9730
45
    if (label != NULL) {
9731
0
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, label);
9732
0
    }
9733
9734
1.29k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9735
1.29k
        lastoffset = offset;
9736
1.29k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9737
9738
1.29k
        switch (tag_no) {
9739
908
        case 0: /* subscriberProcessId */
9740
908
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
9741
908
            break;
9742
159
        case 1: /* requestingSource */
9743
159
            offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
9744
159
            break;
9745
97
        case 2: /* request */
9746
97
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
9747
97
                "request: ", BACnetLifeSafetyOperation, 64);
9748
97
            break;
9749
92
        case 3: /* objectId */
9750
92
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
9751
92
            break;
9752
33
        default:
9753
33
            return offset;
9754
1.29k
        }
9755
1.25k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9756
1.25k
    }
9757
5
    return offset;
9758
45
}
9759
9760
typedef struct _value_string_enum {
9761
  uint8_t tag_no;
9762
  const value_string *valstr;
9763
} value_string_enum;
9764
9765
static const value_string_enum
9766
BACnetPropertyStatesEnums[] = {
9767
    {   1, BACnetBinaryPV },
9768
    {   2, BACnetEventType },
9769
    {   3, BACnetPolarity },
9770
    {   4, BACnetProgramRequest },
9771
    {   5, BACnetProgramState },
9772
    {   6, BACnetProgramError },
9773
    {   7, BACnetReliability },
9774
    {   8, BACnetEventState },
9775
    {   9, BACnetDeviceStatus },
9776
    {  10, BACnetEngineeringUnits },
9777
    {  12, BACnetLifeSafetyMode },
9778
    {  13, BACnetLifeSafetyState },
9779
    {  14, BACnetRestartReason },
9780
    {  15, BACnetDoorAlarmState },
9781
    {  16, BACnetAction },
9782
    {  17, BACnetDoorSecuredStatus },
9783
    {  18, BACnetDoorStatus },
9784
    {  19, BACnetDoorValue },
9785
    {  20, BACnetFileAccessMethod },
9786
    {  21, BACnetLockStatus },
9787
    {  22, BACnetLifeSafetyOperation },
9788
    {  23, BACnetMaintenance },
9789
    {  24, BACnetNodeType },
9790
    {  25, BACnetNotifyType },
9791
    {  26, BACnetSecurityLevel },
9792
    {  27, BACnetShedState },
9793
    {  28, BACnetSilencedState },
9794
    {  30, BACnetAccessEvent },
9795
    {  31, BACnetAccessZoneOccupancyState },
9796
    {  32, BACnetAccessCredentialDisableReason },
9797
    {  33, BACnetAccessCredentialDisable },
9798
    {  34, BACnetAuthenticationStatus },
9799
    {  36, BACnetBackupState },
9800
    {  37, BACnetWriteStatus },
9801
    {  38, BACnetLightingInProgress },
9802
    {  39, BACnetLightingOperation },
9803
    {  40, BACnetLightingTransition },
9804
    {  42, BACnetBinaryLightingPV },
9805
    {  43, BACnetTimerState },
9806
    {  44, BACnetTimerTransition },
9807
    {  45, BACnetIpMode },
9808
    {  46, BACnetNetworkPortCommand },
9809
    {  47, BACnetNetworkType },
9810
    {  48, BACnetNetworkNumberQuality },
9811
    {  49, BACnetEscalatorOperationDirection },
9812
    {  50, BACnetEscalatorFault },
9813
    {  51, BACnetEscalatorMode },
9814
    {  52, BACnetLiftCarDirection },
9815
    {  53, BACnetLiftCarDoorCommand },
9816
    {  54, BACnetLiftCarDriveStatus },
9817
    {  55, BACnetLiftCarMode },
9818
    {  56, BACnetLiftGroupMode },
9819
    {  57, BACnetLiftFault },
9820
    {  58, BACnetProtocolLevel },
9821
    {  59, BACnetAuditLevel },
9822
    {  60, BACnetAuditOperation }
9823
};
9824
50.8k
#define BACnetPropertyStatesEnums_Size array_length(BACnetPropertyStatesEnums)
9825
9826
static unsigned
9827
fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9828
10.4k
{
9829
10.4k
    uint8_t      tag_no, tag_info;
9830
10.4k
    uint32_t     lvt;
9831
10.4k
    uint32_t     idx;
9832
10.4k
    const char* label;
9833
10.4k
    const value_string_enum* valstrenum;
9834
9835
10.4k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9836
10.4k
    label = wmem_strdup_printf(pinfo->pool, "%s: ",
9837
10.4k
                               val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
9838
9839
10.4k
    switch (tag_no) {
9840
4.38k
    case 0:
9841
4.38k
        offset = fBooleanTag(tvb, pinfo, tree, offset, label);
9842
4.38k
        break;
9843
379
    case 11:
9844
379
        offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
9845
379
        break;
9846
7
    case 41:
9847
7
        offset = fSignedTag(tvb, pinfo, tree, offset, label);
9848
7
        break;
9849
6
    case 63:
9850
6
        offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
9851
6
        break;
9852
5.70k
    default:
9853
5.70k
        valstrenum = NULL;
9854
9855
50.8k
        for (idx = 0; idx < BACnetPropertyStatesEnums_Size; idx++) {
9856
50.3k
            valstrenum = &BACnetPropertyStatesEnums[idx];
9857
50.3k
            if (valstrenum->tag_no == tag_no &&
9858
5.21k
                valstrenum->valstr != NULL) {
9859
5.21k
                break;
9860
5.21k
            }
9861
45.1k
            valstrenum = NULL;
9862
45.1k
        }
9863
9864
5.70k
        if (valstrenum == NULL)
9865
490
        {
9866
490
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, label, NULL);
9867
            /* don't use Abstract type here because it is context tagged and therefore we don't know app type */
9868
490
        }
9869
5.21k
        else
9870
5.21k
        {
9871
5.21k
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
9872
5.21k
                    VALS(valstrenum->valstr), 64);
9873
5.21k
        }
9874
5.70k
        break;
9875
10.4k
    }
9876
10.4k
    return offset;
9877
10.4k
}
9878
9879
9880
/*
9881
BACnetDeviceObjectPropertyValue ::= SEQUENCE {
9882
      deviceIdentifier       [0]      BACnetObjectIdentifier,
9883
      objectIdentifier       [1]      BACnetObjectIdentifier,
9884
      propertyIdentifier     [2]      BACnetPropertyIdentifier,
9885
      arrayIndex             [3]      Unsigned OPTIONAL,
9886
      value                  [4]      ABSTRACT-SYNTAX.&Type
9887
      }
9888
*/
9889
static unsigned
9890
// NOLINTNEXTLINE(misc-no-recursion)
9891
fDeviceObjectPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9892
350
{
9893
350
    unsigned   lastoffset = 0;
9894
350
    uint8_t tag_no, tag_info;
9895
350
    uint32_t lvt;
9896
9897
1.29k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9898
1.29k
        lastoffset = offset;
9899
        /* check the tag.  A closing tag means we are done */
9900
1.29k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9901
1.29k
        if (tag_is_closing(tag_info)) {
9902
13
            return offset;
9903
13
        }
9904
1.28k
        switch (tag_no) {
9905
570
        case 0: /* deviceIdentifier */
9906
570
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
9907
570
            break;
9908
50
        case 1: /* objectIdentifier */
9909
50
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
9910
50
            break;
9911
172
        case 2: /* propertyIdentifier */
9912
172
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9913
172
            break;
9914
85
        case 3: /* arrayIndex - OPTIONAL */
9915
85
            offset = fUnsignedTag(tvb, pinfo, tree, offset,
9916
85
                "arrayIndex: ");
9917
85
            break;
9918
221
        case 4: /* value */
9919
221
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9920
221
            offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9921
221
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9922
221
            break;
9923
182
        default:
9924
182
            return offset;
9925
1.28k
        }
9926
1.08k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9927
1.08k
    }
9928
139
    return offset;
9929
350
}
9930
9931
/*
9932
BACnetDeviceObjectPropertyReference ::= SEQUENCE {
9933
      objectIdentifier       [0]      BACnetObjectIdentifier,
9934
      propertyIdentifier     [1]      BACnetPropertyIdentifier,
9935
      propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
9936
                                                                -- if omitted with an array then
9937
                                                                -- the entire array is referenced
9938
      deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
9939
      }
9940
*/
9941
static unsigned
9942
fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9943
76
{
9944
76
    return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9945
76
}
9946
9947
/*
9948
BACnetDeviceObjectPropertyReference ::= SEQUENCE {
9949
      objectIdentifier       [0]      BACnetObjectIdentifier,
9950
      propertyIdentifier     [1]      BACnetPropertyIdentifier,
9951
      propertyArrayIndex     [2]      Unsigned OPTIONAL, -- used only with array datatype
9952
                                                                -- if omitted with an array then
9953
                                                                -- the entire array is referenced
9954
      deviceIdentifier       [3]      BACnetObjectIdentifier OPTIONAL
9955
      }
9956
*/
9957
static unsigned
9958
// NOLINTNEXTLINE(misc-no-recursion)
9959
fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9960
2.80k
{
9961
2.80k
    unsigned   lastoffset = 0;
9962
2.80k
    uint8_t tag_no, tag_info;
9963
2.80k
    uint32_t lvt;
9964
9965
7.03k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9966
7.01k
        lastoffset = offset;
9967
        /* check the tag.  A closing tag means we are done */
9968
7.01k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9969
7.01k
        if (tag_is_closing(tag_info)) {
9970
1.05k
            return offset;
9971
1.05k
        }
9972
5.96k
        switch (tag_no) {
9973
1.88k
        case 0: /* objectIdentifier */
9974
1.88k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
9975
1.88k
            break;
9976
1.72k
        case 1: /* propertyIdentifier */
9977
1.72k
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9978
1.72k
            break;
9979
759
        case 2: /* arrayIndex - OPTIONAL */
9980
759
            offset = fUnsignedTag(tvb, pinfo, tree, offset,
9981
759
                "arrayIndex: ");
9982
759
            break;
9983
521
        case 3: /* deviceIdentifier - OPTIONAL */
9984
521
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
9985
521
            break;
9986
1.07k
        default:
9987
1.07k
            return offset;
9988
5.96k
        }
9989
4.84k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9990
4.84k
    }
9991
638
    return offset;
9992
2.80k
}
9993
9994
static unsigned
9995
// NOLINTNEXTLINE(misc-no-recursion)
9996
fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9997
5.15k
{
9998
5.15k
    unsigned    lastoffset = offset;
9999
5.15k
    uint8_t     tag_no, tag_info;
10000
5.15k
    uint32_t    lvt;
10001
5.15k
    proto_tree *subtree = tree;
10002
5.15k
    proto_tree *pvtree;
10003
10004
5.15k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10005
5.15k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
10006
5.15k
        ett_bacapp_value, NULL, "notification parameters (%d) %s",
10007
5.15k
        tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
10008
    /* Opening tag for parameter choice */
10009
5.15k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10010
10011
5.15k
    switch (tag_no) {
10012
334
    case 0: /* change-of-bitstring */
10013
603
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10014
600
            lastoffset = offset;
10015
600
            switch (fTagNo(tvb, offset)) {
10016
294
            case 0:
10017
294
                offset = fBitStringTag(tvb, pinfo, subtree, offset,
10018
294
                    "referenced-bitstring: ");
10019
294
                break;
10020
34
            case 1:
10021
34
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10022
34
                    "status-flags: ", BACnetStatusFlags);
10023
34
                lastoffset = offset;
10024
34
                break;
10025
272
            default:
10026
272
                break;
10027
600
            }
10028
573
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10029
573
        }
10030
307
        break;
10031
307
    case 1: /* change-of-state */
10032
368
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10033
366
            lastoffset = offset;
10034
366
            switch (fTagNo(tvb, offset)) {
10035
264
            case 0:
10036
264
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10037
264
                offset  = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
10038
264
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10039
264
                break;
10040
39
            case 1:
10041
39
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10042
39
                    "status-flags: ", BACnetStatusFlags);
10043
39
                lastoffset = offset;
10044
39
                break;
10045
63
            default:
10046
63
                break;
10047
366
            }
10048
359
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10049
359
        }
10050
102
        break;
10051
203
    case 2: /* change-of-value */
10052
329
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10053
325
            lastoffset = offset;
10054
325
            switch (fTagNo(tvb, offset)) {
10055
138
            case 0:
10056
138
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10057
138
                switch (fTagNo(tvb, offset)) {
10058
79
                case 0:
10059
79
                    offset = fBitStringTag(tvb, pinfo, subtree, offset,
10060
79
                        "changed-bits: ");
10061
79
                    break;
10062
8
                case 1:
10063
8
                    offset = fRealTag(tvb, pinfo, subtree, offset,
10064
8
                        "changed-value: ");
10065
8
                    break;
10066
51
                default:
10067
51
                    break;
10068
138
                }
10069
126
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10070
126
                break;
10071
12
            case 1:
10072
12
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10073
12
                    "status-flags: ", BACnetStatusFlags);
10074
12
                lastoffset = offset;
10075
12
                break;
10076
175
            default:
10077
175
                break;
10078
325
            }
10079
313
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10080
313
        }
10081
191
        break;
10082
1.00k
    case 3: /* command-failure */
10083
2.66k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10084
2.64k
            lastoffset = offset;
10085
2.64k
            switch (fTagNo(tvb, offset)) {
10086
1.68k
            case 0: /* "command-value: " */
10087
                /* from BACnet Table 13-3,
10088
                    Standard Object Property Values Returned in Notifications */
10089
1.68k
                propertyIdentifier = 85; /* PRESENT_VALUE */
10090
1.68k
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10091
1.68k
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10092
1.68k
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10093
1.68k
                break;
10094
327
            case 1:
10095
327
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10096
327
                    "status-flags: ", BACnetStatusFlags);
10097
327
                break;
10098
87
            case 2: /* "feedback-value: " */
10099
87
                propertyIdentifier = 40; /* FEEDBACK_VALUE */
10100
87
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10101
87
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10102
87
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10103
87
                lastoffset = offset;
10104
87
                break;
10105
544
            default:
10106
544
                break;
10107
2.64k
            }
10108
2.25k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10109
2.25k
        }
10110
611
        break;
10111
611
    case 4: /* floating-limit */
10112
610
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10113
608
            lastoffset = offset;
10114
608
            switch (fTagNo(tvb, offset)) {
10115
310
            case 0:
10116
310
                offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
10117
310
                break;
10118
68
            case 1:
10119
68
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10120
68
                    "status-flags: ", BACnetStatusFlags);
10121
68
                break;
10122
129
            case 2:
10123
129
                offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
10124
129
                break;
10125
21
            case 3:
10126
21
                offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
10127
21
                lastoffset = offset;
10128
21
                break;
10129
80
            default:
10130
80
                break;
10131
608
            }
10132
597
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10133
597
        }
10134
100
        break;
10135
112
    case 5: /* out-of-range */
10136
694
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10137
692
            lastoffset = offset;
10138
692
            switch (fTagNo(tvb, offset)) {
10139
287
            case 0:
10140
287
                offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10141
287
                break;
10142
122
            case 1:
10143
122
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10144
122
                    "status-flags: ", BACnetStatusFlags);
10145
122
                break;
10146
176
            case 2:
10147
176
                offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
10148
176
                break;
10149
26
            case 3:
10150
26
                offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10151
26
                lastoffset = offset;
10152
26
                break;
10153
81
            default:
10154
81
                break;
10155
692
            }
10156
689
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10157
689
        }
10158
109
        break;
10159
868
    case 6:
10160
1.68k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10161
1.53k
            lastoffset = offset;
10162
1.53k
            offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
10163
1.53k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10164
1.53k
        }
10165
868
        break;
10166
90
    case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
10167
623
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10168
621
            lastoffset = offset;
10169
621
            switch (fTagNo(tvb, offset)) {
10170
307
            case 0:
10171
307
                offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_device_identifier); /* buffer-device */
10172
307
                break;
10173
114
            case 1:
10174
114
                offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier); /* buffer-object */
10175
114
                break;
10176
116
            case 2:
10177
116
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10178
116
                offset  = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
10179
116
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10180
116
                break;
10181
9
            case 3:
10182
9
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10183
9
                offset  = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
10184
9
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10185
9
                lastoffset = offset;
10186
9
                break;
10187
75
            default:
10188
75
                break;
10189
621
            }
10190
617
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10191
617
        }
10192
86
        break;
10193
154
    case 8: /* change-of-life-safety */
10194
2.05k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10195
2.05k
            lastoffset = offset;
10196
2.05k
            switch (fTagNo(tvb, offset)) {
10197
1.44k
            case 0:
10198
1.44k
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10199
1.44k
                    "new-state: ", BACnetLifeSafetyState, 256);
10200
1.44k
                break;
10201
354
            case 1:
10202
354
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10203
354
                    "new-mode: ", BACnetLifeSafetyMode, 256);
10204
354
                break;
10205
110
            case 2:
10206
110
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10207
110
                    "status-flags: ", BACnetStatusFlags);
10208
110
                break;
10209
30
            case 3:
10210
30
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10211
30
                    "operation-expected: ", BACnetLifeSafetyOperation, 64);
10212
30
                lastoffset = offset;
10213
30
                break;
10214
112
            default:
10215
112
                break;
10216
2.05k
            }
10217
2.04k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10218
2.04k
        }
10219
147
        break;
10220
203
    case 9: /* extended */
10221
1.76k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10222
1.75k
            lastoffset = offset;
10223
1.75k
            switch (fTagNo(tvb, offset)) {
10224
1.41k
            case 0:
10225
1.41k
                offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10226
1.41k
                break;
10227
156
            case 1:
10228
156
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "extended-event-type: ");
10229
156
                break;
10230
135
            case 2: /* parameters */
10231
135
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10232
10233
2.65k
                while (tvb_reported_length_remaining(tvb, offset) > 0) {
10234
2.62k
                    const unsigned param_lastoffset = offset;
10235
2.62k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10236
2.62k
                    if (tag_is_closing(tag_info))
10237
32
                    {
10238
32
                        break;
10239
32
                    }
10240
10241
2.59k
                    if (tag_is_opening(tag_info))
10242
350
                    {
10243
350
                        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10244
350
                        offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
10245
350
                        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10246
350
                    }
10247
2.24k
                    else
10248
2.24k
                    {
10249
2.24k
                        offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
10250
2.24k
                    }
10251
2.59k
                    if (offset <= param_lastoffset)
10252
71
                        break;     /* nothing happened, exit loop */
10253
2.59k
                }
10254
10255
135
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10256
135
                lastoffset = offset;
10257
135
                break;
10258
57
            default:
10259
57
                break;
10260
1.75k
            }
10261
1.72k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10262
1.72k
        }
10263
169
        break;
10264
169
    case 10: /* buffer ready */
10265
459
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10266
455
            lastoffset = offset;
10267
455
            switch (fTagNo(tvb, offset)) {
10268
185
            case 0: /* buffer-property */
10269
185
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10270
185
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10271
185
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10272
185
                break;
10273
147
            case 1:
10274
147
                offset  = fUnsignedTag(tvb, pinfo, subtree, offset,
10275
147
                    "previous-notification: ");
10276
147
                break;
10277
12
            case 2:
10278
12
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10279
12
                    "current-notification: ");
10280
12
                lastoffset = offset;
10281
12
                break;
10282
111
            default:
10283
111
                break;
10284
455
            }
10285
445
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10286
445
        }
10287
126
        break;
10288
126
    case 11: /* unsigned range */
10289
839
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10290
836
            lastoffset = offset;
10291
836
            switch (fTagNo(tvb, offset)) {
10292
664
            case 0:
10293
664
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10294
664
                    "exceeding-value: ");
10295
664
                break;
10296
93
            case 1:
10297
93
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10298
93
                    "status-flags: ", BACnetStatusFlags);
10299
93
                break;
10300
18
            case 2:
10301
18
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10302
18
                    "exceeded-limit: ");
10303
18
                lastoffset = offset;
10304
18
                break;
10305
61
            default:
10306
61
                break;
10307
836
            }
10308
832
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10309
832
        }
10310
82
        break;
10311
        /* 12 reserved */
10312
280
    case 13: /* access-event */
10313
3.09k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10314
3.09k
            lastoffset = offset;
10315
3.09k
            switch (fTagNo(tvb, offset)) {
10316
1.38k
            case 0:
10317
1.38k
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10318
1.38k
                                              "access event: ", BACnetAccessEvent, 512);
10319
1.38k
                break;
10320
199
            case 1:
10321
199
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10322
199
                    "status-flags: ", BACnetStatusFlags);
10323
199
                break;
10324
516
            case 2:
10325
516
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10326
516
                    "access-event-tag: ");
10327
516
                break;
10328
350
            case 3:
10329
350
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10330
350
                offset  = fTimeStamp(tvb, pinfo, subtree, offset, "access-event-time: ");
10331
350
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10332
350
                break;
10333
377
            case 4:
10334
377
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10335
377
                offset  = fDeviceObjectReference(tvb, pinfo, subtree, offset);
10336
377
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10337
377
                break;
10338
88
            case 5: /* optional authentication-factor */
10339
88
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10340
88
                offset  = fAuthenticationFactor(tvb, pinfo, subtree, offset);
10341
88
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10342
88
                lastoffset = offset;
10343
88
                break;
10344
175
            default:
10345
175
                break;
10346
3.09k
            }
10347
3.07k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10348
3.07k
        }
10349
263
        break;
10350
263
    case 14: /* double-out-of-range */
10351
518
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10352
514
            lastoffset = offset;
10353
514
            switch (fTagNo(tvb, offset)) {
10354
230
            case 0:
10355
230
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10356
230
                break;
10357
139
            case 1:
10358
139
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10359
139
                    "status-flags: ", BACnetStatusFlags);
10360
139
                break;
10361
87
            case 2:
10362
87
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
10363
87
                break;
10364
8
            case 3:
10365
8
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10366
8
                lastoffset = offset;
10367
8
                break;
10368
50
            default:
10369
50
                break;
10370
514
            }
10371
502
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10372
502
        }
10373
61
        break;
10374
78
    case 15: /* signed-out-of-range */
10375
805
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10376
802
            lastoffset = offset;
10377
802
            switch (fTagNo(tvb, offset)) {
10378
594
            case 0:
10379
594
                offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10380
594
                break;
10381
69
            case 1:
10382
69
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10383
69
                    "status-flags: ", BACnetStatusFlags);
10384
69
                break;
10385
65
            case 2:
10386
65
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10387
65
                break;
10388
18
            case 3:
10389
18
                offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10390
18
                lastoffset = offset;
10391
18
                break;
10392
56
            default:
10393
56
                break;
10394
802
            }
10395
801
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10396
801
        }
10397
77
        break;
10398
77
    case 16: /* unsigned-out-of-range */
10399
944
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10400
935
            lastoffset = offset;
10401
935
            switch (fTagNo(tvb, offset)) {
10402
729
            case 0:
10403
729
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10404
729
                break;
10405
28
            case 1:
10406
28
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10407
28
                    "status-flags: ", BACnetStatusFlags);
10408
28
                break;
10409
150
            case 2:
10410
150
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10411
150
                break;
10412
4
            case 3:
10413
4
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10414
4
                lastoffset = offset;
10415
4
                break;
10416
24
            default:
10417
24
                break;
10418
935
            }
10419
934
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10420
934
        }
10421
37
        break;
10422
37
    case 17: /* change-of-characterstring */
10423
32
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10424
32
            lastoffset = offset;
10425
32
            switch (fTagNo(tvb, offset)) {
10426
2
            case 0:
10427
                 /* changed-value (CharacterString) */
10428
2
                offset  = fCharacterString(tvb, pinfo, subtree, offset, "changed-value: ");
10429
2
                break;
10430
5
            case 1:
10431
5
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10432
5
                    "status-flags: ", BACnetStatusFlags);
10433
5
                break;
10434
0
            case 2:
10435
                /* alarm-value (CharacterString) */
10436
0
                offset  = fCharacterString(tvb, pinfo, subtree, offset, "alarm-value: ");
10437
0
                lastoffset = offset;
10438
0
                break;
10439
25
            default:
10440
25
                break;
10441
32
            }
10442
30
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10443
30
        }
10444
25
        break;
10445
35
    case 18: /* change-of-status-flags */
10446
171
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10447
            /* exit loop if nothing happens inside */
10448
171
            lastoffset = offset;
10449
171
            switch (fTagNo(tvb, offset)) {
10450
139
            case 0:
10451
139
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10452
10453
139
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10454
139
                if (tag_is_context_specific(tag_info)) {
10455
42
                    propertyIdentifier = 85; /* suppose present-value here */
10456
42
                    offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10457
97
                } else {
10458
97
                    offset = fPresentValue(tvb, pinfo, tree, offset, BACnetStatusFlags, 0, BACAPP_PRESENT_VALUE_ENUM);
10459
97
                }
10460
10461
139
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10462
139
                break;
10463
4
            case 1:
10464
4
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10465
4
                    "referenced-flags: ", BACnetStatusFlags);
10466
4
                lastoffset = offset;
10467
4
                break;
10468
28
            default:
10469
28
                break;
10470
171
            }
10471
167
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10472
167
        }
10473
31
        break;
10474
31
    case 19: /* change-of-reliability */
10475
195
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10476
            /* exit loop if nothing happens inside */
10477
194
            lastoffset = offset;
10478
10479
194
            switch (fTagNo(tvb, offset)) {
10480
154
            case 0:
10481
154
               offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "reliability:", BACnetReliability);
10482
154
               break;
10483
17
            case 1:
10484
17
               offset = fBitStringTagVS(tvb, pinfo, subtree, offset, "status-flags: ", BACnetStatusFlags);
10485
17
               break;
10486
10
            case 2: /* property-values */
10487
10
               fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10488
10
               if (tag_is_closing(tag_info)) {
10489
2
                  offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10490
2
               return offset;
10491
2
               }
10492
8
               pvtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "property-values");
10493
8
               offset += fTagHeaderTree(tvb, pinfo, pvtree, offset, &tag_no, &tag_info, &lvt);
10494
8
               offset = fBACnetPropertyValue(tvb, pinfo, pvtree, offset);
10495
8
               offset += fTagHeaderTree(tvb, pinfo, pvtree, offset, &tag_no, &tag_info, &lvt);
10496
8
               break;
10497
13
            default:
10498
13
               break;
10499
194
           }
10500
191
           if (offset <= lastoffset)
10501
13
               break;     /* nothing happened, exit loop */
10502
191
        }
10503
14
        break;
10504
14
    case 20: /* context tag [20] is not used */
10505
9
        break;
10506
9
    case 21: /* change-of-discrete-value */
10507
107
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10508
            /* exit loop if nothing happens inside */
10509
107
            lastoffset = offset;
10510
107
            switch (fTagNo(tvb, offset)) {
10511
38
            case 0: /* new-value */
10512
38
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10513
10514
38
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10515
38
                if (tag_is_opening(tag_info))
10516
0
                {
10517
0
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10518
0
                    offset  = fDateTime(tvb, pinfo, subtree, offset, "new-value: ");
10519
0
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10520
0
                }
10521
38
                else
10522
38
                {
10523
38
                    offset  = fApplicationTypes(tvb, pinfo, subtree, offset, "new-value: ");
10524
38
                }
10525
10526
38
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10527
38
                break;
10528
60
            case 1: /* status-flags */
10529
60
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10530
60
                    "status-flags: ", BACnetStatusFlags);
10531
60
                break;
10532
9
            default:
10533
9
                break;
10534
107
            }
10535
107
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10536
107
        }
10537
9
        break;
10538
59
    case 22: /* change-of-timer */
10539
1.40k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10540
            /* exit loop if nothing happens inside */
10541
1.39k
            lastoffset = offset;
10542
1.39k
            switch (fTagNo(tvb, offset)) {
10543
910
            case 0: /* new-state */
10544
910
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10545
910
                    "new-state: ", BACnetTimerState, 256);
10546
910
                break;
10547
162
            case 1: /* status-flags */
10548
162
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10549
162
                    "status-flags: ", BACnetStatusFlags);
10550
162
                break;
10551
75
            case 2: /* update-time */
10552
75
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10553
75
                offset  = fDateTime(tvb, pinfo, subtree, offset, "update-time: ");
10554
75
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10555
75
                break;
10556
118
            case 3: /* last-state-change (OPTIONAL) */
10557
118
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10558
118
                    "new-state: ", BACnetTimerTransition, 256);
10559
118
                break;
10560
83
            case 4: /* initial-timeout (OPTIONAL) */
10561
83
                offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "initial-timeout: ");
10562
83
                break;
10563
49
            default:
10564
49
                break;
10565
1.39k
            }
10566
1.39k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10567
1.39k
        }
10568
54
        break;
10569
10570
        /* todo: add new parameters here ... */
10571
1.10k
    default:
10572
1.10k
        offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10573
1.10k
        break;
10574
5.15k
    }
10575
10576
    /* Closing tag for parameter choice */
10577
4.36k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10578
10579
4.36k
    return offset;
10580
5.15k
}
10581
10582
static unsigned
10583
// NOLINTNEXTLINE(misc-no-recursion)
10584
fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10585
26.3k
{
10586
26.3k
    unsigned    lastoffset = offset;
10587
26.3k
    uint8_t     tag_no, tag_info;
10588
26.3k
    uint32_t    lvt;
10589
26.3k
    proto_tree *subtree = tree;
10590
10591
26.3k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10592
26.3k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
10593
26.3k
        ett_bacapp_value, NULL, "event parameters (%d) %s",
10594
26.3k
        tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
10595
10596
    /* Opening tag for parameter choice */
10597
26.3k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10598
10599
26.3k
    switch (tag_no) {
10600
2.90k
    case 0: /* change-of-bitstring */
10601
13.6k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10602
11.1k
            lastoffset = offset;
10603
11.1k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10604
11.1k
            if (tag_is_closing(tag_info)) {
10605
318
                break;
10606
318
            }
10607
10.8k
            switch (tag_no) {
10608
7.88k
            case 0:
10609
7.88k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10610
7.88k
                break;
10611
356
            case 1:
10612
356
                offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
10613
356
                break;
10614
163
            case 2: /* SEQUENCE OF BIT STRING */
10615
163
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10616
863
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10617
774
                    lastoffset = offset;
10618
774
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10619
774
                    if (tag_is_closing(tag_info)) {
10620
74
                        break;
10621
74
                    }
10622
700
                    offset = fBitStringTag(tvb, pinfo, subtree, offset,
10623
700
                                           "bitstring value: ");
10624
700
                }
10625
163
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10626
163
                break;
10627
2.42k
            default:
10628
2.42k
                break;
10629
10.8k
            }
10630
10.8k
        }
10631
2.77k
        break;
10632
2.77k
    case 1: /* change-of-state */
10633
3.30k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10634
2.47k
            lastoffset = offset;
10635
2.47k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10636
2.47k
            if (tag_is_closing(tag_info)) {
10637
150
                break;
10638
150
            }
10639
2.32k
            switch (tag_no) {
10640
1.06k
            case 0:
10641
1.06k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10642
1.06k
                break;
10643
453
            case 1: /* SEQUENCE OF BACnetPropertyStates */
10644
453
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10645
8.90k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10646
8.82k
                    lastoffset = offset;
10647
8.82k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10648
8.82k
                    if (tag_is_closing(tag_info)) {
10649
373
                        break;
10650
373
                    }
10651
8.45k
                    offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
10652
8.45k
                }
10653
453
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10654
453
                break;
10655
807
            default:
10656
807
                break;
10657
2.32k
            }
10658
2.32k
        }
10659
976
        break;
10660
2.20k
    case 2: /* change-of-value */
10661
6.64k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10662
4.44k
            lastoffset = offset;
10663
4.44k
            switch (fTagNo(tvb, offset)) {
10664
1.94k
            case 0:
10665
1.94k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10666
1.94k
                break;
10667
318
            case 1: /* don't loop it, it's a CHOICE */
10668
318
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10669
318
                switch (fTagNo(tvb, offset)) {
10670
50
                case 0:
10671
50
                    offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
10672
50
                    break;
10673
182
                case 1:
10674
182
                    offset = fRealTag(tvb, pinfo, subtree, offset,
10675
182
                                       "referenced Property Increment: ");
10676
182
                    break;
10677
83
                default:
10678
83
                    break;
10679
318
                }
10680
311
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10681
311
                break;
10682
2.18k
            default:
10683
2.18k
                break;
10684
4.44k
            }
10685
4.44k
        }
10686
2.19k
        break;
10687
2.19k
    case 3: /* command-failure */
10688
5.73k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10689
3.67k
            lastoffset = offset;
10690
3.67k
            tag_no = fTagNo(tvb, offset);
10691
3.67k
            switch (tag_no) {
10692
1.36k
            case 0:
10693
1.36k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10694
1.36k
                break;
10695
253
            case 1:
10696
253
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10697
253
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10698
253
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10699
253
                break;
10700
2.05k
            default:
10701
2.05k
                break;
10702
3.67k
            }
10703
3.67k
        }
10704
2.06k
        break;
10705
2.06k
    case 4: /* floating-limit */
10706
8.97k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10707
8.07k
            lastoffset = offset;
10708
8.07k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10709
8.07k
            if (tag_is_closing(tag_info)) {
10710
258
                break;
10711
258
            }
10712
7.81k
            switch (tag_no) {
10713
4.61k
            case 0:
10714
4.61k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10715
4.61k
                break;
10716
456
            case 1:
10717
456
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10718
456
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10719
456
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10720
456
                break;
10721
378
            case 2:
10722
378
                offset  = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
10723
378
                break;
10724
496
            case 3:
10725
496
                offset  = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
10726
496
                break;
10727
993
            case 4:
10728
993
                offset  = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
10729
993
                break;
10730
876
            default:
10731
876
                break;
10732
7.81k
            }
10733
7.81k
        }
10734
1.15k
        break;
10735
2.09k
    case 5: /* out-of-range */
10736
7.56k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10737
5.48k
            lastoffset = offset;
10738
5.48k
            switch (fTagNo(tvb, offset)) {
10739
2.25k
            case 0:
10740
2.25k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10741
2.25k
                break;
10742
412
            case 1:
10743
412
                offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
10744
412
                break;
10745
396
            case 2:
10746
396
                offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
10747
396
                break;
10748
352
            case 3:
10749
352
                offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
10750
352
                break;
10751
2.06k
            default:
10752
2.06k
                break;
10753
5.48k
            }
10754
5.48k
        }
10755
2.08k
        break;
10756
2.08k
    case 6: /* complex-event-type */
10757
        /* deprecated */
10758
1.42k
        offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
10759
1.42k
        break;
10760
2.10k
    case 7: /* buffer-ready */
10761
        /* deprecated */
10762
3.84k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
10763
3.82k
            lastoffset = offset;
10764
3.82k
            switch (fTagNo(tvb, offset)) {
10765
1.38k
            case 0:
10766
1.38k
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
10767
1.38k
                break;
10768
359
            case 1:
10769
359
                offset = fUnsignedTag(tvb, pinfo, tree, offset,
10770
359
                                       "previous notification count: ");
10771
359
                break;
10772
2.08k
            default:
10773
2.08k
                return offset;
10774
3.82k
            }
10775
3.82k
        }
10776
11
        break;
10777
1.35k
    case 8: /* change-of-life-safety */
10778
4.00k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10779
2.71k
            lastoffset = offset;
10780
2.71k
            switch (fTagNo(tvb, offset)) {
10781
983
            case 0:
10782
983
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10783
983
                break;
10784
182
            case 1:
10785
182
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10786
1.15k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10787
1.13k
                    lastoffset = offset;
10788
1.13k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10789
1.13k
                    if (tag_is_closing(tag_info)) {
10790
162
                        break;
10791
162
                    }
10792
971
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10793
971
                                                  "life safety alarm value: ", BACnetLifeSafetyState, 256);
10794
971
                }
10795
182
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10796
182
                break;
10797
131
            case 2:
10798
131
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10799
2.08k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10800
2.05k
                    lastoffset = offset;
10801
2.05k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10802
2.05k
                    if (tag_is_closing(tag_info)) {
10803
103
                        break;
10804
103
                    }
10805
1.95k
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10806
1.95k
                                                  "alarm value: ", BACnetLifeSafetyState, 256);
10807
1.95k
                }
10808
131
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10809
131
                break;
10810
126
            case 3:
10811
126
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10812
126
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10813
126
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10814
126
                break;
10815
1.29k
            default:
10816
1.29k
                break;
10817
2.71k
            }
10818
2.71k
        }
10819
1.29k
        break;
10820
1.94k
    case 9: /* extended */
10821
3.86k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10822
3.85k
            lastoffset = offset;
10823
3.85k
            switch (fTagNo(tvb, offset)) {
10824
1.52k
            case 0:
10825
1.52k
                offset = fVendorIdentifier(tvb, pinfo, tree, offset);
10826
1.52k
                break;
10827
390
            case 1:
10828
390
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "extended-event-type: ");
10829
390
                break;
10830
366
            case 2: /* parameters */
10831
366
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10832
4.85k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10833
4.49k
                    lastoffset = offset;
10834
4.49k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10835
4.49k
                    if (tag_is_closing(tag_info) && tag_no == 2) {
10836
11
                        break;
10837
11
                    }
10838
10839
4.48k
                    if ( ! tag_is_context_specific(tag_info)) {
10840
3.15k
                        offset  = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
10841
3.15k
                    } else {
10842
1.32k
                        if (tag_no == 0) {
10843
703
                            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10844
703
                            offset  = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
10845
703
                            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10846
703
                        } else {
10847
626
                            offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
10848
626
                        }
10849
1.32k
                    }
10850
4.48k
                }
10851
366
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10852
366
                lastoffset = offset;
10853
366
                break;
10854
1.56k
            default:
10855
1.56k
                break;
10856
3.85k
            }
10857
3.72k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10858
3.72k
        }
10859
1.81k
        break;
10860
1.81k
    case 10: /* buffer-ready */
10861
4.42k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10862
2.87k
            lastoffset = offset;
10863
2.87k
            switch (fTagNo(tvb, offset)) {
10864
948
            case 0:
10865
948
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10866
948
                                       "notification-threshold: ");
10867
948
                break;
10868
393
            case 1:
10869
393
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10870
393
                                       "previous-notification-count: ");
10871
393
                break;
10872
1.53k
            default:
10873
1.53k
                break;
10874
2.87k
            }
10875
2.87k
        }
10876
1.54k
        break;
10877
1.60k
    case 11: /* unsigned-range */
10878
5.30k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10879
3.69k
            lastoffset = offset;
10880
3.69k
            switch (fTagNo(tvb, offset)) {
10881
1.37k
            case 0:
10882
1.37k
                offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
10883
1.37k
                break;
10884
525
            case 1:
10885
525
                offset = fUnsignedTag(tvb, pinfo, tree, offset,
10886
525
                                       "low-limit: ");
10887
525
                break;
10888
202
            case 2:
10889
202
                offset = fUnsignedTag(tvb, pinfo, tree, offset,
10890
202
                                       "high-limit: ");
10891
202
                break;
10892
1.59k
            default:
10893
1.59k
                break;
10894
3.69k
            }
10895
3.69k
        }
10896
1.60k
        break;
10897
1.60k
    case 13: /* access-event */
10898
2.25k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10899
1.29k
            lastoffset = offset;
10900
1.29k
            switch (fTagNo(tvb, offset)) {
10901
195
            case 0:
10902
                /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
10903
195
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10904
2.11k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10905
2.09k
                    lastoffset = offset;
10906
2.09k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10907
2.09k
                    if (tag_is_closing(tag_info)) {
10908
176
                        break;
10909
176
                    }
10910
1.91k
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10911
1.91k
                                                  "access event: ", BACnetAccessEvent, 512);
10912
1.91k
                }
10913
195
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10914
195
                break;
10915
155
            case 1:
10916
155
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10917
155
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10918
155
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10919
155
                break;
10920
949
            default:
10921
949
                break;
10922
1.29k
            }
10923
1.29k
        }
10924
958
        break;
10925
1.77k
    case 14: /* double-out-of-range */
10926
6.53k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10927
4.78k
            lastoffset = offset;
10928
4.78k
            switch (fTagNo(tvb, offset)) {
10929
2.04k
            case 0:
10930
2.04k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10931
2.04k
                break;
10932
220
            case 1:
10933
220
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
10934
220
                break;
10935
429
            case 2:
10936
429
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
10937
429
                break;
10938
361
            case 3:
10939
361
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
10940
361
                break;
10941
1.73k
            default:
10942
1.73k
                break;
10943
4.78k
            }
10944
4.78k
        }
10945
1.74k
        break;
10946
1.74k
    case 15: /* signed-out-of-range */
10947
1.45k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10948
1.38k
            lastoffset = offset;
10949
1.38k
            switch (fTagNo(tvb, offset)) {
10950
953
            case 0:
10951
953
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10952
953
                break;
10953
159
            case 1:
10954
159
                offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
10955
159
                break;
10956
82
            case 2:
10957
82
                offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
10958
82
                break;
10959
114
            case 3:
10960
114
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10961
114
                break;
10962
72
            default:
10963
72
                break;
10964
1.38k
            }
10965
1.38k
        }
10966
73
        break;
10967
73
    case 16: /* unsigned-out-of-range */
10968
1.94k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10969
1.87k
            lastoffset = offset;
10970
1.87k
            switch (fTagNo(tvb, offset)) {
10971
825
            case 0:
10972
825
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10973
825
                break;
10974
782
            case 1:
10975
782
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
10976
782
                break;
10977
35
            case 2:
10978
35
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
10979
35
                break;
10980
166
            case 3:
10981
166
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10982
166
                break;
10983
67
            default:
10984
67
                break;
10985
1.87k
            }
10986
1.87k
        }
10987
71
        break;
10988
71
    case 17: /* change-of-characterstring */
10989
164
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10990
146
            lastoffset = offset;
10991
146
            switch (fTagNo(tvb, offset)) {
10992
102
            case 0:
10993
102
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10994
102
                break;
10995
26
            case 1: /* SEQUENCE OF CharacterString */
10996
26
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10997
310
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10998
292
                    lastoffset = offset;
10999
292
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11000
292
                    if (tag_is_closing(tag_info)) {
11001
8
                        break;
11002
8
                    }
11003
284
                    offset  = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
11004
284
                }
11005
26
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11006
26
                break;
11007
18
            default:
11008
18
                break;
11009
146
            }
11010
146
        }
11011
18
        break;
11012
59
    case 18: /* change-of-status-flags */
11013
663
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11014
606
            lastoffset = offset;
11015
606
            switch (fTagNo(tvb, offset)) {
11016
389
            case 0:
11017
389
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11018
389
                break;
11019
163
            case 1:
11020
163
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11021
163
                    "selected flags: ", BACnetStatusFlags);
11022
163
                break;
11023
54
            default:
11024
54
                break;
11025
606
            }
11026
606
        }
11027
57
        break;
11028
57
    case 19: /* has been intentionally omitted. It parallels the change-of-reliability event type */
11029
1
        break;
11030
12
    case 20: /* none */
11031
        /* no closing tag expected only context tag here */
11032
12
        return offset;
11033
19
    case 21: /* change-of-discrete-value */
11034
89
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11035
70
            lastoffset = offset;
11036
70
            switch (fTagNo(tvb, offset)) {
11037
51
            case 0:
11038
51
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11039
51
                break;
11040
19
            default:
11041
19
                break;
11042
70
            }
11043
70
        }
11044
19
        break;
11045
71
    case 22: /* change-of-timer */
11046
1.08k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11047
1.02k
            lastoffset = offset;
11048
1.02k
            switch (fTagNo(tvb, offset)) {
11049
688
            case 0: /* time-delay */
11050
688
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11051
688
                break;
11052
76
            case 1: /* alarm-values */
11053
76
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11054
1.21k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11055
1.20k
                    lastoffset = offset;
11056
1.20k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11057
1.20k
                    if (tag_is_closing(tag_info)) {
11058
69
                        break;
11059
69
                    }
11060
1.13k
                offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
11061
1.13k
                                                  "alarm value: ", BACnetTimerState);
11062
1.13k
                }
11063
76
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11064
76
                break;
11065
200
            case 2: /* update-time-reference */
11066
200
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11067
200
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11068
200
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11069
200
                break;
11070
62
            default:
11071
62
                break;
11072
1.02k
            }
11073
1.02k
        }
11074
63
        break;
11075
    /* todo: add new event-parameter cases here */
11076
1.71k
  default:
11077
1.71k
        break;
11078
26.3k
    }
11079
11080
    /* Closing tag for parameter choice */
11081
23.6k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11082
23.6k
    return offset;
11083
26.3k
}
11084
11085
static unsigned
11086
fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11087
8.55k
{
11088
8.55k
    unsigned    lastoffset = offset;
11089
8.55k
    uint8_t     tag_no, tag_info;
11090
8.55k
    uint32_t    lvt;
11091
8.55k
    proto_tree *subtree = tree;
11092
11093
8.55k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11094
8.55k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11095
8.55k
      ett_bacapp_value, NULL, "fault parameters (%d) %s",
11096
8.55k
      tag_no, val_to_str_const(tag_no, BACnetFaultType, "invalid type"));
11097
11098
    /* Opening tag for parameter choice */
11099
8.55k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11100
11101
8.55k
    switch (tag_no) {
11102
3.37k
    case 0: /* none */
11103
        /* no closing tag expected only context tag here */
11104
3.37k
        return offset;
11105
461
    case 1: /* fault-characterstring */
11106
965
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11107
530
            lastoffset = offset;
11108
530
            switch (fTagNo(tvb, offset)) {
11109
97
            case 0: /* SEQUENCE OF CharacterString */
11110
97
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11111
380
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11112
354
                    lastoffset = offset;
11113
354
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11114
354
                    if (tag_is_closing(tag_info)) {
11115
71
                        break;
11116
71
                    }
11117
283
                    offset = fCharacterString(tvb, pinfo, subtree, offset, "fault value: ");
11118
283
                }
11119
97
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11120
97
                break;
11121
433
            default:
11122
433
                break;
11123
530
            }
11124
530
        }
11125
435
        break;
11126
435
    case 2: /* fault-extended */
11127
1.61k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11128
1.20k
            lastoffset = offset;
11129
1.20k
            switch (fTagNo(tvb, offset)) {
11130
677
            case 0:
11131
677
                offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
11132
677
                break;
11133
114
            case 1:
11134
114
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "extended-fault-type: ");
11135
114
                break;
11136
153
            case 2: /* parameters */
11137
153
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11138
153
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
11139
153
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11140
153
                lastoffset = offset;
11141
153
                break;
11142
260
            default:
11143
260
                break;
11144
1.20k
            }
11145
1.20k
        }
11146
412
        break;
11147
861
    case 3: /* fault-life-safety */
11148
1.79k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11149
950
            lastoffset = offset;
11150
950
            switch (fTagNo(tvb, offset)) {
11151
61
            case 0:
11152
61
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11153
1.03k
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11154
1.01k
                    lastoffset = offset;
11155
1.01k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11156
1.01k
                    if (tag_is_closing(tag_info)) {
11157
41
                        break;
11158
41
                    }
11159
976
                    offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
11160
976
                      "fault value: ", BACnetLifeSafetyState);
11161
976
                }
11162
61
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11163
61
                break;
11164
54
            case 1:
11165
54
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11166
54
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11167
54
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11168
54
                break;
11169
835
            default:
11170
835
                break;
11171
950
            }
11172
950
        }
11173
841
        break;
11174
841
    case 4: /* fault-state */
11175
1.52k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11176
822
            lastoffset = offset;
11177
822
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11178
822
            if (tag_is_closing(tag_info)) {
11179
58
                break;
11180
58
            }
11181
764
            switch (tag_no) {
11182
67
            case 0: /* SEQUENCE OF BACnetPropertyStates */
11183
67
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11184
1.83k
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11185
1.81k
                    lastoffset = offset;
11186
1.81k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11187
1.81k
                    if (tag_is_closing(tag_info)) {
11188
43
                        break;
11189
43
                    }
11190
1.77k
                    offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
11191
1.77k
                }
11192
67
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11193
67
                break;
11194
696
            default:
11195
696
                break;
11196
764
            }
11197
764
        }
11198
758
        break;
11199
758
    case 5: /* fault-status-flags */
11200
735
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11201
402
            lastoffset = offset;
11202
402
            switch (fTagNo(tvb, offset)) {
11203
74
            case 0:
11204
74
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11205
74
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11206
74
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11207
74
                break;
11208
328
            default:
11209
328
                break;
11210
402
            }
11211
402
        }
11212
333
        break;
11213
579
    case 6: /* fault-out-of-range */
11214
1.88k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11215
1.35k
            lastoffset = offset;
11216
1.35k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11217
1.35k
            if (tag_is_closing(tag_info)) {
11218
43
                break;
11219
43
            }
11220
1.31k
            switch (fTagNo(tvb, offset)) {
11221
664
            case 0:
11222
664
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11223
664
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "min-normal-value: ");
11224
664
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11225
664
                break;
11226
118
            case 1:
11227
118
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11228
118
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "max-normal-value: ");
11229
118
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11230
118
                break;
11231
531
            default:
11232
531
                break;
11233
1.31k
            }
11234
1.31k
        }
11235
576
        break;
11236
576
    case 7: /* fault-listed */
11237
889
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11238
476
            lastoffset = offset;
11239
476
            switch (fTagNo(tvb, offset)) {
11240
68
            case 0:
11241
68
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11242
68
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11243
68
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11244
68
                break;
11245
408
            default:
11246
408
                break;
11247
476
          }
11248
476
        }
11249
413
      break;
11250
1.33k
    default:
11251
1.33k
      break;
11252
8.55k
    }
11253
11254
    /* Closing tag for parameter choice */
11255
5.10k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11256
5.10k
    return offset;
11257
8.55k
}
11258
11259
static unsigned
11260
fEventNotificationSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11261
92
{
11262
92
    unsigned    lastoffset = 0;
11263
92
    uint8_t     tag_no, tag_info;
11264
92
    uint32_t    lvt;
11265
92
    proto_tree *subtree;
11266
92
    unsigned    itemno = 1;
11267
11268
725
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {  /* exit loop if nothing happens inside */
11269
724
        lastoffset = offset;
11270
724
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11271
724
        if (tag_is_closing(tag_info)) {
11272
4
            return offset;
11273
4
        }
11274
720
        switch (tag_no) {
11275
136
        case 0: /* recipient  */
11276
136
            tree = proto_tree_add_subtree_format(tree, tvb, offset, 1,
11277
136
              ett_bacapp_value, NULL, "Subscription %d", itemno);    /* add tree label and indent */
11278
136
            itemno = itemno + 1;
11279
11280
136
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
11281
136
              ett_bacapp_value, NULL, "Recipient: ");    /* add tree label and indent */
11282
136
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
11283
136
            offset = fRecipient(tvb, pinfo, subtree, offset);
11284
136
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
11285
136
            break;
11286
157
        case 1: /* process-identifier  */
11287
157
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Process Identifier: ");
11288
157
            break;
11289
284
        case 2: /* issue-confirmed-notifications  */
11290
284
            offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
11291
284
            break;
11292
57
        case 3: /* time-remaining  */
11293
57
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
11294
57
            break;
11295
86
        default:
11296
86
            return offset;
11297
720
        }
11298
720
    }
11299
11300
1
    return offset;
11301
92
}
11302
11303
static unsigned
11304
fLightingCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11305
216
{
11306
216
    unsigned   lastoffset = 0;
11307
216
    uint8_t tag_no, tag_info;
11308
216
    uint32_t lvt;
11309
216
    proto_tree *subtree = tree;
11310
11311
216
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11312
216
      ett_bacapp_value, NULL, "%s", lable);
11313
11314
3.62k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11315
3.61k
        lastoffset = offset;
11316
        /* check the tag.  A closing tag means we are done */
11317
3.61k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11318
3.61k
        if (tag_is_closing(tag_info)) {
11319
60
            return offset;
11320
60
        }
11321
3.55k
        switch (tag_no) {
11322
1.92k
        case 0: /* operation */
11323
1.92k
            offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "operation: ", BACnetLightingOperation);
11324
1.92k
            break;
11325
402
        case 1: /* target-level */
11326
402
            offset = fRealTag(tvb, pinfo, subtree, offset, "target-level: ");
11327
402
            break;
11328
345
        case 2: /* ramp-rate */
11329
345
            offset = fRealTag(tvb, pinfo, subtree, offset, "ramp-rate: ");
11330
345
            break;
11331
188
        case 3: /* step-increment */
11332
188
            offset = fRealTag(tvb, pinfo, subtree, offset, "step-increment: ");
11333
188
            break;
11334
302
        case 4: /* fade-time */
11335
302
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "fade-time: ");
11336
302
            break;
11337
254
        case 5: /* priority */
11338
254
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "priority: ");
11339
254
            break;
11340
141
        default:
11341
141
            return offset;
11342
3.55k
        }
11343
3.55k
    }
11344
11345
9
    return offset;
11346
216
}
11347
11348
static unsigned
11349
fColorCommand(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable)
11350
295
{
11351
295
    unsigned   lastoffset = 0;
11352
295
    uint8_t tag_no, tag_info;
11353
295
    uint32_t lvt;
11354
295
    proto_tree* subtree = tree;
11355
11356
295
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11357
295
        ett_bacapp_value, NULL, "%s", lable);
11358
11359
3.22k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11360
3.20k
        lastoffset = offset;
11361
        /* check the tag.  A closing tag means we are done */
11362
3.20k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11363
3.20k
        if (tag_is_closing(tag_info)) {
11364
27
            return offset;
11365
27
        }
11366
3.17k
        switch (tag_no) {
11367
1.60k
        case 0: /* operation */
11368
1.60k
            offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "operation: ", BACnetColorOperation);
11369
1.60k
            break;
11370
136
        case 1: /* target-color */
11371
136
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11372
136
            offset = fXyColor(tvb, pinfo, subtree, offset, "xy-color: ");
11373
136
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11374
136
            break;
11375
474
        case 2: /* target-color-temperature */
11376
474
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "target-color-temperature: ");
11377
474
            break;
11378
323
        case 3: /* fade-time */
11379
323
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "fade-time: ");
11380
323
            break;
11381
204
        case 4: /* ramp-rate */
11382
204
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "ramp-rate: ");
11383
204
            break;
11384
199
        case 5: /* step-increment */
11385
199
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "step-increment: ");
11386
199
            break;
11387
229
        default:
11388
229
            return offset;
11389
3.17k
        }
11390
3.17k
    }
11391
11392
21
    return offset;
11393
295
}
11394
11395
static unsigned
11396
fXyColor(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* label)
11397
310
{
11398
310
    proto_tree* subtree = tree;
11399
11400
310
    if (label != NULL) {
11401
310
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
11402
310
    }
11403
310
    offset = fRealTag(tvb, pinfo, subtree, offset, "x-coordinate: ");
11404
310
    return fRealTag(tvb, pinfo, subtree, offset, "y-coordinate: ");
11405
310
}
11406
11407
static unsigned
11408
// NOLINTNEXTLINE(misc-no-recursion)
11409
fTimerStateChangeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11410
77
{
11411
77
    unsigned   lastoffset = 0;
11412
77
    uint8_t tag_no, tag_info;
11413
77
    uint32_t lvt;
11414
77
    int32_t save_propertyIdentifier;
11415
77
    unsigned ftag_offset;
11416
11417
619
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11418
615
        lastoffset = offset;
11419
        /* check the tag. A closing tag means we are done */
11420
615
        ftag_offset = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11421
615
        if (tag_is_closing(tag_info)) {
11422
45
            return offset;
11423
45
        }
11424
570
        if (tag_is_context_specific(tag_info)){
11425
167
            switch (tag_no) {
11426
118
            case 0: /* no-value */
11427
118
                offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
11428
118
                break;
11429
6
            case 1: /* constructed-value */
11430
6
                offset += ftag_offset;
11431
                /* this ASN-1 construction may contain also an property identifier, so
11432
                   save the one we have got and restore it later and invalidate current
11433
                   one to avoid misinterpretations */
11434
6
                save_propertyIdentifier = propertyIdentifier;
11435
6
                propertyIdentifier = -1;
11436
6
                offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
11437
6
                propertyIdentifier = save_propertyIdentifier;
11438
6
                offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11439
6
                break;
11440
0
            case 2: /* date-time */
11441
0
                offset += ftag_offset;
11442
0
                offset = fDateTime(tvb, pinfo, tree, offset, "date-time: ");
11443
0
                offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11444
0
                break;
11445
17
            case 3: /* lighting-command */
11446
17
                offset += ftag_offset;
11447
17
                offset = fLightingCommand(tvb, pinfo, tree, offset, "lighting-command: ");
11448
17
                offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11449
17
                break;
11450
26
            default:
11451
26
                return offset;
11452
167
            }
11453
167
        }
11454
403
        else {
11455
403
            offset = fApplicationTypes(tvb, pinfo, tree, offset, NULL);
11456
403
        }
11457
570
    }
11458
4
    return offset;
11459
77
}
11460
11461
static unsigned
11462
fHostAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11463
777
{
11464
777
    uint8_t tag_no, tag_info;
11465
777
    uint32_t lvt;
11466
11467
777
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
11468
776
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11469
776
        switch (tag_no) {
11470
592
        case 0: /* none */
11471
592
            offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
11472
592
            break;
11473
19
        case 1: /* ip-address */
11474
19
            offset = fOctetString(tvb, pinfo, tree, offset, "ip-address: ", lvt);
11475
19
            break;
11476
24
        case 2: /* internet name (see RFC 1123) */
11477
24
            offset = fCharacterString(tvb, pinfo, tree, offset, "name: ");
11478
24
            break;
11479
140
        default:
11480
140
            return offset;
11481
776
        }
11482
776
    }
11483
11484
634
    return offset;
11485
777
}
11486
11487
static unsigned
11488
fHostNPort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11489
580
{
11490
580
    unsigned   lastoffset = 0;
11491
580
    uint8_t tag_no, tag_info;
11492
580
    uint32_t lvt;
11493
580
    proto_tree *subtree = tree;
11494
11495
580
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11496
580
        ett_bacapp_value, NULL, "%s", lable);
11497
11498
1.55k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11499
1.54k
        lastoffset = offset;
11500
        /* check the tag.  A closing tag means we are done */
11501
1.54k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11502
1.54k
        if (tag_is_closing(tag_info)) {
11503
46
            return offset;
11504
46
        }
11505
1.49k
        switch (tag_no) {
11506
777
        case 0: /* host */
11507
777
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11508
777
            offset = fHostAddress(tvb, pinfo, subtree, offset);
11509
777
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11510
777
            break;
11511
204
        case 1: /* port */
11512
204
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "port: ");
11513
204
            break;
11514
518
        default:
11515
518
            return offset;
11516
1.49k
        }
11517
1.49k
    }
11518
11519
10
    return offset;
11520
580
}
11521
11522
static unsigned
11523
fBDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11524
92
{
11525
92
    unsigned   lastoffset = 0;
11526
92
    uint8_t tag_no, tag_info;
11527
92
    uint32_t lvt;
11528
92
    proto_tree *subtree = tree;
11529
11530
92
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11531
92
                ett_bacapp_value, NULL, "%s", lable);
11532
11533
318
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11534
316
        lastoffset = offset;
11535
        /* check the tag.  A closing tag means we are done */
11536
316
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11537
316
        if (tag_is_closing(tag_info)) {
11538
9
            return offset;
11539
9
        }
11540
11541
307
        switch (tag_no) {
11542
199
        case 0: /* bbmd-address */
11543
199
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11544
199
            offset = fHostNPort(tvb, pinfo, subtree, offset, "bbmd-address: ");
11545
199
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11546
199
            break;
11547
32
        case 1: /* bbmd-mask */
11548
32
            offset = fOctetString(tvb, pinfo, subtree, offset, "bbmd-mask: ", lvt);
11549
32
            break;
11550
76
        default:
11551
76
            return offset;
11552
307
        }
11553
307
    }
11554
11555
2
    return offset;
11556
92
}
11557
11558
static unsigned
11559
fFDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11560
81
{
11561
81
    unsigned   lastoffset = 0;
11562
81
    uint8_t tag_no, tag_info;
11563
81
    uint32_t lvt;
11564
81
    proto_tree *subtree = tree;
11565
11566
81
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11567
81
                ett_bacapp_value, NULL, "%s", lable);
11568
11569
683
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11570
683
        lastoffset = offset;
11571
        /* check the tag.  A closing tag means we are done */
11572
683
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11573
683
        if (tag_is_closing(tag_info)) {
11574
1
            return offset;
11575
1
        }
11576
11577
682
        switch (tag_no) {
11578
337
        case 0: /* bacnetip-address */
11579
337
            offset = fOctetString(tvb, pinfo, subtree, offset, "bacnetip-address: ", lvt);
11580
337
            break;
11581
10
        case 1: /* time-to-live */
11582
10
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "time-to-live: ");
11583
10
            break;
11584
255
        case 2: /* remaining-time-to-live */
11585
255
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "remaining-time-to-live: ");
11586
255
            break;
11587
80
        default:
11588
80
            return offset;
11589
682
        }
11590
682
    }
11591
11592
0
  return offset;
11593
81
}
11594
11595
static unsigned
11596
fRouterEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11597
46
{
11598
46
    unsigned   lastoffset = 0;
11599
46
    uint8_t tag_no, tag_info;
11600
46
    uint32_t lvt;
11601
11602
718
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11603
717
        lastoffset = offset;
11604
        /* check the tag.  A closing tag means we are done */
11605
717
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11606
717
        if (tag_is_closing(tag_info)) {
11607
26
            break;
11608
26
        }
11609
691
        switch (tag_no) {
11610
151
        case 0: /* network number */
11611
151
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "network number: ");
11612
151
            break;
11613
334
        case 1: /* MAC address */
11614
334
            offset = fOctetString(tvb, pinfo, tree, offset, "MAC address: ", lvt);
11615
334
            break;
11616
155
        case 2: /* status */
11617
155
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "status: ", BACnetRouterStatus);
11618
155
            break;
11619
37
        case 3: /* performance index */
11620
37
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "performance index: ");
11621
37
            break;
11622
14
        default:
11623
14
            return offset;
11624
691
        }
11625
672
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11626
672
    }
11627
11628
27
    return offset;
11629
46
}
11630
11631
static unsigned
11632
fVMACEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11633
24
{
11634
24
    unsigned   lastoffset = 0;
11635
24
    uint8_t tag_no, tag_info;
11636
24
    uint32_t lvt;
11637
11638
105
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11639
104
        lastoffset = offset;
11640
        /* check the tag.  A closing tag means we are done */
11641
104
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11642
104
        if (tag_is_closing(tag_info)) {
11643
0
            break;
11644
0
        }
11645
104
        switch (tag_no) {
11646
59
        case 0: /* virtual mac address */
11647
59
            offset = fOctetString(tvb, pinfo, tree, offset, "virtual MAC address: ", lvt);
11648
59
            break;
11649
22
        case 1: /* native mac address */
11650
22
            offset = fOctetString(tvb, pinfo, tree, offset, "native MAC address: ", lvt);
11651
22
            break;
11652
23
        default:
11653
23
            return offset;
11654
104
        }
11655
81
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11656
81
  }
11657
11658
1
  return offset;
11659
24
}
11660
11661
static unsigned
11662
fValueSource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11663
605
{
11664
605
    uint8_t tag_no, tag_info;
11665
605
    uint32_t lvt;
11666
11667
605
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
11668
605
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11669
605
        switch (tag_no) {
11670
410
        case 0: /* null */
11671
410
            offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
11672
410
            break;
11673
41
        case 1: /* object reference */
11674
41
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11675
41
            offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
11676
41
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11677
41
            break;
11678
62
        case 2: /* address */
11679
62
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11680
62
            offset = fAddress(tvb, pinfo, tree, offset);
11681
62
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11682
62
            break;
11683
92
        default:
11684
92
            return offset;
11685
605
        }
11686
605
    }
11687
11688
504
  return offset;
11689
605
}
11690
11691
static unsigned
11692
fAssignedLandingCalls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11693
2.71k
{
11694
2.71k
    unsigned   lastoffset = 0;
11695
2.71k
    uint8_t tag_no, tag_info;
11696
2.71k
    uint32_t lvt;
11697
11698
2.71k
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11699
11700
3.70k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11701
3.69k
        lastoffset = offset;
11702
        /* check the tag.  A closing tag means we are done */
11703
3.69k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11704
3.69k
        if (tag_is_closing(tag_info)) {
11705
58
            break;
11706
58
        }
11707
3.63k
        switch (tag_no) {
11708
816
        case 0: /* floor number */
11709
816
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
11710
816
            break;
11711
175
        case 1: /* direction */
11712
175
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "direction: ", BACnetLiftCarDirection);
11713
175
            break;
11714
2.64k
        default:
11715
2.64k
            return offset;
11716
3.63k
        }
11717
987
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11718
987
    }
11719
11720
71
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11721
71
    return offset;
11722
2.71k
}
11723
11724
static unsigned
11725
fLandingCallStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11726
178
{
11727
178
    unsigned   lastoffset = 0;
11728
178
    uint8_t tag_no, tag_info;
11729
178
    uint32_t lvt;
11730
11731
1.87k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11732
1.86k
        lastoffset = offset;
11733
        /* check the tag.  A closing tag means we are done */
11734
1.86k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11735
1.86k
        if (tag_is_closing(tag_info)) {
11736
29
            break;
11737
29
        }
11738
1.83k
        switch (tag_no) {
11739
982
        case 0: /* floor number */
11740
982
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
11741
982
            break;
11742
484
        case 1: /* direction */
11743
484
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "direction: ", BACnetLiftCarDirection);
11744
484
            break;
11745
123
        case 2: /* destination */
11746
123
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "destination: ");
11747
123
            break;
11748
107
        case 3: /* floor-text */
11749
107
            offset = fCharacterString(tvb, pinfo, tree, offset, "floor-text: ");
11750
107
            break;
11751
143
        default:
11752
143
            return offset;
11753
1.83k
        }
11754
1.69k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11755
1.69k
    }
11756
11757
32
    return offset;
11758
178
}
11759
11760
static unsigned
11761
fLandingDoorStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11762
677
{
11763
677
    unsigned   lastoffset = 0;
11764
677
    uint8_t tag_no, tag_info;
11765
677
    uint32_t lvt;
11766
11767
677
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11768
11769
1.10k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11770
1.10k
        lastoffset = offset;
11771
        /* check the tag.  A closing tag means we are done */
11772
1.10k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11773
1.10k
        if (tag_is_closing(tag_info)) {
11774
46
            break;
11775
46
        }
11776
1.05k
        switch (tag_no) {
11777
380
        case 0: /* floor number */
11778
380
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
11779
380
            break;
11780
50
        case 1: /* door status */
11781
50
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "door status: ", BACnetDoorStatus);
11782
50
            break;
11783
626
        default:
11784
626
            return offset;
11785
1.05k
        }
11786
427
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11787
427
    }
11788
11789
48
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11790
48
    return offset;
11791
677
}
11792
11793
static unsigned
11794
fCOVMultipleSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11795
444
{
11796
444
    unsigned   lastoffset = 0;
11797
444
    uint8_t tag_no, tag_info;
11798
444
    uint32_t lvt;
11799
11800
973
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11801
969
        lastoffset = offset;
11802
        /* check the tag.  A closing tag means we are done */
11803
969
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11804
969
        if (tag_is_closing(tag_info)) {
11805
9
            break;
11806
9
        }
11807
960
        switch (tag_no) {
11808
103
        case 0: /* recipient */
11809
103
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11810
103
            offset = fRecipientProcess(tvb, pinfo, tree, offset);
11811
103
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11812
103
            break;
11813
96
        case 1: /* issue-confirmed-notifications */
11814
96
            offset = fBooleanTag(tvb, pinfo, tree, offset, "issue confirmed notifications: ");
11815
96
            break;
11816
146
        case 2: /* time-remaining */
11817
146
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "time remaining: ");
11818
146
            break;
11819
181
        case 3: /* max-notification-delay */
11820
181
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "max notification delay: ");
11821
181
            break;
11822
386
        case 4: /* list-of-cov-subscription-specifications */
11823
386
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11824
666
            while (tvb_reported_length_remaining(tvb, offset) > 0) {
11825
662
                lastoffset = offset;
11826
                /* check the tag.  A closing tag means we are done */
11827
662
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11828
662
                if (tag_is_closing(tag_info)) {
11829
10
                    break;
11830
10
                }
11831
652
                switch (tag_no) {
11832
273
                case 0: /* monitored-object-identifier */
11833
273
                    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
11834
273
                    break;
11835
16
                case 1: /* list-of-cov-references */
11836
16
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11837
141
                    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11838
141
                    lastoffset = offset;
11839
                    /* check the tag.  A closing tag means we are done */
11840
141
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11841
141
                    if (tag_is_closing(tag_info)) {
11842
8
                        break;
11843
8
                    }
11844
133
                    switch (tag_no) {
11845
51
                    case 0: /* monitored-property */
11846
51
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11847
51
                        offset = fBACnetPropertyReference(tvb, pinfo, tree, offset, 0);
11848
51
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11849
51
                        break;
11850
11
                    case 1: /* cov-increment */
11851
11
                        offset = fRealTag(tvb, pinfo, tree, offset, "cov-increment: ");
11852
11
                        break;
11853
63
                    case 2: /* timestamped */
11854
63
                        offset = fBooleanTag(tvb, pinfo, tree, offset, "timestamped: ");
11855
63
                        break;
11856
8
                    default:
11857
8
                        return offset;
11858
133
                    }
11859
125
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11860
125
                    }
11861
8
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11862
8
                    break;
11863
363
                default:
11864
363
                    return offset;
11865
652
                }
11866
280
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11867
280
            }
11868
14
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11869
14
            break;
11870
48
        default:
11871
48
            return offset;
11872
960
        }
11873
529
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11874
529
    }
11875
11876
13
    return offset;
11877
444
}
11878
11879
static unsigned
11880
fNameValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11881
2.07k
{
11882
2.07k
    unsigned   lastoffset = 0;
11883
2.07k
    uint8_t tag_no, tag_info;
11884
2.07k
    uint32_t lvt;
11885
11886
4.79k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11887
4.78k
        lastoffset = offset;
11888
        /* check the tag.  A closing tag means we are done */
11889
4.78k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11890
4.78k
        if (tag_is_closing(tag_info)) {
11891
57
            break;
11892
57
        }
11893
4.72k
        if (tag_is_context_specific(tag_info)) {
11894
1.96k
            switch (tag_no) {
11895
52
            case 0: /* name */
11896
52
            offset = fCharacterString(tvb, pinfo, tree, offset, "name: ");
11897
52
            break;
11898
29
            case 1: /* date+time value */
11899
29
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11900
29
            offset = fDateTime(tvb, pinfo, tree, offset, "value: ");
11901
29
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11902
29
            break;
11903
1.88k
            default: /* abstract syntax and type */
11904
            /* DMR Should be fAbstractNSyntax, but that's where we came from! */
11905
1.88k
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "value: ");
11906
1.88k
            break;
11907
1.96k
            }
11908
1.96k
        }
11909
2.75k
        else {
11910
            /* DMR Should be fAbstractNSyntax, but that's where we came from! */
11911
2.75k
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "value: ");
11912
2.75k
        }
11913
4.71k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11914
4.71k
    }
11915
2.06k
    return offset;
11916
2.07k
}
11917
11918
static unsigned
11919
fNameValueCollection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11920
1.84k
{
11921
1.84k
    unsigned   lastoffset = 0;
11922
1.84k
    uint8_t tag_no, tag_info;
11923
1.84k
    uint32_t lvt;
11924
1.84k
    proto_tree *subtree = tree;
11925
11926
1.84k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11927
1.84k
            ett_bacapp_value, NULL, "%s", "name-value-collection: ");
11928
11929
1.84k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11930
11931
3.92k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11932
2.15k
        lastoffset = offset;
11933
        /* check the tag.  A closing tag means we are done */
11934
2.15k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11935
2.15k
        if (tag_is_closing(tag_info)) {
11936
76
            break;
11937
76
        }
11938
11939
2.07k
        offset = fNameValue(tvb, pinfo, subtree, offset);
11940
2.07k
    }
11941
11942
1.84k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11943
1.84k
    return offset;
11944
1.84k
}
11945
11946
static unsigned
11947
fObjectSelector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11948
0
{
11949
0
    unsigned   lastoffset = 0;
11950
0
    uint8_t tag_no, tag_info;
11951
0
    uint32_t lvt;
11952
11953
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
11954
0
        lastoffset = offset;
11955
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11956
0
        if (tag_is_closing(tag_info)) {
11957
0
            break;
11958
0
        }
11959
11960
0
        switch (tag_no) {
11961
0
        case 0: /* NULL */
11962
0
            offset = fNullTag(tvb, pinfo, tree, offset, "NULL: ");
11963
0
            break;
11964
0
        case 9: /* object-type */
11965
0
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, "object-type: ", BACnetObjectType, 256);
11966
0
            break;
11967
0
        case 12: /* object */
11968
0
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
11969
0
            break;
11970
0
        default:
11971
0
            break;
11972
0
        }
11973
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11974
0
    }
11975
0
    return offset;
11976
0
}
11977
11978
static unsigned
11979
fDeviceAddressProxyTableEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11980
0
{
11981
0
    unsigned   lastoffset = 0;
11982
0
    uint8_t tag_no, tag_info;
11983
0
    uint32_t lvt;
11984
0
    proto_tree *subtree = tree;
11985
11986
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11987
0
                ett_bacapp_value, NULL, "%s", lable);
11988
11989
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11990
0
        lastoffset = offset;
11991
        /* check the tag.  A closing tag means we are done */
11992
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11993
0
        if (tag_is_closing(tag_info)) {
11994
0
            return offset;
11995
0
        }
11996
11997
0
        switch (tag_no) {
11998
0
        case 0: /* address */
11999
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12000
0
            offset = fAddress(tvb, pinfo, subtree, offset);
12001
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12002
0
            break;
12003
0
        case 1: /* i-am */
12004
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12005
0
            offset = fIAmRequest(tvb, pinfo, subtree, offset);
12006
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12007
0
            break;
12008
0
        case 2: /* last-i-am-time */
12009
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12010
0
            offset = fDateTime(tvb, pinfo, subtree, offset, "issued: ");
12011
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12012
0
            break;
12013
0
        default:
12014
0
            break;
12015
0
        }
12016
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12017
0
    }
12018
12019
0
    return offset;
12020
0
}
12021
12022
static unsigned
12023
fAccessToken(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12024
493
{
12025
493
    unsigned   lastoffset = 0;
12026
493
    uint8_t tag_no, tag_info;
12027
493
    uint32_t lvt;
12028
493
    proto_tree *subtree = tree;
12029
493
    proto_tree *subsubtree = tree;
12030
12031
493
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12032
493
                ett_bacapp_value, NULL, "%s", lable);
12033
12034
8.82k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12035
8.78k
        lastoffset = offset;
12036
        /* check the tag.  A closing tag means we are done */
12037
8.78k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12038
8.78k
        if (tag_is_closing(tag_info)) {
12039
166
            return offset;
12040
166
        }
12041
12042
8.62k
        switch (tag_no) {
12043
5.05k
        case 0: /* issuer */
12044
5.05k
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "issuer: ");
12045
5.05k
            break;
12046
269
        case 1: /* issued */
12047
269
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12048
269
            offset = fDateTime(tvb, pinfo, subtree, offset, "issued: ");
12049
269
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12050
269
            break;
12051
193
        case 2: /* audience */
12052
193
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12053
193
            subsubtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12054
193
                      ett_bacapp_value, NULL, "%s", "audience:");
12055
12056
3.80k
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12057
3.77k
                lastoffset = offset;
12058
                /* check the tag.  A closing tag means we are done */
12059
3.77k
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12060
3.77k
                if (tag_is_closing(tag_info)) {
12061
159
                    break;
12062
159
                }
12063
12064
3.61k
                offset = fSignedTag(tvb, pinfo, subsubtree, offset, "listener: ");
12065
3.61k
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12066
3.61k
            }
12067
193
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12068
193
            break;
12069
847
        case 3: /* not-before */
12070
847
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12071
847
            offset = fDateTime(tvb, pinfo, subtree, offset, "not-before: ");
12072
847
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12073
847
            break;
12074
264
        case 4: /* not-after */
12075
264
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12076
264
            offset = fDateTime(tvb, pinfo, subtree, offset, "not-after: ");
12077
264
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12078
264
            break;
12079
191
        case 5: /* client */
12080
191
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "client: ");
12081
191
            break;
12082
326
        case 6: /* constraint */
12083
326
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12084
326
            offset = fAuthorizationConstraint(tvb, pinfo, subtree, offset, "constraint: ");
12085
326
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12086
326
            break;
12087
125
        case 7: /* scope */
12088
125
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12089
125
            offset = fAuthorizationScope(tvb, pinfo, subtree, offset, "scope: ");
12090
125
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12091
125
            break;
12092
718
        case 8: /* key-id */
12093
718
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "key-id: ");
12094
718
            break;
12095
436
        case 9: /* signature */
12096
436
            offset = fOctetString(tvb, pinfo, subtree, offset, "signature", lvt);
12097
436
            break;
12098
201
        default:
12099
201
            break;
12100
8.62k
        }
12101
8.52k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12102
8.52k
    }
12103
12104
234
    return offset;
12105
493
}
12106
12107
unsigned
12108
bacnet_dissect_token(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
12109
    unsigned offset, const char *lable)
12110
0
{
12111
0
    return fAccessToken(tvb, pinfo, tree, offset, lable);
12112
0
}
12113
12114
static unsigned
12115
fAuthenticationClient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12116
70
{
12117
70
    unsigned   lastoffset = 0;
12118
70
    uint8_t tag_no, tag_info;
12119
70
    uint32_t lvt;
12120
70
    proto_tree *subtree = tree;
12121
12122
70
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12123
70
                ett_bacapp_value, NULL, "%s", lable);
12124
12125
1.41k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12126
1.40k
        lastoffset = offset;
12127
        /* check the tag.  A closing tag means we are done */
12128
1.40k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12129
1.40k
        if (tag_is_closing(tag_info)) {
12130
57
            return offset;
12131
57
        }
12132
12133
1.34k
        offset = fBooleanTag(tvb, pinfo, subtree, offset, "authenticated: ");
12134
1.34k
        offset = fUnsignedTag(tvb, pinfo, subtree, offset, "device: ");
12135
1.34k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12136
1.34k
    }
12137
12138
13
    return offset;
12139
70
}
12140
12141
static unsigned
12142
fAuthorizationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12143
838
{
12144
838
    unsigned   lastoffset = 0;
12145
838
    uint8_t tag_no, tag_info;
12146
838
    uint32_t lvt;
12147
838
    proto_tree *subtree = tree;
12148
12149
838
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12150
838
                ett_bacapp_value, NULL, "%s", lable);
12151
12152
1.86k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12153
1.86k
        lastoffset = offset;
12154
        /* check the tag.  A closing tag means we are done */
12155
1.86k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12156
1.86k
        if (tag_is_closing(tag_info)) {
12157
25
            return offset;
12158
25
        }
12159
12160
1.84k
        switch (tag_no) {
12161
643
        case 0: /* time-stamp */
12162
643
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12163
643
            offset = fDateTime(tvb, pinfo, subtree, offset, "time-stamp: ");
12164
643
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12165
643
            break;
12166
71
        case 1: /* address */
12167
71
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12168
71
            offset = fAddress(tvb, pinfo, subtree, offset);
12169
71
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12170
71
            break;
12171
28
        case 2: /* client */
12172
28
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12173
28
            offset = fAuthenticationClient(tvb, pinfo, subtree, offset, "client: ");
12174
28
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12175
28
            break;
12176
148
        case 3: /* token */
12177
148
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12178
148
            offset = fAccessToken(tvb, pinfo, subtree, offset, "token: ");
12179
148
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12180
148
            break;
12181
137
        case 4: /* decision */
12182
137
            offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "decision: ", BACnetAuthorizationDecision);
12183
137
            break;
12184
111
        case 5: /* decision-details */
12185
111
            offset = fCharacterString(tvb, pinfo, subtree, offset, "decision-details: ");
12186
111
            break;
12187
706
        default:
12188
706
            break;
12189
1.84k
        }
12190
1.81k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12191
1.81k
    }
12192
12193
782
    return offset;
12194
838
}
12195
12196
static unsigned
12197
fAuthenticationPeer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12198
33
{
12199
33
    unsigned   lastoffset = 0;
12200
33
    uint8_t tag_no, tag_info;
12201
33
    uint32_t lvt;
12202
33
    proto_tree *subtree = tree;
12203
12204
33
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12205
33
                ett_bacapp_value, NULL, "%s", lable);
12206
12207
483
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12208
482
        lastoffset = offset;
12209
        /* check the tag.  A closing tag means we are done */
12210
482
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12211
482
        if (tag_is_closing(tag_info)) {
12212
16
            return offset;
12213
16
        }
12214
12215
466
        switch (tag_no) {
12216
173
        case 0: /* host */
12217
173
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12218
173
            offset = fHostNPort(tvb, pinfo, subtree, offset, "host: ");
12219
173
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12220
173
            break;
12221
293
        default:
12222
293
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "device: ");
12223
293
            offset = fBooleanTag(tvb, pinfo, subtree, offset, "auth-aware: ");
12224
293
            offset = fBooleanTag(tvb, pinfo, subtree, offset, "router: ");
12225
293
            offset = fBooleanTag(tvb, pinfo, subtree, offset, "hub: ");
12226
293
            break;
12227
466
        }
12228
450
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12229
450
    }
12230
12231
1
    return offset;
12232
33
}
12233
12234
static unsigned
12235
fAuthenticationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12236
293
{
12237
293
    unsigned   lastoffset = 0;
12238
293
    uint8_t tag_no, tag_info;
12239
293
    uint32_t lvt;
12240
293
    proto_tree *subtree = tree;
12241
12242
293
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12243
293
                ett_bacapp_value, NULL, "%s", lable);
12244
12245
877
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12246
876
        lastoffset = offset;
12247
        /* check the tag.  A closing tag means we are done */
12248
876
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12249
876
        if (tag_is_closing(tag_info)) {
12250
15
            return offset;
12251
15
        }
12252
12253
861
        switch (tag_no) {
12254
254
    case 0: /* time-stamp */
12255
254
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12256
254
      offset = fDateTime(tvb, pinfo, subtree, offset, "time-stamp: ");
12257
254
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12258
254
            break;
12259
33
    case 1: /* peer */
12260
33
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12261
33
      offset = fAuthenticationPeer(tvb, pinfo, subtree, offset, "peer: ");
12262
33
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12263
33
            break;
12264
42
    case 2: /* client */
12265
42
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12266
42
      offset = fAuthenticationClient(tvb, pinfo, subtree, offset, "client: ");
12267
42
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12268
42
            break;
12269
236
    case 3: /* decision */
12270
236
      offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "decision: ", BACnetAuthenticationDecision);
12271
236
            break;
12272
53
    case 4: /* decision-details */
12273
53
      offset = fCharacterString(tvb, pinfo, subtree, offset, "decision-details: ");
12274
53
            break;
12275
243
        default:
12276
243
            break;
12277
861
        }
12278
832
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12279
832
    }
12280
12281
249
    return offset;
12282
293
}
12283
12284
static unsigned
12285
fAuthorizationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12286
1
{
12287
1
    unsigned   lastoffset = 0;
12288
1
    uint8_t tag_no, tag_info;
12289
1
    uint32_t lvt;
12290
1
    proto_tree *subtree = tree;
12291
1
    proto_tree *subsubtree = tree;
12292
12293
1
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12294
1
                ett_bacapp_value, NULL, "%s", lable);
12295
12296
1
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12297
1
        lastoffset = offset;
12298
        /* check the tag.  A closing tag means we are done */
12299
1
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12300
1
        if (tag_is_closing(tag_info)) {
12301
0
            return offset;
12302
0
        }
12303
12304
1
        switch (tag_no) {
12305
0
        case 0: /* not-before */
12306
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12307
0
      offset = fDateTime(tvb, pinfo, subtree, offset, "not-before: ");
12308
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12309
0
            break;
12310
0
        case 1: /* not-after */
12311
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12312
0
      offset = fDateTime(tvb, pinfo, subtree, offset, "not-after: ");
12313
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12314
0
            break;
12315
0
        case 2: /* clients */
12316
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12317
0
      subsubtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12318
0
                ett_bacapp_value, NULL, "%s", "clients:");
12319
12320
0
      while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12321
0
        lastoffset = offset;
12322
        /* check the tag.  A closing tag means we are done */
12323
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12324
0
        if (tag_is_closing(tag_info)) {
12325
0
          break;
12326
0
        }
12327
12328
0
                offset = fApplicationTypes(tvb, pinfo, subsubtree, offset, "client: ");
12329
0
      }
12330
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12331
0
            break;
12332
0
        case 3: /* constraint */
12333
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12334
0
      offset = fAuthorizationConstraint(tvb, pinfo, subtree, offset, "constraint: ");
12335
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12336
0
            break;
12337
0
        case 4: /* scope */
12338
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12339
0
      offset = fAuthorizationScope(tvb, pinfo, subtree, offset, "scope: ");
12340
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12341
0
            break;
12342
1
        default:
12343
1
            break;
12344
1
        }
12345
1
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12346
1
    }
12347
12348
1
    return offset;
12349
1
}
12350
12351
static unsigned
12352
fAuthorizationConstraint(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12353
326
{
12354
326
    unsigned   lastoffset = 0;
12355
326
    uint8_t tag_no, tag_info;
12356
326
    uint32_t lvt;
12357
326
    proto_tree *subtree = tree;
12358
12359
326
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12360
326
                ett_bacapp_value, NULL, "%s", lable);
12361
12362
1.01k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12363
1.00k
        lastoffset = offset;
12364
        /* check the tag.  A closing tag means we are done */
12365
1.00k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12366
1.00k
        if (tag_is_closing(tag_info)) {
12367
49
            return offset;
12368
49
        }
12369
12370
955
    offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "origin: ", BACnetAuthorizationConstraintOrigin);
12371
955
    offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "authentication: ", BACnetAuthorizationConstraintAuthentication);
12372
955
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12373
955
    }
12374
12375
277
    return offset;
12376
326
}
12377
12378
static unsigned
12379
fAuthorizationScope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12380
192
{
12381
192
    unsigned   lastoffset = 0, len;
12382
192
    uint8_t tag_no, tag_info;
12383
192
    uint32_t lvt;
12384
192
    proto_tree *subtree = tree;
12385
192
    proto_tree *subsubtree = tree;
12386
12387
192
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12388
192
                ett_bacapp_value, NULL, "%s", lable);
12389
12390
795
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12391
791
        lastoffset = offset;
12392
        /* check the tag.  A closing tag means we are done */
12393
791
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12394
791
        if (tag_is_closing(tag_info)) {
12395
41
            return offset;
12396
41
        }
12397
12398
750
        switch (tag_no) {
12399
139
        case 0: /* extended */
12400
139
            if (tag_is_opening(tag_info)) {
12401
12
                subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "extended: ");
12402
12
                offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
12403
12404
162
                while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {  /* exit loop if nothing happens inside */
12405
155
                    lastoffset = offset;
12406
155
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12407
155
                    if (tag_is_closing(tag_info)) {
12408
5
                        fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
12409
5
                        offset += len;
12410
5
                        break;
12411
5
                    }
12412
12413
150
                    offset = fCharacterString(tvb, pinfo, subsubtree, offset, "scope: ");
12414
150
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12415
150
                }
12416
127
            } else {
12417
127
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
12418
127
            }
12419
139
            break;
12420
611
        default: /* standard */
12421
611
            offset = fBitStringTagVS(tvb, pinfo, subtree, offset, "standard: ", BACnetAuthorizationScopeStandard);
12422
611
            break;
12423
750
        }
12424
730
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12425
730
    }
12426
12427
131
    return offset;
12428
192
}
12429
12430
unsigned
12431
bacnet_dissect_scope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
12432
    unsigned offset, const char *lable)
12433
0
{
12434
0
    return fAuthorizationScope(tvb, pinfo, tree, offset, lable);
12435
0
}
12436
12437
static unsigned
12438
fAuthorizationScopeDescription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12439
0
{
12440
0
    unsigned   lastoffset = 0;
12441
0
    uint8_t tag_no, tag_info;
12442
0
    uint32_t lvt;
12443
0
    proto_tree *subtree = tree;
12444
12445
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12446
0
                ett_bacapp_value, NULL, "%s", lable);
12447
12448
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12449
0
    lastoffset = offset;
12450
        /* check the tag.  A closing tag means we are done */
12451
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12452
0
        if (tag_is_closing(tag_info)) {
12453
0
            return offset;
12454
0
        }
12455
12456
0
        offset = fCharacterString(tvb, pinfo, subtree, offset, "name: ");
12457
0
        offset = fCharacterString(tvb, pinfo, subtree, offset, "description: ");
12458
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12459
0
    }
12460
12461
0
    return offset;
12462
0
}
12463
12464
static unsigned
12465
fAuthorizationServer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12466
0
{
12467
0
    unsigned   lastoffset = 0;
12468
0
    uint8_t tag_no, tag_info;
12469
0
    uint32_t lvt;
12470
0
    proto_tree *subtree = tree;
12471
12472
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12473
0
                ett_bacapp_value, NULL, "%s", lable);
12474
12475
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12476
0
        lastoffset = offset;
12477
        /* check the tag.  A closing tag means we are done */
12478
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12479
0
        if (tag_is_closing(tag_info)) {
12480
0
            return offset;
12481
0
        }
12482
12483
0
        switch (tag_no) {
12484
0
        case 0: /* auth-server */
12485
0
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "auth-server: ");
12486
0
            break;
12487
0
        case 1: /* signing-key #1 */
12488
0
            offset = fOctetString(tvb, pinfo, subtree, offset, "signing-key #1: ", lvt);
12489
0
            break;
12490
0
        case 2: /* signing-key #2 */
12491
0
            offset = fOctetString(tvb, pinfo, subtree, offset, "signing-key #2: ", lvt);
12492
0
            break;
12493
0
        default:
12494
0
            break;
12495
0
        }
12496
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12497
0
    }
12498
12499
0
    return offset;
12500
0
}
12501
12502
static unsigned
12503
fAuthorizationStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12504
173
{
12505
173
    unsigned   lastoffset = 0;
12506
173
    uint8_t tag_no, tag_info;
12507
173
    uint32_t lvt;
12508
173
    proto_tree *subtree = tree;
12509
12510
173
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12511
173
                ett_bacapp_value, NULL, "%s", lable);
12512
12513
1.62k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12514
1.62k
        lastoffset = offset;
12515
        /* check the tag.  A closing tag means we are done */
12516
1.62k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12517
1.62k
        if (tag_is_closing(tag_info)) {
12518
19
            return offset;
12519
19
        }
12520
12521
1.60k
        switch (tag_no) {
12522
426
        case 0: /* posture */
12523
426
            offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "posture: ", BACnetAuthorizationPosture);
12524
426
            break;
12525
34
        case 1: /* error */
12526
34
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12527
34
            offset = fError(tvb, pinfo, subtree, offset);
12528
34
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12529
34
            break;
12530
35
        case 2: /* error-source */
12531
35
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12532
35
            offset = fObjectPropertyReference(tvb, pinfo, subtree, offset);
12533
35
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12534
35
            break;
12535
75
        case 3: /* error-details */
12536
75
            offset = fCharacterString(tvb, pinfo, subtree, offset, "error-details: ");
12537
75
            break;
12538
86
        case 4: /* authentication-success */
12539
86
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12540
150
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12541
123
                lastoffset = offset;
12542
                /* check the tag.  A closing tag means we are done */
12543
123
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12544
123
                if (tag_is_closing(tag_info)) {
12545
16
                    break;
12546
16
                }
12547
12548
107
                offset = fAuthenticationEvent(tvb, pinfo, subtree, offset, "authentication-success");
12549
107
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12550
107
            }
12551
86
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12552
86
            break;
12553
172
        case 5: /* authentication-failure */
12554
172
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12555
192
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12556
189
                lastoffset = offset;
12557
                /* check the tag.  A closing tag means we are done */
12558
189
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12559
189
                if (tag_is_closing(tag_info)) {
12560
3
                    break;
12561
3
                }
12562
12563
186
                offset = fAuthenticationEvent(tvb, pinfo, subtree, offset, "authentication-failure");
12564
186
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12565
186
            }
12566
172
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12567
172
            break;
12568
130
        case 6: /* authorization-success */
12569
130
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12570
160
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12571
159
                lastoffset = offset;
12572
                /* check the tag.  A closing tag means we are done */
12573
159
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12574
159
                if (tag_is_closing(tag_info)) {
12575
8
                    break;
12576
8
                }
12577
12578
151
                offset = fAuthorizationEvent(tvb, pinfo, subtree, offset, "authorization-success");
12579
151
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12580
151
            }
12581
130
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12582
130
            break;
12583
591
        case 7: /* authorization-failure */
12584
591
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12585
745
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12586
714
                lastoffset = offset;
12587
                /* check the tag.  A closing tag means we are done */
12588
714
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12589
714
                if (tag_is_closing(tag_info)) {
12590
27
                    break;
12591
27
                }
12592
12593
687
                offset = fAuthorizationEvent(tvb, pinfo, subtree, offset, "authorization-failure");
12594
687
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12595
687
            }
12596
591
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12597
591
            break;
12598
56
        default:
12599
56
            break;
12600
1.60k
        }
12601
1.53k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12602
1.53k
    }
12603
12604
81
    return offset;
12605
173
}
12606
12607
static unsigned
12608
fStageLimitValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12609
3
{
12610
3
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
12611
0
        return offset;
12612
3
    offset = fRealTag(tvb, pinfo, tree, offset, "limit: ");
12613
3
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
12614
1
        return offset;
12615
2
    offset = fBitStringTag(tvb, pinfo, tree, offset, "values: ");
12616
2
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
12617
0
        return offset;
12618
2
    offset = fRealTag(tvb, pinfo, tree, offset, "deadband: ");
12619
2
    return offset;
12620
2
}
12621
12622
static unsigned
12623
fLifeSafetyInfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12624
0
{
12625
0
    unsigned   lastoffset = 0;
12626
0
    uint8_t tag_no, tag_info;
12627
0
    uint32_t lvt;
12628
12629
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12630
0
        lastoffset = offset;
12631
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12632
0
        if (tag_is_closing(tag_info)) {
12633
0
            break;
12634
0
        }
12635
12636
0
        switch (tag_no) {
12637
0
        case 0: /* requesting-process-identifier */
12638
0
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "requesting-process-identifier: ");
12639
0
            break;
12640
0
        case 1: /* request */
12641
0
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
12642
0
                "requested-operation: ", BACnetLifeSafetyOperation, 64);
12643
0
            break;
12644
0
        default:
12645
0
            break;
12646
0
        }
12647
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12648
0
    }
12649
0
    return offset;
12650
0
}
12651
12652
static unsigned
12653
fAcknowledgeAlarmInfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12654
0
{
12655
0
    unsigned   lastoffset = 0;
12656
0
    uint8_t tag_no, tag_info;
12657
0
    uint32_t lvt;
12658
12659
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12660
0
        lastoffset = offset;
12661
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12662
0
        if (tag_is_closing(tag_info)) {
12663
0
            break;
12664
0
        }
12665
12666
0
        switch (tag_no) {
12667
0
        case 0: /* event-state-acknowledged */
12668
0
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
12669
0
                "event-state-acknowledged: ", BACnetEventState, 64);
12670
0
            break;
12671
0
        case 1: /* timestamp */
12672
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12673
0
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "source-timestamp: ");
12674
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12675
0
            break;
12676
0
        default:
12677
0
            break;
12678
0
        }
12679
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12680
0
    }
12681
0
    return offset;
12682
0
}
12683
12684
static unsigned
12685
// NOLINTNEXTLINE(misc-no-recursion)
12686
fAuditNotificationInfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12687
1.59k
{
12688
1.59k
    unsigned   len, lastoffset = 0;
12689
1.59k
    uint8_t tag_no, tag_info;
12690
1.59k
    uint32_t lvt;
12691
1.59k
    uint32_t operation = 0;
12692
1.59k
    proto_tree *subtree = tree;
12693
12694
25.2k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12695
24.9k
        lastoffset = offset;
12696
24.9k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12697
24.9k
        if (tag_is_closing(tag_info)) {
12698
311
            break;
12699
311
        }
12700
12701
24.6k
        switch (tag_no) {
12702
6.39k
        case 0: /* source-timestamp */
12703
6.39k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12704
6.39k
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "source-timestamp: ");
12705
6.39k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12706
6.39k
            break;
12707
1.32k
        case 1: /* target-timestamp */
12708
1.32k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12709
1.32k
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "target-timestamp: ");
12710
1.32k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12711
1.32k
            break;
12712
1.88k
        case 2: /* source-device */
12713
1.88k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "source-device: ");
12714
1.88k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12715
1.88k
            offset = fRecipient(tvb, pinfo, subtree, offset);
12716
1.88k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12717
1.88k
            break;
12718
653
        case 3: /* source-object */
12719
653
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "source-object: ");
12720
653
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
12721
653
            break;
12722
1.67k
        case 4: /* operation */
12723
1.67k
            fUnsigned32(tvb, offset, lvt, &operation);
12724
1.67k
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
12725
1.67k
                  "operation: ", BACnetAuditOperation, 64);
12726
1.67k
            break;
12727
763
        case 5: /* source-comment */
12728
763
            offset  = fCharacterString(tvb, pinfo, tree, offset, "source-comment: ");
12729
763
            break;
12730
1.12k
        case 6: /* target-comment */
12731
1.12k
            offset  = fCharacterString(tvb, pinfo, tree, offset, "target-comment: ");
12732
1.12k
            break;
12733
898
        case 7: /* invoke-id */
12734
898
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "invoke-id: ");
12735
898
            break;
12736
655
        case 8: /* source-user-id */
12737
655
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "source-user-id: ");
12738
655
            break;
12739
1.13k
        case 9: /* source-user-role */
12740
1.13k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "source-user-role: ");
12741
1.13k
            break;
12742
1.29k
        case 10: /* target-device */
12743
1.29k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-device: ");
12744
1.29k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12745
1.29k
            offset = fRecipient(tvb, pinfo, subtree, offset);
12746
1.29k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12747
1.29k
            break;
12748
387
        case 11: /* target-object */
12749
387
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-object: ");
12750
387
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
12751
387
            break;
12752
2.73k
        case 12: /* target-property */
12753
2.73k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-property: ");
12754
2.73k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12755
2.73k
            offset = fPropertyReference(tvb, pinfo, subtree, offset, 0, 0);
12756
2.73k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12757
2.73k
            break;
12758
1.68k
        case 13: /* target-priority */
12759
1.68k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: ");
12760
1.68k
            break;
12761
1.83k
        case 14: /* target-value */
12762
1.83k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-value: ");
12763
1.83k
            if (operation == 4) {
12764
                /* operation life safety */
12765
                /* inspect next tag */
12766
0
                fTagHeader(tvb, pinfo, offset + len, &tag_no, &tag_info, &lvt);
12767
0
                if ( tag_no == 0 &&
12768
0
                     ! tag_is_opening(tag_info) &&
12769
0
                     tag_is_context_specific(tag_info) ) {
12770
0
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12771
0
                    offset = fLifeSafetyInfo(tvb, pinfo, subtree, offset);
12772
0
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12773
0
                } else {
12774
                    /* abstract syntax and type */
12775
0
                    offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
12776
0
                }
12777
1.83k
            } else if ( operation == 5 ) {
12778
                /* operation acknowledge alarm */
12779
                /* inspect next tag */
12780
0
                fTagHeader(tvb, pinfo, offset + len, &tag_no, &tag_info, &lvt);
12781
0
                if ( tag_no == 0 &&
12782
0
                     ! tag_is_opening(tag_info) &&
12783
0
                     tag_is_context_specific(tag_info) ) {
12784
0
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12785
0
                    offset = fAcknowledgeAlarmInfo(tvb, pinfo, subtree, offset);
12786
0
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12787
0
                } else {
12788
                    /* abstract syntax and type */
12789
0
                    offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
12790
0
                }
12791
1.83k
            } else {
12792
                /* abstract syntax and type */
12793
1.83k
                offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
12794
1.83k
            }
12795
1.83k
            break;
12796
1
        case 15: /* current-value */
12797
1
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "current-value: ");
12798
            /* always abstract syntax and type */
12799
1
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
12800
1
            break;
12801
11
        case 16: /* error-result */
12802
11
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "error-result: ");
12803
11
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12804
11
            offset = fError(tvb, pinfo, subtree, offset);
12805
11
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12806
11
            break;
12807
173
        default:
12808
173
            break;
12809
24.6k
        }
12810
23.8k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12811
23.8k
    }
12812
796
    return offset;
12813
1.59k
}
12814
12815
static unsigned
12816
// NOLINTNEXTLINE(misc-no-recursion)
12817
fAuditLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12818
202
{
12819
202
    unsigned    lastoffset = 0;
12820
202
    uint8_t     tag_no, tag_info;
12821
202
    uint32_t    lvt;
12822
202
    proto_tree *subtree = tree;
12823
12824
720
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12825
717
        lastoffset = offset;
12826
717
        fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12827
717
        if (tag_is_closing(tag_info)) {
12828
40
            break;
12829
40
        }
12830
12831
677
        switch (tag_no) {
12832
425
        case 0: /* timestamp */
12833
425
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12834
425
            offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
12835
425
            offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
12836
425
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12837
425
            break;
12838
157
        case 1: /* logDatum: don't loop, it's a CHOICE */
12839
157
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12840
157
            switch (fTagNo(tvb, offset)) {
12841
30
            case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
12842
30
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
12843
30
                break;
12844
67
            case 1: /* notification */
12845
67
                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
12846
67
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12847
67
                offset  = fAuditNotificationInfo(tvb, pinfo, subtree, offset);
12848
67
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12849
67
                break;
12850
16
            case 2: /* time-change */
12851
16
                offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
12852
16
                break;
12853
44
            default:
12854
44
                return offset;
12855
157
            }
12856
102
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12857
102
            break;
12858
95
        default:
12859
95
            return offset;
12860
677
        }
12861
518
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12862
518
    }
12863
43
    return offset;
12864
202
}
12865
12866
static unsigned
12867
// NOLINTNEXTLINE(misc-no-recursion)
12868
fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12869
0
{
12870
0
    unsigned    lastoffset = 0;
12871
0
    uint8_t     tag_no, tag_info;
12872
0
    uint32_t    lvt;
12873
0
    proto_tree *subtree = tree;
12874
12875
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12876
0
        lastoffset = offset;
12877
0
        switch (fTagNo(tvb, offset)) {
12878
0
        case 0: /* timestamp */
12879
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12880
0
            offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
12881
0
            offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
12882
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12883
0
            break;
12884
0
        case 1: /* logDatum: don't loop, it's a CHOICE */
12885
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12886
0
            switch (fTagNo(tvb, offset)) {
12887
0
            case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
12888
0
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
12889
0
                break;
12890
0
            case 1: /* notification */
12891
0
                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
12892
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12893
0
                offset  = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
12894
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12895
0
                break;
12896
0
            case 2: /* time-change */
12897
0
                offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
12898
0
                break;
12899
0
            default:
12900
0
                return offset;
12901
0
            }
12902
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12903
0
            break;
12904
0
        default:
12905
0
            return offset;
12906
0
        }
12907
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12908
0
    }
12909
0
    return offset;
12910
0
}
12911
12912
static unsigned
12913
// NOLINTNEXTLINE(misc-no-recursion)
12914
fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12915
6
{
12916
6
    unsigned   lastoffset = 0;
12917
6
    uint8_t tag_no, tag_info;
12918
6
    uint32_t lvt;
12919
6
    int32_t save_propertyIdentifier;
12920
12921
54
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12922
54
        lastoffset = offset;
12923
54
        switch (fTagNo(tvb, offset)) {
12924
10
        case 0: /* timestamp */
12925
10
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12926
10
            offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
12927
10
            offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
12928
10
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12929
10
            break;
12930
29
        case 1: /* logDatum: don't loop, it's a CHOICE */
12931
29
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12932
29
            switch (fTagNo(tvb, offset)) {
12933
2
            case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
12934
2
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status: ", BACnetLogStatus);
12935
2
                break;
12936
24
            case 1:
12937
24
                offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
12938
24
                break;
12939
0
            case 2:
12940
0
                offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
12941
0
                break;
12942
0
            case 3:
12943
0
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
12944
0
                break;
12945
0
            case 4:
12946
0
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
12947
0
                break;
12948
2
            case 5:
12949
2
                offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
12950
2
                break;
12951
1
            case 6:
12952
1
                offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
12953
1
                break;
12954
0
            case 7:
12955
0
                offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
12956
0
                break;
12957
0
            case 8:
12958
0
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12959
0
                offset  = fError(tvb, pinfo, tree, offset);
12960
0
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12961
0
                break;
12962
0
            case 9:
12963
0
                offset = fRealTag(tvb, pinfo, tree, offset, "time change: ");
12964
0
                break;
12965
0
            case 10:    /* any Value */
12966
0
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12967
                /* this ASN-1 construction may contain also an property identifier, so
12968
                   save the one we have got and restore it later and invalidate current
12969
                   one to avoid misinterpretations */
12970
0
                save_propertyIdentifier = propertyIdentifier;
12971
0
                propertyIdentifier = -1;
12972
0
                offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
12973
0
                propertyIdentifier = save_propertyIdentifier;
12974
0
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12975
0
                break;
12976
0
            default:
12977
0
                return offset;
12978
29
            }
12979
27
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12980
27
            break;
12981
12
        case 2:
12982
            /* Changed this to BitString per BACnet Spec. */
12983
12
            offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags: ", BACnetStatusFlags);
12984
12
            break;
12985
3
        default:
12986
3
            return offset;
12987
54
        }
12988
48
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12989
48
    }
12990
0
    return offset;
12991
6
}
12992
12993
static unsigned
12994
// NOLINTNEXTLINE(misc-no-recursion)
12995
fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12996
0
{
12997
0
    unsigned   lastoffset = 0;
12998
0
    uint8_t tag_no, tag_info;
12999
0
    uint32_t lvt;
13000
0
    int32_t save_propertyIdentifier;
13001
13002
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13003
0
        lastoffset = offset;
13004
0
        switch (fTagNo(tvb, offset)) {
13005
0
        case 0: /* timestamp */
13006
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13007
0
            offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
13008
0
            offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
13009
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13010
0
            break;
13011
0
        case 1: /* logData: don't loop, it's a CHOICE */
13012
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13013
0
            switch (fTagNo(tvb, offset)) {
13014
0
            case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
13015
0
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status: ", BACnetLogStatus);
13016
0
                break;
13017
0
            case 1: /* log-data: SEQUENCE OF CHOICE */
13018
0
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13019
0
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset != lastoffset)) {  /* exit loop if nothing happens inside */
13020
0
                    lastoffset = offset;
13021
0
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13022
0
                    if (tag_is_closing(tag_info)) {
13023
0
                        lastoffset = offset;
13024
0
                        break;
13025
0
                    }
13026
0
                    switch (tag_no) {
13027
0
                    case 0:
13028
0
                        offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
13029
0
                        break;
13030
0
                    case 1:
13031
0
                        offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
13032
0
                        break;
13033
0
                    case 2:
13034
0
                        offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
13035
0
                        break;
13036
0
                    case 3:
13037
0
                        offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
13038
0
                        break;
13039
0
                    case 4:
13040
0
                        offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
13041
0
                        break;
13042
0
                    case 5:
13043
0
                        offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
13044
0
                        break;
13045
0
                    case 6:
13046
0
                        offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
13047
0
                        break;
13048
0
                    case 7:
13049
0
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13050
0
                        offset  = fError(tvb, pinfo, tree, offset);
13051
0
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13052
0
                        break;
13053
0
                    case 8: /* any Value */
13054
0
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13055
                        /* this ASN-1 construction may contain also an property identifier, so
13056
                           save the one we have got and restore it later and invalidate current
13057
                           one to avoid misinterpretations */
13058
0
                        save_propertyIdentifier = propertyIdentifier;
13059
0
                        propertyIdentifier = -1;
13060
0
                        offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
13061
0
                        propertyIdentifier = save_propertyIdentifier;
13062
0
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13063
0
                        break;
13064
0
                    default:
13065
0
                        return offset;
13066
0
                    }
13067
0
                }
13068
0
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13069
0
                break;
13070
0
            case 2:
13071
0
                offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
13072
0
                break;
13073
0
            default:
13074
0
                return offset;
13075
0
            }
13076
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13077
0
            break;
13078
0
        default:
13079
0
            return offset;
13080
0
        }
13081
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13082
0
    }
13083
0
    return offset;
13084
0
}
13085
13086
13087
static unsigned
13088
// NOLINTNEXTLINE(misc-no-recursion)
13089
fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13090
2.32k
{
13091
2.32k
    unsigned   lastoffset = 0;
13092
2.32k
    uint8_t tag_no, tag_info;
13093
2.32k
    uint32_t lvt;
13094
13095
66.2k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13096
65.9k
        lastoffset = offset;
13097
65.9k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13098
65.9k
        if (tag_is_closing(tag_info)) {
13099
445
            break;
13100
445
        }
13101
13102
65.4k
        switch (tag_no) {
13103
32.4k
        case 0: /* ProcessId */
13104
32.4k
            offset  = fProcessId(tvb, pinfo, tree, offset);
13105
32.4k
            break;
13106
2.39k
        case 1: /* initiating ObjectId */
13107
2.39k
            offset  = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13108
2.39k
            break;
13109
3.32k
        case 2: /* event ObjectId */
13110
3.32k
            offset  = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13111
3.32k
            break;
13112
3.14k
        case 3: /* time stamp */
13113
3.14k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13114
3.14k
            offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
13115
3.14k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13116
3.14k
            break;
13117
2.06k
        case 4: /* notificationClass */
13118
2.06k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
13119
2.06k
            break;
13120
1.99k
        case 5: /* Priority */
13121
1.99k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
13122
1.99k
            break;
13123
3.32k
        case 6: /* EventType */
13124
3.32k
            offset = fEventType(tvb, pinfo, tree, offset);
13125
3.32k
            break;
13126
1.09k
        case 7: /* messageText */
13127
1.09k
            offset  = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
13128
1.09k
            break;
13129
2.97k
        case 8: /* NotifyType */
13130
2.97k
            offset = fNotifyType(tvb, pinfo, tree, offset);
13131
2.97k
            break;
13132
2.17k
        case 9: /* ackRequired */
13133
2.17k
            offset  = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
13134
2.17k
            break;
13135
2.80k
        case 10: /* fromState */
13136
2.80k
            offset = fFromState(tvb, pinfo, tree, offset);
13137
2.80k
            break;
13138
2.20k
        case 11: /* toState */
13139
2.20k
            offset = fToState(tvb, pinfo, tree, offset);
13140
2.20k
            break;
13141
5.15k
        case 12: /* NotificationParameters */
13142
5.15k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13143
5.15k
            offset  = fNotificationParameters(tvb, pinfo, tree, offset);
13144
5.15k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13145
5.15k
            break;
13146
327
        default:
13147
327
            break;
13148
65.4k
        }
13149
64.2k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13150
64.2k
    }
13151
1.08k
    return offset;
13152
2.32k
}
13153
13154
static unsigned
13155
fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13156
58
{
13157
58
    return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
13158
58
}
13159
13160
static unsigned
13161
fConfirmedCOVNotificationMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13162
107
{
13163
107
    unsigned    lastoffset = 0, len;
13164
107
    uint8_t     tag_no, tag_info;
13165
107
    uint32_t    lvt;
13166
107
    proto_tree *subtree = tree;
13167
107
    proto_tree *subsubtree = tree;
13168
13169
4.57k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13170
4.55k
        lastoffset = offset;
13171
4.55k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13172
4.55k
        if (tag_is_closing(tag_info)) {
13173
1.94k
            offset += len;
13174
1.94k
            subtree = tree;
13175
1.94k
            continue;
13176
1.94k
        }
13177
13178
2.60k
        switch (tag_no) {
13179
1.70k
        case 0: /* ProcessId */
13180
1.70k
            offset = fProcessId(tvb, pinfo, tree, offset);
13181
1.70k
            break;
13182
186
        case 1: /* initiating DeviceId */
13183
186
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
13184
186
            break;
13185
341
        case 2: /* time remaining */
13186
341
            offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining: ");
13187
341
            break;
13188
290
        case 3: /* timestamp */
13189
290
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13190
290
            offset = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
13191
290
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13192
290
            break;
13193
41
        case 4: /* list-of-cov-notifications */
13194
41
            if (tag_is_opening(tag_info)) {
13195
                /* new subtree for list-of-cov-notifications */
13196
27
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-notifications: ");
13197
27
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13198
13199
129
                while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13200
128
                    lastoffset = offset;
13201
128
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13202
128
                    if (tag_is_closing(tag_info)) {
13203
                        /* end for list-of-cov-notifications */
13204
15
                        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13205
15
                        offset += len;
13206
15
                        subtree = tree;
13207
15
                        break;
13208
15
                    }
13209
13210
113
                    switch (tag_no) {
13211
104
                    case 0: /* monitored-object-identifier */
13212
104
                        offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
13213
104
                        break;
13214
3
                    case 1: /* list-of-values */
13215
3
                        if (tag_is_opening(tag_info)) {
13216
                            /* new subtree for list-of-values */
13217
0
                            subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-values: ");
13218
0
                            offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
13219
13220
0
                            while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13221
0
                            lastoffset = offset;
13222
0
                            len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13223
0
                            if (tag_is_closing(tag_info)) {
13224
                                /* end of list-of-values */
13225
0
                                fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
13226
0
                                offset += len;
13227
0
                                break;
13228
0
                            }
13229
13230
0
                            switch (tag_no) {
13231
0
                            case 0: /* PropertyIdentifier */
13232
0
                                offset = fPropertyIdentifier(tvb, pinfo, subsubtree, offset);
13233
0
                                break;
13234
0
                            case 1: /* propertyArrayIndex */
13235
0
                                offset = fPropertyArrayIndex(tvb, pinfo, subsubtree, offset);
13236
0
                                break;
13237
0
                            case 2: /* property-value */
13238
0
                                offset = fPropertyValue(tvb, pinfo, subsubtree, offset, tag_info);
13239
0
                                break;
13240
0
                            case 3: /* time-of-change */
13241
0
                                offset = fTime(tvb, pinfo, subsubtree, offset, "time of change: ");
13242
0
                                break;
13243
0
                            default:
13244
                                /* wrong tag encoding */
13245
0
                                return offset;
13246
0
                            }
13247
0
                            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13248
0
                            }
13249
0
                        }
13250
3
                        else {
13251
                            /* wrong tag encoding */
13252
3
                            expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
13253
3
                        }
13254
3
                        break;
13255
6
                    default:
13256
                        /* wrong tag encoding */
13257
6
                        return offset;
13258
113
                    }
13259
105
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13260
105
                }
13261
27
            }
13262
14
            else {
13263
                /* wrong tag encoding */
13264
14
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13265
14
            }
13266
33
            break;
13267
42
        default:
13268
            /* wrong tag encoding */
13269
42
            return offset;
13270
2.60k
        }
13271
2.54k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13272
2.54k
    }
13273
42
    return offset;
13274
107
}
13275
13276
static unsigned
13277
fUnconfirmedCOVNotificationMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13278
15
{
13279
15
    return fConfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
13280
15
}
13281
13282
static unsigned
13283
fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13284
204
{
13285
204
    unsigned    lastoffset = 0, len;
13286
204
    uint8_t     tag_no, tag_info;
13287
204
    uint32_t    lvt;
13288
204
    proto_tree *subtree = tree;
13289
13290
4.16k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13291
4.13k
        lastoffset = offset;
13292
4.13k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13293
4.13k
        if (tag_is_closing(tag_info)) {
13294
903
            fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13295
903
            offset += len;
13296
903
            subtree = tree;
13297
903
            continue;
13298
903
        }
13299
13300
3.23k
        switch (tag_no) {
13301
1.70k
        case 0: /* ProcessId */
13302
1.70k
            offset = fProcessId(tvb, pinfo, tree, offset);
13303
1.70k
            break;
13304
196
        case 1: /* initiating DeviceId */
13305
196
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_device_identifier);
13306
196
            break;
13307
242
        case 2: /* monitored ObjectId */
13308
242
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
13309
242
            break;
13310
764
        case 3: /* time remaining */
13311
764
            offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining: ");
13312
764
            break;
13313
227
        case 4: /* List of Values */
13314
227
            if (tag_is_opening(tag_info)) {
13315
207
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list of Values: ");
13316
207
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13317
207
            offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
13318
207
            }
13319
20
            else {
13320
20
            expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13321
20
            }
13322
227
            break;
13323
99
        default:
13324
99
            return offset;
13325
3.23k
        }
13326
3.07k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13327
3.07k
    }
13328
46
    return offset;
13329
204
}
13330
13331
static unsigned
13332
fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13333
24
{
13334
24
    return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
13335
24
}
13336
13337
static unsigned
13338
fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13339
227
{
13340
227
    unsigned   lastoffset = 0;
13341
227
    uint8_t tag_no = 0, tag_info = 0;
13342
227
    uint32_t lvt = 0;
13343
13344
5.26k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13345
5.22k
        lastoffset = offset;
13346
5.22k
        switch (fTagNo(tvb, offset)) {
13347
3.23k
        case 0: /* acknowledgingProcessId */
13348
3.23k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
13349
3.23k
            break;
13350
273
        case 1: /* eventObjectId */
13351
273
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13352
273
            break;
13353
367
        case 2: /* eventStateAcknowledged */
13354
367
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13355
367
                "event State Acknowledged: ", BACnetEventState, 64);
13356
367
            break;
13357
530
        case 3: /* timeStamp */
13358
530
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13359
530
            offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
13360
530
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13361
530
            break;
13362
366
        case 4: /* acknowledgementSource */
13363
366
            offset  = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
13364
366
            break;
13365
300
        case 5: /* timeOfAcknowledgement */
13366
300
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13367
300
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
13368
300
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13369
300
            break;
13370
157
        default:
13371
157
            return offset;
13372
5.22k
        }
13373
5.03k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13374
5.03k
    }
13375
36
    return offset;
13376
227
}
13377
13378
static unsigned
13379
fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13380
20
{
13381
20
    unsigned lastoffset = 0;
13382
13383
65
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13384
65
        lastoffset = offset;
13385
65
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
13386
65
        offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
13387
65
            "alarm State: ", BACnetEventState, 64);
13388
65
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13389
65
            "acknowledged Transitions: ", BACnetEventTransitionBits);
13390
65
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13391
65
    }
13392
20
    return  offset;
13393
20
}
13394
13395
static unsigned
13396
fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13397
97
{
13398
97
    unsigned   lastoffset = 0;
13399
97
    uint8_t tag_no, tag_info;
13400
97
    uint32_t lvt;
13401
13402
3.20k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13403
3.17k
        lastoffset = offset;
13404
3.17k
        switch (fTagNo(tvb, offset)) {
13405
1.91k
        case 0: /* acknowledgmentFilter */
13406
1.91k
            offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13407
1.91k
                "acknowledgment Filter: ", BACnetAcknowledgementFilter);
13408
1.91k
            break;
13409
187
        case 1: /* eventObjectId - OPTIONAL */
13410
187
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13411
187
            offset  = fRecipientProcess(tvb, pinfo, tree, offset);
13412
187
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13413
187
            break;
13414
270
        case 2: /* eventStateFilter */
13415
270
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
13416
270
                "event State Filter: ", BACnetEventStateFilter);
13417
270
            break;
13418
350
        case 3: /* eventTypeFilter - OPTIONAL */
13419
350
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
13420
350
                "event Type Filter: ", BACnetEventType);
13421
350
            break;
13422
118
        case 4: /* priorityFilter */
13423
118
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13424
118
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
13425
118
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
13426
118
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13427
118
            break;
13428
286
        case 5: /* notificationClassFilter - OPTIONAL */
13429
286
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
13430
286
            break;
13431
54
        default:
13432
54
            return offset;
13433
3.17k
        }
13434
3.10k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13435
3.10k
    }
13436
29
    return offset;
13437
97
}
13438
13439
static unsigned
13440
fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13441
37
{
13442
37
    unsigned lastoffset = 0;
13443
13444
280
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13445
271
        lastoffset = offset;
13446
271
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
13447
271
        offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
13448
271
            "event Type: ", BACnetEventType, 64);
13449
271
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13450
271
            "event State: ", BACnetEventState);
13451
271
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
13452
271
        if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2)  /* Notification Class - OPTIONAL */
13453
57
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
13454
271
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13455
271
    }
13456
13457
37
    return  offset;
13458
37
}
13459
13460
static unsigned
13461
fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13462
24
{
13463
24
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
13464
24
        if (fTagNo(tvb, offset) == 0) {
13465
20
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13466
20
        }
13467
24
    }
13468
24
    return offset;
13469
24
}
13470
13471
static unsigned
13472
flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13473
210
{
13474
210
    unsigned    lastoffset = 0;
13475
210
    uint8_t     tag_no, tag_info;
13476
210
    uint32_t    lvt;
13477
210
    proto_tree* subtree = tree;
13478
13479
2.52k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13480
2.51k
        lastoffset = offset;
13481
2.51k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13482
        /* we are finished here if we spot a closing tag */
13483
2.51k
        if (tag_is_closing(tag_info)) {
13484
43
            break;
13485
43
        }
13486
2.46k
        switch (tag_no) {
13487
745
        case 0: /* ObjectId */
13488
745
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13489
745
            break;
13490
257
        case 1: /* eventState */
13491
257
            offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13492
257
                "event State: ", BACnetEventState);
13493
257
            break;
13494
330
        case 2: /* acknowledgedTransitions */
13495
330
            offset = fBitStringTagVS(tvb, pinfo, tree, offset,
13496
330
                "acknowledged Transitions: ", BACnetEventTransitionBits);
13497
330
            break;
13498
419
        case 3: /* eventTimeStamps */
13499
419
            subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
13500
419
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13501
419
            offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
13502
419
            offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
13503
419
            offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
13504
419
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13505
419
            break;
13506
301
        case 4: /* notifyType */
13507
301
            offset = fNotifyType(tvb, pinfo, tree, offset);
13508
301
            break;
13509
171
        case 5: /* eventEnable */
13510
171
            offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
13511
171
                "event Enable: ", BACnetEventTransitionBits);
13512
171
            break;
13513
112
        case 6: /* eventPriorities */
13514
112
            subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventPriorities");
13515
112
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13516
112
            offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
13517
112
            offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
13518
112
            offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
13519
112
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13520
112
            break;
13521
131
        default:
13522
131
            return offset;
13523
2.46k
        }
13524
2.31k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13525
2.31k
    }
13526
54
    return offset;
13527
210
}
13528
13529
static unsigned
13530
fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13531
135
{
13532
135
    unsigned   lastoffset = 0;
13533
135
    uint8_t tag_no, tag_info;
13534
135
    uint32_t lvt;
13535
13536
135
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
13537
159
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13538
154
        lastoffset = offset;
13539
154
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13540
        /* we are finished here if we spot a closing tag */
13541
154
        if (tag_is_closing(tag_info)) {
13542
5
            break;
13543
5
        }
13544
149
        offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
13545
149
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13546
149
    }
13547
135
    return offset;
13548
135
}
13549
13550
static unsigned
13551
fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13552
70
{
13553
70
    unsigned   lastoffset = 0;
13554
70
    uint8_t tag_no, tag_info;
13555
70
    uint32_t lvt;
13556
13557
393
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13558
389
        lastoffset = offset;
13559
389
        switch (fTagNo(tvb, offset)) {
13560
210
        case 0: /* listOfEventSummaries */
13561
210
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13562
210
            offset  = flistOfEventSummaries(tvb, pinfo, tree, offset);
13563
210
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13564
210
            break;
13565
150
        case 1: /* moreEvents */
13566
150
            offset  = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
13567
150
            break;
13568
29
        default:
13569
29
            return offset;
13570
389
        }
13571
323
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13572
323
    }
13573
4
    return offset;
13574
70
}
13575
13576
static unsigned
13577
fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13578
1.12k
{
13579
1.12k
    unsigned    lastoffset = 0, len;
13580
1.12k
    uint8_t     tag_no, tag_info;
13581
1.12k
    uint32_t    lvt;
13582
1.12k
    proto_tree *subtree    = tree;
13583
13584
1.12k
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
13585
13586
8.10k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13587
8.08k
        lastoffset = offset;
13588
8.08k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13589
8.08k
        if (tag_is_closing(tag_info)) {
13590
4.25k
            offset += len;
13591
4.25k
            subtree = tree;
13592
4.25k
            continue;
13593
4.25k
        }
13594
13595
3.82k
        switch (tag_no) {
13596
1.81k
        case 0: /* ObjectId */
13597
1.81k
            offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
13598
1.81k
            break;
13599
1.59k
        case 3: /* listOfElements */
13600
1.59k
            if (tag_is_opening(tag_info)) {
13601
1.53k
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfElements");
13602
1.53k
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13603
1.53k
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
13604
1.53k
                fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13605
1.53k
            } else {
13606
62
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13607
62
            }
13608
1.59k
            break;
13609
421
        default:
13610
421
            return offset;
13611
3.82k
        }
13612
2.79k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13613
2.79k
    }
13614
93
    return offset;
13615
1.12k
}
13616
13617
static unsigned
13618
fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13619
2
{
13620
2
    return fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13621
2
}
13622
13623
static unsigned
13624
fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13625
39
{
13626
39
    unsigned lastoffset = 0;
13627
13628
751
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13629
743
        lastoffset = offset;
13630
13631
743
        switch (fTagNo(tvb, offset)) {
13632
494
        case 0: /* timeDuration */
13633
494
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
13634
494
            break;
13635
114
        case 1: /* enable-disable */
13636
114
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
13637
114
                BACnetEnableDisable);
13638
114
            break;
13639
111
        case 2: /* password - OPTIONAL */
13640
111
            offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
13641
111
            break;
13642
24
        default:
13643
24
            return offset;
13644
743
        }
13645
712
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13646
712
    }
13647
8
    return offset;
13648
39
}
13649
13650
static unsigned
13651
fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13652
26
{
13653
26
    unsigned lastoffset = 0;
13654
13655
459
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13656
456
        lastoffset = offset;
13657
13658
456
        switch (fTagNo(tvb, offset)) {
13659
291
        case 0: /* reinitializedStateOfDevice */
13660
291
            offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13661
291
                "reinitialized State Of Device: ",
13662
291
                BACnetReinitializedStateOfDevice);
13663
291
            break;
13664
144
        case 1: /* password - OPTIONAL */
13665
144
            offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
13666
144
            break;
13667
21
        default:
13668
21
            return offset;
13669
456
        }
13670
433
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13671
433
    }
13672
3
    return offset;
13673
26
}
13674
13675
static unsigned
13676
fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13677
2
{
13678
2
    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13679
2
                                          "vtClass: ", BACnetVTClass);
13680
2
    return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
13681
2
}
13682
13683
static unsigned
13684
fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13685
21
{
13686
21
    return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
13687
21
}
13688
13689
static unsigned
13690
fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13691
57
{
13692
57
    unsigned lastoffset = 0;
13693
13694
1.11k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13695
1.10k
        lastoffset = offset;
13696
1.10k
        offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
13697
1.10k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13698
1.10k
    }
13699
57
    return offset;
13700
57
}
13701
13702
static unsigned
13703
fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13704
13
{
13705
13
    offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
13706
13
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
13707
13
    return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
13708
13
}
13709
13710
static unsigned
13711
fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13712
6
{
13713
6
    unsigned lastoffset = 0;
13714
13715
37
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13716
37
        lastoffset = offset;
13717
13718
37
        switch (fTagNo(tvb, offset)) {
13719
22
        case 0: /* BOOLEAN */
13720
22
            offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
13721
22
            break;
13722
9
        case 1: /* Unsigned OPTIONAL */
13723
9
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
13724
9
            break;
13725
6
        default:
13726
6
            return offset;
13727
37
        }
13728
31
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13729
31
    }
13730
0
    return offset;
13731
6
}
13732
13733
static unsigned
13734
fConfirmedAuditNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13735
1.43k
{
13736
1.43k
    unsigned   lastoffset = 0;
13737
1.43k
    unsigned   firstloop = 1;
13738
1.43k
    uint8_t tag_no, tag_info;
13739
1.43k
    uint32_t lvt;
13740
13741
2.89k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13742
1.78k
        lastoffset = offset;
13743
1.78k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13744
1.78k
        if (tag_is_closing(tag_info)) {
13745
257
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13746
257
            break;
13747
257
        }
13748
13749
1.53k
        if (tag_is_opening(tag_info) && firstloop) {
13750
96
            firstloop = 0;
13751
96
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13752
96
        }
13753
13754
1.53k
        offset = fAuditNotificationInfo(tvb, pinfo, tree, offset);
13755
1.53k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13756
1.53k
    }
13757
1.43k
    return offset;
13758
1.43k
}
13759
13760
static unsigned
13761
fUnconfirmedAuditNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13762
16
{
13763
16
    return fConfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
13764
16
}
13765
13766
static unsigned
13767
fAuditLogQueryByTargetParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13768
371
{
13769
371
    unsigned   lastoffset = 0;
13770
371
    uint8_t tag_no, tag_info;
13771
371
    uint32_t lvt;
13772
13773
4.20k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13774
4.19k
        lastoffset = offset;
13775
4.19k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13776
4.19k
        if (tag_is_closing(tag_info)) {
13777
95
            break;
13778
95
        }
13779
13780
4.09k
        switch (tag_no) {
13781
1.35k
        case 0: /* target-device-identifier */
13782
1.35k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
13783
1.35k
            break;
13784
295
        case 1: /* target-device-address */
13785
295
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13786
295
            offset  = fAddress(tvb, pinfo, tree, offset);
13787
295
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13788
295
            break;
13789
289
        case 2: /* target-object-identifier */
13790
289
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13791
289
            break;
13792
427
        case 3: /* target-property-identifier */
13793
427
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
13794
427
            break;
13795
678
        case 4: /* target-property-array-index */
13796
678
            offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
13797
678
            break;
13798
195
        case 5: /* target-priority */
13799
195
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: ");
13800
195
            break;
13801
257
        case 6: /* target-operation */
13802
257
            offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
13803
257
                  "target-operation: ", BACnetAuditOperation);
13804
257
            break;
13805
419
        case 7: /* successful-action */
13806
419
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13807
419
                  "target-successful-action: ", BACnetSuccessFilter, 64);
13808
419
            break;
13809
186
        default:
13810
186
            return offset;
13811
4.09k
        }
13812
3.87k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13813
3.87k
    }
13814
148
    return offset;
13815
371
}
13816
13817
static unsigned
13818
fAuditLogQueryBySourceParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13819
221
{
13820
221
    unsigned   lastoffset = 0;
13821
221
    uint8_t tag_no, tag_info;
13822
221
    uint32_t lvt;
13823
13824
2.33k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13825
2.32k
        lastoffset = offset;
13826
2.32k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13827
2.32k
        if (tag_is_closing(tag_info)) {
13828
43
            break;
13829
43
        }
13830
13831
2.28k
        switch (tag_no) {
13832
767
        case 0: /* source-device-identifier */
13833
767
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
13834
767
            break;
13835
666
        case 1: /* source-device-address */
13836
666
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13837
666
            offset  = fAddress(tvb, pinfo, tree, offset);
13838
666
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13839
666
            break;
13840
180
        case 2: /* source-object-identifier */
13841
180
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13842
180
            break;
13843
177
        case 3: /* source-operation */
13844
177
            offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
13845
177
                  "source-operation: ", BACnetAuditOperation);
13846
177
            break;
13847
345
        case 4: /* successful-action */
13848
345
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13849
345
                  "source-successful-action: ", BACnetSuccessFilter, 64);
13850
345
            break;
13851
148
        default:
13852
148
            return offset;
13853
2.28k
        }
13854
2.11k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13855
2.11k
    }
13856
50
    return offset;
13857
221
}
13858
13859
static unsigned
13860
fAuditLogQueryParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13861
530
{
13862
530
    unsigned   lastoffset = 0;
13863
530
    uint8_t tag_no, tag_info;
13864
530
    uint32_t lvt;
13865
530
    proto_tree *subtree = tree;
13866
13867
1.04k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13868
1.03k
        lastoffset = offset;
13869
1.03k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13870
1.03k
        if (tag_is_closing(tag_info)) {
13871
253
            break;
13872
253
        }
13873
13874
780
        switch (tag_no) {
13875
371
        case 0: /* query-by-target-parameters */
13876
371
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "target-parameters: ");
13877
371
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13878
371
            offset  = fAuditLogQueryByTargetParameters(tvb, pinfo, subtree, offset);
13879
371
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13880
371
            break;
13881
221
        case 1: /* query-by-source-parameters */
13882
221
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "source-parameters: ");
13883
221
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13884
221
            offset  = fAuditLogQueryBySourceParameters(tvb, pinfo, subtree, offset);
13885
221
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13886
221
            break;
13887
186
        default:
13888
186
            return offset;
13889
780
        }
13890
511
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13891
511
    }
13892
261
    return offset;
13893
530
}
13894
13895
static unsigned
13896
fAuditLogQueryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13897
224
{
13898
224
    unsigned   lastoffset = 0;
13899
224
    uint8_t tag_no, tag_info;
13900
224
    uint32_t lvt;
13901
224
    proto_tree *subtree = tree;
13902
13903
2.74k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13904
2.73k
        lastoffset = offset;
13905
2.73k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13906
13907
2.73k
        switch (tag_no) {
13908
707
        case 0: /* audit-log */
13909
707
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13910
707
            break;
13911
530
        case 1: /* query-parameters */
13912
530
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "query-parameters: ");
13913
530
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13914
530
            offset = fAuditLogQueryParameters(tvb, pinfo, subtree, offset);
13915
530
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13916
530
            break;
13917
826
        case 2: /* start-at-sequence-number */
13918
826
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "start-at-sequence-number: ");
13919
826
            break;
13920
577
        case 3: /* requested-count */
13921
577
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "requested-count: ");
13922
577
            break;
13923
95
        default:
13924
95
            return offset;
13925
2.73k
        }
13926
2.52k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13927
2.52k
    }
13928
11
    return offset;
13929
224
}
13930
13931
static unsigned
13932
fAuditLogRecordResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13933
299
{
13934
299
    unsigned   lastoffset = 0;
13935
299
    uint8_t tag_no, tag_info;
13936
299
    uint32_t lvt;
13937
299
    proto_tree *subtree = tree;
13938
13939
1.29k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13940
1.29k
        lastoffset = offset;
13941
1.29k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13942
1.29k
        if (tag_is_closing(tag_info)) {
13943
126
            break;
13944
126
        }
13945
13946
1.16k
        switch (tag_no) {
13947
815
        case 0 : /* sequence-number */
13948
815
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "sequence-number: ");
13949
815
            break;
13950
202
        case 1: /* log-record */
13951
202
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "log-record: ");
13952
202
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13953
202
            offset = fAuditLogRecord(tvb, pinfo, subtree, offset);
13954
202
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13955
202
            break;
13956
147
        default:
13957
147
            return offset;
13958
1.16k
        }
13959
994
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13960
994
    }
13961
129
    return offset;
13962
299
}
13963
13964
static unsigned
13965
fAuditLogQueryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13966
74
{
13967
74
    unsigned   lastoffset = 0;
13968
74
    uint8_t tag_no, tag_info;
13969
74
    uint32_t lvt;
13970
74
    proto_tree *subtree = tree;
13971
13972
2.29k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13973
2.29k
        lastoffset = offset;
13974
2.29k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13975
13976
2.29k
        switch (tag_no) {
13977
428
        case 0: /* audit-log */
13978
428
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13979
428
            break;
13980
299
        case 1: /* records */
13981
299
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "records: ");
13982
299
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13983
299
            offset = fAuditLogRecordResult(tvb, pinfo, subtree, offset);
13984
299
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13985
299
            break;
13986
1.52k
        case 2: /* no-more-items */
13987
1.52k
            offset = fBooleanTag(tvb, pinfo, tree, offset, "no-more-items: ");
13988
1.52k
            break;
13989
37
        default:
13990
37
            return offset;
13991
2.29k
        }
13992
2.22k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13993
2.22k
    }
13994
5
    return offset;
13995
74
}
13996
13997
static unsigned
13998
fAuthRequestTokenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
13999
337
{
14000
337
    unsigned   lastoffset = 0;
14001
337
    uint8_t tag_no, tag_info;
14002
337
    uint32_t lvt;
14003
337
    proto_tree *subtree = tree;
14004
337
    proto_tree *subsubtree = tree;
14005
14006
337
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
14007
337
        ett_bacapp_value, NULL, "%s", lable);
14008
14009
1.37k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14010
1.36k
        lastoffset = offset;
14011
        /* check the tag.  A closing tag means we are done */
14012
1.36k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14013
1.36k
        if (tag_is_closing(tag_info)) {
14014
174
            return offset;
14015
174
        }
14016
14017
1.18k
        switch (tag_no) {
14018
915
        case 0: /* client */
14019
915
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "client: ");
14020
915
            break;
14021
85
        case 1: /* audience */
14022
85
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14023
85
            subsubtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
14024
85
                      ett_bacapp_value, NULL, "%s", "audience:");
14025
14026
2.11k
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14027
2.09k
                lastoffset = offset;
14028
                /* check the tag.  A closing tag means we are done */
14029
2.09k
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14030
2.09k
                if (tag_is_closing(tag_info)) {
14031
62
                    break;
14032
62
                }
14033
14034
2.02k
                offset = fSignedTag(tvb, pinfo, subsubtree, offset, "listener: ");
14035
2.02k
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14036
2.02k
            }
14037
85
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14038
85
            break;
14039
67
        case 2: /* scope */
14040
67
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14041
67
            offset = fAuthorizationScope(tvb, pinfo, subtree, offset, "scope: ");
14042
67
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14043
67
            break;
14044
120
        default:
14045
120
            return offset;
14046
1.18k
        }
14047
1.18k
    }
14048
14049
11
    return offset;
14050
337
}
14051
14052
static unsigned
14053
fAuthRequestRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14054
93
{
14055
93
    unsigned   lastoffset = 0;
14056
93
    uint8_t tag_no, tag_info;
14057
93
    uint32_t lvt;
14058
93
    proto_tree *subtree = tree;
14059
14060
387
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14061
383
        lastoffset = offset;
14062
383
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14063
14064
383
        switch (tag_no) {
14065
337
        case 0: /* token */
14066
337
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14067
337
            offset = fAuthRequestTokenRequest(tvb, pinfo, subtree, offset, "token: ");
14068
337
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14069
337
            break;
14070
46
        default:
14071
46
            return offset;
14072
383
        }
14073
294
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14074
294
    }
14075
4
    return offset;
14076
93
}
14077
14078
static unsigned
14079
fAuthRequestAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14080
156
{
14081
156
    unsigned   lastoffset = 0;
14082
156
    uint8_t tag_no, tag_info;
14083
156
    uint32_t lvt;
14084
156
    proto_tree *subtree = tree;
14085
14086
392
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14087
389
        lastoffset = offset;
14088
389
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14089
14090
389
        switch (tag_no) {
14091
344
        case 0: /* token */
14092
344
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14093
344
            offset = fAccessToken(tvb, pinfo, subtree, offset, "token: ");
14094
344
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14095
344
            break;
14096
45
        default:
14097
45
            return offset;
14098
389
        }
14099
236
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14100
236
    }
14101
3
    return offset;
14102
156
}
14103
14104
static unsigned
14105
fAuthRequestError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14106
37
{
14107
37
    unsigned   lastoffset = 0;
14108
37
    uint8_t tag_no, tag_info;
14109
37
    uint32_t lvt;
14110
37
    proto_tree *subtree = tree;
14111
14112
445
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14113
441
        lastoffset = offset;
14114
441
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14115
14116
441
        switch (tag_no) {
14117
201
        case 0: /* error */
14118
201
            offset = fContextTaggedError(tvb, pinfo, subtree, offset);
14119
201
            break;
14120
209
        case 1: /* details */
14121
209
            offset = fCharacterString(tvb, pinfo, subtree, offset, "details: ");
14122
209
            break;
14123
31
        default:
14124
31
            return offset;
14125
441
        }
14126
408
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14127
408
    }
14128
4
    return offset;
14129
37
}
14130
14131
static unsigned
14132
fWhoAmIRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14133
5
{
14134
5
    unsigned   lastoffset = 0;
14135
14136
13
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14137
11
        lastoffset = offset;
14138
11
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: ");
14139
11
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: ");
14140
11
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: ");
14141
11
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14142
11
    }
14143
5
    return offset;
14144
5
}
14145
14146
static unsigned
14147
fYouAreRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14148
18
{
14149
18
    unsigned   lastoffset = 0;
14150
18
    uint8_t tag_no, tag_info;
14151
18
    uint32_t lvt;
14152
14153
    /* https://bacnet.org/wp-content/uploads/sites/4/2022/08/Add-135-2016bz.pdf
14154
     * Vendor ID            | M
14155
     * Model Name           | M
14156
     * Serial Number        | M
14157
     * Device Identifier    | C
14158
     * Device MAC Addresss  | C
14159
     *
14160
     * "Either the 'Device Identifier', or 'Device MAC Address', or both shall
14161
     * be present."
14162
     */
14163
14164
    /* XXX - Does this really need to loop? */
14165
156
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14166
156
        lastoffset = offset;
14167
156
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: ");
14168
156
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: ");
14169
156
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: ");
14170
14171
        /* At least one of Device Identifier (12) or Device MAC Address (6)
14172
         * shall be present, so we should error if neither are. */
14173
156
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14174
156
        switch (tag_no) {
14175
9
        case 12:
14176
9
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
14177
9
            if (tvb_reported_length_remaining(tvb, offset) == 0) {
14178
0
                return offset;
14179
0
            }
14180
9
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14181
9
            if (tag_no != 6) {
14182
9
                expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
14183
9
            }
14184
            /* FALLTHROUGH */
14185
16
        case 6:
14186
16
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device MAC address: ");
14187
16
            break;
14188
138
        default:
14189
138
            expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
14190
156
        }
14191
154
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14192
154
    }
14193
16
    return offset;
14194
18
}
14195
14196
static unsigned
14197
fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14198
45
{
14199
45
    unsigned lastoffset = 0;
14200
14201
1.79k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14202
1.79k
        lastoffset = offset;
14203
14204
1.79k
        switch (fTagNo(tvb, offset)) {
14205
504
        case 0: /* Unsigned32 */
14206
504
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
14207
504
            break;
14208
681
        case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
14209
681
            proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
14210
681
            break;
14211
129
        case 2: /* Character String OPTIONAL */
14212
129
            offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
14213
129
            break;
14214
100
        case 3: /* Character String OPTIONAL */
14215
100
            offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
14216
100
            break;
14217
344
        case 4: /* Boolean OPTIONAL */
14218
344
            offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
14219
344
            break;
14220
33
        default:
14221
33
            return offset;
14222
1.79k
        }
14223
1.75k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14224
1.75k
    }
14225
7
    return offset;
14226
45
}
14227
14228
static unsigned
14229
fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14230
2
{
14231
2
    return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
14232
2
}
14233
14234
static unsigned
14235
fAuthenticationFactor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14236
101
{
14237
101
    unsigned   lastoffset = 0;
14238
101
    uint8_t tag_no, tag_info;
14239
101
    uint32_t lvt;
14240
14241
799
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14242
793
        lastoffset = offset;
14243
793
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14244
        /* quit loop if we spot a closing tag */
14245
793
        if (tag_is_closing(tag_info)) {
14246
27
            break;
14247
27
        }
14248
14249
766
        switch (tag_no) {
14250
546
        case 0: /* format-type */
14251
546
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "format-type: ", NULL);
14252
546
            break;
14253
70
        case 1: /* format-class */
14254
70
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "format-class: ");
14255
70
            break;
14256
83
        case 2: /* value */
14257
83
            offset = fOctetString(tvb, pinfo, tree, offset, "value: ", lvt);
14258
83
            break;
14259
67
        default:
14260
67
            break;
14261
766
        }
14262
14263
765
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14264
765
    }
14265
14266
100
    return offset;
14267
101
}
14268
14269
static unsigned
14270
fAuthenticationFactorFormat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14271
118
{
14272
118
    unsigned   lastoffset = 0;
14273
118
    uint8_t tag_no, tag_info;
14274
118
    uint32_t lvt;
14275
14276
1.42k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14277
1.41k
        lastoffset = offset;
14278
1.41k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14279
        /* quit loop if we spot a closing tag */
14280
1.41k
        if (tag_is_closing(tag_info)) {
14281
7
            break;
14282
7
        }
14283
14284
1.41k
        switch (tag_no) {
14285
642
        case 0: /* format-type */
14286
642
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "format-type: ", NULL);
14287
642
            break;
14288
410
        case 1: /* vendor-id */
14289
410
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "vendor-id: ");
14290
410
            break;
14291
252
        case 2: /* vendor-format */
14292
252
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "vendor-format: ");
14293
252
            break;
14294
108
        default:
14295
108
            break;
14296
1.41k
        }
14297
14298
1.41k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14299
1.41k
    }
14300
14301
118
    return offset;
14302
118
}
14303
14304
static unsigned
14305
fAuthenticationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14306
131
{
14307
131
    unsigned   lastoffset = 0;
14308
131
    uint8_t tag_no, tag_info;
14309
131
    uint32_t lvt;
14310
14311
446
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14312
441
        lastoffset = offset;
14313
441
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14314
        /* quit loop if we spot a closing tag */
14315
441
        if (tag_is_closing(tag_info)) {
14316
9
            break;
14317
9
        }
14318
14319
432
        switch (tag_no) {
14320
85
        case 0: /* policy */
14321
85
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14322
239
            while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14323
234
                lastoffset = offset;
14324
234
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14325
                /* quit loop if we spot a closing tag */
14326
234
                if (tag_is_closing(tag_info)) {
14327
28
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14328
28
                    break;
14329
28
                }
14330
14331
206
                switch (tag_no) {
14332
123
                case 0: /* credential-data-input */
14333
123
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14334
123
                    offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
14335
123
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14336
123
                    break;
14337
37
                case 1: /* index */
14338
37
                    offset = fUnsignedTag(tvb, pinfo, tree, offset, "index: ");
14339
37
                    break;
14340
46
                default:
14341
46
                    break;
14342
206
                }
14343
14344
200
                if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14345
200
            }
14346
79
            break;
14347
143
        case 1: /* order-enforced */
14348
143
            offset = fBooleanTag(tvb, pinfo, tree, offset, "order-enforced: ");
14349
143
            break;
14350
143
        case 2: /* timeout */
14351
143
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "timeout: ");
14352
143
            break;
14353
61
        default:
14354
61
            break;
14355
432
        }
14356
14357
422
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14358
422
    }
14359
14360
121
    return offset;
14361
131
}
14362
14363
static unsigned
14364
fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14365
10
{
14366
10
    uint8_t tag_no, tag_info;
14367
10
    uint32_t lvt;
14368
14369
10
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier); /* Requesting Device Identifier */
14370
10
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14371
10
    offset = fAddress(tvb, pinfo, tree, offset);
14372
10
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14373
10
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier); /* Remote Device Identifier */
14374
10
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14375
10
    offset = fAddress(tvb, pinfo, tree, offset);
14376
10
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14377
10
    return offset;
14378
10
}
14379
14380
static unsigned
14381
fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14382
31
{
14383
    /* Same as AddListElement request after service choice */
14384
31
    return fAddListElementRequest(tvb, pinfo, tree, offset);
14385
31
}
14386
14387
static unsigned
14388
fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14389
4
{
14390
4
    return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
14391
4
}
14392
14393
static unsigned
14394
fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14395
38
{
14396
38
    unsigned    lastoffset = 0, len;
14397
38
    uint8_t     tag_no, tag_info;
14398
38
    uint32_t    lvt;
14399
38
    proto_tree *subtree = tree;
14400
14401
    /* set the optional global properties to indicate not-used */
14402
38
    propertyArrayIndex = -1;
14403
1.24k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14404
1.23k
        lastoffset = offset;
14405
1.23k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14406
1.23k
        if (tag_is_closing(tag_info)) {
14407
528
            offset += len;
14408
528
            subtree = tree;
14409
528
            continue;
14410
528
        }
14411
708
        switch (tag_no) {
14412
337
        case 0: /* objectIdentifier */
14413
337
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14414
337
            break;
14415
176
        case 1: /* propertyIdentifier */
14416
176
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14417
176
            break;
14418
127
        case 2: /* propertyArrayIndex */
14419
127
            offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
14420
127
            break;
14421
46
        case 3: /* propertyValue */
14422
46
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14423
46
            break;
14424
22
        default:
14425
22
            break;
14426
708
        }
14427
701
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14428
701
    }
14429
31
    return offset;
14430
38
}
14431
14432
static unsigned
14433
fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14434
123
{
14435
123
    unsigned    lastoffset = 0;
14436
123
    uint8_t     tag_no, tag_info;
14437
123
    uint32_t    lvt;
14438
123
    proto_tree *subtree = tree;
14439
14440
    /* set the optional global properties to indicate not-used */
14441
123
    propertyArrayIndex = -1;
14442
992
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14443
971
        lastoffset = offset;
14444
971
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14445
        /* quit loop if we spot a closing tag */
14446
971
        if (tag_is_closing(tag_info)) {
14447
26
            break;
14448
26
        }
14449
14450
945
        switch (tag_no) {
14451
433
        case 0: /* objectIdentifier */
14452
433
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14453
433
            break;
14454
110
        case 1: /* propertyIdentifier */
14455
110
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14456
110
            break;
14457
195
        case 2: /* propertyArrayIndex */
14458
195
            offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
14459
195
            break;
14460
28
        case 3: /* propertyValue */
14461
28
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14462
28
            break;
14463
120
        case 4: /* Priority (only used for write) */
14464
120
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
14465
120
            break;
14466
58
        default:
14467
58
            return offset;
14468
945
        }
14469
878
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14470
878
    }
14471
56
    return offset;
14472
123
}
14473
14474
static unsigned
14475
fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14476
47
{
14477
47
    unsigned   lastoffset = 0, len;
14478
47
    uint8_t tag_no, tag_info;
14479
47
    uint32_t lvt;
14480
14481
522
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14482
518
        lastoffset = offset;
14483
518
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14484
        /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
14485
518
        if (tag_is_closing(tag_info)) {
14486
275
            offset += len;
14487
275
            continue;
14488
275
        }
14489
14490
243
        switch (tag_no) {
14491
184
        case 0: /* objectIdentifier */
14492
184
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14493
184
            break;
14494
32
        case 1: /* listOfPropertyValues */
14495
32
            if (tag_is_opening(tag_info)) {
14496
22
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14497
22
                offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
14498
22
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14499
22
            } else {
14500
10
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14501
10
            }
14502
32
            break;
14503
27
        default:
14504
27
            return offset;
14505
243
        }
14506
210
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14507
210
    }
14508
14
    return offset;
14509
47
}
14510
14511
static unsigned
14512
fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14513
47
{
14514
47
    if (offset >= tvb_reported_length(tvb))
14515
0
        return offset;
14516
14517
47
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14518
47
    return fWriteAccessSpecification(tvb, pinfo, tree, offset);
14519
47
}
14520
14521
static unsigned
14522
fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset, uint8_t list)
14523
10.3k
{
14524
10.3k
    unsigned   lastoffset = 0;
14525
10.3k
    uint8_t tag_no, tag_info;
14526
10.3k
    uint32_t lvt;
14527
14528
    /* set the optional global properties to indicate not-used */
14529
10.3k
    propertyArrayIndex = -1;
14530
16.1k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14531
16.1k
        lastoffset = offset;
14532
16.1k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14533
16.1k
        if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
14534
880
            return offset;
14535
15.2k
        } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
14536
2.05k
            return offset;
14537
2.05k
        }
14538
13.2k
        switch (tag_no-tagoffset) {
14539
6.69k
        case 0: /* PropertyIdentifier */
14540
6.69k
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
14541
6.69k
            break;
14542
993
        case 1: /* propertyArrayIndex */
14543
993
            offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
14544
993
            if (list != 0)
14545
46
                break; /* Continue decoding if this may be a list */
14546
            /* FALLTHROUGH */
14547
6.46k
        default:
14548
6.46k
            lastoffset = offset; /* Set loop end condition */
14549
6.46k
            break;
14550
13.2k
        }
14551
13.2k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14552
13.2k
    }
14553
7.37k
    return offset;
14554
10.3k
}
14555
14556
static unsigned
14557
fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t list)
14558
675
{
14559
675
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14560
675
    return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
14561
675
}
14562
14563
static unsigned
14564
fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14565
2.45k
{
14566
2.45k
    unsigned lastoffset = 0;
14567
14568
5.65k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14569
5.64k
        lastoffset = offset;
14570
14571
5.64k
        switch (fTagNo(tvb, offset)) {
14572
3.23k
        case 0: /* ObjectIdentifier */
14573
3.23k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
14574
3.23k
            break;
14575
1.59k
        case 1: /* PropertyIdentifier and propertyArrayIndex */
14576
1.59k
            offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
14577
1.59k
            col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14578
            /* FALLTHROUGH */
14579
2.41k
        default:
14580
2.41k
            lastoffset = offset; /* Set loop end condition */
14581
2.41k
            break;
14582
5.64k
        }
14583
5.61k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14584
5.61k
    }
14585
2.42k
    return offset;
14586
2.45k
}
14587
14588
#if 0
14589
static unsigned
14590
fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, unsigned offset)
14591
{
14592
    unsigned    lastoffset = 0;
14593
    uint8_t     tag_no, tag_info;
14594
    uint32_t    lvt;
14595
    proto_tree* subtree = tree;
14596
    proto_item* tt;
14597
14598
    while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
14599
        lastoffset = offset;
14600
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14601
        if (tag_is_closing(tag_info)) {
14602
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
14603
                &tag_no, &tag_info, &lvt);
14604
            continue;
14605
        }
14606
        switch (tag_no) {
14607
        case 0: /* ObjectIdentifier */
14608
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14609
            break;
14610
        case 1: /* PropertyIdentifier */
14611
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14612
            break;
14613
        case 2: /* propertyArrayIndex */
14614
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
14615
            break;
14616
        case 3:  /* Value */
14617
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14618
            break;
14619
        case 4:  /* Priority */
14620
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
14621
            break;
14622
        default:
14623
            break;
14624
        }
14625
    }
14626
    return offset;
14627
}
14628
#endif
14629
14630
static unsigned
14631
// NOLINTNEXTLINE(misc-no-recursion)
14632
fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14633
419
{
14634
419
    char  i = 1, *str_ar;
14635
419
    unsigned lastoffset = 0;
14636
419
    uint8_t tag_no;
14637
419
    uint8_t tag_info;
14638
419
    uint32_t lvt;
14639
14640
419
    if (propertyArrayIndex > 0) {
14641
        /* BACnetARRAY index 0 refers to the length
14642
        of the array, not the elements of the array.
14643
        BACnetARRAY index -1 is our internal flag that
14644
        the optional index was not used.
14645
        BACnetARRAY refers to this as all elements of the array.
14646
        If the optional index is specified for a BACnetARRAY,
14647
        then that specific array element is referenced. */
14648
168
        i = propertyArrayIndex;
14649
168
    }
14650
1.13k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
14651
        /* exit loop if nothing happens inside */
14652
1.12k
        lastoffset = offset;
14653
1.12k
        str_ar = wmem_strdup_printf(pinfo->pool, "%s[%d]: ",
14654
1.12k
            val_to_split_str(pinfo->pool, 87 , 512,
14655
1.12k
                BACnetPropertyIdentifier,
14656
1.12k
                ASHRAE_Reserved_Fmt,
14657
1.12k
                Vendor_Proprietary_Fmt),
14658
1.12k
            i++);
14659
1.12k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14660
1.12k
        if ( ! tag_is_context_specific(tag_info)) {
14661
            /* DMR Should be fAbstractNSyntax, but that's where we came from! */
14662
844
            offset = fApplicationTypes(tvb, pinfo, tree, offset, str_ar);
14663
844
        } else {
14664
279
            if (tag_is_opening(tag_info) && tag_no == 0) {
14665
34
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14666
34
                offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
14667
34
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14668
245
            } else if (tag_is_opening(tag_info) && tag_no == 1) {
14669
2
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14670
2
                offset = fDate(tvb, pinfo, tree, offset, "Date: ");
14671
2
                offset = fTime(tvb, pinfo, tree, offset, "Time: ");
14672
2
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14673
243
            } else if (tag_is_opening(tag_info) && tag_no == 2) {
14674
3
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14675
3
                offset = fXyColor(tvb, pinfo, tree, offset, "xy-color: ");
14676
3
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14677
240
            } else {
14678
                /* DMR Should be fAbstractNSyntax, but that's where we came from! */
14679
240
                offset = fApplicationTypes(tvb, pinfo, tree, offset, str_ar);
14680
240
            }
14681
279
        }
14682
        /* there are only 16 priority array elements */
14683
1.12k
        if (i > 16) {
14684
197
            break;
14685
197
        }
14686
926
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14687
926
    }
14688
14689
419
    return offset;
14690
419
}
14691
14692
static unsigned
14693
fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14694
1.18k
{
14695
1.18k
    uint8_t tag_no, tag_info;
14696
1.18k
    uint32_t lvt;
14697
1.18k
    unsigned lastoffset = 0;
14698
14699
3.23k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14700
3.22k
        lastoffset = offset;
14701
3.22k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14702
        /* quit loop if we spot an un-matched closing tag */
14703
3.22k
        if (tag_is_closing(tag_info)) {
14704
135
            break;
14705
135
        }
14706
3.09k
        switch (tag_no) {
14707
1.44k
        case 0: /* deviceIdentifier - OPTIONAL */
14708
1.44k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
14709
1.44k
            break;
14710
628
        case 1: /* ObjectIdentifier */
14711
628
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
14712
628
            break;
14713
1.02k
        default:
14714
1.02k
            return offset;
14715
3.09k
        }
14716
2.05k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14717
2.05k
    }
14718
143
    return offset;
14719
1.18k
}
14720
14721
static unsigned
14722
fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14723
103
{
14724
103
    uint8_t tag_no, tag_info;
14725
103
    uint32_t lvt;
14726
103
    unsigned lastoffset = 0;
14727
14728
249
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14729
247
        lastoffset = offset;
14730
247
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14731
        /* quit loop if we spot an un-matched closing tag */
14732
247
        if (tag_is_closing(tag_info)) {
14733
8
            break;
14734
8
        }
14735
239
        switch (tag_no) {
14736
35
        case 0: /* calendarEntry */
14737
35
            if (tag_is_opening(tag_info)) {
14738
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14739
0
                offset  = fCalendarEntry(tvb, pinfo, subtree, offset);
14740
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14741
0
            }
14742
35
            break;
14743
57
        case 1: /* calendarReference */
14744
57
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14745
57
            break;
14746
10
        case 2: /* list of BACnetTimeValue */
14747
10
            if (tag_is_opening(tag_info)) {
14748
4
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14749
4
                offset  = fTimeValue(tvb, pinfo, subtree, offset);
14750
4
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14751
6
            } else {
14752
6
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14753
6
            }
14754
10
            break;
14755
86
        case 3: /* eventPriority */
14756
86
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
14757
86
            break;
14758
51
        default:
14759
51
            return offset;
14760
239
        }
14761
187
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14762
187
    }
14763
51
    return offset;
14764
103
}
14765
14766
static unsigned
14767
fNetworkSecurityPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14768
13
{
14769
13
    unsigned   lastoffset = 0;
14770
13
    uint8_t tag_no, tag_info;
14771
13
    uint32_t lvt;
14772
13
    proto_tree *subtree;
14773
14774
13
    subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "network security policy");
14775
14776
99
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14777
99
        lastoffset = offset;
14778
        /* check the tag.  A closing tag means we are done */
14779
99
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14780
99
        if (tag_is_closing(tag_info)) {
14781
1
            return offset;
14782
1
        }
14783
98
        switch (tag_no) {
14784
76
        case 0: /* port-id */
14785
76
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "port-id: ");
14786
76
            break;
14787
10
        case 1: /* security-level */
14788
10
            offset  = fEnumeratedTag(tvb, pinfo, subtree, offset,
14789
10
                "security-level: ", BACnetSecurityPolicy);
14790
10
            break;
14791
12
        default:
14792
12
            return offset;
14793
98
        }
14794
98
    }
14795
14796
0
    return offset;
14797
13
}
14798
14799
static unsigned
14800
fKeyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14801
0
{
14802
0
    unsigned   lastoffset = 0;
14803
0
    uint8_t tag_no, tag_info;
14804
0
    uint32_t lvt;
14805
14806
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14807
0
        lastoffset = offset;
14808
        /* check the tag.  A closing tag means we are done */
14809
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14810
0
        if (tag_is_closing(tag_info)) {
14811
0
            return offset;
14812
0
        }
14813
0
        switch (tag_no) {
14814
0
        case 0: /* algorithm */
14815
0
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "algorithm: ");
14816
0
            break;
14817
0
        case 1: /* key-id */
14818
0
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "key-id: ");
14819
0
            break;
14820
0
        default:
14821
0
            return offset;
14822
0
        }
14823
0
    }
14824
14825
0
    return offset;
14826
0
}
14827
14828
static unsigned
14829
fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14830
21
{
14831
21
    unsigned   lastoffset = 0;
14832
21
    uint8_t tag_no, tag_info;
14833
21
    uint32_t lvt;
14834
21
    proto_tree *subtree;
14835
14836
21
    subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "security keyset");
14837
14838
66
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14839
61
        lastoffset = offset;
14840
        /* check the tag.  A closing tag means we are done */
14841
61
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14842
61
        if (tag_is_closing(tag_info)) {
14843
0
            return offset;
14844
0
        }
14845
61
        switch (tag_no) {
14846
28
        case 0: /* key-revision */
14847
28
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "key-revision: ");
14848
28
            break;
14849
0
        case 1: /* activation-time */
14850
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14851
0
            offset = fDateTime(tvb, pinfo, subtree, offset, "activation-time: ");
14852
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14853
0
            break;
14854
16
        case 2: /* expiration-time */
14855
16
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14856
16
            offset = fDateTime(tvb, pinfo, subtree, offset, "expiration-time: ");
14857
16
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14858
16
            break;
14859
4
        case 3: /* key-ids */
14860
4
            if (tag_is_opening(tag_info)) {
14861
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14862
0
                offset = fKeyIdentifier(tvb, pinfo, subtree, offset);
14863
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14864
4
            } else {
14865
4
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14866
4
            }
14867
4
            break;
14868
13
        default:
14869
13
            return offset;
14870
61
        }
14871
61
    }
14872
14873
5
    return offset;
14874
21
}
14875
14876
static unsigned
14877
fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14878
14
{
14879
14
    unsigned   lastoffset = 0;
14880
14
    uint8_t tag_no, tag_info;
14881
14
    uint32_t lvt;
14882
14883
50
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14884
49
        lastoffset = offset;
14885
49
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14886
        /* quit loop if we spot a closing tag */
14887
49
        if (tag_is_closing(tag_info)) {
14888
3
            break;
14889
3
        }
14890
14891
46
        switch (fTagNo(tvb, offset)) {
14892
15
        case 0: /* propertyIdentifier */
14893
15
            offset  = fPropertyIdentifier(tvb, pinfo, tree, offset);
14894
15
            break;
14895
22
        case 1: /* propertyArrayIndex */
14896
22
            offset  = fPropertyArrayIndex(tvb, pinfo, tree, offset);
14897
22
            break;
14898
0
        case 2: /* relationSpecifier */
14899
0
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
14900
0
                "relation Specifier: ", BACnetRelationSpecifier);
14901
0
            break;
14902
4
        case 3: /* comparisonValue */
14903
4
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14904
4
            offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
14905
4
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14906
4
            break;
14907
5
        default:
14908
5
            return offset;
14909
46
        }
14910
40
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14911
40
    }
14912
8
    return offset;
14913
14
}
14914
14915
static unsigned
14916
fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14917
24
{
14918
24
    unsigned   lastoffset = 0;
14919
24
    uint8_t tag_no, tag_info;
14920
24
    uint32_t lvt;
14921
14922
312
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14923
309
        lastoffset = offset;
14924
309
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14925
        /* quit loop if we spot a closing tag */
14926
309
        if (tag_is_closing(tag_info)) {
14927
5
            break;
14928
5
        }
14929
14930
304
        switch (tag_no) {
14931
276
        case 0: /* selectionLogic */
14932
276
            offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
14933
276
                "selection Logic: ", BACnetSelectionLogic);
14934
276
            break;
14935
15
        case 1: /* listOfSelectionCriteria */
14936
15
            if (tag_is_opening(tag_info)) {
14937
14
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14938
14
                offset  = fSelectionCriteria(tvb, pinfo, subtree, offset);
14939
14
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14940
14
            } else {
14941
1
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14942
1
            }
14943
15
            break;
14944
13
        default:
14945
13
            return offset;
14946
304
        }
14947
289
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14948
289
    }
14949
9
    return offset;
14950
24
}
14951
14952
14953
static unsigned
14954
fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, unsigned offset)
14955
32
{
14956
32
    unsigned   lastoffset = 0;
14957
32
    uint8_t tag_no, tag_info;
14958
32
    uint32_t lvt;
14959
14960
58
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14961
54
        lastoffset = offset;
14962
54
        fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14963
14964
54
        if (tag_is_opening(tag_info) && tag_no < 2) {
14965
28
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14966
28
            switch (tag_no) {
14967
24
            case 0: /* objectSelectionCriteria */
14968
24
                offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
14969
24
                break;
14970
4
            case 1: /* listOfPropertyReferences */
14971
4
                offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
14972
4
                break;
14973
0
            default:
14974
0
                return offset;
14975
28
            }
14976
26
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14977
26
        }
14978
52
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14979
52
    }
14980
30
    return offset;
14981
32
}
14982
14983
static unsigned
14984
fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14985
103
{
14986
103
    unsigned    lastoffset = 0;
14987
103
    uint8_t     tag_no, tag_info;
14988
103
    uint32_t    lvt;
14989
103
    proto_tree *subtree = tree;
14990
14991
575
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14992
574
        lastoffset = offset;
14993
574
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14994
574
        switch (tag_no) {
14995
279
        case 0: /* objectIdentifier */
14996
279
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14997
279
            break;
14998
209
        case 1: /* listOfPropertyReferences */
14999
209
            if (tag_is_opening(tag_info)) {
15000
190
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfPropertyReferences");
15001
190
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15002
190
                offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
15003
190
            } else if (tag_is_closing(tag_info)) {
15004
7
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
15005
7
                    &tag_no, &tag_info, &lvt);
15006
7
                subtree = tree;
15007
12
            } else {
15008
                /* error condition: let caller handle */
15009
12
                return offset;
15010
12
            }
15011
197
            break;
15012
197
        default:
15013
86
            return offset;
15014
574
        }
15015
472
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15016
472
    }
15017
1
    return offset;
15018
103
}
15019
15020
static unsigned
15021
// NOLINTNEXTLINE(misc-no-recursion)
15022
fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15023
828
{
15024
828
    unsigned    lastoffset = 0, len;
15025
828
    uint8_t     tag_no;
15026
828
    uint8_t     tag_info;
15027
828
    uint32_t    lvt;
15028
828
    proto_tree *subtree = tree;
15029
15030
5.23k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15031
5.22k
        lastoffset = offset;
15032
5.22k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15033
        /* maybe a listOfReadAccessResults if we spot a closing tag here */
15034
5.22k
        if (tag_is_closing(tag_info)) {
15035
1.61k
            offset += len;
15036
1.61k
            if ((tag_no == 4 || tag_no == 5) && (subtree != tree))
15037
24
                subtree = subtree->parent; /* Value and error have extra subtree */
15038
15039
1.61k
        if (tag_no == 1) {
15040
            /* closing list of results for this objectSpecifier */
15041
8
            fTagHeaderTree(tvb, pinfo, subtree, offset - len, &tag_no, &tag_info, &lvt);
15042
            /* look if another objectSpecifier follows here */
15043
8
            if (tvb_reported_length_remaining(tvb, offset) <= 0)
15044
0
                return offset; /* nothing more to decode left */
15045
15046
8
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15047
8
            if (tag_no != 0 || tag_info != 12)
15048
8
                return offset; /* no objectSpecifier */
15049
8
            }
15050
15051
1.60k
            continue;
15052
1.61k
        }
15053
15054
3.60k
        switch (tag_no) {
15055
1.66k
        case 0: /* objectSpecifier */
15056
1.66k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
15057
1.66k
            break;
15058
841
        case 1: /* list of Results */
15059
841
            if (tag_is_opening(tag_info)) {
15060
733
                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfResults");
15061
733
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15062
733
            } else {
15063
108
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15064
108
            }
15065
841
            break;
15066
479
        case 2: /* propertyIdentifier */
15067
479
            offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
15068
479
            break;
15069
70
        case 5: /* propertyAccessError */
15070
70
            if (tag_is_opening(tag_info)) {
15071
43
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "propertyAccessError");
15072
43
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15073
                /* Error Code follows */
15074
43
                offset  = fError(tvb, pinfo, subtree, offset);
15075
43
                fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15076
43
            }
15077
27
            else {
15078
27
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15079
27
            }
15080
70
            break;
15081
552
        default:
15082
552
            return offset;
15083
3.60k
        }
15084
3.04k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15085
3.04k
    }
15086
258
    return offset;
15087
828
}
15088
15089
15090
static unsigned
15091
fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15092
5
{
15093
    /* listOfReadAccessResults */
15094
5
    return fReadAccessResult(tvb, pinfo, tree, offset);
15095
5
}
15096
15097
15098
static unsigned
15099
fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15100
55
{
15101
55
    unsigned   lastoffset = 0;
15102
55
    uint8_t tag_no, tag_info;
15103
55
    uint32_t lvt;
15104
15105
1.07k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15106
1.06k
        lastoffset = offset;
15107
1.06k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15108
15109
1.06k
        if (tag_no < 2) {
15110
1.01k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15111
1.01k
            switch (tag_no) {
15112
535
            case 0: /* objectSpecifier */
15113
535
                switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
15114
445
                case 0: /* objectType */
15115
445
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
15116
445
                    break;
15117
36
                case 1: /* objectIdentifier */
15118
36
                    offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
15119
36
                    break;
15120
53
                default:
15121
53
                    break;
15122
535
                }
15123
532
                break;
15124
532
            case 1: /* propertyValue */
15125
484
                if (tag_is_opening(tag_info)) {
15126
18
                    offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
15127
466
                } else {
15128
466
                    expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15129
466
                }
15130
484
                break;
15131
0
            default:
15132
0
                break;
15133
1.01k
            }
15134
1.01k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15135
1.01k
        }
15136
1.06k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
15137
1.06k
    }
15138
51
    return offset;
15139
55
}
15140
15141
static unsigned
15142
fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15143
1
{
15144
1
    return fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
15145
1
}
15146
15147
static unsigned
15148
fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15149
39
{
15150
39
    uint8_t     tag_no, tag_info;
15151
39
    uint32_t    lvt;
15152
39
    proto_tree *subtree = tree;
15153
15154
39
    offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
15155
15156
39
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
15157
        /* optional range choice */
15158
27
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15159
27
        if (tag_is_opening(tag_info)) {
15160
5
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
15161
5
                val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
15162
5
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15163
5
            switch (tag_no) {
15164
1
            case 3: /* range byPosition */
15165
2
            case 6: /* range bySequenceNumber, 2004 spec */
15166
2
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
15167
2
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
15168
2
                break;
15169
1
            case 4: /* range byTime - deprecated in 2004 */
15170
1
            case 7: /* 2004 spec */
15171
1
                offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
15172
1
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
15173
1
                break;
15174
0
            case 5: /* range timeRange - deprecated in 2004 */
15175
0
                offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
15176
0
                offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
15177
0
                break;
15178
2
            default:
15179
2
                break;
15180
5
            }
15181
4
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15182
4
        }
15183
27
    }
15184
38
    return offset;
15185
39
}
15186
15187
static unsigned
15188
fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15189
222
{
15190
222
    uint8_t     tag_no, tag_info;
15191
222
    uint32_t    lvt;
15192
222
    proto_tree *subtree = tree;
15193
15194
    /* set the optional global properties to indicate not-used */
15195
222
    propertyArrayIndex = -1;
15196
    /* objectIdentifier, propertyIdentifier, and
15197
       OPTIONAL propertyArrayIndex */
15198
222
    offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
15199
    /* resultFlags => BACnetResultFlags ::= BIT STRING */
15200
222
    offset = fBitStringTagVS(tvb, pinfo, tree, offset,
15201
222
        "resultFlags: ",
15202
222
        BACnetResultFlags);
15203
    /* itemCount */
15204
222
    offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
15205
    /* itemData */
15206
222
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15207
222
    if (tag_is_opening(tag_info)) {
15208
211
        col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15209
211
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "itemData");
15210
211
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15211
211
        offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
15212
211
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15213
211
    }
15214
    /* firstSequenceNumber - OPTIONAL */
15215
222
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
15216
107
        offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
15217
107
    }
15218
15219
222
    return offset;
15220
222
}
15221
15222
static unsigned
15223
fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15224
34
{
15225
34
    unsigned    lastoffset = 0;
15226
34
    uint32_t    lvt;
15227
34
    uint8_t     tag_no, tag_info;
15228
34
    proto_tree* subtree = NULL;
15229
15230
34
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15231
15232
34
    if (tag_is_opening(tag_info)) {
15233
10
        subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL,
15234
10
            val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
15235
10
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15236
10
        offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
15237
10
        offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
15238
15239
10
        if (tag_no == 1) {
15240
5
            while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
15241
                /* exit loop if nothing happens inside */
15242
4
                lastoffset = offset;
15243
4
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
15244
4
            }
15245
1
        }
15246
15247
10
        if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
15248
            /* More Flag is not set, so we can look for closing tag in this segment */
15249
9
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15250
9
            if (tag_is_closing(tag_info)) {
15251
3
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15252
3
            }
15253
9
        }
15254
10
    }
15255
34
    return offset;
15256
34
}
15257
15258
static unsigned
15259
fAccessRule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15260
112
{
15261
112
    unsigned   lastoffset = 0;
15262
112
    uint8_t tag_no, tag_info;
15263
112
    uint32_t lvt;
15264
15265
2.67k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15266
2.67k
        lastoffset = offset;
15267
2.67k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15268
        /* quit loop if we spot a closing tag */
15269
2.67k
        if (tag_is_closing(tag_info)) {
15270
31
            break;
15271
31
        }
15272
15273
2.63k
        switch (tag_no) {
15274
1.65k
        case 0: /* time-range-specifier */
15275
1.65k
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "time-range-specifier: ", NULL);
15276
1.65k
            break;
15277
306
        case 1: /* time-range */
15278
306
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15279
306
            offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
15280
306
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15281
306
            break;
15282
228
        case 2: /* location-specifier */
15283
228
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "location-specifier: ", NULL);
15284
228
            break;
15285
219
        case 3: /* location */
15286
219
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15287
219
            offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
15288
219
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15289
219
            break;
15290
166
        case 4: /* enable */
15291
166
            offset = fBooleanTag(tvb, pinfo, tree, offset, "enable: ");
15292
166
            break;
15293
69
        default:
15294
69
            break;
15295
2.63k
        }
15296
15297
2.63k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
15298
2.63k
    }
15299
15300
105
    return offset;
15301
112
}
15302
15303
static unsigned
15304
fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15305
21
{
15306
21
    uint8_t     tag_no, tag_info;
15307
21
    uint32_t    lvt;
15308
21
    proto_tree *subtree = tree;
15309
15310
21
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
15311
15312
21
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15313
15314
21
    if (tag_is_opening(tag_info)) {
15315
12
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
15316
12
                        val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
15317
12
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15318
12
        offset  = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
15319
12
        offset  = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BacnetFileRequestedCount, "unknown option"));
15320
12
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15321
12
    }
15322
21
    return offset;
15323
21
}
15324
15325
static unsigned
15326
fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15327
18
{
15328
15329
18
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier); /* file Identifier */
15330
18
    offset = fAccessMethod(tvb, pinfo, tree, offset);
15331
15332
18
    return offset;
15333
18
}
15334
15335
static unsigned
15336
fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15337
4
{
15338
4
    unsigned tag_no = fTagNo(tvb, offset);
15339
4
    return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
15340
4
}
15341
15342
static unsigned
15343
fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15344
16
{
15345
16
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
15346
16
    offset = fAccessMethod(tvb, pinfo, tree, offset);
15347
15348
16
    return offset;
15349
16
}
15350
15351
static unsigned
15352
fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15353
31
{
15354
31
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15355
31
    return fReadAccessSpecification(tvb, pinfo, subtree, offset);
15356
31
}
15357
15358
static unsigned
15359
fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15360
22
{
15361
22
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15362
22
    return fReadAccessResult(tvb, pinfo, tree, offset);
15363
22
}
15364
15365
static unsigned
15366
fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15367
6.82k
{
15368
6.82k
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
15369
13
        return offset;
15370
15371
6.81k
    switch (service_choice) {
15372
227
    case 0: /* acknowledgeAlarm */
15373
227
        offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
15374
227
        break;
15375
180
    case 1: /* confirmedCOVNotification */
15376
180
        offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
15377
180
        break;
15378
2.27k
    case 2: /* confirmedEventNotification */
15379
2.27k
        offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
15380
2.27k
        break;
15381
0
    case 3: /* confirmedGetAlarmSummary conveys no parameters */
15382
0
        break;
15383
97
    case 4: /* getEnrollmentSummaryRequest */
15384
97
        offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
15385
97
        break;
15386
67
    case 5: /* subscribeCOVRequest */
15387
67
        offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
15388
67
        break;
15389
21
    case 6: /* atomicReadFile-Request */
15390
21
        offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
15391
21
        break;
15392
18
    case 7: /* atomicWriteFile-Request */
15393
18
        offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
15394
18
        break;
15395
1.09k
    case 8: /* AddListElement-Request */
15396
1.09k
        offset = fAddListElementRequest(tvb, pinfo, tree, offset);
15397
1.09k
        break;
15398
31
    case 9: /* removeListElement-Request */
15399
31
        offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
15400
31
        break;
15401
55
    case 10: /* createObjectRequest */
15402
55
        offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
15403
55
        break;
15404
2
    case 11: /* deleteObject */
15405
2
        offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
15406
2
        break;
15407
4
    case 12:
15408
4
        offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
15409
4
        break;
15410
32
    case 13:
15411
32
        offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
15412
32
        break;
15413
31
    case 14:
15414
31
        offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
15415
31
        break;
15416
123
    case 15:
15417
123
        offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
15418
123
        break;
15419
47
    case 16:
15420
47
        offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
15421
47
        break;
15422
39
    case 17:
15423
39
        offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
15424
39
        break;
15425
104
    case 18:
15426
104
        offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
15427
104
        break;
15428
65
    case 19:
15429
65
        offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
15430
65
        break;
15431
26
    case 20:
15432
26
        offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
15433
26
        break;
15434
2
    case 21:
15435
2
        offset = fVtOpenRequest(tvb, pinfo, tree, offset);
15436
2
        break;
15437
48
    case 22:
15438
48
        offset = fVtCloseRequest(tvb, pinfo, tree, offset);
15439
48
        break;
15440
13
    case 23:
15441
13
        offset = fVtDataRequest(tvb, pinfo, tree, offset);
15442
13
        break;
15443
45
    case 24:
15444
45
        offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
15445
45
        break;
15446
10
    case 25:
15447
10
        offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
15448
10
        break;
15449
39
    case 26:
15450
39
        offset = fReadRangeRequest(tvb, pinfo, tree, offset);
15451
39
        break;
15452
45
    case 27:
15453
45
        offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
15454
45
        break;
15455
36
    case 28:
15456
36
        offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
15457
36
        break;
15458
24
    case 29:
15459
24
        offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
15460
24
        break;
15461
118
    case 30:
15462
118
        offset = fSubscribeCOVPropertyMultipleRequest(tvb, pinfo, tree, offset);
15463
118
        break;
15464
92
    case 31:
15465
92
        offset = fConfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
15466
92
        break;
15467
1.41k
    case 32:
15468
1.41k
        offset = fConfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
15469
1.41k
        break;
15470
224
    case 33:
15471
224
        offset = fAuditLogQueryRequest(tvb, pinfo, tree, offset);
15472
224
        break;
15473
93
    case 34:
15474
93
        offset = fAuthRequestRequest(tvb, pinfo, tree, offset);
15475
93
        break;
15476
71
    default:
15477
71
        return offset;
15478
6.81k
    }
15479
3.73k
    return offset;
15480
6.81k
}
15481
15482
static unsigned
15483
fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15484
741
{
15485
741
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
15486
7
        return offset;
15487
15488
734
    switch (service_choice) {
15489
20
    case 3: /* confirmedEventNotificationAck */
15490
20
        offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
15491
20
        break;
15492
37
    case 4: /* getEnrollmentSummaryAck */
15493
37
        offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
15494
37
        break;
15495
16
    case 6: /* atomicReadFile */
15496
16
        offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
15497
16
        break;
15498
4
    case 7: /* atomicReadFileAck */
15499
4
        offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
15500
4
        break;
15501
1
    case 10: /* createObject */
15502
1
        offset = fCreateObjectAck(tvb, pinfo, tree, offset);
15503
1
        break;
15504
38
    case 12:
15505
38
        offset = fReadPropertyAck(tvb, pinfo, tree, offset);
15506
38
        break;
15507
5
    case 13:
15508
5
        offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
15509
5
        break;
15510
22
    case 14:
15511
22
        offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
15512
22
        break;
15513
3
    case 18:
15514
3
        offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
15515
3
        break;
15516
21
    case 21:
15517
21
        offset = fVtOpenAck(tvb, pinfo, tree, offset);
15518
21
        break;
15519
6
    case 23:
15520
6
        offset = fVtDataAck(tvb, pinfo, tree, offset);
15521
6
        break;
15522
2
    case 24:
15523
2
        offset = fAuthenticateAck(tvb, pinfo, tree, offset);
15524
2
        break;
15525
222
    case 26:
15526
222
        offset = fReadRangeAck(tvb, pinfo, tree, offset);
15527
222
        break;
15528
70
    case 29:
15529
70
        offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
15530
70
        break;
15531
74
    case 33:
15532
74
        offset = fAuditLogQueryAck(tvb, pinfo, tree, offset);
15533
74
        break;
15534
156
    case 34:
15535
156
        offset = fAuthRequestAck(tvb, pinfo, tree, offset);
15536
156
        break;
15537
37
    default:
15538
37
        return offset;
15539
734
    }
15540
391
    return offset;
15541
734
}
15542
15543
static unsigned
15544
fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15545
31
{
15546
    /* BACnetObjectIdentifier */
15547
31
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
15548
15549
    /* MaxAPDULengthAccepted */
15550
31
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
15551
15552
    /* segmentationSupported */
15553
31
    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
15554
31
        "Segmentation Supported: ", BACnetSegmentation);
15555
15556
    /* vendor ID */
15557
31
    return fVendorIdentifier(tvb, pinfo, tree, offset);
15558
31
}
15559
15560
static unsigned
15561
fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15562
5
{
15563
    /* BACnetDeviceIdentifier */
15564
5
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
15565
15566
    /* BACnetObjectIdentifier */
15567
5
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
15568
15569
    /* ObjectName */
15570
5
    return fObjectName(tvb, pinfo, tree, offset);
15571
5
}
15572
15573
static unsigned
15574
fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned offset)
15575
29
{
15576
29
    unsigned   lastoffset = 0;
15577
29
    unsigned   val;
15578
29
    uint8_t tag_len;
15579
15580
29
    uint8_t tag_no, tag_info;
15581
29
    uint32_t lvt;
15582
15583
94
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15584
89
        lastoffset = offset;
15585
15586
89
        tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15587
15588
89
        switch (tag_no) {
15589
58
        case 0:
15590
            /* DeviceInstanceRangeLowLimit Optional */
15591
58
            if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15592
25
                col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
15593
58
            offset = fDevice_Instance(tvb, pinfo, tree, offset,
15594
58
                hf_Device_Instance_Range_Low_Limit);
15595
58
            break;
15596
19
        case 1:
15597
            /* DeviceInstanceRangeHighLimit Optional but
15598
                required if DeviceInstanceRangeLowLimit is there */
15599
19
            if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15600
13
                col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
15601
19
            offset = fDevice_Instance(tvb, pinfo, tree, offset,
15602
19
                hf_Device_Instance_Range_High_Limit);
15603
19
            break;
15604
11
        default:
15605
11
            return offset;
15606
89
        }
15607
65
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15608
65
    }
15609
5
    return offset;
15610
29
}
15611
15612
static unsigned
15613
fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15614
656
{
15615
656
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
15616
4
        return offset;
15617
15618
652
    switch (service_choice) {
15619
31
    case 0: /* I-Am-Request */
15620
31
        offset = fIAmRequest(tvb, pinfo, tree, offset);
15621
31
        break;
15622
5
    case 1: /* i-Have Request */
15623
5
        offset = fIHaveRequest(tvb, pinfo, tree, offset);
15624
5
    break;
15625
24
    case 2: /* unconfirmedCOVNotification */
15626
24
        offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
15627
24
        break;
15628
58
    case 3: /* unconfirmedEventNotification */
15629
58
        offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
15630
58
        break;
15631
10
    case 4: /* unconfirmedPrivateTransfer */
15632
10
        offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
15633
10
        break;
15634
8
    case 5: /* unconfirmedTextMessage */
15635
8
        offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
15636
8
        break;
15637
9
    case 6: /* timeSynchronization */
15638
9
        offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
15639
9
        break;
15640
59
    case 7: /* who-Has */
15641
59
        offset = fWhoHas(tvb, pinfo, tree, offset);
15642
59
        break;
15643
29
    case 8: /* who-Is */
15644
29
        offset = fWhoIsRequest(tvb, pinfo, tree, offset);
15645
29
        break;
15646
4
    case 9: /* utcTimeSynchronization */
15647
4
        offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
15648
4
        break;
15649
260
    case 10:
15650
260
        offset = fWriteGroupRequest(tvb, pinfo, tree, offset);
15651
260
        break;
15652
15
    case 11:
15653
15
        offset = fUnconfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
15654
15
        break;
15655
16
    case 12:
15656
16
        offset = fUnconfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
15657
16
        break;
15658
5
    case 13:
15659
5
        offset = fWhoAmIRequest(tvb, pinfo, tree, offset);
15660
5
        break;
15661
18
    case 14:
15662
18
        offset = fYouAreRequest(tvb, pinfo, tree, offset);
15663
18
        break;
15664
101
    default:
15665
101
        break;
15666
652
    }
15667
486
    return offset;
15668
652
}
15669
15670
static unsigned
15671
fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset, uint8_t ack,
15672
        int *svc, proto_item **tt)
15673
7.72k
{
15674
7.72k
    proto_item *tc;
15675
7.72k
    proto_tree *bacapp_tree_control;
15676
7.72k
    int         tmp;
15677
7.72k
    unsigned    extra = 2;
15678
15679
7.72k
    bacapp_seq = 0;
15680
7.72k
    tmp = tvb_get_int8(tvb, offset);
15681
7.72k
    bacapp_flags = tmp & 0x0f;
15682
15683
7.72k
    if (ack == 0) {
15684
6.93k
        extra = 3;
15685
6.93k
    }
15686
7.72k
    *svc = tvb_get_int8(tvb, offset+extra);
15687
7.72k
    if (bacapp_flags & 0x08)
15688
235
        *svc = tvb_get_int8(tvb, offset+extra+2);
15689
15690
7.72k
    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
15691
7.72k
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
15692
7.72k
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
15693
15694
7.72k
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
15695
7.72k
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
15696
7.72k
    if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
15697
6.93k
        proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
15698
6.93k
        proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
15699
6.93k
                            offset, 1, ENC_BIG_ENDIAN);
15700
6.93k
        proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
15701
6.93k
                            offset, 1, ENC_BIG_ENDIAN);
15702
6.93k
    }
15703
7.72k
    offset++;
15704
7.72k
    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
15705
7.72k
    if (bacapp_flags & 0x08) {
15706
235
        bacapp_seq = tvb_get_uint8(tvb, offset);
15707
235
        proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
15708
235
            offset++, 1, ENC_BIG_ENDIAN);
15709
235
        proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
15710
235
            offset++, 1, ENC_BIG_ENDIAN);
15711
235
    }
15712
7.72k
    *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
15713
7.72k
                  offset++, 1, ENC_BIG_ENDIAN);
15714
7.72k
    return offset;
15715
7.72k
}
15716
15717
static unsigned
15718
fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset, int svc)
15719
6.82k
{   /* BACnet-Confirmed-Request */
15720
    /* ASHRAE 135-2001 20.1.2 */
15721
15722
6.82k
    return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
15723
6.82k
}
15724
15725
static unsigned
15726
fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
15727
6.80k
{   /* BACnet-Confirmed-Request */
15728
    /* ASHRAE 135-2001 20.1.2 */
15729
6.80k
    int         svc;
15730
6.80k
    proto_item *tt = 0;
15731
15732
6.80k
    offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
15733
6.80k
    return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
15734
6.80k
}
15735
15736
static unsigned
15737
fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
15738
656
{   /* BACnet-Unconfirmed-Request-PDU */
15739
    /* ASHRAE 135-2001 20.1.3 */
15740
15741
656
    int tmp;
15742
15743
656
    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
15744
15745
656
    tmp = tvb_get_uint8(tvb, offset);
15746
656
    proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
15747
656
        offset++, 1, ENC_BIG_ENDIAN);
15748
    /* Service Request follows... Variable Encoding 20.2ff */
15749
656
    return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
15750
656
}
15751
15752
static unsigned
15753
fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
15754
46
{   /* BACnet-Simple-Ack-PDU */
15755
    /* ASHRAE 135-2001 20.1.4 */
15756
15757
46
    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
15758
15759
46
    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
15760
46
                offset++, 1, ENC_BIG_ENDIAN);
15761
46
    proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
15762
46
                offset++, 1, ENC_BIG_ENDIAN);
15763
15764
46
    return offset;
15765
46
}
15766
15767
static unsigned
15768
fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset, int svc)
15769
741
{   /* BACnet-Complex-Ack-PDU */
15770
    /* ASHRAE 135-2001 20.1.5 */
15771
15772
    /* Service ACK follows... */
15773
741
    return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
15774
741
}
15775
15776
static unsigned
15777
fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
15778
693
{   /* BACnet-Complex-Ack-PDU */
15779
    /* ASHRAE 135-2001 20.1.5 */
15780
693
    int         svc;
15781
693
    proto_item *tt = 0;
15782
15783
693
    offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
15784
693
    return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
15785
693
}
15786
15787
static unsigned
15788
fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
15789
59
{   /* BACnet-SegmentAck-PDU */
15790
    /* ASHRAE 135-2001 20.1.6 */
15791
15792
59
    proto_item *tc;
15793
59
    proto_tree *bacapp_tree_control;
15794
15795
59
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
15796
59
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
15797
15798
59
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
15799
59
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
15800
59
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
15801
59
                offset++, 1, ENC_BIG_ENDIAN);
15802
59
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
15803
59
                offset++, 1, ENC_BIG_ENDIAN);
15804
59
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
15805
59
                offset++, 1, ENC_BIG_ENDIAN);
15806
59
    return offset;
15807
59
}
15808
15809
static unsigned
15810
fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15811
1.85k
{
15812
1.85k
    uint8_t tag_info   = 0;
15813
1.85k
    uint8_t parsed_tag = 0;
15814
1.85k
    uint32_t lvt        = 0;
15815
15816
1.85k
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
15817
1.85k
    offset  = fError(tvb, pinfo, tree, offset);
15818
1.85k
    return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
15819
1.85k
}
15820
15821
static unsigned
15822
fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15823
106
{
15824
106
    unsigned    lastoffset        = 0;
15825
106
    uint8_t     tag_no            = 0, tag_info = 0;
15826
106
    uint32_t    lvt               = 0;
15827
106
    proto_tree *subtree           = tree;
15828
15829
106
    unsigned    vendor_identifier = 0;
15830
106
    unsigned    service_number    = 0;
15831
106
    uint8_t     tag_len           = 0;
15832
15833
2.88k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
15834
        /* exit loop if nothing happens inside */
15835
2.87k
        lastoffset = offset;
15836
2.87k
        tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15837
2.87k
        switch (tag_no) {
15838
926
        case 0: /* errorType */
15839
926
            offset = fContextTaggedError(tvb, pinfo, subtree, offset);
15840
926
            break;
15841
862
        case 1: /* vendorID */
15842
862
            fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
15843
862
            col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ",    vendor_identifier);
15844
862
            offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
15845
862
            break;
15846
760
        case 2: /* serviceNumber */
15847
760
            fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
15848
760
            col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
15849
760
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
15850
760
            break;
15851
256
        case 3: /* errorParameters */
15852
256
            if (tag_is_opening(tag_info)) {
15853
4
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
15854
4
                    ett_bacapp_value, NULL, "error Parameters");
15855
4
                propertyIdentifier = -1;
15856
4
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15857
4
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
15858
252
            } else if (tag_is_closing(tag_info)) {
15859
244
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
15860
244
                    &tag_no, &tag_info, &lvt);
15861
244
                subtree = tree;
15862
244
            } else {
15863
                /* error condition: let caller handle */
15864
8
                return offset;
15865
8
            }
15866
248
            break;
15867
248
        default:
15868
71
            return offset;
15869
2.87k
        }
15870
2.77k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15871
2.77k
    }
15872
5
    return offset;
15873
106
}
15874
15875
static unsigned
15876
fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15877
55
{
15878
55
    unsigned lastoffset = 0;
15879
15880
600
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15881
595
        lastoffset = offset;
15882
595
        switch (fTagNo(tvb, offset)) {
15883
407
        case 0: /* errorType */
15884
407
            offset = fContextTaggedError(tvb, pinfo, tree, offset);
15885
407
            break;
15886
151
        case 1: /* firstFailedElementNumber */
15887
151
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
15888
151
            break;
15889
37
        default:
15890
37
            return offset;
15891
595
        }
15892
545
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15893
545
    }
15894
5
    return offset;
15895
55
}
15896
15897
static unsigned
15898
fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15899
39
{
15900
    /* Identical to CreateObjectError */
15901
39
    return fCreateObjectError(tvb, pinfo, tree, offset);
15902
39
}
15903
15904
static unsigned
15905
fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15906
23
{
15907
23
    uint8_t tag_no = 0, tag_info = 0;
15908
23
    uint32_t lvt = 0;
15909
15910
23
    if (fTagNo(tvb, offset) == 0) {
15911
        /* errorType */
15912
18
        offset = fContextTaggedError(tvb, pinfo, tree, offset);
15913
18
        if (fTagNo(tvb, offset) == 1) {
15914
            /* listOfVTSessionIdentifiers [OPTIONAL] */
15915
9
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15916
9
            offset  = fVtCloseRequest(tvb, pinfo, tree, offset);
15917
9
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15918
9
        }
15919
18
    }
15920
    /* should report bad packet if initial tag wasn't 0 */
15921
23
    return offset;
15922
23
}
15923
15924
static unsigned
15925
fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15926
27
{
15927
27
    unsigned   lastoffset = 0;
15928
27
    uint8_t tag_no     = 0, tag_info = 0;
15929
27
    uint32_t lvt        = 0;
15930
15931
27
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15932
359
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15933
356
        lastoffset = offset;
15934
356
        switch (fTagNo(tvb, offset)) {
15935
193
        case 0: /* errorType */
15936
193
            offset = fContextTaggedError(tvb, pinfo, tree, offset);
15937
193
            break;
15938
143
        case 1: /* firstFailedWriteAttempt */
15939
143
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15940
143
            offset  = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
15941
143
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15942
143
            break;
15943
20
        default:
15944
20
            return offset;
15945
356
        }
15946
332
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15947
332
    }
15948
3
    return offset;
15949
27
}
15950
15951
static unsigned
15952
fErrorClass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15953
2.76k
{
15954
2.76k
    uint32_t    val = 0, lvt;
15955
2.76k
    uint8_t     tag_no, tag_info;
15956
2.76k
    proto_item *ti;
15957
2.76k
    proto_tree *subtree;
15958
2.76k
    unsigned    tag_len;
15959
15960
2.76k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15961
2.76k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15962
917
    {
15963
917
        ti = proto_tree_add_uint(tree, hf_bacapp_error_class,
15964
917
            tvb, offset, lvt+tag_len, val);
15965
917
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
15966
917
    }
15967
1.84k
    else
15968
1.84k
    {
15969
1.84k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
15970
1.84k
            ett_bacapp_tag, NULL, "Error Class - %u octets (Signed)", lvt);
15971
1.84k
    }
15972
2.76k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15973
2.76k
    offset += tag_len + lvt;
15974
15975
2.76k
    return offset;
15976
2.76k
}
15977
15978
static unsigned
15979
fErrorCode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15980
2.75k
{
15981
2.75k
    uint32_t    val = 0, lvt;
15982
2.75k
    uint8_t     tag_no, tag_info;
15983
2.75k
    proto_item *ti;
15984
2.75k
    proto_tree *subtree;
15985
2.75k
    unsigned    tag_len;
15986
15987
2.75k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15988
2.75k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15989
888
    {
15990
888
        ti = proto_tree_add_uint(tree, hf_bacapp_error_code,
15991
888
            tvb, offset, lvt+tag_len, val);
15992
888
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
15993
888
    }
15994
1.86k
    else
15995
1.86k
    {
15996
1.86k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
15997
1.86k
            ett_bacapp_tag, NULL, "Error Code - %u octets (Signed)", lvt);
15998
1.86k
    }
15999
2.75k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
16000
2.75k
    offset += tag_len + lvt;
16001
16002
2.75k
    return offset;
16003
2.75k
}
16004
16005
static unsigned
16006
fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16007
2.76k
{
16008
2.76k
    offset = fErrorClass(tvb, pinfo, tree, offset);
16009
16010
2.76k
    return fErrorCode(tvb, pinfo, tree, offset);
16011
2.76k
}
16012
16013
static unsigned
16014
fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned service)
16015
397
{
16016
397
    switch (service) {
16017
13
    case 8:
16018
13
        offset = fChangeListError(tvb, pinfo, tree, offset);
16019
13
        break;
16020
26
    case 9:
16021
26
        offset = fChangeListError(tvb, pinfo, tree, offset);
16022
26
        break;
16023
16
    case 10:
16024
16
        offset = fCreateObjectError(tvb, pinfo, tree, offset);
16025
16
        break;
16026
27
    case 16:
16027
27
        offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
16028
27
        break;
16029
106
    case 18:
16030
106
        offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
16031
106
        break;
16032
23
    case 22:
16033
23
        offset = fVTCloseError(tvb, pinfo, tree, offset);
16034
23
        break;
16035
113
    case 30:
16036
113
        offset = fSubscribeCOVPropertyMultipleError(tvb, pinfo, tree, offset);
16037
113
        break;
16038
37
    case 34:
16039
37
        offset = fAuthRequestError(tvb, pinfo, tree, offset);
16040
37
        break;
16041
36
    default:
16042
36
        offset = fError(tvb, pinfo, tree, offset);
16043
36
        break;
16044
397
  }
16045
342
    return offset;
16046
397
}
16047
16048
static unsigned
16049
fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
16050
397
{   /* BACnet-Error-PDU */
16051
    /* ASHRAE 135-2001 20.1.7 */
16052
16053
397
    proto_item *tc;
16054
397
    proto_tree *bacapp_tree_control;
16055
397
    uint8_t     tmp;
16056
16057
397
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16058
397
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16059
16060
397
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16061
397
                offset++, 1, ENC_BIG_ENDIAN);
16062
397
    tmp = tvb_get_uint8(tvb, offset);
16063
397
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
16064
397
                 offset++, 1, ENC_BIG_ENDIAN);
16065
    /* Error Handling follows... */
16066
397
    return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
16067
397
}
16068
16069
static unsigned
16070
fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16071
30
{   /* BACnet-Reject-PDU */
16072
    /* ASHRAE 135-2001 20.1.8 */
16073
16074
30
    proto_item *tc;
16075
30
    proto_tree *bacapp_tree_control;
16076
16077
30
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16078
30
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16079
16080
30
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16081
30
                offset++, 1, ENC_BIG_ENDIAN);
16082
30
    proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
16083
30
                offset++, 1, ENC_BIG_ENDIAN);
16084
30
    return offset;
16085
30
}
16086
16087
static unsigned
16088
fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16089
53
{   /* BACnet-Abort-PDU */
16090
    /* ASHRAE 135-2001 20.1.9 */
16091
16092
53
    proto_item *tc;
16093
53
    proto_tree *bacapp_tree_control;
16094
16095
53
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
16096
53
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16097
16098
53
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
16099
53
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16100
53
                offset++, 1, ENC_BIG_ENDIAN);
16101
53
    proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
16102
53
                offset++, 1, ENC_BIG_ENDIAN);
16103
53
    return offset;
16104
53
}
16105
16106
static unsigned
16107
do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
16108
8.80k
{
16109
8.80k
    uint8_t flag, bacapp_type;
16110
8.80k
    unsigned  offset = 0;
16111
16112
8.80k
    flag = tvb_get_int8(tvb, 0);
16113
8.80k
    bacapp_type = (flag >> 4) & 0x0f;
16114
16115
8.80k
    if (tvb == NULL) {
16116
0
        return 0;
16117
0
    }
16118
16119
    /* ASHRAE 135-2001 20.1.1 */
16120
8.80k
    switch (bacapp_type) {
16121
6.80k
    case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
16122
6.80k
        offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
16123
6.80k
        break;
16124
656
    case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
16125
656
        offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
16126
656
        break;
16127
46
    case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
16128
46
        offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
16129
46
        break;
16130
693
    case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
16131
693
        offset = fComplexAckPDU(tvb, pinfo, tree, offset);
16132
693
        break;
16133
59
    case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
16134
59
        offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
16135
59
        break;
16136
397
    case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
16137
397
        offset = fErrorPDU(tvb, pinfo, tree, offset);
16138
397
        break;
16139
30
    case BACAPP_TYPE_REJECT:    /* BACnet-Reject-PDU */
16140
30
        offset = fRejectPDU(tvb, pinfo, tree, offset);
16141
30
        break;
16142
53
    case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
16143
53
        offset = fAbortPDU(tvb, pinfo, tree, offset);
16144
53
        break;
16145
8.80k
    }
16146
5.27k
    return offset;
16147
8.80k
}
16148
16149
static int
16150
dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
16151
9.04k
{
16152
9.04k
    uint8_t     flag, bacapp_type;
16153
9.04k
    unsigned    save_fragmented  = false, data_offset = 0, /*bacapp_apdu_size,*/ fragment = false;
16154
9.04k
    tvbuff_t   *new_tvb          = NULL;
16155
9.04k
    unsigned    offset           = 0;
16156
9.04k
    uint8_t     bacapp_seqno     = 0;
16157
9.04k
    uint8_t     bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
16158
9.04k
    uint8_t     bacapp_invoke_id = 0;
16159
9.04k
    proto_item *ti;
16160
9.04k
    proto_tree *bacapp_tree      = NULL;
16161
16162
9.04k
    int         svc = 0;
16163
9.04k
    proto_item *tt  = 0;
16164
9.04k
    int8_t      ack = 0;
16165
16166
    /* Strings for BACnet Statistics */
16167
9.04k
    static const char errstr[]       = "ERROR: ";
16168
9.04k
    static const char rejstr[]       = "REJECTED: ";
16169
9.04k
    static const char abortstr[]     = "ABORTED: ";
16170
9.04k
    static const char sackstr[]      = " (SimpleAck)";
16171
9.04k
    static const char cackstr[]      = " (ComplexAck)";
16172
9.04k
    static const char uconfsreqstr[] = " (Unconfirmed Service Request)";
16173
9.04k
    static const char confsreqstr[]  = " (Confirmed Service Request)";
16174
16175
9.04k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
16176
9.04k
    col_clear(pinfo->cinfo, COL_INFO);
16177
16178
9.04k
    flag = tvb_get_uint8(tvb, 0);
16179
9.04k
    bacapp_type = (flag >> 4) & 0x0f;
16180
16181
    /* show some descriptive text in the INFO column */
16182
9.04k
    col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
16183
9.04k
        val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
16184
16185
9.04k
    bacinfo.service_type = NULL;
16186
9.04k
    bacinfo.invoke_id = NULL;
16187
9.04k
    bacinfo.instance_ident = NULL;
16188
9.04k
    bacinfo.object_ident = NULL;
16189
16190
9.04k
    switch (bacapp_type) {
16191
6.93k
    case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
16192
        /* segmented messages have 2 additional bytes */
16193
6.93k
        if (flag & BACAPP_SEGMENTED_REQUEST) {
16194
133
            fragment = true;
16195
133
            ack = 0;
16196
            /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_uint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
16197
133
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 2);
16198
133
            bacapp_seqno = tvb_get_uint8(tvb, offset + 3);
16199
            /* bacapp_prop_win_size = tvb_get_uint8(tvb, offset + 4); */
16200
133
            bacapp_service = tvb_get_uint8(tvb, offset + 5);
16201
133
            data_offset = 6;
16202
6.80k
        } else {
16203
6.80k
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 2);
16204
6.80k
            bacapp_service = tvb_get_uint8(tvb, offset + 3);
16205
6.80k
        }
16206
6.93k
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
16207
6.93k
                        val_to_str_const(bacapp_service,
16208
6.93k
                                         BACnetConfirmedServiceChoice,
16209
6.93k
                                         bacapp_unknown_service_str),
16210
6.93k
                        bacapp_invoke_id);
16211
16212
6.93k
        updateBacnetInfoValue(BACINFO_INVOKEID,
16213
6.93k
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16214
16215
6.93k
        updateBacnetInfoValue(BACINFO_SERVICE,
16216
6.93k
                              wmem_strconcat(pinfo->pool,
16217
6.93k
                                             val_to_str_const(bacapp_service,
16218
6.93k
                                                              BACnetConfirmedServiceChoice,
16219
6.93k
                                                              bacapp_unknown_service_str),
16220
6.93k
                                             confsreqstr, NULL));
16221
6.93k
        break;
16222
656
    case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
16223
656
        bacapp_service = tvb_get_uint8(tvb, offset + 1);
16224
656
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
16225
656
                        val_to_str_const(bacapp_service,
16226
656
                                         BACnetUnconfirmedServiceChoice,
16227
656
                                         bacapp_unknown_service_str));
16228
16229
656
        updateBacnetInfoValue(BACINFO_SERVICE,
16230
656
                              wmem_strconcat(pinfo->pool,
16231
656
                                             val_to_str_const(bacapp_service,
16232
656
                                                              BACnetUnconfirmedServiceChoice,
16233
656
                                                              bacapp_unknown_service_str),
16234
656
                                             uconfsreqstr, NULL));
16235
656
        break;
16236
46
    case BACAPP_TYPE_SIMPLE_ACK:
16237
46
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16238
46
        bacapp_service = tvb_get_uint8(tvb, offset + 2);
16239
46
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16240
46
                        val_to_str_const(bacapp_service,
16241
46
                                         BACnetConfirmedServiceChoice,
16242
46
                                         bacapp_unknown_service_str),
16243
46
                        bacapp_invoke_id);
16244
16245
46
        updateBacnetInfoValue(BACINFO_INVOKEID,
16246
46
                              wmem_strdup_printf(pinfo->pool,
16247
46
                                                 "Invoke ID: %d", bacapp_invoke_id));
16248
16249
46
        updateBacnetInfoValue(BACINFO_SERVICE,
16250
46
                              wmem_strconcat(pinfo->pool,
16251
46
                                             val_to_str_const(bacapp_service,
16252
46
                                                              BACnetConfirmedServiceChoice,
16253
46
                                                              bacapp_unknown_service_str),
16254
46
                                             sackstr, NULL));
16255
46
        break;
16256
797
    case BACAPP_TYPE_COMPLEX_ACK:
16257
        /* segmented messages have 2 additional bytes */
16258
797
        if (flag & BACAPP_SEGMENTED_REQUEST) {
16259
104
            fragment = true;
16260
104
            ack = 1;
16261
            /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
16262
104
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16263
104
            bacapp_seqno = tvb_get_uint8(tvb, offset + 2);
16264
            /* bacapp_prop_win_size = tvb_get_uint8(tvb, offset + 3); */
16265
104
            bacapp_service = tvb_get_uint8(tvb, offset + 4);
16266
104
            data_offset = 5;
16267
693
        } else {
16268
693
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16269
693
            bacapp_service = tvb_get_uint8(tvb, offset + 2);
16270
693
        }
16271
797
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16272
797
                        val_to_str_const(bacapp_service,
16273
797
                                         BACnetConfirmedServiceChoice,
16274
797
                                         bacapp_unknown_service_str),
16275
797
                        bacapp_invoke_id);
16276
16277
797
        updateBacnetInfoValue(BACINFO_INVOKEID,
16278
797
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16279
16280
797
        updateBacnetInfoValue(BACINFO_SERVICE,
16281
797
                              wmem_strconcat(pinfo->pool,
16282
797
                                             val_to_str_const(bacapp_service,
16283
797
                                                              BACnetConfirmedServiceChoice,
16284
797
                                                              bacapp_unknown_service_str),
16285
797
                                             cackstr, NULL));
16286
797
        break;
16287
59
    case BACAPP_TYPE_SEGMENT_ACK:
16288
        /* nothing more to add */
16289
59
        break;
16290
397
    case BACAPP_TYPE_ERROR:
16291
397
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16292
397
        bacapp_service = tvb_get_uint8(tvb, offset + 2);
16293
397
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16294
397
                        val_to_str_const(bacapp_service,
16295
397
                                         BACnetConfirmedServiceChoice,
16296
397
                                         bacapp_unknown_service_str),
16297
397
                        bacapp_invoke_id);
16298
16299
397
        updateBacnetInfoValue(BACINFO_INVOKEID,
16300
397
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16301
16302
397
        updateBacnetInfoValue(BACINFO_SERVICE,
16303
397
                              wmem_strconcat(pinfo->pool,
16304
397
                                             errstr,
16305
397
                                             val_to_str_const(bacapp_service,
16306
397
                                                              BACnetConfirmedServiceChoice,
16307
397
                                                              bacapp_unknown_service_str),
16308
397
                                             NULL));
16309
397
        break;
16310
30
    case BACAPP_TYPE_REJECT:
16311
30
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16312
30
        bacapp_reason = tvb_get_uint8(tvb, offset + 2);
16313
30
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16314
30
                        val_to_split_str(pinfo->pool, bacapp_reason,
16315
30
                                         64,
16316
30
                                         BACnetRejectReason,
16317
30
                                         ASHRAE_Reserved_Fmt,
16318
30
                                         Vendor_Proprietary_Fmt), bacapp_invoke_id);
16319
16320
30
        updateBacnetInfoValue(BACINFO_INVOKEID,
16321
30
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16322
16323
30
        updateBacnetInfoValue(BACINFO_SERVICE,
16324
30
                              wmem_strconcat(pinfo->pool, rejstr,
16325
30
                                             val_to_split_str(pinfo->pool, bacapp_reason, 64,
16326
30
                                                              BACnetRejectReason,
16327
30
                                                              ASHRAE_Reserved_Fmt,
16328
30
                                                              Vendor_Proprietary_Fmt),
16329
30
                                             NULL));
16330
30
        break;
16331
53
    case BACAPP_TYPE_ABORT:
16332
53
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16333
53
        bacapp_reason = tvb_get_uint8(tvb, offset + 2);
16334
53
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16335
53
                        val_to_split_str(pinfo->pool, bacapp_reason,
16336
53
                                         64,
16337
53
                                         BACnetAbortReason,
16338
53
                                         ASHRAE_Reserved_Fmt,
16339
53
                                         Vendor_Proprietary_Fmt), bacapp_invoke_id);
16340
16341
53
        updateBacnetInfoValue(BACINFO_INVOKEID,
16342
53
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16343
16344
53
        updateBacnetInfoValue(BACINFO_SERVICE,
16345
53
                              wmem_strconcat(pinfo->pool, abortstr,
16346
53
                                             val_to_split_str(pinfo->pool, bacapp_reason,
16347
53
                                                              64,
16348
53
                                                              BACnetAbortReason,
16349
53
                                                              ASHRAE_Reserved_Fmt,
16350
53
                                                              Vendor_Proprietary_Fmt),
16351
53
                                             NULL));
16352
53
        break;
16353
        /* UNKNOWN */
16354
68
    default:
16355
        /* nothing more to add */
16356
68
        break;
16357
9.04k
    }
16358
16359
9.03k
    save_fragmented = pinfo->fragmented;
16360
16361
9.03k
    ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
16362
9.03k
    bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
16363
16364
9.03k
    if (!fragment)
16365
8.80k
        do_the_dissection(tvb, pinfo, bacapp_tree);
16366
235
    else
16367
235
        fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
16368
            /* not resetting the offset so the remaining can be done */
16369
16370
9.03k
    if (fragment) { /* fragmented */
16371
235
        fragment_head *frag_msg;
16372
235
        uint32_t ext_seqno = bacapp_seqno;
16373
16374
235
        pinfo->fragmented = true;
16375
16376
235
        if (!PINFO_FD_VISITED(pinfo)) {
16377
235
            frag_msg = fragment_get(&msg_reassembly_table, pinfo, bacapp_invoke_id, NULL);
16378
235
            if (frag_msg && frag_msg->first_gap) {
16379
                /* If we have permanently lost segments then using the last
16380
                 * contiguous sequence number isn't quite right - but we
16381
                 * won't be able to defragment in that case anyway.
16382
                 */
16383
58
                uint32_t prev_seqno = frag_msg->first_gap->offset;
16384
58
                ext_seqno = calculate_extended_seqno(prev_seqno, bacapp_seqno);
16385
16386
58
                if (ext_seqno != bacapp_seqno) {
16387
8
                    p_add_proto_data(wmem_file_scope(), pinfo, proto_bacapp, bacapp_seqno, GUINT_TO_POINTER(ext_seqno));
16388
8
                }
16389
58
            }
16390
235
        } else {
16391
            /* This is not really necessary (because the fragment number is not
16392
             * used by fragment_add_seq_check on the second pass) but makes the
16393
             * fragment number in the Info column be the extended one.
16394
             */
16395
0
            ext_seqno = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo, proto_bacapp, bacapp_seqno));
16396
0
            if (ext_seqno == 0) {
16397
0
                ext_seqno = bacapp_seqno;
16398
0
            }
16399
0
        }
16400
235
        frag_msg = fragment_add_seq_check(&msg_reassembly_table,
16401
235
            tvb, data_offset,
16402
235
            pinfo,
16403
235
            bacapp_invoke_id,      /* ID for fragments belonging together */
16404
235
            NULL,
16405
235
            ext_seqno,             /* fragment sequence number */
16406
235
            tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
16407
235
            flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
16408
235
        new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
16409
235
                "Reassembled BACapp", frag_msg, &msg_frag_items,
16410
235
                NULL, tree);
16411
16412
235
        if (new_tvb) { /* Reassembled */
16413
72
            col_append_str(pinfo->cinfo, COL_INFO,
16414
72
                           " (Message Reassembled)");
16415
163
        } else { /* Not last packet of reassembled Short Message */
16416
163
            col_append_fstr(pinfo->cinfo, COL_INFO,
16417
163
                            " (Message fragment %u)", ext_seqno);
16418
163
        }
16419
235
        if (new_tvb) { /* take it all */
16420
72
            switch (bacapp_type) {
16421
24
            case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
16422
24
                fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
16423
24
                break;
16424
48
            case BACAPP_TYPE_COMPLEX_ACK:
16425
48
                fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
16426
48
                break;
16427
0
            default:
16428
                /* do nothing */
16429
0
                break;
16430
72
            }
16431
72
        }
16432
235
    }
16433
16434
9.03k
    pinfo->fragmented = save_fragmented;
16435
16436
    /* tapping */
16437
9.03k
    tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
16438
9.03k
    return tvb_captured_length(tvb);
16439
9.03k
}
16440
16441
void
16442
proto_register_bacapp(void)
16443
15
{
16444
15
    static hf_register_info hf[] = {
16445
15
        { &hf_bacapp_type,
16446
15
          { "APDU Type",           "bacapp.type",
16447
15
            FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
16448
15
        },
16449
15
        { &hf_bacapp_pduflags,
16450
15
          { "PDU Flags",          "bacapp.pduflags",
16451
15
            FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
16452
15
        },
16453
15
        { &hf_bacapp_SEG,
16454
15
          { "Segmented Request",           "bacapp.segmented_request",
16455
15
            FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
16456
15
        },
16457
15
        { &hf_bacapp_MOR,
16458
15
          { "More Segments",           "bacapp.more_segments",
16459
15
            FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
16460
15
        },
16461
15
        { &hf_bacapp_SA,
16462
15
          { "SA",           "bacapp.SA",
16463
15
            FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
16464
15
        },
16465
15
        { &hf_bacapp_max_adpu_size,
16466
15
          { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
16467
15
            FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
16468
15
        },
16469
15
        { &hf_bacapp_response_segments,
16470
15
          { "Max Response Segments accepted",           "bacapp.response_segments",
16471
15
            FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
16472
15
        },
16473
15
        { &hf_bacapp_object_identifier,
16474
15
          { "Object Identifier",           "bacapp.objectIdentifier",
16475
15
            FT_UINT32, BASE_CUSTOM, CF_FUNC(format_object_identifier), 0, NULL, HFILL }
16476
15
        },
16477
15
        { &hf_bacapp_device_identifier,
16478
15
          { "Device Identifier",           "bacapp.deviceIdentifier",
16479
15
            FT_UINT32, BASE_CUSTOM, CF_FUNC(format_object_identifier), 0, NULL, HFILL }
16480
15
        },
16481
15
        { &hf_bacapp_objectType,
16482
15
          { "Object Type",           "bacapp.objectType",
16483
15
            FT_UINT32, BASE_DEC|BASE_EXT_STRING, &BACnetObjectType_ext, 0xffc00000, NULL, HFILL }
16484
15
        },
16485
15
        { &hf_bacapp_object_name,
16486
15
          { "Object Name",           "bacapp.object_name",
16487
15
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16488
15
        },
16489
15
        { &hf_bacapp_instanceNumber,
16490
15
          { "Instance Number",           "bacapp.instance_number",
16491
15
            FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
16492
15
        },
16493
15
        { &hf_BACnetPropertyIdentifier,
16494
15
          { "Property Identifier", "bacapp.property_identifier",
16495
15
            FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
16496
15
        },
16497
15
        { &hf_BACnetVendorIdentifier,
16498
15
          { "Vendor Identifier", "bacapp.vendor_identifier",
16499
15
            FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
16500
15
        },
16501
15
        { &hf_BACnetRestartReason,
16502
15
          { "Restart Reason", "bacapp.restart_reason",
16503
15
            FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
16504
15
        },
16505
15
        { &hf_bacapp_invoke_id,
16506
15
          { "Invoke ID",           "bacapp.invoke_id",
16507
15
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16508
15
        },
16509
15
        { &hf_bacapp_sequence_number,
16510
15
          { "Sequence Number",           "bacapp.sequence_number",
16511
15
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16512
15
        },
16513
15
        { &hf_bacapp_window_size,
16514
15
          { "Proposed Window Size",           "bacapp.window_size",
16515
15
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16516
15
        },
16517
15
        { &hf_bacapp_service,
16518
15
          { "Service Choice",           "bacapp.confirmed_service",
16519
15
            FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
16520
15
        },
16521
15
        { &hf_bacapp_uservice,
16522
15
          { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
16523
15
            FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
16524
15
        },
16525
15
        { &hf_bacapp_NAK,
16526
15
          { "NAK",           "bacapp.NAK",
16527
15
            FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
16528
15
        },
16529
15
        { &hf_bacapp_SRV,
16530
15
          { "SRV",           "bacapp.SRV",
16531
15
            FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
16532
15
        },
16533
15
        { &hf_bacapp_event_type,
16534
15
          { "Event Type", "bacapp.event_type",
16535
15
            FT_UINT32, BASE_DEC, VALS(BACnetEventType), 0, NULL, HFILL }
16536
15
        },
16537
15
        { &hf_bacapp_notify_type,
16538
15
          { "Notify Type", "bacapp.notify_type",
16539
15
            FT_UINT8, BASE_DEC, VALS(BACnetNotifyType), 0, NULL, HFILL }
16540
15
        },
16541
15
        { &hf_bacapp_error_class,
16542
15
          { "Error Class", "bacapp.error_class",
16543
15
            FT_UINT32, BASE_DEC, VALS(BACnetErrorClass), 0, NULL, HFILL }
16544
15
        },
16545
15
        { &hf_bacapp_error_code,
16546
15
          { "Error Code", "bacapp.error_code",
16547
15
            FT_UINT32, BASE_DEC|BASE_EXT_STRING, &BACnetErrorCode_ext, 0, NULL, HFILL }
16548
15
        },
16549
15
        { &hf_bacapp_present_value_null,
16550
15
          { "Present Value (null)", "bacapp.present_value.null",
16551
15
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16552
15
        },
16553
15
        { &hf_bacapp_present_value_bool,
16554
15
          { "Present Value (bool)", "bacapp.present_value.boolean",
16555
15
            FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
16556
15
        },
16557
15
        { &hf_bacapp_present_value_unsigned,
16558
15
          { "Present Value (uint)", "bacapp.present_value.uint",
16559
15
            FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }
16560
15
        },
16561
15
        { &hf_bacapp_present_value_signed,
16562
15
          { "Present Value (int)", "bacapp.present_value.int",
16563
15
            FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL }
16564
15
        },
16565
15
        { &hf_bacapp_present_value_real,
16566
15
          { "Present Value (real)", "bacapp.present_value.real",
16567
15
            FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL }
16568
15
        },
16569
15
        { &hf_bacapp_present_value_double,
16570
15
          { "Present Value (double)", "bacapp.present_value.double",
16571
15
            FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL }
16572
15
        },
16573
15
        { &hf_bacapp_present_value_octet_string,
16574
15
          { "Present Value (octet string)", "bacapp.present_value.octet_string",
16575
15
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16576
15
        },
16577
15
        { &hf_bacapp_present_value_char_string,
16578
15
          { "Present Value (char string)", "bacapp.present_value.char_string",
16579
15
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16580
15
        },
16581
15
        { &hf_bacapp_present_value_bit_string,
16582
15
          { "Present Value (bit string)", "bacapp.present_value.bit_string",
16583
15
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16584
15
        },
16585
15
        { &hf_bacapp_present_value_enum_index,
16586
15
          { "Present Value (enum index)", "bacapp.present_value.enum_index",
16587
15
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16588
15
        },
16589
15
        { &hf_Device_Instance_Range_Low_Limit,
16590
15
          { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
16591
15
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16592
15
        },
16593
15
        { &hf_Device_Instance_Range_High_Limit,
16594
15
          { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
16595
15
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16596
15
        },
16597
15
        { &hf_BACnetRejectReason,
16598
15
          { "Reject Reason",           "bacapp.reject_reason",
16599
15
            FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
16600
15
        },
16601
15
        { &hf_BACnetAbortReason,
16602
15
          { "Abort Reason",           "bacapp.abort_reason",
16603
15
            FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
16604
15
        },
16605
15
        { &hf_BACnetApplicationTagNumber,
16606
15
          { "Application Tag Number",
16607
15
            "bacapp.application_tag_number",
16608
15
            FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
16609
15
            NULL, HFILL }
16610
15
        },
16611
15
        { &hf_BACnetContextTagNumber,
16612
15
          { "Context Tag Number",
16613
15
            "bacapp.context_tag_number",
16614
15
            FT_UINT8, BASE_DEC, NULL, 0xF0,
16615
15
            NULL, HFILL }
16616
15
        },
16617
15
        { &hf_BACnetExtendedTagNumber,
16618
15
          { "Extended Tag Number",
16619
15
            "bacapp.extended_tag_number",
16620
15
            FT_UINT8, BASE_DEC, NULL, 0,
16621
15
            NULL, HFILL }
16622
15
        },
16623
15
        { &hf_BACnetNamedTag,
16624
15
          { "Named Tag",
16625
15
            "bacapp.named_tag",
16626
15
            FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
16627
15
            NULL, HFILL }
16628
15
        },
16629
15
        { &hf_BACnetCharacterSet,
16630
15
          { "String Character Set",
16631
15
            "bacapp.string_character_set",
16632
15
            FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
16633
15
            NULL, HFILL }
16634
15
        },
16635
15
        { &hf_BACnetCodePage,
16636
15
          { "Code Page",
16637
15
            "bacapp.code_page",
16638
15
            FT_UINT16, BASE_DEC, NULL, 0,
16639
15
            NULL, HFILL }
16640
15
        },
16641
15
        { &hf_BACnetTagClass,
16642
15
          { "Tag Class",           "bacapp.tag_class",
16643
15
            FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
16644
15
        },
16645
15
        { &hf_bacapp_tag_lvt,
16646
15
          { "Length Value Type",
16647
15
            "bacapp.LVT",
16648
15
            FT_UINT8, BASE_DEC, NULL, 0,
16649
15
            NULL, HFILL }
16650
15
        },
16651
15
        { &hf_bacapp_tag_ProcessId,
16652
15
          { "ProcessIdentifier",           "bacapp.processId",
16653
15
            FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
16654
15
        },
16655
15
        { &hf_bacapp_tag_to_state,
16656
15
          { "To State", "bacapp.to_state",
16657
15
            FT_UINT32, BASE_DEC, VALS(BACnetEventState), 0, NULL, HFILL }
16658
15
        },
16659
15
        { &hf_bacapp_tag_from_state,
16660
15
          { "From State", "bacapp.from_state",
16661
15
            FT_UINT32, BASE_DEC, VALS(BACnetEventState), 0, NULL, HFILL }
16662
15
        },
16663
15
        { &hf_bacapp_tag_IPV4,
16664
15
          { "IPV4",           "bacapp.IPV4",
16665
15
            FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
16666
15
        },
16667
15
        { &hf_bacapp_tag_IPV6,
16668
15
          { "IPV6",           "bacapp.IPV6",
16669
15
            FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
16670
15
        },
16671
15
        { &hf_bacapp_tag_PORT,
16672
15
          { "Port",           "bacapp.Port",
16673
15
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
16674
15
        },
16675
15
        { &hf_bacapp_tag_mac_address_broadcast,
16676
15
          { "MAC-address: broadcast",           "bacapp.mac_address_broadcast",
16677
15
            FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
16678
15
        },
16679
15
        { &hf_bacapp_reserved_ashrea,
16680
15
          { "reserved for ASHRAE",           "bacapp.reserved_ashrea",
16681
15
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16682
15
        },
16683
15
        { &hf_bacapp_unused_bits,
16684
15
          { "Unused bits",           "bacapp.unused_bits",
16685
15
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16686
15
        },
16687
15
        { &hf_bacapp_bit,
16688
15
          { "bit",           "bacapp.bit",
16689
15
            FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
16690
15
        },
16691
15
        { &hf_bacapp_complete_bitstring,
16692
15
          { "Complete bitstring",           "bacapp.complete_bitstring",
16693
15
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16694
15
        },
16695
15
        {&hf_msg_fragments,
16696
15
          { "Message fragments", "bacapp.fragments",
16697
15
            FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16698
15
        {&hf_msg_fragment,
16699
15
          { "Message fragment", "bacapp.fragment",
16700
15
            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16701
15
        {&hf_msg_fragment_overlap,
16702
15
          { "Message fragment overlap", "bacapp.fragment.overlap",
16703
15
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16704
15
        {&hf_msg_fragment_overlap_conflicts,
16705
15
          { "Message fragment overlapping with conflicting data",
16706
15
            "bacapp.fragment.overlap.conflicts",
16707
15
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16708
15
        {&hf_msg_fragment_multiple_tails,
16709
15
          { "Message has multiple tail fragments",
16710
15
            "bacapp.fragment.multiple_tails",
16711
15
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16712
15
        {&hf_msg_fragment_too_long_fragment,
16713
15
          { "Message fragment too long", "bacapp.fragment.too_long_fragment",
16714
15
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16715
15
        {&hf_msg_fragment_error,
16716
15
          { "Message defragmentation error", "bacapp.fragment.error",
16717
15
            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16718
15
        {&hf_msg_fragment_count,
16719
15
          { "Message fragment count", "bacapp.fragment.count",
16720
15
            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
16721
15
        {&hf_msg_reassembled_in,
16722
15
          { "Reassembled in", "bacapp.reassembled.in",
16723
15
            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16724
15
        {&hf_msg_reassembled_length,
16725
15
          { "Reassembled BACapp length", "bacapp.reassembled.length",
16726
15
            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
16727
15
    };
16728
15
    static int *ett[] = {
16729
15
        &ett_bacapp,
16730
15
        &ett_bacapp_control,
16731
15
        &ett_bacapp_tag,
16732
15
        &ett_bacapp_list,
16733
15
        &ett_bacapp_value,
16734
15
        &ett_bacapp_object_identifier,
16735
15
        &ett_msg_fragment,
16736
15
        &ett_msg_fragments
16737
16738
15
    };
16739
16740
15
    static ei_register_info ei[] = {
16741
15
        { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
16742
15
        { &ei_bacapp_bad_tag, { "bacapp.bad_tag", PI_MALFORMED, PI_ERROR, "Wrong tag found", EXPFILL }},
16743
15
        { &ei_bacapp_opening_tag, { "bacapp.bad_opening_tag", PI_MALFORMED, PI_ERROR, "Expected Opening Tag!", EXPFILL }},
16744
15
    };
16745
16746
15
    expert_module_t* expert_bacapp;
16747
16748
15
    proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
16749
15
                                           "BACapp", "bacapp");
16750
16751
15
    proto_register_field_array(proto_bacapp, hf, array_length(hf));
16752
15
    proto_register_subtree_array(ett, array_length(ett));
16753
15
    expert_bacapp = expert_register_protocol(proto_bacapp);
16754
15
    expert_register_field_array(expert_bacapp, ei, array_length(ei));
16755
15
    register_dissector("bacapp", dissect_bacapp, proto_bacapp);
16756
16757
15
    reassembly_table_register(&msg_reassembly_table,
16758
15
                          &addresses_reassembly_table_functions);
16759
16760
15
    bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
16761
15
                                                      "BACapp Vendor Identifier", proto_bacapp,
16762
15
                                                      FT_UINT8, BASE_HEX);
16763
16764
    /* Register BACnet Statistic trees */
16765
15
    register_bacapp_stat_trees();
16766
15
    bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
16767
15
}
16768
16769
/*
16770
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
16771
 *
16772
 * Local variables:
16773
 * c-basic-offset: 4
16774
 * tab-width: 8
16775
 * indent-tabs-mode: nil
16776
 * End:
16777
 *
16778
 * vi: set shiftwidth=4 tabstop=8 expandtab:
16779
 * :indentSize=4:tabSize=8:noTabs=true:
16780
 */