FIXUP: WIP: verification_trailer
[wireshark-wip.git] / epan / dissectors / packet-bacapp.c
blob85071529fe5fdf7b25e4bbeae327ae9ebcf9253d
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 * $Id$
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald[AT]wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "config.h"
32 #include <glib.h>
34 #include <epan/packet.h>
35 #include <epan/to_str.h>
36 #include <epan/wmem/wmem.h>
37 #include <epan/reassemble.h>
38 #include <epan/expert.h>
39 #include <epan/stats_tree.h>
40 #include "packet-bacapp.h"
42 static int bacapp_tap = -1;
44 /* formerly bacapp.h contains definitions and forward declarations */
46 #ifndef FAULT
47 #define FAULT proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
48 offset = tvb_length(tvb);
49 #endif
51 /* BACnet PDU Types */
52 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST 0
53 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST 1
54 #define BACAPP_TYPE_SIMPLE_ACK 2
55 #define BACAPP_TYPE_COMPLEX_ACK 3
56 #define BACAPP_TYPE_SEGMENT_ACK 4
57 #define BACAPP_TYPE_ERROR 5
58 #define BACAPP_TYPE_REJECT 6
59 #define BACAPP_TYPE_ABORT 7
60 #define MAX_BACAPP_TYPE 8
62 #define BACAPP_SEGMENTED_REQUEST 0x08
63 #define BACAPP_MORE_SEGMENTS 0x04
64 #define BACAPP_SEGMENTED_RESPONSE 0x02
65 #define BACAPP_SEGMENT_NAK 0x02
66 #define BACAPP_SENT_BY 0x01
69 /**
70 * dissect_bacapp ::= CHOICE {
71 * confirmed-request-PDU [0] BACnet-Confirmed-Request-PDU,
72 * unconfirmed-request-PDU [1] BACnet-Unconfirmed-Request-PDU,
73 * simpleACK-PDU [2] BACnet-SimpleACK-PDU,
74 * complexACK-PDU [3] BACnet-ComplexACK-PDU,
75 * segmentACK-PDU [4] BACnet-SegmentACK-PDU,
76 * error-PDU [5] BACnet-Error-PDU,
77 * reject-PDU [6] BACnet-Reject-PDU,
78 * abort-PDU [7] BACnet-Abort-PDU
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 **/
84 static void
85 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
87 /**
88 * ConfirmedRequest-PDU ::= SEQUENCE {
89 * pdu-type [0] Unsigned (0..15), -- 0 for this PDU Type
90 * segmentedMessage [1] BOOLEAN,
91 * moreFollows [2] BOOLEAN,
92 * segmented-response-accepted [3] BOOLEAN,
93 * reserved [4] Unsigned (0..3), -- must be set zero
94 * max-segments-accepted [5] Unsigned (0..7), -- as per 20.1.2.4
95 * max-APDU-length-accepted [5] Unsigned (0..15), -- as per 20.1.2.5
96 * invokeID [6] Unsigned (0..255),
97 * sequence-number [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
98 * proposed-window-size [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
99 * service-choice [9] BACnetConfirmedServiceChoice,
100 * service-request [10] BACnet-Confirmed-Service-Request OPTIONAL
102 * @param tvb the tv buffer of the current data
103 * @param pinfo the packet info of the current data
104 * @param tree the tree to append this item to
105 * @param offset the offset in the tvb
106 * @return modified offset
108 static guint
109 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
112 * @param tvb the tv buffer of the current data
113 * @param pinfo the packet info of the current data
114 * @param tree the tree to append this item to
115 * @param offset the offset in the tvb
116 * @param ack - indocates whether working on request or ack
117 * @param svc - output variable to return service choice
118 * @param tt - output varable to return service choice item
119 * @return modified offset
121 static guint
122 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
123 gint *svc, proto_item **tt);
126 * Unconfirmed-Request-PDU ::= SEQUENCE {
127 * pdu-type [0] Unsigned (0..15), -- 1 for this PDU type
128 * reserved [1] Unsigned (0..15), -- must be set zero
129 * service-choice [2] BACnetUnconfirmedServiceChoice,
130 * service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
132 * @param tvb the tv buffer of the current data
133 * @param pinfo the packet info of the current data
134 * @param tree the tree to append this item to
135 * @param offset the offset in the tvb
136 * @return modified offset
138 static guint
139 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
142 * SimpleACK-PDU ::= SEQUENCE {
143 * pdu-type [0] Unsigned (0..15), -- 2 for this PDU type
144 * reserved [1] Unsigned (0..15), -- must be set zero
145 * invokeID [2] Unsigned (0..255),
146 * service-ACK-choice [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
148 * @param tvb the tv buffer of the current data
149 * @param pinfo the packet info of the current data
150 * @param tree the tree to append this item to
151 * @param offset the offset in the tvb
152 * @return modified offset
154 static guint
155 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
158 * ComplexACK-PDU ::= SEQUENCE {
159 * pdu-type [0] Unsigned (0..15), -- 3 for this PDU Type
160 * segmentedMessage [1] BOOLEAN,
161 * moreFollows [2] BOOLEAN,
162 * reserved [3] Unsigned (0..3), -- must be set zero
163 * invokeID [4] Unsigned (0..255),
164 * sequence-number [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
165 * proposed-window-size [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
166 * service-ACK-choice [7] BACnetConfirmedServiceChoice,
167 * service-ACK [8] BACnet-Confirmed-Service-Request -- Context-specific tags 0..8 are NOT used in header encoding
169 * @param tvb the tv buffer of the current data
170 * @param pinfo the packet info of the current data
171 * @param tree the tree to append this item to
172 * @param offset the offset in the tvb
173 * @return modified offset
175 static guint
176 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
179 * SegmentACK-PDU ::= SEQUENCE {
180 * pdu-type [0] Unsigned (0..15), -- 4 for this PDU Type
181 * reserved [1] Unsigned (0..3), -- must be set zero
182 * negative-ACK [2] BOOLEAN,
183 * server [3] BOOLEAN,
184 * original-invokeID [4] Unsigned (0..255),
185 * sequence-number [5] Unsigned (0..255),
186 * actual-window-size [6] Unsigned (0..127)
188 * @param tvb the tv buffer of the current data
189 * @param pinfo the packet info of the current data
190 * @param tree the tree to append this item to
191 * @param offset the offset in the tvb
192 * @return modified offset
194 static guint
195 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
198 * Error-PDU ::= SEQUENCE {
199 * pdu-type [0] Unsigned (0..15), -- 5 for this PDU Type
200 * reserved [1] Unsigned (0..3), -- must be set zero
201 * original-invokeID [2] Unsigned (0..255),
202 * error-choice [3] BACnetConfirmedServiceChoice,
203 * error [4] BACnet-Error
205 * @param tvb the tv buffer of the current data
206 * @param pinfo the packet info of the current data
207 * @param tree the tree to append this item to
208 * @param offset the offset in the tvb
209 * @return modified offset
211 static guint
212 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
215 * Reject-PDU ::= SEQUENCE {
216 * pdu-type [0] Unsigned (0..15), -- 6 for this PDU Type
217 * reserved [1] Unsigned (0..3), -- must be set zero
218 * original-invokeID [2] Unsigned (0..255),
219 * reject-reason [3] BACnetRejectReason
221 * @param tvb the tv buffer of the current data
222 * @param pinfo the packet info of the current data
223 * @param tree the tree to append this item to
224 * @param offset the offset in the tvb
225 * @return modified offset
227 static guint
228 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
231 * Abort-PDU ::= SEQUENCE {
232 * pdu-type [0] Unsigned (0..15), -- 7 for this PDU Type
233 * reserved [1] Unsigned (0..3), -- must be set zero
234 * server [2] BOOLEAN,
235 * original-invokeID [3] Unsigned (0..255),
236 * abort-reason [4] BACnetAbortReason
238 * @param tvb the tv buffer of the current data
239 * @param pinfo the packet info of the current data
240 * @param tree the tree to append this item to
241 * @param offset the offset in the tvb
242 * @return modified offset
244 static guint
245 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
248 * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
249 * @param tvb the tv buffer of the current data
250 * @param pinfo the packet info of the current data
251 * @param tree the tree to append this item to
252 * @param offset the offset in the tvb
253 * @param label the label of this item
254 * @return modified offset
256 static guint
257 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
260 * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
261 * @param tvb the tv buffer of the current data
262 * @param pinfo the packet info of the current data
263 * @param tree the tree to append this item to
264 * @param offset the offset in the tvb
265 * @param label the label of this item
266 * @return modified offset
268 static guint
269 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
272 * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
273 * @param tvb the tv buffer of the current data
274 * @param pinfo the packet info of the current data
275 * @param tree the tree to append this item to
276 * @param offset the offset in the tvb
277 * @param label the label of this item
278 * @param lvt length of String
279 * @return modified offset
281 static guint
282 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
285 * 20.2.12, adds the label with Date Value to tree
286 * @param tvb the tv buffer of the current data
287 * @param pinfo the packet info of the current data
288 * @param tree the tree to append this item to
289 * @param offset the offset in the tvb
290 * @param label the label of this item
291 * @return modified offset
293 static guint
294 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
297 * 20.2.13, adds the label with Time Value to tree
298 * @param tvb the tv buffer of the current data
299 * @param pinfo the packet info of the current data
300 * @param tree the tree to append this item to
301 * @param offset the offset in the tvb
302 * @param label the label of this item
303 * @return modified offset
305 static guint
306 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
309 * 20.2.14, adds Object Identifier to tree
310 * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
311 * @param tvb the tv buffer of the current data
312 * @param pinfo the packet info of the current data
313 * @param tree the tree to append this item to
314 * @param offset the offset in the tvb
315 * @return modified offset
317 static guint
318 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
321 * BACnet-Confirmed-Service-Request ::= CHOICE {
323 * @param tvb the tv buffer of the current data
324 * @param pinfo the packet info of the current data
325 * @param tree the tree to append this item to
326 * @param offset the offset in the tvb
327 * @param service_choice the service choice
328 * @return offset
330 static guint
331 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
334 * BACnet-Confirmed-Service-ACK ::= CHOICE {
336 * @param tvb the tv buffer of the current data
337 * @param pinfo the packet info of the current data
338 * @param tree the tree to append this item to
339 * @param offset the offset in the tvb
340 * @param service_choice the service choice
341 * @return offset
343 static guint
344 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
347 * AcknowledgeAlarm-Request ::= SEQUENCE {
348 * acknowledgingProcessIdentifier [0] Unsigned32,
349 * eventObjectIdentifier [1] BACnetObjectIdentifer,
350 * eventStateAcknowledge [2] BACnetEventState,
351 * timeStamp [3] BACnetTimeStamp,
352 * acknowledgementSource [4] Character String,
353 * timeOfAcknowledgement [5] BACnetTimeStamp
355 * @param tvb the tv buffer of the current data
356 * @param pinfo the packet info of the current data
357 * @param tree the tree to append this item to
358 * @param offset the offset in the tvb
359 * @return modified offset
361 static guint
362 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
365 * ConfirmedCOVNotification-Request ::= SEQUENCE {
366 * subscriberProcessIdentifier [0] Unsigned32,
367 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
368 * monitoredObjectIdentifier [2] BACnetObjectIdentifer,
369 * timeRemaining [3] unsigned,
370 * listOfValues [4] SEQUENCE OF BACnetPropertyValues
372 * @param tvb the tv buffer of the current data
373 * @param pinfo the packet info of the current data
374 * @param tree the tree to append this item to
375 * @param offset the offset in the tvb
376 * @return modified offset
378 static guint
379 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
382 * ConfirmedEventNotification-Request ::= SEQUENCE {
383 * ProcessIdentifier [0] Unsigned32,
384 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
385 * eventObjectIdentifier [2] BACnetObjectIdentifer,
386 * timeStamp [3] BACnetTimeStamp,
387 * notificationClass [4] unsigned,
388 * priority [5] unsigned8,
389 * eventType [6] BACnetEventType,
390 * messageText [7] CharacterString OPTIONAL,
391 * notifyType [8] BACnetNotifyType,
392 * ackRequired [9] BOOLEAN OPTIONAL,
393 * fromState [10] BACnetEventState OPTIONAL,
394 * toState [11] BACnetEventState,
395 * eventValues [12] BACnetNotificationParameters OPTIONAL
397 * @param tvb the tv buffer of the current data
398 * @param pinfo the packet info of the current data
399 * @param tree the tree to append this item to
400 * @param offset the offset in the tvb
401 * @return modified offset
403 static guint
404 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
407 * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
408 * objectIdentifier BACnetObjectIdentifer,
409 * alarmState BACnetEventState,
410 * acknowledgedTransitions BACnetEventTransitionBits
412 * @param tvb the tv buffer of the current data
413 * @param pinfo the packet info of the current data
414 * @param tree the tree to append this item to
415 * @param offset the offset in the tvb
416 * @return modified offset
418 static guint
419 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
422 * GetEnrollmentSummary-Request ::= SEQUENCE {
423 * acknowledgmentFilter [0] ENUMERATED {
424 * all (0),
425 * acked (1),
426 * not-acked (2)
427 * },
428 * enrollmentFilter [1] BACnetRecipientProcess OPTIONAL,
429 * eventStateFilter [2] ENUMERATED {
430 * offnormal (0),
431 * fault (1),
432 * normal (2),
433 * all (3),
434 * active (4)
435 * },
436 * eventTypeFilter [3] BACnetEventType OPTIONAL,
437 * priorityFilter [4] SEQUENCE {
438 * minPriority [0] Unsigned8,
439 * maxPriority [1] Unsigned8
440 * } OPTIONAL,
441 * notificationClassFilter [5] Unsigned OPTIONAL
443 * @param tvb the tv buffer of the current data
444 * @param pinfo the packet info of the current data
445 * @param tree the tree to append this item to
446 * @param offset the offset in the tvb
447 * @return modified offset
449 static guint
450 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
453 * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
454 * objectIdentifier BACnetObjectIdentifer,
455 * eventType BACnetEventType,
456 * eventState BACnetEventState,
457 * priority Unsigned8,
458 * notificationClass Unsigned OPTIONAL
460 * @param tvb the tv buffer of the current data
461 * @param pinfo the packet info of the current data
462 * @param tree the tree to append this item to
463 * @param offset the offset in the tvb
464 * @return modified offset
466 static guint
467 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
470 * GetEventInformation-Request ::= SEQUENCE {
471 * lastReceivedObjectIdentifier [0] BACnetObjectIdentifer
473 * @param tvb the tv buffer of the current data
474 * @param pinfo the packet info of the current data
475 * @param tree the tree to append this item to
476 * @param offset the offset in the tvb
477 * @return modified offset
479 static guint
480 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
483 * GetEventInformation-ACK ::= SEQUENCE {
484 * listOfEventSummaries [0] listOfEventSummaries,
485 * moreEvents [1] BOOLEAN
487 * @param tvb the tv buffer of the current data
488 * @param pinfo the packet info of the current data
489 * @param tree the tree to append this item to
490 * @param offset the offset in the tvb
491 * @return modified offset
493 static guint
494 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
497 * LifeSafetyOperation-Request ::= SEQUENCE {
498 * requestingProcessIdentifier [0] Unsigned32
499 * requestingSource [1] CharacterString
500 * request [2] BACnetLifeSafetyOperation
501 * objectIdentifier [3] BACnetObjectIdentifier OPTIONAL
503 * @param tvb the tv buffer of the current data
504 * @param pinfo the packet info of the current data
505 * @param tree the tree to append this item to
506 * @param offset the offset in the tvb
507 * @return modified offset
509 static guint
510 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
513 * SubscribeCOV-Request ::= SEQUENCE {
514 * subscriberProcessIdentifier [0] Unsigned32
515 * monitoredObjectIdentifier [1] BACnetObjectIdentifier
516 * issueConfirmedNotifications [2] BOOLEAN OPTIONAL
517 * lifetime [3] Unsigned OPTIONAL
519 * @param tvb the tv buffer of the current data
520 * @param pinfo the packet info of the current data
521 * @param tree the tree to append this item to
522 * @param offset the offset in the tvb
523 * @return modified offset
525 static guint
526 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
529 * SubscribeCOVProperty-Request ::= SEQUENCE {
530 * subscriberProcessIdentifier [0] Unsigned32
531 * monitoredObjectIdentifier [1] BACnetObjectIdentifier
532 * issueConfirmedNotifications [2] BOOLEAN OPTIONAL
533 * lifetime [3] Unsigned OPTIONAL
534 * monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
535 * covIncrement [5] Unsigned OPTIONAL
537 * @param tvb the tv buffer of the current data
538 * @param pinfo the packet info of the current data
539 * @param tree the tree to append this item to
540 * @param offset the offset in the tvb
541 * @return modified offset
543 static guint
544 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
547 * AtomicReadFile-Request ::= SEQUENCE {
548 * fileIdentifier BACnetObjectIdentifier,
549 * accessMethod CHOICE {
550 * streamAccess [0] SEQUENCE {
551 * fileStartPosition INTEGER,
552 * requestedOctetCount Unsigned
553 * },
554 * recordAccess [1] SEQUENCE {
555 * fileStartRecord INTEGER,
556 * requestedRecordCount Unsigned
560 * @param tvb the tv buffer of the current data
561 * @param pinfo the packet info of the current data
562 * @param tree the tree to append this item to
563 * @param offset the offset in the tvb
564 * @return modified offset
566 static guint
567 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
570 * AtomicWriteFile-ACK ::= SEQUENCE {
571 * endOfFile BOOLEAN,
572 * accessMethod CHOICE {
573 * streamAccess [0] SEQUENCE {
574 * fileStartPosition INTEGER,
575 * fileData OCTET STRING
576 * },
577 * recordAccess [1] SEQUENCE {
578 * fileStartRecord INTEGER,
579 * returnedRecordCount Unsigned,
580 * fileRecordData SEQUENCE OF OCTET STRING
584 * @param tvb the tv buffer of the current data
585 * @param pinfo the packet info of the current data
586 * @param tree the tree to append this item to
587 * @param offset the offset in the tvb
588 * @return modified offset
590 static guint
591 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
594 * AtomicWriteFile-Request ::= SEQUENCE {
595 * fileIdentifier BACnetObjectIdentifier,
596 * accessMethod CHOICE {
597 * streamAccess [0] SEQUENCE {
598 * fileStartPosition INTEGER,
599 * fileData OCTET STRING
600 * },
601 * recordAccess [1] SEQUENCE {
602 * fileStartRecord INTEGER,
603 * recordCount Unsigned,
604 * fileRecordData SEQUENCE OF OCTET STRING
608 * @param tvb the tv buffer of the current data
609 * @param pinfo the packet info of the current data
610 * @param tree the tree to append this item to
611 * @param offset the offset in the tvb
612 * @return modified offset
614 static guint
615 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
618 * AtomicWriteFile-ACK ::= SEQUENCE {
619 * fileStartPosition [0] INTEGER,
620 * fileStartRecord [1] INTEGER,
622 * @param tvb the tv buffer of the current data
623 * @param pinfo the packet info of the current data
624 * @param tree the tree to append this item to
625 * @param offset the offset in the tvb
626 * @return modified offset
628 static guint
629 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
632 * AddListElement-Request ::= SEQUENCE {
633 * objectIdentifier [0] BACnetObjectIdentifier,
634 * propertyIdentifier [1] BACnetPropertyIdentifier,
635 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
636 * listOfElements [3] ABSTRACT-SYNTAX.&Type
638 * @param tvb the tv buffer of the current data
639 * @param pinfo the packet info of the current data
640 * @param tree the tree to append this item to
641 * @param offset the offset in the tvb
642 * @return modified offset
644 static guint
645 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
648 * CreateObject-Request ::= SEQUENCE {
649 * objectSpecifier [0] ObjectSpecifier,
650 * listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
652 * @param tvb the tv buffer of the current data
653 * @param pinfo the packet info of the current data
654 * @param subtree the sub tree to append this item to
655 * @param offset the offset in the tvb
656 * @return modified offset
658 static guint
659 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
662 * CreateObject-Request ::= BACnetObjectIdentifier
663 * @param tvb the tv buffer of the current data
664 * @param pinfo the packet info of the current data
665 * @param tree the tree to append this item to
666 * @param offset the offset in the tvb
667 * @return modified offset
669 static guint
670 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
673 * DeleteObject-Request ::= SEQUENCE {
674 * ObjectIdentifier BACnetObjectIdentifer
676 * @param tvb the tv buffer of the current data
677 * @param pinfo the packet info of the current data
678 * @param tree the tree to append this item to
679 * @param offset the offset in the tvb
680 * @return modified offset
682 static guint
683 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
686 * ReadProperty-Request ::= SEQUENCE {
687 * objectIdentifier [0] BACnetObjectIdentifier,
688 * propertyIdentifier [1] BACnetPropertyIdentifier,
689 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
691 * @param tvb the tv buffer of the current data
692 * @param pinfo the packet info of the current data
693 * @param tree the tree to append this item to
694 * @param offset the offset in the tvb
695 * @return modified offset
697 static guint
698 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
701 * ReadProperty-ACK ::= SEQUENCE {
702 * objectIdentifier [0] BACnetObjectIdentifier,
703 * propertyIdentifier [1] BACnetPropertyIdentifier,
704 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
705 * propertyValue [3] ABSTRACT-SYNTAX.&Type
707 * @param tvb the tv buffer of the current data
708 * @param pinfo the packet info of the current data
709 * @param tree the tree to append this item to
710 * @param offset the offset in the tvb
711 * @return modified offset
713 static guint
714 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
717 * ReadPropertyConditional-Request ::= SEQUENCE {
718 * objectSelectionCriteria [0] objectSelectionCriteria,
719 * listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
721 * @param tvb the tv buffer of the current data
722 * @param pinfo the packet info of the current data
723 * @param subtree the sub tree to append this item to
724 * @param offset the offset in the tvb
725 * @return modified offset
727 static guint
728 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
731 * ReadPropertyConditional-ACK ::= SEQUENCE {
732 * listOfPReadAccessResults SEQUENCE OF ReadAccessResult OPTIONAL
734 * @param tvb the tv buffer of the current data
735 * @param pinfo the packet info of the current data
736 * @param tree the tree to append this item to
737 * @param offset the offset in the tvb
738 * @return modified offset
740 static guint
741 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
744 * ReadPropertyMultiple-Request ::= SEQUENCE {
745 * listOfReadAccessSpecs SEQUENCE OF ReadAccessSpecification
747 * @param tvb the tv buffer of the current data
748 * @param pinfo the packet info of the current data
749 * @param subtree the sub tree to append this item to
750 * @param offset the offset in the tvb
751 * @return offset modified
753 static guint
754 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
757 * ReadPropertyMultiple-Ack ::= SEQUENCE {
758 * listOfReadAccessResults SEQUENCE OF ReadAccessResult
760 * @param tvb the tv buffer of the current data
761 * @parma pinfo
762 * @param tree the tree to append this item to
763 * @param offset the offset in the tvb
764 * @return offset modified
766 static guint
767 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
770 * ReadRange-Request ::= SEQUENCE {
771 * objectIdentifier [0] BACnetObjectIdentifier,
772 * propertyIdentifier [1] BACnetPropertyIdentifier,
773 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
774 * range CHOICE {
775 * byPosition [3] SEQUENCE {
776 * referencedIndex Unsigned,
777 * count INTEGER
778 * },
779 * byTime [4] SEQUENCE {
780 * referenceTime BACnetDateTime,
781 * count INTEGER
782 * },
783 * timeRange [5] SEQUENCE {
784 * beginningTime BACnetDateTime,
785 * endingTime BACnetDateTime
786 * },
787 * } OPTIONAL
789 * @param tvb the tv buffer of the current data
790 * @param pinfo the packet info of the current data
791 * @param tree the tree to append this item to
792 * @param offset the offset in the tvb
793 * @return modified offset
795 static guint
796 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
799 * ReadRange-ACK ::= SEQUENCE {
800 * objectIdentifier [0] BACnetObjectIdentifier,
801 * propertyIdentifier [1] BACnetPropertyIdentifier,
802 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
803 * resultFlags [3] BACnetResultFlags,
804 * itemCount [4] Unsigned,
805 * itemData [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
807 * @param tvb the tv buffer of the current data
808 * @param pinfo the packet info of the current data
809 * @param tree the tree to append this item to
810 * @param offset the offset in the tvb
811 * @return modified offset
813 static guint
814 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
817 * RemoveListElement-Request ::= SEQUENCE {
818 * objectIdentifier [0] BACnetObjectIdentifier,
819 * propertyIdentifier [1] BACnetPropertyIdentifier,
820 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
821 * listOfElements [3] ABSTRACT-SYNTAX.&Type
823 * @param tvb the tv buffer of the current data
824 * @param pinfo the packet info of the current data
825 * @param tree the tree to append this item to
826 * @param offset the offset in the tvb
827 * @return modified offset
829 static guint
830 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
833 * WriteProperty-Request ::= SEQUENCE {
834 * objectIdentifier [0] BACnetObjectIdentifier,
835 * propertyIdentifier [1] BACnetPropertyIdentifier,
836 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
837 * propertyValue [3] ABSTRACT-SYNTAX.&Type
838 * priority [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
840 * @param tvb the tv buffer of the current data
841 * @param pinfo the packet info of the current data
842 * @param tree the tree to append this item to
843 * @param offset the offset in the tvb
844 * @return modified offset
846 static guint
847 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
850 * WritePropertyMultiple-Request ::= SEQUENCE {
851 * listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
853 * @param tvb the tv buffer of the current data
854 * @param pinfo the packet info of the current data
855 * @param tree the tree to append this item to
856 * @param offset the offset in the tvb
857 * @return modified offset
859 static guint
860 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
863 * DeviceCommunicationControl-Request ::= SEQUENCE {
864 * timeDuration [0] Unsigned16 OPTIONAL,
865 * enable-disable [1] ENUMERATED {
866 * enable (0),
867 * disable (1)
868 * },
869 * password [2] CharacterString (SIZE(1..20)) OPTIONAL
871 * @param tvb the tv buffer of the current data
872 * @param pinfo the packet info of the current data
873 * @param tree the tree to append this item to
874 * @param offset the offset in the tvb
875 * @return modified offset
877 static guint
878 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
881 * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
882 * vendorID [0] Unsigned,
883 * serviceNumber [1] Unsigned,
884 * serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
886 * @param tvb the tv buffer of the current data
887 * @param pinfo the packet info of the current data
888 * @param tree the tree to append this item to
889 * @param offset the offset in the tvb
890 * @return modified offset
892 static guint
893 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
896 * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
897 * vendorID [0] Unsigned,
898 * serviceNumber [1] Unsigned,
899 * resultBlock [2] ABSTRACT-SYNTAX.&Type OPTIONAL
901 * @param tvb the tv buffer of the current data
902 * @param pinfo the packet info of the current data
903 * @param tree the tree to append this item to
904 * @param offset the offset in the tvb
905 * @return modified offset
907 static guint
908 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
911 * ConfirmedTextMessage-Request ::= SEQUENCE {
912 * textMessageSourceDevice [0] BACnetObjectIdentifier,
913 * messageClass [1] CHOICE {
914 * numeric [0] Unsigned,
915 * character [1] CharacterString
916 * } OPTIONAL,
917 * messagePriority [2] ENUMERATED {
918 * normal (0),
919 * urgent (1)
920 * },
921 * message [3] CharacterString
923 * @param tvb the tv buffer of the current data
924 * @param pinfo the packet info of the current data
925 * @param tree the tree to append this item to
926 * @param offset the offset in the tvb
927 * @return modified offset
929 static guint
930 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
933 * ReinitializeDevice-Request ::= SEQUENCE {
934 * reinitializedStateOfDevice [0] ENUMERATED {
935 * coldstart (0),
936 * warmstart (1),
937 * startbackup (2),
938 * endbackup (3),
939 * startrestore (4),
940 * endrestore (5),
941 * abortrestor (6)
942 * },
943 * password [1] CharacterString (SIZE(1..20)) OPTIONAL
945 * @param tvb the tv buffer of the current data
946 * @param pinfo the packet info of the current data
947 * @param tree the tree to append this item to
948 * @param offset the offset in the tvb
949 * @return modified offset
951 static guint
952 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
955 * VTOpen-Request ::= SEQUENCE {
956 * vtClass BACnetVTClass,
957 * localVTSessionIdentifier Unsigned8
959 * @param tvb the tv buffer of the current data
960 * @param pinfo the packet info of the current data
961 * @param tree the tree to append this item to
962 * @param offset the offset in the tvb
963 * @return modified offset
965 static guint
966 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
969 * VTOpen-ACK ::= SEQUENCE {
970 * remoteVTSessionIdentifier Unsigned8
972 * @param tvb the tv buffer of the current data
973 * @param pinfo the packet info of the current data
974 * @param tree the tree to append this item to
975 * @param offset the offset in the tvb
976 * @return modified offset
978 static guint
979 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
982 * VTClose-Request ::= SEQUENCE {
983 * listOfRemoteVTSessionIdentifiers SEQUENCE OF Unsigned8
985 * @param tvb the tv buffer of the current data
986 * @param pinfo the packet info of the current data
987 * @param tree the tree to append this item to
988 * @param offset the offset in the tvb
989 * @return modified offset
991 static guint
992 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
995 * VTData-Request ::= SEQUENCE {
996 * vtSessionIdentifier Unsigned8,
997 * vtNewData OCTET STRING,
998 * vtDataFlag Unsigned (0..1)
1000 * @param tvb the tv buffer of the current data
1001 * @param pinfo the packet info of the current data
1002 * @param tree the tree to append this item to
1003 * @param offset the offset in the tvb
1004 * @return modified offset
1006 static guint
1007 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1010 * VTData-ACK ::= SEQUENCE {
1011 * allNewDataAccepted [0] BOOLEAN,
1012 * acceptedOctetCount [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
1014 * @param tvb the tv buffer of the current data
1015 * @param pinfo the packet info of the current data
1016 * @param tree the tree to append this item to
1017 * @param offset the offset in the tvb
1018 * @return modified offset
1020 static guint
1021 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1024 * Authenticate-Request ::= SEQUENCE {
1025 * pseudoRandomNumber [0] Unsigned32,
1026 * excpectedInvokeID [1] Unsigned8 OPTIONAL,
1027 * operatorName [2] CharacterString OPTIONAL,
1028 * operatorPassword [3] CharacterString (SIZE(1..20)) OPTIONAL,
1029 * startEncypheredSession [4] BOOLEAN OPTIONAL
1031 * @param tvb the tv buffer of the current data
1032 * @param pinfo the packet info of the current data
1033 * @param tree the tree to append this item to
1034 * @param offset the offset in the tvb
1035 * @return modified offset
1037 static guint
1038 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1041 * Authenticate-ACK ::= SEQUENCE {
1042 * modifiedRandomNumber Unsigned32,
1044 * @param tvb the tv buffer of the current data
1045 * @param pinfo the packet info of the current data
1046 * @param tree the tree to append this item to
1047 * @param offset the offset in the tvb
1048 * @return modified offset
1050 static guint
1051 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1054 * RequestKey-Request ::= SEQUENCE {
1055 * requestingDeviceIdentifier BACnetObjectIdentifier,
1056 * requestingDeviceAddress BACnetAddress,
1057 * remoteDeviceIdentifier BACnetObjectIdentifier,
1058 * remoteDeviceAddress BACnetAddress
1060 * @param tvb the tv buffer of the current data
1061 * @param pinfo the packet info of the current data
1062 * @param tree the tree to append this item to
1063 * @param offset the offset in the tvb
1064 * @return modified offset
1066 static guint
1067 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1070 * Unconfirmed-Service-Request ::= CHOICE {
1072 * @param tvb the tv buffer of the current data
1073 * @param pinfo the packet info of the current data
1074 * @param tree the tree to append this item to
1075 * @param offset the offset in the tvb
1076 * @param service_choice the service choice
1077 * @return modified offset
1079 static guint
1080 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
1083 * UnconfirmedCOVNotification-Request ::= SEQUENCE {
1084 * subscriberProcessIdentifier [0] Unsigned32,
1085 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
1086 * monitoredObjectIdentifier [2] BACnetObjectIdentifer,
1087 * timeRemaining [3] unsigned,
1088 * listOfValues [4] SEQUENCE OF BACnetPropertyValues
1090 * @param tvb the tv buffer of the current data
1091 * @param pinfo the packet info of the current data
1092 * @param tree the tree to append this item to
1093 * @param offset the offset in the tvb
1094 * @return modified offset
1096 static guint
1097 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1100 * UnconfirmedEventNotification-Request ::= SEQUENCE {
1101 * ProcessIdentifier [0] Unsigned32,
1102 * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
1103 * eventObjectIdentifier [2] BACnetObjectIdentifer,
1104 * timeStamp [3] BACnetTimeStamp,
1105 * notificationClass [4] unsigned,
1106 * priority [5] unsigned8,
1107 * eventType [6] BACnetEventType,
1108 * messageText [7] CharacterString OPTIONAL,
1109 * notifyType [8] BACnetNotifyType,
1110 * ackRequired [9] BOOLEAN OPTIONAL,
1111 * fromState [10] BACnetEventState OPTIONAL,
1112 * toState [11] BACnetEventState,
1113 * eventValues [12] BACnetNotificationParameters OPTIONAL
1115 * @param tvb the tv buffer of the current data
1116 * @param pinfo the packet info of the current data
1117 * @param tree the tree to append this item to
1118 * @param offset the offset in the tvb
1119 * @return modified offset
1121 static guint
1122 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1125 * I-Am-Request ::= SEQUENCE {
1126 * aAmDeviceIdentifier BACnetObjectIdentifier,
1127 * maxAPDULengthAccepted Unsigned,
1128 * segmentationSupported BACnetSegmentation,
1129 * vendorID Unsigned
1131 * @param tvb the tv buffer of the current data
1132 * @param pinfo the packet info of the current data
1133 * @param tree the tree to append this item to
1134 * @param offset the offset in the tvb
1135 * @return modified offset
1137 static guint
1138 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1142 * I-Have-Request ::= SEQUENCE {
1143 * deviceIdentifier BACnetObjectIdentifier,
1144 * objectIdentifier BACnetObjectIdentifier,
1145 * objectName CharacterString
1147 * @param tvb the tv buffer of the current data
1148 * @param pinfo the packet info of the current data
1149 * @param tree the tree to append this item to
1150 * @param offset the offset in the tvb
1151 * @return modified offset
1153 static guint
1154 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1157 * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
1158 * vendorID [0] Unsigned,
1159 * serviceNumber [1] Unsigned,
1160 * serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
1162 * @param tvb the tv buffer of the current data
1163 * @param pinfo the packet info of the current data
1164 * @param tree the tree to append this item to
1165 * @param offset the offset in the tvb
1166 * @return modified offset
1168 static guint
1169 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1172 * UnconfirmedTextMessage-Request ::= SEQUENCE {
1173 * textMessageSourceDevice [0] BACnetObjectIdentifier,
1174 * messageClass [1] CHOICE {
1175 * numeric [0] Unsigned,
1176 * character [1] CharacterString
1177 * } OPTIONAL,
1178 * messagePriority [2] ENUMERATED {
1179 * normal (0),
1180 * urgent (1)
1181 * },
1182 * message [3] CharacterString
1184 * @param tvb the tv buffer of the current data
1185 * @param pinfo the packet info of the current data
1186 * @param tree the tree to append this item to
1187 * @param offset the offset in the tvb
1188 * @return modified offset
1190 static guint
1191 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1194 * TimeSynchronization-Request ::= SEQUENCE {
1195 * BACnetDateTime
1197 * @param tvb the tv buffer of the current data
1198 * @param pinfo the packet info of the current data
1199 * @param tree the tree to append this item to
1200 * @param offset the offset in the tvb
1201 * @return modified offset
1203 static guint
1204 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1207 * UTCTimeSynchronization-Request ::= SEQUENCE {
1208 * BACnetDateTime
1210 * @param tvb the tv buffer of the current data
1211 * @param pinfo the packet info of the current data
1212 * @param tree the tree to append this item to
1213 * @param offset the offset in the tvb
1214 * @return modified offset
1216 static guint
1217 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1220 * Who-Has-Request ::= SEQUENCE {
1221 * limits SEQUENCE {
1222 * deviceInstanceRangeLowLimit [0] Unsigned (0..4194303),
1223 * deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
1224 * } OPTIONAL,
1225 * object CHOICE {
1226 * objectIdentifier [2] BACnetObjectIdentifier,
1227 * objectName [3] CharacterString
1230 * @param tvb the tv buffer of the current data
1231 * @param pinfo the packet info of the current data
1232 * @param tree the tree to append this item to
1233 * @param offset the offset in the tvb
1234 * @return modified offset
1236 static guint
1237 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1240 * Who-Is-Request ::= SEQUENCE {
1241 * deviceInstanceRangeLowLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1242 * deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
1244 * @param tvb the tv buffer of the current data
1245 * @param tree the tree to append this item to
1246 * @param offset the offset in the tvb
1247 * @return modified offset
1249 static guint
1250 fWhoIsRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1253 * BACnet-Error ::= CHOICE {
1254 * addListElement [8] ChangeList-Error,
1255 * removeListElement [9] ChangeList-Error,
1256 * writePropertyMultiple [16] WritePropertyMultiple-Error,
1257 * confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
1258 * vtClose [22] VTClose-Error,
1259 * readRange [26] ObjectAccessService-Error
1260 * [default] Error
1262 * @param tvb the tv buffer of the current data
1263 * @param pinfo the packet info of the current data
1264 * @param tree the tree to append this item to
1265 * @param offset the offset in the tvb
1266 * @param service the service
1267 * @return modified offset
1269 static guint
1270 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
1273 * Dissect a BACnetError in a context tag
1275 * @param tvb the tv buffer of the current data
1276 * @param pinfo the packet info of the current data
1277 * @param tree the tree to append this item to
1278 * @param offset the offset in the tvb
1279 * @return modified offset
1281 static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1284 * ChangeList-Error ::= SEQUENCE {
1285 * errorType [0] Error,
1286 * firstFailedElementNumber [1] Unsigned
1289 * @param tvb the tv buffer of the current data
1290 * @param pinfo the packet info of the current data
1291 * @param tree the tree to append this item to
1292 * @param offset the offset in the tvb
1293 * @return modified offset
1295 static guint
1296 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1299 * CreateObject-Error ::= SEQUENCE {
1300 * errorType [0] Error,
1301 * firstFailedElementNumber [1] Unsigned
1304 * @param tvb the tv buffer of the current data
1305 * @param pinfo the packet info of the current data
1306 * @param tree the tree to append this item to
1307 * @param offset the offset in the tvb
1308 * @return modified offset
1310 static guint
1311 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1314 * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
1315 * errorType [0] Error,
1316 * vendorID [1] Unsigned,
1317 * serviceNumber [2] Unsigned,
1318 * errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
1321 * @param tvb the tv buffer of the current data
1322 * @param pinfo the packet info of the current data
1323 * @param tree the tree to append this item to
1324 * @param offset the offset in the tvb
1325 * @return modified offset
1327 static guint
1328 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1331 * WritePropertyMultiple-Error ::= SEQUENCE {
1332 * errorType [0] Error,
1333 * firstFailedWriteAttempt [1] Unsigned
1336 * @param tvb the tv buffer of the current data
1337 * @param pinfo the packet info of the current data
1338 * @param tree the tree to append this item to
1339 * @param offset the offset in the tvb
1340 * @return modified offset
1342 static guint
1343 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1346 * VTClose-Error ::= SEQUENCE {
1347 * errorType [0] Error,
1348 * listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
1351 * @param tvb the tv buffer of the current data
1352 * @param pinfo the packet info of the current data
1353 * @param tree the tree to append this item to
1354 * @param offset the offset in the tvb
1355 * @return modified offset
1357 static guint
1358 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1361 * BACnet Application Types chapter 20.2.1
1362 * @param tvb the tv buffer of the current data
1363 * @param pinfo the packet info of the current data
1364 * @param tree the tree to append this item to
1365 * @param offset the offset in the tvb
1366 * @param label the label of this item
1367 * @return modified offset
1369 static guint
1370 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1373 * BACnetActionCommand ::= SEQUENCE {
1374 * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
1375 * objectIdentifier [1] BACnetObjectIdentifier,
1376 * propertyIdentifier [2] BACnetPropertyIdentifier,
1377 * propertyArrayIndex [3] Unsigned OPTIONAL, -- used only with array datatype
1378 * propertyValue [4] ABSTRACT-SYNTAX.&Type,
1379 * priority [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
1380 * postDelay [6] Unsigned OPTIONAL,
1381 * quitOnFailure [7] BOOLEAN,
1382 * writeSuccessful [8] BOOLEAN
1384 * @param tvb the tv buffer of the current data
1385 * @param pinfo the packet info of the current data
1386 * @param tree the tree to append this item to
1387 * @param offset the offset in the tvb
1388 * @param tag_match the tag number
1389 * @return modified offset
1391 static guint
1392 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
1395 * BACnetActionList ::= SEQUENCE {
1396 * action [0] SEQUENCE of BACnetActionCommand
1398 * @param tvb the tv buffer of the current data
1399 * @param pinfo the packet info of the current data
1400 * @param tree the tree to append this item to
1401 * @param offset the offset in the tvb
1402 * @return modified offset
1404 static guint
1405 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1407 /** BACnetAddress ::= SEQUENCE {
1408 * network-number Unsigned16, -- A value 0 indicates the local network
1409 * mac-address OCTET STRING -- A string of length 0 indicates a broadcast
1411 * @param tvb the tv buffer of the current data
1412 * @param pinfo the packet info of the current data
1413 * @param tree the tree to append this item to
1414 * @param offset the offset in the tvb
1415 * @return modified offset
1417 static guint
1418 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1421 * BACnetAddressBinding ::= SEQUENCE {
1422 * deviceObjectID BACnetObjectIdentifier
1423 * deviceAddress BacnetAddress
1425 * @param tvb the tv buffer of the current data
1426 * @param pinfo the packet info of the current data
1427 * @param tree the tree to append this item to
1428 * @param offset the offset in the tvb
1429 * @return modified offset
1431 static guint
1432 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1435 * BACnetCalendarEntry ::= CHOICE {
1436 * date [0] Date,
1437 * dateRange [1] BACnetDateRange,
1438 * weekNDay [2] BacnetWeekNday
1440 * @param tvb the tv buffer of the current data
1441 * @param pinfo the packet info of the current data
1442 * @param tree the tree to append this item to
1443 * @param offset the offset in the tvb
1444 * @return modified offset
1446 static guint
1447 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1450 * BACnetClientCOV ::= CHOICE {
1451 * real-increment REAL,
1452 * default-increment NULL
1454 * @param tvb the tv buffer of the current data
1455 * @param tree the tree to append this item to
1456 * @param offset the offset in the tvb
1457 * @return modified offset
1459 static guint
1460 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1464 * BACnetDailySchedule ::= SEQUENCE {
1465 * day-schedule [0] SENQUENCE OF BACnetTimeValue
1467 * @param tvb the tv buffer of the current data
1468 * @param pinfo the packet info of the current data
1469 * @param tree the tree to append this item to
1470 * @param offset the offset in the tvb
1471 * @return modified offset
1473 static guint
1474 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1477 * BACnetWeeklySchedule ::= SEQUENCE {
1478 * week-schedule SENQUENCE SIZE (7) OF BACnetDailySchedule
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 guint
1487 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1490 * BACnetDateRange ::= SEQUENCE {
1491 * StartDate Date,
1492 * EndDate Date
1494 * @param tvb the tv buffer of the current data
1495 * @param pinfo the packet info of the current data
1496 * @param tree the tree to append this item to
1497 * @param offset the offset in the tvb
1498 * @return modified offset
1500 static guint
1501 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1504 * BACnetDateTime ::= SEQUENCE {
1505 * date Date,
1506 * time Time
1508 * @param tvb the tv buffer of the current data
1509 * @param pinfo the packet info of the current data
1510 * @param tree the tree to append this item to
1511 * @param offset the offset in the tvb
1512 * @param label the label of this item
1513 * @return modified offset
1515 static guint
1516 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
1519 * BACnetDestination ::= SEQUENCE {
1520 * validDays BACnetDaysOfWeek,
1521 * fromTime Time,
1522 * toTime Time,
1523 * recipient BACnetRecipient,
1524 * processIdentifier Unsigned32,
1525 * issueConfirmedNotifications BOOLEAN,
1526 * transitions BACnetEventTransitionBits
1528 * @param tvb the tv buffer of the current data
1529 * @param pinfo the packet info of the current data
1530 * @param tree the tree to append this item to
1531 * @param offset the offset in the tvb
1532 * @return modified offset
1534 static guint
1535 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1538 * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
1539 * objectIdentifier [0] BACnetObjectIdentifier,
1540 * propertyIdentifier [1] BACnetPropertyIdentifier,
1541 * propertyArrayIndex [2] Unsigend OPTIONAL,
1542 * deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
1544 * @param tvb the tv buffer of the current data
1545 * @param pinfo the packet info of the current data
1546 * @param tree the tree to append this item to
1547 * @param offset the offset in the tvb
1548 * @return modified offset
1550 static guint
1551 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1554 * BACnetObjectPropertyReference ::= SEQUENCE {
1555 * objectIdentifier [0] BACnetObjectIdentifier,
1556 * propertyIdentifier [1] BACnetPropertyIdentifier,
1557 * propertyArrayIndex [2] Unsigend OPTIONAL,
1559 * @param tvb the tv buffer of the current data
1560 * @param pinfo the packet info of the current data
1561 * @param tree the tree to append this item to
1562 * @param offset the offset in the tvb
1563 * @return modified offset
1565 static guint
1566 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1569 * BACnetDeviceObjectReference ::= SEQUENCE {
1570 * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
1571 * objectIdentifier [1] BACnetObjectIdentifier
1573 * @param tvb the tv buffer of the current data
1574 * @param pinfo the packet info of the current data
1575 * @param tree the tree to append this item to
1576 * @param offset the offset in the tvb
1577 * @return modified offset
1579 static guint
1580 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1583 * BACnetEventParameter ::= CHOICE {
1584 * change-of-bitstring [0] SEQUENCE {
1585 * time-delay [0] Unsigned,
1586 * bitmask [1] BIT STRING,
1587 * list-of-bitstring-values [2] SEQUENCE OF BIT STRING
1588 * },
1589 * change-of-state [1] SEQUENCE {
1590 * time-delay [0] Unsigned,
1591 * list-of-values [1] SEQUENCE OF BACnetPropertyStates
1592 * },
1593 * change-of-value [2] SEQUENCE {
1594 * time-delay [0] Unsigned,
1595 * cov-criteria [1] CHOICE {
1596 * bitmask [0] BIT STRING,
1597 * referenced-property-increment [1] REAL
1599 * },
1600 * command-failure [3] SEQUENCE {
1601 * time-delay [0] Unsigned,
1602 * feedback-property-reference [1] BACnetDeviceObjectPropertyReference
1603 * },
1604 * floating-limit [4] SEQUENCE {
1605 * time-delay [0] Unsigned,
1606 * setpoint-reference [1] BACnetDeviceObjectPropertyReference,
1607 * low-diff-limit [2] REAL,
1608 * high-diff-limit [3] REAL,
1609 * deadband [4] REAL
1610 * },
1611 * out-of-range [5] SEQUENCE {
1612 * time-delay [0] Unsigned,
1613 * low-limit [1] REAL,
1614 * high-limit [2] REAL,
1615 * deadband [3] REAL
1616 * },
1617 * -- context tag 7 is deprecated
1618 * change-of-life-safety [8] SEQUENCE {
1619 * time-delay [0] Unsigned,
1620 * list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
1621 * list-of-alarm-values [2] SEQUENCE OF BACnetLifeSafetyState,
1622 * mode-property-reference [3] BACnetDeviceObjectPropertyReference
1623 * },
1624 * extended [9] SEQUENCE {
1625 * vendor-id [0] Unsigned16,
1626 * extended-event-type [1] Unsigned,
1627 * parameters [2] SEQUENCE OF CHOICE {
1628 * null NULL,
1629 * real REAL,
1630 * integer Unsigned,
1631 * boolean BOOLEAN,
1632 * double Double,
1633 * octet OCTET STRING,
1634 * bitstring BIT STRING,
1635 * enum ENUMERATED,
1636 * reference [0] BACnetDeviceObjectPropertyReference
1638 * },
1639 * buffer-ready [10] SEQUENCE {
1640 * notification-threshold [0] Unsigned,
1641 * previous-notification-count [1] Unsigned32
1642 * },
1643 * unsigned-range [11] SEQUENCE {
1644 * time-delay [0] Unsigned,
1645 * low-limit [1] Unsigned,
1646 * high-limit [2] Unsigned,
1648 * -- context tag 12 is reserved for future addenda
1649 * access-event [13] SEQUENCE {
1650 * list-of-access-events [0] SEQUENCE OF BACnetAccessEvent,
1651 * access-event-time-reference [1] BACnetDeviceObjectPropertyReference
1653 * double-out-of-range [14] SEQUENCE {
1654 * time-delay [0] Unsigned,
1655 * low-limit [1] Double,
1656 * high-limit [2] Double,
1657 * deadband [3] Double
1659 * signed-out-of-range [15] SEQUENCE {
1660 * time-delay [0] Unsigned,
1661 * low-limit [1] INTEGER,
1662 * high-limit [2] INTEGER,
1663 * deadband [3] Unsigned
1665 * unsigned-out-of-range [16] SEQUENCE {
1666 * time-delay [0] Unsigned,
1667 * low-limit [1] Unsigned,
1668 * high-limit [2] Unsigned,
1669 * deadband [3] Unsigned
1671 * change-of-characterstring [17] SEQUENCE {
1672 * time-delay [0] Unsigned,
1673 * list-of-alarm-values [1] SEQUENCE OF CharacterString,
1675 * change-of-status-flags [18] SEQUENCE {
1676 * time-delay [0] Unsigned,
1677 * selected-flags [1] BACnetStatusFlags
1680 * @param tvb the tv buffer of the current data
1681 * @param tree the tree to append this item to
1682 * @param offset the offset in the tvb
1683 * @return modified offset
1685 static guint
1686 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1691 * BACnetLogRecord ::= SEQUENCE {
1692 * timestamp [0] BACnetDateTime,
1693 * logDatum [1] CHOICE {
1694 * log-status [0] BACnetLogStatus,
1695 * boolean-value [1] BOOLEAN,
1696 * real-value [2] REAL,
1697 * enum-value [3] ENUMERATED, -- Optionally limited to 32 bits
1698 * unsigned-value [4] Unsigned, -- Optionally limited to 32 bits
1699 * signed-value [5] INTEGER, -- Optionally limited to 32 bits
1700 * bitstring-value [6] BIT STRING, -- Optionally limited to 32 bits
1701 * null-value [7] NULL,
1702 * failure [8] Error,
1703 * time-change [9] REAL,
1704 * any-value [10] ABSTRACT-SYNTAX.&Type -- Optional
1706 * statusFlags [2] BACnetStatusFlags OPTIONAL
1708 * @param tvb the tv buffer of the current data
1709 * @param pinfo the packet info of the current data
1710 * @param tree the tree to append this item to
1711 * @param offset the offset in the tvb
1712 * @return modified offset
1714 static guint
1715 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1718 * BACnetEventLogRecord ::= SEQUENCE {
1719 * timestamp [0] BACnetDateTime,
1720 * logDatum [1] CHOICE {
1721 * log-status [0] BACnetLogStatus,
1722 * notification [1] ConfirmedEventNotification-Request,
1723 * time-change [2] REAL,
1726 * @param tvb the tv buffer of the current data
1727 * @param pinfo the packet info of the current data
1728 * @param tree the tree to append this item to
1729 * @param offset the offset in the tvb
1730 * @return modified offset
1732 static guint
1733 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1735 static guint
1736 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1739 * BACnetNotificationParameters ::= CHOICE {
1740 * change-of-bitstring [0] SEQUENCE {
1741 * referenced-bitstring [0] BIT STRING,
1742 * status-flags [1] BACnetStatusFlags
1743 * },
1744 * change-of-state [1] SEQUENCE {
1745 * new-state [0] BACnetPropertyStatus,
1746 * status-flags [1] BACnetStatusFlags
1747 * },
1748 * change-of-value [2] SEQUENCE {
1749 * new-value [0] CHOICE {
1750 * changed-bits [0] BIT STRING,
1751 * changed-value [1] REAL
1752 * },
1753 * status-flags [1] BACnetStatusFlags
1754 * },
1755 * command-failure [3] SEQUENCE {
1756 * command-value [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
1757 * status-flags [1] BACnetStatusFlags
1758 * feedback-value [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
1759 * },
1760 * floating-limit [4] SEQUENCE {
1761 * reference-value [0] REAL,
1762 * status-flags [1] BACnetStatusFlags
1763 * setpoint-value [2] REAL,
1764 * error-limit [3] REAL
1765 * },
1766 * out-of-range [5] SEQUENCE {
1767 * exceeding-value [0] REAL,
1768 * status-flags [1] BACnetStatusFlags
1769 * deadband [2] REAL,
1770 * exceeded-limit [3] REAL
1771 * },
1772 * complex-event-type [6] SEQUENCE OF BACnetPropertyValue,
1773 * -- complex tag 7 is deprecated
1774 * change-of-life-safety [8] SEQUENCE {
1775 * new-state [0] BACnetLifeSafetyState,
1776 * new-mode [1] BACnetLifeSafetyState
1777 * status-flags [2] BACnetStatusFlags,
1778 * operation-expected [3] BACnetLifeSafetyOperation
1779 * },
1780 * extended [9] SEQUENCE {
1781 * vendor-id [0] Unsigned16,
1782 * extended-event-type [1] Unsigned,
1783 * parameters [2] SEQUENCE OF CHOICE {
1784 * null NULL,
1785 * real REAL,
1786 * integer Unsigned,
1787 * boolean BOOLEAN,
1788 * double Double,
1789 * octet OCTET STRING,
1790 * bitstring BIT STRING,
1791 * enum ENUMERATED,
1792 * propertyValue [0] BACnetDeviceObjectPropertyValue
1794 * },
1795 * buffer-ready [10] SEQUENCE {
1796 * buffer-property [0] BACnetDeviceObjectPropertyReference,
1797 * previous-notification[1] Unsigned32,
1798 * current-notification [2] BACneUnsigned32tDateTime
1799 * },
1800 * unsigned-range [11] SEQUENCE {
1801 * exceeding-value [0] Unsigned,
1802 * status-flags [1] BACnetStatusFlags,
1803 * exceeded-limit [2] Unsigned
1804 * },
1805 * -- context tag 12 is reserved for future addenda
1806 * access-event [13] SEQUENCE {
1807 * access-event [0] BACnetAccessEvent,
1808 * status-flags [1] BACnetStatusFlags,
1809 * access-event-tag [2] Unsigned,
1810 * access-event-time [3] BACnetTimeStamp,
1811 * access-credential [4] BACnetDeviceObjectReference,
1812 * authentication-factor [5] BACnetAuthenticationFactor OPTIONAL
1813 * },
1814 * double-out-of-range [14] SEQUENCE {
1815 * exceeding-value [0] Double,
1816 * status-flags [1] BACnetStatusFlags
1817 * deadband [2] Double,
1818 * exceeded-limit [3] Double
1819 * },
1820 * signed-out-of-range [15] SEQUENCE {
1821 * exceeding-value [0] INTEGER,
1822 * status-flags [1] BACnetStatusFlags
1823 * deadband [2] Unsigned,
1824 * exceeded-limit [3] INTEGER
1825 * },
1826 * unsigned-out-of-range [16] SEQUENCE {
1827 * exceeding-value [0] Unsigned,
1828 * status-flags [1] BACnetStatusFlags
1829 * deadband [2] Unsigned,
1830 * exceeded-limit [3] Unsigned
1831 * },
1832 * change-of-characterstring [17] SEQUENCE {
1833 * changed-value [0] CharacterString,
1834 * status-flags [1] BACnetStatusFlags
1835 * alarm-value [2] CharacterString
1836 * },
1837 * change-of-status-flags [18] SEQUENCE {
1838 * present-value [0] ABSTRACT-SYNTAX.&Type OPTIONAL,
1839 * -- depends on referenced property
1840 * referenced-flags [1] BACnetStatusFlags
1841 * },
1843 * @param tvb the tv buffer of the current data
1844 * @param pinfo the packet info of the current data
1845 * @param tree the tree to append this item to
1846 * @param offset the offset in the tvb
1847 * @return modified offset
1849 static guint
1850 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1853 * BACnetObjectPropertyReference ::= SEQUENCE {
1854 * objectIdentifier [0] BACnetObjectIdentifier,
1855 * propertyIdentifier [1] BACnetPropertyIdentifier,
1856 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1858 * @param tvb the tv buffer of the current data
1859 * @param pinfo the packet info of the current data
1860 * @param tree the tree to append this item to
1861 * @param offset the offset in the tvb
1862 * @return modified offset
1864 static guint
1865 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1867 #if 0
1869 * BACnetObjectPropertyValue ::= SEQUENCE {
1870 * objectIdentifier [0] BACnetObjectIdentifier,
1871 * propertyIdentifier [1] BACnetPropertyIdentifier,
1872 * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
1873 * -- if omitted with an array the entire array is referenced
1874 * value [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
1875 * priority [4] Unsigned (1..16) OPTIONAL
1877 * @param tvb the tv buffer of the current data
1878 * @param tree the tree to append this item to
1879 * @param offset the offset in the tvb
1880 * @return modified offset
1882 static guint
1883 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset);
1884 #endif
1887 * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
1888 * @param tvb the tv buffer of the current data
1889 * @param pinfo the packet info of the current data
1890 * @param tree the tree to append this item to
1891 * @param offset the offset in the tvb
1892 * @return modified offset
1894 static guint
1895 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1897 static guint
1898 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
1901 * BACnetPropertyReference ::= SEQUENCE {
1902 * propertyIdentifier [0] BACnetPropertyIdentifier,
1903 * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
1905 * @param tvb the tv buffer of the current data
1906 * @param pinfo the packet info of the current data
1907 * @param tree the tree to append this item to
1908 * @param offset the offset in the tvb
1909 * @return modified offset
1911 static guint
1912 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
1914 /* static guint
1915 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
1917 static guint
1918 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1920 static guint
1921 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1924 * BACnetPropertyValue ::= SEQUENCE {
1925 * PropertyIdentifier [0] BACnetPropertyIdentifier,
1926 * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
1927 * -- if omitted with an array the entire array is referenced
1928 * value [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
1929 * priority [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
1931 * @param tvb the tv buffer of the current data
1932 * @param pinfo the packet info of the current data
1933 * @param tree the tree to append this item to
1934 * @param offset the offset in the tvb
1935 * @return modified offset
1937 static guint
1938 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1940 static guint
1941 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
1944 * BACnet Application PDUs chapter 21
1945 * BACnetRecipient::= CHOICE {
1946 * device [0] BACnetObjectIdentifier
1947 * address [1] BACnetAddress
1949 * @param tvb the tv buffer of the current data
1950 * @param pinfo the packet info of the current data
1951 * @param tree the tree to append this item to
1952 * @param offset the offset in the tvb
1953 * @return modified offset
1955 static guint
1956 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1959 * BACnet Application PDUs chapter 21
1960 * BACnetRecipientProcess::= SEQUENCE {
1961 * recipient [0] BACnetRecipient
1962 * processID [1] Unsigned32
1964 * @param tvb the tv buffer of the current data
1965 * @param pinfo the packet info of the current data
1966 * @param tree the tree to append this item to
1967 * @param offset the offset in the tvb
1968 * @return modified offset
1970 static guint
1971 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1973 static guint
1974 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
1976 #if 0
1978 * BACnetSessionKey ::= SEQUENCE {
1979 * sessionKey OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
1980 * peerAddress BACnetAddress
1982 * @param tvb the tv buffer of the current data
1983 * @param tree the tree to append this item to
1984 * @param offset the offset in the tvb
1985 * @return modified offset
1986 * @todo check if checksum is displayed correctly
1988 static guint
1989 fSessionKey(tvbuff_t *tvb, proto_tree *tree, guint offset);
1990 #endif
1993 * BACnetSpecialEvent ::= SEQUENCE {
1994 * period CHOICE {
1995 * calendarEntry [0] BACnetCalendarEntry,
1996 * calendarRefernce [1] BACnetObjectIdentifier
1997 * },
1998 * listOfTimeValues [2] SEQUENCE OF BACnetTimeValue,
1999 * eventPriority [3] Unsigned (1..16)
2001 * @param tvb the tv buffer of the current data
2002 * @param pinfo the packet info of the current data
2003 * @param tree the tree to append this item to
2004 * @param offset the offset in the tvb
2005 * @return modified offset
2007 static guint
2008 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2011 * BACnetTimeStamp ::= CHOICE {
2012 * time [0] Time,
2013 * sequenceNumber [1] Unsigned (0..65535),
2014 * dateTime [2] BACnetDateTime
2016 * @param tvb the tv buffer of the current data
2017 * @param pinfo the packet info of the current data
2018 * @param tree the tree to append this item to
2019 * @param offset the offset in the tvb
2020 * @param label the label of this item
2021 * @return modified offset
2023 static guint
2024 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2026 static guint
2027 fEventTimeStamps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2030 * BACnetTimeValue ::= SEQUENCE {
2031 * time Time,
2032 * value ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
2034 * @param tvb the tv buffer of the current data
2035 * @param pinfo the packet info of the current data
2036 * @param tree the tree to append this item to
2037 * @param offset the offset in the tvb
2038 * @return modified offset
2040 static guint
2041 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2043 #if 0
2045 * BACnetVTSession ::= SEQUENCE {
2046 * local-vtSessionID Unsigned8,
2047 * remote-vtSessionID Unsigned8,
2048 * remote-vtAddress 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
2055 static guint
2056 fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset);
2057 #endif
2060 * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
2061 * -- first octet month (1..12) January = 1, X'FF' = any month
2062 * -- second octet weekOfMonth where: 1 = days numbered 1-7
2063 * -- 2 = days numbered 8-14
2064 * -- 3 = days numbered 15-21
2065 * -- 4 = days numbered 22-28
2066 * -- 5 = days numbered 29-31
2067 * -- 6 = last 7 days of this month
2068 * -- X'FF' = any week of this month
2069 * -- third octet dayOfWeek (1..7) where 1 = Monday
2070 * -- 7 = Sunday
2071 * -- X'FF' = any day of week
2072 * @param tvb the tv buffer of the current data
2073 * @param pinfo the packet info of the current data
2074 * @param tree the tree to append this item to
2075 * @param offset the offset in the tvb
2076 * @return modified offset
2078 static guint
2079 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2082 * ReadAccessResult ::= SEQUENCE {
2083 * objectIdentifier [0] BACnetObjectIdentifier,
2084 * listOfResults [1] SEQUENCE OF SEQUENCE {
2085 * propertyIdentifier [2] BACnetPropertyIdentifier,
2086 * propertyArrayIndex [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
2087 * readResult CHOICE {
2088 * propertyValue [4] ABSTRACT-SYNTAX.&Type,
2089 * propertyAccessError [5] Error
2091 * } OPTIONAL
2093 * @param tvb the tv buffer of the current data
2094 * @param pinfo the packet info of the current data
2095 * @param tree the tree to append this item to
2096 * @param offset the offset in the tvb
2097 * @return modified offset
2099 static guint
2100 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2103 * ReadAccessSpecification ::= SEQUENCE {
2104 * objectIdentifier [0] BACnetObjectIdentifier,
2105 * listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
2107 * @param tvb the tv buffer of the current data
2108 * @param pinfo the packet info of the current data
2109 * @param subtree the subtree to append this item to
2110 * @param offset the offset in the tvb
2111 * @return modified offset
2113 static guint
2114 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2117 * WriteAccessSpecification ::= SEQUENCE {
2118 * objectIdentifier [0] BACnetObjectIdentifier,
2119 * listOfProperty [1] SEQUENCE OF BACnetPropertyValue
2121 * @param tvb the tv buffer of the current data
2122 * @param pinfo the packet info of the current data
2123 * @param subtree the sub tree to append this item to
2124 * @param offset the offset in the tvb
2125 * @return modified offset
2127 static guint
2128 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2131 /********************************************************* Helper functions *******************************************/
2134 * extracts the tag number from the tag header.
2135 * @param tvb the tv buffer of the current data "TestyVirtualBuffer"
2136 * @param offset the offset in the tvb in actual tvb
2137 * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
2139 static guint
2140 fTagNo(tvbuff_t *tvb, guint offset);
2143 * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
2144 * @param tvb the tv buffer of the current data = "TestyVirtualBuffer"
2145 * @param pinfo the packet info of the current data = packet info
2146 * @param offset the offset in the tvb = offset in actual tvb
2147 * @return tag_no BACnet 20.2.1.2 Tag Number
2148 * @return class_tag BACnet 20.2.1.1 Class
2149 * @return lvt BACnet 20.2.1.3 Length/Value/Type
2150 * @return offs = length of this header
2153 static guint
2154 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
2158 * adds processID with max 32Bit unsigned Integer Value to tree
2159 * @param tvb the tv buffer of the current data
2160 * @param pinfo the packet info of the current data
2161 * @param tree the tree to append this item to
2162 * @param offset the offset in the tvb
2163 * @return modified offset
2165 static guint
2166 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2169 * adds timeSpan with max 32Bit unsigned Integer Value to tree
2170 * @param tvb the tv buffer of the current data
2171 * @param pinfo the packet info of the current data
2172 * @param tree the tree to append this item to
2173 * @param offset the offset in the tvb
2174 * @return modified offset
2176 static guint
2177 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2180 * BACnet Application PDUs chapter 21
2181 * BACnetPropertyIdentifier::= ENUMERATED {
2182 * @see bacapp_property_identifier
2184 * @param tvb the tv buffer of the current data
2185 * @param pinfo the packet info of the current data
2186 * @param tree the tree to append this item to
2187 * @param offset the offset in the tvb
2188 * @return modified offset
2190 static guint
2191 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2194 * BACnet Application PDUs chapter 21
2195 * BACnetPropertyArrayIndex::= ENUMERATED {
2196 * @see bacapp_property_array_index
2198 * @param tvb the tv buffer of the current data
2199 * @param pinfo the packet info of the current data
2200 * @param tree the tree to append this item to
2201 * @param offset the offset in the tvb
2202 * @return modified offset
2204 static guint
2205 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2208 * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
2209 * objectIdentifier [0] BACnetObjectIdentifier,
2210 * eventState [1] BACnetEventState,
2211 * acknowledgedTransitions [2] BACnetEventTransitionBits,
2212 * eventTimeStamps [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
2213 * notifyType [4] BACnetNotifyType,
2214 * eventEnable [5] BACnetEventTransitionBits,
2215 * eventPriorities [6] SEQUENCE SIZE (3) OF Unsigned
2217 * @param tvb the tv buffer of the current data
2218 * @param pinfo the packet info of the current data
2219 * @param tree the tree to append this item to
2220 * @param offset the offset in the tvb
2221 * @return modified offset
2223 static guint
2224 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2227 * SelectionCriteria ::= SEQUENCE {
2228 * propertyIdentifier [0] BACnetPropertyIdentifier,
2229 * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
2230 * relationSpecifier [2] ENUMERATED { bacapp_relationSpecifier },
2231 * comparisonValue [3] ABSTRACT-SYNTAX.&Type
2233 * @param tvb the tv buffer of the current data
2234 * @param pinfo the packet info of the current data
2235 * @param tree the tree to append this item to
2236 * @param offset the offset in the tvb
2237 * @return modified offset
2239 static guint
2240 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2243 * objectSelectionCriteria ::= SEQUENCE {
2244 * selectionLogic [0] ENUMERATED { bacapp_selectionLogic },
2245 * listOfSelectionCriteria [1] SelectionCriteria
2247 * @param tvb the tv buffer of the current data
2248 * @param pinfo the packet info of the current data
2249 * @param subtree the sub tree to append this item to
2250 * @param offset the offset in the tvb
2251 * @return modified offset
2253 static guint
2254 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
2257 * BACnet-Error ::= SEQUENCE {
2258 * error-class ENUMERATED {},
2259 * error-code ENUMERATED {}
2262 * @param tvb the tv buffer of the current data
2263 * @param pinfo the packet info of the current data
2264 * @param tree the tree to append this item to
2265 * @param offset the offset in the tvb
2266 * @return modified offset
2268 static guint
2269 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2272 * Generic handler for context tagged values. Mostly for handling
2273 * vendor-defined properties and services.
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
2279 * @todo beautify this ugly construct
2281 static guint
2282 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
2285 * realizes some ABSTRACT-SYNTAX.&Type
2286 * @param tvb the tv buffer of the current data
2287 * @param pinfo the packet info of the current data
2288 * @param tree the tree to append this item to
2289 * @param offset the offset in the tvb
2290 * @return modified offset
2291 * @todo beautify this ugly construct
2293 static guint
2294 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
2297 static guint
2298 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
2299 const value_string *src);
2302 * register_bacapp
2304 void
2305 proto_register_bacapp(void);
2308 * proto_reg_handoff_bacapp
2310 void
2311 proto_reg_handoff_bacapp(void);
2314 * converts XXX coded strings to UTF-8
2315 * else 'in' is copied to 'out'
2316 * @param in -- pointer to string
2317 * @param inbytesleft size of int bytes
2318 * @param out -- pointer to string
2319 * @param outbytesleft size of out bytes
2320 * @param fromcoding coding type
2321 * @return count of modified characters of returned string, -1 for errors
2323 static guint32
2324 fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding);
2326 static void
2327 uni_to_string(char * data, gsize str_length, char *dest_buf);
2329 /* <<<< formerly bacapp.h */
2331 /* reassembly table for segmented messages */
2332 static reassembly_table msg_reassembly_table;
2334 /* some necessary forward function prototypes */
2335 static guint
2336 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
2337 const gchar *label, const value_string *vs);
2339 static const char *bacapp_unknown_service_str = "unknown service"; /* Usage: no format specifiers */
2340 static const char *ASHRAE_Reserved_Fmt = "(%d) Reserved for Use by ASHRAE";
2341 static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
2343 static const value_string
2344 BACnetTypeName[] = {
2345 { 0, "Confirmed-REQ"},
2346 { 1, "Unconfirmed-REQ"},
2347 { 2, "Simple-ACK"},
2348 { 3, "Complex-ACK"},
2349 { 4, "Segment-ACK"},
2350 { 5, "Error"},
2351 { 6, "Reject"},
2352 { 7, "Abort"},
2353 { 0, NULL }
2356 static const true_false_string segments_follow = {
2357 "Segmented Request",
2358 "Unsegmented Request"
2361 static const true_false_string more_follow = {
2362 "More Segments Follow",
2363 "No More Segments Follow"
2366 static const true_false_string segmented_accept = {
2367 "Segmented Response accepted",
2368 "Segmented Response not accepted"
2371 static const true_false_string
2372 BACnetTagClass = {
2373 "Context Specific Tag",
2374 "Application Tag"
2377 static const value_string
2378 BACnetMaxSegmentsAccepted [] = {
2379 { 0, "Unspecified"},
2380 { 1, "2 segments"},
2381 { 2, "4 segments"},
2382 { 3, "8 segments"},
2383 { 4, "16 segments"},
2384 { 5, "32 segments"},
2385 { 6, "64 segments"},
2386 { 7, "Greater than 64 segments"},
2387 { 0, NULL }
2390 static const value_string
2391 BACnetMaxAPDULengthAccepted [] = {
2392 { 0, "Up to MinimumMessageSize (50 octets)"},
2393 { 1, "Up to 128 octets"},
2394 { 2, "Up to 206 octets (fits in a LonTalk frame)"},
2395 { 3, "Up to 480 octets (fits in an ARCNET frame)"},
2396 { 4, "Up to 1024 octets"},
2397 { 5, "Up to 1476 octets (fits in an ISO 8802-3 frame)"},
2398 { 6, "reserved by ASHRAE"},
2399 { 7, "reserved by ASHRAE"},
2400 { 8, "reserved by ASHRAE"},
2401 { 9, "reserved by ASHRAE"},
2402 { 10, "reserved by ASHRAE"},
2403 { 11, "reserved by ASHRAE"},
2404 { 12, "reserved by ASHRAE"},
2405 { 13, "reserved by ASHRAE"},
2406 { 14, "reserved by ASHRAE"},
2407 { 15, "reserved by ASHRAE"},
2408 { 0, NULL}
2411 static const value_string
2412 BACnetRejectReason [] = {
2413 {0, "other"},
2414 {1, "buffer-overflow"},
2415 {2, "inconsistent-parameters"},
2416 {3, "invalid-parameter-data-type"},
2417 {4, "invalid-tag"},
2418 {5, "missing-required-parameter"},
2419 {6, "parameter-out-of-range"},
2420 {7, "too-many-arguments"},
2421 {8, "undefined-enumeration"},
2422 {9, "unrecognized-service"},
2423 {0, NULL}
2426 static const value_string
2427 BACnetRestartReason [] = {
2428 { 0, "unknown"},
2429 { 1, "coldstart"},
2430 { 2, "warmstart"},
2431 { 3, "detected-power-lost"},
2432 { 4, "detected-powered-off"},
2433 { 5, "hardware-watchdog"},
2434 { 6, "software-watchdog"},
2435 { 7, "suspended"},
2436 { 0, NULL}
2439 static const value_string
2440 BACnetApplicationTagNumber [] = {
2441 { 0, "Null"},
2442 { 1, "Boolean"},
2443 { 2, "Unsigned Integer"},
2444 { 3, "Signed Integer (2's complement notation)"},
2445 { 4, "Real (ANSI/IEE-754 floating point)"},
2446 { 5, "Double (ANSI/IEE-754 double precision floating point)"},
2447 { 6, "Octet String"},
2448 { 7, "Character String"},
2449 { 8, "Bit String"},
2450 { 9, "Enumerated"},
2451 { 10, "Date"},
2452 { 11, "Time"},
2453 { 12, "BACnetObjectIdentifier"},
2454 { 13, "reserved by ASHRAE"},
2455 { 14, "reserved by ASHRAE"},
2456 { 15, "reserved by ASHRAE"},
2457 { 0, NULL}
2460 static const value_string
2461 BACnetAction [] = {
2462 { 0, "direct"},
2463 { 1, "reverse"},
2464 { 0, NULL}
2467 static const value_string
2468 BACnetAccessEvent [] = {
2469 { 0, "none"},
2470 { 1, "granted"},
2471 { 2, "muster"},
2472 { 3, "passback-detected"},
2473 { 4, "duress"},
2474 { 5, "trace"},
2475 { 6, "lockout-max-attempts"},
2476 { 7, "lockout-other"},
2477 { 8, "lockout-relinquished"},
2478 { 9, "lockout-by-higher-priority"},
2479 { 10, "out-of-service"},
2480 { 11, "out-of-service-relinquished"},
2481 { 12, "accompaniment-by"},
2482 { 13, "authentication-factor-read"},
2483 { 14, "authorization-delayed"},
2484 { 15, "verification-required"},
2485 /* Enumerated values 128-511 are used for events
2486 * which indicate that access has been denied. */
2487 { 128, "denied-deny-all"},
2488 { 129, "denied-unknown-credential"},
2489 { 130, "denied-authentication-unavailable"},
2490 { 131, "denied-authentication-factor-timeout"},
2491 { 132, "denied-incorrect-authentication-factor"},
2492 { 133, "denied-zone-no-access-rights"},
2493 { 134, "denied-point-no-access-rights"},
2494 { 135, "denied-no-access-rights"},
2495 { 136, "denied-out-of-time-range"},
2496 { 137, "denied-threat-level"},
2497 { 138, "denied-passback"},
2498 { 139, "denied-unexpected-location-usage"},
2499 { 140, "denied-max-attempts"},
2500 { 141, "denied-lower-occupancy-limit"},
2501 { 142, "denied-upper-occupancy-limit"},
2502 { 143, "denied-authentication-factor-lost"},
2503 { 144, "denied-authentication-factor-stolen"},
2504 { 145, "denied-authentication-factor-damaged"},
2505 { 146, "denied-authentication-factor-destroyed"},
2506 { 147, "denied-authentication-factor-disabled"},
2507 { 148, "denied-authentication-factor-error"},
2508 { 149, "denied-credential-unassigned"},
2509 { 150, "denied-credential-not-provisioned"},
2510 { 151, "denied-credential-not-yet-active"},
2511 { 152, "denied-credential-expired"},
2512 { 153, "denied-credential-manual-disable"},
2513 { 154, "denied-credential-lockout"},
2514 { 155, "denied-credential-max-days"},
2515 { 156, "denied-credential-max-uses"},
2516 { 157, "denied-credential-inactivity"},
2517 { 158, "denied-credential-disabled"},
2518 { 159, "denied-no-accompaniment"},
2519 { 160, "denied-incorrect-accompaniment"},
2520 { 161, "denied-lockout"},
2521 { 162, "denied-verification-failed"},
2522 { 163, "denied-verification-timeout"},
2523 { 164, "denied-other"},
2524 { 0, NULL}
2525 /* Enumerated values 0-512 are reserved for definition by ASHRAE.
2526 Enumerated values 512-65535 may be used by others subject to
2527 procedures and constraints described in Clause 23. */
2530 static const value_string
2531 BACnetFileAccessMethod [] = {
2532 { 0, "record-access"},
2533 { 1, "stream-access"},
2534 { 0, NULL}
2537 /* For some reason, BACnet defines the choice parameter
2538 in the file read and write services backwards from the
2539 BACnetFileAccessMethod enumeration.
2541 static const value_string
2542 BACnetFileAccessOption [] = {
2543 { 0, "stream access"},
2544 { 1, "record access"},
2545 { 0, NULL}
2548 static const value_string
2549 BACnetFileStartOption [] = {
2550 { 0, "File Start Position: "},
2551 { 1, "File Start Record: "},
2552 { 0, NULL}
2555 static const value_string
2556 BACnetFileRequestCount [] = {
2557 { 0, "Requested Octet Count: "},
2558 { 1, "Requested Record Count: "},
2559 { 0, NULL}
2562 static const value_string
2563 BACnetFileWriteInfo [] = {
2564 { 0, "File Data: "},
2565 { 1, "Record Count: "},
2566 { 0, NULL}
2569 static const value_string
2570 BACnetAbortReason [] = {
2571 { 0, "other"},
2572 { 1, "buffer-overflow"},
2573 { 2, "invalid-apdu-in-this-state"},
2574 { 3, "preempted-by-higher-priority-task"},
2575 { 4, "segmentation-not-supported"},
2576 { 0, NULL}
2579 static const value_string
2580 BACnetLifeSafetyMode [] = {
2581 { 0, "off"},
2582 { 1, "on"},
2583 { 2, "test"},
2584 { 3, "manned"},
2585 { 4, "unmanned"},
2586 { 5, "armed"},
2587 { 6, "disarmed"},
2588 { 7, "prearmed"},
2589 { 8, "slow"},
2590 { 9, "fast"},
2591 { 10, "disconnected"},
2592 { 11, "enabled"},
2593 { 12, "disabled"},
2594 { 13, "atomic-release-disabled"},
2595 { 14, "default"},
2596 { 0, NULL}
2597 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2598 Enumerated values 256-65535 may be used by others subject to
2599 procedures and constraints described in Clause 23. */
2602 static const value_string
2603 BACnetLifeSafetyOperation [] = {
2604 { 0, "none"},
2605 { 1, "silence"},
2606 { 2, "silence-audible"},
2607 { 3, "silence-visual"},
2608 { 4, "reset"},
2609 { 5, "reset-alarm"},
2610 { 6, "reset-fault"},
2611 { 7, "unsilence"},
2612 { 8, "unsilence-audible"},
2613 { 9, "unsilence-visual"},
2614 { 0, NULL}
2615 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
2616 Enumerated values 64-65535 may be used by others subject to
2617 procedures and constraints described in Clause 23. */
2620 #if 0
2621 static const value_string
2622 BACnetLimitEnable [] = {
2623 { 0, "lowLimitEnable"},
2624 { 1, "highLimitEnable"},
2625 { 0, NULL}
2627 #endif
2629 static const value_string
2630 BACnetLifeSafetyState [] = {
2631 { 0, "quiet"},
2632 { 1, "pre-alarm"},
2633 { 2, "alarm"},
2634 { 3, "fault"},
2635 { 4, "fault-pre-alarm"},
2636 { 5, "fault-alarm"},
2637 { 6, "not-ready"},
2638 { 7, "active"},
2639 { 8, "tamper"},
2640 { 9, "test-alarm"},
2641 { 10, "test-active"},
2642 { 11, "test-fault"},
2643 { 12, "test-fault-alarm"},
2644 { 13, "holdup"},
2645 { 14, "duress"},
2646 { 15, "tamper-alarm"},
2647 { 16, "abnormal"},
2648 { 17, "emergency-power"},
2649 { 18, "delayed"},
2650 { 19, "blocked"},
2651 { 20, "local-alarm"},
2652 { 21, "general-alarm"},
2653 { 22, "supervisory"},
2654 { 23, "test-supervisory"},
2655 { 0, NULL}
2656 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
2657 Enumerated values 256-65535 may be used by others subject to
2658 procedures and constraints described in Clause 23. */
2661 static const value_string
2662 BACnetConfirmedServiceChoice [] = {
2663 { 0, "acknowledgeAlarm"},
2664 { 1, "confirmedCOVNotification"},
2665 { 2, "confirmedEventNotification"},
2666 { 3, "getAlarmSummary"},
2667 { 4, "getEnrollmentSummary"},
2668 { 5, "subscribeCOV"},
2669 { 6, "atomicReadFile"},
2670 { 7, "atomicWriteFile"},
2671 { 8, "addListElement"},
2672 { 9, "removeListElement"},
2673 { 10, "createObject"},
2674 { 11, "deleteObject"},
2675 { 12, "readProperty"},
2676 { 13, "readPropertyConditional"},
2677 { 14, "readPropertyMultiple"},
2678 { 15, "writeProperty"},
2679 { 16, "writePropertyMultiple"},
2680 { 17, "deviceCommunicationControl"},
2681 { 18, "confirmedPrivateTransfer"},
2682 { 19, "confirmedTextMessage"},
2683 { 20, "reinitializeDevice"},
2684 { 21, "vtOpen"},
2685 { 22, "vtClose"},
2686 { 23, "vtData"},
2687 { 24, "authenticate"},
2688 { 25, "requestKey"},
2689 { 26, "readRange"},
2690 { 27, "lifeSafetyOperation"},
2691 { 28, "subscribeCOVProperty"},
2692 { 29, "getEventInformation"},
2693 { 30, "reserved by ASHRAE"},
2694 { 0, NULL}
2697 static const value_string
2698 BACnetReliability [] = {
2699 { 0, "no-fault-detected"},
2700 { 1, "no-sensor"},
2701 { 2, "over-range"},
2702 { 3, "under-range"},
2703 { 4, "open-loop"},
2704 { 5, "shorted-loop"},
2705 { 6, "no-output"},
2706 { 7, "unreliable-other"},
2707 { 8, "process-error"},
2708 { 9, "multi-state-fault"},
2709 { 10, "configuration-error"},
2710 /* enumeration value 11 is reserved for a future addendum */
2711 { 12, "communication-failure"},
2712 { 13, "member-fault"},
2713 { 0, NULL}
2716 static const value_string
2717 BACnetUnconfirmedServiceChoice [] = {
2718 { 0, "i-Am"},
2719 { 1, "i-Have"},
2720 { 2, "unconfirmedCOVNotification"},
2721 { 3, "unconfirmedEventNotification"},
2722 { 4, "unconfirmedPrivateTransfer"},
2723 { 5, "unconfirmedTextMessage"},
2724 { 6, "timeSynchronization"},
2725 { 7, "who-Has"},
2726 { 8, "who-Is"},
2727 { 9, "utcTimeSynchronization"},
2728 { 0, NULL}
2731 #if 0
2732 static const value_string
2733 BACnetUnconfirmedServiceRequest [] = {
2734 { 0, "i-Am-Request"},
2735 { 1, "i-Have-Request"},
2736 { 2, "unconfirmedCOVNotification-Request"},
2737 { 3, "unconfirmedEventNotification-Request"},
2738 { 4, "unconfirmedPrivateTransfer-Request"},
2739 { 5, "unconfirmedTextMessage-Request"},
2740 { 6, "timeSynchronization-Request"},
2741 { 7, "who-Has-Request"},
2742 { 8, "who-Is-Request"},
2743 { 9, "utcTimeSynchonization-Request"},
2744 { 0, NULL}
2746 #endif
2748 static const value_string
2749 BACnetObjectType [] = {
2750 { 0, "analog-input"},
2751 { 1, "analog-output"},
2752 { 2, "analog-value"},
2753 { 3, "binary-input"},
2754 { 4, "binary-output"},
2755 { 5, "binary-value"},
2756 { 6, "calendar"},
2757 { 7, "command"},
2758 { 8, "device"},
2759 { 9, "event-enrollment"},
2760 { 10, "file"},
2761 { 11, "group"},
2762 { 12, "loop"},
2763 { 13, "multi-state-input"},
2764 { 14, "multi-state-output"},
2765 { 15, "notification-class"},
2766 { 16, "program"},
2767 { 17, "schedule"},
2768 { 18, "averaging"},
2769 { 19, "multi-state-value"},
2770 { 20, "trend-log"},
2771 { 21, "life-safety-point"},
2772 { 22, "life-safety-zone"},
2773 { 23, "accumulator"},
2774 { 24, "pulse-converter"},
2775 { 25, "event-log"},
2776 { 26, "global-group"},
2777 { 27, "trend-log-multiple"},
2778 { 28, "load-control"},
2779 { 29, "structured-view"},
2780 { 30, "access-door"}, /* 30-37 added with addanda 135-2008j */
2781 /* value 31 is unassigned */
2782 { 32, "access-credential"},
2783 { 33, "access-point"},
2784 { 34, "access-rights"},
2785 { 35, "access-user"},
2786 { 36, "access-zone"},
2787 { 37, "credential-data-input"},
2788 { 38, "network-security"},
2789 { 39, "bitstring-value"}, /* 39-50 added with addenda 135-2008w */
2790 { 40, "characterstring-value"},
2791 { 41, "date-pattern-value"},
2792 { 42, "date-value"},
2793 { 43, "datetime-pattern-value"},
2794 { 44, "datetime-value"},
2795 { 45, "integer-value"},
2796 { 46, "large-analog-value"},
2797 { 47, "octetstring-value"},
2798 { 48, "positive-integer-value"},
2799 { 49, "time-pattern-value"},
2800 { 50, "time-value"},
2801 { 0, NULL}
2802 /* Enumerated values 0-127 are reserved for definition by ASHRAE.
2803 Enumerated values 128-1023 may be used by others subject to
2804 the procedures and constraints described in Clause 23. */
2807 static const value_string
2808 BACnetEngineeringUnits [] = {
2809 { 0, "Sq Meters"},
2810 { 1, "Sq Feet"},
2811 { 2, "Milliamperes"},
2812 { 3, "Amperes"},
2813 { 4, "Ohms"},
2814 { 5, "Volts"},
2815 { 6, "Kilovolts"},
2816 { 7, "Megavolts"},
2817 { 8, "Volt Amperes"},
2818 { 9, "Kilovolt Amperes"},
2819 { 10, "Megavolt Amperes"},
2820 { 11, "Volt Amperes Reactive"},
2821 { 12, "Kilovolt Amperes Reactive"},
2822 { 13, "Megavolt Amperes Reactive"},
2823 { 14, "Degrees Phase"},
2824 { 15, "Power Factor"},
2825 { 16, "Joules"},
2826 { 17, "Kilojoules"},
2827 { 18, "Watt Hours"},
2828 { 19, "Kilowatt Hours"},
2829 { 20, "BTUs"},
2830 { 21, "Therms"},
2831 { 22, "Ton Hours"},
2832 { 23, "Joules Per Kg Dry Air"},
2833 { 24, "BTUs Per Pound Dry Air"},
2834 { 25, "Cycles Per Hour"},
2835 { 26, "Cycles Per Minute"},
2836 { 27, "Hertz"},
2837 { 28, "Grams Of Water Per Kilogram Dry Air"},
2838 { 29, "Relative Humidity"},
2839 { 30, "Millimeters"},
2840 { 31, "Meters"},
2841 { 32, "Inches"},
2842 { 33, "Feed"},
2843 { 34, "Watts Per Sq Foot"},
2844 { 35, "Watts Per Sq meter"},
2845 { 36, "Lumens"},
2846 { 37, "Lux"},
2847 { 38, "Foot Candles"},
2848 { 39, "Kilograms"},
2849 { 40, "Pounds Mass"},
2850 { 41, "Tons"},
2851 { 42, "Kgs per Second"},
2852 { 43, "Kgs Per Minute"},
2853 { 44, "Kgs Per Hour"},
2854 { 45, "Pounds Mass Per Minute"},
2855 { 46, "Pounds Mass Per Hour"},
2856 { 47, "Watt"},
2857 { 48, "Kilowatts"},
2858 { 49, "Megawatts"},
2859 { 50, "BTUs Per Hour"},
2860 { 51, "Horsepower"},
2861 { 52, "Tons Refrigeration"},
2862 { 53, "Pascals"},
2863 { 54, "Kilopascals"},
2864 { 55, "Bars"},
2865 { 56, "Pounds Force Per Square Inch"},
2866 { 57, "Centimeters Of Water"},
2867 { 58, "Inches Of Water"},
2868 { 59, "Millimeters Of Mercury"},
2869 { 60, "Centimeters Of Mercury"},
2870 { 61, "Inches Of Mercury"},
2871 { 62, "Degrees Celsius"},
2872 { 63, "Degrees Kelvin"},
2873 { 64, "Degrees Fahrenheit"},
2874 { 65, "Degree Days Celsius"},
2875 { 66, "Degree Days Fahrenheit"},
2876 { 67, "Years"},
2877 { 68, "Months"},
2878 { 69, "Weeks"},
2879 { 70, "Days"},
2880 { 71, "Hours"},
2881 { 72, "Minutes"},
2882 { 73, "Seconds"},
2883 { 74, "Meters Per Second"},
2884 { 75, "Kilometers Per Hour"},
2885 { 76, "Feed Per Second"},
2886 { 77, "Feet Per Minute"},
2887 { 78, "Miles Per Hour"},
2888 { 79, "Cubic Feet"},
2889 { 80, "Cubic Meters"},
2890 { 81, "Imperial Gallons"},
2891 { 82, "Liters"},
2892 { 83, "US Gallons"},
2893 { 84, "Cubic Feet Per Minute"},
2894 { 85, "Cubic Meters Per Second"},
2895 { 86, "Imperial Gallons Per Minute"},
2896 { 87, "Liters Per Second"},
2897 { 88, "Liters Per Minute"},
2898 { 89, "US Gallons Per Minute"},
2899 { 90, "Degrees Angular"},
2900 { 91, "Degrees Celsius Per Hour"},
2901 { 92, "Degrees Celsius Per Minute"},
2902 { 93, "Degrees Fahrenheit Per Hour"},
2903 { 94, "Degrees Fahrenheit Per Minute"},
2904 { 95, "No Units"},
2905 { 96, "Parts Per Million"},
2906 { 97, "Parts Per Billion"},
2907 { 98, "Percent"},
2908 { 99, "Pecent Per Second"},
2909 { 100, "Per Minute"},
2910 { 101, "Per Second"},
2911 { 102, "Psi Per Degree Fahrenheit"},
2912 { 103, "Radians"},
2913 { 104, "Revolutions Per Min"},
2914 { 105, "Currency1"},
2915 { 106, "Currency2"},
2916 { 107, "Currency3"},
2917 { 108, "Currency4"},
2918 { 109, "Currency5"},
2919 { 110, "Currency6"},
2920 { 111, "Currency7"},
2921 { 112, "Currency8"},
2922 { 113, "Currency9"},
2923 { 114, "Currency10"},
2924 { 115, "Sq Inches"},
2925 { 116, "Sq Centimeters"},
2926 { 117, "BTUs Per Pound"},
2927 { 118, "Centimeters"},
2928 { 119, "Pounds Mass Per Second"},
2929 { 120, "Delta Degrees Fahrenheit"},
2930 { 121, "Delta Degrees Kelvin"},
2931 { 122, "Kilohms"},
2932 { 123, "Megohms"},
2933 { 124, "Millivolts"},
2934 { 125, "Kilojoules Per Kg"},
2935 { 126, "Megajoules"},
2936 { 127, "Joules Per Degree Kelvin"},
2937 { 128, "Joules Per Kg Degree Kelvin"},
2938 { 129, "Kilohertz"},
2939 { 130, "Megahertz"},
2940 { 131, "Per Hour"},
2941 { 132, "Milliwatts"},
2942 { 133, "Hectopascals"},
2943 { 134, "Millibars"},
2944 { 135, "Cubic Meters Per Hour"},
2945 { 136, "Liters Per Hour"},
2946 { 137, "KWatt Hours Per Square Meter"},
2947 { 138, "KWatt Hours Per Square Foot"},
2948 { 139, "Megajoules Per Square Meter"},
2949 { 140, "Megajoules Per Square Foot"},
2950 { 141, "Watts Per Sq Meter Degree Kelvin"},
2951 { 142, "Cubic Feet Per Second"},
2952 { 143, "Percent Obstruction Per Foot"},
2953 { 144, "Percent Obstruction Per Meter"},
2954 { 145, "milliohms"},
2955 { 146, "megawatt-hours"},
2956 { 147, "kilo-btus"},
2957 { 148, "mega-btus"},
2958 { 149, "kilojoules-per-kilogram-dry-air"},
2959 { 150, "megajoules-per-kilogram-dry-air"},
2960 { 151, "kilojoules-per-degree-Kelvin"},
2961 { 152, "megajoules-per-degree-Kelvin"},
2962 { 153, "newton"},
2963 { 154, "grams-per-second"},
2964 { 155, "grams-per-minute"},
2965 { 156, "tons-per-hour"},
2966 { 157, "kilo-btus-per-hour"},
2967 { 158, "hundredths-seconds"},
2968 { 159, "milliseconds"},
2969 { 160, "newton-meters"},
2970 { 161, "millimeters-per-second"},
2971 { 162, "millimeters-per-minute"},
2972 { 163, "meters-per-minute"},
2973 { 164, "meters-per-hour"},
2974 { 165, "cubic-meters-per-minute"},
2975 { 166, "meters-per-second-per-second"},
2976 { 167, "amperes-per-meter"},
2977 { 168, "amperes-per-square-meter"},
2978 { 169, "ampere-square-meters"},
2979 { 170, "farads"},
2980 { 171, "henrys"},
2981 { 172, "ohm-meters"},
2982 { 173, "siemens"},
2983 { 174, "siemens-per-meter"},
2984 { 175, "teslas"},
2985 { 176, "volts-per-degree-Kelvin"},
2986 { 177, "volts-per-meter"},
2987 { 178, "webers"},
2988 { 179, "candelas"},
2989 { 180, "candelas-per-square-meter"},
2990 { 181, "degrees-Kelvin-per-hour"},
2991 { 182, "degrees-Kelvin-per-minute"},
2992 { 183, "joule-seconds"},
2993 { 184, "radians-per-second"},
2994 { 185, "square-meters-per-Newton"},
2995 { 186, "kilograms-per-cubic-meter"},
2996 { 187, "newton-seconds"},
2997 { 188, "newtons-per-meter"},
2998 { 189, "watts-per-meter-per-degree-Kelvin"},
2999 { 190, "micro-siemens"},
3000 { 191, "cubic-feet-per-hour"},
3001 { 192, "us-gallons-per-hour"},
3002 { 193, "kilometers"},
3003 { 194, "micrometers"},
3004 { 195, "grams"},
3005 { 196, "milligrams"},
3006 { 197, "milliliters"},
3007 { 198, "milliliters-per-second"},
3008 { 199, "decibels"},
3009 { 200, "decibels-millivolt"},
3010 { 201, "decibels-volt"},
3011 { 202, "millisiemens"},
3012 { 203, "watt-hours-reactive"},
3013 { 204, "kilowatt-hours-reactive"},
3014 { 205, "megawatt-hours-reactive"},
3015 { 206, "millimeters-of-water"},
3016 { 207, "per-mille"},
3017 { 208, "grams-per-gram"},
3018 { 209, "kilograms-per-kilogram"},
3019 { 210, "grams-per-kilogram"},
3020 { 211, "milligrams-per-gram"},
3021 { 212, "milligrams-per-kilogram"},
3022 { 213, "grams-per-milliliter"},
3023 { 214, "grams-per-liter"},
3024 { 215, "milligrams-per-liter"},
3025 { 216, "micrograms-per-liter"},
3026 { 217, "grams-per-cubic-meter"},
3027 { 218, "milligrams-per-cubic-meter"},
3028 { 219, "micrograms-per-cubic-meter"},
3029 { 220, "nanograms-per-cubic-meter"},
3030 { 221, "grams-per-cubic-centimeter"},
3031 { 222, "becquerels"},
3032 { 223, "kilobecquerels"},
3033 { 224, "megabecquerels"},
3034 { 225, "gray"},
3035 { 226, "milligray"},
3036 { 227, "microgray"},
3037 { 228, "sieverts"},
3038 { 229, "millisieverts"},
3039 { 230, "microsieverts"},
3040 { 231, "microsieverts-per-hour"},
3041 { 232, "decibels-a"},
3042 { 233, "nephelometric-turbidity-unit"},
3043 { 234, "pH"},
3044 { 235, "grams-per-square-meter"},
3045 { 236, "minutes-per-degree-kelvin"},
3046 { 0, NULL}
3047 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3048 Enumerated values 256-65535 may be used by others subject to
3049 the procedures and constraints described in Clause 23. */
3052 static const value_string
3053 BACnetErrorCode [] = {
3054 { 0, "other"},
3055 { 1, "authentication-failed"},
3056 { 2, "configuration-in-progress"},
3057 { 3, "device-busy"},
3058 { 4, "dynamic-creation-not-supported"},
3059 { 5, "file-access-denied"},
3060 { 6, "incompatible-security-levels"},
3061 { 7, "inconsistent-parameters"},
3062 { 8, "inconsistent-selection-criterion"},
3063 { 9, "invalid-data-type"},
3064 { 10, "invalid-file-access-method"},
3065 { 11, "invalid-file-start-position"},
3066 { 12, "invalid-operator-name"},
3067 { 13, "invalid-parameter-data-type"},
3068 { 14, "invalid-time-stamp"},
3069 { 15, "key-generation-error"},
3070 { 16, "missing-required-parameter"},
3071 { 17, "no-objects-of-specified-type"},
3072 { 18, "no-space-for-object"},
3073 { 19, "no-space-to-add-list-element"},
3074 { 20, "no-space-to-write-property"},
3075 { 21, "no-vt-sessions-available"},
3076 { 22, "property-is-not-a-list"},
3077 { 23, "object-deletion-not-permitted"},
3078 { 24, "object-identifier-already-exists"},
3079 { 25, "operational-problem"},
3080 { 26, "password-failure"},
3081 { 27, "read-access-denied"},
3082 { 28, "security-not-supported"},
3083 { 29, "service-request-denied"},
3084 { 30, "timeout"},
3085 { 31, "unknown-object"},
3086 { 32, "unknown-property"},
3087 { 33, "removed enumeration"},
3088 { 34, "unknown-vt-class"},
3089 { 35, "unknown-vt-session"},
3090 { 36, "unsupported-object-type"},
3091 { 37, "value-out-of-range"},
3092 { 38, "vt-session-already-closed"},
3093 { 39, "vt-session-termination-failure"},
3094 { 40, "write-access-denied"},
3095 { 41, "character-set-not-supported"},
3096 { 42, "invalid-array-index"},
3097 { 43, "cov-subscription-failed"},
3098 { 44, "not-cov-property"},
3099 { 45, "optional-functionality-not-supported"},
3100 { 46, "invalid-configuration-data"},
3101 { 47, "datatype-not-supported"},
3102 { 48, "duplicate-name"},
3103 { 49, "duplicate-object-id"},
3104 { 50, "property-is-not-an-array"},
3105 { 73, "invalid-event-state"},
3106 { 74, "no-alarm-configured"},
3107 { 75, "log-buffer-full"},
3108 { 76, "logged-value-purged"},
3109 { 77, "no-property-specified"},
3110 { 78, "not-configured-for-triggered-logging"},
3111 { 79, "unknown-subscription"},
3112 { 80, "parameter-out-of-range"},
3113 { 81, "list-element-not-found"},
3114 { 82, "busy"},
3115 { 83, "communication-disabled"},
3116 { 84, "success"},
3117 { 85, "access-denied"},
3118 { 86, "bad-destination-address"},
3119 { 87, "bad-destination-device-id"},
3120 { 88, "bad-signature"},
3121 { 89, "bad-source-address"},
3122 { 90, "bad-timestamp"},
3123 { 91, "cannot-use-key"},
3124 { 92, "cannot-verify-message-id"},
3125 { 93, "correct-key-revision"},
3126 { 94, "destination-device-id-required"},
3127 { 95, "duplicate-message"},
3128 { 96, "encryption-not-configured"},
3129 { 97, "encryption-required"},
3130 { 98, "incorrect-key"},
3131 { 99, "invalid-key-data"},
3132 { 100, "key-update-in-progress"},
3133 { 101, "malformed-message"},
3134 { 102, "not-key-server"},
3135 { 103, "security-not-configured"},
3136 { 104, "source-security-required"},
3137 { 105, "too-many-keys"},
3138 { 106, "unknown-authentication-type"},
3139 { 107, "unknown-key"},
3140 { 108, "unknown-key-revision"},
3141 { 109, "unknown-source-message"},
3142 { 110, "not-router-to-dnet"},
3143 { 111, "router-busy"},
3144 { 112, "unknown-network-message"},
3145 { 113, "message-too-long"},
3146 { 114, "security-error"},
3147 { 115, "addressing-error"},
3148 { 116, "write-bdt-failed"},
3149 { 117, "read-bdt-failed"},
3150 { 118, "register-foreign-device-failed"},
3151 { 119, "read-fdt-failed"},
3152 { 120, "delete-fdt-entry-failed"},
3153 { 121, "distribute-broadcast-failed"},
3154 { 122, "unknown-file-size"},
3155 { 123, "abort-apdu-too-long"},
3156 { 124, "abort-application-exceeded-reply-time"},
3157 { 125, "abort-out-of-resources"},
3158 { 126, "abort-tsm-timeout"},
3159 { 127, "abort-window-size-out-of-range"},
3160 { 128, "file-full"},
3161 { 129, "inconsistent-configuration"},
3162 { 130, "inconsistent-object-type"},
3163 { 131, "internal-error"},
3164 { 132, "not-configured"},
3165 { 133, "out-of-memory"},
3166 { 134, "value-too-long"},
3167 { 135, "abort-insufficient-security"},
3168 { 136, "abort-security-error"},
3169 { 0, NULL}
3170 /* Enumerated values 0-255 are reserved for definition by ASHRAE.
3171 Enumerated values 256-65535 may be used by others subject to the
3172 procedures and constraints described in Clause 23. */
3175 static const value_string
3176 BACnetPropertyIdentifier [] = {
3177 { 0, "acked-transition"},
3178 { 1, "ack-required"},
3179 { 2, "action"},
3180 { 3, "action-text"},
3181 { 4, "active-text"},
3182 { 5, "active-vt-session"},
3183 { 6, "alarm-value"},
3184 { 7, "alarm-values"},
3185 { 8, "all"},
3186 { 9, "all-write-successful"},
3187 { 10, "apdu-segment-timeout"},
3188 { 11, "apdu-timeout"},
3189 { 12, "application-software-version"},
3190 { 13, "archive"},
3191 { 14, "bias"},
3192 { 15, "change-of-state-count"},
3193 { 16, "change-of-state-time"},
3194 { 17, "notification-class"},
3195 { 18, "the property in this place was deleted"},
3196 { 19, "controlled-variable-reference"},
3197 { 20, "controlled-variable-units"},
3198 { 21, "controlled-variable-value"},
3199 { 22, "cov-increment"},
3200 { 23, "datelist"},
3201 { 24, "daylights-savings-status"},
3202 { 25, "deadband"},
3203 { 26, "derivative-constant"},
3204 { 27, "derivative-constant-units"},
3205 { 28, "description"},
3206 { 29, "description-of-halt"},
3207 { 30, "device-address-binding"},
3208 { 31, "device-type"},
3209 { 32, "effective-period"},
3210 { 33, "elapsed-active-time"},
3211 { 34, "error-limit"},
3212 { 35, "event-enable"},
3213 { 36, "event-state"},
3214 { 37, "event-type"},
3215 { 38, "exception-schedule"},
3216 { 39, "fault-values"},
3217 { 40, "feedback-value"},
3218 { 41, "file-access-method"},
3219 { 42, "file-size"},
3220 { 43, "file-type"},
3221 { 44, "firmware-revision"},
3222 { 45, "high-limit"},
3223 { 46, "inactive-text"},
3224 { 47, "in-progress"},
3225 { 48, "instance-of"},
3226 { 49, "integral-constant"},
3227 { 50, "integral-constant-units"},
3228 { 51, "issue-confirmed-notifications"},
3229 { 52, "limit-enable"},
3230 { 53, "list-of-group-members"},
3231 { 54, "list-of-object-property-references"},
3232 { 55, "list-of-session-keys"},
3233 { 56, "local-date"},
3234 { 57, "local-time"},
3235 { 58, "location"},
3236 { 59, "low-limit"},
3237 { 60, "manipulated-variable-reference"},
3238 { 61, "maximum-output"},
3239 { 62, "max-apdu-length-accepted"},
3240 { 63, "max-info-frames"},
3241 { 64, "max-master"},
3242 { 65, "max-pres-value"},
3243 { 66, "minimum-off-time"},
3244 { 67, "minimum-on-time"},
3245 { 68, "minimum-output"},
3246 { 69, "min-pres-value"},
3247 { 70, "model-name"},
3248 { 71, "modification-date"},
3249 { 72, "notify-type"},
3250 { 73, "number-of-APDU-retries"},
3251 { 74, "number-of-states"},
3252 { 75, "object-identifier"},
3253 { 76, "object-list"},
3254 { 77, "object-name"},
3255 { 78, "object-property-reference"},
3256 { 79, "object-type"},
3257 { 80, "optional"},
3258 { 81, "out-of-service"},
3259 { 82, "output-units"},
3260 { 83, "event-parameters"},
3261 { 84, "polarity"},
3262 { 85, "present-value"},
3263 { 86, "priority"},
3264 { 87, "priority-array"},
3265 { 88, "priority-for-writing"},
3266 { 89, "process-identifier"},
3267 { 90, "program-change"},
3268 { 91, "program-location"},
3269 { 92, "program-state"},
3270 { 93, "proportional-constant"},
3271 { 94, "proportional-constant-units"},
3272 { 95, "protocol-conformance-class"},
3273 { 96, "protocol-object-types-supported"},
3274 { 97, "protocol-services-supported"},
3275 { 98, "protocol-version"},
3276 { 99, "read-only"},
3277 { 100, "reason-for-halt"},
3278 { 101, "recipient"},
3279 { 102, "recipient-list"},
3280 { 103, "reliability"},
3281 { 104, "relinquish-default"},
3282 { 105, "required"},
3283 { 106, "resolution"},
3284 { 107, "segmentation-supported"},
3285 { 108, "setpoint"},
3286 { 109, "setpoint-reference"},
3287 { 110, "state-text"},
3288 { 111, "status-flags"},
3289 { 112, "system-status"},
3290 { 113, "time-delay"},
3291 { 114, "time-of-active-time-reset"},
3292 { 115, "time-of-state-count-reset"},
3293 { 116, "time-synchronization-recipients"},
3294 { 117, "units"},
3295 { 118, "update-interval"},
3296 { 119, "utc-offset"},
3297 { 120, "vendor-identifier"},
3298 { 121, "vendor-name"},
3299 { 122, "vt-class-supported"},
3300 { 123, "weekly-schedule"},
3301 { 124, "attempted-samples"},
3302 { 125, "average-value"},
3303 { 126, "buffer-size"},
3304 { 127, "client-cov-increment"},
3305 { 128, "cov-resubscription-interval"},
3306 { 129, "current-notify-time"},
3307 { 130, "event-time-stamp"},
3308 { 131, "log-buffer"},
3309 { 132, "log-device-object-property"},
3310 { 133, "enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
3311 { 134, "log-interval"},
3312 { 135, "maximum-value"},
3313 { 136, "minimum-value"},
3314 { 137, "notification-threshold"},
3315 { 138, "previous-notify-time"},
3316 { 139, "protocol-revision"},
3317 { 140, "records-since-notification"},
3318 { 141, "record-count"},
3319 { 142, "start-time"},
3320 { 143, "stop-time"},
3321 { 144, "stop-when-full"},
3322 { 145, "total-record-count"},
3323 { 146, "valid-samples"},
3324 { 147, "window-interval"},
3325 { 148, "window-samples"},
3326 { 149, "maximum-value-time-stamp"},
3327 { 150, "minimum-value-time-stamp"},
3328 { 151, "variance-value"},
3329 { 152, "active-cov-subscriptions"},
3330 { 153, "backup-failure-timeout"},
3331 { 154, "configuration-files"},
3332 { 155, "database-revision"},
3333 { 156, "direct-reading"},
3334 { 157, "last-restore-time"},
3335 { 158, "maintenance-required"},
3336 { 159, "member-of"},
3337 { 160, "mode"},
3338 { 161, "operation-expected"},
3339 { 162, "setting"},
3340 { 163, "silenced"},
3341 { 164, "tracking-value"},
3342 { 165, "zone-members"},
3343 { 166, "life-safety-alarm-values"},
3344 { 167, "max-segments-accepted"},
3345 { 168, "profile-name"},
3346 { 169, "auto-slave-discovery"},
3347 { 170, "manual-slave-address-binding"},
3348 { 171, "slave-address-binding"},
3349 { 172, "slave-proxy-enable"},
3350 { 173, "last-notify-record"}, /* bug 4117 */
3351 { 174, "schedule-default"},
3352 { 175, "accepted-modes"},
3353 { 176, "adjust-value"},
3354 { 177, "count"},
3355 { 178, "count-before-change"},
3356 { 179, "count-change-time"},
3357 { 180, "cov-period"},
3358 { 181, "input-reference"},
3359 { 182, "limit-monitoring-interval"},
3360 { 183, "logging-device"},
3361 { 184, "logging-record"},
3362 { 185, "prescale"},
3363 { 186, "pulse-rate"},
3364 { 187, "scale"},
3365 { 188, "scale-factor"},
3366 { 189, "update-time"},
3367 { 190, "value-before-change"},
3368 { 191, "value-set"},
3369 { 192, "value-change-time"},
3370 { 193, "align-intervals"},
3371 { 194, "group-member-names"},
3372 { 195, "interval-offset"},
3373 { 196, "last-restart-reason"},
3374 { 197, "logging-type"},
3375 { 198, "member-status-flags"},
3376 { 199, "notification-period"},
3377 { 200, "previous-notify-record"},
3378 { 201, "requested-update-interval"},
3379 { 202, "restart-notification-recipients"},
3380 { 203, "time-of-device-restart"},
3381 { 204, "time-synchronization-interval"},
3382 { 205, "trigger"},
3383 { 206, "UTC-time-synchronization-recipients"},
3384 { 207, "node-subtype"},
3385 { 208, "node-type"},
3386 { 209, "structured-object-list"},
3387 { 210, "subordinate-annotations"},
3388 { 211, "subordinate-list"},
3389 { 212, "actual-shed-level"},
3390 { 213, "duty-window"},
3391 { 214, "expected-shed-level"},
3392 { 215, "full-duty-baseline"},
3393 { 216, "node-subtype"},
3394 { 217, "node-type"},
3395 { 218, "requested-shed-level"},
3396 { 219, "shed-duration"},
3397 { 220, "shed-level-descriptions"},
3398 { 221, "shed-levels"},
3399 { 222, "state-description"},
3400 /* enumeration values 223-225 are unassigned */
3401 { 226, "door-alarm-state"},
3402 { 227, "door-extended-pulse-time"},
3403 { 228, "door-members"},
3404 { 229, "door-open-too-long-time"},
3405 { 230, "door-pulse-time"},
3406 { 231, "door-status"},
3407 { 232, "door-unlock-delay-time"},
3408 { 233, "lock-status"},
3409 { 234, "masked-alarm-values"},
3410 { 235, "secured-status"},
3411 /* enumeration values 236-243 are unassigned */
3412 { 244, "absentee-limit"}, /* added with addenda 135-2008j */
3413 { 245, "access-alarm-events"},
3414 { 246, "access-doors"},
3415 { 247, "access-event"},
3416 { 248, "access-event-authentication-factor"},
3417 { 249, "access-event-credential"},
3418 { 250, "access-event-time"},
3419 { 251, "access-transaction-events"},
3420 { 252, "accompaniment"},
3421 { 253, "accompaniment-time"},
3422 { 254, "activation-time"},
3423 { 255, "active-authentication-policy"},
3424 { 256, "assigned-access-rights"},
3425 { 257, "authentication-factors"},
3426 { 258, "authentication-policy-list"},
3427 { 259, "authentication-policy-names"},
3428 { 260, "authentication-status"},
3429 { 261, "authorization-mode"},
3430 { 262, "belongs-to"},
3431 { 263, "credential-disable"},
3432 { 264, "credential-status"},
3433 { 265, "credentials"},
3434 { 266, "credentials-in-zone"},
3435 { 267, "days-remaining"},
3436 { 268, "entry-points"},
3437 { 269, "exit-points"},
3438 { 270, "expiry-time"},
3439 { 271, "extended-time-enable"},
3440 { 272, "failed-attempt-events"},
3441 { 273, "failed-attempts"},
3442 { 274, "failed-attempts-time"},
3443 { 275, "last-access-event"},
3444 { 276, "last-access-point"},
3445 { 277, "last-credential-added"},
3446 { 278, "last-credential-added-time"},
3447 { 279, "last-credential-removed"},
3448 { 280, "last-credential-removed-time"},
3449 { 281, "last-use-time"},
3450 { 282, "lockout"},
3451 { 283, "lockout-relinquish-time"},
3452 { 284, "master-exemption"},
3453 { 285, "max-failed-attempts"},
3454 { 286, "members"},
3455 { 287, "muster-point"},
3456 { 288, "negative-access-rules"},
3457 { 289, "number-of-authentication-policies"},
3458 { 290, "occupancy-count"},
3459 { 291, "occupancy-count-adjust"},
3460 { 292, "occupancy-count-enable"},
3461 { 293, "occupancy-exemption"},
3462 { 294, "occupancy-lower-limit"},
3463 { 295, "occupancy-lower-limit-enforced"},
3464 { 296, "occupancy-state"},
3465 { 297, "occupancy-upper-limit"},
3466 { 298, "occupancy-upper-limit-enforced"},
3467 { 299, "passback-exemption"},
3468 { 300, "passback-mode"},
3469 { 301, "passback-timeout"},
3470 { 302, "positive-access-rules"},
3471 { 303, "reason-for-disable"},
3472 { 304, "supported-formats"},
3473 { 305, "supported-format-classes"},
3474 { 306, "threat-authority"},
3475 { 307, "threat-level"},
3476 { 308, "trace-flag"},
3477 { 309, "transaction-notification-class"},
3478 { 310, "user-external-identifier"},
3479 { 311, "user-information-reference"},
3480 /* enumeration values 312-316 are unassigned */
3481 { 317, "user-name"},
3482 { 318, "user-type"},
3483 { 319, "uses-remaining"},
3484 { 320, "zone-from"},
3485 { 321, "zone-to"},
3486 { 322, "access-event-tag"},
3487 { 323, "global-identifier"},
3488 /* enumeration values 324-325 reserved for future addenda */
3489 { 326, "verification-time"},
3490 { 327, "base-device-security-policy"},
3491 { 328, "distribution-key-revision"},
3492 { 329, "do-not-hide"},
3493 { 330, "key-sets"},
3494 { 331, "last-key-server"},
3495 { 332, "network-access-security-policies"},
3496 { 333, "packet-reorder-time"},
3497 { 334, "security-pdu-timeout"},
3498 { 335, "security-time-window"},
3499 { 336, "supported-security-algorithms"},
3500 { 337, "update-key-set-timeout"},
3501 { 338, "backup-and-restore-state"},
3502 { 339, "backup-preparation-time"},
3503 { 340, "restore-completion-time"},
3504 { 341, "restore-preparation-time"},
3505 { 342, "bit-mask"}, /* addenda 135-2008w */
3506 { 343, "bit-text"},
3507 { 344, "is-utc"},
3508 { 345, "group-members"},
3509 { 346, "group-member-names"},
3510 { 347, "member-status-flags"},
3511 { 348, "requested-update-interval"},
3512 { 349, "covu-period"},
3513 { 350, "covu-recipients"},
3514 { 351, "event-message-texts"},
3515 { 0, NULL}
3516 /* Enumerated values 0-511 are reserved for definition by ASHRAE.
3517 Enumerated values 512-4194303 may be used by others subject to
3518 the procedures and constraints described in Clause 23. */
3521 static const value_string
3522 BACnetBinaryPV [] = {
3523 { 0, "inactive"},
3524 { 1, "active"},
3525 { 0, NULL}
3529 #define ANSI_X34 0
3530 #define IBM_MS_DBCS 1
3531 #define JIS_C_6226 2
3532 #define ISO_10646_UCS4 3
3533 #define ISO_10646_UCS2 4
3534 #define ISO_18859_1 5
3535 static const value_string
3536 BACnetCharacterSet [] = {
3537 { ANSI_X34, "ANSI X3.4 / UTF-8 (since 2010)"},
3538 { IBM_MS_DBCS, "IBM/Microsoft DBCS"},
3539 { JIS_C_6226, "JIS C 6226"},
3540 { ISO_10646_UCS4, "ISO 10646(UCS-4)"},
3541 { ISO_10646_UCS2, "ISO 10646(UCS-2)"},
3542 { ISO_18859_1, "ISO 18859-1"},
3543 { 0, NULL}
3546 static const value_string
3547 BACnetStatusFlags [] = {
3548 { 0, "in-alarm"},
3549 { 1, "fault"},
3550 { 2, "overridden"},
3551 { 3, "out-of-service"},
3552 { 0, NULL}
3555 static const value_string
3556 BACnetMessagePriority [] = {
3557 { 0, "normal"},
3558 { 1, "urgent"},
3559 { 0, NULL}
3562 static const value_string
3563 BACnetAcknowledgementFilter [] = {
3564 { 0, "all"},
3565 { 1, "acked"},
3566 { 2, "not-acked"},
3567 { 0, NULL}
3570 static const value_string
3571 BACnetResultFlags [] = {
3572 { 0, "firstitem"},
3573 { 1, "lastitem"},
3574 { 2, "moreitems"},
3575 { 0, NULL}
3578 static const value_string
3579 BACnetRelationSpecifier [] = {
3580 { 0, "equal"},
3581 { 1, "not-equal"},
3582 { 2, "less-than"},
3583 { 3, "greater-than"},
3584 { 4, "less-than-or-equal"},
3585 { 5, "greater-than-or-equal"},
3586 { 0, NULL}
3589 static const value_string
3590 BACnetSelectionLogic [] = {
3591 { 0, "and"},
3592 { 1, "or"},
3593 { 2, "all"},
3594 { 0, NULL}
3597 static const value_string
3598 BACnetEventStateFilter [] = {
3599 { 0, "offnormal"},
3600 { 1, "fault"},
3601 { 2, "normal"},
3602 { 3, "all"},
3603 { 4, "active"},
3604 { 0, NULL}
3607 static const value_string
3608 BACnetEventTransitionBits [] = {
3609 { 0, "to-offnormal"},
3610 { 1, "to-fault"},
3611 { 2, "to-normal"},
3612 { 0, NULL}
3615 static const value_string
3616 BACnetSegmentation [] = {
3617 { 0, "segmented-both"},
3618 { 1, "segmented-transmit"},
3619 { 2, "segmented-receive"},
3620 { 3, "no-segmentation"},
3621 { 0, NULL}
3624 static const value_string
3625 BACnetSilencedState [] = {
3626 { 0, "unsilenced"},
3627 { 1, "audible-silenced"},
3628 { 2, "visible-silenced"},
3629 { 3, "all-silenced"},
3630 { 0, NULL}
3633 static const value_string
3634 BACnetDeviceStatus [] = {
3635 { 0, "operational"},
3636 { 1, "operational-read-only"},
3637 { 2, "download-required"},
3638 { 3, "download-in-progress"},
3639 { 4, "non-operational"},
3640 { 5, "backup-in-progress"},
3641 { 0, NULL}
3644 static const value_string
3645 BACnetEnableDisable [] = {
3646 { 0, "enable"},
3647 { 1, "disable"},
3648 { 2, "disable-initiation"},
3649 { 0, NULL}
3652 static const value_string
3653 months [] = {
3654 { 1, "January" },
3655 { 2, "February" },
3656 { 3, "March" },
3657 { 4, "April" },
3658 { 5, "May" },
3659 { 6, "June" },
3660 { 7, "July" },
3661 { 8, "August" },
3662 { 9, "September" },
3663 { 10, "October" },
3664 { 11, "November" },
3665 { 12, "December" },
3666 { 255, "any month" },
3667 { 0, NULL }
3670 static const value_string
3671 weekofmonth [] = {
3672 { 1, "days numbered 1-7" },
3673 { 2, "days numbered 8-14" },
3674 { 3, "days numbered 15-21" },
3675 { 4, "days numbered 22-28" },
3676 { 5, "days numbered 29-31" },
3677 { 6, "last 7 days of this month" },
3678 { 255, "any week of this month" },
3679 { 0, NULL }
3682 /* note: notification class object recipient-list uses
3683 different day-of-week enum */
3684 static const value_string
3685 day_of_week [] = {
3686 { 1, "Monday" },
3687 { 2, "Tuesday" },
3688 { 3, "Wednesday" },
3689 { 4, "Thursday" },
3690 { 5, "Friday" },
3691 { 6, "Saturday" },
3692 { 7, "Sunday" },
3693 { 255, "any day of week" },
3694 { 0, NULL }
3697 static const value_string
3698 BACnetErrorClass [] = {
3699 { 0, "device" },
3700 { 1, "object" },
3701 { 2, "property" },
3702 { 3, "resources" },
3703 { 4, "security" },
3704 { 5, "services" },
3705 { 6, "vt" },
3706 { 7, "communication" },
3707 { 0, NULL }
3708 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3709 Enumerated values64-65535 may be used by others subject to
3710 the procedures and constraints described in Clause 23. */
3713 static const value_string
3714 BACnetVTClass [] = {
3715 { 0, "default-terminal" },
3716 { 1, "ansi-x3-64" },
3717 { 2, "dec-vt52" },
3718 { 3, "dec-vt100" },
3719 { 4, "dec-vt200" },
3720 { 5, "hp-700-94" },
3721 { 6, "ibm-3130" },
3722 { 0, NULL }
3725 static const value_string
3726 BACnetEventType [] = {
3727 { 0, "change-of-bitstring" },
3728 { 1, "change-of-state" },
3729 { 2, "change-of-value" },
3730 { 3, "command-failure" },
3731 { 4, "floating-limit" },
3732 { 5, "out-of-range" },
3733 { 6, "complex-event-type" },
3734 { 7, "(deprecated)buffer-ready" },
3735 { 8, "change-of-life-safety" },
3736 { 9, "extended" },
3737 { 10, "buffer-ready" },
3738 { 11, "unsigned-range" },
3739 { 14, "double-out-of-range"}, /* added with addenda 135-2008w */
3740 { 15, "signed-out-of-range"},
3741 { 16, "unsigned-out-of-range"},
3742 { 17, "change-of-characterstring"},
3743 { 18, "change-of-status-flags"},
3744 { 0, NULL }
3745 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3746 Enumerated values 64-65535 may be used by others subject to
3747 the procedures and constraints described in Clause 23.
3748 It is expected that these enumerated values will correspond
3749 to the use of the complex-event-type CHOICE [6] of the
3750 BACnetNotificationParameters production. */
3753 static const value_string
3754 BACnetEventState [] = {
3755 { 0, "normal" },
3756 { 1, "fault" },
3757 { 2, "offnormal" },
3758 { 3, "high-limit" },
3759 { 4, "low-limit" },
3760 { 5, "life-safety-alarm" },
3761 { 0, NULL }
3762 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3763 Enumerated values 64-65535 may be used by others subject to
3764 the procedures and constraints described in Clause 23. */
3767 static const value_string
3768 BACnetLogStatus [] = {
3769 { 0, "log-disabled" },
3770 { 1, "buffer-purged" },
3771 { 2, "log-interrupted"},
3772 { 0, NULL }
3775 static const value_string
3776 BACnetMaintenance [] = {
3777 { 0, "none" },
3778 { 1, "periodic-test" },
3779 { 2, "need-service-operational" },
3780 { 3, "need-service-inoperative" },
3781 { 0, NULL }
3784 static const value_string
3785 BACnetNotifyType [] = {
3786 { 0, "alarm" },
3787 { 1, "event" },
3788 { 2, "ack-notification" },
3789 { 0, NULL }
3792 static const value_string
3793 BACnetServicesSupported [] = {
3794 { 0, "acknowledgeAlarm"},
3795 { 1, "confirmedCOVNotification"},
3796 { 2, "confirmedEventNotification"},
3797 { 3, "getAlarmSummary"},
3798 { 4, "getEnrollmentSummary"},
3799 { 5, "subscribeCOV"},
3800 { 6, "atomicReadFile"},
3801 { 7, "atomicWriteFile"},
3802 { 8, "addListElement"},
3803 { 9, "removeListElement"},
3804 { 10, "createObject"},
3805 { 11, "deleteObject"},
3806 { 12, "readProperty"},
3807 { 13, "readPropertyConditional"},
3808 { 14, "readPropertyMultiple"},
3809 { 15, "writeProperty"},
3810 { 16, "writePropertyMultiple"},
3811 { 17, "deviceCommunicationControl"},
3812 { 18, "confirmedPrivateTransfer"},
3813 { 19, "confirmedTextMessage"},
3814 { 20, "reinitializeDevice"},
3815 { 21, "vtOpen"},
3816 { 22, "vtClose"},
3817 { 23, "vtData"},
3818 { 24, "authenticate"},
3819 { 25, "requestKey"},
3820 { 26, "i-Am"},
3821 { 27, "i-Have"},
3822 { 28, "unconfirmedCOVNotification"},
3823 { 29, "unconfirmedEventNotification"},
3824 { 30, "unconfirmedPrivateTransfer"},
3825 { 31, "unconfirmedTextMessage"},
3826 { 32, "timeSynchronization"},
3827 { 33, "who-Has"},
3828 { 34, "who-Is"},
3829 { 35, "readRange"},
3830 { 36, "utcTimeSynchronization"},
3831 { 37, "lifeSafetyOperation"},
3832 { 38, "subscribeCOVProperty"},
3833 { 39, "getEventInformation"},
3834 { 0, NULL}
3837 static const value_string
3838 BACnetPropertyStates [] = {
3839 { 0, "boolean-value"},
3840 { 1, "binary-value"},
3841 { 2, "event-type"},
3842 { 3, "polarity"},
3843 { 4, "program-change"},
3844 { 5, "program-state"},
3845 { 6, "reason-for-halt"},
3846 { 7, "reliability"},
3847 { 8, "state"},
3848 { 9, "system-status"},
3849 { 10, "units"},
3850 { 11, "unsigned-value"},
3851 { 12, "life-safety-mode"},
3852 { 13, "life-safety-state"},
3853 { 14, "restart-reason"},
3854 { 15, "door-alarm-state"},
3855 { 16, "action"},
3856 { 17, "door-secured-status"},
3857 { 18, "door-status"},
3858 { 19, "door-value"},
3859 { 20, "file-access-method"},
3860 { 21, "lock-status"},
3861 { 22, "life-safety-operation"},
3862 { 23, "maintenance"},
3863 { 24, "node-type"},
3864 { 25, "notify-type"},
3865 { 26, "security-level"},
3866 { 27, "shed-state"},
3867 { 28, "silenced-state"},
3868 /* context tag 29 reserved for future addenda */
3869 { 29, "unknown-29"},
3870 { 30, "access-event"},
3871 { 31, "zone-occupancy-state"},
3872 { 32, "access-credential-disable-reason"},
3873 { 33, "access-credential-disable"},
3874 { 34, "authentication-status"},
3875 { 35, "unknown-35"},
3876 { 36, "backup-state"},
3877 { 0, NULL}
3878 /* Tag values 0-63 are reserved for definition by ASHRAE.
3879 Tag values of 64-254 may be used by others to accommodate
3880 vendor specific properties that have discrete or enumerated values,
3881 subject to the constraints described in Clause 23. */
3884 static const value_string
3885 BACnetProgramError [] = {
3886 { 0, "normal"},
3887 { 1, "load-failed"},
3888 { 2, "internal"},
3889 { 3, "program"},
3890 { 4, "other"},
3891 { 0, NULL}
3892 /* Enumerated values 0-63 are reserved for definition by ASHRAE.
3893 Enumerated values 64-65535 may be used by others subject to
3894 the procedures and constraints described in Clause 23. */
3897 static const value_string
3898 BACnetProgramRequest [] = {
3899 { 0, "ready"},
3900 { 1, "load"},
3901 { 2, "run"},
3902 { 3, "halt"},
3903 { 4, "restart"},
3904 { 4, "unload"},
3905 { 0, NULL}
3908 static const value_string
3909 BACnetProgramState [] = {
3910 { 0, "idle"},
3911 { 1, "loading"},
3912 { 2, "running"},
3913 { 3, "waiting"},
3914 { 4, "halted"},
3915 { 4, "unloading"},
3916 { 0, NULL}
3919 static const value_string
3920 BACnetReinitializedStateOfDevice [] = {
3921 { 0, "coldstart"},
3922 { 1, "warmstart"},
3923 { 2, "startbackup"},
3924 { 3, "endbackup"},
3925 { 4, "startrestore"},
3926 { 5, "endrestore"},
3927 { 6, "abortrestore"},
3928 { 0, NULL}
3931 static const value_string
3932 BACnetPolarity [] = {
3933 { 0, "normal"},
3934 { 1, "reverse"},
3935 { 0, NULL}
3938 static const value_string
3939 BACnetTagNames[] = {
3940 { 5, "Extended Value" },
3941 { 6, "Opening Tag" },
3942 { 7, "Closing Tag" },
3943 { 0, NULL }
3946 static const value_string
3947 BACnetReadRangeOptions[] = {
3948 { 3, "range byPosition" },
3949 { 4, "range byTime" },
3950 { 5, "range timeRange" },
3951 { 6, "range bySequenceNumber" },
3952 { 7, "range byTime" },
3953 { 0, NULL }
3956 /* Present_Value for Load Control Object */
3957 static const value_string
3958 BACnetShedState[] = {
3959 { 0, "shed-inactive" },
3960 { 1, "shed-request-pending" },
3961 { 2, "shed-compliant" },
3962 { 3, "shed-non-compliant" },
3963 { 0, NULL }
3966 static const value_string
3967 BACnetNodeType [] = {
3968 { 0, "unknown" },
3969 { 1, "system" },
3970 { 2, "network" },
3971 { 3, "device" },
3972 { 4, "organizational" },
3973 { 5, "area" },
3974 { 6, "equipment" },
3975 { 7, "point" },
3976 { 8, "collection" },
3977 { 9, "property" },
3978 { 10, "functional" },
3979 { 11, "other" },
3980 { 0, NULL }
3983 static const value_string
3984 BACnetLoggingType [] = {
3985 { 0, "polled" },
3986 { 1, "cov" },
3987 { 2, "triggered" },
3988 { 0, NULL }
3991 static const value_string
3992 BACnetDoorStatus [] = {
3993 { 0, "closed" },
3994 { 1, "opened" },
3995 { 2, "unknown" },
3996 { 0, NULL }
3999 static const value_string
4000 BACnetLockStatus [] = {
4001 { 0, "locked" },
4002 { 1, "unlocked" },
4003 { 2, "fault" },
4004 { 3, "unknown" },
4005 { 0, NULL }
4008 static const value_string
4009 BACnetDoorSecuredStatus [] = {
4010 { 0, "secured" },
4011 { 1, "unsecured" },
4012 { 2, "unknown" },
4013 { 0, NULL }
4016 static const value_string
4017 BACnetDoorAlarmState [] = {
4018 { 0, "normal" },
4019 { 1, "alarm" },
4020 { 2, "door-open-too-long" },
4021 { 3, "forced-open" },
4022 { 4, "tamper" },
4023 { 5, "door-fault" },
4024 { 6, "lock-down" },
4025 { 7, "free-access" },
4026 { 8, "egress-open" },
4027 { 0, NULL }
4030 static const value_string
4031 BACnetAccumulatorStatus [] = {
4032 { 0, "normal" },
4033 { 1, "starting" },
4034 { 2, "recovered" },
4035 { 3, "abnormal" },
4036 { 4, "failed" },
4037 { 0, NULL }
4040 /* These values are (manually) transferred from
4041 * http://www.bacnet.org/VendorID/BACnet Vendor IDs.htm
4042 * Version: "As of September 16, 2013"
4045 static const value_string
4046 BACnetVendorIdentifiers [] = {
4047 { 0, "ASHRAE" },
4048 { 1, "NIST" },
4049 { 2, "The Trane Company" },
4050 { 3, "McQuay International" },
4051 { 4, "PolarSoft" },
4052 { 5, "Johnson Controls, Inc." },
4053 { 6, "American Auto-Matrix" },
4054 { 7, "Siemens Schweiz AG (Formerly: Landis & Staefa Division Europe)" },
4055 { 8, "Delta Controls" },
4056 { 9, "Siemens Schweiz AG" },
4057 { 10, "Tour Andover Controls Corporation" },
4058 { 11, "TAC" },
4059 { 12, "Orion Analysis Corporation" },
4060 { 13, "Teletrol Systems Inc." },
4061 { 14, "Cimetrics Technology" },
4062 { 15, "Cornell University" },
4063 { 16, "United Technologies Carrier" },
4064 { 17, "Honeywell Inc." },
4065 { 18, "Alerton / Honeywell" },
4066 { 19, "TAC AB" },
4067 { 20, "Hewlett-Packard Company" },
4068 { 21, "Dorsette's Inc." },
4069 { 22, "Siemens Schweiz AG (Formerly: Cerberus AG)" },
4070 { 23, "York Controls Group" },
4071 { 24, "Automated Logic Corporation" },
4072 { 25, "CSI Control Systems International" },
4073 { 26, "Phoenix Controls Corporation" },
4074 { 27, "Innovex Technologies, Inc." },
4075 { 28, "KMC Controls, Inc." },
4076 { 29, "Xn Technologies, Inc." },
4077 { 30, "Hyundai Information Technology Co., Ltd." },
4078 { 31, "Tokimec Inc." },
4079 { 32, "Simplex" },
4080 { 33, "North Building Technologies Limited" },
4081 { 34, "Notifier" },
4082 { 35, "Reliable Controls Corporation" },
4083 { 36, "Tridium Inc." },
4084 { 37, "Sierra Monitor Corporation/FieldServer Technologies" },
4085 { 38, "Silicon Energy" },
4086 { 39, "Kieback & Peter GmbH & Co KG" },
4087 { 40, "Anacon Systems, Inc." },
4088 { 41, "Systems Controls & Instruments, LLC" },
4089 { 42, "Lithonia Lighting" },
4090 { 43, "Micropower Manufacturing" },
4091 { 44, "Matrix Controls" },
4092 { 45, "METALAIRE" },
4093 { 46, "ESS Engineering" },
4094 { 47, "Sphere Systems Pty Ltd." },
4095 { 48, "Walker Technologies Corporation" },
4096 { 49, "H I Solutions, Inc." },
4097 { 50, "MBS GmbH" },
4098 { 51, "SAMSON AG" },
4099 { 52, "Badger Meter Inc." },
4100 { 53, "DAIKIN Industries Ltd." },
4101 { 54, "NARA Controls Inc." },
4102 { 55, "Mammoth Inc." },
4103 { 56, "Liebert Corporation" },
4104 { 57, "SEMCO Incorporated" },
4105 { 58, "Air Monitor Corporation" },
4106 { 59, "TRIATEK, LLC" },
4107 { 60, "NexLight" },
4108 { 61, "Multistack" },
4109 { 62, "TSI Incorporated" },
4110 { 63, "Weather-Rite, Inc." },
4111 { 64, "Dunham-Bush" },
4112 { 65, "Reliance Electric" },
4113 { 66, "LCS Inc." },
4114 { 67, "Regulator Australia PTY Ltd." },
4115 { 68, "Touch-Plate Lighting Controls" },
4116 { 69, "Amann GmbH" },
4117 { 70, "RLE Technologies" },
4118 { 71, "Cardkey Systems" },
4119 { 72, "SECOM Co., Ltd." },
4120 { 73, "ABB Gebaudetechnik AG Bereich NetServ" },
4121 { 74, "KNX Association cvba" },
4122 { 75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
4123 { 76, "Nohmi Bosai, Ltd." },
4124 { 77, "Carel S.p.A." },
4125 { 78, "AirSense Technology, Inc." },
4126 { 79, "Hochiki Corporation" },
4127 { 80, "Fr. Sauter AG" },
4128 { 81, "Matsushita Electric Works, Ltd." },
4129 { 82, "Mitsubishi Electric Corporation, Inazawa Works" },
4130 { 83, "Mitsubishi Heavy Industries, Ltd." },
4131 { 84, "ITT Bell & Gossett" },
4132 { 85, "Yamatake Building Systems Co., Ltd." },
4133 { 86, "The Watt Stopper, Inc." },
4134 { 87, "Aichi Tokei Denki Co., Ltd." },
4135 { 88, "Activation Technologies, LLC" },
4136 { 89, "Saia-Burgess Controls, Ltd." },
4137 { 90, "Hitachi, Ltd." },
4138 { 91, "Novar Corp./Trend Control Systems Ltd." },
4139 { 92, "Mitsubishi Electric Lighting Corporation" },
4140 { 93, "Argus Control Systems, Ltd." },
4141 { 94, "Kyuki Corporation" },
4142 { 95, "Richards-Zeta Building Intelligence, Inc." },
4143 { 96, "Scientech R&D, Inc." },
4144 { 97, "VCI Controls, Inc." },
4145 { 98, "Toshiba Corporation" },
4146 { 99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
4147 { 100, "Custom Mechanical Equipment, LLC" },
4148 { 101, "ClimateMaster" },
4149 { 102, "ICP Panel-Tec, Inc." },
4150 { 103, "D-Tek Controls" },
4151 { 104, "NEC Engineering, Ltd." },
4152 { 105, "PRIVA BV" },
4153 { 106, "Meidensha Corporation" },
4154 { 107, "JCI Systems Integration Services" },
4155 { 108, "Freedom Corporation" },
4156 { 109, "Neuberger Gebaudeautomation GmbH" },
4157 { 110, "Sitronix" },
4158 { 111, "Leviton Manufacturing" },
4159 { 112, "Fujitsu Limited" },
4160 { 113, "Emerson Network Power" },
4161 { 114, "S. A. Armstrong, Ltd." },
4162 { 115, "Visonet AG" },
4163 { 116, "M&M Systems, Inc." },
4164 { 117, "Custom Software Engineering" },
4165 { 118, "Nittan Company, Limited" },
4166 { 119, "Elutions Inc. (Wizcon Systems SAS)" },
4167 { 120, "Pacom Systems Pty., Ltd." },
4168 { 121, "Unico, Inc." },
4169 { 122, "Ebtron, Inc." },
4170 { 123, "Scada Engine" },
4171 { 124, "AC Technology Corporation" },
4172 { 125, "Eagle Technology" },
4173 { 126, "Data Aire, Inc." },
4174 { 127, "ABB, Inc." },
4175 { 128, "Transbit Sp. z o. o." },
4176 { 129, "Toshiba Carrier Corporation" },
4177 { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
4178 { 131, "Tokai Soft" },
4179 { 132, "Blue Ridge Technologies" },
4180 { 133, "Veris Industries" },
4181 { 134, "Centaurus Prime" },
4182 { 135, "Sand Network Systems" },
4183 { 136, "Regulvar, Inc." },
4184 { 137, "AFDtek Division of Fastek International Inc." },
4185 { 138, "PowerCold Comfort Air Solutions, Inc." },
4186 { 139, "I Controls" },
4187 { 140, "Viconics Electronics, Inc." },
4188 { 141, "Yaskawa America, Inc." },
4189 { 142, "DEOS control systems GmbH" },
4190 { 143, "Digitale Mess- und Steuersysteme AG" },
4191 { 144, "Fujitsu General Limited" },
4192 { 145, "Project Engineering S.r.l." },
4193 { 146, "Sanyo Electric Co., Ltd." },
4194 { 147, "Integrated Information Systems, Inc." },
4195 { 148, "Temco Controls, Ltd." },
4196 { 149, "Airtek International Inc." },
4197 { 150, "Advantech Corporation" },
4198 { 151, "Titan Products, Ltd." },
4199 { 152, "Regel Partners" },
4200 { 153, "National Environmental Product" },
4201 { 154, "Unitec Corporation" },
4202 { 155, "Kanden Engineering Company" },
4203 { 156, "Messner Gebaudetechnik GmbH" },
4204 { 157, "Integrated.CH" },
4205 { 158, "EH Price Limited" },
4206 { 159, "SE-Elektronic GmbH" },
4207 { 160, "Rockwell Automation" },
4208 { 161, "Enflex Corp." },
4209 { 162, "ASI Controls" },
4210 { 163, "SysMik GmbH Dresden" },
4211 { 164, "HSC Regelungstechnik GmbH" },
4212 { 165, "Smart Temp Australia Pty. Ltd." },
4213 { 166, "Cooper Controls" },
4214 { 167, "Duksan Mecasys Co., Ltd." },
4215 { 168, "Fuji IT Co., Ltd." },
4216 { 169, "Vacon Plc" },
4217 { 170, "Leader Controls" },
4218 { 171, "Cylon Controls, Ltd." },
4219 { 172, "Compas" },
4220 { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
4221 { 174, "Building Control Integrators" },
4222 { 175, "ITG Worldwide (M) Sdn Bhd" },
4223 { 176, "Lutron Electronics Co., Inc." },
4224 { 178, "LOYTEC Electronics GmbH" },
4225 { 179, "ProLon" },
4226 { 180, "Mega Controls Limited" },
4227 { 181, "Micro Control Systems, Inc." },
4228 { 182, "Kiyon, Inc." },
4229 { 183, "Dust Networks" },
4230 { 184, "Advanced Building Automation Systems" },
4231 { 185, "Hermos AG" },
4232 { 186, "CEZIM" },
4233 { 187, "Softing" },
4234 { 188, "Lynxspring" },
4235 { 189, "Schneider Toshiba Inverter Europe" },
4236 { 190, "Danfoss Drives A/S" },
4237 { 191, "Eaton Corporation" },
4238 { 192, "Matyca S.A." },
4239 { 193, "Botech AB" },
4240 { 194, "Noveo, Inc." },
4241 { 195, "AMEV" },
4242 { 196, "Yokogawa Electric Corporation" },
4243 { 197, "GFR Gesellschaft fur Regelungstechnik" },
4244 { 198, "Exact Logic" },
4245 { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
4246 { 200, "Kandenko Co., Ltd." },
4247 { 201, "DTF, Daten-Technik Fries" },
4248 { 202, "Klimasoft, Ltd." },
4249 { 203, "Toshiba Schneider Inverter Corporation" },
4250 { 204, "Control Applications, Ltd." },
4251 { 205, "KDT Systems Co., Ltd." },
4252 { 206, "Onicon Incorporated" },
4253 { 207, "Automation Displays, Inc." },
4254 { 208, "Control Solutions, Inc." },
4255 { 209, "Remsdaq Limited" },
4256 { 210, "NTT Facilities, Inc." },
4257 { 211, "VIPA GmbH" },
4258 { 212, "TSC21 Association of Japan" },
4259 { 213, "Strato Automation" },
4260 { 214, "HRW Limited" },
4261 { 215, "Lighting Control & Design, Inc." },
4262 { 216, "Mercy Electronic and Electrical Industries" },
4263 { 217, "Samsung SDS Co., Ltd" },
4264 { 218, "Impact Facility Solutions, Inc." },
4265 { 219, "Aircuity" },
4266 { 220, "Control Techniques, Ltd." },
4267 { 221, "OpenGeneral Pty., Ltd." },
4268 { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
4269 { 223, "Cerus Industrial" },
4270 { 224, "Chloride Power Protection Company" },
4271 { 225, "Computrols, Inc." },
4272 { 226, "Phoenix Contact GmbH & Co. KG" },
4273 { 227, "Grundfos Management A/S" },
4274 { 228, "Ridder Drive Systems" },
4275 { 229, "Soft Device SDN BHD" },
4276 { 230, "Integrated Control Technology Limited" },
4277 { 231, "AIRxpert Systems, Inc." },
4278 { 232, "Microtrol Limited" },
4279 { 233, "Red Lion Controls" },
4280 { 234, "Digital Electronics Corporation" },
4281 { 235, "Ennovatis GmbH" },
4282 { 236, "Serotonin Software Technologies, Inc." },
4283 { 237, "LS Industrial Systems Co., Ltd." },
4284 { 238, "Square D Company" },
4285 { 239, "S Squared Innovations, Inc." },
4286 { 240, "Aricent Ltd." },
4287 { 241, "EtherMetrics, LLC" },
4288 { 242, "Industrial Control Communications, Inc." },
4289 { 243, "Paragon Controls, Inc." },
4290 { 244, "A. O. Smith Corporation" },
4291 { 245, "Contemporary Control Systems, Inc." },
4292 { 246, "Intesis Software SL" },
4293 { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
4294 { 248, "Heat-Timer Corporation" },
4295 { 249, "Ingrasys Technology, Inc." },
4296 { 250, "Costerm Building Automation" },
4297 { 251, "WILO SE" },
4298 { 252, "Embedia Technologies Corp." },
4299 { 253, "Technilog" },
4300 { 254, "HR Controls Ltd. & Co. KG" },
4301 { 255, "Lennox International, Inc." },
4302 { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
4303 { 257, "Thermomax, Ltd." },
4304 { 258, "ELCON Electronic Control, Ltd." },
4305 { 259, "Larmia Control AB" },
4306 { 260, "BACnet Stack at SourceForge" },
4307 { 261, "G4S Security Services A/S" },
4308 { 262, "Exor International S.p.A." },
4309 { 263, "Cristal Controles" },
4310 { 264, "Regin AB" },
4311 { 265, "Dimension Software, Inc." },
4312 { 266, "SynapSense Corporation" },
4313 { 267, "Beijing Nantree Electronic Co., Ltd." },
4314 { 268, "Camus Hydronics Ltd." },
4315 { 269, "Kawasaki Heavy Industries, Ltd." },
4316 { 270, "Critical Environment Technologies" },
4317 { 271, "ILSHIN IBS Co., Ltd." },
4318 { 272, "ELESTA Energy Control AG" },
4319 { 273, "KROPMAN Installatietechniek" },
4320 { 274, "Baldor Electric Company" },
4321 { 275, "INGA mbH" },
4322 { 276, "GE Consumer & Industrial" },
4323 { 277, "Functional Devices, Inc." },
4324 { 278, "ESAC" },
4325 { 279, "M-System Co., Ltd." },
4326 { 280, "Yokota Co., Ltd." },
4327 { 281, "Hitranse Technology Co., LTD" },
4328 { 282, "Federspiel Controls" },
4329 { 283, "Kele, Inc." },
4330 { 284, "Opera Electronics, Inc." },
4331 { 285, "Gentec" },
4332 { 286, "Embedded Science Labs, LLC" },
4333 { 287, "Parker Hannifin Corporation" },
4334 { 288, "MaCaPS International Limited" },
4335 { 289, "Link4 Corporation" },
4336 { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
4337 { 291, "Pribusin, Inc." },
4338 { 292, "Advantage Controls" },
4339 { 293, "Critical Room Control" },
4340 { 294, "LEGRAND" },
4341 { 295, "Tongdy Control Technology Co., Ltd." },
4342 { 296, "ISSARO Integrierte Systemtechnik" },
4343 { 297, "Pro-Dev Industries" },
4344 { 298, "DRI-STEEM" },
4345 { 299, "Creative Electronic GmbH" },
4346 { 300, "Swegon AB" },
4347 { 301, "Jan Brachacek" },
4348 { 302, "Hitachi Appliances, Inc." },
4349 { 303, "Real Time Automation, Inc." },
4350 { 304, "ITEC Hankyu-Hanshin Co." },
4351 { 305, "Cyrus E&M Engineering Co., Ltd." },
4352 { 306, "Racine Federated, Inc." },
4353 { 307, "Cirrascale Corporation" },
4354 { 308, "Elesta GmbH Building Automation" },
4355 { 309, "Securiton" },
4356 { 310, "OSlsoft, Inc." },
4357 { 311, "Hanazeder Electronic GmbH" },
4358 { 312, "Honeywell Security Deutschland, Novar GmbH" },
4359 { 313, "Siemens Energy & Automation, Inc." },
4360 { 314, "ETM Professional Control GmbH" },
4361 { 315, "Meitav-tec, Ltd." },
4362 { 316, "Janitza Electronics GmbH" },
4363 { 317, "MKS Nordhausen" },
4364 { 318, "De Gier Drive Systems B.V." },
4365 { 319, "Cypress Envirosystems" },
4366 { 320, "SMARTron s.r.o." },
4367 { 321, "Verari Systems, Inc." },
4368 { 322, "K-W Electronic Service, Inc." },
4369 { 323, "ALFA-SMART Energy Management" },
4370 { 324, "Telkonet, Inc." },
4371 { 325, "Securiton GmbH" },
4372 { 326, "Cemtrex, Inc." },
4373 { 327, "Performance Technologies, Inc." },
4374 { 328, "Xtralis (Aust) Pty Ltd" },
4375 { 329, "TROX GmbH" },
4376 { 330, "Beijing Hysine Technology Co., Ltd" },
4377 { 331, "RCK Controls, Inc." },
4378 { 332, "Distech Controls SAS" },
4379 { 333, "Novar/Honeywell" },
4380 { 334, "The S4 Group, Inc." },
4381 { 335, "Schneider Electric" },
4382 { 336, "LHA Systems" },
4383 { 337, "GHM engineering Group, Inc." },
4384 { 338, "Cllimalux S.A." },
4385 { 339, "VAISALA Oyj" },
4386 { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
4387 { 341, "SCADAmetrics" },
4388 { 342, "POWERPEG NSI Limited" },
4389 { 343, "BACnet Interoperability Testing Services, Inc." },
4390 { 344, "Teco a.s." },
4391 { 345, "Plexus Technology, Inc." },
4392 { 346, "Energy Focus, Inc." },
4393 { 347, "Powersmiths International Corp." },
4394 { 348, "Nichibei Co., Ltd." },
4395 { 349, "HKC Technology Ltd." },
4396 { 350, "Ovation Networks, Inc." },
4397 { 351, "Setra Systems" },
4398 { 352, "AVG Automation" },
4399 { 353, "ZXC Ltd." },
4400 { 354, "Byte Sphere" },
4401 { 355, "Generiton Co., Ltd." },
4402 { 356, "Holter Regelarmaturen GmbH & Co. KG" },
4403 { 357, "Bedford Instruments, LLC" },
4404 { 358, "Standair Inc." },
4405 { 359, "WEG Automation - R&D" },
4406 { 360, "Prolon Control Systems ApS" },
4407 { 361, "Inneasoft" },
4408 { 362, "ConneXSoft GmbH" },
4409 { 363, "CEAG Notlichtsysteme GmbH" },
4410 { 364, "Distech Controls Inc." },
4411 { 365, "Industrial Technology Research Institute" },
4412 { 366, "ICONICS, Inc." },
4413 { 367, "IQ Controls s.c." },
4414 { 368, "OJ Electronics A/S" },
4415 { 369, "Rolbit Ltd." },
4416 { 370, "Synapsys Solutions Ltd." },
4417 { 371, "ACME Engineering Prod. Ltd." },
4418 { 372, "Zener Electric Pty, Ltd." },
4419 { 373, "Selectronix, Inc." },
4420 { 374, "Gorbet & Banerjee, LLC." },
4421 { 375, "IME" },
4422 { 376, "Stephen H. Dawson Computer Service" },
4423 { 377, "Accutrol, LLC" },
4424 { 378, "Schneider Elektronik GmbH" },
4425 { 379, "Alpha-Inno Tec GmbH" },
4426 { 380, "ADMMicro, Inc." },
4427 { 381, "Greystone Energy Systems, Inc." },
4428 { 382, "CAP Technologie" },
4429 { 383, "KeRo Systems" },
4430 { 384, "Domat Control System s.r.o." },
4431 { 385, "Efektronics Pty. Ltd." },
4432 { 386, "Hekatron Vertriebs GmbH" },
4433 { 387, "Securiton AG" },
4434 { 388, "Carlo Gavazzi Controls SpA" },
4435 { 389, "Chipkin Automation Systems" },
4436 { 390, "Savant Systems, LLC" },
4437 { 391, "Simmtronic Lighting Controls" },
4438 { 392, "Abelko Innovation AB" },
4439 { 393, "Seresco Technologies Inc." },
4440 { 394, "IT Watchdogs" },
4441 { 395, "Automation Assist Japan Corp." },
4442 { 396, "Thermokon Sensortechnik GmbH" },
4443 { 397, "EGauge Systems, LLC" },
4444 { 398, "Quantum Automation (ASIA) PTE, Ltd." },
4445 { 399, "Toshiba Lighting & Technology Corp." },
4446 { 400, "SPIN Engenharia de Automaca Ltda." },
4447 { 401, "Logistics Systems & Software Services India PVT. Ltd." },
4448 { 402, "Delta Controls Integration Products" },
4449 { 403, "Focus Media" },
4450 { 404, "LUMEnergi Inc." },
4451 { 405, "Kara Systems" },
4452 { 406, "RF Code, Inc." },
4453 { 407, "Fatek Automation Corp." },
4454 { 408, "JANDA Software Company, LLC" },
4455 { 409, "Open System Solutions Limited" },
4456 { 410, "Intelec Systems PTY Ltd." },
4457 { 411, "Ecolodgix, LLC" },
4458 { 412, "Douglas Lighting Controls" },
4459 { 413, "iSAtech GmbH" },
4460 { 414, "AREAL" },
4461 { 415, "Beckhoff Automation GmbH" },
4462 { 416, "IPAS GmbH" },
4463 { 417, "KE2 Therm Solutions" },
4464 { 418, "Base2Products" },
4465 { 419, "DTL Controls, LLC" },
4466 { 420, "INNCOM International, Inc." },
4467 { 421, "BTR Netcom GmbH" },
4468 { 422, "Greentrol Automation, Inc" },
4469 { 423, "BELIMO Automation AG" },
4470 { 424, "Samsung Heavy Industries Co, Ltd" },
4471 { 425, "Triacta Power Technologies, Inc." },
4472 { 426, "Globestar Systems" },
4473 { 427, "MLB Advanced Media, LP" },
4474 { 428, "SWG Stuckmann Wirtschaftliche Gebaudesysteme GmbH" },
4475 { 429, "SensorSwitch" },
4476 { 430, "Multitek Power Limited" },
4477 { 431, "Aquametro AG" },
4478 { 432, "LG Electronics Inc." },
4479 { 433, "Electronic Theatre Controls, Inc." },
4480 { 434, "Mitsubishi Electric Corporation Nagoya Works" },
4481 { 435, "Delta Electronics, Inc." },
4482 { 436, "Elma Kurtalj, Ltd." },
4483 { 437, "ADT Fire and Security Sp. A.o.o." },
4484 { 438, "Nedap Security Management" },
4485 { 439, "ESC Automation Inc." },
4486 { 440, "DSP4YOU Ltd." },
4487 { 441, "GE Sensing and Inspection Technologies" },
4488 { 442, "Embedded Systems SIA" },
4489 { 443, "BEFEGA GmbH" },
4490 { 444, "Baseline Inc." },
4491 { 445, "M2M Systems Integrators" },
4492 { 446, "OEMCtrl" },
4493 { 447, "Clarkson Controls Limited" },
4494 { 448, "Rogerwell Control System Limited" },
4495 { 449, "SCL Elements" },
4496 { 450, "Hitachi Ltd." },
4497 { 451, "Newron System SA" },
4498 { 452, "BEVECO Gebouwautomatisering BV" },
4499 { 453, "Streamside Solutions" },
4500 { 454, "Yellowstone Soft" },
4501 { 455, "Oztech Intelligent Systems Pty Ltd." },
4502 { 456, "Novelan GmbH" },
4503 { 457, "Flexim Americas Corporation" },
4504 { 458, "ICP DAS Co., Ltd." },
4505 { 459, "CARMA Industries Inc." },
4506 { 460, "Log-One Ltd." },
4507 { 461, "TECO Electric & Machinery Co., Ltd." },
4508 { 462, "ConnectEx, Inc." },
4509 { 463, "Turbo DDC Sudwest" },
4510 { 464, "Quatrosense Environmental Ltd." },
4511 { 465, "Fifth Light Technology Ltd." },
4512 { 466, "Scientific Solutions, Ltd." },
4513 { 467, "Controller Area Network Solutions (M) Sdn Bhd" },
4514 { 468, "RESOL - Elektronische Regelungen GmbH" },
4515 { 469, "RPBUS LLC" },
4516 { 470, "BRS Sistemas Eletronicos" },
4517 { 471, "WindowMaster A/S" },
4518 { 472, "Sunlux Technologies Ltd." },
4519 { 473, "Measurlogic" },
4520 { 474, "Frimat GmbH" },
4521 { 475, "Spirax Sarco" },
4522 { 476, "Luxtron" },
4523 { 477, "Raypak Inc" },
4524 { 478, "Air Monitor Corporation" },
4525 { 479, "Regler Och Webbteknik Sverige (ROWS)" },
4526 { 480, "Intelligent Lighting Controls Inc." },
4527 { 481, "Sanyo Electric Industry Co., Ltd" },
4528 { 482, "E-Mon Energy Monitoring Products" },
4529 { 483, "Digital Control Systems" },
4530 { 484, "ATI Airtest Technologies, Inc." },
4531 { 485, "SCS SA" },
4532 { 486, "HMS Industrial Networks AB" },
4533 { 487, "Shenzhen Universal Intellisys Co Ltd" },
4534 { 488, "EK Intellisys Sdn Bhd" },
4535 { 489, "SysCom" },
4536 { 490, "Firecom, Inc." },
4537 { 491, "ESA Elektroschaltanlagen Grimma GmbH" },
4538 { 492, "Kumahira Co Ltd" },
4539 { 493, "Hotraco" },
4540 { 494, "SABO Elektronik GmbH" },
4541 { 495, "Equip'Trans" },
4542 { 496, "TCS Basys Controls" },
4543 { 497, "FlowCon International A/S" },
4544 { 498, "ThyssenKrupp Elevator Americas" },
4545 { 499, "Abatement Technologies" },
4546 { 500, "Continental Control Systems, LLC" },
4547 { 501, "WISAG Automatisierungstechnik GmbH & Co KG" },
4548 { 502, "EasyIO" },
4549 { 503, "EAP-Electric GmbH" },
4550 { 504, "Hardmeier" },
4551 { 505, "Mircom Group of Companies" },
4552 { 506, "Quest Controls" },
4553 { 507, "Mestek, Inc" },
4554 { 508, "Pulse Energy" },
4555 { 509, "Tachikawa Corporation" },
4556 { 510, "University of Nebraska-Lincoln" },
4557 { 511, "Redwood Systems" },
4558 { 512, "PASStec Industrie-Elektronik GmbH" },
4559 { 513, "NgEK, Inc." },
4560 { 514, "FAW Electronics Ltd" },
4561 { 515, "Jireh Energy Tech Co., Ltd." },
4562 { 516, "Enlighted Inc." },
4563 { 517, "El-Piast Sp. Z o.o" },
4564 { 518, "NetxAutomation Software GmbH" },
4565 { 519, "Invertek Drives" },
4566 { 520, "Deutschmann Automation GmbH & Co. KG" },
4567 { 521, "EMU Electronic AG" },
4568 { 522, "Phaedrus Limited" },
4569 { 523, "Sigmatek GmbH & Co KG" },
4570 { 524, "Marlin Controls" },
4571 { 525, "Circutor, SA" },
4572 { 526, "UTC Fire & Security" },
4573 { 527, "DENT Instruments, Inc." },
4574 { 528, "FHP Manufacturing Company - Bosch Group" },
4575 { 529, "GE Intelligent Platforms" },
4576 { 530, "Inner Range Pty Ltd" },
4577 { 531, "GLAS Energy Technology" },
4578 { 532, "MSR-Electronic-GmbH" },
4579 { 533, "Energy Control Systems, Inc." },
4580 { 534, "EMT Controls" },
4581 { 535, "Daintree Networks Inc." },
4582 { 536, "EURO ICC d.o.o" },
4583 { 537, "TE Connectivity Energy" },
4584 { 538, "GEZE GmbH" },
4585 { 539, "NEC Corporation" },
4586 { 540, "Ho Cheung International Company Limited" },
4587 { 541, "Sharp Manufacturing Systems Corporation" },
4588 { 542, "DOT CONTROLS a.s." },
4589 { 543, "BeaconMedaes" },
4590 { 544, "Midea Commercial Aircon" },
4591 { 545, "WattMaster Controls" },
4592 { 546, "Kamstrup A/S" },
4593 { 547, "CA Computer Automation GmbH" },
4594 { 548, "Laars Heating Systems Company" },
4595 { 549, "Hitachi Systems, Ltd." },
4596 { 550, "Fushan AKE Electronic Engineering Co., Ltd." },
4597 { 551, "Toshiba International Corporation" },
4598 { 552, "Starman Systems, LLC" },
4599 { 553, "Samsung Techwin Co., Ltd." },
4600 { 554, "ISAS-Integrated Switchgear and Systems P/L" },
4601 { 556, "Obvius" },
4602 { 557, "Marek Guzik" },
4603 { 558, "Vortek Instruments, LLC" },
4604 { 559, "Universal Lighting Technologies" },
4605 { 560, "Myers Power Products, Inc." },
4606 { 561, "Vector Controls GmbH" },
4607 { 562, "Crestron Electronics, Inc." },
4608 { 563, "A&E Controls Limited" },
4609 { 564, "Projektomontaza A.D." },
4610 { 565, "Freeaire Refrigeration" },
4611 { 566, "Aqua Cooler Pty Limited" },
4612 { 567, "Basic Controls" },
4613 { 568, "GE Measurement and Control Solutions Advanced Sensors" },
4614 { 569, "EQUAL Networks" },
4615 { 570, "Millennial Net" },
4616 { 571, "APLI Ltd" },
4617 { 572, "Electro Industries/GaugeTech" },
4618 { 573, "SangMyung University" },
4619 { 574, "Coppertree Analytics, Inc." },
4620 { 575, "CoreNetiX GmbH" },
4621 { 576, "Acutherm" },
4622 { 577, "Dr. Riedel Automatisierungstechnik GmbH" },
4623 { 578, "Shina System Co., Ltd" },
4624 { 579, "Iqapertus" },
4625 { 580, "PSE Technology" },
4626 { 581, "BA Systems" },
4627 { 582, "BTICINO" },
4628 { 583, "Monico, Inc." },
4629 { 584, "iCue" },
4630 { 585, "tekmar Control Systems Ltd." },
4631 { 586, "Control Technology Corporation" },
4632 { 587, "GFAE GmbH" },
4633 { 588, "BeKa Software GmbH" },
4634 { 589, "Isoil Industria SpA" },
4635 { 590, "Home Systems Consulting SpA" },
4636 { 591, "Socomec" },
4637 { 592, "Everex Communications, Inc." },
4638 { 593, "Ceiec Electric Technology" },
4639 { 594, "Atrila GmbH" },
4640 { 595, "WingTechs" },
4641 { 596, "Shenzhen Mek Intellisys Pte Ltd." },
4642 { 597, "Nestfield Co., Ltd." },
4643 { 598, "Swissphone Telecom AG" },
4644 { 599, "PNTECH JSC" },
4645 { 600, "Horner APG, LLC" },
4646 { 601, "PVI Industries, LLC" },
4647 { 602, "Ela-compil" },
4648 { 603, "Pegasus Automation International LLC" },
4649 { 604, "Wight Electronic Services Ltd." },
4650 { 605, "Marcom" },
4651 { 606, "Exhausto A/S" },
4652 { 607, "Dwyer Instruments, Inc." },
4653 { 608, "Link GmbH" },
4654 { 609, "Oppermann Regelgerate GmbH" },
4655 { 610, "NuAire, Inc." },
4656 { 611, "Nortec Humidity, Inc." },
4657 { 612, "Bigwood Systems, Inc." },
4658 { 613, "Enbala Power Networks" },
4659 { 614, "Inter Energy Co., Ltd." },
4660 { 615, "ETC" },
4661 { 616, "COMELEC S.A.R.L" },
4662 { 617, "Pythia Technologies" },
4663 { 618, "TrendPoint Systems, Inc." },
4664 { 619, "AWEX" },
4665 { 620, "Eurevia" },
4666 { 621, "Kongsberg E-lon AS" },
4667 { 622, "FlaktWoods" },
4668 { 623, "E + E Elektronik GES M.B.H." },
4669 { 624, "ARC Informatique" },
4670 { 625, "SKIDATA AG" },
4671 { 626, "WSW Solutions" },
4672 { 627, "Trefon Electronic GmbH" },
4673 { 628, "Dongseo System" },
4674 { 629, "Kanontec Intelligence Technology Co., Ltd." },
4675 { 630, "EVCO S.p.A." },
4676 { 631, "Accuenergy (CANADA) Inc." },
4677 { 632, "SoftDEL" },
4678 { 633, "Orion Energy Systems, Inc." },
4679 { 634, "Roboticsware" },
4680 { 635, "DOMIQ Sp. z o.o." },
4681 { 636, "Solidyne" },
4682 { 637, "Elecsys Corporation" },
4683 { 638, "Conditionaire International Pty. Limited" },
4684 { 639, "Quebec, Inc." },
4685 { 640, "Homerun Holdings" },
4686 { 641, "RFM, Inc." },
4687 { 642, "Comptek" },
4688 { 643, "Westco Systems, Inc." },
4689 { 644, "Advancis Software & Services GmbH" },
4690 { 645, "Intergrid, LLC" },
4691 { 646, "Markerr Controls, Inc." },
4692 { 647, "Toshiba Elevator and Building Systems Corporation" },
4693 { 648, "Spectrum Controls, Inc." },
4694 { 649, "Mkservice" },
4695 { 650, "Fox Thermal Instruments" },
4696 { 651, "SyxthSense Ltd" },
4697 { 652, "DUHA System S R.O." },
4698 { 653, "NIBE" },
4699 { 654, "Melink Corporation" },
4700 { 655, "Fritz-Haber-Institut" },
4701 { 656, "MTU Onsite Energy GmbH, Gas Power Systems" },
4702 { 657, "Omega Engineering, Inc." },
4703 { 658, "Avelon" },
4704 { 659, "Ywire Technologies, Inc." },
4705 { 660, "M.R. Engineering Co., Ltd." },
4706 { 661, "Lochinvar, LLC" },
4707 { 662, "Sontay Limited" },
4708 { 663, "GRUPA Slawomir Chelminski" },
4709 { 664, "Arch Meter Corporation" },
4710 { 665, "Senva, Inc." },
4711 { 667, "FM-Tec" },
4712 { 668, "Systems Specialists, Inc." },
4713 { 669, "SenseAir" },
4714 { 670, "AB IndustrieTechnik Srl" },
4715 { 671, "Cortland Research, LLC" },
4716 { 672, "MediaView" },
4717 { 673, "VDA Elettronica" },
4718 { 674, "CSS, Inc." },
4719 { 675, "Tek-Air Systems, Inc." },
4720 { 676, "ICDT" },
4721 { 677, "The Armstrong Monitoring Corporation" },
4722 { 678, "DIXELL S.r.l" },
4723 { 679, "Lead System, Inc." },
4724 { 680, "ISM EuroCenter S.A." },
4725 { 681, "TDIS" },
4726 { 682, "Trade FIDES" },
4727 { 683, "Knurr GmbH (Emerson Network Power)" },
4728 { 684, "Resource Data Management" },
4729 { 685, "Abies Technology, Inc." },
4730 { 686, "Amalva" },
4731 { 687, "MIRAE Electrical Mfg. Co., Ltd." },
4732 { 688, "HunterDouglas Architectural Projects Scandinavia ApS" },
4733 { 689, "RUNPAQ Group Co., Ltd" },
4734 { 690, "Unicard SA" },
4735 { 691, "IE Technologies" },
4736 { 692, "Ruskin Manufacturing" },
4737 { 693, "Calon Associates Limited" },
4738 { 694, "Contec Co., Ltd." },
4739 { 0, NULL }
4741 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
4743 static int proto_bacapp = -1;
4744 static int hf_bacapp_type = -1;
4745 static int hf_bacapp_pduflags = -1;
4746 static int hf_bacapp_SEG = -1;
4747 static int hf_bacapp_MOR = -1;
4748 static int hf_bacapp_SA = -1;
4749 static int hf_bacapp_response_segments = -1;
4750 static int hf_bacapp_max_adpu_size = -1;
4751 static int hf_bacapp_invoke_id = -1;
4752 static int hf_bacapp_objectType = -1;
4753 static int hf_bacapp_instanceNumber = -1;
4754 static int hf_bacapp_sequence_number = -1;
4755 static int hf_bacapp_window_size = -1;
4756 static int hf_bacapp_service = -1;
4757 static int hf_bacapp_NAK = -1;
4758 static int hf_bacapp_SRV = -1;
4759 static int hf_Device_Instance_Range_Low_Limit = -1;
4760 static int hf_Device_Instance_Range_High_Limit = -1;
4761 static int hf_BACnetRejectReason = -1;
4762 static int hf_BACnetAbortReason = -1;
4763 static int hf_BACnetApplicationTagNumber = -1;
4764 static int hf_BACnetContextTagNumber = -1;
4765 static int hf_BACnetExtendedTagNumber = -1;
4766 static int hf_BACnetNamedTag = -1;
4767 static int hf_BACnetTagClass = -1;
4768 static int hf_BACnetCharacterSet = -1;
4769 static int hf_bacapp_tag_lvt = -1;
4770 static int hf_bacapp_tag_ProcessId = -1;
4771 static int hf_bacapp_uservice = -1;
4772 static int hf_BACnetPropertyIdentifier = -1;
4773 static int hf_BACnetVendorIdentifier = -1;
4774 static int hf_BACnetRestartReason = -1;
4775 static int hf_bacapp_tag_IPV4 = -1;
4776 static int hf_bacapp_tag_IPV6 = -1;
4777 static int hf_bacapp_tag_PORT = -1;
4778 /* some more variables for segmented messages */
4779 static int hf_msg_fragments = -1;
4780 static int hf_msg_fragment = -1;
4781 static int hf_msg_fragment_overlap = -1;
4782 static int hf_msg_fragment_overlap_conflicts = -1;
4783 static int hf_msg_fragment_multiple_tails = -1;
4784 static int hf_msg_fragment_too_long_fragment = -1;
4785 static int hf_msg_fragment_error = -1;
4786 static int hf_msg_fragment_count = -1;
4787 static int hf_msg_reassembled_in = -1;
4788 static int hf_msg_reassembled_length = -1;
4790 static gint ett_msg_fragment = -1;
4791 static gint ett_msg_fragments = -1;
4793 static gint ett_bacapp = -1;
4794 static gint ett_bacapp_control = -1;
4795 static gint ett_bacapp_tag = -1;
4796 static gint ett_bacapp_list = -1;
4797 static gint ett_bacapp_value = -1;
4799 static expert_field ei_bacapp_bad_length = EI_INIT;
4801 static gint32 propertyIdentifier = -1;
4802 static gint32 propertyArrayIndex = -1;
4803 static guint32 object_type = 4096;
4805 static guint8 bacapp_flags = 0;
4806 static guint8 bacapp_seq = 0;
4808 /* Defined to allow vendor identifier registration of private transfer dissectors */
4809 static dissector_table_t bacapp_dissector_table;
4812 /* Stat: BACnet Packets sorted by IP */
4813 bacapp_info_value_t bacinfo;
4815 static const gchar* st_str_packets_by_ip = "BACnet Packets by IP";
4816 static const gchar* st_str_packets_by_ip_dst = "By Destination";
4817 static const gchar* st_str_packets_by_ip_src = "By Source";
4818 static int st_node_packets_by_ip = -1;
4819 static int st_node_packets_by_ip_dst = -1;
4820 static int st_node_packets_by_ip_src = -1;
4822 static void
4823 bacapp_packet_stats_tree_init(stats_tree* st)
4825 st_node_packets_by_ip = stats_tree_create_pivot(st, st_str_packets_by_ip, 0);
4826 st_node_packets_by_ip_src = stats_tree_create_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4827 st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4830 static int
4831 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4833 int packets_for_this_dst;
4834 int packets_for_this_src;
4835 int service_for_this_dst;
4836 int service_for_this_src;
4837 int src_for_this_dst;
4838 int dst_for_this_src;
4839 int objectid_for_this_dst;
4840 int objectid_for_this_src;
4841 int instanceid_for_this_dst;
4842 int instanceid_for_this_src;
4843 gchar *dststr;
4844 gchar *srcstr;
4845 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4847 srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4848 dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4850 tick_stat_node(st, st_str_packets_by_ip, 0, TRUE);
4851 packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
4852 packets_for_this_src = tick_stat_node(st, st_str_packets_by_ip_src, st_node_packets_by_ip, TRUE);
4853 src_for_this_dst = tick_stat_node(st, dststr, packets_for_this_dst, TRUE);
4854 dst_for_this_src = tick_stat_node(st, srcstr, packets_for_this_src, TRUE);
4855 service_for_this_src = tick_stat_node(st, dststr, dst_for_this_src, TRUE);
4856 service_for_this_dst = tick_stat_node(st, srcstr, src_for_this_dst, TRUE);
4857 if (binfo->service_type) {
4858 objectid_for_this_dst = tick_stat_node(st, binfo->service_type, service_for_this_dst, TRUE);
4859 objectid_for_this_src = tick_stat_node(st, binfo->service_type, service_for_this_src, TRUE);
4860 if (binfo->object_ident) {
4861 instanceid_for_this_dst = tick_stat_node(st, binfo->object_ident, objectid_for_this_dst, TRUE);
4862 tick_stat_node(st, binfo->instance_ident, instanceid_for_this_dst, FALSE);
4863 instanceid_for_this_src = tick_stat_node(st, binfo->object_ident, objectid_for_this_src, TRUE);
4864 tick_stat_node(st, binfo->instance_ident, instanceid_for_this_src, FALSE);
4868 return 1;
4871 /* Stat: BACnet Packets sorted by Service */
4872 static const gchar* st_str_packets_by_service = "BACnet Packets by Service";
4873 static int st_node_packets_by_service = -1;
4875 static void
4876 bacapp_service_stats_tree_init(stats_tree* st)
4878 st_node_packets_by_service = stats_tree_create_pivot(st, st_str_packets_by_service, 0);
4881 static int
4882 bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4884 int servicetype;
4885 int src, dst;
4886 int objectid;
4888 gchar *dststr;
4889 gchar *srcstr;
4891 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4893 srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4894 dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4896 tick_stat_node(st, st_str_packets_by_service, 0, TRUE);
4897 if (binfo->service_type) {
4898 servicetype = tick_stat_node(st, binfo->service_type, st_node_packets_by_service, TRUE);
4899 src = tick_stat_node(st, srcstr, servicetype, TRUE);
4900 dst = tick_stat_node(st, dststr, src, TRUE);
4901 if (binfo->object_ident) {
4902 objectid = tick_stat_node(st, binfo->object_ident, dst, TRUE);
4903 tick_stat_node(st, binfo->instance_ident, objectid, FALSE);
4907 return 1;
4910 /* Stat: BACnet Packets sorted by Object Type */
4911 static const gchar* st_str_packets_by_objectid = "BACnet Packets by Object Type";
4912 static int st_node_packets_by_objectid = -1;
4914 static void
4915 bacapp_objectid_stats_tree_init(stats_tree* st)
4917 st_node_packets_by_objectid = stats_tree_create_pivot(st, st_str_packets_by_objectid, 0);
4920 static int
4921 bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4923 int servicetype;
4924 int src, dst;
4925 int objectid;
4927 gchar *dststr;
4928 gchar *srcstr;
4929 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4931 srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4932 dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4934 tick_stat_node(st, st_str_packets_by_objectid, 0, TRUE);
4935 if (binfo->object_ident) {
4936 objectid = tick_stat_node(st, binfo->object_ident, st_node_packets_by_objectid, TRUE);
4937 src = tick_stat_node(st, srcstr, objectid, TRUE);
4938 dst = tick_stat_node(st, dststr, src, TRUE);
4939 if (binfo->service_type) {
4940 servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
4941 tick_stat_node(st, binfo->instance_ident, servicetype, FALSE);
4945 return 1;
4948 /* Stat: BACnet Packets sorted by Instance No */
4949 static const gchar* st_str_packets_by_instanceid = "BACnet Packets by Instance ID";
4950 static int st_node_packets_by_instanceid = -1;
4952 static void
4953 bacapp_instanceid_stats_tree_init(stats_tree* st)
4955 st_node_packets_by_instanceid = stats_tree_create_pivot(st, st_str_packets_by_instanceid, 0);
4958 static int
4959 bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
4961 int servicetype;
4962 int src, dst;
4963 int instanceid;
4965 gchar *dststr;
4966 gchar *srcstr;
4967 const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
4969 srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", address_to_str(&pinfo->src), NULL);
4970 dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", address_to_str(&pinfo->dst), NULL);
4972 tick_stat_node(st, st_str_packets_by_instanceid, 0, TRUE);
4973 if (binfo->object_ident) {
4974 instanceid = tick_stat_node(st, binfo->instance_ident, st_node_packets_by_instanceid, TRUE);
4975 src = tick_stat_node(st, srcstr, instanceid, TRUE);
4976 dst = tick_stat_node(st, dststr, src, TRUE);
4977 if (binfo->service_type) {
4978 servicetype = tick_stat_node(st, binfo->service_type, dst, TRUE);
4979 tick_stat_node(st, binfo->object_ident, servicetype, FALSE);
4982 return 1;
4986 /* register all BACnet Ststistic trees */
4987 static void
4988 register_bacapp_stat_trees(void)
4990 stats_tree_register("bacapp", "bacapp_ip", "BACnet/Packets sorted by IP", 0,
4991 bacapp_stats_tree_packet, bacapp_packet_stats_tree_init, NULL);
4992 stats_tree_register("bacapp", "bacapp_service", "BACnet/Packets sorted by Service", 0,
4993 bacapp_stats_tree_service, bacapp_service_stats_tree_init, NULL);
4994 stats_tree_register("bacapp", "bacapp_objectid", "BACnet/Packets sorted by Object Type", 0,
4995 bacapp_stats_tree_objectid, bacapp_objectid_stats_tree_init, NULL);
4996 stats_tree_register("bacapp", "bacapp_instanceid", "BACnet/Packets sorted by Instance ID", 0,
4997 bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
5000 /* 'data' must be ep_ allocated */
5001 static gint
5002 updateBacnetInfoValue(gint whichval, const gchar *data)
5004 if (whichval == BACINFO_SERVICE) {
5005 bacinfo.service_type = data;
5006 return 0;
5008 if (whichval == BACINFO_INVOKEID) {
5009 bacinfo.invoke_id = data;
5010 return 0;
5012 if (whichval == BACINFO_OBJECTID) {
5013 bacinfo.object_ident = data;
5014 return 0;
5016 if (whichval == BACINFO_INSTANCEID) {
5017 bacinfo.instance_ident = data;
5018 return 0;
5020 return -1;
5023 static const fragment_items msg_frag_items = {
5024 /* Fragment subtrees */
5025 &ett_msg_fragment,
5026 &ett_msg_fragments,
5027 /* Fragment fields */
5028 &hf_msg_fragments,
5029 &hf_msg_fragment,
5030 &hf_msg_fragment_overlap,
5031 &hf_msg_fragment_overlap_conflicts,
5032 &hf_msg_fragment_multiple_tails,
5033 &hf_msg_fragment_too_long_fragment,
5034 &hf_msg_fragment_error,
5035 &hf_msg_fragment_count,
5036 /* Reassembled in field */
5037 &hf_msg_reassembled_in,
5038 /* Reassembled length field */
5039 &hf_msg_reassembled_length,
5040 /* Reassembled data field */
5041 NULL,
5042 /* Tag */
5043 "Message fragments"
5046 #if 0
5047 /* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
5048 /* FIXME: fGetMaxAPDUSize is commented out, as it is not used. It was used to set variables which were not later used. */
5049 static const guint MaxAPDUSize [] = { 50, 128, 206, 480, 1024, 1476 };
5051 static guint
5052 fGetMaxAPDUSize(guint8 idx)
5054 /* only 16 values are defined, so use & 0x0f */
5055 /* check the size of the Array, deliver either the entry
5056 or the first entry if idx is outside of the array (bug 3736 comment#7) */
5058 if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
5059 return MaxAPDUSize[0];
5060 else
5061 return MaxAPDUSize[idx & 0x0f];
5063 #endif
5066 /* Used when there are ranges of reserved and proprietary enumerations */
5067 static const char*
5068 val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
5069 const char *fmt, const char *split_fmt)
5071 if (val < split_val)
5072 return val_to_str(val, vs, fmt);
5073 else
5074 return val_to_str(val, vs, split_fmt);
5077 /* from clause 20.2.1.3.2 Constructed Data */
5078 /* returns true if the extended value is used */
5079 static gboolean
5080 tag_is_extended_value(guint8 tag)
5082 return (tag & 0x07) == 5;
5085 static gboolean
5086 tag_is_opening(guint8 tag)
5088 return (tag & 0x07) == 6;
5091 static gboolean
5092 tag_is_closing(guint8 tag)
5094 return (tag & 0x07) == 7;
5097 /* from clause 20.2.1.1 Class
5098 class bit shall be one for context specific tags */
5099 /* returns true if the tag is context specific */
5100 static gboolean
5101 tag_is_context_specific(guint8 tag)
5103 return (tag & 0x08) != 0;
5106 static gboolean
5107 tag_is_extended_tag_number(guint8 tag)
5109 return ((tag & 0xF0) == 0xF0);
5112 static guint32
5113 object_id_type(guint32 object_identifier)
5115 return ((object_identifier >> 22) & 0x3FF);
5118 static guint32
5119 object_id_instance(guint32 object_identifier)
5121 return (object_identifier & 0x3FFFFF);
5124 static guint
5125 fTagNo(tvbuff_t *tvb, guint offset)
5127 return (guint)(tvb_get_guint8(tvb, offset) >> 4);
5130 static gboolean
5131 fUnsigned32(tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
5133 gboolean valid = TRUE;
5135 switch (lvt) {
5136 case 1:
5137 *val = tvb_get_guint8(tvb, offset);
5138 break;
5139 case 2:
5140 *val = tvb_get_ntohs(tvb, offset);
5141 break;
5142 case 3:
5143 *val = tvb_get_ntoh24(tvb, offset);
5144 break;
5145 case 4:
5146 *val = tvb_get_ntohl(tvb, offset);
5147 break;
5148 default:
5149 valid = FALSE;
5150 break;
5153 return valid;
5156 static gboolean
5157 fUnsigned64(tvbuff_t *tvb, guint offset, guint32 lvt, guint64 *val)
5159 gboolean valid = FALSE;
5160 gint64 value = 0;
5161 guint8 data, i;
5163 if (lvt && (lvt <= 8)) {
5164 valid = TRUE;
5165 for (i = 0; i < lvt; i++) {
5166 data = tvb_get_guint8(tvb, offset+i);
5167 value = (value << 8) + data;
5169 *val = value;
5172 return valid;
5175 /* BACnet Signed Value uses 2's complement notation, but with a twist:
5176 All signed integers shall be encoded in the smallest number of octets
5177 possible. That is, the first octet of any multi-octet encoded value
5178 shall not be X'00' if the most significant bit (bit 7) of the second
5179 octet is 0, and the first octet shall not be X'FF' if the most
5180 significant bit of the second octet is 1. ASHRAE-135-2004-20.2.5 */
5181 static gboolean
5182 fSigned64(tvbuff_t *tvb, guint offset, guint32 lvt, gint64 *val)
5184 gboolean valid = FALSE;
5185 gint64 value = 0;
5186 guint8 data;
5187 guint32 i;
5189 /* we can only handle 7 bytes for a 64-bit value due to signed-ness */
5190 if (lvt && (lvt <= 7)) {
5191 valid = TRUE;
5192 data = tvb_get_guint8(tvb, offset);
5193 if ((data & 0x80) != 0)
5194 value = (-1 << 8) | data;
5195 else
5196 value = data;
5197 for (i = 1; i < lvt; i++) {
5198 data = tvb_get_guint8(tvb, offset+i);
5199 value = (value << 8) + data;
5201 *val = value;
5204 return valid;
5207 static guint
5208 fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5209 guint offset, guint8 *tag_no, guint8* tag_info, guint32 *lvt)
5211 proto_item *ti = NULL;
5212 guint8 tag;
5213 guint8 value;
5214 guint tag_len = 1;
5215 guint lvt_len = 1; /* used for tree display of lvt */
5216 guint lvt_offset; /* used for tree display of lvt */
5218 lvt_offset = offset;
5219 tag = tvb_get_guint8(tvb, offset);
5220 *tag_info = 0;
5221 *lvt = tag & 0x07;
5223 /* To solve the problem of lvt values of 6/7 being indeterminate - it */
5224 /* can mean open/close tag or length of 6/7 after the length is */
5225 /* computed below - store whole tag info, not just context bit. */
5226 if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
5227 *tag_no = tag >> 4;
5228 if (tag_is_extended_tag_number(tag)) {
5229 *tag_no = tvb_get_guint8(tvb, offset + tag_len++);
5231 if (tag_is_extended_value(tag)) { /* length is more than 4 Bytes */
5232 lvt_offset += tag_len;
5233 value = tvb_get_guint8(tvb, lvt_offset);
5234 tag_len++;
5235 if (value == 254) { /* length is encoded with 16 Bits */
5236 *lvt = tvb_get_ntohs(tvb, lvt_offset+1);
5237 tag_len += 2;
5238 lvt_len += 2;
5239 } else if (value == 255) { /* length is encoded with 32 Bits */
5240 *lvt = tvb_get_ntohl(tvb, lvt_offset+1);
5241 tag_len += 4;
5242 lvt_len += 4;
5243 } else
5244 *lvt = value;
5247 if (tree) {
5248 proto_tree *subtree;
5249 if (tag_is_opening(tag))
5250 ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
5251 else if (tag_is_closing(tag))
5252 ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
5253 else if (tag_is_context_specific(tag)) {
5254 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5255 "Context Tag: %u, Length/Value/Type: %u",
5256 *tag_no, *lvt);
5257 } else
5258 ti = proto_tree_add_text(tree, tvb, offset, tag_len,
5259 "Application Tag: %s, Length/Value/Type: %u",
5260 val_to_str(*tag_no,
5261 BACnetApplicationTagNumber,
5262 ASHRAE_Reserved_Fmt),
5263 *lvt);
5265 /* details if needed */
5266 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5267 proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
5268 if (tag_is_extended_tag_number(tag)) {
5269 proto_tree_add_uint_format(subtree,
5270 hf_BACnetContextTagNumber,
5271 tvb, offset, 1, tag,
5272 "Extended Tag Number");
5273 proto_tree_add_item(subtree,
5274 hf_BACnetExtendedTagNumber,
5275 tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5276 } else {
5277 if (tag_is_context_specific(tag))
5278 proto_tree_add_item(subtree,
5279 hf_BACnetContextTagNumber,
5280 tvb, offset, 1, ENC_BIG_ENDIAN);
5281 else
5282 proto_tree_add_item(subtree,
5283 hf_BACnetApplicationTagNumber,
5284 tvb, offset, 1, ENC_BIG_ENDIAN);
5286 if (tag_is_closing(tag) || tag_is_opening(tag))
5287 proto_tree_add_item(subtree,
5288 hf_BACnetNamedTag,
5289 tvb, offset, 1, ENC_BIG_ENDIAN);
5290 else if (tag_is_extended_value(tag)) {
5291 proto_tree_add_item(subtree,
5292 hf_BACnetNamedTag,
5293 tvb, offset, 1, ENC_BIG_ENDIAN);
5294 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5295 tvb, lvt_offset, lvt_len, *lvt);
5296 } else
5297 proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
5298 tvb, lvt_offset, lvt_len, *lvt);
5299 } /* if (tree) */
5301 if (*lvt > tvb_length(tvb)) {
5302 expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5303 "LVT length too long: %d > %d", *lvt,
5304 tvb_length(tvb));
5305 *lvt = 1;
5308 return tag_len;
5311 static guint
5312 fTagHeader(tvbuff_t *tvb, packet_info *pinfo, guint offset, guint8 *tag_no, guint8* tag_info,
5313 guint32 *lvt)
5315 return fTagHeaderTree(tvb, pinfo, NULL, offset, tag_no, tag_info, lvt);
5318 static guint
5319 fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5321 guint8 tag_no, tag_info;
5322 guint32 lvt;
5323 proto_item *ti;
5324 proto_tree *subtree;
5326 ti = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
5327 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5328 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5330 return offset + 1;
5333 static guint
5334 fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5336 guint8 tag_no, tag_info;
5337 guint32 lvt = 0;
5338 proto_item *ti;
5339 proto_tree *subtree;
5340 guint bool_len = 1;
5342 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5343 if (tag_info && lvt == 1) {
5344 lvt = tvb_get_guint8(tvb, offset+1);
5345 ++bool_len;
5348 ti = proto_tree_add_text(tree, tvb, offset, bool_len,
5349 "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
5350 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5351 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5353 return offset + bool_len;
5356 static guint
5357 fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5359 guint64 val = 0;
5360 guint8 tag_no, tag_info;
5361 guint32 lvt;
5362 guint tag_len;
5363 proto_item *ti;
5364 proto_tree *subtree;
5366 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5367 /* only support up to an 8 byte (64-bit) integer */
5368 if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
5369 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5370 "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
5371 else
5372 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5373 "%s - %u octets (Unsigned)", label, lvt);
5374 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5375 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5377 return offset+tag_len+lvt;
5380 static guint
5381 fDevice_Instance(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, int hf)
5383 guint8 tag_no, tag_info;
5384 guint32 lvt, safe_lvt;
5385 guint tag_len;
5386 proto_item *ti;
5387 proto_tree *subtree;
5389 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5391 if (lvt > 4)
5392 safe_lvt = 4;
5393 else
5394 safe_lvt = lvt;
5396 ti = proto_tree_add_item(tree, hf, tvb, offset+tag_len, safe_lvt, ENC_BIG_ENDIAN);
5398 if (lvt != safe_lvt)
5399 expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
5400 "This field claims to be an impossible %u bytes, while the max is %u", lvt, safe_lvt);
5402 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5403 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5405 return offset+tag_len+lvt;
5408 /* set split_val to zero when not needed */
5409 static guint
5410 fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5411 guint offset, const gchar *label, const value_string *vs, guint32 split_val)
5413 guint32 val = 0;
5414 guint8 tag_no, tag_info;
5415 guint32 lvt;
5416 guint tag_len;
5417 proto_item *ti;
5418 proto_tree *subtree;
5420 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5421 /* only support up to a 4 byte (32-bit) enumeration */
5422 if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
5423 if (vs)
5424 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5425 "%s %s", label, val_to_split_str(val, split_val, vs,
5426 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
5427 else
5428 ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5429 "%s %u", label, val);
5430 } else {
5431 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5432 "%s - %u octets (enumeration)", label, lvt);
5434 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5435 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5437 return offset+tag_len+lvt;
5440 static guint
5441 fEnumeratedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5442 guint offset, const gchar *label, const value_string *vs)
5444 return fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, vs, 0);
5447 static guint
5448 fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5450 gint64 val = 0;
5451 guint8 tag_no, tag_info;
5452 guint32 lvt;
5453 guint tag_len;
5454 proto_item *ti;
5455 proto_tree *subtree;
5457 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5458 if (fSigned64(tvb, offset + tag_len, lvt, &val))
5459 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5460 "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
5461 else
5462 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5463 "%s - %u octets (Signed)", label, lvt);
5464 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5465 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5467 return offset+tag_len+lvt;
5470 static guint
5471 fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5473 guint8 tag_no, tag_info;
5474 guint32 lvt;
5475 guint tag_len;
5476 gfloat f_val;
5477 proto_item *ti;
5478 proto_tree *subtree;
5480 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5481 f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
5482 ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
5483 "%s%f (Real)", label, f_val);
5484 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5485 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5487 return offset+tag_len+4;
5490 static guint
5491 fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5493 guint8 tag_no, tag_info;
5494 guint32 lvt;
5495 guint tag_len;
5496 gdouble d_val;
5497 proto_item *ti;
5498 proto_tree *subtree;
5500 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5501 d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
5502 ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
5503 "%s%f (Double)", label, d_val);
5504 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5505 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5507 return offset+tag_len+8;
5510 static guint
5511 fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5513 guint32 val = 0, lvt;
5514 guint8 tag_no, tag_info;
5515 proto_item *ti;
5516 proto_tree *subtree;
5517 guint tag_len;
5519 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5520 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5521 ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
5522 tvb, offset, lvt+tag_len, val);
5523 else
5524 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5525 "Process Identifier - %u octets (Signed)", lvt);
5526 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5527 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5528 offset += tag_len + lvt;
5530 return offset;
5533 static guint
5534 fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5536 guint32 val = 0, lvt;
5537 guint8 tag_no, tag_info;
5538 proto_item *ti;
5539 proto_tree *subtree;
5540 guint tag_len;
5542 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5543 if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
5544 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5545 "%s (hh.mm.ss): %d.%02d.%02d%s",
5546 label,
5547 (val / 3600), ((val % 3600) / 60), (val % 60),
5548 val == 0 ? " (indefinite)" : "");
5549 else
5550 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5551 "%s - %u octets (Signed)", label, lvt);
5552 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5553 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5555 return offset+tag_len+lvt;
5558 static guint
5559 fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5561 guint32 month, weekOfMonth, dayOfWeek;
5562 guint8 tag_no, tag_info;
5563 guint32 lvt;
5564 guint tag_len;
5565 proto_item *ti;
5566 proto_tree *subtree;
5568 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5569 month = tvb_get_guint8(tvb, offset+tag_len);
5570 weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
5571 dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
5572 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
5573 val_to_str(month, months, "month (%d) not found"),
5574 val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
5575 val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
5576 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5577 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5579 return offset+tag_len+lvt;
5582 static guint
5583 fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5585 guint32 year, month, day, weekday;
5586 guint8 tag_no, tag_info;
5587 guint32 lvt;
5588 guint tag_len;
5589 proto_item *ti;
5590 proto_tree *subtree;
5592 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5593 year = tvb_get_guint8(tvb, offset+tag_len);
5594 month = tvb_get_guint8(tvb, offset+tag_len+1);
5595 day = tvb_get_guint8(tvb, offset+tag_len+2);
5596 weekday = tvb_get_guint8(tvb, offset+tag_len+3);
5597 if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
5598 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5599 "%sany", label);
5601 else if (year != 255) {
5602 year += 1900;
5603 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5604 "%s%s %d, %d, (Day of Week = %s)",
5605 label, val_to_str(month,
5606 months,
5607 "month (%d) not found"),
5608 day, year, val_to_str(weekday,
5609 day_of_week,
5610 "(%d) not found"));
5611 } else {
5612 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5613 "%s%s %d, any year, (Day of Week = %s)",
5614 label, val_to_str(month, months, "month (%d) not found"),
5615 day, val_to_str(weekday, day_of_week, "(%d) not found"));
5617 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5618 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5620 return offset+tag_len+lvt;
5623 static guint
5624 fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5626 guint32 hour, minute, second, msec, lvt;
5627 guint8 tag_no, tag_info;
5628 guint tag_len;
5629 proto_item *ti;
5630 proto_tree *subtree;
5632 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5633 hour = tvb_get_guint8(tvb, offset+tag_len);
5634 minute = tvb_get_guint8(tvb, offset+tag_len+1);
5635 second = tvb_get_guint8(tvb, offset+tag_len+2);
5636 msec = tvb_get_guint8(tvb, offset+tag_len+3);
5637 if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
5638 ti = proto_tree_add_text(tree, tvb, offset,
5639 lvt+tag_len, "%sany", label);
5640 else
5641 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
5642 "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
5643 label,
5644 hour > 12 ? hour - 12 : hour,
5645 minute, second, msec,
5646 hour >= 12 ? "P.M." : "A.M.",
5647 hour, minute, second, msec);
5648 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5649 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5651 return offset+tag_len+lvt;
5654 static guint
5655 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5657 proto_tree *subtree = tree;
5658 proto_item *tt;
5660 if (label != NULL) {
5661 tt = proto_tree_add_text(subtree, tvb, offset, 10, "%s", label);
5662 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5664 offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
5665 return fTime(tvb, pinfo, subtree, offset, "Time: ");
5668 static guint
5669 fTimeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5671 guint lastoffset = 0;
5672 guint8 tag_no, tag_info;
5673 guint32 lvt;
5675 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
5676 lastoffset = offset;
5677 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5678 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
5679 return offset;
5681 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
5682 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
5684 if (offset == lastoffset) break; /* exit loop if nothing happens inside */
5686 return offset;
5689 static guint
5690 fCalendarEntry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5692 guint8 tag_no, tag_info;
5693 guint32 lvt;
5695 switch (fTagNo(tvb, offset)) {
5696 case 0: /* Date */
5697 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
5698 break;
5699 case 1: /* dateRange */
5700 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5701 offset = fDateRange(tvb, pinfo, tree, offset);
5702 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5703 break;
5704 case 2: /* BACnetWeekNDay */
5705 offset = fWeekNDay(tvb, pinfo, tree, offset);
5706 break;
5707 default:
5708 return offset;
5711 return offset;
5714 static guint
5715 fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
5717 guint32 lvt = 0;
5718 proto_tree* subtree = tree;
5719 proto_item* ti = 0;
5721 if (tvb_reported_length_remaining(tvb, offset) > 0) {
5722 ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
5723 if (ti) {
5724 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5726 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
5727 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
5728 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
5730 return offset;
5733 static guint
5734 fTimeStamp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
5736 guint8 tag_no = 0, tag_info = 0;
5737 guint32 lvt = 0;
5739 if (tvb_reported_length_remaining(tvb, offset) > 0) { /* don't loop, it's a CHOICE */
5740 switch (fTagNo(tvb, offset)) {
5741 case 0: /* time */
5742 offset = fTime(tvb, pinfo, tree, offset, label?label:"time: ");
5743 break;
5744 case 1: /* sequenceNumber */
5745 offset = fUnsignedTag(tvb, pinfo, tree, offset,
5746 label?label:"sequence number: ");
5747 break;
5748 case 2: /* dateTime */
5749 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5750 offset = fDateTime(tvb, pinfo, tree, offset, label?label:"date time: ");
5751 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5752 break;
5753 default:
5754 return offset;
5758 return offset;
5762 static guint
5763 fClientCOV(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5765 if (tvb_reported_length_remaining(tvb, offset) > 0) {
5766 offset = fApplicationTypes(tvb, pinfo, tree, offset, "increment: ");
5768 return offset;
5771 static const value_string
5772 BACnetDaysOfWeek [] = {
5773 { 0, "Monday" },
5774 { 1, "Tuesday" },
5775 { 2, "Wednesday" },
5776 { 3, "Thursday" },
5777 { 4, "Friday" },
5778 { 5, "Saturday" },
5779 { 6, "Sunday" },
5780 { 0, NULL }
5783 static guint
5784 fDestination(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5786 if (tvb_reported_length_remaining(tvb, offset) > 0) {
5787 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
5788 "valid Days: ", BACnetDaysOfWeek);
5789 offset = fTime(tvb, pinfo, tree, offset, "from time: ");
5790 offset = fTime(tvb, pinfo, tree, offset, "to time: ");
5791 offset = fRecipient(tvb, pinfo, tree, offset);
5792 offset = fProcessId(tvb, pinfo, tree, offset);
5793 offset = fApplicationTypes(tvb, pinfo, tree, offset,
5794 "issue confirmed notifications: ");
5795 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
5796 "transitions: ", BACnetEventTransitionBits);
5798 return offset;
5802 static guint
5803 fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5805 gchar *tmp;
5806 guint start = offset;
5807 guint8 tag_no, tag_info;
5808 proto_tree *subtree = tree;
5809 proto_item *ti = 0;
5811 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5813 if (lvt > 0) {
5814 tmp = tvb_bytes_to_str(tvb, offset, lvt);
5815 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
5816 offset += lvt;
5819 if (ti)
5820 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5822 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5824 return offset;
5827 static guint
5828 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
5830 gchar *tmp;
5831 guint start = offset;
5832 guint8 tag_no, tag_info;
5833 proto_tree* subtree = tree;
5834 proto_item* ti;
5836 offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5838 ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
5840 if (lvt > 0) {
5841 if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
5843 guint32 ip = tvb_get_ipv4(tvb, offset);
5844 guint16 port = tvb_get_ntohs(tvb, offset+4);
5846 proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
5847 proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
5849 } else {
5850 if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
5851 struct e_in6_addr addr;
5852 guint16 port = tvb_get_ntohs(tvb, offset+16);
5853 tvb_get_ipv6(tvb, offset, &addr);
5855 proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
5856 proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
5858 } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
5859 tmp = tvb_bytes_to_str(tvb, offset, lvt);
5860 ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
5863 offset += lvt;
5866 if (ti)
5867 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5869 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
5871 return offset;
5874 static guint
5875 fAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5877 guint8 tag_no, tag_info;
5878 guint32 lvt;
5879 guint offs;
5881 offset = fUnsignedTag(tvb, pinfo, tree, offset, "network-number");
5882 offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5883 if (lvt == 0) {
5884 proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
5885 offset += offs;
5886 } else
5887 offset = fMacAddress(tvb, pinfo, tree, offset, "MAC-address: ", lvt);
5889 return offset;
5892 static guint
5893 fSessionKey(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5895 offset = fOctetString(tvb, pinfo, tree, offset, "session key: ", 8);
5896 return fAddress(tvb, pinfo, tree, offset);
5899 static guint
5900 fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5902 guint8 tag_no, tag_info;
5903 guint32 lvt;
5904 guint tag_length;
5905 proto_item *ti;
5906 proto_tree *subtree;
5907 guint32 object_id;
5909 tag_length = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5910 object_id = tvb_get_ntohl(tvb, offset+tag_length);
5911 object_type = object_id_type(object_id);
5912 ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
5913 "ObjectIdentifier: %s, %u",
5914 val_to_split_str(object_type,
5915 128,
5916 BACnetObjectType,
5917 ASHRAE_Reserved_Fmt,
5918 Vendor_Proprietary_Fmt),
5919 object_id_instance(object_id));
5920 if (col_get_writable(pinfo->cinfo))
5921 col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
5922 val_to_split_str(object_type,
5923 128,
5924 BACnetObjectType,
5925 ASHRAE_Reserved_Fmt,
5926 Vendor_Proprietary_Fmt),
5927 object_id_instance(object_id));
5929 /* update BACnet Statistics */
5930 updateBacnetInfoValue(BACINFO_OBJECTID,
5931 wmem_strdup(wmem_packet_scope(),
5932 val_to_split_str(object_type, 128,
5933 BACnetObjectType, ASHRAE_Reserved_Fmt,
5934 Vendor_Proprietary_Fmt)));
5935 updateBacnetInfoValue(BACINFO_INSTANCEID,
5936 wmem_strdup_printf(wmem_packet_scope(),
5937 "Instance ID: %u",
5938 object_id_instance(object_id)));
5940 /* here are the details of how we arrived at the above text */
5941 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
5942 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
5943 offset += tag_length;
5944 proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
5945 proto_tree_add_item(subtree, hf_bacapp_instanceNumber, tvb, offset, 4, ENC_BIG_ENDIAN);
5946 offset += 4;
5948 return offset;
5951 static guint
5952 fRecipient(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5954 guint8 tag_no, tag_info;
5955 guint32 lvt;
5957 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
5958 if (tag_no < 2) {
5959 if (tag_no == 0) { /* device */
5960 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
5962 else { /* address */
5963 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5964 offset = fAddress(tvb, pinfo, tree, offset);
5965 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
5968 return offset;
5971 static guint
5972 fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
5974 guint lastoffset = 0;
5975 guint8 tag_no, tag_info;
5976 guint32 lvt;
5977 proto_tree *orgtree = tree;
5978 proto_item *tt;
5979 proto_tree *subtree;
5981 /* beginning of new item - indent and label */
5982 tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Recipient Process" );
5983 tree = proto_item_add_subtree(tt, ett_bacapp_value);
5985 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
5986 lastoffset = offset;
5988 switch (fTagNo(tvb, offset)) {
5989 case 0: /* recipient */
5990 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
5991 tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient"); /* add tree label and indent */
5992 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
5993 offset = fRecipient(tvb, pinfo, subtree, offset);
5994 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
5995 break;
5996 case 1: /* processId */
5997 offset = fProcessId(tvb, pinfo, tree, offset);
5998 lastoffset = offset;
5999 break;
6000 default:
6001 break;
6003 if (offset == lastoffset) break; /* nothing happened, exit loop */
6005 return offset;
6008 static guint
6009 fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6011 guint lastoffset = 0;
6012 guint8 tag_no, tag_info;
6013 guint32 lvt;
6014 proto_tree *subtree;
6015 proto_item *tt;
6016 proto_tree *orgtree = tree;
6017 guint itemno = 1;
6019 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6020 lastoffset = offset;
6021 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6022 if (tag_is_closing(tag_info) ) {
6023 return offset;
6025 switch (tag_no) {
6027 case 0: /* recipient */
6028 /* beginning of new item in list */
6029 tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Subscription %d",itemno); /* add tree label and indent */
6030 itemno = itemno + 1;
6031 tree = proto_item_add_subtree(tt, ett_bacapp_value);
6033 tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient"); /* add tree label and indent */
6034 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6035 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
6036 offset = fRecipientProcess(tvb, pinfo, subtree, offset);
6037 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context close */
6038 break;
6039 case 1: /* MonitoredPropertyReference */
6040 tt = proto_tree_add_text(tree, tvb, offset, 1, "Monitored Property Reference");
6041 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
6042 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6043 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
6044 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6045 break;
6046 case 2: /* IssueConfirmedNotifications - boolean */
6047 offset = fBooleanTag(tvb, pinfo, tree, offset, "Issue Confirmed Notifications: ");
6048 break;
6049 case 3: /* TimeRemaining */
6050 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Time Remaining: ");
6051 break;
6052 case 4: /* COVIncrement */
6053 offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
6054 break;
6055 default:
6056 break;
6058 if (offset == lastoffset) break; /* nothing happened, exit loop */
6060 return offset;
6063 static guint
6064 fAddressBinding(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6066 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6067 return fAddress(tvb, pinfo, tree, offset);
6070 static guint
6071 fActionCommand(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
6073 guint lastoffset = 0, len;
6074 guint8 tag_no, tag_info;
6075 guint32 lvt;
6076 proto_tree *subtree = tree;
6078 /* set the optional global properties to indicate not-used */
6079 propertyArrayIndex = -1;
6080 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6081 lastoffset = offset;
6082 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6083 if (tag_is_closing(tag_info) ) {
6084 if (tag_no == tag_match) {
6085 return offset;
6087 offset += len;
6088 subtree = tree;
6089 continue;
6091 switch (tag_no) {
6093 case 0: /* deviceIdentifier */
6094 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6095 break;
6096 case 1: /* objectIdentifier */
6097 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
6098 break;
6099 case 2: /* propertyIdentifier */
6100 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
6101 break;
6102 case 3: /* propertyArrayIndex */
6103 offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
6104 break;
6105 case 4: /* propertyValue */
6106 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
6107 break;
6108 case 5: /* priority */
6109 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
6110 break;
6111 case 6: /* postDelay */
6112 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Post Delay: ");
6113 break;
6114 case 7: /* quitOnFailure */
6115 offset = fBooleanTag(tvb, pinfo, subtree, offset,
6116 "Quit On Failure: ");
6117 break;
6118 case 8: /* writeSuccessful */
6119 offset = fBooleanTag(tvb, pinfo, subtree, offset,
6120 "Write Successful: ");
6121 break;
6122 default:
6123 return offset;
6125 if (offset == lastoffset) break; /* nothing happened, exit loop */
6127 return offset;
6130 /* BACnetActionList ::= SEQUENCE{
6131 action [0] SEQUENCE OF BACnetActionCommand
6134 static guint
6135 fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6137 guint lastoffset = 0, len;
6138 guint8 tag_no, tag_info;
6139 guint32 lvt;
6140 proto_tree *subtree = tree;
6141 proto_item *ti;
6143 while (tvb_reported_length_remaining(tvb, offset) > 0) {
6144 lastoffset = offset;
6145 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6146 if (tag_is_closing(tag_info)) {
6147 subtree = tree;
6148 if ( tag_no != 0 ) /* don't eat the closing property tag, just return */
6149 return offset;
6150 offset += len;
6151 continue;
6153 if (tag_is_opening(tag_info)) {
6154 ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
6155 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6156 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
6157 &tag_no, &tag_info, &lvt);
6159 switch (tag_no) {
6160 case 0: /* BACnetActionCommand */
6161 offset = fActionCommand(tvb, pinfo, subtree, offset, tag_no);
6162 break;
6163 default:
6164 break;
6166 if (offset == lastoffset) break; /* nothing happened, exit loop */
6168 return offset;
6171 static guint
6172 fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6174 guint8 tag_no, tag_info;
6175 guint32 lvt;
6176 guint tag_len;
6177 proto_item *ti;
6178 proto_tree *subtree;
6179 const gchar *label = "Property Identifier";
6181 propertyIdentifier = 0; /* global Variable */
6182 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6183 /* can we decode this value? */
6184 if (fUnsigned32(tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
6185 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6186 "%s: %s (%u)", label,
6187 val_to_split_str(propertyIdentifier, 512,
6188 BACnetPropertyIdentifier,
6189 ASHRAE_Reserved_Fmt,
6190 Vendor_Proprietary_Fmt), propertyIdentifier);
6191 if (col_get_writable(pinfo->cinfo))
6192 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
6193 val_to_split_str(propertyIdentifier, 512,
6194 BACnetPropertyIdentifier,
6195 ASHRAE_Reserved_Fmt,
6196 Vendor_Proprietary_Fmt));
6197 } else {
6198 /* property identifiers cannot be larger than 22-bits */
6199 return offset;
6201 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6202 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6203 proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
6204 offset+tag_len, lvt, ENC_BIG_ENDIAN);
6206 return offset+tag_len+lvt;
6209 static guint
6210 fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6212 guint8 tag_no, tag_info;
6213 guint32 lvt;
6214 guint tag_len;
6215 proto_item *ti;
6216 proto_tree *subtree;
6218 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6219 if (fUnsigned32(tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
6220 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6221 "property Array Index (Unsigned) %u", propertyArrayIndex);
6222 else
6223 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
6224 "property Array Index - %u octets (Unsigned)", lvt);
6225 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6226 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6228 return offset+tag_len+lvt;
6231 static guint
6232 fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6234 guint8 tag_no, tag_info, character_set;
6235 guint32 lvt, l;
6236 gsize inbytesleft, outbytesleft = 512;
6237 guint offs, extra = 1;
6238 guint8 *str_val;
6239 const char *coding;
6240 guint8 bf_arr[512], *out = &bf_arr[0];
6241 proto_item *ti;
6242 proto_tree *subtree;
6243 guint start = offset;
6245 if (tvb_reported_length_remaining(tvb, offset) > 0) {
6247 offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6249 character_set = tvb_get_guint8(tvb, offset+offs);
6250 /* Account for code page if DBCS */
6251 if (character_set == 1) {
6252 extra = 3;
6254 offset += (offs+extra);
6255 lvt -= (extra);
6257 do {
6258 inbytesleft = l = MIN(lvt, 256);
6260 * XXX - are we guaranteed that these encoding
6261 * names correspond, on *all* platforms with
6262 * iconv(), to the encodings we want?
6263 * If not (and perhaps even if so), we should
6264 * perhaps have our own iconv() implementation,
6265 * with a different name, so that we control the
6266 * encodings it supports and the names of those
6267 * encodings.
6269 * We should also handle that in the general
6270 * string handling code, rather than making it
6271 * specific to the BACAPP dissector, as many
6272 * other dissectors need to handle various
6273 * character encodings.
6275 str_val = tvb_get_string(wmem_packet_scope(), tvb, offset, l);
6276 /** this decoding may be not correct for multi-byte characters, Lka */
6277 switch (character_set) {
6278 case ANSI_X34:
6279 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UTF-8");
6280 coding = "UTF-8";
6281 break;
6282 case IBM_MS_DBCS:
6283 out = str_val;
6284 coding = "IBM MS DBCS";
6285 break;
6286 case JIS_C_6226:
6287 out = str_val;
6288 coding = "JIS C 6226";
6289 break;
6290 case ISO_10646_UCS4:
6291 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
6292 coding = "ISO 10646 UCS-4";
6293 break;
6294 case ISO_10646_UCS2:
6295 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
6296 coding = "ISO 10646 UCS-2";
6297 break;
6298 case ISO_18859_1:
6299 fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
6300 coding = "ISO 8859-1";
6301 break;
6302 default:
6303 out = str_val;
6304 coding = "unknown";
6305 break;
6307 ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s '%s'", label, coding, out);
6308 lvt -= l;
6309 offset += l;
6310 } while (lvt > 0);
6312 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6314 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6315 proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
6317 if (character_set == 1) {
6318 proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
6320 /* XXX - put the string value here */
6322 return offset;
6325 static guint
6326 fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label,
6327 const value_string *src)
6329 guint8 tag_no, tag_info, tmp;
6330 gint j, unused, skip;
6331 guint start = offset;
6332 guint offs;
6333 guint32 lvt, i, numberOfBytes;
6334 guint8 bf_arr[256];
6335 proto_tree* subtree = tree;
6336 proto_item* ti;
6338 offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6339 numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
6340 offset += offs;
6341 unused = tvb_get_guint8(tvb, offset); /* get the unused Bits */
6342 ti = proto_tree_add_text(tree, tvb, start, offs+lvt,
6343 "%s(Bit String)", label);
6344 if (ti) {
6345 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6347 fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
6348 proto_tree_add_text(subtree, tvb, offset, 1,
6349 "Unused bits: %u", unused);
6350 skip = 0;
6351 for (i = 0; i < numberOfBytes; i++) {
6352 tmp = tvb_get_guint8(tvb, (offset)+i+1);
6353 if (i == numberOfBytes-1) { skip = unused; }
6354 for (j = 0; j < 8-skip; j++) {
6355 if (src != NULL) {
6356 if (tmp & (1 << (7 - j)))
6357 proto_tree_add_text(subtree, tvb,
6358 offset+i+1, 1,
6359 "%s = TRUE",
6360 val_to_str((guint) (i*8 +j),
6361 src,
6362 ASHRAE_Reserved_Fmt));
6363 else
6364 proto_tree_add_text(subtree, tvb,
6365 offset+i+1, 1,
6366 "%s = FALSE",
6367 val_to_str((guint) (i*8 +j),
6368 src,
6369 ASHRAE_Reserved_Fmt));
6370 } else {
6371 bf_arr[MIN(255, (i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
6376 if (src == NULL) {
6377 bf_arr[MIN(255, numberOfBytes*8-unused)] = 0;
6378 proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
6381 offset += lvt;
6383 return offset;
6386 static guint
6387 fBitStringTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6389 return fBitStringTagVS(tvb, pinfo, tree, offset, label, NULL);
6392 /* handles generic application types, as well as enumerated and enumerations
6393 with reserved and proprietarty ranges (split) */
6394 static guint
6395 fApplicationTypesEnumeratedSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6396 const gchar *label, const value_string *src, guint32 split_val)
6398 guint8 tag_no, tag_info;
6399 guint32 lvt;
6400 guint tag_len;
6402 if (tvb_reported_length_remaining(tvb, offset) > 0) {
6404 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6405 if (!tag_is_context_specific(tag_info)) {
6406 switch (tag_no) {
6407 case 0: /** NULL 20.2.2 */
6408 offset = fNullTag(tvb, pinfo, tree, offset, label);
6409 break;
6410 case 1: /** BOOLEAN 20.2.3 */
6411 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
6412 break;
6413 case 2: /** Unsigned Integer 20.2.4 */
6414 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
6415 break;
6416 case 3: /** Signed Integer 20.2.5 */
6417 offset = fSignedTag(tvb, pinfo, tree, offset, label);
6418 break;
6419 case 4: /** Real 20.2.6 */
6420 offset = fRealTag(tvb, pinfo, tree, offset, label);
6421 break;
6422 case 5: /** Double 20.2.7 */
6423 offset = fDoubleTag(tvb, pinfo, tree, offset, label);
6424 break;
6425 case 6: /** Octet String 20.2.8 */
6426 offset = fOctetString(tvb, pinfo, tree, offset, label, lvt);
6427 break;
6428 case 7: /** Character String 20.2.9 */
6429 offset = fCharacterString(tvb, pinfo, tree, offset, label);
6430 break;
6431 case 8: /** Bit String 20.2.10 */
6432 offset = fBitStringTagVS(tvb, pinfo, tree, offset, label, src);
6433 break;
6434 case 9: /** Enumerated 20.2.11 */
6435 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label, src, split_val);
6436 break;
6437 case 10: /** Date 20.2.12 */
6438 offset = fDate(tvb, pinfo, tree, offset, label);
6439 break;
6440 case 11: /** Time 20.2.13 */
6441 offset = fTime(tvb, pinfo, tree, offset, label);
6442 break;
6443 case 12: /** BACnetObjectIdentifier 20.2.14 */
6444 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
6445 break;
6446 case 13: /* reserved for ASHRAE */
6447 case 14:
6448 case 15:
6449 proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
6450 offset += lvt + tag_len;
6451 break;
6452 default:
6453 break;
6458 return offset;
6461 static guint
6462 fShedLevel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6464 guint lastoffset = 0;
6466 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6467 lastoffset = offset;
6469 switch (fTagNo(tvb, offset)) {
6470 case 0: /* percent */
6471 offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed percent: ");
6472 break;
6473 case 1: /* level */
6474 offset = fUnsignedTag(tvb, pinfo, tree, offset, "shed level: ");
6475 break;
6476 case 2: /* amount */
6477 offset = fRealTag(tvb, pinfo, tree, offset, "shed amount: ");
6478 break;
6479 default:
6480 return offset;
6482 if (offset == lastoffset) break; /* nothing happened, exit loop */
6484 return offset;
6487 static guint
6488 fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6489 const gchar *label, const value_string *vs)
6491 return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
6494 static guint
6495 fApplicationTypes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
6496 const gchar *label)
6498 return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
6501 static guint
6502 fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
6504 guint8 tag_no, tag_info;
6505 guint32 lvt;
6506 guint tag_len;
6507 proto_item *ti;
6508 proto_tree *subtree;
6509 gint tvb_len;
6511 (void)label;
6512 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6513 /* cap the the suggested length in case of bad data */
6514 tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
6515 if ((tvb_len >= 0) && ((guint32)tvb_len < lvt)) {
6516 lvt = tvb_len;
6518 ti = proto_tree_add_text(tree, tvb, offset+tag_len, lvt,
6519 "Context Value (as %u DATA octets)", lvt);
6521 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
6522 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
6524 return offset + tag_len + lvt;
6527 BACnetPrescale ::= SEQUENCE {
6528 multiplier [0] Unsigned,
6529 moduloDivide [1] Unsigned
6532 static guint
6533 fPrescale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6535 guint8 tag_no, tag_info;
6536 guint32 lvt;
6537 guint lastoffset = 0;
6539 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6540 lastoffset = offset;
6541 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6542 if (tag_is_closing(tag_info) ) {
6543 return offset;
6545 switch (tag_no) {
6546 case 0: /* multiplier */
6547 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Multiplier: ");
6548 break;
6549 case 1: /* moduloDivide */
6550 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Modulo Divide: ");
6551 break;
6552 default:
6553 return offset;
6555 if (offset == lastoffset) break; /* nothing happened, exit loop */
6557 return offset;
6561 BACnetScale ::= CHOICE {
6562 floatScale [0] REAL,
6563 integerScale [1] INTEGER
6566 static guint
6567 fScale(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6569 guint8 tag_no, tag_info;
6570 guint32 lvt;
6571 guint lastoffset = 0;
6573 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6574 lastoffset = offset;
6575 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6576 if (tag_is_closing(tag_info) ) {
6577 return offset;
6579 switch (tag_no) {
6580 case 0: /* floatScale */
6581 offset = fRealTag(tvb, pinfo, tree, offset, "Float Scale: ");
6582 break;
6583 case 1: /* integerScale */
6584 offset = fSignedTag(tvb, pinfo, tree, offset, "Integer Scale: ");
6585 break;
6586 default:
6587 return offset;
6589 if (offset == lastoffset) break; /* nothing happened, exit loop */
6591 return offset;
6594 BACnetAccumulatorRecord ::= SEQUENCE {
6595 timestamp [0] BACnetDateTime,
6596 presentValue [1] Unsigned,
6597 accumulatedValue [2] Unsigned,
6598 accumulatortStatus [3] ENUMERATED {
6599 normal (0),
6600 starting (1),
6601 recovered (2),
6602 abnormal (3),
6603 failed (4)
6607 static guint
6608 fLoggingRecord(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
6610 guint8 tag_no, tag_info;
6611 guint32 lvt;
6612 guint lastoffset = 0;
6614 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6615 lastoffset = offset;
6616 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6617 if (tag_is_closing(tag_info) ) {
6618 return offset;
6620 switch (tag_no) {
6621 case 0: /* timestamp */
6622 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6623 offset = fDateTime(tvb, pinfo, tree, offset, "Timestamp: ");
6624 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6625 break;
6626 case 1: /* presentValue */
6627 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Present Value: ");
6628 break;
6629 case 2: /* accumulatedValue */
6630 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Accumulated Value: ");
6631 break;
6632 case 3: /* accumulatorStatus */
6633 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "Accumulator Status: ", BACnetAccumulatorStatus);
6634 break;
6635 default:
6636 return offset;
6638 if (offset == lastoffset) break; /* nothing happened, exit loop */
6640 return offset;
6644 SEQ OF Any enumeration (current usage is SEQ OF BACnetDoorAlarmState
6646 static guint
6647 fSequenceOfEnums(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, const value_string *vs)
6649 guint8 tag_no, tag_info;
6650 guint32 lvt;
6651 guint lastoffset = 0;
6653 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6654 lastoffset = offset;
6655 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6656 if (tag_is_closing(tag_info) ) {
6657 return offset;
6659 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, label, vs);
6660 if ( offset == lastoffset ) break;
6662 return offset;
6666 SEQ OF BACnetDeviceObjectReference (accessed as an array)
6669 static guint
6670 fDoorMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6672 guint8 tag_no, tag_info;
6673 guint32 lvt;
6674 guint lastoffset = 0;
6676 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6677 lastoffset = offset;
6678 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6679 if (tag_is_closing(tag_info) ) {
6680 return offset;
6682 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6683 if (offset == lastoffset) break;
6685 return offset;
6689 SEQ OF ReadAccessSpecification
6691 static guint
6692 fListOfGroupMembers(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6694 guint8 tag_no, tag_info;
6695 guint32 lvt;
6696 guint lastoffset = 0;
6698 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6699 lastoffset = offset;
6700 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6701 if (tag_is_closing(tag_info) ) {
6702 return offset;
6704 offset = fReadAccessSpecification(tvb, pinfo, tree, offset);
6705 if ( offset == lastoffset ) break;
6707 return offset;
6710 static guint
6711 fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
6713 guint8 tag_no, tag_info;
6714 guint32 lvt;
6715 guint lastoffset = 0, depth = 0;
6716 char ar[256];
6717 guint32 save_object_type;
6719 if (propertyIdentifier >= 0) {
6720 g_snprintf(ar, sizeof(ar), "%s: ",
6721 val_to_split_str(propertyIdentifier, 512,
6722 BACnetPropertyIdentifier,
6723 ASHRAE_Reserved_Fmt,
6724 Vendor_Proprietary_Fmt));
6725 } else {
6726 g_snprintf(ar, sizeof(ar), "Abstract Type: ");
6728 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
6729 lastoffset = offset;
6730 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
6731 if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
6732 if (depth <= 0) return offset;
6735 /* Application Tags */
6736 switch (propertyIdentifier) {
6737 case 2: /* action */
6738 /* loop object is application tagged,
6739 command object is context tagged */
6740 if (tag_is_context_specific(tag_info)) {
6741 /* BACnetActionList */
6742 offset = fActionList(tvb, pinfo, tree, offset);
6743 } else {
6744 /* BACnetAction */
6745 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6746 BACnetAction);
6748 break;
6749 case 30: /* BACnetAddressBinding */
6750 offset = fAddressBinding(tvb, pinfo, tree, offset);
6751 break;
6752 case 54: /* list of object property reference */
6753 offset = fLOPR(tvb, pinfo, tree, offset);
6754 break;
6755 case 55: /* list-of-session-keys */
6756 fSessionKey(tvb, pinfo, tree, offset);
6757 break;
6758 case 79: /* object-type */
6759 case 96: /* protocol-object-types-supported */
6760 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar,
6761 BACnetObjectType, 128);
6762 break;
6763 case 97: /* Protocol-Services-Supported */
6764 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6765 BACnetServicesSupported);
6766 break;
6767 case 102: /* recipient-list */
6768 offset = fDestination(tvb, pinfo, tree, offset);
6769 break;
6770 case 107: /* segmentation-supported */
6771 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6772 BACnetSegmentation);
6773 break;
6774 case 111: /* Status-Flags */
6775 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6776 BACnetStatusFlags);
6777 break;
6778 case 112: /* System-Status */
6779 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6780 BACnetDeviceStatus);
6781 break;
6782 case 117: /* units */
6783 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar,
6784 BACnetEngineeringUnits);
6785 break;
6786 case 87: /* priority-array -- accessed as a BACnetARRAY */
6787 if (propertyArrayIndex == 0) {
6788 /* BACnetARRAY index 0 refers to the length
6789 of the array, not the elements of the array */
6790 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6791 } else {
6792 offset = fPriorityArray(tvb, pinfo, tree, offset);
6794 break;
6795 case 38: /* exception-schedule */
6796 if (object_type < 128) {
6797 if (propertyArrayIndex == 0) {
6798 /* BACnetARRAY index 0 refers to the length
6799 of the array, not the elements of the array */
6800 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6801 } else {
6802 offset = fSpecialEvent(tvb, pinfo, tree, offset);
6805 break;
6806 case 19: /* controlled-variable-reference */
6807 case 60: /* manipulated-variable-reference */
6808 case 132: /* log-device-object-property */
6809 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
6810 break;
6811 case 109: /* Setpoint-Reference */
6812 /* setpoint-Reference is actually BACnetSetpointReference which is a SEQ of [0] */
6813 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6814 offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
6815 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6816 break;
6817 case 123: /* weekly-schedule -- accessed as a BACnetARRAY */
6818 if (object_type < 128) {
6819 if (propertyArrayIndex == 0) {
6820 /* BACnetARRAY index 0 refers to the length
6821 of the array, not the elements of the array */
6822 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6823 } else {
6824 offset = fWeeklySchedule(tvb, pinfo, tree, offset);
6827 break;
6828 case 127: /* client COV increment */
6829 offset = fClientCOV(tvb, pinfo, tree, offset);
6830 break;
6831 case 131: /* log-buffer */
6832 if ( object_type == 25 )
6833 offset = fEventLogRecord(tvb, pinfo, tree, offset);
6834 else if ( object_type == 27 )
6835 offset = fLogMultipleRecord(tvb, pinfo, tree, offset);
6836 else
6837 offset = fLogRecord(tvb, pinfo, tree, offset);
6838 break;
6839 case 159: /* member-of */
6840 case 165: /* zone-members */
6841 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6842 break;
6843 case 196: /* last-restart-reason */
6844 offset = fRestartReason(tvb, pinfo, tree, offset);
6845 break;
6846 case 212: /* actual-shed-level */
6847 case 214: /* expected-shed-level */
6848 case 218: /* requested-shed-level */
6849 offset = fShedLevel(tvb, pinfo, tree, offset);
6850 break;
6851 case 152: /* active-cov-subscriptions */
6852 offset = fCOVSubscription(tvb, pinfo, tree, offset);
6853 break;
6854 case 23: /* date-list */
6855 offset = fCalendarEntry(tvb, pinfo, tree, offset);
6856 break;
6857 case 116: /* time-sychronization-recipients */
6858 offset = fRecipient(tvb, pinfo, tree, offset);
6859 break;
6860 case 83: /* event-parameters */
6861 offset = fEventParameter(tvb, pinfo, tree, offset);
6862 break;
6863 case 211: /* subordinate-list */
6864 offset = fDeviceObjectReference(tvb, pinfo, tree, offset);
6865 break;
6866 case 130: /* event-time-stamp */
6867 offset = fEventTimeStamps(tvb, pinfo, tree, offset);
6868 break;
6869 case 197: /* logging-type */
6870 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLoggingType);
6871 break;
6872 case 36: /* event-state */
6873 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, ar, BACnetEventState, 64);
6874 break;
6875 case 103: /* reliability */
6876 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetReliability);
6877 break;
6878 case 72: /* notify-type */
6879 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNotifyType);
6880 break;
6881 case 208: /* node-type */
6882 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetNodeType);
6883 break;
6884 case 231: /* door-status */
6885 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorStatus);
6886 break;
6887 case 233: /* lock-status */
6888 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLockStatus);
6889 break;
6890 case 235: /* secured-status */
6891 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetDoorSecuredStatus);
6892 break;
6893 case 158: /* maintenance-required */
6894 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetMaintenance);
6895 break;
6896 case 92: /* program-state */
6897 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramState);
6898 break;
6899 case 90: /* program-change */
6900 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramRequest);
6901 break;
6902 case 100: /* reason-for-halt */
6903 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError);
6904 break;
6905 case 160: /* mode */
6906 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode);
6907 break;
6908 case 163: /* silenced */
6909 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetSilencedState);
6910 break;
6911 case 161: /* operation-expected */
6912 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyOperation);
6913 break;
6914 case 164: /* tracking-value */
6915 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyState);
6916 break;
6917 case 41: /* file-access-method */
6918 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetFileAccessMethod);
6919 break;
6920 case 185: /* prescale */
6921 offset = fPrescale(tvb, pinfo, tree, offset);
6922 break;
6923 case 187: /* scale */
6924 offset = fScale(tvb, pinfo, tree, offset);
6925 break;
6926 case 184: /* logging-record */
6927 offset = fLoggingRecord(tvb, pinfo, tree, offset);
6928 break;
6929 case 228: /* door-members */
6930 offset = fDoorMembers(tvb, pinfo, tree, offset);
6931 break;
6932 case 181: /* input-reference */
6933 offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6934 break;
6935 case 78: /* object-property-reference */
6936 offset = fObjectPropertyReference(tvb, pinfo, tree, offset);
6937 break;
6938 case 234: /* masked-alarm-values */
6939 offset = fSequenceOfEnums(tvb, pinfo, tree, offset, "masked-alarm-value: ", BACnetDoorAlarmState);
6940 break;
6941 case 53: /* list-of-group-members */
6942 save_object_type = object_type;
6943 offset = fListOfGroupMembers(tvb, pinfo, tree, offset);
6944 object_type = save_object_type;
6945 break;
6946 case 85: /* present-value */
6947 if ( object_type == 11 ) /* group object handling of present-value */
6949 offset = fReadAccessResult(tvb, pinfo, tree, offset);
6950 break;
6952 /* intentially fall through here so don't reorder this case statement */
6953 default:
6954 if (tag_info) {
6955 if (tag_is_opening(tag_info)) {
6956 ++depth;
6957 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6958 } else if (tag_is_closing(tag_info)) {
6959 --depth;
6960 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
6961 } else {
6962 offset = fContextTaggedValue(tvb, pinfo, tree, offset, ar);
6964 } else {
6965 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
6967 break;
6969 if (offset == lastoffset) break; /* nothing happened, exit loop */
6971 return offset;
6975 static guint
6976 fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
6978 guint8 tag_no;
6979 guint32 lvt;
6981 if (tag_is_opening(tag_info)) {
6982 offset += fTagHeaderTree(tvb, pinfo, tree, offset,
6983 &tag_no, &tag_info, &lvt);
6984 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
6985 if (tvb_length_remaining(tvb, offset) > 0) {
6986 offset += fTagHeaderTree(tvb, pinfo, tree, offset,
6987 &tag_no, &tag_info, &lvt);
6989 } else {
6990 proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
6991 "expected Opening Tag!");
6992 offset = tvb_length(tvb);
6995 return offset;
6999 static guint
7000 fPropertyIdentifierValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
7002 guint lastoffset = offset;
7003 guint8 tag_no, tag_info;
7004 guint32 lvt;
7006 offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
7007 if (offset > lastoffset) {
7008 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7009 if (tag_no == tagoffset+2) { /* Value - might not be present in ReadAccessResult */
7010 offset = fPropertyValue(tvb, pinfo, tree, offset, tag_info);
7013 return offset;
7016 static guint
7017 fBACnetPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7019 guint lastoffset = 0;
7020 guint8 tag_no, tag_info;
7021 guint32 lvt;
7023 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7024 lastoffset = offset;
7025 offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
7026 if (offset > lastoffset) {
7027 /* detect optional priority
7028 by looking to see if the next tag is context tag number 3 */
7029 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7030 if (tag_is_context_specific(tag_info) && (tag_no == 3))
7031 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
7033 if (offset == lastoffset) break; /* nothing happened, exit loop */
7035 return offset;
7038 static guint
7039 fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7041 guint lastoffset = 0, len;
7042 guint8 tag_no, tag_info;
7043 guint32 lvt;
7044 proto_tree *subtree = tree;
7045 proto_item *tt;
7047 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7048 lastoffset = offset;
7049 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7050 if (tag_is_closing(tag_info)) {
7051 offset += len;
7052 subtree = tree;
7053 continue;
7056 switch (tag_no) {
7057 case 0: /* ProcessId */
7058 offset = fUnsignedTag(tvb, pinfo, tree, offset, "subscriber Process Id: ");
7059 break;
7060 case 1: /* monitored ObjectId */
7061 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7062 break;
7063 case 2: /* issueConfirmedNotifications */
7064 offset = fBooleanTag(tvb, pinfo, tree, offset, "issue Confirmed Notifications: ");
7065 break;
7066 case 3: /* life time */
7067 offset = fTimeSpan(tvb, pinfo, tree, offset, "life time");
7068 break;
7069 case 4: /* monitoredPropertyIdentifier */
7070 if (tag_is_opening(tag_info)) {
7071 tt = proto_tree_add_text(subtree, tvb, offset, 1, "monitoredPropertyIdentifier");
7072 if (tt) {
7073 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7075 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7076 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
7077 break;
7079 FAULT;
7080 break;
7081 case 5: /* covIncrement */
7082 offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
7083 break;
7084 default:
7085 return offset;
7087 if (offset == lastoffset) break; /* nothing happened, exit loop */
7089 return offset;
7092 static guint
7093 fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7095 return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
7098 static guint
7099 fWhoHas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7101 guint lastoffset = 0;
7103 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7104 lastoffset = offset;
7106 switch (fTagNo(tvb, offset)) {
7107 case 0: /* deviceInstanceLowLimit */
7108 offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance Low Limit: ");
7109 break;
7110 case 1: /* deviceInstanceHighLimit */
7111 offset = fUnsignedTag(tvb, pinfo, tree, offset, "device Instance High Limit: ");
7112 break;
7113 case 2: /* BACnetObjectId */
7114 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7115 break;
7116 case 3: /* messageText */
7117 offset = fCharacterString(tvb, pinfo, tree, offset, "Object Name: ");
7118 break;
7119 default:
7120 return offset;
7122 if (offset == lastoffset) break; /* nothing happened, exit loop */
7124 return offset;
7128 static guint
7129 fDailySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
7131 guint lastoffset = 0;
7132 guint8 tag_no, tag_info;
7133 guint32 lvt;
7135 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7136 if (tag_is_opening(tag_info) && tag_no == 0) {
7137 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
7138 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7139 lastoffset = offset;
7140 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7141 if (tag_is_closing(tag_info)) {
7142 /* should be closing context tag 0 */
7143 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7144 return offset;
7147 offset = fTimeValue(tvb, pinfo, subtree, offset);
7148 if (offset == lastoffset) break; /* nothing happened, exit loop */
7150 } else if ((tag_no == 0) && (lvt == 0)) {
7151 /* not sure null (empty array element) is legal */
7152 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7154 return offset;
7157 static guint
7158 fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7160 guint lastoffset = 0;
7161 guint8 tag_no, tag_info;
7162 guint32 lvt;
7163 guint i = 1; /* day of week array index */
7164 proto_tree *subtree = tree;
7165 proto_item *tt;
7167 if (propertyArrayIndex > 0) {
7168 /* BACnetARRAY index 0 refers to the length
7169 of the array, not the elements of the array.
7170 BACnetARRAY index -1 is our internal flag that
7171 the optional index was not used.
7172 BACnetARRAY refers to this as all elements of the array.
7173 If the optional index is specified for a BACnetARRAY,
7174 then that specific array element is referenced. */
7175 i = propertyArrayIndex;
7177 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7178 lastoffset = offset;
7179 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7180 if (tag_is_closing(tag_info)) {
7181 return offset; /* outer encoding will print out closing tag */
7183 tt = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str(i++, day_of_week, "day of week (%d) not found"));
7184 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7185 offset = fDailySchedule(tvb, pinfo, subtree, offset);
7186 if (offset == lastoffset) break; /* nothing happened, exit loop */
7188 return offset;
7192 static guint
7193 fUTCTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7195 if (tvb_reported_length_remaining(tvb, offset) <= 0)
7196 return offset;
7198 return fDateTime(tvb, pinfo, tree, offset, "UTC-Time: ");
7201 static guint
7202 fTimeSynchronizationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7204 if (tvb_reported_length_remaining(tvb, offset) <= 0)
7205 return offset;
7207 return fDateTime(tvb, pinfo, tree, offset, NULL);
7210 static guint
7211 fDateRange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7213 if (tvb_reported_length_remaining(tvb, offset) <= 0)
7214 return offset;
7215 offset = fDate(tvb, pinfo, tree, offset, "Start Date: ");
7216 return fDate(tvb, pinfo, tree, offset, "End Date: ");
7219 static guint
7220 fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7222 guint32 val = 0;
7223 guint8 tag_no, tag_info;
7224 guint32 lvt;
7225 guint tag_len;
7226 proto_item *ti;
7227 proto_tree *subtree;
7228 const gchar *label = "Vendor ID";
7230 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7231 if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7232 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7233 "%s: %s (%u)",
7234 label,
7235 val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
7236 val);
7237 else
7238 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7239 "%s - %u octets (Unsigned)", label, lvt);
7240 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7241 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7243 if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1 and <= 2 are supported */
7244 proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7245 "Wrong length indicated. Expected 1 or 2, got %u", lvt);
7246 return offset+tag_len+lvt;
7249 proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
7250 offset+tag_len, lvt, ENC_BIG_ENDIAN);
7252 return offset+tag_len+lvt;
7255 static guint
7256 fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7258 guint32 val = 0;
7259 guint8 tag_no, tag_info;
7260 guint32 lvt;
7261 guint tag_len;
7262 proto_item *ti;
7263 proto_tree *subtree;
7264 const gchar *label = "Restart Reason";
7266 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7267 if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
7268 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7269 "%s: %s (%u)", label,
7270 val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
7271 else
7272 ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
7273 "%s - %u octets (Unsigned)", label, lvt);
7274 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
7275 fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7277 if (lvt != 1) {
7278 proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
7279 "Wrong length indicated. Expected 1, got %u", lvt);
7280 return offset+tag_len+lvt;
7283 proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
7284 offset+tag_len, lvt, ENC_BIG_ENDIAN);
7286 return offset+tag_len+lvt;
7289 static guint
7290 fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7292 guint lastoffset = 0;
7294 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7295 lastoffset = offset;
7296 switch (fTagNo(tvb, offset)) {
7298 case 0: /* textMessageSourceDevice */
7299 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7300 break;
7301 case 1: /* messageClass */
7302 switch (fTagNo(tvb, offset)) {
7303 case 0: /* numeric */
7304 offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: ");
7305 break;
7306 case 1: /* character */
7307 offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: ");
7308 break;
7310 break;
7311 case 2: /* messagePriority */
7312 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ",
7313 BACnetMessagePriority);
7314 break;
7315 case 3: /* message */
7316 offset = fCharacterString(tvb, pinfo, tree, offset, "message: ");
7317 break;
7318 default:
7319 return offset;
7321 if (offset == lastoffset) break; /* nothing happened, exit loop */
7323 return offset;
7326 static guint
7327 fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7329 return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
7332 static guint
7333 fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7335 guint lastoffset, len;
7336 guint8 tag_no, tag_info;
7337 guint32 lvt;
7338 proto_tree *subtree = tree;
7339 proto_item *tt;
7340 tvbuff_t *next_tvb;
7341 guint vendor_identifier = 0;
7342 guint service_number = 0;
7344 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7345 fUnsigned32(tvb, offset+len, lvt, &vendor_identifier);
7346 if (col_get_writable(pinfo->cinfo))
7347 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
7348 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7350 next_tvb = tvb_new_subset_remaining(tvb, offset);
7351 if (dissector_try_uint(bacapp_dissector_table,
7352 vendor_identifier, next_tvb, pinfo, tree)) {
7353 /* we parsed it so skip over length and we are done */
7354 offset += tvb_length(next_tvb);
7355 return offset;
7358 /* Not handled by vendor dissector */
7360 /* exit loop if nothing happens inside */
7361 while (tvb_reported_length_remaining(tvb, offset) > 0) {
7362 lastoffset = offset;
7363 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7364 if (tag_is_closing(tag_info)) {
7365 if (tag_no == 2) { /* Make sure it's the expected tag */
7366 offset += len;
7367 subtree = tree;
7368 continue;
7369 } else {
7370 break; /* End loop if incorrect closing tag */
7373 switch (tag_no) {
7375 /* vendorID is now parsed above */
7376 case 1: /* serviceNumber */
7377 fUnsigned32(tvb, offset+len, lvt, &service_number);
7378 if (col_get_writable(pinfo->cinfo))
7379 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ", service_number);
7380 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
7381 break;
7382 case 2: /*serviceParameters */
7383 if (tag_is_opening(tag_info)) {
7384 tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
7385 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7386 propertyIdentifier = -1;
7387 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7388 break;
7390 FAULT;
7391 break;
7392 default:
7393 return offset;
7395 if (offset == lastoffset) break; /* nothing happened, exit loop */
7398 return offset;
7401 static guint
7402 fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7404 return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7407 static guint
7408 fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7410 return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
7413 static guint
7414 fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
7416 guint lastoffset = 0;
7417 guint8 tag_no, tag_info;
7418 guint32 lvt;
7419 proto_tree *subtree = tree;
7420 proto_item *tt;
7422 if (label != NULL) {
7423 tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", label);
7424 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7427 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7428 lastoffset = offset;
7429 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7431 switch (tag_no) {
7432 case 0: /* subscriberProcessId */
7433 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "requesting Process Id: ");
7434 break;
7435 case 1: /* requestingSource */
7436 offset = fCharacterString(tvb, pinfo, tree, offset, "requesting Source: ");
7437 break;
7438 case 2: /* request */
7439 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
7440 "request: ", BACnetLifeSafetyOperation, 64);
7441 break;
7442 case 3: /* objectId */
7443 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
7444 break;
7445 default:
7446 return offset;
7448 if (offset == lastoffset) break; /* nothing happened, exit loop */
7450 return offset;
7453 typedef struct _value_string_enum {
7454 const value_string *valstr;
7455 } value_string_enum;
7457 static const value_string_enum
7458 BACnetPropertyStatesEnums[] = {
7459 { NULL },
7460 {BACnetBinaryPV },
7461 {BACnetEventType },
7462 {BACnetPolarity },
7463 {BACnetProgramRequest },
7464 {BACnetProgramState },
7465 {BACnetProgramError },
7466 {BACnetReliability },
7467 {BACnetEventState },
7468 {BACnetDeviceStatus },
7469 {BACnetEngineeringUnits },
7470 { NULL },
7471 {BACnetLifeSafetyMode },
7472 {BACnetLifeSafetyState },
7473 {BACnetRestartReason },
7474 {BACnetDoorAlarmState },
7475 {BACnetAction },
7476 {BACnetDoorSecuredStatus },
7477 {BACnetDoorStatus },
7478 { NULL }, /* {BACnetDoorValue }, */
7479 {BACnetFileAccessMethod },
7480 {BACnetLockStatus },
7481 {BACnetLifeSafetyOperation },
7482 {BACnetMaintenance },
7483 {BACnetNodeType },
7484 {BACnetNotifyType },
7485 { NULL }, /* {BACnetSecurityLevel }, */
7486 {BACnetShedState },
7487 {BACnetSilencedState },
7488 { NULL },
7489 { NULL }, /* {BACnetAccessEvent }, */
7490 { NULL }, /* {BACnetZoneOccupancyState }, */
7491 { NULL }, /* {BACnetAccessCredentialDisableReason }, */
7492 { NULL }, /* {BACnetAccessCredentialDisable }, */
7493 { NULL }, /* {BACnetAuthenticationStatus }, */
7494 { NULL },
7495 { NULL }, /* {BACnetBackupState }, */
7497 #define BACnetPropertyStatesEnums_Size 36
7499 static guint
7500 fBACnetPropertyStates(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint offset)
7502 guint8 tag_no, tag_info;
7503 guint32 lvt;
7504 const gchar* label;
7506 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7507 label = wmem_strdup_printf(wmem_packet_scope(), "%s: ",
7508 val_to_str_const( tag_no, VALS(BACnetPropertyStates), "Unknown State" ));
7510 switch (tag_no) {
7511 case 0:
7512 offset = fBooleanTag(tvb, pinfo, tree, offset, label);
7513 break;
7514 case 11:
7515 offset = fUnsignedTag(tvb, pinfo, tree, offset, label);
7516 break;
7517 default:
7518 if ( (tag_no > BACnetPropertyStatesEnums_Size) ||
7519 VALS(BACnetPropertyStatesEnums[tag_no].valstr) == NULL)
7521 offset = fEnumeratedTag(tvb, pinfo, tree, offset, label, NULL);
7522 /* don't use Abstract type here because it is context tagged and therefore we don't know app type */
7524 else
7526 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, label,
7527 VALS(BACnetPropertyStatesEnums[tag_no].valstr), 64);
7529 break;
7531 return offset;
7536 BACnetDeviceObjectPropertyValue ::= SEQUENCE {
7537 deviceIdentifier [0] BACnetObjectIdentifier,
7538 objectIdentifier [1] BACnetObjectIdentifier,
7539 propertyIdentifier [2] BACnetPropertyIdentifier,
7540 arrayIndex [3] Unsigned OPTIONAL,
7541 value [4] ABSTRACT-SYNTAX.&Type
7544 static guint
7545 fDeviceObjectPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7547 guint lastoffset = 0;
7548 guint8 tag_no, tag_info;
7549 guint32 lvt;
7551 while (tvb_reported_length_remaining(tvb, offset) > 0) {
7552 lastoffset = offset;
7553 /* check the tag. A closing tag means we are done */
7554 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7555 if (tag_is_closing(tag_info)) {
7556 return offset;
7558 switch (tag_no) {
7559 case 0: /* deviceIdentifier */
7560 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7561 break;
7562 case 1: /* objectIdentifier */
7563 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7564 break;
7565 case 2: /* propertyIdentifier */
7566 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7567 break;
7568 case 3: /* arrayIndex - OPTIONAL */
7569 offset = fUnsignedTag(tvb, pinfo, tree, offset,
7570 "arrayIndex: ");
7571 break;
7572 case 4: /* value */
7573 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7574 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
7575 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
7576 break;
7577 default:
7578 return offset;
7580 if (offset == lastoffset) break; /* nothing happened, exit loop */
7582 return offset;
7586 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7587 objectIdentifier [0] BACnetObjectIdentifier,
7588 propertyIdentifier [1] BACnetPropertyIdentifier,
7589 propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
7590 -- if omitted with an array then
7591 -- the entire array is referenced
7592 deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
7595 static guint
7596 fObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7598 return fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
7602 BACnetDeviceObjectPropertyReference ::= SEQUENCE {
7603 objectIdentifier [0] BACnetObjectIdentifier,
7604 propertyIdentifier [1] BACnetPropertyIdentifier,
7605 propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
7606 -- if omitted with an array then
7607 -- the entire array is referenced
7608 deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
7611 static guint
7612 fDeviceObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7614 guint lastoffset = 0;
7615 guint8 tag_no, tag_info;
7616 guint32 lvt;
7618 while (tvb_reported_length_remaining(tvb, offset) > 0) {
7619 lastoffset = offset;
7620 /* check the tag. A closing tag means we are done */
7621 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7622 if (tag_is_closing(tag_info)) {
7623 return offset;
7625 switch (tag_no) {
7626 case 0: /* objectIdentifier */
7627 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7628 break;
7629 case 1: /* propertyIdentifier */
7630 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
7631 break;
7632 case 2: /* arrayIndex - OPTIONAL */
7633 offset = fUnsignedTag(tvb, pinfo, tree, offset,
7634 "arrayIndex: ");
7635 break;
7636 case 3: /* deviceIdentifier - OPTIONAL */
7637 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
7638 break;
7639 default:
7640 return offset;
7642 if (offset == lastoffset) break; /* nothing happened, exit loop */
7644 return offset;
7647 static guint
7648 fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
7650 guint lastoffset = offset;
7651 guint8 tag_no, tag_info;
7652 guint32 lvt;
7653 proto_tree *subtree = tree;
7654 proto_item *tt;
7656 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
7657 tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters (%d) %s",
7658 tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
7659 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
7660 /* Opening tag for parameter choice */
7661 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7663 switch (tag_no) {
7664 case 0: /* change-of-bitstring */
7665 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7666 lastoffset = offset;
7667 switch (fTagNo(tvb, offset)) {
7668 case 0:
7669 offset = fBitStringTag(tvb, pinfo, subtree, offset,
7670 "referenced-bitstring: ");
7671 break;
7672 case 1:
7673 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7674 "status-flags: ", BACnetStatusFlags);
7675 lastoffset = offset;
7676 break;
7677 default:
7678 break;
7680 if (offset == lastoffset) break; /* nothing happened, exit loop */
7682 break;
7683 case 1: /* change-of-state */
7684 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7685 lastoffset = offset;
7686 switch (fTagNo(tvb, offset)) {
7687 case 0:
7688 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7689 offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
7690 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7691 break;
7692 case 1:
7693 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7694 "status-flags: ", BACnetStatusFlags);
7695 lastoffset = offset;
7696 break;
7697 default:
7698 break;
7700 if (offset == lastoffset) break; /* nothing happened, exit loop */
7702 break;
7703 case 2: /* change-of-value */
7704 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7705 lastoffset = offset;
7706 switch (fTagNo(tvb, offset)) {
7707 case 0:
7708 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7709 switch (fTagNo(tvb, offset)) {
7710 case 0:
7711 offset = fBitStringTag(tvb, pinfo, subtree, offset,
7712 "changed-bits: ");
7713 break;
7714 case 1:
7715 offset = fRealTag(tvb, pinfo, subtree, offset,
7716 "changed-value: ");
7717 break;
7718 default:
7719 break;
7721 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7722 break;
7723 case 1:
7724 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7725 "status-flags: ", BACnetStatusFlags);
7726 lastoffset = offset;
7727 break;
7728 default:
7729 break;
7731 if (offset == lastoffset) break; /* nothing happened, exit loop */
7733 break;
7734 case 3: /* command-failure */
7735 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7736 lastoffset = offset;
7737 switch (fTagNo(tvb, offset)) {
7738 case 0: /* "command-value: " */
7739 /* from BACnet Table 13-3,
7740 Standard Object Property Values Returned in Notifications */
7741 propertyIdentifier = 85; /* PRESENT_VALUE */
7742 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7743 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7744 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7745 break;
7746 case 1:
7747 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7748 "status-flags: ", BACnetStatusFlags);
7749 break;
7750 case 2: /* "feedback-value: " */
7751 propertyIdentifier = 40; /* FEEDBACK_VALUE */
7752 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7753 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
7754 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7755 lastoffset = offset;
7756 break;
7757 default:
7758 break;
7760 if (offset == lastoffset) break; /* nothing happened, exit loop */
7762 break;
7763 case 4: /* floating-limit */
7764 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7765 lastoffset = offset;
7766 switch (fTagNo(tvb, offset)) {
7767 case 0:
7768 offset = fRealTag(tvb, pinfo, subtree, offset, "reference-value: ");
7769 break;
7770 case 1:
7771 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7772 "status-flags: ", BACnetStatusFlags);
7773 break;
7774 case 2:
7775 offset = fRealTag(tvb, pinfo, subtree, offset, "setpoint-value: ");
7776 break;
7777 case 3:
7778 offset = fRealTag(tvb, pinfo, subtree, offset, "error-limit: ");
7779 lastoffset = offset;
7780 break;
7781 default:
7782 break;
7784 if (offset == lastoffset) break; /* nothing happened, exit loop */
7786 break;
7787 case 5: /* out-of-range */
7788 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7789 lastoffset = offset;
7790 switch (fTagNo(tvb, offset)) {
7791 case 0:
7792 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7793 break;
7794 case 1:
7795 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7796 "status-flags: ", BACnetStatusFlags);
7797 break;
7798 case 2:
7799 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
7800 break;
7801 case 3:
7802 offset = fRealTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7803 lastoffset = offset;
7804 break;
7805 default:
7806 break;
7808 if (offset == lastoffset) break; /* nothing happened, exit loop */
7810 break;
7811 case 6:
7812 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7813 lastoffset = offset;
7814 offset =fBACnetPropertyValue(tvb, pinfo, subtree, offset);
7815 if (offset == lastoffset) break; /* nothing happened, exit loop */
7817 break;
7818 case 7: /* deprecated (was 'buffer-ready', changed and moved to [10]) */
7819 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7820 lastoffset = offset;
7821 switch (fTagNo(tvb, offset)) {
7822 case 0:
7823 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-device */
7824 break;
7825 case 1:
7826 offset = fObjectIdentifier(tvb, pinfo, subtree, offset); /* buffer-object */
7827 break;
7828 case 2:
7829 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7830 offset = fDateTime(tvb, pinfo, subtree, offset, "previous-notification: ");
7831 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7832 break;
7833 case 3:
7834 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7835 offset = fDateTime(tvb, pinfo, subtree, offset, "current-notification: ");
7836 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7837 lastoffset = offset;
7838 break;
7839 default:
7840 break;
7842 if (offset == lastoffset) break; /* nothing happened, exit loop */
7844 break;
7845 case 8: /* change-of-life-safety */
7846 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7847 lastoffset = offset;
7848 switch (fTagNo(tvb, offset)) {
7849 case 0:
7850 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7851 "new-state: ", BACnetLifeSafetyState, 256);
7852 break;
7853 case 1:
7854 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7855 "new-mode: ", BACnetLifeSafetyMode, 256);
7856 break;
7857 case 2:
7858 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7859 "status-flags: ", BACnetStatusFlags);
7860 break;
7861 case 3:
7862 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
7863 "operation-expected: ", BACnetLifeSafetyOperation, 64);
7864 lastoffset = offset;
7865 break;
7866 default:
7867 break;
7869 if (offset == lastoffset) break; /* nothing happened, exit loop */
7871 break;
7872 case 9: /* extended */
7873 while (tvb_reported_length_remaining(tvb, offset) > 0) {
7874 lastoffset = offset;
7875 switch (fTagNo(tvb, offset)) {
7876 case 0:
7877 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
7878 break;
7879 case 1:
7880 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7881 "extended-event-type: ");
7882 break;
7883 case 2: /* parameters */
7884 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7885 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
7886 offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
7887 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7888 lastoffset = offset;
7889 break;
7890 default:
7891 break;
7893 if (offset == lastoffset) break; /* nothing happened, exit loop */
7895 break;
7896 case 10: /* buffer ready */
7897 while (tvb_reported_length_remaining(tvb, offset) > 0) {
7898 lastoffset = offset;
7899 switch (fTagNo(tvb, offset)) {
7900 case 0: /* buffer-property */
7901 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7902 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
7903 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
7904 break;
7905 case 1:
7906 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7907 "previous-notification: ");
7908 break;
7909 case 2:
7910 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7911 "current-notification: ");
7912 lastoffset = offset;
7913 break;
7914 default:
7915 break;
7917 if (offset == lastoffset) break; /* nothing happened, exit loop */
7919 break;
7920 case 11: /* unsigned range */
7921 while (tvb_reported_length_remaining(tvb, offset) > 0) {
7922 lastoffset = offset;
7923 switch (fTagNo(tvb, offset)) {
7924 case 0:
7925 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7926 "exceeding-value: ");
7927 break;
7928 case 1:
7929 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7930 "status-flags: ", BACnetStatusFlags);
7931 break;
7932 case 2:
7933 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
7934 "exceeded-limit: ");
7935 lastoffset = offset;
7936 break;
7937 default:
7938 break;
7940 if (offset == lastoffset) break; /* nothing happened, exit loop */
7942 break;
7943 /* 12 reserved */
7944 case 13: /* access-event */
7945 break;
7946 case 14: /* double-out-of-range */
7947 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7948 lastoffset = offset;
7949 switch (fTagNo(tvb, offset)) {
7950 case 0:
7951 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7952 break;
7953 case 1:
7954 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7955 "status-flags: ", BACnetStatusFlags);
7956 break;
7957 case 2:
7958 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
7959 break;
7960 case 3:
7961 offset = fDoubleTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7962 lastoffset = offset;
7963 break;
7964 default:
7965 break;
7967 if (offset == lastoffset) break; /* nothing happened, exit loop */
7969 break;
7970 case 15: /* signed-out-of-range */
7971 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7972 lastoffset = offset;
7973 switch (fTagNo(tvb, offset)) {
7974 case 0:
7975 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
7976 break;
7977 case 1:
7978 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
7979 "status-flags: ", BACnetStatusFlags);
7980 break;
7981 case 2:
7982 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
7983 break;
7984 case 3:
7985 offset = fSignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
7986 lastoffset = offset;
7987 break;
7988 default:
7989 break;
7991 if (offset == lastoffset) break; /* nothing happened, exit loop */
7993 break;
7994 case 16: /* unsigned-out-of-range */
7995 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
7996 lastoffset = offset;
7997 switch (fTagNo(tvb, offset)) {
7998 case 0:
7999 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeding-value: ");
8000 break;
8001 case 1:
8002 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8003 "status-flags: ", BACnetStatusFlags);
8004 break;
8005 case 2:
8006 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8007 break;
8008 case 3:
8009 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "exceeded-limit: ");
8010 lastoffset = offset;
8011 break;
8012 default:
8013 break;
8015 if (offset == lastoffset) break; /* nothing happened, exit loop */
8017 break;
8018 case 17: /* change-of-characterstring */
8019 break;
8020 case 18: /* change-of-status-flags */
8021 break;
8022 /* todo: add new parameters here ... */
8023 default:
8024 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
8025 break;
8028 /* Closing tag for parameter choice */
8029 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8031 return offset;
8034 static guint
8035 fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8037 guint lastoffset = offset;
8038 guint8 tag_no, tag_info;
8039 guint32 lvt;
8040 proto_tree *subtree = tree;
8041 proto_item *tt;
8043 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8044 tt = proto_tree_add_text(subtree, tvb, offset, 0, "event parameters (%d) %s",
8045 tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
8046 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8047 /* Opening tag for parameter choice */
8048 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8050 switch (tag_no) {
8051 case 0: /* change-of-bitstring */
8052 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8053 lastoffset = offset;
8054 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8055 if (tag_is_closing(tag_info)) {
8056 break;
8058 switch (tag_no) {
8059 case 0:
8060 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8061 break;
8062 case 1:
8063 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8064 break;
8065 case 2: /* SEQUENCE OF BIT STRING */
8066 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8067 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8068 lastoffset = offset;
8069 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8070 if (tag_is_closing(tag_info)) {
8071 break;
8073 offset = fBitStringTag(tvb, pinfo, subtree, offset,
8074 "bitstring value: ");
8076 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8077 break;
8078 default:
8079 break;
8082 break;
8083 case 1: /* change-of-state */
8084 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8085 lastoffset = offset;
8086 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8087 if (tag_is_closing(tag_info)) {
8088 break;
8090 switch (tag_no) {
8091 case 0:
8092 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8093 break;
8094 case 1: /* SEQUENCE OF BACnetPropertyStates */
8095 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8096 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8097 lastoffset = offset;
8098 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8099 if (tag_is_closing(tag_info)) {
8100 break;
8102 offset = fBACnetPropertyStates(tvb, pinfo, subtree, offset);
8104 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8105 break;
8106 default:
8107 break;
8110 break;
8111 case 2: /* change-of-value */
8112 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8113 lastoffset = offset;
8114 switch (fTagNo(tvb, offset)) {
8115 case 0:
8116 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8117 break;
8118 case 1: /* don't loop it, it's a CHOICE */
8119 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8120 switch (fTagNo(tvb, offset)) {
8121 case 0:
8122 offset = fBitStringTag(tvb, pinfo, subtree, offset, "bitmask: ");
8123 break;
8124 case 1:
8125 offset = fRealTag(tvb, pinfo, subtree, offset,
8126 "referenced Property Increment: ");
8127 break;
8128 default:
8129 break;
8131 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8132 break;
8133 default:
8134 break;
8137 break;
8138 case 3: /* command-failure */
8139 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8140 lastoffset = offset;
8141 tag_no = fTagNo(tvb, offset);
8142 switch (tag_no) {
8143 case 0:
8144 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8145 break;
8146 case 1:
8147 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8148 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8149 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8150 break;
8151 default:
8152 break;
8155 break;
8156 case 4: /* floating-limit */
8157 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8158 lastoffset = offset;
8159 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8160 if (tag_is_closing(tag_info)) {
8161 break;
8163 switch (tag_no) {
8164 case 0:
8165 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8166 break;
8167 case 1:
8168 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8169 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8170 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8171 break;
8172 case 2:
8173 offset = fRealTag(tvb, pinfo, subtree, offset, "low diff limit: ");
8174 break;
8175 case 3:
8176 offset = fRealTag(tvb, pinfo, subtree, offset, "high diff limit: ");
8177 break;
8178 case 4:
8179 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8180 break;
8181 default:
8182 break;
8185 break;
8186 case 5: /* out-of-range */
8187 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8188 lastoffset = offset;
8189 switch (fTagNo(tvb, offset)) {
8190 case 0:
8191 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8192 break;
8193 case 1:
8194 offset = fRealTag(tvb, pinfo, subtree, offset, "low limit: ");
8195 break;
8196 case 2:
8197 offset = fRealTag(tvb, pinfo, subtree, offset, "high limit: ");
8198 break;
8199 case 3:
8200 offset = fRealTag(tvb, pinfo, subtree, offset, "deadband: ");
8201 break;
8202 default:
8203 break;
8206 break;
8207 /* deprectated
8208 case 6:
8209 offset = fBACnetPropertyValue (tvb, pinfo, tree, offset);
8210 break;
8213 case 7: /* buffer-ready */
8214 #if 0
8215 /* deprecated */
8216 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
8217 lastoffset = offset;
8218 switch (fTagNo(tvb, offset)) {
8219 case 0:
8220 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification threshold");
8221 break;
8222 case 1:
8223 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8224 "previous notification count: ");
8225 break;
8226 default:
8227 return offset;
8230 #endif
8231 break;
8232 case 8: /* change-of-life-safety */
8233 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8234 lastoffset = offset;
8235 switch (fTagNo(tvb, offset)) {
8236 case 0:
8237 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8238 break;
8239 case 1:
8240 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8241 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8242 lastoffset = offset;
8243 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8244 if (tag_is_closing(tag_info)) {
8245 break;
8247 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8248 "life safety alarm value: ", BACnetLifeSafetyState, 256);
8250 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8251 break;
8252 case 2:
8253 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8254 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8255 lastoffset = offset;
8256 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8257 if (tag_is_closing(tag_info)) {
8258 break;
8260 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8261 "alarm value: ", BACnetLifeSafetyState, 256);
8263 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8264 break;
8265 case 3:
8266 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8267 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8268 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8269 break;
8270 default:
8271 break;
8274 break;
8275 case 9: /* extended */
8276 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8277 lastoffset = offset;
8278 switch (fTagNo(tvb, offset)) {
8279 case 0:
8280 offset = fVendorIdentifier(tvb, pinfo, tree, offset);
8281 break;
8282 case 1:
8283 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8284 "extended-event-type: ");
8285 break;
8286 case 2: /* parameters */
8287 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8288 offset = fApplicationTypes(tvb, pinfo, tree, offset, "parameters: ");
8289 offset = fDeviceObjectPropertyValue(tvb, pinfo, tree, offset);
8290 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8291 lastoffset = offset;
8292 break;
8293 default:
8294 break;
8296 if (offset == lastoffset) break; /* nothing happened, exit loop */
8298 break;
8299 case 10: /* buffer-ready */
8300 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8301 lastoffset = offset;
8302 switch (fTagNo(tvb, offset)) {
8303 case 0:
8304 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8305 "notification-threshold: ");
8306 break;
8307 case 1:
8308 offset = fUnsignedTag(tvb, pinfo, subtree, offset,
8309 "previous-notification-count: ");
8310 break;
8311 default:
8312 break;
8315 break;
8316 case 11: /* unsigned-range */
8317 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8318 lastoffset = offset;
8319 switch (fTagNo(tvb, offset)) {
8320 case 0:
8321 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time Delay");
8322 break;
8323 case 1:
8324 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8325 "low-limit: ");
8326 break;
8327 case 2:
8328 offset = fUnsignedTag(tvb, pinfo, tree, offset,
8329 "high-limit: ");
8330 break;
8331 default:
8332 break;
8335 break;
8336 case 13: /* access-event */
8337 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8338 lastoffset = offset;
8339 switch (fTagNo(tvb, offset)) {
8340 case 0:
8341 /* TODO: [0] SEQUENCE OF BACnetAccessEvent */
8342 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8343 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8344 lastoffset = offset;
8345 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8346 if (tag_is_closing(tag_info)) {
8347 break;
8349 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset,
8350 "access event: ", BACnetAccessEvent, 512);
8352 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8353 break;
8354 case 1:
8355 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8356 offset = fDeviceObjectPropertyReference(tvb, pinfo, subtree, offset);
8357 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8358 break;
8359 default:
8360 break;
8363 break;
8364 case 14: /* double-out-of-range */
8365 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8366 lastoffset = offset;
8367 switch (fTagNo(tvb, offset)) {
8368 case 0:
8369 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8370 break;
8371 case 1:
8372 offset = fDoubleTag(tvb, pinfo, subtree, offset, "low limit: ");
8373 break;
8374 case 2:
8375 offset = fDoubleTag(tvb, pinfo, subtree, offset, "high limit: ");
8376 break;
8377 case 3:
8378 offset = fDoubleTag(tvb, pinfo, subtree, offset, "deadband: ");
8379 break;
8380 default:
8381 break;
8384 break;
8385 case 15: /* signed-out-of-range */
8386 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8387 lastoffset = offset;
8388 switch (fTagNo(tvb, offset)) {
8389 case 0:
8390 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8391 break;
8392 case 1:
8393 offset = fSignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8394 break;
8395 case 2:
8396 offset = fSignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8397 break;
8398 case 3:
8399 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8400 break;
8401 default:
8402 break;
8405 break;
8406 case 16: /* unsigned-out-of-range */
8407 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8408 lastoffset = offset;
8409 switch (fTagNo(tvb, offset)) {
8410 case 0:
8411 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8412 break;
8413 case 1:
8414 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "low limit: ");
8415 break;
8416 case 2:
8417 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "high limit: ");
8418 break;
8419 case 3:
8420 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "deadband: ");
8421 break;
8422 default:
8423 break;
8426 break;
8427 case 17: /* change-of-characterstring */
8428 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8429 lastoffset = offset;
8430 switch (fTagNo(tvb, offset)) {
8431 case 0:
8432 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8433 break;
8434 case 1: /* SEQUENCE OF CharacterString */
8435 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8436 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8437 lastoffset = offset;
8438 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8439 if (tag_is_closing(tag_info)) {
8440 break;
8442 offset = fCharacterString(tvb, pinfo, tree, offset, "alarm value: ");
8444 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8445 break;
8446 default:
8447 break;
8450 break;
8451 case 18: /* change-of-status-flags */
8452 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
8453 lastoffset = offset;
8454 switch (fTagNo(tvb, offset)) {
8455 case 0:
8456 offset = fTimeSpan(tvb, pinfo, subtree, offset, "Time Delay");
8457 break;
8458 case 1:
8459 offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
8460 "selected flags: ", BACnetStatusFlags);
8461 break;
8462 default:
8463 break;
8466 break;
8467 /* todo: add new event-parameter cases here */
8468 default:
8469 break;
8472 /* Closing tag for parameter choice */
8473 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8474 return offset;
8477 static guint
8478 fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8480 guint lastoffset = 0;
8481 guint8 tag_no, tag_info;
8482 guint32 lvt;
8483 proto_tree *subtree = tree;
8484 proto_item *tt;
8486 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8487 lastoffset = offset;
8488 switch (fTagNo(tvb, offset)) {
8489 case 0: /* timestamp */
8490 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8491 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
8492 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
8493 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8494 break;
8495 case 1: /* logDatum: don't loop, it's a CHOICE */
8496 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8497 switch (fTagNo(tvb, offset)) {
8498 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
8499 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8500 break;
8501 case 1: /* todo: move this to new method fConfirmedEventNotificationRequestTag... */
8502 tt = proto_tree_add_text(tree, tvb, offset, 1, "notification: ");
8503 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8504 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8505 offset = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
8506 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8507 break;
8508 case 2:
8509 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8510 break;
8511 default:
8512 return offset;
8514 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8515 break;
8516 default:
8517 return offset;
8519 if (offset == lastoffset) break; /* nothing happened, exit loop */
8521 return offset;
8524 static guint
8525 fLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8527 guint lastoffset = 0;
8528 guint8 tag_no, tag_info;
8529 guint32 lvt;
8531 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8532 lastoffset = offset;
8533 switch (fTagNo(tvb, offset)) {
8534 case 0: /* timestamp */
8535 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8536 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
8537 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
8538 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8539 break;
8540 case 1: /* logDatum: don't loop, it's a CHOICE */
8541 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8542 switch (fTagNo(tvb, offset)) {
8543 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
8544 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8545 break;
8546 case 1:
8547 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8548 break;
8549 case 2:
8550 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8551 break;
8552 case 3:
8553 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8554 break;
8555 case 4:
8556 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8557 break;
8558 case 5:
8559 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8560 break;
8561 case 6:
8562 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8563 break;
8564 case 7:
8565 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8566 break;
8567 case 8:
8568 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8569 offset = fError(tvb, pinfo, tree, offset);
8570 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8571 break;
8572 case 9:
8573 offset = fRealTag(tvb, pinfo, tree, offset, "time change: ");
8574 break;
8575 case 10: /* any Value */
8576 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8577 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8578 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8579 break;
8580 default:
8581 return offset;
8583 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8584 break;
8585 case 2:
8586 /* Changed this to BitString per BACnet Spec. */
8587 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "Status Flags:", BACnetStatusFlags);
8588 break;
8589 default:
8590 return offset;
8592 if (offset == lastoffset) break; /* nothing happened, exit loop */
8594 return offset;
8597 static guint
8598 fLogMultipleRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8600 guint lastoffset = 0;
8601 guint8 tag_no, tag_info;
8602 guint32 lvt;
8604 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8605 lastoffset = offset;
8606 switch (fTagNo(tvb, offset)) {
8607 case 0: /* timestamp */
8608 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8609 offset = fDate(tvb, pinfo, tree, offset, "Date: ");
8610 offset = fTime(tvb, pinfo, tree, offset, "Time: ");
8611 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8612 break;
8613 case 1: /* logData: don't loop, it's a CHOICE */
8614 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8615 switch (fTagNo(tvb, offset)) {
8616 case 0: /* logStatus */ /* Changed this to BitString per BACnet Spec. */
8617 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
8618 break;
8619 case 1: /* log-data: SEQUENCE OF CHOICE */
8620 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8621 while ((tvb_reported_length_remaining(tvb, offset) > 0) && (offset != lastoffset)) { /* exit loop if nothing happens inside */
8622 lastoffset = offset;
8623 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8624 if (tag_is_closing(tag_info)) {
8625 lastoffset = offset;
8626 break;
8628 switch (tag_no) {
8629 case 0:
8630 offset = fBooleanTag(tvb, pinfo, tree, offset, "boolean-value: ");
8631 break;
8632 case 1:
8633 offset = fRealTag(tvb, pinfo, tree, offset, "real value: ");
8634 break;
8635 case 2:
8636 offset = fUnsignedTag(tvb, pinfo, tree, offset, "enum value: ");
8637 break;
8638 case 3:
8639 offset = fUnsignedTag(tvb, pinfo, tree, offset, "unsigned value: ");
8640 break;
8641 case 4:
8642 offset = fSignedTag(tvb, pinfo, tree, offset, "signed value: ");
8643 break;
8644 case 5:
8645 offset = fBitStringTag(tvb, pinfo, tree, offset, "bitstring value: ");
8646 break;
8647 case 6:
8648 offset = fNullTag(tvb, pinfo, tree, offset, "null value: ");
8649 break;
8650 case 7:
8651 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8652 offset = fError(tvb, pinfo, tree, offset);
8653 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8654 break;
8655 case 8: /* any Value */
8656 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8657 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
8658 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8659 break;
8660 default:
8661 return offset;
8664 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8665 break;
8666 case 2:
8667 offset = fRealTag(tvb, pinfo, tree, offset, "time-change: ");
8668 break;
8669 default:
8670 return offset;
8672 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8673 break;
8674 default:
8675 return offset;
8677 if (offset == lastoffset) break; /* nothing happened, exit loop */
8679 return offset;
8683 static guint
8684 fConfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8686 guint lastoffset = 0;
8687 guint8 tag_no, tag_info;
8688 guint32 lvt;
8690 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8691 lastoffset = offset;
8692 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8693 if (tag_is_closing(tag_info)) {
8694 break;
8697 switch (tag_no) {
8698 case 0: /* ProcessId */
8699 offset = fProcessId(tvb, pinfo, tree, offset);
8700 break;
8701 case 1: /* initiating ObjectId */
8702 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8703 break;
8704 case 2: /* event ObjectId */
8705 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8706 break;
8707 case 3: /* time stamp */
8708 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8709 offset = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8710 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8711 break;
8712 case 4: /* notificationClass */
8713 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
8714 break;
8715 case 5: /* Priority */
8716 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Priority: ");
8717 break;
8718 case 6: /* EventType */
8719 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8720 "Event Type: ", BACnetEventType, 64);
8721 break;
8722 case 7: /* messageText */
8723 offset = fCharacterString(tvb, pinfo, tree, offset, "message Text: ");
8724 break;
8725 case 8: /* NotifyType */
8726 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8727 "Notify Type: ", BACnetNotifyType);
8728 break;
8729 case 9: /* ackRequired */
8730 offset = fBooleanTag(tvb, pinfo, tree, offset, "ack Required: ");
8731 break;
8732 case 10: /* fromState */
8733 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8734 "from State: ", BACnetEventState, 64);
8735 break;
8736 case 11: /* toState */
8737 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8738 "to State: ", BACnetEventState, 64);
8739 break;
8740 case 12: /* NotificationParameters */
8741 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8742 offset = fNotificationParameters(tvb, pinfo, tree, offset);
8743 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8744 break;
8745 default:
8746 break;
8748 if (offset == lastoffset) break; /* nothing happened, exit loop */
8750 return offset;
8753 static guint
8754 fUnconfirmedEventNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8756 return fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
8759 static guint
8760 fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8762 guint lastoffset = 0, len;
8763 guint8 tag_no, tag_info;
8764 guint32 lvt;
8765 proto_tree *subtree = tree;
8766 proto_item *tt;
8768 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8769 lastoffset = offset;
8770 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8771 if (tag_is_closing(tag_info)) {
8772 offset += len;
8773 subtree = tree;
8774 continue;
8777 switch (tag_no) {
8778 case 0: /* ProcessId */
8779 offset = fProcessId(tvb, pinfo, tree, offset);
8780 break;
8781 case 1: /* initiating DeviceId */
8782 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8783 break;
8784 case 2: /* monitored ObjectId */
8785 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
8786 break;
8787 case 3: /* time remaining */
8788 offset = fTimeSpan(tvb, pinfo, tree, offset, "Time remaining");
8789 break;
8790 case 4: /* List of Values */
8791 if (tag_is_opening(tag_info)) {
8792 tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
8793 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
8794 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8795 offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
8796 break;
8798 FAULT;
8799 break;
8800 default:
8801 return offset;
8803 if (offset == lastoffset) break; /* nothing happened, exit loop */
8805 return offset;
8808 static guint
8809 fUnconfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8811 return fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
8814 static guint
8815 fAcknowledgeAlarmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8817 guint lastoffset = 0;
8818 guint8 tag_no = 0, tag_info = 0;
8819 guint32 lvt = 0;
8821 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8822 lastoffset = offset;
8823 switch (fTagNo(tvb, offset)) {
8824 case 0: /* acknowledgingProcessId */
8825 offset = fUnsignedTag(tvb, pinfo, tree, offset, "acknowledging Process Id: ");
8826 break;
8827 case 1: /* eventObjectId */
8828 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8829 break;
8830 case 2: /* eventStateAcknowledged */
8831 offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset,
8832 "event State Acknowledged: ", BACnetEventState, 64);
8833 break;
8834 case 3: /* timeStamp */
8835 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8836 offset = fTimeStamp(tvb, pinfo, tree, offset, NULL);
8837 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8838 break;
8839 case 4: /* acknowledgementSource */
8840 offset = fCharacterString(tvb, pinfo, tree, offset, "acknowledgement Source: ");
8841 break;
8842 case 5: /* timeOfAcknowledgement */
8843 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8844 offset = fTimeStamp(tvb, pinfo, tree, offset, "acknowledgement timestamp: ");
8845 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8846 break;
8847 default:
8848 return offset;
8850 if (offset == lastoffset) break; /* nothing happened, exit loop */
8852 return offset;
8855 static guint
8856 fGetAlarmSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8858 guint lastoffset = 0;
8860 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8861 lastoffset = offset;
8862 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
8863 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
8864 "alarm State: ", BACnetEventState, 64);
8865 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8866 "acknowledged Transitions: ", BACnetEventTransitionBits);
8867 if (offset == lastoffset) break; /* nothing happened, exit loop */
8869 return offset;
8872 static guint
8873 fGetEnrollmentSummaryRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8875 guint lastoffset = 0;
8876 guint8 tag_no, tag_info;
8877 guint32 lvt;
8879 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8880 lastoffset = offset;
8881 switch (fTagNo(tvb, offset)) {
8882 case 0: /* acknowledgmentFilter */
8883 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8884 "acknowledgment Filter: ", BACnetAcknowledgementFilter);
8885 break;
8886 case 1: /* eventObjectId - OPTIONAL */
8887 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8888 offset = fRecipientProcess(tvb, pinfo, tree, offset);
8889 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8890 break;
8891 case 2: /* eventStateFilter */
8892 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8893 "event State Filter: ", BACnetEventStateFilter);
8894 break;
8895 case 3: /* eventTypeFilter - OPTIONAL */
8896 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8897 "event Type Filter: ", BACnetEventType);
8898 break;
8899 case 4: /* priorityFilter */
8900 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8901 offset = fUnsignedTag(tvb, pinfo, tree, offset, "min Priority: ");
8902 offset = fUnsignedTag(tvb, pinfo, tree, offset, "max Priority: ");
8903 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
8904 break;
8905 case 5: /* notificationClassFilter - OPTIONAL */
8906 offset = fUnsignedTag(tvb, pinfo, tree, offset, "notification Class Filter: ");
8907 break;
8908 default:
8909 return offset;
8911 if (offset == lastoffset) break; /* nothing happened, exit loop */
8913 return offset;
8916 static guint
8917 fGetEnrollmentSummaryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8919 guint lastoffset = 0;
8921 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8922 lastoffset = offset;
8923 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
8924 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
8925 "event Type: ", BACnetEventType, 64);
8926 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
8927 "event State: ", BACnetEventState);
8928 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Priority: ");
8929 if (tvb_reported_length_remaining(tvb, offset) > 0 && fTagNo(tvb, offset) == 2) /* Notification Class - OPTIONAL */
8930 offset = fUnsignedTag(tvb, pinfo, tree, offset, "Notification Class: ");
8931 if (offset == lastoffset) break; /* nothing happened, exit loop */
8934 return offset;
8937 static guint
8938 fGetEventInformationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8940 if (tvb_reported_length_remaining(tvb, offset) > 0) {
8941 if (fTagNo(tvb, offset) == 0) {
8942 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8945 return offset;
8948 static guint
8949 flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
8951 guint lastoffset = 0;
8952 guint8 tag_no, tag_info;
8953 guint32 lvt;
8954 proto_tree* subtree = tree;
8955 proto_item* ti = 0;
8957 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
8958 lastoffset = offset;
8959 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
8960 /* we are finished here if we spot a closing tag */
8961 if (tag_is_closing(tag_info)) {
8962 break;
8964 switch (tag_no) {
8965 case 0: /* ObjectId */
8966 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
8967 break;
8968 case 1: /* eventState */
8969 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8970 "event State: ", BACnetEventState);
8971 break;
8972 case 2: /* acknowledgedTransitions */
8973 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
8974 "acknowledged Transitions: ", BACnetEventTransitionBits);
8975 break;
8976 case 3: /* eventTimeStamps */
8977 ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
8978 if (ti) {
8979 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
8981 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8982 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
8983 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
8984 offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
8985 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
8986 break;
8987 case 4: /* notifyType */
8988 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
8989 "Notify Type: ", BACnetNotifyType);
8990 break;
8991 case 5: /* eventEnable */
8992 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
8993 "event Enable: ", BACnetEventTransitionBits);
8994 break;
8995 case 6: /* eventPriorities */
8996 ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventPriorities");
8997 if (ti) {
8998 subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
9000 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9001 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
9002 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
9003 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-NORMAL Priority: ");
9004 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9005 break;
9006 default:
9007 return offset;
9009 if (offset == lastoffset) break; /* nothing happened, exit loop */
9011 return offset;
9014 static guint
9015 fLOPR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9017 guint lastoffset = 0;
9018 guint8 tag_no, tag_info;
9019 guint32 lvt;
9021 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9022 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9023 lastoffset = offset;
9024 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9025 /* we are finished here if we spot a closing tag */
9026 if (tag_is_closing(tag_info)) {
9027 break;
9029 offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
9030 if (offset == lastoffset) break; /* nothing happened, exit loop */
9032 return offset;
9035 static guint
9036 fGetEventInformationACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9038 guint lastoffset = 0;
9039 guint8 tag_no, tag_info;
9040 guint32 lvt;
9042 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9043 lastoffset = offset;
9044 switch (fTagNo(tvb, offset)) {
9045 case 0: /* listOfEventSummaries */
9046 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9047 offset = flistOfEventSummaries(tvb, pinfo, tree, offset);
9048 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9049 break;
9050 case 1: /* moreEvents */
9051 offset = fBooleanTag(tvb, pinfo, tree, offset, "more Events: ");
9052 break;
9053 default:
9054 return offset;
9056 if (offset == lastoffset) break; /* nothing happened, exit loop */
9058 return offset;
9061 static guint
9062 fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9064 guint lastoffset = 0, len;
9065 guint8 tag_no, tag_info;
9066 guint32 lvt;
9067 proto_tree *subtree = tree;
9068 proto_item *tt;
9070 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9072 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9073 lastoffset = offset;
9074 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9075 if (tag_is_closing(tag_info)) {
9076 offset += len;
9077 subtree = tree;
9078 continue;
9081 switch (tag_no) {
9082 case 0: /* ObjectId */
9083 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9084 break;
9085 case 3: /* listOfElements */
9086 if (tag_is_opening(tag_info)) {
9087 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
9088 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9089 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9090 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9091 break;
9093 FAULT;
9094 break;
9095 default:
9096 return offset;
9098 if (offset == lastoffset) break; /* nothing happened, exit loop */
9100 return offset;
9103 static guint
9104 fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9106 return fObjectIdentifier(tvb, pinfo, tree, offset);
9109 static guint
9110 fDeviceCommunicationControlRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9112 guint lastoffset = 0;
9114 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9115 lastoffset = offset;
9117 switch (fTagNo(tvb, offset)) {
9118 case 0: /* timeDuration */
9119 offset = fUnsignedTag(tvb, pinfo, tree, offset, "time Duration: ");
9120 break;
9121 case 1: /* enable-disable */
9122 offset = fEnumeratedTag(tvb, pinfo, tree, offset, "enable-disable: ",
9123 BACnetEnableDisable);
9124 break;
9125 case 2: /* password - OPTIONAL */
9126 offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9127 break;
9128 default:
9129 return offset;
9131 if (offset == lastoffset) break; /* nothing happened, exit loop */
9133 return offset;
9136 static guint
9137 fReinitializeDeviceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9139 guint lastoffset = 0;
9141 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9142 lastoffset = offset;
9144 switch (fTagNo(tvb, offset)) {
9145 case 0: /* reinitializedStateOfDevice */
9146 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9147 "reinitialized State Of Device: ",
9148 BACnetReinitializedStateOfDevice);
9149 break;
9150 case 1: /* password - OPTIONAL */
9151 offset = fCharacterString(tvb, pinfo, tree, offset, "Password: ");
9152 break;
9153 default:
9154 return offset;
9156 if (offset == lastoffset) break; /* nothing happened, exit loop */
9158 return offset;
9161 static guint
9162 fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9164 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
9165 "vtClass: ", BACnetVTClass);
9166 return fApplicationTypes(tvb, pinfo, tree, offset, "local VT Session ID: ");
9169 static guint
9170 fVtOpenAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9172 return fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9175 static guint
9176 fVtCloseRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9178 guint lastoffset = 0;
9180 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9181 lastoffset = offset;
9182 offset= fApplicationTypes(tvb, pinfo, tree, offset, "remote VT Session ID: ");
9183 if (offset == lastoffset) break; /* nothing happened, exit loop */
9185 return offset;
9188 static guint
9189 fVtDataRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9191 offset= fApplicationTypes(tvb, pinfo, tree, offset, "VT Session ID: ");
9192 offset = fApplicationTypes(tvb, pinfo, tree, offset, "VT New Data: ");
9193 return fApplicationTypes(tvb, pinfo, tree, offset, "VT Data Flag: ");
9196 static guint
9197 fVtDataAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9199 guint lastoffset = 0;
9201 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9202 lastoffset = offset;
9204 switch (fTagNo(tvb, offset)) {
9205 case 0: /* BOOLEAN */
9206 offset = fBooleanTag(tvb, pinfo, tree, offset, "all New Data Accepted: ");
9207 break;
9208 case 1: /* Unsigned OPTIONAL */
9209 offset = fUnsignedTag(tvb, pinfo, tree, offset, "accepted Octet Count: ");
9210 break;
9211 default:
9212 return offset;
9214 if (offset == lastoffset) break; /* nothing happened, exit loop */
9216 return offset;
9219 static guint
9220 fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9222 guint lastoffset = 0;
9224 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9225 lastoffset = offset;
9227 switch (fTagNo(tvb, offset)) {
9228 case 0: /* Unsigned32 */
9229 offset = fUnsignedTag(tvb, pinfo, tree, offset, "pseudo Random Number: ");
9230 break;
9231 case 1: /* expected Invoke ID Unsigned8 OPTIONAL */
9232 proto_tree_add_item(tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
9233 break;
9234 case 2: /* Chararacter String OPTIONAL */
9235 offset = fCharacterString(tvb, pinfo, tree, offset, "operator Name: ");
9236 break;
9237 case 3: /* Chararacter String OPTIONAL */
9238 offset = fCharacterString(tvb, pinfo, tree, offset, "operator Password: ");
9239 break;
9240 case 4: /* Boolean OPTIONAL */
9241 offset = fBooleanTag(tvb, pinfo, tree, offset, "start Encyphered Session: ");
9242 break;
9243 default:
9244 return offset;
9246 if (offset == lastoffset) break; /* nothing happened, exit loop */
9248 return offset;
9251 static guint
9252 fAuthenticateAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9254 return fApplicationTypes(tvb, pinfo, tree, offset, "modified Random Number: ");
9257 static guint
9258 fRequestKeyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9260 offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Requesting Device Identifier */
9261 offset = fAddress(tvb, pinfo, tree, offset);
9262 offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* Remote Device Identifier */
9263 return fAddress(tvb, pinfo, tree, offset);
9266 static guint
9267 fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9269 /* Same as AddListElement request after service choice */
9270 return fAddListElementRequest(tvb, pinfo, tree, offset);
9273 static guint
9274 fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9276 return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
9279 static guint
9280 fReadPropertyAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9282 guint lastoffset = 0, len;
9283 guint8 tag_no, tag_info;
9284 guint32 lvt;
9285 proto_tree *subtree = tree;
9287 /* set the optional global properties to indicate not-used */
9288 propertyArrayIndex = -1;
9289 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9290 lastoffset = offset;
9291 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9292 if (tag_is_closing(tag_info)) {
9293 offset += len;
9294 subtree = tree;
9295 continue;
9297 switch (tag_no) {
9298 case 0: /* objectIdentifier */
9299 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9300 break;
9301 case 1: /* propertyIdentifier */
9302 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9303 break;
9304 case 2: /* propertyArrayIndex */
9305 offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9306 break;
9307 case 3: /* propertyValue */
9308 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9309 break;
9310 default:
9311 break;
9313 if (offset == lastoffset) break; /* nothing happened, exit loop */
9315 return offset;
9318 static guint
9319 fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9321 guint lastoffset = 0;
9322 guint8 tag_no, tag_info;
9323 guint32 lvt;
9324 proto_tree *subtree = tree;
9326 /* set the optional global properties to indicate not-used */
9327 propertyArrayIndex = -1;
9328 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9329 lastoffset = offset;
9330 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9331 /* quit loop if we spot a closing tag */
9332 if (tag_is_closing(tag_info)) {
9333 break;
9336 switch (tag_no) {
9337 case 0: /* objectIdentifier */
9338 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9339 break;
9340 case 1: /* propertyIdentifier */
9341 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9342 break;
9343 case 2: /* propertyArrayIndex */
9344 offset = fPropertyArrayIndex(tvb, pinfo, subtree, offset);
9345 break;
9346 case 3: /* propertyValue */
9347 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9348 break;
9349 case 4: /* Priority (only used for write) */
9350 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9351 break;
9352 default:
9353 return offset;
9355 if (offset == lastoffset) break; /* nothing happened, exit loop */
9357 return offset;
9360 static guint
9361 fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9363 guint lastoffset = 0, len;
9364 guint8 tag_no, tag_info;
9365 guint32 lvt;
9367 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9368 lastoffset = offset;
9369 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9370 /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
9371 if (tag_is_closing(tag_info)) {
9372 offset += len;
9373 continue;
9376 switch (tag_no) {
9377 case 0: /* objectIdentifier */
9378 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9379 break;
9380 case 1: /* listOfPropertyValues */
9381 if (tag_is_opening(tag_info)) {
9382 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9383 offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9384 break;
9386 FAULT;
9387 break;
9388 default:
9389 return offset;
9391 if (offset == lastoffset) break; /* nothing happened, exit loop */
9393 return offset;
9396 static guint
9397 fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9399 if (offset >= tvb_reported_length(tvb))
9400 return offset;
9402 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9403 return fWriteAccessSpecification(tvb, pinfo, tree, offset);
9406 static guint
9407 fPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
9409 guint lastoffset = 0;
9410 guint8 tag_no, tag_info;
9411 guint32 lvt;
9413 /* set the optional global properties to indicate not-used */
9414 propertyArrayIndex = -1;
9415 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9416 lastoffset = offset;
9417 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9418 if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
9419 return offset;
9420 } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
9421 return offset;
9423 switch (tag_no-tagoffset) {
9424 case 0: /* PropertyIdentifier */
9425 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9426 break;
9427 case 1: /* propertyArrayIndex */
9428 offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9429 if (list != 0) break; /* Continue decoding if this may be a list */
9430 default:
9431 lastoffset = offset; /* Set loop end condition */
9432 break;
9434 if (offset == lastoffset) break; /* nothing happened, exit loop */
9436 return offset;
9439 static guint
9440 fBACnetPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
9442 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9443 return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
9446 static guint
9447 fBACnetObjectPropertyReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9449 guint lastoffset = 0;
9451 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9452 lastoffset = offset;
9454 switch (fTagNo(tvb, offset)) {
9455 case 0: /* ObjectIdentifier */
9456 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9457 break;
9458 case 1: /* PropertyIdentifier and propertyArrayIndex */
9459 offset = fPropertyReference(tvb, pinfo, tree, offset, 1, 0);
9460 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9461 default:
9462 lastoffset = offset; /* Set loop end condition */
9463 break;
9465 if (offset == lastoffset) break; /* nothing happened, exit loop */
9467 return offset;
9470 #if 0
9471 static guint
9472 fObjectPropertyValue(tvbuff_t *tvb, proto_tree *tree, guint offset)
9474 guint lastoffset = 0;
9475 guint8 tag_no, tag_info;
9476 guint32 lvt;
9477 proto_tree* subtree = tree;
9478 proto_item* tt;
9480 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
9481 lastoffset = offset;
9482 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9483 if (tag_is_closing(tag_info)) {
9484 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9485 &tag_no, &tag_info, &lvt);
9486 continue;
9488 switch (tag_no) {
9489 case 0: /* ObjectIdentifier */
9490 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9491 break;
9492 case 1: /* PropertyIdentifier */
9493 offset = fPropertyIdentifier(tvb, pinfo, subtree, offset);
9494 break;
9495 case 2: /* propertyArrayIndex */
9496 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "property Array Index: ");
9497 break;
9498 case 3: /* Value */
9499 offset = fPropertyValue(tvb, pinfo, subtree, offset, tag_info);
9500 break;
9501 case 4: /* Priority */
9502 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "Priority: ");
9503 break;
9504 default:
9505 break;
9508 return offset;
9510 #endif
9512 static guint
9513 fPriorityArray(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9515 char i = 1, ar[256];
9516 guint lastoffset = 0;
9518 if (propertyArrayIndex > 0) {
9519 /* BACnetARRAY index 0 refers to the length
9520 of the array, not the elements of the array.
9521 BACnetARRAY index -1 is our internal flag that
9522 the optional index was not used.
9523 BACnetARRAY refers to this as all elements of the array.
9524 If the optional index is specified for a BACnetARRAY,
9525 then that specific array element is referenced. */
9526 i = propertyArrayIndex;
9528 while (tvb_reported_length_remaining(tvb, offset) > 0) {
9529 /* exit loop if nothing happens inside */
9530 lastoffset = offset;
9531 g_snprintf(ar, sizeof(ar), "%s[%d]: ",
9532 val_to_split_str(87 , 512,
9533 BACnetPropertyIdentifier,
9534 ASHRAE_Reserved_Fmt,
9535 Vendor_Proprietary_Fmt),
9536 i++);
9537 /* DMR Should be fAbstractNSyntax, but that's where we came from! */
9538 offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
9539 /* there are only 16 priority array elements */
9540 if (i > 16) {
9541 break;
9543 if (offset == lastoffset) break; /* nothing happened, exit loop */
9546 return offset;
9549 static guint
9550 fDeviceObjectReference(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9552 guint lastoffset = 0;
9554 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9555 lastoffset = offset;
9557 switch (fTagNo(tvb, offset)) {
9558 case 0: /* deviceIdentifier - OPTIONAL */
9559 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9560 break;
9561 case 1: /* ObjectIdentifier */
9562 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9563 break;
9564 default:
9565 return offset;
9567 if (offset == lastoffset) break; /* nothing happened, exit loop */
9569 return offset;
9572 static guint
9573 fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9575 guint8 tag_no, tag_info;
9576 guint32 lvt;
9577 guint lastoffset = 0, len;
9578 gboolean closing_found = FALSE; /* tracks when we are done decoding the fSpecialEvent entries */
9580 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9581 lastoffset = offset;
9582 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9583 /* maybe a SEQUENCE of SpecialEvents if we spot a closing tag */
9584 if (tag_is_closing(tag_info)) {
9585 /* if we find 2 closing tags in succession we need to exit without incrementing the offset again */
9586 /* This handles the special case where we have a special event entry in an RPM-ACK msg */
9587 if ( closing_found == TRUE )
9588 break;
9589 offset += len;
9590 closing_found = TRUE;
9591 continue;
9594 switch (tag_no) {
9595 case 0: /* calendarEntry */
9596 if (tag_is_opening(tag_info)) {
9597 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9598 offset = fCalendarEntry(tvb, pinfo, subtree, offset);
9599 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9601 break;
9602 case 1: /* calendarReference */
9603 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9604 break;
9605 case 2: /* list of BACnetTimeValue */
9606 if (tag_is_opening(tag_info)) {
9607 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9608 offset = fTimeValue(tvb, pinfo, subtree, offset);
9609 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9610 break;
9612 FAULT;
9613 break;
9614 case 3: /* eventPriority */
9615 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
9616 break;
9617 default:
9618 return offset;
9620 closing_found = FALSE; /* reset our closing tag status, we processed another open tag */
9621 if (offset == lastoffset) break; /* nothing happened, exit loop */
9623 return offset;
9626 static guint
9627 fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9629 guint lastoffset = 0, len;
9630 guint8 tag_no, tag_info;
9631 guint32 lvt;
9633 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9634 lastoffset = offset;
9635 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9636 /* maybe a listOfSelectionCriteria if we spot a closing tag */
9637 if (tag_is_closing(tag_info)) {
9638 offset += len;
9639 continue;
9642 switch (fTagNo(tvb, offset)) {
9643 case 0: /* propertyIdentifier */
9644 offset = fPropertyIdentifier(tvb, pinfo, tree, offset);
9645 break;
9646 case 1: /* propertyArrayIndex */
9647 offset = fPropertyArrayIndex(tvb, pinfo, tree, offset);
9648 break;
9649 case 2: /* relationSpecifier */
9650 offset = fEnumeratedTag(tvb, pinfo, tree, offset,
9651 "relation Specifier: ", BACnetRelationSpecifier);
9652 break;
9653 case 3: /* comparisonValue */
9654 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9655 offset = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
9656 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
9657 break;
9658 default:
9659 return offset;
9661 if (offset == lastoffset) break; /* nothing happened, exit loop */
9663 return offset;
9666 static guint
9667 fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9669 guint lastoffset = 0;
9670 guint8 tag_no, tag_info;
9671 guint32 lvt;
9673 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9674 lastoffset = offset;
9675 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9676 /* quit loop if we spot a closing tag */
9677 if (tag_is_closing(tag_info)) {
9678 break;
9681 switch (tag_no) {
9682 case 0: /* selectionLogic */
9683 offset = fEnumeratedTag(tvb, pinfo, subtree, offset,
9684 "selection Logic: ", BACnetSelectionLogic);
9685 break;
9686 case 1: /* listOfSelectionCriteria */
9687 if (tag_is_opening(tag_info)) {
9688 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9689 offset = fSelectionCriteria(tvb, pinfo, subtree, offset);
9690 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9691 break;
9693 FAULT;
9694 break;
9695 default:
9696 return offset;
9698 if (offset == lastoffset) break; /* nothing happened, exit loop */
9700 return offset;
9704 static guint
9705 fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
9707 guint lastoffset = 0;
9708 guint8 tag_no, tag_info;
9709 guint32 lvt;
9711 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9712 lastoffset = offset;
9713 fTagHeader (tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9715 if (tag_is_opening(tag_info) && tag_no < 2) {
9716 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9717 switch (tag_no) {
9718 case 0: /* objectSelectionCriteria */
9719 offset = fObjectSelectionCriteria(tvb, pinfo, subtree, offset);
9720 break;
9721 case 1: /* listOfPropertyReferences */
9722 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9723 break;
9724 default:
9725 return offset;
9727 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9729 if (offset == lastoffset) break; /* nothing happened, exit loop */
9731 return offset;
9734 static guint
9735 fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9737 guint lastoffset = 0;
9738 guint8 tag_no, tag_info;
9739 guint32 lvt;
9740 proto_item *tt;
9741 proto_tree *subtree = tree;
9743 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9744 lastoffset = offset;
9745 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9746 switch (tag_no) {
9747 case 0: /* objectIdentifier */
9748 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9749 break;
9750 case 1: /* listOfPropertyReferences */
9751 if (tag_is_opening(tag_info)) {
9752 tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfPropertyReferences");
9753 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9754 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9755 offset = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
9756 } else if (tag_is_closing(tag_info)) {
9757 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
9758 &tag_no, &tag_info, &lvt);
9759 subtree = tree;
9760 } else {
9761 /* error condition: let caller handle */
9762 return offset;
9764 break;
9765 default:
9766 return offset;
9768 if (offset == lastoffset) break; /* nothing happened, exit loop */
9770 return offset;
9773 static guint
9774 fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9776 guint lastoffset = 0, len;
9777 guint8 tag_no;
9778 guint8 tag_info;
9779 guint32 lvt;
9780 proto_tree *subtree = tree;
9781 proto_item *tt;
9783 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9784 lastoffset = offset;
9785 len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9786 /* maybe a listOfReadAccessResults if we spot a closing tag here */
9787 if (tag_is_closing(tag_info)) {
9788 offset += len;
9789 if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
9790 continue;
9793 switch (tag_no) {
9794 case 0: /* objectSpecifier */
9795 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
9796 break;
9797 case 1: /* list of Results */
9798 if (tag_is_opening(tag_info)) {
9799 tt = proto_tree_add_text(tree, tvb, offset, 1, "listOfResults");
9800 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9801 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9802 break;
9804 FAULT;
9805 break;
9806 case 2: /* propertyIdentifier */
9807 offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
9808 break;
9809 case 5: /* propertyAccessError */
9810 if (tag_is_opening(tag_info)) {
9811 tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
9812 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9813 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9814 /* Error Code follows */
9815 offset = fError(tvb, pinfo, subtree, offset);
9816 break;
9818 FAULT;
9819 break;
9820 default:
9821 return offset;
9823 if (offset == lastoffset) break; /* nothing happened, exit loop */
9825 return offset;
9829 static guint
9830 fReadPropertyConditionalAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9832 /* listOfReadAccessResults */
9833 return fReadAccessResult(tvb, pinfo, tree, offset);
9837 static guint
9838 fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
9840 guint lastoffset = 0;
9841 guint8 tag_no, tag_info;
9842 guint32 lvt;
9844 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
9845 lastoffset = offset;
9846 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9848 if (tag_no < 2) {
9849 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9850 switch (tag_no) {
9851 case 0: /* objectSpecifier */
9852 switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
9853 case 0: /* objectType */
9854 offset = fEnumeratedTagSplit(tvb, pinfo, subtree, offset, "Object Type: ", BACnetObjectType, 128);
9855 break;
9856 case 1: /* objectIdentifier */
9857 offset = fObjectIdentifier(tvb, pinfo, subtree, offset);
9858 break;
9859 default:
9860 break;
9862 break;
9863 case 1: /* propertyValue */
9864 if (tag_is_opening(tag_info)) {
9865 offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
9866 break;
9868 FAULT;
9869 break;
9870 default:
9871 break;
9873 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9875 if (offset == lastoffset) break; /* nothing happened, exit loop */
9877 return offset;
9880 static guint
9881 fCreateObjectAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9883 return fObjectIdentifier(tvb, pinfo, tree, offset);
9886 static guint
9887 fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9889 guint8 tag_no, tag_info;
9890 guint32 lvt;
9891 proto_tree *subtree = tree;
9892 proto_item *tt;
9894 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9896 if (tvb_reported_length_remaining(tvb, offset) > 0) {
9897 /* optional range choice */
9898 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9899 if (tag_is_opening(tag_info)) {
9900 tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
9901 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9902 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9903 switch (tag_no) {
9904 case 3: /* range byPosition */
9905 case 6: /* range bySequenceNumber, 2004 spec */
9906 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Index: ");
9907 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9908 break;
9909 case 4: /* range byTime - deprecated in 2004 */
9910 case 7: /* 2004 spec */
9911 offset = fDateTime(tvb, pinfo, subtree, offset, "reference Date/Time: ");
9912 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "reference Count: ");
9913 break;
9914 case 5: /* range timeRange - deprecated in 2004 */
9915 offset = fDateTime(tvb, pinfo, subtree, offset, "beginning Time: ");
9916 offset = fDateTime(tvb, pinfo, subtree, offset, "ending Time: ");
9917 break;
9918 default:
9919 break;
9921 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9924 return offset;
9927 static guint
9928 fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9930 guint8 tag_no, tag_info;
9931 guint32 lvt;
9932 proto_tree *subtree = tree;
9933 proto_item *tt;
9935 /* set the optional global properties to indicate not-used */
9936 propertyArrayIndex = -1;
9937 /* objectIdentifier, propertyIdentifier, and
9938 OPTIONAL propertyArrayIndex */
9939 offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
9940 /* resultFlags => BACnetResultFlags ::= BIT STRING */
9941 offset = fBitStringTagVS(tvb, pinfo, tree, offset,
9942 "resultFlags: ",
9943 BACnetResultFlags);
9944 /* itemCount */
9945 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "item Count: ");
9946 /* itemData */
9947 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9948 if (tag_is_opening(tag_info)) {
9949 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
9950 tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
9951 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9952 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9953 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
9954 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9956 /* firstSequenceNumber - OPTIONAL */
9957 if (tvb_reported_length_remaining(tvb, offset) > 0) {
9958 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "first Sequence Number: ");
9961 return offset;
9964 static guint
9965 fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
9967 guint lastoffset = 0;
9968 guint32 lvt;
9969 guint8 tag_no, tag_info;
9970 proto_item* tt;
9971 proto_tree* subtree = NULL;
9973 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9975 if (tag_is_opening(tag_info)) {
9976 tt = proto_tree_add_text(tree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
9977 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
9978 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9979 offset = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
9980 offset = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
9982 if (tag_no == 1) {
9983 while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
9984 /* exit loop if nothing happens inside */
9985 lastoffset = offset;
9986 offset = fApplicationTypes(tvb, pinfo, subtree, offset, "Record Data: ");
9990 if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0) {
9991 /* More Flag is not set, so we can look for closing tag in this segment */
9992 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
9993 if (tag_is_closing(tag_info)) {
9994 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
9998 return offset;
10001 static guint
10002 fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10004 guint8 tag_no, tag_info;
10005 guint32 lvt;
10006 proto_tree *subtree = tree;
10007 proto_item *tt;
10009 offset = fObjectIdentifier(tvb, pinfo, tree, offset);
10011 fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10013 if (tag_is_opening(tag_info)) {
10014 tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
10015 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
10016 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10017 offset = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10018 offset = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileRequestCount, "unknown option"));
10019 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10021 return offset;
10024 static guint
10025 fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10028 offset = fObjectIdentifier(tvb, pinfo, tree, offset); /* file Identifier */
10029 offset = fAccessMethod(tvb, pinfo, tree, offset);
10031 return offset;
10034 static guint
10035 fAtomicWriteFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10037 guint tag_no = fTagNo(tvb, offset);
10038 return fSignedTag(tvb, pinfo, tree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
10041 static guint
10042 fAtomicReadFileAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10044 offset = fApplicationTypes(tvb, pinfo, tree, offset, "End Of File: ");
10045 offset = fAccessMethod(tvb, pinfo, tree, offset);
10047 return offset;
10050 static guint
10051 fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
10053 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10054 return fReadAccessSpecification(tvb, pinfo, subtree, offset);
10057 static guint
10058 fReadPropertyMultipleAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10060 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10061 return fReadAccessResult(tvb, pinfo, tree, offset);
10064 static guint
10065 fConfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10067 if (tvb_reported_length_remaining(tvb, offset) <= 0)
10068 return offset;
10070 switch (service_choice) {
10071 case 0: /* acknowledgeAlarm */
10072 offset = fAcknowledgeAlarmRequest(tvb, pinfo, tree, offset);
10073 break;
10074 case 1: /* confirmedCOVNotification */
10075 offset = fConfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10076 break;
10077 case 2: /* confirmedEventNotification */
10078 offset = fConfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10079 break;
10080 case 3: /* confirmedGetAlarmSummary conveys no parameters */
10081 break;
10082 case 4: /* getEnrollmentSummaryRequest */
10083 offset = fGetEnrollmentSummaryRequest(tvb, pinfo, tree, offset);
10084 break;
10085 case 5: /* subscribeCOVRequest */
10086 offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
10087 break;
10088 case 6: /* atomicReadFile-Request */
10089 offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
10090 break;
10091 case 7: /* atomicWriteFile-Request */
10092 offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
10093 break;
10094 case 8: /* AddListElement-Request */
10095 offset = fAddListElementRequest(tvb, pinfo, tree, offset);
10096 break;
10097 case 9: /* removeListElement-Request */
10098 offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
10099 break;
10100 case 10: /* createObjectRequest */
10101 offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
10102 break;
10103 case 11: /* deleteObject */
10104 offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
10105 break;
10106 case 12:
10107 offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
10108 break;
10109 case 13:
10110 offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
10111 break;
10112 case 14:
10113 offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
10114 break;
10115 case 15:
10116 offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
10117 break;
10118 case 16:
10119 offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
10120 break;
10121 case 17:
10122 offset = fDeviceCommunicationControlRequest(tvb, pinfo, tree, offset);
10123 break;
10124 case 18:
10125 offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10126 break;
10127 case 19:
10128 offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10129 break;
10130 case 20:
10131 offset = fReinitializeDeviceRequest(tvb, pinfo, tree, offset);
10132 break;
10133 case 21:
10134 offset = fVtOpenRequest(tvb, pinfo, tree, offset);
10135 break;
10136 case 22:
10137 offset = fVtCloseRequest(tvb, pinfo, tree, offset);
10138 break;
10139 case 23:
10140 offset = fVtDataRequest(tvb, pinfo, tree, offset);
10141 break;
10142 case 24:
10143 offset = fAuthenticateRequest(tvb, pinfo, tree, offset);
10144 break;
10145 case 25:
10146 offset = fRequestKeyRequest(tvb, pinfo, tree, offset);
10147 break;
10148 case 26:
10149 offset = fReadRangeRequest(tvb, pinfo, tree, offset);
10150 break;
10151 case 27:
10152 offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
10153 break;
10154 case 28:
10155 offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
10156 break;
10157 case 29:
10158 offset = fGetEventInformationRequest(tvb, pinfo, tree, offset);
10159 break;
10160 default:
10161 return offset;
10163 return offset;
10166 static guint
10167 fConfirmedServiceAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10169 if (tvb_reported_length_remaining(tvb, offset) <= 0)
10170 return offset;
10172 switch (service_choice) {
10173 case 3: /* confirmedEventNotificationAck */
10174 offset = fGetAlarmSummaryAck(tvb, pinfo, tree, offset);
10175 break;
10176 case 4: /* getEnrollmentSummaryAck */
10177 offset = fGetEnrollmentSummaryAck(tvb, pinfo, tree, offset);
10178 break;
10179 case 6: /* atomicReadFile */
10180 offset = fAtomicReadFileAck(tvb, pinfo, tree, offset);
10181 break;
10182 case 7: /* atomicReadFileAck */
10183 offset = fAtomicWriteFileAck(tvb, pinfo, tree, offset);
10184 break;
10185 case 10: /* createObject */
10186 offset = fCreateObjectAck(tvb, pinfo, tree, offset);
10187 break;
10188 case 12:
10189 offset = fReadPropertyAck(tvb, pinfo, tree, offset);
10190 break;
10191 case 13:
10192 offset = fReadPropertyConditionalAck(tvb, pinfo, tree, offset);
10193 break;
10194 case 14:
10195 offset = fReadPropertyMultipleAck(tvb, pinfo, tree, offset);
10196 break;
10197 case 18:
10198 offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
10199 break;
10200 case 21:
10201 offset = fVtOpenAck(tvb, pinfo, tree, offset);
10202 break;
10203 case 23:
10204 offset = fVtDataAck(tvb, pinfo, tree, offset);
10205 break;
10206 case 24:
10207 offset = fAuthenticateAck(tvb, pinfo, tree, offset);
10208 break;
10209 case 26:
10210 offset = fReadRangeAck(tvb, pinfo, tree, offset);
10211 break;
10212 case 29:
10213 offset = fGetEventInformationACK(tvb, pinfo, tree, offset);
10214 break;
10215 default:
10216 return offset;
10218 return offset;
10221 static guint
10222 fIAmRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10224 /* BACnetObjectIdentifier */
10225 offset = fApplicationTypes(tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
10227 /* MaxAPDULengthAccepted */
10228 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
10230 /* segmentationSupported */
10231 offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset,
10232 "Segmentation Supported: ", BACnetSegmentation);
10234 /* vendor ID */
10235 return fVendorIdentifier(tvb, pinfo, tree, offset);
10238 static guint
10239 fIHaveRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10241 /* BACnetDeviceIdentifier */
10242 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: ");
10244 /* BACnetObjectIdentifier */
10245 offset = fApplicationTypes(tvb, pinfo, tree, offset, "Object Identifier: ");
10247 /* ObjectName */
10248 return fApplicationTypes(tvb, pinfo, tree, offset, "Object Name: ");
10252 static guint
10253 fWhoIsRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, guint offset)
10255 guint lastoffset = 0;
10256 guint val;
10257 guint8 tag_len;
10259 guint8 tag_no, tag_info;
10260 guint32 lvt;
10262 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10263 lastoffset = offset;
10265 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10267 switch (tag_no) {
10268 case 0:
10269 /* DeviceInstanceRangeLowLimit Optional */
10270 if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10271 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10272 offset = fDevice_Instance(tvb, pinfo, tree, offset,
10273 hf_Device_Instance_Range_Low_Limit);
10274 break;
10275 case 1:
10276 /* DeviceInstanceRangeHighLimit Optional but
10277 required if DeviceInstanceRangeLowLimit is there */
10278 if (col_get_writable(pinfo->cinfo) && fUnsigned32(tvb, offset+tag_len, lvt, &val))
10279 col_append_fstr(pinfo->cinfo, COL_INFO, "%d ", val);
10280 offset = fDevice_Instance(tvb, pinfo, tree, offset,
10281 hf_Device_Instance_Range_High_Limit);
10282 break;
10283 default:
10284 return offset;
10286 if (offset == lastoffset) break; /* nothing happened, exit loop */
10288 return offset;
10291 static guint
10292 fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
10294 if (tvb_reported_length_remaining(tvb, offset) <= 0)
10295 return offset;
10297 switch (service_choice) {
10298 case 0: /* I-Am-Request */
10299 offset = fIAmRequest(tvb, pinfo, tree, offset);
10300 break;
10301 case 1: /* i-Have Request */
10302 offset = fIHaveRequest(tvb, pinfo, tree, offset);
10303 break;
10304 case 2: /* unconfirmedCOVNotification */
10305 offset = fUnconfirmedCOVNotificationRequest(tvb, pinfo, tree, offset);
10306 break;
10307 case 3: /* unconfirmedEventNotification */
10308 offset = fUnconfirmedEventNotificationRequest(tvb, pinfo, tree, offset);
10309 break;
10310 case 4: /* unconfirmedPrivateTransfer */
10311 offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
10312 break;
10313 case 5: /* unconfirmedTextMessage */
10314 offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
10315 break;
10316 case 206: /* utc-time-synchronization-recipients */
10317 case 6: /* timeSynchronization */
10318 offset = fTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10319 break;
10320 case 7: /* who-Has */
10321 offset = fWhoHas(tvb, pinfo, tree, offset);
10322 break;
10323 case 8: /* who-Is */
10324 offset = fWhoIsRequest(tvb, pinfo, tree, offset);
10325 break;
10326 case 9: /* utcTimeSynchronization */
10327 offset = fUTCTimeSynchronizationRequest(tvb, pinfo, tree, offset);
10328 break;
10329 default:
10330 break;
10332 return offset;
10335 static guint
10336 fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
10337 gint *svc, proto_item **tt)
10339 proto_item *tc;
10340 proto_tree *bacapp_tree_control;
10341 gint tmp;
10342 guint extra = 2;
10344 bacapp_seq = 0;
10345 tmp = (gint) tvb_get_guint8(tvb, offset);
10346 bacapp_flags = tmp & 0x0f;
10348 if (ack == 0) {
10349 extra = 3;
10351 *svc = (gint) tvb_get_guint8(tvb, offset+extra);
10352 if (bacapp_flags & 0x08)
10353 *svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
10355 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10356 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, ENC_BIG_ENDIAN);
10357 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
10359 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, ENC_BIG_ENDIAN);
10360 proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, ENC_BIG_ENDIAN);
10361 if (ack == 0) { /* The following are for ConfirmedRequest, not Complex ack */
10362 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, ENC_BIG_ENDIAN);
10363 proto_tree_add_item(bacapp_tree, hf_bacapp_response_segments, tvb,
10364 offset, 1, ENC_BIG_ENDIAN);
10365 proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
10366 offset, 1, ENC_BIG_ENDIAN);
10368 offset++;
10369 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, ENC_BIG_ENDIAN);
10370 if (bacapp_flags & 0x08) {
10371 bacapp_seq = tvb_get_guint8(tvb, offset);
10372 proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
10373 offset++, 1, ENC_BIG_ENDIAN);
10374 proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
10375 offset++, 1, ENC_BIG_ENDIAN);
10377 *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10378 offset++, 1, ENC_BIG_ENDIAN);
10379 return offset;
10382 static guint
10383 fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10384 { /* BACnet-Confirmed-Request */
10385 /* ASHRAE 135-2001 20.1.2 */
10387 return fConfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, svc);
10390 static guint
10391 fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10392 { /* BACnet-Confirmed-Request */
10393 /* ASHRAE 135-2001 20.1.2 */
10394 gint svc;
10395 proto_item *tt = 0;
10397 offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
10398 return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
10401 static guint
10402 fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10403 { /* BACnet-Unconfirmed-Request-PDU */
10404 /* ASHRAE 135-2001 20.1.3 */
10406 gint tmp;
10408 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10410 tmp = tvb_get_guint8(tvb, offset);
10411 proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
10412 offset++, 1, ENC_BIG_ENDIAN);
10413 /* Service Request follows... Variable Encoding 20.2ff */
10414 return fUnconfirmedServiceRequest(tvb, pinfo, bacapp_tree, offset, tmp);
10417 static guint
10418 fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10419 { /* BACnet-Simple-Ack-PDU */
10420 /* ASHRAE 135-2001 20.1.4 */
10422 proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10424 proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
10425 offset++, 1, ENC_BIG_ENDIAN);
10426 proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
10427 offset++, 1, ENC_BIG_ENDIAN);
10429 return offset;
10432 static guint
10433 fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
10434 { /* BACnet-Complex-Ack-PDU */
10435 /* ASHRAE 135-2001 20.1.5 */
10437 /* Service ACK follows... */
10438 return fConfirmedServiceAck(tvb, pinfo, bacapp_tree, offset, svc);
10441 static guint
10442 fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10443 { /* BACnet-Complex-Ack-PDU */
10444 /* ASHRAE 135-2001 20.1.5 */
10445 gint svc;
10446 proto_item *tt = 0;
10448 offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
10449 return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
10452 static guint
10453 fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10454 { /* BACnet-SegmentAck-PDU */
10455 /* ASHRAE 135-2001 20.1.6 */
10457 proto_item *tc;
10458 proto_tree *bacapp_tree_control;
10460 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10461 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10463 proto_tree_add_item(bacapp_tree_control, hf_bacapp_NAK, tvb, offset, 1, ENC_BIG_ENDIAN);
10464 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10465 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10466 offset++, 1, ENC_BIG_ENDIAN);
10467 proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
10468 offset++, 1, ENC_BIG_ENDIAN);
10469 proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
10470 offset++, 1, ENC_BIG_ENDIAN);
10471 return offset;
10474 static guint
10475 fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10477 guint8 tag_info = 0;
10478 guint8 parsed_tag = 0;
10479 guint32 lvt = 0;
10481 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10482 offset = fError(tvb, pinfo, tree, offset);
10483 return offset + fTagHeaderTree(tvb, pinfo, tree, offset, &parsed_tag, &tag_info, &lvt);
10486 static guint
10487 fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10489 guint lastoffset = 0;
10490 guint8 tag_no = 0, tag_info = 0;
10491 guint32 lvt = 0;
10492 proto_tree *subtree = tree;
10493 proto_item *tt;
10495 guint vendor_identifier = 0;
10496 guint service_number = 0;
10497 guint8 tag_len = 0;
10499 while (tvb_reported_length_remaining(tvb, offset) > 0) {
10500 /* exit loop if nothing happens inside */
10501 lastoffset = offset;
10502 tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
10503 switch (tag_no) {
10504 case 0: /* errorType */
10505 offset = fContextTaggedError(tvb, pinfo, subtree, offset);
10506 break;
10507 case 1: /* vendorID */
10508 fUnsigned32(tvb, offset+tag_len, lvt, &vendor_identifier);
10509 if (col_get_writable(pinfo->cinfo))
10510 col_append_fstr(pinfo->cinfo, COL_INFO, "V=%u ", vendor_identifier);
10511 offset = fVendorIdentifier(tvb, pinfo, subtree, offset);
10512 break;
10513 case 2: /* serviceNumber */
10514 fUnsigned32(tvb, offset+tag_len, lvt, &service_number);
10515 if (col_get_writable(pinfo->cinfo))
10516 col_append_fstr(pinfo->cinfo, COL_INFO, "SN=%u ", service_number);
10517 offset = fUnsignedTag(tvb, pinfo, subtree, offset, "service Number: ");
10518 break;
10519 case 3: /* errorParameters */
10520 if (tag_is_opening(tag_info)) {
10521 tt = proto_tree_add_text(subtree, tvb, offset, 1,
10522 "error Parameters");
10523 subtree = proto_item_add_subtree(tt, ett_bacapp_value);
10524 propertyIdentifier = -1;
10525 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
10526 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
10527 } else if (tag_is_closing(tag_info)) {
10528 offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
10529 &tag_no, &tag_info, &lvt);
10530 subtree = tree;
10531 } else {
10532 /* error condition: let caller handle */
10533 return offset;
10535 break;
10536 default:
10537 return offset;
10539 if (offset == lastoffset) break; /* nothing happened, exit loop */
10541 return offset;
10544 static guint
10545 fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10547 guint lastoffset = 0;
10549 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10550 lastoffset = offset;
10551 switch (fTagNo(tvb, offset)) {
10552 case 0: /* errorType */
10553 offset = fContextTaggedError(tvb, pinfo, tree, offset);
10554 break;
10555 case 1: /* firstFailedElementNumber */
10556 offset = fUnsignedTag(tvb, pinfo, tree, offset, "first failed element number: ");
10557 break;
10558 default:
10559 return offset;
10561 if (offset == lastoffset) break; /* nothing happened, exit loop */
10563 return offset;
10566 static guint
10567 fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10569 /* Identical to CreateObjectError */
10570 return fCreateObjectError(tvb, pinfo, tree, offset);
10573 static guint
10574 fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10576 guint8 tag_no = 0, tag_info = 0;
10577 guint32 lvt = 0;
10579 if (fTagNo(tvb, offset) == 0) {
10580 /* errorType */
10581 offset = fContextTaggedError(tvb, pinfo, tree, offset);
10582 if (fTagNo(tvb, offset) == 1) {
10583 /* listOfVTSessionIdentifiers [OPTIONAL] */
10584 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10585 offset = fVtCloseRequest(tvb, pinfo, tree, offset);
10586 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10589 /* should report bad packet if initial tag wasn't 0 */
10590 return offset;
10593 static guint
10594 fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10596 guint lastoffset = 0;
10597 guint8 tag_no = 0, tag_info = 0;
10598 guint32 lvt = 0;
10600 col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
10601 while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
10602 lastoffset = offset;
10603 switch (fTagNo(tvb, offset)) {
10604 case 0: /* errorType */
10605 offset = fContextTaggedError(tvb, pinfo, tree, offset);
10606 break;
10607 case 1: /* firstFailedWriteAttempt */
10608 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10609 offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
10610 offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt);
10611 break;
10612 default:
10613 return offset;
10615 if (offset == lastoffset) break; /* nothing happened, exit loop */
10617 return offset;
10620 static guint
10621 fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
10623 offset = fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10624 "error Class: ", BACnetErrorClass, 64);
10625 return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset,
10626 "error Code: ", BACnetErrorCode, 256);
10629 static guint
10630 fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
10632 switch (service) {
10633 case 8: /* no break here !!!! */
10634 case 9:
10635 offset = fChangeListError(tvb, pinfo, tree, offset);
10636 break;
10637 case 10:
10638 offset = fCreateObjectError(tvb, pinfo, tree, offset);
10639 break;
10640 case 16:
10641 offset = fWritePropertyMultipleError(tvb, pinfo, tree, offset);
10642 break;
10643 case 18:
10644 offset = fConfirmedPrivateTransferError(tvb, pinfo, tree, offset);
10645 break;
10646 case 22:
10647 offset = fVTCloseError(tvb, pinfo, tree, offset);
10648 break;
10649 default:
10650 return fError(tvb, pinfo, tree, offset);
10652 return offset;
10655 static guint
10656 fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
10657 { /* BACnet-Error-PDU */
10658 /* ASHRAE 135-2001 20.1.7 */
10660 proto_item *tc;
10661 proto_tree *bacapp_tree_control;
10662 guint8 tmp;
10664 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10665 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10667 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10668 offset++, 1, ENC_BIG_ENDIAN);
10669 tmp = tvb_get_guint8(tvb, offset);
10670 proto_tree_add_item(bacapp_tree_control, hf_bacapp_service, tvb,
10671 offset++, 1, ENC_BIG_ENDIAN);
10672 /* Error Handling follows... */
10673 return fBACnetError(tvb, pinfo, bacapp_tree, offset, tmp);
10676 static guint
10677 fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10678 { /* BACnet-Reject-PDU */
10679 /* ASHRAE 135-2001 20.1.8 */
10681 proto_item *tc;
10682 proto_tree *bacapp_tree_control;
10684 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, ENC_BIG_ENDIAN);
10685 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10687 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10688 offset++, 1, ENC_BIG_ENDIAN);
10689 proto_tree_add_item(bacapp_tree_control, hf_BACnetRejectReason, tvb,
10690 offset++, 1, ENC_BIG_ENDIAN);
10691 return offset;
10694 static guint
10695 fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
10696 { /* BACnet-Abort-PDU */
10697 /* ASHRAE 135-2001 20.1.9 */
10699 proto_item *tc;
10700 proto_tree *bacapp_tree_control;
10702 tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
10703 bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
10705 proto_tree_add_item(bacapp_tree_control, hf_bacapp_SRV, tvb, offset++, 1, ENC_BIG_ENDIAN);
10706 proto_tree_add_item(bacapp_tree_control, hf_bacapp_invoke_id, tvb,
10707 offset++, 1, ENC_BIG_ENDIAN);
10708 proto_tree_add_item(bacapp_tree_control, hf_BACnetAbortReason, tvb,
10709 offset++, 1, ENC_BIG_ENDIAN);
10710 return offset;
10713 static guint
10714 do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10716 guint8 flag, bacapp_type;
10717 guint offset = 0;
10719 flag = (gint) tvb_get_guint8(tvb, 0);
10720 bacapp_type = (flag >> 4) & 0x0f;
10722 if (tvb == NULL) {
10723 return 0;
10726 /* ASHRAE 135-2001 20.1.1 */
10727 switch (bacapp_type) {
10728 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
10729 offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
10730 break;
10731 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: /* BACnet-Unconfirmed-Request-PDU */
10732 offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
10733 break;
10734 case BACAPP_TYPE_SIMPLE_ACK: /* BACnet-Simple-Ack-PDU */
10735 offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
10736 break;
10737 case BACAPP_TYPE_COMPLEX_ACK: /* BACnet-Complex-Ack-PDU */
10738 offset = fComplexAckPDU(tvb, pinfo, tree, offset);
10739 break;
10740 case BACAPP_TYPE_SEGMENT_ACK: /* BACnet-SegmentAck-PDU */
10741 offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
10742 break;
10743 case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
10744 offset = fErrorPDU(tvb, pinfo, tree, offset);
10745 break;
10746 case BACAPP_TYPE_REJECT: /* BACnet-Reject-PDU */
10747 offset = fRejectPDU(tvb, pinfo, tree, offset);
10748 break;
10749 case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
10750 offset = fAbortPDU(tvb, pinfo, tree, offset);
10751 break;
10753 return offset;
10756 static void
10757 dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
10759 guint8 flag, bacapp_type;
10760 guint save_fragmented = FALSE, data_offset = 0, /*bacapp_apdu_size,*/ fragment = FALSE;
10761 tvbuff_t *new_tvb = NULL;
10762 guint offset = 0;
10763 guint8 bacapp_seqno = 0;
10764 guint8 bacapp_service, bacapp_reason/*, bacapp_prop_win_size*/;
10765 guint8 bacapp_invoke_id = 0;
10766 proto_item *ti;
10767 proto_tree *bacapp_tree = NULL;
10769 gint svc = 0;
10770 proto_item *tt = 0;
10771 gint8 ack = 0;
10773 /* Strings for BACnet Statistics */
10774 const gchar errstr[] = "ERROR: ";
10775 const gchar rejstr[] = "REJECTED: ";
10776 const gchar abortstr[] = "ABORTED: ";
10777 const gchar sackstr[] = " (SimpleAck)";
10778 const gchar cackstr[] = " (ComplexAck)";
10779 const gchar uconfsreqstr[] = " (Unconfirmed Service Request)";
10780 const gchar confsreqstr[] = " (Confirmed Service Request)";
10782 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
10783 col_clear(pinfo->cinfo, COL_INFO);
10785 flag = tvb_get_guint8(tvb, 0);
10786 bacapp_type = (flag >> 4) & 0x0f;
10788 /* show some descriptive text in the INFO column */
10789 col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
10790 val_to_str_const(bacapp_type, BACnetTypeName, "# unknown APDU #"));
10792 bacinfo.service_type = NULL;
10793 bacinfo.invoke_id = NULL;
10794 bacinfo.instance_ident = NULL;
10795 bacinfo.object_ident = NULL;
10797 switch (bacapp_type) {
10798 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
10799 /* segmented messages have 2 additional bytes */
10800 if (flag & BACAPP_SEGMENTED_REQUEST) {
10801 fragment = TRUE;
10802 ack = 0;
10803 /* bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); */ /* has 16 values, reserved are 50 Bytes */
10804 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10805 bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
10806 /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4); */
10807 bacapp_service = tvb_get_guint8(tvb, offset + 5);
10808 data_offset = 6;
10809 } else {
10810 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
10811 bacapp_service = tvb_get_guint8(tvb, offset + 3);
10813 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
10814 val_to_str_const(bacapp_service,
10815 BACnetConfirmedServiceChoice,
10816 bacapp_unknown_service_str),
10817 bacapp_invoke_id);
10819 updateBacnetInfoValue(BACINFO_INVOKEID,
10820 wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10822 updateBacnetInfoValue(BACINFO_SERVICE,
10823 wmem_strconcat(wmem_packet_scope(),
10824 val_to_str_const(bacapp_service,
10825 BACnetConfirmedServiceChoice,
10826 bacapp_unknown_service_str),
10827 confsreqstr, NULL));
10828 break;
10829 case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
10830 bacapp_service = tvb_get_guint8(tvb, offset + 1);
10831 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
10832 val_to_str_const(bacapp_service,
10833 BACnetUnconfirmedServiceChoice,
10834 bacapp_unknown_service_str));
10836 updateBacnetInfoValue(BACINFO_SERVICE,
10837 wmem_strconcat(wmem_packet_scope(),
10838 val_to_str_const(bacapp_service,
10839 BACnetUnconfirmedServiceChoice,
10840 bacapp_unknown_service_str),
10841 uconfsreqstr, NULL));
10842 break;
10843 case BACAPP_TYPE_SIMPLE_ACK:
10844 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10845 bacapp_service = tvb_get_guint8(tvb, offset + 2);
10846 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10847 val_to_str_const(bacapp_service,
10848 BACnetConfirmedServiceChoice,
10849 bacapp_unknown_service_str),
10850 bacapp_invoke_id);
10852 updateBacnetInfoValue(BACINFO_INVOKEID,
10853 wmem_strdup_printf(wmem_packet_scope(),
10854 "Invoke ID: %d", bacapp_invoke_id));
10856 updateBacnetInfoValue(BACINFO_SERVICE,
10857 wmem_strconcat(wmem_packet_scope(),
10858 val_to_str_const(bacapp_service,
10859 BACnetConfirmedServiceChoice,
10860 bacapp_unknown_service_str),
10861 sackstr, NULL));
10862 break;
10863 case BACAPP_TYPE_COMPLEX_ACK:
10864 /* segmented messages have 2 additional bytes */
10865 if (flag & BACAPP_SEGMENTED_REQUEST) {
10866 fragment = TRUE;
10867 ack = 1;
10868 /* bacapp_apdu_size = fGetMaxAPDUSize(0); */ /* has minimum of 50 Bytes */
10869 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10870 bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
10871 /* bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3); */
10872 bacapp_service = tvb_get_guint8(tvb, offset + 4);
10873 data_offset = 5;
10874 } else {
10875 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10876 bacapp_service = tvb_get_guint8(tvb, offset + 2);
10878 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10879 val_to_str_const(bacapp_service,
10880 BACnetConfirmedServiceChoice,
10881 bacapp_unknown_service_str),
10882 bacapp_invoke_id);
10884 updateBacnetInfoValue(BACINFO_INVOKEID,
10885 wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10887 updateBacnetInfoValue(BACINFO_SERVICE,
10888 wmem_strconcat(wmem_packet_scope(),
10889 val_to_str_const(bacapp_service,
10890 BACnetConfirmedServiceChoice,
10891 bacapp_unknown_service_str),
10892 cackstr, NULL));
10893 break;
10894 case BACAPP_TYPE_SEGMENT_ACK:
10895 /* nothing more to add */
10896 break;
10897 case BACAPP_TYPE_ERROR:
10898 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10899 bacapp_service = tvb_get_guint8(tvb, offset + 2);
10900 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10901 val_to_str_const(bacapp_service,
10902 BACnetConfirmedServiceChoice,
10903 bacapp_unknown_service_str),
10904 bacapp_invoke_id);
10906 updateBacnetInfoValue(BACINFO_INVOKEID,
10907 wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10909 updateBacnetInfoValue(BACINFO_SERVICE,
10910 wmem_strconcat(wmem_packet_scope(),
10911 errstr,
10912 val_to_str_const(bacapp_service,
10913 BACnetConfirmedServiceChoice,
10914 bacapp_unknown_service_str),
10915 NULL));
10916 break;
10917 case BACAPP_TYPE_REJECT:
10918 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10919 bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10920 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10921 val_to_split_str(bacapp_reason,
10923 BACnetRejectReason,
10924 ASHRAE_Reserved_Fmt,
10925 Vendor_Proprietary_Fmt), bacapp_invoke_id);
10927 updateBacnetInfoValue(BACINFO_INVOKEID,
10928 wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10930 updateBacnetInfoValue(BACINFO_SERVICE,
10931 wmem_strconcat(wmem_packet_scope(), rejstr,
10932 val_to_split_str(bacapp_reason, 64,
10933 BACnetRejectReason,
10934 ASHRAE_Reserved_Fmt,
10935 Vendor_Proprietary_Fmt),
10936 NULL));
10937 break;
10938 case BACAPP_TYPE_ABORT:
10939 bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
10940 bacapp_reason = tvb_get_guint8(tvb, offset + 2);
10941 col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
10942 val_to_split_str(bacapp_reason,
10944 BACnetAbortReason,
10945 ASHRAE_Reserved_Fmt,
10946 Vendor_Proprietary_Fmt), bacapp_invoke_id);
10948 updateBacnetInfoValue(BACINFO_INVOKEID,
10949 wmem_strdup_printf(wmem_packet_scope(), "Invoke ID: %d", bacapp_invoke_id));
10951 updateBacnetInfoValue(BACINFO_SERVICE,
10952 wmem_strconcat(wmem_packet_scope(), abortstr,
10953 val_to_split_str(bacapp_reason,
10955 BACnetAbortReason,
10956 ASHRAE_Reserved_Fmt,
10957 Vendor_Proprietary_Fmt),
10958 NULL));
10959 break;
10960 /* UNKNOWN */
10961 default:
10962 /* nothing more to add */
10963 break;
10966 save_fragmented = pinfo->fragmented;
10968 ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, ENC_NA);
10969 bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
10971 if (!fragment)
10972 do_the_dissection(tvb, pinfo, bacapp_tree);
10973 else
10974 fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
10975 /* not resetting the offset so the remaining can be done */
10977 if (fragment) { /* fragmented */
10978 fragment_head *frag_msg;
10980 pinfo->fragmented = TRUE;
10982 frag_msg = fragment_add_seq_check(&msg_reassembly_table,
10983 tvb, data_offset,
10984 pinfo,
10985 bacapp_invoke_id, /* ID for fragments belonging together */
10986 NULL,
10987 bacapp_seqno, /* fragment sequence number */
10988 tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
10989 flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
10990 new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
10991 "Reassembled BACapp", frag_msg, &msg_frag_items,
10992 NULL, tree);
10994 if (new_tvb) { /* Reassembled */
10995 col_append_str(pinfo->cinfo, COL_INFO,
10996 " (Message Reassembled)");
10997 } else { /* Not last packet of reassembled Short Message */
10998 col_append_fstr(pinfo->cinfo, COL_INFO,
10999 " (Message fragment %u)", bacapp_seqno);
11001 if (new_tvb) { /* take it all */
11002 switch (bacapp_type) {
11003 case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
11004 fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11005 break;
11006 case BACAPP_TYPE_COMPLEX_ACK:
11007 fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
11008 break;
11009 default:
11010 /* do nothing */
11011 break;
11016 pinfo->fragmented = save_fragmented;
11018 /* tapping */
11019 tap_queue_packet(bacapp_tap, pinfo, &bacinfo);
11022 static void
11023 bacapp_init_routine(void)
11025 reassembly_table_init(&msg_reassembly_table,
11026 &addresses_reassembly_table_functions);
11029 static guint32
11030 fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding)
11032 guint32 i;
11033 GIConv icd;
11035 if ((icd = g_iconv_open("UTF-8", fromcoding)) != (GIConv) -1) {
11036 i = (guint32) g_iconv(icd, &in, inbytesleft, &out, outbytesleft);
11037 /* g_iconv incremented 'out'; now ensure it's NULL terminated */
11038 out[0] = '\0';
11040 g_iconv_close(icd);
11041 return i;
11044 uni_to_string(in, *inbytesleft, out);
11045 out[*inbytesleft] = '\0';
11046 *outbytesleft -= *inbytesleft;
11047 *inbytesleft = 0;
11049 return 0;
11052 static void
11053 uni_to_string(char * data, gsize str_length, char *dest_buf)
11055 gint i;
11056 guint16 c_char;
11057 gsize length_remaining;
11059 length_remaining = str_length;
11060 dest_buf[0] = '\0';
11061 if (str_length == 0) {
11062 return;
11064 for ( i = 0; i < (gint) str_length; i++ ) {
11065 c_char = data[i];
11066 if ((c_char < 0x20) || (c_char > 0x7e)) {
11067 if (c_char != 0x00) {
11068 c_char = '.';
11069 dest_buf[i] = c_char & 0xff;
11070 } else {
11071 i--;
11072 str_length--;
11074 } else {
11075 dest_buf[i] = c_char & 0xff;
11077 length_remaining--;
11079 if (length_remaining == 0) {
11080 dest_buf[i+1] = '\0';
11081 return;
11084 if (i < 0) {
11085 i = 0;
11087 dest_buf[i] = '\0';
11088 return;
11091 void
11092 proto_register_bacapp(void)
11094 static hf_register_info hf[] = {
11095 { &hf_bacapp_type,
11096 { "APDU Type", "bacapp.type",
11097 FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
11099 { &hf_bacapp_pduflags,
11100 { "PDU Flags", "bacapp.pduflags",
11101 FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
11103 { &hf_bacapp_SEG,
11104 { "Segmented Request", "bacapp.segmented_request",
11105 FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
11107 { &hf_bacapp_MOR,
11108 { "More Segments", "bacapp.more_segments",
11109 FT_BOOLEAN, 8, TFS(&more_follow), 0x04, "More Segments Follow", HFILL }
11111 { &hf_bacapp_SA,
11112 { "SA", "bacapp.SA",
11113 FT_BOOLEAN, 8, TFS(&segmented_accept), 0x02, "Segmented Response accepted", HFILL }
11115 { &hf_bacapp_max_adpu_size,
11116 { "Size of Maximum ADPU accepted", "bacapp.max_adpu_size",
11117 FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
11119 { &hf_bacapp_response_segments,
11120 { "Max Response Segments accepted", "bacapp.response_segments",
11121 FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
11123 { &hf_bacapp_objectType,
11124 { "Object Type", "bacapp.objectType",
11125 FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
11127 { &hf_bacapp_instanceNumber,
11128 { "Instance Number", "bacapp.instance_number",
11129 FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
11131 { &hf_BACnetPropertyIdentifier,
11132 { "Property Identifier", "bacapp.property_identifier",
11133 FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
11135 { &hf_BACnetVendorIdentifier,
11136 { "Vendor Identifier", "bacapp.vendor_identifier",
11137 FT_UINT16, BASE_DEC|BASE_EXT_STRING, &BACnetVendorIdentifiers_ext, 0, NULL, HFILL }
11139 { &hf_BACnetRestartReason,
11140 { "Restart Reason", "bacapp.restart_reason",
11141 FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
11143 { &hf_bacapp_invoke_id,
11144 { "Invoke ID", "bacapp.invoke_id",
11145 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11147 { &hf_bacapp_sequence_number,
11148 { "Sequence Number", "bacapp.sequence_number",
11149 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11151 { &hf_bacapp_window_size,
11152 { "Proposed Window Size", "bacapp.window_size",
11153 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
11155 { &hf_bacapp_service,
11156 { "Service Choice", "bacapp.confirmed_service",
11157 FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
11159 { &hf_bacapp_uservice,
11160 { "Unconfirmed Service Choice", "bacapp.unconfirmed_service",
11161 FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
11163 { &hf_bacapp_NAK,
11164 { "NAK", "bacapp.NAK",
11165 FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
11167 { &hf_bacapp_SRV,
11168 { "SRV", "bacapp.SRV",
11169 FT_BOOLEAN, 8, NULL, 0x01, "Server", HFILL }
11171 { &hf_Device_Instance_Range_Low_Limit,
11172 { "Device Instance Range Low Limit", "bacapp.who_is.low_limit",
11173 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11175 { &hf_Device_Instance_Range_High_Limit,
11176 { "Device Instance Range High Limit", "bacapp.who_is.high_limit",
11177 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
11179 { &hf_BACnetRejectReason,
11180 { "Reject Reason", "bacapp.reject_reason",
11181 FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
11183 { &hf_BACnetAbortReason,
11184 { "Abort Reason", "bacapp.abort_reason",
11185 FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
11187 { &hf_BACnetApplicationTagNumber,
11188 { "Application Tag Number",
11189 "bacapp.application_tag_number",
11190 FT_UINT8, BASE_DEC, VALS(BACnetApplicationTagNumber), 0xF0,
11191 NULL, HFILL }
11193 { &hf_BACnetContextTagNumber,
11194 { "Context Tag Number",
11195 "bacapp.context_tag_number",
11196 FT_UINT8, BASE_DEC, NULL, 0xF0,
11197 NULL, HFILL }
11199 { &hf_BACnetExtendedTagNumber,
11200 { "Extended Tag Number",
11201 "bacapp.extended_tag_number",
11202 FT_UINT8, BASE_DEC, NULL, 0,
11203 NULL, HFILL }
11205 { &hf_BACnetNamedTag,
11206 { "Named Tag",
11207 "bacapp.named_tag",
11208 FT_UINT8, BASE_DEC, VALS(BACnetTagNames), 0x07,
11209 NULL, HFILL }
11211 { &hf_BACnetCharacterSet,
11212 { "String Character Set",
11213 "bacapp.string_character_set",
11214 FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
11215 NULL, HFILL }
11217 { &hf_BACnetTagClass,
11218 { "Tag Class", "bacapp.tag_class",
11219 FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
11221 { &hf_bacapp_tag_lvt,
11222 { "Length Value Type",
11223 "bacapp.LVT",
11224 FT_UINT8, BASE_DEC, NULL, 0,
11225 NULL, HFILL }
11227 { &hf_bacapp_tag_ProcessId,
11228 { "ProcessIdentifier", "bacapp.processId",
11229 FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
11231 { &hf_bacapp_tag_IPV4,
11232 { "IPV4", "bacapp.IPV4",
11233 FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11235 { &hf_bacapp_tag_IPV6,
11236 { "IPV6", "bacapp.IPV6",
11237 FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
11239 { &hf_bacapp_tag_PORT,
11240 { "Port", "bacapp.Port",
11241 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
11243 {&hf_msg_fragments,
11244 {"Message fragments", "bacapp.fragments",
11245 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11246 {&hf_msg_fragment,
11247 {"Message fragment", "bacapp.fragment",
11248 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11249 {&hf_msg_fragment_overlap,
11250 {"Message fragment overlap", "bacapp.fragment.overlap",
11251 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11252 {&hf_msg_fragment_overlap_conflicts,
11253 {"Message fragment overlapping with conflicting data",
11254 "bacapp.fragment.overlap.conflicts",
11255 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11256 {&hf_msg_fragment_multiple_tails,
11257 {"Message has multiple tail fragments",
11258 "bacapp.fragment.multiple_tails",
11259 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11260 {&hf_msg_fragment_too_long_fragment,
11261 {"Message fragment too long", "bacapp.fragment.too_long_fragment",
11262 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11263 {&hf_msg_fragment_error,
11264 {"Message defragmentation error", "bacapp.fragment.error",
11265 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11266 {&hf_msg_fragment_count,
11267 {"Message fragment count", "bacapp.fragment.count",
11268 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
11269 {&hf_msg_reassembled_in,
11270 {"Reassembled in", "bacapp.reassembled.in",
11271 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
11272 {&hf_msg_reassembled_length,
11273 {"Reassembled BACapp length", "bacapp.reassembled.length",
11274 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
11276 static gint *ett[] = {
11277 &ett_bacapp,
11278 &ett_bacapp_control,
11279 &ett_bacapp_tag,
11280 &ett_bacapp_list,
11281 &ett_bacapp_value,
11282 &ett_msg_fragment,
11283 &ett_msg_fragments
11287 static ei_register_info ei[] = {
11288 { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
11291 expert_module_t* expert_bacapp;
11293 proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
11294 "BACapp", "bacapp");
11296 proto_register_field_array(proto_bacapp, hf, array_length(hf));
11297 proto_register_subtree_array(ett, array_length(ett));
11298 expert_bacapp = expert_register_protocol(proto_bacapp);
11299 expert_register_field_array(expert_bacapp, ei, array_length(ei));
11300 register_dissector("bacapp", dissect_bacapp, proto_bacapp);
11301 register_init_routine(&bacapp_init_routine);
11303 bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
11304 "BACapp Vendor Identifier",
11305 FT_UINT8, BASE_HEX);
11307 /* Register BACnet Statistic trees */
11308 register_bacapp_stat_trees();
11309 bacapp_tap = register_tap("bacapp"); /* BACnet statistics tap */
11313 * Editor modelines - http://www.wireshark.org/tools/modelines.html
11315 * Local variables:
11316 * c-basic-offset: 4
11317 * tab-width: 8
11318 * indent-tabs-mode: nil
11319 * End:
11321 * vi: set shiftwidth=4 tabstop=8 expandtab:
11322 * :indentSize=4:tabSize=8:noTabs=true: