Coverage Report

Created: 2026-01-02 06:13

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
28
static int bacapp_tap;
29
30
/* formerly bacapp.h  contains definitions and forward declarations */
31
32
/* BACnet PDU Types */
33
14.4k
#define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
34
1.32k
#define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
35
94
#define BACAPP_TYPE_SIMPLE_ACK                                  2
36
1.30k
#define BACAPP_TYPE_COMPLEX_ACK                                 3
37
52
#define BACAPP_TYPE_SEGMENT_ACK                                 4
38
688
#define BACAPP_TYPE_ERROR                                       5
39
44
#define BACAPP_TYPE_REJECT                                      6
40
144
#define BACAPP_TYPE_ABORT                                       7
41
#define MAX_BACAPP_TYPE                                         8
42
43
7.94k
#define BACAPP_SEGMENTED_REQUEST 0x08
44
275
#define BACAPP_MORE_SEGMENTS 0x04
45
#define BACAPP_SEGMENTED_RESPONSE 0x02
46
#define BACAPP_SEGMENT_NAK 0x02
47
#define BACAPP_SENT_BY 0x01
48
49
/**
50
 * dissect_bacapp ::= CHOICE {
51
 *  confirmed-request-PDU       [0] BACnet-Confirmed-Request-PDU,
52
 *  unconfirmed-request-PDU     [1] BACnet-Unconfirmed-Request-PDU,
53
 *  simpleACK-PDU               [2] BACnet-SimpleACK-PDU,
54
 *  complexACK-PDU              [3] BACnet-ComplexACK-PDU,
55
 *  segmentACK-PDU              [4] BACnet-SegmentACK-PDU,
56
 *  error-PDU                   [5] BACnet-Error-PDU,
57
 *  reject-PDU                  [6] BACnet-Reject-PDU,
58
 *  abort-PDU                   [7] BACnet-Abort-PDU
59
 * }
60
 * @param tvb the tv buffer of the current data
61
 * @param pinfo the packet info of the current data
62
 * @param tree the tree to append this item to
63
 **/
64
65
/**
66
 * ConfirmedRequest-PDU ::= SEQUENCE {
67
 *  pdu-type                    [0] Unsigned (0..15), -- 0 for this PDU Type
68
 *  segmentedMessage            [1] BOOLEAN,
69
 *  moreFollows                 [2] BOOLEAN,
70
 *  segmented-response-accepted [3] BOOLEAN,
71
 *  reserved                    [4] Unsigned (0..3), -- must be set zero
72
 *  max-segments-accepted       [5] Unsigned (0..7), -- as per 20.1.2.4
73
 *  max-APDU-length-accepted    [5] Unsigned (0..15), -- as per 20.1.2.5
74
 *  invokeID                    [6] Unsigned (0..255),
75
 *  sequence-number             [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
76
 *  proposed-window-size        [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
77
 *  service-choice              [9] BACnetConfirmedServiceChoice,
78
 *  service-request             [10] BACnet-Confirmed-Service-Request OPTIONAL
79
 * }
80
 * @param tvb the tv buffer of the current data
81
 * @param pinfo the packet info of the current data
82
 * @param tree the tree to append this item to
83
 * @param offset the offset in the tvb
84
 * @return modified offset
85
 */
86
static unsigned
87
fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
88
89
/**
90
 * @param tvb the tv buffer of the current data
91
 * @param pinfo the packet info of the current data
92
 * @param tree the tree to append this item to
93
 * @param offset the offset in the tvb
94
 * @param ack - indicates whether working on request or ack
95
 * @param svc - output variable to return service choice
96
 * @param tt  - output varable to return service choice item
97
 * @return modified offset
98
 */
99
static unsigned
100
fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t ack,
101
                int *svc, proto_item **tt);
102
103
/**
104
 * Unconfirmed-Request-PDU ::= SEQUENCE {
105
 *  pdu-type        [0] Unsigned (0..15), -- 1 for this PDU type
106
 *  reserved        [1] Unsigned (0..15), -- must be set zero
107
 *  service-choice  [2] BACnetUnconfirmedServiceChoice,
108
 *  service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
109
 * }
110
 * @param tvb the tv buffer of the current data
111
 * @param pinfo the packet info of the current data
112
 * @param tree the tree to append this item to
113
 * @param offset the offset in the tvb
114
 * @return modified offset
115
 */
116
static unsigned
117
fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
118
119
/**
120
 * SimpleACK-PDU ::= SEQUENCE {
121
 *  pdu-type            [0] Unsigned (0..15), -- 2 for this PDU type
122
 *  reserved            [1] Unsigned (0..15), -- must be set zero
123
 *  invokeID            [2] Unsigned (0..255),
124
 *  service-ACK-choice  [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
125
 * }
126
 * @param tvb the tv buffer of the current data
127
 * @param pinfo the packet info of the current data
128
 * @param tree the tree to append this item to
129
 * @param offset the offset in the tvb
130
 * @return modified offset
131
 */
132
static unsigned
133
fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
134
135
/**
136
 * ComplexACK-PDU ::= SEQUENCE {
137
 *  pdu-type                [0] Unsigned (0..15), -- 3 for this PDU Type
138
 *  segmentedMessage        [1] BOOLEAN,
139
 *  moreFollows             [2] BOOLEAN,
140
 *  reserved                [3] Unsigned (0..3), -- must be set zero
141
 *  invokeID                [4] Unsigned (0..255),
142
 *  sequence-number         [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
143
 *  proposed-window-size    [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
144
 *  service-ACK-choice      [7] BACnetConfirmedServiceChoice,
145
 *  service-ACK             [8] BACnet-Confirmed-Service-Request  -- Context-specific tags 0..8 are NOT used in header encoding
146
 * }
147
 * @param tvb the tv buffer of the current data
148
 * @param pinfo the packet info of the current data
149
 * @param tree the tree to append this item to
150
 * @param offset the offset in the tvb
151
 * @return modified offset
152
 */
153
static unsigned
154
fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
155
156
/**
157
 * SegmentACK-PDU ::= SEQUENCE {
158
 *  pdu-type                [0] Unsigned (0..15), -- 4 for this PDU Type
159
 *  reserved                [1] Unsigned (0..3), -- must be set zero
160
 *  negative-ACK            [2] BOOLEAN,
161
 *  server                  [3] BOOLEAN,
162
 *  original-invokeID       [4] Unsigned (0..255),
163
 *  sequence-number         [5] Unsigned (0..255),
164
 *  actual-window-size      [6] Unsigned (0..127)
165
 * }
166
 * @param tvb the tv buffer of the current data
167
 * @param pinfo the packet info of the current data
168
 * @param tree the tree to append this item to
169
 * @param offset the offset in the tvb
170
 * @return modified offset
171
 */
172
static unsigned
173
fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
174
175
/**
176
 * Error-PDU ::= SEQUENCE {
177
 *  pdu-type                [0] Unsigned (0..15), -- 5 for this PDU Type
178
 *  reserved                [1] Unsigned (0..3), -- must be set zero
179
 *  original-invokeID       [2] Unsigned (0..255),
180
 *  error-choice            [3] BACnetConfirmedServiceChoice,
181
 *  error                   [4] BACnet-Error
182
 * }
183
 * @param tvb the tv buffer of the current data
184
 * @param pinfo the packet info of the current data
185
 * @param tree the tree to append this item to
186
 * @param offset the offset in the tvb
187
 * @return modified offset
188
 */
189
static unsigned
190
fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
191
192
/**
193
 * Reject-PDU ::= SEQUENCE {
194
 *  pdu-type                [0] Unsigned (0..15), -- 6 for this PDU Type
195
 *  reserved                [1] Unsigned (0..3), -- must be set zero
196
 *  original-invokeID       [2] Unsigned (0..255),
197
 *  reject-reason           [3] BACnetRejectReason
198
 * }
199
 * @param tvb the tv buffer of the current data
200
 * @param pinfo the packet info of the current data
201
 * @param tree the tree to append this item to
202
 * @param offset the offset in the tvb
203
 * @return modified offset
204
 */
205
static unsigned
206
fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
207
208
/**
209
 * Abort-PDU ::= SEQUENCE {
210
 *  pdu-type                [0] Unsigned (0..15), -- 7 for this PDU Type
211
 *  reserved                [1] Unsigned (0..3), -- must be set zero
212
 *  server                  [2] BOOLEAN,
213
 *  original-invokeID       [3] Unsigned (0..255),
214
 *  abort-reason            [4] BACnetAbortReason
215
 * }
216
 * @param tvb the tv buffer of the current data
217
 * @param pinfo the packet info of the current data
218
 * @param tree the tree to append this item to
219
 * @param offset the offset in the tvb
220
 * @return modified offset
221
 */
222
static unsigned
223
fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
224
225
/**
226
 * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
227
 * @param tvb the tv buffer of the current data
228
 * @param pinfo the packet info of the current data
229
 * @param tree the tree to append this item to
230
 * @param offset the offset in the tvb
231
 * @param label the label of this item
232
 * @return modified offset
233
 */
234
static unsigned
235
fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
236
237
/**
238
 * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
239
 * @param tvb the tv buffer of the current data
240
 * @param pinfo the packet info of the current data
241
 * @param tree the tree to append this item to
242
 * @param offset the offset in the tvb
243
 * @param label the label of this item
244
 * @return modified offset
245
 */
246
static unsigned
247
fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
248
249
/**
250
 * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
251
 * @param tvb the tv buffer of the current data
252
 * @param pinfo the packet info of the current data
253
 * @param tree the tree to append this item to
254
 * @param offset the offset in the tvb
255
 * @param label the label of this item
256
 * @param lvt length of String
257
 * @return modified offset
258
 */
259
static unsigned
260
fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt);
261
262
/**
263
 * 20.2.12, adds the label with Date Value to tree
264
 * @param tvb the tv buffer of the current data
265
 * @param pinfo the packet info of the current data
266
 * @param tree the tree to append this item to
267
 * @param offset the offset in the tvb
268
 * @param label the label of this item
269
 * @return modified offset
270
 */
271
static unsigned
272
fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
273
274
/**
275
 * 20.2.13, adds the label with Time Value to tree
276
 * @param tvb the tv buffer of the current data
277
 * @param pinfo the packet info of the current data
278
 * @param tree the tree to append this item to
279
 * @param offset the offset in the tvb
280
 * @param label the label of this item
281
 * @return modified offset
282
 */
283
static unsigned
284
fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
285
286
/**
287
 * 20.2.14, adds Object Identifier to tree
288
 * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
289
 * @param tvb the tv buffer of the current data
290
 * @param pinfo the packet info of the current data
291
 * @param tree the tree to append this item to
292
 * @param offset the offset in the tvb
293
 * @param hfid the hfid of the item to use (e.g., hf_bacapp_object_identifier
294
 *  or hf_bacapp_device_identifier)
295
 * @return modified offset
296
 */
297
static unsigned
298
fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int hfid);
299
300
/**
301
 * BACnet-Confirmed-Service-Request ::= CHOICE {
302
 * }
303
 * @param tvb the tv buffer of the current data
304
 * @param pinfo the packet info of the current data
305
 * @param tree the tree to append this item to
306
 * @param offset the offset in the tvb
307
 * @param service_choice the service choice
308
 * @return offset
309
 */
310
static unsigned
311
fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
312
313
/**
314
 * BACnet-Confirmed-Service-ACK ::= CHOICE {
315
 * }
316
 * @param tvb the tv buffer of the current data
317
 * @param pinfo the packet info of the current data
318
 * @param tree the tree to append this item to
319
 * @param offset the offset in the tvb
320
 * @param service_choice the service choice
321
 * @return offset
322
 */
323
static unsigned
324
fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
325
326
/**
327
 * AcknowledgeAlarm-Request ::= SEQUENCE {
328
 *  acknowledgingProcessIdentifier [0] Unsigned32,
329
 *  eventObjectIdentifier          [1] BACnetObjectIdentifier,
330
 *  eventStateAcknowledge          [2] BACnetEventState,
331
 *  timeStamp                      [3] BACnetTimeStamp,
332
 *  acknowledgementSource          [4] Character String,
333
 *  timeOfAcknowledgement          [5] BACnetTimeStamp
334
 * }
335
 * @param tvb the tv buffer of the current data
336
 * @param pinfo the packet info of the current data
337
 * @param tree the tree to append this item to
338
 * @param offset the offset in the tvb
339
 * @return modified offset
340
 */
341
static unsigned
342
fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
343
344
/**
345
 * ConfirmedCOVNotification-Request ::= SEQUENCE {
346
 *  subscriberProcessIdentifier [0] Unsigned32,
347
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
348
 *  monitoredObjectIdentifier   [2] BACnetObjectIdentifier,
349
 *  timeRemaining               [3] unsigned,
350
 *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
351
 * }
352
 * @param tvb the tv buffer of the current data
353
 * @param pinfo the packet info of the current data
354
 * @param tree the tree to append this item to
355
 * @param offset the offset in the tvb
356
 * @return modified offset
357
 */
358
static unsigned
359
fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
360
361
/**
362
 * ConfirmedEventNotification-Request ::= SEQUENCE {
363
 *  ProcessIdentifier           [0] Unsigned32,
364
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
365
 *  eventObjectIdentifier       [2] BACnetObjectIdentifier,
366
 *  timeStamp                   [3] BACnetTimeStamp,
367
 *  notificationClass           [4] unsigned,
368
 *  priority                    [5] unsigned8,
369
 *  eventType                   [6] BACnetEventType,
370
 *  messageText                 [7] CharacterString OPTIONAL,
371
 *  notifyType                  [8] BACnetNotifyType,
372
 *  ackRequired                 [9] BOOLEAN OPTIONAL,
373
 *  fromState                  [10] BACnetEventState OPTIONAL,
374
 *  toState                    [11] BACnetEventState,
375
 *  eventValues                [12] BACnetNotificationParameters OPTIONAL
376
 * }
377
 * @param tvb the tv buffer of the current data
378
 * @param pinfo the packet info of the current data
379
 * @param tree the tree to append this item to
380
 * @param offset the offset in the tvb
381
 * @return modified offset
382
 */
383
static unsigned
384
fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo,  proto_tree *tree, unsigned offset);
385
386
/**
387
 * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
388
 *  objectIdentifier         BACnetObjectIdentifier,
389
 *  alarmState               BACnetEventState,
390
 *  acknowledgedTransitions  BACnetEventTransitionBits
391
 * }
392
 * @param tvb the tv buffer of the current data
393
 * @param pinfo the packet info of the current data
394
 * @param tree the tree to append this item to
395
 * @param offset the offset in the tvb
396
 * @return modified offset
397
 */
398
static unsigned
399
fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
400
401
/**
402
 * GetEnrollmentSummary-Request ::= SEQUENCE {
403
 *  acknowledgmentFilter    [0] ENUMERATED {
404
 *      all       (0),
405
 *      acked     (1),
406
 *      not-acked (2)
407
 *      },
408
 *  enrollmentFilter        [1] BACnetRecipientProcess OPTIONAL,
409
 *  eventStateFilter        [2] ENUMERATED {
410
 *      offnormal (0),
411
 *      fault     (1),
412
 *      normal    (2),
413
 *      all       (3),
414
 *      active    (4)
415
 *      },
416
 *  eventTypeFilter         [3] BACnetEventType OPTIONAL,
417
 *  priorityFilter          [4] SEQUENCE {
418
 *      minPriority [0] Unsigned8,
419
 *      maxPriority [1] Unsigned8
420
 *      } OPTIONAL,
421
 *  notificationClassFilter [5] Unsigned OPTIONAL
422
 * }
423
 * @param tvb the tv buffer of the current data
424
 * @param pinfo the packet info of the current data
425
 * @param tree the tree to append this item to
426
 * @param offset the offset in the tvb
427
 * @return modified offset
428
 */
429
static unsigned
430
fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
431
432
/**
433
 * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
434
 *  objectIdentifier    BACnetObjectIdentifier,
435
 *  eventType           BACnetEventType,
436
 *  eventState          BACnetEventState,
437
 *  priority            Unsigned8,
438
 *  notificationClass   Unsigned OPTIONAL
439
 * }
440
 * @param tvb the tv buffer of the current data
441
 * @param pinfo the packet info of the current data
442
 * @param tree the tree to append this item to
443
 * @param offset the offset in the tvb
444
 * @return modified offset
445
 */
446
static unsigned
447
fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
448
449
/**
450
 * GetEventInformation-Request ::= SEQUENCE {
451
 *  lastReceivedObjectIdentifier    [0] BACnetObjectIdentifier
452
 * }
453
 * @param tvb the tv buffer of the current data
454
 * @param pinfo the packet info of the current data
455
 * @param tree the tree to append this item to
456
 * @param offset the offset in the tvb
457
 * @return modified offset
458
 */
459
static unsigned
460
fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
461
462
/**
463
 * GetEventInformation-ACK ::= SEQUENCE {
464
 *  listOfEventSummaries [0] listOfEventSummaries,
465
 *  moreEvents           [1] BOOLEAN
466
 * }
467
 * @param tvb the tv buffer of the current data
468
 * @param pinfo the packet info of the current data
469
 * @param tree the tree to append this item to
470
 * @param offset the offset in the tvb
471
 * @return modified offset
472
 */
473
static unsigned
474
fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
475
476
/**
477
 * LifeSafetyOperation-Request ::= SEQUENCE {
478
 *  requestingProcessIdentifier [0] Unsigned32
479
 *  requestingSource            [1] CharacterString
480
 *  request                     [2] BACnetLifeSafetyOperation
481
 *  objectIdentifier            [3] BACnetObjectIdentifier OPTIONAL
482
 * }
483
 * @param tvb the tv buffer of the current data
484
 * @param pinfo the packet info of the current data
485
 * @param tree the tree to append this item to
486
 * @param offset the offset in the tvb
487
 * @return modified offset
488
 */
489
static unsigned
490
fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
491
492
/**
493
 * SubscribeCOV-Request ::= SEQUENCE {
494
 *  subscriberProcessIdentifier [0] Unsigned32
495
 *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
496
 *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
497
 *  lifetime                    [3] Unsigned OPTIONAL
498
 * }
499
 * @param tvb the tv buffer of the current data
500
 * @param pinfo the packet info of the current data
501
 * @param tree the tree to append this item to
502
 * @param offset the offset in the tvb
503
 * @return modified offset
504
 */
505
static unsigned
506
fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
507
508
/**
509
 * SubscribeCOVProperty-Request ::= SEQUENCE {
510
 *  subscriberProcessIdentifier [0] Unsigned32
511
 *  monitoredObjectIdentifier   [1] BACnetObjectIdentifier
512
 *  issueConfirmedNotifications [2] BOOLEAN OPTIONAL
513
 *  lifetime                    [3] Unsigned OPTIONAL
514
 *  monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
515
 *  covIncrement                [5] Unsigned OPTIONAL
516
 * }
517
 * @param tvb the tv buffer of the current data
518
 * @param pinfo the packet info of the current data
519
 * @param tree the tree to append this item to
520
 * @param offset the offset in the tvb
521
 * @return modified offset
522
 */
523
static unsigned
524
fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
525
526
/**
527
 * AtomicReadFile-Request ::= SEQUENCE {
528
 *  fileIdentifier  BACnetObjectIdentifier,
529
 *  accessMethod    CHOICE {
530
 *      streamAccess    [0] SEQUENCE {
531
 *          fileStartPosition   INTEGER,
532
 *          requestedOctetCount Unsigned
533
 *          },
534
 *      recordAccess    [1] SEQUENCE {
535
 *          fileStartRecord      INTEGER,
536
 *          requestedRecordCount Unsigned
537
 *          }
538
 *      }
539
 * }
540
 * @param tvb the tv buffer of the current data
541
 * @param pinfo the packet info of the current data
542
 * @param tree the tree to append this item to
543
 * @param offset the offset in the tvb
544
 * @return modified offset
545
 */
546
static unsigned
547
fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
548
549
/**
550
 * AtomicWriteFile-ACK ::= SEQUENCE {
551
 *  endOfFile   BOOLEAN,
552
 *  accessMethod    CHOICE {
553
 *      streamAccess    [0] SEQUENCE {
554
 *          fileStartPosition   INTEGER,
555
 *          fileData            OCTET STRING
556
 *          },
557
 *      recordAccess    [1] SEQUENCE {
558
 *          fileStartRecord     INTEGER,
559
 *          returnedRecordCount Unsigned,
560
 *          fileRecordData      SEQUENCE OF OCTET STRING
561
 *          }
562
 *      }
563
 * }
564
 * @param tvb the tv buffer of the current data
565
 * @param pinfo the packet info of the current data
566
 * @param tree the tree to append this item to
567
 * @param offset the offset in the tvb
568
 * @return modified offset
569
 */
570
static unsigned
571
fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
572
573
/**
574
 * AtomicWriteFile-Request ::= SEQUENCE {
575
 *  fileIdentifier  BACnetObjectIdentifier,
576
 *  accessMethod    CHOICE {
577
 *      streamAccess    [0] SEQUENCE {
578
 *          fileStartPosition  INTEGER,
579
 *          fileData           OCTET STRING
580
 *          },
581
 *      recordAccess    [1] SEQUENCE {
582
 *          fileStartRecord    INTEGER,
583
 *          recordCount        Unsigned,
584
 *          fileRecordData     SEQUENCE OF OCTET STRING
585
 *          }
586
 *      }
587
 * }
588
 * @param tvb the tv buffer of the current data
589
 * @param pinfo the packet info of the current data
590
 * @param tree the tree to append this item to
591
 * @param offset the offset in the tvb
592
 * @return modified offset
593
 */
594
static unsigned
595
fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
596
597
/**
598
 * AtomicWriteFile-ACK ::= SEQUENCE {
599
 *      fileStartPosition [0] INTEGER,
600
 *      fileStartRecord   [1] INTEGER,
601
 * }
602
 * @param tvb the tv buffer of the current data
603
 * @param pinfo the packet info of the current data
604
 * @param tree the tree to append this item to
605
 * @param offset the offset in the tvb
606
 * @return modified offset
607
 */
608
static unsigned
609
fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
610
611
/**
612
 * AddListElement-Request ::= SEQUENCE {
613
 *  objectIdentifier   [0] BACnetObjectIdentifier,
614
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
615
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
616
 *  listOfElements     [3] ABSTRACT-SYNTAX.&Type
617
 * }
618
 * @param tvb the tv buffer of the current data
619
 * @param pinfo the packet info of the current data
620
 * @param tree the tree to append this item to
621
 * @param offset the offset in the tvb
622
 * @return modified offset
623
 */
624
static unsigned
625
fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
626
627
/**
628
 * CreateObject-Request ::= SEQUENCE {
629
 *  objectSpecifier     [0] ObjectSpecifier,
630
 *  listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
631
 * }
632
 * @param tvb the tv buffer of the current data
633
 * @param pinfo the packet info of the current data
634
 * @param subtree the sub tree to append this item to
635
 * @param offset the offset in the tvb
636
 * @return modified offset
637
 */
638
static unsigned
639
fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
640
641
/**
642
 * CreateObject-Request ::= BACnetObjectIdentifier
643
 * @param tvb the tv buffer of the current data
644
 * @param pinfo the packet info of the current data
645
 * @param tree the tree to append this item to
646
 * @param offset the offset in the tvb
647
 * @return modified offset
648
 */
649
static unsigned
650
fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
651
652
/**
653
 * DeleteObject-Request ::= SEQUENCE {
654
 *  ObjectIdentifier    BACnetObjectIdentifier
655
 * }
656
 * @param tvb the tv buffer of the current data
657
 * @param pinfo the packet info of the current data
658
 * @param tree the tree to append this item to
659
 * @param offset the offset in the tvb
660
 * @return modified offset
661
 */
662
static unsigned
663
fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
664
665
/**
666
 * ReadProperty-Request ::= SEQUENCE {
667
 *  objectIdentifier    [0] BACnetObjectIdentifier,
668
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
669
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
670
 * }
671
 * @param tvb the tv buffer of the current data
672
 * @param pinfo the packet info of the current data
673
 * @param tree the tree to append this item to
674
 * @param offset the offset in the tvb
675
 * @return modified offset
676
 */
677
static unsigned
678
fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
679
680
/**
681
 * ReadProperty-ACK ::= SEQUENCE {
682
 *  objectIdentifier   [0] BACnetObjectIdentifier,
683
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
684
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
685
 *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
686
 * }
687
 * @param tvb the tv buffer of the current data
688
 * @param pinfo the packet info of the current data
689
 * @param tree the tree to append this item to
690
 * @param offset the offset in the tvb
691
 * @return modified offset
692
 */
693
static unsigned
694
fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
695
696
/**
697
 * ReadPropertyConditional-Request ::= SEQUENCE {
698
 *  objectSelectionCriteria  [0] objectSelectionCriteria,
699
 *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
700
 * }
701
 * @param tvb the tv buffer of the current data
702
 * @param pinfo the packet info of the current data
703
 * @param subtree the  sub tree to append this item to
704
 * @param offset the offset in the tvb
705
 * @return modified offset
706
 */
707
static unsigned
708
fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
709
710
/**
711
 * ReadPropertyConditional-ACK ::= SEQUENCE {
712
 *  listOfPReadAccessResults    SEQUENCE OF ReadAccessResult OPTIONAL
713
 * }
714
 * @param tvb the tv buffer of the current data
715
 * @param pinfo the packet info of the current data
716
 * @param tree the tree to append this item to
717
 * @param offset the offset in the tvb
718
 * @return modified offset
719
 */
720
static unsigned
721
fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
722
723
/**
724
 * ReadPropertyMultiple-Request ::= SEQUENCE {
725
 *  listOfReadAccessSpecs   SEQUENCE OF ReadAccessSpecification
726
 * }
727
 * @param tvb the tv buffer of the current data
728
 * @param pinfo the packet info of the current data
729
 * @param subtree the sub tree to append this item to
730
 * @param offset the offset in the tvb
731
 * @return offset modified
732
 */
733
static unsigned
734
fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
735
736
/**
737
 * ReadPropertyMultiple-Ack ::= SEQUENCE {
738
 *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
739
 * }
740
 * @param tvb the tv buffer of the current data
741
 * @param pinfo the packet info of the current data
742
 * @param tree the tree to append this item to
743
 * @param offset the offset in the tvb
744
 * @return offset modified
745
 */
746
static unsigned
747
fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
748
749
/**
750
 * ReadRange-Request ::= SEQUENCE {
751
 *  objectIdentifier    [0] BACnetObjectIdentifier,
752
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
753
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
754
 *  range   CHOICE {
755
 *      byPosition  [3] SEQUENCE {
756
 *          referencedIndex Unsigned,
757
 *          count INTEGER
758
 *          },
759
 *      byTime      [4] SEQUENCE {
760
 *          referenceTime BACnetDateTime,
761
 *          count INTEGER
762
 *          },
763
 *      timeRange   [5] SEQUENCE {
764
 *          beginningTime BACnetDateTime,
765
 *          endingTime BACnetDateTime
766
 *          },
767
 *      } OPTIONAL
768
 * }
769
 * @param tvb the tv buffer of the current data
770
 * @param pinfo the packet info of the current data
771
 * @param tree the tree to append this item to
772
 * @param offset the offset in the tvb
773
 * @return modified offset
774
 */
775
static unsigned
776
fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
777
778
/**
779
 * ReadRange-ACK ::= SEQUENCE {
780
 *  objectIdentifier   [0] BACnetObjectIdentifier,
781
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
782
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
783
 *  resultFlags        [3] BACnetResultFlags,
784
 *  itemCount          [4] Unsigned,
785
 *  itemData           [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
786
 * }
787
 * @param tvb the tv buffer of the current data
788
 * @param pinfo the packet info of the current data
789
 * @param tree the tree to append this item to
790
 * @param offset the offset in the tvb
791
 * @return modified offset
792
 */
793
static unsigned
794
fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
795
796
/**
797
 * RemoveListElement-Request ::= SEQUENCE {
798
 *  objectIdentifier    [0] BACnetObjectIdentifier,
799
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
800
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
801
 *  listOfElements  [3] ABSTRACT-SYNTAX.&Type
802
 * }
803
 * @param tvb the tv buffer of the current data
804
 * @param pinfo the packet info of the current data
805
 * @param tree the tree to append this item to
806
 * @param offset the offset in the tvb
807
 * @return modified offset
808
 */
809
static unsigned
810
fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
811
812
/**
813
 * WriteProperty-Request ::= SEQUENCE {
814
 *  objectIdentifier   [0] BACnetObjectIdentifier,
815
 *  propertyIdentifier [1] BACnetPropertyIdentifier,
816
 *  propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
817
 *  propertyValue      [3] ABSTRACT-SYNTAX.&Type
818
 *  priority           [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
819
 * }
820
 * @param tvb the tv buffer of the current data
821
 * @param pinfo the packet info of the current data
822
 * @param tree the tree to append this item to
823
 * @param offset the offset in the tvb
824
 * @return modified offset
825
 */
826
static unsigned
827
fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
828
829
/**
830
 * WritePropertyMultiple-Request ::= SEQUENCE {
831
 *  listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
832
 * }
833
 * @param tvb the tv buffer of the current data
834
 * @param pinfo the packet info of the current data
835
 * @param tree the tree to append this item to
836
 * @param offset the offset in the tvb
837
 * @return modified offset
838
 */
839
static unsigned
840
fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
841
842
/**
843
 * DeviceCommunicationControl-Request ::= SEQUENCE {
844
 *  timeDuration    [0] Unsigned16 OPTIONAL,
845
 *  enable-disable  [1] ENUMERATED {
846
 *      enable  (0),
847
 *      disable (1)
848
 *      },
849
 *  password        [2] CharacterString (SIZE(1..20)) OPTIONAL
850
 * }
851
 * @param tvb the tv buffer of the current data
852
 * @param pinfo the packet info of the current data
853
 * @param tree the tree to append this item to
854
 * @param offset the offset in the tvb
855
 * @return modified offset
856
 */
857
static unsigned
858
fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
859
860
/**
861
 * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
862
 *  vendorID          [0] Unsigned,
863
 *  serviceNumber     [1] Unsigned,
864
 *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
865
 * }
866
 * @param tvb the tv buffer of the current data
867
 * @param pinfo the packet info of the current data
868
 * @param tree the tree to append this item to
869
 * @param offset the offset in the tvb
870
 * @return modified offset
871
 */
872
static unsigned
873
fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
874
875
/**
876
 * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
877
 *  vendorID      [0] Unsigned,
878
 *  serviceNumber [1] Unsigned,
879
 *  resultBlock   [2] ABSTRACT-SYNTAX.&Type OPTIONAL
880
 * }
881
 * @param tvb the tv buffer of the current data
882
 * @param pinfo the packet info of the current data
883
 * @param tree the tree to append this item to
884
 * @param offset the offset in the tvb
885
 * @return modified offset
886
 */
887
static unsigned
888
fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
889
890
/**
891
 * ConfirmedTextMessage-Request ::=  SEQUENCE {
892
 *  textMessageSourceDevice [0] BACnetObjectIdentifier,
893
 *  messageClass            [1] CHOICE {
894
 *      numeric   [0] Unsigned,
895
 *      character [1] CharacterString
896
 *      } OPTIONAL,
897
 *  messagePriority         [2] ENUMERATED {
898
 *      normal (0),
899
 *      urgent (1)
900
 *      },
901
 *  message [3] CharacterString
902
 * }
903
 * @param tvb the tv buffer of the current data
904
 * @param pinfo the packet info of the current data
905
 * @param tree the tree to append this item to
906
 * @param offset the offset in the tvb
907
 * @return modified offset
908
 */
909
static unsigned
910
fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
911
912
/**
913
 * ReinitializeDevice-Request ::= SEQUENCE {
914
 *  reinitializedStateOfDevice  [0] ENUMERATED {
915
 *      coldstart    (0),
916
 *      warmstart    (1),
917
 *      startbackup  (2),
918
 *      endbackup    (3),
919
 *      startrestore (4),
920
 *      endrestore   (5),
921
 *      abortrestor  (6)
922
 *      },
923
 *  password                    [1] CharacterString (SIZE(1..20)) OPTIONAL
924
 * }
925
 * @param tvb the tv buffer of the current data
926
 * @param pinfo the packet info of the current data
927
 * @param tree the tree to append this item to
928
 * @param offset the offset in the tvb
929
 * @return modified offset
930
 */
931
static unsigned
932
fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
933
934
/**
935
 * VTOpen-Request ::= SEQUENCE {
936
 *  vtClass BACnetVTClass,
937
 *  localVTSessionIdentifier    Unsigned8
938
 * }
939
 * @param tvb the tv buffer of the current data
940
 * @param pinfo the packet info of the current data
941
 * @param tree the tree to append this item to
942
 * @param offset the offset in the tvb
943
 * @return modified offset
944
 */
945
static unsigned
946
fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
947
948
/**
949
 * VTOpen-ACK ::= SEQUENCE {
950
 *  remoteVTSessionIdentifier   Unsigned8
951
 * }
952
 * @param tvb the tv buffer of the current data
953
 * @param pinfo the packet info of the current data
954
 * @param tree the tree to append this item to
955
 * @param offset the offset in the tvb
956
 * @return modified offset
957
 */
958
static unsigned
959
fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
960
961
/**
962
 * VTClose-Request ::= SEQUENCE {
963
 *  listOfRemoteVTSessionIdentifiers    SEQUENCE OF Unsigned8
964
 * }
965
 * @param tvb the tv buffer of the current data
966
 * @param pinfo the packet info of the current data
967
 * @param tree the tree to append this item to
968
 * @param offset the offset in the tvb
969
 * @return modified offset
970
 */
971
static unsigned
972
fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
973
974
/**
975
 * VTData-Request ::= SEQUENCE {
976
 *  vtSessionIdentifier Unsigned8,
977
 *  vtNewData           OCTET STRING,
978
 *  vtDataFlag          Unsigned (0..1)
979
 * }
980
 * @param tvb the tv buffer of the current data
981
 * @param pinfo the packet info of the current data
982
 * @param tree the tree to append this item to
983
 * @param offset the offset in the tvb
984
 * @return modified offset
985
 */
986
static unsigned
987
fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
988
989
/**
990
 * VTData-ACK ::= SEQUENCE {
991
 *  allNewDataAccepted  [0] BOOLEAN,
992
 *  acceptedOctetCount  [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = false
993
 * }
994
 * @param tvb the tv buffer of the current data
995
 * @param pinfo the packet info of the current data
996
 * @param tree the tree to append this item to
997
 * @param offset the offset in the tvb
998
 * @return modified offset
999
 */
1000
static unsigned
1001
fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1002
1003
/**
1004
 * Authenticate-Request ::= SEQUENCE {
1005
 *  pseudoRandomNumber     [0] Unsigned32,
1006
 *  expectedInvokeID       [1] Unsigned8 OPTIONAL,
1007
 *  operatorName           [2] CharacterString OPTIONAL,
1008
 *  operatorPassword       [3] CharacterString (SIZE(1..20)) OPTIONAL,
1009
 *  startEncypheredSession [4] BOOLEAN OPTIONAL
1010
 * }
1011
 * @param tvb the tv buffer of the current data
1012
 * @param pinfo the packet info of the current data
1013
 * @param tree the tree to append this item to
1014
 * @param offset the offset in the tvb
1015
 * @return modified offset
1016
 */
1017
static unsigned
1018
fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1019
1020
/**
1021
 * Authenticate-ACK ::= SEQUENCE {
1022
 *  modifiedRandomNumber    Unsigned32,
1023
 * }
1024
 * @param tvb the tv buffer of the current data
1025
 * @param pinfo the packet info of the current data
1026
 * @param tree the tree to append this item to
1027
 * @param offset the offset in the tvb
1028
 * @return modified offset
1029
 */
1030
static unsigned
1031
fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1032
1033
/**
1034
 * RequestKey-Request ::= SEQUENCE {
1035
 *  requestingDeviceIdentifier BACnetObjectIdentifier,
1036
 *  requestingDeviceAddress    BACnetAddress,
1037
 *  remoteDeviceIdentifier     BACnetObjectIdentifier,
1038
 *  remoteDeviceAddress        BACnetAddress
1039
 * }
1040
 * @param tvb the tv buffer of the current data
1041
 * @param pinfo the packet info of the current data
1042
 * @param tree the tree to append this item to
1043
 * @param offset the offset in the tvb
1044
 * @return modified offset
1045
 */
1046
static unsigned
1047
fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1048
1049
/**
1050
 * Unconfirmed-Service-Request ::= CHOICE {
1051
 * }
1052
 * @param tvb the tv buffer of the current data
1053
 * @param pinfo the packet info of the current data
1054
 * @param tree the tree to append this item to
1055
 * @param offset the offset in the tvb
1056
 * @param service_choice the service choice
1057
 * @return modified offset
1058
 */
1059
static unsigned
1060
fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
1061
1062
/**
1063
 * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1064
 *  subscriberProcessIdentifier [0] Unsigned32,
1065
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
1066
 *  monitoredObjectIdentifier   [2] BACnetObjectIdentifier,
1067
 *  timeRemaining               [3] unsigned,
1068
 *  listOfValues                [4] SEQUENCE OF BACnetPropertyValues
1069
 * }
1070
 * @param tvb the tv buffer of the current data
1071
 * @param pinfo the packet info of the current data
1072
 * @param tree the tree to append this item to
1073
 * @param offset the offset in the tvb
1074
 * @return modified offset
1075
 */
1076
static unsigned
1077
fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1078
1079
/**
1080
 * UnconfirmedEventNotification-Request ::= SEQUENCE {
1081
 *  ProcessIdentifier           [0] Unsigned32,
1082
 *  initiatingDeviceIdentifier  [1] BACnetObjectIdentifier,
1083
 *  eventObjectIdentifier       [2] BACnetObjectIdentifier,
1084
 *  timeStamp                   [3] BACnetTimeStamp,
1085
 *  notificationClass           [4] unsigned,
1086
 *  priority                    [5] unsigned8,
1087
 *  eventType                   [6] BACnetEventType,
1088
 *  messageText                 [7] CharacterString OPTIONAL,
1089
 *  notifyType                  [8] BACnetNotifyType,
1090
 *  ackRequired                 [9] BOOLEAN OPTIONAL,
1091
 *  fromState                  [10] BACnetEventState OPTIONAL,
1092
 *  toState                    [11] BACnetEventState,
1093
 *  eventValues                [12] BACnetNotificationParameters OPTIONAL
1094
 * }
1095
 * @param tvb the tv buffer of the current data
1096
 * @param pinfo the packet info of the current data
1097
 * @param tree the tree to append this item to
1098
 * @param offset the offset in the tvb
1099
 * @return modified offset
1100
 */
1101
static unsigned
1102
fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1103
1104
/**
1105
 * I-Am-Request ::= SEQUENCE {
1106
 *  aAmDeviceIdentifier BACnetObjectIdentifier,
1107
 *  maxAPDULengthAccepted   Unsigned,
1108
 *  segmentationSupported   BACnetSegmentation,
1109
 *  vendorID    Unsigned
1110
 * }
1111
 * @param tvb the tv buffer of the current data
1112
 * @param pinfo the packet info of the current data
1113
 * @param tree the tree to append this item to
1114
 * @param offset the offset in the tvb
1115
 * @return modified offset
1116
 */
1117
static unsigned
1118
fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1119
1120
1121
/**
1122
 * I-Have-Request ::= SEQUENCE {
1123
 *  deviceIdentifier  BACnetObjectIdentifier,
1124
 *  objectIdentifier  BACnetObjectIdentifier,
1125
 *  objectName        CharacterString
1126
 * }
1127
 * @param tvb the tv buffer of the current data
1128
 * @param pinfo the packet info of the current data
1129
 * @param tree the tree to append this item to
1130
 * @param offset the offset in the tvb
1131
 * @return modified offset
1132
 */
1133
static unsigned
1134
fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1135
1136
/**
1137
 * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1138
 *  vendorID          [0] Unsigned,
1139
 *  serviceNumber     [1] Unsigned,
1140
 *  serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1141
 * }
1142
 * @param tvb the tv buffer of the current data
1143
 * @param pinfo the packet info of the current data
1144
 * @param tree the tree to append this item to
1145
 * @param offset the offset in the tvb
1146
 * @return modified offset
1147
 */
1148
static unsigned
1149
fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1150
1151
/**
1152
 * UnconfirmedTextMessage-Request ::=  SEQUENCE {
1153
 *  textMessageSourceDevice [0] BACnetObjectIdentifier,
1154
 *  messageClass            [1] CHOICE {
1155
 *      numeric   [0] Unsigned,
1156
 *      character [1] CharacterString
1157
 *      } OPTIONAL,
1158
 *  messagePriority         [2] ENUMERATED {
1159
 *      normal (0),
1160
 *      urgent (1)
1161
 *      },
1162
 *  message                 [3] CharacterString
1163
 * }
1164
 * @param tvb the tv buffer of the current data
1165
 * @param pinfo the packet info of the current data
1166
 * @param tree the tree to append this item to
1167
 * @param offset the offset in the tvb
1168
 * @return modified offset
1169
 */
1170
static unsigned
1171
fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1172
1173
/**
1174
 * TimeSynchronization-Request ::=  SEQUENCE {
1175
 *  BACnetDateTime
1176
 * }
1177
 * @param tvb the tv buffer of the current data
1178
 * @param pinfo the packet info of the current data
1179
 * @param tree the tree to append this item to
1180
 * @param offset the offset in the tvb
1181
 * @return modified offset
1182
 */
1183
static unsigned
1184
fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1185
1186
/**
1187
 * UTCTimeSynchronization-Request ::=  SEQUENCE {
1188
 *  BACnetDateTime
1189
 * }
1190
 * @param tvb the tv buffer of the current data
1191
 * @param pinfo the packet info of the current data
1192
 * @param tree the tree to append this item to
1193
 * @param offset the offset in the tvb
1194
 * @return modified offset
1195
 */
1196
static unsigned
1197
fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1198
1199
/**
1200
 * Who-Has-Request ::=  SEQUENCE {
1201
 *  limits SEQUENCE {
1202
 *      deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303),
1203
 *      deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1204
 *      } OPTIONAL,
1205
 *  object CHOICE {
1206
 *      objectIdentifier             [2] BACnetObjectIdentifier,
1207
 *      objectName                   [3] CharacterString
1208
 *      }
1209
 * }
1210
 * @param tvb the tv buffer of the current data
1211
 * @param pinfo the packet info of the current data
1212
 * @param tree the tree to append this item to
1213
 * @param offset the offset in the tvb
1214
 * @return modified offset
1215
 */
1216
static unsigned
1217
fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1218
1219
/**
1220
 * Who-Is-Request ::= SEQUENCE {
1221
 *  deviceInstanceRangeLowLimit  [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1222
 *  deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1223
 * }
1224
 * @param tvb the tv buffer of the current data
1225
 * @param tree the tree to append this item to
1226
 * @param offset the offset in the tvb
1227
 * @return modified offset
1228
 */
1229
static unsigned
1230
fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1231
1232
/**
1233
 * BACnet-Error ::= CHOICE {
1234
 *  addListElement           [8] ChangeList-Error,
1235
 *  removeListElement        [9] ChangeList-Error,
1236
 *  writePropertyMultiple   [16] WritePropertyMultiple-Error,
1237
 *  confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1238
 *  vtClose                 [22] VTClose-Error,
1239
 *  readRange               [26] ObjectAccessService-Error
1240
 *                          [default] Error
1241
 * }
1242
 * @param tvb the tv buffer of the current data
1243
 * @param pinfo the packet info of the current data
1244
 * @param tree the tree to append this item to
1245
 * @param offset the offset in the tvb
1246
 * @param service the service
1247
 * @return modified offset
1248
 */
1249
static unsigned
1250
fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned service);
1251
1252
/**
1253
 * Dissect a BACnetError in a context tag
1254
 *
1255
 * @param tvb the tv buffer of the current data
1256
 * @param pinfo the packet info of the current data
1257
 * @param tree the tree to append this item to
1258
 * @param offset the offset in the tvb
1259
 * @return modified offset
1260
 */
1261
static unsigned fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1262
1263
/**
1264
 * ChangeList-Error ::= SEQUENCE {
1265
 *    errorType                [0] Error,
1266
 *    firstFailedElementNumber [1] Unsigned
1267
 *    }
1268
 * }
1269
 * @param tvb the tv buffer of the current data
1270
 * @param pinfo the packet info of the current data
1271
 * @param tree the tree to append this item to
1272
 * @param offset the offset in the tvb
1273
 * @return modified offset
1274
 */
1275
static unsigned
1276
fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1277
1278
/**
1279
 * CreateObject-Error ::= SEQUENCE {
1280
 *    errorType                [0] Error,
1281
 *    firstFailedElementNumber [1] Unsigned
1282
 *    }
1283
 * }
1284
 * @param tvb the tv buffer of the current data
1285
 * @param pinfo the packet info of the current data
1286
 * @param tree the tree to append this item to
1287
 * @param offset the offset in the tvb
1288
 * @return modified offset
1289
 */
1290
static unsigned
1291
fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1292
1293
/**
1294
 * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1295
 *    errorType       [0] Error,
1296
 *    vendorID        [1] Unsigned,
1297
 *    serviceNumber   [2] Unsigned,
1298
 *    errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1299
 *    }
1300
 * }
1301
 * @param tvb the tv buffer of the current data
1302
 * @param pinfo the packet info of the current data
1303
 * @param tree the tree to append this item to
1304
 * @param offset the offset in the tvb
1305
 * @return modified offset
1306
 */
1307
static unsigned
1308
fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1309
1310
/**
1311
 * WritePropertyMultiple-Error ::= SEQUENCE {
1312
 *    errorType               [0] Error,
1313
 *    firstFailedWriteAttempt [1] Unsigned
1314
 *    }
1315
 * }
1316
 * @param tvb the tv buffer of the current data
1317
 * @param pinfo the packet info of the current data
1318
 * @param tree the tree to append this item to
1319
 * @param offset the offset in the tvb
1320
 * @return modified offset
1321
 */
1322
static unsigned
1323
fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1324
1325
/**
1326
 * VTClose-Error ::= SEQUENCE {
1327
 *    errorType                  [0] Error,
1328
 *    listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1329
 *    }
1330
 * }
1331
 * @param tvb the tv buffer of the current data
1332
 * @param pinfo the packet info of the current data
1333
 * @param tree the tree to append this item to
1334
 * @param offset the offset in the tvb
1335
 * @return modified offset
1336
 */
1337
static unsigned
1338
fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1339
1340
/**
1341
 * BACnet Application Types chapter 20.2.1
1342
 * @param tvb the tv buffer of the current data
1343
 * @param pinfo the packet info of the current data
1344
 * @param tree the tree to append this item to
1345
 * @param offset the offset in the tvb
1346
 * @param label the label of this item
1347
 * @return modified offset
1348
 */
1349
static unsigned
1350
fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
1351
1352
/**
1353
 * BACnetActionCommand ::= SEQUENCE {
1354
 *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1355
 *  objectIdentifier    [1] BACnetObjectIdentifier,
1356
 *  propertyIdentifier  [2] BACnetPropertyIdentifier,
1357
 *  propertyArrayIndex  [3] Unsigned OPTIONAL, -- used only with array datatype
1358
 *  propertyValue       [4] ABSTRACT-SYNTAX.&Type,
1359
 *  priority            [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1360
 *  postDelay           [6] Unsigned OPTIONAL,
1361
 *  quitOnFailure       [7] BOOLEAN,
1362
 *  writeSuccessful     [8] BOOLEAN
1363
 * }
1364
 * @param tvb the tv buffer of the current data
1365
 * @param pinfo the packet info of the current data
1366
 * @param tree the tree to append this item to
1367
 * @param offset the offset in the tvb
1368
 * @param tag_match the tag number
1369
 * @return modified offset
1370
 */
1371
static unsigned
1372
fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_match);
1373
1374
/**
1375
 * BACnetActionList ::= SEQUENCE {
1376
 *  action  [0] SEQUENCE of BACnetActionCommand
1377
 * }
1378
 * @param tvb the tv buffer of the current data
1379
 * @param pinfo the packet info of the current data
1380
 * @param tree the tree to append this item to
1381
 * @param offset the offset in the tvb
1382
 * @return modified offset
1383
 */
1384
static unsigned
1385
fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1386
1387
/** BACnetAddress ::= SEQUENCE {
1388
 *  network-number  Unsigned16, -- A value 0 indicates the local network
1389
 *  mac-address     OCTET STRING -- A string of length 0 indicates a broadcast
1390
 * }
1391
 * @param tvb the tv buffer of the current data
1392
 * @param pinfo the packet info of the current data
1393
 * @param tree the tree to append this item to
1394
 * @param offset the offset in the tvb
1395
 * @return modified offset
1396
 */
1397
static unsigned
1398
fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1399
1400
/**
1401
 * BACnetAddressBinding ::= SEQUENCE {
1402
 *  deviceObjectID  BACnetObjectIdentifier
1403
 *  deviceAddress   BacnetAddress
1404
 * }
1405
 * @param tvb the tv buffer of the current data
1406
 * @param pinfo the packet info of the current data
1407
 * @param tree the tree to append this item to
1408
 * @param offset the offset in the tvb
1409
 * @return modified offset
1410
 */
1411
static unsigned
1412
fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1413
1414
/**
1415
 * BACnetCalendarEntry ::= CHOICE {
1416
 *  date        [0] Date,
1417
 *  dateRange   [1] BACnetDateRange,
1418
 *  weekNDay    [2] BacnetWeekNday
1419
 * }
1420
 * @param tvb the tv buffer of the current data
1421
 * @param pinfo the packet info of the current data
1422
 * @param tree the tree to append this item to
1423
 * @param offset the offset in the tvb
1424
 * @return modified offset
1425
 */
1426
static unsigned
1427
fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1428
1429
/**
1430
 * BACnetClientCOV ::= CHOICE {
1431
 *  real-increment  REAL,
1432
 *  default-increment   NULL
1433
 * }
1434
 * @param tvb the tv buffer of the current data
1435
 * @param tree the tree to append this item to
1436
 * @param offset the offset in the tvb
1437
 * @return modified offset
1438
 */
1439
static unsigned
1440
fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1441
1442
1443
/**
1444
 * BACnetDailySchedule ::= SEQUENCE {
1445
 *  day-schedule    [0] SENQUENCE OF BACnetTimeValue
1446
 * }
1447
 * @param tvb the tv buffer of the current data
1448
 * @param pinfo the packet info of the current data
1449
 * @param tree the tree to append this item to
1450
 * @param offset the offset in the tvb
1451
 * @return modified offset
1452
 */
1453
static unsigned
1454
fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1455
1456
/**
1457
 * BACnetHealth ::= SEQUENCE {
1458
 *  timestamp                   [0] BACnetDateTime,
1459
 *  result                      [1] Error,
1460
 *  property                    [2] BACnetPropertyIdentifier OPTIONAL,
1461
 *  details                     [3] CharacterString OPTIONAL
1462
 * }
1463
 * @param tvb the tv buffer of the current data
1464
 * @param pinfo the packet info of the current data
1465
 * @param tree the tree to append this item to
1466
 * @param offset the offset in the tvb
1467
 * @return modified offset
1468
 */
1469
static unsigned
1470
fHealth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1471
1472
/**
1473
 * BACnetSCFailedConnectionRequest ::= SEQUENCE {
1474
 *  timestamp                   [0] BACnetDateTime,
1475
 *  peer-address                [1] BACnetHostNPort,
1476
 *  peer-vmac                   [2] OCTET STRING (SIZE(6))
1477
 *  peer-uuid                   [3] OCTET STRING (SIZE(16))
1478
 *  error                       [4] Error OPTIONAL
1479
 *  error-details               [5] CharacterString OPTIONAL
1480
 * }
1481
 * @param tvb the tv buffer of the current data
1482
 * @param pinfo the packet info of the current data
1483
 * @param tree the tree to append this item to
1484
 * @param offset the offset in the tvb
1485
 * @return modified offset
1486
 */
1487
static unsigned
1488
fSCFailedConnectionRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1489
1490
/**
1491
 * BACnetSCDirectConnection ::= SEQUENCE {
1492
 *  uri                         [0] CharacterString
1493
 *  connection-state            [1] BACnetSCConnectionState,
1494
 *  connect-timestamp           [2] BACnetDateTime,
1495
 *  disconnect-timestamp        [3] BACnetDateTime,
1496
 *  peer-address                [4] BACnetHostNPort,
1497
 *  peer-vmac                   [5] OCTET STRING (SIZE(6))
1498
 *  peer-uuid                   [6] OCTET STRING (SIZE(16))
1499
 *  error                       [7] Error OPTIONAL
1500
 *  error-details               [8] CharacterString OPTIONAL
1501
 * }
1502
 * @param tvb the tv buffer of the current data
1503
 * @param pinfo the packet info of the current data
1504
 * @param tree the tree to append this item to
1505
 * @param offset the offset in the tvb
1506
 * @return modified offset
1507
 */
1508
static unsigned
1509
fSCDirectConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1510
1511
/**
1512
 * BACnetSCHubConnection ::= SEQUENCE {
1513
 *  connection-state            [0] BACnetSCConnectionState,
1514
 *  connect-timestamp           [1] BACnetDateTime,
1515
 *  disconnect-timestamp        [2] BACnetDateTime,
1516
 *  error                       [3] Error OPTIONAL
1517
 *  error-details               [4] CharacterString OPTIONAL
1518
 * }
1519
 * @param tvb the tv buffer of the current data
1520
 * @param pinfo the packet info of the current data
1521
 * @param tree the tree to append this item to
1522
 * @param offset the offset in the tvb
1523
 * @return modified offset
1524
 */
1525
static unsigned
1526
fSCHubConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1527
1528
/**
1529
 * BACnetSCHubFunctionConnection ::= SEQUENCE {
1530
 *  connection-state            [0] BACnetSCConnectionState,
1531
 *  connect-timestamp           [1] BACnetDateTime,
1532
 *  disconnect-timestamp        [2] BACnetDateTime,
1533
 *  peer-address                [3] BACnetHostNPort,
1534
 *  peer-vmac                   [4] OCTET STRING (SIZE(6))
1535
 *  peer-uuid                   [5] OCTET STRING (SIZE(16))
1536
 *  error                       [6] Error OPTIONAL
1537
 *  error-details               [7] CharacterString OPTIONAL
1538
 * }
1539
 * @param tvb the tv buffer of the current data
1540
 * @param pinfo the packet info of the current data
1541
 * @param tree the tree to append this item to
1542
 * @param offset the offset in the tvb
1543
 * @return modified offset
1544
 */
1545
static unsigned
1546
fSCHubFunctionConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1547
1548
/**
1549
 * BACnetWeeklySchedule ::= SEQUENCE {
1550
 *  week-schedule    SENQUENCE SIZE (7) OF BACnetDailySchedule
1551
 * }
1552
 * @param tvb the tv buffer of the current data
1553
 * @param pinfo the packet info of the current data
1554
 * @param tree the tree to append this item to
1555
 * @param offset the offset in the tvb
1556
 * @return modified offset
1557
 */
1558
static unsigned
1559
fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1560
1561
/**
1562
 * BACnetDateRange ::= SEQUENCE {
1563
 *  StartDate   Date,
1564
 *  EndDate     Date
1565
 * }
1566
 * @param tvb the tv buffer of the current data
1567
 * @param pinfo the packet info of the current data
1568
 * @param tree the tree to append this item to
1569
 * @param offset the offset in the tvb
1570
 * @return modified offset
1571
 */
1572
static unsigned
1573
fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1574
1575
/**
1576
 * BACnetDateTime ::= SEQUENCE {
1577
 *  date   Date,
1578
 *  time   Time
1579
 * }
1580
 * @param tvb the tv buffer of the current data
1581
 * @param pinfo the packet info of the current data
1582
 * @param tree the tree to append this item to
1583
 * @param offset the offset in the tvb
1584
 * @param label the label of this item
1585
 * @return modified offset
1586
 */
1587
static unsigned
1588
fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
1589
1590
/**
1591
 * BACnetDestination ::= SEQUENCE {
1592
 *  validDays   BACnetDaysOfWeek,
1593
 *  fromTime    Time,
1594
 *  toTime      Time,
1595
 *  recipient   BACnetRecipient,
1596
 *  processIdentifier   Unsigned32,
1597
 *  issueConfirmedNotifications BOOLEAN,
1598
 *  transitions BACnetEventTransitionBits
1599
 * }
1600
 * @param tvb the tv buffer of the current data
1601
 * @param pinfo the packet info of the current data
1602
 * @param tree the tree to append this item to
1603
 * @param offset the offset in the tvb
1604
 * @return modified offset
1605
 */
1606
static unsigned
1607
fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1608
1609
/**
1610
 * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1611
 *  objectIdentifier    [0] BACnetObjectIdentifier,
1612
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1613
 *  propertyArrayIndex  [2] Unsigned OPTIONAL,
1614
 *  deviceIdentifier    [3] BACnetObjectIdentifier OPTIONAL
1615
 * }
1616
 * @param tvb the tv buffer of the current data
1617
 * @param pinfo the packet info of the current data
1618
 * @param tree the tree to append this item to
1619
 * @param offset the offset in the tvb
1620
 * @return modified offset
1621
 */
1622
static unsigned
1623
fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1624
1625
/**
1626
 * BACnetObjectPropertyReference ::= SEQUENCE {
1627
 *  objectIdentifier    [0] BACnetObjectIdentifier,
1628
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1629
 *  propertyArrayIndex  [2] Unsigned OPTIONAL,
1630
 * }
1631
 * @param tvb the tv buffer of the current data
1632
 * @param pinfo the packet info of the current data
1633
 * @param tree the tree to append this item to
1634
 * @param offset the offset in the tvb
1635
 * @return modified offset
1636
 */
1637
static unsigned
1638
fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1639
1640
/**
1641
 * BACnetDeviceObjectReference ::= SEQUENCE {
1642
 *  deviceIdentifier    [0] BACnetObjectIdentifier OPTIONAL,
1643
 *  objectIdentifier    [1] BACnetObjectIdentifier
1644
 * }
1645
 * @param tvb the tv buffer of the current data
1646
 * @param pinfo the packet info of the current data
1647
 * @param tree the tree to append this item to
1648
 * @param offset the offset in the tvb
1649
 * @return modified offset
1650
 */
1651
static unsigned
1652
fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1653
1654
/**
1655
 * BACnetEventParameter ::= CHOICE {
1656
 *  change-of-bitstring             [0] SEQUENCE {
1657
 *      time-delay                       [0] Unsigned,
1658
 *      bitmask                          [1] BIT STRING,
1659
 *      list-of-bitstring-values         [2] SEQUENCE OF BIT STRING
1660
 *      },
1661
 *  change-of-state                 [1] SEQUENCE {
1662
 *      time-delay     [0] Unsigned,
1663
 *      list-of-values [1] SEQUENCE OF BACnetPropertyStates
1664
 *      },
1665
 *  change-of-value                 [2] SEQUENCE {
1666
 *      time-delay   [0] Unsigned,
1667
 *      cov-criteria [1] CHOICE {
1668
 *          bitmask                       [0] BIT STRING,
1669
 *          referenced-property-increment [1] REAL
1670
 *          }
1671
 *      },
1672
 *  command-failure                 [3] SEQUENCE {
1673
 *      time-delay                       [0] Unsigned,
1674
 *      feedback-property-reference      [1] BACnetDeviceObjectPropertyReference
1675
 *      },
1676
 *  floating-limit                  [4] SEQUENCE {
1677
 *      time-delay                       [0] Unsigned,
1678
 *      setpoint-reference               [1] BACnetDeviceObjectPropertyReference,
1679
 *      low-diff-limit                   [2] REAL,
1680
 *      high-diff-limit                  [3] REAL,
1681
 *      deadband                         [4] REAL
1682
 *      },
1683
 *  out-of-range                    [5] SEQUENCE {
1684
 *      time-delay                       [0] Unsigned,
1685
 *      low-limit                        [1] REAL,
1686
 *      high-limit                       [2] REAL,
1687
 *      deadband                         [3] REAL
1688
 *      },
1689
 *  -- context tag 7 is deprecated
1690
 *  change-of-life-safety           [8] SEQUENCE {
1691
 *      time-delay                       [0] Unsigned,
1692
 *      list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1693
 *      list-of-alarm-values             [2] SEQUENCE OF BACnetLifeSafetyState,
1694
 *      mode-property-reference          [3] BACnetDeviceObjectPropertyReference
1695
 *      },
1696
 *  extended                        [9] SEQUENCE {
1697
 *      vendor-id                        [0] Unsigned16,
1698
 *      extended-event-type              [1] Unsigned,
1699
 *      parameters                       [2] SEQUENCE OF CHOICE {
1700
 *          null        NULL,
1701
 *          real        REAL,
1702
 *          integer     Unsigned,
1703
 *          boolean     BOOLEAN,
1704
 *          double      Double,
1705
 *          octet       OCTET STRING,
1706
 *          bitstring   BIT STRING,
1707
 *          enum        ENUMERATED,
1708
 *          reference   [0] BACnetDeviceObjectPropertyReference
1709
 *          }
1710
 *      },
1711
 *  buffer-ready                    [10] SEQUENCE {
1712
 *      notification-threshold           [0] Unsigned,
1713
 *      previous-notification-count      [1] Unsigned32
1714
 *      },
1715
 * unsigned-range                   [11] SEQUENCE {
1716
 *      time-delay                       [0] Unsigned,
1717
 *      low-limit                        [1] Unsigned,
1718
 *      high-limit                       [2] Unsigned,
1719
 *      }
1720
 * -- context tag 12 is reserved for future addenda
1721
 * access-event                     [13] SEQUENCE {
1722
 *      list-of-access-events            [0] SEQUENCE OF BACnetAccessEvent,
1723
 *      access-event-time-reference      [1] BACnetDeviceObjectPropertyReference
1724
 *      }
1725
 * double-out-of-range              [14] SEQUENCE {
1726
 *      time-delay                       [0] Unsigned,
1727
 *      low-limit                        [1] Double,
1728
 *      high-limit                       [2] Double,
1729
 *      deadband                         [3] Double
1730
 *  }
1731
 *  signed-out-of-range             [15] SEQUENCE {
1732
 *      time-delay                       [0] Unsigned,
1733
 *      low-limit                        [1] INTEGER,
1734
 *      high-limit                       [2] INTEGER,
1735
 *      deadband                         [3] Unsigned
1736
 *  }
1737
 *  unsigned-out-of-range           [16] SEQUENCE {
1738
 *      time-delay                       [0] Unsigned,
1739
 *      low-limit                        [1] Unsigned,
1740
 *      high-limit                       [2] Unsigned,
1741
 *      deadband                         [3] Unsigned
1742
 *   }
1743
 *  change-of-characterstring       [17] SEQUENCE {
1744
 *      time-delay                       [0] Unsigned,
1745
 *      list-of-alarm-values             [1] SEQUENCE OF CharacterString,
1746
 *   }
1747
 *  change-of-status-flags          [18] SEQUENCE {
1748
 *      time-delay                       [0] Unsigned,
1749
 *      selected-flags                   [1] BACnetStatusFlags
1750
 *   }
1751
 * }
1752
 * @param tvb the tv buffer of the current data
1753
 * @param tree the tree to append this item to
1754
 * @param offset the offset in the tvb
1755
 * @return modified offset
1756
 */
1757
static unsigned
1758
fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1759
1760
1761
1762
/**
1763
 * BACnetLogRecord ::= SEQUENCE {
1764
 *  timestamp   [0] BACnetDateTime,
1765
 *  logDatum    [1] CHOICE {
1766
 *      log-status      [0] BACnetLogStatus,
1767
 *      boolean-value   [1] BOOLEAN,
1768
 *      real-value      [2] REAL,
1769
 *      enum-value      [3] ENUMERATED, -- Optionally limited to 32 bits
1770
 *      unsigned-value  [4] Unsigned, -- Optionally limited to 32 bits
1771
 *      signed-value    [5] INTEGER, -- Optionally limited to 32 bits
1772
 *      bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1773
 *      null-value      [7] NULL,
1774
 *      failure         [8] Error,
1775
 *      time-change     [9] REAL,
1776
 *      any-value       [10] ABSTRACT-SYNTAX.&Type -- Optional
1777
 *      }
1778
 *  statusFlags [2] BACnetStatusFlags OPTIONAL
1779
 * }
1780
 * @param tvb the tv buffer of the current data
1781
 * @param pinfo the packet info of the current data
1782
 * @param tree the tree to append this item to
1783
 * @param offset the offset in the tvb
1784
 * @return modified offset
1785
 */
1786
static unsigned
1787
fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1788
1789
/**
1790
 * BACnetEventLogRecord ::= SEQUENCE {
1791
 *  timestamp [0] BACnetDateTime,
1792
 *  logDatum  [1] CHOICE {
1793
 *      log-status   [0] BACnetLogStatus,
1794
 *      notification [1] ConfirmedEventNotification-Request,
1795
 *      time-change  [2] REAL,
1796
 *      }
1797
 * }
1798
 * @param tvb the tv buffer of the current data
1799
 * @param pinfo the packet info of the current data
1800
 * @param tree the tree to append this item to
1801
 * @param offset the offset in the tvb
1802
 * @return modified offset
1803
 */
1804
static unsigned
1805
fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1806
1807
static unsigned
1808
fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1809
1810
/**
1811
 * BACnetNotificationParameters ::= CHOICE {
1812
 *  change-of-bitstring [0] SEQUENCE {
1813
 *      referenced-bitstring [0] BIT STRING,
1814
 *      status-flags         [1] BACnetStatusFlags
1815
 *      },
1816
 *  change-of-state [1] SEQUENCE {
1817
 *      new-state            [0] BACnetPropertyStatus,
1818
 *      status-flags         [1] BACnetStatusFlags
1819
 *      },
1820
 *  change-of-value [2] SEQUENCE {
1821
 *      new-value            [0] CHOICE {
1822
 *          changed-bits        [0] BIT STRING,
1823
 *          changed-value       [1] REAL
1824
 *          },
1825
 *      status-flags         [1] BACnetStatusFlags
1826
 *      },
1827
 *  command-failure [3] SEQUENCE {
1828
 *      command-value        [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1829
 *      status-flags         [1] BACnetStatusFlags
1830
 *      feedback-value       [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1831
 *      },
1832
 *  floating-limit [4]  SEQUENCE {
1833
 *      reference-value      [0] REAL,
1834
 *      status-flags         [1] BACnetStatusFlags
1835
 *      setpoint-value       [2] REAL,
1836
 *      error-limit          [3] REAL
1837
 *      },
1838
 *  out-of-range [5]    SEQUENCE {
1839
 *      exceeding-value      [0] REAL,
1840
 *      status-flags         [1] BACnetStatusFlags
1841
 *      deadband             [2] REAL,
1842
 *      exceeded-limit       [3] REAL
1843
 *      },
1844
 *  complex-event-type  [6] SEQUENCE OF BACnetPropertyValue,
1845
 * -- complex tag 7 is deprecated
1846
 *  change-of-life-safety [8]   SEQUENCE {
1847
 *      new-state            [0] BACnetLifeSafetyState,
1848
 *      new-mode             [1] BACnetLifeSafetyState
1849
 *      status-flags         [2] BACnetStatusFlags,
1850
 *      operation-expected   [3] BACnetLifeSafetyOperation
1851
 *      },
1852
 *  extended [9]   SEQUENCE {
1853
 *      vendor-id            [0] Unsigned16,
1854
 *      extended-event-type  [1] Unsigned,
1855
 *      parameters           [2] SEQUENCE OF CHOICE {
1856
 *          null                NULL,
1857
 *          real                REAL,
1858
 *          integer             Unsigned,
1859
 *          boolean             BOOLEAN,
1860
 *          double              Double,
1861
 *          octet               OCTET STRING,
1862
 *          bitstring           BIT STRING,
1863
 *          enum                ENUMERATED,
1864
 *          propertyValue       [0] BACnetDeviceObjectPropertyValue
1865
 *          }
1866
 *      },
1867
 *  buffer-ready [10]    SEQUENCE {
1868
 *      buffer-property      [0] BACnetDeviceObjectPropertyReference,
1869
 *      previous-notification[1] Unsigned32,
1870
 *      current-notification [2] BACneUnsigned32tDateTime
1871
 *      },
1872
 *  unsigned-range [11]    SEQUENCE {
1873
 *      exceeding-value      [0] Unsigned,
1874
 *      status-flags         [1] BACnetStatusFlags,
1875
 *      exceeded-limit       [2] Unsigned
1876
 *      },
1877
 * -- context tag 12 is reserved for future addenda
1878
 *  access-event [13]    SEQUENCE {
1879
 *      access-event          [0] BACnetAccessEvent,
1880
 *      status-flags          [1] BACnetStatusFlags,
1881
 *      access-event-tag      [2] Unsigned,
1882
 *      access-event-time     [3] BACnetTimeStamp,
1883
 *      access-credential     [4] BACnetDeviceObjectReference,
1884
 *      authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1885
 *      },
1886
 *  double-out-of-range [14]    SEQUENCE {
1887
 *      exceeding-value      [0] Double,
1888
 *      status-flags         [1] BACnetStatusFlags
1889
 *      deadband             [2] Double,
1890
 *      exceeded-limit       [3] Double
1891
 *      },
1892
 *  signed-out-of-range [15]    SEQUENCE {
1893
 *      exceeding-value      [0] INTEGER,
1894
 *      status-flags         [1] BACnetStatusFlags
1895
 *      deadband             [2] Unsigned,
1896
 *      exceeded-limit       [3] INTEGER
1897
 *      },
1898
 *  unsigned-out-of-range [16]    SEQUENCE {
1899
 *      exceeding-value      [0] Unsigned,
1900
 *      status-flags         [1] BACnetStatusFlags
1901
 *      deadband             [2] Unsigned,
1902
 *      exceeded-limit       [3] Unsigned
1903
 *      },
1904
 *  change-of-characterstring [17]    SEQUENCE {
1905
 *      changed-value        [0] CharacterString,
1906
 *      status-flags         [1] BACnetStatusFlags
1907
 *      alarm-value          [2] CharacterString
1908
 *      },
1909
 *  change-of-status-flags [18]    SEQUENCE {
1910
 *      present-value        [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1911
 *                              -- depends on referenced property
1912
 *      referenced-flags     [1] BACnetStatusFlags
1913
 *      },
1914
 * }
1915
 * @param tvb the tv buffer of the current data
1916
 * @param pinfo the packet info of the current data
1917
 * @param tree the tree to append this item to
1918
 * @param offset the offset in the tvb
1919
 * @return modified offset
1920
 */
1921
static unsigned
1922
fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1923
1924
/**
1925
 * BACnetObjectPropertyReference ::= SEQUENCE {
1926
 *  objectIdentifier    [0] BACnetObjectIdentifier,
1927
 *  propertyIdentifier  [1] BACnetPropertyIdentifier,
1928
 *  propertyArrayIndex  [2] Unsigned OPTIONAL, -- used only with array datatype
1929
 * }
1930
 * @param tvb the tv buffer of the current data
1931
 * @param pinfo the packet info of the current data
1932
 * @param tree the tree to append this item to
1933
 * @param offset the offset in the tvb
1934
 * @return modified offset
1935
 */
1936
static unsigned
1937
fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1938
1939
#if 0
1940
/**
1941
 * BACnetObjectPropertyValue ::= SEQUENCE {
1942
 *      objectIdentifier   [0] BACnetObjectIdentifier,
1943
 *      propertyIdentifier [1] BACnetPropertyIdentifier,
1944
 *      propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1945
 *                                                -- if omitted with an array the entire array is referenced
1946
 *      value              [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1947
 *      priority           [4] Unsigned (1..16) OPTIONAL
1948
 * }
1949
 * @param tvb the tv buffer of the current data
1950
 * @param tree the tree to append this item to
1951
 * @param offset the offset in the tvb
1952
 * @return modified offset
1953
 */
1954
static unsigned
1955
fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
1956
#endif
1957
1958
/**
1959
 * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1960
 * @param tvb the tv buffer of the current data
1961
 * @param pinfo the packet info of the current data
1962
 * @param tree the tree to append this item to
1963
 * @param offset the offset in the tvb
1964
 * @return modified offset
1965
 */
1966
static unsigned
1967
fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1968
1969
static unsigned
1970
fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset, uint8_t list);
1971
1972
/**
1973
 * BACnetPropertyReference ::= SEQUENCE {
1974
 *  propertyIdentifier  [0] BACnetPropertyIdentifier,
1975
 *  propertyArrayIndex  [1] Unsigned OPTIONAL, -- used only with array datatype
1976
 * }
1977
 * @param tvb the tv buffer of the current data
1978
 * @param pinfo the packet info of the current data
1979
 * @param tree the tree to append this item to
1980
 * @param offset the offset in the tvb
1981
 * @return modified offset
1982
 */
1983
static unsigned
1984
fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t list);
1985
1986
static unsigned
1987
fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1988
1989
static unsigned
1990
fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1991
1992
/**
1993
 * BACnetPropertyValue ::= SEQUENCE {
1994
 *      PropertyIdentifier [0] BACnetPropertyIdentifier,
1995
 *      propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1996
 *                                                -- if omitted with an array the entire array is referenced
1997
 *      value              [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1998
 *      priority           [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1999
 * }
2000
 * @param tvb the tv buffer of the current data
2001
 * @param pinfo the packet info of the current data
2002
 * @param tree the tree to append this item to
2003
 * @param offset the offset in the tvb
2004
 * @return modified offset
2005
 */
2006
static unsigned
2007
fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2008
2009
static unsigned
2010
fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset);
2011
2012
/**
2013
 * BACnet Application PDUs chapter 21
2014
 * BACnetRecipient::= CHOICE {
2015
 *  device  [0] BACnetObjectIdentifier
2016
 *  address [1] BACnetAddress
2017
 * }
2018
 * @param tvb the tv buffer of the current data
2019
 * @param pinfo the packet info of the current data
2020
 * @param tree the tree to append this item to
2021
 * @param offset the offset in the tvb
2022
 * @return modified offset
2023
 */
2024
static unsigned
2025
fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2026
2027
/**
2028
 * BACnet Application PDUs chapter 21
2029
 * BACnetRecipientProcess::= SEQUENCE {
2030
 *  recipient   [0] BACnetRecipient
2031
 *  processID   [1] Unsigned32
2032
 * }
2033
 * @param tvb the tv buffer of the current data
2034
 * @param pinfo the packet info of the current data
2035
 * @param tree the tree to append this item to
2036
 * @param offset the offset in the tvb
2037
 * @return modified offset
2038
 */
2039
static unsigned
2040
fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2041
2042
static unsigned
2043
fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2044
2045
#if 0
2046
/**
2047
 * BACnetSessionKey ::= SEQUENCE {
2048
 *  sessionKey  OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
2049
 *  peerAddress BACnetAddress
2050
 * }
2051
 * @param tvb the tv buffer of the current data
2052
 * @param tree the tree to append this item to
2053
 * @param offset the offset in the tvb
2054
 * @return modified offset
2055
 * @todo check if checksum is displayed correctly
2056
 */
2057
static unsigned
2058
fSessionKey(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
2059
#endif
2060
2061
/**
2062
 * BACnetSpecialEvent ::= SEQUENCE {
2063
 *  period      CHOICE {
2064
 *      calendarEntry       [0] BACnetCalendarEntry,
2065
 *      calendarReference    [1] BACnetObjectIdentifier
2066
 *      },
2067
 *      listOfTimeValues    [2] SEQUENCE OF BACnetTimeValue,
2068
 *      eventPriority       [3] Unsigned (1..16)
2069
 * }
2070
 * @param tvb the tv buffer of the current data
2071
 * @param pinfo the packet info of the current data
2072
 * @param tree the tree to append this item to
2073
 * @param offset the offset in the tvb
2074
 * @return modified offset
2075
 */
2076
static unsigned
2077
fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2078
2079
/**
2080
 * BACnetTimeStamp ::= CHOICE {
2081
 *  time            [0] Time,
2082
 *  sequenceNumber  [1] Unsigned (0..65535),
2083
 *  dateTime        [2] BACnetDateTime
2084
 * }
2085
 * @param tvb the tv buffer of the current data
2086
 * @param pinfo the packet info of the current data
2087
 * @param tree the tree to append this item to
2088
 * @param offset the offset in the tvb
2089
 * @param label the label of this item
2090
 * @return modified offset
2091
 */
2092
static unsigned
2093
fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2094
2095
static unsigned
2096
fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2097
2098
/**
2099
 * BACnetTimeValue ::= SEQUENCE {
2100
 *  time    Time,
2101
 *  value   ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2102
 * }
2103
 * @param tvb the tv buffer of the current data
2104
 * @param pinfo the packet info of the current data
2105
 * @param tree the tree to append this item to
2106
 * @param offset the offset in the tvb
2107
 * @return modified offset
2108
 */
2109
static unsigned
2110
fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2111
2112
#if 0
2113
/**
2114
 * BACnetVTSession ::= SEQUENCE {
2115
 *  local-vtSessionID   Unsigned8,
2116
 *  remote-vtSessionID  Unsigned8,
2117
 *  remote-vtAddress    BACnetAddress
2118
 * }
2119
 * @param tvb the tv buffer of the current data
2120
 * @param tree the tree to append this item to
2121
 * @param offset the offset in the tvb
2122
 * @return modified offset
2123
 */
2124
static unsigned
2125
fVTSession(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
2126
#endif
2127
2128
/**
2129
 * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2130
 * -- first octet month (1..12) January = 1, X'FF' = any month
2131
 * -- second octet weekOfMonth where: 1 = days numbered 1-7
2132
 * -- 2 = days numbered 8-14
2133
 * -- 3 = days numbered 15-21
2134
 * -- 4 = days numbered 22-28
2135
 * -- 5 = days numbered 29-31
2136
 * -- 6 = last 7 days of this month
2137
 * -- X'FF' = any week of this month
2138
 * -- third octet dayOfWeek (1..7) where 1 = Monday
2139
 * -- 7 = Sunday
2140
 * -- X'FF' = any day of week
2141
 * @param tvb the tv buffer of the current data
2142
 * @param pinfo the packet info of the current data
2143
 * @param tree the tree to append this item to
2144
 * @param offset the offset in the tvb
2145
 * @return modified offset
2146
 */
2147
static unsigned
2148
fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2149
2150
/**
2151
 * ReadAccessResult ::= SEQUENCE {
2152
 *  objectIdentifier            [0] BACnetObjectIdentifier,
2153
 *  listOfResults               [1] SEQUENCE OF SEQUENCE {
2154
 *      propertyIdentifier      [2] BACnetPropertyIdentifier,
2155
 *      propertyArrayIndex      [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2156
 *      readResult  CHOICE {
2157
 *          propertyValue       [4] ABSTRACT-SYNTAX.&Type,
2158
 *          propertyAccessError [5] Error
2159
 *      }
2160
 *  } OPTIONAL
2161
 * }
2162
 * @param tvb the tv buffer of the current data
2163
 * @param pinfo the packet info of the current data
2164
 * @param tree the tree to append this item to
2165
 * @param offset the offset in the tvb
2166
 * @return modified offset
2167
 */
2168
static unsigned
2169
fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2170
2171
/**
2172
 * ReadAccessSpecification ::= SEQUENCE {
2173
 *  objectIdentifier         [0] BACnetObjectIdentifier,
2174
 *  listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2175
 * }
2176
 * @param tvb the tv buffer of the current data
2177
 * @param pinfo the packet info of the current data
2178
 * @param subtree the subtree to append this item to
2179
 * @param offset the offset in the tvb
2180
 * @return modified offset
2181
 */
2182
static unsigned
2183
fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2184
2185
/**
2186
 * WriteAccessSpecification ::= SEQUENCE {
2187
 *  objectIdentifier [0] BACnetObjectIdentifier,
2188
 *  listOfProperty   [1] SEQUENCE OF BACnetPropertyValue
2189
 * }
2190
 * @param tvb the tv buffer of the current data
2191
 * @param pinfo the packet info of the current data
2192
 * @param subtree the sub tree to append this item to
2193
 * @param offset the offset in the tvb
2194
 * @return modified offset
2195
 */
2196
static unsigned
2197
fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2198
2199
2200
/********************************************************* Helper functions *******************************************/
2201
2202
/**
2203
 * extracts the tag number from the tag header.
2204
 * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2205
 * @param offset the offset in the tvb in actual tvb
2206
 * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2207
 */
2208
static unsigned
2209
fTagNo(tvbuff_t *tvb, unsigned offset);
2210
2211
/**
2212
 * splits Tag Header corresponding to 20.2.1 General Rules For BACnet Tags
2213
 * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2214
 * @param pinfo the packet info of the current data = packet info
2215
 * @param offset the offset in the tvb = offset in actual tvb
2216
 * @return tag_no BACnet 20.2.1.2 Tag Number
2217
 * @return class_tag BACnet 20.2.1.1 Class
2218
 * @return lvt BACnet 20.2.1.3 Length/Value/Type
2219
 * @return offs = length of this header
2220
 */
2221
2222
static unsigned
2223
fTagHeader(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, uint8_t *tag_no, uint8_t* class_tag, uint32_t *lvt);
2224
2225
2226
/**
2227
 * adds processID with max 32Bit unsigned Integer Value to tree
2228
 * @param tvb the tv buffer of the current data
2229
 * @param pinfo the packet info of the current data
2230
 * @param tree the tree to append this item to
2231
 * @param offset the offset in the tvb
2232
 * @return modified offset
2233
 */
2234
static unsigned
2235
fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2236
2237
/**
2238
 * adds present value to the tree
2239
 * @param tvb the tv buffer of the current data
2240
 * @param pinfo the packet info of the current data
2241
 * @param tree the tree to append this item to
2242
 * @param offset the offset in the tvb
2243
 * @param vs enum of string values when applicable
2244
 * @param split_val enum index
2245
 * @param type present value datatype enum
2246
 * @return modified offset
2247
 */
2248
static unsigned
2249
fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const value_string *vs, uint32_t split_val, BacappPresentValueType type);
2250
2251
/**
2252
 * adds event type to the tree
2253
 * @param tvb the tv buffer of the current data
2254
 * @param pinfo the packet info of the current data
2255
 * @param tree the tree to append this item to
2256
 * @param offset the offset in the tvb
2257
 * @return modified offset
2258
 */
2259
static unsigned
2260
fEventType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2261
2262
/**
2263
 * adds notify type to the tree
2264
 * @param tvb the tv buffer of the current data
2265
 * @param pinfo the packet info of the current data
2266
 * @param tree the tree to append this item to
2267
 * @param offset the offset in the tvb
2268
 * @return modified offset
2269
 */
2270
static unsigned
2271
fNotifyType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2272
2273
/**
2274
 * adds next_state with max 32Bit unsigned Integer Value to tree
2275
 * @param tvb the tv buffer of the current data
2276
 * @param pinfo the packet info of the current data
2277
 * @param tree the tree to append this item to
2278
 * @param offset the offset in the tvb
2279
 * @return modified offset
2280
 */
2281
static unsigned
2282
fToState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2283
2284
/**
2285
 * adds from_state with max 32Bit unsigned Integer Value to tree
2286
 * @param tvb the tv buffer of the current data
2287
 * @param pinfo the packet info of the current data
2288
 * @param tree the tree to append this item to
2289
 * @param offset the offset in the tvb
2290
 * @return modified offset
2291
 */
2292
static unsigned
2293
fFromState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2294
2295
/**
2296
 * adds object_name string value to tree
2297
 * @param tvb the tv buffer of the current data
2298
 * @param pinfo the packet info of the current data
2299
 * @param tree the tree to append this item to
2300
 * @param offset the offset in the tvb
2301
 * @return modified offset
2302
 */
2303
static unsigned
2304
fObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2305
2306
/**
2307
 * wrapper function for fCharacterStringBase
2308
 * @param tvb the tv buffer of the current data
2309
 * @param pinfo the packet info of the current data
2310
 * @param tree the tree to append this item to
2311
 * @param offset the offset in the tvb
2312
 * @return modified offset
2313
 */
2314
static unsigned
2315
fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2316
2317
/**
2318
 * adds string value to tree
2319
 * @param tvb the tv buffer of the current data
2320
 * @param pinfo the packet info of the current data
2321
 * @param tree the tree to append this item to
2322
 * @param offset the offset in the tvb
2323
 * @param present_val_dissect exposes string as present_value property
2324
 * @param object_name_dissect exposes string as object_name property
2325
 * @return modified offset
2326
 */
2327
static unsigned
2328
fCharacterStringBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2329
                     bool present_val_dissect, bool object_name_dissect);
2330
2331
/**
2332
 * adds timeSpan with max 32Bit unsigned Integer Value to tree
2333
 * @param tvb the tv buffer of the current data
2334
 * @param pinfo the packet info of the current data
2335
 * @param tree the tree to append this item to
2336
 * @param offset the offset in the tvb
2337
 * @return modified offset
2338
 */
2339
static unsigned
2340
fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2341
2342
/**
2343
 * BACnet Application PDUs chapter 21
2344
 * BACnetPropertyIdentifier::= ENUMERATED {
2345
 *   @see bacapp_property_identifier
2346
 * }
2347
 * @param tvb the tv buffer of the current data
2348
 * @param pinfo the packet info of the current data
2349
 * @param tree the tree to append this item to
2350
 * @param offset the offset in the tvb
2351
 * @return modified offset
2352
 */
2353
static unsigned
2354
fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2355
2356
/**
2357
 * BACnet Application PDUs chapter 21
2358
 * BACnetPropertyArrayIndex::= ENUMERATED {
2359
 *   @see bacapp_property_array_index
2360
 * }
2361
 * @param tvb the tv buffer of the current data
2362
 * @param pinfo the packet info of the current data
2363
 * @param tree the tree to append this item to
2364
 * @param offset the offset in the tvb
2365
 * @return modified offset
2366
 */
2367
static unsigned
2368
fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2369
2370
/**
2371
 * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2372
 *  objectIdentifier        [0] BACnetObjectIdentifier,
2373
 *  eventState              [1] BACnetEventState,
2374
 *  acknowledgedTransitions [2] BACnetEventTransitionBits,
2375
 *  eventTimeStamps         [3] SEQUENCE SIZE (3) OF BACnetTimeStamps,
2376
 *  notifyType              [4] BACnetNotifyType,
2377
 *  eventEnable             [5] BACnetEventTransitionBits,
2378
 *  eventPriorities         [6] SEQUENCE SIZE (3) OF Unsigned
2379
 * }
2380
 * @param tvb the tv buffer of the current data
2381
 * @param pinfo the packet info of the current data
2382
 * @param tree the tree to append this item to
2383
 * @param offset the offset in the tvb
2384
 * @return modified offset
2385
 */
2386
static unsigned
2387
flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2388
2389
/**
2390
 * SelectionCriteria ::= SEQUENCE {
2391
 *  propertyIdentifier [0] BACnetPropertyIdentifier,
2392
 *  propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2393
 *  relationSpecifier  [2] ENUMERATED { bacapp_relationSpecifier },
2394
 *  comparisonValue    [3] ABSTRACT-SYNTAX.&Type
2395
 * }
2396
 * @param tvb the tv buffer of the current data
2397
 * @param pinfo the packet info of the current data
2398
 * @param tree the tree to append this item to
2399
 * @param offset the offset in the tvb
2400
 * @return modified offset
2401
 */
2402
static unsigned
2403
fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2404
2405
/**
2406
 * objectSelectionCriteria ::= SEQUENCE {
2407
 *  selectionLogic          [0] ENUMERATED { bacapp_selectionLogic },
2408
 *  listOfSelectionCriteria [1] SelectionCriteria
2409
 * }
2410
 * @param tvb the tv buffer of the current data
2411
 * @param pinfo the packet info of the current data
2412
 * @param subtree the sub tree to append this item to
2413
 * @param offset the offset in the tvb
2414
 * @return modified offset
2415
 */
2416
static unsigned
2417
fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2418
2419
/**
2420
 * BACnet-Error ::= SEQUENCE {
2421
 *    error-class ENUMERATED {},
2422
 *    error-code  ENUMERATED {}
2423
 *    }
2424
 * }
2425
 * @param tvb the tv buffer of the current data
2426
 * @param pinfo the packet info of the current data
2427
 * @param tree the tree to append this item to
2428
 * @param offset the offset in the tvb
2429
 * @return modified offset
2430
 */
2431
static unsigned
2432
fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2433
2434
/**
2435
 * Adds error-code from BACnet-Error to the tree
2436
 * @param tvb the tv buffer of the current data
2437
 * @param pinfo the packet info of the current data
2438
 * @param tree the tree to append this item to
2439
 * @param offset the offset in the tvb
2440
 * @return modified offset
2441
 */
2442
static unsigned
2443
fErrorCode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2444
2445
/**
2446
 * Adds error-class from BACnet-Error to the tree
2447
 * @param tvb the tv buffer of the current data
2448
 * @param pinfo the packet info of the current data
2449
 * @param tree the tree to append this item to
2450
 * @param offset the offset in the tvb
2451
 * @return modified offset
2452
 */
2453
static unsigned
2454
fErrorClass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2455
2456
/**
2457
 * Generic handler for context tagged values.  Mostly for handling
2458
 * vendor-defined properties and services.
2459
 * @param tvb the tv buffer of the current data
2460
 * @param pinfo the packet info of the current data
2461
 * @param tree the tree to append this item to
2462
 * @param offset the offset in the tvb
2463
 * @return modified offset
2464
 * @todo beautify this ugly construct
2465
 */
2466
static unsigned
2467
fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2468
2469
/**
2470
 * realizes some ABSTRACT-SYNTAX.&Type
2471
 * @param tvb the tv buffer of the current data
2472
 * @param pinfo the packet info of the current data
2473
 * @param tree the tree to append this item to
2474
 * @param offset the offset in the tvb
2475
 * @return modified offset
2476
 * @todo beautify this ugly construct
2477
 */
2478
static unsigned
2479
fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2480
2481
2482
static unsigned
2483
fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2484
    const value_string *src);
2485
2486
static unsigned
2487
fBitStringTagVSBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2488
    const value_string *src, bool present_val_dissect);
2489
2490
static unsigned
2491
fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2492
2493
static unsigned
2494
fEventNotificationSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2495
2496
static unsigned
2497
fLightingCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2498
2499
static unsigned
2500
fColorCommand(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable);
2501
2502
static unsigned
2503
fXyColor(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable);
2504
2505
static unsigned
2506
fTimerStateChangeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2507
2508
static unsigned
2509
fHostNPort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2510
2511
static unsigned
2512
fBDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2513
2514
static unsigned
2515
fFDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2516
2517
static unsigned
2518
fRouterEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2519
2520
static unsigned
2521
fVMACEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2522
2523
static unsigned
2524
fValueSource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2525
2526
static unsigned
2527
fAssignedLandingCalls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2528
2529
static unsigned
2530
fLandingCallStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2531
2532
static unsigned
2533
fLandingDoorStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2534
2535
static unsigned
2536
fCOVMultipleSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2537
2538
static unsigned
2539
fNameValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2540
2541
static unsigned
2542
fNameValueCollection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2543
2544
static unsigned
2545
fAuthenticationFactor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2546
2547
static unsigned
2548
fAuthenticationFactorFormat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2549
2550
static unsigned
2551
fAuthenticationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2552
2553
static unsigned
2554
fAccessRule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2555
2556
static unsigned
2557
fChannelValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2558
2559
static unsigned
2560
fPropertyAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2561
2562
static unsigned
2563
fNetworkSecurityPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2564
2565
static unsigned
2566
fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2567
2568
static unsigned
2569
fAuditLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2570
2571
static unsigned
2572
fStageLimitValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2573
2574
static unsigned
2575
fObjectSelector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2576
2577
static unsigned
2578
fDeviceAddressProxyTableEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2579
2580
static unsigned
2581
fAccessToken(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2582
2583
static unsigned
2584
fAuthorizationConstraint(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2585
2586
static unsigned
2587
fAuthorizationScope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2588
2589
static unsigned
2590
fAuthenticationClient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2591
2592
static unsigned
2593
fAuthorizationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2594
2595
static unsigned
2596
fAuthenticationPeer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2597
2598
static unsigned
2599
fAuthenticationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2600
2601
static unsigned
2602
fAuthorizationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2603
2604
static unsigned
2605
fAuthorizationScopeDescription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2606
2607
static unsigned
2608
fAuthorizationServer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2609
2610
static unsigned
2611
fAuthorizationStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2612
2613
2614
/**
2615
 * register_bacapp
2616
 */
2617
void
2618
proto_register_bacapp(void);
2619
2620
/* <<<< formerly bacapp.h */
2621
2622
/* reassembly table for segmented messages */
2623
static reassembly_table msg_reassembly_table;
2624
2625
/* some necessary forward function prototypes */
2626
static unsigned
2627
fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
2628
    const char *label, const value_string *vs);
2629
2630
static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
2631
static const char ASHRAE_Reserved_Fmt[] = "(%d) Reserved for Use by ASHRAE";
2632
static const char Vendor_Proprietary_Fmt[] = "(%d) Vendor Proprietary Value";
2633
2634
static const value_string
2635
BACnetTypeName[] = {
2636
    { 0, "Confirmed-REQ"},
2637
    { 1, "Unconfirmed-REQ"},
2638
    { 2, "Simple-ACK"},
2639
    { 3, "Complex-ACK"},
2640
    { 4, "Segment-ACK"},
2641
    { 5, "Error"},
2642
    { 6, "Reject"},
2643
    { 7, "Abort"},
2644
    { 0, NULL }
2645
};
2646
2647
static const true_false_string segments_follow = {
2648
    "Segmented Request",
2649
    "Unsegmented Request"
2650
};
2651
2652
static const true_false_string more_follow = {
2653
    "More Segments Follow",
2654
    "No More Segments Follow"
2655
};
2656
2657
static const true_false_string segmented_accept = {
2658
    "Segmented Response accepted",
2659
    "Segmented Response not accepted"
2660
};
2661
2662
static const true_false_string
2663
BACnetTagClass = {
2664
    "Context Specific Tag",
2665
    "Application Tag"
2666
};
2667
2668
static const value_string
2669
BACnetMaxSegmentsAccepted [] = {
2670
    { 0,  "Unspecified"},
2671
    { 1,  "2 segments"},
2672
    { 2,  "4 segments"},
2673
    { 3,  "8 segments"},
2674
    { 4, "16 segments"},
2675
    { 5, "32 segments"},
2676
    { 6, "64 segments"},
2677
    { 7, "Greater than 64 segments"},
2678
    { 0, NULL }
2679
};
2680
2681
static const value_string
2682
BACnetMaxAPDULengthAccepted [] = {
2683
    {  0, "Up to MinimumMessageSize (50 octets)"},
2684
    {  1, "Up to 128 octets"},
2685
    {  2, "Up to 206 octets (fits in a LonTalk frame)"},
2686
    {  3, "Up to 480 octets (fits in an ARCNET frame)"},
2687
    {  4, "Up to 1024 octets"},
2688
    {  5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2689
    {  6, "reserved by ASHRAE"},
2690
    {  7, "reserved by ASHRAE"},
2691
    {  8, "reserved by ASHRAE"},
2692
    {  9, "reserved by ASHRAE"},
2693
    { 10, "reserved by ASHRAE"},
2694
    { 11, "reserved by ASHRAE"},
2695
    { 12, "reserved by ASHRAE"},
2696
    { 13, "reserved by ASHRAE"},
2697
    { 14, "reserved by ASHRAE"},
2698
    { 15, "reserved by ASHRAE"},
2699
    { 0, NULL}
2700
};
2701
2702
static const value_string
2703
BACnetRejectReason [] = {
2704
    { 0, "other"},
2705
    { 1, "buffer-overflow"},
2706
    { 2, "inconsistent-parameters"},
2707
    { 3, "invalid-parameter-data-type"},
2708
    { 4, "invalid-tag"},
2709
    { 5, "missing-required-parameter"},
2710
    { 6, "parameter-out-of-range"},
2711
    { 7, "too-many-arguments"},
2712
    { 8, "undefined-enumeration"},
2713
    { 9, "unrecognized-service"},
2714
    { 0, NULL}
2715
};
2716
2717
static const value_string
2718
BACnetRestartReason [] = {
2719
    { 0, "unknown"},
2720
    { 1, "coldstart"},
2721
    { 2, "warmstart"},
2722
    { 3, "detected-power-lost"},
2723
    { 4, "detected-powered-off"},
2724
    { 5, "hardware-watchdog"},
2725
    { 6, "software-watchdog"},
2726
    { 7, "suspended"},
2727
    { 8, "activate-changes"},
2728
    { 0, NULL}
2729
};
2730
2731
static const value_string
2732
BACnetApplicationTagNumber [] = {
2733
    {  0, "Null"},
2734
    {  1, "Boolean"},
2735
    {  2, "Unsigned Integer"},
2736
    {  3, "Signed Integer (2's complement notation)"},
2737
    {  4, "Real (ANSI/IEE-754 floating point)"},
2738
    {  5, "Double (ANSI/IEE-754 double precision floating point)"},
2739
    {  6, "Octet String"},
2740
    {  7, "Character String"},
2741
    {  8, "Bit String"},
2742
    {  9, "Enumerated"},
2743
    { 10, "Date"},
2744
    { 11, "Time"},
2745
    { 12, "BACnetObjectIdentifier"},
2746
    { 13, "reserved by ASHRAE"},
2747
    { 14, "reserved by ASHRAE"},
2748
    { 15, "reserved by ASHRAE"},
2749
    { 0,  NULL}
2750
};
2751
2752
static const value_string
2753
BACnetAction [] = {
2754
    { 0, "direct"},
2755
    { 1, "reverse"},
2756
    { 0, NULL}
2757
};
2758
2759
static const value_string
2760
BACnetAccessEvent [] = {
2761
    {  0, "none"},
2762
    {  1, "granted"},
2763
    {  2, "muster"},
2764
    {  3, "passback-detected"},
2765
    {  4, "duress"},
2766
    {  5, "trace"},
2767
    {  6, "lockout-max-attempts"},
2768
    {  7, "lockout-other"},
2769
    {  8, "lockout-relinquished"},
2770
    {  9, "lockout-by-higher-priority"},
2771
    { 10, "out-of-service"},
2772
    { 11, "out-of-service-relinquished"},
2773
    { 12, "accompaniment-by"},
2774
    { 13, "authentication-factor-read"},
2775
    { 14, "authorization-delayed"},
2776
    { 15, "verification-required"},
2777
    /* Enumerated values 128-511 are used for events
2778
     * which indicate that access has been denied. */
2779
    { 128, "denied-deny-all"},
2780
    { 129, "denied-unknown-credential"},
2781
    { 130, "denied-authentication-unavailable"},
2782
    { 131, "denied-authentication-factor-timeout"},
2783
    { 132, "denied-incorrect-authentication-factor"},
2784
    { 133, "denied-zone-no-access-rights"},
2785
    { 134, "denied-point-no-access-rights"},
2786
    { 135, "denied-no-access-rights"},
2787
    { 136, "denied-out-of-time-range"},
2788
    { 137, "denied-threat-level"},
2789
    { 138, "denied-passback"},
2790
    { 139, "denied-unexpected-location-usage"},
2791
    { 140, "denied-max-attempts"},
2792
    { 141, "denied-lower-occupancy-limit"},
2793
    { 142, "denied-upper-occupancy-limit"},
2794
    { 143, "denied-authentication-factor-lost"},
2795
    { 144, "denied-authentication-factor-stolen"},
2796
    { 145, "denied-authentication-factor-damaged"},
2797
    { 146, "denied-authentication-factor-destroyed"},
2798
    { 147, "denied-authentication-factor-disabled"},
2799
    { 148, "denied-authentication-factor-error"},
2800
    { 149, "denied-credential-unassigned"},
2801
    { 150, "denied-credential-not-provisioned"},
2802
    { 151, "denied-credential-not-yet-active"},
2803
    { 152, "denied-credential-expired"},
2804
    { 153, "denied-credential-manual-disable"},
2805
    { 154, "denied-credential-lockout"},
2806
    { 155, "denied-credential-max-days"},
2807
    { 156, "denied-credential-max-uses"},
2808
    { 157, "denied-credential-inactivity"},
2809
    { 158, "denied-credential-disabled"},
2810
    { 159, "denied-no-accompaniment"},
2811
    { 160, "denied-incorrect-accompaniment"},
2812
    { 161, "denied-lockout"},
2813
    { 162, "denied-verification-failed"},
2814
    { 163, "denied-verification-timeout"},
2815
    { 164, "denied-other"},
2816
    { 0,  NULL}
2817
/* Enumerated values 0-512 are reserved for definition by ASHRAE.
2818
   Enumerated values 512-65535 may be used by others subject to
2819
   procedures and constraints described in Clause 23. */
2820
};
2821
2822
static const value_string
2823
BACnetAccessZoneOccupancyState[] = {
2824
    { 0, "normal"},
2825
    { 1, "below-lower-limit"},
2826
    { 2, "at-lower-limit"},
2827
    { 3, "at-upper-limit"},
2828
    { 4, "above-upper-limit"},
2829
    { 5, "disabled"},
2830
    { 6, "not-supported"},
2831
    { 0,  NULL}
2832
};
2833
2834
static const value_string
2835
BACnetAccessPassbackMode[] = {
2836
    { 0, "passback-off" },
2837
    { 1, "hard-passback" },
2838
    { 2, "soft-passback" },
2839
    { 0, NULL }
2840
};
2841
2842
static const value_string
2843
BACnetAccessCredentialDisableReason[] = {
2844
    { 0, "disabled" },
2845
    { 1, "disabled-needs-provisioning" },
2846
    { 2, "disabled-unassigned" },
2847
    { 3, "disabled-not-yet-active" },
2848
    { 4, "disabled-expired" },
2849
    { 5, "disabled-lockout" },
2850
    { 6, "disabled-max-days" },
2851
    { 7, "disabled-max-uses" },
2852
    { 8, "disabled-inactivity" },
2853
    { 9, "disabled-manual" },
2854
    { 0, NULL }
2855
};
2856
2857
static const value_string
2858
BACnetAccessUserType[] = {
2859
    { 0, "asset" },
2860
    { 1, "group" },
2861
    { 2, "person" },
2862
    { 0, NULL }
2863
};
2864
2865
static const value_string
2866
BACnetWriteStatus[] = {
2867
    { 0, "idle" },
2868
    { 1, "in-progress" },
2869
    { 2, "successful" },
2870
    { 3, "failed" },
2871
    { 0, NULL }
2872
};
2873
2874
static const value_string
2875
BACnetLightingTransition[] = {
2876
    { 0, "none" },
2877
    { 1, "fade" },
2878
    { 2, "ramp" },
2879
    { 0, NULL }
2880
};
2881
2882
static const value_string
2883
BACnetSecurityLevel[] = {
2884
    { 0, "incapable" },
2885
    { 1, "plain" },
2886
    { 2, "signed" },
2887
    { 3, "encrypted" },
2888
    { 4, "signed-end-to-end" },
2889
    { 5, "encrypted-end-to-end" },
2890
    { 0, NULL }
2891
};
2892
2893
static const value_string
2894
BACnetAccessCredentialDisable[] = {
2895
    { 0, "none" },
2896
    { 1, "disable" },
2897
    { 2, "disable-manual" },
2898
    { 3, "disable-lockout" },
2899
    { 0, NULL }
2900
};
2901
2902
static const value_string
2903
BACnetAuthenticationStatus[] = {
2904
    { 0, "not-ready" },
2905
    { 1, "ready" },
2906
    { 2, "disabled" },
2907
    { 3, "waiting-for-authentication-factor" },
2908
    { 4, "waiting-for-accompaniment" },
2909
    { 5, "waiting-for-verification" },
2910
    { 6, "in-progress" },
2911
    { 0, NULL }
2912
};
2913
2914
static const value_string
2915
BACnetAuthorizationMode[] = {
2916
    { 0, "authorize" },
2917
    { 1, "grant-active" },
2918
    { 2, "deny-all" },
2919
    { 3, "verification-required" },
2920
    { 4, "authorization-delayed" },
2921
    { 5, "none" },
2922
    { 0, NULL }
2923
};
2924
2925
static const value_string
2926
BACnetAuthorizationExemption[] = {
2927
    { 0, "passback" },
2928
    { 1, "occupancy-check" },
2929
    { 2, "access-rights" },
2930
    { 3, "lockout" },
2931
    { 4, "deny" },
2932
    { 5, "verification" },
2933
    { 6, "authorization-delay" },
2934
    { 0, NULL }
2935
};
2936
2937
static const value_string
2938
BACnetLightingInProgress[] = {
2939
    { 0, "idle" },
2940
    { 1, "fade-active" },
2941
    { 2, "ramp-active" },
2942
    { 3, "not-controlled" },
2943
    { 4, "other" },
2944
    { 5, "trim-active" },
2945
    { 0, NULL }
2946
};
2947
2948
static const value_string
2949
BACnetColorOperationInProgress[] = {
2950
    { 0, "idle" },
2951
    { 1, "fade-active" },
2952
    { 2, "ramp-active" },
2953
    { 3, "not-controlled" },
2954
    { 4, "other" },
2955
    { 0, NULL }
2956
};
2957
2958
static const value_string
2959
BACnetColorTransition[] = {
2960
    { 0, "none" },
2961
    { 1, "fade" },
2962
    { 2, "ramp" },
2963
    { 0, NULL }
2964
};
2965
2966
static const value_string
2967
BACnetBinaryLightingPV[] = {
2968
    { 0, "off" },
2969
    { 1, "on" },
2970
    { 2, "warn" },
2971
    { 3, "warn-off" },
2972
    { 4, "warn-relinquish" },
2973
    { 5, "stop" },
2974
    { 6, "toggle" },
2975
    { 0, NULL }
2976
};
2977
2978
static const value_string
2979
BACnetBackupState[] = {
2980
    { 0, "idle"},
2981
    { 1, "preparing-for-backup"},
2982
    { 2, "preparing-for-restore"},
2983
    { 3, "performing-a-backup"},
2984
    { 4, "performing-a-restore"},
2985
    { 5, "backup-failure"},
2986
    { 6, "restore-failure"},
2987
    { 0,  NULL}
2988
};
2989
2990
static const value_string
2991
BACnetAcknowledgedTransitions[] = {
2992
    { 0, "to-offnormal" },
2993
    { 1, "to-fault" },
2994
    { 2, "to-normal" },
2995
    { 0, NULL }
2996
};
2997
2998
static const value_string
2999
BACnetFileAccessMethod [] = {
3000
    { 0, "record-access"},
3001
    { 1, "stream-access"},
3002
    { 0, NULL}
3003
};
3004
3005
/* For some reason, BACnet defines the choice parameter
3006
   in the file read and write services backwards from the
3007
   BACnetFileAccessMethod enumeration.
3008
*/
3009
static const value_string
3010
BACnetFileAccessOption [] = {
3011
    { 0, "stream access"},
3012
    { 1, "record access"},
3013
    { 0, NULL}
3014
};
3015
3016
static const value_string
3017
BACnetFileStartOption [] = {
3018
    { 0, "File Start Position: "},
3019
    { 1, "File Start Record: "},
3020
    { 0, NULL}
3021
};
3022
3023
static const value_string
3024
BacnetFileRequestedCount [] = {
3025
    { 0, "Requested Octet Count: "},
3026
    { 1, "Requested Record Count: "},
3027
    { 0, NULL}
3028
};
3029
3030
static const value_string
3031
BACnetFileWriteInfo [] = {
3032
    { 0, "File Data: "},
3033
    { 1, "Record Count: "},
3034
    { 0, NULL}
3035
};
3036
3037
static const value_string
3038
BACnetAbortReason [] = {
3039
    { 0, "other"},
3040
    { 1, "buffer-overflow"},
3041
    { 2, "invalid-apdu-in-this-state"},
3042
    { 3, "preempted-by-higher-priority-task"},
3043
    { 4, "segmentation-not-supported"},
3044
    { 5, "security-error"},
3045
    { 6, "insufficient-security"},
3046
    { 7, "window-size-out-of-range"},
3047
    { 8, "application-exceeded-reply-time"},
3048
    { 9, "out-of-resources"},
3049
    { 10, "tsm-timeout"},
3050
    { 11, "apdu-too-long"},
3051
    { 0, NULL}
3052
};
3053
3054
static const value_string
3055
BACnetIpMode [] = {
3056
    { 0, "normal"},
3057
    { 1, "foreign"},
3058
    { 2, "bbmd"},
3059
    { 0,  NULL}
3060
};
3061
3062
static const value_string
3063
BACnetNetworkPortCommand [] = {
3064
    { 0, "idle"},
3065
    { 1, "discard-changes"},
3066
    { 2, "renew-fd-registration"},
3067
    { 3, "restart-slave-discovery"},
3068
    { 4, "renew-dhcp"},
3069
    { 5, "restart-autonegotiation"},
3070
    { 6, "disconnect"},
3071
    { 7, "restart-port"},
3072
    { 8, "generate-csr-file"},
3073
    { 9, "validate-changes"},
3074
    { 10, "restart-device-discovery"},
3075
    { 0,  NULL}
3076
};
3077
3078
static const value_string
3079
BACnetNetworkNumberQuality [] = {
3080
    { 0, "unknown"},
3081
    { 1, "learned"},
3082
    { 2, "learned-configured"},
3083
    { 3, "configured"},
3084
    { 0,  NULL}
3085
};
3086
3087
static const value_string
3088
BACnetNetworkType [] = {
3089
    { 0, "ethernet" },
3090
    { 1, "arcnet" },
3091
    { 2, "mstp" },
3092
    { 3, "ptp" },
3093
    { 4, "lontalk" },
3094
    { 5, "bacnet-ipv4" },
3095
    { 6, "zigbee" },
3096
    { 7, "virtual" },
3097
    { 8, "non-bacnet" },
3098
    { 9, "bacnet-ipv6" },
3099
    {10, "serial" },
3100
    {11, "secure-connect" },
3101
    { 0,  NULL}
3102
};
3103
3104
static const value_string
3105
BACnetSCConnectionState [] = {
3106
    { 0, "not-connected" },
3107
    { 1, "connected" },
3108
    { 2, "disconnected-with-errors" },
3109
    { 3, "failed-to-connect" },
3110
    { 0,  NULL}
3111
};
3112
3113
static const value_string
3114
BACnetSCHubConnectorState [] = {
3115
    { 0, "no-hub-connection" },
3116
    { 1, "connected-to-primary" },
3117
    { 2, "connected-to-failover" },
3118
    { 0,  NULL}
3119
};
3120
3121
static const value_string
3122
BACnetLifeSafetyMode [] = {
3123
    {  0, "off"},
3124
    {  1, "on"},
3125
    {  2, "test"},
3126
    {  3, "manned"},
3127
    {  4, "unmanned"},
3128
    {  5, "armed"},
3129
    {  6, "disarmed"},
3130
    {  7, "prearmed"},
3131
    {  8, "slow"},
3132
    {  9, "fast"},
3133
    { 10, "disconnected"},
3134
    { 11, "enabled"},
3135
    { 12, "disabled"},
3136
    { 13, "atomic-release-disabled"},
3137
    { 14, "default"},
3138
    { 15, "activated-oeo-alarm"},
3139
    { 16, "activated-oeo-evacuate"},
3140
    { 17, "activated-oeo-phase1-recall"},
3141
    { 18, "activated-oeo-unavailable"},
3142
    { 19, "deactivated"},
3143
    { 0,  NULL}
3144
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
3145
   Enumerated values 256-65535 may be used by others subject to
3146
   procedures and constraints described in Clause 23. */
3147
};
3148
3149
static const value_string
3150
BACnetLifeSafetyOperation [] = {
3151
    { 0, "none"},
3152
    { 1, "silence"},
3153
    { 2, "silence-audible"},
3154
    { 3, "silence-visual"},
3155
    { 4, "reset"},
3156
    { 5, "reset-alarm"},
3157
    { 6, "reset-fault"},
3158
    { 7, "unsilence"},
3159
    { 8, "unsilence-audible"},
3160
    { 9, "unsilence-visual"},
3161
    { 0, NULL}
3162
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
3163
   Enumerated values 64-65535 may be used by others subject to
3164
   procedures and constraints described in Clause 23. */
3165
};
3166
3167
static const value_string
3168
BACnetLifeSafetyState [] = {
3169
    {  0, "quiet"},
3170
    {  1, "pre-alarm"},
3171
    {  2, "alarm"},
3172
    {  3, "fault"},
3173
    {  4, "fault-pre-alarm"},
3174
    {  5, "fault-alarm"},
3175
    {  6, "not-ready"},
3176
    {  7, "active"},
3177
    {  8, "tamper"},
3178
    {  9, "test-alarm"},
3179
    { 10, "test-active"},
3180
    { 11, "test-fault"},
3181
    { 12, "test-fault-alarm"},
3182
    { 13, "holdup"},
3183
    { 14, "duress"},
3184
    { 15, "tamper-alarm"},
3185
    { 16, "abnormal"},
3186
    { 17, "emergency-power"},
3187
    { 18, "delayed"},
3188
    { 19, "blocked"},
3189
    { 20, "local-alarm"},
3190
    { 21, "general-alarm"},
3191
    { 22, "supervisory"},
3192
    { 23, "test-supervisory"},
3193
    { 24, "non-default-mode"},
3194
    { 25, "oeo-unavailable"},
3195
    { 26, "oeo-alarm"},
3196
    { 27, "oeo-phase1-recall"},
3197
    { 28, "oeo-evacuate"},
3198
    { 29, "oeo-unaffected"},
3199
    { 30, "test-oeo-unavailable"},
3200
    { 31, "test-oeo-alarm"},
3201
    { 32, "test-oeo-phase1-recall"},
3202
    { 33, "test-oeo-evacuate"},
3203
    { 34, "test-oeo-unaffected"},
3204
    { 0,  NULL}
3205
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
3206
   Enumerated values 256-65535 may be used by others subject to
3207
   procedures and constraints described in Clause 23. */
3208
};
3209
3210
static const value_string
3211
BACnetLimitEnable[] = {
3212
    { 0, "low-limit-enable" },
3213
    { 1, "high-limit-enable" },
3214
    { 0, NULL }
3215
};
3216
3217
static const value_string
3218
BACnetTimerState [] = {
3219
    { 0, "idle"},
3220
    { 1, "running"},
3221
    { 2, "expired"},
3222
    { 0, NULL}
3223
};
3224
3225
static const value_string
3226
BACnetTimerTransition [] = {
3227
    { 0, "none"},
3228
    { 1, "idle-to-running"},
3229
    { 2, "running-to-idle"},
3230
    { 3, "running-to-running"},
3231
    { 4, "running-to-expired"},
3232
    { 5, "forced-to-expired"},
3233
    { 6, "expired-to-idle"},
3234
    { 7, "expired-to-running"},
3235
    { 0, NULL}
3236
};
3237
3238
static const value_string
3239
BACnetEscalatorFault [] = {
3240
    { 0, "controller-fault"},
3241
    { 1, "drive-and-motor-fault"},
3242
    { 2, "mechanical-component-fault"},
3243
    { 3, "overspeed-fault"},
3244
    { 4, "power-supply-fault"},
3245
    { 5, "safety-device-fault"},
3246
    { 6, "controller-supply-fault"},
3247
    { 7, "drive-temperature-exceeded"},
3248
    { 8, "comb-plate-fault"},
3249
    { 0, NULL}
3250
};
3251
3252
static const value_string
3253
BACnetEscalatorMode [] = {
3254
    { 0, "unknown"},
3255
    { 1, "stop"},
3256
    { 2, "up"},
3257
    { 3, "down"},
3258
    { 4, "inspection"},
3259
    { 5, "out-of-service"},
3260
    { 0, NULL}
3261
};
3262
3263
static const value_string
3264
BACnetEscalatorOperationDirection [] = {
3265
    { 0, "unknown"},
3266
    { 1, "stopped"},
3267
    { 2, "up-rated-speed"},
3268
    { 3, "up-reduced-speed"},
3269
    { 4, "down-rated-speed"},
3270
    { 5, "down-reduced-speed"},
3271
    { 0, NULL}
3272
};
3273
3274
static const value_string
3275
BACnetLiftCarDirection [] = {
3276
    { 0, "unknown"},
3277
    { 1, "none"},
3278
    { 2, "stopped"},
3279
    { 3, "up"},
3280
    { 4, "down"},
3281
    { 5, "up-and-down"},
3282
    { 0, NULL}
3283
};
3284
3285
static const value_string
3286
BACnetLiftCarDoorCommand [] = {
3287
    { 0, "none"},
3288
    { 1, "open"},
3289
    { 2, "close"},
3290
    { 0, NULL}
3291
};
3292
3293
static const value_string
3294
BACnetLiftCarDriveStatus [] = {
3295
    { 0, "unknown"},
3296
    { 1, "stationary"},
3297
    { 2, "braking"},
3298
    { 3, "accelerate"},
3299
    { 4, "decelerate"},
3300
    { 5, "rated-speed"},
3301
    { 6, "single-floor-jump"},
3302
    { 7, "two-floor-jump"},
3303
    { 8, "three-floor-jump"},
3304
    { 9, "multi-floor-jump"},
3305
    { 0, NULL}
3306
};
3307
3308
static const value_string
3309
BACnetLiftCarMode [] = {
3310
    { 0, "unknown"},
3311
    { 1, "normal"},
3312
    { 2, "vip"},
3313
    { 3, "homing"},
3314
    { 4, "parking"},
3315
    { 5, "attendant-control"},
3316
    { 6, "firefighter-control"},
3317
    { 7, "emergency-power"},
3318
    { 8, "inspection"},
3319
    { 9, "cabinet-recall"},
3320
    { 10, "earthquake-operation"},
3321
    { 11, "fire-operation"},
3322
    { 12, "out-of-service"},
3323
    { 13, "occupant-evacuation"},
3324
    { 0, NULL}
3325
};
3326
3327
static const value_string
3328
BACnetLiftFault [] = {
3329
    { 0, "controller-fault"},
3330
    { 1, "drive-and-motor-fault"},
3331
    { 2, "governor-and-safety-gear-fault"},
3332
    { 3, "lift-shaft-device-fault"},
3333
    { 4, "power-supply-fault"},
3334
    { 5, "safety-interlock-fault"},
3335
    { 6, "door-closing-fault"},
3336
    { 7, "door-opening-fault"},
3337
    { 8, "car-stopped-outside-landing-zone"},
3338
    { 9, "call-button-stuck"},
3339
    { 10, "start-failure"},
3340
    { 11, "controller-supply-fault"},
3341
    { 12, "self-test-failure"},
3342
    { 13, "runtime-limit-exceeded"},
3343
    { 14, "position-lost"},
3344
    { 15, "drive-temperature-exceeded"},
3345
    { 16, "load-measurement-fault"},
3346
    { 0, NULL}
3347
};
3348
3349
static const value_string
3350
BACnetLiftGroupMode [] = {
3351
    { 0, "unknown"},
3352
    { 1, "normal"},
3353
    { 2, "down-peak"},
3354
    { 3, "two-way"},
3355
    { 4, "four-way"},
3356
    { 5, "emergency-power"},
3357
    { 6, "up-peak"},
3358
    { 0, NULL}
3359
};
3360
3361
static const value_string
3362
BACnetProtocolLevel [] = {
3363
    { 0, "physical"},
3364
    { 1, "protocol"},
3365
    { 2, "bacnet-application"},
3366
    { 3, "non-bacnet-application"},
3367
    { 0, NULL}
3368
};
3369
3370
static const value_string
3371
BACnetRelationship [] = {
3372
    { 0, "unknown"},
3373
    { 1, "default"},
3374
    { 2, "contains"},
3375
    { 3, "contained-by"},
3376
    { 4, "uses"},
3377
    { 5, "used-by"},
3378
    { 6, "commands"},
3379
    { 7, "commanded-by"},
3380
    { 8, "adjusts"},
3381
    { 9, "adjusted-by"},
3382
    { 10, "ingress"},
3383
    { 11, "egress"},
3384
    { 12, "supplies-air"},
3385
    { 13, "receives-air"},
3386
    { 14, "supplies-hot-air"},
3387
    { 15, "receives-hot-air"},
3388
    { 16, "supplies-cool-air"},
3389
    { 17, "receives-cool-air"},
3390
    { 18, "supplies-power"},
3391
    { 19, "receives-power"},
3392
    { 20, "supplies-gas"},
3393
    { 21, "receives-gas"},
3394
    { 22, "supplies-water"},
3395
    { 23, "receives-water"},
3396
    { 24, "supplies-hot-water"},
3397
    { 25, "receives-hot-water"},
3398
    { 26, "supplies-cool-water"},
3399
    { 27, "receives-cool-water"},
3400
    { 28, "supplies-steam"},
3401
    { 29, "receives-steam"},
3402
    { 0, NULL}
3403
};
3404
3405
static const value_string
3406
BACnetLightingOperation[] = {
3407
    { 0, "none" },
3408
    { 1, "fade-to" },
3409
    { 2, "ramp-to" },
3410
    { 3, "step-up" },
3411
    { 4, "step-down" },
3412
    { 5, "step-on" },
3413
    { 6, "step-off" },
3414
    { 7, "warn" },
3415
    { 8, "warn-off" },
3416
    { 9, "warn-relinquish" },
3417
    { 10, "stop" },
3418
    { 11, "restore-on" },
3419
    { 12, "default-on" },
3420
    { 13, "toggle-restor" },
3421
    { 14, "toggle-default" },
3422
    { 0, NULL }
3423
};
3424
3425
static const value_string
3426
BACnetColorOperation[] = {
3427
    { 0, "none" },
3428
    { 1, "fade-to-color" },
3429
    { 2, "fade-to-cct" },
3430
    { 3, "ramp-to-cct" },
3431
    { 4, "step-up-cct" },
3432
    { 5, "step-down-cct" },
3433
    { 6, "stop" },
3434
    { 0, NULL }
3435
};
3436
3437
static const value_string
3438
BACnetConfirmedServiceChoice[] = {
3439
    {  0, "acknowledgeAlarm"},
3440
    {  1, "confirmedCOVNotification"},
3441
    {  2, "confirmedEventNotification"},
3442
    {  3, "getAlarmSummary"},
3443
    {  4, "getEnrollmentSummary"},
3444
    {  5, "subscribeCOV"},
3445
    {  6, "atomicReadFile"},
3446
    {  7, "atomicWriteFile"},
3447
    {  8, "addListElement"},
3448
    {  9, "removeListElement"},
3449
    { 10, "createObject"},
3450
    { 11, "deleteObject"},
3451
    { 12, "readProperty"},
3452
    { 13, "readPropertyConditional"},
3453
    { 14, "readPropertyMultiple"},
3454
    { 15, "writeProperty"},
3455
    { 16, "writePropertyMultiple"},
3456
    { 17, "deviceCommunicationControl"},
3457
    { 18, "confirmedPrivateTransfer"},
3458
    { 19, "confirmedTextMessage"},
3459
    { 20, "reinitializeDevice"},
3460
    { 21, "vtOpen"},
3461
    { 22, "vtClose"},
3462
    { 23, "vtData"},
3463
    { 24, "authenticate"},
3464
    { 25, "requestKey"},
3465
    { 26, "readRange"},
3466
    { 27, "lifeSafetyOperation"},
3467
    { 28, "subscribeCOVProperty"},
3468
    { 29, "getEventInformation"},
3469
    { 30, "subscribeCovPropertyMultiple"},
3470
    { 31, "confirmedCovNotificationMultiple"},
3471
    { 32, "confirmedAuditNotification"},
3472
    { 33, "auditLogQuery"},
3473
    { 34, "aurthRequest" },
3474
    { 0,  NULL}
3475
};
3476
3477
static const value_string
3478
BACnetReliability [] = {
3479
    {  0, "no-fault-detected"},
3480
    {  1, "no-sensor"},
3481
    {  2, "over-range"},
3482
    {  3, "under-range"},
3483
    {  4, "open-loop"},
3484
    {  5, "shorted-loop"},
3485
    {  6, "no-output"},
3486
    {  7, "unreliable-other"},
3487
    {  8, "process-error"},
3488
    {  9, "multi-state-fault"},
3489
    { 10, "configuration-error"},
3490
    { 11, "reserved for a future addendum"},
3491
    { 12, "communication-failure"},
3492
    { 13, "member-fault"},
3493
    { 14, "monitored-object-fault" },
3494
    { 15, "tripped"},
3495
    { 16, "lamp-failure"},
3496
    { 17, "activation-failure"},
3497
    { 18, "renew-dhcp-failure"},
3498
    { 19, "renew-fd-registration-failure"},
3499
    { 20, "restart-auto-negotiation-failure"},
3500
    { 21, "restart-failure"},
3501
    { 22, "proprietary-command-failure"},
3502
    { 23, "faults-listed"},
3503
    { 24, "referenced-object-fault"},
3504
    { 25, "multi-state-out-of-range"},
3505
    { 0,  NULL}
3506
};
3507
3508
static const value_string
3509
BACnetRouterStatus[] = {
3510
    { 0, "available" },
3511
    { 1, "busy" },
3512
    { 2, "disconnected" },
3513
    { 0, NULL }
3514
};
3515
3516
static const value_string
3517
BACnetUnconfirmedServiceChoice [] = {
3518
    { 0, "i-Am"},
3519
    { 1, "i-Have"},
3520
    { 2, "unconfirmedCOVNotification"},
3521
    { 3, "unconfirmedEventNotification"},
3522
    { 4, "unconfirmedPrivateTransfer"},
3523
    { 5, "unconfirmedTextMessage"},
3524
    { 6, "timeSynchronization"},
3525
    { 7, "who-Has"},
3526
    { 8, "who-Is"},
3527
    { 9, "utcTimeSynchronization"},
3528
    { 10, "writeGroup"},
3529
    { 11, "unconfirmedCovNotificationMultiple"},
3530
    { 12, "unconfirmedAuditNotification"},
3531
    { 13, "who-am-I" },
3532
    { 14, "you-are" },
3533
    { 0, NULL}
3534
};
3535
3536
static const value_string
3537
BACnetObjectType [] = {
3538
    {  0, "analog-input"},
3539
    {  1, "analog-output"},
3540
    {  2, "analog-value"},
3541
    {  3, "binary-input"},
3542
    {  4, "binary-output"},
3543
    {  5, "binary-value"},
3544
    {  6, "calendar"},
3545
    {  7, "command"},
3546
    {  8, "device"},
3547
    {  9, "event-enrollment"},
3548
    { 10, "file"},
3549
    { 11, "group"},
3550
    { 12, "loop"},
3551
    { 13, "multi-state-input"},
3552
    { 14, "multi-state-output"},
3553
    { 15, "notification-class"},
3554
    { 16, "program"},
3555
    { 17, "schedule"},
3556
    { 18, "averaging"},
3557
    { 19, "multi-state-value"},
3558
    { 20, "trend-log"},
3559
    { 21, "life-safety-point"},
3560
    { 22, "life-safety-zone"},
3561
    { 23, "accumulator"},
3562
    { 24, "pulse-converter"},
3563
    { 25, "event-log"},
3564
    { 26, "global-group"},
3565
    { 27, "trend-log-multiple"},
3566
    { 28, "load-control"},
3567
    { 29, "structured-view"},
3568
    { 30, "access-door"},     /* 30-37 added with addanda 135-2008j */
3569
    { 31, "timer"},
3570
    { 32, "access-credential"},
3571
    { 33, "access-point"},
3572
    { 34, "access-rights"},
3573
    { 35, "access-user"},
3574
    { 36, "access-zone"},
3575
    { 37, "credential-data-input"},
3576
    { 38, "network-security"},
3577
    { 39, "bitstring-value"},     /* 39-50 added with addenda 135-2008w */
3578
    { 40, "characterstring-value"},
3579
    { 41, "date-pattern-value"},
3580
    { 42, "date-value"},
3581
    { 43, "datetime-pattern-value"},
3582
    { 44, "datetime-value"},
3583
    { 45, "integer-value"},
3584
    { 46, "large-analog-value"},
3585
    { 47, "octetstring-value"},
3586
    { 48, "positive-integer-value"},
3587
    { 49, "time-pattern-value"},
3588
    { 50, "time-value"},
3589
    { 51, "notification-forwarder"},
3590
    { 52, "alert-enrollment"},
3591
    { 53, "channel"},
3592
    { 54, "lighting-output"},
3593
    { 55, "binary-lighting-output"},
3594
    { 56, "network-port"},
3595
    { 57, "elevator-group"},
3596
    { 58, "escalator"},
3597
    { 59, "lift"},
3598
    { 60, "staging"},
3599
    { 61, "audit-log"},
3600
    { 62, "audit-reporter"},
3601
    { 63, "color"},
3602
    { 64, "color-temperature"},
3603
    { 0,  NULL}
3604
/* Enumerated values 0-127 are reserved for definition by ASHRAE.
3605
   Enumerated values 128-1023 may be used by others subject to
3606
   the procedures and constraints described in Clause 23. */
3607
};
3608
static value_string_ext BACnetObjectType_ext = VALUE_STRING_EXT_INIT(BACnetObjectType);
3609
3610
static const value_string
3611
BACnetObjectTypeAbbrev[] = {
3612
    {  0, "AI" },
3613
    {  1, "AO" },
3614
    {  2, "AV" },
3615
    {  3, "BI" },
3616
    {  4, "BO" },
3617
    {  5, "BV" },
3618
    {  6, "CAL" },
3619
    {  7, "CMD" },
3620
    {  8, "DEV" },
3621
    {  9, "EE" },
3622
    { 10, "FV" },
3623
    { 11, "G" },
3624
    { 12, "LP" },
3625
    { 13, "MSI" },
3626
    { 14, "MSO" },
3627
    { 15, "NC" },
3628
    { 16, "PROG" },
3629
    { 17, "SCH" },
3630
    { 18, "AVG" },
3631
    { 19, "MSVV" },
3632
    { 20, "TLV" },
3633
    { 21, "LSP" },
3634
    { 22, "LSZV" },
3635
    { 23, "ACM" },
3636
    { 24, "PC" },
3637
    { 25, "EL" },
3638
    { 26, "GG" },
3639
    { 27, "TLM" },
3640
    { 28, "LCV" },
3641
    { 29, "SV" },
3642
    { 30, "ACD" },
3643
    { 32, "ACC" },
3644
    { 33, "ACP" },
3645
    { 34, "ACR" },
3646
    { 35, "ACU" },
3647
    { 36, "ACZ" },
3648
    { 37, "CDI" },
3649
    { 38, "NS" },
3650
    { 39, "BSV" },
3651
    { 40, "CSV" },
3652
    { 41, "DPV" },
3653
    { 42, "DV" },
3654
    { 43, "DTPV" },
3655
    { 44, "DTV" },
3656
    { 45, "IVV" },
3657
    { 46, "LAV" },
3658
    { 47, "OSV" },
3659
    { 48, "UV" },
3660
    { 49, "TPV" },
3661
    { 50, "TVV" },
3662
    { 51, "NFV" },
3663
    { 52, "AE" },
3664
    { 53, "CH" },
3665
    { 54, "LO" },
3666
    { 55, "BLO" },
3667
    { 56, "NP" },
3668
    { 57, "EG" },
3669
    { 58, "ES" },
3670
    { 59, "L" },
3671
    { 60, "STG" },
3672
    { 61, "ALV" },
3673
    { 62, "AR" },
3674
    { 63, "CO" },
3675
    { 64, "CT" },
3676
    {  0, NULL }
3677
};
3678
3679
static const value_string
3680
BACnetEngineeringUnits [] = {
3681
    {   0, "Sq Meters"},
3682
    {   1, "Sq Feet"},
3683
    {   2, "Milliamperes"},
3684
    {   3, "Amperes"},
3685
    {   4, "Ohms"},
3686
    {   5, "Volts"},
3687
    {   6, "Kilovolts"},
3688
    {   7, "Megavolts"},
3689
    {   8, "Volt Amperes"},
3690
    {   9, "Kilovolt Amperes"},
3691
    {  10, "Megavolt Amperes"},
3692
    {  11, "Volt Amperes Reactive"},
3693
    {  12, "Kilovolt Amperes Reactive"},
3694
    {  13, "Megavolt Amperes Reactive"},
3695
    {  14, "Degrees Phase"},
3696
    {  15, "Power Factor"},
3697
    {  16, "Joules"},
3698
    {  17, "Kilojoules"},
3699
    {  18, "Watt Hours"},
3700
    {  19, "Kilowatt Hours"},
3701
    {  20, "BTUs"},
3702
    {  21, "Therms"},
3703
    {  22, "Ton Hours"},
3704
    {  23, "Joules Per Kg Dry Air"},
3705
    {  24, "BTUs Per Pound Dry Air"},
3706
    {  25, "Cycles Per Hour"},
3707
    {  26, "Cycles Per Minute"},
3708
    {  27, "Hertz"},
3709
    {  28, "Grams Of Water Per Kilogram Dry Air"},
3710
    {  29, "Relative Humidity"},
3711
    {  30, "Millimeters"},
3712
    {  31, "Meters"},
3713
    {  32, "Inches"},
3714
    {  33, "Feed"},
3715
    {  34, "Watts Per Sq Foot"},
3716
    {  35, "Watts Per Sq meter"},
3717
    {  36, "Lumens"},
3718
    {  37, "Lux"},
3719
    {  38, "Foot Candles"},
3720
    {  39, "Kilograms"},
3721
    {  40, "Pounds Mass"},
3722
    {  41, "Tons"},
3723
    {  42, "Kgs per Second"},
3724
    {  43, "Kgs Per Minute"},
3725
    {  44, "Kgs Per Hour"},
3726
    {  45, "Pounds Mass Per Minute"},
3727
    {  46, "Pounds Mass Per Hour"},
3728
    {  47, "Watt"},
3729
    {  48, "Kilowatts"},
3730
    {  49, "Megawatts"},
3731
    {  50, "BTUs Per Hour"},
3732
    {  51, "Horsepower"},
3733
    {  52, "Tons Refrigeration"},
3734
    {  53, "Pascals"},
3735
    {  54, "Kilopascals"},
3736
    {  55, "Bars"},
3737
    {  56, "Pounds Force Per Square Inch"},
3738
    {  57, "Centimeters Of Water"},
3739
    {  58, "Inches Of Water"},
3740
    {  59, "Millimeters Of Mercury"},
3741
    {  60, "Centimeters Of Mercury"},
3742
    {  61, "Inches Of Mercury"},
3743
    {  62, "Degrees Celsius"},
3744
    {  63, "Degrees Kelvin"},
3745
    {  64, "Degrees Fahrenheit"},
3746
    {  65, "Degree Days Celsius"},
3747
    {  66, "Degree Days Fahrenheit"},
3748
    {  67, "Years"},
3749
    {  68, "Months"},
3750
    {  69, "Weeks"},
3751
    {  70, "Days"},
3752
    {  71, "Hours"},
3753
    {  72, "Minutes"},
3754
    {  73, "Seconds"},
3755
    {  74, "Meters Per Second"},
3756
    {  75, "Kilometers Per Hour"},
3757
    {  76, "Feed Per Second"},
3758
    {  77, "Feet Per Minute"},
3759
    {  78, "Miles Per Hour"},
3760
    {  79, "Cubic Feet"},
3761
    {  80, "Cubic Meters"},
3762
    {  81, "Imperial Gallons"},
3763
    {  82, "Liters"},
3764
    {  83, "US Gallons"},
3765
    {  84, "Cubic Feet Per Minute"},
3766
    {  85, "Cubic Meters Per Second"},
3767
    {  86, "Imperial Gallons Per Minute"},
3768
    {  87, "Liters Per Second"},
3769
    {  88, "Liters Per Minute"},
3770
    {  89, "US Gallons Per Minute"},
3771
    {  90, "Degrees Angular"},
3772
    {  91, "Degrees Celsius Per Hour"},
3773
    {  92, "Degrees Celsius Per Minute"},
3774
    {  93, "Degrees Fahrenheit Per Hour"},
3775
    {  94, "Degrees Fahrenheit Per Minute"},
3776
    {  95, "No Units"},
3777
    {  96, "Parts Per Million"},
3778
    {  97, "Parts Per Billion"},
3779
    {  98, "Percent"},
3780
    {  99, "Percent Per Second"},
3781
    { 100, "Per Minute"},
3782
    { 101, "Per Second"},
3783
    { 102, "Psi Per Degree Fahrenheit"},
3784
    { 103, "Radians"},
3785
    { 104, "Revolutions Per Min"},
3786
    { 105, "Currency1"},
3787
    { 106, "Currency2"},
3788
    { 107, "Currency3"},
3789
    { 108, "Currency4"},
3790
    { 109, "Currency5"},
3791
    { 110, "Currency6"},
3792
    { 111, "Currency7"},
3793
    { 112, "Currency8"},
3794
    { 113, "Currency9"},
3795
    { 114, "Currency10"},
3796
    { 115, "Sq Inches"},
3797
    { 116, "Sq Centimeters"},
3798
    { 117, "BTUs Per Pound"},
3799
    { 118, "Centimeters"},
3800
    { 119, "Pounds Mass Per Second"},
3801
    { 120, "Delta Degrees Fahrenheit"},
3802
    { 121, "Delta Degrees Kelvin"},
3803
    { 122, "Kilohms"},
3804
    { 123, "Megohms"},
3805
    { 124, "Millivolts"},
3806
    { 125, "Kilojoules Per Kg"},
3807
    { 126, "Megajoules"},
3808
    { 127, "Joules Per Degree Kelvin"},
3809
    { 128, "Joules Per Kg Degree Kelvin"},
3810
    { 129, "Kilohertz"},
3811
    { 130, "Megahertz"},
3812
    { 131, "Per Hour"},
3813
    { 132, "Milliwatts"},
3814
    { 133, "Hectopascals"},
3815
    { 134, "Millibars"},
3816
    { 135, "Cubic Meters Per Hour"},
3817
    { 136, "Liters Per Hour"},
3818
    { 137, "KWatt Hours Per Square Meter"},
3819
    { 138, "KWatt Hours Per Square Foot"},
3820
    { 139, "Megajoules Per Square Meter"},
3821
    { 140, "Megajoules Per Square Foot"},
3822
    { 141, "Watts Per Sq Meter Degree Kelvin"},
3823
    { 142, "Cubic Feet Per Second"},
3824
    { 143, "Percent Obstruction Per Foot"},
3825
    { 144, "Percent Obstruction Per Meter"},
3826
    { 145, "milliohms"},
3827
    { 146, "megawatt-hours"},
3828
    { 147, "kilo-btus"},
3829
    { 148, "mega-btus"},
3830
    { 149, "kilojoules-per-kilogram-dry-air"},
3831
    { 150, "megajoules-per-kilogram-dry-air"},
3832
    { 151, "kilojoules-per-degree-Kelvin"},
3833
    { 152, "megajoules-per-degree-Kelvin"},
3834
    { 153, "newton"},
3835
    { 154, "grams-per-second"},
3836
    { 155, "grams-per-minute"},
3837
    { 156, "tons-per-hour"},
3838
    { 157, "kilo-btus-per-hour"},
3839
    { 158, "hundredths-seconds"},
3840
    { 159, "milliseconds"},
3841
    { 160, "newton-meters"},
3842
    { 161, "millimeters-per-second"},
3843
    { 162, "millimeters-per-minute"},
3844
    { 163, "meters-per-minute"},
3845
    { 164, "meters-per-hour"},
3846
    { 165, "cubic-meters-per-minute"},
3847
    { 166, "meters-per-second-per-second"},
3848
    { 167, "amperes-per-meter"},
3849
    { 168, "amperes-per-square-meter"},
3850
    { 169, "ampere-square-meters"},
3851
    { 170, "farads"},
3852
    { 171, "henrys"},
3853
    { 172, "ohm-meters"},
3854
    { 173, "siemens"},
3855
    { 174, "siemens-per-meter"},
3856
    { 175, "teslas"},
3857
    { 176, "volts-per-degree-Kelvin"},
3858
    { 177, "volts-per-meter"},
3859
    { 178, "webers"},
3860
    { 179, "candelas"},
3861
    { 180, "candelas-per-square-meter"},
3862
    { 181, "degrees-Kelvin-per-hour"},
3863
    { 182, "degrees-Kelvin-per-minute"},
3864
    { 183, "joule-seconds"},
3865
    { 184, "radians-per-second"},
3866
    { 185, "square-meters-per-Newton"},
3867
    { 186, "kilograms-per-cubic-meter"},
3868
    { 187, "newton-seconds"},
3869
    { 188, "newtons-per-meter"},
3870
    { 189, "watts-per-meter-per-degree-Kelvin"},
3871
    { 190, "micro-siemens"},
3872
    { 191, "cubic-feet-per-hour"},
3873
    { 192, "us-gallons-per-hour"},
3874
    { 193, "kilometers"},
3875
    { 194, "micrometers"},
3876
    { 195, "grams"},
3877
    { 196, "milligrams"},
3878
    { 197, "milliliters"},
3879
    { 198, "milliliters-per-second"},
3880
    { 199, "decibels"},
3881
    { 200, "decibels-millivolt"},
3882
    { 201, "decibels-volt"},
3883
    { 202, "millisiemens"},
3884
    { 203, "watt-hours-reactive"},
3885
    { 204, "kilowatt-hours-reactive"},
3886
    { 205, "megawatt-hours-reactive"},
3887
    { 206, "millimeters-of-water"},
3888
    { 207, "per-mille"},
3889
    { 208, "grams-per-gram"},
3890
    { 209, "kilograms-per-kilogram"},
3891
    { 210, "grams-per-kilogram"},
3892
    { 211, "milligrams-per-gram"},
3893
    { 212, "milligrams-per-kilogram"},
3894
    { 213, "grams-per-milliliter"},
3895
    { 214, "grams-per-liter"},
3896
    { 215, "milligrams-per-liter"},
3897
    { 216, "micrograms-per-liter"},
3898
    { 217, "grams-per-cubic-meter"},
3899
    { 218, "milligrams-per-cubic-meter"},
3900
    { 219, "micrograms-per-cubic-meter"},
3901
    { 220, "nanograms-per-cubic-meter"},
3902
    { 221, "grams-per-cubic-centimeter"},
3903
    { 222, "becquerels"},
3904
    { 223, "kilobecquerels"},
3905
    { 224, "megabecquerels"},
3906
    { 225, "gray"},
3907
    { 226, "milligray"},
3908
    { 227, "microgray"},
3909
    { 228, "sieverts"},
3910
    { 229, "millisieverts"},
3911
    { 230, "microsieverts"},
3912
    { 231, "microsieverts-per-hour"},
3913
    { 232, "decibels-a"},
3914
    { 233, "nephelometric-turbidity-unit"},
3915
    { 234, "pH"},
3916
    { 235, "grams-per-square-meter"},
3917
    { 236, "minutes-per-degree-kelvin"},
3918
    { 237, "ohm-meter-squared-per-meter"},
3919
    { 238, "ampere-seconds"},
3920
    { 239, "volt-ampere-hours"},
3921
    { 240, "kilovolt-ampere-hours"},
3922
    { 241, "megavolt-ampere-hours"},
3923
    { 242, "volt-ampere-hours-reactive"},
3924
    { 243, "kilovolt-ampere-hours-reactive"},
3925
    { 244, "megavolt-ampere-hours-reactive"},
3926
    { 245, "volt-square-hours"},
3927
    { 246, "ampere-square-hours"},
3928
    { 247, "joule-per-hours"},
3929
    { 248, "cubic-feet-per-day"},
3930
    { 249, "cubic-meters-per-day"},
3931
    { 250, "watt-hours-per-cubic-meter"},
3932
    { 251, "joules-per-cubic-meter"},
3933
    { 252, "mole-percent"},
3934
    { 253, "pascal-seconds"},
3935
    { 254, "million-standard-cubic-feet-per-minute"},
3936
    { 255, "unassigned-unit-value-255"},
3937
    { 47808, "standard-cubic-feet-per-day"},
3938
    { 47809, "million-standard-cubic-feet-per-day"},
3939
    { 47810, "thousand-cubic-feet-per-day"},
3940
    { 47811, "thousand-standard-cubic-feet-per-day"},
3941
    { 47812, "pounds-mass-per-day"},
3942
    { 47813, "reserved-unit-47813"},
3943
    { 47814, "millirems"},
3944
    { 47815, "millirems-per-hour"},
3945
    { 47816, "degrees-lovibond"},
3946
    { 47817, "alcohol-by-volume"},
3947
    { 47818, "international-bittering-units"},
3948
    { 47819, "european-bitterness-units"},
3949
    { 47820, "degrees-plato"},
3950
    { 47821, "specific-gravity"},
3951
    { 47822, "european-brewing-convention"},
3952
    { 0,   NULL}
3953
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
3954
   Enumerated values 256-65535 may be used by others subject to
3955
   the procedures and constraints described in Clause 23. */
3956
};
3957
3958
static const value_string
3959
BACnetErrorCode [] = {
3960
    {   0, "other"},
3961
    {   1, "authentication-failed"},
3962
    {   2, "configuration-in-progress"},
3963
    {   3, "device-busy"},
3964
    {   4, "dynamic-creation-not-supported"},
3965
    {   5, "file-access-denied"},
3966
    {   6, "incompatible-security-levels"},
3967
    {   7, "inconsistent-parameters"},
3968
    {   8, "inconsistent-selection-criterion"},
3969
    {   9, "invalid-data-type"},
3970
    {  10, "invalid-file-access-method"},
3971
    {  11, "invalid-file-start-position"},
3972
    {  12, "invalid-operator-name"},
3973
    {  13, "invalid-parameter-data-type"},
3974
    {  14, "invalid-time-stamp"},
3975
    {  15, "key-generation-error"},
3976
    {  16, "missing-required-parameter"},
3977
    {  17, "no-objects-of-specified-type"},
3978
    {  18, "no-space-for-object"},
3979
    {  19, "no-space-to-add-list-element"},
3980
    {  20, "no-space-to-write-property"},
3981
    {  21, "no-vt-sessions-available"},
3982
    {  22, "property-is-not-a-list"},
3983
    {  23, "object-deletion-not-permitted"},
3984
    {  24, "object-identifier-already-exists"},
3985
    {  25, "operational-problem"},
3986
    {  26, "password-failure"},
3987
    {  27, "read-access-denied"},
3988
    {  28, "security-not-supported"},
3989
    {  29, "service-request-denied"},
3990
    {  30, "timeout"},
3991
    {  31, "unknown-object"},
3992
    {  32, "unknown-property"},
3993
    {  33, "removed enumeration"},
3994
    {  34, "unknown-vt-class"},
3995
    {  35, "unknown-vt-session"},
3996
    {  36, "unsupported-object-type"},
3997
    {  37, "value-out-of-range"},
3998
    {  38, "vt-session-already-closed"},
3999
    {  39, "vt-session-termination-failure"},
4000
    {  40, "write-access-denied"},
4001
    {  41, "character-set-not-supported"},
4002
    {  42, "invalid-array-index"},
4003
    {  43, "cov-subscription-failed"},
4004
    {  44, "not-cov-property"},
4005
    {  45, "optional-functionality-not-supported"},
4006
    {  46, "invalid-configuration-data"},
4007
    {  47, "datatype-not-supported"},
4008
    {  48, "duplicate-name"},
4009
    {  49, "duplicate-object-id"},
4010
    {  50, "property-is-not-an-array"},
4011
    {  51, "abort - buffer - overflow" },
4012
    {  52, "abort - invalid - apdu - in - this - state" },
4013
    {  53, "abort - preempted - by - higher - priority - task" },
4014
    {  54, "abort - segmentation - not - supported" },
4015
    {  55, "abort - proprietary" },
4016
    {  56, "abort - other" },
4017
    {  57, "invalid - tag" },
4018
    {  58, "network - down" },
4019
    {  59, "reject - buffer - overflow" },
4020
    {  60, "reject - inconsistent - parameters" },
4021
    {  61, "reject - invalid - parameter - data - type" },
4022
    {  62, "reject - invalid - tag" },
4023
    {  63, "reject - missing - required - parameter" },
4024
    {  64, "reject - parameter - out - of - range" },
4025
    {  65, "reject - too - many - arguments" },
4026
    {  66, "reject - undefined - enumeration" },
4027
    {  67, "reject - unrecognized - service" },
4028
    {  68, "reject - proprietary" },
4029
    {  69, "reject - other" },
4030
    {  70, "unknown - device" },
4031
    {  71, "unknown - route" },
4032
    {  72, "value - not - initialized" },
4033
    {  73, "invalid-event-state"},
4034
    {  74, "no-alarm-configured"},
4035
    {  75, "log-buffer-full"},
4036
    {  76, "logged-value-purged"},
4037
    {  77, "no-property-specified"},
4038
    {  78, "not-configured-for-triggered-logging"},
4039
    {  79, "unknown-subscription"},
4040
    {  80, "parameter-out-of-range"},
4041
    {  81, "list-element-not-found"},
4042
    {  82, "busy"},
4043
    {  83, "communication-disabled"},
4044
    {  84, "success"},
4045
    {  85, "access-denied"},
4046
    {  86, "bad-destination-address"},
4047
    {  87, "bad-destination-device-id"},
4048
    {  88, "bad-signature"},
4049
    {  89, "bad-source-address"},
4050
    {  90, "bad-timestamp"},
4051
    {  91, "cannot-use-key"},
4052
    {  92, "cannot-verify-message-id"},
4053
    {  93, "correct-key-revision"},
4054
    {  94, "destination-device-id-required"},
4055
    {  95, "duplicate-message"},
4056
    {  96, "encryption-not-configured"},
4057
    {  97, "encryption-required"},
4058
    {  98, "incorrect-key"},
4059
    {  99, "invalid-key-data"},
4060
    { 100, "key-update-in-progress"},
4061
    { 101, "malformed-message"},
4062
    { 102, "not-key-server"},
4063
    { 103, "security-not-configured"},
4064
    { 104, "source-security-required"},
4065
    { 105, "too-many-keys"},
4066
    { 106, "unknown-authentication-type"},
4067
    { 107, "unknown-key"},
4068
    { 108, "unknown-key-revision"},
4069
    { 109, "unknown-source-message"},
4070
    { 110, "not-router-to-dnet"},
4071
    { 111, "router-busy"},
4072
    { 112, "unknown-network-message"},
4073
    { 113, "message-too-long"},
4074
    { 114, "security-error"},
4075
    { 115, "addressing-error"},
4076
    { 116, "write-bdt-failed"},
4077
    { 117, "read-bdt-failed"},
4078
    { 118, "register-foreign-device-failed"},
4079
    { 119, "read-fdt-failed"},
4080
    { 120, "delete-fdt-entry-failed"},
4081
    { 121, "distribute-broadcast-failed"},
4082
    { 122, "unknown-file-size"},
4083
    { 123, "abort-apdu-too-long"},
4084
    { 124, "abort-application-exceeded-reply-time"},
4085
    { 125, "abort-out-of-resources"},
4086
    { 126, "abort-tsm-timeout"},
4087
    { 127, "abort-window-size-out-of-range"},
4088
    { 128, "file-full"},
4089
    { 129, "inconsistent-configuration"},
4090
    { 130, "inconsistent-object-type"},
4091
    { 131, "internal-error"},
4092
    { 132, "not-configured"},
4093
    { 133, "out-of-memory"},
4094
    { 134, "value-too-long"},
4095
    { 135, "abort-insufficient-security"},
4096
    { 136, "abort-security-error"},
4097
    { 137, "duplicate-entry"},
4098
    { 138, "invalid-value-in-this-state"},
4099
    { 139, "invalid-operation-in-this-state"},
4100
    { 140, "list-item-not-numbered"},
4101
    { 141, "list-item-not-timestamped"},
4102
    { 142, "invalid-data-encoding"},
4103
    { 143, "bvlc-function-unknown"},
4104
    { 144, "bvlc-proprietary-function-unknown"},
4105
    { 145, "header-encoding-error"},
4106
    { 146, "header-not-understood"},
4107
    { 147, "message-incomplete"},
4108
    { 148, "not-a-bacnet-sc-hub"},
4109
    { 149, "payload-expected"},
4110
    { 150, "unexpected-data"},
4111
    { 151, "node-duplicate-vmac"},
4112
    { 152, "http-unexpected-response-code"},
4113
    { 153, "http-no-upgrade"},
4114
    { 154, "http-resource-not-local"},
4115
    { 155, "http-proxy-authentication-failed"},
4116
    { 156, "http-response-timeout"},
4117
    { 157, "http-response-syntax-error"},
4118
    { 158, "http-response-value-error"},
4119
    { 159, "http-response-missing-header"},
4120
    { 160, "http-websocket-header-error"},
4121
    { 161, "http-upgrade-required"},
4122
    { 162, "http-upgrade-error"},
4123
    { 163, "http-temporary-unavailable"},
4124
    { 164, "http-not-a-server"},
4125
    { 165, "http-error"},
4126
    { 166, "websocket-scheme-not-supported"},
4127
    { 167, "websocket-unknown-control-message"},
4128
    { 168, "websocket-close-error"},
4129
    { 169, "websocket-closed-by-peer"},
4130
    { 170, "websocket-endpoint-leaves"},
4131
    { 171, "websocket-protocol-error"},
4132
    { 172, "websocket-data-not-accepted"},
4133
    { 173, "websocket-closed-abnormally"},
4134
    { 174, "websocket-data-inconsistent"},
4135
    { 175, "websocket-data-against-policy"},
4136
    { 176, "websocket-frame-too-long"},
4137
    { 177, "websocket-extension-missing"},
4138
    { 178, "websocket-request-unavailable"},
4139
    { 179, "websocket-error"},
4140
    { 180, "tls-client-certificate-error"},
4141
    { 181, "tls-server-certificate-error"},
4142
    { 182, "tls-client-authentication-failed"},
4143
    { 183, "tls-server-authentication-failed"},
4144
    { 184, "tls-client-certificate-expired"},
4145
    { 185, "tls-server-certificate-expired"},
4146
    { 186, "tls-client-certificate-revoked"},
4147
    { 187, "tls-server-certificate-revoked"},
4148
    { 188, "tls-error"},
4149
    { 189, "dns-unavailable"},
4150
    { 190, "dns-name-resolution-failed"},
4151
    { 191, "dns-resolver-failure"},
4152
    { 192, "dns-error"},
4153
    { 193, "tcp-connect-timeout"},
4154
    { 194, "tcp-connection-refused"},
4155
    { 195, "tcp-closed-by-local"},
4156
    { 196, "tcp-closed-other"},
4157
    { 197, "tcp-error"},
4158
    { 198, "ip-address-not-reachable"},
4159
    { 199, "ip-error"},
4160
    { 200, "certificate-expired"},
4161
    { 201, "certificate-invalid"},
4162
    { 202, "certificate-malformed"},
4163
    { 203, "certificate-revoked"},
4164
    { 204, "unknown-key"},
4165
    { 205, "referenced-port-in-error"},
4166
    { 206, "not-enabled"},
4167
    { 207, "adjust-scope-required"},
4168
    { 208, "auth-scope-required"},
4169
    { 209, "bind-scope-required"},
4170
    { 210, "config-scope-required"},
4171
    { 211, "control-scope-required"},
4172
    { 212, "extended-scope-required"},
4173
    { 213, "incorrect-client"},
4174
    { 214, "install-scope-required"},
4175
    { 215, "insufficient-scope"},
4176
    { 216, "no-default-scope"},
4177
    { 217, "no-policy"},
4178
    { 218, "revoked-token"},
4179
    { 219, "override-scope-required"},
4180
    { 220, "inactive-token"},
4181
    { 221, "unknown-audience"},
4182
    { 222, "unknown-client"},
4183
    { 223, "unknown-scope"},
4184
    { 224, "view-scope-required"},
4185
    { 225, "incorrect-audience"},
4186
    { 226, "incorrect-client-origin"},
4187
    { 227, "invalid-array-size"},
4188
    { 228, "incorrect-issuer"},
4189
    { 229, "invalid-token"},
4190
    { 0,   NULL}
4191
/* Enumerated values 0-255 are reserved for definition by ASHRAE.
4192
   Enumerated values 256-65535 may be used by others subject to the
4193
   procedures and constraints described in Clause 23. */
4194
};
4195
static value_string_ext BACnetErrorCode_ext = VALUE_STRING_EXT_INIT(BACnetErrorCode);
4196
4197
static const value_string
4198
BACnetPropertyIdentifier [] = {
4199
    {   0, "acked-transition"},
4200
    {   1, "ack-required"},
4201
    {   2, "action"},
4202
    {   3, "action-text"},
4203
    {   4, "active-text"},
4204
    {   5, "active-vt-session"},
4205
    {   6, "alarm-value"},
4206
    {   7, "alarm-values"},
4207
    {   8, "all"},
4208
    {   9, "all-writes-successful"},
4209
    {  10, "apdu-segment-timeout"},
4210
    {  11, "apdu-timeout"},
4211
    {  12, "application-software-version"},
4212
    {  13, "archive"},
4213
    {  14, "bias"},
4214
    {  15, "change-of-state-count"},
4215
    {  16, "change-of-state-time"},
4216
    {  17, "notification-class"},
4217
    {  18, "the property in this place was deleted"},
4218
    {  19, "controlled-variable-reference"},
4219
    {  20, "controlled-variable-units"},
4220
    {  21, "controlled-variable-value"},
4221
    {  22, "cov-increment"},
4222
    {  23, "datelist"},
4223
    {  24, "daylights-savings-status"},
4224
    {  25, "deadband"},
4225
    {  26, "derivative-constant"},
4226
    {  27, "derivative-constant-units"},
4227
    {  28, "description"},
4228
    {  29, "description-of-halt"},
4229
    {  30, "device-address-binding"},
4230
    {  31, "device-type"},
4231
    {  32, "effective-period"},
4232
    {  33, "elapsed-active-time"},
4233
    {  34, "error-limit"},
4234
    {  35, "event-enable"},
4235
    {  36, "event-state"},
4236
    {  37, "event-type"},
4237
    {  38, "exception-schedule"},
4238
    {  39, "fault-values"},
4239
    {  40, "feedback-value"},
4240
    {  41, "file-access-method"},
4241
    {  42, "file-size"},
4242
    {  43, "file-type"},
4243
    {  44, "firmware-revision"},
4244
    {  45, "high-limit"},
4245
    {  46, "inactive-text"},
4246
    {  47, "in-process"},
4247
    {  48, "instance-of"},
4248
    {  49, "integral-constant"},
4249
    {  50, "integral-constant-units"},
4250
    {  51, "issue-confirmed-notifications"},
4251
    {  52, "limit-enable"},
4252
    {  53, "list-of-group-members"},
4253
    {  54, "list-of-object-property-references"},
4254
    {  55, "list-of-session-keys"},
4255
    {  56, "local-date"},
4256
    {  57, "local-time"},
4257
    {  58, "location"},
4258
    {  59, "low-limit"},
4259
    {  60, "manipulated-variable-reference"},
4260
    {  61, "maximum-output"},
4261
    {  62, "max-apdu-length-accepted"},
4262
    {  63, "max-info-frames"},
4263
    {  64, "max-master"},
4264
    {  65, "max-pres-value"},
4265
    {  66, "minimum-off-time"},
4266
    {  67, "minimum-on-time"},
4267
    {  68, "minimum-output"},
4268
    {  69, "min-pres-value"},
4269
    {  70, "model-name"},
4270
    {  71, "modification-date"},
4271
    {  72, "notify-type"},
4272
    {  73, "number-of-APDU-retries"},
4273
    {  74, "number-of-states"},
4274
    {  75, "object-identifier"},
4275
    {  76, "object-list"},
4276
    {  77, "object-name"},
4277
    {  78, "object-property-reference"},
4278
    {  79, "object-type"},
4279
    {  80, "optional"},
4280
    {  81, "out-of-service"},
4281
    {  82, "output-units"},
4282
    {  83, "event-parameters"},
4283
    {  84, "polarity"},
4284
    {  85, "present-value"},
4285
    {  86, "priority"},
4286
    {  87, "priority-array"},
4287
    {  88, "priority-for-writing"},
4288
    {  89, "process-identifier"},
4289
    {  90, "program-change"},
4290
    {  91, "program-location"},
4291
    {  92, "program-state"},
4292
    {  93, "proportional-constant"},
4293
    {  94, "proportional-constant-units"},
4294
    {  95, "protocol-conformance-class"},
4295
    {  96, "protocol-object-types-supported"},
4296
    {  97, "protocol-services-supported"},
4297
    {  98, "protocol-version"},
4298
    {  99, "read-only"},
4299
    { 100, "reason-for-halt"},
4300
    { 101, "recipient"},
4301
    { 102, "recipient-list"},
4302
    { 103, "reliability"},
4303
    { 104, "relinquish-default"},
4304
    { 105, "required"},
4305
    { 106, "resolution"},
4306
    { 107, "segmentation-supported"},
4307
    { 108, "setpoint"},
4308
    { 109, "setpoint-reference"},
4309
    { 110, "state-text"},
4310
    { 111, "status-flags"},
4311
    { 112, "system-status"},
4312
    { 113, "time-delay"},
4313
    { 114, "time-of-active-time-reset"},
4314
    { 115, "time-of-state-count-reset"},
4315
    { 116, "time-synchronization-recipients"},
4316
    { 117, "units"},
4317
    { 118, "update-interval"},
4318
    { 119, "utc-offset"},
4319
    { 120, "vendor-identifier"},
4320
    { 121, "vendor-name"},
4321
    { 122, "vt-class-supported"},
4322
    { 123, "weekly-schedule"},
4323
    { 124, "attempted-samples"},
4324
    { 125, "average-value"},
4325
    { 126, "buffer-size"},
4326
    { 127, "client-cov-increment"},
4327
    { 128, "cov-resubscription-interval"},
4328
    { 129, "current-notify-time"},
4329
    { 130, "event-time-stamp"},
4330
    { 131, "log-buffer"},
4331
    { 132, "log-device-object-property"},
4332
    { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
4333
    { 134, "log-interval"},
4334
    { 135, "maximum-value"},
4335
    { 136, "minimum-value"},
4336
    { 137, "notification-threshold"},
4337
    { 138, "previous-notify-time"},
4338
    { 139, "protocol-revision"},
4339
    { 140, "records-since-notification"},
4340
    { 141, "record-count"},
4341
    { 142, "start-time"},
4342
    { 143, "stop-time"},
4343
    { 144, "stop-when-full"},
4344
    { 145, "total-record-count"},
4345
    { 146, "valid-samples"},
4346
    { 147, "window-interval"},
4347
    { 148, "window-samples"},
4348
    { 149, "maximum-value-time-stamp"},
4349
    { 150, "minimum-value-time-stamp"},
4350
    { 151, "variance-value"},
4351
    { 152, "active-cov-subscriptions"},
4352
    { 153, "backup-failure-timeout"},
4353
    { 154, "configuration-files"},
4354
    { 155, "database-revision"},
4355
    { 156, "direct-reading"},
4356
    { 157, "last-restore-time"},
4357
    { 158, "maintenance-required"},
4358
    { 159, "member-of"},
4359
    { 160, "mode"},
4360
    { 161, "operation-expected"},
4361
    { 162, "setting"},
4362
    { 163, "silenced"},
4363
    { 164, "tracking-value"},
4364
    { 165, "zone-members"},
4365
    { 166, "life-safety-alarm-values"},
4366
    { 167, "max-segments-accepted"},
4367
    { 168, "profile-name"},
4368
    { 169, "auto-slave-discovery"},
4369
    { 170, "manual-slave-address-binding"},
4370
    { 171, "slave-address-binding"},
4371
    { 172, "slave-proxy-enable"},
4372
    { 173, "last-notify-record"},     /* bug 4117 */
4373
    { 174, "schedule-default"},
4374
    { 175, "accepted-modes"},
4375
    { 176, "adjust-value"},
4376
    { 177, "count"},
4377
    { 178, "count-before-change"},
4378
    { 179, "count-change-time"},
4379
    { 180, "cov-period"},
4380
    { 181, "input-reference"},
4381
    { 182, "limit-monitoring-interval"},
4382
    { 183, "logging-object"},
4383
    { 184, "logging-record"},
4384
    { 185, "prescale"},
4385
    { 186, "pulse-rate"},
4386
    { 187, "scale"},
4387
    { 188, "scale-factor"},
4388
    { 189, "update-time"},
4389
    { 190, "value-before-change"},
4390
    { 191, "value-set"},
4391
    { 192, "value-change-time"},
4392
    { 193, "align-intervals"},
4393
    { 194, "group-member-names"},
4394
    { 195, "interval-offset"},
4395
    { 196, "last-restart-reason"},
4396
    { 197, "logging-type"},
4397
    { 198, "member-status-flags"},
4398
    { 199, "notification-period"},
4399
    { 200, "previous-notify-record"},
4400
    { 201, "requested-update-interval"},
4401
    { 202, "restart-notification-recipients"},
4402
    { 203, "time-of-device-restart"},
4403
    { 204, "time-synchronization-interval"},
4404
    { 205, "trigger"},
4405
    { 206, "UTC-time-synchronization-recipients"},
4406
    { 207, "node-subtype"},
4407
    { 208, "node-type"},
4408
    { 209, "structured-object-list"},
4409
    { 210, "subordinate-annotations"},
4410
    { 211, "subordinate-list"},
4411
    { 212, "actual-shed-level"},
4412
    { 213, "duty-window"},
4413
    { 214, "expected-shed-level"},
4414
    { 215, "full-duty-baseline"},
4415
    { 216, "node-subtype"},
4416
    { 217, "node-type"},
4417
    { 218, "requested-shed-level"},
4418
    { 219, "shed-duration"},
4419
    { 220, "shed-level-descriptions"},
4420
    { 221, "shed-levels"},
4421
    { 222, "state-description"},
4422
    /* enumeration values 223-225 are unassigned */
4423
    { 226, "door-alarm-state"},
4424
    { 227, "door-extended-pulse-time"},
4425
    { 228, "door-members"},
4426
    { 229, "door-open-too-long-time"},
4427
    { 230, "door-pulse-time"},
4428
    { 231, "door-status"},
4429
    { 232, "door-unlock-delay-time"},
4430
    { 233, "lock-status"},
4431
    { 234, "masked-alarm-values"},
4432
    { 235, "secured-status"},
4433
    /* enumeration values 236-243 are unassigned */
4434
    { 244, "absentee-limit"},     /* added with addenda 135-2008j */
4435
    { 245, "access-alarm-events"},
4436
    { 246, "access-doors"},
4437
    { 247, "access-event"},
4438
    { 248, "access-event-authentication-factor"},
4439
    { 249, "access-event-credential"},
4440
    { 250, "access-event-time"},
4441
    { 251, "access-transaction-events"},
4442
    { 252, "accompaniment"},
4443
    { 253, "accompaniment-time"},
4444
    { 254, "activation-time"},
4445
    { 255, "active-authentication-policy"},
4446
    { 256, "assigned-access-rights"},
4447
    { 257, "authentication-factors"},
4448
    { 258, "authentication-policy-list"},
4449
    { 259, "authentication-policy-names"},
4450
    { 260, "authentication-status"},
4451
    { 261, "authorization-mode"},
4452
    { 262, "belongs-to"},
4453
    { 263, "credential-disable"},
4454
    { 264, "credential-status"},
4455
    { 265, "credentials"},
4456
    { 266, "credentials-in-zone"},
4457
    { 267, "days-remaining"},
4458
    { 268, "entry-points"},
4459
    { 269, "exit-points"},
4460
    { 270, "expiration-time"},
4461
    { 271, "extended-time-enable"},
4462
    { 272, "failed-attempt-events"},
4463
    { 273, "failed-attempts"},
4464
    { 274, "failed-attempts-time"},
4465
    { 275, "last-access-event"},
4466
    { 276, "last-access-point"},
4467
    { 277, "last-credential-added"},
4468
    { 278, "last-credential-added-time"},
4469
    { 279, "last-credential-removed"},
4470
    { 280, "last-credential-removed-time"},
4471
    { 281, "last-use-time"},
4472
    { 282, "lockout"},
4473
    { 283, "lockout-relinquish-time"},
4474
    { 284, "master-exemption"},
4475
    { 285, "max-failed-attempts"},
4476
    { 286, "members"},
4477
    { 287, "muster-point"},
4478
    { 288, "negative-access-rules"},
4479
    { 289, "number-of-authentication-policies"},
4480
    { 290, "occupancy-count"},
4481
    { 291, "occupancy-count-adjust"},
4482
    { 292, "occupancy-count-enable"},
4483
    { 293, "occupancy-exemption"},
4484
    { 294, "occupancy-lower-limit"},
4485
    { 295, "occupancy-lower-limit-enforced"},
4486
    { 296, "occupancy-state"},
4487
    { 297, "occupancy-upper-limit"},
4488
    { 298, "occupancy-upper-limit-enforced"},
4489
    { 299, "passback-exemption"},
4490
    { 300, "passback-mode"},
4491
    { 301, "passback-timeout"},
4492
    { 302, "positive-access-rules"},
4493
    { 303, "reason-for-disable"},
4494
    { 304, "supported-formats"},
4495
    { 305, "supported-format-classes"},
4496
    { 306, "threat-authority"},
4497
    { 307, "threat-level"},
4498
    { 308, "trace-flag"},
4499
    { 309, "transaction-notification-class"},
4500
    { 310, "user-external-identifier"},
4501
    { 311, "user-information-reference"},
4502
    /* enumeration values 312-316 are unassigned */
4503
    { 317, "user-name"},
4504
    { 318, "user-type"},
4505
    { 319, "uses-remaining"},
4506
    { 320, "zone-from"},
4507
    { 321, "zone-to"},
4508
    { 322, "access-event-tag"},
4509
    { 323, "global-identifier"},
4510
    /* enumeration values 324-325 reserved for future addenda */
4511
    { 326, "verification-time"},
4512
    { 327, "base-device-security-policy"},
4513
    { 328, "distribution-key-revision"},
4514
    { 329, "do-not-hide"},
4515
    { 330, "key-sets"},
4516
    { 331, "last-key-server"},
4517
    { 332, "network-access-security-policies"},
4518
    { 333, "packet-reorder-time"},
4519
    { 334, "security-pdu-timeout"},
4520
    { 335, "security-time-window"},
4521
    { 336, "supported-security-algorithms"},
4522
    { 337, "update-key-set-timeout"},
4523
    { 338, "backup-and-restore-state"},
4524
    { 339, "backup-preparation-time"},
4525
    { 340, "restore-completion-time"},
4526
    { 341, "restore-preparation-time"},
4527
    { 342, "bit-mask"},       /* addenda 135-2008w */
4528
    { 343, "bit-text"},
4529
    { 344, "is-utc"},
4530
    { 345, "group-members"},
4531
    { 346, "group-member-names"},
4532
    { 347, "member-status-flags"},
4533
    { 348, "requested-update-interval"},
4534
    { 349, "covu-period"},
4535
    { 350, "covu-recipients"},
4536
    { 351, "event-message-texts"},
4537
    { 352, "event-message-texts-config"},
4538
    { 353, "event-detection-enable"},
4539
    { 354, "event-algorithm-inhibit"},
4540
    { 355, "event-algorithm-inhibit-ref"},
4541
    { 356, "time-delay-normal"},
4542
    { 357, "reliability-evaluation-inhibit"},
4543
    { 358, "fault-parameters"},
4544
    { 359, "fault-type"},
4545
    { 360, "local-forwarding-only"},
4546
    { 361, "process-identifier-filter"},
4547
    { 362, "subscribed-recipients"},
4548
    { 363, "port-filter"},
4549
    { 364, "authorization-exemptions"},
4550
    { 365, "allow-group-delay-inhibit"},
4551
    { 366, "channel-number"},
4552
    { 367, "control-groups"},
4553
    { 368, "execution-delay"},
4554
    { 369, "last-priority"},
4555
    { 370, "write-status"},
4556
    { 371, "property-list"},
4557
    { 372, "serial-number"},
4558
    { 373, "blink-warn-enable"},
4559
    { 374, "default-fade-time"},
4560
    { 375, "default-ramp-rate"},
4561
    { 376, "default-step-increment"},
4562
    { 377, "egress-time"},
4563
    { 378, "in-progress"},
4564
    { 379, "instantaneous-power"},
4565
    { 380, "lighting-command"},
4566
    { 381, "lighting-command-default-priority"},
4567
    { 382, "max-actual-value"},
4568
    { 383, "min-actual-value"},
4569
    { 384, "power"},
4570
    { 385, "transition"},
4571
    { 386, "egress-active"},
4572
    { 387, "interface-value"},
4573
    { 388, "fault-high-limit"},
4574
    { 389, "fault-low-limit"},
4575
    { 390, "low-diff-limit"},
4576
    { 391, "strike-count"},
4577
    { 392, "time-of-strike-count-reset"},
4578
    { 393, "default-timeout"},
4579
    { 394, "initial-timeout"},
4580
    { 395, "last-state-change"},
4581
    { 396, "state-change-values"},
4582
    { 397, "timer-running"},
4583
    { 398, "timer-state"},
4584
    { 399, "apdu-length"},
4585
    { 400, "bacnet-ip-address"},
4586
    { 401, "bacnet-ip-default-gateway"},
4587
    { 402, "bacnet-ip-dhcp-enable"},
4588
    { 403, "bacnet-ip-dhcp-lease-time"},
4589
    { 404, "bacnet-ip-dhcp-lease-time-remaining"},
4590
    { 405, "bacnet-ip-dhcp-server"},
4591
    { 406, "bacnet-ip-dns-server"},
4592
    { 407, "bacnet-ip-global-address"},
4593
    { 408, "bacnet-ip-mode"},
4594
    { 409, "bacnet-ip-multicast-address"},
4595
    { 410, "bacnet-ip-nat-traversal"},
4596
    { 411, "bacnet-ip-subnet-mask"},
4597
    { 412, "bacnet-ip-udp-port"},
4598
    { 413, "bbmd-accept-fd-registrations"},
4599
    { 414, "bbmd-broadcast-distribution-table"},
4600
    { 415, "bbmd-foreign-device-table"},
4601
    { 416, "changes-pending"},
4602
    { 417, "command"},
4603
    { 418, "fd-bbmd-address"},
4604
    { 419, "fd-subscription-lifetime"},
4605
    { 420, "link-speed"},
4606
    { 421, "link-speeds"},
4607
    { 422, "link-speed-autonegotiate"},
4608
    { 423, "mac-address"},
4609
    { 424, "network-interface-name"},
4610
    { 425, "network-number"},
4611
    { 426, "network-number-quality"},
4612
    { 427, "network-type"},
4613
    { 428, "routing-table"},
4614
    { 429, "virtual-mac-address-table"},
4615
    { 430, "command-time-array"},
4616
    { 431, "current-command-priority"},
4617
    { 432, "last-command-time"},
4618
    { 433, "value-source"},
4619
    { 434, "value-source-array"},
4620
    { 435, "bacnet-ipv6-mode"},
4621
    { 436, "ipv6-address"},
4622
    { 437, "ipv6-prefix-length"},
4623
    { 438, "bacnet-ipv6-udp-port"},
4624
    { 439, "ipv6-default-gateway"},
4625
    { 440, "bacnet-ipv6-multicast-address"},
4626
    { 441, "ipv6-dns-server"},
4627
    { 442, "ipv6-auto-addressing-enable"},
4628
    { 443, "ipv6-dhcp-lease-time"},
4629
    { 444, "ipv6-dhcp-lease-time-remaining"},
4630
    { 445, "ipv6-dhcp-server"},
4631
    { 446, "ipv6-zone-index"},
4632
    { 447, "assigned-landing-calls"},
4633
    { 448, "car-assigned-direction"},
4634
    { 449, "car-door-command"},
4635
    { 450, "car-door-status"},
4636
    { 451, "car-door-text"},
4637
    { 452, "car-door-zone"},
4638
    { 453, "car-drive-status"},
4639
    { 454, "car-load"},
4640
    { 455, "car-load-units"},
4641
    { 456, "car-mode"},
4642
    { 457, "car-moving-direction"},
4643
    { 458, "car-position"},
4644
    { 459, "elevator-group"},
4645
    { 460, "energy-meter"},
4646
    { 461, "energy-meter-ref"},
4647
    { 462, "escalator-mode"},
4648
    { 463, "fault-signals"},
4649
    { 464, "floor-text"},
4650
    { 465, "group-id"},
4651
    { 466, "enumeration value 466 is unassigned"},
4652
    { 467, "group-mode"},
4653
    { 468, "higher-deck"},
4654
    { 469, "installation-id"},
4655
    { 470, "landing-calls"},
4656
    { 471, "landing-call-control"},
4657
    { 472, "landing-door-status"},
4658
    { 473, "lower-deck"},
4659
    { 474, "machine-room-id"},
4660
    { 475, "making-car-call"},
4661
    { 476, "next-stopping-floor"},
4662
    { 477, "operation-direction"},
4663
    { 478, "passenger-alarm"},
4664
    { 479, "power-mode"},
4665
    { 480, "registered-car-call"},
4666
    { 481, "active-cov-multiple-subscriptions"},
4667
    { 482, "protocol-level"},
4668
    { 483, "reference-port"},
4669
    { 484, "deployed-profile-location"},
4670
    { 485, "profile-location"},
4671
    { 486, "tags"},
4672
    { 487, "subordinate-node-types"},
4673
    { 488, "subordinate-tags"},
4674
    { 489, "subordinate-relationship"},
4675
    { 490, "default-subordinate-relationship"},
4676
    { 491, "represents"},
4677
    { 492, "default-present-value"},
4678
    { 493, "present-stage"},
4679
    { 494, "stages"},
4680
    { 495, "stage-names"},
4681
    { 496, "target-references"},
4682
    { 497, "audit-source-reporter"},
4683
    { 498, "audit-level"},
4684
    { 499, "audit-notification-recipient"},
4685
    { 500, "audit-priority-filter"},
4686
    { 501, "auditable-operations"},
4687
    { 502, "delete-on-forward"},
4688
    { 503, "maximum-send-delay"},
4689
    { 504, "monitored-objects"},
4690
    { 505, "send-now"},
4691
    { 506, "floor-number"},
4692
    { 507, "device-uuid"},
4693
    { 508, "additional-reference-ports"},
4694
    { 509, "certificate-signing-request-file"},
4695
    { 510, "command-validation-result"},
4696
    { 511, "issuer-certificate-files"},
4697
    { 4194304, "max-bvlc-length-accepted"},
4698
    { 4194305, "max-npdu-length-accepted"},
4699
    { 4194306, "operational-certificate-file"},
4700
    { 4194307, "current-health"},
4701
    { 4194308, "sc-connect-wait-timeout"},
4702
    { 4194309, "sc-direct-connect-accept-enable"},
4703
    { 4194310, "sc-direct-connect-accept-uris"},
4704
    { 4194311, "ssc-direct-connect-binding"},
4705
    { 4194312, "sc-direct-connect-connection-status"},
4706
    { 4194313, "sc-direct-connect-initiate-enable"},
4707
    { 4194314, "sc-disconnect-wait-timeout"},
4708
    { 4194315, "sc-failed-connection-request"},
4709
    { 4194316, "sc-failover-hub-connection-status"},
4710
    { 4194317, "sc-failover-hub-uri"},
4711
    { 4194318, "sc-hub-connector-state"},
4712
    { 4194319, "sc-hub-function-accept-uris"},
4713
    { 4194320, "sc-hub-function-binding"},
4714
    { 4194321, "sc-hub-function-connection-status"},
4715
    { 4194322, "sc-hub-function-enable"},
4716
    { 4194323, "sc-heartbeat-timeout"},
4717
    { 4194324, "sc-primary-hub-connection-status"},
4718
    { 4194325, "sc-primary-hub-uri"},
4719
    { 4194326, "sc-maximum-reconnect-time"},
4720
    { 4194327, "sc-minimum-reconnect-time"},
4721
    { 4194328, "color-override"},
4722
    { 4194329, "color-reference"},
4723
    { 4194330, "default-color"},
4724
    { 4194331, "default-color-temperature"},
4725
    { 4194332, "override-color-reference"},
4726
    { 4194334, "color-command"},
4727
    { 4194335, "high_end_trim"},
4728
    { 4194336, "low_end_trim"},
4729
    { 4194337, "trim_fade_time"},
4730
    { 4194338, "device-address-proxy-enable"},
4731
    { 4194339, "device-address-proxy-table"},
4732
    { 4194340, "device-address-proxy-timeout"},
4733
    { 4194341, "default-on-value"},
4734
    { 4194342, "last-on-value"},
4735
    { 4194343, "authorization-cache"},
4736
    { 4194344, "authorization-groups"},
4737
    { 4194345, "authorization-policy"},
4738
    { 4194346, "authorization-scope"},
4739
    { 4194347, "authorization-server"},
4740
    { 4194348, "authorization-status"},
4741
    { 4194349, "max-proxied-i-ams-per-second"},
4742
    { 0,   NULL}
4743
/* Enumerated values 0-511 are reserved for definition by ASHRAE.
4744
   Enumerated values 512-4194303 may be used by others subject to
4745
   the procedures and constraints described in Clause 23. */
4746
};
4747
4748
static const value_string
4749
BACnetBinaryPV [] = {
4750
    { 0, "inactive"},
4751
    { 1, "active"},
4752
    { 0, NULL}
4753
};
4754
4755
4756
415
#define ANSI_X3_4      0 /* ANSI X3.4, a/k/a "ASCII"; full UTF-8 since 2010 */
4757
                         /* See, for example, ANSI/ASHRAE Addendum k to ANSI/ASHRAE Standard 135-2008 */
4758
                         /* XXX - I've seen captures using this for ISO 8859-1 */
4759
13.0k
#define IBM_MS_DBCS    1 /* "IBM/Microsoft DBCS"; was there only one such DBCS? */
4760
125
#define JIS_C_6226     2 /* JIS C 6226 */
4761
139
#define ISO_10646_UCS4 3 /* ISO 10646 (UCS-4) - 4-byte Unicode */
4762
66
#define ISO_10646_UCS2 4 /* ISO 10646 (UCS-2) - 2-byte Unicode Basic Multilingual Plane (not UTF-16, presumably) */
4763
56
#define ISO_8859_1     5 /* ISO 8859-1 */
4764
static const value_string
4765
BACnetCharacterSet [] = {
4766
    { ANSI_X3_4,      "ANSI X3.4 / UTF-8 (since 2010)"},
4767
    { IBM_MS_DBCS,    "IBM/Microsoft DBCS"},
4768
    { JIS_C_6226,     "JIS C 6226"},
4769
    { ISO_10646_UCS4, "ISO 10646 (UCS-4)"},
4770
    { ISO_10646_UCS2, "ISO 10646 (UCS-2)"},
4771
    { ISO_8859_1,     "ISO 8859-1"},
4772
    { 0,     NULL}
4773
};
4774
4775
static const value_string
4776
BACnetStatusFlags [] = {
4777
    { 0, "in-alarm"},
4778
    { 1, "fault"},
4779
    { 2, "overridden"},
4780
    { 3, "out-of-service"},
4781
    { 0, NULL}
4782
};
4783
4784
static const value_string
4785
BACnetMessagePriority [] = {
4786
    { 0, "normal"},
4787
    { 1, "urgent"},
4788
    { 0, NULL}
4789
};
4790
4791
static const value_string
4792
BACnetAcknowledgementFilter [] = {
4793
    { 0, "all"},
4794
    { 1, "acked"},
4795
    { 2, "not-acked"},
4796
    { 0, NULL}
4797
};
4798
4799
static const value_string
4800
BACnetResultFlags [] = {
4801
    { 0, "first-item"},
4802
    { 1, "last-item"},
4803
    { 2, "more-items"},
4804
    { 0, NULL}
4805
};
4806
4807
static const value_string
4808
BACnetRelationSpecifier [] = {
4809
    { 0, "equal"},
4810
    { 1, "not-equal"},
4811
    { 2, "less-than"},
4812
    { 3, "greater-than"},
4813
    { 4, "less-than-or-equal"},
4814
    { 5, "greater-than-or-equal"},
4815
    { 0, NULL}
4816
};
4817
4818
static const value_string
4819
BACnetSelectionLogic [] = {
4820
    { 0, "and"},
4821
    { 1, "or"},
4822
    { 2, "all"},
4823
    { 0, NULL}
4824
};
4825
4826
static const value_string
4827
BACnetEventStateFilter [] = {
4828
    { 0, "offnormal"},
4829
    { 1, "fault"},
4830
    { 2, "normal"},
4831
    { 3, "all"},
4832
    { 4, "active"},
4833
    { 0, NULL}
4834
};
4835
4836
static const value_string
4837
BACnetEventTransitionBits [] = {
4838
    { 0, "to-offnormal"},
4839
    { 1, "to-fault"},
4840
    { 2, "to-normal"},
4841
    { 0, NULL}
4842
};
4843
4844
static const value_string
4845
BACnetSegmentation [] = {
4846
    { 0, "segmented-both"},
4847
    { 1, "segmented-transmit"},
4848
    { 2, "segmented-receive"},
4849
    { 3, "no-segmentation"},
4850
    { 0, NULL}
4851
};
4852
4853
static const value_string
4854
BACnetSilencedState [] = {
4855
    { 0, "unsilenced"},
4856
    { 1, "audible-silenced"},
4857
    { 2, "visible-silenced"},
4858
    { 3, "all-silenced"},
4859
    { 0, NULL}
4860
};
4861
4862
static const value_string
4863
BACnetDeviceStatus [] = {
4864
    { 0, "operational"},
4865
    { 1, "operational-read-only"},
4866
    { 2, "download-required"},
4867
    { 3, "download-in-progress"},
4868
    { 4, "non-operational"},
4869
    { 5, "backup-in-progress"},
4870
    { 0, NULL}
4871
};
4872
4873
static const value_string
4874
BACnetEnableDisable [] = {
4875
    { 0, "enable"},
4876
    { 1, "disable"},
4877
    { 2, "disable-initiation"},
4878
    { 0, NULL}
4879
};
4880
4881
static const value_string
4882
months [] = {
4883
    {   1, "January" },
4884
    {   2, "February" },
4885
    {   3, "March" },
4886
    {   4, "April" },
4887
    {   5, "May" },
4888
    {   6, "June" },
4889
    {   7, "July" },
4890
    {   8, "August" },
4891
    {   9, "September" },
4892
    {  10, "October" },
4893
    {  11, "November" },
4894
    {  12, "December" },
4895
    {  13, "odd month" },
4896
    {  14, "even month" },
4897
    { 255, "any month" },
4898
    { 0,   NULL }
4899
};
4900
4901
static const value_string
4902
weekofmonth [] = {
4903
    {   1, "days numbered 1-7" },
4904
    {   2, "days numbered 8-14" },
4905
    {   3, "days numbered 15-21" },
4906
    {   4, "days numbered 22-28" },
4907
    {   5, "days numbered 29-31" },
4908
    {   6, "last 7 days of this month" },
4909
    {   7, "any of 7 days prior to last 7 days of this month" },
4910
    {   8, "any of 7 days prior to last 14 days of this month" },
4911
    {   9, "any of 7 days prior to last 21 days of this month" },
4912
    { 255, "any week of this month" },
4913
    { 0,   NULL }
4914
};
4915
4916
/* note: notification class object recipient-list uses
4917
   different day-of-week enum */
4918
static const value_string
4919
day_of_week [] = {
4920
    {   1, "Monday" },
4921
    {   2, "Tuesday" },
4922
    {   3, "Wednesday" },
4923
    {   4, "Thursday" },
4924
    {   5, "Friday" },
4925
    {   6, "Saturday" },
4926
    {   7, "Sunday" },
4927
    { 255, "any day of week" },
4928
    { 0,   NULL }
4929
};
4930
4931
static const value_string
4932
BACnetErrorClass [] = {
4933
    { 0, "device" },
4934
    { 1, "object" },
4935
    { 2, "property" },
4936
    { 3, "resources" },
4937
    { 4, "security" },
4938
    { 5, "services" },
4939
    { 6, "vt" },
4940
    { 7, "communication" },
4941
    { 0, NULL }
4942
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
4943
   Enumerated values64-65535 may be used by others subject to
4944
   the procedures and constraints described in Clause 23. */
4945
};
4946
4947
static const value_string
4948
BACnetVTClass [] = {
4949
    { 0, "default-terminal" },
4950
    { 1, "ansi-x3-64" },
4951
    { 2, "dec-vt52" },
4952
    { 3, "dec-vt100" },
4953
    { 4, "dec-vt200" },
4954
    { 5, "hp-700-94" },
4955
    { 6, "ibm-3130" },
4956
    { 0, NULL }
4957
};
4958
4959
static const value_string
4960
BACnetEventType [] = {
4961
    {  0, "change-of-bitstring" },
4962
    {  1, "change-of-state" },
4963
    {  2, "change-of-value" },
4964
    {  3, "command-failure" },
4965
    {  4, "floating-limit" },
4966
    {  5, "out-of-range" },
4967
    {  6, "complex-event-type" },
4968
    {  7, "(deprecated)event-buffer-ready" },
4969
    {  8, "change-of-life-safety" },
4970
    {  9, "extended" },
4971
    { 10, "buffer-ready" },
4972
    { 11, "unsigned-range" },
4973
    { 13, "access-event" },
4974
    { 14, "double-out-of-range"},     /* added with addenda 135-2008w */
4975
    { 15, "signed-out-of-range"},
4976
    { 16, "unsigned-out-of-range"},
4977
    { 17, "change-of-characterstring"},
4978
    { 18, "change-of-status-flags"},
4979
    { 19, "change-of-reliability" },
4980
    { 20, "none" },
4981
    { 21, "change-of-discrete-value"},
4982
    { 22, "change-of-timer"},
4983
    { 0,  NULL }
4984
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
4985
   Enumerated values 64-65535 may be used by others subject to
4986
   the procedures and constraints described in Clause 23.
4987
   It is expected that these enumerated values will correspond
4988
   to the use of the complex-event-type CHOICE [6] of the
4989
   BACnetNotificationParameters production. */
4990
};
4991
4992
static const value_string
4993
BACnetEventState [] = {
4994
    { 0, "normal" },
4995
    { 1, "fault" },
4996
    { 2, "offnormal" },
4997
    { 3, "high-limit" },
4998
    { 4, "low-limit" },
4999
    { 5, "life-safety-alarm" },
5000
    { 0, NULL }
5001
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
5002
   Enumerated values 64-65535 may be used by others subject to
5003
   the procedures and constraints described in Clause 23.  */
5004
};
5005
5006
static const value_string
5007
BACnetLogStatus [] = {
5008
    { 0, "log-disabled" },
5009
    { 1, "buffer-purged" },
5010
    { 2, "log-interrupted"},
5011
    { 0, NULL }
5012
};
5013
5014
static const value_string
5015
BACnetMaintenance [] = {
5016
    { 0, "none" },
5017
    { 1, "periodic-test" },
5018
    { 2, "need-service-operational" },
5019
    { 3, "need-service-inoperative" },
5020
    { 0, NULL }
5021
};
5022
5023
static const value_string
5024
BACnetNotifyType [] = {
5025
    { 0, "alarm" },
5026
    { 1, "event" },
5027
    { 2, "ack-notification" },
5028
    { 0, NULL }
5029
};
5030
5031
static const value_string
5032
BACnetServicesSupported [] = {
5033
    {  0, "acknowledgeAlarm"},
5034
    {  1, "confirmedCOVNotification"},
5035
    {  2, "confirmedEventNotification"},
5036
    {  3, "getAlarmSummary"},
5037
    {  4, "getEnrollmentSummary"},
5038
    {  5, "subscribeCOV"},
5039
    {  6, "atomicReadFile"},
5040
    {  7, "atomicWriteFile"},
5041
    {  8, "addListElement"},
5042
    {  9, "removeListElement"},
5043
    { 10, "createObject"},
5044
    { 11, "deleteObject"},
5045
    { 12, "readProperty"},
5046
    { 13, "readPropertyConditional"},
5047
    { 14, "readPropertyMultiple"},
5048
    { 15, "writeProperty"},
5049
    { 16, "writePropertyMultiple"},
5050
    { 17, "deviceCommunicationControl"},
5051
    { 18, "confirmedPrivateTransfer"},
5052
    { 19, "confirmedTextMessage"},
5053
    { 20, "reinitializeDevice"},
5054
    { 21, "vtOpen"},
5055
    { 22, "vtClose"},
5056
    { 23, "vtData"},
5057
    { 24, "authenticate"},
5058
    { 25, "requestKey"},
5059
    { 26, "i-Am"},
5060
    { 27, "i-Have"},
5061
    { 28, "unconfirmedCOVNotification"},
5062
    { 29, "unconfirmedEventNotification"},
5063
    { 30, "unconfirmedPrivateTransfer"},
5064
    { 31, "unconfirmedTextMessage"},
5065
    { 32, "timeSynchronization"},
5066
    { 33, "who-Has"},
5067
    { 34, "who-Is"},
5068
    { 35, "readRange"},
5069
    { 36, "utcTimeSynchronization"},
5070
    { 37, "lifeSafetyOperation"},
5071
    { 38, "subscribeCOVProperty"},
5072
    { 39, "getEventInformation"},
5073
    { 40, "write-group"},
5074
    { 41, "subscribe-cov-property-multiple"},
5075
    { 42, "confirmed-cov-notification-multiple"},
5076
    { 43, "unconfirmed-cov-notification-multiple"},
5077
    { 44, "confirmed-audit-notification"},
5078
    { 45, "audit-log-query"},
5079
    { 46, "unconfirmed-audit-notification"},
5080
    { 47, "who-am-i"},
5081
    { 48, "you-are"},
5082
    { 49, "auth-request"},
5083
    { 0,  NULL}
5084
};
5085
5086
static const value_string
5087
BACnetPropertyStates [] = {
5088
    {  0, "boolean-value"},
5089
    {  1, "binary-value"},
5090
    {  2, "event-type"},
5091
    {  3, "polarity"},
5092
    {  4, "program-change"},
5093
    {  5, "program-state"},
5094
    {  6, "reason-for-halt"},
5095
    {  7, "reliability"},
5096
    {  8, "state"},
5097
    {  9, "system-status"},
5098
    { 10, "units"},
5099
    { 11, "unsigned-value"},
5100
    { 12, "life-safety-mode"},
5101
    { 13, "life-safety-state"},
5102
    { 14, "restart-reason"},
5103
    { 15, "door-alarm-state"},
5104
    { 16, "action"},
5105
    { 17, "door-secured-status"},
5106
    { 18, "door-status"},
5107
    { 19, "door-value"},
5108
    { 20, "file-access-method"},
5109
    { 21, "lock-status"},
5110
    { 22, "life-safety-operation"},
5111
    { 23, "maintenance"},
5112
    { 24, "node-type"},
5113
    { 25, "notify-type"},
5114
    { 26, "security-level"},
5115
    { 27, "shed-state"},
5116
    { 28, "silenced-state"},
5117
    { 29, "unknown-29"},
5118
    { 30, "access-event"},
5119
    { 31, "zone-occupancy-state"},
5120
    { 32, "access-credential-disable-reason"},
5121
    { 33, "access-credential-disable"},
5122
    { 34, "authentication-status"},
5123
    { 35, "unknown-35"},
5124
    { 36, "backup-state"},
5125
    { 37, "write-status"},
5126
    { 38, "lighting-in-progress"},
5127
    { 39, "lighting-operation"},
5128
    { 40, "lighting-transition"},
5129
    { 41, "signed-value"},
5130
    { 42, "unknown-42"},
5131
    { 43, "timer-state"},
5132
    { 44, "timer-transition"},
5133
    { 45, "bacnet-ip-mode"},
5134
    { 46, "network-port-command"},
5135
    { 47, "network-type"},
5136
    { 48, "network-number-quality"},
5137
    { 49, "escalator-operation-direction"},
5138
    { 50, "escalator-fault"},
5139
    { 51, "escalator-mode"},
5140
    { 52, "lift-car-direction"},
5141
    { 53, "lift-car-door-command"},
5142
    { 54, "lift-car-drive-status"},
5143
    { 55, "lift-car-mode"},
5144
    { 56, "lift-group-mode"},
5145
    { 57, "lift-fault"},
5146
    { 58, "protocol-level"},
5147
    { 59, "audit-level"},
5148
    { 60, "audit-operation"},
5149
    { 63, "extended-value"},
5150
    {256, "-- example-one"},
5151
    {257, "-- example-two"},
5152
    {258, "sc-connection-state"},
5153
    {259, "sc-hub-connecto-state"},
5154
    { 0, NULL}
5155
/* Tag values 0-63 are reserved for definition by ASHRAE.
5156
   Tag values of 64-254 may be used by others to accommodate
5157
   vendor specific properties that have discrete or enumerated values,
5158
   subject to the constraints described in Clause 23. */
5159
};
5160
5161
static const value_string
5162
BACnetProgramError [] = {
5163
    { 0, "normal"},
5164
    { 1, "load-failed"},
5165
    { 2, "internal"},
5166
    { 3, "program"},
5167
    { 4, "other"},
5168
    { 0, NULL}
5169
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
5170
   Enumerated values 64-65535 may be used by others subject to
5171
   the procedures and constraints described in Clause 23. */
5172
};
5173
5174
static const value_string
5175
BACnetProgramRequest [] = {
5176
    { 0, "ready"},
5177
    { 1, "load"},
5178
    { 2, "run"},
5179
    { 3, "halt"},
5180
    { 4, "restart"},
5181
    { 5, "unload"},
5182
    { 0, NULL}
5183
};
5184
5185
static const value_string
5186
BACnetProgramState [] = {
5187
    { 0, "idle"},
5188
    { 1, "loading"},
5189
    { 2, "running"},
5190
    { 3, "waiting"},
5191
    { 4, "halted"},
5192
    { 5, "unloading"},
5193
    { 0, NULL}
5194
};
5195
5196
static const value_string
5197
BACnetReinitializedStateOfDevice [] = {
5198
    { 0, "coldstart"},
5199
    { 1, "warmstart"},
5200
    { 2, "start-backup"},
5201
    { 3, "end-backup"},
5202
    { 4, "start-restore"},
5203
    { 5, "end-restore"},
5204
    { 6, "abort-restore"},
5205
    { 7, "activate-changes"},
5206
    { 0, NULL}
5207
};
5208
5209
static const value_string
5210
BACnetPolarity [] = {
5211
    { 0, "normal"},
5212
    { 1, "reverse"},
5213
    { 0, NULL}
5214
};
5215
5216
static const value_string
5217
BACnetTagNames[] = {
5218
    { 5, "Extended Value" },
5219
    { 6, "Opening Tag" },
5220
    { 7, "Closing Tag" },
5221
    { 0, NULL }
5222
};
5223
5224
static const value_string
5225
BACnetReadRangeOptions[] = {
5226
    { 3, "range byPosition" },
5227
    { 4, "range byTime" },
5228
    { 5, "range timeRange" },
5229
    { 6, "range bySequenceNumber" },
5230
    { 7, "range byTime" },
5231
    { 0, NULL }
5232
};
5233
5234
/* Present_Value for Load Control Object */
5235
static const value_string
5236
BACnetShedState[] = {
5237
    { 0, "shed-inactive" },
5238
    { 1, "shed-request-pending" },
5239
    { 2, "shed-compliant" },
5240
    { 3, "shed-non-compliant" },
5241
    { 0, NULL }
5242
};
5243
5244
static const value_string
5245
BACnetFaultType[] = {
5246
  { 0, "none" },
5247
  { 1, "fault-characterstring" },
5248
  { 2, "fault-extended" },
5249
  { 3, "fault-life-safety" },
5250
  { 4, "fault-state" },
5251
  { 5, "fault-status-flags" },
5252
  { 6, "fault-out-of-range" },
5253
  { 7, "fault-listed" },
5254
  { 0, NULL }
5255
};
5256
5257
static const value_string
5258
BACnetNodeType [] = {
5259
    { 0, "unknown" },
5260
    { 1, "system" },
5261
    { 2, "network" },
5262
    { 3, "device" },
5263
    { 4, "organizational" },
5264
    { 5, "area" },
5265
    { 6, "equipment" },
5266
    { 7, "point" },
5267
    { 8, "collection" },
5268
    { 9, "property" },
5269
    { 10, "functional" },
5270
    { 11, "other" },
5271
    { 12, "subsystem" },
5272
    { 13, "building" },
5273
    { 14, "floor" },
5274
    { 15, "section" },
5275
    { 16, "module" },
5276
    { 17, "tree" },
5277
    { 18, "member" },
5278
    { 19, "protocol" },
5279
    { 20, "room" },
5280
    { 21, "zone" },
5281
    { 0, NULL }
5282
};
5283
5284
static const value_string
5285
BACnetLoggingType [] = {
5286
    { 0, "polled" },
5287
    { 1, "cov" },
5288
    { 2, "triggered" },
5289
    { 0, NULL }
5290
};
5291
5292
static const value_string
5293
BACnetDoorStatus [] = {
5294
    { 0, "closed" },
5295
    { 1, "opened" },
5296
    { 2, "unknown" },
5297
    { 3, "door-fault" },
5298
    { 4, "unused" },
5299
    { 5, "none" },
5300
    { 6, "closing" },
5301
    { 7, "opening" },
5302
    { 8, "safety-locked" },
5303
    { 9, "limited-opened" },
5304
    { 0, NULL }
5305
};
5306
5307
static const value_string
5308
BACnetDoorValue[] = {
5309
  { 0, "lock" },
5310
  { 1, "unlock" },
5311
  { 2, "pulse-unlock" },
5312
  { 3, "extended-pulse-unlock" },
5313
  { 0, NULL }
5314
};
5315
5316
static const value_string
5317
BACnetLockStatus [] = {
5318
    { 0, "locked" },
5319
    { 1, "unlocked" },
5320
    { 2, "fault" },
5321
    { 3, "unknown" },
5322
    { 0, NULL }
5323
};
5324
5325
static const value_string
5326
BACnetDoorSecuredStatus [] = {
5327
    { 0, "secured" },
5328
    { 1, "unsecured" },
5329
    { 2, "unknown" },
5330
    { 0, NULL }
5331
};
5332
5333
static const value_string
5334
BACnetDoorAlarmState [] = {
5335
    { 0, "normal" },
5336
    { 1, "alarm" },
5337
    { 2, "door-open-too-long" },
5338
    { 3, "forced-open" },
5339
    { 4, "tamper" },
5340
    { 5, "door-fault" },
5341
    { 6, "lock-down" },
5342
    { 7, "free-access" },
5343
    { 8, "egress-open" },
5344
    { 0, NULL }
5345
};
5346
5347
static const value_string
5348
BACnetSecurityPolicy [] = {
5349
    { 0, "plain-non-trusted"},
5350
    { 1, "plain-trusted"},
5351
    { 2, "signed-trusted"},
5352
    { 3, "encrypted-trusted"},
5353
    { 0, NULL }
5354
};
5355
5356
static const value_string
5357
BACnetAccumulatorStatus [] = {
5358
    { 0, "normal" },
5359
    { 1, "starting" },
5360
    { 2, "recovered" },
5361
    { 3, "abnormal" },
5362
    { 4, "failed" },
5363
    { 0, NULL }
5364
};
5365
5366
static const value_string
5367
BACnetAuditLevel [] = {
5368
    { 0, "none" },
5369
    { 1, "audit-all" },
5370
    { 2, "audit-config" },
5371
    { 3, "default" },
5372
    { 0, NULL }
5373
};
5374
5375
static const value_string
5376
BACnetAuditPriorityFilter [] = {
5377
    { 1, "manual-life-safety" },
5378
    { 2, "automatic-life-safety" },
5379
    { 3, "priority-3" },
5380
    { 4, "priority-4" },
5381
    { 5, "critical-equipment-controls" },
5382
    { 6, "minimum-on-off" },
5383
    { 7, "priority-7" },
5384
    { 8, "manual-operator" },
5385
    { 9, "priority-9" },
5386
    { 10, "priority-10" },
5387
    { 11, "priority-11" },
5388
    { 12, "priority-12" },
5389
    { 13, "priority-13" },
5390
    { 14, "priority-14" },
5391
    { 15, "priority-15" },
5392
    { 16, "priority-16" },
5393
    { 0, NULL }
5394
};
5395
5396
static const value_string
5397
BACnetAuditOperation [] = {
5398
    { 0, "read" },
5399
    { 1, "write" },
5400
    { 2, "create" },
5401
    { 3, "delete" },
5402
    { 4, "life-safety" },
5403
    { 5, "acknowledge-alarm" },
5404
    { 6, "device-disable-comm" },
5405
    { 7, "device-enable-comm" },
5406
    { 8, "device-reset" },
5407
    { 9, "device-backup" },
5408
    { 10, "device-restore" },
5409
    { 11, "subscription" },
5410
    { 12, "notification" },
5411
    { 13, "auditing-failure" },
5412
    { 14, "network-changes" },
5413
    { 15, "general" },
5414
    { 0, NULL }
5415
};
5416
5417
static const value_string
5418
BACnetSuccessFilter [] = {
5419
    { 0, "all" },
5420
    { 1, "successes-only" },
5421
    { 2, "failures-only" },
5422
    { 0, NULL }
5423
};
5424
5425
static const value_string
5426
BACnetAuthorizationScopeStandard [] = {
5427
    { 0, "view" },
5428
    { 1, "adjust" },
5429
    { 2, "control" },
5430
    { 3, "override" },
5431
    { 4, "config" },
5432
    { 5, "bind" },
5433
    { 6, "install" },
5434
    { 7, "auth" },
5435
    { 8, "infrastructure" },
5436
    { 9, "reserved-9" },
5437
    { 10, "reserved-10" },
5438
    { 11, "reserved-11" },
5439
    { 12, "reserved-12" },
5440
    { 13, "reserved-13" },
5441
    { 14, "reserved-14" },
5442
    { 15, "reserved-15" },
5443
    { 16, "reserved-16" },
5444
    { 17, "reserved-17" },
5445
    { 18, "reserved-18" },
5446
    { 19, "reserved-19" },
5447
    { 20, "reserved-20" },
5448
    { 21, "reserved-21" },
5449
    { 22, "reserved-22" },
5450
    { 23, "reserved-23" },
5451
    { 0, NULL }
5452
};
5453
5454
static const value_string
5455
BACnetAuthorizationPosture[] = {
5456
    { 0, "open" },
5457
    { 1, "proprietary" },
5458
    { 2, "configured" },
5459
    { 3, "misconfigured-partial" },
5460
    { 4, "misconfigured-total" },
5461
    { 0, NULL }
5462
};
5463
5464
static const value_string
5465
BACnetAuthenticationDecision[] = {
5466
    { 0, "allow-match" },
5467
    { 1, "deny-mismatch" },
5468
    { 2, "deny-non-relay" },
5469
    { 0, NULL }
5470
};
5471
5472
static const value_string
5473
BACnetAuthorizationDecision[] = {
5474
    { 0, "allow-by-token" },
5475
    { 1, "allow-by-local-polic" },
5476
    { 2, "deny-no-token-or-policy" },
5477
    { 3, "deny-not-before" },
5478
    { 4, "deny-not-after" },
5479
    { 5, "deny-target-device" },
5480
    { 6, "deny-target-group" },
5481
    { 7, "deny-client-device" },
5482
    { 8, "deny-client-method" },
5483
    { 9, "deny-scope" },
5484
    { 10, "deny-issuer" },
5485
    { 11, "deny-revoked" },
5486
    { 12, "deny-signature" },
5487
    { 13, "deny-other" },
5488
    { 0, NULL }
5489
};
5490
5491
static const value_string
5492
BACnetAuthorizationConstraintOrigin[] = {
5493
    { 0, "direct-connect" },
5494
    { 1, "same-network" },
5495
    { 2, "any-network" },
5496
    { 0, NULL }
5497
};
5498
5499
static const value_string
5500
BACnetAuthorizationConstraintAuthentication[] = {
5501
    { 0, "certified" },
5502
    { 1, "secure-path" },
5503
    { 2, "any-method" },
5504
    { 0, NULL }
5505
};
5506
5507
extern value_string_ext BACnetVendorIdentifiers_ext;
5508
5509
static int proto_bacapp;
5510
static int hf_bacapp_type;
5511
static int hf_bacapp_pduflags;
5512
static int hf_bacapp_SEG;
5513
static int hf_bacapp_MOR;
5514
static int hf_bacapp_SA;
5515
static int hf_bacapp_response_segments;
5516
static int hf_bacapp_max_adpu_size;
5517
static int hf_bacapp_invoke_id;
5518
static int hf_bacapp_object_identifier;
5519
static int hf_bacapp_device_identifier;
5520
static int hf_bacapp_objectType;
5521
static int hf_bacapp_object_name;
5522
static int hf_bacapp_instanceNumber;
5523
static int hf_bacapp_sequence_number;
5524
static int hf_bacapp_window_size;
5525
static int hf_bacapp_service;
5526
static int hf_bacapp_NAK;
5527
static int hf_bacapp_SRV;
5528
static int hf_bacapp_notify_type;
5529
static int hf_bacapp_event_type;
5530
static int hf_bacapp_error_class;
5531
static int hf_bacapp_error_code;
5532
static int hf_Device_Instance_Range_Low_Limit;
5533
static int hf_Device_Instance_Range_High_Limit;
5534
static int hf_BACnetRejectReason;
5535
static int hf_BACnetAbortReason;
5536
static int hf_BACnetApplicationTagNumber;
5537
static int hf_BACnetContextTagNumber;
5538
static int hf_BACnetExtendedTagNumber;
5539
static int hf_BACnetNamedTag;
5540
static int hf_BACnetTagClass;
5541
static int hf_BACnetCharacterSet;
5542
static int hf_BACnetCodePage;
5543
static int hf_bacapp_tag_lvt;
5544
static int hf_bacapp_tag_ProcessId;
5545
static int hf_bacapp_tag_to_state;
5546
static int hf_bacapp_tag_from_state;
5547
static int hf_bacapp_uservice;
5548
static int hf_BACnetPropertyIdentifier;
5549
static int hf_BACnetVendorIdentifier;
5550
static int hf_BACnetRestartReason;
5551
static int hf_bacapp_tag_IPV4;
5552
static int hf_bacapp_tag_IPV6;
5553
static int hf_bacapp_tag_PORT;
5554
static int hf_bacapp_tag_mac_address_broadcast;
5555
static int hf_bacapp_reserved_ashrea;
5556
static int hf_bacapp_unused_bits;
5557
static int hf_bacapp_bit;
5558
static int hf_bacapp_complete_bitstring;
5559
5560
/* present value */
5561
static int hf_bacapp_present_value_null;
5562
static int hf_bacapp_present_value_bool;
5563
static int hf_bacapp_present_value_unsigned;
5564
static int hf_bacapp_present_value_signed;
5565
static int hf_bacapp_present_value_real;
5566
static int hf_bacapp_present_value_double;
5567
static int hf_bacapp_present_value_octet_string;
5568
static int hf_bacapp_present_value_char_string;
5569
static int hf_bacapp_present_value_bit_string;
5570
static int hf_bacapp_present_value_enum_index;
5571
5572
/* some more variables for segmented messages */
5573
static int hf_msg_fragments;
5574
static int hf_msg_fragment;
5575
static int hf_msg_fragment_overlap;
5576
static int hf_msg_fragment_overlap_conflicts;
5577
static int hf_msg_fragment_multiple_tails;
5578
static int hf_msg_fragment_too_long_fragment;
5579
static int hf_msg_fragment_error;
5580
static int hf_msg_fragment_count;
5581
static int hf_msg_reassembled_in;
5582
static int hf_msg_reassembled_length;
5583
5584
static int ett_msg_fragment;
5585
static int ett_msg_fragments;
5586
5587
static int ett_bacapp;
5588
static int ett_bacapp_control;
5589
static int ett_bacapp_tag;
5590
static int ett_bacapp_list;
5591
static int ett_bacapp_value;
5592
static int ett_bacapp_object_identifier;
5593
5594
static expert_field ei_bacapp_bad_length;
5595
static expert_field ei_bacapp_bad_tag;
5596
static expert_field ei_bacapp_opening_tag;
5597
5598
static int32_t propertyIdentifier = -1;
5599
static int32_t propertyArrayIndex = -1;
5600
static uint32_t object_type = 4096;
5601
5602
static uint8_t bacapp_flags;
5603
static uint8_t bacapp_seq;
5604
5605
/* Defined to allow vendor identifier registration of private transfer dissectors */
5606
static dissector_table_t bacapp_dissector_table;
5607
5608
5609
/* Stat: BACnet Packets sorted by IP */
5610
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
14
{
5811
14
    stats_tree_register("bacapp", "bacapp_ip", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by IP", 0,
5812
14
        bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
5813
14
    stats_tree_register("bacapp", "bacapp_service", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Service", 0,
5814
14
        bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
5815
14
    stats_tree_register("bacapp", "bacapp_objectid", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Object Type", 0,
5816
14
        bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
5817
14
    stats_tree_register("bacapp", "bacapp_instanceid", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Instance ID", 0,
5818
14
        bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
5819
14
}
5820
5821
/* 'data' must be allocated with wmem packet scope */
5822
static int
5823
updateBacnetInfoValue(int whichval, const char *data)
5824
80.9k
{
5825
80.9k
    if (whichval == BACINFO_SERVICE) {
5826
9.08k
        bacinfo.service_type = data;
5827
9.08k
        return 0;
5828
9.08k
    }
5829
71.8k
    if (whichval == BACINFO_INVOKEID) {
5830
8.42k
        bacinfo.invoke_id = data;
5831
8.42k
        return 0;
5832
8.42k
    }
5833
63.4k
    if (whichval == BACINFO_OBJECTID) {
5834
31.7k
        bacinfo.object_ident = data;
5835
31.7k
        return 0;
5836
31.7k
    }
5837
31.7k
    if (whichval == BACINFO_INSTANCEID) {
5838
31.7k
        bacinfo.instance_ident = data;
5839
31.7k
        return 0;
5840
31.7k
    }
5841
0
    return -1;
5842
31.7k
}
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
47
{
5872
47
    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
47
    if (seqno + 0x80 < prev_seqno) {
5880
0
        seqno += 0x100;
5881
47
    } else if (prev_seqno + 0x80 < seqno) {
5882
        /* Unlikely, out-of-order packet backwards over the wrap boundary. */
5883
14
        seqno -= 0x100;
5884
14
    }
5885
47
    return seqno;
5886
47
}
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
134k
{
5912
134k
    if (val < split_val)
5913
93.5k
        return val_to_str(scope, val, vs, fmt);
5914
41.4k
    else
5915
41.4k
        return val_to_str(scope, val, vs, split_fmt);
5916
134k
}
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.92M
{
5923
1.92M
    return (tag & 0x07) == 5;
5924
1.92M
}
5925
5926
static bool
5927
tag_is_opening(uint8_t tag)
5928
1.14M
{
5929
1.14M
    return (tag & 0x07) == 6;
5930
1.14M
}
5931
5932
static bool
5933
tag_is_closing(uint8_t tag)
5934
1.48M
{
5935
1.48M
    return (tag & 0x07) == 7;
5936
1.48M
}
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.54M
{
5944
2.54M
    return (tag & 0x08) != 0;
5945
2.54M
}
5946
5947
static bool
5948
tag_is_extended_tag_number(uint8_t tag)
5949
2.00M
{
5950
2.00M
    return ((tag & 0xF0) == 0xF0);
5951
2.00M
}
5952
5953
static uint32_t
5954
object_id_type(uint32_t object_identifier)
5955
32.3k
{
5956
32.3k
    return ((object_identifier >> 22) & 0x3FF);
5957
32.3k
}
5958
5959
static uint32_t
5960
object_id_instance(uint32_t object_identifier)
5961
95.1k
{
5962
95.1k
    return (object_identifier & 0x3FFFFF);
5963
95.1k
}
5964
5965
static unsigned
5966
fTagNo(tvbuff_t *tvb, unsigned offset)
5967
108k
{
5968
108k
    return (unsigned)(tvb_get_uint8(tvb, offset) >> 4);
5969
108k
}
5970
5971
static bool
5972
fUnsigned32(tvbuff_t *tvb, unsigned offset, uint32_t lvt, uint32_t *val)
5973
140k
{
5974
140k
    bool valid = true;
5975
5976
140k
    switch (lvt) {
5977
20.0k
    case 1:
5978
20.0k
        *val = tvb_get_uint8(tvb, offset);
5979
20.0k
        break;
5980
12.3k
    case 2:
5981
12.3k
        *val = tvb_get_ntohs(tvb, offset);
5982
12.3k
        break;
5983
6.62k
    case 3:
5984
6.62k
        *val = tvb_get_ntoh24(tvb, offset);
5985
6.62k
        break;
5986
8.01k
    case 4:
5987
8.01k
        *val = tvb_get_ntohl(tvb, offset);
5988
8.01k
        break;
5989
93.8k
    default:
5990
93.8k
        valid = false;
5991
93.8k
        break;
5992
140k
    }
5993
5994
140k
    return valid;
5995
140k
}
5996
5997
static bool
5998
fUnsigned64(tvbuff_t *tvb, unsigned offset, uint32_t lvt, uint64_t *val)
5999
56.2k
{
6000
56.2k
    bool valid = false;
6001
56.2k
    int64_t  value = 0;
6002
56.2k
    uint8_t  data;
6003
6004
56.2k
    if (lvt && (lvt <= 8)) {
6005
20.6k
        valid = true;
6006
76.4k
        for (unsigned i = 0; i < lvt; i++) {
6007
55.8k
            data = tvb_get_uint8(tvb, offset+i);
6008
55.8k
            value = (value << 8) + data;
6009
55.8k
        }
6010
20.6k
        *val = value;
6011
20.6k
    }
6012
6013
56.2k
    return valid;
6014
56.2k
}
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
8.83k
{
6025
8.83k
    bool valid = false;
6026
8.83k
    int64_t  value = 0;
6027
8.83k
    uint8_t  data;
6028
8.83k
    uint32_t i;
6029
6030
    /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
6031
8.83k
    if (lvt && (lvt <= 7)) {
6032
3.66k
        valid = true;
6033
3.66k
        data = tvb_get_uint8(tvb, offset);
6034
3.66k
        if ((data & 0x80) != 0)
6035
721
            value = (~UINT64_C(0) << 8) | data;
6036
2.94k
        else
6037
2.94k
            value = data;
6038
10.0k
        for (i = 1; i < lvt; i++) {
6039
6.37k
            data = tvb_get_uint8(tvb, offset+i);
6040
6.37k
            value = ((uint64_t)value << 8) | data;
6041
6.37k
        }
6042
3.66k
        *val = value;
6043
3.66k
    }
6044
6045
8.83k
    return valid;
6046
8.83k
}
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.45M
{
6052
1.45M
    proto_item *ti = NULL;
6053
1.45M
    uint8_t     tag;
6054
1.45M
    uint8_t     value;
6055
1.45M
    unsigned    tag_len = 1;
6056
1.45M
    unsigned    lvt_len = 1;    /* used for tree display of lvt */
6057
1.45M
    unsigned    lvt_offset;     /* used for tree display of lvt */
6058
6059
1.45M
    lvt_offset = offset;
6060
1.45M
    tag        = tvb_get_uint8(tvb, offset);
6061
1.45M
    *tag_info  = 0;
6062
1.45M
    *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.45M
    if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
6068
1.45M
    *tag_no = tag >> 4;
6069
1.45M
    if (tag_is_extended_tag_number(tag)) {
6070
48.7k
        *tag_no = tvb_get_uint8(tvb, offset + tag_len++);
6071
48.7k
    }
6072
1.45M
    if (tag_is_extended_value(tag)) {       /* length is more than 4 Bytes */
6073
56.1k
        lvt_offset += tag_len;
6074
56.1k
        value = tvb_get_uint8(tvb, lvt_offset);
6075
56.1k
        tag_len++;
6076
56.1k
        if (value == 254) { /* length is encoded with 16 Bits */
6077
163
            *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
6078
163
            tag_len += 2;
6079
163
            lvt_len += 2;
6080
55.9k
        } else if (value == 255) { /* length is encoded with 32 Bits */
6081
2.05k
            *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
6082
2.05k
            tag_len += 4;
6083
2.05k
            lvt_len += 4;
6084
2.05k
        } else
6085
53.8k
            *lvt = value;
6086
56.1k
    }
6087
6088
1.45M
    if (tree) {
6089
549k
        proto_tree *subtree;
6090
549k
        if (tag_is_opening(tag)) {
6091
47.7k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6092
47.7k
                    ett_bacapp_tag, &ti, "{[%u]", *tag_no );
6093
502k
        } else if (tag_is_closing(tag)) {
6094
27.9k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6095
27.9k
                    ett_bacapp_tag, &ti, "}[%u]", *tag_no );
6096
474k
        } else if (tag_is_context_specific(tag)) {
6097
122k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6098
122k
                    ett_bacapp_tag, &ti,
6099
122k
                    "Context Tag: %u, Length/Value/Type: %u", *tag_no, *lvt);
6100
351k
        } else {
6101
351k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
6102
351k
                    ett_bacapp_tag, &ti,
6103
351k
                    "Application Tag: %s, Length/Value/Type: %u",
6104
351k
                    val_to_str(pinfo->pool, *tag_no, BACnetApplicationTagNumber,
6105
351k
                        ASHRAE_Reserved_Fmt),
6106
351k
                    *lvt);
6107
351k
        }
6108
6109
        /* details if needed */
6110
549k
        proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
6111
549k
        if (tag_is_extended_tag_number(tag)) {
6112
18.0k
            proto_tree_add_uint_format(subtree,
6113
18.0k
                                       hf_BACnetContextTagNumber,
6114
18.0k
                                       tvb, offset, 1, tag,
6115
18.0k
                                       "Extended Tag Number");
6116
18.0k
            proto_tree_add_item(subtree,
6117
18.0k
                                hf_BACnetExtendedTagNumber,
6118
18.0k
                                tvb, offset + 1, 1, ENC_BIG_ENDIAN);
6119
531k
        } else {
6120
531k
            if (tag_is_context_specific(tag))
6121
156k
                proto_tree_add_item(subtree,
6122
156k
                                    hf_BACnetContextTagNumber,
6123
156k
                                    tvb, offset, 1, ENC_BIG_ENDIAN);
6124
375k
            else
6125
375k
                proto_tree_add_item(subtree,
6126
375k
                                    hf_BACnetApplicationTagNumber,
6127
375k
                                    tvb, offset, 1, ENC_BIG_ENDIAN);
6128
531k
        }
6129
549k
        if (tag_is_closing(tag) || tag_is_opening(tag))
6130
75.7k
            proto_tree_add_item(subtree,
6131
75.7k
                                hf_BACnetNamedTag,
6132
75.7k
                                tvb, offset, 1, ENC_BIG_ENDIAN);
6133
474k
        else if (tag_is_extended_value(tag)) {
6134
21.8k
            proto_tree_add_item(subtree,
6135
21.8k
                                hf_BACnetNamedTag,
6136
21.8k
                                tvb, offset, 1, ENC_BIG_ENDIAN);
6137
21.8k
            proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
6138
21.8k
                                tvb, lvt_offset, lvt_len, *lvt);
6139
21.8k
        } else
6140
452k
            proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
6141
452k
                                tvb, lvt_offset, lvt_len, *lvt);
6142
549k
    } /* if (tree) */
6143
6144
1.45M
    if (*lvt > tvb_reported_length(tvb)) {
6145
10.9k
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
6146
10.9k
                               "LVT length too long: %d > %d", *lvt,
6147
10.9k
                               tvb_reported_length(tvb));
6148
10.9k
        *lvt = 1;
6149
10.9k
    }
6150
6151
1.45M
    return tag_len;
6152
1.45M
}
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
903k
{
6158
903k
    return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
6159
903k
}
6160
6161
static unsigned
6162
fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6163
25.7k
{
6164
25.7k
    uint8_t     tag_no, tag_info;
6165
25.7k
    uint32_t    lvt;
6166
25.7k
    proto_tree *subtree;
6167
6168
25.7k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "%sNULL", label);
6169
25.7k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6170
6171
25.7k
    return offset + 1;
6172
25.7k
}
6173
6174
static unsigned
6175
fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6176
14.9k
{
6177
14.9k
    uint8_t     tag_no, tag_info;
6178
14.9k
    uint32_t    lvt      = 0;
6179
14.9k
    proto_tree *subtree;
6180
14.9k
    unsigned    bool_len = 1;
6181
6182
14.9k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6183
14.9k
    if (tag_info && lvt == 1) {
6184
512
        lvt = tvb_get_uint8(tvb, offset+1);
6185
512
        ++bool_len;
6186
512
    }
6187
6188
14.9k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, bool_len,
6189
14.9k
                             ett_bacapp_tag, NULL, "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
6190
14.9k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6191
6192
14.9k
    return offset + bool_len;
6193
14.9k
}
6194
6195
static unsigned
6196
fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6197
55.3k
{
6198
55.3k
    uint64_t    val = 0;
6199
55.3k
    uint8_t     tag_no, tag_info;
6200
55.3k
    uint32_t    lvt;
6201
55.3k
    unsigned    tag_len;
6202
55.3k
    proto_tree *subtree;
6203
6204
55.3k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6205
    /* only support up to an 8 byte (64-bit) integer */
6206
55.3k
    if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
6207
19.9k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6208
19.9k
            ett_bacapp_tag, NULL, "%s(Unsigned) %" PRIu64, label, val);
6209
35.3k
    else
6210
35.3k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6211
35.3k
            ett_bacapp_tag, NULL, "%s - %u octets (Unsigned)", label, lvt);
6212
55.3k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6213
6214
55.3k
    return offset+tag_len+lvt;
6215
55.3k
}
6216
6217
static unsigned
6218
fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int hf)
6219
105
{
6220
105
    uint8_t     tag_no, tag_info;
6221
105
    uint32_t    lvt, safe_lvt;
6222
105
    unsigned    tag_len;
6223
105
    proto_item *ti;
6224
105
    proto_tree *subtree;
6225
6226
105
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6227
6228
105
    if (lvt > 4)
6229
29
        safe_lvt = 4;
6230
76
    else
6231
76
        safe_lvt = lvt;
6232
6233
105
    ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
6234
6235
105
    if (lvt != safe_lvt)
6236
29
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
6237
29
                "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
6238
6239
105
    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6240
105
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6241
6242
105
    return offset+tag_len+lvt;
6243
105
}
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.1k
{
6250
32.1k
    uint32_t    val = 0;
6251
32.1k
    uint8_t     tag_no, tag_info;
6252
32.1k
    uint32_t    lvt;
6253
32.1k
    unsigned    tag_len;
6254
32.1k
    proto_tree *subtree;
6255
6256
32.1k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6257
    /* only support up to a 4 byte (32-bit) enumeration */
6258
32.1k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
6259
9.46k
        if (vs)
6260
8.08k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6261
8.08k
                ett_bacapp_tag, NULL, "%s %s (%u)", label,
6262
8.08k
                val_to_split_str(pinfo->pool, val, split_val, vs,
6263
8.08k
                                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt), val);
6264
1.38k
        else
6265
1.38k
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6266
1.38k
                ett_bacapp_tag, NULL, "%s %u", label, val);
6267
22.7k
    } else {
6268
22.7k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6269
22.7k
            ett_bacapp_tag, NULL, "%s - %u octets (enumeration)", label, lvt);
6270
22.7k
    }
6271
6272
32.1k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6273
6274
32.1k
    return offset+tag_len+lvt;
6275
32.1k
}
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
12.1k
{
6281
12.1k
    return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
6282
12.1k
}
6283
6284
static unsigned
6285
fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6286
7.77k
{
6287
7.77k
    int64_t     val = 0;
6288
7.77k
    uint8_t     tag_no, tag_info;
6289
7.77k
    uint32_t    lvt;
6290
7.77k
    unsigned    tag_len;
6291
7.77k
    proto_tree *subtree;
6292
6293
7.77k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6294
7.77k
    if (fSigned64(tvb, offset + tag_len, lvt, &val))
6295
3.00k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6296
3.00k
            ett_bacapp_tag, NULL, "%s(Signed) %" PRId64, label, val);
6297
4.77k
    else
6298
4.77k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6299
4.77k
            ett_bacapp_tag, NULL, "%s - %u octets (Signed)", label, lvt);
6300
7.77k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6301
6302
7.77k
    return offset+tag_len+lvt;
6303
7.77k
}
6304
6305
static unsigned
6306
fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6307
7.10k
{
6308
7.10k
    uint8_t     tag_no, tag_info;
6309
7.10k
    uint32_t    lvt;
6310
7.10k
    unsigned    tag_len;
6311
7.10k
    float       f_val;
6312
7.10k
    proto_tree *subtree;
6313
6314
7.10k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6315
7.10k
    f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
6316
7.10k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 4+tag_len,
6317
7.10k
        ett_bacapp_tag, NULL, "%s%f (Real)", label, f_val);
6318
7.10k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6319
6320
7.10k
    return offset+tag_len+4;
6321
7.10k
}
6322
6323
static unsigned
6324
fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6325
1.77k
{
6326
1.77k
    uint8_t     tag_no, tag_info;
6327
1.77k
    uint32_t    lvt;
6328
1.77k
    unsigned    tag_len;
6329
1.77k
    double      d_val;
6330
1.77k
    proto_tree  *subtree;
6331
6332
1.77k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6333
1.77k
    d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
6334
1.77k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 8+tag_len,
6335
1.77k
        ett_bacapp_tag, NULL, "%s%f (Double)", label, d_val);
6336
1.77k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6337
6338
1.77k
    return offset+tag_len+8;
6339
1.77k
}
6340
6341
static unsigned
6342
fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6343
35.2k
{
6344
35.2k
    uint32_t    val = 0, lvt;
6345
35.2k
    uint8_t     tag_no, tag_info;
6346
35.2k
    proto_item *ti;
6347
35.2k
    proto_tree *subtree;
6348
35.2k
    unsigned    tag_len;
6349
6350
35.2k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6351
35.2k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6352
6.71k
    {
6353
6.71k
        ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
6354
6.71k
            tvb, offset, lvt+tag_len, val);
6355
6.71k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6356
6.71k
    }
6357
28.5k
    else
6358
28.5k
    {
6359
28.5k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6360
28.5k
            ett_bacapp_tag, NULL, "Process Identifier - %u octets (Signed)", lvt);
6361
28.5k
    }
6362
35.2k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6363
35.2k
    offset += tag_len + lvt;
6364
6365
35.2k
    return offset;
6366
35.2k
}
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
21.9k
{
6371
    // tag vars
6372
21.9k
    uint32_t    lvt;
6373
21.9k
    uint8_t     tag_no, tag_info;
6374
21.9k
    unsigned    tag_len;
6375
21.9k
    unsigned    curr_offset = offset;
6376
    // tree vars
6377
21.9k
    proto_item *tree_item = NULL;
6378
21.9k
    proto_tree *subtree = NULL;
6379
    // dissection vars
6380
21.9k
    unsigned    bool_len = 1;
6381
21.9k
    uint64_t    unsigned_val = 0;
6382
21.9k
    int64_t     signed_val = 0;
6383
21.9k
    float       float_val;
6384
21.9k
    double      double_val;
6385
21.9k
    uint32_t    enum_index = 0;
6386
21.9k
    uint32_t    object_id;
6387
6388
21.9k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6389
21.9k
    switch(type) {
6390
9.81k
        case BACAPP_PRESENT_VALUE_NULL:
6391
9.81k
            tree_item = proto_tree_add_string(tree, hf_bacapp_present_value_null, tvb, offset, lvt+tag_len, "NULL");
6392
9.81k
            curr_offset += 1;
6393
9.81k
            break;
6394
1.21k
        case BACAPP_PRESENT_VALUE_BOOL:
6395
1.21k
            if (tag_info && lvt == 1) {
6396
0
                lvt = tvb_get_uint8(tvb, offset+1);
6397
0
                bool_len++;
6398
0
            }
6399
1.21k
            tree_item = proto_tree_add_boolean(tree, hf_bacapp_present_value_bool, tvb, offset, bool_len, lvt);
6400
1.21k
            curr_offset += bool_len;
6401
1.21k
            break;
6402
951
        case BACAPP_PRESENT_VALUE_UNSIGNED:
6403
951
            if (fUnsigned64(tvb, offset + tag_len, lvt, &unsigned_val))
6404
444
                tree_item = proto_tree_add_uint64(tree, hf_bacapp_present_value_unsigned, tvb, offset, lvt+tag_len, unsigned_val);
6405
951
            curr_offset += tag_len + lvt;
6406
951
            break;
6407
1.06k
        case BACAPP_PRESENT_VALUE_SIGNED:
6408
1.06k
            if (fSigned64(tvb, offset + tag_len, lvt, &signed_val))
6409
631
                tree_item = proto_tree_add_int64(tree, hf_bacapp_present_value_signed, tvb, offset, lvt+tag_len, signed_val);
6410
1.06k
            curr_offset += tag_len + lvt;
6411
1.06k
            break;
6412
610
        case BACAPP_PRESENT_VALUE_REAL:
6413
610
            float_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
6414
610
            double_val = (double) float_val;
6415
610
            tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_real, tvb, offset, lvt+tag_len, double_val);
6416
610
            curr_offset += tag_len + lvt;
6417
610
            break;
6418
459
        case BACAPP_PRESENT_VALUE_DOUBLE:
6419
459
            double_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
6420
459
            tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_double, tvb, offset, lvt+tag_len, double_val);
6421
459
            curr_offset += tag_len + lvt;
6422
459
            break;
6423
975
        case BACAPP_PRESENT_VALUE_OCTET_STRING:
6424
975
            if (lvt > 0)
6425
408
                tree_item = proto_tree_add_item(tree, hf_bacapp_present_value_octet_string, tvb, offset, lvt+tag_len, ENC_NA);
6426
975
            curr_offset += tag_len + lvt;
6427
975
            break;
6428
448
        case BACAPP_PRESENT_VALUE_CHARACTER_STRING:
6429
448
            curr_offset = fCharacterStringBase(tvb, pinfo, tree, offset, NULL, true, false);
6430
448
            break;
6431
746
        case BACAPP_PRESENT_VALUE_BIT_STRING:
6432
746
            curr_offset = fBitStringTagVSBase(tvb, pinfo, tree, offset, NULL, NULL, true);
6433
746
            break;
6434
4.09k
        case BACAPP_PRESENT_VALUE_ENUM:
6435
4.09k
            if (fUnsigned32(tvb, offset+tag_len, lvt, &enum_index)) {
6436
1.83k
                if (vs) {
6437
1.44k
                    subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len, ett_bacapp_tag, NULL,
6438
1.44k
                        "Present Value (enum value): %s",
6439
1.44k
                        val_to_split_str(pinfo->pool, enum_index,
6440
1.44k
                                         split_val, vs,
6441
1.44k
                                         ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
6442
1.44k
                    proto_tree_add_uint(subtree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, enum_index);
6443
1.44k
                    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6444
1.44k
                } else {
6445
386
                    tree_item = proto_tree_add_uint(tree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, enum_index);
6446
386
                }
6447
1.83k
            }
6448
4.09k
            curr_offset += tag_len + lvt;
6449
4.09k
            break;
6450
389
        case BACAPP_PRESENT_VALUE_DATE:
6451
389
            curr_offset = fDate(tvb, pinfo, tree, offset, "Date: ");
6452
389
            break;
6453
550
        case BACAPP_PRESENT_VALUE_TIME:
6454
550
            curr_offset = fTime(tvb, pinfo, tree, offset, "Time: ");
6455
550
            break;
6456
602
        case BACAPP_PRESENT_VALUE_OBJECT_IDENTIFIER:
6457
602
            object_id   = tvb_get_ntohl(tvb, offset+tag_len);
6458
602
            object_type = object_id_type(object_id);
6459
602
            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len + 4, ett_bacapp_tag, NULL,
6460
602
                "Present Value (enum value): %s",
6461
602
                val_to_split_str(pinfo->pool, object_type,
6462
602
                                 128, BACnetObjectType,
6463
602
                                 ASHRAE_Reserved_Fmt,
6464
602
                                 Vendor_Proprietary_Fmt));
6465
602
            proto_tree_add_uint(subtree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, object_type);
6466
602
            fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6467
602
            curr_offset += tag_len + lvt;
6468
602
            break;
6469
0
        default:
6470
0
            curr_offset += tag_len + lvt;
6471
0
            break;
6472
21.9k
    }
6473
6474
21.7k
    if (tree_item != NULL && subtree == NULL) {
6475
13.9k
        subtree = proto_item_add_subtree(tree_item, ett_bacapp_value);
6476
13.9k
        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6477
13.9k
    }
6478
6479
21.7k
    return curr_offset;
6480
21.9k
}
6481
6482
static unsigned
6483
fEventType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6484
4.30k
{
6485
4.30k
    uint32_t    val = 0, lvt;
6486
4.30k
    uint8_t     tag_no, tag_info;
6487
4.30k
    proto_item *ti;
6488
4.30k
    proto_tree *subtree;
6489
4.30k
    unsigned    tag_len;
6490
6491
4.30k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6492
4.30k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6493
2.71k
    {
6494
2.71k
        ti = proto_tree_add_uint(tree, hf_bacapp_event_type,
6495
2.71k
            tvb, offset, lvt+tag_len, val);
6496
2.71k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6497
2.71k
    }
6498
1.59k
    else
6499
1.59k
    {
6500
1.59k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6501
1.59k
            ett_bacapp_tag, NULL, "Event Type - %u octets (Signed)", lvt);
6502
1.59k
    }
6503
4.30k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6504
4.30k
    offset += tag_len + lvt;
6505
6506
4.30k
    return offset;
6507
4.30k
}
6508
6509
static unsigned
6510
fNotifyType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6511
5.21k
{
6512
5.21k
    uint32_t    val = 0, lvt;
6513
5.21k
    uint8_t     tag_no, tag_info;
6514
5.21k
    proto_item *ti;
6515
5.21k
    proto_tree *subtree;
6516
5.21k
    unsigned    tag_len;
6517
6518
5.21k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6519
5.21k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6520
2.12k
    {
6521
2.12k
        ti = proto_tree_add_uint(tree, hf_bacapp_notify_type,
6522
2.12k
            tvb, offset, lvt+tag_len, val);
6523
2.12k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6524
2.12k
    }
6525
3.09k
    else
6526
3.09k
    {
6527
3.09k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6528
3.09k
            ett_bacapp_tag, NULL, "Notify Type - %u octets (Signed)", lvt);
6529
3.09k
    }
6530
5.21k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6531
5.21k
    offset += tag_len + lvt;
6532
6533
5.21k
    return offset;
6534
5.21k
}
6535
6536
static unsigned
6537
fToState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6538
3.37k
{
6539
3.37k
    uint32_t    val = 0, lvt;
6540
3.37k
    uint8_t     tag_no, tag_info;
6541
3.37k
    proto_item *ti;
6542
3.37k
    proto_tree *subtree;
6543
3.37k
    unsigned    tag_len;
6544
6545
3.37k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6546
3.37k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6547
1.51k
    {
6548
1.51k
        ti = proto_tree_add_uint(tree, hf_bacapp_tag_to_state,
6549
1.51k
            tvb, offset, lvt+tag_len, val);
6550
1.51k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6551
1.51k
    }
6552
1.85k
    else
6553
1.85k
    {
6554
1.85k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6555
1.85k
            ett_bacapp_tag, NULL, "To State - %u octets (Signed)", lvt);
6556
1.85k
    }
6557
3.37k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6558
3.37k
    offset += tag_len + lvt;
6559
6560
3.37k
    return offset;
6561
3.37k
}
6562
6563
static unsigned
6564
fFromState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6565
2.81k
{
6566
2.81k
    uint32_t    val = 0, lvt;
6567
2.81k
    uint8_t     tag_no, tag_info;
6568
2.81k
    proto_item *ti;
6569
2.81k
    proto_tree *subtree;
6570
2.81k
    unsigned    tag_len;
6571
6572
2.81k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6573
2.81k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6574
1.33k
    {
6575
1.33k
        ti = proto_tree_add_uint(tree, hf_bacapp_tag_from_state,
6576
1.33k
            tvb, offset, lvt+tag_len, val);
6577
1.33k
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6578
1.33k
    }
6579
1.48k
    else
6580
1.48k
    {
6581
1.48k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6582
1.48k
            ett_bacapp_tag, NULL, "From State - %u octets (Signed)", lvt);
6583
1.48k
    }
6584
2.81k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6585
2.81k
    offset += tag_len + lvt;
6586
6587
2.81k
    return offset;
6588
2.81k
}
6589
6590
static unsigned
6591
fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6592
24.7k
{
6593
24.7k
    uint32_t    val = 0, lvt;
6594
24.7k
    uint8_t     tag_no, tag_info;
6595
24.7k
    proto_tree *subtree;
6596
24.7k
    unsigned    tag_len;
6597
6598
24.7k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6599
24.7k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
6600
3.98k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6601
3.98k
            ett_bacapp_tag, NULL,
6602
3.98k
            "%s (hh.mm.ss): %d.%02d.%02d%s",
6603
3.98k
            label,
6604
3.98k
            (val / 3600), ((val % 3600) / 60), (val % 60),
6605
3.98k
            val == 0 ? " (indefinite)" : "");
6606
20.7k
    else
6607
20.7k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6608
20.7k
            ett_bacapp_tag, NULL,
6609
20.7k
            "%s - %u octets (Signed)", label, lvt);
6610
24.7k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6611
6612
24.7k
    return offset+tag_len+lvt;
6613
24.7k
}
6614
6615
static unsigned
6616
fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6617
219
{
6618
219
    uint32_t    month, weekOfMonth, dayOfWeek;
6619
219
    uint8_t     tag_no, tag_info;
6620
219
    uint32_t    lvt;
6621
219
    unsigned    tag_len;
6622
219
    proto_tree *subtree;
6623
6624
219
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6625
219
    month = tvb_get_uint8(tvb, offset+tag_len);
6626
219
    weekOfMonth = tvb_get_uint8(tvb, offset+tag_len+1);
6627
219
    dayOfWeek = tvb_get_uint8(tvb, offset+tag_len+2);
6628
219
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6629
219
                 ett_bacapp_tag, NULL, "%s %s, %s",
6630
219
                 val_to_str(pinfo->pool, month, months, "month (%d) not found"),
6631
219
                 val_to_str(pinfo->pool, weekOfMonth, weekofmonth, "week of month (%d) not found"),
6632
219
                 val_to_str(pinfo->pool, dayOfWeek, day_of_week, "day of week (%d) not found"));
6633
219
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6634
6635
219
    return offset+tag_len+lvt;
6636
219
}
6637
6638
static unsigned
6639
fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6640
10.2k
{
6641
10.2k
    uint32_t    year, month, day, weekday;
6642
10.2k
    uint8_t     tag_no, tag_info;
6643
10.2k
    uint32_t    lvt;
6644
10.2k
    unsigned    tag_len;
6645
10.2k
    proto_tree *subtree;
6646
6647
10.2k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6648
10.2k
    year    = tvb_get_uint8(tvb, offset+tag_len);
6649
10.2k
    month   = tvb_get_uint8(tvb, offset+tag_len+1);
6650
10.2k
    day     = tvb_get_uint8(tvb, offset+tag_len+2);
6651
10.2k
    weekday = tvb_get_uint8(tvb, offset+tag_len+3);
6652
10.2k
    if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
6653
74
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6654
74
            ett_bacapp_tag, NULL,
6655
74
            "%sany", label);
6656
74
    }
6657
10.1k
    else if (year != 255) {
6658
9.90k
        year += 1900;
6659
9.90k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6660
9.90k
            ett_bacapp_tag, NULL,
6661
9.90k
            "%s%s %d, %d, (Day of Week = %s)",
6662
9.90k
            label, val_to_str(pinfo->pool, month,
6663
9.90k
                months,
6664
9.90k
                "month (%d) not found"),
6665
9.90k
            day, year, val_to_str(pinfo->pool, weekday,
6666
9.90k
                day_of_week,
6667
9.90k
                "(%d) not found"));
6668
9.90k
    } else {
6669
227
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6670
227
            ett_bacapp_tag, NULL,
6671
227
            "%s%s %d, any year, (Day of Week = %s)",
6672
227
            label, val_to_str(pinfo->pool, month, months, "month (%d) not found"),
6673
227
            day, val_to_str(pinfo->pool, weekday, day_of_week, "(%d) not found"));
6674
227
    }
6675
10.2k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6676
6677
10.2k
    return offset+tag_len+lvt;
6678
10.2k
}
6679
6680
static unsigned
6681
fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6682
15.5k
{
6683
15.5k
    uint32_t    hour, minute, second, msec, lvt;
6684
15.5k
    uint8_t     tag_no, tag_info;
6685
15.5k
    unsigned    tag_len;
6686
15.5k
    proto_tree *subtree;
6687
6688
15.5k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6689
15.5k
    hour    = tvb_get_uint8(tvb, offset+tag_len);
6690
15.5k
    minute  = tvb_get_uint8(tvb, offset+tag_len+1);
6691
15.5k
    second  = tvb_get_uint8(tvb, offset+tag_len+2);
6692
15.5k
    msec    = tvb_get_uint8(tvb, offset+tag_len+3);
6693
15.5k
    if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
6694
73
        subtree = proto_tree_add_subtree_format(tree, tvb, offset,
6695
73
            lvt+tag_len, ett_bacapp_tag, NULL,
6696
73
            "%sany", label);
6697
15.4k
    else
6698
15.4k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
6699
15.4k
            ett_bacapp_tag, NULL,
6700
15.4k
            "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
6701
15.4k
            label,
6702
15.4k
            hour > 12 ? hour - 12 : hour,
6703
15.4k
            minute, second, msec,
6704
15.4k
            hour >= 12 ? "P.M." : "A.M.",
6705
15.4k
            hour, minute, second, msec);
6706
15.5k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6707
6708
15.5k
    return offset+tag_len+lvt;
6709
15.5k
}
6710
6711
static unsigned
6712
fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6713
6.76k
{
6714
6.76k
    proto_tree *subtree = tree;
6715
6716
6.76k
    if (label != NULL) {
6717
6.76k
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
6718
6.76k
    }
6719
6.76k
    offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
6720
6.76k
    return fTime(tvb, pinfo, subtree, offset, "Time: ");
6721
6.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
20
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
6731
19
        lastoffset = offset;
6732
19
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6733
19
        if (tag_is_closing(tag_info)) {   /* closing Tag, but not for me */
6734
3
            return offset;
6735
3
        }
6736
16
        offset = fTime(tvb, pinfo, tree, offset, "Time: ");
6737
16
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
6738
6739
16
        if (offset <= lastoffset) break;    /* exit loop if nothing happens inside */
6740
16
    }
6741
1
    return offset;
6742
4
}
6743
6744
static unsigned
6745
fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6746
1.87k
{
6747
1.87k
    uint8_t tag_no, tag_info;
6748
1.87k
    uint32_t lvt;
6749
6750
1.87k
    switch (fTagNo(tvb, offset)) {
6751
1.37k
    case 0: /* Date */
6752
1.37k
        offset = fDate(tvb, pinfo, tree, offset, "Date: ");
6753
1.37k
        break;
6754
166
    case 1: /* dateRange */
6755
166
        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6756
166
        offset  = fDateRange(tvb, pinfo, tree, offset);
6757
166
        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6758
166
        break;
6759
219
    case 2: /* BACnetWeekNDay */
6760
219
        offset = fWeekNDay(tvb, pinfo, tree, offset);
6761
219
        break;
6762
122
    default:
6763
122
        return offset;
6764
1.87k
    }
6765
6766
1.75k
    return offset;
6767
1.87k
}
6768
6769
static unsigned
6770
fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6771
69
{
6772
69
    uint32_t    lvt     = 0;
6773
69
    proto_tree* subtree = tree;
6774
6775
69
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
6776
69
        subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
6777
6778
69
        offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
6779
69
        offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
6780
69
        offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
6781
69
    }
6782
69
    return offset;
6783
69
}
6784
6785
static unsigned
6786
fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
6787
15.1k
{
6788
15.1k
    uint8_t tag_no = 0, tag_info = 0;
6789
15.1k
    uint32_t lvt    = 0;
6790
6791
15.1k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {   /* don't loop, it's a CHOICE */
6792
15.0k
        switch (fTagNo(tvb, offset)) {
6793
6.61k
        case 0: /* time */
6794
6.61k
            offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
6795
6.61k
            break;
6796
1.05k
        case 1: /* sequenceNumber */
6797
1.05k
            offset = fUnsignedTag(tvb, pinfo, tree, offset,
6798
1.05k
                label?label:"sequence number: ");
6799
1.05k
            break;
6800
470
        case 2: /* dateTime */
6801
470
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6802
470
            offset  = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
6803
470
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6804
470
            break;
6805
6.95k
        default:
6806
6.95k
            return offset;
6807
15.0k
        }
6808
15.0k
    }
6809
6810
8.07k
    return offset;
6811
15.1k
}
6812
6813
6814
static unsigned
6815
fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6816
225
{
6817
225
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
6818
225
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
6819
225
    }
6820
225
    return offset;
6821
225
}
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
130
{
6838
130
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
6839
130
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
6840
130
                                             "valid Days: ", BACnetDaysOfWeek);
6841
130
        offset = fTime(tvb, pinfo, tree, offset, "from time: ");
6842
130
        offset = fTime(tvb, pinfo, tree, offset, "to time: ");
6843
130
        offset = fRecipient(tvb, pinfo, tree, offset);
6844
130
        offset = fProcessId(tvb, pinfo, tree, offset);
6845
130
        offset = fApplicationTypes(tvb, pinfo, tree, offset,
6846
130
                                    "issue confirmed notifications: ");
6847
130
        offset = fBitStringTagVS(tvb, pinfo, tree, offset,
6848
130
                                  "transitions: ", BACnetEventTransitionBits);
6849
130
    }
6850
130
    return offset;
6851
130
}
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.54k
{
6857
3.54k
    char       *tmp;
6858
3.54k
    unsigned    start   = offset;
6859
3.54k
    uint8_t     tag_no, tag_info;
6860
3.54k
    proto_tree *subtree = tree;
6861
6862
3.54k
    offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6863
6864
3.54k
    if (lvt > 0) {
6865
1.78k
        tmp = tvb_bytes_to_str(pinfo->pool, tvb, offset, lvt);
6866
1.78k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt,
6867
1.78k
                    ett_bacapp_tag, NULL, "%s %s", label, tmp);
6868
1.78k
        offset += lvt;
6869
1.78k
    }
6870
6871
3.54k
    fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6872
6873
3.54k
    return offset;
6874
3.54k
}
6875
6876
static unsigned
6877
fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt)
6878
1.00k
{
6879
1.00k
    unsigned start = offset;
6880
1.00k
    uint8_t tag_no, tag_info;
6881
1.00k
    proto_tree* subtree = tree;
6882
6883
1.00k
    offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6884
6885
    /* just add the label, with the tagHeader information in its subtree */
6886
1.00k
    subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, label);
6887
6888
1.00k
    if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
6889
153
        proto_tree_add_item(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ENC_BIG_ENDIAN);
6890
153
        proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, ENC_BIG_ENDIAN);
6891
852
    } else if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
6892
3
        proto_tree_add_item(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, ENC_NA);
6893
3
        proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, ENC_BIG_ENDIAN);
6894
849
    } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
6895
849
        subtree = proto_tree_add_subtree(tree, tvb, offset, lvt,
6896
849
                ett_bacapp_tag, NULL, tvb_bytes_to_str(pinfo->pool, tvb, offset, lvt));
6897
849
    }
6898
1.00k
    offset += lvt;
6899
6900
1.00k
    fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6901
6902
1.00k
    return offset;
6903
1.00k
}
6904
6905
static unsigned
6906
fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6907
1.97k
{
6908
1.97k
    uint8_t tag_no, tag_info;
6909
1.97k
    uint32_t lvt;
6910
1.97k
    unsigned   offs;
6911
6912
1.97k
    offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
6913
1.97k
    offs   = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6914
1.97k
    if (lvt == 0) {
6915
943
        proto_tree_add_item(tree, hf_bacapp_tag_mac_address_broadcast, tvb, offset, offs, ENC_NA);
6916
943
        offset += offs;
6917
943
    } else
6918
1.03k
        offset  = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
6919
6920
1.97k
    return offset;
6921
1.97k
}
6922
6923
static unsigned
6924
fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
6925
386
{
6926
386
    offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
6927
386
    return fAddress(tvb, pinfo, tree, offset);
6928
386
}
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
32.1k
{
6947
32.1k
    uint8_t     tag_no, tag_info;
6948
32.1k
    uint32_t    lvt;
6949
32.1k
    unsigned    tag_length;
6950
32.1k
    proto_tree *subtree;
6951
32.1k
    uint32_t    object_id;
6952
6953
32.1k
    tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6954
32.1k
    object_id   = tvb_get_ntohl(tvb, offset+tag_length);
6955
32.1k
    object_type = object_id_type(object_id);
6956
32.1k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_length + 4,
6957
32.1k
            ett_bacapp_tag, NULL, "%s: %s, %u", proto_registrar_get_name(hfid),
6958
32.1k
            val_to_split_str(pinfo->pool, object_type,
6959
32.1k
                128,
6960
32.1k
                BACnetObjectType,
6961
32.1k
                ASHRAE_Reserved_Fmt,
6962
32.1k
                Vendor_Proprietary_Fmt),
6963
32.1k
            object_id_instance(object_id));
6964
6965
32.1k
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
6966
32.1k
            val_to_split_str(pinfo->pool, object_type,
6967
32.1k
                128,
6968
32.1k
                BACnetObjectType,
6969
32.1k
                ASHRAE_Reserved_Fmt,
6970
32.1k
                Vendor_Proprietary_Fmt),
6971
32.1k
            object_id_instance(object_id));
6972
6973
    /* update BACnet Statistics */
6974
32.1k
    updateBacnetInfoValue(BACINFO_OBJECTID,
6975
32.1k
                  wmem_strdup(pinfo->pool,
6976
32.1k
                    val_to_split_str(pinfo->pool, object_type, 128,
6977
32.1k
                                     BACnetObjectType, ASHRAE_Reserved_Fmt,
6978
32.1k
                                     Vendor_Proprietary_Fmt)));
6979
32.1k
    updateBacnetInfoValue(BACINFO_INSTANCEID,
6980
32.1k
                  wmem_strdup_printf(pinfo->pool,
6981
32.1k
                    "Instance ID: %u",
6982
32.1k
                    object_id_instance(object_id)));
6983
6984
    /* here are the details of how we arrived at the above text */
6985
32.1k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6986
32.1k
    offset += tag_length;
6987
32.1k
    static int * const object_identifier_fields[] = {
6988
32.1k
        &hf_bacapp_objectType,
6989
32.1k
        &hf_bacapp_instanceNumber,
6990
32.1k
        NULL
6991
32.1k
    };
6992
32.1k
    proto_tree_add_bitmask_with_flags(subtree, tvb, offset, hfid,
6993
32.1k
        ett_bacapp_object_identifier, object_identifier_fields, ENC_BIG_ENDIAN, BMT_NO_APPEND);
6994
32.1k
    offset += 4;
6995
6996
32.1k
    return offset;
6997
32.1k
}
6998
6999
static unsigned
7000
fObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7001
196
{
7002
196
    return fCharacterStringBase(tvb, pinfo, tree, offset, "Object Name", false, true);
7003
196
}
7004
7005
static unsigned
7006
fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7007
4.27k
{
7008
4.27k
    uint8_t tag_no, tag_info;
7009
4.27k
    uint32_t lvt;
7010
7011
4.27k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7012
4.27k
    if (tag_no < 2) {
7013
1.22k
        if (tag_no == 0) { /* device */
7014
1.13k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
7015
1.13k
        }
7016
84
        else {  /* address */
7017
84
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7018
84
            offset  = fAddress(tvb, pinfo, tree, offset);
7019
84
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7020
84
        }
7021
1.22k
    }
7022
4.27k
    return offset;
7023
4.27k
}
7024
7025
static unsigned
7026
fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7027
569
{
7028
569
    unsigned    lastoffset = 0;
7029
569
    uint8_t     tag_no, tag_info;
7030
569
    uint32_t    lvt;
7031
569
    proto_tree *orgtree    = tree;
7032
569
    proto_tree *subtree;
7033
7034
    /* beginning of new item - indent and label */
7035
569
    tree = proto_tree_add_subtree(orgtree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient Process" );
7036
7037
1.07k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7038
1.06k
        lastoffset = offset;
7039
7040
1.06k
        switch (fTagNo(tvb, offset)) {
7041
511
        case 0: /* recipient */
7042
511
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
7043
511
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
7044
511
            offset  = fRecipient(tvb, pinfo, subtree, offset);
7045
511
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
7046
511
            break;
7047
273
        case 1: /* processId */
7048
273
            offset = fProcessId(tvb, pinfo, tree, offset);
7049
273
            lastoffset = offset;
7050
273
            break;
7051
282
        default:
7052
282
            break;
7053
1.06k
        }
7054
1.05k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7055
1.05k
    }
7056
559
    return offset;
7057
569
}
7058
7059
static unsigned
7060
fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7061
64
{
7062
64
    unsigned    lastoffset = 0;
7063
64
    uint8_t     tag_no, tag_info;
7064
64
    uint32_t    lvt;
7065
64
    proto_tree *subtree;
7066
64
    proto_tree *orgtree    = tree;
7067
64
    unsigned    itemno     = 1;
7068
7069
822
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7070
820
        lastoffset = offset;
7071
820
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7072
820
        if (tag_is_closing(tag_info) ) {
7073
8
            return offset;
7074
8
        }
7075
812
        switch (tag_no) {
7076
7077
135
        case 0: /* recipient */
7078
            /* beginning of new item in list */
7079
135
            tree = proto_tree_add_subtree_format(orgtree, tvb, offset, 1,
7080
135
                ett_bacapp_value, NULL, "Subscription %d",itemno);    /* add tree label and indent */
7081
135
            itemno = itemno + 1;
7082
7083
135
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
7084
135
                ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
7085
135
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
7086
135
            offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
7087
135
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
7088
135
            break;
7089
115
        case 1: /* MonitoredPropertyReference */
7090
115
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
7091
115
                ett_bacapp_value, NULL, "Monitored Property Reference");
7092
115
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7093
115
            offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
7094
115
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7095
115
            break;
7096
324
        case 2: /* IssueConfirmedNotifications - boolean */
7097
324
            offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
7098
324
            break;
7099
87
        case 3: /* TimeRemaining */
7100
87
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
7101
87
            break;
7102
101
        case 4: /* COVIncrement */
7103
101
            offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
7104
101
            break;
7105
49
        default:
7106
49
            break;
7107
812
        }
7108
807
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7109
807
    }
7110
51
    return offset;
7111
64
}
7112
7113
static unsigned
7114
fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7115
251
{
7116
251
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
7117
251
    return fAddress(tvb, pinfo, tree, offset);
7118
251
}
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
799
{
7124
799
    unsigned    lastoffset = 0, len;
7125
799
    uint8_t     tag_no, tag_info;
7126
799
    uint32_t    lvt;
7127
799
    proto_tree *subtree    = tree;
7128
7129
    /* set the optional global properties to indicate not-used */
7130
799
    propertyArrayIndex = -1;
7131
8.00k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7132
7.91k
        lastoffset = offset;
7133
7.91k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7134
7.91k
        if (tag_is_closing(tag_info) ) {
7135
933
            if (tag_no == tag_match) {
7136
63
                return offset;
7137
63
            }
7138
870
            offset += len;
7139
870
            subtree = tree;
7140
870
            continue;
7141
933
        }
7142
6.98k
        switch (tag_no) {
7143
7144
2.27k
        case 0: /* deviceIdentifier */
7145
2.27k
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_device_identifier);
7146
2.27k
            break;
7147
390
        case 1: /* objectIdentifier */
7148
390
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
7149
390
            break;
7150
572
        case 2: /* propertyIdentifier */
7151
572
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
7152
572
            break;
7153
598
        case 3: /* propertyArrayIndex */
7154
598
            offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
7155
598
            break;
7156
454
        case 4: /* propertyValue */
7157
454
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
7158
454
            break;
7159
603
        case 5: /* priority */
7160
603
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
7161
603
            break;
7162
506
        case 6: /* postDelay */
7163
506
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
7164
506
            break;
7165
613
        case 7: /* quitOnFailure */
7166
613
            offset = fBooleanTag(tvb, pinfo, subtree, offset,
7167
613
                "Quit On Failure: ");
7168
613
            break;
7169
472
        case 8: /* writeSuccessful */
7170
472
            offset = fBooleanTag(tvb, pinfo, subtree, offset,
7171
472
                "Write Successful: ");
7172
472
            break;
7173
484
        default:
7174
484
            return offset;
7175
6.98k
        }
7176
6.39k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7177
6.39k
    }
7178
145
    return offset;
7179
799
}
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
865
{
7189
865
    unsigned    lastoffset = 0, len;
7190
865
    uint8_t     tag_no, tag_info;
7191
865
    uint32_t    lvt;
7192
865
    proto_tree *subtree    = tree;
7193
7194
3.00k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
7195
2.91k
        lastoffset = offset;
7196
2.91k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7197
2.91k
        if (tag_is_closing(tag_info)) {
7198
409
            if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
7199
17
                return offset;
7200
            /* print closing tag of action list too */
7201
392
            fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7202
392
            subtree = tree;
7203
392
            offset += len;
7204
392
            continue;
7205
409
        }
7206
2.50k
        if (tag_is_opening(tag_info)) {
7207
1.05k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "Action List");
7208
1.05k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
7209
1.05k
                &tag_no, &tag_info, &lvt);
7210
1.05k
        }
7211
2.50k
        switch (tag_no) {
7212
799
        case 0: /* BACnetActionCommand */
7213
799
            offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
7214
799
            break;
7215
1.70k
        default:
7216
1.70k
            break;
7217
2.50k
        }
7218
2.39k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
7219
2.39k
    }
7220
741
    return offset;
7221
865
}
7222
7223
static unsigned
7224
// NOLINTNEXTLINE(misc-no-recursion)
7225
fPropertyAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7226
842
{
7227
842
  unsigned    lastoffset = 0;
7228
842
  uint8_t     tag_no, tag_info;
7229
842
  uint32_t    lvt;
7230
842
  uint32_t    save_object_type;
7231
842
  uint32_t    save_inner_object_type;
7232
842
  int32_t     save_propertyIdentifier;
7233
7234
  /* save the external entry data because it might get overwritten here */
7235
842
  save_object_type = object_type;
7236
842
  save_propertyIdentifier = propertyIdentifier;
7237
7238
  /* inner object type might get overwritten by device id */
7239
842
  save_inner_object_type = object_type;
7240
7241
2.20k
  while (tvb_reported_length_remaining(tvb, offset) > 0) {
7242
2.02k
    lastoffset = offset;
7243
2.02k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7244
2.02k
    if (tag_is_closing(tag_info)) {
7245
150
        break;
7246
150
    }
7247
7248
1.87k
    switch (tag_no) {
7249
461
    case 0: /* objectIdentifier */
7250
461
        offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
7251
        /* save the local object type because device id might overwrite it */
7252
461
        save_inner_object_type = object_type;
7253
461
        break;
7254
125
    case 1: /* propertyIdentifier */
7255
125
        offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7256
125
        break;
7257
205
    case 2: /* propertyArrayIndex */
7258
205
        offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
7259
205
        break;
7260
87
    case 3: /* deviceIdentifier */
7261
87
        offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
7262
        /* restore the inner object type to decode the right property value */
7263
87
        object_type = save_inner_object_type;
7264
87
        break;
7265
506
    case 4: /* propertyValue */
7266
506
        offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
7267
        /* restore the external values for next loop */
7268
506
        object_type = save_object_type;
7269
506
        propertyIdentifier = save_propertyIdentifier;
7270
506
        break;
7271
53
    case 5: /* propertyAccessError */
7272
53
        if (tag_is_opening(tag_info)) {
7273
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7274
0
            offset = fError(tvb, pinfo, tree, offset);
7275
0
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7276
0
        }
7277
53
        else {
7278
53
            expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
7279
53
        }
7280
        /* restore the external values for next loop */
7281
53
        object_type = save_object_type;
7282
53
        propertyIdentifier = save_propertyIdentifier;
7283
53
        break;
7284
434
    default:
7285
434
        break;
7286
1.87k
    }
7287
7288
1.86k
    if (offset <= lastoffset) break;    /* nothing happened, exit loop */
7289
1.86k
  }
7290
7291
  /* restore the external values for next decoding */
7292
840
  object_type = save_object_type;
7293
840
  propertyIdentifier = save_propertyIdentifier;
7294
840
  return offset;
7295
842
}
7296
7297
static unsigned
7298
fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7299
10.7k
{
7300
10.7k
    uint8_t      tag_no, tag_info;
7301
10.7k
    uint32_t     lvt;
7302
10.7k
    unsigned     tag_len;
7303
10.7k
    proto_tree  *subtree;
7304
10.7k
    static const char *label = "Property Identifier";
7305
7306
10.7k
    propertyIdentifier = 0; /* global Variable */
7307
10.7k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7308
    /* can we decode this value? */
7309
10.7k
    if (fUnsigned32(tvb, offset+tag_len, lvt, (uint32_t *)&propertyIdentifier)) {
7310
8.58k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7311
8.58k
            ett_bacapp_tag, NULL,
7312
8.58k
            "%s: %s (%u)", label,
7313
8.58k
            val_to_split_str(pinfo->pool, propertyIdentifier, 512,
7314
8.58k
                             BACnetPropertyIdentifier,
7315
8.58k
                             ASHRAE_Reserved_Fmt,
7316
8.58k
                             Vendor_Proprietary_Fmt), propertyIdentifier);
7317
8.58k
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
7318
8.58k
                val_to_split_str(pinfo->pool, propertyIdentifier, 512,
7319
8.58k
                                 BACnetPropertyIdentifier,
7320
8.58k
                                 ASHRAE_Reserved_Fmt,
7321
8.58k
                                 Vendor_Proprietary_Fmt));
7322
8.58k
    } else {
7323
        /* property identifiers cannot be larger than 22-bits */
7324
2.12k
        return offset;
7325
2.12k
    }
7326
7327
8.58k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7328
8.58k
    proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
7329
8.58k
        offset+tag_len, lvt, ENC_BIG_ENDIAN);
7330
7331
8.58k
    return offset+tag_len+lvt;
7332
10.7k
}
7333
7334
static unsigned
7335
fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7336
2.72k
{
7337
2.72k
    uint8_t     tag_no, tag_info;
7338
2.72k
    uint32_t    lvt;
7339
2.72k
    unsigned    tag_len;
7340
2.72k
    proto_tree *subtree;
7341
7342
2.72k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7343
2.72k
    if (fUnsigned32(tvb, offset + tag_len, lvt, (uint32_t *)&propertyArrayIndex))
7344
1.68k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7345
1.68k
            ett_bacapp_tag, NULL, "property Array Index (Unsigned) %u", propertyArrayIndex);
7346
1.04k
    else
7347
1.04k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7348
1.04k
            ett_bacapp_tag, NULL, "property Array Index - %u octets (Unsigned)", lvt);
7349
2.72k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7350
7351
2.72k
    return offset+tag_len+lvt;
7352
2.72k
}
7353
7354
static unsigned
7355
fChannelValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7356
9.56k
{
7357
9.56k
  uint8_t     tag_no, tag_info;
7358
9.56k
  uint32_t    lvt;
7359
7360
9.56k
  if (tvb_reported_length_remaining(tvb, offset) > 0) {
7361
9.56k
      fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7362
9.56k
      if (tag_is_opening(tag_info) && tag_no == 0) {
7363
188
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7364
188
          offset = fLightingCommand(tvb, pinfo, tree, offset, "lighting-command: ");
7365
188
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7366
9.37k
      } else if (tag_is_opening(tag_info) && tag_no == 1) {
7367
124
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7368
124
          offset = fXyColor(tvb, pinfo, tree, offset, "xy-color: ");
7369
124
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7370
9.25k
      } else if (tag_is_opening(tag_info) && tag_no == 2) {
7371
265
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7372
265
          offset = fColorCommand(tvb, pinfo, tree, offset, "color-command: ");
7373
265
          offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7374
8.98k
      } else {
7375
8.98k
          if (tag_info) {
7376
2.40k
              offset = fContextTaggedValue(tvb, pinfo, tree, offset, label);
7377
6.58k
          } else {
7378
6.58k
              offset = fApplicationTypes(tvb, pinfo, tree, offset, label);
7379
6.58k
          }
7380
8.98k
      }
7381
9.56k
  }
7382
7383
9.56k
  return offset;
7384
9.56k
}
7385
7386
static unsigned
7387
fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7388
5.97k
{
7389
5.97k
    return fCharacterStringBase(tvb, pinfo, tree, offset, label, false, false);
7390
5.97k
}
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
6.62k
{
7395
6.62k
    uint8_t         tag_no, tag_info, character_set;
7396
6.62k
    uint32_t        lvt, l;
7397
6.62k
    unsigned        offs;
7398
6.62k
    const char     *coding;
7399
6.62k
    uint8_t        *out;
7400
6.62k
    proto_tree     *subtree;
7401
6.62k
    unsigned        start = offset;
7402
7403
6.62k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
7404
7405
6.61k
        offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7406
6.61k
        offset += offs;
7407
7408
6.61k
        character_set = tvb_get_uint8(tvb, offset);
7409
6.61k
        offset++;
7410
6.61k
        lvt--;
7411
7412
        /* Account for code page if DBCS */
7413
6.61k
        if (character_set == IBM_MS_DBCS) {
7414
92
            offset += 2;
7415
92
            lvt -= 2;
7416
92
        }
7417
7418
6.66k
        do {
7419
6.66k
            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
6.66k
            switch (character_set) {
7459
415
            case ANSI_X3_4:
7460
415
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UTF_8);
7461
415
                coding = "UTF-8";
7462
415
                break;
7463
92
            case IBM_MS_DBCS:
7464
92
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
7465
92
                coding = "IBM MS DBCS";
7466
92
                break;
7467
125
            case JIS_C_6226:
7468
125
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
7469
125
                coding = "JIS C 6226";
7470
125
                break;
7471
139
            case ISO_10646_UCS4:
7472
139
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UCS_4|ENC_BIG_ENDIAN);
7473
139
                coding = "ISO 10646 UCS-4";
7474
139
                break;
7475
66
            case ISO_10646_UCS2:
7476
66
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UCS_2|ENC_BIG_ENDIAN);
7477
66
                coding = "ISO 10646 UCS-2";
7478
66
                break;
7479
56
            case ISO_8859_1:
7480
56
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ISO_8859_1);
7481
56
                coding = "ISO 8859-1";
7482
56
                break;
7483
5.74k
            default:
7484
                /* Assume this is some form of extended ASCII, with one-byte code points for ASCII characters */
7485
5.74k
                out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
7486
5.74k
                coding = "unknown";
7487
5.74k
                break;
7488
6.66k
            }
7489
7490
6.40k
            if (present_val_dissect) {
7491
439
                subtree = proto_tree_add_subtree(tree, tvb, offset, l, ett_bacapp_tag, NULL, "present-value");
7492
439
                proto_tree_add_string(subtree, hf_bacapp_present_value_char_string, tvb, offset, l, (const char*) out);
7493
5.96k
            } else if (object_name_dissect) {
7494
182
                subtree = proto_tree_add_subtree(tree, tvb, offset, l, ett_bacapp_tag, NULL, label);
7495
182
                proto_tree_add_string(subtree, hf_bacapp_object_name, tvb, offset, l, (const char*) out);
7496
5.77k
            } else {
7497
5.77k
                subtree = proto_tree_add_subtree_format(tree, tvb, offset, l, ett_bacapp_tag, NULL,
7498
5.77k
                                    "%s%s '%s'", label, coding, out);
7499
5.77k
            }
7500
7501
6.40k
            lvt    -= l;
7502
6.40k
            offset += l;
7503
6.40k
        } while (lvt > 0);
7504
7505
6.35k
        fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
7506
6.35k
        proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
7507
7508
6.35k
        if (character_set == IBM_MS_DBCS) {
7509
79
            proto_tree_add_item(subtree, hf_BACnetCodePage, tvb, start+offs+1, 2, ENC_BIG_ENDIAN);
7510
79
        }
7511
        /* XXX - put the string value here */
7512
6.35k
    }
7513
6.36k
    return offset;
7514
6.62k
}
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
6.39k
{
7520
6.39k
    return fBitStringTagVSBase(tvb, pinfo, tree, offset, label, src, false);
7521
6.39k
}
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
7.14k
{
7527
7.14k
    uint8_t         tag_no, tag_info, tmp;
7528
7.14k
    int             j, unused, skip;
7529
7.14k
    unsigned        start = offset;
7530
7.14k
    unsigned        offs;
7531
7.14k
    uint32_t        lvt, i, numberOfBytes;
7532
7.14k
    char            bf_arr[256 + 1];
7533
7.14k
    proto_tree     *subtree = tree;
7534
7535
7.14k
    offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7536
7.14k
    numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
7537
7.14k
    offset += offs;
7538
7.14k
    unused  = tvb_get_uint8(tvb, offset); /* get the unused Bits */
7539
7540
7.14k
    memset(bf_arr, 0, sizeof(bf_arr));
7541
7.14k
    skip = 0;
7542
40.7k
    for (i = 0; i < numberOfBytes; i++) {
7543
33.5k
        tmp = tvb_get_uint8(tvb, (offset)+i + 1);
7544
33.5k
        if (i == numberOfBytes - 1) { skip = unused; }
7545
266k
        for (j = 0; j < 8 - skip; j++) {
7546
233k
            bf_arr[MIN(sizeof(bf_arr) - 2, (i * 8) + j)] = tmp & (1 << (7 - j)) ? 'T' : 'F';
7547
233k
        }
7548
33.5k
    }
7549
7550
7.14k
    if (!present_val_dissect) {
7551
6.12k
        subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
7552
6.12k
                                    ett_bacapp_tag, NULL,
7553
6.12k
                                    "%s(Bit String) (%s)", label, bf_arr);
7554
6.12k
    } else {
7555
1.02k
        subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
7556
1.02k
                                    ett_bacapp_tag, NULL,
7557
1.02k
                                    "present-value (%s)", bf_arr);
7558
1.02k
    }
7559
7560
7.14k
    fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
7561
7.14k
    proto_tree_add_item(subtree, hf_bacapp_unused_bits, tvb, offset, 1, ENC_NA);
7562
7.14k
    memset(bf_arr, 0, sizeof(bf_arr));
7563
7.14k
    skip = 0;
7564
24.9k
    for (i = 0; i < numberOfBytes; i++) {
7565
17.7k
        tmp = tvb_get_uint8(tvb, (offset)+i+1);
7566
17.7k
        if (i == numberOfBytes-1) { skip = unused; }
7567
126k
        for (j = 0; j < 8-skip; j++) {
7568
108k
            if (src != NULL) {
7569
50.0k
                proto_tree_add_boolean_format(subtree, hf_bacapp_bit, tvb, offset+i+1, 1,
7570
50.0k
                                            (tmp & (1 << (7 - j))), "%s = %s",
7571
50.0k
                                            val_to_str(pinfo->pool, (unsigned) (i*8 +j), src, ASHRAE_Reserved_Fmt),
7572
50.0k
                                            (tmp & (1 << (7 - j))) ? "TRUE" : "FALSE");
7573
58.7k
            } else {
7574
58.7k
                bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
7575
58.7k
            }
7576
108k
        }
7577
17.7k
    }
7578
7579
7.14k
    if (src == NULL) {
7580
3.22k
        bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
7581
3.22k
        proto_tree_add_bytes_format(subtree, hf_bacapp_complete_bitstring, tvb, offset, lvt, NULL, "B'%s'", bf_arr);
7582
3.22k
    }
7583
7584
7.14k
    offset += lvt;
7585
7586
7.14k
    return offset;
7587
7.14k
}
7588
7589
static unsigned
7590
fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7591
1.94k
{
7592
1.94k
    return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
7593
1.94k
}
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
48.1k
{
7601
48.1k
    uint8_t tag_no, tag_info;
7602
48.1k
    uint32_t lvt;
7603
48.1k
    unsigned   tag_len;
7604
7605
48.1k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
7606
48.0k
        tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7607
48.0k
        if (!tag_is_context_specific(tag_info)) {
7608
42.6k
            switch (tag_no) {
7609
23.8k
            case 0: /** NULL 20.2.2 */
7610
23.8k
                offset = fNullTag(tvb, pinfo, tree, offset, label);
7611
23.8k
                break;
7612
3.20k
            case 1: /** BOOLEAN 20.2.3 */
7613
3.20k
                offset = fBooleanTag(tvb, pinfo, tree, offset, label);
7614
3.20k
                break;
7615
2.01k
            case 2: /** Unsigned Integer 20.2.4 */
7616
2.01k
                offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
7617
2.01k
                break;
7618
2.09k
            case 3: /** Signed Integer 20.2.5 */
7619
2.09k
                offset = fSignedTag(tvb, pinfo, tree, offset, label);
7620
2.09k
                break;
7621
956
            case 4: /** Real 20.2.6 */
7622
956
                offset = fRealTag(tvb, pinfo, tree, offset, label);
7623
956
                break;
7624
509
            case 5: /** Double 20.2.7 */
7625
509
                offset = fDoubleTag(tvb, pinfo, tree, offset, label);
7626
509
                break;
7627
1.92k
            case 6: /** Octet String 20.2.8 */
7628
1.92k
                offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
7629
1.92k
                break;
7630
679
            case 7: /** Character String 20.2.9 */
7631
679
                offset = fCharacterString(tvb, pinfo, tree, offset, label);
7632
679
                break;
7633
953
            case 8: /** Bit String 20.2.10 */
7634
953
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
7635
953
                break;
7636
1.06k
            case 9: /** Enumerated 20.2.11 */
7637
1.06k
                offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
7638
1.06k
                break;
7639
952
            case 10: /** Date 20.2.12 */
7640
952
                offset = fDate(tvb, pinfo, tree, offset, label);
7641
952
                break;
7642
1.03k
            case 11: /** Time 20.2.13 */
7643
1.03k
                offset = fTime(tvb, pinfo, tree, offset, label);
7644
1.03k
                break;
7645
874
            case 12: /** BACnetObjectIdentifier 20.2.14 */
7646
874
                offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
7647
874
                break;
7648
972
            case 13: /* reserved for ASHRAE */
7649
2.25k
            case 14:
7650
2.27k
            case 15:
7651
2.27k
                proto_tree_add_bytes_format(tree, hf_bacapp_reserved_ashrea, tvb, offset, lvt+tag_len, NULL, "%s'reserved for ASHRAE'", label);
7652
2.27k
                offset += lvt + tag_len;
7653
2.27k
                break;
7654
221
            default:
7655
221
                break;
7656
42.6k
            }
7657
42.6k
        }
7658
48.0k
    }
7659
47.8k
    return offset;
7660
48.1k
}
7661
7662
static unsigned
7663
fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7664
62
{
7665
62
    unsigned lastoffset = 0;
7666
7667
654
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7668
651
        lastoffset = offset;
7669
7670
651
        switch (fTagNo(tvb, offset)) {
7671
334
        case 0: /* percent */
7672
334
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
7673
334
            break;
7674
166
        case 1: /* level */
7675
166
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
7676
166
            break;
7677
95
        case 2: /* amount */
7678
95
            offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
7679
95
            break;
7680
56
        default:
7681
56
            return offset;
7682
651
        }
7683
592
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7684
592
    }
7685
3
    return offset;
7686
62
}
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
13.3k
{
7692
13.3k
    return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
7693
13.3k
}
7694
7695
static unsigned
7696
fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
7697
    const char *label)
7698
33.2k
{
7699
33.2k
    return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
7700
33.2k
}
7701
7702
static unsigned
7703
fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7704
8.96k
{
7705
8.96k
    uint8_t     tag_no, tag_info;
7706
8.96k
    uint32_t    lvt;
7707
8.96k
    unsigned    tag_len;
7708
8.96k
    proto_tree *subtree;
7709
8.96k
    int         tvb_len;
7710
7711
8.96k
    (void)label;
7712
8.96k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7713
    /* cap the the suggested length in case of bad data */
7714
8.96k
    tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
7715
8.96k
    if ((tvb_len >= 0) && ((uint32_t)tvb_len < lvt)) {
7716
79
        lvt = tvb_len;
7717
79
    }
7718
8.96k
    subtree = proto_tree_add_subtree_format(tree, tvb, offset+tag_len, lvt,
7719
8.96k
        ett_bacapp_tag, NULL, "Context Value (as %u DATA octets)", lvt);
7720
7721
8.96k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7722
7723
8.96k
    return offset + tag_len + lvt;
7724
8.96k
}
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
46
{
7734
46
    uint8_t tag_no, tag_info;
7735
46
    uint32_t lvt;
7736
46
    unsigned   lastoffset = 0;
7737
7738
296
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7739
296
        lastoffset = offset;
7740
296
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7741
296
        if (tag_is_closing(tag_info) ) {
7742
4
            return offset;
7743
4
            }
7744
292
        switch (tag_no) {
7745
190
        case 0: /* multiplier */
7746
190
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
7747
190
            break;
7748
61
        case 1: /* moduloDivide */
7749
61
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
7750
61
            break;
7751
41
        default:
7752
41
            return offset;
7753
292
        }
7754
250
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7755
250
    }
7756
0
    return offset;
7757
7758
46
}
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
40
{
7768
40
    uint8_t tag_no, tag_info;
7769
40
    uint32_t lvt;
7770
40
    unsigned   lastoffset = 0;
7771
7772
95
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7773
92
        lastoffset = offset;
7774
92
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7775
92
        if (tag_is_closing(tag_info) ) {
7776
1
            return offset;
7777
1
            }
7778
91
        switch (tag_no) {
7779
49
        case 0: /* floatScale */
7780
49
            offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
7781
49
            break;
7782
8
        case 1: /* integerScale */
7783
8
            offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
7784
8
            break;
7785
34
        default:
7786
34
            return offset;
7787
91
        }
7788
55
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7789
55
    }
7790
3
    return offset;
7791
40
}
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
185
{
7809
185
    uint8_t tag_no, tag_info;
7810
185
    uint32_t lvt;
7811
185
    unsigned   lastoffset = 0;
7812
7813
883
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7814
880
        lastoffset = offset;
7815
880
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7816
880
        if (tag_is_closing(tag_info) ) {
7817
7
            return offset;
7818
7
            }
7819
873
        switch (tag_no) {
7820
405
        case 0: /* timestamp */
7821
405
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7822
405
            offset  = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
7823
405
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7824
405
            break;
7825
149
        case 1: /* presentValue */
7826
149
            offset = fPresentValue(tvb, pinfo, tree, offset, NULL, 0, BACAPP_PRESENT_VALUE_UNSIGNED);
7827
149
            break;
7828
107
        case 2: /* accumulatedValue */
7829
107
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
7830
107
            break;
7831
40
        case 3: /* accumulatorStatus */
7832
40
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
7833
40
            break;
7834
172
        default:
7835
172
            return offset;
7836
873
        }
7837
698
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
7838
698
    }
7839
3
    return offset;
7840
185
}
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
110
{
7848
110
    uint8_t tag_no, tag_info;
7849
110
    uint32_t lvt;
7850
110
    unsigned   lastoffset = 0;
7851
7852
503
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7853
496
        lastoffset = offset;
7854
496
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7855
496
        if (tag_is_closing(tag_info) ) {
7856
5
            return offset;
7857
5
            }
7858
491
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
7859
491
        if ( offset <= lastoffset ) break;
7860
491
    }
7861
105
    return offset;
7862
110
}
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
52
{
7871
52
    uint8_t tag_no, tag_info;
7872
52
    uint32_t lvt;
7873
52
    unsigned   lastoffset = 0;
7874
7875
69
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7876
66
        lastoffset = offset;
7877
66
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7878
66
        if (tag_is_closing(tag_info) ) {
7879
1
            return offset;
7880
1
            }
7881
65
        offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
7882
65
        if (offset <= lastoffset) break;
7883
65
    }
7884
51
    return offset;
7885
52
}
7886
7887
/*
7888
SEQ OF ReadAccessSpecification
7889
*/
7890
static unsigned
7891
fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7892
108
{
7893
108
    uint8_t tag_no, tag_info;
7894
108
    uint32_t lvt;
7895
108
    unsigned   lastoffset = 0;
7896
7897
135
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7898
134
        lastoffset = offset;
7899
134
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7900
134
        if (tag_is_closing(tag_info) ) {
7901
5
            return offset;
7902
5
            }
7903
129
        offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
7904
129
        if ( offset <= lastoffset ) break;
7905
129
    }
7906
103
    return offset;
7907
108
}
7908
7909
static unsigned
7910
// NOLINTNEXTLINE(misc-no-recursion)
7911
fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7912
10.0k
{
7913
10.0k
    uint8_t tag_no, tag_info;
7914
10.0k
    uint32_t lvt;
7915
10.0k
    unsigned   lastoffset = 0, depth = 0;
7916
10.0k
    char    ar[256];
7917
10.0k
    uint32_t save_object_type;
7918
10.0k
    bool do_default_handling;
7919
7920
10.0k
    if (propertyIdentifier >= 0) {
7921
10.0k
        snprintf(ar, sizeof(ar), "%s: ",
7922
10.0k
            val_to_split_str(pinfo->pool, propertyIdentifier, 512,
7923
10.0k
                BACnetPropertyIdentifier,
7924
10.0k
                ASHRAE_Reserved_Fmt,
7925
10.0k
                Vendor_Proprietary_Fmt));
7926
10.0k
    } else {
7927
29
        snprintf(ar, sizeof(ar), "Abstract Type: ");
7928
29
    }
7929
7930
10.0k
    increment_dissection_depth(pinfo);
7931
7932
120k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
7933
119k
        lastoffset = offset;
7934
119k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7935
119k
        if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
7936
3.11k
            if (depth <= 0) {
7937
2.20k
                goto cleanup;
7938
2.20k
            }
7939
3.11k
        }
7940
7941
117k
        do_default_handling = false;
7942
7943
        /* Application Tags */
7944
117k
        switch (propertyIdentifier) {
7945
2.68k
        case 0: /* acked-transitions */
7946
2.77k
        case 35: /* event-enable */
7947
2.77k
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
7948
2.77k
            BACnetAcknowledgedTransitions);
7949
2.77k
            break;
7950
3.16k
        case 2: /* action */
7951
                /* loop object is application tagged,
7952
                    command object is context tagged */
7953
3.16k
                if (tag_is_context_specific(tag_info)) {
7954
                    /* BACnetActionList */
7955
865
                    offset = fActionList(tvb, pinfo, tree, offset);
7956
2.30k
                } else {
7957
                    /* BACnetAction */
7958
2.30k
                    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
7959
2.30k
                        BACnetAction);
7960
2.30k
                }
7961
3.16k
                break;
7962
2.66k
        case 7: /* alarm-values*/
7963
2.66k
            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
0
            case 31: /* timer */
7972
0
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
7973
0
              break;
7974
5
            case 36: /* access-zone */
7975
5
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
7976
5
              break;
7977
225
            case 39: /* bitstring-value */
7978
2.64k
            default:
7979
2.64k
              if (tag_info) {
7980
1.14k
                if (tag_is_opening(tag_info)) {
7981
343
                  ++depth;
7982
343
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7983
343
                }
7984
797
                else if (tag_is_closing(tag_info)) {
7985
90
                  --depth;
7986
90
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7987
90
                }
7988
707
                else {
7989
707
                  offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
7990
707
                }
7991
1.14k
              }
7992
1.50k
              else {
7993
1.50k
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
7994
1.50k
              }
7995
2.64k
              break;
7996
2.66k
            }
7997
2.66k
            break;
7998
2.66k
        case 37: /* event-type */
7999
318
            offset = fEventType(tvb, pinfo, tree, offset);
8000
318
            break;
8001
3.89k
        case 39: /* fault-values */
8002
3.89k
            switch (object_type) {
8003
0
            case 21: /* life-point */
8004
0
            case 22: /* life-zone */
8005
0
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
8006
0
              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
26
            case 36: /* access-zone */
8014
26
              offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
8015
26
              break;
8016
0
            case 39: /* bitstring-value */
8017
3.87k
            default:
8018
3.87k
              if (tag_info) {
8019
1.88k
                if (tag_is_opening(tag_info)) {
8020
1.12k
                  ++depth;
8021
1.12k
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8022
1.12k
                }
8023
763
                else if (tag_is_closing(tag_info)) {
8024
208
                  --depth;
8025
208
                  offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8026
208
                }
8027
555
                else {
8028
555
                  offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
8029
555
                }
8030
1.88k
              }
8031
1.98k
              else {
8032
1.98k
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8033
1.98k
              }
8034
3.87k
              break;
8035
3.89k
            }
8036
3.88k
            break;
8037
3.88k
        case 30: /* BACnetAddressBinding */
8038
251
        case 331: /* last-key-server */
8039
251
            offset = fAddressBinding(tvb, pinfo, tree, offset);
8040
251
            break;
8041
168
        case 52: /* limit-enable */
8042
168
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLimitEnable);
8043
168
            break;
8044
91
        case 54: /* list of object property reference */
8045
91
            offset = fLOPR(tvb, pinfo, tree, offset);
8046
91
            break;
8047
386
        case 55: /* list-of-session-keys */
8048
386
            offset = fSessionKey(tvb, pinfo, tree, offset);
8049
386
            break;
8050
79
        case 77: /* object-name */
8051
79
            offset = fObjectName(tvb, pinfo, tree, offset);
8052
79
            break;
8053
33
        case 79: /* object-type */
8054
352
        case 96: /* protocol-object-types-supported */
8055
352
            offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
8056
352
                BACnetObjectType, 128);
8057
352
            break;
8058
146
        case 97: /* Protocol-Services-Supported */
8059
146
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8060
146
                BACnetServicesSupported);
8061
146
            break;
8062
130
        case 102: /* recipient-list */
8063
130
            offset = fDestination(tvb, pinfo, tree, offset);
8064
130
            break;
8065
7
        case 107: /* segmentation-supported */
8066
7
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8067
7
                BACnetSegmentation);
8068
7
            break;
8069
73
        case 111: /* Status-Flags */
8070
73
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8071
73
                BACnetStatusFlags);
8072
73
            break;
8073
291
        case 112: /* System-Status */
8074
291
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8075
291
                BACnetDeviceStatus);
8076
291
            break;
8077
92
        case 117: /* units */
8078
94
        case 455: /* car-load-units */
8079
94
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
8080
94
                BACnetEngineeringUnits);
8081
94
            break;
8082
1.30k
        case 87:    /* priority-array -- accessed as a BACnetARRAY */
8083
1.30k
            if (propertyArrayIndex == 0) {
8084
                /* BACnetARRAY index 0 refers to the length
8085
                of the array, not the elements of the array */
8086
262
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8087
1.04k
            } else {
8088
1.04k
                offset = fPriorityArray(tvb, pinfo, tree, offset);
8089
1.04k
            }
8090
1.30k
            break;
8091
118
        case 38:    /* exception-schedule */
8092
118
            if (object_type < 128) {
8093
101
                if (propertyArrayIndex == 0) {
8094
                    /* BACnetARRAY index 0 refers to the length
8095
                    of the array, not the elements of the array */
8096
0
                    offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8097
101
                } else {
8098
101
                    offset = fSpecialEvent(tvb, pinfo, tree, offset);
8099
101
                }
8100
101
            }
8101
118
            break;
8102
16
        case 19:  /* controlled-variable-reference */
8103
23
        case 60:  /* manipulated-variable-reference */
8104
35
        case 78:  /* object-property-reference */
8105
37
        case 181: /* input-reference */
8106
38
        case 355: /* event-algorithm-inhibit-reference */
8107
38
            offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
8108
38
            break;
8109
5
        case 132: /* log-device-object-property */
8110
5
            offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
8111
5
            break;
8112
137
        case 109: /* Setpoint-Reference */
8113
            /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
8114
137
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8115
137
            offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
8116
137
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8117
137
            break;
8118
57
        case 123:   /* weekly-schedule -- accessed as a BACnetARRAY */
8119
57
            if (object_type < 128) {
8120
45
                if (propertyArrayIndex == 0) {
8121
                    /* BACnetARRAY index 0 refers to the length
8122
                    of the array, not the elements of the array */
8123
19
                    offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8124
26
                } else {
8125
26
                    offset = fWeeklySchedule(tvb, pinfo, tree, offset);
8126
26
                }
8127
45
            }
8128
57
            break;
8129
225
        case 127:   /* client COV increment */
8130
225
            offset = fClientCOV(tvb, pinfo, tree, offset);
8131
225
            break;
8132
39
        case 131:  /* log-buffer */
8133
39
            if ( object_type == 61 )
8134
0
                offset = fAuditLogRecord(tvb, pinfo, tree, offset);
8135
39
            else if ( object_type == 25 )
8136
0
                offset = fEventLogRecord(tvb, pinfo, tree, offset);
8137
39
            else if ( object_type == 27 )
8138
0
                offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
8139
39
            else
8140
39
                offset = fLogRecord(tvb, pinfo, tree, offset);
8141
39
            break;
8142
10
        case 159: /* member-of */
8143
14
        case 165: /* zone-members */
8144
51
        case 211: /* subordinate-list */
8145
54
        case 246: /* access-doors */
8146
120
        case 249: /* access-event-credential */
8147
130
        case 252: /* accompaniment */
8148
155
        case 265: /* credentials */
8149
161
        case 266: /* credentials-in-zone */
8150
272
        case 277: /* last-credential-added */
8151
272
        case 279: /* last-credential-removed */
8152
285
        case 286: /* members */
8153
332
        case 320: /* zone-from */
8154
335
        case 321: /* zone-to */
8155
351
        case 461: /* energy-meter-ref */
8156
353
        case 491: /* represents */
8157
353
            offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
8158
353
            break;
8159
1.77k
        case 196: /* last-restart-reason */
8160
1.77k
            offset = fRestartReason(tvb, pinfo, tree, offset);
8161
1.77k
            break;
8162
33
        case 212: /* actual-shed-level */
8163
56
        case 214: /* expected-shed-level */
8164
62
        case 218: /* requested-shed-level */
8165
62
            offset = fShedLevel(tvb, pinfo, tree, offset);
8166
62
            break;
8167
64
        case 152: /* active-cov-subscriptions */
8168
64
            offset = fCOVSubscription(tvb, pinfo, tree, offset);
8169
64
            break;
8170
1.87k
        case 23: /* date-list */
8171
1.87k
            offset = fCalendarEntry(tvb, pinfo, tree, offset);
8172
1.87k
            break;
8173
118
        case 116: /* time-synchronization-recipients */
8174
159
        case 206: /* utc-time-synchronization-recipients */
8175
352
        case 202: /* restart-notification-recipients */
8176
352
            offset = fRecipient(tvb, pinfo, tree, offset);
8177
352
            break;
8178
29.1k
        case 83: /* event-parameters */
8179
29.1k
            offset = fEventParameter(tvb, pinfo, tree, offset);
8180
29.1k
            break;
8181
81
        case 130: /* event-time-stamp */
8182
81
            if (propertyArrayIndex == 0) {
8183
                /* BACnetARRAY index 0 refers to the length
8184
                of the array, not the elements of the array */
8185
12
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8186
69
            } else {
8187
69
                offset = fEventTimeStamps(tvb, pinfo, tree, offset);
8188
69
            }
8189
81
            break;
8190
116
        case 197: /* logging-type */
8191
116
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
8192
116
            break;
8193
563
        case 36: /* event-state */
8194
563
            offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
8195
563
            break;
8196
47
        case 103: /* reliability */
8197
47
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
8198
47
            break;
8199
1.18k
        case 72: /* notify-type */
8200
1.18k
            offset = fNotifyType(tvb, pinfo, tree, offset);
8201
1.18k
            break;
8202
57
        case 208: /* node-type */
8203
57
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
8204
57
            break;
8205
184
        case 231: /* door-status */
8206
266
        case 450: /* car-door-status */
8207
266
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
8208
266
            break;
8209
83
        case 233: /* lock-status */
8210
83
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
8211
83
            break;
8212
62
        case 235: /* secured-status */
8213
62
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
8214
62
            break;
8215
18
        case 158: /* maintenance-required */
8216
18
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
8217
18
            break;
8218
103
        case 92: /* program-state */
8219
103
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
8220
103
            break;
8221
56
        case 90: /* program-change */
8222
56
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
8223
56
            break;
8224
72
        case 100: /* reason-for-halt */
8225
72
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
8226
72
            break;
8227
2
        case 157: /* last-restore-time */
8228
2
            offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8229
2
            break;
8230
103
        case 160: /* mode */
8231
203
        case 175: /* accepted-modes */
8232
203
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
8233
203
            break;
8234
34
        case 163: /* silenced */
8235
34
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
8236
34
            break;
8237
173
        case 161: /* operation-expected */
8238
173
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
8239
173
            break;
8240
1
        case 164: /* tracking-value */
8241
1
            if (object_type == 21 || object_type == 22) /* life-safety-point/zone */
8242
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
8243
1
            else if (object_type == 63) /* color */
8244
0
                offset = fXyColor(tvb, pinfo, tree, offset, ar);
8245
1
            else if (object_type == 64) /* color-temperature */
8246
0
                offset = fUnsignedTag(tvb, pinfo, tree, offset, ar);
8247
1
            else if (object_type == 54) /* lighting-output */
8248
0
                offset = fRealTag(tvb, pinfo, tree, offset, ar);
8249
1
            break;
8250
131
        case 166: /* life-safety-alarm-values */
8251
131
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
8252
131
            break;
8253
610
        case 41: /* file-access-method */
8254
610
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
8255
610
            break;
8256
46
        case 185:  /* prescale */
8257
46
            offset = fPrescale(tvb, pinfo, tree, offset);
8258
46
            break;
8259
40
        case 187:  /* scale */
8260
40
            offset = fScale(tvb, pinfo, tree, offset);
8261
40
            break;
8262
106
        case 189: /* update-time */
8263
106
            if (object_type == 37) /* credential-data-input */
8264
0
                offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8265
106
            else
8266
106
                offset = fDateTime(tvb, pinfo, tree, offset, ar);
8267
106
            break;
8268
185
        case 184: /* logging-record */
8269
185
            offset = fLoggingRecord(tvb, pinfo, tree, offset);
8270
185
            break;
8271
46
        case 203: /* time-of-device-restart */
8272
46
            offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8273
46
            break;
8274
322
        case 226: /* door-alarm-state */
8275
322
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
8276
322
            break;
8277
52
        case 228: /* door-members */
8278
52
            offset = fDoorMembers(tvb, pinfo, tree, offset);
8279
52
            break;
8280
61
        case 234: /* masked-alarm-values */
8281
61
            offset = fSequenceOfEnums(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
8282
61
            break;
8283
1
        case 248: /* access-event-authentication-factor */
8284
1
            offset = fAuthenticationFactor(tvb, pinfo, tree, offset);
8285
1
            break;
8286
322
        case 261: /* authorization-mode */
8287
322
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuthorizationMode);
8288
322
            break;
8289
108
        case 53:  /* list-of-group-members */
8290
108
            save_object_type = object_type;
8291
108
            offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
8292
108
            object_type = save_object_type;
8293
108
            break;
8294
143
        case 296: /* occupancy-state */
8295
143
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
8296
143
            break;
8297
73
        case 300: /* passback-mode */
8298
73
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessPassbackMode);
8299
73
            break;
8300
24
        case 303: /* reason-for-disable */
8301
24
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessCredentialDisableReason);
8302
24
            break;
8303
4
        case 318: /* user-type */
8304
4
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessUserType);
8305
4
            break;
8306
297
        case 330: /* key-sets */
8307
297
            offset = fSecurityKeySet(tvb, pinfo, tree, offset);
8308
297
            break;
8309
0
        case 332: /* network-access-security-policies */
8310
0
            offset = fNetworkSecurityPolicy(tvb, pinfo, tree, offset);
8311
0
            break;
8312
0
        case 338: /* backup-and-restore-state */
8313
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetBackupState);
8314
0
            break;
8315
2
        case 370: /* write-status */
8316
2
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetWriteStatus);
8317
2
            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
52
        case 288: /* negative-access-rules */
8327
127
        case 302: /* positive-access-rules */
8328
127
            offset = fAccessRule(tvb, pinfo, tree, offset);
8329
127
            break;
8330
103
        case 304: /* supported-formats */
8331
103
            offset = fAuthenticationFactorFormat(tvb, pinfo, tree, offset);
8332
103
            break;
8333
155
        case 327: /* base-device-security-policy */
8334
155
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSecurityLevel);
8335
155
            break;
8336
49
        case 371: /* property-list */
8337
49
            offset = fSequenceOfEnums(tvb, pinfo, tree, offset, ar, BACnetPropertyIdentifier);
8338
49
            break;
8339
8.43k
        case 358: /* fault-parameters */
8340
8.43k
            offset = fFaultParameter(tvb, pinfo, tree, offset);
8341
8.43k
            break;
8342
9
        case 359: /* fault type */
8343
9
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFaultType);
8344
9
            break;
8345
76
        case 362: /* subscribed-recipients */
8346
76
            offset = fEventNotificationSubscription(tvb, pinfo, tree, offset);
8347
76
            break;
8348
57
        case 364: /* authorization-exemptions */
8349
57
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuthorizationExemption);
8350
57
            break;
8351
0
        case 378: /* in-progress */
8352
0
            if (object_type == 54) /* lighting-output */
8353
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLightingInProgress);
8354
0
            else if (object_type == 63) /* color */
8355
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorOperationInProgress);
8356
0
            else if (object_type == 64) /* color-temperature */
8357
0
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorOperationInProgress);
8358
0
            break;
8359
2
        case 380: /* lighting-command */
8360
2
            offset = fLightingCommand(tvb, pinfo, tree, offset, ar);
8361
2
            break;
8362
105
        case 16:  /* change-of-state-time */
8363
206
        case 71:  /* modification-date */
8364
272
        case 114: /* time-of-active-time-reset */
8365
1.24k
        case 115: /* time-of-state-count-reset */
8366
1.29k
        case 142: /* start-time */
8367
1.70k
        case 143: /* stop-time */
8368
1.79k
        case 149: /* maximum-value-time-stamp */
8369
2.15k
        case 150: /* minimum-value-time-stamp */
8370
2.38k
        case 179: /* count-change-time */
8371
2.76k
        case 192: /* value-change-time */
8372
2.95k
        case 254: /* activation-time */
8373
3.07k
        case 270: /* expiration-time */
8374
3.12k
        case 278: /* last-credential-added-time */
8375
3.14k
        case 280: /* last-credential-removed-time */
8376
3.16k
        case 281: /* last-use-time */
8377
3.16k
        case 392: /* time-of-strike-count-reset */
8378
3.16k
            offset = fDateTime(tvb, pinfo, tree, offset, ar);
8379
3.16k
            break;
8380
241
        case 258: /* authentication-policy-list */
8381
241
            offset = fAuthenticationPolicy(tvb, pinfo, tree, offset);
8382
241
            break;
8383
0
        case 395: /* last-state-change */
8384
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerTransition);
8385
0
            break;
8386
149
        case 396: /* state-change-values */
8387
149
            offset = fTimerStateChangeValue(tvb, pinfo, tree, offset);
8388
149
            break;
8389
9
        case 398: /* timer-state */
8390
9
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
8391
9
            break;
8392
27
        case 407: /* bacnet-ip-global-address */
8393
27
        case 418: /* fd-bbmd-address */
8394
27
            offset = fHostNPort(tvb, pinfo, tree, offset, ar);
8395
27
            break;
8396
0
        case 408: /* bacnet-ip-mode */
8397
259
        case 435: /* bacnet-ipv6-mode */
8398
259
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetIpMode);
8399
259
            break;
8400
97
        case 414: /* bmd-broadcast-distribution-table */
8401
97
            offset = fBDTEntry(tvb, pinfo, tree, offset, ar);
8402
97
            break;
8403
66
        case 415: /* bbmd-foreign-device-table */
8404
66
            offset = fFDTEntry(tvb, pinfo, tree, offset, ar);
8405
66
            break;
8406
16
        case 417: /* command */
8407
16
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkPortCommand);
8408
16
            break;
8409
0
        case 426: /* network-number-quality */
8410
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkNumberQuality);
8411
0
            break;
8412
20
        case 427: /* network-type */
8413
20
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkType);
8414
20
            break;
8415
87
        case 428: /* routing-table */
8416
87
            offset = fRouterEntry(tvb, pinfo, tree, offset);
8417
87
            break;
8418
45
        case 429: /* virtual-mac-address-table */
8419
45
            offset = fVMACEntry(tvb, pinfo, tree, offset);
8420
45
            break;
8421
15
        case 430: /* command-time-array */
8422
15
            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
15
            } else {
8427
15
                offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8428
15
            }
8429
15
            break;
8430
8
        case 432: /* last-command-time */
8431
8
            offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
8432
8
            break;
8433
1.46k
        case 433: /* value-source */
8434
1.46k
            offset = fValueSource(tvb, pinfo, tree, offset);
8435
1.46k
            break;
8436
1
        case 434: /* value-source-array */
8437
1
            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
1
            } else {
8442
1
                offset = fValueSource(tvb, pinfo, tree, offset);
8443
1
            }
8444
1
            break;
8445
2.71k
        case 447: /* assigned-landing-calls */
8446
2.71k
            offset = fAssignedLandingCalls(tvb, pinfo, tree, offset);
8447
2.71k
            break;
8448
2
        case 448: /* car-assigned-direction */
8449
8
        case 457: /* car-moving-direction */
8450
8
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDirection);
8451
8
            break;
8452
0
        case 449: /* car-door-command */
8453
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDoorCommand);
8454
0
            break;
8455
18
        case 453: /* car-drive-status */
8456
18
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDriveStatus);
8457
18
            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
4
        case 463: /* fault-signals */
8465
4
            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
4
            } else {
8470
4
                if (object_type == 59) /* lift object */
8471
0
                    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftFault);
8472
4
                else
8473
4
                    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorFault);
8474
4
            }
8475
4
            break;
8476
64
        case 467: /* group-mode */
8477
64
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftGroupMode);
8478
64
            break;
8479
47
        case 470: /* landing-calls */
8480
47
            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
47
            } else {
8485
47
                offset = fLandingCallStatus(tvb, pinfo, tree, offset);
8486
47
            }
8487
47
            break;
8488
134
        case 471: /* landing-call-control */
8489
134
            offset = fLandingCallStatus(tvb, pinfo, tree, offset);
8490
134
            break;
8491
827
        case 472: /* landing-door-status */
8492
827
            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
827
            } else {
8497
827
                offset = fLandingDoorStatus(tvb, pinfo, tree, offset);
8498
827
            }
8499
827
            break;
8500
71
        case 477: /* "operation-direction */
8501
71
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorOperationDirection);
8502
71
            break;
8503
404
        case 481: /* active-cov-multiple-subscriptions */
8504
404
            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
404
            } else {
8509
404
                offset = fCOVMultipleSubscription(tvb, pinfo, tree, offset);
8510
404
            }
8511
404
            break;
8512
18
        case 482: /* protocol-level */
8513
18
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProtocolLevel);
8514
18
            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
2
        case 487: /* subordinate-node-types */
8525
2
            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
2
            } else {
8530
2
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
8531
2
            }
8532
2
            break;
8533
1.18k
        case 488: /* subordinate-tags */
8534
1.18k
            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.18k
            } else {
8539
1.18k
                offset = fNameValueCollection(tvb, pinfo, tree, offset);
8540
1.18k
            }
8541
1.18k
            break;
8542
82
        case 489: /* subordinate-relationship */
8543
82
            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
82
            } else {
8548
82
                offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetRelationship);
8549
82
            }
8550
82
            break;
8551
27
        case 490: /* default-subordinate-relationship */
8552
27
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetRelationship);
8553
27
            break;
8554
23
        case 494: /* stages */
8555
23
            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
23
            } else {
8560
23
                offset = fStageLimitValue(tvb, pinfo, tree, offset);
8561
23
            }
8562
23
            break;
8563
16
        case 498: /* audit-level */
8564
16
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditLevel);
8565
16
            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
44
        case 504: /* monitored-objects */
8573
44
            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
44
            } else {
8578
44
                offset = fObjectSelector(tvb, pinfo, tree, offset);
8579
44
            }
8580
44
            break;
8581
77
        case 510:     /* command-validation-result */
8582
77
        case 4194307: /* current-health */
8583
77
            offset = fHealth(tvb, pinfo, tree, offset);
8584
77
            break;
8585
47
        case 4194312: /* sc-direct-connect-connection-status */
8586
47
            offset = fSCDirectConnection(tvb, pinfo, tree, offset);
8587
47
            break;
8588
0
        case 4194315: /* sc-failed-connection-requests */
8589
0
            offset = fSCFailedConnectionRequest(tvb, pinfo, tree, offset);
8590
0
            break;
8591
0
        case 4194316: /* sc-failover-hub-connection-status */
8592
0
        case 4194324: /* sc-primary-hub-connection-status */
8593
0
            offset = fSCHubConnection(tvb, pinfo, tree, offset);
8594
0
            break;
8595
0
        case 4194318: /* sc_hub_connector_state */
8596
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSCHubConnectorState);
8597
0
            break;
8598
40
        case 4194321: /* sc-hub-function-connection-status */
8599
40
            offset = fSCHubFunctionConnection(tvb, pinfo, tree, offset);
8600
40
            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
0
        case 4194343: /* authorization-cache */
8611
0
            offset = fAccessToken(tvb, pinfo, tree, offset, ar);
8612
0
            break;
8613
0
        case 4194345: /* authorization-policy */
8614
0
            offset = fAuthorizationPolicy(tvb, pinfo, tree, offset, ar);
8615
0
            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
0
        case 4194348: /* authorization-status */
8623
0
            offset = fAuthorizationStatus(tvb, pinfo, tree, offset, ar);
8624
0
            break;
8625
8626
28.9k
        case 85:  /* present-value */
8627
28.9k
            if ( object_type == 11 )    /* group object handling of present-value */
8628
684
            {
8629
684
                offset = fReadAccessResult(tvb, pinfo, tree, offset);
8630
684
            }
8631
28.2k
            else if (object_type == 30)  /* access-door object */
8632
313
            {
8633
313
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetDoorValue, 0, BACAPP_PRESENT_VALUE_ENUM);
8634
313
            }
8635
27.9k
            else if (object_type == 21)  /* life-point */
8636
590
            {
8637
590
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetLifeSafetyState, 0, BACAPP_PRESENT_VALUE_ENUM);
8638
590
            }
8639
27.3k
            else if (object_type == 22)  /* life-zone */
8640
1.51k
            {
8641
1.51k
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetLifeSafetyState, 0, BACAPP_PRESENT_VALUE_ENUM);
8642
1.51k
            }
8643
25.8k
            else if (object_type == 53) /* channel object */
8644
105
            {
8645
105
                offset = fChannelValue(tvb, pinfo, tree, offset, ar);
8646
105
            }
8647
25.7k
            else if (object_type == 37) /* credential-data-input */
8648
10
            {
8649
10
                offset = fAuthenticationFactor(tvb, pinfo, tree, offset);
8650
10
            }
8651
25.7k
            else if (object_type == 26) /* global-group */
8652
842
            {
8653
842
                offset = fPropertyAccessResult(tvb, pinfo, tree, offset);
8654
842
            }
8655
24.8k
            else if (object_type == 28) /* loac-control */
8656
875
            {
8657
875
                offset = fPresentValue(tvb, pinfo, tree, offset, BACnetShedState, 0, BACAPP_PRESENT_VALUE_ENUM);
8658
875
            }
8659
23.9k
            else if (object_type == 43) /* date-time-pattern-value */
8660
230
            {
8661
230
                offset = fDateTime(tvb, pinfo, tree, offset, ar);
8662
230
            }
8663
23.7k
            else if (object_type == 44) /* date-time-value */
8664
525
            {
8665
525
                offset = fDateTime(tvb, pinfo, tree, offset, ar);
8666
525
            }
8667
23.2k
            else if (object_type == 63) /* color */
8668
73
            {
8669
73
                offset = fXyColor(tvb, pinfo, tree, offset, ar);
8670
73
            }
8671
23.1k
            else
8672
23.1k
            {
8673
23.1k
                if (!tag_info) {
8674
18.4k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8675
                    // application tag number above 12 reserved for ASHRAE
8676
18.4k
                    if (!tag_is_context_specific(tag_info) && tag_no <= 12) {
8677
18.2k
                        offset = fPresentValue(tvb, pinfo, tree, offset, NULL, 0, (BacappPresentValueType) tag_no);
8678
18.2k
                    }
8679
18.4k
                } else {
8680
4.70k
                    do_default_handling = true;
8681
4.70k
                }
8682
23.1k
            }
8683
28.9k
            break;
8684
11.9k
        default:
8685
11.9k
            do_default_handling = true;
8686
11.9k
            break;
8687
117k
        }
8688
115k
        if (do_default_handling) {
8689
16.6k
            if (tag_info) {
8690
8.74k
                if (tag_is_opening(tag_info)) {
8691
2.83k
                    ++depth;
8692
2.83k
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8693
5.91k
                } else if (tag_is_closing(tag_info)) {
8694
610
                    --depth;
8695
610
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8696
5.30k
                } else {
8697
5.30k
                    offset  = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
8698
5.30k
                }
8699
8.74k
            } else {
8700
7.92k
                offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
8701
7.92k
            }
8702
16.6k
        }
8703
115k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8704
115k
    }
8705
8706
7.98k
cleanup:
8707
7.98k
    decrement_dissection_depth(pinfo);
8708
7.98k
    return offset;
8709
10.0k
}
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.94k
{
8715
3.94k
    uint8_t tag_no;
8716
3.94k
    uint32_t lvt;
8717
8718
3.94k
    if (tag_is_opening(tag_info)) {
8719
3.85k
        offset += fTagHeaderTree(tvb, pinfo, tree, offset,
8720
3.85k
                                 &tag_no, &tag_info, &lvt);
8721
3.85k
        offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8722
3.85k
        if (tvb_reported_length_remaining(tvb, offset) > 0) {
8723
2.64k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset,
8724
2.64k
                                     &tag_no, &tag_info, &lvt);
8725
2.64k
        }
8726
3.85k
    } else {
8727
83
        proto_tree_add_expert(tree, pinfo, &ei_bacapp_opening_tag, tvb, offset, -1);
8728
83
        offset = tvb_reported_length(tvb);
8729
83
    }
8730
8731
3.94k
    return offset;
8732
3.94k
}
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
6.61k
{
8739
6.61k
    unsigned   lastoffset = offset;
8740
6.61k
    uint8_t tag_no, tag_info;
8741
6.61k
    uint32_t lvt;
8742
8743
6.61k
    offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
8744
6.61k
    if (offset > lastoffset) {
8745
2.40k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8746
2.40k
        if (tag_no == tagoffset+2) {  /* Value - might not be present in ReadAccessResult */
8747
755
            offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
8748
755
        }
8749
2.40k
    }
8750
6.61k
    return offset;
8751
6.61k
}
8752
8753
static unsigned
8754
// NOLINTNEXTLINE(misc-no-recursion)
8755
fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8756
4.36k
{
8757
4.36k
    unsigned   lastoffset = 0;
8758
4.36k
    uint8_t tag_no, tag_info;
8759
4.36k
    uint32_t lvt;
8760
8761
6.52k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8762
6.29k
        lastoffset = offset;
8763
6.29k
        offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
8764
6.29k
        if (offset > lastoffset) {
8765
            /* detect optional priority
8766
            by looking to see if the next tag is context tag number 3 */
8767
1.99k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8768
1.99k
            if (tag_is_context_specific(tag_info) && (tag_no == 3))
8769
53
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
8770
1.99k
        }
8771
6.29k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8772
6.29k
    }
8773
4.36k
    return offset;
8774
4.36k
}
8775
8776
static unsigned
8777
fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8778
109
{
8779
109
    unsigned    lastoffset = 0, len;
8780
109
    uint8_t     tag_no, tag_info;
8781
109
    uint32_t    lvt;
8782
109
    proto_tree *subtree = tree;
8783
8784
3.68k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8785
3.67k
        lastoffset = offset;
8786
3.67k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8787
3.67k
        if (tag_is_closing(tag_info)) {
8788
740
            offset += len;
8789
740
            subtree = tree;
8790
740
            continue;
8791
740
        }
8792
8793
2.93k
        switch (tag_no) {
8794
1.77k
        case 0: /* ProcessId */
8795
1.77k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
8796
1.77k
            break;
8797
218
        case 1: /* monitored ObjectId */
8798
218
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
8799
218
            break;
8800
262
        case 2: /* issueConfirmedNotifications */
8801
262
            offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
8802
262
            break;
8803
345
        case 3: /* life time */
8804
345
            offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
8805
345
            break;
8806
128
        case 4: /* monitoredPropertyIdentifier */
8807
128
            if (tag_is_opening(tag_info)) {
8808
114
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "monitoredPropertyIdentifier");
8809
114
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8810
114
                offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
8811
114
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8812
114
            } else {
8813
14
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
8814
14
            }
8815
128
            break;
8816
136
        case 5: /* covIncrement */
8817
136
            offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
8818
136
            break;
8819
67
        default:
8820
67
            return offset;
8821
2.93k
        }
8822
2.85k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8823
2.85k
    }
8824
30
    return offset;
8825
109
}
8826
8827
static unsigned
8828
fSubscribeCOVPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8829
133
{
8830
133
    unsigned    lastoffset = 0, len;
8831
133
    uint8_t     tag_no, tag_info;
8832
133
    uint32_t    lvt;
8833
133
    proto_tree *subtree = tree;
8834
133
    proto_tree *subsubtree = tree;
8835
8836
4.06k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8837
4.04k
        lastoffset = offset;
8838
4.04k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8839
4.04k
        if (tag_is_closing(tag_info)) {
8840
1.30k
            offset += len;
8841
1.30k
            subtree = tree;
8842
1.30k
            continue;
8843
1.30k
        }
8844
8845
2.73k
        switch (tag_no) {
8846
1.32k
        case 0: /* ProcessId */
8847
1.32k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
8848
1.32k
            break;
8849
750
        case 1: /* issueConfirmedNotifications */
8850
750
            offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
8851
750
            break;
8852
246
        case 2: /* life time */
8853
246
            offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
8854
246
            break;
8855
287
        case 3: /* notification delay */
8856
287
            offset = fTimeSpan(tvb, pinfo, tree, offset, "notification delay");
8857
287
            break;
8858
55
        case 4: /* list-of-cov-subscription-specifications */
8859
55
            if (tag_is_opening(tag_info)) {
8860
43
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-subscription-specifications: ");
8861
43
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8862
8863
251
                while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8864
248
                    lastoffset = offset;
8865
248
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8866
248
                    if (tag_is_closing(tag_info)) {
8867
22
                        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8868
22
                        offset += len;
8869
22
                        subtree = tree;
8870
22
                        break;
8871
22
                    }
8872
8873
226
                    switch (tag_no) {
8874
190
                    case 0: /* monitored-object-identifier */
8875
190
                        offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
8876
190
                        break;
8877
28
                    case 1: /* list-of-cov-references */
8878
28
                      if (tag_is_opening(tag_info)) {
8879
26
                          subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-references: ");
8880
26
                          offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8881
8882
64
                          while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8883
64
                              lastoffset = offset;
8884
64
                              len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8885
64
                              if (tag_is_closing(tag_info)) {
8886
19
                                  fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8887
19
                                  offset += len;
8888
19
                                  break;
8889
19
                              }
8890
8891
45
                              switch (tag_no) {
8892
4
                              case 0: /* monitored-property */
8893
4
                                  if (tag_is_opening(tag_info)) {
8894
1
                                      offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8895
1
                                      offset = fBACnetPropertyReference(tvb, pinfo, subsubtree, offset, 1);
8896
1
                                      offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
8897
1
                                  }
8898
3
                                  else {
8899
3
                                      expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
8900
3
                                  }
8901
4
                                  break;
8902
32
                              case 1: /* cov-increment */
8903
32
                                  offset = fRealTag(tvb, pinfo, subsubtree, offset, "COV Increment: ");
8904
32
                                  break;
8905
5
                              case 2: /* timestamped */
8906
5
                                  offset = fBooleanTag(tvb, pinfo, subsubtree, offset, "timestamped: ");
8907
5
                                  break;
8908
4
                              default:
8909
4
                                  return offset;
8910
45
                            }
8911
41
                            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8912
41
                        }
8913
26
                      }
8914
2
                      else {
8915
2
                          expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
8916
2
                      }
8917
24
                      break;
8918
24
                    default:
8919
8
                      return offset;
8920
226
                    }
8921
213
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8922
213
                }
8923
43
            }
8924
12
            else {
8925
12
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
8926
12
            }
8927
42
            break;
8928
75
        default:
8929
75
            return offset;
8930
2.73k
        }
8931
2.63k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8932
2.63k
    }
8933
37
    return offset;
8934
133
}
8935
8936
static unsigned
8937
fSubscribeCOVPropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8938
87
{
8939
87
    unsigned    lastoffset = 0, len;
8940
87
    uint8_t     tag_no, tag_info;
8941
87
    uint32_t    lvt;
8942
8943
419
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8944
411
        lastoffset = offset;
8945
411
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8946
411
        if (tag_is_closing(tag_info)) {
8947
10
            len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8948
10
            offset += len;
8949
10
            break;
8950
10
        }
8951
8952
401
        switch (tag_no) {
8953
298
        case 0: /* normal error */
8954
298
            if (tag_is_opening(tag_info)) {
8955
1
                offset = fContextTaggedError(tvb, pinfo, tree, offset);
8956
1
            }
8957
297
            else {
8958
297
                offset = fError(tvb, pinfo, tree, offset);
8959
297
            }
8960
298
            break;
8961
83
        case 1: /* first-failed-subscription */
8962
83
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8963
8964
616
            while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
8965
611
                lastoffset = offset;
8966
611
                len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8967
611
                if (tag_is_closing(tag_info)) {
8968
32
                    fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8969
32
                    offset += len;
8970
32
                    break;
8971
32
                }
8972
8973
579
                switch (tag_no) {
8974
148
                case 0: /* monitored-object-identifier */
8975
148
                    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
8976
148
                    break;
8977
292
                case 1: /* monitored-property-reference */
8978
292
                    if (tag_is_opening(tag_info)) {
8979
272
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8980
272
                        offset = fBACnetPropertyReference(tvb, pinfo, tree, offset, 1);
8981
272
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8982
272
                    }
8983
20
                    else {
8984
20
                        expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
8985
20
                    }
8986
292
                    break;
8987
115
                case 2: /* error-type */
8988
115
                    offset = fContextTaggedError(tvb, pinfo, tree, offset);
8989
115
                    break;
8990
23
                default:
8991
23
                    return offset;
8992
579
                }
8993
553
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
8994
553
            }
8995
57
            break;
8996
57
        default:
8997
20
            return offset;
8998
401
        }
8999
352
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9000
352
    }
9001
38
    return offset;
9002
87
}
9003
9004
static unsigned
9005
fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9006
79
{
9007
79
    return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
9008
79
}
9009
9010
static unsigned
9011
fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9012
50
{
9013
50
    unsigned lastoffset = 0;
9014
9015
1.36k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9016
1.35k
        lastoffset = offset;
9017
9018
1.35k
        switch (fTagNo(tvb, offset)) {
9019
854
        case 0: /* deviceInstanceLowLimit */
9020
854
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
9021
854
            break;
9022
280
        case 1: /* deviceInstanceHighLimit */
9023
280
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
9024
280
            break;
9025
71
        case 2: /* BACnetObjectId */
9026
71
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
9027
71
            break;
9028
112
        case 3: /* ObjectName */
9029
112
            offset = fObjectName(tvb, pinfo, tree, offset);
9030
112
            break;
9031
34
        default:
9032
34
            return offset;
9033
1.35k
        }
9034
1.31k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9035
1.31k
    }
9036
11
    return offset;
9037
50
}
9038
9039
9040
static unsigned
9041
fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
9042
38
{
9043
38
    unsigned   lastoffset = 0;
9044
38
    uint8_t tag_no, tag_info;
9045
38
    uint32_t lvt;
9046
9047
38
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9048
38
    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
38
    } else if ((tag_no == 0) && (lvt == 0)) {
9063
        /* not sure null (empty array element) is legal */
9064
12
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9065
12
    }
9066
38
    return offset;
9067
38
}
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
77
{
9085
77
    unsigned   lastoffset = 0;
9086
77
    uint8_t tag_no, tag_info;
9087
77
    uint32_t lvt;
9088
9089
738
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9090
737
        lastoffset = offset;
9091
        /* check the tag.  A closing tag means we are done */
9092
737
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9093
737
        if (tag_is_closing(tag_info)) {
9094
11
            return offset;
9095
11
        }
9096
726
        switch (tag_no) {
9097
456
        case 0: /* timestamp */
9098
456
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9099
456
            offset = fDateTime(tvb, pinfo, tree, offset, "timestamp: ");
9100
456
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9101
456
            break;
9102
110
        case 1: /* result */
9103
110
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9104
110
            offset = fError(tvb, pinfo, tree, offset);
9105
110
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9106
110
            break;
9107
37
        case 2: /* property - OPTIONAL*/
9108
37
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9109
37
            break;
9110
76
        case 3: /* details - OPTIONAL */
9111
76
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9112
76
            break;
9113
47
        default:
9114
47
            return offset;
9115
726
        }
9116
667
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9117
667
    }
9118
7
    return offset;
9119
77
}
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
47
{
9142
47
    unsigned   lastoffset = 0;
9143
47
    uint8_t tag_no, tag_info;
9144
47
    uint32_t lvt;
9145
9146
583
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9147
581
        lastoffset = offset;
9148
        /* check the tag.  A closing tag means we are done */
9149
581
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9150
581
        if (tag_is_closing(tag_info)) {
9151
8
            return offset;
9152
8
        }
9153
573
        switch (tag_no) {
9154
124
        case 0: /* uri */
9155
124
            offset = fCharacterString(tvb, pinfo, tree, offset, "uri: ");
9156
124
            break;
9157
7
        case 1: /* connection-state */
9158
7
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
9159
7
            break;
9160
22
        case 2: /* connect-timestamp */
9161
22
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9162
22
            offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
9163
22
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9164
22
            break;
9165
55
        case 3: /* disconnect-timestamp */
9166
55
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9167
55
            offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
9168
55
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9169
55
            break;
9170
147
        case 4: /* peer-address */
9171
147
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9172
147
            offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
9173
147
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9174
147
            break;
9175
45
        case 5: /* peer-vmac */
9176
45
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
9177
45
            break;
9178
47
        case 6: /* peer-uuid */
9179
47
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
9180
47
            break;
9181
97
        case 7: /* error */
9182
97
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9183
97
            offset = fError(tvb, pinfo, tree, offset);
9184
97
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9185
97
            break;
9186
12
        case 8: /* details - OPTIONAL */
9187
12
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9188
12
            break;
9189
17
        default:
9190
17
            return offset;
9191
573
        }
9192
536
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9193
536
    }
9194
2
    return offset;
9195
47
}
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
0
{
9276
0
    unsigned   lastoffset = 0;
9277
0
    uint8_t tag_no, tag_info;
9278
0
    uint32_t lvt;
9279
9280
0
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9281
0
        lastoffset = offset;
9282
        /* check the tag.  A closing tag means we are done */
9283
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9284
0
        if (tag_is_closing(tag_info)) {
9285
0
            return offset;
9286
0
        }
9287
0
        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
0
        default:
9310
0
            return offset;
9311
0
        }
9312
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9313
0
    }
9314
0
    return offset;
9315
0
}
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
40
{
9337
40
    unsigned   lastoffset = 0;
9338
40
    uint8_t tag_no, tag_info;
9339
40
    uint32_t lvt;
9340
9341
634
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9342
633
        lastoffset = offset;
9343
        /* check the tag.  A closing tag means we are done */
9344
633
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9345
633
        if (tag_is_closing(tag_info)) {
9346
7
            return offset;
9347
7
        }
9348
626
        switch (tag_no) {
9349
258
        case 0: /* connection-state */
9350
258
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
9351
258
            break;
9352
9
        case 1: /* connect-timestamp */
9353
9
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9354
9
            offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
9355
9
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9356
9
            break;
9357
23
        case 2: /* disconnect-timestamp */
9358
23
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9359
23
            offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
9360
23
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9361
23
            break;
9362
77
        case 3: /* peer-address */
9363
77
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9364
77
            offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
9365
77
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9366
77
            break;
9367
43
        case 4: /* peer-vmac */
9368
43
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
9369
43
            break;
9370
26
        case 5: /* peer-uuid */
9371
26
            offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
9372
26
            break;
9373
47
        case 6: /* error */
9374
47
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9375
47
            offset = fError(tvb, pinfo, tree, offset);
9376
47
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9377
47
            break;
9378
115
        case 7: /* details - OPTIONAL */
9379
115
            offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
9380
115
            break;
9381
28
        default:
9382
28
            return offset;
9383
626
        }
9384
594
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9385
594
    }
9386
1
    return offset;
9387
40
}
9388
9389
static unsigned
9390
fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9391
26
{
9392
26
    unsigned    lastoffset = 0;
9393
26
    uint8_t     tag_no, tag_info;
9394
26
    uint32_t    lvt;
9395
26
    unsigned    i = 1; /* day of week array index */
9396
26
    proto_tree *subtree = tree;
9397
9398
26
    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
1
        i = propertyArrayIndex;
9407
1
    }
9408
38
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9409
38
        lastoffset = offset;
9410
38
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9411
38
        if (tag_is_closing(tag_info)) {
9412
0
            return offset; /* outer encoding will print out closing tag */
9413
0
        }
9414
38
        subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bacapp_value, NULL,
9415
38
                                val_to_str(pinfo->pool, i++, day_of_week, "day of week (%d) not found"));
9416
38
        offset = fDailySchedule(tvb, pinfo, subtree, offset);
9417
38
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9418
38
    }
9419
26
    return offset;
9420
26
}
9421
9422
9423
static unsigned
9424
fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9425
2
{
9426
2
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
9427
0
        return offset;
9428
9429
2
    return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
9430
2
}
9431
9432
static unsigned
9433
fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9434
3
{
9435
3
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
9436
0
        return offset;
9437
9438
3
    return fDateTime(tvb, pinfo, tree, offset, NULL);
9439
3
}
9440
9441
static unsigned
9442
fWriteGroupRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9443
242
{
9444
242
    unsigned    lastoffset = 0, len;
9445
242
    uint8_t     tag_no, tag_info;
9446
242
    uint32_t    lvt;
9447
242
    proto_tree *subtree = tree;
9448
9449
4.33k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9450
4.27k
        lastoffset = offset;
9451
4.27k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9452
4.27k
        if (tag_is_closing(tag_info)) {
9453
1.27k
            offset += len;
9454
1.27k
            subtree = tree;
9455
1.27k
            continue;
9456
1.27k
        }
9457
9458
2.99k
        switch (tag_no) {
9459
1.62k
        case 0: /* group-number */
9460
1.62k
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Group number: ");
9461
1.62k
            break;
9462
504
        case 1: /* write-priority */
9463
504
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9464
504
            break;
9465
283
        case 2: /* change-list */
9466
283
            if (tag_is_opening(tag_info)) {
9467
272
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "change-list: ");
9468
272
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9469
9470
10.4k
                while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9471
10.4k
                    lastoffset = offset;
9472
10.4k
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9473
10.4k
                    if (tag_is_closing(tag_info)) {
9474
132
                        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9475
132
                        offset += len;
9476
132
                        subtree = tree;
9477
132
                        break;
9478
132
                    }
9479
9480
10.2k
                    switch (tag_no) {
9481
4.16k
                    case 0: /* channel */
9482
4.16k
                        if (tag_info && ! tag_is_opening(tag_info)) {
9483
                            /* context tagged */
9484
386
                            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Channel: ");
9485
3.78k
                        } else {
9486
                            /* application tagged */
9487
3.78k
                            offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
9488
3.78k
                        }
9489
4.16k
                        break;
9490
1.35k
                    case 1: /* overriding-priority */
9491
1.35k
                        if (tag_info && ! tag_is_opening(tag_info)) {
9492
                            /* context tagged */
9493
428
                            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Overriding priority: ");
9494
930
                        } else {
9495
                            /* application tagged */
9496
930
                            offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
9497
930
                        }
9498
1.35k
                        break;
9499
4.74k
                    default: /* channel-value (application tagged, or opening/closing context-0 tagged) */
9500
4.74k
                        offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
9501
4.74k
                        break;
9502
10.2k
                    }
9503
10.2k
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9504
10.2k
                }
9505
272
            }
9506
11
            else {
9507
11
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9508
11
            }
9509
208
            break;
9510
501
        case 3: /* inhibit-delay */
9511
501
            offset = fBooleanTag(tvb, pinfo, tree, offset, "Inhibit delay: ");
9512
501
            break;
9513
75
        default:
9514
75
            return offset;
9515
2.99k
        }
9516
2.84k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9517
2.84k
    }
9518
87
    return offset;
9519
242
}
9520
9521
static unsigned
9522
fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9523
166
{
9524
166
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
9525
0
        return offset;
9526
166
    offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
9527
166
    return fDate(tvb, pinfo, tree, offset, "End Date: ");
9528
166
}
9529
9530
static unsigned
9531
fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9532
4.29k
{
9533
4.29k
    uint32_t     val   = 0;
9534
4.29k
    uint8_t      tag_no, tag_info;
9535
4.29k
    uint32_t     lvt;
9536
4.29k
    unsigned     tag_len;
9537
4.29k
    proto_item  *ti;
9538
4.29k
    proto_tree  *subtree;
9539
4.29k
    static const char *label = "Vendor ID";
9540
9541
4.29k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9542
4.29k
    if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
9543
1.53k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9544
1.53k
            ett_bacapp_tag, &ti, "%s: %s (%u)",
9545
1.53k
            label,
9546
1.53k
            val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
9547
1.53k
            val);
9548
2.75k
    else
9549
2.75k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9550
2.75k
            ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
9551
4.29k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9552
9553
4.29k
    if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
9554
3.14k
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
9555
3.14k
                                "Wrong length indicated. Expected 1 or 2, got %u", lvt);
9556
3.14k
        return offset+tag_len+lvt;
9557
3.14k
    }
9558
9559
1.14k
    proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
9560
1.14k
        offset+tag_len, lvt, ENC_BIG_ENDIAN);
9561
9562
1.14k
    return offset+tag_len+lvt;
9563
4.29k
}
9564
9565
static unsigned
9566
fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9567
1.77k
{
9568
1.77k
    uint32_t     val   = 0;
9569
1.77k
    uint8_t      tag_no, tag_info;
9570
1.77k
    uint32_t     lvt;
9571
1.77k
    unsigned     tag_len;
9572
1.77k
    proto_item  *ti;
9573
1.77k
    proto_tree  *subtree;
9574
1.77k
    static const char *label = "Restart Reason";
9575
9576
1.77k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9577
1.77k
    if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
9578
811
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9579
811
            ett_bacapp_tag, &ti, "%s: %s (%u)", label,
9580
811
            val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
9581
963
    else
9582
963
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
9583
963
            ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
9584
1.77k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9585
9586
1.77k
    if (lvt != 1) {
9587
1.50k
        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
9588
1.50k
                                "Wrong length indicated. Expected 1, got %u", lvt);
9589
1.50k
        return offset+tag_len+lvt;
9590
1.50k
    }
9591
9592
269
    proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
9593
269
        offset+tag_len, lvt, ENC_BIG_ENDIAN);
9594
9595
269
    return offset+tag_len+lvt;
9596
1.77k
}
9597
9598
static unsigned
9599
fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9600
64
{
9601
64
    uint8_t      tag_no, tag_info;
9602
64
    uint32_t     lvt;
9603
64
    unsigned     lastoffset = 0;
9604
9605
1.21k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9606
1.20k
        lastoffset = offset;
9607
1.20k
        switch (fTagNo(tvb, offset)) {
9608
463
        case 0: /* textMessageSourceDevice */
9609
463
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
9610
463
            break;
9611
482
        case 1: /* messageClass */
9612
482
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9613
482
            switch (fTagNo(tvb, offset)) {
9614
21
            case 0: /* numeric */
9615
21
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
9616
21
                break;
9617
418
            case 1: /* character */
9618
418
                offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
9619
418
                break;
9620
482
            }
9621
480
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9622
480
            break;
9623
146
        case 2: /* messagePriority */
9624
146
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
9625
146
                BACnetMessagePriority);
9626
146
            break;
9627
70
        case 3: /* message */
9628
70
            offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
9629
70
            break;
9630
46
        default:
9631
46
            return offset;
9632
1.20k
        }
9633
1.15k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9634
1.15k
    }
9635
8
    return offset;
9636
64
}
9637
9638
static unsigned
9639
fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9640
6
{
9641
6
    return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
9642
6
}
9643
9644
static unsigned
9645
fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9646
88
{
9647
88
    unsigned    lastoffset, len;
9648
88
    uint8_t     tag_no, tag_info;
9649
88
    uint32_t    lvt;
9650
88
    proto_tree *subtree = tree;
9651
88
    tvbuff_t   *next_tvb;
9652
88
    unsigned    vendor_identifier = 0;
9653
88
    unsigned    service_number = 0;
9654
9655
88
    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9656
88
    fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
9657
88
    col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
9658
88
    offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
9659
9660
88
    next_tvb = tvb_new_subset_remaining(tvb, offset);
9661
88
    if (dissector_try_uint(bacapp_dissector_table,
9662
88
        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
342
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9672
330
        lastoffset = offset;
9673
330
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9674
330
        if (tag_is_closing(tag_info)) {
9675
10
            if (tag_no == 2) { /* Make sure it's the expected tag */
9676
3
                offset += len;
9677
3
                subtree = tree;
9678
3
                continue;
9679
7
            } else {
9680
7
                break; /* End loop if incorrect closing tag */
9681
7
            }
9682
10
        }
9683
320
        switch (tag_no) {
9684
9685
            /* vendorID is now parsed above */
9686
247
        case 1: /* serviceNumber */
9687
247
            fUnsigned32(tvb, offset+len, lvt, &service_number);
9688
247
            col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
9689
247
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
9690
247
            break;
9691
13
        case 2: /*serviceParameters */
9692
13
            if (tag_is_opening(tag_info)) {
9693
8
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
9694
8
                        ett_bacapp_value, NULL, "service Parameters");
9695
8
                propertyIdentifier = -1;
9696
8
                offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9697
8
            } else {
9698
5
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
9699
5
            }
9700
13
            break;
9701
60
        default:
9702
60
            return offset;
9703
320
        }
9704
256
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9705
256
    }
9706
9707
24
    return offset;
9708
88
}
9709
9710
static unsigned
9711
fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9712
6
{
9713
6
    return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
9714
6
}
9715
9716
static unsigned
9717
fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9718
4
{
9719
4
    return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
9720
4
}
9721
9722
static unsigned
9723
fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
9724
50
{
9725
50
    unsigned    lastoffset = 0;
9726
50
    uint8_t     tag_no, tag_info;
9727
50
    uint32_t    lvt;
9728
50
    proto_tree *subtree = tree;
9729
9730
50
    if (label != NULL) {
9731
0
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, label);
9732
0
    }
9733
9734
1.38k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
9735
1.37k
        lastoffset = offset;
9736
1.37k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9737
9738
1.37k
        switch (tag_no) {
9739
788
        case 0: /* subscriberProcessId */
9740
788
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
9741
788
            break;
9742
271
        case 1: /* requestingSource */
9743
271
            offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
9744
271
            break;
9745
159
        case 2: /* request */
9746
159
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
9747
159
                "request: ", BACnetLifeSafetyOperation, 64);
9748
159
            break;
9749
120
        case 3: /* objectId */
9750
120
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
9751
120
            break;
9752
30
        default:
9753
30
            return offset;
9754
1.37k
        }
9755
1.33k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9756
1.33k
    }
9757
11
    return offset;
9758
50
}
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
44.9k
#define BACnetPropertyStatesEnums_Size array_length(BACnetPropertyStatesEnums)
9825
9826
static unsigned
9827
fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9828
9.50k
{
9829
9.50k
    uint8_t      tag_no, tag_info;
9830
9.50k
    uint32_t     lvt;
9831
9.50k
    uint32_t     idx;
9832
9.50k
    const char* label;
9833
9.50k
    const value_string_enum* valstrenum;
9834
9835
9.50k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9836
9.50k
    label = wmem_strdup_printf(pinfo->pool, "%s: ",
9837
9.50k
                               val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
9838
9839
9.50k
    switch (tag_no) {
9840
3.91k
    case 0:
9841
3.91k
        offset = fBooleanTag(tvb, pinfo, tree, offset, label);
9842
3.91k
        break;
9843
417
    case 11:
9844
417
        offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
9845
417
        break;
9846
6
    case 41:
9847
6
        offset = fSignedTag(tvb, pinfo, tree, offset, label);
9848
6
        break;
9849
9
    case 63:
9850
9
        offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
9851
9
        break;
9852
5.16k
    default:
9853
5.16k
        valstrenum = NULL;
9854
9855
44.9k
        for (idx = 0; idx < BACnetPropertyStatesEnums_Size; idx++) {
9856
44.6k
            valstrenum = &BACnetPropertyStatesEnums[idx];
9857
44.6k
            if (valstrenum->tag_no == tag_no &&
9858
4.79k
                valstrenum->valstr != NULL) {
9859
4.79k
                break;
9860
4.79k
            }
9861
39.8k
            valstrenum = NULL;
9862
39.8k
        }
9863
9864
5.16k
        if (valstrenum == NULL)
9865
368
        {
9866
368
            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
368
        }
9869
4.79k
        else
9870
4.79k
        {
9871
4.79k
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
9872
4.79k
                    VALS(valstrenum->valstr), 64);
9873
4.79k
        }
9874
5.16k
        break;
9875
9.50k
    }
9876
9.48k
    return offset;
9877
9.50k
}
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
391
{
9893
391
    unsigned   lastoffset = 0;
9894
391
    uint8_t tag_no, tag_info;
9895
391
    uint32_t lvt;
9896
9897
1.25k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9898
1.24k
        lastoffset = offset;
9899
        /* check the tag.  A closing tag means we are done */
9900
1.24k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9901
1.24k
        if (tag_is_closing(tag_info)) {
9902
20
            return offset;
9903
20
        }
9904
1.22k
        switch (tag_no) {
9905
479
        case 0: /* deviceIdentifier */
9906
479
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
9907
479
            break;
9908
84
        case 1: /* objectIdentifier */
9909
84
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
9910
84
            break;
9911
238
        case 2: /* propertyIdentifier */
9912
238
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9913
238
            break;
9914
82
        case 3: /* arrayIndex - OPTIONAL */
9915
82
            offset = fUnsignedTag(tvb, pinfo, tree, offset,
9916
82
                "arrayIndex: ");
9917
82
            break;
9918
220
        case 4: /* value */
9919
220
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9920
220
            offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9921
220
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9922
220
            break;
9923
124
        default:
9924
124
            return offset;
9925
1.22k
        }
9926
1.09k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9927
1.09k
    }
9928
234
    return offset;
9929
391
}
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
38
{
9944
38
    return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9945
38
}
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.83k
{
9961
2.83k
    unsigned   lastoffset = 0;
9962
2.83k
    uint8_t tag_no, tag_info;
9963
2.83k
    uint32_t lvt;
9964
9965
7.20k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
9966
7.17k
        lastoffset = offset;
9967
        /* check the tag.  A closing tag means we are done */
9968
7.17k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9969
7.17k
        if (tag_is_closing(tag_info)) {
9970
771
            return offset;
9971
771
        }
9972
6.40k
        switch (tag_no) {
9973
1.83k
        case 0: /* objectIdentifier */
9974
1.83k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
9975
1.83k
            break;
9976
2.24k
        case 1: /* propertyIdentifier */
9977
2.24k
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9978
2.24k
            break;
9979
750
        case 2: /* arrayIndex - OPTIONAL */
9980
750
            offset = fUnsignedTag(tvb, pinfo, tree, offset,
9981
750
                "arrayIndex: ");
9982
750
            break;
9983
420
        case 3: /* deviceIdentifier - OPTIONAL */
9984
420
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
9985
420
            break;
9986
1.15k
        default:
9987
1.15k
            return offset;
9988
6.40k
        }
9989
5.22k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
9990
5.22k
    }
9991
879
    return offset;
9992
2.83k
}
9993
9994
static unsigned
9995
// NOLINTNEXTLINE(misc-no-recursion)
9996
fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9997
5.67k
{
9998
5.67k
    unsigned    lastoffset = offset;
9999
5.67k
    uint8_t     tag_no, tag_info;
10000
5.67k
    uint32_t    lvt;
10001
5.67k
    proto_tree *subtree = tree;
10002
5.67k
    proto_tree *pvtree;
10003
10004
5.67k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10005
5.67k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
10006
5.67k
        ett_bacapp_value, NULL, "notification parameters (%d) %s",
10007
5.67k
        tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
10008
    /* Opening tag for parameter choice */
10009
5.67k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10010
10011
5.67k
    switch (tag_no) {
10012
319
    case 0: /* change-of-bitstring */
10013
579
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10014
572
            lastoffset = offset;
10015
572
            switch (fTagNo(tvb, offset)) {
10016
299
            case 0:
10017
299
                offset = fBitStringTag(tvb, pinfo, subtree, offset,
10018
299
                    "referenced-bitstring: ");
10019
299
                break;
10020
36
            case 1:
10021
36
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10022
36
                    "status-flags: ", BACnetStatusFlags);
10023
36
                lastoffset = offset;
10024
36
                break;
10025
237
            default:
10026
237
                break;
10027
572
            }
10028
531
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10029
531
        }
10030
278
        break;
10031
278
    case 1: /* change-of-state */
10032
342
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10033
336
            lastoffset = offset;
10034
336
            switch (fTagNo(tvb, offset)) {
10035
238
            case 0:
10036
238
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10037
238
                offset  = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
10038
238
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10039
238
                break;
10040
33
            case 1:
10041
33
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10042
33
                    "status-flags: ", BACnetStatusFlags);
10043
33
                lastoffset = offset;
10044
33
                break;
10045
65
            default:
10046
65
                break;
10047
336
            }
10048
330
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10049
330
        }
10050
103
        break;
10051
218
    case 2: /* change-of-value */
10052
292
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10053
289
            lastoffset = offset;
10054
289
            switch (fTagNo(tvb, offset)) {
10055
83
            case 0:
10056
83
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10057
83
                switch (fTagNo(tvb, offset)) {
10058
43
                case 0:
10059
43
                    offset = fBitStringTag(tvb, pinfo, subtree, offset,
10060
43
                        "changed-bits: ");
10061
43
                    break;
10062
8
                case 1:
10063
8
                    offset = fRealTag(tvb, pinfo, subtree, offset,
10064
8
                        "changed-value: ");
10065
8
                    break;
10066
32
                default:
10067
32
                    break;
10068
83
                }
10069
74
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10070
74
                break;
10071
19
            case 1:
10072
19
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10073
19
                    "status-flags: ", BACnetStatusFlags);
10074
19
                lastoffset = offset;
10075
19
                break;
10076
187
            default:
10077
187
                break;
10078
289
            }
10079
280
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10080
280
        }
10081
209
        break;
10082
933
    case 3: /* command-failure */
10083
2.27k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10084
2.26k
            lastoffset = offset;
10085
2.26k
            switch (fTagNo(tvb, offset)) {
10086
1.45k
            case 0: /* "command-value: " */
10087
                /* from BACnet Table 13-3,
10088
                    Standard Object Property Values Returned in Notifications */
10089
1.45k
                propertyIdentifier = 85; /* PRESENT_VALUE */
10090
1.45k
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10091
1.45k
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10092
1.45k
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10093
1.45k
                break;
10094
221
            case 1:
10095
221
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10096
221
                    "status-flags: ", BACnetStatusFlags);
10097
221
                break;
10098
76
            case 2: /* "feedback-value: " */
10099
76
                propertyIdentifier = 40; /* FEEDBACK_VALUE */
10100
76
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10101
76
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10102
76
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10103
76
                lastoffset = offset;
10104
76
                break;
10105
512
            default:
10106
512
                break;
10107
2.26k
            }
10108
1.89k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10109
1.89k
        }
10110
565
        break;
10111
565
    case 4: /* floating-limit */
10112
589
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10113
586
            lastoffset = offset;
10114
586
            switch (fTagNo(tvb, offset)) {
10115
297
            case 0:
10116
297
                offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
10117
297
                break;
10118
110
            case 1:
10119
110
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10120
110
                    "status-flags: ", BACnetStatusFlags);
10121
110
                break;
10122
77
            case 2:
10123
77
                offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
10124
77
                break;
10125
24
            case 3:
10126
24
                offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
10127
24
                lastoffset = offset;
10128
24
                break;
10129
78
            default:
10130
78
                break;
10131
586
            }
10132
581
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10133
581
        }
10134
103
        break;
10135
108
    case 5: /* out-of-range */
10136
674
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10137
670
            lastoffset = offset;
10138
670
            switch (fTagNo(tvb, offset)) {
10139
286
            case 0:
10140
286
                offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10141
286
                break;
10142
208
            case 1:
10143
208
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10144
208
                    "status-flags: ", BACnetStatusFlags);
10145
208
                break;
10146
80
            case 2:
10147
80
                offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
10148
80
                break;
10149
32
            case 3:
10150
32
                offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10151
32
                lastoffset = offset;
10152
32
                break;
10153
64
            default:
10154
64
                break;
10155
670
            }
10156
661
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10157
661
        }
10158
99
        break;
10159
1.10k
    case 6:
10160
2.11k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10161
1.93k
            lastoffset = offset;
10162
1.93k
            offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
10163
1.93k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10164
1.93k
        }
10165
1.10k
        break;
10166
117
    case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
10167
851
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10168
844
            lastoffset = offset;
10169
844
            switch (fTagNo(tvb, offset)) {
10170
323
            case 0:
10171
323
                offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_device_identifier); /* buffer-device */
10172
323
                break;
10173
217
            case 1:
10174
217
                offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier); /* buffer-object */
10175
217
                break;
10176
203
            case 2:
10177
203
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10178
203
                offset  = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
10179
203
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10180
203
                break;
10181
19
            case 3:
10182
19
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10183
19
                offset  = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
10184
19
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10185
19
                lastoffset = offset;
10186
19
                break;
10187
82
            default:
10188
82
                break;
10189
844
            }
10190
834
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10191
834
        }
10192
107
        break;
10193
131
    case 8: /* change-of-life-safety */
10194
1.57k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10195
1.56k
            lastoffset = offset;
10196
1.56k
            switch (fTagNo(tvb, offset)) {
10197
1.09k
            case 0:
10198
1.09k
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10199
1.09k
                    "new-state: ", BACnetLifeSafetyState, 256);
10200
1.09k
                break;
10201
223
            case 1:
10202
223
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10203
223
                    "new-mode: ", BACnetLifeSafetyMode, 256);
10204
223
                break;
10205
131
            case 2:
10206
131
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10207
131
                    "status-flags: ", BACnetStatusFlags);
10208
131
                break;
10209
27
            case 3:
10210
27
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10211
27
                    "operation-expected: ", BACnetLifeSafetyOperation, 64);
10212
27
                lastoffset = offset;
10213
27
                break;
10214
97
            default:
10215
97
                break;
10216
1.56k
            }
10217
1.56k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10218
1.56k
        }
10219
128
        break;
10220
192
    case 9: /* extended */
10221
1.05k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10222
1.05k
            lastoffset = offset;
10223
1.05k
            switch (fTagNo(tvb, offset)) {
10224
741
            case 0:
10225
741
                offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10226
741
                break;
10227
121
            case 1:
10228
121
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "extended-event-type: ");
10229
121
                break;
10230
121
            case 2: /* parameters */
10231
121
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10232
10233
2.48k
                while (tvb_reported_length_remaining(tvb, offset) > 0) {
10234
2.44k
                    const unsigned param_lastoffset = offset;
10235
2.44k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10236
2.44k
                    if (tag_is_closing(tag_info))
10237
24
                    {
10238
24
                        break;
10239
24
                    }
10240
10241
2.41k
                    if (tag_is_opening(tag_info))
10242
391
                    {
10243
391
                        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10244
391
                        offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
10245
391
                        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10246
391
                    }
10247
2.02k
                    else
10248
2.02k
                    {
10249
2.02k
                        offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
10250
2.02k
                    }
10251
2.41k
                    if (offset <= param_lastoffset)
10252
57
                        break;     /* nothing happened, exit loop */
10253
2.41k
                }
10254
10255
121
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10256
121
                lastoffset = offset;
10257
121
                break;
10258
69
            default:
10259
69
                break;
10260
1.05k
            }
10261
1.01k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10262
1.01k
        }
10263
152
        break;
10264
152
    case 10: /* buffer ready */
10265
464
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10266
461
            lastoffset = offset;
10267
461
            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
167
            case 1:
10274
167
                offset  = fUnsignedTag(tvb, pinfo, subtree, offset,
10275
167
                    "previous-notification: ");
10276
167
                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
97
            default:
10283
97
                break;
10284
461
            }
10285
452
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10286
452
        }
10287
112
        break;
10288
112
    case 11: /* unsigned range */
10289
922
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10290
919
            lastoffset = offset;
10291
919
            switch (fTagNo(tvb, offset)) {
10292
672
            case 0:
10293
672
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10294
672
                    "exceeding-value: ");
10295
672
                break;
10296
150
            case 1:
10297
150
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10298
150
                    "status-flags: ", BACnetStatusFlags);
10299
150
                break;
10300
15
            case 2:
10301
15
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10302
15
                    "exceeded-limit: ");
10303
15
                lastoffset = offset;
10304
15
                break;
10305
82
            default:
10306
82
                break;
10307
919
            }
10308
913
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10309
913
        }
10310
98
        break;
10311
        /* 12 reserved */
10312
218
    case 13: /* access-event */
10313
3.86k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10314
3.85k
            lastoffset = offset;
10315
3.85k
            switch (fTagNo(tvb, offset)) {
10316
2.10k
            case 0:
10317
2.10k
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10318
2.10k
                                              "access event: ", BACnetAccessEvent, 512);
10319
2.10k
                break;
10320
403
            case 1:
10321
403
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10322
403
                    "status-flags: ", BACnetStatusFlags);
10323
403
                break;
10324
343
            case 2:
10325
343
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10326
343
                    "access-event-tag: ");
10327
343
                break;
10328
360
            case 3:
10329
360
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10330
360
                offset  = fTimeStamp(tvb, pinfo, subtree, offset, "access-event-time: ");
10331
360
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10332
360
                break;
10333
455
            case 4:
10334
455
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10335
455
                offset  = fDeviceObjectReference(tvb, pinfo, subtree, offset);
10336
455
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10337
455
                break;
10338
58
            case 5: /* optional authentication-factor */
10339
58
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10340
58
                offset  = fAuthenticationFactor(tvb, pinfo, subtree, offset);
10341
58
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10342
58
                lastoffset = offset;
10343
58
                break;
10344
136
            default:
10345
136
                break;
10346
3.85k
            }
10347
3.83k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10348
3.83k
        }
10349
199
        break;
10350
199
    case 14: /* double-out-of-range */
10351
530
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10352
526
            lastoffset = offset;
10353
526
            switch (fTagNo(tvb, offset)) {
10354
234
            case 0:
10355
234
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10356
234
                break;
10357
111
            case 1:
10358
111
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10359
111
                    "status-flags: ", BACnetStatusFlags);
10360
111
                break;
10361
105
            case 2:
10362
105
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
10363
105
                break;
10364
15
            case 3:
10365
15
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10366
15
                lastoffset = offset;
10367
15
                break;
10368
61
            default:
10369
61
                break;
10370
526
            }
10371
515
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10372
515
        }
10373
78
        break;
10374
81
    case 15: /* signed-out-of-range */
10375
1.11k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10376
1.11k
            lastoffset = offset;
10377
1.11k
            switch (fTagNo(tvb, offset)) {
10378
937
            case 0:
10379
937
                offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10380
937
                break;
10381
60
            case 1:
10382
60
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10383
60
                    "status-flags: ", BACnetStatusFlags);
10384
60
                break;
10385
43
            case 2:
10386
43
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10387
43
                break;
10388
30
            case 3:
10389
30
                offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10390
30
                lastoffset = offset;
10391
30
                break;
10392
48
            default:
10393
48
                break;
10394
1.11k
            }
10395
1.11k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10396
1.11k
        }
10397
79
        break;
10398
79
    case 16: /* unsigned-out-of-range */
10399
1.55k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10400
1.55k
            lastoffset = offset;
10401
1.55k
            switch (fTagNo(tvb, offset)) {
10402
903
            case 0:
10403
903
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
10404
903
                break;
10405
266
            case 1:
10406
266
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10407
266
                    "status-flags: ", BACnetStatusFlags);
10408
266
                break;
10409
335
            case 2:
10410
335
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10411
335
                break;
10412
7
            case 3:
10413
7
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
10414
7
                lastoffset = offset;
10415
7
                break;
10416
40
            default:
10417
40
                break;
10418
1.55k
            }
10419
1.54k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10420
1.54k
        }
10421
52
        break;
10422
52
    case 17: /* change-of-characterstring */
10423
51
        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
10424
51
            lastoffset = offset;
10425
51
            switch (fTagNo(tvb, offset)) {
10426
30
            case 0:
10427
                 /* changed-value (CharacterString) */
10428
30
                offset  = fCharacterString(tvb, pinfo, subtree, offset, "changed-value: ");
10429
30
                break;
10430
9
            case 1:
10431
9
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10432
9
                    "status-flags: ", BACnetStatusFlags);
10433
9
                break;
10434
1
            case 2:
10435
                /* alarm-value (CharacterString) */
10436
1
                offset  = fCharacterString(tvb, pinfo, subtree, offset, "alarm-value: ");
10437
1
                lastoffset = offset;
10438
1
                break;
10439
11
            default:
10440
11
                break;
10441
51
            }
10442
49
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10443
49
        }
10444
12
        break;
10445
32
    case 18: /* change-of-status-flags */
10446
288
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10447
            /* exit loop if nothing happens inside */
10448
286
            lastoffset = offset;
10449
286
            switch (fTagNo(tvb, offset)) {
10450
262
            case 0:
10451
262
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10452
10453
262
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10454
262
                if (tag_is_context_specific(tag_info)) {
10455
31
                    propertyIdentifier = 85; /* suppose present-value here */
10456
31
                    offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10457
231
                } else {
10458
231
                    offset = fPresentValue(tvb, pinfo, tree, offset, BACnetStatusFlags, 0, BACAPP_PRESENT_VALUE_ENUM);
10459
231
                }
10460
10461
262
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10462
262
                break;
10463
2
            case 1:
10464
2
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10465
2
                    "referenced-flags: ", BACnetStatusFlags);
10466
2
                lastoffset = offset;
10467
2
                break;
10468
22
            default:
10469
22
                break;
10470
286
            }
10471
279
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10472
279
        }
10473
25
        break;
10474
36
    case 19: /* change-of-reliability */
10475
668
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10476
            /* exit loop if nothing happens inside */
10477
667
            lastoffset = offset;
10478
10479
667
            switch (fTagNo(tvb, offset)) {
10480
375
            case 0:
10481
375
               offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "reliability:", BACnetReliability);
10482
375
               break;
10483
111
            case 1:
10484
111
               offset = fBitStringTagVS(tvb, pinfo, subtree, offset, "status-flags: ", BACnetStatusFlags);
10485
111
               break;
10486
152
            case 2: /* property-values */
10487
152
               fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10488
152
               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
150
               pvtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "property-values");
10493
150
               offset += fTagHeaderTree(tvb, pinfo, pvtree, offset, &tag_no, &tag_info, &lvt);
10494
150
               offset = fBACnetPropertyValue(tvb, pinfo, pvtree, offset);
10495
150
               offset += fTagHeaderTree(tvb, pinfo, pvtree, offset, &tag_no, &tag_info, &lvt);
10496
150
               break;
10497
29
            default:
10498
29
               break;
10499
667
           }
10500
661
           if (offset <= lastoffset)
10501
29
               break;     /* nothing happened, exit loop */
10502
661
        }
10503
30
        break;
10504
30
    case 20: /* context tag [20] is not used */
10505
7
        break;
10506
25
    case 21: /* change-of-discrete-value */
10507
297
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10508
            /* exit loop if nothing happens inside */
10509
296
            lastoffset = offset;
10510
296
            switch (fTagNo(tvb, offset)) {
10511
238
            case 0: /* new-value */
10512
238
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10513
10514
238
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10515
238
                if (tag_is_opening(tag_info))
10516
19
                {
10517
19
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10518
19
                    offset  = fDateTime(tvb, pinfo, subtree, offset, "new-value: ");
10519
19
                    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10520
19
                }
10521
219
                else
10522
219
                {
10523
219
                    offset  = fApplicationTypes(tvb, pinfo, subtree, offset, "new-value: ");
10524
219
                }
10525
10526
238
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10527
238
                break;
10528
35
            case 1: /* status-flags */
10529
35
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10530
35
                    "status-flags: ", BACnetStatusFlags);
10531
35
                break;
10532
23
            default:
10533
23
                break;
10534
296
            }
10535
295
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10536
295
        }
10537
24
        break;
10538
65
    case 22: /* change-of-timer */
10539
2.54k
        while (tvb_reported_length_remaining(tvb, offset) > 0) {
10540
            /* exit loop if nothing happens inside */
10541
2.54k
            lastoffset = offset;
10542
2.54k
            switch (fTagNo(tvb, offset)) {
10543
1.74k
            case 0: /* new-state */
10544
1.74k
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10545
1.74k
                    "new-state: ", BACnetTimerState, 256);
10546
1.74k
                break;
10547
76
            case 1: /* status-flags */
10548
76
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
10549
76
                    "status-flags: ", BACnetStatusFlags);
10550
76
                break;
10551
204
            case 2: /* update-time */
10552
204
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10553
204
                offset  = fDateTime(tvb, pinfo, subtree, offset, "update-time: ");
10554
204
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10555
204
                break;
10556
330
            case 3: /* last-state-change (OPTIONAL) */
10557
330
                offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10558
330
                    "new-state: ", BACnetTimerTransition, 256);
10559
330
                break;
10560
131
            case 4: /* initial-timeout (OPTIONAL) */
10561
131
                offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "initial-timeout: ");
10562
131
                break;
10563
57
            default:
10564
57
                break;
10565
2.54k
            }
10566
2.53k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10567
2.53k
        }
10568
59
        break;
10569
10570
        /* todo: add new parameters here ... */
10571
1.48k
    default:
10572
1.48k
        offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10573
1.48k
        break;
10574
5.67k
    }
10575
10576
    /* Closing tag for parameter choice */
10577
4.84k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10578
10579
4.84k
    return offset;
10580
5.67k
}
10581
10582
static unsigned
10583
// NOLINTNEXTLINE(misc-no-recursion)
10584
fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10585
29.1k
{
10586
29.1k
    unsigned    lastoffset = offset;
10587
29.1k
    uint8_t     tag_no, tag_info;
10588
29.1k
    uint32_t    lvt;
10589
29.1k
    proto_tree *subtree = tree;
10590
10591
29.1k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10592
29.1k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
10593
29.1k
        ett_bacapp_value, NULL, "event parameters (%d) %s",
10594
29.1k
        tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
10595
10596
    /* Opening tag for parameter choice */
10597
29.1k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10598
10599
29.1k
    switch (tag_no) {
10600
3.22k
    case 0: /* change-of-bitstring */
10601
14.5k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10602
11.7k
            lastoffset = offset;
10603
11.7k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10604
11.7k
            if (tag_is_closing(tag_info)) {
10605
345
                break;
10606
345
            }
10607
11.4k
            switch (tag_no) {
10608
7.88k
            case 0:
10609
7.88k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10610
7.88k
                break;
10611
665
            case 1:
10612
665
                offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
10613
665
                break;
10614
181
            case 2: /* SEQUENCE OF BIT STRING */
10615
181
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10616
1.07k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10617
972
                    lastoffset = offset;
10618
972
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10619
972
                    if (tag_is_closing(tag_info)) {
10620
77
                        break;
10621
77
                    }
10622
895
                    offset = fBitStringTag(tvb, pinfo, subtree, offset,
10623
895
                                           "bitstring value: ");
10624
895
                }
10625
181
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10626
181
                break;
10627
2.70k
            default:
10628
2.70k
                break;
10629
11.4k
            }
10630
11.4k
        }
10631
3.09k
        break;
10632
3.09k
    case 1: /* change-of-state */
10633
2.99k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10634
2.17k
            lastoffset = offset;
10635
2.17k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10636
2.17k
            if (tag_is_closing(tag_info)) {
10637
98
                break;
10638
98
            }
10639
2.07k
            switch (tag_no) {
10640
998
            case 0:
10641
998
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10642
998
                break;
10643
274
            case 1: /* SEQUENCE OF BACnetPropertyStates */
10644
274
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10645
8.05k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10646
7.97k
                    lastoffset = offset;
10647
7.97k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10648
7.97k
                    if (tag_is_closing(tag_info)) {
10649
194
                        break;
10650
194
                    }
10651
7.78k
                    offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
10652
7.78k
                }
10653
274
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10654
274
                break;
10655
805
            default:
10656
805
                break;
10657
2.07k
            }
10658
2.07k
        }
10659
920
        break;
10660
2.32k
    case 2: /* change-of-value */
10661
6.79k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10662
4.48k
            lastoffset = offset;
10663
4.48k
            switch (fTagNo(tvb, offset)) {
10664
1.84k
            case 0:
10665
1.84k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10666
1.84k
                break;
10667
342
            case 1: /* don't loop it, it's a CHOICE */
10668
342
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10669
342
                switch (fTagNo(tvb, offset)) {
10670
25
                case 0:
10671
25
                    offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
10672
25
                    break;
10673
228
                case 1:
10674
228
                    offset = fRealTag(tvb, pinfo, subtree, offset,
10675
228
                                       "referenced Property Increment: ");
10676
228
                    break;
10677
88
                default:
10678
88
                    break;
10679
342
                }
10680
337
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10681
337
                break;
10682
2.29k
            default:
10683
2.29k
                break;
10684
4.48k
            }
10685
4.48k
        }
10686
2.31k
        break;
10687
2.31k
    case 3: /* command-failure */
10688
4.46k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10689
2.92k
            lastoffset = offset;
10690
2.92k
            tag_no = fTagNo(tvb, offset);
10691
2.92k
            switch (tag_no) {
10692
992
            case 0:
10693
992
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10694
992
                break;
10695
398
            case 1:
10696
398
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10697
398
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10698
398
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10699
398
                break;
10700
1.53k
            default:
10701
1.53k
                break;
10702
2.92k
            }
10703
2.92k
        }
10704
1.54k
        break;
10705
1.54k
    case 4: /* floating-limit */
10706
9.03k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10707
7.83k
            lastoffset = offset;
10708
7.83k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10709
7.83k
            if (tag_is_closing(tag_info)) {
10710
268
                break;
10711
268
            }
10712
7.56k
            switch (tag_no) {
10713
3.65k
            case 0:
10714
3.65k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10715
3.65k
                break;
10716
610
            case 1:
10717
610
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10718
610
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10719
610
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10720
610
                break;
10721
340
            case 2:
10722
340
                offset  = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
10723
340
                break;
10724
453
            case 3:
10725
453
                offset  = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
10726
453
                break;
10727
1.33k
            case 4:
10728
1.33k
                offset  = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
10729
1.33k
                break;
10730
1.17k
            default:
10731
1.17k
                break;
10732
7.56k
            }
10733
7.56k
        }
10734
1.47k
        break;
10735
1.55k
    case 5: /* out-of-range */
10736
5.40k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10737
3.85k
            lastoffset = offset;
10738
3.85k
            switch (fTagNo(tvb, offset)) {
10739
1.35k
            case 0:
10740
1.35k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10741
1.35k
                break;
10742
293
            case 1:
10743
293
                offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
10744
293
                break;
10745
381
            case 2:
10746
381
                offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
10747
381
                break;
10748
298
            case 3:
10749
298
                offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
10750
298
                break;
10751
1.53k
            default:
10752
1.53k
                break;
10753
3.85k
            }
10754
3.85k
        }
10755
1.54k
        break;
10756
1.91k
    case 6: /* complex-event-type */
10757
        /* deprecated */
10758
1.91k
        offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
10759
1.91k
        break;
10760
2.65k
    case 7: /* buffer-ready */
10761
        /* deprecated */
10762
5.06k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
10763
5.04k
            lastoffset = offset;
10764
5.04k
            switch (fTagNo(tvb, offset)) {
10765
1.65k
            case 0:
10766
1.65k
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
10767
1.65k
                break;
10768
751
            case 1:
10769
751
                offset = fUnsignedTag(tvb, pinfo, tree, offset,
10770
751
                                       "previous notification count: ");
10771
751
                break;
10772
2.63k
            default:
10773
2.63k
                return offset;
10774
5.04k
            }
10775
5.04k
        }
10776
18
        break;
10777
1.74k
    case 8: /* change-of-life-safety */
10778
5.09k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10779
3.39k
            lastoffset = offset;
10780
3.39k
            switch (fTagNo(tvb, offset)) {
10781
1.18k
            case 0:
10782
1.18k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10783
1.18k
                break;
10784
166
            case 1:
10785
166
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10786
1.29k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10787
1.28k
                    lastoffset = offset;
10788
1.28k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10789
1.28k
                    if (tag_is_closing(tag_info)) {
10790
151
                        break;
10791
151
                    }
10792
1.13k
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10793
1.13k
                                                  "life safety alarm value: ", BACnetLifeSafetyState, 256);
10794
1.13k
                }
10795
166
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10796
166
                break;
10797
196
            case 2:
10798
196
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10799
1.62k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10800
1.60k
                    lastoffset = offset;
10801
1.60k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10802
1.60k
                    if (tag_is_closing(tag_info)) {
10803
173
                        break;
10804
173
                    }
10805
1.42k
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10806
1.42k
                                                  "alarm value: ", BACnetLifeSafetyState, 256);
10807
1.42k
                }
10808
196
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10809
196
                break;
10810
154
            case 3:
10811
154
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10812
154
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10813
154
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10814
154
                break;
10815
1.69k
            default:
10816
1.69k
                break;
10817
3.39k
            }
10818
3.39k
        }
10819
1.70k
        break;
10820
2.66k
    case 9: /* extended */
10821
4.49k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10822
4.49k
            lastoffset = offset;
10823
4.49k
            switch (fTagNo(tvb, offset)) {
10824
1.41k
            case 0:
10825
1.41k
                offset = fVendorIdentifier(tvb, pinfo, tree, offset);
10826
1.41k
                break;
10827
431
            case 1:
10828
431
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "extended-event-type: ");
10829
431
                break;
10830
308
            case 2: /* parameters */
10831
308
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10832
4.46k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10833
4.19k
                    lastoffset = offset;
10834
4.19k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10835
4.19k
                    if (tag_is_closing(tag_info) && tag_no == 2) {
10836
31
                        break;
10837
31
                    }
10838
10839
4.16k
                    if ( ! tag_is_context_specific(tag_info)) {
10840
3.10k
                        offset  = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
10841
3.10k
                    } else {
10842
1.05k
                        if (tag_no == 0) {
10843
550
                            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10844
550
                            offset  = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
10845
550
                            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10846
550
                        } else {
10847
503
                            offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
10848
503
                        }
10849
1.05k
                    }
10850
4.16k
                }
10851
308
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10852
308
                lastoffset = offset;
10853
308
                break;
10854
2.33k
            default:
10855
2.33k
                break;
10856
4.49k
            }
10857
4.33k
            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
10858
4.33k
        }
10859
2.50k
        break;
10860
2.50k
    case 10: /* buffer-ready */
10861
3.67k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10862
2.49k
            lastoffset = offset;
10863
2.49k
            switch (fTagNo(tvb, offset)) {
10864
843
            case 0:
10865
843
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10866
843
                                       "notification-threshold: ");
10867
843
                break;
10868
474
            case 1:
10869
474
                offset = fUnsignedTag(tvb, pinfo, subtree, offset,
10870
474
                                       "previous-notification-count: ");
10871
474
                break;
10872
1.17k
            default:
10873
1.17k
                break;
10874
2.49k
            }
10875
2.49k
        }
10876
1.18k
        break;
10877
1.45k
    case 11: /* unsigned-range */
10878
4.42k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10879
2.97k
            lastoffset = offset;
10880
2.97k
            switch (fTagNo(tvb, offset)) {
10881
1.12k
            case 0:
10882
1.12k
                offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
10883
1.12k
                break;
10884
234
            case 1:
10885
234
                offset = fUnsignedTag(tvb, pinfo, tree, offset,
10886
234
                                       "low-limit: ");
10887
234
                break;
10888
172
            case 2:
10889
172
                offset = fUnsignedTag(tvb, pinfo, tree, offset,
10890
172
                                       "high-limit: ");
10891
172
                break;
10892
1.44k
            default:
10893
1.44k
                break;
10894
2.97k
            }
10895
2.97k
        }
10896
1.45k
        break;
10897
1.45k
    case 13: /* access-event */
10898
3.23k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10899
1.94k
            lastoffset = offset;
10900
1.94k
            switch (fTagNo(tvb, offset)) {
10901
461
            case 0:
10902
                /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
10903
461
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10904
2.71k
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10905
2.67k
                    lastoffset = offset;
10906
2.67k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10907
2.67k
                    if (tag_is_closing(tag_info)) {
10908
426
                        break;
10909
426
                    }
10910
2.25k
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
10911
2.25k
                                                  "access event: ", BACnetAccessEvent, 512);
10912
2.25k
                }
10913
461
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10914
461
                break;
10915
202
            case 1:
10916
202
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10917
202
                offset  = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
10918
202
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10919
202
                break;
10920
1.28k
            default:
10921
1.28k
                break;
10922
1.94k
            }
10923
1.94k
        }
10924
1.28k
        break;
10925
1.54k
    case 14: /* double-out-of-range */
10926
5.86k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10927
4.34k
            lastoffset = offset;
10928
4.34k
            switch (fTagNo(tvb, offset)) {
10929
1.93k
            case 0:
10930
1.93k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10931
1.93k
                break;
10932
230
            case 1:
10933
230
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
10934
230
                break;
10935
391
            case 2:
10936
391
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
10937
391
                break;
10938
287
            case 3:
10939
287
                offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
10940
287
                break;
10941
1.51k
            default:
10942
1.51k
                break;
10943
4.34k
            }
10944
4.34k
        }
10945
1.52k
        break;
10946
1.52k
    case 15: /* signed-out-of-range */
10947
1.12k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10948
1.03k
            lastoffset = offset;
10949
1.03k
            switch (fTagNo(tvb, offset)) {
10950
481
            case 0:
10951
481
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10952
481
                break;
10953
87
            case 1:
10954
87
                offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
10955
87
                break;
10956
188
            case 2:
10957
188
                offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
10958
188
                break;
10959
197
            case 3:
10960
197
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10961
197
                break;
10962
82
            default:
10963
82
                break;
10964
1.03k
            }
10965
1.03k
        }
10966
87
        break;
10967
94
    case 16: /* unsigned-out-of-range */
10968
2.56k
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10969
2.47k
            lastoffset = offset;
10970
2.47k
            switch (fTagNo(tvb, offset)) {
10971
1.03k
            case 0:
10972
1.03k
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10973
1.03k
                break;
10974
1.12k
            case 1:
10975
1.12k
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
10976
1.12k
                break;
10977
57
            case 2:
10978
57
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
10979
57
                break;
10980
173
            case 3:
10981
173
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
10982
173
                break;
10983
83
            default:
10984
83
                break;
10985
2.47k
            }
10986
2.47k
        }
10987
94
        break;
10988
94
    case 17: /* change-of-characterstring */
10989
214
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
10990
193
            lastoffset = offset;
10991
193
            switch (fTagNo(tvb, offset)) {
10992
143
            case 0:
10993
143
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
10994
143
                break;
10995
29
            case 1: /* SEQUENCE OF CharacterString */
10996
29
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10997
304
                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
17
                        break;
11002
17
                    }
11003
275
                    offset  = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
11004
275
                }
11005
29
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11006
29
                break;
11007
21
            default:
11008
21
                break;
11009
193
            }
11010
193
        }
11011
21
        break;
11012
39
    case 18: /* change-of-status-flags */
11013
509
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11014
473
            lastoffset = offset;
11015
473
            switch (fTagNo(tvb, offset)) {
11016
344
            case 0:
11017
344
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11018
344
                break;
11019
94
            case 1:
11020
94
                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11021
94
                    "selected flags: ", BACnetStatusFlags);
11022
94
                break;
11023
35
            default:
11024
35
                break;
11025
473
            }
11026
473
        }
11027
36
        break;
11028
36
    case 19: /* has been intentionally omitted. It parallels the change-of-reliability event type */
11029
0
        break;
11030
14
    case 20: /* none */
11031
        /* no closing tag expected only context tag here */
11032
14
        return offset;
11033
15
    case 21: /* change-of-discrete-value */
11034
170
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11035
155
            lastoffset = offset;
11036
155
            switch (fTagNo(tvb, offset)) {
11037
140
            case 0:
11038
140
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11039
140
                break;
11040
15
            default:
11041
15
                break;
11042
155
            }
11043
155
        }
11044
15
        break;
11045
80
    case 22: /* change-of-timer */
11046
532
        while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11047
459
            lastoffset = offset;
11048
459
            switch (fTagNo(tvb, offset)) {
11049
200
            case 0: /* time-delay */
11050
200
                offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11051
200
                break;
11052
85
            case 1: /* alarm-values */
11053
85
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11054
750
                while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
11055
743
                    lastoffset = offset;
11056
743
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11057
743
                    if (tag_is_closing(tag_info)) {
11058
78
                        break;
11059
78
                    }
11060
665
                offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
11061
665
                                                  "alarm value: ", BACnetTimerState);
11062
665
                }
11063
85
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11064
85
                break;
11065
108
            case 2: /* update-time-reference */
11066
108
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11067
108
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11068
108
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11069
108
                break;
11070
66
            default:
11071
66
                break;
11072
459
            }
11073
459
        }
11074
73
        break;
11075
    /* todo: add new event-parameter cases here */
11076
3.08k
  default:
11077
3.08k
        break;
11078
29.1k
    }
11079
11080
    /* Closing tag for parameter choice */
11081
25.8k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11082
25.8k
    return offset;
11083
29.1k
}
11084
11085
static unsigned
11086
fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11087
8.43k
{
11088
8.43k
    unsigned    lastoffset = offset;
11089
8.43k
    uint8_t     tag_no, tag_info;
11090
8.43k
    uint32_t    lvt;
11091
8.43k
    proto_tree *subtree = tree;
11092
11093
8.43k
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11094
8.43k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11095
8.43k
      ett_bacapp_value, NULL, "fault parameters (%d) %s",
11096
8.43k
      tag_no, val_to_str_const(tag_no, BACnetFaultType, "invalid type"));
11097
11098
    /* Opening tag for parameter choice */
11099
8.43k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11100
11101
8.43k
    switch (tag_no) {
11102
2.85k
    case 0: /* none */
11103
        /* no closing tag expected only context tag here */
11104
2.85k
        return offset;
11105
529
    case 1: /* fault-characterstring */
11106
1.04k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11107
539
            lastoffset = offset;
11108
539
            switch (fTagNo(tvb, offset)) {
11109
36
            case 0: /* SEQUENCE OF CharacterString */
11110
36
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11111
338
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11112
315
                    lastoffset = offset;
11113
315
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11114
315
                    if (tag_is_closing(tag_info)) {
11115
13
                        break;
11116
13
                    }
11117
302
                    offset = fCharacterString(tvb, pinfo, subtree, offset, "fault value: ");
11118
302
                }
11119
36
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11120
36
                break;
11121
503
            default:
11122
503
                break;
11123
539
            }
11124
539
        }
11125
506
        break;
11126
514
    case 2: /* fault-extended */
11127
2.07k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11128
1.57k
            lastoffset = offset;
11129
1.57k
            switch (fTagNo(tvb, offset)) {
11130
845
            case 0:
11131
845
                offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
11132
845
                break;
11133
220
            case 1:
11134
220
                offset = fUnsignedTag(tvb, pinfo, subtree, offset, "extended-fault-type: ");
11135
220
                break;
11136
148
            case 2: /* parameters */
11137
148
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11138
148
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
11139
148
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11140
148
                lastoffset = offset;
11141
148
                break;
11142
359
            default:
11143
359
                break;
11144
1.57k
            }
11145
1.57k
        }
11146
506
        break;
11147
506
    case 3: /* fault-life-safety */
11148
725
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11149
442
            lastoffset = offset;
11150
442
            switch (fTagNo(tvb, offset)) {
11151
68
            case 0:
11152
68
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11153
1.04k
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11154
1.02k
                    lastoffset = offset;
11155
1.02k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11156
1.02k
                    if (tag_is_closing(tag_info)) {
11157
51
                        break;
11158
51
                    }
11159
974
                    offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
11160
974
                      "fault value: ", BACnetLifeSafetyState);
11161
974
                }
11162
68
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11163
68
                break;
11164
94
            case 1:
11165
94
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11166
94
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11167
94
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11168
94
                break;
11169
280
            default:
11170
280
                break;
11171
442
            }
11172
442
        }
11173
283
        break;
11174
526
    case 4: /* fault-state */
11175
1.07k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11176
581
            lastoffset = offset;
11177
581
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11178
581
            if (tag_is_closing(tag_info)) {
11179
17
                break;
11180
17
            }
11181
564
            switch (tag_no) {
11182
73
            case 0: /* SEQUENCE OF BACnetPropertyStates */
11183
73
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11184
1.56k
                while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11185
1.54k
                    lastoffset = offset;
11186
1.54k
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11187
1.54k
                    if (tag_is_closing(tag_info)) {
11188
60
                        break;
11189
60
                    }
11190
1.48k
                    offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
11191
1.48k
                }
11192
73
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11193
73
                break;
11194
491
            default:
11195
491
                break;
11196
564
            }
11197
564
        }
11198
513
        break;
11199
513
    case 5: /* fault-status-flags */
11200
906
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11201
500
            lastoffset = offset;
11202
500
            switch (fTagNo(tvb, offset)) {
11203
98
            case 0:
11204
98
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11205
98
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11206
98
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11207
98
                break;
11208
402
            default:
11209
402
                break;
11210
500
            }
11211
500
        }
11212
406
        break;
11213
1.21k
    case 6: /* fault-out-of-range */
11214
2.88k
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11215
1.74k
            lastoffset = offset;
11216
1.74k
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11217
1.74k
            if (tag_is_closing(tag_info)) {
11218
69
                break;
11219
69
            }
11220
1.67k
            switch (fTagNo(tvb, offset)) {
11221
368
            case 0:
11222
368
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11223
368
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "min-normal-value: ");
11224
368
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11225
368
                break;
11226
162
            case 1:
11227
162
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11228
162
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "max-normal-value: ");
11229
162
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11230
162
                break;
11231
1.14k
            default:
11232
1.14k
                break;
11233
1.67k
            }
11234
1.67k
        }
11235
1.21k
        break;
11236
1.21k
    case 7: /* fault-listed */
11237
954
        while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) {  /* exit loop if nothing happens inside */
11238
511
            lastoffset = offset;
11239
511
            switch (fTagNo(tvb, offset)) {
11240
71
            case 0:
11241
71
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11242
71
                offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11243
71
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11244
71
                break;
11245
440
            default:
11246
440
                break;
11247
511
          }
11248
511
        }
11249
443
      break;
11250
1.63k
    default:
11251
1.63k
      break;
11252
8.43k
    }
11253
11254
    /* Closing tag for parameter choice */
11255
5.50k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11256
5.50k
    return offset;
11257
8.43k
}
11258
11259
static unsigned
11260
fEventNotificationSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11261
76
{
11262
76
    unsigned    lastoffset = 0;
11263
76
    uint8_t     tag_no, tag_info;
11264
76
    uint32_t    lvt;
11265
76
    proto_tree *subtree;
11266
76
    unsigned    itemno = 1;
11267
11268
1.18k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {  /* exit loop if nothing happens inside */
11269
1.18k
        lastoffset = offset;
11270
1.18k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11271
1.18k
        if (tag_is_closing(tag_info)) {
11272
6
            return offset;
11273
6
        }
11274
1.17k
        switch (tag_no) {
11275
250
        case 0: /* recipient  */
11276
250
            tree = proto_tree_add_subtree_format(tree, tvb, offset, 1,
11277
250
              ett_bacapp_value, NULL, "Subscription %d", itemno);    /* add tree label and indent */
11278
250
            itemno = itemno + 1;
11279
11280
250
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
11281
250
              ett_bacapp_value, NULL, "Recipient: ");    /* add tree label and indent */
11282
250
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
11283
250
            offset = fRecipient(tvb, pinfo, subtree, offset);
11284
250
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
11285
250
            break;
11286
179
        case 1: /* process-identifier  */
11287
179
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Process Identifier: ");
11288
179
            break;
11289
524
        case 2: /* issue-confirmed-notifications  */
11290
524
            offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
11291
524
            break;
11292
156
        case 3: /* time-remaining  */
11293
156
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
11294
156
            break;
11295
66
        default:
11296
66
            return offset;
11297
1.17k
        }
11298
1.17k
    }
11299
11300
3
    return offset;
11301
76
}
11302
11303
static unsigned
11304
fLightingCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11305
219
{
11306
219
    unsigned   lastoffset = 0;
11307
219
    uint8_t tag_no, tag_info;
11308
219
    uint32_t lvt;
11309
219
    proto_tree *subtree = tree;
11310
11311
219
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11312
219
      ett_bacapp_value, NULL, "%s", lable);
11313
11314
3.27k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11315
3.25k
        lastoffset = offset;
11316
        /* check the tag.  A closing tag means we are done */
11317
3.25k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11318
3.25k
        if (tag_is_closing(tag_info)) {
11319
61
            return offset;
11320
61
        }
11321
3.19k
        switch (tag_no) {
11322
1.35k
        case 0: /* operation */
11323
1.35k
            offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "operation: ", BACnetLightingOperation);
11324
1.35k
            break;
11325
300
        case 1: /* target-level */
11326
300
            offset = fRealTag(tvb, pinfo, subtree, offset, "target-level: ");
11327
300
            break;
11328
199
        case 2: /* ramp-rate */
11329
199
            offset = fRealTag(tvb, pinfo, subtree, offset, "ramp-rate: ");
11330
199
            break;
11331
198
        case 3: /* step-increment */
11332
198
            offset = fRealTag(tvb, pinfo, subtree, offset, "step-increment: ");
11333
198
            break;
11334
449
        case 4: /* fade-time */
11335
449
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "fade-time: ");
11336
449
            break;
11337
567
        case 5: /* priority */
11338
567
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "priority: ");
11339
567
            break;
11340
126
        default:
11341
126
            return offset;
11342
3.19k
        }
11343
3.19k
    }
11344
11345
23
    return offset;
11346
219
}
11347
11348
static unsigned
11349
fColorCommand(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable)
11350
265
{
11351
265
    unsigned   lastoffset = 0;
11352
265
    uint8_t tag_no, tag_info;
11353
265
    uint32_t lvt;
11354
265
    proto_tree* subtree = tree;
11355
11356
265
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11357
265
        ett_bacapp_value, NULL, "%s", lable);
11358
11359
3.07k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11360
3.05k
        lastoffset = offset;
11361
        /* check the tag.  A closing tag means we are done */
11362
3.05k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11363
3.05k
        if (tag_is_closing(tag_info)) {
11364
78
            return offset;
11365
78
        }
11366
2.98k
        switch (tag_no) {
11367
1.27k
        case 0: /* operation */
11368
1.27k
            offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "operation: ", BACnetColorOperation);
11369
1.27k
            break;
11370
203
        case 1: /* target-color */
11371
203
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11372
203
            offset = fXyColor(tvb, pinfo, subtree, offset, "xy-color: ");
11373
203
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11374
203
            break;
11375
355
        case 2: /* target-color-temperature */
11376
355
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "target-color-temperature: ");
11377
355
            break;
11378
268
        case 3: /* fade-time */
11379
268
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "fade-time: ");
11380
268
            break;
11381
404
        case 4: /* ramp-rate */
11382
404
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "ramp-rate: ");
11383
404
            break;
11384
313
        case 5: /* step-increment */
11385
313
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "step-increment: ");
11386
313
            break;
11387
165
        default:
11388
165
            return offset;
11389
2.98k
        }
11390
2.98k
    }
11391
11392
13
    return offset;
11393
265
}
11394
11395
static unsigned
11396
fXyColor(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* label)
11397
413
{
11398
413
    proto_tree* subtree = tree;
11399
11400
413
    if (label != NULL) {
11401
413
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
11402
413
    }
11403
413
    offset = fRealTag(tvb, pinfo, subtree, offset, "x-coordinate: ");
11404
413
    return fRealTag(tvb, pinfo, subtree, offset, "y-coordinate: ");
11405
413
}
11406
11407
static unsigned
11408
// NOLINTNEXTLINE(misc-no-recursion)
11409
fTimerStateChangeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11410
149
{
11411
149
    unsigned   lastoffset = 0;
11412
149
    uint8_t tag_no, tag_info;
11413
149
    uint32_t lvt;
11414
149
    int32_t save_propertyIdentifier;
11415
149
    unsigned ftag_offset;
11416
11417
855
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11418
842
        lastoffset = offset;
11419
        /* check the tag. A closing tag means we are done */
11420
842
        ftag_offset = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11421
842
        if (tag_is_closing(tag_info)) {
11422
11
            return offset;
11423
11
        }
11424
831
        if (tag_is_context_specific(tag_info)){
11425
255
            switch (tag_no) {
11426
79
            case 0: /* no-value */
11427
79
                offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
11428
79
                break;
11429
10
            case 1: /* constructed-value */
11430
10
                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
10
                save_propertyIdentifier = propertyIdentifier;
11435
10
                propertyIdentifier = -1;
11436
10
                offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
11437
10
                propertyIdentifier = save_propertyIdentifier;
11438
10
                offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11439
10
                break;
11440
16
            case 2: /* date-time */
11441
16
                offset += ftag_offset;
11442
16
                offset = fDateTime(tvb, pinfo, tree, offset, "date-time: ");
11443
16
                offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11444
16
                break;
11445
29
            case 3: /* lighting-command */
11446
29
                offset += ftag_offset;
11447
29
                offset = fLightingCommand(tvb, pinfo, tree, offset, "lighting-command: ");
11448
29
                offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11449
29
                break;
11450
121
            default:
11451
121
                return offset;
11452
255
            }
11453
255
        }
11454
576
        else {
11455
576
            offset = fApplicationTypes(tvb, pinfo, tree, offset, NULL);
11456
576
        }
11457
831
    }
11458
13
    return offset;
11459
149
}
11460
11461
static unsigned
11462
fHostAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11463
667
{
11464
667
    uint8_t tag_no, tag_info;
11465
667
    uint32_t lvt;
11466
11467
667
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
11468
666
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11469
666
        switch (tag_no) {
11470
569
        case 0: /* none */
11471
569
            offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
11472
569
            break;
11473
11
        case 1: /* ip-address */
11474
11
            offset = fOctetString(tvb, pinfo, tree, offset, "ip-address: ", lvt);
11475
11
            break;
11476
11
        case 2: /* internet name (see RFC 1123) */
11477
11
            offset = fCharacterString(tvb, pinfo, tree, offset, "name: ");
11478
11
            break;
11479
75
        default:
11480
75
            return offset;
11481
666
        }
11482
666
    }
11483
11484
591
    return offset;
11485
667
}
11486
11487
static unsigned
11488
fHostNPort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11489
446
{
11490
446
    unsigned   lastoffset = 0;
11491
446
    uint8_t tag_no, tag_info;
11492
446
    uint32_t lvt;
11493
446
    proto_tree *subtree = tree;
11494
11495
446
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11496
446
        ett_bacapp_value, NULL, "%s", lable);
11497
11498
1.25k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11499
1.25k
        lastoffset = offset;
11500
        /* check the tag.  A closing tag means we are done */
11501
1.25k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11502
1.25k
        if (tag_is_closing(tag_info)) {
11503
23
            return offset;
11504
23
        }
11505
1.22k
        switch (tag_no) {
11506
667
        case 0: /* host */
11507
667
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11508
667
            offset = fHostAddress(tvb, pinfo, subtree, offset);
11509
667
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11510
667
            break;
11511
142
        case 1: /* port */
11512
142
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "port: ");
11513
142
            break;
11514
420
        default:
11515
420
            return offset;
11516
1.22k
        }
11517
1.22k
    }
11518
11519
1
    return offset;
11520
446
}
11521
11522
static unsigned
11523
fBDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11524
97
{
11525
97
    unsigned   lastoffset = 0;
11526
97
    uint8_t tag_no, tag_info;
11527
97
    uint32_t lvt;
11528
97
    proto_tree *subtree = tree;
11529
11530
97
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11531
97
                ett_bacapp_value, NULL, "%s", lable);
11532
11533
322
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11534
321
        lastoffset = offset;
11535
        /* check the tag.  A closing tag means we are done */
11536
321
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11537
321
        if (tag_is_closing(tag_info)) {
11538
18
            return offset;
11539
18
        }
11540
11541
303
        switch (tag_no) {
11542
195
        case 0: /* bbmd-address */
11543
195
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11544
195
            offset = fHostNPort(tvb, pinfo, subtree, offset, "bbmd-address: ");
11545
195
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11546
195
            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
303
        }
11553
303
    }
11554
11555
1
    return offset;
11556
97
}
11557
11558
static unsigned
11559
fFDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
11560
66
{
11561
66
    unsigned   lastoffset = 0;
11562
66
    uint8_t tag_no, tag_info;
11563
66
    uint32_t lvt;
11564
66
    proto_tree *subtree = tree;
11565
11566
66
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11567
66
                ett_bacapp_value, NULL, "%s", lable);
11568
11569
304
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11570
304
        lastoffset = offset;
11571
        /* check the tag.  A closing tag means we are done */
11572
304
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11573
304
        if (tag_is_closing(tag_info)) {
11574
4
            return offset;
11575
4
        }
11576
11577
300
        switch (tag_no) {
11578
200
        case 0: /* bacnetip-address */
11579
200
            offset = fOctetString(tvb, pinfo, subtree, offset, "bacnetip-address: ", lvt);
11580
200
            break;
11581
8
        case 1: /* time-to-live */
11582
8
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "time-to-live: ");
11583
8
            break;
11584
30
        case 2: /* remaining-time-to-live */
11585
30
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "remaining-time-to-live: ");
11586
30
            break;
11587
62
        default:
11588
62
            return offset;
11589
300
        }
11590
300
    }
11591
11592
0
  return offset;
11593
66
}
11594
11595
static unsigned
11596
fRouterEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11597
87
{
11598
87
    unsigned   lastoffset = 0;
11599
87
    uint8_t tag_no, tag_info;
11600
87
    uint32_t lvt;
11601
11602
1.00k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11603
999
        lastoffset = offset;
11604
        /* check the tag.  A closing tag means we are done */
11605
999
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11606
999
        if (tag_is_closing(tag_info)) {
11607
13
            break;
11608
13
        }
11609
986
        switch (tag_no) {
11610
286
        case 0: /* network number */
11611
286
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "network number: ");
11612
286
            break;
11613
395
        case 1: /* MAC address */
11614
395
            offset = fOctetString(tvb, pinfo, tree, offset, "MAC address: ", lvt);
11615
395
            break;
11616
108
        case 2: /* status */
11617
108
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "status: ", BACnetRouterStatus);
11618
108
            break;
11619
128
        case 3: /* performance index */
11620
128
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "performance index: ");
11621
128
            break;
11622
68
        default:
11623
68
            return offset;
11624
986
        }
11625
917
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11626
917
    }
11627
11628
18
    return offset;
11629
87
}
11630
11631
static unsigned
11632
fVMACEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11633
45
{
11634
45
    unsigned   lastoffset = 0;
11635
45
    uint8_t tag_no, tag_info;
11636
45
    uint32_t lvt;
11637
11638
194
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11639
190
        lastoffset = offset;
11640
        /* check the tag.  A closing tag means we are done */
11641
190
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11642
190
        if (tag_is_closing(tag_info)) {
11643
3
            break;
11644
3
        }
11645
187
        switch (tag_no) {
11646
102
        case 0: /* virtual mac address */
11647
102
            offset = fOctetString(tvb, pinfo, tree, offset, "virtual MAC address: ", lvt);
11648
102
            break;
11649
47
        case 1: /* native mac address */
11650
47
            offset = fOctetString(tvb, pinfo, tree, offset, "native MAC address: ", lvt);
11651
47
            break;
11652
38
        default:
11653
38
            return offset;
11654
187
        }
11655
149
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11656
149
  }
11657
11658
7
  return offset;
11659
45
}
11660
11661
static unsigned
11662
fValueSource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11663
1.46k
{
11664
1.46k
    uint8_t tag_no, tag_info;
11665
1.46k
    uint32_t lvt;
11666
11667
1.46k
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
11668
1.46k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11669
1.46k
        switch (tag_no) {
11670
1.15k
        case 0: /* null */
11671
1.15k
            offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
11672
1.15k
            break;
11673
70
        case 1: /* object reference */
11674
70
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11675
70
            offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
11676
70
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11677
70
            break;
11678
165
        case 2: /* address */
11679
165
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11680
165
            offset = fAddress(tvb, pinfo, tree, offset);
11681
165
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11682
165
            break;
11683
78
        default:
11684
78
            return offset;
11685
1.46k
        }
11686
1.46k
    }
11687
11688
1.37k
  return offset;
11689
1.46k
}
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.87k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11701
3.86k
        lastoffset = offset;
11702
        /* check the tag.  A closing tag means we are done */
11703
3.86k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11704
3.86k
        if (tag_is_closing(tag_info)) {
11705
110
            break;
11706
110
        }
11707
3.75k
        switch (tag_no) {
11708
909
        case 0: /* floor number */
11709
909
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
11710
909
            break;
11711
260
        case 1: /* direction */
11712
260
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "direction: ", BACnetLiftCarDirection);
11713
260
            break;
11714
2.58k
        default:
11715
2.58k
            return offset;
11716
3.75k
        }
11717
1.16k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11718
1.16k
    }
11719
11720
124
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11721
124
    return offset;
11722
2.71k
}
11723
11724
static unsigned
11725
fLandingCallStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11726
181
{
11727
181
    unsigned   lastoffset = 0;
11728
181
    uint8_t tag_no, tag_info;
11729
181
    uint32_t lvt;
11730
11731
2.52k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11732
2.52k
        lastoffset = offset;
11733
        /* check the tag.  A closing tag means we are done */
11734
2.52k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11735
2.52k
        if (tag_is_closing(tag_info)) {
11736
34
            break;
11737
34
        }
11738
2.48k
        switch (tag_no) {
11739
1.28k
        case 0: /* floor number */
11740
1.28k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
11741
1.28k
            break;
11742
609
        case 1: /* direction */
11743
609
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "direction: ", BACnetLiftCarDirection);
11744
609
            break;
11745
307
        case 2: /* destination */
11746
307
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "destination: ");
11747
307
            break;
11748
153
        case 3: /* floor-text */
11749
153
            offset = fCharacterString(tvb, pinfo, tree, offset, "floor-text: ");
11750
153
            break;
11751
138
        default:
11752
138
            return offset;
11753
2.48k
        }
11754
2.34k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11755
2.34k
    }
11756
11757
36
    return offset;
11758
181
}
11759
11760
static unsigned
11761
fLandingDoorStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11762
827
{
11763
827
    unsigned   lastoffset = 0;
11764
827
    uint8_t tag_no, tag_info;
11765
827
    uint32_t lvt;
11766
11767
827
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11768
11769
1.56k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11770
1.55k
        lastoffset = offset;
11771
        /* check the tag.  A closing tag means we are done */
11772
1.55k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11773
1.55k
        if (tag_is_closing(tag_info)) {
11774
39
            break;
11775
39
        }
11776
1.52k
        switch (tag_no) {
11777
638
        case 0: /* floor number */
11778
638
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
11779
638
            break;
11780
102
        case 1: /* door status */
11781
102
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "door status: ", BACnetDoorStatus);
11782
102
            break;
11783
780
        default:
11784
780
            return offset;
11785
1.52k
        }
11786
740
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11787
740
    }
11788
11789
47
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11790
47
    return offset;
11791
827
}
11792
11793
static unsigned
11794
fCOVMultipleSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11795
404
{
11796
404
    unsigned   lastoffset = 0;
11797
404
    uint8_t tag_no, tag_info;
11798
404
    uint32_t lvt;
11799
11800
1.07k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11801
1.07k
        lastoffset = offset;
11802
        /* check the tag.  A closing tag means we are done */
11803
1.07k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11804
1.07k
        if (tag_is_closing(tag_info)) {
11805
11
            break;
11806
11
        }
11807
1.05k
        switch (tag_no) {
11808
111
        case 0: /* recipient */
11809
111
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11810
111
            offset = fRecipientProcess(tvb, pinfo, tree, offset);
11811
111
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11812
111
            break;
11813
208
        case 1: /* issue-confirmed-notifications */
11814
208
            offset = fBooleanTag(tvb, pinfo, tree, offset, "issue confirmed notifications: ");
11815
208
            break;
11816
125
        case 2: /* time-remaining */
11817
125
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "time remaining: ");
11818
125
            break;
11819
224
        case 3: /* max-notification-delay */
11820
224
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "max notification delay: ");
11821
224
            break;
11822
329
        case 4: /* list-of-cov-subscription-specifications */
11823
329
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11824
754
            while (tvb_reported_length_remaining(tvb, offset) > 0) {
11825
750
                lastoffset = offset;
11826
                /* check the tag.  A closing tag means we are done */
11827
750
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11828
750
                if (tag_is_closing(tag_info)) {
11829
11
                    break;
11830
11
                }
11831
739
                switch (tag_no) {
11832
393
                case 0: /* monitored-object-identifier */
11833
393
                    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
11834
393
                    break;
11835
79
                case 1: /* list-of-cov-references */
11836
79
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11837
406
                    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11838
404
                    lastoffset = offset;
11839
                    /* check the tag.  A closing tag means we are done */
11840
404
                    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11841
404
                    if (tag_is_closing(tag_info)) {
11842
32
                        break;
11843
32
                    }
11844
372
                    switch (tag_no) {
11845
127
                    case 0: /* monitored-property */
11846
127
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11847
127
                        offset = fBACnetPropertyReference(tvb, pinfo, tree, offset, 0);
11848
127
                        offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11849
127
                        break;
11850
38
                    case 1: /* cov-increment */
11851
38
                        offset = fRealTag(tvb, pinfo, tree, offset, "cov-increment: ");
11852
38
                        break;
11853
163
                    case 2: /* timestamped */
11854
163
                        offset = fBooleanTag(tvb, pinfo, tree, offset, "timestamped: ");
11855
163
                        break;
11856
44
                    default:
11857
44
                        return offset;
11858
372
                    }
11859
327
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11860
327
                    }
11861
34
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11862
34
                    break;
11863
267
                default:
11864
267
                    return offset;
11865
739
                }
11866
425
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11867
425
            }
11868
15
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11869
15
            break;
11870
62
        default:
11871
62
            return offset;
11872
1.05k
        }
11873
674
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11874
674
    }
11875
11876
19
    return offset;
11877
404
}
11878
11879
static unsigned
11880
fNameValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11881
1.44k
{
11882
1.44k
    unsigned   lastoffset = 0;
11883
1.44k
    uint8_t tag_no, tag_info;
11884
1.44k
    uint32_t lvt;
11885
11886
3.89k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
11887
3.87k
        lastoffset = offset;
11888
        /* check the tag.  A closing tag means we are done */
11889
3.87k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11890
3.87k
        if (tag_is_closing(tag_info)) {
11891
91
            break;
11892
91
        }
11893
3.78k
        if (tag_is_context_specific(tag_info)) {
11894
1.44k
            switch (tag_no) {
11895
95
            case 0: /* name */
11896
95
            offset = fCharacterString(tvb, pinfo, tree, offset, "name: ");
11897
95
            break;
11898
49
            case 1: /* date+time value */
11899
49
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11900
49
            offset = fDateTime(tvb, pinfo, tree, offset, "value: ");
11901
49
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11902
49
            break;
11903
1.30k
            default: /* abstract syntax and type */
11904
            /* DMR Should be fAbstractNSyntax, but that's where we came from! */
11905
1.30k
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "value: ");
11906
1.30k
            break;
11907
1.44k
            }
11908
1.44k
        }
11909
2.34k
        else {
11910
            /* DMR Should be fAbstractNSyntax, but that's where we came from! */
11911
2.34k
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "value: ");
11912
2.34k
        }
11913
3.78k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11914
3.78k
    }
11915
1.43k
    return offset;
11916
1.44k
}
11917
11918
static unsigned
11919
fNameValueCollection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11920
1.18k
{
11921
1.18k
    unsigned   lastoffset = 0;
11922
1.18k
    uint8_t tag_no, tag_info;
11923
1.18k
    uint32_t lvt;
11924
1.18k
    proto_tree *subtree = tree;
11925
11926
1.18k
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11927
1.18k
            ett_bacapp_value, NULL, "%s", "name-value-collection: ");
11928
11929
1.18k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11930
11931
2.62k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
11932
1.55k
        lastoffset = offset;
11933
        /* check the tag.  A closing tag means we are done */
11934
1.55k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11935
1.55k
        if (tag_is_closing(tag_info)) {
11936
113
            break;
11937
113
        }
11938
11939
1.44k
        offset = fNameValue(tvb, pinfo, subtree, offset);
11940
1.44k
    }
11941
11942
1.18k
    offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11943
1.18k
    return offset;
11944
1.18k
}
11945
11946
static unsigned
11947
fObjectSelector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11948
44
{
11949
44
    unsigned   lastoffset = 0;
11950
44
    uint8_t tag_no, tag_info;
11951
44
    uint32_t lvt;
11952
11953
148
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
11954
148
        lastoffset = offset;
11955
148
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11956
148
        if (tag_is_closing(tag_info)) {
11957
3
            break;
11958
3
        }
11959
11960
145
        switch (tag_no) {
11961
75
        case 0: /* NULL */
11962
75
            offset = fNullTag(tvb, pinfo, tree, offset, "NULL: ");
11963
75
            break;
11964
2
        case 9: /* object-type */
11965
2
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, "object-type: ", BACnetObjectType, 256);
11966
2
            break;
11967
27
        case 12: /* object */
11968
27
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
11969
27
            break;
11970
41
        default:
11971
41
            break;
11972
145
        }
11973
145
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
11974
145
    }
11975
44
    return offset;
11976
44
}
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
369
{
12025
369
    unsigned   lastoffset = 0;
12026
369
    uint8_t tag_no, tag_info;
12027
369
    uint32_t lvt;
12028
369
    proto_tree *subtree = tree;
12029
369
    proto_tree *subsubtree = tree;
12030
12031
369
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12032
369
                ett_bacapp_value, NULL, "%s", lable);
12033
12034
4.68k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12035
4.67k
        lastoffset = offset;
12036
        /* check the tag.  A closing tag means we are done */
12037
4.67k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12038
4.67k
        if (tag_is_closing(tag_info)) {
12039
113
            return offset;
12040
113
        }
12041
12042
4.55k
        switch (tag_no) {
12043
2.45k
        case 0: /* issuer */
12044
2.45k
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "issuer: ");
12045
2.45k
            break;
12046
123
        case 1: /* issued */
12047
123
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12048
123
            offset = fDateTime(tvb, pinfo, subtree, offset, "issued: ");
12049
123
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12050
123
            break;
12051
104
        case 2: /* audience */
12052
104
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12053
104
            subsubtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12054
104
                      ett_bacapp_value, NULL, "%s", "audience:");
12055
12056
1.35k
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12057
1.32k
                lastoffset = offset;
12058
                /* check the tag.  A closing tag means we are done */
12059
1.32k
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12060
1.32k
                if (tag_is_closing(tag_info)) {
12061
76
                    break;
12062
76
                }
12063
12064
1.24k
                offset = fSignedTag(tvb, pinfo, subsubtree, offset, "listener: ");
12065
1.24k
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12066
1.24k
            }
12067
104
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12068
104
            break;
12069
153
        case 3: /* not-before */
12070
153
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12071
153
            offset = fDateTime(tvb, pinfo, subtree, offset, "not-before: ");
12072
153
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12073
153
            break;
12074
212
        case 4: /* not-after */
12075
212
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12076
212
            offset = fDateTime(tvb, pinfo, subtree, offset, "not-after: ");
12077
212
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12078
212
            break;
12079
171
        case 5: /* client */
12080
171
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "client: ");
12081
171
            break;
12082
527
        case 6: /* constraint */
12083
527
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12084
527
            offset = fAuthorizationConstraint(tvb, pinfo, subtree, offset, "constraint: ");
12085
527
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12086
527
            break;
12087
53
        case 7: /* scope */
12088
53
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12089
53
            offset = fAuthorizationScope(tvb, pinfo, subtree, offset, "scope: ");
12090
53
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12091
53
            break;
12092
366
        case 8: /* key-id */
12093
366
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "key-id: ");
12094
366
            break;
12095
231
        case 9: /* signature */
12096
231
            offset = fOctetString(tvb, pinfo, subtree, offset, "signature", lvt);
12097
231
            break;
12098
165
        default:
12099
165
            break;
12100
4.55k
        }
12101
4.48k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12102
4.48k
    }
12103
12104
180
    return offset;
12105
369
}
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
0
{
12117
0
    unsigned   lastoffset = 0;
12118
0
    uint8_t tag_no, tag_info;
12119
0
    uint32_t lvt;
12120
0
    proto_tree *subtree = tree;
12121
12122
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12123
0
                ett_bacapp_value, NULL, "%s", lable);
12124
12125
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12126
0
        lastoffset = offset;
12127
        /* check the tag.  A closing tag means we are done */
12128
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12129
0
        if (tag_is_closing(tag_info)) {
12130
0
            return offset;
12131
0
        }
12132
12133
0
        offset = fBooleanTag(tvb, pinfo, subtree, offset, "authenticated: ");
12134
0
        offset = fUnsignedTag(tvb, pinfo, subtree, offset, "device: ");
12135
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12136
0
    }
12137
12138
0
    return offset;
12139
0
}
12140
12141
static unsigned
12142
fAuthorizationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12143
0
{
12144
0
    unsigned   lastoffset = 0;
12145
0
    uint8_t tag_no, tag_info;
12146
0
    uint32_t lvt;
12147
0
    proto_tree *subtree = tree;
12148
12149
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12150
0
                ett_bacapp_value, NULL, "%s", lable);
12151
12152
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12153
0
        lastoffset = offset;
12154
        /* check the tag.  A closing tag means we are done */
12155
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12156
0
        if (tag_is_closing(tag_info)) {
12157
0
            return offset;
12158
0
        }
12159
12160
0
        switch (tag_no) {
12161
0
        case 0: /* time-stamp */
12162
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12163
0
            offset = fDateTime(tvb, pinfo, subtree, offset, "time-stamp: ");
12164
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12165
0
            break;
12166
0
        case 1: /* address */
12167
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12168
0
            offset = fAddress(tvb, pinfo, subtree, offset);
12169
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12170
0
            break;
12171
0
        case 2: /* client */
12172
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12173
0
            offset = fAuthenticationClient(tvb, pinfo, subtree, offset, "client: ");
12174
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12175
0
            break;
12176
0
        case 3: /* token */
12177
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12178
0
            offset = fAccessToken(tvb, pinfo, subtree, offset, "token: ");
12179
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12180
0
            break;
12181
0
        case 4: /* decision */
12182
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "decision: ", BACnetAuthorizationDecision);
12183
0
            break;
12184
0
        case 5: /* decision-details */
12185
0
            offset = fCharacterString(tvb, pinfo, subtree, offset, "decision-details: ");
12186
0
            break;
12187
0
        default:
12188
0
            break;
12189
0
        }
12190
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12191
0
    }
12192
12193
0
    return offset;
12194
0
}
12195
12196
static unsigned
12197
fAuthenticationPeer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12198
0
{
12199
0
    unsigned   lastoffset = 0;
12200
0
    uint8_t tag_no, tag_info;
12201
0
    uint32_t lvt;
12202
0
    proto_tree *subtree = tree;
12203
12204
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12205
0
                ett_bacapp_value, NULL, "%s", lable);
12206
12207
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12208
0
        lastoffset = offset;
12209
        /* check the tag.  A closing tag means we are done */
12210
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12211
0
        if (tag_is_closing(tag_info)) {
12212
0
            return offset;
12213
0
        }
12214
12215
0
        switch (tag_no) {
12216
0
        case 0: /* host */
12217
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12218
0
            offset = fHostNPort(tvb, pinfo, subtree, offset, "host: ");
12219
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12220
0
            break;
12221
0
        default:
12222
0
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "device: ");
12223
0
            offset = fBooleanTag(tvb, pinfo, subtree, offset, "auth-aware: ");
12224
0
            offset = fBooleanTag(tvb, pinfo, subtree, offset, "router: ");
12225
0
            offset = fBooleanTag(tvb, pinfo, subtree, offset, "hub: ");
12226
0
            break;
12227
0
        }
12228
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12229
0
    }
12230
12231
0
    return offset;
12232
0
}
12233
12234
static unsigned
12235
fAuthenticationEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12236
0
{
12237
0
    unsigned   lastoffset = 0;
12238
0
    uint8_t tag_no, tag_info;
12239
0
    uint32_t lvt;
12240
0
    proto_tree *subtree = tree;
12241
12242
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12243
0
                ett_bacapp_value, NULL, "%s", lable);
12244
12245
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12246
0
        lastoffset = offset;
12247
        /* check the tag.  A closing tag means we are done */
12248
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12249
0
        if (tag_is_closing(tag_info)) {
12250
0
            return offset;
12251
0
        }
12252
12253
0
        switch (tag_no) {
12254
0
    case 0: /* time-stamp */
12255
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12256
0
      offset = fDateTime(tvb, pinfo, subtree, offset, "time-stamp: ");
12257
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12258
0
            break;
12259
0
    case 1: /* peer */
12260
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12261
0
      offset = fAuthenticationPeer(tvb, pinfo, subtree, offset, "peer: ");
12262
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12263
0
            break;
12264
0
    case 2: /* client */
12265
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12266
0
      offset = fAuthenticationClient(tvb, pinfo, subtree, offset, "client: ");
12267
0
      offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12268
0
            break;
12269
0
    case 3: /* decision */
12270
0
      offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "decision: ", BACnetAuthenticationDecision);
12271
0
            break;
12272
0
    case 4: /* decision-details */
12273
0
      offset = fCharacterString(tvb, pinfo, subtree, offset, "decision-details: ");
12274
0
            break;
12275
0
        default:
12276
0
            break;
12277
0
        }
12278
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12279
0
    }
12280
12281
0
    return offset;
12282
0
}
12283
12284
static unsigned
12285
fAuthorizationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12286
0
{
12287
0
    unsigned   lastoffset = 0;
12288
0
    uint8_t tag_no, tag_info;
12289
0
    uint32_t lvt;
12290
0
    proto_tree *subtree = tree;
12291
0
    proto_tree *subsubtree = tree;
12292
12293
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12294
0
                ett_bacapp_value, NULL, "%s", lable);
12295
12296
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12297
0
        lastoffset = offset;
12298
        /* check the tag.  A closing tag means we are done */
12299
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12300
0
        if (tag_is_closing(tag_info)) {
12301
0
            return offset;
12302
0
        }
12303
12304
0
        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
0
        default:
12343
0
            break;
12344
0
        }
12345
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12346
0
    }
12347
12348
0
    return offset;
12349
0
}
12350
12351
static unsigned
12352
fAuthorizationConstraint(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12353
527
{
12354
527
    unsigned   lastoffset = 0;
12355
527
    uint8_t tag_no, tag_info;
12356
527
    uint32_t lvt;
12357
527
    proto_tree *subtree = tree;
12358
12359
527
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12360
527
                ett_bacapp_value, NULL, "%s", lable);
12361
12362
1.27k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12363
1.25k
        lastoffset = offset;
12364
        /* check the tag.  A closing tag means we are done */
12365
1.25k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12366
1.25k
        if (tag_is_closing(tag_info)) {
12367
24
            return offset;
12368
24
        }
12369
12370
1.22k
    offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "origin: ", BACnetAuthorizationConstraintOrigin);
12371
1.22k
    offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "authentication: ", BACnetAuthorizationConstraintAuthentication);
12372
1.22k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12373
1.22k
    }
12374
12375
503
    return offset;
12376
527
}
12377
12378
static unsigned
12379
fAuthorizationScope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12380
129
{
12381
129
    unsigned   lastoffset = 0, len;
12382
129
    uint8_t tag_no, tag_info;
12383
129
    uint32_t lvt;
12384
129
    proto_tree *subtree = tree;
12385
129
    proto_tree *subsubtree = tree;
12386
12387
129
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12388
129
                ett_bacapp_value, NULL, "%s", lable);
12389
12390
544
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12391
541
        lastoffset = offset;
12392
        /* check the tag.  A closing tag means we are done */
12393
541
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12394
541
        if (tag_is_closing(tag_info)) {
12395
10
            return offset;
12396
10
        }
12397
12398
531
        switch (tag_no) {
12399
105
        case 0: /* extended */
12400
105
            if (tag_is_opening(tag_info)) {
12401
7
                subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "extended: ");
12402
7
                offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
12403
12404
29
                while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {  /* exit loop if nothing happens inside */
12405
23
                    lastoffset = offset;
12406
23
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12407
23
                    if (tag_is_closing(tag_info)) {
12408
1
                        fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
12409
1
                        offset += len;
12410
1
                        break;
12411
1
                    }
12412
12413
22
                    offset = fCharacterString(tvb, pinfo, subsubtree, offset, "scope: ");
12414
22
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12415
22
                }
12416
98
            } else {
12417
98
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
12418
98
            }
12419
105
            break;
12420
426
        default: /* standard */
12421
426
            offset = fBitStringTagVS(tvb, pinfo, subtree, offset, "standard: ", BACnetAuthorizationScopeStandard);
12422
426
            break;
12423
531
        }
12424
513
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12425
513
    }
12426
12427
101
    return offset;
12428
129
}
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
0
{
12505
0
    unsigned   lastoffset = 0;
12506
0
    uint8_t tag_no, tag_info;
12507
0
    uint32_t lvt;
12508
0
    proto_tree *subtree = tree;
12509
12510
0
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12511
0
                ett_bacapp_value, NULL, "%s", lable);
12512
12513
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12514
0
        lastoffset = offset;
12515
        /* check the tag.  A closing tag means we are done */
12516
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12517
0
        if (tag_is_closing(tag_info)) {
12518
0
            return offset;
12519
0
        }
12520
12521
0
        switch (tag_no) {
12522
0
        case 0: /* posture */
12523
0
            offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset, "posture: ", BACnetAuthorizationPosture);
12524
0
            break;
12525
0
        case 1: /* error */
12526
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12527
0
            offset = fError(tvb, pinfo, subtree, offset);
12528
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12529
0
            break;
12530
0
        case 2: /* error-source */
12531
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12532
0
            offset = fObjectPropertyReference(tvb, pinfo, subtree, offset);
12533
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12534
0
            break;
12535
0
        case 3: /* error-details */
12536
0
            offset = fCharacterString(tvb, pinfo, subtree, offset, "error-details: ");
12537
0
            break;
12538
0
        case 4: /* authentication-success */
12539
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12540
0
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12541
0
                lastoffset = offset;
12542
                /* check the tag.  A closing tag means we are done */
12543
0
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12544
0
                if (tag_is_closing(tag_info)) {
12545
0
                    break;
12546
0
                }
12547
12548
0
                offset = fAuthenticationEvent(tvb, pinfo, subtree, offset, "authentication-success");
12549
0
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12550
0
            }
12551
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12552
0
            break;
12553
0
        case 5: /* authentication-failure */
12554
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12555
0
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12556
0
                lastoffset = offset;
12557
                /* check the tag.  A closing tag means we are done */
12558
0
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12559
0
                if (tag_is_closing(tag_info)) {
12560
0
                    break;
12561
0
                }
12562
12563
0
                offset = fAuthenticationEvent(tvb, pinfo, subtree, offset, "authentication-failure");
12564
0
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12565
0
            }
12566
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12567
0
            break;
12568
0
        case 6: /* authorization-success */
12569
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12570
0
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12571
0
                lastoffset = offset;
12572
                /* check the tag.  A closing tag means we are done */
12573
0
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12574
0
                if (tag_is_closing(tag_info)) {
12575
0
                    break;
12576
0
                }
12577
12578
0
                offset = fAuthorizationEvent(tvb, pinfo, subtree, offset, "authorization-success");
12579
0
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12580
0
            }
12581
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12582
0
            break;
12583
0
        case 7: /* authorization-failure */
12584
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12585
0
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12586
0
                lastoffset = offset;
12587
                /* check the tag.  A closing tag means we are done */
12588
0
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12589
0
                if (tag_is_closing(tag_info)) {
12590
0
                    break;
12591
0
                }
12592
12593
0
                offset = fAuthorizationEvent(tvb, pinfo, subtree, offset, "authorization-failure");
12594
0
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12595
0
            }
12596
0
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12597
0
            break;
12598
0
        default:
12599
0
            break;
12600
0
        }
12601
0
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12602
0
    }
12603
12604
0
    return offset;
12605
0
}
12606
12607
static unsigned
12608
fStageLimitValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12609
23
{
12610
23
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
12611
0
        return offset;
12612
23
    offset = fRealTag(tvb, pinfo, tree, offset, "limit: ");
12613
23
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
12614
1
        return offset;
12615
22
    offset = fBitStringTag(tvb, pinfo, tree, offset, "values: ");
12616
22
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
12617
1
        return offset;
12618
21
    offset = fRealTag(tvb, pinfo, tree, offset, "deadband: ");
12619
21
    return offset;
12620
22
}
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.68k
{
12688
1.68k
    unsigned   len, lastoffset = 0;
12689
1.68k
    uint8_t tag_no, tag_info;
12690
1.68k
    uint32_t lvt;
12691
1.68k
    uint32_t operation = 0;
12692
1.68k
    proto_tree *subtree = tree;
12693
12694
26.8k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12695
26.5k
        lastoffset = offset;
12696
26.5k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12697
26.5k
        if (tag_is_closing(tag_info)) {
12698
312
            break;
12699
312
        }
12700
12701
26.2k
        switch (tag_no) {
12702
7.55k
        case 0: /* source-timestamp */
12703
7.55k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12704
7.55k
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "source-timestamp: ");
12705
7.55k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12706
7.55k
            break;
12707
1.37k
        case 1: /* target-timestamp */
12708
1.37k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12709
1.37k
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "target-timestamp: ");
12710
1.37k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12711
1.37k
            break;
12712
1.62k
        case 2: /* source-device */
12713
1.62k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "source-device: ");
12714
1.62k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12715
1.62k
            offset = fRecipient(tvb, pinfo, subtree, offset);
12716
1.62k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12717
1.62k
            break;
12718
836
        case 3: /* source-object */
12719
836
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "source-object: ");
12720
836
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
12721
836
            break;
12722
1.94k
        case 4: /* operation */
12723
1.94k
            fUnsigned32(tvb, offset, lvt, &operation);
12724
1.94k
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
12725
1.94k
                  "operation: ", BACnetAuditOperation, 64);
12726
1.94k
            break;
12727
730
        case 5: /* source-comment */
12728
730
            offset  = fCharacterString(tvb, pinfo, tree, offset, "source-comment: ");
12729
730
            break;
12730
726
        case 6: /* target-comment */
12731
726
            offset  = fCharacterString(tvb, pinfo, tree, offset, "target-comment: ");
12732
726
            break;
12733
1.34k
        case 7: /* invoke-id */
12734
1.34k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "invoke-id: ");
12735
1.34k
            break;
12736
998
        case 8: /* source-user-id */
12737
998
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "source-user-id: ");
12738
998
            break;
12739
769
        case 9: /* source-user-role */
12740
769
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "source-user-role: ");
12741
769
            break;
12742
1.40k
        case 10: /* target-device */
12743
1.40k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-device: ");
12744
1.40k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12745
1.40k
            offset = fRecipient(tvb, pinfo, subtree, offset);
12746
1.40k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12747
1.40k
            break;
12748
518
        case 11: /* target-object */
12749
518
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-object: ");
12750
518
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
12751
518
            break;
12752
3.11k
        case 12: /* target-property */
12753
3.11k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-property: ");
12754
3.11k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12755
3.11k
            offset = fPropertyReference(tvb, pinfo, subtree, offset, 0, 0);
12756
3.11k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12757
3.11k
            break;
12758
943
        case 13: /* target-priority */
12759
943
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: ");
12760
943
            break;
12761
2.17k
        case 14: /* target-value */
12762
2.17k
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-value: ");
12763
2.17k
            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
2.17k
            } 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
2.17k
            } else {
12792
                /* abstract syntax and type */
12793
2.17k
                offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
12794
2.17k
            }
12795
2.17k
            break;
12796
13
        case 15: /* current-value */
12797
13
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "current-value: ");
12798
            /* always abstract syntax and type */
12799
13
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
12800
13
            break;
12801
15
        case 16: /* error-result */
12802
15
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "error-result: ");
12803
15
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12804
15
            offset = fError(tvb, pinfo, subtree, offset);
12805
15
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12806
15
            break;
12807
172
        default:
12808
172
            break;
12809
26.2k
        }
12810
25.3k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12811
25.3k
    }
12812
785
    return offset;
12813
1.68k
}
12814
12815
static unsigned
12816
// NOLINTNEXTLINE(misc-no-recursion)
12817
fAuditLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12818
141
{
12819
141
    unsigned    lastoffset = 0;
12820
141
    uint8_t     tag_no, tag_info;
12821
141
    uint32_t    lvt;
12822
141
    proto_tree *subtree = tree;
12823
12824
521
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12825
519
        lastoffset = offset;
12826
519
        fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12827
519
        if (tag_is_closing(tag_info)) {
12828
34
            break;
12829
34
        }
12830
12831
485
        switch (tag_no) {
12832
311
        case 0: /* timestamp */
12833
311
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12834
311
            offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
12835
311
            offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
12836
311
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12837
311
            break;
12838
111
        case 1: /* logDatum: don't loop, it's a CHOICE */
12839
111
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12840
111
            switch (fTagNo(tvb, offset)) {
12841
16
            case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
12842
16
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
12843
16
                break;
12844
61
            case 1: /* notification */
12845
61
                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
12846
61
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12847
61
                offset  = fAuditNotificationInfo(tvb, pinfo, subtree, offset);
12848
61
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12849
61
                break;
12850
9
            case 2: /* time-change */
12851
9
                offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
12852
9
                break;
12853
22
            default:
12854
22
                return offset;
12855
111
            }
12856
78
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12857
78
            break;
12858
63
        default:
12859
63
            return offset;
12860
485
        }
12861
380
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12862
380
    }
12863
36
    return offset;
12864
141
}
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
39
{
12916
39
    unsigned   lastoffset = 0;
12917
39
    uint8_t tag_no, tag_info;
12918
39
    uint32_t lvt;
12919
39
    int32_t save_propertyIdentifier;
12920
12921
198
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
12922
197
        lastoffset = offset;
12923
197
        switch (fTagNo(tvb, offset)) {
12924
79
        case 0: /* timestamp */
12925
79
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12926
79
            offset  = fDate(tvb, pinfo, tree, offset, "Date: ");
12927
79
            offset  = fTime(tvb, pinfo, tree, offset, "Time: ");
12928
79
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12929
79
            break;
12930
54
        case 1: /* logDatum: don't loop, it's a CHOICE */
12931
54
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12932
54
            switch (fTagNo(tvb, offset)) {
12933
1
            case 0: /* logStatus */    /* Changed this to BitString per BACnet Spec. */
12934
1
                offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status: ", BACnetLogStatus);
12935
1
                break;
12936
38
            case 1:
12937
38
                offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
12938
38
                break;
12939
3
            case 2:
12940
3
                offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
12941
3
                break;
12942
1
            case 3:
12943
1
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
12944
1
                break;
12945
0
            case 4:
12946
0
                offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
12947
0
                break;
12948
6
            case 5:
12949
6
                offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
12950
6
                break;
12951
1
            case 6:
12952
1
                offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
12953
1
                break;
12954
1
            case 7:
12955
1
                offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
12956
1
                break;
12957
2
            case 8:
12958
2
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12959
2
                offset  = fError(tvb, pinfo, tree, offset);
12960
2
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12961
2
                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
1
            default:
12977
1
                return offset;
12978
54
            }
12979
52
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12980
52
            break;
12981
29
        case 2:
12982
            /* Changed this to BitString per BACnet Spec. */
12983
29
            offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags: ", BACnetStatusFlags);
12984
29
            break;
12985
35
        default:
12986
35
            return offset;
12987
197
        }
12988
159
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
12989
159
    }
12990
1
    return offset;
12991
39
}
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.47k
{
13091
2.47k
    unsigned   lastoffset = 0;
13092
2.47k
    uint8_t tag_no, tag_info;
13093
2.47k
    uint32_t lvt;
13094
13095
68.5k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13096
68.1k
        lastoffset = offset;
13097
68.1k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13098
68.1k
        if (tag_is_closing(tag_info)) {
13099
493
            break;
13100
493
        }
13101
13102
67.6k
        switch (tag_no) {
13103
31.1k
        case 0: /* ProcessId */
13104
31.1k
            offset  = fProcessId(tvb, pinfo, tree, offset);
13105
31.1k
            break;
13106
2.74k
        case 1: /* initiating ObjectId */
13107
2.74k
            offset  = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13108
2.74k
            break;
13109
3.13k
        case 2: /* event ObjectId */
13110
3.13k
            offset  = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13111
3.13k
            break;
13112
3.76k
        case 3: /* time stamp */
13113
3.76k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13114
3.76k
            offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
13115
3.76k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13116
3.76k
            break;
13117
2.02k
        case 4: /* notificationClass */
13118
2.02k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
13119
2.02k
            break;
13120
2.10k
        case 5: /* Priority */
13121
2.10k
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
13122
2.10k
            break;
13123
3.99k
        case 6: /* EventType */
13124
3.99k
            offset = fEventType(tvb, pinfo, tree, offset);
13125
3.99k
            break;
13126
964
        case 7: /* messageText */
13127
964
            offset  = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
13128
964
            break;
13129
3.56k
        case 8: /* NotifyType */
13130
3.56k
            offset = fNotifyType(tvb, pinfo, tree, offset);
13131
3.56k
            break;
13132
2.09k
        case 9: /* ackRequired */
13133
2.09k
            offset  = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
13134
2.09k
            break;
13135
2.81k
        case 10: /* fromState */
13136
2.81k
            offset = fFromState(tvb, pinfo, tree, offset);
13137
2.81k
            break;
13138
3.37k
        case 11: /* toState */
13139
3.37k
            offset = fToState(tvb, pinfo, tree, offset);
13140
3.37k
            break;
13141
5.67k
        case 12: /* NotificationParameters */
13142
5.67k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13143
5.67k
            offset  = fNotificationParameters(tvb, pinfo, tree, offset);
13144
5.67k
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13145
5.67k
            break;
13146
298
        default:
13147
298
            break;
13148
67.6k
        }
13149
66.3k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13150
66.3k
    }
13151
1.14k
    return offset;
13152
2.47k
}
13153
13154
static unsigned
13155
fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13156
105
{
13157
105
    return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
13158
105
}
13159
13160
static unsigned
13161
fConfirmedCOVNotificationMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13162
98
{
13163
98
    unsigned    lastoffset = 0, len;
13164
98
    uint8_t     tag_no, tag_info;
13165
98
    uint32_t    lvt;
13166
98
    proto_tree *subtree = tree;
13167
98
    proto_tree *subsubtree = tree;
13168
13169
3.61k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13170
3.59k
        lastoffset = offset;
13171
3.59k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13172
3.59k
        if (tag_is_closing(tag_info)) {
13173
1.07k
            offset += len;
13174
1.07k
            subtree = tree;
13175
1.07k
            continue;
13176
1.07k
        }
13177
13178
2.51k
        switch (tag_no) {
13179
1.78k
        case 0: /* ProcessId */
13180
1.78k
            offset = fProcessId(tvb, pinfo, tree, offset);
13181
1.78k
            break;
13182
180
        case 1: /* initiating DeviceId */
13183
180
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
13184
180
            break;
13185
210
        case 2: /* time remaining */
13186
210
            offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining: ");
13187
210
            break;
13188
243
        case 3: /* timestamp */
13189
243
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13190
243
            offset = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
13191
243
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13192
243
            break;
13193
59
        case 4: /* list-of-cov-notifications */
13194
59
            if (tag_is_opening(tag_info)) {
13195
                /* new subtree for list-of-cov-notifications */
13196
49
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-notifications: ");
13197
49
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13198
13199
285
                while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13200
285
                    lastoffset = offset;
13201
285
                    len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13202
285
                    if (tag_is_closing(tag_info)) {
13203
                        /* end for list-of-cov-notifications */
13204
37
                        fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13205
37
                        offset += len;
13206
37
                        subtree = tree;
13207
37
                        break;
13208
37
                    }
13209
13210
248
                    switch (tag_no) {
13211
235
                    case 0: /* monitored-object-identifier */
13212
235
                        offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
13213
235
                        break;
13214
8
                    case 1: /* list-of-values */
13215
8
                        if (tag_is_opening(tag_info)) {
13216
                            /* new subtree for list-of-values */
13217
6
                            subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-values: ");
13218
6
                            offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
13219
13220
17
                            while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13221
17
                            lastoffset = offset;
13222
17
                            len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13223
17
                            if (tag_is_closing(tag_info)) {
13224
                                /* end of list-of-values */
13225
1
                                fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
13226
1
                                offset += len;
13227
1
                                break;
13228
1
                            }
13229
13230
16
                            switch (tag_no) {
13231
3
                            case 0: /* PropertyIdentifier */
13232
3
                                offset = fPropertyIdentifier(tvb, pinfo, subsubtree, offset);
13233
3
                                break;
13234
5
                            case 1: /* propertyArrayIndex */
13235
5
                                offset = fPropertyArrayIndex(tvb, pinfo, subsubtree, offset);
13236
5
                                break;
13237
0
                            case 2: /* property-value */
13238
0
                                offset = fPropertyValue(tvb, pinfo, subsubtree, offset, tag_info);
13239
0
                                break;
13240
5
                            case 3: /* time-of-change */
13241
5
                                offset = fTime(tvb, pinfo, subsubtree, offset, "time of change: ");
13242
5
                                break;
13243
3
                            default:
13244
                                /* wrong tag encoding */
13245
3
                                return offset;
13246
16
                            }
13247
13
                            if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13248
13
                            }
13249
6
                        }
13250
2
                        else {
13251
                            /* wrong tag encoding */
13252
2
                            expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
13253
2
                        }
13254
5
                        break;
13255
5
                    default:
13256
                        /* wrong tag encoding */
13257
5
                        return offset;
13258
248
                    }
13259
240
                    if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13260
240
                }
13261
49
            }
13262
10
            else {
13263
                /* wrong tag encoding */
13264
10
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13265
10
            }
13266
51
            break;
13267
51
        default:
13268
            /* wrong tag encoding */
13269
41
            return offset;
13270
2.51k
        }
13271
2.45k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13272
2.45k
    }
13273
35
    return offset;
13274
98
}
13275
13276
static unsigned
13277
fUnconfirmedCOVNotificationMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13278
24
{
13279
24
    return fConfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
13280
24
}
13281
13282
static unsigned
13283
fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13284
248
{
13285
248
    unsigned    lastoffset = 0, len;
13286
248
    uint8_t     tag_no, tag_info;
13287
248
    uint32_t    lvt;
13288
248
    proto_tree *subtree = tree;
13289
13290
4.06k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13291
4.02k
        lastoffset = offset;
13292
4.02k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13293
4.02k
        if (tag_is_closing(tag_info)) {
13294
918
            fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13295
918
            offset += len;
13296
918
            subtree = tree;
13297
918
            continue;
13298
918
        }
13299
13300
3.10k
        switch (tag_no) {
13301
1.91k
        case 0: /* ProcessId */
13302
1.91k
            offset = fProcessId(tvb, pinfo, tree, offset);
13303
1.91k
            break;
13304
195
        case 1: /* initiating DeviceId */
13305
195
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_device_identifier);
13306
195
            break;
13307
318
        case 2: /* monitored ObjectId */
13308
318
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
13309
318
            break;
13310
347
        case 3: /* time remaining */
13311
347
            offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining: ");
13312
347
            break;
13313
225
        case 4: /* List of Values */
13314
225
            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
18
            else {
13320
18
            expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13321
18
            }
13322
225
            break;
13323
105
        default:
13324
105
            return offset;
13325
3.10k
        }
13326
2.91k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13327
2.91k
    }
13328
56
    return offset;
13329
248
}
13330
13331
static unsigned
13332
fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13333
9
{
13334
9
    return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
13335
9
}
13336
13337
static unsigned
13338
fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13339
228
{
13340
228
    unsigned   lastoffset = 0;
13341
228
    uint8_t tag_no = 0, tag_info = 0;
13342
228
    uint32_t lvt = 0;
13343
13344
4.76k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13345
4.72k
        lastoffset = offset;
13346
4.72k
        switch (fTagNo(tvb, offset)) {
13347
2.41k
        case 0: /* acknowledgingProcessId */
13348
2.41k
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
13349
2.41k
            break;
13350
299
        case 1: /* eventObjectId */
13351
299
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13352
299
            break;
13353
502
        case 2: /* eventStateAcknowledged */
13354
502
            offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13355
502
                "event State Acknowledged: ", BACnetEventState, 64);
13356
502
            break;
13357
812
        case 3: /* timeStamp */
13358
812
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13359
812
            offset  = fTimeStamp(tvb, pinfo, tree, offset, NULL);
13360
812
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13361
812
            break;
13362
282
        case 4: /* acknowledgementSource */
13363
282
            offset  = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
13364
282
            break;
13365
268
        case 5: /* timeOfAcknowledgement */
13366
268
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13367
268
            offset  = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
13368
268
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13369
268
            break;
13370
150
        default:
13371
150
            return offset;
13372
4.72k
        }
13373
4.54k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13374
4.54k
    }
13375
40
    return offset;
13376
228
}
13377
13378
static unsigned
13379
fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13380
40
{
13381
40
    unsigned lastoffset = 0;
13382
13383
195
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13384
186
        lastoffset = offset;
13385
186
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
13386
186
        offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
13387
186
            "alarm State: ", BACnetEventState, 64);
13388
186
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13389
186
            "acknowledged Transitions: ", BACnetEventTransitionBits);
13390
186
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13391
186
    }
13392
40
    return  offset;
13393
40
}
13394
13395
static unsigned
13396
fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13397
108
{
13398
108
    unsigned   lastoffset = 0;
13399
108
    uint8_t tag_no, tag_info;
13400
108
    uint32_t lvt;
13401
13402
2.99k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13403
2.96k
        lastoffset = offset;
13404
2.96k
        switch (fTagNo(tvb, offset)) {
13405
1.44k
        case 0: /* acknowledgmentFilter */
13406
1.44k
            offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13407
1.44k
                "acknowledgment Filter: ", BACnetAcknowledgementFilter);
13408
1.44k
            break;
13409
323
        case 1: /* eventObjectId - OPTIONAL */
13410
323
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13411
323
            offset  = fRecipientProcess(tvb, pinfo, tree, offset);
13412
323
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13413
323
            break;
13414
454
        case 2: /* eventStateFilter */
13415
454
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
13416
454
                "event State Filter: ", BACnetEventStateFilter);
13417
454
            break;
13418
364
        case 3: /* eventTypeFilter - OPTIONAL */
13419
364
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
13420
364
                "event Type Filter: ", BACnetEventType);
13421
364
            break;
13422
126
        case 4: /* priorityFilter */
13423
126
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13424
126
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
13425
126
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
13426
126
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13427
126
            break;
13428
211
        case 5: /* notificationClassFilter - OPTIONAL */
13429
211
            offset  = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
13430
211
            break;
13431
48
        default:
13432
48
            return offset;
13433
2.96k
        }
13434
2.88k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13435
2.88k
    }
13436
25
    return offset;
13437
108
}
13438
13439
static unsigned
13440
fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13441
43
{
13442
43
    unsigned lastoffset = 0;
13443
13444
400
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13445
380
        lastoffset = offset;
13446
380
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
13447
380
        offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
13448
380
            "event Type: ", BACnetEventType, 64);
13449
380
        offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13450
380
            "event State: ", BACnetEventState);
13451
380
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
13452
380
        if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2)  /* Notification Class - OPTIONAL */
13453
42
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
13454
380
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13455
380
    }
13456
13457
43
    return  offset;
13458
43
}
13459
13460
static unsigned
13461
fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13462
37
{
13463
37
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
13464
37
        if (fTagNo(tvb, offset) == 0) {
13465
35
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13466
35
        }
13467
37
    }
13468
37
    return offset;
13469
37
}
13470
13471
static unsigned
13472
flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13473
186
{
13474
186
    unsigned    lastoffset = 0;
13475
186
    uint8_t     tag_no, tag_info;
13476
186
    uint32_t    lvt;
13477
186
    proto_tree* subtree = tree;
13478
13479
2.11k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13480
2.10k
        lastoffset = offset;
13481
2.10k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13482
        /* we are finished here if we spot a closing tag */
13483
2.10k
        if (tag_is_closing(tag_info)) {
13484
57
            break;
13485
57
        }
13486
2.05k
        switch (tag_no) {
13487
649
        case 0: /* ObjectId */
13488
649
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13489
649
            break;
13490
208
        case 1: /* eventState */
13491
208
            offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13492
208
                "event State: ", BACnetEventState);
13493
208
            break;
13494
108
        case 2: /* acknowledgedTransitions */
13495
108
            offset = fBitStringTagVS(tvb, pinfo, tree, offset,
13496
108
                "acknowledged Transitions: ", BACnetEventTransitionBits);
13497
108
            break;
13498
247
        case 3: /* eventTimeStamps */
13499
247
            subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
13500
247
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13501
247
            offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
13502
247
            offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
13503
247
            offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
13504
247
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13505
247
            break;
13506
465
        case 4: /* notifyType */
13507
465
            offset = fNotifyType(tvb, pinfo, tree, offset);
13508
465
            break;
13509
183
        case 5: /* eventEnable */
13510
183
            offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
13511
183
                "event Enable: ", BACnetEventTransitionBits);
13512
183
            break;
13513
97
        case 6: /* eventPriorities */
13514
97
            subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventPriorities");
13515
97
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13516
97
            offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
13517
97
            offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
13518
97
            offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
13519
97
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13520
97
            break;
13521
95
        default:
13522
95
            return offset;
13523
2.05k
        }
13524
1.93k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13525
1.93k
    }
13526
67
    return offset;
13527
186
}
13528
13529
static unsigned
13530
fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13531
91
{
13532
91
    unsigned   lastoffset = 0;
13533
91
    uint8_t tag_no, tag_info;
13534
91
    uint32_t lvt;
13535
13536
91
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
13537
113
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13538
111
        lastoffset = offset;
13539
111
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13540
        /* we are finished here if we spot a closing tag */
13541
111
        if (tag_is_closing(tag_info)) {
13542
2
            break;
13543
2
        }
13544
109
        offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
13545
109
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13546
109
    }
13547
91
    return offset;
13548
91
}
13549
13550
static unsigned
13551
fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13552
76
{
13553
76
    unsigned   lastoffset = 0;
13554
76
    uint8_t tag_no, tag_info;
13555
76
    uint32_t lvt;
13556
13557
382
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13558
378
        lastoffset = offset;
13559
378
        switch (fTagNo(tvb, offset)) {
13560
186
        case 0: /* listOfEventSummaries */
13561
186
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13562
186
            offset  = flistOfEventSummaries(tvb, pinfo, tree, offset);
13563
186
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13564
186
            break;
13565
154
        case 1: /* moreEvents */
13566
154
            offset  = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
13567
154
            break;
13568
38
        default:
13569
38
            return offset;
13570
378
        }
13571
306
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13572
306
    }
13573
4
    return offset;
13574
76
}
13575
13576
static unsigned
13577
fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13578
1.23k
{
13579
1.23k
    unsigned    lastoffset = 0, len;
13580
1.23k
    uint8_t     tag_no, tag_info;
13581
1.23k
    uint32_t    lvt;
13582
1.23k
    proto_tree *subtree    = tree;
13583
13584
1.23k
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
13585
13586
8.82k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13587
8.81k
        lastoffset = offset;
13588
8.81k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13589
8.81k
        if (tag_is_closing(tag_info)) {
13590
4.70k
            offset += len;
13591
4.70k
            subtree = tree;
13592
4.70k
            continue;
13593
4.70k
        }
13594
13595
4.11k
        switch (tag_no) {
13596
1.90k
        case 0: /* ObjectId */
13597
1.90k
            offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
13598
1.90k
            break;
13599
1.69k
        case 3: /* listOfElements */
13600
1.69k
            if (tag_is_opening(tag_info)) {
13601
1.64k
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfElements");
13602
1.64k
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13603
1.64k
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
13604
1.64k
                fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13605
1.64k
            } else {
13606
46
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13607
46
            }
13608
1.69k
            break;
13609
509
        default:
13610
509
            return offset;
13611
4.11k
        }
13612
2.94k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13613
2.94k
    }
13614
67
    return offset;
13615
1.23k
}
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
44
{
13626
44
    unsigned lastoffset = 0;
13627
13628
692
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13629
685
        lastoffset = offset;
13630
13631
685
        switch (fTagNo(tvb, offset)) {
13632
361
        case 0: /* timeDuration */
13633
361
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
13634
361
            break;
13635
218
        case 1: /* enable-disable */
13636
218
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
13637
218
                BACnetEnableDisable);
13638
218
            break;
13639
78
        case 2: /* password - OPTIONAL */
13640
78
            offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
13641
78
            break;
13642
28
        default:
13643
28
            return offset;
13644
685
        }
13645
648
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13646
648
    }
13647
7
    return offset;
13648
44
}
13649
13650
static unsigned
13651
fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13652
31
{
13653
31
    unsigned lastoffset = 0;
13654
13655
627
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13656
622
        lastoffset = offset;
13657
13658
622
        switch (fTagNo(tvb, offset)) {
13659
420
        case 0: /* reinitializedStateOfDevice */
13660
420
            offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13661
420
                "reinitialized State Of Device: ",
13662
420
                BACnetReinitializedStateOfDevice);
13663
420
            break;
13664
177
        case 1: /* password - OPTIONAL */
13665
177
            offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
13666
177
            break;
13667
25
        default:
13668
25
            return offset;
13669
622
        }
13670
596
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13671
596
    }
13672
5
    return offset;
13673
31
}
13674
13675
static unsigned
13676
fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13677
8
{
13678
8
    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13679
8
                                          "vtClass: ", BACnetVTClass);
13680
8
    return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
13681
8
}
13682
13683
static unsigned
13684
fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13685
2
{
13686
2
    return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
13687
2
}
13688
13689
static unsigned
13690
fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13691
42
{
13692
42
    unsigned lastoffset = 0;
13693
13694
622
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13695
607
        lastoffset = offset;
13696
607
        offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
13697
607
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13698
607
    }
13699
42
    return offset;
13700
42
}
13701
13702
static unsigned
13703
fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13704
14
{
13705
14
    offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
13706
14
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
13707
14
    return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
13708
14
}
13709
13710
static unsigned
13711
fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13712
11
{
13713
11
    unsigned lastoffset = 0;
13714
13715
188
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13716
188
        lastoffset = offset;
13717
13718
188
        switch (fTagNo(tvb, offset)) {
13719
158
        case 0: /* BOOLEAN */
13720
158
            offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
13721
158
            break;
13722
19
        case 1: /* Unsigned OPTIONAL */
13723
19
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
13724
19
            break;
13725
11
        default:
13726
11
            return offset;
13727
188
        }
13728
177
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13729
177
    }
13730
0
    return offset;
13731
11
}
13732
13733
static unsigned
13734
fConfirmedAuditNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13735
1.52k
{
13736
1.52k
    unsigned   lastoffset = 0;
13737
1.52k
    unsigned   firstloop = 1;
13738
1.52k
    uint8_t tag_no, tag_info;
13739
1.52k
    uint32_t lvt;
13740
13741
3.07k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13742
1.88k
        lastoffset = offset;
13743
1.88k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13744
1.88k
        if (tag_is_closing(tag_info)) {
13745
261
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13746
261
            break;
13747
261
        }
13748
13749
1.61k
        if (tag_is_opening(tag_info) && firstloop) {
13750
40
            firstloop = 0;
13751
40
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13752
40
        }
13753
13754
1.61k
        offset = fAuditNotificationInfo(tvb, pinfo, tree, offset);
13755
1.61k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13756
1.61k
    }
13757
1.52k
    return offset;
13758
1.52k
}
13759
13760
static unsigned
13761
fUnconfirmedAuditNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13762
17
{
13763
17
    return fConfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
13764
17
}
13765
13766
static unsigned
13767
fAuditLogQueryByTargetParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13768
461
{
13769
461
    unsigned   lastoffset = 0;
13770
461
    uint8_t tag_no, tag_info;
13771
461
    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
122
            break;
13778
122
        }
13779
13780
4.07k
        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
405
        case 1: /* target-device-address */
13785
405
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13786
405
            offset  = fAddress(tvb, pinfo, tree, offset);
13787
405
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13788
405
            break;
13789
351
        case 2: /* target-object-identifier */
13790
351
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13791
351
            break;
13792
464
        case 3: /* target-property-identifier */
13793
464
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
13794
464
            break;
13795
312
        case 4: /* target-property-array-index */
13796
312
            offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
13797
312
            break;
13798
362
        case 5: /* target-priority */
13799
362
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: ");
13800
362
            break;
13801
251
        case 6: /* target-operation */
13802
251
            offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
13803
251
                  "target-operation: ", BACnetAuditOperation);
13804
251
            break;
13805
388
        case 7: /* successful-action */
13806
388
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13807
388
                  "target-successful-action: ", BACnetSuccessFilter, 64);
13808
388
            break;
13809
187
        default:
13810
187
            return offset;
13811
4.07k
        }
13812
3.83k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13813
3.83k
    }
13814
221
    return offset;
13815
461
}
13816
13817
static unsigned
13818
fAuditLogQueryBySourceParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13819
205
{
13820
205
    unsigned   lastoffset = 0;
13821
205
    uint8_t tag_no, tag_info;
13822
205
    uint32_t lvt;
13823
13824
1.94k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13825
1.94k
        lastoffset = offset;
13826
1.94k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13827
1.94k
        if (tag_is_closing(tag_info)) {
13828
55
            break;
13829
55
        }
13830
13831
1.88k
        switch (tag_no) {
13832
527
        case 0: /* source-device-identifier */
13833
527
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
13834
527
            break;
13835
682
        case 1: /* source-device-address */
13836
682
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13837
682
            offset  = fAddress(tvb, pinfo, tree, offset);
13838
682
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13839
682
            break;
13840
173
        case 2: /* source-object-identifier */
13841
173
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13842
173
            break;
13843
207
        case 3: /* source-operation */
13844
207
            offset  = fBitStringTagVS(tvb, pinfo, tree, offset,
13845
207
                  "source-operation: ", BACnetAuditOperation);
13846
207
            break;
13847
178
        case 4: /* successful-action */
13848
178
            offset  = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13849
178
                  "source-successful-action: ", BACnetSuccessFilter, 64);
13850
178
            break;
13851
120
        default:
13852
120
            return offset;
13853
1.88k
        }
13854
1.74k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13855
1.74k
    }
13856
60
    return offset;
13857
205
}
13858
13859
static unsigned
13860
fAuditLogQueryParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13861
486
{
13862
486
    unsigned   lastoffset = 0;
13863
486
    uint8_t tag_no, tag_info;
13864
486
    uint32_t lvt;
13865
486
    proto_tree *subtree = tree;
13866
13867
1.05k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13868
1.04k
        lastoffset = offset;
13869
1.04k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13870
1.04k
        if (tag_is_closing(tag_info)) {
13871
199
            break;
13872
199
        }
13873
13874
849
        switch (tag_no) {
13875
461
        case 0: /* query-by-target-parameters */
13876
461
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "target-parameters: ");
13877
461
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13878
461
            offset  = fAuditLogQueryByTargetParameters(tvb, pinfo, subtree, offset);
13879
461
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13880
461
            break;
13881
205
        case 1: /* query-by-source-parameters */
13882
205
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "source-parameters: ");
13883
205
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13884
205
            offset  = fAuditLogQueryBySourceParameters(tvb, pinfo, subtree, offset);
13885
205
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13886
205
            break;
13887
183
        default:
13888
183
            return offset;
13889
849
        }
13890
570
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13891
570
    }
13892
207
    return offset;
13893
486
}
13894
13895
static unsigned
13896
fAuditLogQueryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13897
231
{
13898
231
    unsigned   lastoffset = 0;
13899
231
    uint8_t tag_no, tag_info;
13900
231
    uint32_t lvt;
13901
231
    proto_tree *subtree = tree;
13902
13903
2.86k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13904
2.84k
        lastoffset = offset;
13905
2.84k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13906
13907
2.84k
        switch (tag_no) {
13908
730
        case 0: /* audit-log */
13909
730
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13910
730
            break;
13911
486
        case 1: /* query-parameters */
13912
486
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "query-parameters: ");
13913
486
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13914
486
            offset = fAuditLogQueryParameters(tvb, pinfo, subtree, offset);
13915
486
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13916
486
            break;
13917
779
        case 2: /* start-at-sequence-number */
13918
779
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "start-at-sequence-number: ");
13919
779
            break;
13920
762
        case 3: /* requested-count */
13921
762
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "requested-count: ");
13922
762
            break;
13923
80
        default:
13924
80
            return offset;
13925
2.84k
        }
13926
2.63k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13927
2.63k
    }
13928
19
    return offset;
13929
231
}
13930
13931
static unsigned
13932
fAuditLogRecordResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13933
230
{
13934
230
    unsigned   lastoffset = 0;
13935
230
    uint8_t tag_no, tag_info;
13936
230
    uint32_t lvt;
13937
230
    proto_tree *subtree = tree;
13938
13939
983
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13940
981
        lastoffset = offset;
13941
981
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13942
981
        if (tag_is_closing(tag_info)) {
13943
117
            break;
13944
117
        }
13945
13946
864
        switch (tag_no) {
13947
634
        case 0 : /* sequence-number */
13948
634
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "sequence-number: ");
13949
634
            break;
13950
141
        case 1: /* log-record */
13951
141
            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "log-record: ");
13952
141
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13953
141
            offset = fAuditLogRecord(tvb, pinfo, subtree, offset);
13954
141
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13955
141
            break;
13956
89
        default:
13957
89
            return offset;
13958
864
        }
13959
753
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13960
753
    }
13961
119
    return offset;
13962
230
}
13963
13964
static unsigned
13965
fAuditLogQueryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13966
69
{
13967
69
    unsigned   lastoffset = 0;
13968
69
    uint8_t tag_no, tag_info;
13969
69
    uint32_t lvt;
13970
69
    proto_tree *subtree = tree;
13971
13972
1.20k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
13973
1.20k
        lastoffset = offset;
13974
1.20k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13975
13976
1.20k
        switch (tag_no) {
13977
257
        case 0: /* audit-log */
13978
257
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
13979
257
            break;
13980
230
        case 1: /* records */
13981
230
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "records: ");
13982
230
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13983
230
            offset = fAuditLogRecordResult(tvb, pinfo, subtree, offset);
13984
230
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13985
230
            break;
13986
684
        case 2: /* no-more-items */
13987
684
            offset = fBooleanTag(tvb, pinfo, tree, offset, "no-more-items: ");
13988
684
            break;
13989
32
        default:
13990
32
            return offset;
13991
1.20k
        }
13992
1.14k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
13993
1.14k
    }
13994
5
    return offset;
13995
69
}
13996
13997
static unsigned
13998
fAuthRequestTokenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
13999
334
{
14000
334
    unsigned   lastoffset = 0;
14001
334
    uint8_t tag_no, tag_info;
14002
334
    uint32_t lvt;
14003
334
    proto_tree *subtree = tree;
14004
334
    proto_tree *subsubtree = tree;
14005
14006
334
    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
14007
334
        ett_bacapp_value, NULL, "%s", lable);
14008
14009
1.79k
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14010
1.78k
        lastoffset = offset;
14011
        /* check the tag.  A closing tag means we are done */
14012
1.78k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14013
1.78k
        if (tag_is_closing(tag_info)) {
14014
156
            return offset;
14015
156
        }
14016
14017
1.63k
        switch (tag_no) {
14018
1.34k
        case 0: /* client */
14019
1.34k
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "client: ");
14020
1.34k
            break;
14021
79
        case 1: /* audience */
14022
79
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14023
79
            subsubtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
14024
79
                      ett_bacapp_value, NULL, "%s", "audience:");
14025
14026
3.24k
            while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14027
3.22k
                lastoffset = offset;
14028
                /* check the tag.  A closing tag means we are done */
14029
3.22k
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14030
3.22k
                if (tag_is_closing(tag_info)) {
14031
59
                    break;
14032
59
                }
14033
14034
3.16k
                offset = fSignedTag(tvb, pinfo, subsubtree, offset, "listener: ");
14035
3.16k
                if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14036
3.16k
            }
14037
79
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14038
79
            break;
14039
76
        case 2: /* scope */
14040
76
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14041
76
            offset = fAuthorizationScope(tvb, pinfo, subtree, offset, "scope: ");
14042
76
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14043
76
            break;
14044
135
        default:
14045
135
            return offset;
14046
1.63k
        }
14047
1.63k
    }
14048
14049
7
    return offset;
14050
334
}
14051
14052
static unsigned
14053
fAuthRequestRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14054
79
{
14055
79
    unsigned   lastoffset = 0;
14056
79
    uint8_t tag_no, tag_info;
14057
79
    uint32_t lvt;
14058
79
    proto_tree *subtree = tree;
14059
14060
370
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14061
367
        lastoffset = offset;
14062
367
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14063
14064
367
        switch (tag_no) {
14065
334
        case 0: /* token */
14066
334
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14067
334
            offset = fAuthRequestTokenRequest(tvb, pinfo, subtree, offset, "token: ");
14068
334
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14069
334
            break;
14070
32
        default:
14071
32
            return offset;
14072
367
        }
14073
291
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14074
291
    }
14075
3
    return offset;
14076
79
}
14077
14078
static unsigned
14079
fAuthRequestAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14080
139
{
14081
139
    unsigned   lastoffset = 0;
14082
139
    uint8_t tag_no, tag_info;
14083
139
    uint32_t lvt;
14084
139
    proto_tree *subtree = tree;
14085
14086
417
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14087
414
        lastoffset = offset;
14088
414
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14089
14090
414
        switch (tag_no) {
14091
369
        case 0: /* token */
14092
369
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14093
369
            offset = fAccessToken(tvb, pinfo, subtree, offset, "token: ");
14094
369
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14095
369
            break;
14096
44
        default:
14097
44
            return offset;
14098
414
        }
14099
278
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14100
278
    }
14101
3
    return offset;
14102
139
}
14103
14104
static unsigned
14105
fAuthRequestError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14106
16
{
14107
16
    unsigned   lastoffset = 0;
14108
16
    uint8_t tag_no, tag_info;
14109
16
    uint32_t lvt;
14110
16
    proto_tree *subtree = tree;
14111
14112
128
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14113
127
        lastoffset = offset;
14114
127
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14115
14116
127
        switch (tag_no) {
14117
93
        case 0: /* error */
14118
93
            offset = fContextTaggedError(tvb, pinfo, subtree, offset);
14119
93
            break;
14120
24
        case 1: /* details */
14121
24
            offset = fCharacterString(tvb, pinfo, subtree, offset, "details: ");
14122
24
            break;
14123
10
        default:
14124
10
            return offset;
14125
127
        }
14126
112
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14127
112
    }
14128
1
    return offset;
14129
16
}
14130
14131
static unsigned
14132
fWhoAmIRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14133
14
{
14134
14
    unsigned   lastoffset = 0;
14135
14136
107
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14137
105
        lastoffset = offset;
14138
105
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: ");
14139
105
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: ");
14140
105
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: ");
14141
105
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14142
105
    }
14143
14
    return offset;
14144
14
}
14145
14146
static unsigned
14147
fYouAreRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14148
21
{
14149
21
    unsigned   lastoffset = 0;
14150
21
    uint8_t tag_no, tag_info;
14151
21
    uint32_t lvt;
14152
14153
180
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14154
174
        lastoffset = offset;
14155
174
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: ");
14156
174
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: ");
14157
174
        offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: ");
14158
14159
174
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14160
174
        if(tvb_reported_length_remaining(tvb, offset) > 0 && tag_no == 12) {
14161
17
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
14162
17
        }
14163
14164
174
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14165
174
        if(tvb_reported_length_remaining(tvb, offset) > 0 && tag_no == 6) {
14166
17
            offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device MAC address: ");
14167
17
        }
14168
174
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14169
174
    }
14170
21
    return offset;
14171
21
}
14172
14173
static unsigned
14174
fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14175
58
{
14176
58
    unsigned lastoffset = 0;
14177
14178
1.76k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14179
1.75k
        lastoffset = offset;
14180
14181
1.75k
        switch (fTagNo(tvb, offset)) {
14182
680
        case 0: /* Unsigned32 */
14183
680
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
14184
680
            break;
14185
448
        case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
14186
448
            proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
14187
448
            break;
14188
140
        case 2: /* Character String OPTIONAL */
14189
140
            offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
14190
140
            break;
14191
201
        case 3: /* Character String OPTIONAL */
14192
201
            offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
14193
201
            break;
14194
247
        case 4: /* Boolean OPTIONAL */
14195
247
            offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
14196
247
            break;
14197
43
        default:
14198
43
            return offset;
14199
1.75k
        }
14200
1.70k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14201
1.70k
    }
14202
8
    return offset;
14203
58
}
14204
14205
static unsigned
14206
fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14207
2
{
14208
2
    return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
14209
2
}
14210
14211
static unsigned
14212
fAuthenticationFactor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14213
69
{
14214
69
    unsigned   lastoffset = 0;
14215
69
    uint8_t tag_no, tag_info;
14216
69
    uint32_t lvt;
14217
14218
938
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14219
935
        lastoffset = offset;
14220
935
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14221
        /* quit loop if we spot a closing tag */
14222
935
        if (tag_is_closing(tag_info)) {
14223
15
            break;
14224
15
        }
14225
14226
920
        switch (tag_no) {
14227
646
        case 0: /* format-type */
14228
646
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "format-type: ", NULL);
14229
646
            break;
14230
161
        case 1: /* format-class */
14231
161
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "format-class: ");
14232
161
            break;
14233
62
        case 2: /* value */
14234
62
            offset = fOctetString(tvb, pinfo, tree, offset, "value: ", lvt);
14235
62
            break;
14236
50
        default:
14237
50
            break;
14238
920
        }
14239
14240
919
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14241
919
    }
14242
14243
68
    return offset;
14244
69
}
14245
14246
static unsigned
14247
fAuthenticationFactorFormat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14248
103
{
14249
103
    unsigned   lastoffset = 0;
14250
103
    uint8_t tag_no, tag_info;
14251
103
    uint32_t lvt;
14252
14253
1.20k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14254
1.20k
        lastoffset = offset;
14255
1.20k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14256
        /* quit loop if we spot a closing tag */
14257
1.20k
        if (tag_is_closing(tag_info)) {
14258
3
            break;
14259
3
        }
14260
14261
1.20k
        switch (tag_no) {
14262
721
        case 0: /* format-type */
14263
721
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "format-type: ", NULL);
14264
721
            break;
14265
209
        case 1: /* vendor-id */
14266
209
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "vendor-id: ");
14267
209
            break;
14268
173
        case 2: /* vendor-format */
14269
173
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "vendor-format: ");
14270
173
            break;
14271
98
        default:
14272
98
            break;
14273
1.20k
        }
14274
14275
1.20k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14276
1.20k
    }
14277
14278
103
    return offset;
14279
103
}
14280
14281
static unsigned
14282
fAuthenticationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14283
241
{
14284
241
    unsigned   lastoffset = 0;
14285
241
    uint8_t tag_no, tag_info;
14286
241
    uint32_t lvt;
14287
14288
711
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14289
705
        lastoffset = offset;
14290
705
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14291
        /* quit loop if we spot a closing tag */
14292
705
        if (tag_is_closing(tag_info)) {
14293
8
            break;
14294
8
        }
14295
14296
697
        switch (tag_no) {
14297
119
        case 0: /* policy */
14298
119
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14299
501
            while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14300
497
                lastoffset = offset;
14301
497
                fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14302
                /* quit loop if we spot a closing tag */
14303
497
                if (tag_is_closing(tag_info)) {
14304
29
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14305
29
                    break;
14306
29
                }
14307
14308
468
                switch (tag_no) {
14309
201
                case 0: /* credential-data-input */
14310
201
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14311
201
                    offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
14312
201
                    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14313
201
                    break;
14314
194
                case 1: /* index */
14315
194
                    offset = fUnsignedTag(tvb, pinfo, tree, offset, "index: ");
14316
194
                    break;
14317
73
                default:
14318
73
                    break;
14319
468
                }
14320
14321
455
                if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14322
455
            }
14323
106
            break;
14324
215
        case 1: /* order-enforced */
14325
215
            offset = fBooleanTag(tvb, pinfo, tree, offset, "order-enforced: ");
14326
215
            break;
14327
223
        case 2: /* timeout */
14328
223
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "timeout: ");
14329
223
            break;
14330
140
        default:
14331
140
            break;
14332
697
        }
14333
14334
683
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
14335
683
    }
14336
14337
227
    return offset;
14338
241
}
14339
14340
static unsigned
14341
fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14342
7
{
14343
7
    uint8_t tag_no, tag_info;
14344
7
    uint32_t lvt;
14345
14346
7
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier); /* Requesting Device Identifier */
14347
7
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14348
7
    offset = fAddress(tvb, pinfo, tree, offset);
14349
7
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14350
7
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier); /* Remote Device Identifier */
14351
7
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14352
7
    offset = fAddress(tvb, pinfo, tree, offset);
14353
7
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14354
7
    return offset;
14355
7
}
14356
14357
static unsigned
14358
fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14359
39
{
14360
    /* Same as AddListElement request after service choice */
14361
39
    return fAddListElementRequest(tvb, pinfo, tree, offset);
14362
39
}
14363
14364
static unsigned
14365
fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14366
8
{
14367
8
    return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
14368
8
}
14369
14370
static unsigned
14371
fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14372
39
{
14373
39
    unsigned    lastoffset = 0, len;
14374
39
    uint8_t     tag_no, tag_info;
14375
39
    uint32_t    lvt;
14376
39
    proto_tree *subtree = tree;
14377
14378
    /* set the optional global properties to indicate not-used */
14379
39
    propertyArrayIndex = -1;
14380
1.15k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14381
1.15k
        lastoffset = offset;
14382
1.15k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14383
1.15k
        if (tag_is_closing(tag_info)) {
14384
563
            offset += len;
14385
563
            subtree = tree;
14386
563
            continue;
14387
563
        }
14388
588
        switch (tag_no) {
14389
384
        case 0: /* objectIdentifier */
14390
384
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14391
384
            break;
14392
104
        case 1: /* propertyIdentifier */
14393
104
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14394
104
            break;
14395
64
        case 2: /* propertyArrayIndex */
14396
64
            offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
14397
64
            break;
14398
15
        case 3: /* propertyValue */
14399
15
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14400
15
            break;
14401
20
        default:
14402
20
            break;
14403
588
        }
14404
579
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14405
579
    }
14406
30
    return offset;
14407
39
}
14408
14409
static unsigned
14410
fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14411
83
{
14412
83
    unsigned    lastoffset = 0;
14413
83
    uint8_t     tag_no, tag_info;
14414
83
    uint32_t    lvt;
14415
83
    proto_tree *subtree = tree;
14416
14417
    /* set the optional global properties to indicate not-used */
14418
83
    propertyArrayIndex = -1;
14419
1.59k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14420
1.58k
        lastoffset = offset;
14421
1.58k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14422
        /* quit loop if we spot a closing tag */
14423
1.58k
        if (tag_is_closing(tag_info)) {
14424
20
            break;
14425
20
        }
14426
14427
1.56k
        switch (tag_no) {
14428
527
        case 0: /* objectIdentifier */
14429
527
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14430
527
            break;
14431
112
        case 1: /* propertyIdentifier */
14432
112
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14433
112
            break;
14434
299
        case 2: /* propertyArrayIndex */
14435
299
            offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
14436
299
            break;
14437
22
        case 3: /* propertyValue */
14438
22
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14439
22
            break;
14440
570
        case 4: /* Priority (only used for write) */
14441
570
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
14442
570
            break;
14443
32
        default:
14444
32
            return offset;
14445
1.56k
        }
14446
1.52k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14447
1.52k
    }
14448
40
    return offset;
14449
83
}
14450
14451
static unsigned
14452
fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14453
43
{
14454
43
    unsigned   lastoffset = 0, len;
14455
43
    uint8_t tag_no, tag_info;
14456
43
    uint32_t lvt;
14457
14458
768
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14459
763
        lastoffset = offset;
14460
763
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14461
        /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
14462
763
        if (tag_is_closing(tag_info)) {
14463
502
            offset += len;
14464
502
            continue;
14465
502
        }
14466
14467
261
        switch (tag_no) {
14468
219
        case 0: /* objectIdentifier */
14469
219
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14470
219
            break;
14471
24
        case 1: /* listOfPropertyValues */
14472
24
            if (tag_is_opening(tag_info)) {
14473
8
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14474
8
                offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
14475
8
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14476
16
            } else {
14477
16
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14478
16
            }
14479
24
            break;
14480
18
        default:
14481
18
            return offset;
14482
261
        }
14483
239
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14484
239
    }
14485
21
    return offset;
14486
43
}
14487
14488
static unsigned
14489
fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14490
43
{
14491
43
    if (offset >= tvb_reported_length(tvb))
14492
0
        return offset;
14493
14494
43
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14495
43
    return fWriteAccessSpecification(tvb, pinfo, tree, offset);
14496
43
}
14497
14498
static unsigned
14499
fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset, uint8_t list)
14500
12.1k
{
14501
12.1k
    unsigned   lastoffset = 0;
14502
12.1k
    uint8_t tag_no, tag_info;
14503
12.1k
    uint32_t lvt;
14504
14505
    /* set the optional global properties to indicate not-used */
14506
12.1k
    propertyArrayIndex = -1;
14507
18.0k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14508
18.0k
        lastoffset = offset;
14509
18.0k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14510
18.0k
        if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
14511
1.04k
            return offset;
14512
16.9k
        } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
14513
2.15k
            return offset;
14514
2.15k
        }
14515
14.8k
        switch (tag_no-tagoffset) {
14516
6.73k
        case 0: /* PropertyIdentifier */
14517
6.73k
            offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
14518
6.73k
            break;
14519
1.12k
        case 1: /* propertyArrayIndex */
14520
1.12k
            offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
14521
1.12k
            if (list != 0)
14522
21
                break; /* Continue decoding if this may be a list */
14523
            /* FALLTHROUGH */
14524
8.05k
        default:
14525
8.05k
            lastoffset = offset; /* Set loop end condition */
14526
8.05k
            break;
14527
14.8k
        }
14528
14.8k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14529
14.8k
    }
14530
8.90k
    return offset;
14531
12.1k
}
14532
14533
static unsigned
14534
fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t list)
14535
871
{
14536
871
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14537
871
    return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
14538
871
}
14539
14540
static unsigned
14541
fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14542
2.37k
{
14543
2.37k
    unsigned lastoffset = 0;
14544
14545
5.51k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14546
5.50k
        lastoffset = offset;
14547
14548
5.50k
        switch (fTagNo(tvb, offset)) {
14549
3.16k
        case 0: /* ObjectIdentifier */
14550
3.16k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
14551
3.16k
            break;
14552
1.52k
        case 1: /* PropertyIdentifier and propertyArrayIndex */
14553
1.52k
            offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
14554
1.52k
            col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14555
            /* FALLTHROUGH */
14556
2.34k
        default:
14557
2.34k
            lastoffset = offset; /* Set loop end condition */
14558
2.34k
            break;
14559
5.50k
        }
14560
5.47k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14561
5.47k
    }
14562
2.34k
    return offset;
14563
2.37k
}
14564
14565
#if 0
14566
static unsigned
14567
fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, unsigned offset)
14568
{
14569
    unsigned    lastoffset = 0;
14570
    uint8_t     tag_no, tag_info;
14571
    uint32_t    lvt;
14572
    proto_tree* subtree = tree;
14573
    proto_item* tt;
14574
14575
    while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {  /* exit loop if nothing happens inside */
14576
        lastoffset = offset;
14577
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14578
        if (tag_is_closing(tag_info)) {
14579
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
14580
                &tag_no, &tag_info, &lvt);
14581
            continue;
14582
        }
14583
        switch (tag_no) {
14584
        case 0: /* ObjectIdentifier */
14585
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14586
            break;
14587
        case 1: /* PropertyIdentifier */
14588
            offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14589
            break;
14590
        case 2: /* propertyArrayIndex */
14591
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
14592
            break;
14593
        case 3:  /* Value */
14594
            offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14595
            break;
14596
        case 4:  /* Priority */
14597
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
14598
            break;
14599
        default:
14600
            break;
14601
        }
14602
    }
14603
    return offset;
14604
}
14605
#endif
14606
14607
static unsigned
14608
// NOLINTNEXTLINE(misc-no-recursion)
14609
fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14610
1.04k
{
14611
1.04k
    char  i = 1, *str_ar;
14612
1.04k
    unsigned lastoffset = 0;
14613
1.04k
    uint8_t tag_no;
14614
1.04k
    uint8_t tag_info;
14615
1.04k
    uint32_t lvt;
14616
14617
1.04k
    if (propertyArrayIndex > 0) {
14618
        /* BACnetARRAY index 0 refers to the length
14619
        of the array, not the elements of the array.
14620
        BACnetARRAY index -1 is our internal flag that
14621
        the optional index was not used.
14622
        BACnetARRAY refers to this as all elements of the array.
14623
        If the optional index is specified for a BACnetARRAY,
14624
        then that specific array element is referenced. */
14625
177
        i = propertyArrayIndex;
14626
177
    }
14627
2.68k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
14628
        /* exit loop if nothing happens inside */
14629
2.33k
        lastoffset = offset;
14630
2.33k
        str_ar = wmem_strdup_printf(pinfo->pool, "%s[%d]: ",
14631
2.33k
            val_to_split_str(pinfo->pool, 87 , 512,
14632
2.33k
                BACnetPropertyIdentifier,
14633
2.33k
                ASHRAE_Reserved_Fmt,
14634
2.33k
                Vendor_Proprietary_Fmt),
14635
2.33k
            i++);
14636
2.33k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14637
2.33k
        if ( ! tag_is_context_specific(tag_info)) {
14638
            /* DMR Should be fAbstractNSyntax, but that's where we came from! */
14639
1.07k
            offset = fApplicationTypes(tvb, pinfo, tree, offset, str_ar);
14640
1.25k
        } else {
14641
1.25k
            if (tag_is_opening(tag_info) && tag_no == 0) {
14642
636
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14643
636
                offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
14644
636
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14645
636
            } else if (tag_is_opening(tag_info) && tag_no == 1) {
14646
1
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14647
1
                offset = fDate(tvb, pinfo, tree, offset, "Date: ");
14648
1
                offset = fTime(tvb, pinfo, tree, offset, "Time: ");
14649
1
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14650
621
            } else if (tag_is_opening(tag_info) && tag_no == 2) {
14651
13
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14652
13
                offset = fXyColor(tvb, pinfo, tree, offset, "xy-color: ");
14653
13
                offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14654
608
            } else {
14655
                /* DMR Should be fAbstractNSyntax, but that's where we came from! */
14656
608
                offset = fApplicationTypes(tvb, pinfo, tree, offset, str_ar);
14657
608
            }
14658
1.25k
        }
14659
        /* there are only 16 priority array elements */
14660
2.33k
        if (i > 16) {
14661
104
            break;
14662
104
        }
14663
2.23k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14664
2.23k
    }
14665
14666
1.04k
    return offset;
14667
1.04k
}
14668
14669
static unsigned
14670
fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14671
1.42k
{
14672
1.42k
    uint8_t tag_no, tag_info;
14673
1.42k
    uint32_t lvt;
14674
1.42k
    unsigned lastoffset = 0;
14675
14676
4.17k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14677
4.15k
        lastoffset = offset;
14678
4.15k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14679
        /* quit loop if we spot an un-matched closing tag */
14680
4.15k
        if (tag_is_closing(tag_info)) {
14681
278
            break;
14682
278
        }
14683
3.87k
        switch (tag_no) {
14684
1.85k
        case 0: /* deviceIdentifier - OPTIONAL */
14685
1.85k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_device_identifier);
14686
1.85k
            break;
14687
917
        case 1: /* ObjectIdentifier */
14688
917
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
14689
917
            break;
14690
1.10k
        default:
14691
1.10k
            return offset;
14692
3.87k
        }
14693
2.74k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14694
2.74k
    }
14695
294
    return offset;
14696
1.42k
}
14697
14698
static unsigned
14699
fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14700
101
{
14701
101
    uint8_t tag_no, tag_info;
14702
101
    uint32_t lvt;
14703
101
    unsigned lastoffset = 0;
14704
14705
167
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14706
166
        lastoffset = offset;
14707
166
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14708
        /* quit loop if we spot an un-matched closing tag */
14709
166
        if (tag_is_closing(tag_info)) {
14710
1
            break;
14711
1
        }
14712
165
        switch (tag_no) {
14713
35
        case 0: /* calendarEntry */
14714
35
            if (tag_is_opening(tag_info)) {
14715
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14716
0
                offset  = fCalendarEntry(tvb, pinfo, subtree, offset);
14717
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14718
0
            }
14719
35
            break;
14720
18
        case 1: /* calendarReference */
14721
18
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14722
18
            break;
14723
14
        case 2: /* list of BACnetTimeValue */
14724
14
            if (tag_is_opening(tag_info)) {
14725
4
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14726
4
                offset  = fTimeValue(tvb, pinfo, subtree, offset);
14727
4
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14728
10
            } else {
14729
10
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14730
10
            }
14731
14
            break;
14732
45
        case 3: /* eventPriority */
14733
45
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
14734
45
            break;
14735
53
        default:
14736
53
            return offset;
14737
165
        }
14738
111
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14739
111
    }
14740
47
    return offset;
14741
101
}
14742
14743
static unsigned
14744
fNetworkSecurityPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14745
0
{
14746
0
    unsigned   lastoffset = 0;
14747
0
    uint8_t tag_no, tag_info;
14748
0
    uint32_t lvt;
14749
0
    proto_tree *subtree;
14750
14751
0
    subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "network security policy");
14752
14753
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14754
0
        lastoffset = offset;
14755
        /* check the tag.  A closing tag means we are done */
14756
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14757
0
        if (tag_is_closing(tag_info)) {
14758
0
            return offset;
14759
0
        }
14760
0
        switch (tag_no) {
14761
0
        case 0: /* port-id */
14762
0
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "port-id: ");
14763
0
            break;
14764
0
        case 1: /* security-level */
14765
0
            offset  = fEnumeratedTag(tvb, pinfo, subtree, offset,
14766
0
                "security-level: ", BACnetSecurityPolicy);
14767
0
            break;
14768
0
        default:
14769
0
            return offset;
14770
0
        }
14771
0
    }
14772
14773
0
    return offset;
14774
0
}
14775
14776
static unsigned
14777
fKeyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14778
0
{
14779
0
    unsigned   lastoffset = 0;
14780
0
    uint8_t tag_no, tag_info;
14781
0
    uint32_t lvt;
14782
14783
0
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14784
0
        lastoffset = offset;
14785
        /* check the tag.  A closing tag means we are done */
14786
0
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14787
0
        if (tag_is_closing(tag_info)) {
14788
0
            return offset;
14789
0
        }
14790
0
        switch (tag_no) {
14791
0
        case 0: /* algorithm */
14792
0
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "algorithm: ");
14793
0
            break;
14794
0
        case 1: /* key-id */
14795
0
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "key-id: ");
14796
0
            break;
14797
0
        default:
14798
0
            return offset;
14799
0
        }
14800
0
    }
14801
14802
0
    return offset;
14803
0
}
14804
14805
static unsigned
14806
fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14807
297
{
14808
297
    unsigned   lastoffset = 0;
14809
297
    uint8_t tag_no, tag_info;
14810
297
    uint32_t lvt;
14811
297
    proto_tree *subtree;
14812
14813
297
    subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "security keyset");
14814
14815
978
    while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
14816
955
        lastoffset = offset;
14817
        /* check the tag.  A closing tag means we are done */
14818
955
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14819
955
        if (tag_is_closing(tag_info)) {
14820
2
            return offset;
14821
2
        }
14822
953
        switch (tag_no) {
14823
606
        case 0: /* key-revision */
14824
606
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "key-revision: ");
14825
606
            break;
14826
22
        case 1: /* activation-time */
14827
22
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14828
22
            offset = fDateTime(tvb, pinfo, subtree, offset, "activation-time: ");
14829
22
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14830
22
            break;
14831
32
        case 2: /* expiration-time */
14832
32
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14833
32
            offset = fDateTime(tvb, pinfo, subtree, offset, "expiration-time: ");
14834
32
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14835
32
            break;
14836
22
        case 3: /* key-ids */
14837
22
            if (tag_is_opening(tag_info)) {
14838
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14839
0
                offset = fKeyIdentifier(tvb, pinfo, subtree, offset);
14840
0
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14841
22
            } else {
14842
22
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14843
22
            }
14844
22
            break;
14845
271
        default:
14846
271
            return offset;
14847
953
        }
14848
953
    }
14849
14850
23
    return offset;
14851
297
}
14852
14853
static unsigned
14854
fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14855
62
{
14856
62
    unsigned   lastoffset = 0;
14857
62
    uint8_t tag_no, tag_info;
14858
62
    uint32_t lvt;
14859
14860
286
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14861
285
        lastoffset = offset;
14862
285
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14863
        /* quit loop if we spot a closing tag */
14864
285
        if (tag_is_closing(tag_info)) {
14865
12
            break;
14866
12
        }
14867
14868
273
        switch (fTagNo(tvb, offset)) {
14869
72
        case 0: /* propertyIdentifier */
14870
72
            offset  = fPropertyIdentifier(tvb, pinfo, tree, offset);
14871
72
            break;
14872
118
        case 1: /* propertyArrayIndex */
14873
118
            offset  = fPropertyArrayIndex(tvb, pinfo, tree, offset);
14874
118
            break;
14875
33
        case 2: /* relationSpecifier */
14876
33
            offset  = fEnumeratedTag(tvb, pinfo, tree, offset,
14877
33
                "relation Specifier: ", BACnetRelationSpecifier);
14878
33
            break;
14879
31
        case 3: /* comparisonValue */
14880
31
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14881
31
            offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
14882
31
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14883
31
            break;
14884
19
        default:
14885
19
            return offset;
14886
273
        }
14887
251
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14888
251
    }
14889
40
    return offset;
14890
62
}
14891
14892
static unsigned
14893
fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14894
46
{
14895
46
    unsigned   lastoffset = 0;
14896
46
    uint8_t tag_no, tag_info;
14897
46
    uint32_t lvt;
14898
14899
346
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14900
344
        lastoffset = offset;
14901
344
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14902
        /* quit loop if we spot a closing tag */
14903
344
        if (tag_is_closing(tag_info)) {
14904
5
            break;
14905
5
        }
14906
14907
339
        switch (tag_no) {
14908
242
        case 0: /* selectionLogic */
14909
242
            offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
14910
242
                "selection Logic: ", BACnetSelectionLogic);
14911
242
            break;
14912
72
        case 1: /* listOfSelectionCriteria */
14913
72
            if (tag_is_opening(tag_info)) {
14914
62
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14915
62
                offset  = fSelectionCriteria(tvb, pinfo, subtree, offset);
14916
62
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14917
62
            } else {
14918
10
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14919
10
            }
14920
72
            break;
14921
25
        default:
14922
25
            return offset;
14923
339
        }
14924
310
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14925
310
    }
14926
17
    return offset;
14927
46
}
14928
14929
14930
static unsigned
14931
fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, unsigned offset)
14932
49
{
14933
49
    unsigned   lastoffset = 0;
14934
49
    uint8_t tag_no, tag_info;
14935
49
    uint32_t lvt;
14936
14937
115
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14938
112
        lastoffset = offset;
14939
112
        fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14940
14941
112
        if (tag_is_opening(tag_info) && tag_no < 2) {
14942
70
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14943
70
            switch (tag_no) {
14944
46
            case 0: /* objectSelectionCriteria */
14945
46
                offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
14946
46
                break;
14947
24
            case 1: /* listOfPropertyReferences */
14948
24
                offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
14949
24
                break;
14950
0
            default:
14951
0
                return offset;
14952
70
            }
14953
66
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14954
66
        }
14955
108
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14956
108
    }
14957
45
    return offset;
14958
49
}
14959
14960
static unsigned
14961
fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14962
167
{
14963
167
    unsigned    lastoffset = 0;
14964
167
    uint8_t     tag_no, tag_info;
14965
167
    uint32_t    lvt;
14966
167
    proto_tree *subtree = tree;
14967
14968
850
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
14969
846
        lastoffset = offset;
14970
846
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14971
846
        switch (tag_no) {
14972
347
        case 0: /* objectIdentifier */
14973
347
            offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
14974
347
            break;
14975
352
        case 1: /* listOfPropertyReferences */
14976
352
            if (tag_is_opening(tag_info)) {
14977
333
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfPropertyReferences");
14978
333
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14979
333
                offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
14980
333
            } else if (tag_is_closing(tag_info)) {
14981
7
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
14982
7
                    &tag_no, &tag_info, &lvt);
14983
7
                subtree = tree;
14984
12
            } else {
14985
                /* error condition: let caller handle */
14986
12
                return offset;
14987
12
            }
14988
340
            break;
14989
340
        default:
14990
147
            return offset;
14991
846
        }
14992
683
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
14993
683
    }
14994
4
    return offset;
14995
167
}
14996
14997
static unsigned
14998
// NOLINTNEXTLINE(misc-no-recursion)
14999
fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15000
713
{
15001
713
    unsigned    lastoffset = 0, len;
15002
713
    uint8_t     tag_no;
15003
713
    uint8_t     tag_info;
15004
713
    uint32_t    lvt;
15005
713
    proto_tree *subtree = tree;
15006
15007
4.26k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15008
4.26k
        lastoffset = offset;
15009
4.26k
        len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15010
        /* maybe a listOfReadAccessResults if we spot a closing tag here */
15011
4.26k
        if (tag_is_closing(tag_info)) {
15012
1.52k
            offset += len;
15013
1.52k
            if ((tag_no == 4 || tag_no == 5) && (subtree != tree))
15014
8
                subtree = subtree->parent; /* Value and error have extra subtree */
15015
15016
1.52k
        if (tag_no == 1) {
15017
            /* closing list of results for this objectSpecifier */
15018
7
            fTagHeaderTree(tvb, pinfo, subtree, offset - len, &tag_no, &tag_info, &lvt);
15019
            /* look if another objectSpecifier follows here */
15020
7
            if (tvb_reported_length_remaining(tvb, offset) <= 0)
15021
1
                return offset; /* nothing more to decode left */
15022
15023
6
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15024
6
            if (tag_no != 0 || tag_info != 12)
15025
6
                return offset; /* no objectSpecifier */
15026
6
            }
15027
15028
1.51k
            continue;
15029
1.52k
        }
15030
15031
2.73k
        switch (tag_no) {
15032
1.64k
        case 0: /* objectSpecifier */
15033
1.64k
            offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
15034
1.64k
            break;
15035
207
        case 1: /* list of Results */
15036
207
            if (tag_is_opening(tag_info)) {
15037
101
                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfResults");
15038
101
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15039
106
            } else {
15040
106
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15041
106
            }
15042
207
            break;
15043
315
        case 2: /* propertyIdentifier */
15044
315
            offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
15045
315
            break;
15046
78
        case 5: /* propertyAccessError */
15047
78
            if (tag_is_opening(tag_info)) {
15048
34
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "propertyAccessError");
15049
34
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15050
                /* Error Code follows */
15051
34
                offset  = fError(tvb, pinfo, subtree, offset);
15052
34
                fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15053
34
            }
15054
44
            else {
15055
44
                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15056
44
            }
15057
78
            break;
15058
487
        default:
15059
487
            return offset;
15060
2.73k
        }
15061
2.24k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15062
2.24k
    }
15063
210
    return offset;
15064
713
}
15065
15066
15067
static unsigned
15068
fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15069
7
{
15070
    /* listOfReadAccessResults */
15071
7
    return fReadAccessResult(tvb, pinfo, tree, offset);
15072
7
}
15073
15074
15075
static unsigned
15076
fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15077
51
{
15078
51
    unsigned   lastoffset = 0;
15079
51
    uint8_t tag_no, tag_info;
15080
51
    uint32_t lvt;
15081
15082
1.19k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15083
1.19k
        lastoffset = offset;
15084
1.19k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15085
15086
1.19k
        if (tag_no < 2) {
15087
1.15k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15088
1.15k
            switch (tag_no) {
15089
772
            case 0: /* objectSpecifier */
15090
772
                switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
15091
649
                case 0: /* objectType */
15092
649
                    offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
15093
649
                    break;
15094
47
                case 1: /* objectIdentifier */
15095
47
                    offset = fObjectIdentifier(tvb, pinfo, subtree, offset, hf_bacapp_object_identifier);
15096
47
                    break;
15097
72
                default:
15098
72
                    break;
15099
772
                }
15100
768
                break;
15101
768
            case 1: /* propertyValue */
15102
379
                if (tag_is_opening(tag_info)) {
15103
151
                    offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
15104
228
                } else {
15105
228
                    expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15106
228
                }
15107
379
                break;
15108
0
            default:
15109
0
                break;
15110
1.15k
            }
15111
1.14k
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15112
1.14k
        }
15113
1.18k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
15114
1.18k
    }
15115
46
    return offset;
15116
51
}
15117
15118
static unsigned
15119
fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15120
2
{
15121
2
    return fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
15122
2
}
15123
15124
static unsigned
15125
fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15126
34
{
15127
34
    uint8_t     tag_no, tag_info;
15128
34
    uint32_t    lvt;
15129
34
    proto_tree *subtree = tree;
15130
15131
34
    offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
15132
15133
34
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
15134
        /* optional range choice */
15135
29
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15136
29
        if (tag_is_opening(tag_info)) {
15137
7
            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
15138
7
                val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
15139
7
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15140
7
            switch (tag_no) {
15141
0
            case 3: /* range byPosition */
15142
0
            case 6: /* range bySequenceNumber, 2004 spec */
15143
0
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
15144
0
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
15145
0
                break;
15146
0
            case 4: /* range byTime - deprecated in 2004 */
15147
2
            case 7: /* 2004 spec */
15148
2
                offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
15149
2
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
15150
2
                break;
15151
0
            case 5: /* range timeRange - deprecated in 2004 */
15152
0
                offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
15153
0
                offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
15154
0
                break;
15155
5
            default:
15156
5
                break;
15157
7
            }
15158
7
            offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15159
7
        }
15160
29
    }
15161
34
    return offset;
15162
34
}
15163
15164
static unsigned
15165
fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15166
80
{
15167
80
    uint8_t     tag_no, tag_info;
15168
80
    uint32_t    lvt;
15169
80
    proto_tree *subtree = tree;
15170
15171
    /* set the optional global properties to indicate not-used */
15172
80
    propertyArrayIndex = -1;
15173
    /* objectIdentifier, propertyIdentifier, and
15174
       OPTIONAL propertyArrayIndex */
15175
80
    offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
15176
    /* resultFlags => BACnetResultFlags ::= BIT STRING */
15177
80
    offset = fBitStringTagVS(tvb, pinfo, tree, offset,
15178
80
        "resultFlags: ",
15179
80
        BACnetResultFlags);
15180
    /* itemCount */
15181
80
    offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
15182
    /* itemData */
15183
80
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15184
80
    if (tag_is_opening(tag_info)) {
15185
67
        col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15186
67
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "itemData");
15187
67
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15188
67
        offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
15189
67
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15190
67
    }
15191
    /* firstSequenceNumber - OPTIONAL */
15192
80
    if (tvb_reported_length_remaining(tvb, offset) > 0) {
15193
51
        offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
15194
51
    }
15195
15196
80
    return offset;
15197
80
}
15198
15199
static unsigned
15200
fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15201
37
{
15202
37
    unsigned    lastoffset = 0;
15203
37
    uint32_t    lvt;
15204
37
    uint8_t     tag_no, tag_info;
15205
37
    proto_tree* subtree = NULL;
15206
15207
37
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15208
15209
37
    if (tag_is_opening(tag_info)) {
15210
25
        subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL,
15211
25
            val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
15212
25
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15213
25
        offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
15214
25
        offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
15215
15216
25
        if (tag_no == 1) {
15217
70
            while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
15218
                /* exit loop if nothing happens inside */
15219
65
                lastoffset = offset;
15220
65
                offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
15221
65
            }
15222
5
        }
15223
15224
25
        if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
15225
            /* More Flag is not set, so we can look for closing tag in this segment */
15226
22
            fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15227
22
            if (tag_is_closing(tag_info)) {
15228
6
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15229
6
            }
15230
22
        }
15231
25
    }
15232
37
    return offset;
15233
37
}
15234
15235
static unsigned
15236
fAccessRule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15237
127
{
15238
127
    unsigned   lastoffset = 0;
15239
127
    uint8_t tag_no, tag_info;
15240
127
    uint32_t lvt;
15241
15242
1.93k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15243
1.92k
        lastoffset = offset;
15244
1.92k
        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15245
        /* quit loop if we spot a closing tag */
15246
1.92k
        if (tag_is_closing(tag_info)) {
15247
18
            break;
15248
18
        }
15249
15250
1.90k
        switch (tag_no) {
15251
566
        case 0: /* time-range-specifier */
15252
566
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "time-range-specifier: ", NULL);
15253
566
            break;
15254
213
        case 1: /* time-range */
15255
213
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15256
213
            offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
15257
213
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15258
213
            break;
15259
337
        case 2: /* location-specifier */
15260
337
            offset = fEnumeratedTag(tvb, pinfo, tree, offset, "location-specifier: ", NULL);
15261
337
            break;
15262
281
        case 3: /* location */
15263
281
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15264
281
            offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
15265
281
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15266
281
            break;
15267
416
        case 4: /* enable */
15268
416
            offset = fBooleanTag(tvb, pinfo, tree, offset, "enable: ");
15269
416
            break;
15270
91
        default:
15271
91
            break;
15272
1.90k
        }
15273
15274
1.89k
        if (offset <= lastoffset) break;    /* nothing happened, exit loop */
15275
1.89k
    }
15276
15277
118
    return offset;
15278
127
}
15279
15280
static unsigned
15281
fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15282
10
{
15283
10
    uint8_t     tag_no, tag_info;
15284
10
    uint32_t    lvt;
15285
10
    proto_tree *subtree = tree;
15286
15287
10
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier);
15288
15289
10
    fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15290
15291
10
    if (tag_is_opening(tag_info)) {
15292
6
        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
15293
6
                        val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
15294
6
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15295
6
        offset  = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
15296
6
        offset  = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BacnetFileRequestedCount, "unknown option"));
15297
6
        offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15298
6
    }
15299
10
    return offset;
15300
10
}
15301
15302
static unsigned
15303
fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15304
6
{
15305
15306
6
    offset = fObjectIdentifier(tvb, pinfo, tree, offset, hf_bacapp_object_identifier); /* file Identifier */
15307
6
    offset = fAccessMethod(tvb, pinfo, tree, offset);
15308
15309
6
    return offset;
15310
6
}
15311
15312
static unsigned
15313
fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15314
2
{
15315
2
    unsigned tag_no = fTagNo(tvb, offset);
15316
2
    return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
15317
2
}
15318
15319
static unsigned
15320
fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15321
31
{
15322
31
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
15323
31
    offset = fAccessMethod(tvb, pinfo, tree, offset);
15324
15325
31
    return offset;
15326
31
}
15327
15328
static unsigned
15329
fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15330
38
{
15331
38
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15332
38
    return fReadAccessSpecification(tvb, pinfo, subtree, offset);
15333
38
}
15334
15335
static unsigned
15336
fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15337
22
{
15338
22
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15339
22
    return fReadAccessResult(tvb, pinfo, tree, offset);
15340
22
}
15341
15342
static unsigned
15343
fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15344
7.16k
{
15345
7.16k
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
15346
21
        return offset;
15347
15348
7.14k
    switch (service_choice) {
15349
228
    case 0: /* acknowledgeAlarm */
15350
228
        offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
15351
228
        break;
15352
239
    case 1: /* confirmedCOVNotification */
15353
239
        offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
15354
239
        break;
15355
2.37k
    case 2: /* confirmedEventNotification */
15356
2.37k
        offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
15357
2.37k
        break;
15358
0
    case 3: /* confirmedGetAlarmSummary conveys no parameters */
15359
0
        break;
15360
108
    case 4: /* getEnrollmentSummaryRequest */
15361
108
        offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
15362
108
        break;
15363
79
    case 5: /* subscribeCOVRequest */
15364
79
        offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
15365
79
        break;
15366
10
    case 6: /* atomicReadFile-Request */
15367
10
        offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
15368
10
        break;
15369
6
    case 7: /* atomicWriteFile-Request */
15370
6
        offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
15371
6
        break;
15372
1.19k
    case 8: /* AddListElement-Request */
15373
1.19k
        offset = fAddListElementRequest(tvb, pinfo, tree, offset);
15374
1.19k
        break;
15375
39
    case 9: /* removeListElement-Request */
15376
39
        offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
15377
39
        break;
15378
51
    case 10: /* createObjectRequest */
15379
51
        offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
15380
51
        break;
15381
2
    case 11: /* deleteObject */
15382
2
        offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
15383
2
        break;
15384
8
    case 12:
15385
8
        offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
15386
8
        break;
15387
49
    case 13:
15388
49
        offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
15389
49
        break;
15390
38
    case 14:
15391
38
        offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
15392
38
        break;
15393
83
    case 15:
15394
83
        offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
15395
83
        break;
15396
43
    case 16:
15397
43
        offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
15398
43
        break;
15399
44
    case 17:
15400
44
        offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
15401
44
        break;
15402
78
    case 18:
15403
78
        offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
15404
78
        break;
15405
58
    case 19:
15406
58
        offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
15407
58
        break;
15408
31
    case 20:
15409
31
        offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
15410
31
        break;
15411
8
    case 21:
15412
8
        offset = fVtOpenRequest(tvb, pinfo, tree, offset);
15413
8
        break;
15414
26
    case 22:
15415
26
        offset = fVtCloseRequest(tvb, pinfo, tree, offset);
15416
26
        break;
15417
14
    case 23:
15418
14
        offset = fVtDataRequest(tvb, pinfo, tree, offset);
15419
14
        break;
15420
58
    case 24:
15421
58
        offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
15422
58
        break;
15423
7
    case 25:
15424
7
        offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
15425
7
        break;
15426
34
    case 26:
15427
34
        offset = fReadRangeRequest(tvb, pinfo, tree, offset);
15428
34
        break;
15429
50
    case 27:
15430
50
        offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
15431
50
        break;
15432
30
    case 28:
15433
30
        offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
15434
30
        break;
15435
37
    case 29:
15436
37
        offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
15437
37
        break;
15438
133
    case 30:
15439
133
        offset = fSubscribeCOVPropertyMultipleRequest(tvb, pinfo, tree, offset);
15440
133
        break;
15441
74
    case 31:
15442
74
        offset = fConfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
15443
74
        break;
15444
1.50k
    case 32:
15445
1.50k
        offset = fConfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
15446
1.50k
        break;
15447
231
    case 33:
15448
231
        offset = fAuditLogQueryRequest(tvb, pinfo, tree, offset);
15449
231
        break;
15450
79
    case 34:
15451
79
        offset = fAuthRequestRequest(tvb, pinfo, tree, offset);
15452
79
        break;
15453
93
    default:
15454
93
        return offset;
15455
7.14k
    }
15456
3.77k
    return offset;
15457
7.14k
}
15458
15459
static unsigned
15460
fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15461
621
{
15462
621
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
15463
16
        return offset;
15464
15465
605
    switch (service_choice) {
15466
40
    case 3: /* confirmedEventNotificationAck */
15467
40
        offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
15468
40
        break;
15469
43
    case 4: /* getEnrollmentSummaryAck */
15470
43
        offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
15471
43
        break;
15472
31
    case 6: /* atomicReadFile */
15473
31
        offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
15474
31
        break;
15475
2
    case 7: /* atomicReadFileAck */
15476
2
        offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
15477
2
        break;
15478
2
    case 10: /* createObject */
15479
2
        offset = fCreateObjectAck(tvb, pinfo, tree, offset);
15480
2
        break;
15481
39
    case 12:
15482
39
        offset = fReadPropertyAck(tvb, pinfo, tree, offset);
15483
39
        break;
15484
7
    case 13:
15485
7
        offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
15486
7
        break;
15487
22
    case 14:
15488
22
        offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
15489
22
        break;
15490
4
    case 18:
15491
4
        offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
15492
4
        break;
15493
2
    case 21:
15494
2
        offset = fVtOpenAck(tvb, pinfo, tree, offset);
15495
2
        break;
15496
11
    case 23:
15497
11
        offset = fVtDataAck(tvb, pinfo, tree, offset);
15498
11
        break;
15499
2
    case 24:
15500
2
        offset = fAuthenticateAck(tvb, pinfo, tree, offset);
15501
2
        break;
15502
80
    case 26:
15503
80
        offset = fReadRangeAck(tvb, pinfo, tree, offset);
15504
80
        break;
15505
76
    case 29:
15506
76
        offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
15507
76
        break;
15508
69
    case 33:
15509
69
        offset = fAuditLogQueryAck(tvb, pinfo, tree, offset);
15510
69
        break;
15511
139
    case 34:
15512
139
        offset = fAuthRequestAck(tvb, pinfo, tree, offset);
15513
139
        break;
15514
36
    default:
15515
36
        return offset;
15516
605
    }
15517
362
    return offset;
15518
605
}
15519
15520
static unsigned
15521
fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15522
24
{
15523
    /* BACnetObjectIdentifier */
15524
24
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
15525
15526
    /* MaxAPDULengthAccepted */
15527
24
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
15528
15529
    /* segmentationSupported */
15530
24
    offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
15531
24
        "Segmentation Supported: ", BACnetSegmentation);
15532
15533
    /* vendor ID */
15534
24
    return fVendorIdentifier(tvb, pinfo, tree, offset);
15535
24
}
15536
15537
static unsigned
15538
fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15539
5
{
15540
    /* BACnetDeviceIdentifier */
15541
5
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
15542
15543
    /* BACnetObjectIdentifier */
15544
5
    offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
15545
15546
    /* ObjectName */
15547
5
    return fObjectName(tvb, pinfo, tree, offset);
15548
5
}
15549
15550
static unsigned
15551
fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned offset)
15552
32
{
15553
32
    unsigned   lastoffset = 0;
15554
32
    unsigned   val;
15555
32
    uint8_t tag_len;
15556
15557
32
    uint8_t tag_no, tag_info;
15558
32
    uint32_t lvt;
15559
15560
130
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15561
125
        lastoffset = offset;
15562
15563
125
        tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15564
15565
125
        switch (tag_no) {
15566
79
        case 0:
15567
            /* DeviceInstanceRangeLowLimit Optional */
15568
79
            if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15569
35
                col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
15570
79
            offset = fDevice_Instance(tvb, pinfo, tree, offset,
15571
79
                hf_Device_Instance_Range_Low_Limit);
15572
79
            break;
15573
27
        case 1:
15574
            /* DeviceInstanceRangeHighLimit Optional but
15575
                required if DeviceInstanceRangeLowLimit is there */
15576
27
            if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15577
13
                col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
15578
27
            offset = fDevice_Instance(tvb, pinfo, tree, offset,
15579
27
                hf_Device_Instance_Range_High_Limit);
15580
27
            break;
15581
18
        default:
15582
18
            return offset;
15583
125
        }
15584
98
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15585
98
    }
15586
5
    return offset;
15587
32
}
15588
15589
static unsigned
15590
fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15591
660
{
15592
660
    if (tvb_reported_length_remaining(tvb, offset) <= 0)
15593
2
        return offset;
15594
15595
658
    switch (service_choice) {
15596
24
    case 0: /* I-Am-Request */
15597
24
        offset = fIAmRequest(tvb, pinfo, tree, offset);
15598
24
        break;
15599
5
    case 1: /* i-Have Request */
15600
5
        offset = fIHaveRequest(tvb, pinfo, tree, offset);
15601
5
    break;
15602
9
    case 2: /* unconfirmedCOVNotification */
15603
9
        offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
15604
9
        break;
15605
105
    case 3: /* unconfirmedEventNotification */
15606
105
        offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
15607
105
        break;
15608
6
    case 4: /* unconfirmedPrivateTransfer */
15609
6
        offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
15610
6
        break;
15611
6
    case 5: /* unconfirmedTextMessage */
15612
6
        offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
15613
6
        break;
15614
3
    case 6: /* timeSynchronization */
15615
3
        offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
15616
3
        break;
15617
50
    case 7: /* who-Has */
15618
50
        offset = fWhoHas(tvb, pinfo, tree, offset);
15619
50
        break;
15620
32
    case 8: /* who-Is */
15621
32
        offset = fWhoIsRequest(tvb, pinfo, tree, offset);
15622
32
        break;
15623
2
    case 9: /* utcTimeSynchronization */
15624
2
        offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
15625
2
        break;
15626
242
    case 10:
15627
242
        offset = fWriteGroupRequest(tvb, pinfo, tree, offset);
15628
242
        break;
15629
24
    case 11:
15630
24
        offset = fUnconfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
15631
24
        break;
15632
17
    case 12:
15633
17
        offset = fUnconfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
15634
17
        break;
15635
14
    case 13:
15636
14
        offset = fWhoAmIRequest(tvb, pinfo, tree, offset);
15637
14
        break;
15638
21
    case 14:
15639
21
        offset = fYouAreRequest(tvb, pinfo, tree, offset);
15640
21
        break;
15641
98
    default:
15642
98
        break;
15643
658
    }
15644
483
    return offset;
15645
658
}
15646
15647
static unsigned
15648
fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset, uint8_t ack,
15649
        int *svc, proto_item **tt)
15650
7.93k
{
15651
7.93k
    proto_item *tc;
15652
7.93k
    proto_tree *bacapp_tree_control;
15653
7.93k
    int         tmp;
15654
7.93k
    unsigned    extra = 2;
15655
15656
7.93k
    bacapp_seq = 0;
15657
7.93k
    tmp = tvb_get_int8(tvb, offset);
15658
7.93k
    bacapp_flags = tmp & 0x0f;
15659
15660
7.93k
    if (ack == 0) {
15661
7.25k
        extra = 3;
15662
7.25k
    }
15663
7.93k
    *svc = tvb_get_int8(tvb, offset+extra);
15664
7.93k
    if (bacapp_flags & 0x08)
15665
250
        *svc = tvb_get_int8(tvb, offset+extra+2);
15666
15667
7.93k
    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
15668
7.93k
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
15669
7.93k
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
15670
15671
7.93k
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
15672
7.93k
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
15673
7.93k
    if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
15674
7.25k
        proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
15675
7.25k
        proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
15676
7.25k
                            offset, 1, ENC_BIG_ENDIAN);
15677
7.25k
        proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
15678
7.25k
                            offset, 1, ENC_BIG_ENDIAN);
15679
7.25k
    }
15680
7.93k
    offset++;
15681
7.93k
    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
15682
7.93k
    if (bacapp_flags & 0x08) {
15683
250
        bacapp_seq = tvb_get_uint8(tvb, offset);
15684
250
        proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
15685
250
            offset++, 1, ENC_BIG_ENDIAN);
15686
250
        proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
15687
250
            offset++, 1, ENC_BIG_ENDIAN);
15688
250
    }
15689
7.93k
    *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
15690
7.93k
                  offset++, 1, ENC_BIG_ENDIAN);
15691
7.93k
    return offset;
15692
7.93k
}
15693
15694
static unsigned
15695
fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset, int svc)
15696
7.16k
{   /* BACnet-Confirmed-Request */
15697
    /* ASHRAE 135-2001 20.1.2 */
15698
15699
7.16k
    return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
15700
7.16k
}
15701
15702
static unsigned
15703
fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
15704
7.13k
{   /* BACnet-Confirmed-Request */
15705
    /* ASHRAE 135-2001 20.1.2 */
15706
7.13k
    int         svc;
15707
7.13k
    proto_item *tt = 0;
15708
15709
7.13k
    offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
15710
7.13k
    return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
15711
7.13k
}
15712
15713
static unsigned
15714
fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
15715
660
{   /* BACnet-Unconfirmed-Request-PDU */
15716
    /* ASHRAE 135-2001 20.1.3 */
15717
15718
660
    int tmp;
15719
15720
660
    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
15721
15722
660
    tmp = tvb_get_uint8(tvb, offset);
15723
660
    proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
15724
660
        offset++, 1, ENC_BIG_ENDIAN);
15725
    /* Service Request follows... Variable Encoding 20.2ff */
15726
660
    return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
15727
660
}
15728
15729
static unsigned
15730
fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
15731
47
{   /* BACnet-Simple-Ack-PDU */
15732
    /* ASHRAE 135-2001 20.1.4 */
15733
15734
47
    proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
15735
15736
47
    proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
15737
47
                offset++, 1, ENC_BIG_ENDIAN);
15738
47
    proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
15739
47
                offset++, 1, ENC_BIG_ENDIAN);
15740
15741
47
    return offset;
15742
47
}
15743
15744
static unsigned
15745
fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset, int svc)
15746
621
{   /* BACnet-Complex-Ack-PDU */
15747
    /* ASHRAE 135-2001 20.1.5 */
15748
15749
    /* Service ACK follows... */
15750
621
    return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
15751
621
}
15752
15753
static unsigned
15754
fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
15755
549
{   /* BACnet-Complex-Ack-PDU */
15756
    /* ASHRAE 135-2001 20.1.5 */
15757
549
    int         svc;
15758
549
    proto_item *tt = 0;
15759
15760
549
    offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
15761
549
    return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
15762
549
}
15763
15764
static unsigned
15765
fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
15766
26
{   /* BACnet-SegmentAck-PDU */
15767
    /* ASHRAE 135-2001 20.1.6 */
15768
15769
26
    proto_item *tc;
15770
26
    proto_tree *bacapp_tree_control;
15771
15772
26
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
15773
26
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
15774
15775
26
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
15776
26
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
15777
26
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
15778
26
                offset++, 1, ENC_BIG_ENDIAN);
15779
26
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
15780
26
                offset++, 1, ENC_BIG_ENDIAN);
15781
26
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
15782
26
                offset++, 1, ENC_BIG_ENDIAN);
15783
26
    return offset;
15784
26
}
15785
15786
static unsigned
15787
fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15788
1.81k
{
15789
1.81k
    uint8_t tag_info   = 0;
15790
1.81k
    uint8_t parsed_tag = 0;
15791
1.81k
    uint32_t lvt        = 0;
15792
15793
1.81k
    offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
15794
1.81k
    offset  = fError(tvb, pinfo, tree, offset);
15795
1.81k
    return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
15796
1.81k
}
15797
15798
static unsigned
15799
fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15800
114
{
15801
114
    unsigned    lastoffset        = 0;
15802
114
    uint8_t     tag_no            = 0, tag_info = 0;
15803
114
    uint32_t    lvt               = 0;
15804
114
    proto_tree *subtree           = tree;
15805
15806
114
    unsigned    vendor_identifier = 0;
15807
114
    unsigned    service_number    = 0;
15808
114
    uint8_t     tag_len           = 0;
15809
15810
3.54k
    while (tvb_reported_length_remaining(tvb, offset) > 0) {
15811
        /* exit loop if nothing happens inside */
15812
3.53k
        lastoffset = offset;
15813
3.53k
        tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15814
3.53k
        switch (tag_no) {
15815
1.10k
        case 0: /* errorType */
15816
1.10k
            offset = fContextTaggedError(tvb, pinfo, subtree, offset);
15817
1.10k
            break;
15818
1.18k
        case 1: /* vendorID */
15819
1.18k
            fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
15820
1.18k
            col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ",    vendor_identifier);
15821
1.18k
            offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
15822
1.18k
            break;
15823
1.01k
        case 2: /* serviceNumber */
15824
1.01k
            fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
15825
1.01k
            col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ",   service_number);
15826
1.01k
            offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
15827
1.01k
            break;
15828
164
        case 3: /* errorParameters */
15829
164
            if (tag_is_opening(tag_info)) {
15830
8
                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
15831
8
                    ett_bacapp_value, NULL, "error Parameters");
15832
8
                propertyIdentifier = -1;
15833
8
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15834
8
                offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
15835
156
            } else if (tag_is_closing(tag_info)) {
15836
152
                offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
15837
152
                    &tag_no, &tag_info, &lvt);
15838
152
                subtree = tree;
15839
152
            } else {
15840
                /* error condition: let caller handle */
15841
4
                return offset;
15842
4
            }
15843
160
            break;
15844
160
        default:
15845
71
            return offset;
15846
3.53k
        }
15847
3.43k
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15848
3.43k
    }
15849
12
    return offset;
15850
114
}
15851
15852
static unsigned
15853
fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15854
52
{
15855
52
    unsigned lastoffset = 0;
15856
15857
544
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15858
536
        lastoffset = offset;
15859
536
        switch (fTagNo(tvb, offset)) {
15860
325
        case 0: /* errorType */
15861
325
            offset = fContextTaggedError(tvb, pinfo, tree, offset);
15862
325
            break;
15863
178
        case 1: /* firstFailedElementNumber */
15864
178
            offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
15865
178
            break;
15866
33
        default:
15867
33
            return offset;
15868
536
        }
15869
492
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15870
492
    }
15871
8
    return offset;
15872
52
}
15873
15874
static unsigned
15875
fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15876
39
{
15877
    /* Identical to CreateObjectError */
15878
39
    return fCreateObjectError(tvb, pinfo, tree, offset);
15879
39
}
15880
15881
static unsigned
15882
fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15883
21
{
15884
21
    uint8_t tag_no = 0, tag_info = 0;
15885
21
    uint32_t lvt = 0;
15886
15887
21
    if (fTagNo(tvb, offset) == 0) {
15888
        /* errorType */
15889
20
        offset = fContextTaggedError(tvb, pinfo, tree, offset);
15890
20
        if (fTagNo(tvb, offset) == 1) {
15891
            /* listOfVTSessionIdentifiers [OPTIONAL] */
15892
16
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15893
16
            offset  = fVtCloseRequest(tvb, pinfo, tree, offset);
15894
16
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15895
16
        }
15896
20
    }
15897
    /* should report bad packet if initial tag wasn't 0 */
15898
21
    return offset;
15899
21
}
15900
15901
static unsigned
15902
fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15903
30
{
15904
30
    unsigned   lastoffset = 0;
15905
30
    uint8_t tag_no     = 0, tag_info = 0;
15906
30
    uint32_t lvt        = 0;
15907
15908
30
    col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15909
277
    while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
15910
274
        lastoffset = offset;
15911
274
        switch (fTagNo(tvb, offset)) {
15912
158
        case 0: /* errorType */
15913
158
            offset = fContextTaggedError(tvb, pinfo, tree, offset);
15914
158
            break;
15915
94
        case 1: /* firstFailedWriteAttempt */
15916
94
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15917
94
            offset  = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
15918
94
            offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15919
94
            break;
15920
22
        default:
15921
22
            return offset;
15922
274
        }
15923
247
        if (offset <= lastoffset) break;     /* nothing happened, exit loop */
15924
247
    }
15925
3
    return offset;
15926
30
}
15927
15928
static unsigned
15929
fErrorClass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15930
2.43k
{
15931
2.43k
    uint32_t    val = 0, lvt;
15932
2.43k
    uint8_t     tag_no, tag_info;
15933
2.43k
    proto_item *ti;
15934
2.43k
    proto_tree *subtree;
15935
2.43k
    unsigned    tag_len;
15936
15937
2.43k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15938
2.43k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15939
767
    {
15940
767
        ti = proto_tree_add_uint(tree, hf_bacapp_error_class,
15941
767
            tvb, offset, lvt+tag_len, val);
15942
767
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
15943
767
    }
15944
1.67k
    else
15945
1.67k
    {
15946
1.67k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
15947
1.67k
            ett_bacapp_tag, NULL, "Error Class - %u octets (Signed)", lvt);
15948
1.67k
    }
15949
2.43k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15950
2.43k
    offset += tag_len + lvt;
15951
15952
2.43k
    return offset;
15953
2.43k
}
15954
15955
static unsigned
15956
fErrorCode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15957
2.43k
{
15958
2.43k
    uint32_t    val = 0, lvt;
15959
2.43k
    uint8_t     tag_no, tag_info;
15960
2.43k
    proto_item *ti;
15961
2.43k
    proto_tree *subtree;
15962
2.43k
    unsigned    tag_len;
15963
15964
2.43k
    tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15965
2.43k
    if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15966
730
    {
15967
730
        ti = proto_tree_add_uint(tree, hf_bacapp_error_code,
15968
730
            tvb, offset, lvt+tag_len, val);
15969
730
        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
15970
730
    }
15971
1.70k
    else
15972
1.70k
    {
15973
1.70k
        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
15974
1.70k
            ett_bacapp_tag, NULL, "Error Code - %u octets (Signed)", lvt);
15975
1.70k
    }
15976
2.43k
    fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15977
2.43k
    offset += tag_len + lvt;
15978
15979
2.43k
    return offset;
15980
2.43k
}
15981
15982
static unsigned
15983
fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15984
2.43k
{
15985
2.43k
    offset = fErrorClass(tvb, pinfo, tree, offset);
15986
15987
2.43k
    return fErrorCode(tvb, pinfo, tree, offset);
15988
2.43k
}
15989
15990
static unsigned
15991
fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned service)
15992
344
{
15993
344
    switch (service) {
15994
13
    case 8:
15995
13
        offset = fChangeListError(tvb, pinfo, tree, offset);
15996
13
        break;
15997
26
    case 9:
15998
26
        offset = fChangeListError(tvb, pinfo, tree, offset);
15999
26
        break;
16000
13
    case 10:
16001
13
        offset = fCreateObjectError(tvb, pinfo, tree, offset);
16002
13
        break;
16003
30
    case 16:
16004
30
        offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
16005
30
        break;
16006
114
    case 18:
16007
114
        offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
16008
114
        break;
16009
21
    case 22:
16010
21
        offset = fVTCloseError(tvb, pinfo, tree, offset);
16011
21
        break;
16012
87
    case 30:
16013
87
        offset = fSubscribeCOVPropertyMultipleError(tvb, pinfo, tree, offset);
16014
87
        break;
16015
16
    case 34:
16016
16
        offset = fAuthRequestError(tvb, pinfo, tree, offset);
16017
16
        break;
16018
24
    default:
16019
24
        offset = fError(tvb, pinfo, tree, offset);
16020
24
        break;
16021
344
  }
16022
287
    return offset;
16023
344
}
16024
16025
static unsigned
16026
fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
16027
344
{   /* BACnet-Error-PDU */
16028
    /* ASHRAE 135-2001 20.1.7 */
16029
16030
344
    proto_item *tc;
16031
344
    proto_tree *bacapp_tree_control;
16032
344
    uint8_t     tmp;
16033
16034
344
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16035
344
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16036
16037
344
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16038
344
                offset++, 1, ENC_BIG_ENDIAN);
16039
344
    tmp = tvb_get_uint8(tvb, offset);
16040
344
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
16041
344
                 offset++, 1, ENC_BIG_ENDIAN);
16042
    /* Error Handling follows... */
16043
344
    return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
16044
344
}
16045
16046
static unsigned
16047
fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16048
22
{   /* BACnet-Reject-PDU */
16049
    /* ASHRAE 135-2001 20.1.8 */
16050
16051
22
    proto_item *tc;
16052
22
    proto_tree *bacapp_tree_control;
16053
16054
22
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16055
22
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16056
16057
22
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16058
22
                offset++, 1, ENC_BIG_ENDIAN);
16059
22
    proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
16060
22
                offset++, 1, ENC_BIG_ENDIAN);
16061
22
    return offset;
16062
22
}
16063
16064
static unsigned
16065
fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16066
72
{   /* BACnet-Abort-PDU */
16067
    /* ASHRAE 135-2001 20.1.9 */
16068
16069
72
    proto_item *tc;
16070
72
    proto_tree *bacapp_tree_control;
16071
16072
72
    tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
16073
72
    bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16074
16075
72
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
16076
72
    proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16077
72
                offset++, 1, ENC_BIG_ENDIAN);
16078
72
    proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
16079
72
                offset++, 1, ENC_BIG_ENDIAN);
16080
72
    return offset;
16081
72
}
16082
16083
static unsigned
16084
do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
16085
8.94k
{
16086
8.94k
    uint8_t flag, bacapp_type;
16087
8.94k
    unsigned  offset = 0;
16088
16089
8.94k
    flag = tvb_get_int8(tvb, 0);
16090
8.94k
    bacapp_type = (flag >> 4) & 0x0f;
16091
16092
8.94k
    if (tvb == NULL) {
16093
0
        return 0;
16094
0
    }
16095
16096
    /* ASHRAE 135-2001 20.1.1 */
16097
8.94k
    switch (bacapp_type) {
16098
7.13k
    case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
16099
7.13k
        offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
16100
7.13k
        break;
16101
660
    case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:   /* BACnet-Unconfirmed-Request-PDU */
16102
660
        offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
16103
660
        break;
16104
47
    case BACAPP_TYPE_SIMPLE_ACK:    /* BACnet-Simple-Ack-PDU */
16105
47
        offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
16106
47
        break;
16107
549
    case BACAPP_TYPE_COMPLEX_ACK:   /* BACnet-Complex-Ack-PDU */
16108
549
        offset = fComplexAckPDU(tvb, pinfo, tree, offset);
16109
549
        break;
16110
26
    case BACAPP_TYPE_SEGMENT_ACK:   /* BACnet-SegmentAck-PDU */
16111
26
        offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
16112
26
        break;
16113
344
    case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
16114
344
        offset = fErrorPDU(tvb, pinfo, tree, offset);
16115
344
        break;
16116
22
    case BACAPP_TYPE_REJECT:    /* BACnet-Reject-PDU */
16117
22
        offset = fRejectPDU(tvb, pinfo, tree, offset);
16118
22
        break;
16119
72
    case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
16120
72
        offset = fAbortPDU(tvb, pinfo, tree, offset);
16121
72
        break;
16122
8.94k
    }
16123
5.23k
    return offset;
16124
8.94k
}
16125
16126
static int
16127
dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
16128
9.21k
{
16129
9.21k
    uint8_t     flag, bacapp_type;
16130
9.21k
    unsigned    save_fragmented  = false, data_offset = 0, /*bacapp_apdu_size,*/ fragment = false;
16131
9.21k
    tvbuff_t   *new_tvb          = NULL;
16132
9.21k
    unsigned    offset           = 0;
16133
9.21k
    uint8_t     bacapp_seqno     = 0;
16134
9.21k
    uint8_t     bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
16135
9.21k
    uint8_t     bacapp_invoke_id = 0;
16136
9.21k
    proto_item *ti;
16137
9.21k
    proto_tree *bacapp_tree      = NULL;
16138
16139
9.21k
    int         svc = 0;
16140
9.21k
    proto_item *tt  = 0;
16141
9.21k
    int8_t      ack = 0;
16142
16143
    /* Strings for BACnet Statistics */
16144
9.21k
    static const char errstr[]       = "ERROR: ";
16145
9.21k
    static const char rejstr[]       = "REJECTED: ";
16146
9.21k
    static const char abortstr[]     = "ABORTED: ";
16147
9.21k
    static const char sackstr[]      = " (SimpleAck)";
16148
9.21k
    static const char cackstr[]      = " (ComplexAck)";
16149
9.21k
    static const char uconfsreqstr[] = " (Unconfirmed Service Request)";
16150
9.21k
    static const char confsreqstr[]  = " (Confirmed Service Request)";
16151
16152
9.21k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
16153
9.21k
    col_clear(pinfo->cinfo, COL_INFO);
16154
16155
9.21k
    flag = tvb_get_uint8(tvb, 0);
16156
9.21k
    bacapp_type = (flag >> 4) & 0x0f;
16157
16158
    /* show some descriptive text in the INFO column */
16159
9.21k
    col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
16160
9.21k
        val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
16161
16162
9.21k
    bacinfo.service_type = NULL;
16163
9.21k
    bacinfo.invoke_id = NULL;
16164
9.21k
    bacinfo.instance_ident = NULL;
16165
9.21k
    bacinfo.object_ident = NULL;
16166
16167
9.21k
    switch (bacapp_type) {
16168
7.26k
    case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
16169
        /* segmented messages have 2 additional bytes */
16170
7.26k
        if (flag & BACAPP_SEGMENTED_REQUEST) {
16171
122
            fragment = true;
16172
122
            ack = 0;
16173
            /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_uint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
16174
122
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 2);
16175
122
            bacapp_seqno = tvb_get_uint8(tvb, offset + 3);
16176
            /* bacapp_prop_win_size = tvb_get_uint8(tvb, offset + 4); */
16177
122
            bacapp_service = tvb_get_uint8(tvb, offset + 5);
16178
122
            data_offset = 6;
16179
7.14k
        } else {
16180
7.14k
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 2);
16181
7.14k
            bacapp_service = tvb_get_uint8(tvb, offset + 3);
16182
7.14k
        }
16183
7.26k
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
16184
7.26k
                        val_to_str_const(bacapp_service,
16185
7.26k
                                         BACnetConfirmedServiceChoice,
16186
7.26k
                                         bacapp_unknown_service_str),
16187
7.26k
                        bacapp_invoke_id);
16188
16189
7.26k
        updateBacnetInfoValue(BACINFO_INVOKEID,
16190
7.26k
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16191
16192
7.26k
        updateBacnetInfoValue(BACINFO_SERVICE,
16193
7.26k
                              wmem_strconcat(pinfo->pool,
16194
7.26k
                                             val_to_str_const(bacapp_service,
16195
7.26k
                                                              BACnetConfirmedServiceChoice,
16196
7.26k
                                                              bacapp_unknown_service_str),
16197
7.26k
                                             confsreqstr, NULL));
16198
7.26k
        break;
16199
660
    case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
16200
660
        bacapp_service = tvb_get_uint8(tvb, offset + 1);
16201
660
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
16202
660
                        val_to_str_const(bacapp_service,
16203
660
                                         BACnetUnconfirmedServiceChoice,
16204
660
                                         bacapp_unknown_service_str));
16205
16206
660
        updateBacnetInfoValue(BACINFO_SERVICE,
16207
660
                              wmem_strconcat(pinfo->pool,
16208
660
                                             val_to_str_const(bacapp_service,
16209
660
                                                              BACnetUnconfirmedServiceChoice,
16210
660
                                                              bacapp_unknown_service_str),
16211
660
                                             uconfsreqstr, NULL));
16212
660
        break;
16213
47
    case BACAPP_TYPE_SIMPLE_ACK:
16214
47
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16215
47
        bacapp_service = tvb_get_uint8(tvb, offset + 2);
16216
47
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16217
47
                        val_to_str_const(bacapp_service,
16218
47
                                         BACnetConfirmedServiceChoice,
16219
47
                                         bacapp_unknown_service_str),
16220
47
                        bacapp_invoke_id);
16221
16222
47
        updateBacnetInfoValue(BACINFO_INVOKEID,
16223
47
                              wmem_strdup_printf(pinfo->pool,
16224
47
                                                 "Invoke ID: %d", bacapp_invoke_id));
16225
16226
47
        updateBacnetInfoValue(BACINFO_SERVICE,
16227
47
                              wmem_strconcat(pinfo->pool,
16228
47
                                             val_to_str_const(bacapp_service,
16229
47
                                                              BACnetConfirmedServiceChoice,
16230
47
                                                              bacapp_unknown_service_str),
16231
47
                                             sackstr, NULL));
16232
47
        break;
16233
682
    case BACAPP_TYPE_COMPLEX_ACK:
16234
        /* segmented messages have 2 additional bytes */
16235
682
        if (flag & BACAPP_SEGMENTED_REQUEST) {
16236
133
            fragment = true;
16237
133
            ack = 1;
16238
            /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
16239
133
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16240
133
            bacapp_seqno = tvb_get_uint8(tvb, offset + 2);
16241
            /* bacapp_prop_win_size = tvb_get_uint8(tvb, offset + 3); */
16242
133
            bacapp_service = tvb_get_uint8(tvb, offset + 4);
16243
133
            data_offset = 5;
16244
549
        } else {
16245
549
            bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16246
549
            bacapp_service = tvb_get_uint8(tvb, offset + 2);
16247
549
        }
16248
682
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16249
682
                        val_to_str_const(bacapp_service,
16250
682
                                         BACnetConfirmedServiceChoice,
16251
682
                                         bacapp_unknown_service_str),
16252
682
                        bacapp_invoke_id);
16253
16254
682
        updateBacnetInfoValue(BACINFO_INVOKEID,
16255
682
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16256
16257
682
        updateBacnetInfoValue(BACINFO_SERVICE,
16258
682
                              wmem_strconcat(pinfo->pool,
16259
682
                                             val_to_str_const(bacapp_service,
16260
682
                                                              BACnetConfirmedServiceChoice,
16261
682
                                                              bacapp_unknown_service_str),
16262
682
                                             cackstr, NULL));
16263
682
        break;
16264
26
    case BACAPP_TYPE_SEGMENT_ACK:
16265
        /* nothing more to add */
16266
26
        break;
16267
344
    case BACAPP_TYPE_ERROR:
16268
344
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16269
344
        bacapp_service = tvb_get_uint8(tvb, offset + 2);
16270
344
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16271
344
                        val_to_str_const(bacapp_service,
16272
344
                                         BACnetConfirmedServiceChoice,
16273
344
                                         bacapp_unknown_service_str),
16274
344
                        bacapp_invoke_id);
16275
16276
344
        updateBacnetInfoValue(BACINFO_INVOKEID,
16277
344
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16278
16279
344
        updateBacnetInfoValue(BACINFO_SERVICE,
16280
344
                              wmem_strconcat(pinfo->pool,
16281
344
                                             errstr,
16282
344
                                             val_to_str_const(bacapp_service,
16283
344
                                                              BACnetConfirmedServiceChoice,
16284
344
                                                              bacapp_unknown_service_str),
16285
344
                                             NULL));
16286
344
        break;
16287
22
    case BACAPP_TYPE_REJECT:
16288
22
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16289
22
        bacapp_reason = tvb_get_uint8(tvb, offset + 2);
16290
22
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16291
22
                        val_to_split_str(pinfo->pool, bacapp_reason,
16292
22
                                         64,
16293
22
                                         BACnetRejectReason,
16294
22
                                         ASHRAE_Reserved_Fmt,
16295
22
                                         Vendor_Proprietary_Fmt), bacapp_invoke_id);
16296
16297
22
        updateBacnetInfoValue(BACINFO_INVOKEID,
16298
22
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16299
16300
22
        updateBacnetInfoValue(BACINFO_SERVICE,
16301
22
                              wmem_strconcat(pinfo->pool, rejstr,
16302
22
                                             val_to_split_str(pinfo->pool, bacapp_reason, 64,
16303
22
                                                              BACnetRejectReason,
16304
22
                                                              ASHRAE_Reserved_Fmt,
16305
22
                                                              Vendor_Proprietary_Fmt),
16306
22
                                             NULL));
16307
22
        break;
16308
72
    case BACAPP_TYPE_ABORT:
16309
72
        bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16310
72
        bacapp_reason = tvb_get_uint8(tvb, offset + 2);
16311
72
        col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16312
72
                        val_to_split_str(pinfo->pool, bacapp_reason,
16313
72
                                         64,
16314
72
                                         BACnetAbortReason,
16315
72
                                         ASHRAE_Reserved_Fmt,
16316
72
                                         Vendor_Proprietary_Fmt), bacapp_invoke_id);
16317
16318
72
        updateBacnetInfoValue(BACINFO_INVOKEID,
16319
72
                              wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16320
16321
72
        updateBacnetInfoValue(BACINFO_SERVICE,
16322
72
                              wmem_strconcat(pinfo->pool, abortstr,
16323
72
                                             val_to_split_str(pinfo->pool, bacapp_reason,
16324
72
                                                              64,
16325
72
                                                              BACnetAbortReason,
16326
72
                                                              ASHRAE_Reserved_Fmt,
16327
72
                                                              Vendor_Proprietary_Fmt),
16328
72
                                             NULL));
16329
72
        break;
16330
        /* UNKNOWN */
16331
88
    default:
16332
        /* nothing more to add */
16333
88
        break;
16334
9.21k
    }
16335
16336
9.19k
    save_fragmented = pinfo->fragmented;
16337
16338
9.19k
    ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
16339
9.19k
    bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
16340
16341
9.19k
    if (!fragment)
16342
8.94k
        do_the_dissection(tvb, pinfo, bacapp_tree);
16343
250
    else
16344
250
        fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
16345
            /* not resetting the offset so the remaining can be done */
16346
16347
9.19k
    if (fragment) { /* fragmented */
16348
250
        fragment_head *frag_msg;
16349
250
        uint32_t ext_seqno = bacapp_seqno;
16350
16351
250
        pinfo->fragmented = true;
16352
16353
250
        if (!PINFO_FD_VISITED(pinfo)) {
16354
250
            frag_msg = fragment_get(&msg_reassembly_table, pinfo, bacapp_invoke_id, NULL);
16355
250
            if (frag_msg && frag_msg->first_gap) {
16356
                /* If we have permanently lost segments then using the last
16357
                 * contiguous sequence number isn't quite right - but we
16358
                 * won't be able to defragment in that case anyway.
16359
                 */
16360
47
                uint32_t prev_seqno = frag_msg->first_gap->offset;
16361
47
                ext_seqno = calculate_extended_seqno(prev_seqno, bacapp_seqno);
16362
16363
47
                if (ext_seqno != bacapp_seqno) {
16364
14
                    p_add_proto_data(wmem_file_scope(), pinfo, proto_bacapp, bacapp_seqno, GUINT_TO_POINTER(ext_seqno));
16365
14
                }
16366
47
            }
16367
250
        } else {
16368
            /* This is not really necessary (because the fragment number is not
16369
             * used by fragment_add_seq_check on the second pass) but makes the
16370
             * fragment number in the Info column be the extended one.
16371
             */
16372
0
            ext_seqno = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo, proto_bacapp, bacapp_seqno));
16373
0
            if (ext_seqno == 0) {
16374
0
                ext_seqno = bacapp_seqno;
16375
0
            }
16376
0
        }
16377
250
        frag_msg = fragment_add_seq_check(&msg_reassembly_table,
16378
250
            tvb, data_offset,
16379
250
            pinfo,
16380
250
            bacapp_invoke_id,      /* ID for fragments belonging together */
16381
250
            NULL,
16382
250
            ext_seqno,             /* fragment sequence number */
16383
250
            tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
16384
250
            flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
16385
250
        new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
16386
250
                "Reassembled BACapp", frag_msg, &msg_frag_items,
16387
250
                NULL, tree);
16388
16389
250
        if (new_tvb) { /* Reassembled */
16390
96
            col_append_str(pinfo->cinfo, COL_INFO,
16391
96
                           " (Message Reassembled)");
16392
154
        } else { /* Not last packet of reassembled Short Message */
16393
154
            col_append_fstr(pinfo->cinfo, COL_INFO,
16394
154
                            " (Message fragment %u)", ext_seqno);
16395
154
        }
16396
250
        if (new_tvb) { /* take it all */
16397
96
            switch (bacapp_type) {
16398
24
            case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
16399
24
                fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
16400
24
                break;
16401
72
            case BACAPP_TYPE_COMPLEX_ACK:
16402
72
                fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
16403
72
                break;
16404
0
            default:
16405
                /* do nothing */
16406
0
                break;
16407
96
            }
16408
96
        }
16409
250
    }
16410
16411
9.19k
    pinfo->fragmented = save_fragmented;
16412
16413
    /* tapping */
16414
9.19k
    tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
16415
9.19k
    return tvb_captured_length(tvb);
16416
9.19k
}
16417
16418
void
16419
proto_register_bacapp(void)
16420
14
{
16421
14
    static hf_register_info hf[] = {
16422
14
        { &hf_bacapp_type,
16423
14
          { "APDU Type",           "bacapp.type",
16424
14
            FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
16425
14
        },
16426
14
        { &hf_bacapp_pduflags,
16427
14
          { "PDU Flags",          "bacapp.pduflags",
16428
14
            FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
16429
14
        },
16430
14
        { &hf_bacapp_SEG,
16431
14
          { "Segmented Request",           "bacapp.segmented_request",
16432
14
            FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
16433
14
        },
16434
14
        { &hf_bacapp_MOR,
16435
14
          { "More Segments",           "bacapp.more_segments",
16436
14
            FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
16437
14
        },
16438
14
        { &hf_bacapp_SA,
16439
14
          { "SA",           "bacapp.SA",
16440
14
            FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
16441
14
        },
16442
14
        { &hf_bacapp_max_adpu_size,
16443
14
          { "Size of Maximum ADPU accepted",           "bacapp.max_adpu_size",
16444
14
            FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
16445
14
        },
16446
14
        { &hf_bacapp_response_segments,
16447
14
          { "Max Response Segments accepted",           "bacapp.response_segments",
16448
14
            FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
16449
14
        },
16450
14
        { &hf_bacapp_object_identifier,
16451
14
          { "Object Identifier",           "bacapp.objectIdentifier",
16452
14
            FT_UINT32, BASE_CUSTOM, CF_FUNC(format_object_identifier), 0, NULL, HFILL }
16453
14
        },
16454
14
        { &hf_bacapp_device_identifier,
16455
14
          { "Device Identifier",           "bacapp.deviceIdentifier",
16456
14
            FT_UINT32, BASE_CUSTOM, CF_FUNC(format_object_identifier), 0, NULL, HFILL }
16457
14
        },
16458
14
        { &hf_bacapp_objectType,
16459
14
          { "Object Type",           "bacapp.objectType",
16460
14
            FT_UINT32, BASE_DEC|BASE_EXT_STRING, &BACnetObjectType_ext, 0xffc00000, NULL, HFILL }
16461
14
        },
16462
14
        { &hf_bacapp_object_name,
16463
14
          { "Object Name",           "bacapp.object_name",
16464
14
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16465
14
        },
16466
14
        { &hf_bacapp_instanceNumber,
16467
14
          { "Instance Number",           "bacapp.instance_number",
16468
14
            FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
16469
14
        },
16470
14
        { &hf_BACnetPropertyIdentifier,
16471
14
          { "Property Identifier", "bacapp.property_identifier",
16472
14
            FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
16473
14
        },
16474
14
        { &hf_BACnetVendorIdentifier,
16475
14
          { "Vendor Identifier", "bacapp.vendor_identifier",
16476
14
            FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
16477
14
        },
16478
14
        { &hf_BACnetRestartReason,
16479
14
          { "Restart Reason", "bacapp.restart_reason",
16480
14
            FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
16481
14
        },
16482
14
        { &hf_bacapp_invoke_id,
16483
14
          { "Invoke ID",           "bacapp.invoke_id",
16484
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16485
14
        },
16486
14
        { &hf_bacapp_sequence_number,
16487
14
          { "Sequence Number",           "bacapp.sequence_number",
16488
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16489
14
        },
16490
14
        { &hf_bacapp_window_size,
16491
14
          { "Proposed Window Size",           "bacapp.window_size",
16492
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16493
14
        },
16494
14
        { &hf_bacapp_service,
16495
14
          { "Service Choice",           "bacapp.confirmed_service",
16496
14
            FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
16497
14
        },
16498
14
        { &hf_bacapp_uservice,
16499
14
          { "Unconfirmed Service Choice",           "bacapp.unconfirmed_service",
16500
14
            FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
16501
14
        },
16502
14
        { &hf_bacapp_NAK,
16503
14
          { "NAK",           "bacapp.NAK",
16504
14
            FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
16505
14
        },
16506
14
        { &hf_bacapp_SRV,
16507
14
          { "SRV",           "bacapp.SRV",
16508
14
            FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
16509
14
        },
16510
14
        { &hf_bacapp_event_type,
16511
14
          { "Event Type", "bacapp.event_type",
16512
14
            FT_UINT32, BASE_DEC, VALS(BACnetEventType), 0, NULL, HFILL }
16513
14
        },
16514
14
        { &hf_bacapp_notify_type,
16515
14
          { "Notify Type", "bacapp.notify_type",
16516
14
            FT_UINT8, BASE_DEC, VALS(BACnetNotifyType), 0, NULL, HFILL }
16517
14
        },
16518
14
        { &hf_bacapp_error_class,
16519
14
          { "Error Class", "bacapp.error_class",
16520
14
            FT_UINT32, BASE_DEC, VALS(BACnetErrorClass), 0, NULL, HFILL }
16521
14
        },
16522
14
        { &hf_bacapp_error_code,
16523
14
          { "Error Code", "bacapp.error_code",
16524
14
            FT_UINT32, BASE_DEC|BASE_EXT_STRING, &BACnetErrorCode_ext, 0, NULL, HFILL }
16525
14
        },
16526
14
        { &hf_bacapp_present_value_null,
16527
14
          { "Present Value (null)", "bacapp.present_value.null",
16528
14
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16529
14
        },
16530
14
        { &hf_bacapp_present_value_bool,
16531
14
          { "Present Value (bool)", "bacapp.present_value.boolean",
16532
14
            FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
16533
14
        },
16534
14
        { &hf_bacapp_present_value_unsigned,
16535
14
          { "Present Value (uint)", "bacapp.present_value.uint",
16536
14
            FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }
16537
14
        },
16538
14
        { &hf_bacapp_present_value_signed,
16539
14
          { "Present Value (int)", "bacapp.present_value.int",
16540
14
            FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL }
16541
14
        },
16542
14
        { &hf_bacapp_present_value_real,
16543
14
          { "Present Value (real)", "bacapp.present_value.real",
16544
14
            FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL }
16545
14
        },
16546
14
        { &hf_bacapp_present_value_double,
16547
14
          { "Present Value (double)", "bacapp.present_value.double",
16548
14
            FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL }
16549
14
        },
16550
14
        { &hf_bacapp_present_value_octet_string,
16551
14
          { "Present Value (octet string)", "bacapp.present_value.octet_string",
16552
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16553
14
        },
16554
14
        { &hf_bacapp_present_value_char_string,
16555
14
          { "Present Value (char string)", "bacapp.present_value.char_string",
16556
14
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16557
14
        },
16558
14
        { &hf_bacapp_present_value_bit_string,
16559
14
          { "Present Value (bit string)", "bacapp.present_value.bit_string",
16560
14
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16561
14
        },
16562
14
        { &hf_bacapp_present_value_enum_index,
16563
14
          { "Present Value (enum index)", "bacapp.present_value.enum_index",
16564
14
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16565
14
        },
16566
14
        { &hf_Device_Instance_Range_Low_Limit,
16567
14
          { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
16568
14
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16569
14
        },
16570
14
        { &hf_Device_Instance_Range_High_Limit,
16571
14
          { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
16572
14
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16573
14
        },
16574
14
        { &hf_BACnetRejectReason,
16575
14
          { "Reject Reason",           "bacapp.reject_reason",
16576
14
            FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
16577
14
        },
16578
14
        { &hf_BACnetAbortReason,
16579
14
          { "Abort Reason",           "bacapp.abort_reason",
16580
14
            FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
16581
14
        },
16582
14
        { &hf_BACnetApplicationTagNumber,
16583
14
          { "Application Tag Number",
16584
14
            "bacapp.application_tag_number",
16585
14
            FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
16586
14
            NULL, HFILL }
16587
14
        },
16588
14
        { &hf_BACnetContextTagNumber,
16589
14
          { "Context Tag Number",
16590
14
            "bacapp.context_tag_number",
16591
14
            FT_UINT8, BASE_DEC, NULL, 0xF0,
16592
14
            NULL, HFILL }
16593
14
        },
16594
14
        { &hf_BACnetExtendedTagNumber,
16595
14
          { "Extended Tag Number",
16596
14
            "bacapp.extended_tag_number",
16597
14
            FT_UINT8, BASE_DEC, NULL, 0,
16598
14
            NULL, HFILL }
16599
14
        },
16600
14
        { &hf_BACnetNamedTag,
16601
14
          { "Named Tag",
16602
14
            "bacapp.named_tag",
16603
14
            FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
16604
14
            NULL, HFILL }
16605
14
        },
16606
14
        { &hf_BACnetCharacterSet,
16607
14
          { "String Character Set",
16608
14
            "bacapp.string_character_set",
16609
14
            FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
16610
14
            NULL, HFILL }
16611
14
        },
16612
14
        { &hf_BACnetCodePage,
16613
14
          { "Code Page",
16614
14
            "bacapp.code_page",
16615
14
            FT_UINT16, BASE_DEC, NULL, 0,
16616
14
            NULL, HFILL }
16617
14
        },
16618
14
        { &hf_BACnetTagClass,
16619
14
          { "Tag Class",           "bacapp.tag_class",
16620
14
            FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
16621
14
        },
16622
14
        { &hf_bacapp_tag_lvt,
16623
14
          { "Length Value Type",
16624
14
            "bacapp.LVT",
16625
14
            FT_UINT8, BASE_DEC, NULL, 0,
16626
14
            NULL, HFILL }
16627
14
        },
16628
14
        { &hf_bacapp_tag_ProcessId,
16629
14
          { "ProcessIdentifier",           "bacapp.processId",
16630
14
            FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
16631
14
        },
16632
14
        { &hf_bacapp_tag_to_state,
16633
14
          { "To State", "bacapp.to_state",
16634
14
            FT_UINT32, BASE_DEC, VALS(BACnetEventState), 0, NULL, HFILL }
16635
14
        },
16636
14
        { &hf_bacapp_tag_from_state,
16637
14
          { "From State", "bacapp.from_state",
16638
14
            FT_UINT32, BASE_DEC, VALS(BACnetEventState), 0, NULL, HFILL }
16639
14
        },
16640
14
        { &hf_bacapp_tag_IPV4,
16641
14
          { "IPV4",           "bacapp.IPV4",
16642
14
            FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
16643
14
        },
16644
14
        { &hf_bacapp_tag_IPV6,
16645
14
          { "IPV6",           "bacapp.IPV6",
16646
14
            FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
16647
14
        },
16648
14
        { &hf_bacapp_tag_PORT,
16649
14
          { "Port",           "bacapp.Port",
16650
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
16651
14
        },
16652
14
        { &hf_bacapp_tag_mac_address_broadcast,
16653
14
          { "MAC-address: broadcast",           "bacapp.mac_address_broadcast",
16654
14
            FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
16655
14
        },
16656
14
        { &hf_bacapp_reserved_ashrea,
16657
14
          { "reserved for ASHRAE",           "bacapp.reserved_ashrea",
16658
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16659
14
        },
16660
14
        { &hf_bacapp_unused_bits,
16661
14
          { "Unused bits",           "bacapp.unused_bits",
16662
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16663
14
        },
16664
14
        { &hf_bacapp_bit,
16665
14
          { "bit",           "bacapp.bit",
16666
14
            FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
16667
14
        },
16668
14
        { &hf_bacapp_complete_bitstring,
16669
14
          { "Complete bitstring",           "bacapp.complete_bitstring",
16670
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16671
14
        },
16672
14
        {&hf_msg_fragments,
16673
14
          { "Message fragments", "bacapp.fragments",
16674
14
            FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16675
14
        {&hf_msg_fragment,
16676
14
          { "Message fragment", "bacapp.fragment",
16677
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16678
14
        {&hf_msg_fragment_overlap,
16679
14
          { "Message fragment overlap", "bacapp.fragment.overlap",
16680
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16681
14
        {&hf_msg_fragment_overlap_conflicts,
16682
14
          { "Message fragment overlapping with conflicting data",
16683
14
            "bacapp.fragment.overlap.conflicts",
16684
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16685
14
        {&hf_msg_fragment_multiple_tails,
16686
14
          { "Message has multiple tail fragments",
16687
14
            "bacapp.fragment.multiple_tails",
16688
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16689
14
        {&hf_msg_fragment_too_long_fragment,
16690
14
          { "Message fragment too long", "bacapp.fragment.too_long_fragment",
16691
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16692
14
        {&hf_msg_fragment_error,
16693
14
          { "Message defragmentation error", "bacapp.fragment.error",
16694
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16695
14
        {&hf_msg_fragment_count,
16696
14
          { "Message fragment count", "bacapp.fragment.count",
16697
14
            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
16698
14
        {&hf_msg_reassembled_in,
16699
14
          { "Reassembled in", "bacapp.reassembled.in",
16700
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
16701
14
        {&hf_msg_reassembled_length,
16702
14
          { "Reassembled BACapp length", "bacapp.reassembled.length",
16703
14
            FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
16704
14
    };
16705
14
    static int *ett[] = {
16706
14
        &ett_bacapp,
16707
14
        &ett_bacapp_control,
16708
14
        &ett_bacapp_tag,
16709
14
        &ett_bacapp_list,
16710
14
        &ett_bacapp_value,
16711
14
        &ett_bacapp_object_identifier,
16712
14
        &ett_msg_fragment,
16713
14
        &ett_msg_fragments
16714
16715
14
    };
16716
16717
14
    static ei_register_info ei[] = {
16718
14
        { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
16719
14
        { &ei_bacapp_bad_tag, { "bacapp.bad_tag", PI_MALFORMED, PI_ERROR, "Wrong tag found", EXPFILL }},
16720
14
        { &ei_bacapp_opening_tag, { "bacapp.bad_opening_tag", PI_MALFORMED, PI_ERROR, "Expected Opening Tag!", EXPFILL }},
16721
14
    };
16722
16723
14
    expert_module_t* expert_bacapp;
16724
16725
14
    proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
16726
14
                                           "BACapp", "bacapp");
16727
16728
14
    proto_register_field_array(proto_bacapp, hf, array_length(hf));
16729
14
    proto_register_subtree_array(ett, array_length(ett));
16730
14
    expert_bacapp = expert_register_protocol(proto_bacapp);
16731
14
    expert_register_field_array(expert_bacapp, ei, array_length(ei));
16732
14
    register_dissector("bacapp", dissect_bacapp, proto_bacapp);
16733
16734
14
    reassembly_table_register(&msg_reassembly_table,
16735
14
                          &addresses_reassembly_table_functions);
16736
16737
14
    bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
16738
14
                                                      "BACapp Vendor Identifier", proto_bacapp,
16739
14
                                                      FT_UINT8, BASE_HEX);
16740
16741
    /* Register BACnet Statistic trees */
16742
14
    register_bacapp_stat_trees();
16743
14
    bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
16744
14
}
16745
16746
/*
16747
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
16748
 *
16749
 * Local variables:
16750
 * c-basic-offset: 4
16751
 * tab-width: 8
16752
 * indent-tabs-mode: nil
16753
 * End:
16754
 *
16755
 * vi: set shiftwidth=4 tabstop=8 expandtab:
16756
 * :indentSize=4:tabSize=8:noTabs=true:
16757
 */