Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-bacapp.c
blobc776a7b6dacd8009091960dc018aa3aa848650f8
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
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald[AT]wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "config.h"
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"
28 static int bacapp_tap;
30 /* formerly bacapp.h contains definitions and forward declarations */
32 /* BACnet PDU Types */
33 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST 0
34 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST 1
35 #define BACAPP_TYPE_SIMPLE_ACK 2
36 #define BACAPP_TYPE_COMPLEX_ACK 3
37 #define BACAPP_TYPE_SEGMENT_ACK 4
38 #define BACAPP_TYPE_ERROR 5
39 #define BACAPP_TYPE_REJECT 6
40 #define BACAPP_TYPE_ABORT 7
41 #define MAX_BACAPP_TYPE 8
43 #define BACAPP_SEGMENTED_REQUEST 0x08
44 #define BACAPP_MORE_SEGMENTS 0x04
45 #define BACAPP_SEGMENTED_RESPONSE 0x02
46 #define BACAPP_SEGMENT_NAK 0x02
47 #define BACAPP_SENT_BY 0x01
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 **/
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
86 static unsigned
87 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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 - indocates 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
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);
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
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
116 static unsigned
117 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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
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
132 static unsigned
133 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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
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
153 static unsigned
154 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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)
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
172 static unsigned
173 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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
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
189 static unsigned
190 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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
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
205 static unsigned
206 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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
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
222 static unsigned
223 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
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
234 static unsigned
235 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
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
246 static unsigned
247 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
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
259 static unsigned
260 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt);
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
271 static unsigned
272 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
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
283 static unsigned
284 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
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 label the label of this item
294 * @return modified offset
296 static unsigned
297 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
300 * BACnet-Confirmed-Service-Request ::= CHOICE {
302 * @param tvb the tv buffer of the current data
303 * @param pinfo the packet info of the current data
304 * @param tree the tree to append this item to
305 * @param offset the offset in the tvb
306 * @param service_choice the service choice
307 * @return offset
309 static unsigned
310 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
313 * BACnet-Confirmed-Service-ACK ::= CHOICE {
315 * @param tvb the tv buffer of the current data
316 * @param pinfo the packet info of the current data
317 * @param tree the tree to append this item to
318 * @param offset the offset in the tvb
319 * @param service_choice the service choice
320 * @return offset
322 static unsigned
323 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
326 * AcknowledgeAlarm-Request ::= SEQUENCE {
327 * acknowledgingProcessIdentifier [0] Unsigned32,
328 * eventObjectIdentifier [1] BACnetObjectIdentifer,
329 * eventStateAcknowledge [2] BACnetEventState,
330 * timeStamp [3] BACnetTimeStamp,
331 * acknowledgementSource [4] Character String,
332 * timeOfAcknowledgement [5] BACnetTimeStamp
334 * @param tvb the tv buffer of the current data
335 * @param pinfo the packet info of the current data
336 * @param tree the tree to append this item to
337 * @param offset the offset in the tvb
338 * @return modified offset
340 static unsigned
341 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
344 * ConfirmedCOVNotification-Request ::= SEQUENCE {
345 * subscriberProcessIdentifier [0] Unsigned32,
346 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
347 * monitoredObjectIdentifier [2] BACnetObjectIdentifer,
348 * timeRemaining [3] unsigned,
349 * listOfValues [4] SEQUENCE OF BACnetPropertyValues
351 * @param tvb the tv buffer of the current data
352 * @param pinfo the packet info of the current data
353 * @param tree the tree to append this item to
354 * @param offset the offset in the tvb
355 * @return modified offset
357 static unsigned
358 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
361 * ConfirmedEventNotification-Request ::= SEQUENCE {
362 * ProcessIdentifier [0] Unsigned32,
363 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
364 * eventObjectIdentifier [2] BACnetObjectIdentifer,
365 * timeStamp [3] BACnetTimeStamp,
366 * notificationClass [4] unsigned,
367 * priority [5] unsigned8,
368 * eventType [6] BACnetEventType,
369 * messageText [7] CharacterString OPTIONAL,
370 * notifyType [8] BACnetNotifyType,
371 * ackRequired [9] BOOLEAN OPTIONAL,
372 * fromState [10] BACnetEventState OPTIONAL,
373 * toState [11] BACnetEventState,
374 * eventValues [12] BACnetNotificationParameters OPTIONAL
376 * @param tvb the tv buffer of the current data
377 * @param pinfo the packet info of the current data
378 * @param tree the tree to append this item to
379 * @param offset the offset in the tvb
380 * @return modified offset
382 static unsigned
383 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
386 * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
387 * objectIdentifier BACnetObjectIdentifer,
388 * alarmState BACnetEventState,
389 * acknowledgedTransitions BACnetEventTransitionBits
391 * @param tvb the tv buffer of the current data
392 * @param pinfo the packet info of the current data
393 * @param tree the tree to append this item to
394 * @param offset the offset in the tvb
395 * @return modified offset
397 static unsigned
398 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
401 * GetEnrollmentSummary-Request ::= SEQUENCE {
402 * acknowledgmentFilter [0] ENUMERATED {
403 * all (0),
404 * acked (1),
405 * not-acked (2)
406 * },
407 * enrollmentFilter [1] BACnetRecipientProcess OPTIONAL,
408 * eventStateFilter [2] ENUMERATED {
409 * offnormal (0),
410 * fault (1),
411 * normal (2),
412 * all (3),
413 * active (4)
414 * },
415 * eventTypeFilter [3] BACnetEventType OPTIONAL,
416 * priorityFilter [4] SEQUENCE {
417 * minPriority [0] Unsigned8,
418 * maxPriority [1] Unsigned8
419 * } OPTIONAL,
420 * notificationClassFilter [5] Unsigned OPTIONAL
422 * @param tvb the tv buffer of the current data
423 * @param pinfo the packet info of the current data
424 * @param tree the tree to append this item to
425 * @param offset the offset in the tvb
426 * @return modified offset
428 static unsigned
429 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
432 * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
433 * objectIdentifier BACnetObjectIdentifer,
434 * eventType BACnetEventType,
435 * eventState BACnetEventState,
436 * priority Unsigned8,
437 * notificationClass Unsigned OPTIONAL
439 * @param tvb the tv buffer of the current data
440 * @param pinfo the packet info of the current data
441 * @param tree the tree to append this item to
442 * @param offset the offset in the tvb
443 * @return modified offset
445 static unsigned
446 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
449 * GetEventInformation-Request ::= SEQUENCE {
450 * lastReceivedObjectIdentifier [0] BACnetObjectIdentifer
452 * @param tvb the tv buffer of the current data
453 * @param pinfo the packet info of the current data
454 * @param tree the tree to append this item to
455 * @param offset the offset in the tvb
456 * @return modified offset
458 static unsigned
459 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
462 * GetEventInformation-ACK ::= SEQUENCE {
463 * listOfEventSummaries [0] listOfEventSummaries,
464 * moreEvents [1] BOOLEAN
466 * @param tvb the tv buffer of the current data
467 * @param pinfo the packet info of the current data
468 * @param tree the tree to append this item to
469 * @param offset the offset in the tvb
470 * @return modified offset
472 static unsigned
473 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
476 * LifeSafetyOperation-Request ::= SEQUENCE {
477 * requestingProcessIdentifier [0] Unsigned32
478 * requestingSource [1] CharacterString
479 * request [2] BACnetLifeSafetyOperation
480 * objectIdentifier [3] BACnetObjectIdentifier OPTIONAL
482 * @param tvb the tv buffer of the current data
483 * @param pinfo the packet info of the current data
484 * @param tree the tree to append this item to
485 * @param offset the offset in the tvb
486 * @return modified offset
488 static unsigned
489 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
492 * SubscribeCOV-Request ::= SEQUENCE {
493 * subscriberProcessIdentifier [0] Unsigned32
494 * monitoredObjectIdentifier [1] BACnetObjectIdentifier
495 * issueConfirmedNotifications [2] BOOLEAN OPTIONAL
496 * lifetime [3] Unsigned OPTIONAL
498 * @param tvb the tv buffer of the current data
499 * @param pinfo the packet info of the current data
500 * @param tree the tree to append this item to
501 * @param offset the offset in the tvb
502 * @return modified offset
504 static unsigned
505 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
508 * SubscribeCOVProperty-Request ::= SEQUENCE {
509 * subscriberProcessIdentifier [0] Unsigned32
510 * monitoredObjectIdentifier [1] BACnetObjectIdentifier
511 * issueConfirmedNotifications [2] BOOLEAN OPTIONAL
512 * lifetime [3] Unsigned OPTIONAL
513 * monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
514 * covIncrement [5] Unsigned OPTIONAL
516 * @param tvb the tv buffer of the current data
517 * @param pinfo the packet info of the current data
518 * @param tree the tree to append this item to
519 * @param offset the offset in the tvb
520 * @return modified offset
522 static unsigned
523 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
526 * AtomicReadFile-Request ::= SEQUENCE {
527 * fileIdentifier BACnetObjectIdentifier,
528 * accessMethod CHOICE {
529 * streamAccess [0] SEQUENCE {
530 * fileStartPosition INTEGER,
531 * requestedOctetCount Unsigned
532 * },
533 * recordAccess [1] SEQUENCE {
534 * fileStartRecord INTEGER,
535 * requestedRecordCount Unsigned
539 * @param tvb the tv buffer of the current data
540 * @param pinfo the packet info of the current data
541 * @param tree the tree to append this item to
542 * @param offset the offset in the tvb
543 * @return modified offset
545 static unsigned
546 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
549 * AtomicWriteFile-ACK ::= SEQUENCE {
550 * endOfFile BOOLEAN,
551 * accessMethod CHOICE {
552 * streamAccess [0] SEQUENCE {
553 * fileStartPosition INTEGER,
554 * fileData OCTET STRING
555 * },
556 * recordAccess [1] SEQUENCE {
557 * fileStartRecord INTEGER,
558 * returnedRecordCount Unsigned,
559 * fileRecordData SEQUENCE OF OCTET STRING
563 * @param tvb the tv buffer of the current data
564 * @param pinfo the packet info of the current data
565 * @param tree the tree to append this item to
566 * @param offset the offset in the tvb
567 * @return modified offset
569 static unsigned
570 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
573 * AtomicWriteFile-Request ::= SEQUENCE {
574 * fileIdentifier BACnetObjectIdentifier,
575 * accessMethod CHOICE {
576 * streamAccess [0] SEQUENCE {
577 * fileStartPosition INTEGER,
578 * fileData OCTET STRING
579 * },
580 * recordAccess [1] SEQUENCE {
581 * fileStartRecord INTEGER,
582 * recordCount Unsigned,
583 * fileRecordData SEQUENCE OF OCTET STRING
587 * @param tvb the tv buffer of the current data
588 * @param pinfo the packet info of the current data
589 * @param tree the tree to append this item to
590 * @param offset the offset in the tvb
591 * @return modified offset
593 static unsigned
594 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
597 * AtomicWriteFile-ACK ::= SEQUENCE {
598 * fileStartPosition [0] INTEGER,
599 * fileStartRecord [1] INTEGER,
601 * @param tvb the tv buffer of the current data
602 * @param pinfo the packet info of the current data
603 * @param tree the tree to append this item to
604 * @param offset the offset in the tvb
605 * @return modified offset
607 static unsigned
608 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
611 * AddListElement-Request ::= SEQUENCE {
612 * objectIdentifier [0] BACnetObjectIdentifier,
613 * propertyIdentifier [1] BACnetPropertyIdentifier,
614 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
615 * listOfElements [3] ABSTRACT-SYNTAX.&Type
617 * @param tvb the tv buffer of the current data
618 * @param pinfo the packet info of the current data
619 * @param tree the tree to append this item to
620 * @param offset the offset in the tvb
621 * @return modified offset
623 static unsigned
624 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
627 * CreateObject-Request ::= SEQUENCE {
628 * objectSpecifier [0] ObjectSpecifier,
629 * listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
631 * @param tvb the tv buffer of the current data
632 * @param pinfo the packet info of the current data
633 * @param subtree the sub tree to append this item to
634 * @param offset the offset in the tvb
635 * @return modified offset
637 static unsigned
638 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
641 * CreateObject-Request ::= BACnetObjectIdentifier
642 * @param tvb the tv buffer of the current data
643 * @param pinfo the packet info of the current data
644 * @param tree the tree to append this item to
645 * @param offset the offset in the tvb
646 * @return modified offset
648 static unsigned
649 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
652 * DeleteObject-Request ::= SEQUENCE {
653 * ObjectIdentifier BACnetObjectIdentifer
655 * @param tvb the tv buffer of the current data
656 * @param pinfo the packet info of the current data
657 * @param tree the tree to append this item to
658 * @param offset the offset in the tvb
659 * @return modified offset
661 static unsigned
662 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
665 * ReadProperty-Request ::= SEQUENCE {
666 * objectIdentifier [0] BACnetObjectIdentifier,
667 * propertyIdentifier [1] BACnetPropertyIdentifier,
668 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
670 * @param tvb the tv buffer of the current data
671 * @param pinfo the packet info of the current data
672 * @param tree the tree to append this item to
673 * @param offset the offset in the tvb
674 * @return modified offset
676 static unsigned
677 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
680 * ReadProperty-ACK ::= SEQUENCE {
681 * objectIdentifier [0] BACnetObjectIdentifier,
682 * propertyIdentifier [1] BACnetPropertyIdentifier,
683 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
684 * propertyValue [3] ABSTRACT-SYNTAX.&Type
686 * @param tvb the tv buffer of the current data
687 * @param pinfo the packet info of the current data
688 * @param tree the tree to append this item to
689 * @param offset the offset in the tvb
690 * @return modified offset
692 static unsigned
693 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
696 * ReadPropertyConditional-Request ::= SEQUENCE {
697 * objectSelectionCriteria [0] objectSelectionCriteria,
698 * listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
700 * @param tvb the tv buffer of the current data
701 * @param pinfo the packet info of the current data
702 * @param subtree the sub tree to append this item to
703 * @param offset the offset in the tvb
704 * @return modified offset
706 static unsigned
707 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
710 * ReadPropertyConditional-ACK ::= SEQUENCE {
711 * listOfPReadAccessResults SEQUENCE OF ReadAccessResult OPTIONAL
713 * @param tvb the tv buffer of the current data
714 * @param pinfo the packet info of the current data
715 * @param tree the tree to append this item to
716 * @param offset the offset in the tvb
717 * @return modified offset
719 static unsigned
720 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
723 * ReadPropertyMultiple-Request ::= SEQUENCE {
724 * listOfReadAccessSpecs SEQUENCE OF ReadAccessSpecification
726 * @param tvb the tv buffer of the current data
727 * @param pinfo the packet info of the current data
728 * @param subtree the sub tree to append this item to
729 * @param offset the offset in the tvb
730 * @return offset modified
732 static unsigned
733 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
736 * ReadPropertyMultiple-Ack ::= SEQUENCE {
737 * listOfReadAccessResults SEQUENCE OF ReadAccessResult
739 * @param tvb the tv buffer of the current data
740 * @param pinfo the packet info of the current data
741 * @param tree the tree to append this item to
742 * @param offset the offset in the tvb
743 * @return offset modified
745 static unsigned
746 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
749 * ReadRange-Request ::= SEQUENCE {
750 * objectIdentifier [0] BACnetObjectIdentifier,
751 * propertyIdentifier [1] BACnetPropertyIdentifier,
752 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
753 * range CHOICE {
754 * byPosition [3] SEQUENCE {
755 * referencedIndex Unsigned,
756 * count INTEGER
757 * },
758 * byTime [4] SEQUENCE {
759 * referenceTime BACnetDateTime,
760 * count INTEGER
761 * },
762 * timeRange [5] SEQUENCE {
763 * beginningTime BACnetDateTime,
764 * endingTime BACnetDateTime
765 * },
766 * } OPTIONAL
768 * @param tvb the tv buffer of the current data
769 * @param pinfo the packet info of the current data
770 * @param tree the tree to append this item to
771 * @param offset the offset in the tvb
772 * @return modified offset
774 static unsigned
775 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
778 * ReadRange-ACK ::= SEQUENCE {
779 * objectIdentifier [0] BACnetObjectIdentifier,
780 * propertyIdentifier [1] BACnetPropertyIdentifier,
781 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
782 * resultFlags [3] BACnetResultFlags,
783 * itemCount [4] Unsigned,
784 * itemData [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
786 * @param tvb the tv buffer of the current data
787 * @param pinfo the packet info of the current data
788 * @param tree the tree to append this item to
789 * @param offset the offset in the tvb
790 * @return modified offset
792 static unsigned
793 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
796 * RemoveListElement-Request ::= SEQUENCE {
797 * objectIdentifier [0] BACnetObjectIdentifier,
798 * propertyIdentifier [1] BACnetPropertyIdentifier,
799 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
800 * listOfElements [3] ABSTRACT-SYNTAX.&Type
802 * @param tvb the tv buffer of the current data
803 * @param pinfo the packet info of the current data
804 * @param tree the tree to append this item to
805 * @param offset the offset in the tvb
806 * @return modified offset
808 static unsigned
809 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
812 * WriteProperty-Request ::= SEQUENCE {
813 * objectIdentifier [0] BACnetObjectIdentifier,
814 * propertyIdentifier [1] BACnetPropertyIdentifier,
815 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
816 * propertyValue [3] ABSTRACT-SYNTAX.&Type
817 * priority [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
819 * @param tvb the tv buffer of the current data
820 * @param pinfo the packet info of the current data
821 * @param tree the tree to append this item to
822 * @param offset the offset in the tvb
823 * @return modified offset
825 static unsigned
826 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
829 * WritePropertyMultiple-Request ::= SEQUENCE {
830 * listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
832 * @param tvb the tv buffer of the current data
833 * @param pinfo the packet info of the current data
834 * @param tree the tree to append this item to
835 * @param offset the offset in the tvb
836 * @return modified offset
838 static unsigned
839 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
842 * DeviceCommunicationControl-Request ::= SEQUENCE {
843 * timeDuration [0] Unsigned16 OPTIONAL,
844 * enable-disable [1] ENUMERATED {
845 * enable (0),
846 * disable (1)
847 * },
848 * password [2] CharacterString (SIZE(1..20)) OPTIONAL
850 * @param tvb the tv buffer of the current data
851 * @param pinfo the packet info of the current data
852 * @param tree the tree to append this item to
853 * @param offset the offset in the tvb
854 * @return modified offset
856 static unsigned
857 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
860 * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
861 * vendorID [0] Unsigned,
862 * serviceNumber [1] Unsigned,
863 * serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
865 * @param tvb the tv buffer of the current data
866 * @param pinfo the packet info of the current data
867 * @param tree the tree to append this item to
868 * @param offset the offset in the tvb
869 * @return modified offset
871 static unsigned
872 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
875 * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
876 * vendorID [0] Unsigned,
877 * serviceNumber [1] Unsigned,
878 * resultBlock [2] ABSTRACT-SYNTAX.&Type OPTIONAL
880 * @param tvb the tv buffer of the current data
881 * @param pinfo the packet info of the current data
882 * @param tree the tree to append this item to
883 * @param offset the offset in the tvb
884 * @return modified offset
886 static unsigned
887 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
890 * ConfirmedTextMessage-Request ::= SEQUENCE {
891 * textMessageSourceDevice [0] BACnetObjectIdentifier,
892 * messageClass [1] CHOICE {
893 * numeric [0] Unsigned,
894 * character [1] CharacterString
895 * } OPTIONAL,
896 * messagePriority [2] ENUMERATED {
897 * normal (0),
898 * urgent (1)
899 * },
900 * message [3] CharacterString
902 * @param tvb the tv buffer of the current data
903 * @param pinfo the packet info of the current data
904 * @param tree the tree to append this item to
905 * @param offset the offset in the tvb
906 * @return modified offset
908 static unsigned
909 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
912 * ReinitializeDevice-Request ::= SEQUENCE {
913 * reinitializedStateOfDevice [0] ENUMERATED {
914 * coldstart (0),
915 * warmstart (1),
916 * startbackup (2),
917 * endbackup (3),
918 * startrestore (4),
919 * endrestore (5),
920 * abortrestor (6)
921 * },
922 * password [1] CharacterString (SIZE(1..20)) OPTIONAL
924 * @param tvb the tv buffer of the current data
925 * @param pinfo the packet info of the current data
926 * @param tree the tree to append this item to
927 * @param offset the offset in the tvb
928 * @return modified offset
930 static unsigned
931 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
934 * VTOpen-Request ::= SEQUENCE {
935 * vtClass BACnetVTClass,
936 * localVTSessionIdentifier Unsigned8
938 * @param tvb the tv buffer of the current data
939 * @param pinfo the packet info of the current data
940 * @param tree the tree to append this item to
941 * @param offset the offset in the tvb
942 * @return modified offset
944 static unsigned
945 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
948 * VTOpen-ACK ::= SEQUENCE {
949 * remoteVTSessionIdentifier Unsigned8
951 * @param tvb the tv buffer of the current data
952 * @param pinfo the packet info of the current data
953 * @param tree the tree to append this item to
954 * @param offset the offset in the tvb
955 * @return modified offset
957 static unsigned
958 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
961 * VTClose-Request ::= SEQUENCE {
962 * listOfRemoteVTSessionIdentifiers SEQUENCE OF Unsigned8
964 * @param tvb the tv buffer of the current data
965 * @param pinfo the packet info of the current data
966 * @param tree the tree to append this item to
967 * @param offset the offset in the tvb
968 * @return modified offset
970 static unsigned
971 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
974 * VTData-Request ::= SEQUENCE {
975 * vtSessionIdentifier Unsigned8,
976 * vtNewData OCTET STRING,
977 * vtDataFlag Unsigned (0..1)
979 * @param tvb the tv buffer of the current data
980 * @param pinfo the packet info of the current data
981 * @param tree the tree to append this item to
982 * @param offset the offset in the tvb
983 * @return modified offset
985 static unsigned
986 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
989 * VTData-ACK ::= SEQUENCE {
990 * allNewDataAccepted [0] BOOLEAN,
991 * acceptedOctetCount [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = false
993 * @param tvb the tv buffer of the current data
994 * @param pinfo the packet info of the current data
995 * @param tree the tree to append this item to
996 * @param offset the offset in the tvb
997 * @return modified offset
999 static unsigned
1000 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1003 * Authenticate-Request ::= SEQUENCE {
1004 * pseudoRandomNumber [0] Unsigned32,
1005 * excpectedInvokeID [1] Unsigned8 OPTIONAL,
1006 * operatorName [2] CharacterString OPTIONAL,
1007 * operatorPassword [3] CharacterString (SIZE(1..20)) OPTIONAL,
1008 * startEncypheredSession [4] BOOLEAN OPTIONAL
1010 * @param tvb the tv buffer of the current data
1011 * @param pinfo the packet info of the current data
1012 * @param tree the tree to append this item to
1013 * @param offset the offset in the tvb
1014 * @return modified offset
1016 static unsigned
1017 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1020 * Authenticate-ACK ::= SEQUENCE {
1021 * modifiedRandomNumber Unsigned32,
1023 * @param tvb the tv buffer of the current data
1024 * @param pinfo the packet info of the current data
1025 * @param tree the tree to append this item to
1026 * @param offset the offset in the tvb
1027 * @return modified offset
1029 static unsigned
1030 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1033 * RequestKey-Request ::= SEQUENCE {
1034 * requestingDeviceIdentifier BACnetObjectIdentifier,
1035 * requestingDeviceAddress BACnetAddress,
1036 * remoteDeviceIdentifier BACnetObjectIdentifier,
1037 * remoteDeviceAddress BACnetAddress
1039 * @param tvb the tv buffer of the current data
1040 * @param pinfo the packet info of the current data
1041 * @param tree the tree to append this item to
1042 * @param offset the offset in the tvb
1043 * @return modified offset
1045 static unsigned
1046 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1049 * Unconfirmed-Service-Request ::= CHOICE {
1051 * @param tvb the tv buffer of the current data
1052 * @param pinfo the packet info of the current data
1053 * @param tree the tree to append this item to
1054 * @param offset the offset in the tvb
1055 * @param service_choice the service choice
1056 * @return modified offset
1058 static unsigned
1059 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice);
1062 * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1063 * subscriberProcessIdentifier [0] Unsigned32,
1064 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
1065 * monitoredObjectIdentifier [2] BACnetObjectIdentifer,
1066 * timeRemaining [3] unsigned,
1067 * listOfValues [4] SEQUENCE OF BACnetPropertyValues
1069 * @param tvb the tv buffer of the current data
1070 * @param pinfo the packet info of the current data
1071 * @param tree the tree to append this item to
1072 * @param offset the offset in the tvb
1073 * @return modified offset
1075 static unsigned
1076 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1079 * UnconfirmedEventNotification-Request ::= SEQUENCE {
1080 * ProcessIdentifier [0] Unsigned32,
1081 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
1082 * eventObjectIdentifier [2] BACnetObjectIdentifer,
1083 * timeStamp [3] BACnetTimeStamp,
1084 * notificationClass [4] unsigned,
1085 * priority [5] unsigned8,
1086 * eventType [6] BACnetEventType,
1087 * messageText [7] CharacterString OPTIONAL,
1088 * notifyType [8] BACnetNotifyType,
1089 * ackRequired [9] BOOLEAN OPTIONAL,
1090 * fromState [10] BACnetEventState OPTIONAL,
1091 * toState [11] BACnetEventState,
1092 * eventValues [12] BACnetNotificationParameters OPTIONAL
1094 * @param tvb the tv buffer of the current data
1095 * @param pinfo the packet info of the current data
1096 * @param tree the tree to append this item to
1097 * @param offset the offset in the tvb
1098 * @return modified offset
1100 static unsigned
1101 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1104 * I-Am-Request ::= SEQUENCE {
1105 * aAmDeviceIdentifier BACnetObjectIdentifier,
1106 * maxAPDULengthAccepted Unsigned,
1107 * segmentationSupported BACnetSegmentation,
1108 * vendorID Unsigned
1110 * @param tvb the tv buffer of the current data
1111 * @param pinfo the packet info of the current data
1112 * @param tree the tree to append this item to
1113 * @param offset the offset in the tvb
1114 * @return modified offset
1116 static unsigned
1117 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1121 * I-Have-Request ::= SEQUENCE {
1122 * deviceIdentifier BACnetObjectIdentifier,
1123 * objectIdentifier BACnetObjectIdentifier,
1124 * objectName CharacterString
1126 * @param tvb the tv buffer of the current data
1127 * @param pinfo the packet info of the current data
1128 * @param tree the tree to append this item to
1129 * @param offset the offset in the tvb
1130 * @return modified offset
1132 static unsigned
1133 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1136 * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1137 * vendorID [0] Unsigned,
1138 * serviceNumber [1] Unsigned,
1139 * serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1141 * @param tvb the tv buffer of the current data
1142 * @param pinfo the packet info of the current data
1143 * @param tree the tree to append this item to
1144 * @param offset the offset in the tvb
1145 * @return modified offset
1147 static unsigned
1148 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1151 * UnconfirmedTextMessage-Request ::= SEQUENCE {
1152 * textMessageSourceDevice [0] BACnetObjectIdentifier,
1153 * messageClass [1] CHOICE {
1154 * numeric [0] Unsigned,
1155 * character [1] CharacterString
1156 * } OPTIONAL,
1157 * messagePriority [2] ENUMERATED {
1158 * normal (0),
1159 * urgent (1)
1160 * },
1161 * message [3] CharacterString
1163 * @param tvb the tv buffer of the current data
1164 * @param pinfo the packet info of the current data
1165 * @param tree the tree to append this item to
1166 * @param offset the offset in the tvb
1167 * @return modified offset
1169 static unsigned
1170 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1173 * TimeSynchronization-Request ::= SEQUENCE {
1174 * BACnetDateTime
1176 * @param tvb the tv buffer of the current data
1177 * @param pinfo the packet info of the current data
1178 * @param tree the tree to append this item to
1179 * @param offset the offset in the tvb
1180 * @return modified offset
1182 static unsigned
1183 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1186 * UTCTimeSynchronization-Request ::= SEQUENCE {
1187 * BACnetDateTime
1189 * @param tvb the tv buffer of the current data
1190 * @param pinfo the packet info of the current data
1191 * @param tree the tree to append this item to
1192 * @param offset the offset in the tvb
1193 * @return modified offset
1195 static unsigned
1196 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1199 * Who-Has-Request ::= SEQUENCE {
1200 * limits SEQUENCE {
1201 * deviceInstanceRangeLowLimit [0] Unsigned (0..4194303),
1202 * deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1203 * } OPTIONAL,
1204 * object CHOICE {
1205 * objectIdentifier [2] BACnetObjectIdentifier,
1206 * objectName [3] CharacterString
1209 * @param tvb the tv buffer of the current data
1210 * @param pinfo the packet info of the current data
1211 * @param tree the tree to append this item to
1212 * @param offset the offset in the tvb
1213 * @return modified offset
1215 static unsigned
1216 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1219 * Who-Is-Request ::= SEQUENCE {
1220 * deviceInstanceRangeLowLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1221 * deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1223 * @param tvb the tv buffer of the current data
1224 * @param tree the tree to append this item to
1225 * @param offset the offset in the tvb
1226 * @return modified offset
1228 static unsigned
1229 fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1232 * BACnet-Error ::= CHOICE {
1233 * addListElement [8] ChangeList-Error,
1234 * removeListElement [9] ChangeList-Error,
1235 * writePropertyMultiple [16] WritePropertyMultiple-Error,
1236 * confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1237 * vtClose [22] VTClose-Error,
1238 * readRange [26] ObjectAccessService-Error
1239 * [default] Error
1241 * @param tvb the tv buffer of the current data
1242 * @param pinfo the packet info of the current data
1243 * @param tree the tree to append this item to
1244 * @param offset the offset in the tvb
1245 * @param service the service
1246 * @return modified offset
1248 static unsigned
1249 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned service);
1252 * Dissect a BACnetError in a context tag
1254 * @param tvb the tv buffer of the current data
1255 * @param pinfo the packet info of the current data
1256 * @param tree the tree to append this item to
1257 * @param offset the offset in the tvb
1258 * @return modified offset
1260 static unsigned fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1263 * ChangeList-Error ::= SEQUENCE {
1264 * errorType [0] Error,
1265 * firstFailedElementNumber [1] Unsigned
1268 * @param tvb the tv buffer of the current data
1269 * @param pinfo the packet info of the current data
1270 * @param tree the tree to append this item to
1271 * @param offset the offset in the tvb
1272 * @return modified offset
1274 static unsigned
1275 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1278 * CreateObject-Error ::= SEQUENCE {
1279 * errorType [0] Error,
1280 * firstFailedElementNumber [1] Unsigned
1283 * @param tvb the tv buffer of the current data
1284 * @param pinfo the packet info of the current data
1285 * @param tree the tree to append this item to
1286 * @param offset the offset in the tvb
1287 * @return modified offset
1289 static unsigned
1290 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1293 * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1294 * errorType [0] Error,
1295 * vendorID [1] Unsigned,
1296 * serviceNumber [2] Unsigned,
1297 * errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1300 * @param tvb the tv buffer of the current data
1301 * @param pinfo the packet info of the current data
1302 * @param tree the tree to append this item to
1303 * @param offset the offset in the tvb
1304 * @return modified offset
1306 static unsigned
1307 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1310 * WritePropertyMultiple-Error ::= SEQUENCE {
1311 * errorType [0] Error,
1312 * firstFailedWriteAttempt [1] Unsigned
1315 * @param tvb the tv buffer of the current data
1316 * @param pinfo the packet info of the current data
1317 * @param tree the tree to append this item to
1318 * @param offset the offset in the tvb
1319 * @return modified offset
1321 static unsigned
1322 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1325 * VTClose-Error ::= SEQUENCE {
1326 * errorType [0] Error,
1327 * listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1330 * @param tvb the tv buffer of the current data
1331 * @param pinfo the packet info of the current data
1332 * @param tree the tree to append this item to
1333 * @param offset the offset in the tvb
1334 * @return modified offset
1336 static unsigned
1337 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1340 * BACnet Application Types chapter 20.2.1
1341 * @param tvb the tv buffer of the current data
1342 * @param pinfo the packet info of the current data
1343 * @param tree the tree to append this item to
1344 * @param offset the offset in the tvb
1345 * @param label the label of this item
1346 * @return modified offset
1348 static unsigned
1349 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
1352 * BACnetActionCommand ::= SEQUENCE {
1353 * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
1354 * objectIdentifier [1] BACnetObjectIdentifier,
1355 * propertyIdentifier [2] BACnetPropertyIdentifier,
1356 * propertyArrayIndex [3] Unsigned OPTIONAL, -- used only with array datatype
1357 * propertyValue [4] ABSTRACT-SYNTAX.&Type,
1358 * priority [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1359 * postDelay [6] Unsigned OPTIONAL,
1360 * quitOnFailure [7] BOOLEAN,
1361 * writeSuccessful [8] BOOLEAN
1363 * @param tvb the tv buffer of the current data
1364 * @param pinfo the packet info of the current data
1365 * @param tree the tree to append this item to
1366 * @param offset the offset in the tvb
1367 * @param tag_match the tag number
1368 * @return modified offset
1370 static unsigned
1371 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_match);
1374 * BACnetActionList ::= SEQUENCE {
1375 * action [0] SEQUENCE of BACnetActionCommand
1377 * @param tvb the tv buffer of the current data
1378 * @param pinfo the packet info of the current data
1379 * @param tree the tree to append this item to
1380 * @param offset the offset in the tvb
1381 * @return modified offset
1383 static unsigned
1384 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1386 /** BACnetAddress ::= SEQUENCE {
1387 * network-number Unsigned16, -- A value 0 indicates the local network
1388 * mac-address OCTET STRING -- A string of length 0 indicates a broadcast
1390 * @param tvb the tv buffer of the current data
1391 * @param pinfo the packet info of the current data
1392 * @param tree the tree to append this item to
1393 * @param offset the offset in the tvb
1394 * @return modified offset
1396 static unsigned
1397 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1400 * BACnetAddressBinding ::= SEQUENCE {
1401 * deviceObjectID BACnetObjectIdentifier
1402 * deviceAddress BacnetAddress
1404 * @param tvb the tv buffer of the current data
1405 * @param pinfo the packet info of the current data
1406 * @param tree the tree to append this item to
1407 * @param offset the offset in the tvb
1408 * @return modified offset
1410 static unsigned
1411 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1414 * BACnetCalendarEntry ::= CHOICE {
1415 * date [0] Date,
1416 * dateRange [1] BACnetDateRange,
1417 * weekNDay [2] BacnetWeekNday
1419 * @param tvb the tv buffer of the current data
1420 * @param pinfo the packet info of the current data
1421 * @param tree the tree to append this item to
1422 * @param offset the offset in the tvb
1423 * @return modified offset
1425 static unsigned
1426 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1429 * BACnetClientCOV ::= CHOICE {
1430 * real-increment REAL,
1431 * default-increment NULL
1433 * @param tvb the tv buffer of the current data
1434 * @param tree the tree to append this item to
1435 * @param offset the offset in the tvb
1436 * @return modified offset
1438 static unsigned
1439 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1443 * BACnetDailySchedule ::= SEQUENCE {
1444 * day-schedule [0] SENQUENCE OF BACnetTimeValue
1446 * @param tvb the tv buffer of the current data
1447 * @param pinfo the packet info of the current data
1448 * @param tree the tree to append this item to
1449 * @param offset the offset in the tvb
1450 * @return modified offset
1452 static unsigned
1453 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1456 * BACnetHealth ::= SEQUENCE {
1457 * timestamp [0] BACnetDateTime,
1458 * result [1] Error,
1459 * property [2] BACnetPropertiyIdentifier OPTIONAL,
1460 * details [3] CharacterString OPTIONAL
1462 * @param tvb the tv buffer of the current data
1463 * @param pinfo the packet info of the current data
1464 * @param tree the tree to append this item to
1465 * @param offset the offset in the tvb
1466 * @return modified offset
1468 static unsigned
1469 fHealth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1472 * BACnetSCFailedConnectionRequest ::= SEQUENCE {
1473 * timestamp [0] BACnetDateTime,
1474 * peer-address [1] BACnetHostNPort,
1475 * peer-vmac [2] OCTET STRING (SIZE(6))
1476 * peer-uuid [3] OCTET STRING (SIZE(16))
1477 * error [4] Error OPTIONAL
1478 * error-details [5] CharacterString OPTIONAL
1480 * @param tvb the tv buffer of the current data
1481 * @param pinfo the packet info of the current data
1482 * @param tree the tree to append this item to
1483 * @param offset the offset in the tvb
1484 * @return modified offset
1486 static unsigned
1487 fSCFailedConnectionRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1490 * BACnetSCDirectConnection ::= SEQUENCE {
1491 * uri [0] CharacterString
1492 * connection-state [1] BACnetSCConnectionState,
1493 * connect-timestamp [2] BACnetDateTime,
1494 * disconnect-timestamp [3] BACnetDateTime,
1495 * peer-address [4] BACnetHostNPort,
1496 * peer-vmac [5] OCTET STRING (SIZE(6))
1497 * peer-uuid [6] OCTET STRING (SIZE(16))
1498 * error [7] Error OPTIONAL
1499 * error-details [8] CharacterString OPTIONAL
1501 * @param tvb the tv buffer of the current data
1502 * @param pinfo the packet info of the current data
1503 * @param tree the tree to append this item to
1504 * @param offset the offset in the tvb
1505 * @return modified offset
1507 static unsigned
1508 fSCDirectConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1511 * BACnetSCHubConnection ::= SEQUENCE {
1512 * connection-state [0] BACnetSCConnectionState,
1513 * connect-timestamp [1] BACnetDateTime,
1514 * disconnect-timestamp [2] BACnetDateTime,
1515 * error [3] Error OPTIONAL
1516 * error-details [4] CharacterString OPTIONAL
1518 * @param tvb the tv buffer of the current data
1519 * @param pinfo the packet info of the current data
1520 * @param tree the tree to append this item to
1521 * @param offset the offset in the tvb
1522 * @return modified offset
1524 static unsigned
1525 fSCHubConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1528 * BACnetSCHubFunctionConnection ::= SEQUENCE {
1529 * connection-state [0] BACnetSCConnectionState,
1530 * connect-timestamp [1] BACnetDateTime,
1531 * disconnect-timestamp [2] BACnetDateTime,
1532 * peer-address [3] BACnetHostNPort,
1533 * peer-vmac [4] OCTET STRING (SIZE(6))
1534 * peer-uuid [5] OCTET STRING (SIZE(16))
1535 * error [6] Error OPTIONAL
1536 * error-details [7] CharacterString OPTIONAL
1538 * @param tvb the tv buffer of the current data
1539 * @param pinfo the packet info of the current data
1540 * @param tree the tree to append this item to
1541 * @param offset the offset in the tvb
1542 * @return modified offset
1544 static unsigned
1545 fSCHubFunctionConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1548 * BACnetWeeklySchedule ::= SEQUENCE {
1549 * week-schedule SENQUENCE SIZE (7) OF BACnetDailySchedule
1551 * @param tvb the tv buffer of the current data
1552 * @param pinfo the packet info of the current data
1553 * @param tree the tree to append this item to
1554 * @param offset the offset in the tvb
1555 * @return modified offset
1557 static unsigned
1558 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1561 * BACnetDateRange ::= SEQUENCE {
1562 * StartDate Date,
1563 * EndDate Date
1565 * @param tvb the tv buffer of the current data
1566 * @param pinfo the packet info of the current data
1567 * @param tree the tree to append this item to
1568 * @param offset the offset in the tvb
1569 * @return modified offset
1571 static unsigned
1572 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1575 * BACnetDateTime ::= SEQUENCE {
1576 * date Date,
1577 * time Time
1579 * @param tvb the tv buffer of the current data
1580 * @param pinfo the packet info of the current data
1581 * @param tree the tree to append this item to
1582 * @param offset the offset in the tvb
1583 * @param label the label of this item
1584 * @return modified offset
1586 static unsigned
1587 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
1590 * BACnetDestination ::= SEQUENCE {
1591 * validDays BACnetDaysOfWeek,
1592 * fromTime Time,
1593 * toTime Time,
1594 * recipient BACnetRecipient,
1595 * processIdentifier Unsigned32,
1596 * issueConfirmedNotifications BOOLEAN,
1597 * transitions BACnetEventTransitionBits
1599 * @param tvb the tv buffer of the current data
1600 * @param pinfo the packet info of the current data
1601 * @param tree the tree to append this item to
1602 * @param offset the offset in the tvb
1603 * @return modified offset
1605 static unsigned
1606 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1609 * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1610 * objectIdentifier [0] BACnetObjectIdentifier,
1611 * propertyIdentifier [1] BACnetPropertyIdentifier,
1612 * propertyArrayIndex [2] Unsigend OPTIONAL,
1613 * deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
1615 * @param tvb the tv buffer of the current data
1616 * @param pinfo the packet info of the current data
1617 * @param tree the tree to append this item to
1618 * @param offset the offset in the tvb
1619 * @return modified offset
1621 static unsigned
1622 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1625 * BACnetObjectPropertyReference ::= SEQUENCE {
1626 * objectIdentifier [0] BACnetObjectIdentifier,
1627 * propertyIdentifier [1] BACnetPropertyIdentifier,
1628 * propertyArrayIndex [2] Unsigend OPTIONAL,
1630 * @param tvb the tv buffer of the current data
1631 * @param pinfo the packet info of the current data
1632 * @param tree the tree to append this item to
1633 * @param offset the offset in the tvb
1634 * @return modified offset
1636 static unsigned
1637 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1640 * BACnetDeviceObjectReference ::= SEQUENCE {
1641 * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
1642 * objectIdentifier [1] BACnetObjectIdentifier
1644 * @param tvb the tv buffer of the current data
1645 * @param pinfo the packet info of the current data
1646 * @param tree the tree to append this item to
1647 * @param offset the offset in the tvb
1648 * @return modified offset
1650 static unsigned
1651 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1654 * BACnetEventParameter ::= CHOICE {
1655 * change-of-bitstring [0] SEQUENCE {
1656 * time-delay [0] Unsigned,
1657 * bitmask [1] BIT STRING,
1658 * list-of-bitstring-values [2] SEQUENCE OF BIT STRING
1659 * },
1660 * change-of-state [1] SEQUENCE {
1661 * time-delay [0] Unsigned,
1662 * list-of-values [1] SEQUENCE OF BACnetPropertyStates
1663 * },
1664 * change-of-value [2] SEQUENCE {
1665 * time-delay [0] Unsigned,
1666 * cov-criteria [1] CHOICE {
1667 * bitmask [0] BIT STRING,
1668 * referenced-property-increment [1] REAL
1670 * },
1671 * command-failure [3] SEQUENCE {
1672 * time-delay [0] Unsigned,
1673 * feedback-property-reference [1] BACnetDeviceObjectPropertyReference
1674 * },
1675 * floating-limit [4] SEQUENCE {
1676 * time-delay [0] Unsigned,
1677 * setpoint-reference [1] BACnetDeviceObjectPropertyReference,
1678 * low-diff-limit [2] REAL,
1679 * high-diff-limit [3] REAL,
1680 * deadband [4] REAL
1681 * },
1682 * out-of-range [5] SEQUENCE {
1683 * time-delay [0] Unsigned,
1684 * low-limit [1] REAL,
1685 * high-limit [2] REAL,
1686 * deadband [3] REAL
1687 * },
1688 * -- context tag 7 is deprecated
1689 * change-of-life-safety [8] SEQUENCE {
1690 * time-delay [0] Unsigned,
1691 * list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1692 * list-of-alarm-values [2] SEQUENCE OF BACnetLifeSafetyState,
1693 * mode-property-reference [3] BACnetDeviceObjectPropertyReference
1694 * },
1695 * extended [9] SEQUENCE {
1696 * vendor-id [0] Unsigned16,
1697 * extended-event-type [1] Unsigned,
1698 * parameters [2] SEQUENCE OF CHOICE {
1699 * null NULL,
1700 * real REAL,
1701 * integer Unsigned,
1702 * boolean BOOLEAN,
1703 * double Double,
1704 * octet OCTET STRING,
1705 * bitstring BIT STRING,
1706 * enum ENUMERATED,
1707 * reference [0] BACnetDeviceObjectPropertyReference
1709 * },
1710 * buffer-ready [10] SEQUENCE {
1711 * notification-threshold [0] Unsigned,
1712 * previous-notification-count [1] Unsigned32
1713 * },
1714 * unsigned-range [11] SEQUENCE {
1715 * time-delay [0] Unsigned,
1716 * low-limit [1] Unsigned,
1717 * high-limit [2] Unsigned,
1719 * -- context tag 12 is reserved for future addenda
1720 * access-event [13] SEQUENCE {
1721 * list-of-access-events [0] SEQUENCE OF BACnetAccessEvent,
1722 * access-event-time-reference [1] BACnetDeviceObjectPropertyReference
1724 * double-out-of-range [14] SEQUENCE {
1725 * time-delay [0] Unsigned,
1726 * low-limit [1] Double,
1727 * high-limit [2] Double,
1728 * deadband [3] Double
1730 * signed-out-of-range [15] SEQUENCE {
1731 * time-delay [0] Unsigned,
1732 * low-limit [1] INTEGER,
1733 * high-limit [2] INTEGER,
1734 * deadband [3] Unsigned
1736 * unsigned-out-of-range [16] SEQUENCE {
1737 * time-delay [0] Unsigned,
1738 * low-limit [1] Unsigned,
1739 * high-limit [2] Unsigned,
1740 * deadband [3] Unsigned
1742 * change-of-characterstring [17] SEQUENCE {
1743 * time-delay [0] Unsigned,
1744 * list-of-alarm-values [1] SEQUENCE OF CharacterString,
1746 * change-of-status-flags [18] SEQUENCE {
1747 * time-delay [0] Unsigned,
1748 * selected-flags [1] BACnetStatusFlags
1751 * @param tvb the tv buffer of the current data
1752 * @param tree the tree to append this item to
1753 * @param offset the offset in the tvb
1754 * @return modified offset
1756 static unsigned
1757 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1762 * BACnetLogRecord ::= SEQUENCE {
1763 * timestamp [0] BACnetDateTime,
1764 * logDatum [1] CHOICE {
1765 * log-status [0] BACnetLogStatus,
1766 * boolean-value [1] BOOLEAN,
1767 * real-value [2] REAL,
1768 * enum-value [3] ENUMERATED, -- Optionally limited to 32 bits
1769 * unsigned-value [4] Unsigned, -- Optionally limited to 32 bits
1770 * signed-value [5] INTEGER, -- Optionally limited to 32 bits
1771 * bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1772 * null-value [7] NULL,
1773 * failure [8] Error,
1774 * time-change [9] REAL,
1775 * any-value [10] ABSTRACT-SYNTAX.&Type -- Optional
1777 * statusFlags [2] BACnetStatusFlags OPTIONAL
1779 * @param tvb the tv buffer of the current data
1780 * @param pinfo the packet info of the current data
1781 * @param tree the tree to append this item to
1782 * @param offset the offset in the tvb
1783 * @return modified offset
1785 static unsigned
1786 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1789 * BACnetEventLogRecord ::= SEQUENCE {
1790 * timestamp [0] BACnetDateTime,
1791 * logDatum [1] CHOICE {
1792 * log-status [0] BACnetLogStatus,
1793 * notification [1] ConfirmedEventNotification-Request,
1794 * time-change [2] REAL,
1797 * @param tvb the tv buffer of the current data
1798 * @param pinfo the packet info of the current data
1799 * @param tree the tree to append this item to
1800 * @param offset the offset in the tvb
1801 * @return modified offset
1803 static unsigned
1804 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1806 static unsigned
1807 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1810 * BACnetNotificationParameters ::= CHOICE {
1811 * change-of-bitstring [0] SEQUENCE {
1812 * referenced-bitstring [0] BIT STRING,
1813 * status-flags [1] BACnetStatusFlags
1814 * },
1815 * change-of-state [1] SEQUENCE {
1816 * new-state [0] BACnetPropertyStatus,
1817 * status-flags [1] BACnetStatusFlags
1818 * },
1819 * change-of-value [2] SEQUENCE {
1820 * new-value [0] CHOICE {
1821 * changed-bits [0] BIT STRING,
1822 * changed-value [1] REAL
1823 * },
1824 * status-flags [1] BACnetStatusFlags
1825 * },
1826 * command-failure [3] SEQUENCE {
1827 * command-value [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1828 * status-flags [1] BACnetStatusFlags
1829 * feedback-value [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1830 * },
1831 * floating-limit [4] SEQUENCE {
1832 * reference-value [0] REAL,
1833 * status-flags [1] BACnetStatusFlags
1834 * setpoint-value [2] REAL,
1835 * error-limit [3] REAL
1836 * },
1837 * out-of-range [5] SEQUENCE {
1838 * exceeding-value [0] REAL,
1839 * status-flags [1] BACnetStatusFlags
1840 * deadband [2] REAL,
1841 * exceeded-limit [3] REAL
1842 * },
1843 * complex-event-type [6] SEQUENCE OF BACnetPropertyValue,
1844 * -- complex tag 7 is deprecated
1845 * change-of-life-safety [8] SEQUENCE {
1846 * new-state [0] BACnetLifeSafetyState,
1847 * new-mode [1] BACnetLifeSafetyState
1848 * status-flags [2] BACnetStatusFlags,
1849 * operation-expected [3] BACnetLifeSafetyOperation
1850 * },
1851 * extended [9] SEQUENCE {
1852 * vendor-id [0] Unsigned16,
1853 * extended-event-type [1] Unsigned,
1854 * parameters [2] SEQUENCE OF CHOICE {
1855 * null NULL,
1856 * real REAL,
1857 * integer Unsigned,
1858 * boolean BOOLEAN,
1859 * double Double,
1860 * octet OCTET STRING,
1861 * bitstring BIT STRING,
1862 * enum ENUMERATED,
1863 * propertyValue [0] BACnetDeviceObjectPropertyValue
1865 * },
1866 * buffer-ready [10] SEQUENCE {
1867 * buffer-property [0] BACnetDeviceObjectPropertyReference,
1868 * previous-notification[1] Unsigned32,
1869 * current-notification [2] BACneUnsigned32tDateTime
1870 * },
1871 * unsigned-range [11] SEQUENCE {
1872 * exceeding-value [0] Unsigned,
1873 * status-flags [1] BACnetStatusFlags,
1874 * exceeded-limit [2] Unsigned
1875 * },
1876 * -- context tag 12 is reserved for future addenda
1877 * access-event [13] SEQUENCE {
1878 * access-event [0] BACnetAccessEvent,
1879 * status-flags [1] BACnetStatusFlags,
1880 * access-event-tag [2] Unsigned,
1881 * access-event-time [3] BACnetTimeStamp,
1882 * access-credential [4] BACnetDeviceObjectReference,
1883 * authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1884 * },
1885 * double-out-of-range [14] SEQUENCE {
1886 * exceeding-value [0] Double,
1887 * status-flags [1] BACnetStatusFlags
1888 * deadband [2] Double,
1889 * exceeded-limit [3] Double
1890 * },
1891 * signed-out-of-range [15] SEQUENCE {
1892 * exceeding-value [0] INTEGER,
1893 * status-flags [1] BACnetStatusFlags
1894 * deadband [2] Unsigned,
1895 * exceeded-limit [3] INTEGER
1896 * },
1897 * unsigned-out-of-range [16] SEQUENCE {
1898 * exceeding-value [0] Unsigned,
1899 * status-flags [1] BACnetStatusFlags
1900 * deadband [2] Unsigned,
1901 * exceeded-limit [3] Unsigned
1902 * },
1903 * change-of-characterstring [17] SEQUENCE {
1904 * changed-value [0] CharacterString,
1905 * status-flags [1] BACnetStatusFlags
1906 * alarm-value [2] CharacterString
1907 * },
1908 * change-of-status-flags [18] SEQUENCE {
1909 * present-value [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1910 * -- depends on referenced property
1911 * referenced-flags [1] BACnetStatusFlags
1912 * },
1914 * @param tvb the tv buffer of the current data
1915 * @param pinfo the packet info of the current data
1916 * @param tree the tree to append this item to
1917 * @param offset the offset in the tvb
1918 * @return modified offset
1920 static unsigned
1921 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1924 * BACnetObjectPropertyReference ::= SEQUENCE {
1925 * objectIdentifier [0] BACnetObjectIdentifier,
1926 * propertyIdentifier [1] BACnetPropertyIdentifier,
1927 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1929 * @param tvb the tv buffer of the current data
1930 * @param pinfo the packet info of the current data
1931 * @param tree the tree to append this item to
1932 * @param offset the offset in the tvb
1933 * @return modified offset
1935 static unsigned
1936 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1938 #if 0
1940 * BACnetObjectPropertyValue ::= SEQUENCE {
1941 * objectIdentifier [0] BACnetObjectIdentifier,
1942 * propertyIdentifier [1] BACnetPropertyIdentifier,
1943 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1944 * -- if omitted with an array the entire array is referenced
1945 * value [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1946 * priority [4] Unsigned (1..16) OPTIONAL
1948 * @param tvb the tv buffer of the current data
1949 * @param tree the tree to append this item to
1950 * @param offset the offset in the tvb
1951 * @return modified offset
1953 static unsigned
1954 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
1955 #endif
1958 * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1959 * @param tvb the tv buffer of the current data
1960 * @param pinfo the packet info of the current data
1961 * @param tree the tree to append this item to
1962 * @param offset the offset in the tvb
1963 * @return modified offset
1965 static unsigned
1966 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1968 static unsigned
1969 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset, uint8_t list);
1972 * BACnetPropertyReference ::= SEQUENCE {
1973 * propertyIdentifier [0] BACnetPropertyIdentifier,
1974 * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
1976 * @param tvb the tv buffer of the current data
1977 * @param pinfo the packet info of the current data
1978 * @param tree the tree to append this item to
1979 * @param offset the offset in the tvb
1980 * @return modified offset
1982 static unsigned
1983 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t list);
1985 static unsigned
1986 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1988 static unsigned
1989 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
1992 * BACnetPropertyValue ::= SEQUENCE {
1993 * PropertyIdentifier [0] BACnetPropertyIdentifier,
1994 * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1995 * -- if omitted with an array the entire array is referenced
1996 * value [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1997 * priority [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1999 * @param tvb the tv buffer of the current data
2000 * @param pinfo the packet info of the current data
2001 * @param tree the tree to append this item to
2002 * @param offset the offset in the tvb
2003 * @return modified offset
2005 static unsigned
2006 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2008 static unsigned
2009 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset);
2012 * BACnet Application PDUs chapter 21
2013 * BACnetRecipient::= CHOICE {
2014 * device [0] BACnetObjectIdentifier
2015 * address [1] BACnetAddress
2017 * @param tvb the tv buffer of the current data
2018 * @param pinfo the packet info of the current data
2019 * @param tree the tree to append this item to
2020 * @param offset the offset in the tvb
2021 * @return modified offset
2023 static unsigned
2024 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2027 * BACnet Application PDUs chapter 21
2028 * BACnetRecipientProcess::= SEQUENCE {
2029 * recipient [0] BACnetRecipient
2030 * processID [1] Unsigned32
2032 * @param tvb the tv buffer of the current data
2033 * @param pinfo the packet info of the current data
2034 * @param tree the tree to append this item to
2035 * @param offset the offset in the tvb
2036 * @return modified offset
2038 static unsigned
2039 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2041 static unsigned
2042 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2044 #if 0
2046 * BACnetSessionKey ::= SEQUENCE {
2047 * sessionKey OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
2048 * peerAddress BACnetAddress
2050 * @param tvb the tv buffer of the current data
2051 * @param tree the tree to append this item to
2052 * @param offset the offset in the tvb
2053 * @return modified offset
2054 * @todo check if checksum is displayed correctly
2056 static unsigned
2057 fSessionKey(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
2058 #endif
2061 * BACnetSpecialEvent ::= SEQUENCE {
2062 * period CHOICE {
2063 * calendarEntry [0] BACnetCalendarEntry,
2064 * calendarRefernce [1] BACnetObjectIdentifier
2065 * },
2066 * listOfTimeValues [2] SEQUENCE OF BACnetTimeValue,
2067 * eventPriority [3] Unsigned (1..16)
2069 * @param tvb the tv buffer of the current data
2070 * @param pinfo the packet info of the current data
2071 * @param tree the tree to append this item to
2072 * @param offset the offset in the tvb
2073 * @return modified offset
2075 static unsigned
2076 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2079 * BACnetTimeStamp ::= CHOICE {
2080 * time [0] Time,
2081 * sequenceNumber [1] Unsigned (0..65535),
2082 * dateTime [2] BACnetDateTime
2084 * @param tvb the tv buffer of the current data
2085 * @param pinfo the packet info of the current data
2086 * @param tree the tree to append this item to
2087 * @param offset the offset in the tvb
2088 * @param label the label of this item
2089 * @return modified offset
2091 static unsigned
2092 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2094 static unsigned
2095 fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2098 * BACnetTimeValue ::= SEQUENCE {
2099 * time Time,
2100 * value ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2102 * @param tvb the tv buffer of the current data
2103 * @param pinfo the packet info of the current data
2104 * @param tree the tree to append this item to
2105 * @param offset the offset in the tvb
2106 * @return modified offset
2108 static unsigned
2109 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2111 #if 0
2113 * BACnetVTSession ::= SEQUENCE {
2114 * local-vtSessionID Unsigned8,
2115 * remote-vtSessionID Unsigned8,
2116 * remote-vtAddress BACnetAddress
2118 * @param tvb the tv buffer of the current data
2119 * @param tree the tree to append this item to
2120 * @param offset the offset in the tvb
2121 * @return modified offset
2123 static unsigned
2124 fVTSession(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
2125 #endif
2128 * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2129 * -- first octet month (1..12) January = 1, X'FF' = any month
2130 * -- second octet weekOfMonth where: 1 = days numbered 1-7
2131 * -- 2 = days numbered 8-14
2132 * -- 3 = days numbered 15-21
2133 * -- 4 = days numbered 22-28
2134 * -- 5 = days numbered 29-31
2135 * -- 6 = last 7 days of this month
2136 * -- X'FF' = any week of this month
2137 * -- third octet dayOfWeek (1..7) where 1 = Monday
2138 * -- 7 = Sunday
2139 * -- X'FF' = any day of week
2140 * @param tvb the tv buffer of the current data
2141 * @param pinfo the packet info of the current data
2142 * @param tree the tree to append this item to
2143 * @param offset the offset in the tvb
2144 * @return modified offset
2146 static unsigned
2147 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2150 * ReadAccessResult ::= SEQUENCE {
2151 * objectIdentifier [0] BACnetObjectIdentifier,
2152 * listOfResults [1] SEQUENCE OF SEQUENCE {
2153 * propertyIdentifier [2] BACnetPropertyIdentifier,
2154 * propertyArrayIndex [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2155 * readResult CHOICE {
2156 * propertyValue [4] ABSTRACT-SYNTAX.&Type,
2157 * propertyAccessError [5] Error
2159 * } OPTIONAL
2161 * @param tvb the tv buffer of the current data
2162 * @param pinfo the packet info of the current data
2163 * @param tree the tree to append this item to
2164 * @param offset the offset in the tvb
2165 * @return modified offset
2167 static unsigned
2168 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2171 * ReadAccessSpecification ::= SEQUENCE {
2172 * objectIdentifier [0] BACnetObjectIdentifier,
2173 * listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2175 * @param tvb the tv buffer of the current data
2176 * @param pinfo the packet info of the current data
2177 * @param subtree the subtree to append this item to
2178 * @param offset the offset in the tvb
2179 * @return modified offset
2181 static unsigned
2182 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2185 * WriteAccessSpecification ::= SEQUENCE {
2186 * objectIdentifier [0] BACnetObjectIdentifier,
2187 * listOfProperty [1] SEQUENCE OF BACnetPropertyValue
2189 * @param tvb the tv buffer of the current data
2190 * @param pinfo the packet info of the current data
2191 * @param subtree the sub tree to append this item to
2192 * @param offset the offset in the tvb
2193 * @return modified offset
2195 static unsigned
2196 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2199 /********************************************************* Helper functions *******************************************/
2202 * extracts the tag number from the tag header.
2203 * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2204 * @param offset the offset in the tvb in actual tvb
2205 * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2207 static unsigned
2208 fTagNo(tvbuff_t *tvb, unsigned offset);
2211 * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
2212 * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2213 * @param pinfo the packet info of the current data = packet info
2214 * @param offset the offset in the tvb = offset in actual tvb
2215 * @return tag_no BACnet 20.2.1.2 Tag Number
2216 * @return class_tag BACnet 20.2.1.1 Class
2217 * @return lvt BACnet 20.2.1.3 Length/Value/Type
2218 * @return offs = length of this header
2221 static unsigned
2222 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, uint8_t *tag_no, uint8_t* class_tag, uint32_t *lvt);
2226 * adds processID with max 32Bit unsigned Integer Value to tree
2227 * @param tvb the tv buffer of the current data
2228 * @param pinfo the packet info of the current data
2229 * @param tree the tree to append this item to
2230 * @param offset the offset in the tvb
2231 * @return modified offset
2233 static unsigned
2234 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2237 * adds present value to the tree
2238 * @param tvb the tv buffer of the current data
2239 * @param pinfo the packet info of the current data
2240 * @param tree the tree to append this item to
2241 * @param offset the offset in the tvb
2242 * @param vs enum of string values when applicable
2243 * @param split_val enum index
2244 * @param type present value datatype enum
2245 * @return modified offset
2247 static unsigned
2248 fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const value_string *vs, uint32_t split_val, BacappPresentValueType type);
2251 * adds event type to the tree
2252 * @param tvb the tv buffer of the current data
2253 * @param pinfo the packet info of the current data
2254 * @param tree the tree to append this item to
2255 * @param offset the offset in the tvb
2256 * @return modified offset
2258 static unsigned
2259 fEventType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2262 * adds notify type to the tree
2263 * @param tvb the tv buffer of the current data
2264 * @param pinfo the packet info of the current data
2265 * @param tree the tree to append this item to
2266 * @param offset the offset in the tvb
2267 * @return modified offset
2269 static unsigned
2270 fNotifyType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2273 * adds next_state with max 32Bit unsigned Integer Value to tree
2274 * @param tvb the tv buffer of the current data
2275 * @param pinfo the packet info of the current data
2276 * @param tree the tree to append this item to
2277 * @param offset the offset in the tvb
2278 * @return modified offset
2280 static unsigned
2281 fToState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2284 * adds from_state with max 32Bit unsigned Integer Value to tree
2285 * @param tvb the tv buffer of the current data
2286 * @param pinfo the packet info of the current data
2287 * @param tree the tree to append this item to
2288 * @param offset the offset in the tvb
2289 * @return modified offset
2291 static unsigned
2292 fFromState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2295 * adds object_name string value to tree
2296 * @param tvb the tv buffer of the current data
2297 * @param pinfo the packet info of the current data
2298 * @param tree the tree to append this item to
2299 * @param offset the offset in the tvb
2300 * @return modified offset
2302 static unsigned
2303 fObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2306 * wrapper function for fCharacterStringBase
2307 * @param tvb the tv buffer of the current data
2308 * @param pinfo the packet info of the current data
2309 * @param tree the tree to append this item to
2310 * @param offset the offset in the tvb
2311 * @return modified offset
2313 static unsigned
2314 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2317 * adds string value to tree
2318 * @param tvb the tv buffer of the current data
2319 * @param pinfo the packet info of the current data
2320 * @param tree the tree to append this item to
2321 * @param offset the offset in the tvb
2322 * @param present_val_dissect exposes string as present_value property
2323 * @param object_name_dissect exposes string as object_name property
2324 * @return modified offset
2326 static unsigned
2327 fCharacterStringBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2328 bool present_val_dissect, bool object_name_dissect);
2331 * adds timeSpan with max 32Bit unsigned Integer Value to tree
2332 * @param tvb the tv buffer of the current data
2333 * @param pinfo the packet info of the current data
2334 * @param tree the tree to append this item to
2335 * @param offset the offset in the tvb
2336 * @return modified offset
2338 static unsigned
2339 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2342 * BACnet Application PDUs chapter 21
2343 * BACnetPropertyIdentifier::= ENUMERATED {
2344 * @see bacapp_property_identifier
2346 * @param tvb the tv buffer of the current data
2347 * @param pinfo the packet info of the current data
2348 * @param tree the tree to append this item to
2349 * @param offset the offset in the tvb
2350 * @return modified offset
2352 static unsigned
2353 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2356 * BACnet Application PDUs chapter 21
2357 * BACnetPropertyArrayIndex::= ENUMERATED {
2358 * @see bacapp_property_array_index
2360 * @param tvb the tv buffer of the current data
2361 * @param pinfo the packet info of the current data
2362 * @param tree the tree to append this item to
2363 * @param offset the offset in the tvb
2364 * @return modified offset
2366 static unsigned
2367 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2370 * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2371 * objectIdentifier [0] BACnetObjectIdentifier,
2372 * eventState [1] BACnetEventState,
2373 * acknowledgedTransitions [2] BACnetEventTransitionBits,
2374 * eventTimeStamps [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2375 * notifyType [4] BACnetNotifyType,
2376 * eventEnable [5] BACnetEventTransitionBits,
2377 * eventPriorities [6] SEQUENCE SIZE (3) OF Unsigned
2379 * @param tvb the tv buffer of the current data
2380 * @param pinfo the packet info of the current data
2381 * @param tree the tree to append this item to
2382 * @param offset the offset in the tvb
2383 * @return modified offset
2385 static unsigned
2386 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2389 * SelectionCriteria ::= SEQUENCE {
2390 * propertyIdentifier [0] BACnetPropertyIdentifier,
2391 * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2392 * relationSpecifier [2] ENUMERATED { bacapp_relationSpecifier },
2393 * comparisonValue [3] ABSTRACT-SYNTAX.&Type
2395 * @param tvb the tv buffer of the current data
2396 * @param pinfo the packet info of the current data
2397 * @param tree the tree to append this item to
2398 * @param offset the offset in the tvb
2399 * @return modified offset
2401 static unsigned
2402 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2405 * objectSelectionCriteria ::= SEQUENCE {
2406 * selectionLogic [0] ENUMERATED { bacapp_selectionLogic },
2407 * listOfSelectionCriteria [1] SelectionCriteria
2409 * @param tvb the tv buffer of the current data
2410 * @param pinfo the packet info of the current data
2411 * @param subtree the sub tree to append this item to
2412 * @param offset the offset in the tvb
2413 * @return modified offset
2415 static unsigned
2416 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset);
2419 * BACnet-Error ::= SEQUENCE {
2420 * error-class ENUMERATED {},
2421 * error-code ENUMERATED {}
2424 * @param tvb the tv buffer of the current data
2425 * @param pinfo the packet info of the current data
2426 * @param tree the tree to append this item to
2427 * @param offset the offset in the tvb
2428 * @return modified offset
2430 static unsigned
2431 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2434 * Adds error-code from BACnet-Error to the tree
2435 * @param tvb the tv buffer of the current data
2436 * @param pinfo the packet info of the current data
2437 * @param tree the tree to append this item to
2438 * @param offset the offset in the tvb
2439 * @return modified offset
2441 static unsigned
2442 fErrorCode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2445 * Adds error-class from BACnet-Error to the tree
2446 * @param tvb the tv buffer of the current data
2447 * @param pinfo the packet info of the current data
2448 * @param tree the tree to append this item to
2449 * @param offset the offset in the tvb
2450 * @return modified offset
2452 static unsigned
2453 fErrorClass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2456 * Generic handler for context tagged values. Mostly for handling
2457 * vendor-defined properties and services.
2458 * @param tvb the tv buffer of the current data
2459 * @param pinfo the packet info of the current data
2460 * @param tree the tree to append this item to
2461 * @param offset the offset in the tvb
2462 * @return modified offset
2463 * @todo beautify this ugly construct
2465 static unsigned
2466 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2469 * realizes some ABSTRACT-SYNTAX.&Type
2470 * @param tvb the tv buffer of the current data
2471 * @param pinfo the packet info of the current data
2472 * @param tree the tree to append this item to
2473 * @param offset the offset in the tvb
2474 * @return modified offset
2475 * @todo beautify this ugly construct
2477 static unsigned
2478 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2481 static unsigned
2482 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2483 const value_string *src);
2485 static unsigned
2486 fBitStringTagVSBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
2487 const value_string *src, bool present_val_dissect);
2489 static unsigned
2490 fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2492 static unsigned
2493 fEventNotificationSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2495 static unsigned
2496 fLightingCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2498 static unsigned
2499 fColorCommand(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable);
2501 static unsigned
2502 fXyColor(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable);
2504 static unsigned
2505 fTimerStateChangeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2507 static unsigned
2508 fHostNPort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2510 static unsigned
2511 fBDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2513 static unsigned
2514 fFDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable);
2516 static unsigned
2517 fRouterEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2519 static unsigned
2520 fVMACEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2522 static unsigned
2523 fValueSource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2525 static unsigned
2526 fAssignedLandingCalls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2528 static unsigned
2529 fLandingCallStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2531 static unsigned
2532 fLandingDoorStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2534 static unsigned
2535 fCOVMultipleSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2537 static unsigned
2538 fNameValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2540 static unsigned
2541 fNameValueCollection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2543 static unsigned
2544 fAuthenticationFactor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2546 static unsigned
2547 fAuthenticationFactorFormat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2549 static unsigned
2550 fAuthenticationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2552 static unsigned
2553 fAccessRule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2555 static unsigned
2556 fChannelValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label);
2558 static unsigned
2559 fPropertyAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2561 static unsigned
2562 fNetworkSecurityPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2564 static unsigned
2565 fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2567 static unsigned
2568 fAuditLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2570 static unsigned
2571 fStageLimitValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2573 static unsigned
2574 fObjectSelector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset);
2578 * register_bacapp
2580 void
2581 proto_register_bacapp(void);
2583 /* <<<< formerly bacapp.h */
2585 /* reassembly table for segmented messages */
2586 static reassembly_table msg_reassembly_table;
2588 /* some necessary forward function prototypes */
2589 static unsigned
2590 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
2591 const char *label, const value_string *vs);
2593 static const char *bacapp_unknown_service_str = "unknown service"; /* Usage: no format specifiers */
2594 static const char ASHRAE_Reserved_Fmt[] = "(%d) Reserved for Use by ASHRAE";
2595 static const char Vendor_Proprietary_Fmt[] = "(%d) Vendor Proprietary Value";
2597 static const value_string
2598 BACnetTypeName[] = {
2599 { 0, "Confirmed-REQ"},
2600 { 1, "Unconfirmed-REQ"},
2601 { 2, "Simple-ACK"},
2602 { 3, "Complex-ACK"},
2603 { 4, "Segment-ACK"},
2604 { 5, "Error"},
2605 { 6, "Reject"},
2606 { 7, "Abort"},
2607 { 0, NULL }
2610 static const true_false_string segments_follow = {
2611 "Segmented Request",
2612 "Unsegmented Request"
2615 static const true_false_string more_follow = {
2616 "More Segments Follow",
2617 "No More Segments Follow"
2620 static const true_false_string segmented_accept = {
2621 "Segmented Response accepted",
2622 "Segmented Response not accepted"
2625 static const true_false_string
2626 BACnetTagClass = {
2627 "Context Specific Tag",
2628 "Application Tag"
2631 static const value_string
2632 BACnetMaxSegmentsAccepted [] = {
2633 { 0, "Unspecified"},
2634 { 1, "2 segments"},
2635 { 2, "4 segments"},
2636 { 3, "8 segments"},
2637 { 4, "16 segments"},
2638 { 5, "32 segments"},
2639 { 6, "64 segments"},
2640 { 7, "Greater than 64 segments"},
2641 { 0, NULL }
2644 static const value_string
2645 BACnetMaxAPDULengthAccepted [] = {
2646 { 0, "Up to MinimumMessageSize (50 octets)"},
2647 { 1, "Up to 128 octets"},
2648 { 2, "Up to 206 octets (fits in a LonTalk frame)"},
2649 { 3, "Up to 480 octets (fits in an ARCNET frame)"},
2650 { 4, "Up to 1024 octets"},
2651 { 5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2652 { 6, "reserved by ASHRAE"},
2653 { 7, "reserved by ASHRAE"},
2654 { 8, "reserved by ASHRAE"},
2655 { 9, "reserved by ASHRAE"},
2656 { 10, "reserved by ASHRAE"},
2657 { 11, "reserved by ASHRAE"},
2658 { 12, "reserved by ASHRAE"},
2659 { 13, "reserved by ASHRAE"},
2660 { 14, "reserved by ASHRAE"},
2661 { 15, "reserved by ASHRAE"},
2662 { 0, NULL}
2665 static const value_string
2666 BACnetRejectReason [] = {
2667 { 0, "other"},
2668 { 1, "buffer-overflow"},
2669 { 2, "inconsistent-parameters"},
2670 { 3, "invalid-parameter-data-type"},
2671 { 4, "invalid-tag"},
2672 { 5, "missing-required-parameter"},
2673 { 6, "parameter-out-of-range"},
2674 { 7, "too-many-arguments"},
2675 { 8, "undefined-enumeration"},
2676 { 9, "unrecognized-service"},
2677 { 0, NULL}
2680 static const value_string
2681 BACnetRestartReason [] = {
2682 { 0, "unknown"},
2683 { 1, "coldstart"},
2684 { 2, "warmstart"},
2685 { 3, "detected-power-lost"},
2686 { 4, "detected-powered-off"},
2687 { 5, "hardware-watchdog"},
2688 { 6, "software-watchdog"},
2689 { 7, "suspended"},
2690 { 8, "activate-changes"},
2691 { 0, NULL}
2694 static const value_string
2695 BACnetApplicationTagNumber [] = {
2696 { 0, "Null"},
2697 { 1, "Boolean"},
2698 { 2, "Unsigned Integer"},
2699 { 3, "Signed Integer (2's complement notation)"},
2700 { 4, "Real (ANSI/IEE-754 floating point)"},
2701 { 5, "Double (ANSI/IEE-754 double precision floating point)"},
2702 { 6, "Octet String"},
2703 { 7, "Character String"},
2704 { 8, "Bit String"},
2705 { 9, "Enumerated"},
2706 { 10, "Date"},
2707 { 11, "Time"},
2708 { 12, "BACnetObjectIdentifier"},
2709 { 13, "reserved by ASHRAE"},
2710 { 14, "reserved by ASHRAE"},
2711 { 15, "reserved by ASHRAE"},
2712 { 0, NULL}
2715 static const value_string
2716 BACnetAction [] = {
2717 { 0, "direct"},
2718 { 1, "reverse"},
2719 { 0, NULL}
2722 static const value_string
2723 BACnetAccessEvent [] = {
2724 { 0, "none"},
2725 { 1, "granted"},
2726 { 2, "muster"},
2727 { 3, "passback-detected"},
2728 { 4, "duress"},
2729 { 5, "trace"},
2730 { 6, "lockout-max-attempts"},
2731 { 7, "lockout-other"},
2732 { 8, "lockout-relinquished"},
2733 { 9, "lockout-by-higher-priority"},
2734 { 10, "out-of-service"},
2735 { 11, "out-of-service-relinquished"},
2736 { 12, "accompaniment-by"},
2737 { 13, "authentication-factor-read"},
2738 { 14, "authorization-delayed"},
2739 { 15, "verification-required"},
2740 /* Enumerated values 128-511 are used for events
2741 * which indicate that access has been denied. */
2742 { 128, "denied-deny-all"},
2743 { 129, "denied-unknown-credential"},
2744 { 130, "denied-authentication-unavailable"},
2745 { 131, "denied-authentication-factor-timeout"},
2746 { 132, "denied-incorrect-authentication-factor"},
2747 { 133, "denied-zone-no-access-rights"},
2748 { 134, "denied-point-no-access-rights"},
2749 { 135, "denied-no-access-rights"},
2750 { 136, "denied-out-of-time-range"},
2751 { 137, "denied-threat-level"},
2752 { 138, "denied-passback"},
2753 { 139, "denied-unexpected-location-usage"},
2754 { 140, "denied-max-attempts"},
2755 { 141, "denied-lower-occupancy-limit"},
2756 { 142, "denied-upper-occupancy-limit"},
2757 { 143, "denied-authentication-factor-lost"},
2758 { 144, "denied-authentication-factor-stolen"},
2759 { 145, "denied-authentication-factor-damaged"},
2760 { 146, "denied-authentication-factor-destroyed"},
2761 { 147, "denied-authentication-factor-disabled"},
2762 { 148, "denied-authentication-factor-error"},
2763 { 149, "denied-credential-unassigned"},
2764 { 150, "denied-credential-not-provisioned"},
2765 { 151, "denied-credential-not-yet-active"},
2766 { 152, "denied-credential-expired"},
2767 { 153, "denied-credential-manual-disable"},
2768 { 154, "denied-credential-lockout"},
2769 { 155, "denied-credential-max-days"},
2770 { 156, "denied-credential-max-uses"},
2771 { 157, "denied-credential-inactivity"},
2772 { 158, "denied-credential-disabled"},
2773 { 159, "denied-no-accompaniment"},
2774 { 160, "denied-incorrect-accompaniment"},
2775 { 161, "denied-lockout"},
2776 { 162, "denied-verification-failed"},
2777 { 163, "denied-verification-timeout"},
2778 { 164, "denied-other"},
2779 { 0, NULL}
2780 /* Enumerated values 0-512 are reserved for definition by ASHRAE.
2781 Enumerated values 512-65535 may be used by others subject to
2782 procedures and constraints described in Clause 23. */
2785 static const value_string
2786 BACnetAccessZoneOccupancyState[] = {
2787 { 0, "normal"},
2788 { 1, "below-lower-limit"},
2789 { 2, "at-lower-limit"},
2790 { 3, "at-upper-limit"},
2791 { 4, "above-upper-limit"},
2792 { 5, "disabled"},
2793 { 6, "not-supported"},
2794 { 0, NULL}
2797 static const value_string
2798 BACnetAccessPassbackMode[] = {
2799 { 0, "passback-off" },
2800 { 1, "hard-passback" },
2801 { 2, "soft-passback" },
2802 { 0, NULL }
2805 static const value_string
2806 BACnetAccessCredentialDisableReason[] = {
2807 { 0, "disabled" },
2808 { 1, "disabled-needs-provisioning" },
2809 { 2, "disabled-unassigned" },
2810 { 3, "disabled-not-yet-active" },
2811 { 4, "disabled-expired" },
2812 { 5, "disabled-lockout" },
2813 { 6, "disabled-max-days" },
2814 { 7, "disabled-max-uses" },
2815 { 8, "disabled-inactivity" },
2816 { 9, "disabled-manual" },
2817 { 0, NULL }
2820 static const value_string
2821 BACnetAccessUserType[] = {
2822 { 0, "asset" },
2823 { 1, "group" },
2824 { 2, "person" },
2825 { 0, NULL }
2828 static const value_string
2829 BACnetWriteStatus[] = {
2830 { 0, "idle" },
2831 { 1, "in-progress" },
2832 { 2, "successful" },
2833 { 3, "failed" },
2834 { 0, NULL }
2837 static const value_string
2838 BACnetLightingTransition[] = {
2839 { 0, "none" },
2840 { 1, "fade" },
2841 { 2, "ramp" },
2842 { 0, NULL }
2845 static const value_string
2846 BACnetSecurityLevel[] = {
2847 { 0, "incapable" },
2848 { 1, "plain" },
2849 { 2, "signed" },
2850 { 3, "encrypted" },
2851 { 4, "signed-end-to-end" },
2852 { 5, "encrypted-end-to-end" },
2853 { 0, NULL }
2856 static const value_string
2857 BACnetAccessCredentialDisable[] = {
2858 { 0, "none" },
2859 { 1, "disable" },
2860 { 2, "disable-manual" },
2861 { 3, "disable-lockout" },
2862 { 0, NULL }
2865 static const value_string
2866 BACnetAuthenticationStatus[] = {
2867 { 0, "not-ready" },
2868 { 1, "ready" },
2869 { 2, "disabled" },
2870 { 3, "waiting-for-authentication-factor" },
2871 { 4, "waiting-for-accompaniment" },
2872 { 5, "waiting-for-verification" },
2873 { 6, "in-progress" },
2874 { 0, NULL }
2877 static const value_string
2878 BACnetAuthorizationMode[] = {
2879 { 0, "authorize" },
2880 { 1, "grant-active" },
2881 { 2, "deny-all" },
2882 { 3, "verification-required" },
2883 { 4, "authorization-delayed" },
2884 { 5, "none" },
2885 { 0, NULL }
2888 static const value_string
2889 BACnetAuthorizationExemption[] = {
2890 { 0, "passback" },
2891 { 1, "occupancy-check" },
2892 { 2, "access-rights" },
2893 { 3, "lockout" },
2894 { 4, "deny" },
2895 { 5, "verification" },
2896 { 6, "authorization-delay" },
2897 { 0, NULL }
2900 static const value_string
2901 BACnetLightingInProgress[] = {
2902 { 0, "idle" },
2903 { 1, "fade-active" },
2904 { 2, "ramp-active" },
2905 { 3, "not-controlled" },
2906 { 4, "other" },
2907 { 5, "trim-active" },
2908 { 0, NULL }
2911 static const value_string
2912 BACnetColorOperationInProgress[] = {
2913 { 0, "idle" },
2914 { 1, "fade-active" },
2915 { 2, "ramp-active" },
2916 { 3, "not-controlled" },
2917 { 4, "other" },
2918 { 0, NULL }
2921 static const value_string
2922 BACnetColorTransition[] = {
2923 { 0, "none" },
2924 { 1, "fade" },
2925 { 2, "ramp" },
2926 { 0, NULL }
2929 static const value_string
2930 BACnetBinaryLightingPV[] = {
2931 { 0, "off" },
2932 { 1, "on" },
2933 { 2, "warn" },
2934 { 3, "warn-off" },
2935 { 4, "warn-relinquish" },
2936 { 5, "stop" },
2937 { 0, NULL }
2940 static const value_string
2941 BACnetBackupState[] = {
2942 { 0, "idle"},
2943 { 1, "preparing-for-backup"},
2944 { 2, "preparing-for-restore"},
2945 { 3, "performing-a-backup"},
2946 { 4, "performing-a-restore"},
2947 { 5, "backup-failure"},
2948 { 6, "restore-failure"},
2949 { 0, NULL}
2952 static const value_string
2953 BACnetAcknowledgedTransitions[] = {
2954 { 0, "to-offnormal" },
2955 { 1, "to-fault" },
2956 { 2, "to-normal" },
2957 { 0, NULL }
2960 static const value_string
2961 BACnetFileAccessMethod [] = {
2962 { 0, "record-access"},
2963 { 1, "stream-access"},
2964 { 0, NULL}
2967 /* For some reason, BACnet defines the choice parameter
2968 in the file read and write services backwards from the
2969 BACnetFileAccessMethod enumeration.
2971 static const value_string
2972 BACnetFileAccessOption [] = {
2973 { 0, "stream access"},
2974 { 1, "record access"},
2975 { 0, NULL}
2978 static const value_string
2979 BACnetFileStartOption [] = {
2980 { 0, "File Start Position: "},
2981 { 1, "File Start Record: "},
2982 { 0, NULL}
2985 static const value_string
2986 BacnetFileRequestedCount [] = {
2987 { 0, "Requested Octet Count: "},
2988 { 1, "Requested Record Count: "},
2989 { 0, NULL}
2992 static const value_string
2993 BACnetFileWriteInfo [] = {
2994 { 0, "File Data: "},
2995 { 1, "Record Count: "},
2996 { 0, NULL}
2999 static const value_string
3000 BACnetAbortReason [] = {
3001 { 0, "other"},
3002 { 1, "buffer-overflow"},
3003 { 2, "invalid-apdu-in-this-state"},
3004 { 3, "preempted-by-higher-priority-task"},
3005 { 4, "segmentation-not-supported"},
3006 { 5, "security-error"},
3007 { 6, "insufficient-security"},
3008 { 7, "window-size-out-of-range"},
3009 { 8, "application-exceeded-reply-time"},
3010 { 9, "out-of-resources"},
3011 { 10, "tsm-timeout"},
3012 { 11, "apdu-too-long"},
3013 { 0, NULL}
3016 static const value_string
3017 BACnetIpMode [] = {
3018 { 0, "normal"},
3019 { 1, "foreign"},
3020 { 2, "bbmd"},
3021 { 0, NULL}
3024 static const value_string
3025 BACnetNetworkPortCommand [] = {
3026 { 0, "idle"},
3027 { 1, "discard-changes"},
3028 { 2, "renew-fd-registration"},
3029 { 3, "restart-slave-discovery"},
3030 { 4, "renew-dhcp"},
3031 { 5, "restart-autonegotiation"},
3032 { 6, "disconnect"},
3033 { 7, "restart-port"},
3034 { 8, "generate-csr-file"},
3035 { 9, "validate-changes"},
3036 { 0, NULL}
3039 static const value_string
3040 BACnetNetworkNumberQuality [] = {
3041 { 0, "unknown"},
3042 { 1, "learned"},
3043 { 2, "learned-configured"},
3044 { 3, "configured"},
3045 { 0, NULL}
3048 static const value_string
3049 BACnetNetworkType [] = {
3050 { 0, "ethernet" },
3051 { 1, "arcnet" },
3052 { 2, "mstp" },
3053 { 3, "ptp" },
3054 { 4, "lontalk" },
3055 { 5, "bacnet-ipv4" },
3056 { 6, "zigbee" },
3057 { 7, "virtual" },
3058 { 8, "non-bacnet" },
3059 { 9, "bacnet-ipv6" },
3060 {10, "serial" },
3061 {11, "secure-connect" },
3062 { 0, NULL}
3065 static const value_string
3066 BACnetSCConnectionState [] = {
3067 { 0, "not-connected" },
3068 { 1, "connected" },
3069 { 2, "disconnected-with-errors" },
3070 { 3, "failed-to-connect" },
3071 { 0, NULL}
3074 static const value_string
3075 BACnetSCHubConnectorState [] = {
3076 { 0, "no-hub-connection" },
3077 { 1, "connected-to-primary" },
3078 { 2, "connected-to-failover" },
3079 { 0, NULL}
3082 static const value_string
3083 BACnetLifeSafetyMode [] = {
3084 { 0, "off"},
3085 { 1, "on"},
3086 { 2, "test"},
3087 { 3, "manned"},
3088 { 4, "unmanned"},
3089 { 5, "armed"},
3090 { 6, "disarmed"},
3091 { 7, "prearmed"},
3092 { 8, "slow"},
3093 { 9, "fast"},
3094 { 10, "disconnected"},
3095 { 11, "enabled"},
3096 { 12, "disabled"},
3097 { 13, "atomic-release-disabled"},
3098 { 14, "default"},
3099 { 15, "activated-oeo-alarm"},
3100 { 16, "activated-oeo-evacuate"},
3101 { 17, "activated-oeo-phase1-recall"},
3102 { 18, "activated-oeo-unavailable"},
3103 { 19, "deactivated"},
3104 { 0, NULL}
3105 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3106 Enumerated values 256-65535 may be used by others subject to
3107 procedures and constraints described in Clause 23. */
3110 static const value_string
3111 BACnetLifeSafetyOperation [] = {
3112 { 0, "none"},
3113 { 1, "silence"},
3114 { 2, "silence-audible"},
3115 { 3, "silence-visual"},
3116 { 4, "reset"},
3117 { 5, "reset-alarm"},
3118 { 6, "reset-fault"},
3119 { 7, "unsilence"},
3120 { 8, "unsilence-audible"},
3121 { 9, "unsilence-visual"},
3122 { 0, NULL}
3123 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3124 Enumerated values 64-65535 may be used by others subject to
3125 procedures and constraints described in Clause 23. */
3128 static const value_string
3129 BACnetLifeSafetyState [] = {
3130 { 0, "quiet"},
3131 { 1, "pre-alarm"},
3132 { 2, "alarm"},
3133 { 3, "fault"},
3134 { 4, "fault-pre-alarm"},
3135 { 5, "fault-alarm"},
3136 { 6, "not-ready"},
3137 { 7, "active"},
3138 { 8, "tamper"},
3139 { 9, "test-alarm"},
3140 { 10, "test-active"},
3141 { 11, "test-fault"},
3142 { 12, "test-fault-alarm"},
3143 { 13, "holdup"},
3144 { 14, "duress"},
3145 { 15, "tamper-alarm"},
3146 { 16, "abnormal"},
3147 { 17, "emergency-power"},
3148 { 18, "delayed"},
3149 { 19, "blocked"},
3150 { 20, "local-alarm"},
3151 { 21, "general-alarm"},
3152 { 22, "supervisory"},
3153 { 23, "test-supervisory"},
3154 { 24, "non-default-mode"},
3155 { 25, "oeo-unavailable"},
3156 { 26, "oeo-alarm"},
3157 { 27, "oeo-phase1-recall"},
3158 { 28, "oeo-evacuate"},
3159 { 29, "oeo-unaffected"},
3160 { 30, "test-oeo-unavailable"},
3161 { 31, "test-oeo-alarm"},
3162 { 32, "test-oeo-phase1-recall"},
3163 { 33, "test-oeo-evacuate"},
3164 { 34, "test-oeo-unaffected"},
3165 { 0, NULL}
3166 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3167 Enumerated values 256-65535 may be used by others subject to
3168 procedures and constraints described in Clause 23. */
3171 static const value_string
3172 BACnetLimitEnable[] = {
3173 { 0, "low-limit-enable" },
3174 { 1, "high-limit-enable" },
3175 { 0, NULL }
3178 static const value_string
3179 BACnetTimerState [] = {
3180 { 0, "idle"},
3181 { 1, "running"},
3182 { 2, "expired"},
3183 { 0, NULL}
3186 static const value_string
3187 BACnetTimerTransition [] = {
3188 { 0, "none"},
3189 { 1, "idle-to-running"},
3190 { 2, "running-to-idle"},
3191 { 3, "running-to-running"},
3192 { 4, "running-to-expired"},
3193 { 5, "forced-to-expired"},
3194 { 6, "expired-to-idle"},
3195 { 7, "expired-to-running"},
3196 { 0, NULL}
3199 static const value_string
3200 BACnetEscalatorFault [] = {
3201 { 0, "controller-fault"},
3202 { 1, "drive-and-motor-fault"},
3203 { 2, "mechanical-component-fault"},
3204 { 3, "overspeed-fault"},
3205 { 4, "power-supply-fault"},
3206 { 5, "safety-device-fault"},
3207 { 6, "controller-supply-fault"},
3208 { 7, "drive-temperature-exceeded"},
3209 { 8, "comb-plate-fault"},
3210 { 0, NULL}
3213 static const value_string
3214 BACnetEscalatorMode [] = {
3215 { 0, "unknown"},
3216 { 1, "stop"},
3217 { 2, "up"},
3218 { 3, "down"},
3219 { 4, "inspection"},
3220 { 5, "out-of-service"},
3221 { 0, NULL}
3224 static const value_string
3225 BACnetEscalatorOperationDirection [] = {
3226 { 0, "unknown"},
3227 { 1, "stopped"},
3228 { 2, "up-rated-speed"},
3229 { 3, "up-reduced-speed"},
3230 { 4, "down-rated-speed"},
3231 { 5, "down-reduced-speed"},
3232 { 0, NULL}
3235 static const value_string
3236 BACnetLiftCarDirection [] = {
3237 { 0, "unknown"},
3238 { 1, "none"},
3239 { 2, "stopped"},
3240 { 3, "up"},
3241 { 4, "down"},
3242 { 5, "up-and-down"},
3243 { 0, NULL}
3246 static const value_string
3247 BACnetLiftCarDoorCommand [] = {
3248 { 0, "none"},
3249 { 1, "open"},
3250 { 2, "close"},
3251 { 0, NULL}
3254 static const value_string
3255 BACnetLiftCarDriveStatus [] = {
3256 { 0, "unknown"},
3257 { 1, "stationary"},
3258 { 2, "braking"},
3259 { 3, "accelerate"},
3260 { 4, "decelerate"},
3261 { 5, "rated-speed"},
3262 { 6, "single-floor-jump"},
3263 { 7, "two-floor-jump"},
3264 { 8, "three-floor-jump"},
3265 { 9, "multi-floor-jump"},
3266 { 0, NULL}
3269 static const value_string
3270 BACnetLiftCarMode [] = {
3271 { 0, "unknown"},
3272 { 1, "normal"},
3273 { 2, "vip"},
3274 { 3, "homing"},
3275 { 4, "parking"},
3276 { 5, "attendant-control"},
3277 { 6, "firefighter-control"},
3278 { 7, "emergency-power"},
3279 { 8, "inspection"},
3280 { 9, "cabinet-recall"},
3281 { 10, "earthquake-operation"},
3282 { 11, "fire-operation"},
3283 { 12, "out-of-service"},
3284 { 13, "occupant-evacuation"},
3285 { 0, NULL}
3288 static const value_string
3289 BACnetLiftFault [] = {
3290 { 0, "controller-fault"},
3291 { 1, "drive-and-motor-fault"},
3292 { 2, "governor-and-safety-gear-fault"},
3293 { 3, "lift-shaft-device-fault"},
3294 { 4, "power-supply-fault"},
3295 { 5, "safety-interlock-fault"},
3296 { 6, "door-closing-fault"},
3297 { 7, "door-opening-fault"},
3298 { 8, "car-stopped-outside-landing-zone"},
3299 { 9, "call-button-stuck"},
3300 { 10, "start-failure"},
3301 { 11, "controller-supply-fault"},
3302 { 12, "self-test-failure"},
3303 { 13, "runtime-limit-exceeded"},
3304 { 14, "position-lost"},
3305 { 15, "drive-temperature-exceeded"},
3306 { 16, "load-measurement-fault"},
3307 { 0, NULL}
3310 static const value_string
3311 BACnetLiftGroupMode [] = {
3312 { 0, "unknown"},
3313 { 1, "normal"},
3314 { 2, "down-peak"},
3315 { 3, "two-way"},
3316 { 4, "four-way"},
3317 { 5, "emergency-power"},
3318 { 6, "up-peak"},
3319 { 0, NULL}
3322 static const value_string
3323 BACnetProtocolLevel [] = {
3324 { 0, "physical"},
3325 { 1, "protocol"},
3326 { 2, "bacnet-application"},
3327 { 3, "non-bacnet-application"},
3328 { 0, NULL}
3331 static const value_string
3332 BACnetRelationship [] = {
3333 { 0, "unknown"},
3334 { 1, "default"},
3335 { 2, "contains"},
3336 { 3, "contained-by"},
3337 { 4, "uses"},
3338 { 5, "used-by"},
3339 { 6, "commands"},
3340 { 7, "commanded-by"},
3341 { 8, "adjusts"},
3342 { 9, "adjusted-by"},
3343 { 10, "ingress"},
3344 { 11, "egress"},
3345 { 12, "supplies-air"},
3346 { 13, "receives-air"},
3347 { 14, "supplies-hot-air"},
3348 { 15, "receives-hot-air"},
3349 { 16, "supplies-cool-air"},
3350 { 17, "receives-cool-air"},
3351 { 18, "supplies-power"},
3352 { 19, "receives-power"},
3353 { 20, "supplies-gas"},
3354 { 21, "receives-gas"},
3355 { 22, "supplies-water"},
3356 { 23, "receives-water"},
3357 { 24, "supplies-hot-water"},
3358 { 25, "receives-hot-water"},
3359 { 26, "supplies-cool-water"},
3360 { 27, "receives-cool-water"},
3361 { 28, "supplies-steam"},
3362 { 29, "receives-steam"},
3363 { 0, NULL}
3366 static const value_string
3367 BACnetLightingOperation[] = {
3368 { 0, "none" },
3369 { 1, "fade-to" },
3370 { 2, "ramp-to" },
3371 { 3, "step-up" },
3372 { 4, "step-down" },
3373 { 5, "step-on" },
3374 { 6, "step-off" },
3375 { 7, "warn" },
3376 { 8, "warn-off" },
3377 { 9, "warn-relinquish" },
3378 { 10, "stop" },
3379 { 0, NULL }
3382 static const value_string
3383 BACnetColorOperation[] = {
3384 { 0, "none" },
3385 { 1, "fade-to-color" },
3386 { 2, "fade-to-cct" },
3387 { 3, "ramp-to-cct" },
3388 { 4, "step-up-cct" },
3389 { 5, "step-down-cct" },
3390 { 6, "stop" },
3391 { 0, NULL }
3394 static const value_string
3395 BACnetConfirmedServiceChoice[] = {
3396 { 0, "acknowledgeAlarm"},
3397 { 1, "confirmedCOVNotification"},
3398 { 2, "confirmedEventNotification"},
3399 { 3, "getAlarmSummary"},
3400 { 4, "getEnrollmentSummary"},
3401 { 5, "subscribeCOV"},
3402 { 6, "atomicReadFile"},
3403 { 7, "atomicWriteFile"},
3404 { 8, "addListElement"},
3405 { 9, "removeListElement"},
3406 { 10, "createObject"},
3407 { 11, "deleteObject"},
3408 { 12, "readProperty"},
3409 { 13, "readPropertyConditional"},
3410 { 14, "readPropertyMultiple"},
3411 { 15, "writeProperty"},
3412 { 16, "writePropertyMultiple"},
3413 { 17, "deviceCommunicationControl"},
3414 { 18, "confirmedPrivateTransfer"},
3415 { 19, "confirmedTextMessage"},
3416 { 20, "reinitializeDevice"},
3417 { 21, "vtOpen"},
3418 { 22, "vtClose"},
3419 { 23, "vtData"},
3420 { 24, "authenticate"},
3421 { 25, "requestKey"},
3422 { 26, "readRange"},
3423 { 27, "lifeSafetyOperation"},
3424 { 28, "subscribeCOVProperty"},
3425 { 29, "getEventInformation"},
3426 { 30, "subscribeCovPropertyMultiple"},
3427 { 31, "confirmedCovNotificationMultiple"},
3428 { 32, "confirmedAuditNotification"},
3429 { 33, "auditLogQuery"},
3430 { 0, NULL}
3433 static const value_string
3434 BACnetReliability [] = {
3435 { 0, "no-fault-detected"},
3436 { 1, "no-sensor"},
3437 { 2, "over-range"},
3438 { 3, "under-range"},
3439 { 4, "open-loop"},
3440 { 5, "shorted-loop"},
3441 { 6, "no-output"},
3442 { 7, "unreliable-other"},
3443 { 8, "process-error"},
3444 { 9, "multi-state-fault"},
3445 { 10, "configuration-error"},
3446 { 11, "reserved for a future addendum"},
3447 { 12, "communication-failure"},
3448 { 13, "member-fault"},
3449 { 14, "monitored-object-fault" },
3450 { 15, "tripped"},
3451 { 16, "lamp-failure"},
3452 { 17, "activation-failure"},
3453 { 18, "renew-dhcp-failure"},
3454 { 19, "renew-fd-registration-failure"},
3455 { 20, "restart-auto-negotiation-failure"},
3456 { 21, "restart-failure"},
3457 { 22, "proprietary-command-failure"},
3458 { 23, "faults-listed"},
3459 { 24, "referenced-object-fault"},
3460 { 25, "multi-state-out-of-range"},
3461 { 0, NULL}
3464 static const value_string
3465 BACnetRouterStatus[] = {
3466 { 0, "available" },
3467 { 1, "busy" },
3468 { 2, "disconnected" },
3469 { 0, NULL }
3472 static const value_string
3473 BACnetUnconfirmedServiceChoice [] = {
3474 { 0, "i-Am"},
3475 { 1, "i-Have"},
3476 { 2, "unconfirmedCOVNotification"},
3477 { 3, "unconfirmedEventNotification"},
3478 { 4, "unconfirmedPrivateTransfer"},
3479 { 5, "unconfirmedTextMessage"},
3480 { 6, "timeSynchronization"},
3481 { 7, "who-Has"},
3482 { 8, "who-Is"},
3483 { 9, "utcTimeSynchronization"},
3484 { 10, "writeGroup"},
3485 { 11, "unconfirmedCovNotificationMultiple"},
3486 { 12, "unconfirmedAuditNotification"},
3487 { 13, "who-am-I" },
3488 { 14, "you-are" },
3489 { 0, NULL}
3492 static const value_string
3493 BACnetObjectType [] = {
3494 { 0, "analog-input"},
3495 { 1, "analog-output"},
3496 { 2, "analog-value"},
3497 { 3, "binary-input"},
3498 { 4, "binary-output"},
3499 { 5, "binary-value"},
3500 { 6, "calendar"},
3501 { 7, "command"},
3502 { 8, "device"},
3503 { 9, "event-enrollment"},
3504 { 10, "file"},
3505 { 11, "group"},
3506 { 12, "loop"},
3507 { 13, "multi-state-input"},
3508 { 14, "multi-state-output"},
3509 { 15, "notification-class"},
3510 { 16, "program"},
3511 { 17, "schedule"},
3512 { 18, "averaging"},
3513 { 19, "multi-state-value"},
3514 { 20, "trend-log"},
3515 { 21, "life-safety-point"},
3516 { 22, "life-safety-zone"},
3517 { 23, "accumulator"},
3518 { 24, "pulse-converter"},
3519 { 25, "event-log"},
3520 { 26, "global-group"},
3521 { 27, "trend-log-multiple"},
3522 { 28, "load-control"},
3523 { 29, "structured-view"},
3524 { 30, "access-door"}, /* 30-37 added with addanda 135-2008j */
3525 { 31, "timer"},
3526 { 32, "access-credential"},
3527 { 33, "access-point"},
3528 { 34, "access-rights"},
3529 { 35, "access-user"},
3530 { 36, "access-zone"},
3531 { 37, "credential-data-input"},
3532 { 38, "network-security"},
3533 { 39, "bitstring-value"}, /* 39-50 added with addenda 135-2008w */
3534 { 40, "characterstring-value"},
3535 { 41, "date-pattern-value"},
3536 { 42, "date-value"},
3537 { 43, "datetime-pattern-value"},
3538 { 44, "datetime-value"},
3539 { 45, "integer-value"},
3540 { 46, "large-analog-value"},
3541 { 47, "octetstring-value"},
3542 { 48, "positive-integer-value"},
3543 { 49, "time-pattern-value"},
3544 { 50, "time-value"},
3545 { 51, "notification-forwarder"},
3546 { 52, "alert-enrollment"},
3547 { 53, "channel"},
3548 { 54, "lighting-output"},
3549 { 55, "binary-lighting-output"},
3550 { 56, "network-port"},
3551 { 57, "elevator-group"},
3552 { 58, "escalator"},
3553 { 59, "lift"},
3554 { 60, "staging"},
3555 { 61, "audit-log"},
3556 { 62, "audit-reporter"},
3557 { 63, "color"},
3558 { 64, "color-temperature"},
3559 { 0, NULL}
3560 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
3561 Enumerated values 128-1023 may be used by others subject to
3562 the procedures and constraints described in Clause 23. */
3565 static const value_string
3566 BACnetEngineeringUnits [] = {
3567 { 0, "Sq Meters"},
3568 { 1, "Sq Feet"},
3569 { 2, "Milliamperes"},
3570 { 3, "Amperes"},
3571 { 4, "Ohms"},
3572 { 5, "Volts"},
3573 { 6, "Kilovolts"},
3574 { 7, "Megavolts"},
3575 { 8, "Volt Amperes"},
3576 { 9, "Kilovolt Amperes"},
3577 { 10, "Megavolt Amperes"},
3578 { 11, "Volt Amperes Reactive"},
3579 { 12, "Kilovolt Amperes Reactive"},
3580 { 13, "Megavolt Amperes Reactive"},
3581 { 14, "Degrees Phase"},
3582 { 15, "Power Factor"},
3583 { 16, "Joules"},
3584 { 17, "Kilojoules"},
3585 { 18, "Watt Hours"},
3586 { 19, "Kilowatt Hours"},
3587 { 20, "BTUs"},
3588 { 21, "Therms"},
3589 { 22, "Ton Hours"},
3590 { 23, "Joules Per Kg Dry Air"},
3591 { 24, "BTUs Per Pound Dry Air"},
3592 { 25, "Cycles Per Hour"},
3593 { 26, "Cycles Per Minute"},
3594 { 27, "Hertz"},
3595 { 28, "Grams Of Water Per Kilogram Dry Air"},
3596 { 29, "Relative Humidity"},
3597 { 30, "Millimeters"},
3598 { 31, "Meters"},
3599 { 32, "Inches"},
3600 { 33, "Feed"},
3601 { 34, "Watts Per Sq Foot"},
3602 { 35, "Watts Per Sq meter"},
3603 { 36, "Lumens"},
3604 { 37, "Lux"},
3605 { 38, "Foot Candles"},
3606 { 39, "Kilograms"},
3607 { 40, "Pounds Mass"},
3608 { 41, "Tons"},
3609 { 42, "Kgs per Second"},
3610 { 43, "Kgs Per Minute"},
3611 { 44, "Kgs Per Hour"},
3612 { 45, "Pounds Mass Per Minute"},
3613 { 46, "Pounds Mass Per Hour"},
3614 { 47, "Watt"},
3615 { 48, "Kilowatts"},
3616 { 49, "Megawatts"},
3617 { 50, "BTUs Per Hour"},
3618 { 51, "Horsepower"},
3619 { 52, "Tons Refrigeration"},
3620 { 53, "Pascals"},
3621 { 54, "Kilopascals"},
3622 { 55, "Bars"},
3623 { 56, "Pounds Force Per Square Inch"},
3624 { 57, "Centimeters Of Water"},
3625 { 58, "Inches Of Water"},
3626 { 59, "Millimeters Of Mercury"},
3627 { 60, "Centimeters Of Mercury"},
3628 { 61, "Inches Of Mercury"},
3629 { 62, "Degrees Celsius"},
3630 { 63, "Degrees Kelvin"},
3631 { 64, "Degrees Fahrenheit"},
3632 { 65, "Degree Days Celsius"},
3633 { 66, "Degree Days Fahrenheit"},
3634 { 67, "Years"},
3635 { 68, "Months"},
3636 { 69, "Weeks"},
3637 { 70, "Days"},
3638 { 71, "Hours"},
3639 { 72, "Minutes"},
3640 { 73, "Seconds"},
3641 { 74, "Meters Per Second"},
3642 { 75, "Kilometers Per Hour"},
3643 { 76, "Feed Per Second"},
3644 { 77, "Feet Per Minute"},
3645 { 78, "Miles Per Hour"},
3646 { 79, "Cubic Feet"},
3647 { 80, "Cubic Meters"},
3648 { 81, "Imperial Gallons"},
3649 { 82, "Liters"},
3650 { 83, "US Gallons"},
3651 { 84, "Cubic Feet Per Minute"},
3652 { 85, "Cubic Meters Per Second"},
3653 { 86, "Imperial Gallons Per Minute"},
3654 { 87, "Liters Per Second"},
3655 { 88, "Liters Per Minute"},
3656 { 89, "US Gallons Per Minute"},
3657 { 90, "Degrees Angular"},
3658 { 91, "Degrees Celsius Per Hour"},
3659 { 92, "Degrees Celsius Per Minute"},
3660 { 93, "Degrees Fahrenheit Per Hour"},
3661 { 94, "Degrees Fahrenheit Per Minute"},
3662 { 95, "No Units"},
3663 { 96, "Parts Per Million"},
3664 { 97, "Parts Per Billion"},
3665 { 98, "Percent"},
3666 { 99, "Percent Per Second"},
3667 { 100, "Per Minute"},
3668 { 101, "Per Second"},
3669 { 102, "Psi Per Degree Fahrenheit"},
3670 { 103, "Radians"},
3671 { 104, "Revolutions Per Min"},
3672 { 105, "Currency1"},
3673 { 106, "Currency2"},
3674 { 107, "Currency3"},
3675 { 108, "Currency4"},
3676 { 109, "Currency5"},
3677 { 110, "Currency6"},
3678 { 111, "Currency7"},
3679 { 112, "Currency8"},
3680 { 113, "Currency9"},
3681 { 114, "Currency10"},
3682 { 115, "Sq Inches"},
3683 { 116, "Sq Centimeters"},
3684 { 117, "BTUs Per Pound"},
3685 { 118, "Centimeters"},
3686 { 119, "Pounds Mass Per Second"},
3687 { 120, "Delta Degrees Fahrenheit"},
3688 { 121, "Delta Degrees Kelvin"},
3689 { 122, "Kilohms"},
3690 { 123, "Megohms"},
3691 { 124, "Millivolts"},
3692 { 125, "Kilojoules Per Kg"},
3693 { 126, "Megajoules"},
3694 { 127, "Joules Per Degree Kelvin"},
3695 { 128, "Joules Per Kg Degree Kelvin"},
3696 { 129, "Kilohertz"},
3697 { 130, "Megahertz"},
3698 { 131, "Per Hour"},
3699 { 132, "Milliwatts"},
3700 { 133, "Hectopascals"},
3701 { 134, "Millibars"},
3702 { 135, "Cubic Meters Per Hour"},
3703 { 136, "Liters Per Hour"},
3704 { 137, "KWatt Hours Per Square Meter"},
3705 { 138, "KWatt Hours Per Square Foot"},
3706 { 139, "Megajoules Per Square Meter"},
3707 { 140, "Megajoules Per Square Foot"},
3708 { 141, "Watts Per Sq Meter Degree Kelvin"},
3709 { 142, "Cubic Feet Per Second"},
3710 { 143, "Percent Obstruction Per Foot"},
3711 { 144, "Percent Obstruction Per Meter"},
3712 { 145, "milliohms"},
3713 { 146, "megawatt-hours"},
3714 { 147, "kilo-btus"},
3715 { 148, "mega-btus"},
3716 { 149, "kilojoules-per-kilogram-dry-air"},
3717 { 150, "megajoules-per-kilogram-dry-air"},
3718 { 151, "kilojoules-per-degree-Kelvin"},
3719 { 152, "megajoules-per-degree-Kelvin"},
3720 { 153, "newton"},
3721 { 154, "grams-per-second"},
3722 { 155, "grams-per-minute"},
3723 { 156, "tons-per-hour"},
3724 { 157, "kilo-btus-per-hour"},
3725 { 158, "hundredths-seconds"},
3726 { 159, "milliseconds"},
3727 { 160, "newton-meters"},
3728 { 161, "millimeters-per-second"},
3729 { 162, "millimeters-per-minute"},
3730 { 163, "meters-per-minute"},
3731 { 164, "meters-per-hour"},
3732 { 165, "cubic-meters-per-minute"},
3733 { 166, "meters-per-second-per-second"},
3734 { 167, "amperes-per-meter"},
3735 { 168, "amperes-per-square-meter"},
3736 { 169, "ampere-square-meters"},
3737 { 170, "farads"},
3738 { 171, "henrys"},
3739 { 172, "ohm-meters"},
3740 { 173, "siemens"},
3741 { 174, "siemens-per-meter"},
3742 { 175, "teslas"},
3743 { 176, "volts-per-degree-Kelvin"},
3744 { 177, "volts-per-meter"},
3745 { 178, "webers"},
3746 { 179, "candelas"},
3747 { 180, "candelas-per-square-meter"},
3748 { 181, "degrees-Kelvin-per-hour"},
3749 { 182, "degrees-Kelvin-per-minute"},
3750 { 183, "joule-seconds"},
3751 { 184, "radians-per-second"},
3752 { 185, "square-meters-per-Newton"},
3753 { 186, "kilograms-per-cubic-meter"},
3754 { 187, "newton-seconds"},
3755 { 188, "newtons-per-meter"},
3756 { 189, "watts-per-meter-per-degree-Kelvin"},
3757 { 190, "micro-siemens"},
3758 { 191, "cubic-feet-per-hour"},
3759 { 192, "us-gallons-per-hour"},
3760 { 193, "kilometers"},
3761 { 194, "micrometers"},
3762 { 195, "grams"},
3763 { 196, "milligrams"},
3764 { 197, "milliliters"},
3765 { 198, "milliliters-per-second"},
3766 { 199, "decibels"},
3767 { 200, "decibels-millivolt"},
3768 { 201, "decibels-volt"},
3769 { 202, "millisiemens"},
3770 { 203, "watt-hours-reactive"},
3771 { 204, "kilowatt-hours-reactive"},
3772 { 205, "megawatt-hours-reactive"},
3773 { 206, "millimeters-of-water"},
3774 { 207, "per-mille"},
3775 { 208, "grams-per-gram"},
3776 { 209, "kilograms-per-kilogram"},
3777 { 210, "grams-per-kilogram"},
3778 { 211, "milligrams-per-gram"},
3779 { 212, "milligrams-per-kilogram"},
3780 { 213, "grams-per-milliliter"},
3781 { 214, "grams-per-liter"},
3782 { 215, "milligrams-per-liter"},
3783 { 216, "micrograms-per-liter"},
3784 { 217, "grams-per-cubic-meter"},
3785 { 218, "milligrams-per-cubic-meter"},
3786 { 219, "micrograms-per-cubic-meter"},
3787 { 220, "nanograms-per-cubic-meter"},
3788 { 221, "grams-per-cubic-centimeter"},
3789 { 222, "becquerels"},
3790 { 223, "kilobecquerels"},
3791 { 224, "megabecquerels"},
3792 { 225, "gray"},
3793 { 226, "milligray"},
3794 { 227, "microgray"},
3795 { 228, "sieverts"},
3796 { 229, "millisieverts"},
3797 { 230, "microsieverts"},
3798 { 231, "microsieverts-per-hour"},
3799 { 232, "decibels-a"},
3800 { 233, "nephelometric-turbidity-unit"},
3801 { 234, "pH"},
3802 { 235, "grams-per-square-meter"},
3803 { 236, "minutes-per-degree-kelvin"},
3804 { 237, "ohm-meter-squared-per-meter"},
3805 { 238, "ampere-seconds"},
3806 { 239, "volt-ampere-hours"},
3807 { 240, "kilovolt-ampere-hours"},
3808 { 241, "megavolt-ampere-hours"},
3809 { 242, "volt-ampere-hours-reactive"},
3810 { 243, "kilovolt-ampere-hours-reactive"},
3811 { 244, "megavolt-ampere-hours-reactive"},
3812 { 245, "volt-square-hours"},
3813 { 246, "ampere-square-hours"},
3814 { 247, "joule-per-hours"},
3815 { 248, "cubic-feet-per-day"},
3816 { 249, "cubic-meters-per-day"},
3817 { 250, "watt-hours-per-cubic-meter"},
3818 { 251, "joules-per-cubic-meter"},
3819 { 252, "mole-percent"},
3820 { 253, "pascal-seconds"},
3821 { 254, "million-standard-cubic-feet-per-minute"},
3822 { 255, "unassigned-unit-value-255"},
3823 { 47808, "standard-cubic-feet-per-day"},
3824 { 47809, "million-standard-cubic-feet-per-day"},
3825 { 47810, "thousand-cubic-feet-per-day"},
3826 { 47811, "thousand-standard-cubic-feet-per-day"},
3827 { 47812, "pounds-mass-per-day"},
3828 { 47813, "reserved-unit-47813"},
3829 { 47814, "millirems"},
3830 { 47815, "millirems-per-hour"},
3831 { 47816, "degrees-lovibond"},
3832 { 47817, "alcohol-by-volume"},
3833 { 47818, "international-bittering-units"},
3834 { 47819, "european-bitterness-units"},
3835 { 47820, "degrees-plato"},
3836 { 47821, "specific-gravity"},
3837 { 47822, "european-brewing-convention"},
3838 { 0, NULL}
3839 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3840 Enumerated values 256-65535 may be used by others subject to
3841 the procedures and constraints described in Clause 23. */
3844 static const value_string
3845 BACnetErrorCode [] = {
3846 { 0, "other"},
3847 { 1, "authentication-failed"},
3848 { 2, "configuration-in-progress"},
3849 { 3, "device-busy"},
3850 { 4, "dynamic-creation-not-supported"},
3851 { 5, "file-access-denied"},
3852 { 6, "incompatible-security-levels"},
3853 { 7, "inconsistent-parameters"},
3854 { 8, "inconsistent-selection-criterion"},
3855 { 9, "invalid-data-type"},
3856 { 10, "invalid-file-access-method"},
3857 { 11, "invalid-file-start-position"},
3858 { 12, "invalid-operator-name"},
3859 { 13, "invalid-parameter-data-type"},
3860 { 14, "invalid-time-stamp"},
3861 { 15, "key-generation-error"},
3862 { 16, "missing-required-parameter"},
3863 { 17, "no-objects-of-specified-type"},
3864 { 18, "no-space-for-object"},
3865 { 19, "no-space-to-add-list-element"},
3866 { 20, "no-space-to-write-property"},
3867 { 21, "no-vt-sessions-available"},
3868 { 22, "property-is-not-a-list"},
3869 { 23, "object-deletion-not-permitted"},
3870 { 24, "object-identifier-already-exists"},
3871 { 25, "operational-problem"},
3872 { 26, "password-failure"},
3873 { 27, "read-access-denied"},
3874 { 28, "security-not-supported"},
3875 { 29, "service-request-denied"},
3876 { 30, "timeout"},
3877 { 31, "unknown-object"},
3878 { 32, "unknown-property"},
3879 { 33, "removed enumeration"},
3880 { 34, "unknown-vt-class"},
3881 { 35, "unknown-vt-session"},
3882 { 36, "unsupported-object-type"},
3883 { 37, "value-out-of-range"},
3884 { 38, "vt-session-already-closed"},
3885 { 39, "vt-session-termination-failure"},
3886 { 40, "write-access-denied"},
3887 { 41, "character-set-not-supported"},
3888 { 42, "invalid-array-index"},
3889 { 43, "cov-subscription-failed"},
3890 { 44, "not-cov-property"},
3891 { 45, "optional-functionality-not-supported"},
3892 { 46, "invalid-configuration-data"},
3893 { 47, "datatype-not-supported"},
3894 { 48, "duplicate-name"},
3895 { 49, "duplicate-object-id"},
3896 { 50, "property-is-not-an-array"},
3897 { 51, "abort - buffer - overflow" },
3898 { 52, "abort - invalid - apdu - in - this - state" },
3899 { 53, "abort - preempted - by - higher - priority - task" },
3900 { 54, "abort - segmentation - not - supported" },
3901 { 55, "abort - proprietary" },
3902 { 56, "abort - other" },
3903 { 57, "invalid - tag" },
3904 { 58, "network - down" },
3905 { 59, "reject - buffer - overflow" },
3906 { 60, "reject - inconsistent - parameters" },
3907 { 61, "reject - invalid - parameter - data - type" },
3908 { 62, "reject - invalid - tag" },
3909 { 63, "reject - missing - required - parameter" },
3910 { 64, "reject - parameter - out - of - range" },
3911 { 65, "reject - too - many - arguments" },
3912 { 66, "reject - undefined - enumeration" },
3913 { 67, "reject - unrecognized - service" },
3914 { 68, "reject - proprietary" },
3915 { 69, "reject - other" },
3916 { 70, "unknown - device" },
3917 { 71, "unknown - route" },
3918 { 72, "value - not - initialized" },
3919 { 73, "invalid-event-state"},
3920 { 74, "no-alarm-configured"},
3921 { 75, "log-buffer-full"},
3922 { 76, "logged-value-purged"},
3923 { 77, "no-property-specified"},
3924 { 78, "not-configured-for-triggered-logging"},
3925 { 79, "unknown-subscription"},
3926 { 80, "parameter-out-of-range"},
3927 { 81, "list-element-not-found"},
3928 { 82, "busy"},
3929 { 83, "communication-disabled"},
3930 { 84, "success"},
3931 { 85, "access-denied"},
3932 { 86, "bad-destination-address"},
3933 { 87, "bad-destination-device-id"},
3934 { 88, "bad-signature"},
3935 { 89, "bad-source-address"},
3936 { 90, "bad-timestamp"},
3937 { 91, "cannot-use-key"},
3938 { 92, "cannot-verify-message-id"},
3939 { 93, "correct-key-revision"},
3940 { 94, "destination-device-id-required"},
3941 { 95, "duplicate-message"},
3942 { 96, "encryption-not-configured"},
3943 { 97, "encryption-required"},
3944 { 98, "incorrect-key"},
3945 { 99, "invalid-key-data"},
3946 { 100, "key-update-in-progress"},
3947 { 101, "malformed-message"},
3948 { 102, "not-key-server"},
3949 { 103, "security-not-configured"},
3950 { 104, "source-security-required"},
3951 { 105, "too-many-keys"},
3952 { 106, "unknown-authentication-type"},
3953 { 107, "unknown-key"},
3954 { 108, "unknown-key-revision"},
3955 { 109, "unknown-source-message"},
3956 { 110, "not-router-to-dnet"},
3957 { 111, "router-busy"},
3958 { 112, "unknown-network-message"},
3959 { 113, "message-too-long"},
3960 { 114, "security-error"},
3961 { 115, "addressing-error"},
3962 { 116, "write-bdt-failed"},
3963 { 117, "read-bdt-failed"},
3964 { 118, "register-foreign-device-failed"},
3965 { 119, "read-fdt-failed"},
3966 { 120, "delete-fdt-entry-failed"},
3967 { 121, "distribute-broadcast-failed"},
3968 { 122, "unknown-file-size"},
3969 { 123, "abort-apdu-too-long"},
3970 { 124, "abort-application-exceeded-reply-time"},
3971 { 125, "abort-out-of-resources"},
3972 { 126, "abort-tsm-timeout"},
3973 { 127, "abort-window-size-out-of-range"},
3974 { 128, "file-full"},
3975 { 129, "inconsistent-configuration"},
3976 { 130, "inconsistent-object-type"},
3977 { 131, "internal-error"},
3978 { 132, "not-configured"},
3979 { 133, "out-of-memory"},
3980 { 134, "value-too-long"},
3981 { 135, "abort-insufficient-security"},
3982 { 136, "abort-security-error"},
3983 { 137, "duplicate-entry"},
3984 { 138, "invalid-value-in-this-state"},
3985 { 139, "invalid-operation-in-this-state"},
3986 { 140, "list-item-not-numbered"},
3987 { 141, "list-item-not-timestamped"},
3988 { 142, "invalid-data-encoding"},
3989 { 143, "bvlc-function-unknown"},
3990 { 144, "bvlc-proprietary-function-unknown"},
3991 { 145, "header-encoding-error"},
3992 { 146, "header-not-understood"},
3993 { 147, "message-incomplete"},
3994 { 148, "not-a-bacnet-sc-hub"},
3995 { 149, "payload-expected"},
3996 { 150, "unexpected-data"},
3997 { 151, "node-duplicate-vmac"},
3998 { 152, "http-unexpected-response-code"},
3999 { 153, "http-no-upgrade"},
4000 { 154, "http-resource-not-local"},
4001 { 155, "http-proxy-authentication-failed"},
4002 { 156, "http-response-timeout"},
4003 { 157, "http-response-syntax-error"},
4004 { 158, "http-response-value-error"},
4005 { 159, "http-response-missing-header"},
4006 { 160, "http-websocket-header-error"},
4007 { 161, "http-upgrade-required"},
4008 { 162, "http-upgrade-error"},
4009 { 163, "http-temporary-unavailable"},
4010 { 164, "http-not-a-server"},
4011 { 165, "http-error"},
4012 { 166, "websocket-scheme-not-supported"},
4013 { 167, "websocket-unknown-control-message"},
4014 { 168, "websocket-close-error"},
4015 { 169, "websocket-closed-by-peer"},
4016 { 170, "websocket-endpoint-leaves"},
4017 { 171, "websocket-protocol-error"},
4018 { 172, "websocket-data-not-accepted"},
4019 { 173, "websocket-closed-abnormally"},
4020 { 174, "websocket-data-inconsistent"},
4021 { 175, "websocket-data-against-policy"},
4022 { 176, "websocket-frame-too-long"},
4023 { 177, "websocket-extension-missing"},
4024 { 178, "websocket-request-unavailable"},
4025 { 179, "websocket-error"},
4026 { 180, "tls-client-certificate-error"},
4027 { 181, "tls-server-certificate-error"},
4028 { 182, "tls-client-authentication-failed"},
4029 { 183, "tls-server-authentication-failed"},
4030 { 184, "tls-client-certificate-expired"},
4031 { 185, "tls-server-certificate-expired"},
4032 { 186, "tls-client-certificate-revoked"},
4033 { 187, "tls-server-certificate-revoked"},
4034 { 188, "tls-error"},
4035 { 189, "dns-unavailable"},
4036 { 190, "dns-name-resolution-failed"},
4037 { 191, "dns-resolver-failure"},
4038 { 192, "dns-error"},
4039 { 193, "tcp-connect-timeout"},
4040 { 194, "tcp-connection-refused"},
4041 { 195, "tcp-closed-by-local"},
4042 { 196, "tcp-closed-other"},
4043 { 197, "tcp-error"},
4044 { 198, "ip-address-not-reachable"},
4045 { 199, "ip-error"},
4046 { 0, NULL}
4047 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
4048 Enumerated values 256-65535 may be used by others subject to the
4049 procedures and constraints described in Clause 23. */
4052 static const value_string
4053 BACnetPropertyIdentifier [] = {
4054 { 0, "acked-transition"},
4055 { 1, "ack-required"},
4056 { 2, "action"},
4057 { 3, "action-text"},
4058 { 4, "active-text"},
4059 { 5, "active-vt-session"},
4060 { 6, "alarm-value"},
4061 { 7, "alarm-values"},
4062 { 8, "all"},
4063 { 9, "all-writes-successful"},
4064 { 10, "apdu-segment-timeout"},
4065 { 11, "apdu-timeout"},
4066 { 12, "application-software-version"},
4067 { 13, "archive"},
4068 { 14, "bias"},
4069 { 15, "change-of-state-count"},
4070 { 16, "change-of-state-time"},
4071 { 17, "notification-class"},
4072 { 18, "the property in this place was deleted"},
4073 { 19, "controlled-variable-reference"},
4074 { 20, "controlled-variable-units"},
4075 { 21, "controlled-variable-value"},
4076 { 22, "cov-increment"},
4077 { 23, "datelist"},
4078 { 24, "daylights-savings-status"},
4079 { 25, "deadband"},
4080 { 26, "derivative-constant"},
4081 { 27, "derivative-constant-units"},
4082 { 28, "description"},
4083 { 29, "description-of-halt"},
4084 { 30, "device-address-binding"},
4085 { 31, "device-type"},
4086 { 32, "effective-period"},
4087 { 33, "elapsed-active-time"},
4088 { 34, "error-limit"},
4089 { 35, "event-enable"},
4090 { 36, "event-state"},
4091 { 37, "event-type"},
4092 { 38, "exception-schedule"},
4093 { 39, "fault-values"},
4094 { 40, "feedback-value"},
4095 { 41, "file-access-method"},
4096 { 42, "file-size"},
4097 { 43, "file-type"},
4098 { 44, "firmware-revision"},
4099 { 45, "high-limit"},
4100 { 46, "inactive-text"},
4101 { 47, "in-process"},
4102 { 48, "instance-of"},
4103 { 49, "integral-constant"},
4104 { 50, "integral-constant-units"},
4105 { 51, "issue-confirmed-notifications"},
4106 { 52, "limit-enable"},
4107 { 53, "list-of-group-members"},
4108 { 54, "list-of-object-property-references"},
4109 { 55, "list-of-session-keys"},
4110 { 56, "local-date"},
4111 { 57, "local-time"},
4112 { 58, "location"},
4113 { 59, "low-limit"},
4114 { 60, "manipulated-variable-reference"},
4115 { 61, "maximum-output"},
4116 { 62, "max-apdu-length-accepted"},
4117 { 63, "max-info-frames"},
4118 { 64, "max-master"},
4119 { 65, "max-pres-value"},
4120 { 66, "minimum-off-time"},
4121 { 67, "minimum-on-time"},
4122 { 68, "minimum-output"},
4123 { 69, "min-pres-value"},
4124 { 70, "model-name"},
4125 { 71, "modification-date"},
4126 { 72, "notify-type"},
4127 { 73, "number-of-APDU-retries"},
4128 { 74, "number-of-states"},
4129 { 75, "object-identifier"},
4130 { 76, "object-list"},
4131 { 77, "object-name"},
4132 { 78, "object-property-reference"},
4133 { 79, "object-type"},
4134 { 80, "optional"},
4135 { 81, "out-of-service"},
4136 { 82, "output-units"},
4137 { 83, "event-parameters"},
4138 { 84, "polarity"},
4139 { 85, "present-value"},
4140 { 86, "priority"},
4141 { 87, "priority-array"},
4142 { 88, "priority-for-writing"},
4143 { 89, "process-identifier"},
4144 { 90, "program-change"},
4145 { 91, "program-location"},
4146 { 92, "program-state"},
4147 { 93, "proportional-constant"},
4148 { 94, "proportional-constant-units"},
4149 { 95, "protocol-conformance-class"},
4150 { 96, "protocol-object-types-supported"},
4151 { 97, "protocol-services-supported"},
4152 { 98, "protocol-version"},
4153 { 99, "read-only"},
4154 { 100, "reason-for-halt"},
4155 { 101, "recipient"},
4156 { 102, "recipient-list"},
4157 { 103, "reliability"},
4158 { 104, "relinquish-default"},
4159 { 105, "required"},
4160 { 106, "resolution"},
4161 { 107, "segmentation-supported"},
4162 { 108, "setpoint"},
4163 { 109, "setpoint-reference"},
4164 { 110, "state-text"},
4165 { 111, "status-flags"},
4166 { 112, "system-status"},
4167 { 113, "time-delay"},
4168 { 114, "time-of-active-time-reset"},
4169 { 115, "time-of-state-count-reset"},
4170 { 116, "time-synchronization-recipients"},
4171 { 117, "units"},
4172 { 118, "update-interval"},
4173 { 119, "utc-offset"},
4174 { 120, "vendor-identifier"},
4175 { 121, "vendor-name"},
4176 { 122, "vt-class-supported"},
4177 { 123, "weekly-schedule"},
4178 { 124, "attempted-samples"},
4179 { 125, "average-value"},
4180 { 126, "buffer-size"},
4181 { 127, "client-cov-increment"},
4182 { 128, "cov-resubscription-interval"},
4183 { 129, "current-notify-time"},
4184 { 130, "event-time-stamp"},
4185 { 131, "log-buffer"},
4186 { 132, "log-device-object-property"},
4187 { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
4188 { 134, "log-interval"},
4189 { 135, "maximum-value"},
4190 { 136, "minimum-value"},
4191 { 137, "notification-threshold"},
4192 { 138, "previous-notify-time"},
4193 { 139, "protocol-revision"},
4194 { 140, "records-since-notification"},
4195 { 141, "record-count"},
4196 { 142, "start-time"},
4197 { 143, "stop-time"},
4198 { 144, "stop-when-full"},
4199 { 145, "total-record-count"},
4200 { 146, "valid-samples"},
4201 { 147, "window-interval"},
4202 { 148, "window-samples"},
4203 { 149, "maximum-value-time-stamp"},
4204 { 150, "minimum-value-time-stamp"},
4205 { 151, "variance-value"},
4206 { 152, "active-cov-subscriptions"},
4207 { 153, "backup-failure-timeout"},
4208 { 154, "configuration-files"},
4209 { 155, "database-revision"},
4210 { 156, "direct-reading"},
4211 { 157, "last-restore-time"},
4212 { 158, "maintenance-required"},
4213 { 159, "member-of"},
4214 { 160, "mode"},
4215 { 161, "operation-expected"},
4216 { 162, "setting"},
4217 { 163, "silenced"},
4218 { 164, "tracking-value"},
4219 { 165, "zone-members"},
4220 { 166, "life-safety-alarm-values"},
4221 { 167, "max-segments-accepted"},
4222 { 168, "profile-name"},
4223 { 169, "auto-slave-discovery"},
4224 { 170, "manual-slave-address-binding"},
4225 { 171, "slave-address-binding"},
4226 { 172, "slave-proxy-enable"},
4227 { 173, "last-notify-record"}, /* bug 4117 */
4228 { 174, "schedule-default"},
4229 { 175, "accepted-modes"},
4230 { 176, "adjust-value"},
4231 { 177, "count"},
4232 { 178, "count-before-change"},
4233 { 179, "count-change-time"},
4234 { 180, "cov-period"},
4235 { 181, "input-reference"},
4236 { 182, "limit-monitoring-interval"},
4237 { 183, "logging-object"},
4238 { 184, "logging-record"},
4239 { 185, "prescale"},
4240 { 186, "pulse-rate"},
4241 { 187, "scale"},
4242 { 188, "scale-factor"},
4243 { 189, "update-time"},
4244 { 190, "value-before-change"},
4245 { 191, "value-set"},
4246 { 192, "value-change-time"},
4247 { 193, "align-intervals"},
4248 { 194, "group-member-names"},
4249 { 195, "interval-offset"},
4250 { 196, "last-restart-reason"},
4251 { 197, "logging-type"},
4252 { 198, "member-status-flags"},
4253 { 199, "notification-period"},
4254 { 200, "previous-notify-record"},
4255 { 201, "requested-update-interval"},
4256 { 202, "restart-notification-recipients"},
4257 { 203, "time-of-device-restart"},
4258 { 204, "time-synchronization-interval"},
4259 { 205, "trigger"},
4260 { 206, "UTC-time-synchronization-recipients"},
4261 { 207, "node-subtype"},
4262 { 208, "node-type"},
4263 { 209, "structured-object-list"},
4264 { 210, "subordinate-annotations"},
4265 { 211, "subordinate-list"},
4266 { 212, "actual-shed-level"},
4267 { 213, "duty-window"},
4268 { 214, "expected-shed-level"},
4269 { 215, "full-duty-baseline"},
4270 { 216, "node-subtype"},
4271 { 217, "node-type"},
4272 { 218, "requested-shed-level"},
4273 { 219, "shed-duration"},
4274 { 220, "shed-level-descriptions"},
4275 { 221, "shed-levels"},
4276 { 222, "state-description"},
4277 /* enumeration values 223-225 are unassigned */
4278 { 226, "door-alarm-state"},
4279 { 227, "door-extended-pulse-time"},
4280 { 228, "door-members"},
4281 { 229, "door-open-too-long-time"},
4282 { 230, "door-pulse-time"},
4283 { 231, "door-status"},
4284 { 232, "door-unlock-delay-time"},
4285 { 233, "lock-status"},
4286 { 234, "masked-alarm-values"},
4287 { 235, "secured-status"},
4288 /* enumeration values 236-243 are unassigned */
4289 { 244, "absentee-limit"}, /* added with addenda 135-2008j */
4290 { 245, "access-alarm-events"},
4291 { 246, "access-doors"},
4292 { 247, "access-event"},
4293 { 248, "access-event-authentication-factor"},
4294 { 249, "access-event-credential"},
4295 { 250, "access-event-time"},
4296 { 251, "access-transaction-events"},
4297 { 252, "accompaniment"},
4298 { 253, "accompaniment-time"},
4299 { 254, "activation-time"},
4300 { 255, "active-authentication-policy"},
4301 { 256, "assigned-access-rights"},
4302 { 257, "authentication-factors"},
4303 { 258, "authentication-policy-list"},
4304 { 259, "authentication-policy-names"},
4305 { 260, "authentication-status"},
4306 { 261, "authorization-mode"},
4307 { 262, "belongs-to"},
4308 { 263, "credential-disable"},
4309 { 264, "credential-status"},
4310 { 265, "credentials"},
4311 { 266, "credentials-in-zone"},
4312 { 267, "days-remaining"},
4313 { 268, "entry-points"},
4314 { 269, "exit-points"},
4315 { 270, "expiration-time"},
4316 { 271, "extended-time-enable"},
4317 { 272, "failed-attempt-events"},
4318 { 273, "failed-attempts"},
4319 { 274, "failed-attempts-time"},
4320 { 275, "last-access-event"},
4321 { 276, "last-access-point"},
4322 { 277, "last-credential-added"},
4323 { 278, "last-credential-added-time"},
4324 { 279, "last-credential-removed"},
4325 { 280, "last-credential-removed-time"},
4326 { 281, "last-use-time"},
4327 { 282, "lockout"},
4328 { 283, "lockout-relinquish-time"},
4329 { 284, "master-exemption"},
4330 { 285, "max-failed-attempts"},
4331 { 286, "members"},
4332 { 287, "muster-point"},
4333 { 288, "negative-access-rules"},
4334 { 289, "number-of-authentication-policies"},
4335 { 290, "occupancy-count"},
4336 { 291, "occupancy-count-adjust"},
4337 { 292, "occupancy-count-enable"},
4338 { 293, "occupancy-exemption"},
4339 { 294, "occupancy-lower-limit"},
4340 { 295, "occupancy-lower-limit-enforced"},
4341 { 296, "occupancy-state"},
4342 { 297, "occupancy-upper-limit"},
4343 { 298, "occupancy-upper-limit-enforced"},
4344 { 299, "passback-exemption"},
4345 { 300, "passback-mode"},
4346 { 301, "passback-timeout"},
4347 { 302, "positive-access-rules"},
4348 { 303, "reason-for-disable"},
4349 { 304, "supported-formats"},
4350 { 305, "supported-format-classes"},
4351 { 306, "threat-authority"},
4352 { 307, "threat-level"},
4353 { 308, "trace-flag"},
4354 { 309, "transaction-notification-class"},
4355 { 310, "user-external-identifier"},
4356 { 311, "user-information-reference"},
4357 /* enumeration values 312-316 are unassigned */
4358 { 317, "user-name"},
4359 { 318, "user-type"},
4360 { 319, "uses-remaining"},
4361 { 320, "zone-from"},
4362 { 321, "zone-to"},
4363 { 322, "access-event-tag"},
4364 { 323, "global-identifier"},
4365 /* enumeration values 324-325 reserved for future addenda */
4366 { 326, "verification-time"},
4367 { 327, "base-device-security-policy"},
4368 { 328, "distribution-key-revision"},
4369 { 329, "do-not-hide"},
4370 { 330, "key-sets"},
4371 { 331, "last-key-server"},
4372 { 332, "network-access-security-policies"},
4373 { 333, "packet-reorder-time"},
4374 { 334, "security-pdu-timeout"},
4375 { 335, "security-time-window"},
4376 { 336, "supported-security-algorithms"},
4377 { 337, "update-key-set-timeout"},
4378 { 338, "backup-and-restore-state"},
4379 { 339, "backup-preparation-time"},
4380 { 340, "restore-completion-time"},
4381 { 341, "restore-preparation-time"},
4382 { 342, "bit-mask"}, /* addenda 135-2008w */
4383 { 343, "bit-text"},
4384 { 344, "is-utc"},
4385 { 345, "group-members"},
4386 { 346, "group-member-names"},
4387 { 347, "member-status-flags"},
4388 { 348, "requested-update-interval"},
4389 { 349, "covu-period"},
4390 { 350, "covu-recipients"},
4391 { 351, "event-message-texts"},
4392 { 352, "event-message-texts-config"},
4393 { 353, "event-detection-enable"},
4394 { 354, "event-algorithm-inhibit"},
4395 { 355, "event-algorithm-inhibit-ref"},
4396 { 356, "time-delay-normal"},
4397 { 357, "reliability-evaluation-inhibit"},
4398 { 358, "fault-parameters"},
4399 { 359, "fault-type"},
4400 { 360, "local-forwarding-only"},
4401 { 361, "process-identifier-filter"},
4402 { 362, "subscribed-recipients"},
4403 { 363, "port-filter"},
4404 { 364, "authorization-exemptions"},
4405 { 365, "allow-group-delay-inhibit"},
4406 { 366, "channel-number"},
4407 { 367, "control-groups"},
4408 { 368, "execution-delay"},
4409 { 369, "last-priority"},
4410 { 370, "write-status"},
4411 { 371, "property-list"},
4412 { 372, "serial-number"},
4413 { 373, "blink-warn-enable"},
4414 { 374, "default-fade-time"},
4415 { 375, "default-ramp-rate"},
4416 { 376, "default-step-increment"},
4417 { 377, "egress-time"},
4418 { 378, "in-progress"},
4419 { 379, "instantaneous-power"},
4420 { 380, "lighting-command"},
4421 { 381, "lighting-command-default-priority"},
4422 { 382, "max-actual-value"},
4423 { 383, "min-actual-value"},
4424 { 384, "power"},
4425 { 385, "transition"},
4426 { 386, "egress-active"},
4427 { 387, "interface-value"},
4428 { 388, "fault-high-limit"},
4429 { 389, "fault-low-limit"},
4430 { 390, "low-diff-limit"},
4431 { 391, "strike-count"},
4432 { 392, "time-of-strike-count-reset"},
4433 { 393, "default-timeout"},
4434 { 394, "initial-timeout"},
4435 { 395, "last-state-change"},
4436 { 396, "state-change-values"},
4437 { 397, "timer-running"},
4438 { 398, "timer-state"},
4439 { 399, "apdu-length"},
4440 { 400, "bacnet-ip-address"},
4441 { 401, "bacnet-ip-default-gateway"},
4442 { 402, "bacnet-ip-dhcp-enable"},
4443 { 403, "bacnet-ip-dhcp-lease-time"},
4444 { 404, "bacnet-ip-dhcp-lease-time-remaining"},
4445 { 405, "bacnet-ip-dhcp-server"},
4446 { 406, "bacnet-ip-dns-server"},
4447 { 407, "bacnet-ip-global-address"},
4448 { 408, "bacnet-ip-mode"},
4449 { 409, "bacnet-ip-multicast-address"},
4450 { 410, "bacnet-ip-nat-traversal"},
4451 { 411, "bacnet-ip-subnet-mask"},
4452 { 412, "bacnet-ip-udp-port"},
4453 { 413, "bbmd-accept-fd-registrations"},
4454 { 414, "bbmd-broadcast-distribution-table"},
4455 { 415, "bbmd-foreign-device-table"},
4456 { 416, "changes-pending"},
4457 { 417, "command"},
4458 { 418, "fd-bbmd-address"},
4459 { 419, "fd-subscription-lifetime"},
4460 { 420, "link-speed"},
4461 { 421, "link-speeds"},
4462 { 422, "link-speed-autonegotiate"},
4463 { 423, "mac-address"},
4464 { 424, "network-interface-name"},
4465 { 425, "network-number"},
4466 { 426, "network-number-quality"},
4467 { 427, "network-type"},
4468 { 428, "routing-table"},
4469 { 429, "virtual-mac-address-table"},
4470 { 430, "command-time-array"},
4471 { 431, "current-command-priority"},
4472 { 432, "last-command-time"},
4473 { 433, "value-source"},
4474 { 434, "value-source-array"},
4475 { 435, "bacnet-ipv6-mode"},
4476 { 436, "ipv6-address"},
4477 { 437, "ipv6-prefix-length"},
4478 { 438, "bacnet-ipv6-udp-port"},
4479 { 439, "ipv6-default-gateway"},
4480 { 440, "bacnet-ipv6-multicast-address"},
4481 { 441, "ipv6-dns-server"},
4482 { 442, "ipv6-auto-addressing-enable"},
4483 { 443, "ipv6-dhcp-lease-time"},
4484 { 444, "ipv6-dhcp-lease-time-remaining"},
4485 { 445, "ipv6-dhcp-server"},
4486 { 446, "ipv6-zone-index"},
4487 { 447, "assigned-landing-calls"},
4488 { 448, "car-assigned-direction"},
4489 { 449, "car-door-command"},
4490 { 450, "car-door-status"},
4491 { 451, "car-door-text"},
4492 { 452, "car-door-zone"},
4493 { 453, "car-drive-status"},
4494 { 454, "car-load"},
4495 { 455, "car-load-units"},
4496 { 456, "car-mode"},
4497 { 457, "car-moving-direction"},
4498 { 458, "car-position"},
4499 { 459, "elevator-group"},
4500 { 460, "energy-meter"},
4501 { 461, "energy-meter-ref"},
4502 { 462, "escalator-mode"},
4503 { 463, "fault-signals"},
4504 { 464, "floor-text"},
4505 { 465, "group-id"},
4506 { 466, "enumeration value 466 is unassigned"},
4507 { 467, "group-mode"},
4508 { 468, "higher-deck"},
4509 { 469, "installation-id"},
4510 { 470, "landing-calls"},
4511 { 471, "landing-call-control"},
4512 { 472, "landing-door-status"},
4513 { 473, "lower-deck"},
4514 { 474, "machine-room-id"},
4515 { 475, "making-car-call"},
4516 { 476, "next-stopping-floor"},
4517 { 477, "operation-direction"},
4518 { 478, "passenger-alarm"},
4519 { 479, "power-mode"},
4520 { 480, "registered-car-call"},
4521 { 481, "active-cov-multiple-subscriptions"},
4522 { 482, "protocol-level"},
4523 { 483, "reference-port"},
4524 { 484, "deployed-profile-location"},
4525 { 485, "profile-location"},
4526 { 486, "tags"},
4527 { 487, "subordinate-node-types"},
4528 { 488, "subordinate-tags"},
4529 { 489, "subordinate-relationship"},
4530 { 490, "default-subordinate-relationship"},
4531 { 491, "represents"},
4532 { 492, "default-present-value"},
4533 { 493, "present-stage"},
4534 { 494, "stages"},
4535 { 495, "stage-names"},
4536 { 496, "target-references"},
4537 { 497, "audit-source-reporter"},
4538 { 498, "audit-level"},
4539 { 499, "audit-notification-recipient"},
4540 { 500, "audit-priority-filter"},
4541 { 501, "auditable-operations"},
4542 { 502, "delete-on-forward"},
4543 { 503, "maximum-send-delay"},
4544 { 504, "monitored-objects"},
4545 { 505, "send-now"},
4546 { 506, "floor-number"},
4547 { 507, "device-uuid"},
4548 { 508, "additional-reference-ports"},
4549 { 509, "certificate-signing-request-file"},
4550 { 510, "command-validation-result"},
4551 { 511, "issuer-certificate-files"},
4552 { 4194304, "max-bvlc-length-accepted"},
4553 { 4194305, "max-npdu-length-accepted"},
4554 { 4194306, "operational-certificate-file"},
4555 { 4194307, "current-health"},
4556 { 4194308, "sc-connect-wait-timeout"},
4557 { 4194309, "sc-direct-connect-accept-enable"},
4558 { 4194310, "sc-direct-connect-accept-uris"},
4559 { 4194311, "ssc-direct-connect-binding"},
4560 { 4194312, "sc-direct-connect-connection-status"},
4561 { 4194313, "sc-direct-connect-initiate-enable"},
4562 { 4194314, "sc-disconnect-wait-timeout"},
4563 { 4194315, "sc-failed-connection-request"},
4564 { 4194316, "sc-failover-hub-connection-status"},
4565 { 4194317, "sc-failover-hub-uri"},
4566 { 4194318, "sc-hub-connector-state"},
4567 { 4194319, "sc-hub-function-accept-uris"},
4568 { 4194320, "sc-hub-function-binding"},
4569 { 4194321, "sc-hub-function-connection-status"},
4570 { 4194322, "sc-hub-function-enable"},
4571 { 4194323, "sc-heartbeat-timeout"},
4572 { 4194324, "sc-primary-hub-connection-status"},
4573 { 4194325, "sc-primary-hub-uri"},
4574 { 4194326, "sc-maximum-reconnect-time"},
4575 { 4194327, "sc-minimum-reconnect-time"},
4576 { 4194328, "color-override"},
4577 { 4194329, "color-reference"},
4578 { 4194330, "default-color"},
4579 { 4194331, "default-color-temperature"},
4580 { 4194332, "override-color-reference"},
4581 { 4194334, "color-command"},
4582 { 4194335, "high_end_trim"},
4583 { 4194336, "low_end_trim"},
4584 { 4194337, "trim_fade_time"},
4585 { 0, NULL}
4586 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
4587 Enumerated values 512-4194303 may be used by others subject to
4588 the procedures and constraints described in Clause 23. */
4591 static const value_string
4592 BACnetBinaryPV [] = {
4593 { 0, "inactive"},
4594 { 1, "active"},
4595 { 0, NULL}
4599 #define ANSI_X3_4 0 /* ANSI X3.4, a/k/a "ASCII"; full UTF-8 since 2010 */
4600 /* See, for example, ANSI/ASHRAE Addendum k to ANSI/ASHRAE Standard 135-2008 */
4601 /* XXX - I've seen captures using this for ISO 8859-1 */
4602 #define IBM_MS_DBCS 1 /* "IBM/Microsoft DBCS"; was there only one such DBCS? */
4603 #define JIS_C_6226 2 /* JIS C 6226 */
4604 #define ISO_10646_UCS4 3 /* ISO 10646 (UCS-4) - 4-byte Unicode */
4605 #define ISO_10646_UCS2 4 /* ISO 10646 (UCS-2) - 2-byte Unicode Basic Multilingual Plane (not UTF-16, presumably) */
4606 #define ISO_8859_1 5 /* ISO 8859-1 */
4607 static const value_string
4608 BACnetCharacterSet [] = {
4609 { ANSI_X3_4, "ANSI X3.4 / UTF-8 (since 2010)"},
4610 { IBM_MS_DBCS, "IBM/Microsoft DBCS"},
4611 { JIS_C_6226, "JIS C 6226"},
4612 { ISO_10646_UCS4, "ISO 10646 (UCS-4)"},
4613 { ISO_10646_UCS2, "ISO 10646 (UCS-2)"},
4614 { ISO_8859_1, "ISO 8859-1"},
4615 { 0, NULL}
4618 static const value_string
4619 BACnetStatusFlags [] = {
4620 { 0, "in-alarm"},
4621 { 1, "fault"},
4622 { 2, "overridden"},
4623 { 3, "out-of-service"},
4624 { 0, NULL}
4627 static const value_string
4628 BACnetMessagePriority [] = {
4629 { 0, "normal"},
4630 { 1, "urgent"},
4631 { 0, NULL}
4634 static const value_string
4635 BACnetAcknowledgementFilter [] = {
4636 { 0, "all"},
4637 { 1, "acked"},
4638 { 2, "not-acked"},
4639 { 0, NULL}
4642 static const value_string
4643 BACnetResultFlags [] = {
4644 { 0, "first-item"},
4645 { 1, "last-item"},
4646 { 2, "more-items"},
4647 { 0, NULL}
4650 static const value_string
4651 BACnetRelationSpecifier [] = {
4652 { 0, "equal"},
4653 { 1, "not-equal"},
4654 { 2, "less-than"},
4655 { 3, "greater-than"},
4656 { 4, "less-than-or-equal"},
4657 { 5, "greater-than-or-equal"},
4658 { 0, NULL}
4661 static const value_string
4662 BACnetSelectionLogic [] = {
4663 { 0, "and"},
4664 { 1, "or"},
4665 { 2, "all"},
4666 { 0, NULL}
4669 static const value_string
4670 BACnetEventStateFilter [] = {
4671 { 0, "offnormal"},
4672 { 1, "fault"},
4673 { 2, "normal"},
4674 { 3, "all"},
4675 { 4, "active"},
4676 { 0, NULL}
4679 static const value_string
4680 BACnetEventTransitionBits [] = {
4681 { 0, "to-offnormal"},
4682 { 1, "to-fault"},
4683 { 2, "to-normal"},
4684 { 0, NULL}
4687 static const value_string
4688 BACnetSegmentation [] = {
4689 { 0, "segmented-both"},
4690 { 1, "segmented-transmit"},
4691 { 2, "segmented-receive"},
4692 { 3, "no-segmentation"},
4693 { 0, NULL}
4696 static const value_string
4697 BACnetSilencedState [] = {
4698 { 0, "unsilenced"},
4699 { 1, "audible-silenced"},
4700 { 2, "visible-silenced"},
4701 { 3, "all-silenced"},
4702 { 0, NULL}
4705 static const value_string
4706 BACnetDeviceStatus [] = {
4707 { 0, "operational"},
4708 { 1, "operational-read-only"},
4709 { 2, "download-required"},
4710 { 3, "download-in-progress"},
4711 { 4, "non-operational"},
4712 { 5, "backup-in-progress"},
4713 { 0, NULL}
4716 static const value_string
4717 BACnetEnableDisable [] = {
4718 { 0, "enable"},
4719 { 1, "disable"},
4720 { 2, "disable-initiation"},
4721 { 0, NULL}
4724 static const value_string
4725 months [] = {
4726 { 1, "January" },
4727 { 2, "February" },
4728 { 3, "March" },
4729 { 4, "April" },
4730 { 5, "May" },
4731 { 6, "June" },
4732 { 7, "July" },
4733 { 8, "August" },
4734 { 9, "September" },
4735 { 10, "October" },
4736 { 11, "November" },
4737 { 12, "December" },
4738 { 13, "odd month" },
4739 { 14, "even month" },
4740 { 255, "any month" },
4741 { 0, NULL }
4744 static const value_string
4745 weekofmonth [] = {
4746 { 1, "days numbered 1-7" },
4747 { 2, "days numbered 8-14" },
4748 { 3, "days numbered 15-21" },
4749 { 4, "days numbered 22-28" },
4750 { 5, "days numbered 29-31" },
4751 { 6, "last 7 days of this month" },
4752 { 7, "any of 7 days prior to last 7 days of this month" },
4753 { 8, "any of 7 days prior to last 14 days of this month" },
4754 { 9, "any of 7 days prior to last 21 days of this month" },
4755 { 255, "any week of this month" },
4756 { 0, NULL }
4759 /* note: notification class object recipient-list uses
4760 different day-of-week enum */
4761 static const value_string
4762 day_of_week [] = {
4763 { 1, "Monday" },
4764 { 2, "Tuesday" },
4765 { 3, "Wednesday" },
4766 { 4, "Thursday" },
4767 { 5, "Friday" },
4768 { 6, "Saturday" },
4769 { 7, "Sunday" },
4770 { 255, "any day of week" },
4771 { 0, NULL }
4774 static const value_string
4775 BACnetErrorClass [] = {
4776 { 0, "device" },
4777 { 1, "object" },
4778 { 2, "property" },
4779 { 3, "resources" },
4780 { 4, "security" },
4781 { 5, "services" },
4782 { 6, "vt" },
4783 { 7, "communication" },
4784 { 0, NULL }
4785 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
4786 Enumerated values64-65535 may be used by others subject to
4787 the procedures and constraints described in Clause 23. */
4790 static const value_string
4791 BACnetVTClass [] = {
4792 { 0, "default-terminal" },
4793 { 1, "ansi-x3-64" },
4794 { 2, "dec-vt52" },
4795 { 3, "dec-vt100" },
4796 { 4, "dec-vt200" },
4797 { 5, "hp-700-94" },
4798 { 6, "ibm-3130" },
4799 { 0, NULL }
4802 static const value_string
4803 BACnetEventType [] = {
4804 { 0, "change-of-bitstring" },
4805 { 1, "change-of-state" },
4806 { 2, "change-of-value" },
4807 { 3, "command-failure" },
4808 { 4, "floating-limit" },
4809 { 5, "out-of-range" },
4810 { 6, "complex-event-type" },
4811 { 7, "(deprecated)event-buffer-ready" },
4812 { 8, "change-of-life-safety" },
4813 { 9, "extended" },
4814 { 10, "buffer-ready" },
4815 { 11, "unsigned-range" },
4816 { 13, "access-event" },
4817 { 14, "double-out-of-range"}, /* added with addenda 135-2008w */
4818 { 15, "signed-out-of-range"},
4819 { 16, "unsigned-out-of-range"},
4820 { 17, "change-of-characterstring"},
4821 { 18, "change-of-status-flags"},
4822 { 19, "change-of-reliability" },
4823 { 20, "none" },
4824 { 21, "change-of-discrete-value"},
4825 { 22, "change-of-timer"},
4826 { 0, NULL }
4827 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
4828 Enumerated values 64-65535 may be used by others subject to
4829 the procedures and constraints described in Clause 23.
4830 It is expected that these enumerated values will correspond
4831 to the use of the complex-event-type CHOICE [6] of the
4832 BACnetNotificationParameters production. */
4835 static const value_string
4836 BACnetEventState [] = {
4837 { 0, "normal" },
4838 { 1, "fault" },
4839 { 2, "offnormal" },
4840 { 3, "high-limit" },
4841 { 4, "low-limit" },
4842 { 5, "life-safety-alarm" },
4843 { 0, NULL }
4844 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
4845 Enumerated values 64-65535 may be used by others subject to
4846 the procedures and constraints described in Clause 23. */
4849 static const value_string
4850 BACnetLogStatus [] = {
4851 { 0, "log-disabled" },
4852 { 1, "buffer-purged" },
4853 { 2, "log-interrupted"},
4854 { 0, NULL }
4857 static const value_string
4858 BACnetMaintenance [] = {
4859 { 0, "none" },
4860 { 1, "periodic-test" },
4861 { 2, "need-service-operational" },
4862 { 3, "need-service-inoperative" },
4863 { 0, NULL }
4866 static const value_string
4867 BACnetNotifyType [] = {
4868 { 0, "alarm" },
4869 { 1, "event" },
4870 { 2, "ack-notification" },
4871 { 0, NULL }
4874 static const value_string
4875 BACnetServicesSupported [] = {
4876 { 0, "acknowledgeAlarm"},
4877 { 1, "confirmedCOVNotification"},
4878 { 2, "confirmedEventNotification"},
4879 { 3, "getAlarmSummary"},
4880 { 4, "getEnrollmentSummary"},
4881 { 5, "subscribeCOV"},
4882 { 6, "atomicReadFile"},
4883 { 7, "atomicWriteFile"},
4884 { 8, "addListElement"},
4885 { 9, "removeListElement"},
4886 { 10, "createObject"},
4887 { 11, "deleteObject"},
4888 { 12, "readProperty"},
4889 { 13, "readPropertyConditional"},
4890 { 14, "readPropertyMultiple"},
4891 { 15, "writeProperty"},
4892 { 16, "writePropertyMultiple"},
4893 { 17, "deviceCommunicationControl"},
4894 { 18, "confirmedPrivateTransfer"},
4895 { 19, "confirmedTextMessage"},
4896 { 20, "reinitializeDevice"},
4897 { 21, "vtOpen"},
4898 { 22, "vtClose"},
4899 { 23, "vtData"},
4900 { 24, "authenticate"},
4901 { 25, "requestKey"},
4902 { 26, "i-Am"},
4903 { 27, "i-Have"},
4904 { 28, "unconfirmedCOVNotification"},
4905 { 29, "unconfirmedEventNotification"},
4906 { 30, "unconfirmedPrivateTransfer"},
4907 { 31, "unconfirmedTextMessage"},
4908 { 32, "timeSynchronization"},
4909 { 33, "who-Has"},
4910 { 34, "who-Is"},
4911 { 35, "readRange"},
4912 { 36, "utcTimeSynchronization"},
4913 { 37, "lifeSafetyOperation"},
4914 { 38, "subscribeCOVProperty"},
4915 { 39, "getEventInformation"},
4916 { 40, "write-group"},
4917 { 41, "subscribe-cov-property-multiple"},
4918 { 42, "confirmed-cov-notification-multiple"},
4919 { 43, "unconfirmed-cov-notification-multiple"},
4920 { 44, "confirmed-audit-notification" },
4921 { 45, "audit-log-query" },
4922 { 46, "unconfirmed-audit-notification" },
4923 { 0, NULL}
4926 static const value_string
4927 BACnetPropertyStates [] = {
4928 { 0, "boolean-value"},
4929 { 1, "binary-value"},
4930 { 2, "event-type"},
4931 { 3, "polarity"},
4932 { 4, "program-change"},
4933 { 5, "program-state"},
4934 { 6, "reason-for-halt"},
4935 { 7, "reliability"},
4936 { 8, "state"},
4937 { 9, "system-status"},
4938 { 10, "units"},
4939 { 11, "unsigned-value"},
4940 { 12, "life-safety-mode"},
4941 { 13, "life-safety-state"},
4942 { 14, "restart-reason"},
4943 { 15, "door-alarm-state"},
4944 { 16, "action"},
4945 { 17, "door-secured-status"},
4946 { 18, "door-status"},
4947 { 19, "door-value"},
4948 { 20, "file-access-method"},
4949 { 21, "lock-status"},
4950 { 22, "life-safety-operation"},
4951 { 23, "maintenance"},
4952 { 24, "node-type"},
4953 { 25, "notify-type"},
4954 { 26, "security-level"},
4955 { 27, "shed-state"},
4956 { 28, "silenced-state"},
4957 { 29, "unknown-29"},
4958 { 30, "access-event"},
4959 { 31, "zone-occupancy-state"},
4960 { 32, "access-credential-disable-reason"},
4961 { 33, "access-credential-disable"},
4962 { 34, "authentication-status"},
4963 { 35, "unknown-35"},
4964 { 36, "backup-state"},
4965 { 37, "write-status"},
4966 { 38, "lighting-in-progress"},
4967 { 39, "lighting-operation"},
4968 { 40, "lighting-transition"},
4969 { 41, "signed-value"},
4970 { 42, "unknown-42"},
4971 { 43, "timer-state"},
4972 { 44, "timer-transition"},
4973 { 45, "bacnet-ip-mode"},
4974 { 46, "network-port-command"},
4975 { 47, "network-type"},
4976 { 48, "network-number-quality"},
4977 { 49, "escalator-operation-direction"},
4978 { 50, "escalator-fault"},
4979 { 51, "escalator-mode"},
4980 { 52, "lift-car-direction"},
4981 { 53, "lift-car-door-command"},
4982 { 54, "lift-car-drive-status"},
4983 { 55, "lift-car-mode"},
4984 { 56, "lift-group-mode"},
4985 { 57, "lift-fault"},
4986 { 58, "protocol-level"},
4987 { 59, "audit-level"},
4988 { 60, "audit-operation"},
4989 { 63, "extended-value"},
4990 {256, "-- example-one"},
4991 {257, "-- example-two"},
4992 {258, "sc-connection-state"},
4993 {259, "sc-hub-connecto-state"},
4994 { 0, NULL}
4995 /* Tag values 0-63 are reserved for definition by ASHRAE.
4996 Tag values of 64-254 may be used by others to accommodate
4997 vendor specific properties that have discrete or enumerated values,
4998 subject to the constraints described in Clause 23. */
5001 static const value_string
5002 BACnetProgramError [] = {
5003 { 0, "normal"},
5004 { 1, "load-failed"},
5005 { 2, "internal"},
5006 { 3, "program"},
5007 { 4, "other"},
5008 { 0, NULL}
5009 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
5010 Enumerated values 64-65535 may be used by others subject to
5011 the procedures and constraints described in Clause 23. */
5014 static const value_string
5015 BACnetProgramRequest [] = {
5016 { 0, "ready"},
5017 { 1, "load"},
5018 { 2, "run"},
5019 { 3, "halt"},
5020 { 4, "restart"},
5021 { 5, "unload"},
5022 { 0, NULL}
5025 static const value_string
5026 BACnetProgramState [] = {
5027 { 0, "idle"},
5028 { 1, "loading"},
5029 { 2, "running"},
5030 { 3, "waiting"},
5031 { 4, "halted"},
5032 { 5, "unloading"},
5033 { 0, NULL}
5036 static const value_string
5037 BACnetReinitializedStateOfDevice [] = {
5038 { 0, "coldstart"},
5039 { 1, "warmstart"},
5040 { 2, "start-backup"},
5041 { 3, "end-backup"},
5042 { 4, "start-restore"},
5043 { 5, "end-restore"},
5044 { 6, "abort-restore"},
5045 { 7, "activate-changes"},
5046 { 0, NULL}
5049 static const value_string
5050 BACnetPolarity [] = {
5051 { 0, "normal"},
5052 { 1, "reverse"},
5053 { 0, NULL}
5056 static const value_string
5057 BACnetTagNames[] = {
5058 { 5, "Extended Value" },
5059 { 6, "Opening Tag" },
5060 { 7, "Closing Tag" },
5061 { 0, NULL }
5064 static const value_string
5065 BACnetReadRangeOptions[] = {
5066 { 3, "range byPosition" },
5067 { 4, "range byTime" },
5068 { 5, "range timeRange" },
5069 { 6, "range bySequenceNumber" },
5070 { 7, "range byTime" },
5071 { 0, NULL }
5074 /* Present_Value for Load Control Object */
5075 static const value_string
5076 BACnetShedState[] = {
5077 { 0, "shed-inactive" },
5078 { 1, "shed-request-pending" },
5079 { 2, "shed-compliant" },
5080 { 3, "shed-non-compliant" },
5081 { 0, NULL }
5084 static const value_string
5085 BACnetFaultType[] = {
5086 { 0, "none" },
5087 { 1, "fault-characterstring" },
5088 { 2, "fault-extended" },
5089 { 3, "fault-life-safety" },
5090 { 4, "fault-state" },
5091 { 5, "fault-status-flags" },
5092 { 6, "fault-out-of-range" },
5093 { 7, "fault-listed" },
5094 { 0, NULL }
5097 static const value_string
5098 BACnetNodeType [] = {
5099 { 0, "unknown" },
5100 { 1, "system" },
5101 { 2, "network" },
5102 { 3, "device" },
5103 { 4, "organizational" },
5104 { 5, "area" },
5105 { 6, "equipment" },
5106 { 7, "point" },
5107 { 8, "collection" },
5108 { 9, "property" },
5109 { 10, "functional" },
5110 { 11, "other" },
5111 { 12, "subsystem" },
5112 { 13, "building" },
5113 { 14, "floor" },
5114 { 15, "section" },
5115 { 16, "module" },
5116 { 17, "tree" },
5117 { 18, "member" },
5118 { 19, "protocol" },
5119 { 20, "room" },
5120 { 21, "zone" },
5121 { 0, NULL }
5124 static const value_string
5125 BACnetLoggingType [] = {
5126 { 0, "polled" },
5127 { 1, "cov" },
5128 { 2, "triggered" },
5129 { 0, NULL }
5132 static const value_string
5133 BACnetDoorStatus [] = {
5134 { 0, "closed" },
5135 { 1, "opened" },
5136 { 2, "unknown" },
5137 { 3, "door-fault" },
5138 { 4, "unused" },
5139 { 5, "none" },
5140 { 6, "closing" },
5141 { 7, "opening" },
5142 { 8, "safety-locked" },
5143 { 9, "limited-opened" },
5144 { 0, NULL }
5147 static const value_string
5148 BACnetDoorValue[] = {
5149 { 0, "lock" },
5150 { 1, "unlock" },
5151 { 2, "pulse-unlock" },
5152 { 3, "extended-pulse-unlock" },
5153 { 0, NULL }
5156 static const value_string
5157 BACnetLockStatus [] = {
5158 { 0, "locked" },
5159 { 1, "unlocked" },
5160 { 2, "fault" },
5161 { 3, "unknown" },
5162 { 0, NULL }
5165 static const value_string
5166 BACnetDoorSecuredStatus [] = {
5167 { 0, "secured" },
5168 { 1, "unsecured" },
5169 { 2, "unknown" },
5170 { 0, NULL }
5173 static const value_string
5174 BACnetDoorAlarmState [] = {
5175 { 0, "normal" },
5176 { 1, "alarm" },
5177 { 2, "door-open-too-long" },
5178 { 3, "forced-open" },
5179 { 4, "tamper" },
5180 { 5, "door-fault" },
5181 { 6, "lock-down" },
5182 { 7, "free-access" },
5183 { 8, "egress-open" },
5184 { 0, NULL }
5187 static const value_string
5188 BACnetSecurityPolicy [] = {
5189 { 0, "plain-non-trusted"},
5190 { 1, "plain-trusted"},
5191 { 2, "signed-trusted"},
5192 { 3, "encrypted-trusted"},
5193 { 0, NULL }
5196 static const value_string
5197 BACnetAccumulatorStatus [] = {
5198 { 0, "normal" },
5199 { 1, "starting" },
5200 { 2, "recovered" },
5201 { 3, "abnormal" },
5202 { 4, "failed" },
5203 { 0, NULL }
5206 static const value_string
5207 BACnetAuditLevel [] = {
5208 { 0, "none" },
5209 { 1, "audit-all" },
5210 { 2, "audit-config" },
5211 { 3, "default" },
5212 { 0, NULL }
5215 static const value_string
5216 BACnetAuditPriorityFilter [] = {
5217 { 1, "manual-life-safety" },
5218 { 2, "automatic-life-safety" },
5219 { 3, "priority-3" },
5220 { 4, "priority-4" },
5221 { 5, "critical-equipment-controls" },
5222 { 6, "minimum-on-off" },
5223 { 7, "priority-7" },
5224 { 8, "manual-operator" },
5225 { 9, "priority-9" },
5226 { 10, "priority-10" },
5227 { 11, "priority-11" },
5228 { 12, "priority-12" },
5229 { 13, "priority-13" },
5230 { 14, "priority-14" },
5231 { 15, "priority-15" },
5232 { 16, "priority-16" },
5233 { 0, NULL }
5236 static const value_string
5237 BACnetAuditOperation [] = {
5238 { 0, "read" },
5239 { 1, "write" },
5240 { 2, "create" },
5241 { 3, "delete" },
5242 { 4, "life-safety" },
5243 { 5, "acknowledge-alarm" },
5244 { 6, "device-disable-comm" },
5245 { 7, "device-enable-comm" },
5246 { 8, "device-reset" },
5247 { 9, "device-backup" },
5248 { 10, "device-restore" },
5249 { 11, "subscription" },
5250 { 12, "notification" },
5251 { 13, "auditing-failure" },
5252 { 14, "network-changes" },
5253 { 15, "general" },
5254 { 0, NULL }
5257 static const value_string
5258 BACnetSuccessFilter [] = {
5259 { 0, "all" },
5260 { 1, "successes-only" },
5261 { 2, "failures-only" },
5262 { 0, NULL }
5266 /* These values are generated by tools/generate-bacnet-vendors.py from
5267 * https://bacnet.org/assigned-vendor-ids/
5268 * Version: "As of January 24, 2024"
5271 static const value_string
5272 BACnetVendorIdentifiers [] = {
5273 { 0, "ASHRAE" },
5274 { 1, "NIST" },
5275 { 2, "The Trane Company" },
5276 { 3, "Daikin Applied Americas" },
5277 { 4, "PolarSoft" },
5278 { 5, "Johnson Controls, Inc." },
5279 { 6, "ABB (Formerly American Auto-Matrix)" },
5280 { 7, "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)" },
5281 { 8, "Delta Controls" },
5282 { 9, "Siemens Schweiz AG" },
5283 { 10, "Schneider Electric" },
5284 { 11, "TAC" },
5285 { 12, "Orion Analysis Corporation" },
5286 { 13, "Teletrol Systems Inc." },
5287 { 14, "Cimetrics Technology" },
5288 { 15, "Cornell University" },
5289 { 16, "United Technologies Carrier" },
5290 { 17, "Honeywell Inc." },
5291 { 18, "Alerton / Honeywell" },
5292 { 19, "TAC AB" },
5293 { 20, "Hewlett-Packard Company" },
5294 { 21, "Dorsette’s Inc." },
5295 { 22, "Siemens Schweiz AG (Formerly: Cerberus AG)" },
5296 { 23, "York Controls Group" },
5297 { 24, "Automated Logic Corporation" },
5298 { 25, "CSI Control Systems International" },
5299 { 26, "Phoenix Controls Corporation" },
5300 { 27, "Innovex Technologies, Inc." },
5301 { 28, "KMC Controls, Inc." },
5302 { 29, "Xn Technologies, Inc." },
5303 { 30, "Hyundai Information Technology Co., Ltd." },
5304 { 31, "Tokimec Inc." },
5305 { 32, "Simplex" },
5306 { 33, "North Building Technologies Limited" },
5307 { 34, "Notifier" },
5308 { 35, "Reliable Controls Corporation" },
5309 { 36, "Tridium Inc." },
5310 { 37, "MSA Safety" },
5311 { 38, "Silicon Energy" },
5312 { 39, "Kieback & Peter GmbH & Co KG" },
5313 { 40, "Anacon Systems, Inc." },
5314 { 41, "Systems Controls & Instruments, LLC" },
5315 { 42, "Acuity Brands Lighting, Inc." },
5316 { 43, "Micropower Manufacturing" },
5317 { 44, "Matrix Controls" },
5318 { 45, "METALAIRE" },
5319 { 46, "ESS Engineering" },
5320 { 47, "Sphere Systems Pty Ltd." },
5321 { 48, "Walker Technologies Corporation" },
5322 { 49, "H I Solutions, Inc." },
5323 { 50, "MBS GmbH" },
5324 { 51, "SAMSON AG" },
5325 { 52, "Badger Meter Inc." },
5326 { 53, "DAIKIN Industries Ltd." },
5327 { 54, "NARA Controls Inc." },
5328 { 55, "Mammoth Inc." },
5329 { 56, "Liebert Corporation" },
5330 { 57, "SEMCO Incorporated" },
5331 { 58, "Air Monitor Corporation" },
5332 { 59, "TRIATEK, LLC" },
5333 { 60, "NexLight" },
5334 { 61, "Multistack" },
5335 { 62, "TSI Incorporated" },
5336 { 63, "Weather-Rite, Inc." },
5337 { 64, "Dunham-Bush" },
5338 { 65, "Reliance Electric" },
5339 { 66, "LCS Inc." },
5340 { 67, "Regulator Australia PTY Ltd." },
5341 { 68, "Touch-Plate Lighting Controls" },
5342 { 69, "Amann GmbH" },
5343 { 70, "RLE Technologies" },
5344 { 71, "Cardkey Systems" },
5345 { 72, "SECOM Co., Ltd." },
5346 { 73, "ABB Gebäudetechnik AG Bereich NetServ" },
5347 { 74, "KNX Association cvba" },
5348 { 75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
5349 { 76, "Nohmi Bosai, Ltd." },
5350 { 77, "Carel Industries S.p.A." },
5351 { 78, "UTC Fire & Security España, S.L." },
5352 { 79, "Hochiki Corporation" },
5353 { 80, "Fr. Sauter AG" },
5354 { 81, "Matsushita Electric Works, Ltd." },
5355 { 82, "Mitsubishi Electric Corporation, Inazawa Works" },
5356 { 83, "Mitsubishi Heavy Industries, Ltd." },
5357 { 84, "Xylem, Inc." },
5358 { 85, "Yamatake Building Systems Co., Ltd." },
5359 { 86, "The Watt Stopper, Inc." },
5360 { 87, "Aichi Tokei Denki Co., Ltd." },
5361 { 88, "Activation Technologies, LLC" },
5362 { 89, "Saia-Burgess Controls, Ltd." },
5363 { 90, "Hitachi, Ltd." },
5364 { 91, "Novar Corp./Trend Control Systems Ltd." },
5365 { 92, "Mitsubishi Electric Lighting Corporation" },
5366 { 93, "Argus Control Systems, Ltd." },
5367 { 94, "Kyuki Corporation" },
5368 { 95, "Richards-Zeta Building Intelligence, Inc." },
5369 { 96, "Scientech R&D, Inc." },
5370 { 97, "VCI Controls, Inc." },
5371 { 98, "Toshiba Corporation" },
5372 { 99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
5373 { 100, "Custom Mechanical Equipment, LLC" },
5374 { 101, "ClimateMaster" },
5375 { 102, "ICP Panel-Tec, Inc." },
5376 { 103, "D-Tek Controls" },
5377 { 104, "NEC Engineering, Ltd." },
5378 { 105, "PRIVA BV" },
5379 { 106, "Meidensha Corporation" },
5380 { 107, "JCI Systems Integration Services" },
5381 { 108, "Freedom Corporation" },
5382 { 109, "Neuberger Gebäudeautomation GmbH" },
5383 { 110, "eZi Controls" },
5384 { 111, "Leviton Manufacturing" },
5385 { 112, "Fujitsu Limited" },
5386 { 113, "Vertiv (Formerly Emerson Network Power)" },
5387 { 114, "S. A. Armstrong, Ltd." },
5388 { 115, "Visonet AG" },
5389 { 116, "M&M Systems, Inc." },
5390 { 117, "Custom Software Engineering" },
5391 { 118, "Nittan Company, Limited" },
5392 { 119, "Elutions Inc. (Wizcon Systems SAS)" },
5393 { 120, "Pacom Systems Pty., Ltd." },
5394 { 121, "Unico, Inc." },
5395 { 122, "Ebtron, Inc." },
5396 { 123, "Scada Engine" },
5397 { 124, "Lenze Americas (Formerly: AC Technology Corporation)" },
5398 { 125, "Eagle Technology" },
5399 { 126, "Data Aire, Inc." },
5400 { 127, "ABB, Inc." },
5401 { 128, "Transbit Sp. z o. o." },
5402 { 129, "Carrier Japan Corporation" },
5403 { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
5404 { 131, "Tokai Soft" },
5405 { 132, "Blue Ridge Technologies" },
5406 { 133, "Veris Industries" },
5407 { 134, "Centaurus Prime" },
5408 { 135, "Sand Network Systems" },
5409 { 136, "Regulvar, Inc." },
5410 { 137, "AFDtek Division of Fastek International Inc." },
5411 { 138, "PowerCold Comfort Air Solutions, Inc." },
5412 { 139, "I Controls" },
5413 { 140, "Viconics Electronics, Inc." },
5414 { 141, "Yaskawa America, Inc." },
5415 { 142, "DEOS control systems GmbH" },
5416 { 143, "Digitale Mess- und Steuersysteme AG" },
5417 { 144, "Fujitsu General Limited" },
5418 { 145, "Project Engineering S.r.l." },
5419 { 146, "Sanyo Electric Co., Ltd." },
5420 { 147, "Integrated Information Systems, Inc." },
5421 { 148, "Temco Controls, Ltd." },
5422 { 149, "Airtek International Inc." },
5423 { 150, "Advantech Corporation" },
5424 { 151, "Titan Products, Ltd." },
5425 { 152, "Regel Partners" },
5426 { 153, "National Environmental Product" },
5427 { 154, "Unitec Corporation" },
5428 { 155, "Kanden Engineering Company" },
5429 { 156, "Messner Gebäudetechnik GmbH" },
5430 { 157, "Integrated.CH" },
5431 { 158, "Price Industries" },
5432 { 159, "SE-Elektronic GmbH" },
5433 { 160, "Rockwell Automation" },
5434 { 161, "Enflex Corp." },
5435 { 162, "ASI Controls" },
5436 { 163, "SysMik GmbH Dresden" },
5437 { 164, "HSC Regelungstechnik GmbH" },
5438 { 165, "Smart Temp Australia Pty. Ltd." },
5439 { 166, "Cooper Controls" },
5440 { 167, "Duksan Mecasys Co., Ltd." },
5441 { 168, "Fuji IT Co., Ltd." },
5442 { 169, "Vacon Plc" },
5443 { 170, "Leader Controls" },
5444 { 171, "ABB (Formerly Cylon Controls, Ltd)" },
5445 { 172, "Compas" },
5446 { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
5447 { 174, "Building Control Integrators" },
5448 { 175, "ITG Worldwide (M) Sdn Bhd" },
5449 { 176, "Lutron Electronics Co., Inc." },
5450 { 177, "Cooper-Atkins Corporation" },
5451 { 178, "LOYTEC Electronics GmbH" },
5452 { 179, "ProLon" },
5453 { 180, "Mega Controls Limited" },
5454 { 181, "Micro Control Systems, Inc." },
5455 { 182, "Kiyon, Inc." },
5456 { 183, "Dust Networks" },
5457 { 184, "Advanced Building Automation Systems" },
5458 { 185, "Hermos AG" },
5459 { 186, "CEZIM" },
5460 { 187, "Softing" },
5461 { 188, "Lynxspring, Inc." },
5462 { 189, "Schneider Toshiba Inverter Europe" },
5463 { 190, "Danfoss Drives A/S" },
5464 { 191, "Eaton Corporation" },
5465 { 192, "Matyca S.A." },
5466 { 193, "Botech AB" },
5467 { 194, "Noveo, Inc." },
5468 { 195, "AMEV" },
5469 { 196, "Yokogawa Electric Corporation" },
5470 { 197, "Bosch Building Automation GmbH" },
5471 { 198, "Exact Logic" },
5472 { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
5473 { 200, "Kandenko Co., Ltd." },
5474 { 201, "DTF, Daten-Technik Fries" },
5475 { 202, "Klimasoft, Ltd." },
5476 { 203, "Toshiba Schneider Inverter Corporation" },
5477 { 204, "Control Applications, Ltd." },
5478 { 205, "CIMON CO., Ltd." },
5479 { 206, "Onicon Incorporated" },
5480 { 207, "Automation Displays, Inc." },
5481 { 208, "Control Solutions, Inc." },
5482 { 209, "Remsdaq Limited" },
5483 { 210, "NTT Facilities, Inc." },
5484 { 211, "VIPA GmbH" },
5485 { 212, "TSC21 Association of Japan" },
5486 { 213, "Strato Automation" },
5487 { 214, "HRW Limited" },
5488 { 215, "Lighting Control & Design, Inc." },
5489 { 216, "Mercy Electronic and Electrical Industries" },
5490 { 217, "Samsung SDS Co., Ltd" },
5491 { 218, "Impact Facility Solutions, Inc." },
5492 { 219, "Aircuity" },
5493 { 220, "Control Techniques, Ltd." },
5494 { 221, "OpenGeneral Pty., Ltd." },
5495 { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
5496 { 223, "Franklin Electric" },
5497 { 224, "Chloride Power Protection Company" },
5498 { 225, "Computrols, Inc." },
5499 { 226, "Phoenix Contact GmbH & Co. KG" },
5500 { 227, "Grundfos Management A/S" },
5501 { 228, "Ridder Drive Systems" },
5502 { 229, "Soft Device SDN BHD" },
5503 { 230, "Integrated Control Technology Limited" },
5504 { 231, "AIRxpert Systems, Inc." },
5505 { 232, "Microtrol Limited" },
5506 { 233, "Red Lion Controls" },
5507 { 234, "Digital Electronics Corporation" },
5508 { 235, "Ennovatis GmbH" },
5509 { 236, "Serotonin Software Technologies, Inc." },
5510 { 237, "LS Industrial Systems Co., Ltd." },
5511 { 238, "Square D Company" },
5512 { 239, "S Squared Innovations, Inc." },
5513 { 240, "Aricent Ltd." },
5514 { 241, "EtherMetrics, LLC" },
5515 { 242, "Industrial Control Communications, Inc." },
5516 { 243, "Paragon Controls, Inc." },
5517 { 244, "A. O. Smith Corporation" },
5518 { 245, "Contemporary Control Systems, Inc." },
5519 { 246, "HMS Industrial Networks SLU" },
5520 { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
5521 { 248, "Heat-Timer Corporation" },
5522 { 249, "Ingrasys Technology, Inc." },
5523 { 250, "Costerm Building Automation" },
5524 { 251, "WILO SE" },
5525 { 252, "Embedia Technologies Corp." },
5526 { 253, "Technilog" },
5527 { 254, "HR Controls Ltd. & Co. KG" },
5528 { 255, "Lennox International, Inc." },
5529 { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
5530 { 257, "Thermomax, Ltd." },
5531 { 258, "ELCON Electronic Control, Ltd." },
5532 { 259, "Larmia Control AB" },
5533 { 260, "BACnet Stack at SourceForge" },
5534 { 261, "G4S Security Services A/S" },
5535 { 262, "Exor International S.p.A." },
5536 { 263, "Cristal Controles" },
5537 { 264, "Regin AB" },
5538 { 265, "Dimension Software, Inc." },
5539 { 266, "SynapSense Corporation" },
5540 { 267, "Beijing Nantree Electronic Co., Ltd." },
5541 { 268, "Camus Hydronics Ltd." },
5542 { 269, "Kawasaki Heavy Industries, Ltd." },
5543 { 270, "Critical Environment Technologies" },
5544 { 271, "ILSHIN IBS Co., Ltd." },
5545 { 272, "ELESTA Energy Control AG" },
5546 { 273, "KROPMAN Installatietechniek" },
5547 { 274, "Baldor Electric Company" },
5548 { 275, "INGA mbH" },
5549 { 276, "GE Consumer & Industrial" },
5550 { 277, "Functional Devices, Inc." },
5551 { 278, "StudioSC" },
5552 { 279, "M-System Co., Ltd." },
5553 { 280, "Yokota Co., Ltd." },
5554 { 281, "Hitranse Technology Co., LTD" },
5555 { 282, "Vigilent Corporation" },
5556 { 283, "Kele, Inc." },
5557 { 284, "BELIMO Automation AG" },
5558 { 285, "Gentec" },
5559 { 286, "Embedded Science Labs, LLC" },
5560 { 287, "Parker Hannifin Corporation" },
5561 { 288, "MaCaPS International Limited" },
5562 { 289, "Link4 Corporation" },
5563 { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
5564 { 291, "Pribusin, Inc." },
5565 { 292, "Advantage Controls" },
5566 { 293, "Critical Room Control" },
5567 { 294, "LEGRAND" },
5568 { 295, "Tongdy Control Technology Co., Ltd." },
5569 { 296, "ISSARO Integrierte Systemtechnik" },
5570 { 297, "Pro-Dev Industries" },
5571 { 298, "DRI-STEEM" },
5572 { 299, "Creative Electronic GmbH" },
5573 { 300, "Swegon AB" },
5574 { 301, "FIRVENA s.r.o." },
5575 { 302, "Hitachi Appliances, Inc." },
5576 { 303, "Real Time Automation, Inc." },
5577 { 304, "ITEC Hankyu-Hanshin Co." },
5578 { 305, "Cyrus E&M Engineering Co., Ltd." },
5579 { 306, "Badger Meter" },
5580 { 307, "Cirrascale Corporation" },
5581 { 308, "Elesta GmbH Building Automation" },
5582 { 309, "Securiton" },
5583 { 310, "OSlsoft, Inc." },
5584 { 311, "Hanazeder Electronic GmbH" },
5585 { 312, "Honeywell Security Deutschland, Novar GmbH" },
5586 { 313, "Siemens Industry, Inc." },
5587 { 314, "ETM Professional Control GmbH" },
5588 { 315, "Meitav-tec, Ltd." },
5589 { 316, "Janitza Electronics GmbH" },
5590 { 317, "MKS Nordhausen" },
5591 { 318, "De Gier Drive Systems B.V." },
5592 { 319, "Cypress Envirosystems" },
5593 { 320, "SMARTron s.r.o." },
5594 { 321, "Verari Systems, Inc." },
5595 { 322, "K-W Electronic Service, Inc." },
5596 { 323, "ALFA-SMART Energy Management" },
5597 { 324, "Telkonet, Inc." },
5598 { 325, "Securiton GmbH" },
5599 { 326, "Cemtrex, Inc." },
5600 { 327, "Performance Technologies, Inc." },
5601 { 328, "Xtralis (Aust) Pty Ltd" },
5602 { 329, "TROX GmbH" },
5603 { 330, "Beijing Hysine Technology Co., Ltd" },
5604 { 331, "RCK Controls, Inc." },
5605 { 332, "Distech Controls SAS" },
5606 { 333, "Novar/Honeywell" },
5607 { 334, "S4 Integration Solutions" },
5608 { 335, "Schneider Electric" },
5609 { 336, "LHA Systems" },
5610 { 337, "GHM engineering Group, Inc." },
5611 { 338, "Cllimalux S.A." },
5612 { 339, "VAISALA Oyj" },
5613 { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
5614 { 341, "SCADAmetrics" },
5615 { 342, "POWERPEG NSI Limited" },
5616 { 343, "BACnet Interoperability Testing Services, Inc." },
5617 { 344, "Teco a.s." },
5618 { 345, "Plexus Technology, Inc." },
5619 { 346, "Energy Focus, Inc." },
5620 { 347, "Powersmiths International Corp." },
5621 { 348, "Nichibei Co., Ltd." },
5622 { 349, "HKC Technology Ltd." },
5623 { 350, "Ovation Networks, Inc." },
5624 { 351, "Setra Systems" },
5625 { 352, "AVG Automation" },
5626 { 353, "ZXC Ltd." },
5627 { 354, "Byte Sphere" },
5628 { 355, "Generiton Co., Ltd." },
5629 { 356, "Holter Regelarmaturen GmbH & Co. KG" },
5630 { 357, "Bedford Instruments, LLC" },
5631 { 358, "Standair Inc." },
5632 { 359, "WEG Automation – R&D" },
5633 { 360, "Prolon Control Systems ApS" },
5634 { 361, "Inneasoft" },
5635 { 362, "ConneXSoft GmbH" },
5636 { 363, "CEAG Notlichtsysteme GmbH" },
5637 { 364, "Distech Controls Inc." },
5638 { 365, "Industrial Technology Research Institute" },
5639 { 366, "ICONICS, Inc." },
5640 { 367, "IQ Controls s.c." },
5641 { 368, "OJ Electronics A/S" },
5642 { 369, "Rolbit Ltd." },
5643 { 370, "Synapsys Solutions Ltd." },
5644 { 371, "ACME Engineering Prod. Ltd." },
5645 { 372, "Zener Electric Pty, Ltd." },
5646 { 373, "Selectronix, Inc." },
5647 { 374, "Gorbet & Banerjee, LLC." },
5648 { 375, "IME" },
5649 { 376, "Stephen H. Dawson Computer Service" },
5650 { 377, "Accutrol, LLC" },
5651 { 378, "Schneider Elektronik GmbH" },
5652 { 379, "Alpha-Inno Tec GmbH" },
5653 { 380, "ADMMicro, Inc." },
5654 { 381, "Greystone Energy Systems, Inc." },
5655 { 382, "CAP Technologie" },
5656 { 383, "KeRo Systems" },
5657 { 384, "Domat Control System s.r.o." },
5658 { 385, "Efektronics Pty. Ltd." },
5659 { 386, "Hekatron Vertriebs GmbH" },
5660 { 387, "Securiton AG" },
5661 { 388, "Carlo Gavazzi Controls SpA" },
5662 { 389, "Chipkin Automation Systems" },
5663 { 390, "Savant Systems, LLC" },
5664 { 391, "Simmtronic Lighting Controls" },
5665 { 392, "Abelko Innovation AB" },
5666 { 393, "Seresco Technologies Inc." },
5667 { 394, "IT Watchdogs" },
5668 { 395, "Automation Assist Japan Corp." },
5669 { 396, "Thermokon Sensortechnik GmbH" },
5670 { 397, "EGauge Systems, LLC" },
5671 { 398, "Quantum Automation (ASIA) PTE, Ltd." },
5672 { 399, "Toshiba Lighting & Technology Corp." },
5673 { 400, "SPIN Engenharia de Automação Ltda." },
5674 { 401, "Logistics Systems & Software Services India PVT. Ltd." },
5675 { 402, "Delta Controls Integration Products" },
5676 { 403, "Focus Media" },
5677 { 404, "LUMEnergi Inc." },
5678 { 405, "Kara Systems" },
5679 { 406, "RF Code, Inc." },
5680 { 407, "Fatek Automation Corp." },
5681 { 408, "JANDA Software Company, LLC" },
5682 { 409, "Open System Solutions Limited" },
5683 { 410, "Intelec Systems PTY Ltd." },
5684 { 411, "Ecolodgix, LLC" },
5685 { 412, "Douglas Lighting Controls" },
5686 { 413, "iSAtech GmbH" },
5687 { 414, "AREAL" },
5688 { 415, "Beckhoff Automation" },
5689 { 416, "IPAS GmbH" },
5690 { 417, "KE2 Therm Solutions" },
5691 { 418, "Base2Products" },
5692 { 419, "DTL Controls, LLC" },
5693 { 420, "INNCOM International, Inc." },
5694 { 421, "METZ CONNECT GmbH" },
5695 { 422, "Greentrol Automation, Inc" },
5696 { 423, "BELIMO Automation AG" },
5697 { 424, "Samsung Heavy Industries Co, Ltd" },
5698 { 425, "Triacta Power Technologies, Inc." },
5699 { 426, "Globestar Systems" },
5700 { 427, "MLB Advanced Media, LP" },
5701 { 428, "SWG Stuckmann Wirtschaftliche Gebäudesysteme GmbH" },
5702 { 429, "SensorSwitch" },
5703 { 430, "Multitek Power Limited" },
5704 { 431, "Aquametro AG" },
5705 { 432, "LG Electronics Inc." },
5706 { 433, "Electronic Theatre Controls, Inc." },
5707 { 434, "Mitsubishi Electric Corporation Nagoya Works" },
5708 { 435, "Delta Electronics, Inc." },
5709 { 436, "Elma Kurtalj, Ltd." },
5710 { 437, "Tyco Fire & Security GmbH" },
5711 { 438, "Nedap Security Management" },
5712 { 439, "ESC Automation Inc." },
5713 { 440, "DSP4YOU Ltd." },
5714 { 441, "GE Sensing and Inspection Technologies" },
5715 { 442, "Embedded Systems SIA" },
5716 { 443, "BEFEGA GmbH" },
5717 { 444, "Baseline Inc." },
5718 { 445, "Key2Act" },
5719 { 446, "OEMCtrl" },
5720 { 447, "Clarkson Controls Limited" },
5721 { 448, "Rogerwell Control System Limited" },
5722 { 449, "SCL Elements" },
5723 { 450, "Hitachi Ltd." },
5724 { 451, "Newron System SA" },
5725 { 452, "BEVECO Gebouwautomatisering BV" },
5726 { 453, "Streamside Solutions" },
5727 { 454, "Yellowstone Soft" },
5728 { 455, "Oztech Intelligent Systems Pty Ltd." },
5729 { 456, "Novelan GmbH" },
5730 { 457, "Flexim Americas Corporation" },
5731 { 458, "ICP DAS Co., Ltd." },
5732 { 459, "CARMA Industries Inc." },
5733 { 460, "Log-One Ltd." },
5734 { 461, "TECO Electric & Machinery Co., Ltd." },
5735 { 462, "ConnectEx, Inc." },
5736 { 463, "Turbo DDC Südwest" },
5737 { 464, "Quatrosense Environmental Ltd." },
5738 { 465, "Fifth Light Technology Ltd." },
5739 { 466, "Scientific Solutions, Ltd." },
5740 { 467, "Controller Area Network Solutions (M) Sdn Bhd" },
5741 { 468, "RESOL – Elektronische Regelungen GmbH" },
5742 { 469, "RPBUS LLC" },
5743 { 470, "BRS Sistemas Eletronicos" },
5744 { 471, "WindowMaster A/S" },
5745 { 472, "Sunlux Technologies Ltd." },
5746 { 473, "Measurlogic" },
5747 { 474, "Frimat GmbH" },
5748 { 475, "Spirax Sarco" },
5749 { 476, "Luxtron" },
5750 { 477, "Raypak Inc" },
5751 { 478, "Air Monitor Corporation" },
5752 { 479, "Regler Och Webbteknik Sverige (ROWS)" },
5753 { 480, "Intelligent Lighting Controls Inc." },
5754 { 481, "Sanyo Electric Industry Co., Ltd" },
5755 { 482, "E-Mon Energy Monitoring Products" },
5756 { 483, "Digital Control Systems" },
5757 { 484, "ATI Airtest Technologies, Inc." },
5758 { 485, "SCS SA" },
5759 { 486, "HMS Industrial Networks AB" },
5760 { 487, "Shenzhen Universal Intellisys Co Ltd" },
5761 { 488, "EK Intellisys Sdn Bhd" },
5762 { 489, "SysCom" },
5763 { 490, "Firecom, Inc." },
5764 { 491, "ESA Elektroschaltanlagen Grimma GmbH" },
5765 { 492, "Kumahira Co Ltd" },
5766 { 493, "Hotraco" },
5767 { 494, "SABO Elektronik GmbH" },
5768 { 495, "Equip’Trans" },
5769 { 496, "Temperature Control Specialities Co., Inc (TCS)" },
5770 { 497, "FlowCon International A/S" },
5771 { 498, "ThyssenKrupp Elevator Americas" },
5772 { 499, "Abatement Technologies" },
5773 { 500, "Continental Control Systems, LLC" },
5774 { 501, "WISAG Automatisierungstechnik GmbH & Co KG" },
5775 { 502, "EasyIO" },
5776 { 503, "EAP-Electric GmbH" },
5777 { 504, "Hardmeier" },
5778 { 505, "Mircom Group of Companies" },
5779 { 506, "Quest Controls" },
5780 { 507, "Mestek, Inc" },
5781 { 508, "Pulse Energy" },
5782 { 509, "Tachikawa Corporation" },
5783 { 510, "University of Nebraska-Lincoln" },
5784 { 511, "Redwood Systems" },
5785 { 512, "PASStec Industrie-Elektronik GmbH" },
5786 { 513, "NgEK, Inc." },
5787 { 514, "t-mac Technologies" },
5788 { 515, "Jireh Energy Tech Co., Ltd." },
5789 { 516, "Enlighted Inc." },
5790 { 517, "El-Piast Sp. Z o.o" },
5791 { 518, "NetxAutomation Software GmbH" },
5792 { 519, "Invertek Drives" },
5793 { 520, "Deutschmann Automation GmbH & Co. KG" },
5794 { 521, "EMU Electronic AG" },
5795 { 522, "Phaedrus Limited" },
5796 { 523, "Sigmatek GmbH & Co KG" },
5797 { 524, "Marlin Controls" },
5798 { 525, "Circutor, SA" },
5799 { 526, "UTC Fire & Security" },
5800 { 527, "DENT Instruments, Inc." },
5801 { 528, "FHP Manufacturing Company – Bosch Group" },
5802 { 529, "GE Intelligent Platforms" },
5803 { 530, "Inner Range Pty Ltd" },
5804 { 531, "GLAS Energy Technology" },
5805 { 532, "MSR-Electronic-GmbH" },
5806 { 533, "Energy Control Systems, Inc." },
5807 { 534, "EMT Controls" },
5808 { 535, "Daintree" },
5809 { 536, "EURO ICC d.o.o" },
5810 { 537, "TE Connectivity Energy" },
5811 { 538, "GEZE GmbH" },
5812 { 539, "NEC Corporation" },
5813 { 540, "Ho Cheung International Company Limited" },
5814 { 541, "Sharp Manufacturing Systems Corporation" },
5815 { 542, "DOT CONTROLS a.s." },
5816 { 543, "BeaconMedæs" },
5817 { 544, "Midea Commercial Aircon" },
5818 { 545, "WattMaster Controls" },
5819 { 546, "Kamstrup A/S" },
5820 { 547, "CA Computer Automation GmbH" },
5821 { 548, "Laars Heating Systems Company" },
5822 { 549, "Hitachi Systems, Ltd." },
5823 { 550, "Fushan AKE Electronic Engineering Co., Ltd." },
5824 { 551, "Toshiba International Corporation" },
5825 { 552, "Starman Systems, LLC" },
5826 { 553, "Samsung Techwin Co., Ltd." },
5827 { 554, "ISAS-Integrated Switchgear and Systems P/L" },
5828 { 555, "Reserved for ASHRAE" },
5829 { 556, "Obvius" },
5830 { 557, "Marek Guzik" },
5831 { 558, "Vortek Instruments, LLC" },
5832 { 559, "Universal Lighting Technologies" },
5833 { 560, "Myers Power Products, Inc." },
5834 { 561, "Vector Controls GmbH" },
5835 { 562, "Crestron Electronics, Inc." },
5836 { 563, "A&E Controls Limited" },
5837 { 564, "Projektomontaza A.D." },
5838 { 565, "Freeaire Refrigeration" },
5839 { 566, "Aqua Cooler Pty Limited" },
5840 { 567, "Basic Controls" },
5841 { 568, "GE Measurement and Control Solutions Advanced Sensors" },
5842 { 569, "EQUAL Networks" },
5843 { 570, "Millennial Net" },
5844 { 571, "APLI Ltd" },
5845 { 572, "Electro Industries/GaugeTech" },
5846 { 573, "SangMyung University" },
5847 { 574, "Coppertree Analytics, Inc." },
5848 { 575, "CoreNetiX GmbH" },
5849 { 576, "Acutherm" },
5850 { 577, "Dr. Riedel Automatisierungstechnik GmbH" },
5851 { 578, "Shina System Co., Ltd" },
5852 { 579, "Iqapertus" },
5853 { 580, "PSE Technology" },
5854 { 581, "BA Systems" },
5855 { 582, "BTICINO" },
5856 { 583, "Monico, Inc." },
5857 { 584, "iCue" },
5858 { 585, "tekmar Control Systems Ltd." },
5859 { 586, "Control Technology Corporation" },
5860 { 587, "GFAE GmbH" },
5861 { 588, "BeKa Software GmbH" },
5862 { 589, "Isoil Industria SpA" },
5863 { 590, "Home Systems Consulting SpA" },
5864 { 591, "Socomec" },
5865 { 592, "Everex Communications, Inc." },
5866 { 593, "CET Electric Technology, Inc." },
5867 { 594, "Atrila GmbH" },
5868 { 595, "WingTechs" },
5869 { 596, "Shenzhen Mek Intellisys Pte Ltd." },
5870 { 597, "Nestfield Co., Ltd." },
5871 { 598, "Swissphone Telecom AG" },
5872 { 599, "PNTECH JSC" },
5873 { 600, "Horner APG, LLC" },
5874 { 601, "PVI Industries, LLC" },
5875 { 602, "Ela-compil" },
5876 { 603, "Pegasus Automation International LLC" },
5877 { 604, "Wight Electronic Services Ltd." },
5878 { 605, "Marcom" },
5879 { 606, "Exhausto A/S" },
5880 { 607, "Dwyer Instruments, Inc." },
5881 { 608, "Link GmbH" },
5882 { 609, "Oppermann Regelgerate GmbH" },
5883 { 610, "NuAire, Inc." },
5884 { 611, "Nortec Humidity, Inc." },
5885 { 612, "Bigwood Systems, Inc." },
5886 { 613, "Enbala Power Networks" },
5887 { 614, "Inter Energy Co., Ltd." },
5888 { 615, "ETC" },
5889 { 616, "COMELEC S.A.R.L" },
5890 { 617, "Pythia Technologies" },
5891 { 618, "TrendPoint Systems, Inc." },
5892 { 619, "AWEX" },
5893 { 620, "Eurevia" },
5894 { 621, "Kongsberg E-lon AS" },
5895 { 622, "FlaktWoods" },
5896 { 623, "E + E Elektronik GES M.B.H." },
5897 { 624, "ARC Informatique" },
5898 { 625, "SKIDATA AG" },
5899 { 626, "WSW Solutions" },
5900 { 627, "Trefon Electronic GmbH" },
5901 { 628, "Dongseo System" },
5902 { 629, "Kanontec Intelligence Technology Co., Ltd." },
5903 { 630, "EVCO S.p.A." },
5904 { 631, "Accuenergy (Canada) Inc." },
5905 { 632, "SoftDEL" },
5906 { 633, "Orion Energy Systems, Inc." },
5907 { 634, "Roboticsware" },
5908 { 635, "DOMIQ Sp. z o.o." },
5909 { 636, "Solidyne" },
5910 { 637, "Elecsys Corporation" },
5911 { 638, "Conditionaire International Pty. Limited" },
5912 { 639, "Quebec, Inc." },
5913 { 640, "Homerun Holdings" },
5914 { 641, "Murata Americas" },
5915 { 642, "Comptek" },
5916 { 643, "Westco Systems, Inc." },
5917 { 644, "Advancis Software & Services GmbH" },
5918 { 645, "Intergrid, LLC" },
5919 { 646, "Markerr Controls, Inc." },
5920 { 647, "Toshiba Elevator and Building Systems Corporation" },
5921 { 648, "Spectrum Controls, Inc." },
5922 { 649, "Mkservice" },
5923 { 650, "Fox Thermal Instruments" },
5924 { 651, "SyxthSense Ltd" },
5925 { 652, "DUHA System S R.O." },
5926 { 653, "NIBE" },
5927 { 654, "Melink Corporation" },
5928 { 655, "Fritz-Haber-Institut" },
5929 { 656, "MTU Onsite Energy GmbH, Gas Power Systems" },
5930 { 657, "Omega Engineering, Inc." },
5931 { 658, "Avelon" },
5932 { 659, "Ywire Technologies, Inc." },
5933 { 660, "M.R. Engineering Co., Ltd." },
5934 { 661, "Lochinvar, LLC" },
5935 { 662, "Sontay Limited" },
5936 { 663, "GRUPA Slawomir Chelminski" },
5937 { 664, "Arch Meter Corporation" },
5938 { 665, "Senva, Inc." },
5939 { 666, "Reserved for ASHRAE" },
5940 { 667, "FM-Tec" },
5941 { 668, "Systems Specialists, Inc." },
5942 { 669, "SenseAir" },
5943 { 670, "AB IndustrieTechnik Srl" },
5944 { 671, "Cortland Research, LLC" },
5945 { 672, "MediaView" },
5946 { 673, "VDA Elettronica" },
5947 { 674, "CSS, Inc." },
5948 { 675, "Tek-Air Systems, Inc." },
5949 { 676, "ICDT" },
5950 { 677, "The Armstrong Monitoring Corporation" },
5951 { 678, "DIXELL S.r.l" },
5952 { 679, "Lead System, Inc." },
5953 { 680, "ISM EuroCenter S.A." },
5954 { 681, "TDIS" },
5955 { 682, "Trade FIDES" },
5956 { 683, "Knürr GmbH (Emerson Network Power)" },
5957 { 684, "Resource Data Management" },
5958 { 685, "Abies Technology, Inc." },
5959 { 686, "UAB Komfovent" },
5960 { 687, "MIRAE Electrical Mfg. Co., Ltd." },
5961 { 688, "HunterDouglas Architectural Projects Scandinavia ApS" },
5962 { 689, "RUNPAQ Group Co., Ltd" },
5963 { 690, "Unicard SA" },
5964 { 691, "IE Technologies" },
5965 { 692, "Ruskin Manufacturing" },
5966 { 693, "Calon Associates Limited" },
5967 { 694, "Contec Co., Ltd." },
5968 { 695, "iT GmbH" },
5969 { 696, "Autani Corporation" },
5970 { 697, "Christian Fortin" },
5971 { 698, "HDL" },
5972 { 699, "IPID Sp. Z.O.O Limited" },
5973 { 700, "Fuji Electric Co., Ltd" },
5974 { 701, "View, Inc." },
5975 { 702, "Samsung S1 Corporation" },
5976 { 703, "New Lift" },
5977 { 704, "VRT Systems" },
5978 { 705, "Motion Control Engineering, Inc." },
5979 { 706, "Weiss Klimatechnik GmbH" },
5980 { 707, "Elkon" },
5981 { 708, "Eliwell Controls S.r.l." },
5982 { 709, "Japan Computer Technos Corp" },
5983 { 710, "Rational Network ehf" },
5984 { 711, "Magnum Energy Solutions, LLC" },
5985 { 712, "MelRok" },
5986 { 713, "VAE Group" },
5987 { 714, "LGCNS" },
5988 { 715, "Berghof Automationstechnik GmbH" },
5989 { 716, "Quark Communications, Inc." },
5990 { 717, "Sontex" },
5991 { 718, "mivune AG" },
5992 { 719, "Panduit" },
5993 { 720, "Smart Controls, LLC" },
5994 { 721, "Compu-Aire, Inc." },
5995 { 722, "Sierra" },
5996 { 723, "ProtoSense Technologies" },
5997 { 724, "Eltrac Technologies Pvt Ltd" },
5998 { 725, "Bektas Invisible Controls GmbH" },
5999 { 726, "Entelec" },
6000 { 727, "INNEXIV" },
6001 { 728, "Covenant" },
6002 { 729, "Davitor AB" },
6003 { 730, "TongFang Technovator" },
6004 { 731, "Building Robotics, Inc." },
6005 { 732, "HSS-MSR UG" },
6006 { 733, "FramTack LLC" },
6007 { 734, "B. L. Acoustics, Ltd." },
6008 { 735, "Traxxon Rock Drills, Ltd" },
6009 { 736, "Franke" },
6010 { 737, "Wurm GmbH & Co" },
6011 { 738, "AddENERGIE" },
6012 { 739, "Mirle Automation Corporation" },
6013 { 740, "Ibis Networks" },
6014 { 741, "ID-KARTA s.r.o." },
6015 { 742, "Anaren, Inc." },
6016 { 743, "Span, Incorporated" },
6017 { 744, "Bosch Thermotechnology Corp" },
6018 { 745, "DRC Technology S.A." },
6019 { 746, "Shanghai Energy Building Technology Co, Ltd" },
6020 { 747, "Fraport AG" },
6021 { 748, "Flowgroup" },
6022 { 749, "Skytron Energy, GmbH" },
6023 { 750, "ALTEL Wicha, Golda Sp. J." },
6024 { 751, "Drupal" },
6025 { 752, "Axiomatic Technology, Ltd" },
6026 { 753, "Bohnke + Partner" },
6027 { 754, "Function1" },
6028 { 755, "Optergy Pty, Ltd" },
6029 { 756, "LSI Virticus" },
6030 { 757, "Konzeptpark GmbH" },
6031 { 758, "NX Lighting Controls" },
6032 { 759, "eCurv, Inc." },
6033 { 760, "Agnosys GmbH" },
6034 { 761, "Shanghai Sunfull Automation Co., LTD" },
6035 { 762, "Kurz Instruments, Inc." },
6036 { 763, "Cias Elettronica S.r.l." },
6037 { 764, "Multiaqua, Inc." },
6038 { 765, "BlueBox" },
6039 { 766, "Sensidyne" },
6040 { 767, "Viessmann Elektronik GmbH" },
6041 { 768, "ADFweb.com srl" },
6042 { 769, "Gaylord Industries" },
6043 { 770, "Majur Ltd." },
6044 { 771, "Shanghai Huilin Technology Co., Ltd." },
6045 { 772, "Exotronic" },
6046 { 773, "SAFECONTROL s.r.o." },
6047 { 774, "Amatis" },
6048 { 775, "Universal Electric Corporation" },
6049 { 776, "iBACnet" },
6050 { 777, "Reserved for ASHRAE" },
6051 { 778, "Smartrise Engineering, Inc." },
6052 { 779, "Miratron, Inc." },
6053 { 780, "SmartEdge" },
6054 { 781, "Mitsubishi Electric Australia Pty Ltd" },
6055 { 782, "Triangle Research International Ptd Ltd" },
6056 { 783, "Produal Oy" },
6057 { 784, "Milestone Systems A/S" },
6058 { 785, "Trustbridge" },
6059 { 786, "Feedback Solutions" },
6060 { 787, "IES" },
6061 { 788, "ABB Power Protection SA" },
6062 { 789, "Riptide IO" },
6063 { 790, "Messerschmitt Systems AG" },
6064 { 791, "Dezem Energy Controlling" },
6065 { 792, "MechoSystems" },
6066 { 793, "evon GmbH" },
6067 { 794, "CS Lab GmbH" },
6068 { 795, "8760 Enterprises, Inc." },
6069 { 796, "Touche Controls" },
6070 { 797, "Ontrol Teknik Malzeme San. ve Tic. A.S." },
6071 { 798, "Uni Control System Sp. Z o.o." },
6072 { 799, "Weihai Ploumeter Co., Ltd" },
6073 { 800, "Elcom International Pvt. Ltd" },
6074 { 801, "Signify" },
6075 { 802, "AutomationDirect" },
6076 { 803, "Paragon Robotics" },
6077 { 804, "SMT System & Modules Technology AG" },
6078 { 805, "Radix IoT LLC" },
6079 { 806, "CMR Controls Ltd" },
6080 { 807, "Innovari, Inc." },
6081 { 808, "ABB Control Products" },
6082 { 809, "Gesellschaft fur Gebäudeautomation mbH" },
6083 { 810, "RODI Systems Corp." },
6084 { 811, "Nextek Power Systems" },
6085 { 812, "Creative Lighting" },
6086 { 813, "WaterFurnace International" },
6087 { 814, "Mercury Security" },
6088 { 815, "Hisense (Shandong) Air-Conditioning Co., Ltd." },
6089 { 816, "Layered Solutions, Inc." },
6090 { 817, "Leegood Automatic System, Inc." },
6091 { 818, "Shanghai Restar Technology Co., Ltd." },
6092 { 819, "Reimann Ingenieurbüro" },
6093 { 820, "LynTec" },
6094 { 821, "HTP" },
6095 { 822, "Elkor Technologies, Inc." },
6096 { 823, "Bentrol Pty Ltd" },
6097 { 824, "Team-Control Oy" },
6098 { 825, "NextDevice, LLC" },
6099 { 826, "iSMA CONTROLLI S.p.a." },
6100 { 827, "King I Electronics Co., Ltd" },
6101 { 828, "SAMDAV" },
6102 { 829, "Next Gen Industries Pvt. Ltd." },
6103 { 830, "Entic LLC" },
6104 { 831, "ETAP" },
6105 { 832, "Moralle Electronics Limited" },
6106 { 833, "Leicom AG" },
6107 { 834, "Watts Regulator Company" },
6108 { 835, "S.C. Orbtronics S.R.L." },
6109 { 836, "Gaussan Technologies" },
6110 { 837, "WEBfactory GmbH" },
6111 { 838, "Ocean Controls" },
6112 { 839, "Messana Air-Ray Conditioning s.r.l." },
6113 { 840, "Hangzhou BATOWN Technology Co. Ltd." },
6114 { 841, "Reasonable Controls" },
6115 { 842, "Servisys, Inc." },
6116 { 843, "halstrup-walcher GmbH" },
6117 { 844, "SWG Automation Fuzhou Limited" },
6118 { 845, "KSB Aktiengesellschaft" },
6119 { 846, "Hybryd Sp. z o.o." },
6120 { 847, "Helvatron AG" },
6121 { 848, "Oderon Sp. Z.O.O." },
6122 { 849, "mikolab" },
6123 { 850, "Exodraft" },
6124 { 851, "Hochhuth GmbH" },
6125 { 852, "Integrated System Technologies Ltd." },
6126 { 853, "Shanghai Cellcons Controls Co., Ltd" },
6127 { 854, "Emme Controls, LLC" },
6128 { 855, "Field Diagnostic Services, Inc." },
6129 { 856, "Ges Teknik A.S." },
6130 { 857, "Global Power Products, Inc." },
6131 { 858, "Option NV" },
6132 { 859, "BV-Control AG" },
6133 { 860, "Sigren Engineering AG" },
6134 { 861, "Shanghai Jaltone Technology Co., Ltd." },
6135 { 862, "MaxLine Solutions Ltd" },
6136 { 863, "Kron Instrumentos Elétricos Ltda" },
6137 { 864, "Thermo Matrix" },
6138 { 865, "Infinite Automation Systems, Inc." },
6139 { 866, "Vantage" },
6140 { 867, "Elecon Measurements Pvt Ltd" },
6141 { 868, "TBA" },
6142 { 869, "Carnes Company" },
6143 { 870, "Harman Professional" },
6144 { 871, "Nenutec Asia Pacific Pte Ltd" },
6145 { 872, "Gia NV" },
6146 { 873, "Kepware Tehnologies" },
6147 { 874, "Temperature Electronics Ltd" },
6148 { 875, "Packet Power" },
6149 { 876, "Project Haystack Corporation" },
6150 { 877, "DEOS Controls Americas Inc." },
6151 { 878, "Senseware Inc" },
6152 { 879, "MST Systemtechnik AG" },
6153 { 880, "Lonix Ltd" },
6154 { 881, "Gossen Metrawatt GmbH" },
6155 { 882, "Aviosys International Inc." },
6156 { 883, "Efficient Building Automation Corp." },
6157 { 884, "Accutron Instruments Inc." },
6158 { 885, "Vermont Energy Control Systems LLC" },
6159 { 886, "DCC Dynamics" },
6160 { 887, "B.E.G. Brück Electronic GmbH" },
6161 { 888, "Reserved for ASHRAE" },
6162 { 889, "NGBS Hungary Ltd." },
6163 { 890, "ILLUM Technology, LLC" },
6164 { 891, "Delta Controls Germany Limited" },
6165 { 892, "S+T Service & Technique S.A." },
6166 { 893, "SimpleSoft" },
6167 { 894, "Altair Engineering" },
6168 { 895, "EZEN Solution Inc." },
6169 { 896, "Fujitec Co. Ltd." },
6170 { 897, "Terralux" },
6171 { 898, "Annicom" },
6172 { 899, "Bihl+Wiedemann GmbH" },
6173 { 900, "Draper, Inc." },
6174 { 901, "Schüco International KG" },
6175 { 902, "Otis Elevator Company" },
6176 { 903, "Fidelix Oy" },
6177 { 904, "RAM GmbH Mess- und Regeltechnik" },
6178 { 905, "WEMS" },
6179 { 906, "Ravel Electronics Pvt Ltd" },
6180 { 907, "OmniMagni" },
6181 { 908, "Echelon" },
6182 { 909, "Intellimeter Canada, Inc." },
6183 { 910, "Bithouse Oy" },
6184 { 911, "Reserved for ASHRAE" },
6185 { 912, "BuildPulse" },
6186 { 913, "Shenzhen 1000 Building Automation Co. Ltd" },
6187 { 914, "AED Engineering GmbH" },
6188 { 915, "Güntner GmbH & Co. KG" },
6189 { 916, "KNXlogic" },
6190 { 917, "CIM Environmental Group" },
6191 { 918, "Flow Control" },
6192 { 919, "Lumen Cache, Inc." },
6193 { 920, "Ecosystem" },
6194 { 921, "Potter Electric Signal Company, LLC" },
6195 { 922, "Tyco Fire & Security S.p.A." },
6196 { 923, "Watanabe Electric Industry Co., Ltd." },
6197 { 924, "Causam Energy" },
6198 { 925, "W-tec AG" },
6199 { 926, "IMI Hydronic Engineering International SA" },
6200 { 927, "ARIGO Software" },
6201 { 928, "MSA Safety" },
6202 { 929, "Smart Solucoes Ltda – MERCATO" },
6203 { 930, "PIATRA Engineering" },
6204 { 931, "ODIN Automation Systems, LLC" },
6205 { 932, "Belparts NV" },
6206 { 933, "UAB, SALDA" },
6207 { 934, "Alre-IT Regeltechnik GmbH" },
6208 { 935, "Ingenieurbüro H. Lertes GmbH & Co. KG" },
6209 { 936, "Breathing Buildings" },
6210 { 937, "eWON SA" },
6211 { 938, "Cav. Uff. Giacomo Cimberio S.p.A" },
6212 { 939, "PKE Electronics AG" },
6213 { 940, "Allen" },
6214 { 941, "Kastle Systems" },
6215 { 942, "Logical Electro-Mechanical (EM) Systems, Inc." },
6216 { 943, "ppKinetics Instruments, LLC" },
6217 { 944, "Cathexis Technologies" },
6218 { 945, "Sylop sp. Z o.o. sp.k" },
6219 { 946, "Brauns Control GmbH" },
6220 { 947, "OMRON SOCIAL SOLUTIONS CO., LTD." },
6221 { 948, "Wildeboer Bauteile Gmbh" },
6222 { 949, "Shanghai Biens Technologies Ltd" },
6223 { 950, "Beijing HZHY Technology Co., Ltd" },
6224 { 951, "Building Clouds" },
6225 { 952, "The University of Sheffield-Department of Electronic and Electrical Engineering" },
6226 { 953, "Fabtronics Australia Pty Ltd" },
6227 { 954, "SLAT" },
6228 { 955, "Software Motor Corporation" },
6229 { 956, "Armstrong International Inc." },
6230 { 957, "Steril-Aire, Inc." },
6231 { 958, "Infinique" },
6232 { 959, "Arcom" },
6233 { 960, "Argo Performance, Ltd" },
6234 { 961, "Dialight" },
6235 { 962, "Ideal Technical Solutions" },
6236 { 963, "Neurobat AG" },
6237 { 964, "Neyer Software Consulting LLC" },
6238 { 965, "SCADA Technology Development Co., Ltd." },
6239 { 966, "Demand Logic Limited" },
6240 { 967, "GWA Group Limited" },
6241 { 968, "Occitaline" },
6242 { 969, "NAO Digital Co., Ltd." },
6243 { 970, "Shenzhen Chanslink Network Technology Co., Ltd." },
6244 { 971, "Samsung Electronics Co., Ltd." },
6245 { 972, "Mesa Laboratories, Inc." },
6246 { 973, "Fischer" },
6247 { 974, "OpSys Solutions Ltd." },
6248 { 975, "Advanced Devices Limited" },
6249 { 976, "Condair" },
6250 { 977, "INELCOM Ingenieria Electronica Comercial S.A." },
6251 { 978, "GridPoint, Inc." },
6252 { 979, "ADF Technologies Sdn Bhd" },
6253 { 980, "EPM, Inc." },
6254 { 981, "Lighting Controls Ltd" },
6255 { 982, "Perix Controls Ltd." },
6256 { 983, "AERCO International, Inc." },
6257 { 984, "KONE Inc." },
6258 { 985, "Ziehl-Abegg SE" },
6259 { 986, "Robot, S.A." },
6260 { 987, "Optigo Networks, Inc." },
6261 { 988, "Openmotics BVBA" },
6262 { 989, "Metropolitan Industries, Inc." },
6263 { 990, "Huawei Technologies Co., Ltd." },
6264 { 991, "Digital Lumens, Inc." },
6265 { 992, "Vanti" },
6266 { 993, "Cree Lighting" },
6267 { 994, "Richmond Heights SDN BHD" },
6268 { 995, "Payne-Sparkman Lighting Mangement" },
6269 { 996, "Ashcroft" },
6270 { 997, "Jet Controls Corp" },
6271 { 998, "Zumtobel Lighting GmbH" },
6272 { 999, "Reserved for ASHRAE" },
6273 { 1000, "Ekon GmbH" },
6274 { 1001, "Molex" },
6275 { 1002, "Maco Lighting Pty Ltd." },
6276 { 1003, "Axecon Corp." },
6277 { 1004, "Tensor plc" },
6278 { 1005, "Kaseman Environmental Control Equipment (Shanghai) Limited" },
6279 { 1006, "AB Axis Industries" },
6280 { 1007, "Netix Controls" },
6281 { 1008, "Eldridge Products, Inc." },
6282 { 1009, "Micronics" },
6283 { 1010, "Fortecho Solutions Ltd" },
6284 { 1011, "Sellers Manufacturing Company" },
6285 { 1012, "Rite-Hite Doors, Inc." },
6286 { 1013, "Violet Defense LLC" },
6287 { 1014, "Simna" },
6288 { 1015, "Multi-Énergie Best Inc." },
6289 { 1016, "Mega System Technologies, Inc." },
6290 { 1017, "Rheem" },
6291 { 1018, "Ing. Punzenberger COPA-DATA GmbH" },
6292 { 1019, "MEC Electronics GmbH" },
6293 { 1020, "Taco Comfort Solutions" },
6294 { 1021, "Alexander Maier GmbH" },
6295 { 1022, "Ecorithm, Inc." },
6296 { 1023, "Accurro Ltd" },
6297 { 1024, "ROMTECK Australia Pty Ltd" },
6298 { 1025, "Splash Monitoring Limited" },
6299 { 1026, "Light Application" },
6300 { 1027, "Logical Building Automation" },
6301 { 1028, "Exilight Oy" },
6302 { 1029, "Hager Electro SAS" },
6303 { 1030, "KLIF Co., LTD" },
6304 { 1031, "HygroMatik" },
6305 { 1032, "Daniel Mousseau Programmation & Electronique" },
6306 { 1033, "Aerionics Inc." },
6307 { 1034, "M2S Electronique Ltee" },
6308 { 1035, "Automation Components, Inc." },
6309 { 1036, "Niobrara Research & Development Corporation" },
6310 { 1037, "Netcom Sicherheitstechnik GmbH" },
6311 { 1038, "Lumel S.A." },
6312 { 1039, "Great Plains Industries, Inc." },
6313 { 1040, "Domotica Labs S.R.L" },
6314 { 1041, "Energy Cloud, Inc." },
6315 { 1042, "Vomatec" },
6316 { 1043, "Demma Companies" },
6317 { 1044, "Valsena" },
6318 { 1045, "Comsys Bärtsch AG" },
6319 { 1046, "bGrid" },
6320 { 1047, "MDJ Software Pty Ltd" },
6321 { 1048, "Dimonoff, Inc." },
6322 { 1049, "Edomo Systems, GmbH" },
6323 { 1050, "Effektiv, LLC" },
6324 { 1051, "SteamOVap" },
6325 { 1052, "grandcentrix GmbH" },
6326 { 1053, "Weintek Labs, Inc." },
6327 { 1054, "Intefox GmbH" },
6328 { 1055, "Radius22 Automation Company" },
6329 { 1056, "Ringdale, Inc." },
6330 { 1057, "Iwaki America" },
6331 { 1058, "Bractlet" },
6332 { 1059, "STULZ Air Technology Systems, Inc." },
6333 { 1060, "Climate Ready Engineering Pty Ltd" },
6334 { 1061, "Genea Energy Partners" },
6335 { 1062, "IoTall Chile" },
6336 { 1063, "IKS Co., Ltd." },
6337 { 1064, "Yodiwo AB" },
6338 { 1065, "TITAN electronic GmbH" },
6339 { 1066, "IDEC Corporation" },
6340 { 1067, "SIFRI SL" },
6341 { 1068, "Thermal Gas Systems Inc." },
6342 { 1069, "Building Automation Products, Inc." },
6343 { 1070, "Asset Mapping" },
6344 { 1071, "Smarteh Company" },
6345 { 1072, "Datapod (Australia) Pty Ltd." },
6346 { 1073, "Buildings Alive Pty Ltd" },
6347 { 1074, "Digital Elektronik" },
6348 { 1075, "Talent Automação e Tecnologia Ltda" },
6349 { 1076, "Norposh Limited" },
6350 { 1077, "Merkur Funksysteme AG" },
6351 { 1078, "Faster CZ spol. S.r.o" },
6352 { 1079, "Eco-Adapt" },
6353 { 1080, "Energocentrum Plus, s.r.o" },
6354 { 1081, "amBX UK Ltd" },
6355 { 1082, "Western Reserve Controls, Inc." },
6356 { 1083, "LayerZero Power Systems, Inc." },
6357 { 1084, "CIC Jan Hřebec s.r.o." },
6358 { 1085, "Sigrov BV" },
6359 { 1086, "ISYS-Intelligent Systems" },
6360 { 1087, "Gas Detection (Australia) Pty Ltd" },
6361 { 1088, "Kinco Automation (Shanghai) Ltd." },
6362 { 1089, "Lars Energy, LLC" },
6363 { 1090, "Flamefast (UK) Ltd." },
6364 { 1091, "Royal Service Air Conditioning" },
6365 { 1092, "Ampio Sp. Z o.o." },
6366 { 1093, "Inovonics Wireless Corporation" },
6367 { 1094, "Nvent Thermal Management" },
6368 { 1095, "Sinowell Control System Ltd" },
6369 { 1096, "Moxa Inc." },
6370 { 1097, "Matrix iControl SDN BHD" },
6371 { 1098, "PurpleSwift" },
6372 { 1099, "OTIM Technologies" },
6373 { 1100, "FlowMate Limited" },
6374 { 1101, "Degree Controls, Inc." },
6375 { 1102, "Fei Xing (Shanghai) Software Technologies Co., Ltd." },
6376 { 1103, "Berg GmbH" },
6377 { 1104, "ARENZ.IT" },
6378 { 1105, "Edelstrom Electronic Devices & Designing LLC" },
6379 { 1106, "Drive Connect, LLC" },
6380 { 1107, "DevelopNow" },
6381 { 1108, "Poort" },
6382 { 1109, "VMEIL Information (Shanghai) Ltd" },
6383 { 1110, "Rayleigh Instruments" },
6384 { 1111, "Reserved for ASHRAE" },
6385 { 1112, "CODESYS Development" },
6386 { 1113, "Smartware Technologies Group, LLC" },
6387 { 1114, "Polar Bear Solutions" },
6388 { 1115, "Codra" },
6389 { 1116, "Pharos Architectural Controls Ltd" },
6390 { 1117, "EngiNear Ltd." },
6391 { 1118, "Ad Hoc Electronics" },
6392 { 1119, "Unified Microsystems" },
6393 { 1120, "Industrieelektronik Brandenburg GmbH" },
6394 { 1121, "Hartmann GmbH" },
6395 { 1122, "Piscada" },
6396 { 1123, "KMB systems, s.r.o." },
6397 { 1124, "PowerTech Engineering AS" },
6398 { 1125, "Telefonbau Arthur Schwabe GmbH & Co. KG" },
6399 { 1126, "Wuxi Fistwelove Technology Co., Ltd." },
6400 { 1127, "Prysm" },
6401 { 1128, "STEINEL GmbH" },
6402 { 1129, "Georg Fischer JRG AG" },
6403 { 1130, "Make Develop SL" },
6404 { 1131, "Monnit Corporation" },
6405 { 1132, "Mirror Life Corporation" },
6406 { 1133, "Secure Meters Limited" },
6407 { 1134, "PECO" },
6408 { 1135, ".CCTECH, Inc." },
6409 { 1136, "LightFi Limited" },
6410 { 1137, "Nice Spa" },
6411 { 1138, "Fiber SenSys, Inc." },
6412 { 1139, "B&D Buchta und Degeorgi" },
6413 { 1140, "Ventacity Systems, Inc." },
6414 { 1141, "Hitachi-Johnson Controls Air Conditioning, Inc." },
6415 { 1142, "Sage Metering, Inc." },
6416 { 1143, "Andel Limited" },
6417 { 1144, "ECOSmart Technologies" },
6418 { 1145, "S.E.T." },
6419 { 1146, "Protec Fire Detection Spain SL" },
6420 { 1147, "AGRAMER UG" },
6421 { 1148, "Anylink Electronic GmbH" },
6422 { 1149, "Schindler, Ltd" },
6423 { 1150, "Jibreel Abdeen Est." },
6424 { 1151, "Fluidyne Control Systems Pvt. Ltd" },
6425 { 1152, "Prism Systems, Inc." },
6426 { 1153, "Enertiv" },
6427 { 1154, "Mirasoft GmbH & Co. KG" },
6428 { 1155, "DUALTECH IT" },
6429 { 1156, "Countlogic, LLC" },
6430 { 1157, "Kohler" },
6431 { 1158, "Chen Sen Controls Co., Ltd." },
6432 { 1159, "Greenheck" },
6433 { 1160, "Intwine Connect, LLC" },
6434 { 1161, "Karlborgs Elkontroll" },
6435 { 1162, "Datakom" },
6436 { 1163, "Hoga Control AS" },
6437 { 1164, "Cool Automation" },
6438 { 1165, "Inter Search Co., Ltd" },
6439 { 1166, "DABBEL-Automation Intelligence GmbH" },
6440 { 1167, "Gadgeon Engineering Smartness" },
6441 { 1168, "Coster Group S.r.l." },
6442 { 1169, "Walter Müller AG" },
6443 { 1170, "Fluke" },
6444 { 1171, "Quintex Systems Ltd" },
6445 { 1172, "Senfficient SDN BHD" },
6446 { 1173, "Nube iO Operations Pty Ltd" },
6447 { 1174, "DAS Integrator Pte Ltd" },
6448 { 1175, "CREVIS Co., Ltd" },
6449 { 1176, "iSquared software inc." },
6450 { 1177, "KTG GmbH" },
6451 { 1178, "POK Group Oy" },
6452 { 1179, "Adiscom" },
6453 { 1180, "Incusense" },
6454 { 1181, "75F" },
6455 { 1182, "Anord Mardix, Inc." },
6456 { 1183, "HOSCH Gebäudeautomation Neue Produkte GmbH" },
6457 { 1184, "Bosch.IO GmbH" },
6458 { 1185, "Royal Boon Edam International B.V." },
6459 { 1186, "Clack Corporation" },
6460 { 1187, "Unitex Controls LLC" },
6461 { 1188, "KTC Göteborg AB" },
6462 { 1189, "Interzon AB" },
6463 { 1190, "ISDE ING SL" },
6464 { 1191, "ABM automation building messaging GmbH" },
6465 { 1192, "Kentec Electronics Ltd" },
6466 { 1193, "Emerson Commercial and Residential Solutions" },
6467 { 1194, "Powerside" },
6468 { 1195, "SMC Group" },
6469 { 1196, "EOS Weather Instruments" },
6470 { 1197, "Zonex Systems" },
6471 { 1198, "Generex Systems Computervertriebsgesellschaft mbH" },
6472 { 1199, "Energy Wall LLC" },
6473 { 1200, "Thermofin" },
6474 { 1201, "SDATAWAY SA" },
6475 { 1202, "Biddle Air Systems Limited" },
6476 { 1203, "Kessler Ellis Products" },
6477 { 1204, "Thermoscreens" },
6478 { 1205, "Modio" },
6479 { 1206, "Newron Solutions" },
6480 { 1207, "Unitronics" },
6481 { 1208, "TRILUX GmbH & Co. KG" },
6482 { 1209, "Kollmorgen Steuerungstechnik GmbH" },
6483 { 1210, "Bosch Rexroth AG" },
6484 { 1211, "Alarko Carrier" },
6485 { 1212, "Verdigris Technologies" },
6486 { 1213, "Shanghai SIIC-Longchuang Smartech So., Ltd." },
6487 { 1214, "Quinda Co." },
6488 { 1215, "GRUNER AG" },
6489 { 1216, "BACMOVE" },
6490 { 1217, "PSIDAC AB" },
6491 { 1218, "ISICON-Control Automation" },
6492 { 1219, "Big Ass Fans" },
6493 { 1220, "din – Dietmar Nocker Facility Management GmbH" },
6494 { 1221, "Teldio" },
6495 { 1222, "MIKROKLIMA s.r.o." },
6496 { 1223, "Density" },
6497 { 1224, "ICONAG-Leittechnik GmbH" },
6498 { 1225, "Awair" },
6499 { 1226, "T&D Engineering, Ltd" },
6500 { 1227, "Sistemas Digitales" },
6501 { 1228, "Loxone Electronics GmbH" },
6502 { 1229, "ActronAir" },
6503 { 1230, "Inductive Automation" },
6504 { 1231, "Thor Engineering GmbH" },
6505 { 1232, "Berner International, LLC" },
6506 { 1233, "Potsdam Sensors LLC" },
6507 { 1234, "Kohler Mira Ltd" },
6508 { 1235, "Tecomon GmbH" },
6509 { 1236, "Two Dimensional Instruments, LLC" },
6510 { 1237, "LEFA Technologies Pte. Ltd." },
6511 { 1238, "EATON CEAG Notlichtsysteme GmbH" },
6512 { 1239, "Commbox Tecnologia" },
6513 { 1240, "IPVideo Corporation" },
6514 { 1241, "Bender GmbH & Co. KG" },
6515 { 1242, "Rhymebus Corporation" },
6516 { 1243, "Axon Systems Ltd" },
6517 { 1244, "Engineered Air" },
6518 { 1245, "Elipse Software Ltda" },
6519 { 1246, "Simatix Building Technologies Pvt. Ltd." },
6520 { 1247, "W.A. Benjamin Electric Co." },
6521 { 1248, "TROX Air Conditioning Components (Suzhou) Co. Ltd." },
6522 { 1249, "SC Medical Pty Ltd." },
6523 { 1250, "Elcanic A/S" },
6524 { 1251, "Obeo AS" },
6525 { 1252, "Tapa, Inc." },
6526 { 1253, "ASE Smart Energy, Inc." },
6527 { 1254, "Performance Services, Inc." },
6528 { 1255, "Veridify Security" },
6529 { 1256, "CD Innovation LTD" },
6530 { 1257, "Ben Peoples Industries, LLC" },
6531 { 1258, "UNICOMM Sp. z o.o" },
6532 { 1259, "Thing Technologies GmbH" },
6533 { 1260, "Beijing Hailin Control Technology, Inc." },
6534 { 1261, "Digital Realty" },
6535 { 1262, "Agrowtek Inc." },
6536 { 1263, "DSP Innovation BV" },
6537 { 1264, "STV Electronic GmbH" },
6538 { 1265, "Elmeasure India Pvt Ltd." },
6539 { 1266, "Pineshore Energy LLC" },
6540 { 1267, "Brasch Environmental Technologies, LLC" },
6541 { 1268, "Lion Controls Co., LTD" },
6542 { 1269, "Sinux" },
6543 { 1270, "Avnet Inc." },
6544 { 1271, "Somfy Activites SA" },
6545 { 1272, "Amico" },
6546 { 1273, "SageGlass" },
6547 { 1274, "AuVerte" },
6548 { 1275, "Agile Connects Pvt. Ltd." },
6549 { 1276, "Locimation Pty Ltd" },
6550 { 1277, "Envio Systems GmbH" },
6551 { 1278, "Voytech Systems Limited" },
6552 { 1279, "Davidsmeyer und Paul GmbH" },
6553 { 1280, "Lusher Engineering Services" },
6554 { 1281, "CHNT Nanjing Techsel Intelligent Company LTD" },
6555 { 1282, "Threetronics Pty Ltd" },
6556 { 1283, "SkyFoundry, LLC" },
6557 { 1284, "HanilProTech" },
6558 { 1285, "Sensorscall" },
6559 { 1286, "Shanghai Jingpu Information Technology, Co., Ltd." },
6560 { 1287, "Lichtmanufaktur Berlin GmbH" },
6561 { 1288, "Eco Parking Technologies" },
6562 { 1289, "Envision Digital International Pte Ltd" },
6563 { 1290, "Antony Developpement Electronique" },
6564 { 1291, "i2systems" },
6565 { 1292, "Thureon International Limited" },
6566 { 1293, "Pulsafeeder" },
6567 { 1294, "MegaChips Corporation" },
6568 { 1295, "TES Controls" },
6569 { 1296, "Cermate" },
6570 { 1297, "Grand Valley State University" },
6571 { 1298, "Symcon Gmbh" },
6572 { 1299, "The Chicago Faucet Company" },
6573 { 1300, "Geberit AG" },
6574 { 1301, "Rex Controls" },
6575 { 1302, "IVMS GmbH" },
6576 { 1303, "MNPP Saturn Ltd." },
6577 { 1304, "Regal Beloit" },
6578 { 1305, "ACS-Air Conditioning Solutions" },
6579 { 1306, "GBX Technology, LLC" },
6580 { 1307, "Kaiterra" },
6581 { 1308, "ThinKuan loT Technology (Shanghai) Co., Ltd" },
6582 { 1309, "HoCoSto B.V." },
6583 { 1310, "Shenzhen AS-AI Technology Co., Ltd." },
6584 { 1311, "RPS S.p.a." },
6585 { 1312, "Esmé solutions" },
6586 { 1313, "IOTech Systems Limited" },
6587 { 1314, "i-AutoLogic Co., Ltd." },
6588 { 1315, "New Age Micro, LLC" },
6589 { 1316, "Guardian Glass" },
6590 { 1317, "Guangzhou Zhaoyu Information Technology" },
6591 { 1318, "ACE IoT Solutions LLC" },
6592 { 1319, "Poris Electronics Co., Ltd." },
6593 { 1320, "Terminus Technologies Group" },
6594 { 1321, "Intech 21, Inc." },
6595 { 1322, "Accurate Electronics" },
6596 { 1323, "Fluence Bioengineering" },
6597 { 1324, "Mun Hean Singapore Pte Ltd" },
6598 { 1325, "Katronic AG & Co. KG" },
6599 { 1326, "Suzhou XinAo Information Technology Co. Ltd" },
6600 { 1327, "Linktekk Technology, JSC." },
6601 { 1328, "Stirling Ultracold" },
6602 { 1329, "UV Partners, Inc." },
6603 { 1330, "ProMinent GmbH" },
6604 { 1331, "Multi-Tech Systems, Inc." },
6605 { 1332, "JUMO GmbH & Co. KG" },
6606 { 1333, "Qingdao Huarui Technology Co. Ltd.," },
6607 { 1334, "Cairn Systemes" },
6608 { 1335, "NeuroLogic Research Corp." },
6609 { 1336, "Transition Technologies Advanced Solutions Sp. z o.o" },
6610 { 1337, "Xxter bv" },
6611 { 1338, "PassiveLogic" },
6612 { 1339, "EnSmart Controls" },
6613 { 1340, "Watts Heating and Hot Water Solutions, dba Lync" },
6614 { 1341, "Troposphaira Technologies LLP" },
6615 { 1342, "Network Thermostat" },
6616 { 1343, "Titanium Intelligent Solutions, LLC" },
6617 { 1344, "Numa Products, LLC" },
6618 { 1345, "WAREMA Renkhoff SE" },
6619 { 1346, "Frese A/S" },
6620 { 1347, "Mapped" },
6621 { 1348, "ELEKTRODESIGN ventilatory s.r.o" },
6622 { 1349, "AirCare Automation, Inc." },
6623 { 1350, "Antrum" },
6624 { 1351, "Bao Linh Connect Technology" },
6625 { 1352, "Virginia Controls, LLC" },
6626 { 1353, "Duosys SDN BHD" },
6627 { 1354, "Onsen SAS" },
6628 { 1355, "Vaughn Thermal Corporation" },
6629 { 1356, "Thermoplastic Engineering Ltd (TPE)" },
6630 { 1357, "Wirth Research Ltd." },
6631 { 1358, "SST Automation" },
6632 { 1359, "Shanghai Bencol Electronic Technology Co., Ltd" },
6633 { 1360, "AIWAA Systems Private Limited" },
6634 { 1361, "Enless Wireless" },
6635 { 1362, "Ozuno Engineering Pty Ltd" },
6636 { 1363, "Hubbell, The Electric Heater Company" },
6637 { 1364, "Industrial Turnaround Corporation (ITAC)" },
6638 { 1365, "Wadsworth Control Systems" },
6639 { 1366, "Services Hilo Inc." },
6640 { 1367, "iDM Energiesysteme GmbH" },
6641 { 1368, "BeNext B.V." },
6642 { 1369, "CleanAir.ai Corporation" },
6643 { 1370, "Revolution Microelectronics (America) Inc." },
6644 { 1371, "Real-Time Systems GmbH" },
6645 { 1372, "ZedBee Technologies Pvt Ltd" },
6646 { 1373, "Winmate Technology Solutions Pvt. Ltd." },
6647 { 1374, "Senticon Ltd." },
6648 { 1375, "Rossaker AB" },
6649 { 1376, "OPIT Solutions Ltd" },
6650 { 1377, "Hotowell International Co., Limited" },
6651 { 1378, "Inim Electronics S.R.L. Unipersonale" },
6652 { 1379, "Airthings ASA" },
6653 { 1380, "Analog Devices, Inc." },
6654 { 1381, "AIDirections DMCC" },
6655 { 1382, "Prima Electro S.p.A." },
6656 { 1383, "KLT Control System Ltd." },
6657 { 1384, "Evolution Controls Inc." },
6658 { 1385, "Bever Innovations" },
6659 { 1386, "Pelican Wireless Systems" },
6660 { 1387, "Control Concepts Inc." },
6661 { 1388, "Augmatic Technologies Pvt. Ltd." },
6662 { 1389, "Xiamen Milesight loT Co., Ltd" },
6663 { 1390, "Tianjin Anjie loT Schience and Technology Co., Ltd" },
6664 { 1391, "Guangzhou S. Energy Electronics Technology Co. Ltd." },
6665 { 1392, "AKVO Atmospheric Water Systems Pvt. Ltd." },
6666 { 1393, "EmFirst Co. Ltd." },
6667 { 1394, "Iion Systems ApS" },
6668 { 1396, "SAF Tehnika JSC" },
6669 { 1397, "Komfort IQ, Inc." },
6670 { 1398, "CoolTera Limited" },
6671 { 1399, "Hadron Solutions S.r.l.s" },
6672 { 1401, "Bitpool" },
6673 { 1402, "Sonicu, LLC" },
6674 { 1403, "Rishabh Instruments Limited" },
6675 { 1404, "Thing Warehouse LLC" },
6676 { 1405, "Innofriends GmbH" },
6677 { 1406, "Metronic AKP Sp. J." },
6678 { 1407, "Techknave" },
6679 { 1408, "Elsner Elektronik" },
6680 { 1409, "LEFOO Industrial (Hangzhou) Co., Ltd." },
6681 { 1410, "Calibration Technologies, Inc." },
6682 { 1411, "Allorado" },
6683 { 1412, "Verkada" },
6684 { 1413, "Wattsense" },
6685 { 1414, "Emerson Automation Solutions" },
6686 { 1415, "Growlink" },
6687 { 1416, "Olympia Electronics" },
6688 { 1417, "Normal Software, Inc." },
6689 { 1418, "ST Engineering Solution JSC" },
6690 { 1419, "Industrial Flow Solutions" },
6691 { 1420, "Ubiqisense ApS" },
6692 { 1421, "Tiger-Soft" },
6693 { 1422, "Ecodom Srl" },
6694 { 1423, "Bilgipro IoT Systems" },
6695 { 1424, "planspur netdesign GmbH" },
6696 { 1425, "Dolphin Solutions Ltd" },
6697 { 1426, "Mitsubishi Electric Corporation, Kobe Works" },
6698 { 1427, "Ecovena" },
6699 { 1428, "Gree Electric Appliances Inc of Zhuhai" },
6700 { 1429, "Conspec Controls" },
6701 { 1430, "Hangzhou Hikvision Digital Technology Co., Ltd." },
6702 { 1431, "Crystal Peak Security" },
6703 { 1432, "PermAlert" },
6704 { 1433, "Zhejiang Misilin Technology Co., Ltd." },
6705 { 1434, "Dekker Vacuum Technologies" },
6706 { 1435, "Edwards Limited" },
6707 { 1436, "Leybold GmbH" },
6708 { 1437, "International Gas Detectors" },
6709 { 1438, "Atlas Copco Airpower NV" },
6710 { 1439, "Air Sentry Limited" },
6711 { 1440, "Aelsys" },
6712 { 1441, "Granby Consulting LLC" },
6713 { 1442, "Clever Relay" },
6714 { 1443, "Monico Monitoring, Inc." },
6715 { 1444, "Oqdo" },
6716 { 1445, "Matrix Comsec Private Limited" },
6717 { 1446, "Resource Solutions" },
6718 { 1447, "American Gas Safety, LLC" },
6719 { 1448, "S&S Northern Ltd." },
6720 { 1449, "Ulbios Techsens" },
6721 { 1450, "Bowery Farming, Inc." },
6722 { 1451, "Ryobi Limited" },
6723 { 1452, "EkkoSense Ltd" },
6724 { 1453, "ClimaCool" },
6725 { 1454, "Grid Connect Inc." },
6726 { 1455, "Ziegler Instrumentation UK Ltd" },
6727 { 1456, "ControlTec, LLC" },
6728 { 1457, "Aeterlink Corporation" },
6729 { 1458, "Alpha Epsilon Automation" },
6730 { 1459, "Astralite Inc." },
6731 { 1460, "Delta Fire Ltda." },
6732 { 1461, "Bock Water Heaters, Inc." },
6733 { 1462, "Cleaver-Brooks" },
6734 { 1463, "Scanalytics, Inc." },
6735 { 1464, "WI6LABS" },
6736 { 1465, "AC&T System Co., Ltd" },
6737 { 1466, "VergeSense" },
6738 { 1467, "Systemair Mfg. Inc." },
6739 { 1468, "Seeley International" },
6740 { 1469, "Crane Building Services & Utilities" },
6741 { 1470, "Brady Corporation" },
6742 { 1471, "Qingdao Hisense Hitachi Air-Conditioning Systems Co., Ltd." },
6743 { 1472, "Golden Quality Co. Ltd." },
6744 { 1473, "Elvaco AB" },
6745 { 1474, "Strong Technology, LLC" },
6746 { 1475, "REC Environmental Technology (Guangzhou) Company Limited" },
6747 { 1476, "Disruptive Technologies Research AS" },
6748 { 1477, "Nico Consultancy Limited" },
6749 { 1478, "Horten lot (Jiangsu) Co., Ltd." },
6750 { 1479, "Paxton Controls Corp." },
6751 { 1480, "Fell Technology AS" },
6752 { 1481, "SHLOK Information Systems India Private Limited" },
6753 { 1482, "Microgro PLC Ltd." },
6754 { 1483, "Clouder Oy" },
6755 { 1484, "Gebäude Automatisierung GmbH" },
6756 { 1485, "solvimus GmbH" },
6757 { 0, NULL }
6759 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
6761 static int proto_bacapp;
6762 static int hf_bacapp_type;
6763 static int hf_bacapp_pduflags;
6764 static int hf_bacapp_SEG;
6765 static int hf_bacapp_MOR;
6766 static int hf_bacapp_SA;
6767 static int hf_bacapp_response_segments;
6768 static int hf_bacapp_max_adpu_size;
6769 static int hf_bacapp_invoke_id;
6770 static int hf_bacapp_objectType;
6771 static int hf_bacapp_object_name;
6772 static int hf_bacapp_instanceNumber;
6773 static int hf_bacapp_sequence_number;
6774 static int hf_bacapp_window_size;
6775 static int hf_bacapp_service;
6776 static int hf_bacapp_NAK;
6777 static int hf_bacapp_SRV;
6778 static int hf_bacapp_notify_type;
6779 static int hf_bacapp_event_type;
6780 static int hf_bacapp_error_class;
6781 static int hf_bacapp_error_code;
6782 static int hf_Device_Instance_Range_Low_Limit;
6783 static int hf_Device_Instance_Range_High_Limit;
6784 static int hf_BACnetRejectReason;
6785 static int hf_BACnetAbortReason;
6786 static int hf_BACnetApplicationTagNumber;
6787 static int hf_BACnetContextTagNumber;
6788 static int hf_BACnetExtendedTagNumber;
6789 static int hf_BACnetNamedTag;
6790 static int hf_BACnetTagClass;
6791 static int hf_BACnetCharacterSet;
6792 static int hf_BACnetCodePage;
6793 static int hf_bacapp_tag_lvt;
6794 static int hf_bacapp_tag_ProcessId;
6795 static int hf_bacapp_tag_to_state;
6796 static int hf_bacapp_tag_from_state;
6797 static int hf_bacapp_uservice;
6798 static int hf_BACnetPropertyIdentifier;
6799 static int hf_BACnetVendorIdentifier;
6800 static int hf_BACnetRestartReason;
6801 static int hf_bacapp_tag_IPV4;
6802 static int hf_bacapp_tag_IPV6;
6803 static int hf_bacapp_tag_PORT;
6804 static int hf_bacapp_tag_mac_address_broadcast;
6805 static int hf_bacapp_reserved_ashrea;
6806 static int hf_bacapp_unused_bits;
6807 static int hf_bacapp_bit;
6808 static int hf_bacapp_complete_bitstring;
6810 /* present value */
6811 static int hf_bacapp_present_value_null;
6812 static int hf_bacapp_present_value_bool;
6813 static int hf_bacapp_present_value_unsigned;
6814 static int hf_bacapp_present_value_signed;
6815 static int hf_bacapp_present_value_real;
6816 static int hf_bacapp_present_value_double;
6817 static int hf_bacapp_present_value_octet_string;
6818 static int hf_bacapp_present_value_char_string;
6819 static int hf_bacapp_present_value_bit_string;
6820 static int hf_bacapp_present_value_enum_index;
6822 /* some more variables for segmented messages */
6823 static int hf_msg_fragments;
6824 static int hf_msg_fragment;
6825 static int hf_msg_fragment_overlap;
6826 static int hf_msg_fragment_overlap_conflicts;
6827 static int hf_msg_fragment_multiple_tails;
6828 static int hf_msg_fragment_too_long_fragment;
6829 static int hf_msg_fragment_error;
6830 static int hf_msg_fragment_count;
6831 static int hf_msg_reassembled_in;
6832 static int hf_msg_reassembled_length;
6834 static int ett_msg_fragment;
6835 static int ett_msg_fragments;
6837 static int ett_bacapp;
6838 static int ett_bacapp_control;
6839 static int ett_bacapp_tag;
6840 static int ett_bacapp_list;
6841 static int ett_bacapp_value;
6843 static expert_field ei_bacapp_bad_length;
6844 static expert_field ei_bacapp_bad_tag;
6845 static expert_field ei_bacapp_opening_tag;
6847 static int32_t propertyIdentifier = -1;
6848 static int32_t propertyArrayIndex = -1;
6849 static uint32_t object_type = 4096;
6851 static uint8_t bacapp_flags;
6852 static uint8_t bacapp_seq;
6854 /* Defined to allow vendor identifier registration of private transfer dissectors */
6855 static dissector_table_t bacapp_dissector_table;
6858 /* Stat: BACnet Packets sorted by IP */
6859 bacapp_info_value_t bacinfo;
6861 static const char* st_str_packets_by_ip = "BACnet Packets by IP";
6862 static const char* st_str_packets_by_ip_dst = "By Destination";
6863 static const char* st_str_packets_by_ip_src = "By Source";
6864 static int st_node_packets_by_ip = -1;
6865 static int st_node_packets_by_ip_dst = -1;
6866 static int st_node_packets_by_ip_src = -1;
6868 static void
6869 bacapp_packet_stats_tree_init(stats_tree* st)
6871 st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
6872 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);
6873 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);
6876 static char *
6877 bacapp_get_address_label(const char *tag, address *addr)
6879 char *addr_str, *label_str;
6881 addr_str = address_to_str(NULL, addr);
6882 label_str = wmem_strconcat(NULL, tag, addr_str, NULL);
6883 wmem_free(NULL, addr_str);
6884 return label_str;
6887 static tap_packet_status
6888 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
6890 int packets_for_this_dst;
6891 int packets_for_this_src;
6892 int service_for_this_dst;
6893 int service_for_this_src;
6894 int src_for_this_dst;
6895 int dst_for_this_src;
6896 int objectid_for_this_dst;
6897 int objectid_for_this_src;
6898 int instanceid_for_this_dst;
6899 int instanceid_for_this_src;
6900 char *dststr;
6901 char *srcstr;
6902 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
6904 srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
6905 dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
6907 tick_stat_node(st, st_str_packets_by_ip, 0, true);
6908 packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, true);
6909 packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, true);
6910 src_for_this_dst = tick_stat_node(st, dststr, packets_for_this_dst, true);
6911 dst_for_this_src = tick_stat_node(st, srcstr, packets_for_this_src, true);
6912 service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, true);
6913 service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, true);
6914 if (binfo->service_type) {
6915 objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, true);
6916 objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, true);
6917 if (binfo->object_ident) {
6918 instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, true);
6919 tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, false);
6920 instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, true);
6921 tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, false);
6925 wmem_free(NULL, srcstr);
6926 wmem_free(NULL, dststr);
6928 return TAP_PACKET_REDRAW;
6931 /* Stat: BACnet Packets sorted by Service */
6932 static const char* st_str_packets_by_service = "BACnet Packets by Service";
6933 static int st_node_packets_by_service = -1;
6935 static void
6936 bacapp_service_stats_tree_init(stats_tree* st)
6938 st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
6941 static tap_packet_status
6942 bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
6944 int servicetype;
6945 int src, dst;
6946 int objectid;
6948 char *dststr;
6949 char *srcstr;
6951 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
6953 srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
6954 dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
6956 tick_stat_node(st, st_str_packets_by_service, 0, true);
6957 if (binfo->service_type) {
6958 servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, true);
6959 src = tick_stat_node(st, srcstr, servicetype, true);
6960 dst = tick_stat_node(st, dststr, src, true);
6961 if (binfo->object_ident) {
6962 objectid = tick_stat_node(st, binfo->object_ident, dst, true);
6963 tick_stat_node(st, binfo->instance_ident, objectid, false);
6967 wmem_free(NULL, srcstr);
6968 wmem_free(NULL, dststr);
6970 return TAP_PACKET_REDRAW;
6973 /* Stat: BACnet Packets sorted by Object Type */
6974 static const char* st_str_packets_by_objectid = "BACnet Packets by Object Type";
6975 static int st_node_packets_by_objectid = -1;
6977 static void
6978 bacapp_objectid_stats_tree_init(stats_tree* st)
6980 st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
6983 static tap_packet_status
6984 bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
6986 int servicetype;
6987 int src, dst;
6988 int objectid;
6990 char *dststr;
6991 char *srcstr;
6992 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
6994 srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
6995 dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
6997 tick_stat_node(st, st_str_packets_by_objectid, 0, true);
6998 if (binfo->object_ident) {
6999 objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, true);
7000 src = tick_stat_node(st, srcstr, objectid, true);
7001 dst = tick_stat_node(st, dststr, src, true);
7002 if (binfo->service_type) {
7003 servicetype = tick_stat_node(st, binfo->service_type, dst, true);
7004 tick_stat_node(st, binfo->instance_ident, servicetype, false);
7008 wmem_free(NULL, srcstr);
7009 wmem_free(NULL, dststr);
7011 return TAP_PACKET_REDRAW;
7014 /* Stat: BACnet Packets sorted by Instance No */
7015 static const char* st_str_packets_by_instanceid = "BACnet Packets by Instance ID";
7016 static int st_node_packets_by_instanceid = -1;
7018 static void
7019 bacapp_instanceid_stats_tree_init(stats_tree* st)
7021 st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
7024 static tap_packet_status
7025 bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_)
7027 int servicetype;
7028 int src, dst;
7029 int instanceid;
7031 char *dststr;
7032 char *srcstr;
7033 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
7035 srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
7036 dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
7038 tick_stat_node(st, st_str_packets_by_instanceid, 0, true);
7039 if (binfo->object_ident) {
7040 instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, true);
7041 src = tick_stat_node(st, srcstr, instanceid, true);
7042 dst = tick_stat_node(st, dststr, src, true);
7043 if (binfo->service_type) {
7044 servicetype = tick_stat_node(st, binfo->service_type, dst, true);
7045 tick_stat_node(st, binfo->object_ident, servicetype, false);
7049 wmem_free(NULL, srcstr);
7050 wmem_free(NULL, dststr);
7052 return TAP_PACKET_REDRAW;
7056 /* register all BACnet Statistic trees */
7057 static void
7058 register_bacapp_stat_trees(void)
7060 stats_tree_register("bacapp", "bacapp_ip", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by IP", 0,
7061 bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
7062 stats_tree_register("bacapp", "bacapp_service", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Service", 0,
7063 bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
7064 stats_tree_register("bacapp", "bacapp_objectid", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Object Type", 0,
7065 bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
7066 stats_tree_register("bacapp", "bacapp_instanceid", "BACnet" STATS_TREE_MENU_SEPARATOR "Packets sorted by Instance ID", 0,
7067 bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
7070 /* 'data' must be allocated with wmem packet scope */
7071 static int
7072 updateBacnetInfoValue(int whichval, const char *data)
7074 if (whichval == BACINFO_SERVICE) {
7075 bacinfo.service_type = data;
7076 return 0;
7078 if (whichval == BACINFO_INVOKEID) {
7079 bacinfo.invoke_id = data;
7080 return 0;
7082 if (whichval == BACINFO_OBJECTID) {
7083 bacinfo.object_ident = data;
7084 return 0;
7086 if (whichval == BACINFO_INSTANCEID) {
7087 bacinfo.instance_ident = data;
7088 return 0;
7090 return -1;
7093 static const fragment_items msg_frag_items = {
7094 /* Fragment subtrees */
7095 &ett_msg_fragment,
7096 &ett_msg_fragments,
7097 /* Fragment fields */
7098 &hf_msg_fragments,
7099 &hf_msg_fragment,
7100 &hf_msg_fragment_overlap,
7101 &hf_msg_fragment_overlap_conflicts,
7102 &hf_msg_fragment_multiple_tails,
7103 &hf_msg_fragment_too_long_fragment,
7104 &hf_msg_fragment_error,
7105 &hf_msg_fragment_count,
7106 /* Reassembled in field */
7107 &hf_msg_reassembled_in,
7108 /* Reassembled length field */
7109 &hf_msg_reassembled_length,
7110 /* Reassembled data field */
7111 NULL,
7112 /* Tag */
7113 "Message fragments"
7116 #if 0
7117 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
7118 /* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
7119 static const unsigned MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
7121 static unsigned
7122 fGetMaxAPDUSize(uint8_t idx)
7124 /* only 16 values are defined, so use & 0x0f */
7125 /* check the size of the Array, deliver either the entry
7126 or the first entry if idx is outside of the array (bug 3736 comment#7) */
7128 if ((idx & 0x0f) >= (int)array_length(MaxAPDUSize))
7129 return MaxAPDUSize[0];
7130 else
7131 return MaxAPDUSize[idx & 0x0f];
7133 #endif
7135 static const char*
7136 val_to_split_str(uint32_t val, uint32_t split_val, const value_string *vs,
7137 const char *fmt, const char *split_fmt)
7138 G_GNUC_PRINTF(4, 0)
7139 G_GNUC_PRINTF(5, 0);
7141 /* Used when there are ranges of reserved and proprietary enumerations */
7142 static const char*
7143 val_to_split_str(uint32_t val, uint32_t split_val, const value_string *vs,
7144 const char *fmt, const char *split_fmt)
7146 if (val < split_val)
7147 return val_to_str(val, vs, fmt);
7148 else
7149 return val_to_str(val, vs, split_fmt);
7152 /* from clause 20.2.1.3.2 Constructed Data */
7153 /* returns true if the extended value is used */
7154 static bool
7155 tag_is_extended_value(uint8_t tag)
7157 return (tag & 0x07) == 5;
7160 static bool
7161 tag_is_opening(uint8_t tag)
7163 return (tag & 0x07) == 6;
7166 static bool
7167 tag_is_closing(uint8_t tag)
7169 return (tag & 0x07) == 7;
7172 /* from clause 20.2.1.1 Class
7173 class bit shall be one for context specific tags */
7174 /* returns true if the tag is context specific */
7175 static bool
7176 tag_is_context_specific(uint8_t tag)
7178 return (tag & 0x08) != 0;
7181 static bool
7182 tag_is_extended_tag_number(uint8_t tag)
7184 return ((tag & 0xF0) == 0xF0);
7187 static uint32_t
7188 object_id_type(uint32_t object_identifier)
7190 return ((object_identifier >> 22) & 0x3FF);
7193 static uint32_t
7194 object_id_instance(uint32_t object_identifier)
7196 return (object_identifier & 0x3FFFFF);
7199 static unsigned
7200 fTagNo(tvbuff_t *tvb, unsigned offset)
7202 return (unsigned)(tvb_get_uint8(tvb, offset) >> 4);
7205 static bool
7206 fUnsigned32(tvbuff_t *tvb, unsigned offset, uint32_t lvt, uint32_t *val)
7208 bool valid = true;
7210 switch (lvt) {
7211 case 1:
7212 *val = tvb_get_uint8(tvb, offset);
7213 break;
7214 case 2:
7215 *val = tvb_get_ntohs(tvb, offset);
7216 break;
7217 case 3:
7218 *val = tvb_get_ntoh24(tvb, offset);
7219 break;
7220 case 4:
7221 *val = tvb_get_ntohl(tvb, offset);
7222 break;
7223 default:
7224 valid = false;
7225 break;
7228 return valid;
7231 static bool
7232 fUnsigned64(tvbuff_t *tvb, unsigned offset, uint32_t lvt, uint64_t *val)
7234 bool valid = false;
7235 int64_t value = 0;
7236 uint8_t data, i;
7238 if (lvt && (lvt <= 8)) {
7239 valid = true;
7240 for (i = 0; i < lvt; i++) {
7241 data = tvb_get_uint8(tvb, offset+i);
7242 value = (value << 8) + data;
7244 *val = value;
7247 return valid;
7250 /* BACnet Signed Value uses 2's complement notation, but with a twist:
7251 All signed integers shall be encoded in the smallest number of octets
7252 possible. That is, the first octet of any multi-octet encoded value
7253 shall not be X'00' if the most significant bit (bit 7) of the second
7254 octet is 0, and the first octet shall not be X'FF' if the most
7255 significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
7256 static bool
7257 fSigned64(tvbuff_t *tvb, unsigned offset, uint32_t lvt, int64_t *val)
7259 bool valid = false;
7260 int64_t value = 0;
7261 uint8_t data;
7262 uint32_t i;
7264 /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
7265 if (lvt && (lvt <= 7)) {
7266 valid = true;
7267 data = tvb_get_uint8(tvb, offset);
7268 if ((data & 0x80) != 0)
7269 value = (~UINT64_C(0) << 8) | data;
7270 else
7271 value = data;
7272 for (i = 1; i < lvt; i++) {
7273 data = tvb_get_uint8(tvb, offset+i);
7274 value = ((uint64_t)value << 8) | data;
7276 *val = value;
7279 return valid;
7282 static unsigned
7283 fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7284 unsigned offset, uint8_t *tag_no, uint8_t* tag_info, uint32_t *lvt)
7286 proto_item *ti = NULL;
7287 uint8_t tag;
7288 uint8_t value;
7289 unsigned tag_len = 1;
7290 unsigned lvt_len = 1; /* used for tree display of lvt */
7291 unsigned lvt_offset; /* used for tree display of lvt */
7293 lvt_offset = offset;
7294 tag = tvb_get_uint8(tvb, offset);
7295 *tag_info = 0;
7296 *lvt = tag & 0x07;
7298 /* To solve the problem of lvt values of 6/7 being indeterminate - it */
7299 /* can mean open/close tag or length of 6/7 after the length is */
7300 /* computed below - store whole tag info, not just context bit. */
7301 if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
7302 *tag_no = tag >> 4;
7303 if (tag_is_extended_tag_number(tag)) {
7304 *tag_no = tvb_get_uint8(tvb, offset + tag_len++);
7306 if (tag_is_extended_value(tag)) { /* length is more than 4 Bytes */
7307 lvt_offset += tag_len;
7308 value = tvb_get_uint8(tvb, lvt_offset);
7309 tag_len++;
7310 if (value == 254) { /* length is encoded with 16 Bits */
7311 *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
7312 tag_len += 2;
7313 lvt_len += 2;
7314 } else if (value == 255) { /* length is encoded with 32 Bits */
7315 *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
7316 tag_len += 4;
7317 lvt_len += 4;
7318 } else
7319 *lvt = value;
7322 if (tree) {
7323 proto_tree *subtree;
7324 if (tag_is_opening(tag)) {
7325 subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
7326 ett_bacapp_tag, &ti, "{[%u]", *tag_no );
7327 } else if (tag_is_closing(tag)) {
7328 subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
7329 ett_bacapp_tag, &ti, "}[%u]", *tag_no );
7330 } else if (tag_is_context_specific(tag)) {
7331 subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
7332 ett_bacapp_tag, &ti,
7333 "Context Tag: %u, Length/Value/Type: %u", *tag_no, *lvt);
7334 } else {
7335 subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
7336 ett_bacapp_tag, &ti,
7337 "Application Tag: %s, Length/Value/Type: %u",
7338 val_to_str(*tag_no, BACnetApplicationTagNumber,
7339 ASHRAE_Reserved_Fmt),
7340 *lvt);
7343 /* details if needed */
7344 proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
7345 if (tag_is_extended_tag_number(tag)) {
7346 proto_tree_add_uint_format(subtree,
7347 hf_BACnetContextTagNumber,
7348 tvb, offset, 1, tag,
7349 "Extended Tag Number");
7350 proto_tree_add_item(subtree,
7351 hf_BACnetExtendedTagNumber,
7352 tvb, offset + 1, 1, ENC_BIG_ENDIAN);
7353 } else {
7354 if (tag_is_context_specific(tag))
7355 proto_tree_add_item(subtree,
7356 hf_BACnetContextTagNumber,
7357 tvb, offset, 1, ENC_BIG_ENDIAN);
7358 else
7359 proto_tree_add_item(subtree,
7360 hf_BACnetApplicationTagNumber,
7361 tvb, offset, 1, ENC_BIG_ENDIAN);
7363 if (tag_is_closing(tag) || tag_is_opening(tag))
7364 proto_tree_add_item(subtree,
7365 hf_BACnetNamedTag,
7366 tvb, offset, 1, ENC_BIG_ENDIAN);
7367 else if (tag_is_extended_value(tag)) {
7368 proto_tree_add_item(subtree,
7369 hf_BACnetNamedTag,
7370 tvb, offset, 1, ENC_BIG_ENDIAN);
7371 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
7372 tvb, lvt_offset, lvt_len, *lvt);
7373 } else
7374 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
7375 tvb, lvt_offset, lvt_len, *lvt);
7376 } /* if (tree) */
7378 if (*lvt > tvb_reported_length(tvb)) {
7379 expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
7380 "LVT length too long: %d > %d", *lvt,
7381 tvb_reported_length(tvb));
7382 *lvt = 1;
7385 return tag_len;
7388 static unsigned
7389 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, uint8_t *tag_no, uint8_t* tag_info,
7390 uint32_t *lvt)
7392 return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
7395 static unsigned
7396 fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7398 uint8_t tag_no, tag_info;
7399 uint32_t lvt;
7400 proto_tree *subtree;
7402 subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "%sNULL", label);
7403 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7405 return offset + 1;
7408 static unsigned
7409 fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7411 uint8_t tag_no, tag_info;
7412 uint32_t lvt = 0;
7413 proto_tree *subtree;
7414 unsigned bool_len = 1;
7416 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7417 if (tag_info && lvt == 1) {
7418 lvt = tvb_get_uint8(tvb, offset+1);
7419 ++bool_len;
7422 subtree = proto_tree_add_subtree_format(tree, tvb, offset, bool_len,
7423 ett_bacapp_tag, NULL, "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
7424 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7426 return offset + bool_len;
7429 static unsigned
7430 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7432 uint64_t val = 0;
7433 uint8_t tag_no, tag_info;
7434 uint32_t lvt;
7435 unsigned tag_len;
7436 proto_tree *subtree;
7438 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7439 /* only support up to an 8 byte (64-bit) integer */
7440 if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
7441 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7442 ett_bacapp_tag, NULL, "%s(Unsigned) %" PRIu64, label, val);
7443 else
7444 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7445 ett_bacapp_tag, NULL, "%s - %u octets (Unsigned)", label, lvt);
7446 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7448 return offset+tag_len+lvt;
7451 static unsigned
7452 fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int hf)
7454 uint8_t tag_no, tag_info;
7455 uint32_t lvt, safe_lvt;
7456 unsigned tag_len;
7457 proto_item *ti;
7458 proto_tree *subtree;
7460 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7462 if (lvt > 4)
7463 safe_lvt = 4;
7464 else
7465 safe_lvt = lvt;
7467 ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
7469 if (lvt != safe_lvt)
7470 expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
7471 "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
7473 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7474 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7476 return offset+tag_len+lvt;
7479 /* set split_val to zero when not needed */
7480 static unsigned
7481 fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7482 unsigned offset, const char *label, const value_string *vs, uint32_t split_val)
7484 uint32_t val = 0;
7485 uint8_t tag_no, tag_info;
7486 uint32_t lvt;
7487 unsigned tag_len;
7488 proto_tree *subtree;
7490 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7491 /* only support up to a 4 byte (32-bit) enumeration */
7492 if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
7493 if (vs)
7494 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7495 ett_bacapp_tag, NULL, "%s %s (%u)", label, val_to_split_str(val, split_val, vs,
7496 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt), val);
7497 else
7498 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7499 ett_bacapp_tag, NULL, "%s %u", label, val);
7500 } else {
7501 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7502 ett_bacapp_tag, NULL, "%s - %u octets (enumeration)", label, lvt);
7505 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7507 return offset+tag_len+lvt;
7510 static unsigned
7511 fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7512 unsigned offset, const char *label, const value_string *vs)
7514 return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
7517 static unsigned
7518 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7520 int64_t val = 0;
7521 uint8_t tag_no, tag_info;
7522 uint32_t lvt;
7523 unsigned tag_len;
7524 proto_tree *subtree;
7526 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7527 if (fSigned64(tvb, offset + tag_len, lvt, &val))
7528 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7529 ett_bacapp_tag, NULL, "%s(Signed) %" PRId64, label, val);
7530 else
7531 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7532 ett_bacapp_tag, NULL, "%s - %u octets (Signed)", label, lvt);
7533 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7535 return offset+tag_len+lvt;
7538 static unsigned
7539 fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7541 uint8_t tag_no, tag_info;
7542 uint32_t lvt;
7543 unsigned tag_len;
7544 float f_val;
7545 proto_tree *subtree;
7547 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7548 f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
7549 subtree = proto_tree_add_subtree_format(tree, tvb, offset, 4+tag_len,
7550 ett_bacapp_tag, NULL, "%s%f (Real)", label, f_val);
7551 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7553 return offset+tag_len+4;
7556 static unsigned
7557 fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7559 uint8_t tag_no, tag_info;
7560 uint32_t lvt;
7561 unsigned tag_len;
7562 double d_val;
7563 proto_tree *subtree;
7565 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7566 d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
7567 subtree = proto_tree_add_subtree_format(tree, tvb, offset, 8+tag_len,
7568 ett_bacapp_tag, NULL, "%s%f (Double)", label, d_val);
7569 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7571 return offset+tag_len+8;
7574 static unsigned
7575 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7577 uint32_t val = 0, lvt;
7578 uint8_t tag_no, tag_info;
7579 proto_item *ti;
7580 proto_tree *subtree;
7581 unsigned tag_len;
7583 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7584 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
7586 ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
7587 tvb, offset, lvt+tag_len, val);
7588 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7590 else
7592 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7593 ett_bacapp_tag, NULL, "Process Identifier - %u octets (Signed)", lvt);
7595 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7596 offset += tag_len + lvt;
7598 return offset;
7601 static unsigned
7602 fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const value_string *vs, uint32_t split_val, BacappPresentValueType type)
7604 // tag vars
7605 uint32_t lvt;
7606 uint8_t tag_no, tag_info;
7607 unsigned tag_len;
7608 unsigned curr_offset = offset;
7609 // tree vars
7610 proto_item *tree_item = NULL;
7611 proto_tree *subtree = NULL;
7612 // dissection vars
7613 unsigned bool_len = 1;
7614 uint64_t unsigned_val = 0;
7615 int64_t signed_val = 0;
7616 float float_val;
7617 double double_val;
7618 uint32_t enum_index = 0;
7619 uint32_t object_id;
7621 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7622 switch(type) {
7623 case BACAPP_PRESENT_VALUE_NULL:
7624 tree_item = proto_tree_add_string(tree, hf_bacapp_present_value_null, tvb, offset, lvt+tag_len, "NULL");
7625 curr_offset += 1;
7626 break;
7627 case BACAPP_PRESENT_VALUE_BOOL:
7628 if (tag_info && lvt == 1) {
7629 lvt = tvb_get_uint8(tvb, offset+1);
7630 bool_len++;
7632 tree_item = proto_tree_add_boolean(tree, hf_bacapp_present_value_bool, tvb, offset, bool_len, lvt);
7633 curr_offset += bool_len;
7634 break;
7635 case BACAPP_PRESENT_VALUE_UNSIGNED:
7636 if (fUnsigned64(tvb, offset + tag_len, lvt, &unsigned_val))
7637 tree_item = proto_tree_add_uint64(tree, hf_bacapp_present_value_unsigned, tvb, offset, lvt+tag_len, unsigned_val);
7638 curr_offset += tag_len + lvt;
7639 break;
7640 case BACAPP_PRESENT_VALUE_SIGNED:
7641 if (fSigned64(tvb, offset + tag_len, lvt, &signed_val))
7642 tree_item = proto_tree_add_int64(tree, hf_bacapp_present_value_signed, tvb, offset, lvt+tag_len, signed_val);
7643 curr_offset += tag_len + lvt;
7644 break;
7645 case BACAPP_PRESENT_VALUE_REAL:
7646 float_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
7647 double_val = (double) float_val;
7648 tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_real, tvb, offset, lvt+tag_len, double_val);
7649 curr_offset += tag_len + lvt;
7650 break;
7651 case BACAPP_PRESENT_VALUE_DOUBLE:
7652 double_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
7653 tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_double, tvb, offset, lvt+tag_len, double_val);
7654 curr_offset += tag_len + lvt;
7655 break;
7656 case BACAPP_PRESENT_VALUE_OCTET_STRING:
7657 if (lvt > 0)
7658 tree_item = proto_tree_add_item(tree, hf_bacapp_present_value_octet_string, tvb, offset, lvt+tag_len, ENC_NA);
7659 curr_offset += tag_len + lvt;
7660 break;
7661 case BACAPP_PRESENT_VALUE_CHARACTER_STRING:
7662 curr_offset = fCharacterStringBase(tvb, pinfo, tree, offset, NULL, true, false);
7663 break;
7664 case BACAPP_PRESENT_VALUE_BIT_STRING:
7665 curr_offset = fBitStringTagVSBase(tvb, pinfo, tree, offset, NULL, NULL, true);
7666 break;
7667 case BACAPP_PRESENT_VALUE_ENUM:
7668 if (fUnsigned32(tvb, offset+tag_len, lvt, &enum_index)) {
7669 if (vs) {
7670 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len, ett_bacapp_tag, NULL,
7671 "Present Value (enum value): %s",
7672 val_to_split_str(enum_index,
7673 split_val,
7675 ASHRAE_Reserved_Fmt,
7676 Vendor_Proprietary_Fmt));
7677 proto_tree_add_uint(subtree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, enum_index);
7678 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7679 } else {
7680 tree_item = proto_tree_add_uint(tree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, enum_index);
7683 curr_offset += tag_len + lvt;
7684 break;
7685 case BACAPP_PRESENT_VALUE_DATE:
7686 curr_offset = fDate(tvb, pinfo, tree, offset, "Date: ");
7687 break;
7688 case BACAPP_PRESENT_VALUE_TIME:
7689 curr_offset = fTime(tvb, pinfo, tree, offset, "Time: ");
7690 break;
7691 case BACAPP_PRESENT_VALUE_OBJECT_IDENTIFIER:
7692 object_id = tvb_get_ntohl(tvb, offset+tag_len);
7693 object_type = object_id_type(object_id);
7694 subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len + 4, ett_bacapp_tag, NULL,
7695 "Present Value (enum value): %s",
7696 val_to_split_str(object_type,
7697 128,
7698 BACnetObjectType,
7699 ASHRAE_Reserved_Fmt,
7700 Vendor_Proprietary_Fmt));
7701 proto_tree_add_uint(subtree, hf_bacapp_present_value_enum_index, tvb, offset, lvt+tag_len, object_type);
7702 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7703 curr_offset += tag_len + lvt;
7704 break;
7705 default:
7706 curr_offset += tag_len + lvt;
7707 break;
7710 if (tree_item != NULL && subtree == NULL) {
7711 subtree = proto_item_add_subtree(tree_item, ett_bacapp_value);
7712 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7715 return curr_offset;
7718 static unsigned
7719 fEventType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7721 uint32_t val = 0, lvt;
7722 uint8_t tag_no, tag_info;
7723 proto_item *ti;
7724 proto_tree *subtree;
7725 unsigned tag_len;
7727 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7728 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
7730 ti = proto_tree_add_uint(tree, hf_bacapp_event_type,
7731 tvb, offset, lvt+tag_len, val);
7732 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7734 else
7736 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7737 ett_bacapp_tag, NULL, "Event Type - %u octets (Signed)", lvt);
7739 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7740 offset += tag_len + lvt;
7742 return offset;
7745 static unsigned
7746 fNotifyType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7748 uint32_t val = 0, lvt;
7749 uint8_t tag_no, tag_info;
7750 proto_item *ti;
7751 proto_tree *subtree;
7752 unsigned tag_len;
7754 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7755 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
7757 ti = proto_tree_add_uint(tree, hf_bacapp_notify_type,
7758 tvb, offset, lvt+tag_len, val);
7759 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7761 else
7763 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7764 ett_bacapp_tag, NULL, "Notify Type - %u octets (Signed)", lvt);
7766 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7767 offset += tag_len + lvt;
7769 return offset;
7772 static unsigned
7773 fToState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7775 uint32_t val = 0, lvt;
7776 uint8_t tag_no, tag_info;
7777 proto_item *ti;
7778 proto_tree *subtree;
7779 unsigned tag_len;
7781 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7782 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
7784 ti = proto_tree_add_uint(tree, hf_bacapp_tag_to_state,
7785 tvb, offset, lvt+tag_len, val);
7786 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7788 else
7790 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7791 ett_bacapp_tag, NULL, "To State - %u octets (Signed)", lvt);
7793 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7794 offset += tag_len + lvt;
7796 return offset;
7799 static unsigned
7800 fFromState(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7802 uint32_t val = 0, lvt;
7803 uint8_t tag_no, tag_info;
7804 proto_item *ti;
7805 proto_tree *subtree;
7806 unsigned tag_len;
7808 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7809 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
7811 ti = proto_tree_add_uint(tree, hf_bacapp_tag_from_state,
7812 tvb, offset, lvt+tag_len, val);
7813 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7815 else
7817 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7818 ett_bacapp_tag, NULL, "From State - %u octets (Signed)", lvt);
7820 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7821 offset += tag_len + lvt;
7823 return offset;
7826 static unsigned
7827 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7829 uint32_t val = 0, lvt;
7830 uint8_t tag_no, tag_info;
7831 proto_tree *subtree;
7832 unsigned tag_len;
7834 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7835 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
7836 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7837 ett_bacapp_tag, NULL,
7838 "%s (hh.mm.ss): %d.%02d.%02d%s",
7839 label,
7840 (val / 3600), ((val % 3600) / 60), (val % 60),
7841 val == 0 ? " (indefinite)" : "");
7842 else
7843 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7844 ett_bacapp_tag, NULL,
7845 "%s - %u octets (Signed)", label, lvt);
7846 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7848 return offset+tag_len+lvt;
7851 static unsigned
7852 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7854 uint32_t month, weekOfMonth, dayOfWeek;
7855 uint8_t tag_no, tag_info;
7856 uint32_t lvt;
7857 unsigned tag_len;
7858 proto_tree *subtree;
7860 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7861 month = tvb_get_uint8(tvb, offset+tag_len);
7862 weekOfMonth = tvb_get_uint8(tvb, offset+tag_len+1);
7863 dayOfWeek = tvb_get_uint8(tvb, offset+tag_len+2);
7864 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7865 ett_bacapp_tag, NULL, "%s %s, %s",
7866 val_to_str(month, months, "month (%d) not found"),
7867 val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
7868 val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
7869 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7871 return offset+tag_len+lvt;
7874 static unsigned
7875 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7877 uint32_t year, month, day, weekday;
7878 uint8_t tag_no, tag_info;
7879 uint32_t lvt;
7880 unsigned tag_len;
7881 proto_tree *subtree;
7883 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7884 year = tvb_get_uint8(tvb, offset+tag_len);
7885 month = tvb_get_uint8(tvb, offset+tag_len+1);
7886 day = tvb_get_uint8(tvb, offset+tag_len+2);
7887 weekday = tvb_get_uint8(tvb, offset+tag_len+3);
7888 if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
7889 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7890 ett_bacapp_tag, NULL,
7891 "%sany", label);
7893 else if (year != 255) {
7894 year += 1900;
7895 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7896 ett_bacapp_tag, NULL,
7897 "%s%s %d, %d, (Day of Week = %s)",
7898 label, val_to_str(month,
7899 months,
7900 "month (%d) not found"),
7901 day, year, val_to_str(weekday,
7902 day_of_week,
7903 "(%d) not found"));
7904 } else {
7905 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7906 ett_bacapp_tag, NULL,
7907 "%s%s %d, any year, (Day of Week = %s)",
7908 label, val_to_str(month, months, "month (%d) not found"),
7909 day, val_to_str(weekday, day_of_week, "(%d) not found"));
7911 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7913 return offset+tag_len+lvt;
7916 static unsigned
7917 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7919 uint32_t hour, minute, second, msec, lvt;
7920 uint8_t tag_no, tag_info;
7921 unsigned tag_len;
7922 proto_tree *subtree;
7924 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7925 hour = tvb_get_uint8(tvb, offset+tag_len);
7926 minute = tvb_get_uint8(tvb, offset+tag_len+1);
7927 second = tvb_get_uint8(tvb, offset+tag_len+2);
7928 msec = tvb_get_uint8(tvb, offset+tag_len+3);
7929 if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
7930 subtree = proto_tree_add_subtree_format(tree, tvb, offset,
7931 lvt+tag_len, ett_bacapp_tag, NULL,
7932 "%sany", label);
7933 else
7934 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
7935 ett_bacapp_tag, NULL,
7936 "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
7937 label,
7938 hour > 12 ? hour - 12 : hour,
7939 minute, second, msec,
7940 hour >= 12 ? "P.M." : "A.M.",
7941 hour, minute, second, msec);
7942 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7944 return offset+tag_len+lvt;
7947 static unsigned
7948 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
7950 proto_tree *subtree = tree;
7952 if (label != NULL) {
7953 subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
7955 offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
7956 return fTime(tvb, pinfo, subtree, offset, "Time: ");
7959 static unsigned
7960 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7962 unsigned lastoffset = 0;
7963 uint8_t tag_no, tag_info;
7964 uint32_t lvt;
7966 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7967 lastoffset = offset;
7968 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7969 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
7970 return offset;
7972 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
7973 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
7975 if (offset <= lastoffset) break; /* exit loop if nothing happens inside */
7977 return offset;
7980 static unsigned
7981 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
7983 uint8_t tag_no, tag_info;
7984 uint32_t lvt;
7986 switch (fTagNo(tvb, offset)) {
7987 case 0: /* Date */
7988 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
7989 break;
7990 case 1: /* dateRange */
7991 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7992 offset = fDateRange(tvb, pinfo, tree, offset);
7993 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7994 break;
7995 case 2: /* BACnetWeekNDay */
7996 offset = fWeekNDay(tvb, pinfo, tree, offset);
7997 break;
7998 default:
7999 return offset;
8002 return offset;
8005 static unsigned
8006 fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8008 uint32_t lvt = 0;
8009 proto_tree* subtree = tree;
8011 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8012 subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
8014 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
8015 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
8016 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
8018 return offset;
8021 static unsigned
8022 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
8024 uint8_t tag_no = 0, tag_info = 0;
8025 uint32_t lvt = 0;
8027 if (tvb_reported_length_remaining(tvb, offset) > 0) { /* don't loop, it's a CHOICE */
8028 switch (fTagNo(tvb, offset)) {
8029 case 0: /* time */
8030 offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
8031 break;
8032 case 1: /* sequenceNumber */
8033 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8034 label?label:"sequence number: ");
8035 break;
8036 case 2: /* dateTime */
8037 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8038 offset = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
8039 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8040 break;
8041 default:
8042 return offset;
8046 return offset;
8050 static unsigned
8051 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8053 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8054 offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
8056 return offset;
8059 static const value_string
8060 BACnetDaysOfWeek [] = {
8061 { 0, "Monday" },
8062 { 1, "Tuesday" },
8063 { 2, "Wednesday" },
8064 { 3, "Thursday" },
8065 { 4, "Friday" },
8066 { 5, "Saturday" },
8067 { 6, "Sunday" },
8068 { 0, NULL }
8071 static unsigned
8072 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8074 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8075 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8076 "valid Days: ", BACnetDaysOfWeek);
8077 offset = fTime(tvb, pinfo, tree, offset, "from time: ");
8078 offset = fTime(tvb, pinfo, tree, offset, "to time: ");
8079 offset = fRecipient(tvb, pinfo, tree, offset);
8080 offset = fProcessId(tvb, pinfo, tree, offset);
8081 offset = fApplicationTypes(tvb, pinfo, tree, offset,
8082 "issue confirmed notifications: ");
8083 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
8084 "transitions: ", BACnetEventTransitionBits);
8086 return offset;
8090 static unsigned
8091 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt)
8093 char *tmp;
8094 unsigned start = offset;
8095 uint8_t tag_no, tag_info;
8096 proto_tree *subtree = tree;
8098 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8100 if (lvt > 0) {
8101 tmp = tvb_bytes_to_str(pinfo->pool, tvb, offset, lvt);
8102 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt,
8103 ett_bacapp_tag, NULL, "%s %s", label, tmp);
8104 offset += lvt;
8107 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
8109 return offset;
8112 static unsigned
8113 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, uint32_t lvt)
8115 unsigned start = offset;
8116 uint8_t tag_no, tag_info;
8117 proto_tree* subtree = tree;
8119 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8121 /* just add the label, with the tagHeader information in its subtree */
8122 subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, label);
8124 if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
8125 proto_tree_add_item(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ENC_BIG_ENDIAN);
8126 proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, ENC_BIG_ENDIAN);
8127 } else if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
8128 proto_tree_add_item(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, ENC_NA);
8129 proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, ENC_BIG_ENDIAN);
8130 } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
8131 subtree = proto_tree_add_subtree(tree, tvb, offset, lvt,
8132 ett_bacapp_tag, NULL, tvb_bytes_to_str(pinfo->pool, tvb, offset, lvt));
8134 offset += lvt;
8136 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
8138 return offset;
8141 static unsigned
8142 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8144 uint8_t tag_no, tag_info;
8145 uint32_t lvt;
8146 unsigned offs;
8148 offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
8149 offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8150 if (lvt == 0) {
8151 proto_tree_add_item(tree, hf_bacapp_tag_mac_address_broadcast, tvb, offset, offs, ENC_NA);
8152 offset += offs;
8153 } else
8154 offset = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
8156 return offset;
8159 static unsigned
8160 fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8162 offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
8163 return fAddress(tvb, pinfo, tree, offset);
8166 static unsigned
8167 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
8169 uint8_t tag_no, tag_info;
8170 uint32_t lvt;
8171 unsigned tag_length;
8172 proto_tree *subtree;
8173 uint32_t object_id;
8175 tag_length = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8176 object_id = tvb_get_ntohl(tvb, offset+tag_length);
8177 object_type = object_id_type(object_id);
8178 subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_length + 4,
8179 ett_bacapp_tag, NULL, "%s%s, %u", label,
8180 val_to_split_str(object_type,
8181 128,
8182 BACnetObjectType,
8183 ASHRAE_Reserved_Fmt,
8184 Vendor_Proprietary_Fmt),
8185 object_id_instance(object_id));
8187 col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
8188 val_to_split_str(object_type,
8189 128,
8190 BACnetObjectType,
8191 ASHRAE_Reserved_Fmt,
8192 Vendor_Proprietary_Fmt),
8193 object_id_instance(object_id));
8195 /* update BACnet Statistics */
8196 updateBacnetInfoValue(BACINFO_OBJECTID,
8197 wmem_strdup(pinfo->pool,
8198 val_to_split_str(object_type, 128,
8199 BACnetObjectType, ASHRAE_Reserved_Fmt,
8200 Vendor_Proprietary_Fmt)));
8201 updateBacnetInfoValue(BACINFO_INSTANCEID,
8202 wmem_strdup_printf(pinfo->pool,
8203 "Instance ID: %u",
8204 object_id_instance(object_id)));
8206 /* here are the details of how we arrived at the above text */
8207 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8208 offset += tag_length;
8209 proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
8210 proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, ENC_BIG_ENDIAN);
8211 offset += 4;
8213 return offset;
8216 static unsigned
8217 fObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8219 return fCharacterStringBase(tvb, pinfo, tree, offset, "Object Name", false, true);
8222 static unsigned
8223 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8225 uint8_t tag_no, tag_info;
8226 uint32_t lvt;
8228 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8229 if (tag_no < 2) {
8230 if (tag_no == 0) { /* device */
8231 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
8233 else { /* address */
8234 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8235 offset = fAddress(tvb, pinfo, tree, offset);
8236 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8239 return offset;
8242 static unsigned
8243 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8245 unsigned lastoffset = 0;
8246 uint8_t tag_no, tag_info;
8247 uint32_t lvt;
8248 proto_tree *orgtree = tree;
8249 proto_tree *subtree;
8251 /* beginning of new item - indent and label */
8252 tree = proto_tree_add_subtree(orgtree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient Process" );
8254 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8255 lastoffset = offset;
8257 switch (fTagNo(tvb, offset)) {
8258 case 0: /* recipient */
8259 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
8260 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient"); /* add tree label and indent */
8261 offset = fRecipient(tvb, pinfo, subtree, offset);
8262 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
8263 break;
8264 case 1: /* processId */
8265 offset = fProcessId(tvb, pinfo, tree, offset);
8266 lastoffset = offset;
8267 break;
8268 default:
8269 break;
8271 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8273 return offset;
8276 static unsigned
8277 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8279 unsigned lastoffset = 0;
8280 uint8_t tag_no, tag_info;
8281 uint32_t lvt;
8282 proto_tree *subtree;
8283 proto_tree *orgtree = tree;
8284 unsigned itemno = 1;
8286 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8287 lastoffset = offset;
8288 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8289 if (tag_is_closing(tag_info) ) {
8290 return offset;
8292 switch (tag_no) {
8294 case 0: /* recipient */
8295 /* beginning of new item in list */
8296 tree = proto_tree_add_subtree_format(orgtree, tvb, offset, 1,
8297 ett_bacapp_value, NULL, "Subscription %d",itemno); /* add tree label and indent */
8298 itemno = itemno + 1;
8300 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
8301 ett_bacapp_value, NULL, "Recipient"); /* add tree label and indent */
8302 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
8303 offset = fRecipientProcess(tvb, pinfo, subtree, offset);
8304 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
8305 break;
8306 case 1: /* MonitoredPropertyReference */
8307 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
8308 ett_bacapp_value, NULL, "Monitored Property Reference");
8309 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8310 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
8311 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8312 break;
8313 case 2: /* IssueConfirmedNotifications - boolean */
8314 offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
8315 break;
8316 case 3: /* TimeRemaining */
8317 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
8318 break;
8319 case 4: /* COVIncrement */
8320 offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
8321 break;
8322 default:
8323 break;
8325 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8327 return offset;
8330 static unsigned
8331 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8333 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
8334 return fAddress(tvb, pinfo, tree, offset);
8337 static unsigned
8338 // NOLINTNEXTLINE(misc-no-recursion)
8339 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_match)
8341 unsigned lastoffset = 0, len;
8342 uint8_t tag_no, tag_info;
8343 uint32_t lvt;
8344 proto_tree *subtree = tree;
8346 /* set the optional global properties to indicate not-used */
8347 propertyArrayIndex = -1;
8348 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8349 lastoffset = offset;
8350 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8351 if (tag_is_closing(tag_info) ) {
8352 if (tag_no == tag_match) {
8353 return offset;
8355 offset += len;
8356 subtree = tree;
8357 continue;
8359 switch (tag_no) {
8361 case 0: /* deviceIdentifier */
8362 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "DeviceIdentifier: ");
8363 break;
8364 case 1: /* objectIdentifier */
8365 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
8366 break;
8367 case 2: /* propertyIdentifier */
8368 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
8369 break;
8370 case 3: /* propertyArrayIndex */
8371 offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
8372 break;
8373 case 4: /* propertyValue */
8374 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
8375 break;
8376 case 5: /* priority */
8377 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
8378 break;
8379 case 6: /* postDelay */
8380 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
8381 break;
8382 case 7: /* quitOnFailure */
8383 offset = fBooleanTag(tvb, pinfo, subtree, offset,
8384 "Quit On Failure: ");
8385 break;
8386 case 8: /* writeSuccessful */
8387 offset = fBooleanTag(tvb, pinfo, subtree, offset,
8388 "Write Successful: ");
8389 break;
8390 default:
8391 return offset;
8393 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8395 return offset;
8398 /* BACnetActionList ::= SEQUENCE{
8399 action [0] SEQUENCE OF BACnetActionCommand
8402 static unsigned
8403 // NOLINTNEXTLINE(misc-no-recursion)
8404 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8406 unsigned lastoffset = 0, len;
8407 uint8_t tag_no, tag_info;
8408 uint32_t lvt;
8409 proto_tree *subtree = tree;
8411 while (tvb_reported_length_remaining(tvb, offset) > 0) {
8412 lastoffset = offset;
8413 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8414 if (tag_is_closing(tag_info)) {
8415 if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
8416 return offset;
8417 /* print closing tag of action list too */
8418 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8419 subtree = tree;
8420 offset += len;
8421 continue;
8423 if (tag_is_opening(tag_info)) {
8424 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "Action List");
8425 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
8426 &tag_no, &tag_info, &lvt);
8428 switch (tag_no) {
8429 case 0: /* BACnetActionCommand */
8430 offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
8431 break;
8432 default:
8433 break;
8435 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8437 return offset;
8440 static unsigned
8441 // NOLINTNEXTLINE(misc-no-recursion)
8442 fPropertyAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8444 unsigned lastoffset = 0;
8445 uint8_t tag_no, tag_info;
8446 uint32_t lvt;
8447 uint32_t save_object_type;
8448 uint32_t save_inner_object_type;
8449 int32_t save_propertyIdentifier;
8451 /* save the external entry data because it might get overwritten here */
8452 save_object_type = object_type;
8453 save_propertyIdentifier = propertyIdentifier;
8455 /* inner object type might get overwritten by device id */
8456 save_inner_object_type = object_type;
8458 while (tvb_reported_length_remaining(tvb, offset) > 0) {
8459 lastoffset = offset;
8460 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8461 if (tag_is_closing(tag_info)) {
8462 break;
8465 switch (tag_no) {
8466 case 0: /* objectIdentifier */
8467 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
8468 /* save the local object type because device id might overwrite it */
8469 save_inner_object_type = object_type;
8470 break;
8471 case 1: /* propertyIdentifier */
8472 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
8473 break;
8474 case 2: /* propertyArrayIndex */
8475 offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
8476 break;
8477 case 3: /* deviceIdentifier */
8478 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
8479 /* restore the inner object type to decode the right property value */
8480 object_type = save_inner_object_type;
8481 break;
8482 case 4: /* propertyValue */
8483 offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
8484 /* restore the external values for next loop */
8485 object_type = save_object_type;
8486 propertyIdentifier = save_propertyIdentifier;
8487 break;
8488 case 5: /* propertyAccessError */
8489 if (tag_is_opening(tag_info)) {
8490 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8491 offset = fError(tvb, pinfo, tree, offset);
8492 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8494 else {
8495 expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
8497 /* restore the external values for next loop */
8498 object_type = save_object_type;
8499 propertyIdentifier = save_propertyIdentifier;
8500 break;
8501 default:
8502 break;
8505 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8508 /* restore the external values for next decoding */
8509 object_type = save_object_type;
8510 propertyIdentifier = save_propertyIdentifier;
8511 return offset;
8514 static unsigned
8515 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8517 uint8_t tag_no, tag_info;
8518 uint32_t lvt;
8519 unsigned tag_len;
8520 proto_tree *subtree;
8521 static const char *label = "Property Identifier";
8523 propertyIdentifier = 0; /* global Variable */
8524 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8525 /* can we decode this value? */
8526 if (fUnsigned32(tvb, offset+tag_len, lvt, (uint32_t *)&propertyIdentifier)) {
8527 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
8528 ett_bacapp_tag, NULL,
8529 "%s: %s (%u)", label,
8530 val_to_split_str(propertyIdentifier, 512,
8531 BACnetPropertyIdentifier,
8532 ASHRAE_Reserved_Fmt,
8533 Vendor_Proprietary_Fmt), propertyIdentifier);
8534 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
8535 val_to_split_str(propertyIdentifier, 512,
8536 BACnetPropertyIdentifier,
8537 ASHRAE_Reserved_Fmt,
8538 Vendor_Proprietary_Fmt));
8539 } else {
8540 /* property identifiers cannot be larger than 22-bits */
8541 return offset;
8544 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8545 proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
8546 offset+tag_len, lvt, ENC_BIG_ENDIAN);
8548 return offset+tag_len+lvt;
8551 static unsigned
8552 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8554 uint8_t tag_no, tag_info;
8555 uint32_t lvt;
8556 unsigned tag_len;
8557 proto_tree *subtree;
8559 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8560 if (fUnsigned32(tvb, offset + tag_len, lvt, (uint32_t *)&propertyArrayIndex))
8561 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
8562 ett_bacapp_tag, NULL, "property Array Index (Unsigned) %u", propertyArrayIndex);
8563 else
8564 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
8565 ett_bacapp_tag, NULL, "property Array Index - %u octets (Unsigned)", lvt);
8566 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8568 return offset+tag_len+lvt;
8571 static unsigned
8572 fChannelValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
8574 uint8_t tag_no, tag_info;
8575 uint32_t lvt;
8577 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8578 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8579 if (tag_is_opening(tag_info) && tag_no == 0) {
8580 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8581 offset = fLightingCommand(tvb, pinfo, tree, offset, "lighting-command: ");
8582 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8583 } else if (tag_is_opening(tag_info) && tag_no == 1) {
8584 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8585 offset = fXyColor(tvb, pinfo, tree, offset, "xy-color: ");
8586 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8587 } else if (tag_is_opening(tag_info) && tag_no == 2) {
8588 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8589 offset = fColorCommand(tvb, pinfo, tree, offset, "color-command: ");
8590 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8591 } else {
8592 if (tag_info) {
8593 offset = fContextTaggedValue(tvb, pinfo, tree, offset, label);
8594 } else {
8595 offset = fApplicationTypes(tvb, pinfo, tree, offset, label);
8600 return offset;
8603 static unsigned
8604 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
8606 return fCharacterStringBase(tvb, pinfo, tree, offset, label, false, false);
8609 static unsigned
8610 fCharacterStringBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, bool present_val_dissect, bool object_name_dissect)
8612 uint8_t tag_no, tag_info, character_set;
8613 uint32_t lvt, l;
8614 unsigned offs;
8615 const char *coding;
8616 uint8_t *out;
8617 proto_tree *subtree;
8618 unsigned start = offset;
8620 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8622 offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8623 offset += offs;
8625 character_set = tvb_get_uint8(tvb, offset);
8626 offset++;
8627 lvt--;
8629 /* Account for code page if DBCS */
8630 if (character_set == IBM_MS_DBCS) {
8631 offset += 2;
8632 lvt -= 2;
8635 do {
8636 l = MIN(lvt, 256);
8638 * XXX - are we guaranteed that these encoding
8639 * names correspond, on *all* platforms with
8640 * iconv(), to the encodings we want?
8642 * Not necessarily. These specify "character sets" but
8643 * not the encodings. IBM/MS DBCS specifies that it uses
8644 * some IBM or MS double byte character set, but does not
8645 * specify the code page - there was a proposal to explicitly
8646 * add the code page, but that was apparently withdrawn in favor
8647 * of just deprecating using DBCS, as it never got past a draft
8648 * (One problem could be that IBM and MS code pages with the
8649 * same number are slightly different, and then there's non
8650 * IBM/MS unofficial ones that got used, sometimes conflicting
8651 * numbers.) Even if we assume that they certainly mean one
8652 * of the DBCS and not just any non ISO-8859-1 code page, there's
8653 * all four types of CJK to choose from. -
8654 * http://www.bacnet.org/Addenda/Add-135-2004k-PPR1-chair-approved.pdf
8655 * JIS C 6226 (now JIS X 0208)
8656 * http://www.bacnet.org/Addenda/Add-135-2008k.pdf
8657 * is a character set, which are supported by several different
8658 * encodings, the main types being ISO-2022-JP (JIS X 0202,
8659 * a 7 bit encoding), Shift-JIS (most common), and EUC-JP (UNIX).
8660 * It is unclear which encoding this refers to.
8662 * If not (and perhaps even if so), we should
8663 * perhaps have our own iconv() implementation,
8664 * with a different name, so that we control the
8665 * encodings it supports and the names of those
8666 * encodings.
8668 * We should also handle that in the general
8669 * string handling code, rather than making it
8670 * specific to the BACAPP dissector, as many
8671 * other dissectors need to handle various
8672 * character encodings.
8674 /** this decoding may be not correct for multi-byte characters, Lka */
8675 switch (character_set) {
8676 case ANSI_X3_4:
8677 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UTF_8);
8678 coding = "UTF-8";
8679 break;
8680 case IBM_MS_DBCS:
8681 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
8682 coding = "IBM MS DBCS";
8683 break;
8684 case JIS_C_6226:
8685 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
8686 coding = "JIS C 6226";
8687 break;
8688 case ISO_10646_UCS4:
8689 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UCS_4|ENC_BIG_ENDIAN);
8690 coding = "ISO 10646 UCS-4";
8691 break;
8692 case ISO_10646_UCS2:
8693 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_UCS_2|ENC_BIG_ENDIAN);
8694 coding = "ISO 10646 UCS-2";
8695 break;
8696 case ISO_8859_1:
8697 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ISO_8859_1);
8698 coding = "ISO 8859-1";
8699 break;
8700 default:
8701 /* Assume this is some form of extended ASCII, with one-byte code points for ASCII characters */
8702 out = tvb_get_string_enc(pinfo->pool, tvb, offset, l, ENC_ASCII);
8703 coding = "unknown";
8704 break;
8707 if (present_val_dissect) {
8708 subtree = proto_tree_add_subtree(tree, tvb, offset, l, ett_bacapp_tag, NULL, "present-value");
8709 proto_tree_add_string(subtree, hf_bacapp_present_value_char_string, tvb, offset, l, (const char*) out);
8710 } else if (object_name_dissect) {
8711 subtree = proto_tree_add_subtree(tree, tvb, offset, l, ett_bacapp_tag, NULL, label);
8712 proto_tree_add_string(subtree, hf_bacapp_object_name, tvb, offset, l, (const char*) out);
8713 } else {
8714 subtree = proto_tree_add_subtree_format(tree, tvb, offset, l, ett_bacapp_tag, NULL,
8715 "%s%s '%s'", label, coding, out);
8718 lvt -= l;
8719 offset += l;
8720 } while (lvt > 0);
8722 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
8723 proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
8725 if (character_set == IBM_MS_DBCS) {
8726 proto_tree_add_item(subtree, hf_BACnetCodePage, tvb, start+offs+1, 2, ENC_BIG_ENDIAN);
8728 /* XXX - put the string value here */
8730 return offset;
8733 static unsigned
8734 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
8735 const value_string *src)
8737 return fBitStringTagVSBase(tvb, pinfo, tree, offset, label, src, false);
8740 static unsigned
8741 fBitStringTagVSBase(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label,
8742 const value_string *src, bool present_val_dissect)
8744 uint8_t tag_no, tag_info, tmp;
8745 int j, unused, skip;
8746 unsigned start = offset;
8747 unsigned offs;
8748 uint32_t lvt, i, numberOfBytes;
8749 char bf_arr[256 + 1];
8750 proto_tree *subtree = tree;
8752 offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8753 numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
8754 offset += offs;
8755 unused = tvb_get_uint8(tvb, offset); /* get the unused Bits */
8757 memset(bf_arr, 0, sizeof(bf_arr));
8758 skip = 0;
8759 for (i = 0; i < numberOfBytes; i++) {
8760 tmp = tvb_get_uint8(tvb, (offset)+i + 1);
8761 if (i == numberOfBytes - 1) { skip = unused; }
8762 for (j = 0; j < 8 - skip; j++) {
8763 bf_arr[MIN(sizeof(bf_arr) - 2, (i * 8) + j)] = tmp & (1 << (7 - j)) ? 'T' : 'F';
8767 if (!present_val_dissect) {
8768 subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
8769 ett_bacapp_tag, NULL,
8770 "%s(Bit String) (%s)", label, bf_arr);
8771 } else {
8772 subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
8773 ett_bacapp_tag, NULL,
8774 "present-value (%s)", bf_arr);
8777 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
8778 proto_tree_add_item(subtree, hf_bacapp_unused_bits, tvb, offset, 1, ENC_NA);
8779 memset(bf_arr, 0, sizeof(bf_arr));
8780 skip = 0;
8781 for (i = 0; i < numberOfBytes; i++) {
8782 tmp = tvb_get_uint8(tvb, (offset)+i+1);
8783 if (i == numberOfBytes-1) { skip = unused; }
8784 for (j = 0; j < 8-skip; j++) {
8785 if (src != NULL) {
8786 proto_tree_add_boolean_format(subtree, hf_bacapp_bit, tvb, offset+i+1, 1,
8787 (tmp & (1 << (7 - j))), "%s = %s",
8788 val_to_str((unsigned) (i*8 +j), src, ASHRAE_Reserved_Fmt),
8789 (tmp & (1 << (7 - j))) ? "TRUE" : "FALSE");
8790 } else {
8791 bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
8796 if (src == NULL) {
8797 bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
8798 proto_tree_add_bytes_format(subtree, hf_bacapp_complete_bitstring, tvb, offset, lvt, NULL, "B'%s'", bf_arr);
8801 offset += lvt;
8803 return offset;
8806 static unsigned
8807 fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
8809 return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
8812 /* handles generic application types, as well as enumerated and enumerations
8813 with reserved and proprietarty ranges (split) */
8814 static unsigned
8815 fApplicationTypesEnumeratedSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
8816 const char *label, const value_string *src, uint32_t split_val)
8818 uint8_t tag_no, tag_info;
8819 uint32_t lvt;
8820 unsigned tag_len;
8822 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8823 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8824 if (!tag_is_context_specific(tag_info)) {
8825 switch (tag_no) {
8826 case 0: /** NULL 20.2.2 */
8827 offset = fNullTag(tvb, pinfo, tree, offset, label);
8828 break;
8829 case 1: /** BOOLEAN 20.2.3 */
8830 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
8831 break;
8832 case 2: /** Unsigned Integer 20.2.4 */
8833 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
8834 break;
8835 case 3: /** Signed Integer 20.2.5 */
8836 offset = fSignedTag(tvb, pinfo, tree, offset, label);
8837 break;
8838 case 4: /** Real 20.2.6 */
8839 offset = fRealTag(tvb, pinfo, tree, offset, label);
8840 break;
8841 case 5: /** Double 20.2.7 */
8842 offset = fDoubleTag(tvb, pinfo, tree, offset, label);
8843 break;
8844 case 6: /** Octet String 20.2.8 */
8845 offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
8846 break;
8847 case 7: /** Character String 20.2.9 */
8848 offset = fCharacterString(tvb, pinfo, tree, offset, label);
8849 break;
8850 case 8: /** Bit String 20.2.10 */
8851 offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
8852 break;
8853 case 9: /** Enumerated 20.2.11 */
8854 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
8855 break;
8856 case 10: /** Date 20.2.12 */
8857 offset = fDate(tvb, pinfo, tree, offset, label);
8858 break;
8859 case 11: /** Time 20.2.13 */
8860 offset = fTime(tvb, pinfo, tree, offset, label);
8861 break;
8862 case 12: /** BACnetObjectIdentifier 20.2.14 */
8863 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
8864 break;
8865 case 13: /* reserved for ASHRAE */
8866 case 14:
8867 case 15:
8868 proto_tree_add_bytes_format(tree, hf_bacapp_reserved_ashrea, tvb, offset, lvt+tag_len, NULL, "%s'reserved for ASHRAE'", label);
8869 offset += lvt + tag_len;
8870 break;
8871 default:
8872 break;
8876 return offset;
8879 static unsigned
8880 fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8882 unsigned lastoffset = 0;
8884 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8885 lastoffset = offset;
8887 switch (fTagNo(tvb, offset)) {
8888 case 0: /* percent */
8889 offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
8890 break;
8891 case 1: /* level */
8892 offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
8893 break;
8894 case 2: /* amount */
8895 offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
8896 break;
8897 default:
8898 return offset;
8900 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8902 return offset;
8905 static unsigned
8906 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
8907 const char *label, const value_string *vs)
8909 return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
8912 static unsigned
8913 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
8914 const char *label)
8916 return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
8919 static unsigned
8920 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
8922 uint8_t tag_no, tag_info;
8923 uint32_t lvt;
8924 unsigned tag_len;
8925 proto_tree *subtree;
8926 int tvb_len;
8928 (void)label;
8929 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8930 /* cap the the suggested length in case of bad data */
8931 tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
8932 if ((tvb_len >= 0) && ((uint32_t)tvb_len < lvt)) {
8933 lvt = tvb_len;
8935 subtree = proto_tree_add_subtree_format(tree, tvb, offset+tag_len, lvt,
8936 ett_bacapp_tag, NULL, "Context Value (as %u DATA octets)", lvt);
8938 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8940 return offset + tag_len + lvt;
8943 BACnetPrescale ::= SEQUENCE {
8944 multiplier [0] Unsigned,
8945 moduloDivide [1] Unsigned
8948 static unsigned
8949 fPrescale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8951 uint8_t tag_no, tag_info;
8952 uint32_t lvt;
8953 unsigned lastoffset = 0;
8955 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8956 lastoffset = offset;
8957 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8958 if (tag_is_closing(tag_info) ) {
8959 return offset;
8961 switch (tag_no) {
8962 case 0: /* multiplier */
8963 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
8964 break;
8965 case 1: /* moduloDivide */
8966 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
8967 break;
8968 default:
8969 return offset;
8971 if (offset <= lastoffset) break; /* nothing happened, exit loop */
8973 return offset;
8977 BACnetScale ::= CHOICE {
8978 floatScale [0] REAL,
8979 integerScale [1] INTEGER
8982 static unsigned
8983 fScale(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
8985 uint8_t tag_no, tag_info;
8986 uint32_t lvt;
8987 unsigned lastoffset = 0;
8989 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8990 lastoffset = offset;
8991 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8992 if (tag_is_closing(tag_info) ) {
8993 return offset;
8995 switch (tag_no) {
8996 case 0: /* floatScale */
8997 offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
8998 break;
8999 case 1: /* integerScale */
9000 offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
9001 break;
9002 default:
9003 return offset;
9005 if (offset <= lastoffset) break; /* nothing happened, exit loop */
9007 return offset;
9010 BACnetAccumulatorRecord ::= SEQUENCE {
9011 timestamp [0] BACnetDateTime,
9012 presentValue [1] Unsigned,
9013 accumulatedValue [2] Unsigned,
9014 accumulatortStatus [3] ENUMERATED {
9015 normal (0),
9016 starting (1),
9017 recovered (2),
9018 abnormal (3),
9019 failed (4)
9023 static unsigned
9024 fLoggingRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9026 uint8_t tag_no, tag_info;
9027 uint32_t lvt;
9028 unsigned lastoffset = 0;
9030 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9031 lastoffset = offset;
9032 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9033 if (tag_is_closing(tag_info) ) {
9034 return offset;
9036 switch (tag_no) {
9037 case 0: /* timestamp */
9038 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9039 offset = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
9040 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9041 break;
9042 case 1: /* presentValue */
9043 offset = fPresentValue(tvb, pinfo, tree, offset, NULL, 0, BACAPP_PRESENT_VALUE_UNSIGNED);
9044 break;
9045 case 2: /* accumulatedValue */
9046 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
9047 break;
9048 case 3: /* accumulatorStatus */
9049 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
9050 break;
9051 default:
9052 return offset;
9054 if (offset <= lastoffset) break; /* nothing happened, exit loop */
9056 return offset;
9060 SEQ OF Any enumeration (current usage is SEQ OF BACnetDoorAlarmState
9062 static unsigned
9063 fSequenceOfEnums(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label, const value_string *vs)
9065 uint8_t tag_no, tag_info;
9066 uint32_t lvt;
9067 unsigned lastoffset = 0;
9069 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9070 lastoffset = offset;
9071 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9072 if (tag_is_closing(tag_info) ) {
9073 return offset;
9075 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
9076 if ( offset <= lastoffset ) break;
9078 return offset;
9082 SEQ OF BACnetDeviceObjectReference (accessed as an array)
9085 static unsigned
9086 fDoorMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9088 uint8_t tag_no, tag_info;
9089 uint32_t lvt;
9090 unsigned lastoffset = 0;
9092 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9093 lastoffset = offset;
9094 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9095 if (tag_is_closing(tag_info) ) {
9096 return offset;
9098 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
9099 if (offset <= lastoffset) break;
9101 return offset;
9105 SEQ OF ReadAccessSpecification
9107 static unsigned
9108 fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9110 uint8_t tag_no, tag_info;
9111 uint32_t lvt;
9112 unsigned lastoffset = 0;
9114 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9115 lastoffset = offset;
9116 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9117 if (tag_is_closing(tag_info) ) {
9118 return offset;
9120 offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
9121 if ( offset <= lastoffset ) break;
9123 return offset;
9126 static unsigned
9127 // NOLINTNEXTLINE(misc-no-recursion)
9128 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9130 uint8_t tag_no, tag_info;
9131 uint32_t lvt;
9132 unsigned lastoffset = 0, depth = 0;
9133 char ar[256];
9134 uint32_t save_object_type;
9135 bool do_default_handling;
9137 if (propertyIdentifier >= 0) {
9138 snprintf(ar, sizeof(ar), "%s: ",
9139 val_to_split_str(propertyIdentifier, 512,
9140 BACnetPropertyIdentifier,
9141 ASHRAE_Reserved_Fmt,
9142 Vendor_Proprietary_Fmt));
9143 } else {
9144 snprintf(ar, sizeof(ar), "Abstract Type: ");
9147 increment_dissection_depth(pinfo);
9149 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9150 lastoffset = offset;
9151 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9152 if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
9153 if (depth <= 0) {
9154 goto cleanup;
9158 do_default_handling = false;
9160 /* Application Tags */
9161 switch (propertyIdentifier) {
9162 case 0: /* acked-transitions */
9163 case 35: /* event-enable */
9164 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9165 BACnetAcknowledgedTransitions);
9166 break;
9167 case 2: /* action */
9168 /* loop object is application tagged,
9169 command object is context tagged */
9170 if (tag_is_context_specific(tag_info)) {
9171 /* BACnetActionList */
9172 offset = fActionList(tvb, pinfo, tree, offset);
9173 } else {
9174 /* BACnetAction */
9175 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9176 BACnetAction);
9178 break;
9179 case 7: /* alarm-values*/
9180 switch (object_type) {
9181 case 21: /* life-point */
9182 case 22: /* life-zone */
9183 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
9184 break;
9185 case 30: /* access-door */
9186 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
9187 break;
9188 case 31: /* timer */
9189 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
9190 break;
9191 case 36: /* access-zone */
9192 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
9193 break;
9194 case 39: /* bitstring-value */
9195 default:
9196 if (tag_info) {
9197 if (tag_is_opening(tag_info)) {
9198 ++depth;
9199 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9201 else if (tag_is_closing(tag_info)) {
9202 --depth;
9203 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9205 else {
9206 offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
9209 else {
9210 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9212 break;
9214 break;
9215 case 37: /* event-type */
9216 offset = fEventType(tvb, pinfo, tree, offset);
9217 break;
9218 case 39: /* fault-values */
9219 switch (object_type) {
9220 case 21: /* life-point */
9221 case 22: /* life-zone */
9222 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
9223 break;
9224 case 30: /* access-door */
9225 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
9226 break;
9227 case 31: /* timer */
9228 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
9229 break;
9230 case 36: /* access-zone */
9231 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
9232 break;
9233 case 39: /* bitstring-value */
9234 default:
9235 if (tag_info) {
9236 if (tag_is_opening(tag_info)) {
9237 ++depth;
9238 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9240 else if (tag_is_closing(tag_info)) {
9241 --depth;
9242 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9244 else {
9245 offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
9248 else {
9249 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9251 break;
9253 break;
9254 case 30: /* BACnetAddressBinding */
9255 case 331: /* last-key-server */
9256 offset = fAddressBinding(tvb, pinfo, tree, offset);
9257 break;
9258 case 52: /* limit-enable */
9259 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLimitEnable);
9260 break;
9261 case 54: /* list of object property reference */
9262 offset = fLOPR(tvb, pinfo, tree, offset);
9263 break;
9264 case 55: /* list-of-session-keys */
9265 fSessionKey(tvb, pinfo, tree, offset);
9266 break;
9267 case 77: /* object-name */
9268 offset = fObjectName(tvb, pinfo, tree, offset);
9269 break;
9270 case 79: /* object-type */
9271 case 96: /* protocol-object-types-supported */
9272 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
9273 BACnetObjectType, 128);
9274 break;
9275 case 97: /* Protocol-Services-Supported */
9276 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9277 BACnetServicesSupported);
9278 break;
9279 case 102: /* recipient-list */
9280 offset = fDestination(tvb, pinfo, tree, offset);
9281 break;
9282 case 107: /* segmentation-supported */
9283 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9284 BACnetSegmentation);
9285 break;
9286 case 111: /* Status-Flags */
9287 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9288 BACnetStatusFlags);
9289 break;
9290 case 112: /* System-Status */
9291 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9292 BACnetDeviceStatus);
9293 break;
9294 case 117: /* units */
9295 case 455: /* car-load-units */
9296 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
9297 BACnetEngineeringUnits);
9298 break;
9299 case 87: /* priority-array -- accessed as a BACnetARRAY */
9300 if (propertyArrayIndex == 0) {
9301 /* BACnetARRAY index 0 refers to the length
9302 of the array, not the elements of the array */
9303 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9304 } else {
9305 offset = fPriorityArray(tvb, pinfo, tree, offset);
9307 break;
9308 case 38: /* exception-schedule */
9309 if (object_type < 128) {
9310 if (propertyArrayIndex == 0) {
9311 /* BACnetARRAY index 0 refers to the length
9312 of the array, not the elements of the array */
9313 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9314 } else {
9315 offset = fSpecialEvent(tvb, pinfo, tree, offset);
9318 break;
9319 case 19: /* controlled-variable-reference */
9320 case 60: /* manipulated-variable-reference */
9321 case 78: /* object-property-reference */
9322 case 181: /* input-reference */
9323 case 355: /* event-algorithm-inhibit-reference */
9324 offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
9325 break;
9326 case 132: /* log-device-object-property */
9327 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9328 break;
9329 case 109: /* Setpoint-Reference */
9330 /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
9331 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9332 offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
9333 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9334 break;
9335 case 123: /* weekly-schedule -- accessed as a BACnetARRAY */
9336 if (object_type < 128) {
9337 if (propertyArrayIndex == 0) {
9338 /* BACnetARRAY index 0 refers to the length
9339 of the array, not the elements of the array */
9340 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9341 } else {
9342 offset = fWeeklySchedule(tvb, pinfo, tree, offset);
9345 break;
9346 case 127: /* client COV increment */
9347 offset = fClientCOV(tvb, pinfo, tree, offset);
9348 break;
9349 case 131: /* log-buffer */
9350 if ( object_type == 61 )
9351 offset = fAuditLogRecord(tvb, pinfo, tree, offset);
9352 else if ( object_type == 25 )
9353 offset = fEventLogRecord(tvb, pinfo, tree, offset);
9354 else if ( object_type == 27 )
9355 offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
9356 else
9357 offset = fLogRecord(tvb, pinfo, tree, offset);
9358 break;
9359 case 159: /* member-of */
9360 case 165: /* zone-members */
9361 case 211: /* subordinate-list */
9362 case 246: /* access-doors */
9363 case 249: /* access-event-credential */
9364 case 252: /* accompaniment */
9365 case 265: /* credentials */
9366 case 266: /* credentials-in-zone */
9367 case 277: /* last-credential-added */
9368 case 279: /* last-credential-removed */
9369 case 286: /* members */
9370 case 320: /* zone-from */
9371 case 321: /* zone-to */
9372 case 461: /* energy-meter-ref */
9373 case 491: /* represents */
9374 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
9375 break;
9376 case 196: /* last-restart-reason */
9377 offset = fRestartReason(tvb, pinfo, tree, offset);
9378 break;
9379 case 212: /* actual-shed-level */
9380 case 214: /* expected-shed-level */
9381 case 218: /* requested-shed-level */
9382 offset = fShedLevel(tvb, pinfo, tree, offset);
9383 break;
9384 case 152: /* active-cov-subscriptions */
9385 offset = fCOVSubscription(tvb, pinfo, tree, offset);
9386 break;
9387 case 23: /* date-list */
9388 offset = fCalendarEntry(tvb, pinfo, tree, offset);
9389 break;
9390 case 116: /* time-sychronization-recipients */
9391 case 206: /* utc-time-synchronization-recipients */
9392 case 202: /* restart-notification-recipients */
9393 offset = fRecipient(tvb, pinfo, tree, offset);
9394 break;
9395 case 83: /* event-parameters */
9396 offset = fEventParameter(tvb, pinfo, tree, offset);
9397 break;
9398 case 130: /* event-time-stamp */
9399 if (propertyArrayIndex == 0) {
9400 /* BACnetARRAY index 0 refers to the length
9401 of the array, not the elements of the array */
9402 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9403 } else {
9404 offset = fEventTimeStamps(tvb, pinfo, tree, offset);
9406 break;
9407 case 197: /* logging-type */
9408 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
9409 break;
9410 case 36: /* event-state */
9411 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
9412 break;
9413 case 103: /* reliability */
9414 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
9415 break;
9416 case 72: /* notify-type */
9417 offset = fNotifyType(tvb, pinfo, tree, offset);
9418 break;
9419 case 208: /* node-type */
9420 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
9421 break;
9422 case 231: /* door-status */
9423 case 450: /* car-door-status */
9424 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
9425 break;
9426 case 233: /* lock-status */
9427 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
9428 break;
9429 case 235: /* secured-status */
9430 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
9431 break;
9432 case 158: /* maintenance-required */
9433 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
9434 break;
9435 case 92: /* program-state */
9436 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
9437 break;
9438 case 90: /* program-change */
9439 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
9440 break;
9441 case 100: /* reason-for-halt */
9442 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
9443 break;
9444 case 157: /* last-restore-time */
9445 offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
9446 break;
9447 case 160: /* mode */
9448 case 175: /* accepted-modes */
9449 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
9450 break;
9451 case 163: /* silenced */
9452 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
9453 break;
9454 case 161: /* operation-expected */
9455 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
9456 break;
9457 case 164: /* tracking-value */
9458 if (object_type == 21 || object_type == 22) /* life-safety-point/zone */
9459 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
9460 else if (object_type == 63) /* color */
9461 offset = fXyColor(tvb, pinfo, tree, offset, ar);
9462 else if (object_type == 64) /* color-temperature */
9463 offset = fUnsignedTag(tvb, pinfo, tree, offset, ar);
9464 else if (object_type == 54) /* lighting-output */
9465 offset = fRealTag(tvb, pinfo, tree, offset, ar);
9466 break;
9467 case 166: /* life-safety-alarm-values */
9468 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
9469 break;
9470 case 41: /* file-access-method */
9471 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
9472 break;
9473 case 185: /* prescale */
9474 offset = fPrescale(tvb, pinfo, tree, offset);
9475 break;
9476 case 187: /* scale */
9477 offset = fScale(tvb, pinfo, tree, offset);
9478 break;
9479 case 189: /* update-time */
9480 if (object_type == 37) /* credential-data-input */
9481 offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
9482 else
9483 offset = fDateTime(tvb, pinfo, tree, offset, ar);
9484 break;
9485 case 184: /* logging-record */
9486 offset = fLoggingRecord(tvb, pinfo, tree, offset);
9487 break;
9488 case 203: /* time-of-device-restart */
9489 offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
9490 break;
9491 case 226: /* door-alarm-state */
9492 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
9493 break;
9494 case 228: /* door-members */
9495 offset = fDoorMembers(tvb, pinfo, tree, offset);
9496 break;
9497 case 234: /* masked-alarm-values */
9498 offset = fSequenceOfEnums(tvb, pinfo, tree, offset, ar, BACnetDoorAlarmState);
9499 break;
9500 case 248: /* access-event-authentication-factor */
9501 offset = fAuthenticationFactor(tvb, pinfo, tree, offset);
9502 break;
9503 case 261: /* authorization-mode */
9504 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuthorizationMode);
9505 break;
9506 case 53: /* list-of-group-members */
9507 save_object_type = object_type;
9508 offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
9509 object_type = save_object_type;
9510 break;
9511 case 296: /* occupancy-state */
9512 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessZoneOccupancyState);
9513 break;
9514 case 300: /* passback-mode */
9515 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessPassbackMode);
9516 break;
9517 case 303: /* reason-for-disable */
9518 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessCredentialDisableReason);
9519 break;
9520 case 318: /* user-type */
9521 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAccessUserType);
9522 break;
9523 case 330: /* key-sets */
9524 offset = fSecurityKeySet(tvb, pinfo, tree, offset);
9525 break;
9526 case 332: /* network-access-security-policies */
9527 offset = fNetworkSecurityPolicy(tvb, pinfo, tree, offset);
9528 break;
9529 case 338: /* backup-and-restore-state */
9530 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetBackupState);
9531 break;
9532 case 370: /* write-status */
9533 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetWriteStatus);
9534 break;
9535 case 385: /* transition */
9536 if (object_type == 54) /* lighting-output */
9537 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLightingTransition);
9538 else if (object_type == 63) /* color */
9539 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorTransition);
9540 else if (object_type == 64) /* color-temperature */
9541 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorTransition);
9542 break;
9543 case 288: /* negative-access-rules */
9544 case 302: /* positive-access-rules */
9545 offset = fAccessRule(tvb, pinfo, tree, offset);
9546 break;
9547 case 304: /* supported-formats */
9548 offset = fAuthenticationFactorFormat(tvb, pinfo, tree, offset);
9549 break;
9550 case 327: /* base-device-security-policy */
9551 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSecurityLevel);
9552 break;
9553 case 371: /* property-list */
9554 offset = fSequenceOfEnums(tvb, pinfo, tree, offset, ar, BACnetPropertyIdentifier);
9555 break;
9556 case 358: /* fault-parameters */
9557 offset = fFaultParameter(tvb, pinfo, tree, offset);
9558 break;
9559 case 359: /* fault type */
9560 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFaultType);
9561 break;
9562 case 362: /* subscribed-recipients */
9563 offset = fEventNotificationSubscription(tvb, pinfo, tree, offset);
9564 break;
9565 case 364: /* authorization-exemptions */
9566 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuthorizationExemption);
9567 break;
9568 case 378: /* in-progress */
9569 if (object_type == 54) /* lighting-output */
9570 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLightingInProgress);
9571 else if (object_type == 63) /* color */
9572 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorOperationInProgress);
9573 else if (object_type == 64) /* color-temperature */
9574 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetColorOperationInProgress);
9575 break;
9576 case 380: /* lighting-command */
9577 offset = fLightingCommand(tvb, pinfo, tree, offset, ar);
9578 break;
9579 case 16: /* change-of-state-time */
9580 case 71: /* modification-date */
9581 case 114: /* time-of-active-time-reset */
9582 case 115: /* time-of-state-count-reset */
9583 case 142: /* start-time */
9584 case 143: /* stop-time */
9585 case 149: /* maximum-value-time-stamp */
9586 case 150: /* minimum-value-time-stamp */
9587 case 179: /* count-change-time */
9588 case 192: /* value-change-time */
9589 case 254: /* activation-time */
9590 case 270: /* expiration-time */
9591 case 278: /* last-credential-added-time */
9592 case 280: /* last-credential-removed-time */
9593 case 281: /* last-use-time */
9594 case 392: /* time-of-strike-count-reset */
9595 offset = fDateTime(tvb, pinfo, tree, offset, ar);
9596 break;
9597 case 258: /* authentication-policy-list */
9598 offset = fAuthenticationPolicy(tvb, pinfo, tree, offset);
9599 break;
9600 case 395: /* last-state-change */
9601 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerTransition);
9602 break;
9603 case 396: /* state-change-values */
9604 offset = fTimerStateChangeValue(tvb, pinfo, tree, offset);
9605 break;
9606 case 398: /* timer-state */
9607 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetTimerState);
9608 break;
9609 case 407: /* bacnet-ip-global-address */
9610 case 418: /* fd-bbmd-address */
9611 offset = fHostNPort(tvb, pinfo, tree, offset, ar);
9612 break;
9613 case 408: /* bacnet-ip-mode */
9614 case 435: /* bacnet-ipv6-mode */
9615 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetIpMode);
9616 break;
9617 case 414: /* bmd-broadcast-distribution-table */
9618 offset = fBDTEntry(tvb, pinfo, tree, offset, ar);
9619 break;
9620 case 415: /* bbmd-foreign-device-table */
9621 offset = fFDTEntry(tvb, pinfo, tree, offset, ar);
9622 break;
9623 case 417: /* command */
9624 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkPortCommand);
9625 break;
9626 case 426: /* network-number-quality */
9627 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkNumberQuality);
9628 break;
9629 case 427: /* network-type */
9630 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNetworkType);
9631 break;
9632 case 428: /* routing-table */
9633 offset = fRouterEntry(tvb, pinfo, tree, offset);
9634 break;
9635 case 429: /* virtual-mac-address-table */
9636 offset = fVMACEntry(tvb, pinfo, tree, offset);
9637 break;
9638 case 430: /* command-time-array */
9639 if (propertyArrayIndex == 0) {
9640 /* BACnetARRAY index 0 refers to the length
9641 of the array, not the elements of the array */
9642 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9643 } else {
9644 offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
9646 break;
9647 case 432: /* last-command-time */
9648 offset = fTimeStamp(tvb, pinfo, tree, offset, ar);
9649 break;
9650 case 433: /* value-source */
9651 offset = fValueSource(tvb, pinfo, tree, offset);
9652 break;
9653 case 434: /* value-source-array */
9654 if (propertyArrayIndex == 0) {
9655 /* BACnetARRAY index 0 refers to the length
9656 of the array, not the elements of the array */
9657 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9658 } else {
9659 offset = fValueSource(tvb, pinfo, tree, offset);
9661 break;
9662 case 447: /* assigned-landing-calls */
9663 offset = fAssignedLandingCalls(tvb, pinfo, tree, offset);
9664 break;
9665 case 448: /* car-assigned-direction */
9666 case 457: /* car-moving-direction */
9667 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDirection);
9668 break;
9669 case 449: /* car-door-command */
9670 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDoorCommand);
9671 break;
9672 case 453: /* car-drive-status */
9673 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarDriveStatus);
9674 break;
9675 case 456: /* car-mode */
9676 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftCarMode);
9677 break;
9678 case 462: /* escalator-mode */
9679 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorMode);
9680 break;
9681 case 463: /* fault-signals */
9682 if (propertyArrayIndex == 0) {
9683 /* BACnetARRAY index 0 refers to the length
9684 of the array, not the elements of the array */
9685 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9686 } else {
9687 if (object_type == 59) /* lift object */
9688 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftFault);
9689 else
9690 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorFault);
9692 break;
9693 case 467: /* group-mode */
9694 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLiftGroupMode);
9695 break;
9696 case 470: /* landing-calls */
9697 if (propertyArrayIndex == 0) {
9698 /* BACnetARRAY index 0 refers to the length
9699 of the array, not the elements of the array */
9700 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9701 } else {
9702 offset = fLandingCallStatus(tvb, pinfo, tree, offset);
9704 break;
9705 case 471: /* landing-call-control */
9706 offset = fLandingCallStatus(tvb, pinfo, tree, offset);
9707 break;
9708 case 472: /* landing-door-status */
9709 if (propertyArrayIndex == 0) {
9710 /* BACnetARRAY index 0 refers to the length
9711 of the array, not the elements of the array */
9712 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9713 } else {
9714 offset = fLandingDoorStatus(tvb, pinfo, tree, offset);
9716 break;
9717 case 477: /* "operation-direction */
9718 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetEscalatorOperationDirection);
9719 break;
9720 case 481: /* active-cov-multiple-subscriptions */
9721 if (propertyArrayIndex == 0) {
9722 /* BACnetARRAY index 0 refers to the length
9723 of the array, not the elements of the array */
9724 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9725 } else {
9726 offset = fCOVMultipleSubscription(tvb, pinfo, tree, offset);
9728 break;
9729 case 482: /* protocol-level */
9730 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProtocolLevel);
9731 break;
9732 case 486: /* tags */
9733 if (propertyArrayIndex == 0) {
9734 /* BACnetARRAY index 0 refers to the length
9735 of the array, not the elements of the array */
9736 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9737 } else {
9738 offset = fNameValue(tvb, pinfo, tree, offset);
9740 break;
9741 case 487: /* subordinate-node-types */
9742 if (propertyArrayIndex == 0) {
9743 /* BACnetARRAY index 0 refers to the length
9744 of the array, not the elements of the array */
9745 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9746 } else {
9747 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
9749 break;
9750 case 488: /* subordinate-tags */
9751 if (propertyArrayIndex == 0) {
9752 /* BACnetARRAY index 0 refers to the length
9753 of the array, not the elements of the array */
9754 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9755 } else {
9756 offset = fNameValueCollection(tvb, pinfo, tree, offset);
9758 break;
9759 case 489: /* subordinate-relationship */
9760 if (propertyArrayIndex == 0) {
9761 /* BACnetARRAY index 0 refers to the length
9762 of the array, not the elements of the array */
9763 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9764 } else {
9765 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetRelationship);
9767 break;
9768 case 490: /* default-subordinate-relationship */
9769 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetRelationship);
9770 break;
9771 case 494: /* stages */
9772 if (propertyArrayIndex == 0) {
9773 /* BACnetARRAY index 0 refers to the length
9774 of the array, not the elements of the array */
9775 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9776 } else {
9777 offset = fStageLimitValue(tvb, pinfo, tree, offset);
9779 break;
9780 case 498: /* audit-level */
9781 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditLevel);
9782 break;
9783 case 500: /* audit-priority-filter */
9784 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditPriorityFilter);
9785 break;
9786 case 501: /* auditable-operations */
9787 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetAuditOperation);
9788 break;
9789 case 504: /* monitored-objects */
9790 if (propertyArrayIndex == 0) {
9791 /* BACnetARRAY index 0 refers to the length
9792 of the array, not the elements of the array */
9793 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9794 } else {
9795 offset = fObjectSelector(tvb, pinfo, tree, offset);
9797 break;
9798 case 510: /* command-validation-result */
9799 case 4194307: /* current-health */
9800 offset = fHealth(tvb, pinfo, tree, offset);
9801 break;
9802 case 4194312: /* sc-direct-connect-connection-status */
9803 offset = fSCDirectConnection(tvb, pinfo, tree, offset);
9804 break;
9805 case 4194315: /* sc-failed-connection-requests */
9806 offset = fSCFailedConnectionRequest(tvb, pinfo, tree, offset);
9807 break;
9808 case 4194316: /* sc-failover-hub-connection-status */
9809 case 4194324: /* sc-primary-hub-connection-status */
9810 offset = fSCHubConnection(tvb, pinfo, tree, offset);
9811 break;
9812 case 4194318: /* sc_hub_connector_state */
9813 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSCHubConnectorState);
9814 break;
9815 case 4194321: /* sc-hub-function-connection-status */
9816 offset = fSCHubFunctionConnection(tvb, pinfo, tree, offset);
9817 break;
9818 case 4194330: /* default-color */
9819 offset = fXyColor(tvb, pinfo, tree, offset, ar);
9820 break;
9821 case 4194334: /* color-command */
9822 offset = fColorCommand(tvb, pinfo, tree, offset, ar);
9823 break;
9825 case 85: /* present-value */
9826 if ( object_type == 11 ) /* group object handling of present-value */
9828 offset = fReadAccessResult(tvb, pinfo, tree, offset);
9830 else if (object_type == 30) /* access-door object */
9832 offset = fPresentValue(tvb, pinfo, tree, offset, BACnetDoorValue, 0, BACAPP_PRESENT_VALUE_ENUM);
9834 else if (object_type == 21) /* life-point */
9836 offset = fPresentValue(tvb, pinfo, tree, offset, BACnetLifeSafetyState, 0, BACAPP_PRESENT_VALUE_ENUM);
9838 else if (object_type == 22) /* life-zone */
9840 offset = fPresentValue(tvb, pinfo, tree, offset, BACnetLifeSafetyState, 0, BACAPP_PRESENT_VALUE_ENUM);
9842 else if (object_type == 53) /* channel object */
9844 offset = fChannelValue(tvb, pinfo, tree, offset, ar);
9846 else if (object_type == 37) /* credential-data-input */
9848 offset = fAuthenticationFactor(tvb, pinfo, tree, offset);
9850 else if (object_type == 26) /* global-group */
9852 offset = fPropertyAccessResult(tvb, pinfo, tree, offset);
9854 else if (object_type == 28) /* loac-control */
9856 offset = fPresentValue(tvb, pinfo, tree, offset, BACnetShedState, 0, BACAPP_PRESENT_VALUE_ENUM);
9858 else if (object_type == 43) /* date-time-pattern-value */
9860 offset = fDateTime(tvb, pinfo, tree, offset, ar);
9862 else if (object_type == 44) /* date-time-value */
9864 offset = fDateTime(tvb, pinfo, tree, offset, ar);
9866 else if (object_type == 63) /* color */
9868 offset = fXyColor(tvb, pinfo, tree, offset, ar);
9870 else
9872 if (!tag_info) {
9873 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9874 // application tag number above 12 reserved for ASHRAE
9875 if (!tag_is_context_specific(tag_info) && tag_no <= 12) {
9876 offset = fPresentValue(tvb, pinfo, tree, offset, NULL, 0, (BacappPresentValueType) tag_no);
9878 } else {
9879 do_default_handling = true;
9882 break;
9883 default:
9884 do_default_handling = true;
9885 break;
9887 if (do_default_handling) {
9888 if (tag_info) {
9889 if (tag_is_opening(tag_info)) {
9890 ++depth;
9891 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9892 } else if (tag_is_closing(tag_info)) {
9893 --depth;
9894 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9895 } else {
9896 offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
9898 } else {
9899 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9902 if (offset <= lastoffset) break; /* nothing happened, exit loop */
9905 cleanup:
9906 decrement_dissection_depth(pinfo);
9907 return offset;
9910 static unsigned
9911 // NOLINTNEXTLINE(misc-no-recursion)
9912 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tag_info)
9914 uint8_t tag_no;
9915 uint32_t lvt;
9917 if (tag_is_opening(tag_info)) {
9918 offset += fTagHeaderTree(tvb, pinfo, tree, offset,
9919 &tag_no, &tag_info, &lvt);
9920 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9921 if (tvb_reported_length_remaining(tvb, offset) > 0) {
9922 offset += fTagHeaderTree(tvb, pinfo, tree, offset,
9923 &tag_no, &tag_info, &lvt);
9925 } else {
9926 proto_tree_add_expert(tree, pinfo, &ei_bacapp_opening_tag, tvb, offset, -1);
9927 offset = tvb_reported_length(tvb);
9930 return offset;
9934 static unsigned
9935 // NOLINTNEXTLINE(misc-no-recursion)
9936 fPropertyIdentifierValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset)
9938 unsigned lastoffset = offset;
9939 uint8_t tag_no, tag_info;
9940 uint32_t lvt;
9942 offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
9943 if (offset > lastoffset) {
9944 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9945 if (tag_no == tagoffset+2) { /* Value - might not be present in ReadAccessResult */
9946 offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
9949 return offset;
9952 static unsigned
9953 // NOLINTNEXTLINE(misc-no-recursion)
9954 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9956 unsigned lastoffset = 0;
9957 uint8_t tag_no, tag_info;
9958 uint32_t lvt;
9960 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9961 lastoffset = offset;
9962 offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
9963 if (offset > lastoffset) {
9964 /* detect optional priority
9965 by looking to see if the next tag is context tag number 3 */
9966 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9967 if (tag_is_context_specific(tag_info) && (tag_no == 3))
9968 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
9970 if (offset <= lastoffset) break; /* nothing happened, exit loop */
9972 return offset;
9975 static unsigned
9976 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
9978 unsigned lastoffset = 0, len;
9979 uint8_t tag_no, tag_info;
9980 uint32_t lvt;
9981 proto_tree *subtree = tree;
9983 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9984 lastoffset = offset;
9985 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9986 if (tag_is_closing(tag_info)) {
9987 offset += len;
9988 subtree = tree;
9989 continue;
9992 switch (tag_no) {
9993 case 0: /* ProcessId */
9994 offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
9995 break;
9996 case 1: /* monitored ObjectId */
9997 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
9998 break;
9999 case 2: /* issueConfirmedNotifications */
10000 offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
10001 break;
10002 case 3: /* life time */
10003 offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
10004 break;
10005 case 4: /* monitoredPropertyIdentifier */
10006 if (tag_is_opening(tag_info)) {
10007 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "monitoredPropertyIdentifier");
10008 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10009 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
10010 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10011 } else {
10012 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
10014 break;
10015 case 5: /* covIncrement */
10016 offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
10017 break;
10018 default:
10019 return offset;
10021 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10023 return offset;
10026 static unsigned
10027 fSubscribeCOVPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10029 unsigned lastoffset = 0, len;
10030 uint8_t tag_no, tag_info;
10031 uint32_t lvt;
10032 proto_tree *subtree = tree;
10033 proto_tree *subsubtree = tree;
10035 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10036 lastoffset = offset;
10037 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10038 if (tag_is_closing(tag_info)) {
10039 offset += len;
10040 subtree = tree;
10041 continue;
10044 switch (tag_no) {
10045 case 0: /* ProcessId */
10046 offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
10047 break;
10048 case 1: /* issueConfirmedNotifications */
10049 offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
10050 break;
10051 case 2: /* life time */
10052 offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
10053 break;
10054 case 3: /* notification delay */
10055 offset = fTimeSpan(tvb, pinfo, tree, offset, "notification delay");
10056 break;
10057 case 4: /* list-of-cov-subscription-specifications */
10058 if (tag_is_opening(tag_info)) {
10059 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-subscription-specifications: ");
10060 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10062 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10063 lastoffset = offset;
10064 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10065 if (tag_is_closing(tag_info)) {
10066 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10067 offset += len;
10068 subtree = tree;
10069 break;
10072 switch (tag_no) {
10073 case 0: /* monitored-object-identifier */
10074 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
10075 break;
10076 case 1: /* list-of-cov-references */
10077 if (tag_is_opening(tag_info)) {
10078 subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-references: ");
10079 offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
10081 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10082 lastoffset = offset;
10083 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10084 if (tag_is_closing(tag_info)) {
10085 fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
10086 offset += len;
10087 break;
10090 switch (tag_no) {
10091 case 0: /* monitored-property */
10092 if (tag_is_opening(tag_info)) {
10093 offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
10094 offset = fBACnetPropertyReference(tvb, pinfo, subsubtree, offset, 1);
10095 offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
10097 else {
10098 expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
10100 break;
10101 case 1: /* cov-increment */
10102 offset = fRealTag(tvb, pinfo, subsubtree, offset, "COV Increment: ");
10103 break;
10104 case 2: /* timestamped */
10105 offset = fBooleanTag(tvb, pinfo, subsubtree, offset, "timestamped: ");
10106 break;
10107 default:
10108 return offset;
10110 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10113 else {
10114 expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
10116 break;
10117 default:
10118 return offset;
10120 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10123 else {
10124 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
10126 break;
10127 default:
10128 return offset;
10130 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10132 return offset;
10135 static unsigned
10136 fSubscribeCOVPropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10138 unsigned lastoffset = 0, len;
10139 uint8_t tag_no, tag_info;
10140 uint32_t lvt;
10142 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10143 lastoffset = offset;
10144 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10145 if (tag_is_closing(tag_info)) {
10146 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10147 offset += len;
10148 break;
10151 switch (tag_no) {
10152 case 0: /* normal error */
10153 if (tag_is_opening(tag_info)) {
10154 offset = fContextTaggedError(tvb, pinfo, tree, offset);
10156 else {
10157 offset = fError(tvb, pinfo, tree, offset);
10159 break;
10160 case 1: /* first-failed-subscription */
10161 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10163 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10164 lastoffset = offset;
10165 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10166 if (tag_is_closing(tag_info)) {
10167 fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10168 offset += len;
10169 break;
10172 switch (tag_no) {
10173 case 0: /* monitored-object-identifier */
10174 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
10175 break;
10176 case 1: /* monitored-property-reference */
10177 if (tag_is_opening(tag_info)) {
10178 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10179 offset = fBACnetPropertyReference(tvb, pinfo, tree, offset, 1);
10180 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10182 else {
10183 expert_add_info(pinfo, tree, &ei_bacapp_bad_tag);
10185 break;
10186 case 2: /* error-type */
10187 offset = fContextTaggedError(tvb, pinfo, tree, offset);
10188 break;
10189 default:
10190 return offset;
10192 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10194 break;
10195 default:
10196 return offset;
10198 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10200 return offset;
10203 static unsigned
10204 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10206 return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
10209 static unsigned
10210 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10212 unsigned lastoffset = 0;
10214 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10215 lastoffset = offset;
10217 switch (fTagNo(tvb, offset)) {
10218 case 0: /* deviceInstanceLowLimit */
10219 offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
10220 break;
10221 case 1: /* deviceInstanceHighLimit */
10222 offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
10223 break;
10224 case 2: /* BACnetObjectId */
10225 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
10226 break;
10227 case 3: /* ObjectName */
10228 offset = fObjectName(tvb, pinfo, tree, offset);
10229 break;
10230 default:
10231 return offset;
10233 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10235 return offset;
10239 static unsigned
10240 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
10242 unsigned lastoffset = 0;
10243 uint8_t tag_no, tag_info;
10244 uint32_t lvt;
10246 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10247 if (tag_is_opening(tag_info) && tag_no == 0) {
10248 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
10249 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10250 lastoffset = offset;
10251 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10252 if (tag_is_closing(tag_info)) {
10253 /* should be closing context tag 0 */
10254 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10255 return offset;
10258 offset = fTimeValue(tvb, pinfo, subtree, offset);
10259 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10261 } else if ((tag_no == 0) && (lvt == 0)) {
10262 /* not sure null (empty array element) is legal */
10263 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10265 return offset;
10269 * BACnetHealth ::= SEQUENCE {
10270 * timestamp [0] BACnetDateTime,
10271 * result [1] Error,
10272 * property [2] BACnetPropertiyIdentifier OPTIONAL,
10273 * details [3] CharacterString OPTIONAL
10275 * @param tvb the tv buffer of the current data
10276 * @param pinfo the packet info of the current data
10277 * @param tree the tree to append this item to
10278 * @param offset the offset in the tvb
10279 * @return modified offset
10281 static unsigned
10282 fHealth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10284 unsigned lastoffset = 0;
10285 uint8_t tag_no, tag_info;
10286 uint32_t lvt;
10288 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10289 lastoffset = offset;
10290 /* check the tag. A closing tag means we are done */
10291 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10292 if (tag_is_closing(tag_info)) {
10293 return offset;
10295 switch (tag_no) {
10296 case 0: /* timestamp */
10297 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10298 offset = fDateTime(tvb, pinfo, tree, offset, "timestamp: ");
10299 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10300 break;
10301 case 1: /* result */
10302 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10303 offset = fError(tvb, pinfo, tree, offset);
10304 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10305 break;
10306 case 2: /* property - OPTIONAL*/
10307 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
10308 break;
10309 case 3: /* details - OPTIONAL */
10310 offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
10311 break;
10312 default:
10313 return offset;
10315 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10317 return offset;
10321 * BACnetSCDirectConnection ::= SEQUENCE {
10322 * uri [0] CharacterString
10323 * connection-state [1] BACnetSCConnectionState,
10324 * connect-timestamp [2] BACnetDateTime,
10325 * disconnect-timestamp [3] BACnetDateTime,
10326 * peer-address [4] BACnetHostNPort,
10327 * peer-vmac [5] OCTET STRING (SIZE(6))
10328 * peer-uuid [6] OCTET STRING (SIZE(16))
10329 * error [7] Error OPTIONAL
10330 * error-details [8] CharacterString OPTIONAL
10332 * @param tvb the tv buffer of the current data
10333 * @param pinfo the packet info of the current data
10334 * @param tree the tree to append this item to
10335 * @param offset the offset in the tvb
10336 * @return modified offset
10338 static unsigned
10339 fSCDirectConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10341 unsigned lastoffset = 0;
10342 uint8_t tag_no, tag_info;
10343 uint32_t lvt;
10345 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10346 lastoffset = offset;
10347 /* check the tag. A closing tag means we are done */
10348 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10349 if (tag_is_closing(tag_info)) {
10350 return offset;
10352 switch (tag_no) {
10353 case 0: /* uri */
10354 offset = fCharacterString(tvb, pinfo, tree, offset, "uri: ");
10355 break;
10356 case 1: /* connection-state */
10357 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
10358 break;
10359 case 2: /* connect-timestamp */
10360 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10361 offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
10362 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10363 break;
10364 case 3: /* disconnect-timestamp */
10365 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10366 offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
10367 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10368 break;
10369 case 4: /* peer-address */
10370 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10371 offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
10372 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10373 break;
10374 case 5: /* peer-vmac */
10375 offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
10376 break;
10377 case 6: /* peer-uuid */
10378 offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
10379 break;
10380 case 7: /* error */
10381 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10382 offset = fError(tvb, pinfo, tree, offset);
10383 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10384 break;
10385 case 8: /* details - OPTIONAL */
10386 offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
10387 break;
10388 default:
10389 return offset;
10391 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10393 return offset;
10397 * BACnetSCFailedConnectionRequest ::= SEQUENCE {
10398 * timestamp [0] BACnetDateTime,
10399 * peer-address [1] BACnetHostNPort,
10400 * peer-vmac [2] OCTET STRING (SIZE(6))
10401 * peer-uuid [3] OCTET STRING (SIZE(16))
10402 * error [4] Error OPTIONAL
10403 * error-details [5] CharacterString OPTIONAL
10405 * @param tvb the tv buffer of the current data
10406 * @param pinfo the packet info of the current data
10407 * @param tree the tree to append this item to
10408 * @param offset the offset in the tvb
10409 * @return modified offset
10411 static unsigned
10412 fSCFailedConnectionRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10414 unsigned lastoffset = 0;
10415 uint8_t tag_no, tag_info;
10416 uint32_t lvt;
10418 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10419 lastoffset = offset;
10420 /* check the tag. A closing tag means we are done */
10421 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10422 if (tag_is_closing(tag_info)) {
10423 return offset;
10425 switch (tag_no) {
10426 case 0: /* timestamp */
10427 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10428 offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
10429 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10430 break;
10431 case 1: /* peer-address */
10432 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10433 offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
10434 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10435 break;
10436 case 2: /* peer-vmac */
10437 offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
10438 break;
10439 case 3: /* peer-uuid */
10440 offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
10441 break;
10442 case 4: /* error */
10443 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10444 offset = fError(tvb, pinfo, tree, offset);
10445 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10446 break;
10447 case 5: /* details - OPTIONAL */
10448 offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
10449 break;
10450 default:
10451 return offset;
10453 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10455 return offset;
10459 * BACnetSCHubConnection ::= SEQUENCE {
10460 * connection-state [0] BACnetSCConnectionState,
10461 * connect-timestamp [1] BACnetDateTime,
10462 * disconnect-timestamp [2] BACnetDateTime,
10463 * error [3] Error OPTIONAL
10464 * error-details [4] CharacterString OPTIONAL
10466 * @param tvb the tv buffer of the current data
10467 * @param pinfo the packet info of the current data
10468 * @param tree the tree to append this item to
10469 * @param offset the offset in the tvb
10470 * @return modified offset
10472 static unsigned
10473 fSCHubConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10475 unsigned lastoffset = 0;
10476 uint8_t tag_no, tag_info;
10477 uint32_t lvt;
10479 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10480 lastoffset = offset;
10481 /* check the tag. A closing tag means we are done */
10482 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10483 if (tag_is_closing(tag_info)) {
10484 return offset;
10486 switch (tag_no) {
10487 case 0: /* connection-state */
10488 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
10489 break;
10490 case 1: /* connect-timestamp */
10491 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10492 offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
10493 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10494 break;
10495 case 2: /* disconnect-timestamp */
10496 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10497 offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
10498 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10499 break;
10500 case 3: /* error */
10501 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10502 offset = fError(tvb, pinfo, tree, offset);
10503 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10504 break;
10505 case 4: /* details - OPTIONAL */
10506 offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
10507 break;
10508 default:
10509 return offset;
10511 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10513 return offset;
10517 * BACnetSCHubFunctionConnection ::= SEQUENCE {
10518 * connection-state [0] BACnetSCConnectionState,
10519 * connect-timestamp [1] BACnetDateTime,
10520 * disconnect-timestamp [2] BACnetDateTime,
10521 * peer-address [3] BACnetHostNPort,
10522 * peer-vmac [4] OCTET STRING (SIZE(6))
10523 * peer-uuid [5] OCTET STRING (SIZE(16))
10524 * error [6] Error OPTIONAL
10525 * error-details [7] CharacterString OPTIONAL
10527 * @param tvb the tv buffer of the current data
10528 * @param pinfo the packet info of the current data
10529 * @param tree the tree to append this item to
10530 * @param offset the offset in the tvb
10531 * @return modified offset
10533 static unsigned
10534 fSCHubFunctionConnection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10536 unsigned lastoffset = 0;
10537 uint8_t tag_no, tag_info;
10538 uint32_t lvt;
10540 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10541 lastoffset = offset;
10542 /* check the tag. A closing tag means we are done */
10543 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10544 if (tag_is_closing(tag_info)) {
10545 return offset;
10547 switch (tag_no) {
10548 case 0: /* connection-state */
10549 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "connection-state: ", BACnetSCConnectionState);
10550 break;
10551 case 1: /* connect-timestamp */
10552 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10553 offset = fDateTime(tvb, pinfo, tree, offset, "connect-timestamp: ");
10554 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10555 break;
10556 case 2: /* disconnect-timestamp */
10557 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10558 offset = fDateTime(tvb, pinfo, tree, offset, "disconnect-timestamp: ");
10559 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10560 break;
10561 case 3: /* peer-address */
10562 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10563 offset = fHostNPort(tvb, pinfo, tree, offset,"peer-address: ");
10564 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10565 break;
10566 case 4: /* peer-vmac */
10567 offset = fOctetString(tvb, pinfo, tree, offset, "peer-vmac: ", lvt);
10568 break;
10569 case 5: /* peer-uuid */
10570 offset = fOctetString(tvb, pinfo, tree, offset, "peer-uuid: ", lvt);
10571 break;
10572 case 6: /* error */
10573 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10574 offset = fError(tvb, pinfo, tree, offset);
10575 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10576 break;
10577 case 7: /* details - OPTIONAL */
10578 offset = fCharacterString(tvb, pinfo, tree, offset, "details: ");
10579 break;
10580 default:
10581 return offset;
10583 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10585 return offset;
10588 static unsigned
10589 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10591 unsigned lastoffset = 0;
10592 uint8_t tag_no, tag_info;
10593 uint32_t lvt;
10594 unsigned i = 1; /* day of week array index */
10595 proto_tree *subtree = tree;
10597 if (propertyArrayIndex > 0) {
10598 /* BACnetARRAY index 0 refers to the length
10599 of the array, not the elements of the array.
10600 BACnetARRAY index -1 is our internal flag that
10601 the optional index was not used.
10602 BACnetARRAY refers to this as all elements of the array.
10603 If the optional index is specified for a BACnetARRAY,
10604 then that specific array element is referenced. */
10605 i = propertyArrayIndex;
10607 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10608 lastoffset = offset;
10609 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10610 if (tag_is_closing(tag_info)) {
10611 return offset; /* outer encoding will print out closing tag */
10613 subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bacapp_value, NULL,
10614 val_to_str(i++, day_of_week, "day of week (%d) not found"));
10615 offset = fDailySchedule(tvb, pinfo, subtree, offset);
10616 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10618 return offset;
10622 static unsigned
10623 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10625 if (tvb_reported_length_remaining(tvb, offset) <= 0)
10626 return offset;
10628 return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
10631 static unsigned
10632 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10634 if (tvb_reported_length_remaining(tvb, offset) <= 0)
10635 return offset;
10637 return fDateTime(tvb, pinfo, tree, offset, NULL);
10640 static unsigned
10641 fWriteGroupRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10643 unsigned lastoffset = 0, len;
10644 uint8_t tag_no, tag_info;
10645 uint32_t lvt;
10646 proto_tree *subtree = tree;
10648 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10649 lastoffset = offset;
10650 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10651 if (tag_is_closing(tag_info)) {
10652 offset += len;
10653 subtree = tree;
10654 continue;
10657 switch (tag_no) {
10658 case 0: /* group-number */
10659 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Group number: ");
10660 break;
10661 case 1: /* write-priority */
10662 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
10663 break;
10664 case 2: /* change-list */
10665 if (tag_is_opening(tag_info)) {
10666 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "change-list: ");
10667 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10669 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10670 lastoffset = offset;
10671 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10672 if (tag_is_closing(tag_info)) {
10673 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10674 offset += len;
10675 subtree = tree;
10676 break;
10679 switch (tag_no) {
10680 case 0: /* channel */
10681 if (tag_info && ! tag_is_opening(tag_info)) {
10682 /* context tagged */
10683 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Channel: ");
10684 } else {
10685 /* application tagged */
10686 offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
10688 break;
10689 case 1: /* overriding-priority */
10690 if (tag_info && ! tag_is_opening(tag_info)) {
10691 /* context tagged */
10692 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Overriding priority: ");
10693 } else {
10694 /* application tagged */
10695 offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
10697 break;
10698 default: /* channel-value (application tagged, or opening/closing context-0 tagged) */
10699 offset = fChannelValue(tvb, pinfo, subtree, offset, "Value: ");
10700 break;
10702 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10705 else {
10706 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
10708 break;
10709 case 3: /* inhibit-delay */
10710 offset = fBooleanTag(tvb, pinfo, tree, offset, "Inhibit delay: ");
10711 break;
10712 default:
10713 return offset;
10715 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10717 return offset;
10720 static unsigned
10721 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10723 if (tvb_reported_length_remaining(tvb, offset) <= 0)
10724 return offset;
10725 offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
10726 return fDate(tvb, pinfo, tree, offset, "End Date: ");
10729 static unsigned
10730 fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10732 uint32_t val = 0;
10733 uint8_t tag_no, tag_info;
10734 uint32_t lvt;
10735 unsigned tag_len;
10736 proto_item *ti;
10737 proto_tree *subtree;
10738 static const char *label = "Vendor ID";
10740 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10741 if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
10742 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
10743 ett_bacapp_tag, &ti, "%s: %s (%u)",
10744 label,
10745 val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
10746 val);
10747 else
10748 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
10749 ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
10750 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10752 if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1 and <= 2 are supported */
10753 expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
10754 "Wrong length indicated. Expected 1 or 2, got %u", lvt);
10755 return offset+tag_len+lvt;
10758 proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
10759 offset+tag_len, lvt, ENC_BIG_ENDIAN);
10761 return offset+tag_len+lvt;
10764 static unsigned
10765 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10767 uint32_t val = 0;
10768 uint8_t tag_no, tag_info;
10769 uint32_t lvt;
10770 unsigned tag_len;
10771 proto_item *ti;
10772 proto_tree *subtree;
10773 static const char *label = "Restart Reason";
10775 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10776 if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
10777 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
10778 ett_bacapp_tag, &ti, "%s: %s (%u)", label,
10779 val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
10780 else
10781 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
10782 ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
10783 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10785 if (lvt != 1) {
10786 expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
10787 "Wrong length indicated. Expected 1, got %u", lvt);
10788 return offset+tag_len+lvt;
10791 proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
10792 offset+tag_len, lvt, ENC_BIG_ENDIAN);
10794 return offset+tag_len+lvt;
10797 static unsigned
10798 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10800 uint8_t tag_no, tag_info;
10801 uint32_t lvt;
10802 unsigned lastoffset = 0;
10804 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10805 lastoffset = offset;
10806 switch (fTagNo(tvb, offset)) {
10807 case 0: /* textMessageSourceDevice */
10808 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
10809 break;
10810 case 1: /* messageClass */
10811 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10812 switch (fTagNo(tvb, offset)) {
10813 case 0: /* numeric */
10814 offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
10815 break;
10816 case 1: /* character */
10817 offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
10818 break;
10820 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10821 break;
10822 case 2: /* messagePriority */
10823 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
10824 BACnetMessagePriority);
10825 break;
10826 case 3: /* message */
10827 offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
10828 break;
10829 default:
10830 return offset;
10832 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10834 return offset;
10837 static unsigned
10838 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10840 return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10843 static unsigned
10844 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10846 unsigned lastoffset, len;
10847 uint8_t tag_no, tag_info;
10848 uint32_t lvt;
10849 proto_tree *subtree = tree;
10850 tvbuff_t *next_tvb;
10851 unsigned vendor_identifier = 0;
10852 unsigned service_number = 0;
10854 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10855 fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
10856 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
10857 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10859 next_tvb = tvb_new_subset_remaining(tvb, offset);
10860 if (dissector_try_uint(bacapp_dissector_table,
10861 vendor_identifier, next_tvb, pinfo, tree)) {
10862 /* we parsed it so skip over length and we are done */
10863 offset += tvb_reported_length(next_tvb);
10864 return offset;
10867 /* Not handled by vendor dissector */
10869 /* exit loop if nothing happens inside */
10870 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10871 lastoffset = offset;
10872 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10873 if (tag_is_closing(tag_info)) {
10874 if (tag_no == 2) { /* Make sure it's the expected tag */
10875 offset += len;
10876 subtree = tree;
10877 continue;
10878 } else {
10879 break; /* End loop if incorrect closing tag */
10882 switch (tag_no) {
10884 /* vendorID is now parsed above */
10885 case 1: /* serviceNumber */
10886 fUnsigned32(tvb, offset+len, lvt, &service_number);
10887 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ", service_number);
10888 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
10889 break;
10890 case 2: /*serviceParameters */
10891 if (tag_is_opening(tag_info)) {
10892 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
10893 ett_bacapp_value, NULL, "service Parameters");
10894 propertyIdentifier = -1;
10895 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10896 } else {
10897 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
10899 break;
10900 default:
10901 return offset;
10903 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10906 return offset;
10909 static unsigned
10910 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10912 return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10915 static unsigned
10916 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
10918 return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10921 static unsigned
10922 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *label)
10924 unsigned lastoffset = 0;
10925 uint8_t tag_no, tag_info;
10926 uint32_t lvt;
10927 proto_tree *subtree = tree;
10929 if (label != NULL) {
10930 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, label);
10933 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10934 lastoffset = offset;
10935 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10937 switch (tag_no) {
10938 case 0: /* subscriberProcessId */
10939 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
10940 break;
10941 case 1: /* requestingSource */
10942 offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
10943 break;
10944 case 2: /* request */
10945 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
10946 "request: ", BACnetLifeSafetyOperation, 64);
10947 break;
10948 case 3: /* objectId */
10949 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
10950 break;
10951 default:
10952 return offset;
10954 if (offset <= lastoffset) break; /* nothing happened, exit loop */
10956 return offset;
10959 typedef struct _value_string_enum {
10960 uint8_t tag_no;
10961 const value_string *valstr;
10962 } value_string_enum;
10964 static const value_string_enum
10965 BACnetPropertyStatesEnums[] = {
10966 { 1, BACnetBinaryPV },
10967 { 2, BACnetEventType },
10968 { 3, BACnetPolarity },
10969 { 4, BACnetProgramRequest },
10970 { 5, BACnetProgramState },
10971 { 6, BACnetProgramError },
10972 { 7, BACnetReliability },
10973 { 8, BACnetEventState },
10974 { 9, BACnetDeviceStatus },
10975 { 10, BACnetEngineeringUnits },
10976 { 12, BACnetLifeSafetyMode },
10977 { 13, BACnetLifeSafetyState },
10978 { 14, BACnetRestartReason },
10979 { 15, BACnetDoorAlarmState },
10980 { 16, BACnetAction },
10981 { 17, BACnetDoorSecuredStatus },
10982 { 18, BACnetDoorStatus },
10983 { 19, BACnetDoorValue },
10984 { 20, BACnetFileAccessMethod },
10985 { 21, BACnetLockStatus },
10986 { 22, BACnetLifeSafetyOperation },
10987 { 23, BACnetMaintenance },
10988 { 24, BACnetNodeType },
10989 { 25, BACnetNotifyType },
10990 { 26, BACnetSecurityLevel },
10991 { 27, BACnetShedState },
10992 { 28, BACnetSilencedState },
10993 { 30, BACnetAccessEvent },
10994 { 31, BACnetAccessZoneOccupancyState },
10995 { 32, BACnetAccessCredentialDisableReason },
10996 { 33, BACnetAccessCredentialDisable },
10997 { 34, BACnetAuthenticationStatus },
10998 { 36, BACnetBackupState },
10999 { 37, BACnetWriteStatus },
11000 { 38, BACnetLightingInProgress },
11001 { 39, BACnetLightingOperation },
11002 { 40, BACnetLightingTransition },
11003 { 42, BACnetBinaryLightingPV },
11004 { 43, BACnetTimerState },
11005 { 44, BACnetTimerTransition },
11006 { 45, BACnetIpMode },
11007 { 46, BACnetNetworkPortCommand },
11008 { 47, BACnetNetworkType },
11009 { 48, BACnetNetworkNumberQuality },
11010 { 49, BACnetEscalatorOperationDirection },
11011 { 50, BACnetEscalatorFault },
11012 { 51, BACnetEscalatorMode },
11013 { 52, BACnetLiftCarDirection },
11014 { 53, BACnetLiftCarDoorCommand },
11015 { 54, BACnetLiftCarDriveStatus },
11016 { 55, BACnetLiftCarMode },
11017 { 56, BACnetLiftGroupMode },
11018 { 57, BACnetLiftFault },
11019 { 58, BACnetProtocolLevel },
11020 { 59, BACnetAuditLevel },
11021 { 60, BACnetAuditOperation }
11023 #define BACnetPropertyStatesEnums_Size array_length(BACnetPropertyStatesEnums)
11025 static unsigned
11026 fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11028 uint8_t tag_no, tag_info;
11029 uint32_t lvt;
11030 uint32_t idx;
11031 const char* label;
11032 const value_string_enum* valstrenum;
11034 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11035 label = wmem_strdup_printf(pinfo->pool, "%s: ",
11036 val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
11038 switch (tag_no) {
11039 case 0:
11040 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
11041 break;
11042 case 11:
11043 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
11044 break;
11045 case 41:
11046 offset = fSignedTag(tvb, pinfo, tree, offset, label);
11047 break;
11048 case 63:
11049 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
11050 break;
11051 default:
11052 valstrenum = NULL;
11054 for (idx = 0; idx < BACnetPropertyStatesEnums_Size; idx++) {
11055 valstrenum = &BACnetPropertyStatesEnums[idx];
11056 if (valstrenum->tag_no == tag_no &&
11057 valstrenum->valstr != NULL) {
11058 break;
11060 valstrenum = NULL;
11063 if (valstrenum == NULL)
11065 offset = fEnumeratedTag(tvb, pinfo, tree, offset, label, NULL);
11066 /* don't use Abstract type here because it is context tagged and therefore we don't know app type */
11068 else
11070 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
11071 VALS(valstrenum->valstr), 64);
11073 break;
11075 return offset;
11080 BACnetDeviceObjectPropertyValue ::= SEQUENCE {
11081 deviceIdentifier [0] BACnetObjectIdentifier,
11082 objectIdentifier [1] BACnetObjectIdentifier,
11083 propertyIdentifier [2] BACnetPropertyIdentifier,
11084 arrayIndex [3] Unsigned OPTIONAL,
11085 value [4] ABSTRACT-SYNTAX.&Type
11088 static unsigned
11089 // NOLINTNEXTLINE(misc-no-recursion)
11090 fDeviceObjectPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11092 unsigned lastoffset = 0;
11093 uint8_t tag_no, tag_info;
11094 uint32_t lvt;
11096 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11097 lastoffset = offset;
11098 /* check the tag. A closing tag means we are done */
11099 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11100 if (tag_is_closing(tag_info)) {
11101 return offset;
11103 switch (tag_no) {
11104 case 0: /* deviceIdentifier */
11105 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
11106 break;
11107 case 1: /* objectIdentifier */
11108 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
11109 break;
11110 case 2: /* propertyIdentifier */
11111 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
11112 break;
11113 case 3: /* arrayIndex - OPTIONAL */
11114 offset = fUnsignedTag(tvb, pinfo, tree, offset,
11115 "arrayIndex: ");
11116 break;
11117 case 4: /* value */
11118 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11119 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
11120 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
11121 break;
11122 default:
11123 return offset;
11125 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11127 return offset;
11131 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
11132 objectIdentifier [0] BACnetObjectIdentifier,
11133 propertyIdentifier [1] BACnetPropertyIdentifier,
11134 propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
11135 -- if omitted with an array then
11136 -- the entire array is referenced
11137 deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
11140 static unsigned
11141 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11143 return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
11147 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
11148 objectIdentifier [0] BACnetObjectIdentifier,
11149 propertyIdentifier [1] BACnetPropertyIdentifier,
11150 propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
11151 -- if omitted with an array then
11152 -- the entire array is referenced
11153 deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
11156 static unsigned
11157 // NOLINTNEXTLINE(misc-no-recursion)
11158 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11160 unsigned lastoffset = 0;
11161 uint8_t tag_no, tag_info;
11162 uint32_t lvt;
11164 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11165 lastoffset = offset;
11166 /* check the tag. A closing tag means we are done */
11167 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11168 if (tag_is_closing(tag_info)) {
11169 return offset;
11171 switch (tag_no) {
11172 case 0: /* objectIdentifier */
11173 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
11174 break;
11175 case 1: /* propertyIdentifier */
11176 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
11177 break;
11178 case 2: /* arrayIndex - OPTIONAL */
11179 offset = fUnsignedTag(tvb, pinfo, tree, offset,
11180 "arrayIndex: ");
11181 break;
11182 case 3: /* deviceIdentifier - OPTIONAL */
11183 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
11184 break;
11185 default:
11186 return offset;
11188 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11190 return offset;
11193 static unsigned
11194 // NOLINTNEXTLINE(misc-no-recursion)
11195 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11197 unsigned lastoffset = offset;
11198 uint8_t tag_no, tag_info;
11199 uint32_t lvt;
11200 proto_tree *subtree = tree;
11201 proto_tree *pvtree;
11203 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11204 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11205 ett_bacapp_value, NULL, "notification parameters (%d) %s",
11206 tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
11207 /* Opening tag for parameter choice */
11208 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11210 switch (tag_no) {
11211 case 0: /* change-of-bitstring */
11212 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11213 lastoffset = offset;
11214 switch (fTagNo(tvb, offset)) {
11215 case 0:
11216 offset = fBitStringTag(tvb, pinfo, subtree, offset,
11217 "referenced-bitstring: ");
11218 break;
11219 case 1:
11220 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11221 "status-flags: ", BACnetStatusFlags);
11222 lastoffset = offset;
11223 break;
11224 default:
11225 break;
11227 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11229 break;
11230 case 1: /* change-of-state */
11231 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11232 lastoffset = offset;
11233 switch (fTagNo(tvb, offset)) {
11234 case 0:
11235 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11236 offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
11237 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11238 break;
11239 case 1:
11240 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11241 "status-flags: ", BACnetStatusFlags);
11242 lastoffset = offset;
11243 break;
11244 default:
11245 break;
11247 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11249 break;
11250 case 2: /* change-of-value */
11251 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11252 lastoffset = offset;
11253 switch (fTagNo(tvb, offset)) {
11254 case 0:
11255 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11256 switch (fTagNo(tvb, offset)) {
11257 case 0:
11258 offset = fBitStringTag(tvb, pinfo, subtree, offset,
11259 "changed-bits: ");
11260 break;
11261 case 1:
11262 offset = fRealTag(tvb, pinfo, subtree, offset,
11263 "changed-value: ");
11264 break;
11265 default:
11266 break;
11268 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11269 break;
11270 case 1:
11271 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11272 "status-flags: ", BACnetStatusFlags);
11273 lastoffset = offset;
11274 break;
11275 default:
11276 break;
11278 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11280 break;
11281 case 3: /* command-failure */
11282 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11283 lastoffset = offset;
11284 switch (fTagNo(tvb, offset)) {
11285 case 0: /* "command-value: " */
11286 /* from BACnet Table 13-3,
11287 Standard Object Property Values Returned in Notifications */
11288 propertyIdentifier = 85; /* PRESENT_VALUE */
11289 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11290 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
11291 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11292 break;
11293 case 1:
11294 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11295 "status-flags: ", BACnetStatusFlags);
11296 break;
11297 case 2: /* "feedback-value: " */
11298 propertyIdentifier = 40; /* FEEDBACK_VALUE */
11299 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11300 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
11301 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11302 lastoffset = offset;
11303 break;
11304 default:
11305 break;
11307 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11309 break;
11310 case 4: /* floating-limit */
11311 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11312 lastoffset = offset;
11313 switch (fTagNo(tvb, offset)) {
11314 case 0:
11315 offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
11316 break;
11317 case 1:
11318 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11319 "status-flags: ", BACnetStatusFlags);
11320 break;
11321 case 2:
11322 offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
11323 break;
11324 case 3:
11325 offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
11326 lastoffset = offset;
11327 break;
11328 default:
11329 break;
11331 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11333 break;
11334 case 5: /* out-of-range */
11335 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11336 lastoffset = offset;
11337 switch (fTagNo(tvb, offset)) {
11338 case 0:
11339 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
11340 break;
11341 case 1:
11342 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11343 "status-flags: ", BACnetStatusFlags);
11344 break;
11345 case 2:
11346 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
11347 break;
11348 case 3:
11349 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
11350 lastoffset = offset;
11351 break;
11352 default:
11353 break;
11355 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11357 break;
11358 case 6:
11359 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11360 lastoffset = offset;
11361 offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
11362 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11364 break;
11365 case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
11366 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11367 lastoffset = offset;
11368 switch (fTagNo(tvb, offset)) {
11369 case 0:
11370 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "DeviceIdentifier: "); /* buffer-device */
11371 break;
11372 case 1:
11373 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: "); /* buffer-object */
11374 break;
11375 case 2:
11376 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11377 offset = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
11378 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11379 break;
11380 case 3:
11381 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11382 offset = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
11383 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11384 lastoffset = offset;
11385 break;
11386 default:
11387 break;
11389 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11391 break;
11392 case 8: /* change-of-life-safety */
11393 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11394 lastoffset = offset;
11395 switch (fTagNo(tvb, offset)) {
11396 case 0:
11397 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11398 "new-state: ", BACnetLifeSafetyState, 256);
11399 break;
11400 case 1:
11401 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11402 "new-mode: ", BACnetLifeSafetyMode, 256);
11403 break;
11404 case 2:
11405 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11406 "status-flags: ", BACnetStatusFlags);
11407 break;
11408 case 3:
11409 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11410 "operation-expected: ", BACnetLifeSafetyOperation, 64);
11411 lastoffset = offset;
11412 break;
11413 default:
11414 break;
11416 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11418 break;
11419 case 9: /* extended */
11420 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11421 lastoffset = offset;
11422 switch (fTagNo(tvb, offset)) {
11423 case 0:
11424 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
11425 break;
11426 case 1:
11427 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "extended-event-type: ");
11428 break;
11429 case 2: /* parameters */
11430 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11432 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11433 const unsigned param_lastoffset = offset;
11434 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11435 if (tag_is_closing(tag_info))
11437 break;
11440 if (tag_is_opening(tag_info))
11442 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11443 offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
11444 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11446 else
11448 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
11450 if (offset <= param_lastoffset)
11451 break; /* nothing happened, exit loop */
11454 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11455 lastoffset = offset;
11456 break;
11457 default:
11458 break;
11460 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11462 break;
11463 case 10: /* buffer ready */
11464 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11465 lastoffset = offset;
11466 switch (fTagNo(tvb, offset)) {
11467 case 0: /* buffer-property */
11468 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11469 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11470 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11471 break;
11472 case 1:
11473 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
11474 "previous-notification: ");
11475 break;
11476 case 2:
11477 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
11478 "current-notification: ");
11479 lastoffset = offset;
11480 break;
11481 default:
11482 break;
11484 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11486 break;
11487 case 11: /* unsigned range */
11488 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11489 lastoffset = offset;
11490 switch (fTagNo(tvb, offset)) {
11491 case 0:
11492 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
11493 "exceeding-value: ");
11494 break;
11495 case 1:
11496 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11497 "status-flags: ", BACnetStatusFlags);
11498 break;
11499 case 2:
11500 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
11501 "exceeded-limit: ");
11502 lastoffset = offset;
11503 break;
11504 default:
11505 break;
11507 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11509 break;
11510 /* 12 reserved */
11511 case 13: /* access-event */
11512 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11513 lastoffset = offset;
11514 switch (fTagNo(tvb, offset)) {
11515 case 0:
11516 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11517 "access event: ", BACnetAccessEvent, 512);
11518 break;
11519 case 1:
11520 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11521 "status-flags: ", BACnetStatusFlags);
11522 break;
11523 case 2:
11524 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
11525 "access-event-tag: ");
11526 break;
11527 case 3:
11528 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11529 offset = fTimeStamp(tvb, pinfo, subtree, offset, "access-event-time: ");
11530 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11531 break;
11532 case 4:
11533 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11534 offset = fDeviceObjectReference(tvb, pinfo, subtree, offset);
11535 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11536 break;
11537 case 5: /* optional authentication-factor */
11538 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11539 offset = fAuthenticationFactor(tvb, pinfo, subtree, offset);
11540 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11541 lastoffset = offset;
11542 break;
11543 default:
11544 break;
11546 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11548 break;
11549 case 14: /* double-out-of-range */
11550 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11551 lastoffset = offset;
11552 switch (fTagNo(tvb, offset)) {
11553 case 0:
11554 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
11555 break;
11556 case 1:
11557 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11558 "status-flags: ", BACnetStatusFlags);
11559 break;
11560 case 2:
11561 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
11562 break;
11563 case 3:
11564 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
11565 lastoffset = offset;
11566 break;
11567 default:
11568 break;
11570 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11572 break;
11573 case 15: /* signed-out-of-range */
11574 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11575 lastoffset = offset;
11576 switch (fTagNo(tvb, offset)) {
11577 case 0:
11578 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
11579 break;
11580 case 1:
11581 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11582 "status-flags: ", BACnetStatusFlags);
11583 break;
11584 case 2:
11585 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
11586 break;
11587 case 3:
11588 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
11589 lastoffset = offset;
11590 break;
11591 default:
11592 break;
11594 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11596 break;
11597 case 16: /* unsigned-out-of-range */
11598 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11599 lastoffset = offset;
11600 switch (fTagNo(tvb, offset)) {
11601 case 0:
11602 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
11603 break;
11604 case 1:
11605 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11606 "status-flags: ", BACnetStatusFlags);
11607 break;
11608 case 2:
11609 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
11610 break;
11611 case 3:
11612 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
11613 lastoffset = offset;
11614 break;
11615 default:
11616 break;
11618 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11620 break;
11621 case 17: /* change-of-characterstring */
11622 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
11623 lastoffset = offset;
11624 switch (fTagNo(tvb, offset)) {
11625 case 0:
11626 /* changed-value (CharacterString) */
11627 offset = fCharacterString(tvb, pinfo, subtree, offset, "changed-value: ");
11628 break;
11629 case 1:
11630 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11631 "status-flags: ", BACnetStatusFlags);
11632 break;
11633 case 2:
11634 /* alarm-value (CharacterString) */
11635 offset = fCharacterString(tvb, pinfo, subtree, offset, "alarm-value: ");
11636 lastoffset = offset;
11637 break;
11638 default:
11639 break;
11641 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11643 break;
11644 case 18: /* change-of-status-flags */
11645 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11646 /* exit loop if nothing happens inside */
11647 lastoffset = offset;
11648 switch (fTagNo(tvb, offset)) {
11649 case 0:
11650 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11652 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11653 if (tag_is_context_specific(tag_info)) {
11654 propertyIdentifier = 85; /* suppose present-value here */
11655 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
11656 } else {
11657 offset = fPresentValue(tvb, pinfo, tree, offset, BACnetStatusFlags, 0, BACAPP_PRESENT_VALUE_ENUM);
11660 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11661 break;
11662 case 1:
11663 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11664 "referenced-flags: ", BACnetStatusFlags);
11665 lastoffset = offset;
11666 break;
11667 default:
11668 break;
11670 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11672 break;
11673 case 19: /* change-of-reliability */
11674 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11675 /* exit loop if nothing happens inside */
11676 lastoffset = offset;
11678 switch (fTagNo(tvb, offset)) {
11679 case 0:
11680 offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "reliability:", BACnetReliability);
11681 break;
11682 case 1:
11683 offset = fBitStringTagVS(tvb, pinfo, subtree, offset, "status-flags: ", BACnetStatusFlags);
11684 break;
11685 case 2: /* property-values */
11686 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11687 if (tag_is_closing(tag_info)) {
11688 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11689 return offset;
11691 pvtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "property-values");
11692 offset += fTagHeaderTree(tvb, pinfo, pvtree, offset, &tag_no, &tag_info, &lvt);
11693 offset = fBACnetPropertyValue(tvb, pinfo, pvtree, offset);
11694 offset += fTagHeaderTree(tvb, pinfo, pvtree, offset, &tag_no, &tag_info, &lvt);
11695 break;
11696 default:
11697 break;
11699 if (offset <= lastoffset)
11700 break; /* nothing happened, exit loop */
11702 break;
11703 case 20: /* context tag [20] is not used */
11704 break;
11705 case 21: /* change-of-discrete-value */
11706 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11707 /* exit loop if nothing happens inside */
11708 lastoffset = offset;
11709 switch (fTagNo(tvb, offset)) {
11710 case 0: /* new-value */
11711 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11713 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11714 if (tag_is_opening(tag_info))
11716 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11717 offset = fDateTime(tvb, pinfo, subtree, offset, "new-value: ");
11718 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11720 else
11722 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "new-value: ");
11725 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11726 break;
11727 case 1: /* status-flags */
11728 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11729 "status-flags: ", BACnetStatusFlags);
11730 break;
11731 default:
11732 break;
11734 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11736 break;
11737 case 22: /* change-of-timer */
11738 while (tvb_reported_length_remaining(tvb, offset) > 0) {
11739 /* exit loop if nothing happens inside */
11740 lastoffset = offset;
11741 switch (fTagNo(tvb, offset)) {
11742 case 0: /* new-state */
11743 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11744 "new-state: ", BACnetTimerState, 256);
11745 break;
11746 case 1: /* status-flags */
11747 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
11748 "status-flags: ", BACnetStatusFlags);
11749 break;
11750 case 2: /* update-time */
11751 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11752 offset = fDateTime(tvb, pinfo, subtree, offset, "update-time: ");
11753 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11754 break;
11755 case 3: /* last-state-change (OPTIONAL) */
11756 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11757 "new-state: ", BACnetTimerTransition, 256);
11758 break;
11759 case 4: /* initial-timeout (OPTIONAL) */
11760 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "initial-timeout: ");
11761 break;
11762 default:
11763 break;
11765 if (offset <= lastoffset) break; /* nothing happened, exit loop */
11767 break;
11769 /* todo: add new parameters here ... */
11770 default:
11771 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
11772 break;
11775 /* Closing tag for parameter choice */
11776 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11778 return offset;
11781 static unsigned
11782 // NOLINTNEXTLINE(misc-no-recursion)
11783 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
11785 unsigned lastoffset = offset;
11786 uint8_t tag_no, tag_info;
11787 uint32_t lvt;
11788 proto_tree *subtree = tree;
11790 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11791 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
11792 ett_bacapp_value, NULL, "event parameters (%d) %s",
11793 tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
11795 /* Opening tag for parameter choice */
11796 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11798 switch (tag_no) {
11799 case 0: /* change-of-bitstring */
11800 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11801 lastoffset = offset;
11802 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11803 if (tag_is_closing(tag_info)) {
11804 break;
11806 switch (tag_no) {
11807 case 0:
11808 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11809 break;
11810 case 1:
11811 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
11812 break;
11813 case 2: /* SEQUENCE OF BIT STRING */
11814 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11815 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11816 lastoffset = offset;
11817 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11818 if (tag_is_closing(tag_info)) {
11819 break;
11821 offset = fBitStringTag(tvb, pinfo, subtree, offset,
11822 "bitstring value: ");
11824 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11825 break;
11826 default:
11827 break;
11830 break;
11831 case 1: /* change-of-state */
11832 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11833 lastoffset = offset;
11834 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11835 if (tag_is_closing(tag_info)) {
11836 break;
11838 switch (tag_no) {
11839 case 0:
11840 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11841 break;
11842 case 1: /* SEQUENCE OF BACnetPropertyStates */
11843 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11844 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11845 lastoffset = offset;
11846 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11847 if (tag_is_closing(tag_info)) {
11848 break;
11850 offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
11852 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11853 break;
11854 default:
11855 break;
11858 break;
11859 case 2: /* change-of-value */
11860 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11861 lastoffset = offset;
11862 switch (fTagNo(tvb, offset)) {
11863 case 0:
11864 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11865 break;
11866 case 1: /* don't loop it, it's a CHOICE */
11867 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11868 switch (fTagNo(tvb, offset)) {
11869 case 0:
11870 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
11871 break;
11872 case 1:
11873 offset = fRealTag(tvb, pinfo, subtree, offset,
11874 "referenced Property Increment: ");
11875 break;
11876 default:
11877 break;
11879 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11880 break;
11881 default:
11882 break;
11885 break;
11886 case 3: /* command-failure */
11887 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11888 lastoffset = offset;
11889 tag_no = fTagNo(tvb, offset);
11890 switch (tag_no) {
11891 case 0:
11892 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11893 break;
11894 case 1:
11895 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11896 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11897 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11898 break;
11899 default:
11900 break;
11903 break;
11904 case 4: /* floating-limit */
11905 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11906 lastoffset = offset;
11907 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11908 if (tag_is_closing(tag_info)) {
11909 break;
11911 switch (tag_no) {
11912 case 0:
11913 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11914 break;
11915 case 1:
11916 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11917 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
11918 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11919 break;
11920 case 2:
11921 offset = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
11922 break;
11923 case 3:
11924 offset = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
11925 break;
11926 case 4:
11927 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
11928 break;
11929 default:
11930 break;
11933 break;
11934 case 5: /* out-of-range */
11935 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11936 lastoffset = offset;
11937 switch (fTagNo(tvb, offset)) {
11938 case 0:
11939 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11940 break;
11941 case 1:
11942 offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
11943 break;
11944 case 2:
11945 offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
11946 break;
11947 case 3:
11948 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
11949 break;
11950 default:
11951 break;
11954 break;
11955 case 6: /* complex-event-type */
11956 /* deprecated */
11957 offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
11958 break;
11959 case 7: /* buffer-ready */
11960 /* deprecated */
11961 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
11962 lastoffset = offset;
11963 switch (fTagNo(tvb, offset)) {
11964 case 0:
11965 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
11966 break;
11967 case 1:
11968 offset = fUnsignedTag(tvb, pinfo, tree, offset,
11969 "previous notification count: ");
11970 break;
11971 default:
11972 return offset;
11975 break;
11976 case 8: /* change-of-life-safety */
11977 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11978 lastoffset = offset;
11979 switch (fTagNo(tvb, offset)) {
11980 case 0:
11981 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
11982 break;
11983 case 1:
11984 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11985 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11986 lastoffset = offset;
11987 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
11988 if (tag_is_closing(tag_info)) {
11989 break;
11991 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
11992 "life safety alarm value: ", BACnetLifeSafetyState, 256);
11994 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11995 break;
11996 case 2:
11997 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
11998 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
11999 lastoffset = offset;
12000 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12001 if (tag_is_closing(tag_info)) {
12002 break;
12004 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
12005 "alarm value: ", BACnetLifeSafetyState, 256);
12007 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12008 break;
12009 case 3:
12010 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12011 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
12012 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12013 break;
12014 default:
12015 break;
12018 break;
12019 case 9: /* extended */
12020 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12021 lastoffset = offset;
12022 switch (fTagNo(tvb, offset)) {
12023 case 0:
12024 offset = fVendorIdentifier(tvb, pinfo, tree, offset);
12025 break;
12026 case 1:
12027 offset = fUnsignedTag(tvb, pinfo, tree, offset, "extended-event-type: ");
12028 break;
12029 case 2: /* parameters */
12030 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12031 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12032 lastoffset = offset;
12033 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12034 if (tag_is_closing(tag_info) && tag_no == 2) {
12035 break;
12038 if ( ! tag_is_context_specific(tag_info)) {
12039 offset = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
12040 } else {
12041 if (tag_no == 0) {
12042 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12043 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
12044 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12045 } else {
12046 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
12050 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12051 lastoffset = offset;
12052 break;
12053 default:
12054 break;
12056 if (offset <= lastoffset) break; /* nothing happened, exit loop */
12058 break;
12059 case 10: /* buffer-ready */
12060 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12061 lastoffset = offset;
12062 switch (fTagNo(tvb, offset)) {
12063 case 0:
12064 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
12065 "notification-threshold: ");
12066 break;
12067 case 1:
12068 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
12069 "previous-notification-count: ");
12070 break;
12071 default:
12072 break;
12075 break;
12076 case 11: /* unsigned-range */
12077 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12078 lastoffset = offset;
12079 switch (fTagNo(tvb, offset)) {
12080 case 0:
12081 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
12082 break;
12083 case 1:
12084 offset = fUnsignedTag(tvb, pinfo, tree, offset,
12085 "low-limit: ");
12086 break;
12087 case 2:
12088 offset = fUnsignedTag(tvb, pinfo, tree, offset,
12089 "high-limit: ");
12090 break;
12091 default:
12092 break;
12095 break;
12096 case 13: /* access-event */
12097 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12098 lastoffset = offset;
12099 switch (fTagNo(tvb, offset)) {
12100 case 0:
12101 /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
12102 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12103 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12104 lastoffset = offset;
12105 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12106 if (tag_is_closing(tag_info)) {
12107 break;
12109 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
12110 "access event: ", BACnetAccessEvent, 512);
12112 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12113 break;
12114 case 1:
12115 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12116 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
12117 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12118 break;
12119 default:
12120 break;
12123 break;
12124 case 14: /* double-out-of-range */
12125 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12126 lastoffset = offset;
12127 switch (fTagNo(tvb, offset)) {
12128 case 0:
12129 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12130 break;
12131 case 1:
12132 offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
12133 break;
12134 case 2:
12135 offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
12136 break;
12137 case 3:
12138 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
12139 break;
12140 default:
12141 break;
12144 break;
12145 case 15: /* signed-out-of-range */
12146 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12147 lastoffset = offset;
12148 switch (fTagNo(tvb, offset)) {
12149 case 0:
12150 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12151 break;
12152 case 1:
12153 offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
12154 break;
12155 case 2:
12156 offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
12157 break;
12158 case 3:
12159 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
12160 break;
12161 default:
12162 break;
12165 break;
12166 case 16: /* unsigned-out-of-range */
12167 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12168 lastoffset = offset;
12169 switch (fTagNo(tvb, offset)) {
12170 case 0:
12171 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12172 break;
12173 case 1:
12174 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
12175 break;
12176 case 2:
12177 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
12178 break;
12179 case 3:
12180 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
12181 break;
12182 default:
12183 break;
12186 break;
12187 case 17: /* change-of-characterstring */
12188 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12189 lastoffset = offset;
12190 switch (fTagNo(tvb, offset)) {
12191 case 0:
12192 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12193 break;
12194 case 1: /* SEQUENCE OF CharacterString */
12195 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12196 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12197 lastoffset = offset;
12198 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12199 if (tag_is_closing(tag_info)) {
12200 break;
12202 offset = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
12204 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12205 break;
12206 default:
12207 break;
12210 break;
12211 case 18: /* change-of-status-flags */
12212 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12213 lastoffset = offset;
12214 switch (fTagNo(tvb, offset)) {
12215 case 0:
12216 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12217 break;
12218 case 1:
12219 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
12220 "selected flags: ", BACnetStatusFlags);
12221 break;
12222 default:
12223 break;
12226 break;
12227 case 19: /* has been intentionally omitted. It parallels the change-of-reliability event type */
12228 break;
12229 case 20: /* none */
12230 /* no closing tag expected only context tag here */
12231 return offset;
12232 case 21: /* change-of-discrete-value */
12233 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12234 lastoffset = offset;
12235 switch (fTagNo(tvb, offset)) {
12236 case 0:
12237 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12238 break;
12239 default:
12240 break;
12243 break;
12244 case 22: /* change-of-timer */
12245 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12246 lastoffset = offset;
12247 switch (fTagNo(tvb, offset)) {
12248 case 0: /* time-delay */
12249 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
12250 break;
12251 case 1: /* alarm-values */
12252 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12253 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
12254 lastoffset = offset;
12255 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12256 if (tag_is_closing(tag_info)) {
12257 break;
12259 offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
12260 "alarm value: ", BACnetTimerState);
12262 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12263 break;
12264 case 2: /* update-time-reference */
12265 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12266 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
12267 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12268 break;
12269 default:
12270 break;
12273 break;
12274 /* todo: add new event-parameter cases here */
12275 default:
12276 break;
12279 /* Closing tag for parameter choice */
12280 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12281 return offset;
12284 static unsigned
12285 fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12287 unsigned lastoffset = offset;
12288 uint8_t tag_no, tag_info;
12289 uint32_t lvt;
12290 proto_tree *subtree = tree;
12292 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12293 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12294 ett_bacapp_value, NULL, "fault parameters (%d) %s",
12295 tag_no, val_to_str_const(tag_no, BACnetFaultType, "invalid type"));
12297 /* Opening tag for parameter choice */
12298 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12300 switch (tag_no) {
12301 case 0: /* none */
12302 /* no closing tag expected only context tag here */
12303 return offset;
12304 case 1: /* fault-characterstring */
12305 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12306 lastoffset = offset;
12307 switch (fTagNo(tvb, offset)) {
12308 case 0: /* SEQUENCE OF CharacterString */
12309 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12310 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12311 lastoffset = offset;
12312 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12313 if (tag_is_closing(tag_info)) {
12314 break;
12316 offset = fCharacterString(tvb, pinfo, subtree, offset, "fault value: ");
12318 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12319 break;
12320 default:
12321 break;
12324 break;
12325 case 2: /* fault-extended */
12326 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12327 lastoffset = offset;
12328 switch (fTagNo(tvb, offset)) {
12329 case 0:
12330 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
12331 break;
12332 case 1:
12333 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "extended-fault-type: ");
12334 break;
12335 case 2: /* parameters */
12336 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12337 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
12338 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12339 lastoffset = offset;
12340 break;
12341 default:
12342 break;
12345 break;
12346 case 3: /* fault-life-safety */
12347 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12348 lastoffset = offset;
12349 switch (fTagNo(tvb, offset)) {
12350 case 0:
12351 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12352 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12353 lastoffset = offset;
12354 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12355 if (tag_is_closing(tag_info)) {
12356 break;
12358 offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
12359 "fault value: ", BACnetLifeSafetyState);
12361 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12362 break;
12363 case 1:
12364 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12365 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
12366 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12367 break;
12368 default:
12369 break;
12372 break;
12373 case 4: /* fault-state */
12374 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12375 lastoffset = offset;
12376 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12377 if (tag_is_closing(tag_info)) {
12378 break;
12380 switch (tag_no) {
12381 case 0: /* SEQUENCE OF BACnetPropertyStates */
12382 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12383 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12384 lastoffset = offset;
12385 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12386 if (tag_is_closing(tag_info)) {
12387 break;
12389 offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
12391 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12392 break;
12393 default:
12394 break;
12397 break;
12398 case 5: /* fault-status-flags */
12399 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12400 lastoffset = offset;
12401 switch (fTagNo(tvb, offset)) {
12402 case 0:
12403 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12404 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
12405 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12406 break;
12407 default:
12408 break;
12411 break;
12412 case 6: /* fault-out-of-range */
12413 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12414 lastoffset = offset;
12415 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12416 if (tag_is_closing(tag_info)) {
12417 break;
12419 switch (fTagNo(tvb, offset)) {
12420 case 0:
12421 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12422 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "min-normal-value: ");
12423 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12424 break;
12425 case 1:
12426 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12427 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "max-normal-value: ");
12428 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12429 break;
12430 default:
12431 break;
12434 break;
12435 case 7: /* fault-listed */
12436 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset>lastoffset)) { /* exit loop if nothing happens inside */
12437 lastoffset = offset;
12438 switch (fTagNo(tvb, offset)) {
12439 case 0:
12440 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12441 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
12442 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12443 break;
12444 default:
12445 break;
12448 break;
12449 default:
12450 break;
12453 /* Closing tag for parameter choice */
12454 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12455 return offset;
12458 static unsigned
12459 fEventNotificationSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12461 unsigned lastoffset = 0;
12462 uint8_t tag_no, tag_info;
12463 uint32_t lvt;
12464 proto_tree *subtree;
12465 unsigned itemno = 1;
12467 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) { /* exit loop if nothing happens inside */
12468 lastoffset = offset;
12469 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12470 if (tag_is_closing(tag_info)) {
12471 return offset;
12473 switch (tag_no) {
12474 case 0: /* recipient */
12475 tree = proto_tree_add_subtree_format(tree, tvb, offset, 1,
12476 ett_bacapp_value, NULL, "Subscription %d", itemno); /* add tree label and indent */
12477 itemno = itemno + 1;
12479 subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
12480 ett_bacapp_value, NULL, "Recipient: "); /* add tree label and indent */
12481 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
12482 offset = fRecipient(tvb, pinfo, subtree, offset);
12483 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
12484 break;
12485 case 1: /* process-identifier */
12486 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Process Identifier: ");
12487 break;
12488 case 2: /* issue-confirmed-notifications */
12489 offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
12490 break;
12491 case 3: /* time-remaining */
12492 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
12493 break;
12494 default:
12495 return offset;
12499 return offset;
12502 static unsigned
12503 fLightingCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12505 unsigned lastoffset = 0;
12506 uint8_t tag_no, tag_info;
12507 uint32_t lvt;
12508 proto_tree *subtree = tree;
12510 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12511 ett_bacapp_value, NULL, "%s", lable);
12513 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12514 lastoffset = offset;
12515 /* check the tag. A closing tag means we are done */
12516 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12517 if (tag_is_closing(tag_info)) {
12518 return offset;
12520 switch (tag_no) {
12521 case 0: /* operation */
12522 offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "operation: ", BACnetLightingOperation);
12523 break;
12524 case 1: /* target-level */
12525 offset = fRealTag(tvb, pinfo, subtree, offset, "target-level: ");
12526 break;
12527 case 2: /* ramp-rate */
12528 offset = fRealTag(tvb, pinfo, subtree, offset, "ramp-rate: ");
12529 break;
12530 case 3: /* step-increment */
12531 offset = fRealTag(tvb, pinfo, subtree, offset, "step-increment: ");
12532 break;
12533 case 4: /* fade-time */
12534 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "fade-time: ");
12535 break;
12536 case 5: /* priority */
12537 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "priority: ");
12538 break;
12539 default:
12540 return offset;
12544 return offset;
12547 static unsigned
12548 fColorCommand(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* lable)
12550 unsigned lastoffset = 0;
12551 uint8_t tag_no, tag_info;
12552 uint32_t lvt;
12553 proto_tree* subtree = tree;
12555 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12556 ett_bacapp_value, NULL, "%s", lable);
12558 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12559 lastoffset = offset;
12560 /* check the tag. A closing tag means we are done */
12561 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12562 if (tag_is_closing(tag_info)) {
12563 return offset;
12565 switch (tag_no) {
12566 case 0: /* operation */
12567 offset = fEnumeratedTag(tvb, pinfo, subtree, offset, "operation: ", BACnetColorOperation);
12568 break;
12569 case 1: /* target-color */
12570 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12571 offset = fXyColor(tvb, pinfo, subtree, offset, "xy-color: ");
12572 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12573 break;
12574 case 2: /* target-color-temperature */
12575 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "target-color-temperature: ");
12576 break;
12577 case 3: /* fade-time */
12578 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "fade-time: ");
12579 break;
12580 case 4: /* ramp-rate */
12581 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "ramp-rate: ");
12582 break;
12583 case 5: /* step-increment */
12584 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "step-increment: ");
12585 break;
12586 default:
12587 return offset;
12591 return offset;
12594 static unsigned
12595 fXyColor(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, unsigned offset, const char* label)
12597 proto_tree* subtree = tree;
12599 if (label != NULL) {
12600 subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
12602 offset = fRealTag(tvb, pinfo, subtree, offset, "x-coordinate: ");
12603 return fRealTag(tvb, pinfo, subtree, offset, "y-coordinate: ");
12606 static unsigned
12607 // NOLINTNEXTLINE(misc-no-recursion)
12608 fTimerStateChangeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12610 unsigned lastoffset = 0;
12611 uint8_t tag_no, tag_info;
12612 uint32_t lvt;
12613 int32_t save_propertyIdentifier;
12614 unsigned ftag_offset;
12616 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12617 lastoffset = offset;
12618 /* check the tag. A closing tag means we are done */
12619 ftag_offset = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12620 if (tag_is_closing(tag_info)) {
12621 return offset;
12623 if (tag_is_context_specific(tag_info)){
12624 switch (tag_no) {
12625 case 0: /* no-value */
12626 offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
12627 break;
12628 case 1: /* constructed-value */
12629 offset += ftag_offset;
12630 /* this ASN-1 construction may contain also an property identifier, so
12631 save the one we have got and restore it later and invalidate current
12632 one to avoid misinterpretations */
12633 save_propertyIdentifier = propertyIdentifier;
12634 propertyIdentifier = -1;
12635 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
12636 propertyIdentifier = save_propertyIdentifier;
12637 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12638 break;
12639 case 2: /* date-time */
12640 offset += ftag_offset;
12641 offset = fDateTime(tvb, pinfo, tree, offset, "date-time: ");
12642 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12643 break;
12644 case 3: /* lighting-command */
12645 offset += ftag_offset;
12646 offset = fLightingCommand(tvb, pinfo, tree, offset, "lighting-command: ");
12647 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12648 break;
12649 default:
12650 return offset;
12653 else {
12654 offset = fApplicationTypes(tvb, pinfo, tree, offset, NULL);
12657 return offset;
12660 static unsigned
12661 fHostAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12663 uint8_t tag_no, tag_info;
12664 uint32_t lvt;
12666 if (tvb_reported_length_remaining(tvb, offset) > 0) {
12667 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12668 switch (tag_no) {
12669 case 0: /* none */
12670 offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
12671 break;
12672 case 1: /* ip-address */
12673 offset = fOctetString(tvb, pinfo, tree, offset, "ip-address: ", lvt);
12674 break;
12675 case 2: /* internet name (see RFC 1123) */
12676 offset = fCharacterString(tvb, pinfo, tree, offset, "name: ");
12677 break;
12678 default:
12679 return offset;
12683 return offset;
12686 static unsigned
12687 fHostNPort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12689 unsigned lastoffset = 0;
12690 uint8_t tag_no, tag_info;
12691 uint32_t lvt;
12692 proto_tree *subtree = tree;
12694 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12695 ett_bacapp_value, NULL, "%s", lable);
12697 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12698 lastoffset = offset;
12699 /* check the tag. A closing tag means we are done */
12700 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12701 if (tag_is_closing(tag_info)) {
12702 return offset;
12704 switch (tag_no) {
12705 case 0: /* host */
12706 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12707 offset = fHostAddress(tvb, pinfo, subtree, offset);
12708 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12709 break;
12710 case 1: /* port */
12711 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "port: ");
12712 break;
12713 default:
12714 return offset;
12718 return offset;
12721 static unsigned
12722 fBDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12724 unsigned lastoffset = 0;
12725 uint8_t tag_no, tag_info;
12726 uint32_t lvt;
12727 proto_tree *subtree = tree;
12729 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12730 ett_bacapp_value, NULL, "%s", lable);
12732 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12733 lastoffset = offset;
12734 /* check the tag. A closing tag means we are done */
12735 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12736 if (tag_is_closing(tag_info)) {
12737 return offset;
12740 switch (tag_no) {
12741 case 0: /* bbmd-address */
12742 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12743 offset = fHostNPort(tvb, pinfo, subtree, offset, "bbmd-address: ");
12744 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
12745 break;
12746 case 1: /* bbmd-mask */
12747 offset = fOctetString(tvb, pinfo, subtree, offset, "bbmd-mask: ", lvt);
12748 break;
12749 default:
12750 return offset;
12754 return offset;
12757 static unsigned
12758 fFDTEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, const char *lable)
12760 unsigned lastoffset = 0;
12761 uint8_t tag_no, tag_info;
12762 uint32_t lvt;
12763 proto_tree *subtree = tree;
12765 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
12766 ett_bacapp_value, NULL, "%s", lable);
12768 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
12769 lastoffset = offset;
12770 /* check the tag. A closing tag means we are done */
12771 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12772 if (tag_is_closing(tag_info)) {
12773 return offset;
12776 switch (tag_no) {
12777 case 0: /* bacnetip-address */
12778 offset = fOctetString(tvb, pinfo, subtree, offset, "bacnetip-address: ", lvt);
12779 break;
12780 case 1: /* time-to-live */
12781 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "time-to-live: ");
12782 break;
12783 case 2: /* remaining-time-to-live */
12784 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "remaining-time-to-live: ");
12785 break;
12786 default:
12787 return offset;
12791 return offset;
12794 static unsigned
12795 fRouterEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12797 unsigned lastoffset = 0;
12798 uint8_t tag_no, tag_info;
12799 uint32_t lvt;
12801 while (tvb_reported_length_remaining(tvb, offset) > 0) {
12802 lastoffset = offset;
12803 /* check the tag. A closing tag means we are done */
12804 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12805 if (tag_is_closing(tag_info)) {
12806 break;
12808 switch (tag_no) {
12809 case 0: /* network number */
12810 offset = fUnsignedTag(tvb, pinfo, tree, offset, "network number: ");
12811 break;
12812 case 1: /* MAC address */
12813 offset = fOctetString(tvb, pinfo, tree, offset, "MAC address: ", lvt);
12814 break;
12815 case 2: /* status */
12816 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "status: ", BACnetRouterStatus);
12817 break;
12818 case 3: /* performance index */
12819 offset = fUnsignedTag(tvb, pinfo, tree, offset, "performance index: ");
12820 break;
12821 default:
12822 return offset;
12824 if (offset <= lastoffset) break; /* nothing happened, exit loop */
12827 return offset;
12830 static unsigned
12831 fVMACEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12833 unsigned lastoffset = 0;
12834 uint8_t tag_no, tag_info;
12835 uint32_t lvt;
12837 while (tvb_reported_length_remaining(tvb, offset) > 0) {
12838 lastoffset = offset;
12839 /* check the tag. A closing tag means we are done */
12840 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12841 if (tag_is_closing(tag_info)) {
12842 break;
12844 switch (tag_no) {
12845 case 0: /* virtual mac address */
12846 offset = fOctetString(tvb, pinfo, tree, offset, "virtual MAC address: ", lvt);
12847 break;
12848 case 1: /* native mac address */
12849 offset = fOctetString(tvb, pinfo, tree, offset, "native MAC address: ", lvt);
12850 break;
12851 default:
12852 return offset;
12854 if (offset <= lastoffset) break; /* nothing happened, exit loop */
12857 return offset;
12860 static unsigned
12861 fValueSource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12863 uint8_t tag_no, tag_info;
12864 uint32_t lvt;
12866 if (tvb_reported_length_remaining(tvb, offset) > 0) {
12867 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12868 switch (tag_no) {
12869 case 0: /* null */
12870 offset = fNullTag(tvb, pinfo, tree, offset, "no-value: ");
12871 break;
12872 case 1: /* object reference */
12873 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12874 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
12875 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12876 break;
12877 case 2: /* address */
12878 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12879 offset = fAddress(tvb, pinfo, tree, offset);
12880 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12881 break;
12882 default:
12883 return offset;
12887 return offset;
12890 static unsigned
12891 fAssignedLandingCalls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12893 unsigned lastoffset = 0;
12894 uint8_t tag_no, tag_info;
12895 uint32_t lvt;
12897 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12899 while (tvb_reported_length_remaining(tvb, offset) > 0) {
12900 lastoffset = offset;
12901 /* check the tag. A closing tag means we are done */
12902 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12903 if (tag_is_closing(tag_info)) {
12904 break;
12906 switch (tag_no) {
12907 case 0: /* floor number */
12908 offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
12909 break;
12910 case 1: /* direction */
12911 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "direction: ", BACnetLiftCarDirection);
12912 break;
12913 default:
12914 return offset;
12916 if (offset <= lastoffset) break; /* nothing happened, exit loop */
12919 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12920 return offset;
12923 static unsigned
12924 fLandingCallStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12926 unsigned lastoffset = 0;
12927 uint8_t tag_no, tag_info;
12928 uint32_t lvt;
12930 while (tvb_reported_length_remaining(tvb, offset) > 0) {
12931 lastoffset = offset;
12932 /* check the tag. A closing tag means we are done */
12933 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12934 if (tag_is_closing(tag_info)) {
12935 break;
12937 switch (tag_no) {
12938 case 0: /* floor number */
12939 offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
12940 break;
12941 case 1: /* direction */
12942 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "direction: ", BACnetLiftCarDirection);
12943 break;
12944 case 2: /* destination */
12945 offset = fUnsignedTag(tvb, pinfo, tree, offset, "destination: ");
12946 break;
12947 case 3: /* floor-text */
12948 offset = fCharacterString(tvb, pinfo, tree, offset, "floor-text: ");
12949 break;
12950 default:
12951 return offset;
12953 if (offset <= lastoffset) break; /* nothing happened, exit loop */
12956 return offset;
12959 static unsigned
12960 fLandingDoorStatus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12962 unsigned lastoffset = 0;
12963 uint8_t tag_no, tag_info;
12964 uint32_t lvt;
12966 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12968 while (tvb_reported_length_remaining(tvb, offset) > 0) {
12969 lastoffset = offset;
12970 /* check the tag. A closing tag means we are done */
12971 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
12972 if (tag_is_closing(tag_info)) {
12973 break;
12975 switch (tag_no) {
12976 case 0: /* floor number */
12977 offset = fUnsignedTag(tvb, pinfo, tree, offset, "floor number: ");
12978 break;
12979 case 1: /* door status */
12980 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "door status: ", BACnetDoorStatus);
12981 break;
12982 default:
12983 return offset;
12985 if (offset <= lastoffset) break; /* nothing happened, exit loop */
12988 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
12989 return offset;
12992 static unsigned
12993 fCOVMultipleSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
12995 unsigned lastoffset = 0;
12996 uint8_t tag_no, tag_info;
12997 uint32_t lvt;
12999 while (tvb_reported_length_remaining(tvb, offset) > 0) {
13000 lastoffset = offset;
13001 /* check the tag. A closing tag means we are done */
13002 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13003 if (tag_is_closing(tag_info)) {
13004 break;
13006 switch (tag_no) {
13007 case 0: /* recipient */
13008 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13009 offset = fRecipientProcess(tvb, pinfo, tree, offset);
13010 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13011 break;
13012 case 1: /* issue-confirmed-notifications */
13013 offset = fBooleanTag(tvb, pinfo, tree, offset, "issue confirmed notifications: ");
13014 break;
13015 case 2: /* time-remaining */
13016 offset = fUnsignedTag(tvb, pinfo, tree, offset, "time remaining: ");
13017 break;
13018 case 3: /* max-notification-delay */
13019 offset = fUnsignedTag(tvb, pinfo, tree, offset, "max notification delay: ");
13020 break;
13021 case 4: /* list-of-cov-subscription-specifications */
13022 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13023 while (tvb_reported_length_remaining(tvb, offset) > 0) {
13024 lastoffset = offset;
13025 /* check the tag. A closing tag means we are done */
13026 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13027 if (tag_is_closing(tag_info)) {
13028 break;
13030 switch (tag_no) {
13031 case 0: /* monitored-object-identifier */
13032 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
13033 break;
13034 case 1: /* list-of-cov-references */
13035 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13036 while (tvb_reported_length_remaining(tvb, offset) > 0) {
13037 lastoffset = offset;
13038 /* check the tag. A closing tag means we are done */
13039 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13040 if (tag_is_closing(tag_info)) {
13041 break;
13043 switch (tag_no) {
13044 case 0: /* monitored-property */
13045 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13046 offset = fBACnetPropertyReference(tvb, pinfo, tree, offset, 0);
13047 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13048 break;
13049 case 1: /* cov-increment */
13050 offset = fRealTag(tvb, pinfo, tree, offset, "cov-increment: ");
13051 break;
13052 case 2: /* timestamped */
13053 offset = fBooleanTag(tvb, pinfo, tree, offset, "timestamped: ");
13054 break;
13055 default:
13056 return offset;
13058 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13060 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13061 break;
13062 default:
13063 return offset;
13065 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13067 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13068 break;
13069 default:
13070 return offset;
13072 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13075 return offset;
13078 static unsigned
13079 fNameValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13081 unsigned lastoffset = 0;
13082 uint8_t tag_no, tag_info;
13083 uint32_t lvt;
13085 while (tvb_reported_length_remaining(tvb, offset) > 0) {
13086 lastoffset = offset;
13087 /* check the tag. A closing tag means we are done */
13088 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13089 if (tag_is_closing(tag_info)) {
13090 break;
13092 if (tag_is_context_specific(tag_info)) {
13093 switch (tag_no) {
13094 case 0: /* name */
13095 offset = fCharacterString(tvb, pinfo, tree, offset, "name: ");
13096 break;
13097 case 1: /* date+time value */
13098 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13099 offset = fDateTime(tvb, pinfo, tree, offset, "value: ");
13100 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13101 break;
13102 default: /* abstract syntax and type */
13103 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
13104 offset = fApplicationTypes(tvb, pinfo, tree, offset, "value: ");
13105 break;
13108 else {
13109 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
13110 offset = fApplicationTypes(tvb, pinfo, tree, offset, "value: ");
13112 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13114 return offset;
13117 static unsigned
13118 fNameValueCollection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13120 unsigned lastoffset = 0;
13121 uint8_t tag_no, tag_info;
13122 uint32_t lvt;
13123 proto_tree *subtree = tree;
13125 subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
13126 ett_bacapp_value, NULL, "%s", "name-value-collection: ");
13128 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13130 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
13131 lastoffset = offset;
13132 /* check the tag. A closing tag means we are done */
13133 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13134 if (tag_is_closing(tag_info)) {
13135 break;
13138 offset = fNameValue(tvb, pinfo, subtree, offset);
13141 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13142 return offset;
13145 static unsigned
13146 fObjectSelector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13148 unsigned lastoffset = 0;
13149 uint8_t tag_no, tag_info;
13150 uint32_t lvt;
13152 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13153 lastoffset = offset;
13154 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13155 if (tag_is_closing(tag_info)) {
13156 break;
13159 switch (tag_no) {
13160 case 0: /* NULL */
13161 offset = fNullTag(tvb, pinfo, tree, offset, "NULL: ");
13162 break;
13163 case 9: /* object-type */
13164 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, "object-type: ", BACnetObjectType, 256);
13165 break;
13166 case 12: /* object */
13167 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
13168 break;
13169 default:
13170 break;
13172 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13174 return offset;
13177 static unsigned
13178 fStageLimitValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13180 if (tvb_reported_length_remaining(tvb, offset) <= 0)
13181 return offset;
13182 offset = fRealTag(tvb, pinfo, tree, offset, "limit: ");
13183 if (tvb_reported_length_remaining(tvb, offset) <= 0)
13184 return offset;
13185 offset = fBitStringTag(tvb, pinfo, tree, offset, "values: ");
13186 if (tvb_reported_length_remaining(tvb, offset) <= 0)
13187 return offset;
13188 offset = fRealTag(tvb, pinfo, tree, offset, "deadband: ");
13189 return offset;
13192 static unsigned
13193 fLifeSafetyInfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13195 unsigned lastoffset = 0;
13196 uint8_t tag_no, tag_info;
13197 uint32_t lvt;
13199 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13200 lastoffset = offset;
13201 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13202 if (tag_is_closing(tag_info)) {
13203 break;
13206 switch (tag_no) {
13207 case 0: /* requesting-process-identifier */
13208 offset = fUnsignedTag(tvb, pinfo, tree, offset, "requesting-process-identifier: ");
13209 break;
13210 case 1: /* request */
13211 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13212 "requested-operation: ", BACnetLifeSafetyOperation, 64);
13213 break;
13214 default:
13215 break;
13217 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13219 return offset;
13222 static unsigned
13223 fAcknowledgeAlarmInfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13225 unsigned lastoffset = 0;
13226 uint8_t tag_no, tag_info;
13227 uint32_t lvt;
13229 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13230 lastoffset = offset;
13231 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13232 if (tag_is_closing(tag_info)) {
13233 break;
13236 switch (tag_no) {
13237 case 0: /* event-state-acknowledged */
13238 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13239 "event-state-acknowledged: ", BACnetEventState, 64);
13240 break;
13241 case 1: /* timestamp */
13242 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13243 offset = fTimeStamp(tvb, pinfo, tree, offset, "source-timestamp: ");
13244 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13245 break;
13246 default:
13247 break;
13249 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13251 return offset;
13254 static unsigned
13255 // NOLINTNEXTLINE(misc-no-recursion)
13256 fAuditNotificationInfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13258 unsigned len, lastoffset = 0;
13259 uint8_t tag_no, tag_info;
13260 uint32_t lvt;
13261 uint32_t operation = 0;
13262 proto_tree *subtree = tree;
13264 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13265 lastoffset = offset;
13266 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13267 if (tag_is_closing(tag_info)) {
13268 break;
13271 switch (tag_no) {
13272 case 0: /* source-timestamp */
13273 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13274 offset = fTimeStamp(tvb, pinfo, tree, offset, "source-timestamp: ");
13275 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13276 break;
13277 case 1: /* target-timestamp */
13278 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13279 offset = fTimeStamp(tvb, pinfo, tree, offset, "target-timestamp: ");
13280 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13281 break;
13282 case 2: /* source-device */
13283 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "source-device: ");
13284 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13285 offset = fRecipient(tvb, pinfo, subtree, offset);
13286 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13287 break;
13288 case 3: /* source-object */
13289 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "source-object: ");
13290 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
13291 break;
13292 case 4: /* operation */
13293 fUnsigned32(tvb, offset, lvt, &operation);
13294 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13295 "operation: ", BACnetAuditOperation, 64);
13296 break;
13297 case 5: /* source-comment */
13298 offset = fCharacterString(tvb, pinfo, tree, offset, "source-comment: ");
13299 break;
13300 case 6: /* target-comment */
13301 offset = fCharacterString(tvb, pinfo, tree, offset, "target-comment: ");
13302 break;
13303 case 7: /* invoke-id */
13304 offset = fUnsignedTag(tvb, pinfo, tree, offset, "invoke-id: ");
13305 break;
13306 case 8: /* source-user-id */
13307 offset = fUnsignedTag(tvb, pinfo, tree, offset, "source-user-id: ");
13308 break;
13309 case 9: /* source-user-role */
13310 offset = fUnsignedTag(tvb, pinfo, tree, offset, "source-user-role: ");
13311 break;
13312 case 10: /* target-device */
13313 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-device: ");
13314 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13315 offset = fRecipient(tvb, pinfo, subtree, offset);
13316 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13317 break;
13318 case 11: /* target-object */
13319 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-object: ");
13320 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
13321 break;
13322 case 12: /* target-property */
13323 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-property: ");
13324 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13325 offset = fPropertyReference(tvb, pinfo, subtree, offset, 0, 0);
13326 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13327 break;
13328 case 13: /* target-priority */
13329 offset = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: ");
13330 break;
13331 case 14: /* target-value */
13332 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "target-value: ");
13333 if (operation == 4) {
13334 /* operation life safety */
13335 /* inspect next tag */
13336 fTagHeader(tvb, pinfo, offset + len, &tag_no, &tag_info, &lvt);
13337 if ( tag_no == 0 &&
13338 ! tag_is_opening(tag_info) &&
13339 tag_is_context_specific(tag_info) ) {
13340 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13341 offset = fLifeSafetyInfo(tvb, pinfo, subtree, offset);
13342 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13343 } else {
13344 /* abstract syntax and type */
13345 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
13347 } else if ( operation == 5 ) {
13348 /* operation acknowledge alarm */
13349 /* inspect next tag */
13350 fTagHeader(tvb, pinfo, offset + len, &tag_no, &tag_info, &lvt);
13351 if ( tag_no == 0 &&
13352 ! tag_is_opening(tag_info) &&
13353 tag_is_context_specific(tag_info) ) {
13354 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13355 offset = fAcknowledgeAlarmInfo(tvb, pinfo, subtree, offset);
13356 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13357 } else {
13358 /* abstract syntax and type */
13359 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
13361 } else {
13362 /* abstract syntax and type */
13363 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
13365 break;
13366 case 15: /* current-value */
13367 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "current-value: ");
13368 /* always abstract syntax and type */
13369 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
13370 break;
13371 case 16: /* error-result */
13372 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "error-result: ");
13373 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
13374 offset = fError(tvb, pinfo, subtree, offset);
13375 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
13376 break;
13377 default:
13378 break;
13380 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13382 return offset;
13385 static unsigned
13386 // NOLINTNEXTLINE(misc-no-recursion)
13387 fAuditLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13389 unsigned lastoffset = 0;
13390 uint8_t tag_no, tag_info;
13391 uint32_t lvt;
13392 proto_tree *subtree = tree;
13394 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13395 lastoffset = offset;
13396 fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13397 if (tag_is_closing(tag_info)) {
13398 break;
13401 switch (tag_no) {
13402 case 0: /* timestamp */
13403 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13404 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
13405 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
13406 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13407 break;
13408 case 1: /* logDatum: don't loop, it's a CHOICE */
13409 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13410 switch (fTagNo(tvb, offset)) {
13411 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
13412 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
13413 break;
13414 case 1: /* notification */
13415 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
13416 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13417 offset = fAuditNotificationInfo(tvb, pinfo, subtree, offset);
13418 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13419 break;
13420 case 2: /* time-change */
13421 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
13422 break;
13423 default:
13424 return offset;
13426 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13427 break;
13428 default:
13429 return offset;
13431 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13433 return offset;
13436 static unsigned
13437 // NOLINTNEXTLINE(misc-no-recursion)
13438 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13440 unsigned lastoffset = 0;
13441 uint8_t tag_no, tag_info;
13442 uint32_t lvt;
13443 proto_tree *subtree = tree;
13445 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13446 lastoffset = offset;
13447 switch (fTagNo(tvb, offset)) {
13448 case 0: /* timestamp */
13449 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13450 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
13451 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
13452 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13453 break;
13454 case 1: /* logDatum: don't loop, it's a CHOICE */
13455 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13456 switch (fTagNo(tvb, offset)) {
13457 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
13458 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
13459 break;
13460 case 1: /* notification */
13461 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
13462 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13463 offset = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
13464 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13465 break;
13466 case 2: /* time-change */
13467 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
13468 break;
13469 default:
13470 return offset;
13472 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13473 break;
13474 default:
13475 return offset;
13477 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13479 return offset;
13482 static unsigned
13483 // NOLINTNEXTLINE(misc-no-recursion)
13484 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13486 unsigned lastoffset = 0;
13487 uint8_t tag_no, tag_info;
13488 uint32_t lvt;
13489 int32_t save_propertyIdentifier;
13491 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13492 lastoffset = offset;
13493 switch (fTagNo(tvb, offset)) {
13494 case 0: /* timestamp */
13495 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13496 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
13497 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
13498 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13499 break;
13500 case 1: /* logDatum: don't loop, it's a CHOICE */
13501 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13502 switch (fTagNo(tvb, offset)) {
13503 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
13504 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status: ", BACnetLogStatus);
13505 break;
13506 case 1:
13507 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
13508 break;
13509 case 2:
13510 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
13511 break;
13512 case 3:
13513 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
13514 break;
13515 case 4:
13516 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
13517 break;
13518 case 5:
13519 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
13520 break;
13521 case 6:
13522 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
13523 break;
13524 case 7:
13525 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
13526 break;
13527 case 8:
13528 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13529 offset = fError(tvb, pinfo, tree, offset);
13530 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13531 break;
13532 case 9:
13533 offset = fRealTag(tvb, pinfo, tree, offset, "time change: ");
13534 break;
13535 case 10: /* any Value */
13536 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13537 /* this ASN-1 construction may contain also an property identifier, so
13538 save the one we have got and restore it later and invalidate current
13539 one to avoid misinterpretations */
13540 save_propertyIdentifier = propertyIdentifier;
13541 propertyIdentifier = -1;
13542 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
13543 propertyIdentifier = save_propertyIdentifier;
13544 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13545 break;
13546 default:
13547 return offset;
13549 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13550 break;
13551 case 2:
13552 /* Changed this to BitString per BACnet Spec. */
13553 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags: ", BACnetStatusFlags);
13554 break;
13555 default:
13556 return offset;
13558 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13560 return offset;
13563 static unsigned
13564 // NOLINTNEXTLINE(misc-no-recursion)
13565 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13567 unsigned lastoffset = 0;
13568 uint8_t tag_no, tag_info;
13569 uint32_t lvt;
13570 int32_t save_propertyIdentifier;
13572 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13573 lastoffset = offset;
13574 switch (fTagNo(tvb, offset)) {
13575 case 0: /* timestamp */
13576 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13577 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
13578 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
13579 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13580 break;
13581 case 1: /* logData: don't loop, it's a CHOICE */
13582 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13583 switch (fTagNo(tvb, offset)) {
13584 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
13585 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status: ", BACnetLogStatus);
13586 break;
13587 case 1: /* log-data: SEQUENCE OF CHOICE */
13588 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13589 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset != lastoffset)) { /* exit loop if nothing happens inside */
13590 lastoffset = offset;
13591 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13592 if (tag_is_closing(tag_info)) {
13593 lastoffset = offset;
13594 break;
13596 switch (tag_no) {
13597 case 0:
13598 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
13599 break;
13600 case 1:
13601 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
13602 break;
13603 case 2:
13604 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
13605 break;
13606 case 3:
13607 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
13608 break;
13609 case 4:
13610 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
13611 break;
13612 case 5:
13613 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
13614 break;
13615 case 6:
13616 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
13617 break;
13618 case 7:
13619 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13620 offset = fError(tvb, pinfo, tree, offset);
13621 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13622 break;
13623 case 8: /* any Value */
13624 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13625 /* this ASN-1 construction may contain also an property identifier, so
13626 save the one we have got and restore it later and invalidate current
13627 one to avoid misinterpretations */
13628 save_propertyIdentifier = propertyIdentifier;
13629 propertyIdentifier = -1;
13630 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
13631 propertyIdentifier = save_propertyIdentifier;
13632 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13633 break;
13634 default:
13635 return offset;
13638 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13639 break;
13640 case 2:
13641 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
13642 break;
13643 default:
13644 return offset;
13646 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13647 break;
13648 default:
13649 return offset;
13651 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13653 return offset;
13657 static unsigned
13658 // NOLINTNEXTLINE(misc-no-recursion)
13659 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13661 unsigned lastoffset = 0;
13662 uint8_t tag_no, tag_info;
13663 uint32_t lvt;
13665 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13666 lastoffset = offset;
13667 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13668 if (tag_is_closing(tag_info)) {
13669 break;
13672 switch (tag_no) {
13673 case 0: /* ProcessId */
13674 offset = fProcessId(tvb, pinfo, tree, offset);
13675 break;
13676 case 1: /* initiating ObjectId */
13677 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
13678 break;
13679 case 2: /* event ObjectId */
13680 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
13681 break;
13682 case 3: /* time stamp */
13683 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13684 offset = fTimeStamp(tvb, pinfo, tree, offset, NULL);
13685 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13686 break;
13687 case 4: /* notificationClass */
13688 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
13689 break;
13690 case 5: /* Priority */
13691 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
13692 break;
13693 case 6: /* EventType */
13694 offset = fEventType(tvb, pinfo, tree, offset);
13695 break;
13696 case 7: /* messageText */
13697 offset = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
13698 break;
13699 case 8: /* NotifyType */
13700 offset = fNotifyType(tvb, pinfo, tree, offset);
13701 break;
13702 case 9: /* ackRequired */
13703 offset = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
13704 break;
13705 case 10: /* fromState */
13706 offset = fFromState(tvb, pinfo, tree, offset);
13707 break;
13708 case 11: /* toState */
13709 offset = fToState(tvb, pinfo, tree, offset);
13710 break;
13711 case 12: /* NotificationParameters */
13712 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13713 offset = fNotificationParameters(tvb, pinfo, tree, offset);
13714 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13715 break;
13716 default:
13717 break;
13719 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13721 return offset;
13724 static unsigned
13725 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13727 return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
13730 static unsigned
13731 fConfirmedCOVNotificationMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13733 unsigned lastoffset = 0, len;
13734 uint8_t tag_no, tag_info;
13735 uint32_t lvt;
13736 proto_tree *subtree = tree;
13737 proto_tree *subsubtree = tree;
13739 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13740 lastoffset = offset;
13741 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13742 if (tag_is_closing(tag_info)) {
13743 offset += len;
13744 subtree = tree;
13745 continue;
13748 switch (tag_no) {
13749 case 0: /* ProcessId */
13750 offset = fProcessId(tvb, pinfo, tree, offset);
13751 break;
13752 case 1: /* initiating DeviceId */
13753 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
13754 break;
13755 case 2: /* time remaining */
13756 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining: ");
13757 break;
13758 case 3: /* timestamp */
13759 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13760 offset = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
13761 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13762 break;
13763 case 4: /* list-of-cov-notifications */
13764 if (tag_is_opening(tag_info)) {
13765 /* new subtree for list-of-cov-notifications */
13766 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-cov-notifications: ");
13767 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13769 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13770 lastoffset = offset;
13771 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13772 if (tag_is_closing(tag_info)) {
13773 /* end for list-of-cov-notifications */
13774 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13775 offset += len;
13776 subtree = tree;
13777 break;
13780 switch (tag_no) {
13781 case 0: /* monitored-object-identifier */
13782 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
13783 break;
13784 case 1: /* list-of-values */
13785 if (tag_is_opening(tag_info)) {
13786 /* new subtree for list-of-values */
13787 subsubtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list-of-values: ");
13788 offset += fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
13790 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13791 lastoffset = offset;
13792 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13793 if (tag_is_closing(tag_info)) {
13794 /* end of list-of-values */
13795 fTagHeaderTree(tvb, pinfo, subsubtree, offset, &tag_no, &tag_info, &lvt);
13796 offset += len;
13797 break;
13800 switch (tag_no) {
13801 case 0: /* PropertyIdentifier */
13802 offset = fPropertyIdentifier(tvb, pinfo, subsubtree, offset);
13803 break;
13804 case 1: /* propertyArrayIndex */
13805 offset = fPropertyArrayIndex(tvb, pinfo, subsubtree, offset);
13806 break;
13807 case 2: /* property-value */
13808 offset = fPropertyValue(tvb, pinfo, subsubtree, offset, tag_info);
13809 break;
13810 case 3: /* time-of-change */
13811 offset = fTime(tvb, pinfo, subsubtree, offset, "time of change: ");
13812 break;
13813 default:
13814 /* wrong tag encoding */
13815 return offset;
13817 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13820 else {
13821 /* wrong tag encoding */
13822 expert_add_info(pinfo, subsubtree, &ei_bacapp_bad_tag);
13824 break;
13825 default:
13826 /* wrong tag encoding */
13827 return offset;
13829 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13832 else {
13833 /* wrong tag encoding */
13834 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13836 break;
13837 default:
13838 /* wrong tag encoding */
13839 return offset;
13841 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13843 return offset;
13846 static unsigned
13847 fUnconfirmedCOVNotificationMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13849 return fConfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
13852 static unsigned
13853 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13855 unsigned lastoffset = 0, len;
13856 uint8_t tag_no, tag_info;
13857 uint32_t lvt;
13858 proto_tree *subtree = tree;
13860 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13861 lastoffset = offset;
13862 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
13863 if (tag_is_closing(tag_info)) {
13864 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13865 offset += len;
13866 subtree = tree;
13867 continue;
13870 switch (tag_no) {
13871 case 0: /* ProcessId */
13872 offset = fProcessId(tvb, pinfo, tree, offset);
13873 break;
13874 case 1: /* initiating DeviceId */
13875 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "DeviceIdentifier: ");
13876 break;
13877 case 2: /* monitored ObjectId */
13878 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
13879 break;
13880 case 3: /* time remaining */
13881 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining: ");
13882 break;
13883 case 4: /* List of Values */
13884 if (tag_is_opening(tag_info)) {
13885 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list of Values: ");
13886 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
13887 offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
13889 else {
13890 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
13892 break;
13893 default:
13894 return offset;
13896 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13898 return offset;
13901 static unsigned
13902 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13904 return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
13907 static unsigned
13908 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13910 unsigned lastoffset = 0;
13911 uint8_t tag_no = 0, tag_info = 0;
13912 uint32_t lvt = 0;
13914 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13915 lastoffset = offset;
13916 switch (fTagNo(tvb, offset)) {
13917 case 0: /* acknowledgingProcessId */
13918 offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
13919 break;
13920 case 1: /* eventObjectId */
13921 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
13922 break;
13923 case 2: /* eventStateAcknowledged */
13924 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
13925 "event State Acknowledged: ", BACnetEventState, 64);
13926 break;
13927 case 3: /* timeStamp */
13928 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13929 offset = fTimeStamp(tvb, pinfo, tree, offset, NULL);
13930 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13931 break;
13932 case 4: /* acknowledgementSource */
13933 offset = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
13934 break;
13935 case 5: /* timeOfAcknowledgement */
13936 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13937 offset = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
13938 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13939 break;
13940 default:
13941 return offset;
13943 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13945 return offset;
13948 static unsigned
13949 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13951 unsigned lastoffset = 0;
13953 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13954 lastoffset = offset;
13955 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
13956 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
13957 "alarm State: ", BACnetEventState, 64);
13958 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
13959 "acknowledged Transitions: ", BACnetEventTransitionBits);
13960 if (offset <= lastoffset) break; /* nothing happened, exit loop */
13962 return offset;
13965 static unsigned
13966 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
13968 unsigned lastoffset = 0;
13969 uint8_t tag_no, tag_info;
13970 uint32_t lvt;
13972 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
13973 lastoffset = offset;
13974 switch (fTagNo(tvb, offset)) {
13975 case 0: /* acknowledgmentFilter */
13976 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13977 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
13978 break;
13979 case 1: /* eventObjectId - OPTIONAL */
13980 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13981 offset = fRecipientProcess(tvb, pinfo, tree, offset);
13982 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13983 break;
13984 case 2: /* eventStateFilter */
13985 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13986 "event State Filter: ", BACnetEventStateFilter);
13987 break;
13988 case 3: /* eventTypeFilter - OPTIONAL */
13989 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
13990 "event Type Filter: ", BACnetEventType);
13991 break;
13992 case 4: /* priorityFilter */
13993 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13994 offset = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
13995 offset = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
13996 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
13997 break;
13998 case 5: /* notificationClassFilter - OPTIONAL */
13999 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
14000 break;
14001 default:
14002 return offset;
14004 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14006 return offset;
14009 static unsigned
14010 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14012 unsigned lastoffset = 0;
14014 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14015 lastoffset = offset;
14016 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
14017 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
14018 "event Type: ", BACnetEventType, 64);
14019 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
14020 "event State: ", BACnetEventState);
14021 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
14022 if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2) /* Notification Class - OPTIONAL */
14023 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
14024 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14027 return offset;
14030 static unsigned
14031 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14033 if (tvb_reported_length_remaining(tvb, offset) > 0) {
14034 if (fTagNo(tvb, offset) == 0) {
14035 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14038 return offset;
14041 static unsigned
14042 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14044 unsigned lastoffset = 0;
14045 uint8_t tag_no, tag_info;
14046 uint32_t lvt;
14047 proto_tree* subtree = tree;
14049 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14050 lastoffset = offset;
14051 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14052 /* we are finished here if we spot a closing tag */
14053 if (tag_is_closing(tag_info)) {
14054 break;
14056 switch (tag_no) {
14057 case 0: /* ObjectId */
14058 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14059 break;
14060 case 1: /* eventState */
14061 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
14062 "event State: ", BACnetEventState);
14063 break;
14064 case 2: /* acknowledgedTransitions */
14065 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
14066 "acknowledged Transitions: ", BACnetEventTransitionBits);
14067 break;
14068 case 3: /* eventTimeStamps */
14069 subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
14070 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14071 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
14072 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
14073 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
14074 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14075 break;
14076 case 4: /* notifyType */
14077 offset = fNotifyType(tvb, pinfo, tree, offset);
14078 break;
14079 case 5: /* eventEnable */
14080 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
14081 "event Enable: ", BACnetEventTransitionBits);
14082 break;
14083 case 6: /* eventPriorities */
14084 subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventPriorities");
14085 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14086 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
14087 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
14088 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
14089 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14090 break;
14091 default:
14092 return offset;
14094 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14096 return offset;
14099 static unsigned
14100 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14102 unsigned lastoffset = 0;
14103 uint8_t tag_no, tag_info;
14104 uint32_t lvt;
14106 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14107 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14108 lastoffset = offset;
14109 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14110 /* we are finished here if we spot a closing tag */
14111 if (tag_is_closing(tag_info)) {
14112 break;
14114 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
14115 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14117 return offset;
14120 static unsigned
14121 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14123 unsigned lastoffset = 0;
14124 uint8_t tag_no, tag_info;
14125 uint32_t lvt;
14127 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14128 lastoffset = offset;
14129 switch (fTagNo(tvb, offset)) {
14130 case 0: /* listOfEventSummaries */
14131 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14132 offset = flistOfEventSummaries(tvb, pinfo, tree, offset);
14133 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14134 break;
14135 case 1: /* moreEvents */
14136 offset = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
14137 break;
14138 default:
14139 return offset;
14141 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14143 return offset;
14146 static unsigned
14147 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14149 unsigned lastoffset = 0, len;
14150 uint8_t tag_no, tag_info;
14151 uint32_t lvt;
14152 proto_tree *subtree = tree;
14154 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14156 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14157 lastoffset = offset;
14158 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14159 if (tag_is_closing(tag_info)) {
14160 offset += len;
14161 subtree = tree;
14162 continue;
14165 switch (tag_no) {
14166 case 0: /* ObjectId */
14167 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
14168 break;
14169 case 3: /* listOfElements */
14170 if (tag_is_opening(tag_info)) {
14171 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfElements");
14172 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14173 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
14174 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14175 } else {
14176 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14178 break;
14179 default:
14180 return offset;
14182 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14184 return offset;
14187 static unsigned
14188 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14190 return fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14193 static unsigned
14194 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14196 unsigned lastoffset = 0;
14198 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14199 lastoffset = offset;
14201 switch (fTagNo(tvb, offset)) {
14202 case 0: /* timeDuration */
14203 offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
14204 break;
14205 case 1: /* enable-disable */
14206 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
14207 BACnetEnableDisable);
14208 break;
14209 case 2: /* password - OPTIONAL */
14210 offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
14211 break;
14212 default:
14213 return offset;
14215 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14217 return offset;
14220 static unsigned
14221 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14223 unsigned lastoffset = 0;
14225 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14226 lastoffset = offset;
14228 switch (fTagNo(tvb, offset)) {
14229 case 0: /* reinitializedStateOfDevice */
14230 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
14231 "reinitialized State Of Device: ",
14232 BACnetReinitializedStateOfDevice);
14233 break;
14234 case 1: /* password - OPTIONAL */
14235 offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
14236 break;
14237 default:
14238 return offset;
14240 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14242 return offset;
14245 static unsigned
14246 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14248 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
14249 "vtClass: ", BACnetVTClass);
14250 return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
14253 static unsigned
14254 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14256 return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
14259 static unsigned
14260 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14262 unsigned lastoffset = 0;
14264 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14265 lastoffset = offset;
14266 offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
14267 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14269 return offset;
14272 static unsigned
14273 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14275 offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
14276 offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
14277 return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
14280 static unsigned
14281 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14283 unsigned lastoffset = 0;
14285 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14286 lastoffset = offset;
14288 switch (fTagNo(tvb, offset)) {
14289 case 0: /* BOOLEAN */
14290 offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
14291 break;
14292 case 1: /* Unsigned OPTIONAL */
14293 offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
14294 break;
14295 default:
14296 return offset;
14298 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14300 return offset;
14303 static unsigned
14304 fConfirmedAuditNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14306 unsigned lastoffset = 0;
14307 unsigned firstloop = 1;
14308 uint8_t tag_no, tag_info;
14309 uint32_t lvt;
14311 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14312 lastoffset = offset;
14313 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14314 if (tag_is_closing(tag_info)) {
14315 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14316 break;
14319 if (tag_is_opening(tag_info) && firstloop) {
14320 firstloop = 0;
14321 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14324 offset = fAuditNotificationInfo(tvb, pinfo, tree, offset);
14325 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14327 return offset;
14330 static unsigned
14331 fUnconfirmedAuditNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14333 return fConfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
14336 static unsigned
14337 fAuditLogQueryByTargetParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14339 unsigned lastoffset = 0;
14340 uint8_t tag_no, tag_info;
14341 uint32_t lvt;
14343 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14344 lastoffset = offset;
14345 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14346 if (tag_is_closing(tag_info)) {
14347 break;
14350 switch (tag_no) {
14351 case 0: /* target-device-identifier */
14352 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
14353 break;
14354 case 1: /* target-device-address */
14355 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14356 offset = fAddress(tvb, pinfo, tree, offset);
14357 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14358 break;
14359 case 2: /* target-object-identifier */
14360 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14361 break;
14362 case 3: /* target-property-identifier */
14363 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
14364 break;
14365 case 4: /* target-property-array-index */
14366 offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
14367 break;
14368 case 5: /* target-priority */
14369 offset = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: ");
14370 break;
14371 case 6: /* target-operation */
14372 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
14373 "target-operation: ", BACnetAuditOperation);
14374 break;
14375 case 7: /* successful-action */
14376 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
14377 "target-successful-action: ", BACnetSuccessFilter, 64);
14378 break;
14379 default:
14380 return offset;
14382 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14384 return offset;
14387 static unsigned
14388 fAuditLogQueryBySourceParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14390 unsigned lastoffset = 0;
14391 uint8_t tag_no, tag_info;
14392 uint32_t lvt;
14394 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14395 lastoffset = offset;
14396 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14397 if (tag_is_closing(tag_info)) {
14398 break;
14401 switch (tag_no) {
14402 case 0: /* source-device-identifier */
14403 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
14404 break;
14405 case 1: /* source-device-address */
14406 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14407 offset = fAddress(tvb, pinfo, tree, offset);
14408 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14409 break;
14410 case 2: /* source-object-identifier */
14411 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14412 break;
14413 case 3: /* source-operation */
14414 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
14415 "source-operation: ", BACnetAuditOperation);
14416 break;
14417 case 4: /* successful-action */
14418 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
14419 "source-successful-action: ", BACnetSuccessFilter, 64);
14420 break;
14421 default:
14422 return offset;
14424 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14426 return offset;
14429 static unsigned
14430 fAuditLogQueryParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14432 unsigned lastoffset = 0;
14433 uint8_t tag_no, tag_info;
14434 uint32_t lvt;
14435 proto_tree *subtree = tree;
14437 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14438 lastoffset = offset;
14439 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14440 if (tag_is_closing(tag_info)) {
14441 break;
14444 switch (tag_no) {
14445 case 0: /* query-by-target-parameters */
14446 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "target-parameters: ");
14447 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14448 offset = fAuditLogQueryByTargetParameters(tvb, pinfo, subtree, offset);
14449 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14450 break;
14451 case 1: /* query-by-source-parameters */
14452 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "source-parameters: ");
14453 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14454 offset = fAuditLogQueryBySourceParameters(tvb, pinfo, subtree, offset);
14455 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14456 break;
14457 default:
14458 return offset;
14460 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14462 return offset;
14465 static unsigned
14466 fAuditLogQueryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14468 unsigned lastoffset = 0;
14469 uint8_t tag_no, tag_info;
14470 uint32_t lvt;
14471 proto_tree *subtree = tree;
14473 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14474 lastoffset = offset;
14475 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14477 switch (tag_no) {
14478 case 0: /* audit-log */
14479 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14480 break;
14481 case 1: /* query-parameters */
14482 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "query-parameters: ");
14483 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14484 offset = fAuditLogQueryParameters(tvb, pinfo, subtree, offset);
14485 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14486 break;
14487 case 2: /* start-at-sequence-number */
14488 offset = fUnsignedTag(tvb, pinfo, tree, offset, "start-at-sequence-number: ");
14489 break;
14490 case 3: /* requested-count */
14491 offset = fUnsignedTag(tvb, pinfo, tree, offset, "requested-count: ");
14492 break;
14493 default:
14494 return offset;
14496 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14498 return offset;
14501 static unsigned
14502 fAuditLogRecordResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14504 unsigned lastoffset = 0;
14505 uint8_t tag_no, tag_info;
14506 uint32_t lvt;
14507 proto_tree *subtree = tree;
14509 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14510 lastoffset = offset;
14511 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14512 if (tag_is_closing(tag_info)) {
14513 break;
14516 switch (tag_no) {
14517 case 0 : /* sequence-number */
14518 offset = fUnsignedTag(tvb, pinfo, tree, offset, "sequence-number: ");
14519 break;
14520 case 1: /* log-record */
14521 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "log-record: ");
14522 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14523 offset = fAuditLogRecord(tvb, pinfo, subtree, offset);
14524 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14525 break;
14526 default:
14527 return offset;
14529 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14531 return offset;
14534 static unsigned
14535 fAuditLogQueryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14537 unsigned lastoffset = 0;
14538 uint8_t tag_no, tag_info;
14539 uint32_t lvt;
14540 proto_tree *subtree = tree;
14542 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14543 lastoffset = offset;
14544 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14546 switch (tag_no) {
14547 case 0: /* audit-log */
14548 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14549 break;
14550 case 1: /* records */
14551 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "records: ");
14552 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14553 offset = fAuditLogRecordResult(tvb, pinfo, subtree, offset);
14554 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14555 break;
14556 case 2: /* no-more-items */
14557 offset = fBooleanTag(tvb, pinfo, tree, offset, "no-more-items: ");
14558 break;
14559 default:
14560 return offset;
14562 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14564 return offset;
14567 static unsigned
14568 fWhoAmIRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14570 unsigned lastoffset = 0;
14572 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14573 lastoffset = offset;
14574 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: ");
14575 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: ");
14576 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: ");
14577 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14579 return offset;
14582 static unsigned
14583 fYouAreRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14585 unsigned lastoffset = 0;
14586 uint8_t tag_no, tag_info;
14587 uint32_t lvt;
14589 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14590 lastoffset = offset;
14591 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: ");
14592 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: ");
14593 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: ");
14595 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14596 if(tvb_reported_length_remaining(tvb, offset) > 0 && tag_no == 12) {
14597 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
14600 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14601 if(tvb_reported_length_remaining(tvb, offset) > 0 && tag_no == 6) {
14602 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device MAC address: ");
14604 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14606 return offset;
14609 static unsigned
14610 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14612 unsigned lastoffset = 0;
14614 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14615 lastoffset = offset;
14617 switch (fTagNo(tvb, offset)) {
14618 case 0: /* Unsigned32 */
14619 offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
14620 break;
14621 case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
14622 proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
14623 break;
14624 case 2: /* Character String OPTIONAL */
14625 offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
14626 break;
14627 case 3: /* Character String OPTIONAL */
14628 offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
14629 break;
14630 case 4: /* Boolean OPTIONAL */
14631 offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
14632 break;
14633 default:
14634 return offset;
14636 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14638 return offset;
14641 static unsigned
14642 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14644 return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
14647 static unsigned
14648 fAuthenticationFactor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14650 unsigned lastoffset = 0;
14651 uint8_t tag_no, tag_info;
14652 uint32_t lvt;
14654 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14655 lastoffset = offset;
14656 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14657 /* quit loop if we spot a closing tag */
14658 if (tag_is_closing(tag_info)) {
14659 break;
14662 switch (tag_no) {
14663 case 0: /* format-type */
14664 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "format-type: ", NULL);
14665 break;
14666 case 1: /* format-class */
14667 offset = fUnsignedTag(tvb, pinfo, tree, offset, "format-class: ");
14668 break;
14669 case 2: /* value */
14670 offset = fOctetString(tvb, pinfo, tree, offset, "value: ", lvt);
14671 break;
14672 default:
14673 break;
14676 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14679 return offset;
14682 static unsigned
14683 fAuthenticationFactorFormat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14685 unsigned lastoffset = 0;
14686 uint8_t tag_no, tag_info;
14687 uint32_t lvt;
14689 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14690 lastoffset = offset;
14691 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14692 /* quit loop if we spot a closing tag */
14693 if (tag_is_closing(tag_info)) {
14694 break;
14697 switch (tag_no) {
14698 case 0: /* format-type */
14699 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "format-type: ", NULL);
14700 break;
14701 case 1: /* vendor-id */
14702 offset = fUnsignedTag(tvb, pinfo, tree, offset, "vendor-id: ");
14703 break;
14704 case 2: /* vendor-format */
14705 offset = fUnsignedTag(tvb, pinfo, tree, offset, "vendor-format: ");
14706 break;
14707 default:
14708 break;
14711 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14714 return offset;
14717 static unsigned
14718 fAuthenticationPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14720 unsigned lastoffset = 0;
14721 uint8_t tag_no, tag_info;
14722 uint32_t lvt;
14724 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14725 lastoffset = offset;
14726 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14727 /* quit loop if we spot a closing tag */
14728 if (tag_is_closing(tag_info)) {
14729 break;
14732 switch (tag_no) {
14733 case 0: /* policy */
14734 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14735 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14736 lastoffset = offset;
14737 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14738 /* quit loop if we spot a closing tag */
14739 if (tag_is_closing(tag_info)) {
14740 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14741 break;
14744 switch (tag_no) {
14745 case 0: /* credential-data-input */
14746 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14747 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
14748 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14749 break;
14750 case 1: /* index */
14751 offset = fUnsignedTag(tvb, pinfo, tree, offset, "index: ");
14752 break;
14753 default:
14754 break;
14757 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14759 break;
14760 case 1: /* order-enforced */
14761 offset = fBooleanTag(tvb, pinfo, tree, offset, "order-enforced: ");
14762 break;
14763 case 2: /* timeout */
14764 offset = fUnsignedTag(tvb, pinfo, tree, offset, "timeout: ");
14765 break;
14766 default:
14767 break;
14770 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14773 return offset;
14776 static unsigned
14777 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14779 uint8_t tag_no, tag_info;
14780 uint32_t lvt;
14782 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: "); /* Requesting Device Identifier */
14783 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14784 offset = fAddress(tvb, pinfo, tree, offset);
14785 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14786 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: "); /* Remote Device Identifier */
14787 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14788 offset = fAddress(tvb, pinfo, tree, offset);
14789 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
14790 return offset;
14793 static unsigned
14794 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14796 /* Same as AddListElement request after service choice */
14797 return fAddListElementRequest(tvb, pinfo, tree, offset);
14800 static unsigned
14801 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14803 return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
14806 static unsigned
14807 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14809 unsigned lastoffset = 0, len;
14810 uint8_t tag_no, tag_info;
14811 uint32_t lvt;
14812 proto_tree *subtree = tree;
14814 /* set the optional global properties to indicate not-used */
14815 propertyArrayIndex = -1;
14816 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14817 lastoffset = offset;
14818 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14819 if (tag_is_closing(tag_info)) {
14820 offset += len;
14821 subtree = tree;
14822 continue;
14824 switch (tag_no) {
14825 case 0: /* objectIdentifier */
14826 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
14827 break;
14828 case 1: /* propertyIdentifier */
14829 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14830 break;
14831 case 2: /* propertyArrayIndex */
14832 offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
14833 break;
14834 case 3: /* propertyValue */
14835 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14836 break;
14837 default:
14838 break;
14840 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14842 return offset;
14845 static unsigned
14846 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14848 unsigned lastoffset = 0;
14849 uint8_t tag_no, tag_info;
14850 uint32_t lvt;
14851 proto_tree *subtree = tree;
14853 /* set the optional global properties to indicate not-used */
14854 propertyArrayIndex = -1;
14855 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14856 lastoffset = offset;
14857 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14858 /* quit loop if we spot a closing tag */
14859 if (tag_is_closing(tag_info)) {
14860 break;
14863 switch (tag_no) {
14864 case 0: /* objectIdentifier */
14865 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
14866 break;
14867 case 1: /* propertyIdentifier */
14868 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
14869 break;
14870 case 2: /* propertyArrayIndex */
14871 offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
14872 break;
14873 case 3: /* propertyValue */
14874 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
14875 break;
14876 case 4: /* Priority (only used for write) */
14877 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
14878 break;
14879 default:
14880 return offset;
14882 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14884 return offset;
14887 static unsigned
14888 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
14890 unsigned lastoffset = 0, len;
14891 uint8_t tag_no, tag_info;
14892 uint32_t lvt;
14894 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14895 lastoffset = offset;
14896 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14897 /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
14898 if (tag_is_closing(tag_info)) {
14899 offset += len;
14900 continue;
14903 switch (tag_no) {
14904 case 0: /* objectIdentifier */
14905 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
14906 break;
14907 case 1: /* listOfPropertyValues */
14908 if (tag_is_opening(tag_info)) {
14909 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
14910 offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
14911 } else {
14912 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
14914 break;
14915 default:
14916 return offset;
14918 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14920 return offset;
14923 static unsigned
14924 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14926 if (offset >= tvb_reported_length(tvb))
14927 return offset;
14929 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14930 return fWriteAccessSpecification(tvb, pinfo, tree, offset);
14933 static unsigned
14934 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t tagoffset, uint8_t list)
14936 unsigned lastoffset = 0;
14937 uint8_t tag_no, tag_info;
14938 uint32_t lvt;
14940 /* set the optional global properties to indicate not-used */
14941 propertyArrayIndex = -1;
14942 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14943 lastoffset = offset;
14944 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
14945 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
14946 return offset;
14947 } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
14948 return offset;
14950 switch (tag_no-tagoffset) {
14951 case 0: /* PropertyIdentifier */
14952 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
14953 break;
14954 case 1: /* propertyArrayIndex */
14955 offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
14956 if (list != 0)
14957 break; /* Continue decoding if this may be a list */
14958 /* FALLTHROUGH */
14959 default:
14960 lastoffset = offset; /* Set loop end condition */
14961 break;
14963 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14965 return offset;
14968 static unsigned
14969 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, uint8_t list)
14971 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14972 return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
14975 static unsigned
14976 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
14978 unsigned lastoffset = 0;
14980 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
14981 lastoffset = offset;
14983 switch (fTagNo(tvb, offset)) {
14984 case 0: /* ObjectIdentifier */
14985 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
14986 break;
14987 case 1: /* PropertyIdentifier and propertyArrayIndex */
14988 offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
14989 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
14990 /* FALLTHROUGH */
14991 default:
14992 lastoffset = offset; /* Set loop end condition */
14993 break;
14995 if (offset <= lastoffset) break; /* nothing happened, exit loop */
14997 return offset;
15000 #if 0
15001 static unsigned
15002 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, unsigned offset)
15004 unsigned lastoffset = 0;
15005 uint8_t tag_no, tag_info;
15006 uint32_t lvt;
15007 proto_tree* subtree = tree;
15008 proto_item* tt;
15010 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
15011 lastoffset = offset;
15012 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15013 if (tag_is_closing(tag_info)) {
15014 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
15015 &tag_no, &tag_info, &lvt);
15016 continue;
15018 switch (tag_no) {
15019 case 0: /* ObjectIdentifier */
15020 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
15021 break;
15022 case 1: /* PropertyIdentifier */
15023 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
15024 break;
15025 case 2: /* propertyArrayIndex */
15026 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
15027 break;
15028 case 3: /* Value */
15029 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
15030 break;
15031 case 4: /* Priority */
15032 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
15033 break;
15034 default:
15035 break;
15038 return offset;
15040 #endif
15042 static unsigned
15043 // NOLINTNEXTLINE(misc-no-recursion)
15044 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15046 char i = 1, ar[256];
15047 unsigned lastoffset = 0;
15048 uint8_t tag_no;
15049 uint8_t tag_info;
15050 uint32_t lvt;
15052 if (propertyArrayIndex > 0) {
15053 /* BACnetARRAY index 0 refers to the length
15054 of the array, not the elements of the array.
15055 BACnetARRAY index -1 is our internal flag that
15056 the optional index was not used.
15057 BACnetARRAY refers to this as all elements of the array.
15058 If the optional index is specified for a BACnetARRAY,
15059 then that specific array element is referenced. */
15060 i = propertyArrayIndex;
15062 while (tvb_reported_length_remaining(tvb, offset) > 0) {
15063 /* exit loop if nothing happens inside */
15064 lastoffset = offset;
15065 snprintf(ar, sizeof(ar), "%s[%d]: ",
15066 val_to_split_str(87 , 512,
15067 BACnetPropertyIdentifier,
15068 ASHRAE_Reserved_Fmt,
15069 Vendor_Proprietary_Fmt),
15070 i++);
15071 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15072 if ( ! tag_is_context_specific(tag_info)) {
15073 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
15074 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
15075 } else {
15076 if (tag_is_opening(tag_info) && tag_no == 0) {
15077 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15078 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
15079 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15080 } else if (tag_is_opening(tag_info) && tag_no == 1) {
15081 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15082 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
15083 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
15084 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15085 } else if (tag_is_opening(tag_info) && tag_no == 2) {
15086 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15087 offset = fXyColor(tvb, pinfo, tree, offset, "xy-color: ");
15088 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15089 } else {
15090 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
15091 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
15094 /* there are only 16 priority array elements */
15095 if (i > 16) {
15096 break;
15098 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15101 return offset;
15104 static unsigned
15105 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15107 uint8_t tag_no, tag_info;
15108 uint32_t lvt;
15109 unsigned lastoffset = 0;
15111 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15112 lastoffset = offset;
15113 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15114 /* quit loop if we spot an un-matched closing tag */
15115 if (tag_is_closing(tag_info)) {
15116 break;
15118 switch (tag_no) {
15119 case 0: /* deviceIdentifier - OPTIONAL */
15120 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: ");
15121 break;
15122 case 1: /* ObjectIdentifier */
15123 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
15124 break;
15125 default:
15126 return offset;
15128 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15130 return offset;
15133 static unsigned
15134 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15136 uint8_t tag_no, tag_info;
15137 uint32_t lvt;
15138 unsigned lastoffset = 0;
15140 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15141 lastoffset = offset;
15142 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15143 /* quit loop if we spot an un-matched closing tag */
15144 if (tag_is_closing(tag_info)) {
15145 break;
15147 switch (tag_no) {
15148 case 0: /* calendarEntry */
15149 if (tag_is_opening(tag_info)) {
15150 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15151 offset = fCalendarEntry(tvb, pinfo, subtree, offset);
15152 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15154 break;
15155 case 1: /* calendarReference */
15156 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
15157 break;
15158 case 2: /* list of BACnetTimeValue */
15159 if (tag_is_opening(tag_info)) {
15160 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15161 offset = fTimeValue(tvb, pinfo, subtree, offset);
15162 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15163 } else {
15164 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15166 break;
15167 case 3: /* eventPriority */
15168 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
15169 break;
15170 default:
15171 return offset;
15173 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15175 return offset;
15178 static unsigned
15179 fNetworkSecurityPolicy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15181 unsigned lastoffset = 0;
15182 uint8_t tag_no, tag_info;
15183 uint32_t lvt;
15184 proto_tree *subtree;
15186 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "network security policy");
15188 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
15189 lastoffset = offset;
15190 /* check the tag. A closing tag means we are done */
15191 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15192 if (tag_is_closing(tag_info)) {
15193 return offset;
15195 switch (tag_no) {
15196 case 0: /* port-id */
15197 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "port-id: ");
15198 break;
15199 case 1: /* security-level */
15200 offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
15201 "security-level: ", BACnetSecurityPolicy);
15202 break;
15203 default:
15204 return offset;
15208 return offset;
15211 static unsigned
15212 fKeyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15214 unsigned lastoffset = 0;
15215 uint8_t tag_no, tag_info;
15216 uint32_t lvt;
15218 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
15219 lastoffset = offset;
15220 /* check the tag. A closing tag means we are done */
15221 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15222 if (tag_is_closing(tag_info)) {
15223 return offset;
15225 switch (tag_no) {
15226 case 0: /* algorithm */
15227 offset = fUnsignedTag(tvb, pinfo, tree, offset, "algorithm: ");
15228 break;
15229 case 1: /* key-id */
15230 offset = fUnsignedTag(tvb, pinfo, tree, offset, "key-id: ");
15231 break;
15232 default:
15233 return offset;
15237 return offset;
15240 static unsigned
15241 fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15243 unsigned lastoffset = 0;
15244 uint8_t tag_no, tag_info;
15245 uint32_t lvt;
15246 proto_tree *subtree;
15248 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "security keyset");
15250 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset > lastoffset) {
15251 lastoffset = offset;
15252 /* check the tag. A closing tag means we are done */
15253 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15254 if (tag_is_closing(tag_info)) {
15255 return offset;
15257 switch (tag_no) {
15258 case 0: /* key-revision */
15259 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "key-revision: ");
15260 break;
15261 case 1: /* activation-time */
15262 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15263 offset = fDateTime(tvb, pinfo, subtree, offset, "activation-time: ");
15264 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15265 break;
15266 case 2: /* expiration-time */
15267 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15268 offset = fDateTime(tvb, pinfo, subtree, offset, "expiration-time: ");
15269 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15270 break;
15271 case 3: /* key-ids */
15272 if (tag_is_opening(tag_info)) {
15273 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15274 offset = fKeyIdentifier(tvb, pinfo, subtree, offset);
15275 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15276 } else {
15277 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15279 break;
15280 default:
15281 return offset;
15285 return offset;
15288 static unsigned
15289 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15291 unsigned lastoffset = 0;
15292 uint8_t tag_no, tag_info;
15293 uint32_t lvt;
15295 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15296 lastoffset = offset;
15297 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15298 /* quit loop if we spot a closing tag */
15299 if (tag_is_closing(tag_info)) {
15300 break;
15303 switch (fTagNo(tvb, offset)) {
15304 case 0: /* propertyIdentifier */
15305 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
15306 break;
15307 case 1: /* propertyArrayIndex */
15308 offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
15309 break;
15310 case 2: /* relationSpecifier */
15311 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
15312 "relation Specifier: ", BACnetRelationSpecifier);
15313 break;
15314 case 3: /* comparisonValue */
15315 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15316 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
15317 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15318 break;
15319 default:
15320 return offset;
15322 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15324 return offset;
15327 static unsigned
15328 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15330 unsigned lastoffset = 0;
15331 uint8_t tag_no, tag_info;
15332 uint32_t lvt;
15334 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15335 lastoffset = offset;
15336 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15337 /* quit loop if we spot a closing tag */
15338 if (tag_is_closing(tag_info)) {
15339 break;
15342 switch (tag_no) {
15343 case 0: /* selectionLogic */
15344 offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
15345 "selection Logic: ", BACnetSelectionLogic);
15346 break;
15347 case 1: /* listOfSelectionCriteria */
15348 if (tag_is_opening(tag_info)) {
15349 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15350 offset = fSelectionCriteria(tvb, pinfo, subtree, offset);
15351 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15352 } else {
15353 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15355 break;
15356 default:
15357 return offset;
15359 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15361 return offset;
15365 static unsigned
15366 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, unsigned offset)
15368 unsigned lastoffset = 0;
15369 uint8_t tag_no, tag_info;
15370 uint32_t lvt;
15372 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15373 lastoffset = offset;
15374 fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15376 if (tag_is_opening(tag_info) && tag_no < 2) {
15377 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15378 switch (tag_no) {
15379 case 0: /* objectSelectionCriteria */
15380 offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
15381 break;
15382 case 1: /* listOfPropertyReferences */
15383 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
15384 break;
15385 default:
15386 return offset;
15388 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15390 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15392 return offset;
15395 static unsigned
15396 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15398 unsigned lastoffset = 0;
15399 uint8_t tag_no, tag_info;
15400 uint32_t lvt;
15401 proto_tree *subtree = tree;
15403 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15404 lastoffset = offset;
15405 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15406 switch (tag_no) {
15407 case 0: /* objectIdentifier */
15408 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
15409 break;
15410 case 1: /* listOfPropertyReferences */
15411 if (tag_is_opening(tag_info)) {
15412 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfPropertyReferences");
15413 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15414 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
15415 } else if (tag_is_closing(tag_info)) {
15416 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
15417 &tag_no, &tag_info, &lvt);
15418 subtree = tree;
15419 } else {
15420 /* error condition: let caller handle */
15421 return offset;
15423 break;
15424 default:
15425 return offset;
15427 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15429 return offset;
15432 static unsigned
15433 // NOLINTNEXTLINE(misc-no-recursion)
15434 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15436 unsigned lastoffset = 0, len;
15437 uint8_t tag_no;
15438 uint8_t tag_info;
15439 uint32_t lvt;
15440 proto_tree *subtree = tree;
15442 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15443 lastoffset = offset;
15444 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15445 /* maybe a listOfReadAccessResults if we spot a closing tag here */
15446 if (tag_is_closing(tag_info)) {
15447 offset += len;
15448 if ((tag_no == 4 || tag_no == 5) && (subtree != tree))
15449 subtree = subtree->parent; /* Value and error have extra subtree */
15451 if (tag_no == 1) {
15452 /* closing list of results for this objectSpecifier */
15453 fTagHeaderTree(tvb, pinfo, subtree, offset - len, &tag_no, &tag_info, &lvt);
15454 /* look if another objectSpecifier follows here */
15455 if (tvb_reported_length_remaining(tvb, offset) <= 0)
15456 return offset; /* nothing more to decode left */
15458 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15459 if (tag_no != 0 || tag_info != 12)
15460 return offset; /* no objectSpecifier */
15463 continue;
15466 switch (tag_no) {
15467 case 0: /* objectSpecifier */
15468 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
15469 break;
15470 case 1: /* list of Results */
15471 if (tag_is_opening(tag_info)) {
15472 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfResults");
15473 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15474 } else {
15475 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15477 break;
15478 case 2: /* propertyIdentifier */
15479 offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
15480 break;
15481 case 5: /* propertyAccessError */
15482 if (tag_is_opening(tag_info)) {
15483 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "propertyAccessError");
15484 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15485 /* Error Code follows */
15486 offset = fError(tvb, pinfo, subtree, offset);
15487 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15489 else {
15490 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15492 break;
15493 default:
15494 return offset;
15496 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15498 return offset;
15502 static unsigned
15503 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15505 /* listOfReadAccessResults */
15506 return fReadAccessResult(tvb, pinfo, tree, offset);
15510 static unsigned
15511 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15513 unsigned lastoffset = 0;
15514 uint8_t tag_no, tag_info;
15515 uint32_t lvt;
15517 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15518 lastoffset = offset;
15519 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15521 if (tag_no < 2) {
15522 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15523 switch (tag_no) {
15524 case 0: /* objectSpecifier */
15525 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
15526 case 0: /* objectType */
15527 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
15528 break;
15529 case 1: /* objectIdentifier */
15530 offset = fObjectIdentifier(tvb, pinfo, subtree, offset, "ObjectIdentifier: ");
15531 break;
15532 default:
15533 break;
15535 break;
15536 case 1: /* propertyValue */
15537 if (tag_is_opening(tag_info)) {
15538 offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
15539 } else {
15540 expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
15542 break;
15543 default:
15544 break;
15546 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15548 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15550 return offset;
15553 static unsigned
15554 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15556 return fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
15559 static unsigned
15560 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15562 uint8_t tag_no, tag_info;
15563 uint32_t lvt;
15564 proto_tree *subtree = tree;
15566 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
15568 if (tvb_reported_length_remaining(tvb, offset) > 0) {
15569 /* optional range choice */
15570 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15571 if (tag_is_opening(tag_info)) {
15572 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
15573 val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
15574 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15575 switch (tag_no) {
15576 case 3: /* range byPosition */
15577 case 6: /* range bySequenceNumber, 2004 spec */
15578 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
15579 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
15580 break;
15581 case 4: /* range byTime - deprecated in 2004 */
15582 case 7: /* 2004 spec */
15583 offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
15584 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
15585 break;
15586 case 5: /* range timeRange - deprecated in 2004 */
15587 offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
15588 offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
15589 break;
15590 default:
15591 break;
15593 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15596 return offset;
15599 static unsigned
15600 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15602 uint8_t tag_no, tag_info;
15603 uint32_t lvt;
15604 proto_tree *subtree = tree;
15606 /* set the optional global properties to indicate not-used */
15607 propertyArrayIndex = -1;
15608 /* objectIdentifier, propertyIdentifier, and
15609 OPTIONAL propertyArrayIndex */
15610 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
15611 /* resultFlags => BACnetResultFlags ::= BIT STRING */
15612 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
15613 "resultFlags: ",
15614 BACnetResultFlags);
15615 /* itemCount */
15616 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
15617 /* itemData */
15618 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15619 if (tag_is_opening(tag_info)) {
15620 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15621 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "itemData");
15622 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15623 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
15624 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15626 /* firstSequenceNumber - OPTIONAL */
15627 if (tvb_reported_length_remaining(tvb, offset) > 0) {
15628 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
15631 return offset;
15634 static unsigned
15635 fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15637 unsigned lastoffset = 0;
15638 uint32_t lvt;
15639 uint8_t tag_no, tag_info;
15640 proto_tree* subtree = NULL;
15642 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15644 if (tag_is_opening(tag_info)) {
15645 subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL,
15646 val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
15647 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15648 offset = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
15649 offset = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
15651 if (tag_no == 1) {
15652 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
15653 /* exit loop if nothing happens inside */
15654 lastoffset = offset;
15655 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
15659 if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
15660 /* More Flag is not set, so we can look for closing tag in this segment */
15661 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15662 if (tag_is_closing(tag_info)) {
15663 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15667 return offset;
15670 static unsigned
15671 fAccessRule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15673 unsigned lastoffset = 0;
15674 uint8_t tag_no, tag_info;
15675 uint32_t lvt;
15677 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15678 lastoffset = offset;
15679 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15680 /* quit loop if we spot a closing tag */
15681 if (tag_is_closing(tag_info)) {
15682 break;
15685 switch (tag_no) {
15686 case 0: /* time-range-specifier */
15687 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "time-range-specifier: ", NULL);
15688 break;
15689 case 1: /* time-range */
15690 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15691 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
15692 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15693 break;
15694 case 2: /* location-specifier */
15695 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "location-specifier: ", NULL);
15696 break;
15697 case 3: /* location */
15698 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15699 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
15700 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
15701 break;
15702 case 4: /* enable */
15703 offset = fBooleanTag(tvb, pinfo, tree, offset, "enable: ");
15704 break;
15705 default:
15706 break;
15709 if (offset <= lastoffset) break; /* nothing happened, exit loop */
15712 return offset;
15715 static unsigned
15716 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15718 uint8_t tag_no, tag_info;
15719 uint32_t lvt;
15720 proto_tree *subtree = tree;
15722 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: ");
15724 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15726 if (tag_is_opening(tag_info)) {
15727 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
15728 val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
15729 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15730 offset = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
15731 offset = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BacnetFileRequestedCount, "unknown option"));
15732 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
15734 return offset;
15737 static unsigned
15738 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15741 offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: "); /* file Identifier */
15742 offset = fAccessMethod(tvb, pinfo, tree, offset);
15744 return offset;
15747 static unsigned
15748 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15750 unsigned tag_no = fTagNo(tvb, offset);
15751 return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
15754 static unsigned
15755 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15757 offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
15758 offset = fAccessMethod(tvb, pinfo, tree, offset);
15760 return offset;
15763 static unsigned
15764 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, unsigned offset)
15766 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15767 return fReadAccessSpecification(tvb, pinfo, subtree, offset);
15770 static unsigned
15771 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15773 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
15774 return fReadAccessResult(tvb, pinfo, tree, offset);
15777 static unsigned
15778 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15780 if (tvb_reported_length_remaining(tvb, offset) <= 0)
15781 return offset;
15783 switch (service_choice) {
15784 case 0: /* acknowledgeAlarm */
15785 offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
15786 break;
15787 case 1: /* confirmedCOVNotification */
15788 offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
15789 break;
15790 case 2: /* confirmedEventNotification */
15791 offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
15792 break;
15793 case 3: /* confirmedGetAlarmSummary conveys no parameters */
15794 break;
15795 case 4: /* getEnrollmentSummaryRequest */
15796 offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
15797 break;
15798 case 5: /* subscribeCOVRequest */
15799 offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
15800 break;
15801 case 6: /* atomicReadFile-Request */
15802 offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
15803 break;
15804 case 7: /* atomicWriteFile-Request */
15805 offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
15806 break;
15807 case 8: /* AddListElement-Request */
15808 offset = fAddListElementRequest(tvb, pinfo, tree, offset);
15809 break;
15810 case 9: /* removeListElement-Request */
15811 offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
15812 break;
15813 case 10: /* createObjectRequest */
15814 offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
15815 break;
15816 case 11: /* deleteObject */
15817 offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
15818 break;
15819 case 12:
15820 offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
15821 break;
15822 case 13:
15823 offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
15824 break;
15825 case 14:
15826 offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
15827 break;
15828 case 15:
15829 offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
15830 break;
15831 case 16:
15832 offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
15833 break;
15834 case 17:
15835 offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
15836 break;
15837 case 18:
15838 offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
15839 break;
15840 case 19:
15841 offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
15842 break;
15843 case 20:
15844 offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
15845 break;
15846 case 21:
15847 offset = fVtOpenRequest(tvb, pinfo, tree, offset);
15848 break;
15849 case 22:
15850 offset = fVtCloseRequest(tvb, pinfo, tree, offset);
15851 break;
15852 case 23:
15853 offset = fVtDataRequest(tvb, pinfo, tree, offset);
15854 break;
15855 case 24:
15856 offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
15857 break;
15858 case 25:
15859 offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
15860 break;
15861 case 26:
15862 offset = fReadRangeRequest(tvb, pinfo, tree, offset);
15863 break;
15864 case 27:
15865 offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
15866 break;
15867 case 28:
15868 offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
15869 break;
15870 case 29:
15871 offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
15872 break;
15873 case 30:
15874 offset = fSubscribeCOVPropertyMultipleRequest(tvb, pinfo, tree, offset);
15875 break;
15876 case 31:
15877 offset = fConfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
15878 break;
15879 case 32:
15880 offset = fConfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
15881 break;
15882 case 33:
15883 offset = fAuditLogQueryRequest(tvb, pinfo, tree, offset);
15884 break;
15885 default:
15886 return offset;
15888 return offset;
15891 static unsigned
15892 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
15894 if (tvb_reported_length_remaining(tvb, offset) <= 0)
15895 return offset;
15897 switch (service_choice) {
15898 case 3: /* confirmedEventNotificationAck */
15899 offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
15900 break;
15901 case 4: /* getEnrollmentSummaryAck */
15902 offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
15903 break;
15904 case 6: /* atomicReadFile */
15905 offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
15906 break;
15907 case 7: /* atomicReadFileAck */
15908 offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
15909 break;
15910 case 10: /* createObject */
15911 offset = fCreateObjectAck(tvb, pinfo, tree, offset);
15912 break;
15913 case 12:
15914 offset = fReadPropertyAck(tvb, pinfo, tree, offset);
15915 break;
15916 case 13:
15917 offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
15918 break;
15919 case 14:
15920 offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
15921 break;
15922 case 18:
15923 offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
15924 break;
15925 case 21:
15926 offset = fVtOpenAck(tvb, pinfo, tree, offset);
15927 break;
15928 case 23:
15929 offset = fVtDataAck(tvb, pinfo, tree, offset);
15930 break;
15931 case 24:
15932 offset = fAuthenticateAck(tvb, pinfo, tree, offset);
15933 break;
15934 case 26:
15935 offset = fReadRangeAck(tvb, pinfo, tree, offset);
15936 break;
15937 case 29:
15938 offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
15939 break;
15940 case 33:
15941 offset = fAuditLogQueryAck(tvb, pinfo, tree, offset);
15942 break;
15943 default:
15944 return offset;
15946 return offset;
15949 static unsigned
15950 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15952 /* BACnetObjectIdentifier */
15953 offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
15955 /* MaxAPDULengthAccepted */
15956 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
15958 /* segmentationSupported */
15959 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
15960 "Segmentation Supported: ", BACnetSegmentation);
15962 /* vendor ID */
15963 return fVendorIdentifier(tvb, pinfo, tree, offset);
15966 static unsigned
15967 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
15969 /* BACnetDeviceIdentifier */
15970 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
15972 /* BACnetObjectIdentifier */
15973 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
15975 /* ObjectName */
15976 return fObjectName(tvb, pinfo, tree, offset);
15979 static unsigned
15980 fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned offset)
15982 unsigned lastoffset = 0;
15983 unsigned val;
15984 uint8_t tag_len;
15986 uint8_t tag_no, tag_info;
15987 uint32_t lvt;
15989 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
15990 lastoffset = offset;
15992 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
15994 switch (tag_no) {
15995 case 0:
15996 /* DeviceInstanceRangeLowLimit Optional */
15997 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
15998 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
15999 offset = fDevice_Instance(tvb, pinfo, tree, offset,
16000 hf_Device_Instance_Range_Low_Limit);
16001 break;
16002 case 1:
16003 /* DeviceInstanceRangeHighLimit Optional but
16004 required if DeviceInstanceRangeLowLimit is there */
16005 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
16006 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
16007 offset = fDevice_Instance(tvb, pinfo, tree, offset,
16008 hf_Device_Instance_Range_High_Limit);
16009 break;
16010 default:
16011 return offset;
16013 if (offset <= lastoffset) break; /* nothing happened, exit loop */
16015 return offset;
16018 static unsigned
16019 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, int service_choice)
16021 if (tvb_reported_length_remaining(tvb, offset) <= 0)
16022 return offset;
16024 switch (service_choice) {
16025 case 0: /* I-Am-Request */
16026 offset = fIAmRequest(tvb, pinfo, tree, offset);
16027 break;
16028 case 1: /* i-Have Request */
16029 offset = fIHaveRequest(tvb, pinfo, tree, offset);
16030 break;
16031 case 2: /* unconfirmedCOVNotification */
16032 offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
16033 break;
16034 case 3: /* unconfirmedEventNotification */
16035 offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
16036 break;
16037 case 4: /* unconfirmedPrivateTransfer */
16038 offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
16039 break;
16040 case 5: /* unconfirmedTextMessage */
16041 offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
16042 break;
16043 case 6: /* timeSynchronization */
16044 offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
16045 break;
16046 case 7: /* who-Has */
16047 offset = fWhoHas(tvb, pinfo, tree, offset);
16048 break;
16049 case 8: /* who-Is */
16050 offset = fWhoIsRequest(tvb, pinfo, tree, offset);
16051 break;
16052 case 9: /* utcTimeSynchronization */
16053 offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
16054 break;
16055 case 10:
16056 offset = fWriteGroupRequest(tvb, pinfo, tree, offset);
16057 break;
16058 case 11:
16059 offset = fUnconfirmedCOVNotificationMultipleRequest(tvb, pinfo, tree, offset);
16060 break;
16061 case 12:
16062 offset = fUnconfirmedAuditNotificationRequest(tvb, pinfo, tree, offset);
16063 break;
16064 case 13:
16065 offset = fWhoAmIRequest(tvb, pinfo, tree, offset);
16066 break;
16067 case 14:
16068 offset = fYouAreRequest(tvb, pinfo, tree, offset);
16069 break;
16070 default:
16071 break;
16073 return offset;
16076 static unsigned
16077 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset, uint8_t ack,
16078 int *svc, proto_item **tt)
16080 proto_item *tc;
16081 proto_tree *bacapp_tree_control;
16082 int tmp;
16083 unsigned extra = 2;
16085 bacapp_seq = 0;
16086 tmp = tvb_get_int8(tvb, offset);
16087 bacapp_flags = tmp & 0x0f;
16089 if (ack == 0) {
16090 extra = 3;
16092 *svc = tvb_get_int8(tvb, offset+extra);
16093 if (bacapp_flags & 0x08)
16094 *svc = tvb_get_int8(tvb, offset+extra+2);
16096 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
16097 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
16098 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
16100 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
16101 proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
16102 if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
16103 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
16104 proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
16105 offset, 1, ENC_BIG_ENDIAN);
16106 proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
16107 offset, 1, ENC_BIG_ENDIAN);
16109 offset++;
16110 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
16111 if (bacapp_flags & 0x08) {
16112 bacapp_seq = tvb_get_uint8(tvb, offset);
16113 proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
16114 offset++, 1, ENC_BIG_ENDIAN);
16115 proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
16116 offset++, 1, ENC_BIG_ENDIAN);
16118 *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
16119 offset++, 1, ENC_BIG_ENDIAN);
16120 return offset;
16123 static unsigned
16124 fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset, int svc)
16125 { /* BACnet-Confirmed-Request */
16126 /* ASHRAE 135-2001 20.1.2 */
16128 return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
16131 static unsigned
16132 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
16133 { /* BACnet-Confirmed-Request */
16134 /* ASHRAE 135-2001 20.1.2 */
16135 int svc;
16136 proto_item *tt = 0;
16138 offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
16139 return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
16142 static unsigned
16143 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
16144 { /* BACnet-Unconfirmed-Request-PDU */
16145 /* ASHRAE 135-2001 20.1.3 */
16147 int tmp;
16149 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16151 tmp = tvb_get_uint8(tvb, offset);
16152 proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
16153 offset++, 1, ENC_BIG_ENDIAN);
16154 /* Service Request follows... Variable Encoding 20.2ff */
16155 return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
16158 static unsigned
16159 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16160 { /* BACnet-Simple-Ack-PDU */
16161 /* ASHRAE 135-2001 20.1.4 */
16163 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16165 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
16166 offset++, 1, ENC_BIG_ENDIAN);
16167 proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
16168 offset++, 1, ENC_BIG_ENDIAN);
16170 return offset;
16173 static unsigned
16174 fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset, int svc)
16175 { /* BACnet-Complex-Ack-PDU */
16176 /* ASHRAE 135-2001 20.1.5 */
16178 /* Service ACK follows... */
16179 return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
16182 static unsigned
16183 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
16184 { /* BACnet-Complex-Ack-PDU */
16185 /* ASHRAE 135-2001 20.1.5 */
16186 int svc;
16187 proto_item *tt = 0;
16189 offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
16190 return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
16193 static unsigned
16194 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16195 { /* BACnet-SegmentAck-PDU */
16196 /* ASHRAE 135-2001 20.1.6 */
16198 proto_item *tc;
16199 proto_tree *bacapp_tree_control;
16201 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
16202 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16204 proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
16205 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
16206 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16207 offset++, 1, ENC_BIG_ENDIAN);
16208 proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
16209 offset++, 1, ENC_BIG_ENDIAN);
16210 proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
16211 offset++, 1, ENC_BIG_ENDIAN);
16212 return offset;
16215 static unsigned
16216 fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16218 uint8_t tag_info = 0;
16219 uint8_t parsed_tag = 0;
16220 uint32_t lvt = 0;
16222 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
16223 offset = fError(tvb, pinfo, tree, offset);
16224 return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
16227 static unsigned
16228 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16230 unsigned lastoffset = 0;
16231 uint8_t tag_no = 0, tag_info = 0;
16232 uint32_t lvt = 0;
16233 proto_tree *subtree = tree;
16235 unsigned vendor_identifier = 0;
16236 unsigned service_number = 0;
16237 uint8_t tag_len = 0;
16239 while (tvb_reported_length_remaining(tvb, offset) > 0) {
16240 /* exit loop if nothing happens inside */
16241 lastoffset = offset;
16242 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
16243 switch (tag_no) {
16244 case 0: /* errorType */
16245 offset = fContextTaggedError(tvb, pinfo, subtree, offset);
16246 break;
16247 case 1: /* vendorID */
16248 fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
16249 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
16250 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
16251 break;
16252 case 2: /* serviceNumber */
16253 fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
16254 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ", service_number);
16255 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
16256 break;
16257 case 3: /* errorParameters */
16258 if (tag_is_opening(tag_info)) {
16259 subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
16260 ett_bacapp_value, NULL, "error Parameters");
16261 propertyIdentifier = -1;
16262 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
16263 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
16264 } else if (tag_is_closing(tag_info)) {
16265 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
16266 &tag_no, &tag_info, &lvt);
16267 subtree = tree;
16268 } else {
16269 /* error condition: let caller handle */
16270 return offset;
16272 break;
16273 default:
16274 return offset;
16276 if (offset <= lastoffset) break; /* nothing happened, exit loop */
16278 return offset;
16281 static unsigned
16282 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16284 unsigned lastoffset = 0;
16286 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
16287 lastoffset = offset;
16288 switch (fTagNo(tvb, offset)) {
16289 case 0: /* errorType */
16290 offset = fContextTaggedError(tvb, pinfo, tree, offset);
16291 break;
16292 case 1: /* firstFailedElementNumber */
16293 offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
16294 break;
16295 default:
16296 return offset;
16298 if (offset <= lastoffset) break; /* nothing happened, exit loop */
16300 return offset;
16303 static unsigned
16304 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16306 /* Identical to CreateObjectError */
16307 return fCreateObjectError(tvb, pinfo, tree, offset);
16310 static unsigned
16311 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16313 uint8_t tag_no = 0, tag_info = 0;
16314 uint32_t lvt = 0;
16316 if (fTagNo(tvb, offset) == 0) {
16317 /* errorType */
16318 offset = fContextTaggedError(tvb, pinfo, tree, offset);
16319 if (fTagNo(tvb, offset) == 1) {
16320 /* listOfVTSessionIdentifiers [OPTIONAL] */
16321 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
16322 offset = fVtCloseRequest(tvb, pinfo, tree, offset);
16323 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
16326 /* should report bad packet if initial tag wasn't 0 */
16327 return offset;
16330 static unsigned
16331 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16333 unsigned lastoffset = 0;
16334 uint8_t tag_no = 0, tag_info = 0;
16335 uint32_t lvt = 0;
16337 col_set_writable(pinfo->cinfo, COL_INFO, false); /* don't set all infos into INFO column */
16338 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
16339 lastoffset = offset;
16340 switch (fTagNo(tvb, offset)) {
16341 case 0: /* errorType */
16342 offset = fContextTaggedError(tvb, pinfo, tree, offset);
16343 break;
16344 case 1: /* firstFailedWriteAttempt */
16345 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
16346 offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
16347 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
16348 break;
16349 default:
16350 return offset;
16352 if (offset <= lastoffset) break; /* nothing happened, exit loop */
16354 return offset;
16357 static unsigned
16358 fErrorClass(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16360 uint32_t val = 0, lvt;
16361 uint8_t tag_no, tag_info;
16362 proto_item *ti;
16363 proto_tree *subtree;
16364 unsigned tag_len;
16366 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
16367 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
16369 ti = proto_tree_add_uint(tree, hf_bacapp_error_class,
16370 tvb, offset, lvt+tag_len, val);
16371 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
16373 else
16375 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
16376 ett_bacapp_tag, NULL, "Error Class - %u octets (Signed)", lvt);
16378 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
16379 offset += tag_len + lvt;
16381 return offset;
16384 static unsigned
16385 fErrorCode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16387 uint32_t val = 0, lvt;
16388 uint8_t tag_no, tag_info;
16389 proto_item *ti;
16390 proto_tree *subtree;
16391 unsigned tag_len;
16393 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
16394 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
16396 ti = proto_tree_add_uint(tree, hf_bacapp_error_code,
16397 tvb, offset, lvt+tag_len, val);
16398 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
16400 else
16402 subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
16403 ett_bacapp_tag, NULL, "Error Code - %u octets (Signed)", lvt);
16405 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
16406 offset += tag_len + lvt;
16408 return offset;
16411 static unsigned
16412 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset)
16414 offset = fErrorClass(tvb, pinfo, tree, offset);
16416 return fErrorCode(tvb, pinfo, tree, offset);
16419 static unsigned
16420 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned service)
16422 switch (service) {
16423 case 8:
16424 offset = fChangeListError(tvb, pinfo, tree, offset);
16425 break;
16426 case 9:
16427 offset = fChangeListError(tvb, pinfo, tree, offset);
16428 break;
16429 case 10:
16430 offset = fCreateObjectError(tvb, pinfo, tree, offset);
16431 break;
16432 case 16:
16433 offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
16434 break;
16435 case 18:
16436 offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
16437 break;
16438 case 22:
16439 offset = fVTCloseError(tvb, pinfo, tree, offset);
16440 break;
16441 case 30:
16442 offset = fSubscribeCOVPropertyMultipleError(tvb, pinfo, tree, offset);
16443 break;
16444 default:
16445 offset = fError(tvb, pinfo, tree, offset);
16446 break;
16448 return offset;
16451 static unsigned
16452 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, unsigned offset)
16453 { /* BACnet-Error-PDU */
16454 /* ASHRAE 135-2001 20.1.7 */
16456 proto_item *tc;
16457 proto_tree *bacapp_tree_control;
16458 uint8_t tmp;
16460 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16461 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16463 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16464 offset++, 1, ENC_BIG_ENDIAN);
16465 tmp = tvb_get_uint8(tvb, offset);
16466 proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
16467 offset++, 1, ENC_BIG_ENDIAN);
16468 /* Error Handling follows... */
16469 return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
16472 static unsigned
16473 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16474 { /* BACnet-Reject-PDU */
16475 /* ASHRAE 135-2001 20.1.8 */
16477 proto_item *tc;
16478 proto_tree *bacapp_tree_control;
16480 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
16481 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16483 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16484 offset++, 1, ENC_BIG_ENDIAN);
16485 proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
16486 offset++, 1, ENC_BIG_ENDIAN);
16487 return offset;
16490 static unsigned
16491 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, unsigned offset)
16492 { /* BACnet-Abort-PDU */
16493 /* ASHRAE 135-2001 20.1.9 */
16495 proto_item *tc;
16496 proto_tree *bacapp_tree_control;
16498 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
16499 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
16501 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
16502 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
16503 offset++, 1, ENC_BIG_ENDIAN);
16504 proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
16505 offset++, 1, ENC_BIG_ENDIAN);
16506 return offset;
16509 static unsigned
16510 do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
16512 uint8_t flag, bacapp_type;
16513 unsigned offset = 0;
16515 flag = tvb_get_int8(tvb, 0);
16516 bacapp_type = (flag >> 4) & 0x0f;
16518 if (tvb == NULL) {
16519 return 0;
16522 /* ASHRAE 135-2001 20.1.1 */
16523 switch (bacapp_type) {
16524 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
16525 offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
16526 break;
16527 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: /* BACnet-Unconfirmed-Request-PDU */
16528 offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
16529 break;
16530 case BACAPP_TYPE_SIMPLE_ACK: /* BACnet-Simple-Ack-PDU */
16531 offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
16532 break;
16533 case BACAPP_TYPE_COMPLEX_ACK: /* BACnet-Complex-Ack-PDU */
16534 offset = fComplexAckPDU(tvb, pinfo, tree, offset);
16535 break;
16536 case BACAPP_TYPE_SEGMENT_ACK: /* BACnet-SegmentAck-PDU */
16537 offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
16538 break;
16539 case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
16540 offset = fErrorPDU(tvb, pinfo, tree, offset);
16541 break;
16542 case BACAPP_TYPE_REJECT: /* BACnet-Reject-PDU */
16543 offset = fRejectPDU(tvb, pinfo, tree, offset);
16544 break;
16545 case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
16546 offset = fAbortPDU(tvb, pinfo, tree, offset);
16547 break;
16549 return offset;
16552 static int
16553 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
16555 uint8_t flag, bacapp_type;
16556 unsigned save_fragmented = false, data_offset = 0, /*bacapp_apdu_size,*/ fragment = false;
16557 tvbuff_t *new_tvb = NULL;
16558 unsigned offset = 0;
16559 uint8_t bacapp_seqno = 0;
16560 uint8_t bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
16561 uint8_t bacapp_invoke_id = 0;
16562 proto_item *ti;
16563 proto_tree *bacapp_tree = NULL;
16565 int svc = 0;
16566 proto_item *tt = 0;
16567 int8_t ack = 0;
16569 /* Strings for BACnet Statistics */
16570 static const char errstr[] = "ERROR: ";
16571 static const char rejstr[] = "REJECTED: ";
16572 static const char abortstr[] = "ABORTED: ";
16573 static const char sackstr[] = " (SimpleAck)";
16574 static const char cackstr[] = " (ComplexAck)";
16575 static const char uconfsreqstr[] = " (Unconfirmed Service Request)";
16576 static const char confsreqstr[] = " (Confirmed Service Request)";
16578 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
16579 col_clear(pinfo->cinfo, COL_INFO);
16581 flag = tvb_get_uint8(tvb, 0);
16582 bacapp_type = (flag >> 4) & 0x0f;
16584 /* show some descriptive text in the INFO column */
16585 col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
16586 val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
16588 bacinfo.service_type = NULL;
16589 bacinfo.invoke_id = NULL;
16590 bacinfo.instance_ident = NULL;
16591 bacinfo.object_ident = NULL;
16593 switch (bacapp_type) {
16594 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
16595 /* segmented messages have 2 additional bytes */
16596 if (flag & BACAPP_SEGMENTED_REQUEST) {
16597 fragment = true;
16598 ack = 0;
16599 /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_uint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
16600 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 2);
16601 bacapp_seqno = tvb_get_uint8(tvb, offset + 3);
16602 /* bacapp_prop_win_size = tvb_get_uint8(tvb, offset + 4); */
16603 bacapp_service = tvb_get_uint8(tvb, offset + 5);
16604 data_offset = 6;
16605 } else {
16606 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 2);
16607 bacapp_service = tvb_get_uint8(tvb, offset + 3);
16609 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
16610 val_to_str_const(bacapp_service,
16611 BACnetConfirmedServiceChoice,
16612 bacapp_unknown_service_str),
16613 bacapp_invoke_id);
16615 updateBacnetInfoValue(BACINFO_INVOKEID,
16616 wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16618 updateBacnetInfoValue(BACINFO_SERVICE,
16619 wmem_strconcat(pinfo->pool,
16620 val_to_str_const(bacapp_service,
16621 BACnetConfirmedServiceChoice,
16622 bacapp_unknown_service_str),
16623 confsreqstr, NULL));
16624 break;
16625 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
16626 bacapp_service = tvb_get_uint8(tvb, offset + 1);
16627 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
16628 val_to_str_const(bacapp_service,
16629 BACnetUnconfirmedServiceChoice,
16630 bacapp_unknown_service_str));
16632 updateBacnetInfoValue(BACINFO_SERVICE,
16633 wmem_strconcat(pinfo->pool,
16634 val_to_str_const(bacapp_service,
16635 BACnetUnconfirmedServiceChoice,
16636 bacapp_unknown_service_str),
16637 uconfsreqstr, NULL));
16638 break;
16639 case BACAPP_TYPE_SIMPLE_ACK:
16640 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16641 bacapp_service = tvb_get_uint8(tvb, offset + 2);
16642 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16643 val_to_str_const(bacapp_service,
16644 BACnetConfirmedServiceChoice,
16645 bacapp_unknown_service_str),
16646 bacapp_invoke_id);
16648 updateBacnetInfoValue(BACINFO_INVOKEID,
16649 wmem_strdup_printf(pinfo->pool,
16650 "Invoke ID: %d", bacapp_invoke_id));
16652 updateBacnetInfoValue(BACINFO_SERVICE,
16653 wmem_strconcat(pinfo->pool,
16654 val_to_str_const(bacapp_service,
16655 BACnetConfirmedServiceChoice,
16656 bacapp_unknown_service_str),
16657 sackstr, NULL));
16658 break;
16659 case BACAPP_TYPE_COMPLEX_ACK:
16660 /* segmented messages have 2 additional bytes */
16661 if (flag & BACAPP_SEGMENTED_REQUEST) {
16662 fragment = true;
16663 ack = 1;
16664 /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
16665 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16666 bacapp_seqno = tvb_get_uint8(tvb, offset + 2);
16667 /* bacapp_prop_win_size = tvb_get_uint8(tvb, offset + 3); */
16668 bacapp_service = tvb_get_uint8(tvb, offset + 4);
16669 data_offset = 5;
16670 } else {
16671 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16672 bacapp_service = tvb_get_uint8(tvb, offset + 2);
16674 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16675 val_to_str_const(bacapp_service,
16676 BACnetConfirmedServiceChoice,
16677 bacapp_unknown_service_str),
16678 bacapp_invoke_id);
16680 updateBacnetInfoValue(BACINFO_INVOKEID,
16681 wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16683 updateBacnetInfoValue(BACINFO_SERVICE,
16684 wmem_strconcat(pinfo->pool,
16685 val_to_str_const(bacapp_service,
16686 BACnetConfirmedServiceChoice,
16687 bacapp_unknown_service_str),
16688 cackstr, NULL));
16689 break;
16690 case BACAPP_TYPE_SEGMENT_ACK:
16691 /* nothing more to add */
16692 break;
16693 case BACAPP_TYPE_ERROR:
16694 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16695 bacapp_service = tvb_get_uint8(tvb, offset + 2);
16696 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16697 val_to_str_const(bacapp_service,
16698 BACnetConfirmedServiceChoice,
16699 bacapp_unknown_service_str),
16700 bacapp_invoke_id);
16702 updateBacnetInfoValue(BACINFO_INVOKEID,
16703 wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16705 updateBacnetInfoValue(BACINFO_SERVICE,
16706 wmem_strconcat(pinfo->pool,
16707 errstr,
16708 val_to_str_const(bacapp_service,
16709 BACnetConfirmedServiceChoice,
16710 bacapp_unknown_service_str),
16711 NULL));
16712 break;
16713 case BACAPP_TYPE_REJECT:
16714 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16715 bacapp_reason = tvb_get_uint8(tvb, offset + 2);
16716 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16717 val_to_split_str(bacapp_reason,
16719 BACnetRejectReason,
16720 ASHRAE_Reserved_Fmt,
16721 Vendor_Proprietary_Fmt), bacapp_invoke_id);
16723 updateBacnetInfoValue(BACINFO_INVOKEID,
16724 wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16726 updateBacnetInfoValue(BACINFO_SERVICE,
16727 wmem_strconcat(pinfo->pool, rejstr,
16728 val_to_split_str(bacapp_reason, 64,
16729 BACnetRejectReason,
16730 ASHRAE_Reserved_Fmt,
16731 Vendor_Proprietary_Fmt),
16732 NULL));
16733 break;
16734 case BACAPP_TYPE_ABORT:
16735 bacapp_invoke_id = tvb_get_uint8(tvb, offset + 1);
16736 bacapp_reason = tvb_get_uint8(tvb, offset + 2);
16737 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
16738 val_to_split_str(bacapp_reason,
16740 BACnetAbortReason,
16741 ASHRAE_Reserved_Fmt,
16742 Vendor_Proprietary_Fmt), bacapp_invoke_id);
16744 updateBacnetInfoValue(BACINFO_INVOKEID,
16745 wmem_strdup_printf(pinfo->pool, "Invoke ID: %d", bacapp_invoke_id));
16747 updateBacnetInfoValue(BACINFO_SERVICE,
16748 wmem_strconcat(pinfo->pool, abortstr,
16749 val_to_split_str(bacapp_reason,
16751 BACnetAbortReason,
16752 ASHRAE_Reserved_Fmt,
16753 Vendor_Proprietary_Fmt),
16754 NULL));
16755 break;
16756 /* UNKNOWN */
16757 default:
16758 /* nothing more to add */
16759 break;
16762 save_fragmented = pinfo->fragmented;
16764 ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
16765 bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
16767 if (!fragment)
16768 do_the_dissection(tvb, pinfo, bacapp_tree);
16769 else
16770 fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
16771 /* not resetting the offset so the remaining can be done */
16773 if (fragment) { /* fragmented */
16774 fragment_head *frag_msg;
16776 pinfo->fragmented = true;
16778 frag_msg = fragment_add_seq_check(&msg_reassembly_table,
16779 tvb, data_offset,
16780 pinfo,
16781 bacapp_invoke_id, /* ID for fragments belonging together */
16782 NULL,
16783 bacapp_seqno, /* fragment sequence number */
16784 tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
16785 flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
16786 new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
16787 "Reassembled BACapp", frag_msg, &msg_frag_items,
16788 NULL, tree);
16790 if (new_tvb) { /* Reassembled */
16791 col_append_str(pinfo->cinfo, COL_INFO,
16792 " (Message Reassembled)");
16793 } else { /* Not last packet of reassembled Short Message */
16794 col_append_fstr(pinfo->cinfo, COL_INFO,
16795 " (Message fragment %u)", bacapp_seqno);
16797 if (new_tvb) { /* take it all */
16798 switch (bacapp_type) {
16799 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
16800 fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
16801 break;
16802 case BACAPP_TYPE_COMPLEX_ACK:
16803 fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
16804 break;
16805 default:
16806 /* do nothing */
16807 break;
16812 pinfo->fragmented = save_fragmented;
16814 /* tapping */
16815 tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
16816 return tvb_captured_length(tvb);
16819 void
16820 proto_register_bacapp(void)
16822 static hf_register_info hf[] = {
16823 { &hf_bacapp_type,
16824 { "APDU Type", "bacapp.type",
16825 FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
16827 { &hf_bacapp_pduflags,
16828 { "PDU Flags", "bacapp.pduflags",
16829 FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
16831 { &hf_bacapp_SEG,
16832 { "Segmented Request", "bacapp.segmented_request",
16833 FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
16835 { &hf_bacapp_MOR,
16836 { "More Segments", "bacapp.more_segments",
16837 FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
16839 { &hf_bacapp_SA,
16840 { "SA", "bacapp.SA",
16841 FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
16843 { &hf_bacapp_max_adpu_size,
16844 { "Size of Maximum ADPU accepted", "bacapp.max_adpu_size",
16845 FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
16847 { &hf_bacapp_response_segments,
16848 { "Max Response Segments accepted", "bacapp.response_segments",
16849 FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
16851 { &hf_bacapp_objectType,
16852 { "Object Type", "bacapp.objectType",
16853 FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
16855 { &hf_bacapp_object_name,
16856 { "Object Name", "bacapp.object_name",
16857 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16859 { &hf_bacapp_instanceNumber,
16860 { "Instance Number", "bacapp.instance_number",
16861 FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
16863 { &hf_BACnetPropertyIdentifier,
16864 { "Property Identifier", "bacapp.property_identifier",
16865 FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
16867 { &hf_BACnetVendorIdentifier,
16868 { "Vendor Identifier", "bacapp.vendor_identifier",
16869 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
16871 { &hf_BACnetRestartReason,
16872 { "Restart Reason", "bacapp.restart_reason",
16873 FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
16875 { &hf_bacapp_invoke_id,
16876 { "Invoke ID", "bacapp.invoke_id",
16877 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16879 { &hf_bacapp_sequence_number,
16880 { "Sequence Number", "bacapp.sequence_number",
16881 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16883 { &hf_bacapp_window_size,
16884 { "Proposed Window Size", "bacapp.window_size",
16885 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
16887 { &hf_bacapp_service,
16888 { "Service Choice", "bacapp.confirmed_service",
16889 FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
16891 { &hf_bacapp_uservice,
16892 { "Unconfirmed Service Choice", "bacapp.unconfirmed_service",
16893 FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
16895 { &hf_bacapp_NAK,
16896 { "NAK", "bacapp.NAK",
16897 FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
16899 { &hf_bacapp_SRV,
16900 { "SRV", "bacapp.SRV",
16901 FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
16903 { &hf_bacapp_event_type,
16904 { "Event Type", "bacapp.event_type",
16905 FT_UINT32, BASE_DEC, VALS(BACnetEventType), 0, NULL, HFILL }
16907 { &hf_bacapp_notify_type,
16908 { "Notify Type", "bacapp.notify_type",
16909 FT_UINT8, BASE_DEC, VALS(BACnetNotifyType), 0, NULL, HFILL }
16911 { &hf_bacapp_error_class,
16912 { "Error Class", "bacapp.error_class",
16913 FT_UINT32, BASE_DEC, VALS(BACnetErrorClass), 0, NULL, HFILL }
16915 { &hf_bacapp_error_code,
16916 { "Error Code", "bacapp.error_code",
16917 FT_UINT32, BASE_DEC, VALS(BACnetErrorCode), 0, NULL, HFILL }
16919 { &hf_bacapp_present_value_null,
16920 { "Present Value (null)", "bacapp.present_value.null",
16921 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16923 { &hf_bacapp_present_value_bool,
16924 { "Present Value (bool)", "bacapp.present_value.boolean",
16925 FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
16927 { &hf_bacapp_present_value_unsigned,
16928 { "Present Value (uint)", "bacapp.present_value.uint",
16929 FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL }
16931 { &hf_bacapp_present_value_signed,
16932 { "Present Value (int)", "bacapp.present_value.int",
16933 FT_INT64, BASE_DEC, NULL, 0, NULL, HFILL }
16935 { &hf_bacapp_present_value_real,
16936 { "Present Value (real)", "bacapp.present_value.real",
16937 FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL }
16939 { &hf_bacapp_present_value_double,
16940 { "Present Value (double)", "bacapp.present_value.double",
16941 FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL }
16943 { &hf_bacapp_present_value_octet_string,
16944 { "Present Value (octet string)", "bacapp.present_value.octet_string",
16945 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
16947 { &hf_bacapp_present_value_char_string,
16948 { "Present Value (char string)", "bacapp.present_value.char_string",
16949 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16951 { &hf_bacapp_present_value_bit_string,
16952 { "Present Value (bit string)", "bacapp.present_value.bit_string",
16953 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
16955 { &hf_bacapp_present_value_enum_index,
16956 { "Present Value (enum index)", "bacapp.present_value.enum_index",
16957 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16959 { &hf_Device_Instance_Range_Low_Limit,
16960 { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
16961 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16963 { &hf_Device_Instance_Range_High_Limit,
16964 { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
16965 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
16967 { &hf_BACnetRejectReason,
16968 { "Reject Reason", "bacapp.reject_reason",
16969 FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
16971 { &hf_BACnetAbortReason,
16972 { "Abort Reason", "bacapp.abort_reason",
16973 FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
16975 { &hf_BACnetApplicationTagNumber,
16976 { "Application Tag Number",
16977 "bacapp.application_tag_number",
16978 FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
16979 NULL, HFILL }
16981 { &hf_BACnetContextTagNumber,
16982 { "Context Tag Number",
16983 "bacapp.context_tag_number",
16984 FT_UINT8, BASE_DEC, NULL, 0xF0,
16985 NULL, HFILL }
16987 { &hf_BACnetExtendedTagNumber,
16988 { "Extended Tag Number",
16989 "bacapp.extended_tag_number",
16990 FT_UINT8, BASE_DEC, NULL, 0,
16991 NULL, HFILL }
16993 { &hf_BACnetNamedTag,
16994 { "Named Tag",
16995 "bacapp.named_tag",
16996 FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
16997 NULL, HFILL }
16999 { &hf_BACnetCharacterSet,
17000 { "String Character Set",
17001 "bacapp.string_character_set",
17002 FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
17003 NULL, HFILL }
17005 { &hf_BACnetCodePage,
17006 { "Code Page",
17007 "bacapp.code_page",
17008 FT_UINT16, BASE_DEC, NULL, 0,
17009 NULL, HFILL }
17011 { &hf_BACnetTagClass,
17012 { "Tag Class", "bacapp.tag_class",
17013 FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
17015 { &hf_bacapp_tag_lvt,
17016 { "Length Value Type",
17017 "bacapp.LVT",
17018 FT_UINT8, BASE_DEC, NULL, 0,
17019 NULL, HFILL }
17021 { &hf_bacapp_tag_ProcessId,
17022 { "ProcessIdentifier", "bacapp.processId",
17023 FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
17025 { &hf_bacapp_tag_to_state,
17026 { "To State", "bacapp.to_state",
17027 FT_UINT32, BASE_DEC, VALS(BACnetEventState), 0, NULL, HFILL }
17029 { &hf_bacapp_tag_from_state,
17030 { "From State", "bacapp.from_state",
17031 FT_UINT32, BASE_DEC, VALS(BACnetEventState), 0, NULL, HFILL }
17033 { &hf_bacapp_tag_IPV4,
17034 { "IPV4", "bacapp.IPV4",
17035 FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
17037 { &hf_bacapp_tag_IPV6,
17038 { "IPV6", "bacapp.IPV6",
17039 FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
17041 { &hf_bacapp_tag_PORT,
17042 { "Port", "bacapp.Port",
17043 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
17045 { &hf_bacapp_tag_mac_address_broadcast,
17046 { "MAC-address: broadcast", "bacapp.mac_address_broadcast",
17047 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
17049 { &hf_bacapp_reserved_ashrea,
17050 { "reserved for ASHRAE", "bacapp.reserved_ashrea",
17051 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
17053 { &hf_bacapp_unused_bits,
17054 { "Unused bits", "bacapp.unused_bits",
17055 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
17057 { &hf_bacapp_bit,
17058 { "bit", "bacapp.bit",
17059 FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }
17061 { &hf_bacapp_complete_bitstring,
17062 { "Complete bitstring", "bacapp.complete_bitstring",
17063 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
17065 {&hf_msg_fragments,
17066 { "Message fragments", "bacapp.fragments",
17067 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17068 {&hf_msg_fragment,
17069 { "Message fragment", "bacapp.fragment",
17070 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17071 {&hf_msg_fragment_overlap,
17072 { "Message fragment overlap", "bacapp.fragment.overlap",
17073 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17074 {&hf_msg_fragment_overlap_conflicts,
17075 { "Message fragment overlapping with conflicting data",
17076 "bacapp.fragment.overlap.conflicts",
17077 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17078 {&hf_msg_fragment_multiple_tails,
17079 { "Message has multiple tail fragments",
17080 "bacapp.fragment.multiple_tails",
17081 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17082 {&hf_msg_fragment_too_long_fragment,
17083 { "Message fragment too long", "bacapp.fragment.too_long_fragment",
17084 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17085 {&hf_msg_fragment_error,
17086 { "Message defragmentation error", "bacapp.fragment.error",
17087 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17088 {&hf_msg_fragment_count,
17089 { "Message fragment count", "bacapp.fragment.count",
17090 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
17091 {&hf_msg_reassembled_in,
17092 { "Reassembled in", "bacapp.reassembled.in",
17093 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
17094 {&hf_msg_reassembled_length,
17095 { "Reassembled BACapp length", "bacapp.reassembled.length",
17096 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
17098 static int *ett[] = {
17099 &ett_bacapp,
17100 &ett_bacapp_control,
17101 &ett_bacapp_tag,
17102 &ett_bacapp_list,
17103 &ett_bacapp_value,
17104 &ett_msg_fragment,
17105 &ett_msg_fragments
17109 static ei_register_info ei[] = {
17110 { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
17111 { &ei_bacapp_bad_tag, { "bacapp.bad_tag", PI_MALFORMED, PI_ERROR, "Wrong tag found", EXPFILL }},
17112 { &ei_bacapp_opening_tag, { "bacapp.bad_opening_tag", PI_MALFORMED, PI_ERROR, "Expected Opening Tag!", EXPFILL }},
17115 expert_module_t* expert_bacapp;
17117 proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
17118 "BACapp", "bacapp");
17120 proto_register_field_array(proto_bacapp, hf, array_length(hf));
17121 proto_register_subtree_array(ett, array_length(ett));
17122 expert_bacapp = expert_register_protocol(proto_bacapp);
17123 expert_register_field_array(expert_bacapp, ei, array_length(ei));
17124 register_dissector("bacapp", dissect_bacapp, proto_bacapp);
17126 reassembly_table_register(&msg_reassembly_table,
17127 &addresses_reassembly_table_functions);
17129 bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
17130 "BACapp Vendor Identifier", proto_bacapp,
17131 FT_UINT8, BASE_HEX);
17133 /* Register BACnet Statistic trees */
17134 register_bacapp_stat_trees();
17135 bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
17139 * Editor modelines - https://www.wireshark.org/tools/modelines.html
17141 * Local variables:
17142 * c-basic-offset: 4
17143 * tab-width: 8
17144 * indent-tabs-mode: nil
17145 * End:
17147 * vi: set shiftwidth=4 tabstop=8 expandtab:
17148 * :indentSize=4:tabSize=8:noTabs=true: