/* packet-bacapp.c
* Routines for BACnet (APDU) dissection
- * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund
- * Enhanced by Steve Karg, 2005, <skarg@users.sourceforge.net>, Atlanta
- * Enhanced by Herbert Lischka, 2005, <lischka@kieback-peter.de>, Berlin
+ * Copyright 2001, Hartmut Mueller <hartmut[AT]abmlinux.org>, FH Dortmund
+ * Enhanced by Steve Karg, 2005, <skarg[AT]users.sourceforge.net>, Atlanta
+ * Enhanced by Herbert Lischka, 2005, <lischka[AT]kieback-peter.de>, Berlin
*
* $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald[AT]wireshark.org>
* Copyright 1998 Gerald Combs
*
* Copied from README.developer,v 1.23
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "packet-bacapp.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/reassemble.h>
+#include <epan/expert.h>
+
+/* formerly bacapp.h contains definitions and forward declarations */
+
+#ifndef FAULT
+#define FAULT proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
+ offset = tvb_length(tvb);
+#endif
+
+/* BACnet PDU Types */
+#define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST 0
+#define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST 1
+#define BACAPP_TYPE_SIMPLE_ACK 2
+#define BACAPP_TYPE_COMPLEX_ACK 3
+#define BACAPP_TYPE_SEGMENT_ACK 4
+#define BACAPP_TYPE_ERROR 5
+#define BACAPP_TYPE_REJECT 6
+#define BACAPP_TYPE_ABORT 7
+#define MAX_BACAPP_TYPE 8
+
+#define BACAPP_SEGMENTED_REQUEST 0x08
+#define BACAPP_MORE_SEGMENTS 0x04
+#define BACAPP_SEGMENTED_RESPONSE 0x02
+#define BACAPP_SEGMENT_NAK 0x02
+#define BACAPP_SENT_BY 0x01
+
+
+/**
+ * dissect_bacapp ::= CHOICE {
+ * confirmed-request-PDU [0] BACnet-Confirmed-Request-PDU,
+ * unconfirmed-request-PDU [1] BACnet-Unconfirmed-Request-PDU,
+ * simpleACK-PDU [2] BACnet-SimpleACK-PDU,
+ * complexACK-PDU [3] BACnet-ComplexACK-PDU,
+ * segmentACK-PDU [4] BACnet-SegmentACK-PDU,
+ * error-PDU [5] BACnet-Error-PDU,
+ * reject-PDU [6] BACnet-Reject-PDU,
+ * abort-PDU [7] BACnet-Abort-PDU
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ **/
+static void
+dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/**
+ * ConfirmedRequest-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 0 for this PDU Type
+ * segmentedMessage [1] BOOLEAN,
+ * moreFollows [2] BOOLEAN,
+ * segmented-response-accepted [3] BOOLEAN,
+ * reserved [4] Unsigned (0..3), -- must be set zero
+ * max-segments-accepted [5] Unsigned (0..7), -- as per 20.1.2.4
+ * max-APDU-length-accepted [5] Unsigned (0..15), -- as per 20.1.2.5
+ * invokeID [6] Unsigned (0..255),
+ * sequence-number [7] Unsigned (0..255) OPTIONAL, -- only if segmented msg
+ * proposed-window-size [8] Unsigned (0..127) OPTIONAL, -- only if segmented msg
+ * service-choice [9] BACnetConfirmedServiceChoice,
+ * service-request [10] BACnet-Confirmed-Service-Request OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param ack - indocates whether working on request or ack
+ * @param svc - output variable to return service choice
+ * @param tt - output varable to return service choice item
+ * @return modified offset
+ */
+static guint
+fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 ack,
+ gint *svc, proto_item **tt);
+
+/**
+ * Unconfirmed-Request-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 1 for this PDU type
+ * reserved [1] Unsigned (0..15), -- must be set zero
+ * service-choice [2] BACnetUnconfirmedServiceChoice,
+ * service-request [3] BACnetUnconfirmedServiceRequest -- Context-specific tags 0..3 are NOT used in header encoding
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SimpleACK-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 2 for this PDU type
+ * reserved [1] Unsigned (0..15), -- must be set zero
+ * invokeID [2] Unsigned (0..255),
+ * service-ACK-choice [3] BACnetUnconfirmedServiceChoice -- Context-specific tags 0..3 are NOT used in header encoding
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ComplexACK-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 3 for this PDU Type
+ * segmentedMessage [1] BOOLEAN,
+ * moreFollows [2] BOOLEAN,
+ * reserved [3] Unsigned (0..3), -- must be set zero
+ * invokeID [4] Unsigned (0..255),
+ * sequence-number [5] Unsigned (0..255) OPTIONAL, -- only if segmented msg
+ * proposed-window-size [6] Unsigned (0..127) OPTIONAL, -- only if segmented msg
+ * service-ACK-choice [7] BACnetConfirmedServiceChoice,
+ * service-ACK [8] BACnet-Confirmed-Service-Request -- Context-specific tags 0..8 are NOT used in header encoding
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SegmentACK-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 4 for this PDU Type
+ * reserved [1] Unsigned (0..3), -- must be set zero
+ * negative-ACK [2] BOOLEAN,
+ * server [3] BOOLEAN,
+ * original-invokeID [4] Unsigned (0..255),
+ * sequence-number [5] Unsigned (0..255),
+ * actual-window-size [6] Unsigned (0..127)
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Error-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 5 for this PDU Type
+ * reserved [1] Unsigned (0..3), -- must be set zero
+ * original-invokeID [2] Unsigned (0..255),
+ * error-choice [3] BACnetConfirmedServiceChoice,
+ * error [4] BACnet-Error
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Reject-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 6 for this PDU Type
+ * reserved [1] Unsigned (0..3), -- must be set zero
+ * original-invokeID [2] Unsigned (0..255),
+ * reject-reason [3] BACnetRejectReason
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRejectPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Abort-PDU ::= SEQUENCE {
+ * pdu-type [0] Unsigned (0..15), -- 7 for this PDU Type
+ * reserved [1] Unsigned (0..3), -- must be set zero
+ * server [2] BOOLEAN,
+ * original-invokeID [3] Unsigned (0..255),
+ * abort-reason [4] BACnetAbortReason
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAbortPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * 20.2.4, adds the label with max 64Bit unsigned Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fUnsignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.5, adds the label with max 64Bit signed Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fSignedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.8, adds the label with Octet String to tree; if lvt == 0 then lvt = restOfFrame
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @param lvt length of String
+ * @return modified offset
+ */
+static guint
+fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt);
+
+/**
+ * 20.2.12, adds the label with Date Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fDate (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.13, adds the label with Time Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * 20.2.14, adds Object Identifier to tree
+ * use BIG ENDIAN: Bits 31..22 Object Type, Bits 21..0 Instance Number
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fObjectIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet-Confirmed-Service-Request ::= CHOICE {
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service_choice
+ * @return offset
+ */
+static guint
+fConfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
+
+/**
+ * BACnet-Confirmed-Service-ACK ::= CHOICE {
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service_choice
+ * @return offset
+ */
+static guint
+fConfirmedServiceAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
+
+/**
+ * AcknowledgeAlarm-Request ::= SEQUENCE {
+ * acknowledgingProcessIdentifier [0] Unsigned32,
+ * eventObjectIdentifier [1] BACnetObjectIdentifer,
+ * eventStateAcknowledge [2] BACnetEventState,
+ * timeStamp [3] BACnetTimeStamp,
+ * acknowledgementSource [4] Character String,
+ * timeOfAcknowledgement [5] BACnetTimeStamp
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAcknowledgeAlarmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedCOVNotification-Request ::= SEQUENCE {
+ * subscriberProcessIdentifier [0] Unsigned32,
+ * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
+ * monitoredObjectIdentifier [2] BACnetObjectIdentifer,
+ * timeRemaining [3] unsigned,
+ * listOfValues [4] SEQUENCE OF BACnetPropertyValues
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedEventNotification-Request ::= SEQUENCE {
+ * ProcessIdentifier [0] Unsigned32,
+ * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
+ * eventObjectIdentifier [2] BACnetObjectIdentifer,
+ * timeStamp [3] BACnetTimeStamp,
+ * notificationClass [4] unsigned,
+ * priority [5] unsigned8,
+ * eventType [6] BACnetEventType,
+ * messageText [7] CharacterString OPTIONAL,
+ * notifyType [8] BACnetNotifyType,
+ * ackRequired [9] BOOLEAN OPTIONAL,
+ * fromState [10] BACnetEventState OPTIONAL,
+ * toState [11] BACnetEventState,
+ * eventValues [12] BACnetNotificationParameters OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetAlarmSummary-ACK ::= SEQUENCE OF SEQUENCE {
+ * objectIdentifier BACnetObjectIdentifer,
+ * alarmState BACnetEventState,
+ * acknowledgedTransitions BACnetEventTransitionBits
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetAlarmSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEnrollmentSummary-Request ::= SEQUENCE {
+ * acknowledgmentFilter [0] ENUMERATED {
+ * all (0),
+ * acked (1),
+ * not-acked (2)
+ * },
+ * enrollmentFilter [1] BACnetRecipientProcess OPTIONAL,
+ * eventStateFilter [2] ENUMERATED {
+ * offnormal (0),
+ * fault (1),
+ * normal (2),
+ * all (3),
+ * active (4)
+ * },
+ * eventTypeFilter [3] BACnetEventType OPTIONAL,
+ * priorityFilter [4] SEQUENCE {
+ * minPriority [0] Unsigned8,
+ * maxPriority [1] Unsigned8
+ * } OPTIONAL,
+ * notificationClassFilter [5] Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEnrollmentSummaryRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEnrollmentSummary-ACK ::= SEQUENCE OF SEQUENCE {
+ * objectIdentifier BACnetObjectIdentifer,
+ * eventType BACnetEventType,
+ * eventState BACnetEventState,
+ * priority Unsigned8,
+ * notificationClass Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEnrollmentSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEventInformation-Request ::= SEQUENCE {
+ * lastReceivedObjectIdentifier [0] BACnetObjectIdentifer
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEventInformationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * GetEventInformation-ACK ::= SEQUENCE {
+ * listOfEventSummaries [0] listOfEventSummaries,
+ * moreEvents [1] BOOLEAN
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fGetEventInformationACK (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * LifeSafetyOperation-Request ::= SEQUENCE {
+ * requestingProcessIdentifier [0] Unsigned32
+ * requestingSource [1] CharacterString
+ * request [2] BACnetLifeSafetyOperation
+ * objectIdentifier [3] BACnetObjectIdentifier OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * SubscribeCOV-Request ::= SEQUENCE {
+ * subscriberProcessIdentifier [0] Unsigned32
+ * monitoredObjectIdentifier [1] BACnetObjectIdentifier
+ * issueConfirmedNotifications [2] BOOLEAN OPTIONAL
+ * lifetime [3] Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param label
+ * @param src
+ * @return modified offset
+ */
+static guint
+fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SubscribeCOVProperty-Request ::= SEQUENCE {
+ * subscriberProcessIdentifier [0] Unsigned32
+ * monitoredObjectIdentifier [1] BACnetObjectIdentifier
+ * issueConfirmedNotifications [2] BOOLEAN OPTIONAL
+ * lifetime [3] Unsigned OPTIONAL
+ * monitoredPropertyIdentifier [4] BACnetPropertyReference OPTIONAL
+ * covIncrement [5] Unsigned OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicReadFile-Request ::= SEQUENCE {
+ * fileIdentifier BACnetObjectIdentifier,
+ * accessMethod CHOICE {
+ * streamAccess [0] SEQUENCE {
+ * fileStartPosition INTEGER,
+ * requestedOctetCount Unsigned
+ * },
+ * recordAccess [1] SEQUENCE {
+ * fileStartRecord INTEGER,
+ * requestedRecordCount Unsigned
+ * }
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicWriteFile-ACK ::= SEQUENCE {
+ * endOfFile BOOLEAN,
+ * accessMethod CHOICE {
+ * streamAccess [0] SEQUENCE {
+ * fileStartPosition INTEGER,
+ * fileData OCTET STRING
+ * },
+ * recordAccess [1] SEQUENCE {
+ * fileStartRecord INTEGER,
+ * returnedRecordCount Unsigned,
+ * fileRecordData SEQUENCE OF OCTET STRING
+ * }
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicReadFileAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicWriteFile-Request ::= SEQUENCE {
+ * fileIdentifier BACnetObjectIdentifier,
+ * accessMethod CHOICE {
+ * streamAccess [0] SEQUENCE {
+ * fileStartPosition INTEGER,
+ * fileData OCTET STRING
+ * },
+ * recordAccess [1] SEQUENCE {
+ * fileStartRecord INTEGER,
+ * recordCount Unsigned,
+ * fileRecordData SEQUENCE OF OCTET STRING
+ * }
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * AtomicWriteFile-ACK ::= SEQUENCE {
+ * fileStartPosition [0] INTEGER,
+ * fileStartRecord [1] INTEGER,
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * AddListElement-Request ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * listOfElements [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * CreateObject-Request ::= SEQUENCE {
+ * objectSpecifier [0] ObjectSpecifier,
+ * listOfInitialValues [1] SEQUENCE OF BACnetPropertyValue OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * CreateObject-Request ::= BACnetObjectIdentifier
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCreateObjectAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * DeleteObject-Request ::= SEQUENCE {
+ * ObjectIdentifier BACnetObjectIdentifer
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadProperty-Request ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadProperty-ACK ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * propertyValue [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadPropertyConditional-Request ::= SEQUENCE {
+ * objectSelectionCriteria [0] objectSelectionCriteria,
+ * listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * ReadPropertyConditional-ACK ::= SEQUENCE {
+ * listOfPReadAccessResults SEQUENCE OF ReadAccessResult OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadPropertyConditionalAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadPropertyMultiple-Request ::= SEQUENCE {
+ * listOfReadAccessSpecs SEQUENCE OF ReadAccessSpecification
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return offset modified
+ */
+static guint
+fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * ReadPropertyMultiple-Ack ::= SEQUENCE {
+ * listOfReadAccessResults SEQUENCE OF ReadAccessResult
+ * }
+ * @param tvb
+ * @parma pinfo
+ * @param tree
+ * @param offset
+ * @return offset modified
+ */
+static guint
+fReadPropertyMultipleAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadRange-Request ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * range CHOICE {
+ * byPosition [3] SEQUENCE {
+ * referencedIndex Unsigned,
+ * count INTEGER
+ * },
+ * byTime [4] SEQUENCE {
+ * referenceTime BACnetDateTime,
+ * count INTEGER
+ * },
+ * timeRange [5] SEQUENCE {
+ * beginningTime BACnetDateTime,
+ * endingTime BACnetDateTime
+ * },
+ * } OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadRangeRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadRange-ACK ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * resultFlags [3] BACnetResultFlags,
+ * itemCount [4] Unsigned,
+ * itemData [5] SEQUENCE OF ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadRangeAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * RemoveListElement-Request ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * listOfElements [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * WriteProperty-Request ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * propertyValue [3] ABSTRACT-SYNTAX.&Type
+ * priority [4] Unsigned8 (1..16) OPTIONAL --used only when property is commandable
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * WritePropertyMultiple-Request ::= SEQUENCE {
+ * listOfWriteAccessSpecifications SEQUENCE OF WriteAccessSpecification
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * DeviceCommunicationControl-Request ::= SEQUENCE {
+ * timeDuration [0] Unsigned16 OPTIONAL,
+ * enable-disable [1] ENUMERATED {
+ * enable (0),
+ * disable (1)
+ * },
+ * password [2] CharacterString (SIZE(1..20)) OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeviceCommunicationControlRequest(tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedPrivateTransfer-Request ::= SEQUENCE {
+ * vendorID [0] Unsigned,
+ * serviceNumber [1] Unsigned,
+ * serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedPrivateTransfer-ACK ::= SEQUENCE {
+ * vendorID [0] Unsigned,
+ * serviceNumber [1] Unsigned,
+ * resultBlock [2] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedTextMessage-Request ::= SEQUENCE {
+ * textMessageSourceDevice [0] BACnetObjectIdentifier,
+ * messageClass [1] CHOICE {
+ * numeric [0] Unsigned,
+ * character [1] CharacterString
+ * } OPTIONAL,
+ * messagePriority [2] ENUMERATED {
+ * normal (0),
+ * urgent (1)
+ * },
+ * message [3] CharacterString
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReinitializeDevice-Request ::= SEQUENCE {
+ * reinitializedStateOfDevice [0] ENUMERATED {
+ * coldstart (0),
+ * warmstart (1),
+ * startbackup (2),
+ * endbackup (3),
+ * startrestore (4),
+ * endrestore (5),
+ * abortrestor (6)
+ * },
+ * password [1] CharacterString (SIZE(1..20)) OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReinitializeDeviceRequest(tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * VTOpen-Request ::= SEQUENCE {
+ * vtClass BACnetVTClass,
+ * localVTSessionIdentifier Unsigned8
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTOpen-ACK ::= SEQUENCE {
+ * remoteVTSessionIdentifier Unsigned8
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtOpenAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTClose-Request ::= SEQUENCE {
+ * listOfRemoteVTSessionIdentifiers SEQUENCE OF Unsigned8
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtCloseRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTData-Request ::= SEQUENCE {
+ * vtSessionIdentifier Unsigned8,
+ * vtNewData OCTET STRING,
+ * vtDataFlag Unsigned (0..1)
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtDataRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTData-ACK ::= SEQUENCE {
+ * allNewDataAccepted [0] BOOLEAN,
+ * acceptedOctetCount [1] Unsigned OPTIONAL -- present only if allNewDataAccepted = FALSE
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVtDataAck (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * Authenticate-Request ::= SEQUENCE {
+ * pseudoRandomNumber [0] Unsigned32,
+ * excpectedInvokeID [1] Unsigned8 OPTIONAL,
+ * operatorName [2] CharacterString OPTIONAL,
+ * operatorPassword [3] CharacterString (SIZE(1..20)) OPTIONAL,
+ * startEncypheredSession [4] BOOLEAN OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAuthenticateRequest (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * Authenticate-ACK ::= SEQUENCE {
+ * modifiedRandomNumber Unsigned32,
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAuthenticateAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * RequestKey-Request ::= SEQUENCE {
+ * requestingDeviceIdentifier BACnetObjectIdentifier,
+ * requestingDeviceAddress BACnetAddress,
+ * remoteDeviceIdentifier BACnetObjectIdentifier,
+ * remoteDeviceAddress BACnetAddress
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRequestKeyRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Unconfirmed-Service-Request ::= CHOICE {
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service_choice
+ * @return modified offset
+ */
+static guint
+fUnconfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice);
+
+/**
+ * UnconfirmedCOVNotification-Request ::= SEQUENCE {
+ * subscriberProcessIdentifier [0] Unsigned32,
+ * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
+ * monitoredObjectIdentifier [2] BACnetObjectIdentifer,
+ * timeRemaining [3] unsigned,
+ * listOfValues [4] SEQUENCE OF BACnetPropertyValues
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * UnconfirmedEventNotification-Request ::= SEQUENCE {
+ * ProcessIdentifier [0] Unsigned32,
+ * initiatingDeviceIdentifier [1] BACnetObjectIdentifer,
+ * eventObjectIdentifier [2] BACnetObjectIdentifer,
+ * timeStamp [3] BACnetTimeStamp,
+ * notificationClass [4] unsigned,
+ * priority [5] unsigned8,
+ * eventType [6] BACnetEventType,
+ * messageText [7] CharacterString OPTIONAL,
+ * notifyType [8] BACnetNotifyType,
+ * ackRequired [9] BOOLEAN OPTIONAL,
+ * fromState [10] BACnetEventState OPTIONAL,
+ * toState [11] BACnetEventState,
+ * eventValues [12] BACnetNotificationParameters OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * I-Am-Request ::= SEQUENCE {
+ * aAmDeviceIdentifier BACnetObjectIdentifier,
+ * maxAPDULengthAccepted Unsigned,
+ * segmentationSupported BACnetSegmentation,
+ * vendorID Unsigned
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fIAmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+/**
+ * I-Have-Request ::= SEQUENCE {
+ * deviceIdentifier BACnetObjectIdentifier,
+ * objectIdentifier BACnetObjectIdentifier,
+ * objectName CharacterString
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fIHaveRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * UnconfirmedPrivateTransfer-Request ::= SEQUENCE {
+ * vendorID [0] Unsigned,
+ * serviceNumber [1] Unsigned,
+ * serviceParameters [2] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * UnconfirmedTextMessage-Request ::= SEQUENCE {
+ * textMessageSourceDevice [0] BACnetObjectIdentifier,
+ * messageClass [1] CHOICE {
+ * numeric [0] Unsigned,
+ * character [1] CharacterString
+ * } OPTIONAL,
+ * messagePriority [2] ENUMERATED {
+ * normal (0),
+ * urgent (1)
+ * },
+ * message [3] CharacterString
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * TimeSynchronization-Request ::= SEQUENCE {
+ * BACnetDateTime
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * UTCTimeSynchronization-Request ::= SEQUENCE {
+ * BACnetDateTime
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fUTCTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * Who-Has-Request ::= SEQUENCE {
+ * limits SEQUENCE {
+ * deviceInstanceRangeLowLimit [0] Unsigned (0..4194303),
+ * deviceInstanceRangeHighLimit [1] Unsigned (0..4194303)
+ * } OPTIONAL,
+ * object CHOICE {
+ * objectIdentifier [2] BACnetObjectIdentifier,
+ * objectName [3] CharacterString
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWhoHas (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Who-Is-Request ::= SEQUENCE {
+ * deviceInstanceRangeLowLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
+ * deviceInstanceRangeHighLimit [0] Unsigned (0..4194303) OPTIONAL, -- must be used as a pair, see 16.9,
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWhoIsRequest (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnet-Error ::= CHOICE {
+ * addListElement [8] ChangeList-Error,
+ * removeListElement [9] ChangeList-Error,
+ * writePropertyMultiple [16] WritePropertyMultiple-Error,
+ * confirmedPrivatTransfer [18] ConfirmedPrivateTransfer-Error,
+ * vtClose [22] VTClose-Error,
+ * readRange [26] ObjectAccessService-Error
+ * [default] Error
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param service
+ * @return modified offset
+ */
+static guint
+fBACnetError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service);
+
+/**
+ * Dissect a BACnetError in a context tag
+ *
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ChangeList-Error ::= SEQUENCE {
+ * errorType [0] Error,
+ * firstFailedElementNumber [1] Unsigned
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * CreateObject-Error ::= SEQUENCE {
+ * errorType [0] Error,
+ * firstFailedElementNumber [1] Unsigned
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ConfirmedPrivateTransfer-Error ::= SEQUENCE {
+ * errorType [0] Error,
+ * vendorID [1] Unsigned,
+ * serviceNumber [2] Unsigned,
+ * errorParameters [3] ABSTRACT-SYNTAX.&Type OPTIONAL
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * WritePropertyMultiple-Error ::= SEQUENCE {
+ * errorType [0] Error,
+ * firstFailedWriteAttempt [1] Unsigned
+ * }
+ * }
+ * @param tvb
+ * @pram pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * VTClose-Error ::= SEQUENCE {
+ * errorType [0] Error,
+ * listOfVTSessionIdentifiers [1] SEQUENCE OF Unsigned8 OPTIONAL
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet Application Types chapter 20.2.1
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fApplicationTypes (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnetActionCommand ::= SEQUENCE {
+ * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
+ * objectIdentifier [1] BACnetObjectIdentifier,
+ * propertyIdentifier [2] BACnetPropertyIdentifier,
+ * propertyArrayIndex [3] Unsigned OPTIONAL, -- used only with array datatype
+ * propertyValue [4] ABSTRACT-SYNTAX.&Type,
+ * priority [5] Unsigned (1..16) OPTIONAL, -- used only when property is commandable
+ * postDelay [6] Unsigned OPTIONAL,
+ * quitOnFailure [7] BOOLEAN,
+ * writeSuccessful [8] BOOLEAN
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param matching tag number
+ * @return modified offset
+ */
+static guint
+fActionCommand (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match);
+
+/**
+ * BACnetActionList ::= SEQUENCE {
+ * action [0] SEQUENCE of BACnetActionCommand
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fActionList (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/** BACnetAddress ::= SEQUENCE {
+ * network-number Unsigned16, -- A value 0 indicates the local network
+ * mac-address OCTET STRING -- A string of length 0 indicates a broadcast
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAddress (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnetAddressBinding ::= SEQUENCE {
+ * deviceObjectID BACnetObjectIdentifier
+ * deviceAddress BacnetAddress
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fAddressBinding (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetCalendaryEntry ::= CHOICE {
+ * date [0] Date,
+ * dateRange [1] BACnetDateRange,
+ * weekNDay [2] BacnetWeekNday
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnetClientCOV ::= CHOICE {
+ * real-increment REAL,
+ * default-increment NULL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fClientCOV (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+/**
+ * BACnetDailySchedule ::= SEQUENCE {
+ * day-schedule [0] SENQUENCE OF BACnetTimeValue
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDailySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetWeeklySchedule ::= SEQUENCE {
+ * week-schedule SENQUENCE SIZE (7) OF BACnetDailySchedule
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWeeklySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDateRange ::= SEQUENCE {
+ * StartDate Date,
+ * EndDate Date
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDateRange (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDateTime ::= SEQUENCE {
+ * date Date,
+ * time Time
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fDateTime (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnetDestination ::= SEQUENCE {
+ * validDays BACnetDaysOfWeek,
+ * fromTime Time,
+ * toTime Time,
+ * recipient BACnetRecipient,
+ * processIdentifier Unsigned32,
+ * issueConfirmedNotifications BOOLEAN,
+ * transitions BACnetEventTransitionBits
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDestination (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDeviceObjectPropertyReference ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigend OPTIONAL,
+ * deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeviceObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetDeviceObjectReference ::= SEQUENCE {
+ * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
+ * objectIdentifier [1] BACnetObjectIdentifier
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fDeviceObjectReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetEventParameter ::= CHOICE {
+ * change-of-bitstring [0] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * bitmask [1] BIT STRING,
+ * list-of-bitstring-values [2] SEQUENCE OF BIT STRING
+ * },
+ * change-of-state [1] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * list-of-values [1] SEQUENCE OF BACnetPropertyStates
+ * },
+ * change-of-value [2] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * cov-criteria [1] CHOICE {
+ * bitmask [0] BIT STRING,
+ * referenced-property-increment [1] REAL
+ * }
+ * },
+ * command-failure [3] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * feedback-property-reference [1] BACnetDeviceObjectPropertyReference
+ * },
+ * floating-limit [4] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * setpoint-reference [1] BACnetDeviceObjectPropertyReference,
+ * low-diff-limit [2] REAL,
+ * high-diff-limit [3] REAL,
+ * deadband [4] REAL
+ * },
+ * out-of-range [5] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * low-limit [1] REAL,
+ * high-limit [2] REAL,
+ * deadband [3] REAL
+ * },
+ * buffer-ready [7] SEQUENCE {
+ * notification-threshold [0] Unsigned,
+ * previous-notification-count [1] Unsigned32
+ * }
+ * change-of-life-safety [8] SEQUENCE {
+ * time-delay [0] Unsigned,
+ * list-of-life-safety-alarm-values [1] SEQUENCE OF BACnetLifeSafetyState,
+ * list-of-alarm-values [2] SEQUENCE OF BACnetLifeSafetyState,
+ * mode-property-reference [3] BACnetDeviceObjectPropertyReference
+ * }
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fEventParameter (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+
+
+/**
+ * BACnetLogRecord ::= SEQUENCE {
+ * timestamp [0] BACnetDateTime,
+ * logDatum [1] CHOICE {
+ * log-status [0] BACnetLogStatus,
+ * boolean-value [1] BOOLEAN,
+ * real-value [2] REAL,
+ * enum-value [3] ENUMERATED, -- Optionally limited to 32 bits
+ * unsigned-value [4] Unsigned, -- Optionally limited to 32 bits
+ * signed-value [5] INTEGER, -- Optionally limited to 32 bits
+ * bitstring-value [6] BIT STRING,-- Optionally limited to 32 bits
+ * null-value [7] NULL,
+ * failure [8] Error,
+ * time-change [9] REAL,
+ * any-value [10] ABSTRACT-SYNTAX.&Type -- Optional
+ * }
+ * statusFlags [2] BACnetStatusFlags OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fLogRecord (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+/**
+ * BACnetNotificationParameters ::= CHOICE {
+ * change-of-bitstring [0] SEQUENCE {
+ * referenced-bitstring [0] BIT STRING,
+ * status-flags [1] BACnetStatusFlags
+ * },
+ * change-of-state [1] SEQUENCE {
+ * new-state [0] BACnetPropertyStatus,
+ * status-flags [1] BACnetStatusFlags
+ * },
+ * change-of-value [2] SEQUENCE {
+ * new-value [0] CHOICE {
+ * changed-bits [0] BIT STRING,
+ * changed-value [1] REAL
+ * },
+ * status-flags [1] BACnetStatusFlags
+ * },
+ * command-failure [3] SEQUENCE {
+ * command-value [0] ABSTRACT-SYNTAX.&Type, -- depends on ref property
+ * status-flags [1] BACnetStatusFlags
+ * feedback-value [2] ABSTRACT-SYNTAX.&Type -- depends on ref property
+ * },
+ * floating-limit [4] SEQUENCE {
+ * reference-value [0] REAL,
+ * status-flags [1] BACnetStatusFlags
+ * setpoint-value [2] REAL,
+ * error-limit [3] REAL
+ * },
+ * out-of-range [5] SEQUENCE {
+ * exceeding-value [0] REAL,
+ * status-flags [1] BACnetStatusFlags
+ * deadband [2] REAL,
+ * exceeded-limit [0] REAL
+ * },
+ * complex-event-type [6] SEQUENCE OF BACnetPropertyValue,
+ * buffer-ready [7] SEQUENCE {
+ * buffer-device [0] BACnetObjectIdentifier,
+ * buffer-object [1] BACnetObjectIdentifier
+ * previous-notification [2] BACnetDateTime,
+ * current-notification [3] BACnetDateTime
+ * },
+ * change-of-life-safety [8] SEQUENCE {
+ * new-state [0] BACnetLifeSafetyState,
+ * new-mode [1] BACnetLifeSafetyState
+ * status-flags [2] BACnetStatusFlags,
+ * operation-expected [3] BACnetLifeSafetyOperation
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fNotificationParameters (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetObjectPropertyReference ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetObjectPropertyValue ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * propertyIdentifier [1] BACnetPropertyIdentifier,
+ * propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ * -- if omitted with an array the entire array is referenced
+ * value [3] ABSTRACT-SYNTAX.&Type, --any datatype appropriate for the specified property
+ * priority [4] Unsigned (1..16) OPTIONAL
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fObjectPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+/**
+ * BACnetPriorityArray ::= SEQUENCE SIZE (16) OF BACnetPriorityValue
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fPriorityArray (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+static guint
+fPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list);
+
+/**
+ * BACnetPropertyReference ::= SEQUENCE {
+ * propertyIdentifier [0] BACnetPropertyIdentifier,
+ * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fBACnetPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list);
+
+/* static guint
+fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset); */
+
+static guint
+fLOPR (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+static guint
+fRestartReason (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetPropertyValue ::= SEQUENCE {
+ * PropertyIdentifier [0] BACnetPropertyIdentifier,
+ * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatypes
+ * -- if omitted with an array the entire array is referenced
+ * value [2] ABSTRACT-SYNTAX.&Type, -- any datatype appropriate for the specified property
+ * priority [3] Unsigned (1..16) OPTIONAL -- used only when property is commandable
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fBACnetPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+static guint
+fPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetRecipient::= CHOICE {
+ * device [0] BACnetObjectIdentifier
+ * address [1] BACnetAddress
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRecipient (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetRecipientProcess::= SEQUENCE {
+ * recipient [0] BACnetRecipient
+ * processID [1] Unsigned32
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fRecipientProcess (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetSessionKey ::= SEQUENCE {
+ * sessionKey OCTET STRING (SIZE(8)), -- 56 bits for key, 8 bits for checksum
+ * peerAddress BACnetAddress
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ * @todo check if checksum is displayed correctly
+ */
+static guint
+fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+/**
+ * BACnetSpecialEvent ::= SEQUENCE {
+ * period CHOICE {
+ * calendarEntry [0] BACnetCalendarEntry,
+ * calendarRefernce [1] BACnetObjectIdentifier
+ * },
+ * listOfTimeValues [2] SEQUENCE OF BACnetTimeValue,
+ * eventPriority [3] Unsigned (1..16)
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSpecialEvent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnetTimeStamp ::= CHOICE {
+ * time [0] Time,
+ * sequenceNumber [1] Unsigned (0..65535),
+ * dateTime [2] BACnetDateTime
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param label
+ * @return modified offset
+ */
+static guint
+fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnetTimeValue ::= SEQUENCE {
+ * time Time,
+ * value ABSTRACT-SYNTAX.&Type -- any primitive datatype, complex types cannot be decoded
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fTimeValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+#if 0
+/**
+ * BACnetVTSession ::= SEQUENCE {
+ * local-vtSessionID Unsigned8,
+ * remote-vtSessionID Unsigned8,
+ * remote-vtAddress BACnetAddress
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fVTSession (tvbuff_t *tvb, proto_tree *tree, guint offset);
+#endif
+
+/**
+ * BACnetWeekNDay ::= OCTET STRING (SIZE (3))
+ * -- first octet month (1..12) January = 1, X'FF' = any month
+ * -- second octet weekOfMonth where: 1 = days numbered 1-7
+ * -- 2 = days numbered 8-14
+ * -- 3 = days numbered 15-21
+ * -- 4 = days numbered 22-28
+ * -- 5 = days numbered 29-31
+ * -- 6 = last 7 days of this month
+ * -- X'FF' = any week of this month
+ * -- third octet dayOfWeek (1..7) where 1 = Monday
+ * -- 7 = Sunday
+ * -- X'FF' = any day of week
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWeekNDay (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * ReadAccessResult ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * listOfResults [1] SEQUENCE OF SEQUENCE {
+ * propertyIdentifier [2] BACnetPropertyIdentifier,
+ * propertyArrayIndex [3] Unsigned OPTIONAL, -- used only with array datatype if omitted with an array the entire array is referenced
+ * readResult CHOICE {
+ * propertyValue [4] ABSTRACT-SYNTAX.&Type,
+ * propertyAccessError [5] Error
+ * }
+ * } OPTIONAL
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadAccessResult (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * ReadAccessSpecification ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * listOfPropertyReferences [1] SEQUENCE OF BACnetPropertyReference
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fReadAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * WriteAccessSpecification ::= SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * listOfProperty [1] SEQUENCE OF BACnetPropertyValue
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fWriteAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+
+/********************************************************* Helper functions *******************************************/
+
+/**
+ * extracts the tag number from the tag header.
+ * @param tvb "TestyVirtualBuffer"
+ * @param offset in actual tvb
+ * @return Tag Number corresponding to BACnet 20.2.1.2 Tag Number
+ */
+static guint
+fTagNo (tvbuff_t *tvb, guint offset);
+
+/**
+ * splits Tag Header coresponding to 20.2.1 General Rules For BACnet Tags
+ * @param tvb = "TestyVirtualBuffer"
+ * @param offset = offset in actual tvb
+ * @return tag_no BACnet 20.2.1.2 Tag Number
+ * @return class_tag BACnet 20.2.1.1 Class
+ * @return lvt BACnet 20.2.1.3 Length/Value/Type
+ * @return offs = length of this header
+ */
+
+static guint
+fTagHeader (tvbuff_t *tvb, guint offset, guint8 *tag_no, guint8* class_tag, guint32 *lvt);
+
+
+/**
+ * adds processID with max 32Bit unsigned Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fProcessId (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * adds timeSpan with max 32Bit unsigned Integer Value to tree
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fTimeSpan (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetPropertyIdentifier::= ENUMERATED {
+ * @see bacapp_property_identifier
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @param tt returnvalue of this item
+ * @return modified offset
+ */
+static guint
+fPropertyIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * BACnet Application PDUs chapter 21
+ * BACnetPropertyArrayIndex::= ENUMERATED {
+ * @see bacapp_property_array_index
+ * }
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @param tt returnvalue of this item
+ * @return modified offset
+ */
+static guint
+fPropertyArrayIndex (tvbuff_t *tvb, proto_tree *tree, guint offset);
+
+/**
+ * listOfEventSummaries ::= SEQUENCE OF SEQUENCE {
+ * objectIdentifier [0] BACnetObjectIdentifier,
+ * eventState [1] BACnetEventState,
+ * acknowledgedTransitions [2] BACnetEventTransitionBits,
+ * eventTimeStamps [3] SEQURNCE SIZE (3) OF BACnetTimeStamps,
+ * notifyType [4] BACnetNotifyType,
+ * eventEnable [5] BACnetEventTransitionBits,
+ * eventPriorities [6] SEQUENCE SIZE (3) OF Unsigned
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+flistOfEventSummaries (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * SelectionCriteria ::= SEQUENCE {
+ * propertyIdentifier [0] BACnetPropertyIdentifier,
+ * propertyArrayIndex [1] Unsigned OPTIONAL, -- used only with array datatype
+ * relationSpecifier [2] ENUMERATED { bacapp_relationSpecifier },
+ * comparisonValue [3] ABSTRACT-SYNTAX.&Type
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * objectSelectionCriteria ::= SEQUENCE {
+ * selectionLogic [0] ENUMERATED { bacapp_selectionLogic },
+ * listOfSelectionCriteria [1] SelectionCriteria
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fObjectSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset);
+
+/**
+ * BACnet-Error ::= SEQUENCE {
+ * error-class ENUMERATED {},
+ * error-code ENUMERATED {}
+ * }
+ * }
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ */
+static guint
+fError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+/**
+ * Generic handler for context tagged values. Mostly for handling
+ * vendor-defined properties and services.
+ * @param tvb
+ * @param tree
+ * @param offset
+ * @return modified offset
+ * @todo beautify this ugly construct
+ */
+static guint
+fContextTaggedValue(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label);
+
+/**
+ * realizes some ABSTRACT-SYNTAX.&Type
+ * @param tvb
+ * @param pinfo
+ * @param tree
+ * @param offset
+ * @return modified offset
+ * @todo beautify this ugly construct
+ */
+static guint
+fAbstractSyntaxNType (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset);
+
+
+static guint
+fBitStringTagVS (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
+ const value_string *src);
+
+/**
+ * register_bacapp
+ */
+void
+proto_register_bacapp(void);
+
+/**
+ * proto_reg_handoff_bacapp
+ */
+void
+proto_reg_handoff_bacapp(void);
+
+/**
+ * converts XXX coded strings to UTF-8
+ * else 'in' is copied to 'out'
+ * @param in -- pointer to string
+ * @param inbytesleft
+ * @param out -- pointer to string
+ * @param outbytesleft
+ * @param fromcoding
+ * @return count of modified characters of returned string, -1 for errors
+ */
+static guint32
+fConvertXXXtoUTF8(gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding);
+
+static void
+uni_to_string(char * data, gsize str_length, char *dest_buf);
+
+/* <<<< formerly bacapp.h */
+
+/* some hashes for segmented messages */
+static GHashTable *msg_fragment_table = NULL;
+static GHashTable *msg_reassembled_table = NULL;
/* some necessary forward function prototypes */
static guint
-fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset,
+fApplicationTypesEnumerated (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
const gchar *label, const value_string *vs);
static const char *bacapp_unknown_service_str = "unknown service";
static const value_string
BACnetTypeName[] = {
- {0, "Confirmed-Request "},
- {1, "Unconfirmed-Request "},
- {2, "SimpleACK "},
- {3, "ComplexACK "},
- {4, "SegmentACK "},
- {5, "Error "},
- {6, "Reject "},
- {7, "Abort "},
+ {0, "Confirmed-REQ"},
+ {1, "Unconfirmed-REQ"},
+ {2, "Simple-ACK"},
+ {3, "Complex-ACK"},
+ {4, "Segment-ACK"},
+ {5, "Error"},
+ {6, "Reject"},
+ {7, "Abort"},
{0, NULL }
};
{0,NULL}
};
+static const value_string
+BACnetRestartReason [] = {
+ {0,"unknown"},
+ {1,"coldstart"},
+ {2,"warmstart"},
+ {3,"detected-power-lost"},
+ {4,"detected-powered-off"},
+ {5,"hardware-watchdog"},
+ {6,"software-watchdog"},
+ {7,"suspended"},
+ {0,NULL}
+};
+
static const value_string
BACnetApplicationTagNumber [] = {
{0,"Null"},
{0,NULL}
};
+/* For some reason, BACnet defines the choice parameter
+ in the file read and write services backwards from the
+ BACnetFileAccessMethod enumeration.
+*/
+static const value_string
+BACnetFileAccessOption [] = {
+ {0,"stream access"},
+ {1,"record access"},
+ {0,NULL}
+};
+
+static const value_string
+BACnetFileStartOption [] = {
+ {0, "File Start Position: "},
+ {1, "File Start Record: "},
+ {0, NULL}
+};
+
+static const value_string
+BACnetFileRequestCount [] = {
+ {0, "Requested Octet Count: "},
+ {1, "Requested Record Count: "},
+ {0, NULL}
+};
+
+static const value_string
+BACnetFileWriteInfo [] = {
+ {0, "File Data: "},
+ {1, "Record Count: "},
+ {0, NULL}
+};
+
static const value_string
BACnetAbortReason [] = {
{0,"other"},
{8,"unsilence-audible"},
{9,"unsilence-visual"},
{0,NULL}
-/* Enumerated values 0-63 are reserved for definition by ASHRAE.
- Enumerated values 64-65535 may be used by others subject to
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+ Enumerated values 64-65535 may be used by others subject to
procedures and constraints described in Clause 23. */
};
{22,"supervisory"},
{23,"test-supervisory"},
{0,NULL}
-/* Enumerated values 0-255 are reserved for definition by ASHRAE.
- Enumerated values 256-65535 may be used by others subject to
+/* Enumerated values 0-255 are reserved for definition by ASHRAE.
+ Enumerated values 256-65535 may be used by others subject to
procedures and constraints described in Clause 23. */
};
static const value_string
BACnetObjectType [] = {
- {0,"analog-input object"},
- {1,"analog-output object"},
- {2,"analog-value object"},
- {3,"binary-input object"},
- {4,"binary-output object"},
- {5,"binary-value object"},
- {6,"calendar object"},
- {7,"command object"},
- {8,"device object"},
- {9,"event-enrollment object"},
- {10,"file object"},
- {11,"group object"},
- {12,"loop object"},
- {13,"multi-state-input object"},
- {14,"multi-state-output object"},
- {15,"notification-class object"},
- {16,"program object"},
- {17,"schedule object"},
- {18,"averaging object"},
- {19,"multi-state-value object"},
- {20,"trend-log object"},
- {21,"life-safety-point object"},
- {22,"life-safety-zone object"},
- {23,"accumulator object"},
- {24,"pulse-converter object"},
+ {0,"analog-input"},
+ {1,"analog-output"},
+ {2,"analog-value"},
+ {3,"binary-input"},
+ {4,"binary-output"},
+ {5,"binary-value"},
+ {6,"calendar"},
+ {7,"command"},
+ {8,"device"},
+ {9,"event-enrollment"},
+ {10,"file"},
+ {11,"group"},
+ {12,"loop"},
+ {13,"multi-state-input"},
+ {14,"multi-state-output"},
+ {15,"notification-class"},
+ {16,"program"},
+ {17,"schedule"},
+ {18,"averaging"},
+ {19,"multi-state-value"},
+ {20,"trend-log"},
+ {21,"life-safety-point"},
+ {22,"life-safety-zone"},
+ {23,"accumulator"},
+ {24,"pulse-converter"},
+ {25,"event-log"},
+ {26,"global-group"},
+ {27,"trend-log-multiple"},
+ {28,"load-control"},
+ {29,"structured-view"},
+ {30,"access-door"}, /* 30-37 added with addanda 135-2008j */
+ {32,"access-credential"},
+ {33,"access-point"},
+ {34,"access-rights"},
+ {35,"access-user"},
+ {36,"access-zone"},
+ {37,"credential-data-input"},
+ {39,"bitstring-value"}, /* 39-50 added with addenda 135-2008w */
+ {40,"characterstring-value"},
+ {41,"date-pattern-value"},
+ {42,"date-value"},
+ {43,"datetime-pattern-value"},
+ {44,"datetime-value"},
+ {45,"integer-value"},
+ {46,"large-analog-value"},
+ {47,"octetstring-value"},
+ {48,"positive-Integer-value"},
+ {49,"time-pattern-value"},
+ {50,"time-value"},
{0, NULL}
/* Enumerated values 0-127 are reserved for definition by ASHRAE.
Enumerated values 128-1023 may be used by others subject to
{10,"Megavolt Amperes"},
{11,"Volt Amperes Reactive"},
{12,"Kilovolt Amperes Reactive"},
- {13,"Megavolt Amperes Ractive"},
+ {13,"Megavolt Amperes Reactive"},
{14,"Degrees Phase"},
{15,"Power Factor"},
{16,"Joules"},
{25,"Cycles Per Hour"},
{26,"Cycles Per Minute"},
{27,"Hertz"},
- {28,"Gramms Of Water Per Kilogram Dry Air"},
+ {28,"Grams Of Water Per Kilogram Dry Air"},
{29,"Relative Humidity"},
{30,"Millimeters"},
{31,"Meters"},
{35,"Watts Per Sq meter"},
{36,"Lumens"},
{37,"Lux"},
- {38,"Foot Candels"},
+ {38,"Foot Candles"},
{39,"Kilograms"},
{40,"Pounds Mass"},
{41,"Tons"},
{60,"Centimeters Of Mercury"},
{61,"Inches Of Mercury"},
{62,"Degrees Celsius"},
- {63,"Degress Kelvin"},
+ {63,"Degrees Kelvin"},
{64,"Degrees Fahrenheit"},
{65,"Degree Days Celsius"},
{66,"Degree Days Fahrenheit"},
{188,"newtons-per-meter"},
{189,"watts-per-meter-per-degree-Kelvin"},
{0,NULL}
-/* Enumerated values 0-255 are reserved for definition by ASHRAE.
- Enumerated values 256-65535 may be used by others subject to
+/* Enumerated values 0-255 are reserved for definition by ASHRAE.
+ Enumerated values 256-65535 may be used by others subject to
the procedures and constraints described in Clause 23. */
};
BACnetErrorCode [] = {
{0,"other"},
{1,"authentication-failed"},
- {2,"character-set-not-supported"},
- {3,"configuration-in-progress"},
- {4,"device-busy"},
+ {2,"configuration-in-progress"},
+ {3,"device-busy"},
+ {4,"dynamic-creation-not-supported"},
{5,"file-access-denied"},
{6,"incompatible-security-levels"},
{7,"inconsistent-parameters"},
{42,"invalid-array-index"},
{43,"cov-subscription-failed"},
{44,"not-cov-property"},
- {45,"optional-functionaltity-not-supported"},
+ {45,"optional-functionality-not-supported"},
{46,"invalid-configuration-data"},
{47,"datatype-not-supported"},
{48,"duplicate-name"},
{49,"duplicate-object-id"},
{50,"property-is-not-an-array"},
+ {73,"invalid-event-state"},
+ {74,"no-alarm-configured"},
{0, NULL}
-/* Enumerated values 0-255 are reserved for definition by ASHRAE.
- Enumerated values 256-65535 may be used by others subject to the
+/* Enumerated values 0-255 are reserved for definition by ASHRAE.
+ Enumerated values 256-65535 may be used by others subject to the
procedures and constraints described in Clause 23. */
};
{130,"event-time-stamp"},
{131,"log-buffer"},
{132,"log-device-object-property"},
- {133,"log-enable"},
+ {133,"enable"}, /* per ANSI/ASHRAE 135-2004 addendum B */
{134,"log-interval"},
{135,"maximum-value"},
{136,"minimum-value"},
{170,"manual-slave-address-binding"},
{171,"slave-address-binding"},
{172,"slave-proxy-enable"},
- {173,"last-notify-time"},
+ {173,"last-notify-record"}, /* bug 4117 */
{174,"schedule-default"},
{175,"accepted-modes"},
{176,"adjust-value"},
{190,"value-before-change"},
{191,"value-set"},
{192,"value-change-time"},
+ {193,"align-intervals"},
+ {194,"group-member-names"},
+ {195,"interval-offset"},
+ {196,"last-restart-reason"},
+ {197,"logging-type"},
+ {198,"member-status-flags"},
+ {199,"notification-period"},
+ {200,"previous-notify-record"},
+ {201,"requested-update-interval"},
+ {202,"restart-notification-recipients"},
+ {203,"time-of-device-restart"},
+ {204,"time-synchronization-recipients"},
+ {205,"trigger"},
+ {206,"UTC-time-synchronization-recipients"},
+ {207,"node-subtype"},
+ {208,"node-type"},
+ {209,"structured-object-list"},
+ {210,"subordinate-annotations"},
+ {211,"subordinate-list"},
+ {212,"actual-shed-level"},
+ {213,"duty-window"},
+ {214,"expected-shed-level"},
+ {215,"full-duty-baseline"},
+ {216,"node-subtype"},
+ {217,"node-type"},
+ {218,"requested-shed-level"},
+ {219,"shed-duration"},
+ {220,"shed-level-descriptions"},
+ {221,"shed-levels"},
+ {222,"state-description"},
+ {226,"door-alarm-state"},
+ {227,"door-extended-pulse-time"},
+ {228,"door-members"},
+ {229,"door-open-too-long-time"},
+ {230,"door-pulse-time"},
+ {231,"door-status"},
+ {232,"door-unlock-delay-time"},
+ {233,"lock-status"},
+ {234,"masked-alarm-values"},
+ {235,"secured-status"},
+ {244,"absentee-limit"}, /* added with addenda 135-2008j */
+ {245,"access-alarm-events"},
+ {246,"access-doors"},
+ {247,"access-event"},
+ {248,"access-event-authentication-factor"},
+ {249,"access-event-credential"},
+ {250,"access-event-time"},
+ {251,"access-transaction-events"},
+ {252,"accompaniment"},
+ {253,"accompaniment-time"},
+ {254,"activation-time"},
+ {255,"active-authentication-policy"},
+ {256,"assigned-access-rights"},
+ {257,"authentication-factors"},
+ {258,"authentication-policy-list"},
+ {259,"authentication-policy-names"},
+ {260,"authentication-status"},
+ {261,"authorization-mode"},
+ {262,"belongs-to"},
+ {263,"credential-disable"},
+ {264,"credential-status"},
+ {265,"credentials"},
+ {266,"credentials-in-zone"},
+ {267,"days-remaining"},
+ {268,"entry-points"},
+ {269,"exit-points"},
+ {270,"expiry-time"},
+ {271,"extended-time-enable"},
+ {272,"failed-attempt-events"},
+ {273,"failed-attempts"},
+ {274,"failed-attempts-time"},
+ {275,"last-access-event"},
+ {276,"last-access-point"},
+ {277,"last-credential-added"},
+ {278,"last-credential-added-time"},
+ {279,"last-credential-removed"},
+ {280,"last-credential-removed-time"},
+ {281,"last-use-time"},
+ {282,"lockout"},
+ {283,"lockout-relinquish-time"},
+ {284,"master-exemption"},
+ {285,"max-failed-attempts"},
+ {286,"members"},
+ {287,"muster-point"},
+ {288,"negative-access-rules"},
+ {289,"number-of-authentication-policies"},
+ {290,"occupancy-count"},
+ {291,"occupancy-count-adjust"},
+ {292,"occupancy-count-enable"},
+ {293,"occupancy-exemption"},
+ {294,"occupancy-lower-limit"},
+ {295,"occupancy-lower-limit-enforced"},
+ {296,"occupancy-state"},
+ {297,"occupancy-upper-limit"},
+ {298,"occupancy-upper-limit-enforced"},
+ {299,"passback-exemption"},
+ {300,"passback-mode"},
+ {301,"passback-timeout"},
+ {302,"positive-access-rules"},
+ {303,"reason-for-disable"},
+ {304,"supported-formats"},
+ {305,"supported-format-classes"},
+ {306,"threat-authority"},
+ {307,"threat-level"},
+ {308,"trace-flag"},
+ {309,"transaction-notification-class"},
+ {310,"user-external-identifier"},
+ {311,"user-information-reference"},
+ /* enumeration values 312-316 reserved for future addenda */
+ {317,"user-name"},
+ {318,"user-type"},
+ {319,"uses-remaining"},
+ {320,"zone-from"},
+ {321,"zone-to"},
+ {322,"access-event-tag"},
+ {323,"global-identifier"},
+ /* enumeration values 324-325 reserved for future addenda */
+ {326,"verification-time"},
+ {342,"bit-mask"}, /* addenda 135-2008w */
+ {343,"bit-text"},
+ {344,"is-utc"},
{0, NULL}
-/* Enumerated values 0-511 are reserved for definition by ASHRAE.
- Enumerated values 512-4194303 may be used by others subject to
+/* Enumerated values 0-511 are reserved for definition by ASHRAE.
+ Enumerated values 512-4194303 may be used by others subject to
the procedures and constraints described in Clause 23. */
};
};
+#define ANSI_X34 0
+#define IBM_MS_DBCS 1
+#define JIS_C_6226 2
+#define ISO_10646_UCS4 3
+#define ISO_10646_UCS2 4
+#define ISO_18859_1 5
static const value_string
BACnetCharacterSet [] = {
- {0,"ANSI X3.4"},
- {1,"IBM/Microsoft DBCS"},
- {2,"JIS C 6226"},
- {3,"ISO 10646(UCS-4)"},
- {4,"ISO 10646(UCS-2)"},
- {5,"ISO 18859-1"},
- {0,NULL}
+ {ANSI_X34, "ANSI X3.4 / UTF-8 (since 2010)"},
+ {IBM_MS_DBCS, "IBM/Microsoft DBCS"},
+ {JIS_C_6226, "JIS C 6226"},
+ {ISO_10646_UCS4, "ISO 10646(UCS-4)"},
+ {ISO_10646_UCS2, "ISO 10646(UCS-2)"},
+ {ISO_18859_1, "ISO 18859-1"},
+ {0, NULL}
};
static const value_string
{0,NULL }
};
+/* note: notification class object recipient-list uses
+ different day-of-week enum */
static const value_string
-days [] = {
+day_of_week [] = {
{1,"Monday" },
{2,"Tuesday" },
{3,"Wednesday" },
{6,"Saturday" },
{7,"Sunday" },
{255,"any day of week" },
- {0,NULL },
+ {0,NULL }
};
static const value_string
{4,"security" },
{5,"services" },
{6,"vt" },
- {0,NULL },
-/* Enumerated values 0-63 are reserved for definition by ASHRAE.
- Enumerated values64-65535 may be used by others subject to
+ {0,NULL }
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+ Enumerated values64-65535 may be used by others subject to
the procedures and constraints described in Clause 23. */
};
{4,"dec-vt200" },
{5,"hp-700-94" },
{6,"ibm-3130" },
- {0,NULL },
+ {0,NULL }
};
static const value_string
{9,"extended" },
{10,"buffer-ready" },
{11,"unsigned-range" },
- {0,NULL },
-/* Enumerated values 0-63 are reserved for definition by ASHRAE.
- Enumerated values 64-65535 may be used by others subject to
- the procedures and constraints described in Clause 23.
- It is expected that these enumerated values will correspond
- to the use of the complex-event-type CHOICE [6] of the
+ {14,"double-out-of-range"}, /* added with addenda 135-2008w */
+ {15,"signed-out-of-range"},
+ {16,"unsigned-out-of-range"},
+ {17,"change-of-characterstring"},
+ {0,NULL }
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+ Enumerated values 64-65535 may be used by others subject to
+ the procedures and constraints described in Clause 23.
+ It is expected that these enumerated values will correspond
+ to the use of the complex-event-type CHOICE [6] of the
BACnetNotificationParameters production. */
};
{3,"high-limit" },
{4,"low-limit" },
{5,"life-safety-alarm" },
- {0,NULL },
-/* Enumerated values 0-63 are reserved for definition by ASHRAE.
- Enumerated values 64-65535 may be used by others subject to
+ {0,NULL }
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+ Enumerated values 64-65535 may be used by others subject to
the procedures and constraints described in Clause 23. */
};
BACnetLogStatus [] = {
{0,"log-disabled" },
{1,"buffer-purged" },
- {0,NULL },
+ {0,NULL }
};
static const value_string
{1,"periodic-test" },
{2,"need-service-operational" },
{3,"need-service-inoperative" },
- {0,NULL },
+ {0,NULL }
};
static const value_string
{0,"alarm" },
{1,"event" },
{2,"ack-notification" },
- {0,NULL },
+ {0,NULL }
};
static const value_string
{11,"unsigned-value"},
{12,"life-safety-mode"},
{13,"life-safety-state"},
+ {14,"door-alarm-state"},
{0,NULL}
-/* Tag values 0-63 are reserved for definition by ASHRAE.
- Tag values of 64-254 may be used by others to accommodate
- vendor specific properties that have discrete or enumerated values,
+/* Tag values 0-63 are reserved for definition by ASHRAE.
+ Tag values of 64-254 may be used by others to accommodate
+ vendor specific properties that have discrete or enumerated values,
subject to the constraints described in Clause 23. */
};
{3,"program"},
{4,"other"},
{0,NULL}
-/* Enumerated values 0-63 are reserved for definition by ASHRAE.
- Enumerated values 64-65535 may be used by others subject to
+/* Enumerated values 0-63 are reserved for definition by ASHRAE.
+ Enumerated values 64-65535 may be used by others subject to
the procedures and constraints described in Clause 23. */
};
{ 0, NULL }
};
+static const value_string
+BACnetReadRangeOptions[] = {
+ { 3, "range byPosition" },
+ { 4, "range byTime" },
+ { 5, "range timeRange" },
+ { 6, "range bySequenceNumber" },
+ { 7, "range byTime" },
+ { 0, NULL }
+};
+
+/* Present_Value for Load Control Object */
+static const value_string
+BACnetShedState[] = {
+ { 0, "shed-inactive" },
+ { 1, "shed-request-pending" },
+ { 2, "shed-compliant" },
+ { 3, "shed-non-compliant" },
+ { 0, NULL }
+};
+
+static const value_string
+BACnetVendorIdentifiers [] = {
+ { 0, "ASHRAE" },
+ { 1, "NIST" },
+ { 2, "The Trane Company" },
+ { 3, "McQuay International" },
+ { 4, "PolarSoft" },
+ { 5, "Johnson Controls, Inc." },
+ { 6, "American Auto-Matrix" },
+ { 7, "Siemens Building Technologies, Ltd., Landis & Staefa Division Europe" },
+ { 8, "Delta Controls" },
+ { 9, "Siemens Building Technologies, Inc." },
+ { 10, "Tour Andover Controls Corporation" },
+ { 11, "TAC" },
+ { 12, "Orion Analysis Corporation" },
+ { 13, "Teletrol Systems Inc." },
+ { 14, "Cimetrics Technology" },
+ { 15, "Cornell University" },
+ { 16, "United Technologies Carrier" },
+ { 17, "Honeywell Inc." },
+ { 18, "Alerton / Honeywell" },
+ { 19, "TAC AB" },
+ { 20, "Hewlett-Packard Company" },
+ { 21, "Dorsette's Inc." },
+ { 22, "Cerberus AG" },
+ { 23, "York Controls Group" },
+ { 24, "Automated Logic Corporation" },
+ { 25, "CSI Control Systems International" },
+ { 26, "Phoenix Controls Corporation" },
+ { 27, "Innovex Technologies, Inc." },
+ { 28, "KMC Controls, Inc." },
+ { 29, "Xn Technologies, Inc." },
+ { 30, "Hyundai Information Technology Co., Ltd." },
+ { 31, "Tokimec Inc." },
+ { 32, "Simplex" },
+ { 33, "North Communications Limited" },
+ { 34, "Notifier" },
+ { 35, "Reliable Controls Corporation" },
+ { 36, "Tridium Inc." },
+ { 37, "Sierra Monitor Corp." },
+ { 38, "Silicon Energy" },
+ { 39, "Kieback & Peter GmbH & Co KG" },
+ { 40, "Anacon Systems, Inc." },
+ { 41, "Systems Controls & Instruments, LLC" },
+ { 42, "Lithonia Lighting" },
+ { 43, "Micropower Manufacturing" },
+ { 44, "Matrix Controls" },
+ { 45, "METALAIRE" },
+ { 46, "ESS Engineering" },
+ { 47, "Sphere Systems Pty Ltd." },
+ { 48, "Walker Technologies Corporation" },
+ { 49, "H I Solutions, Inc." },
+ { 50, "MBS GmbH" },
+ { 51, "SAMSON AG" },
+ { 52, "Badger Meter Inc." },
+ { 53, "DAIKIN Industries Ltd." },
+ { 54, "NARA Controls Inc." },
+ { 55, "Mammoth Inc." },
+ { 56, "Liebert Corporation" },
+ { 57, "SEMCO Incorporated" },
+ { 58, "Air Monitor Corporation" },
+ { 59, "TRIATEK, Inc." },
+ { 60, "NexLight" },
+ { 61, "Multistack" },
+ { 62, "TSI Incorporated" },
+ { 63, "Weather-Rite, Inc." },
+ { 64, "Dunham-Bush" },
+ { 65, "Reliance Electric" },
+ { 66, "LCS Inc." },
+ { 67, "Regulator Australia PTY Ltd." },
+ { 68, "Touch-Plate Lighting Controls" },
+ { 69, "Amann GmbH" },
+ { 70, "RLE Technologies" },
+ { 71, "Cardkey Systems" },
+ { 72, "SECOM Co., Ltd." },
+ { 73, "ABB Gebaudetechnik AG Bereich NetServ" },
+ { 74, "KNX Association cvba" },
+ { 75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
+ { 76, "Nohmi Bosai, Ltd." },
+ { 77, "Carel S.p.A." },
+ { 78, "AirSense Technology, Inc." },
+ { 79, "Hochiki Corporation" },
+ { 80, "Fr. Sauter AG" },
+ { 81, "Matsushita Electric Works, Ltd." },
+ { 82, "Mitsubishi Electric Corporation, Inazawa Works" },
+ { 83, "Mitsubishi Heavy Industries, Ltd." },
+ { 84, "ITT Bell & Gossett" },
+ { 85, "Yamatake Building Systems Co., Ltd." },
+ { 86, "The Watt Stopper, Inc." },
+ { 87, "Aichi Tokei Denki Co., Ltd." },
+ { 88, "Activation Technologies, LLC" },
+ { 89, "Saia-Burgess Controls, Ltd." },
+ { 90, "Hitachi, Ltd." },
+ { 91, "Novar Corp./Trend Control Systems Ltd." },
+ { 92, "Mitsubishi Electric Lighting Corporation" },
+ { 93, "Argus Control Systems, Ltd." },
+ { 94, "Kyuki Corporation" },
+ { 95, "Richards-Zeta Building Intelligence, Inc." },
+ { 96, "Scientech R&D, Inc." },
+ { 97, "VCI Controls, Inc." },
+ { 98, "Toshiba Corporation" },
+ { 99, "Mitsubishi Electric Corporation Air Conditioning & Refrigeration Systems Works" },
+ { 100, "Custom Mechanical Equipment, LLC" },
+ { 101, "ClimateMaster" },
+ { 102, "ICP Panel-Tec, Inc." },
+ { 103, "D-Tek Controls" },
+ { 104, "NEC Engineering, Ltd." },
+ { 105, "PRIVA BV" },
+ { 106, "Meidensha Corporation" },
+ { 107, "JCI Systems Integration Services" },
+ { 108, "Freedom Corporation" },
+ { 109, "Neuberger Gebaudeautomation GmbH" },
+ { 110, "Sitronix" },
+ { 111, "Leviton Manufacturing" },
+ { 112, "Fujitsu Limited" },
+ { 113, "Emerson Network Power" },
+ { 114, "S. A. Armstrong, Ltd." },
+ { 115, "Visonet AG" },
+ { 116, "M&M Systems, Inc." },
+ { 117, "Custom Software Engineering" },
+ { 118, "Nittan Company, Limited" },
+ { 119, "Elutions Inc. (Wizcon Systems SAS)" },
+ { 120, "Pacom Systems Pty., Ltd." },
+ { 121, "Unico, Inc." },
+ { 122, "Ebtron, Inc." },
+ { 123, "Scada Engine" },
+ { 124, "AC Technology Corporation" },
+ { 125, "Eagle Technology" },
+ { 126, "Data Aire, Inc." },
+ { 127, "ABB, Inc." },
+ { 128, "Transbit Sp. z o. o." },
+ { 129, "Toshiba Carrier Corporation" },
+ { 130, "Shenzhen Junzhi Hi-Tech Co., Ltd." },
+ { 131, "Tokai Soft" },
+ { 132, "Lumisys" },
+ { 133, "Veris Industries" },
+ { 134, "Centaurus Prime" },
+ { 135, "Sand Network Systems" },
+ { 136, "Regulvar, Inc." },
+ { 137, "Fastek International, Ltd." },
+ { 138, "PowerCold Comfort Air Solutions, Inc." },
+ { 139, "I Controls" },
+ { 140, "Viconics Electronics, Inc." },
+ { 141, "Yaskawa Electric America, Inc." },
+ { 142, "Plueth Regelsysteme" },
+ { 143, "Digitale Mess- und Steuersysteme AG" },
+ { 144, "Fujitsu General Limited" },
+ { 145, "Project Engineering S.r.l." },
+ { 146, "Sanyo Electric Co., Ltd." },
+ { 147, "Integrated Information Systems, Inc." },
+ { 148, "Temco Controls, Ltd." },
+ { 149, "Airtek Technologies, Inc." },
+ { 150, "Advantech Corporation" },
+ { 151, "Titan Products, Ltd." },
+ { 152, "Regel Partners" },
+ { 153, "National Environmental Product" },
+ { 154, "Unitec Corporation" },
+ { 155, "Kanden Engineering Company" },
+ { 156, "Messner Gebaudetechnik GmbH" },
+ { 157, "Integrated.CH" },
+ { 158, "EH Price Limited" },
+ { 159, "SE-Elektronic GmbH" },
+ { 160, "Rockwell Automation" },
+ { 161, "Enflex Corp." },
+ { 162, "ASI Controls" },
+ { 163, "SysMik GmbH Dresden" },
+ { 164, "HSC Regelungstechnik GmbH" },
+ { 165, "Smart Temp Australia Pty. Ltd." },
+ { 166, "PCI Lighting Control Systems" },
+ { 167, "Duksan Mecasys Co., Ltd." },
+ { 168, "Fuji IT Co., Ltd." },
+ { 169, "Vacon Plc" },
+ { 170, "Leader Controls" },
+ { 171, "Cylon Controls, Ltd." },
+ { 172, "Compas" },
+ { 173, "Mitsubishi Electric Building Techno-Service Co., Ltd." },
+ { 174, "Building Control Integrators" },
+ { 175, "ITG Worldwide (M) Sdn Bhd" },
+ { 176, "Lutron Electronics Co., Inc." },
+ { 177, "Cooper-Atkins Corporation" },
+ { 178, "LOYTEC Electronics GmbH" },
+ { 179, "ProLon" },
+ { 180, "Mega Controls Limited" },
+ { 181, "Micro Control Systems, Inc." },
+ { 182, "Kiyon, Inc." },
+ { 183, "Dust Networks" },
+ { 184, "Advanced Building Automation Systems" },
+ { 185, "Hermos AG" },
+ { 186, "CEZIM" },
+ { 187, "Softing" },
+ { 188, "Lynxspring" },
+ { 189, "Schneider Toshiba Inverter Europe" },
+ { 190, "Danfoss Drives A/S" },
+ { 191, "Eaton Corporation" },
+ { 192, "Matyca S.A." },
+ { 193, "Botech AB" },
+ { 194, "Noveo, Inc." },
+ { 195, "AMEV" },
+ { 196, "Yokogawa Electric Corporation" },
+ { 197, "GFR Gesellschaft fur Regelungstechnik" },
+ { 198, "Exact Logic" },
+ { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
+ { 200, "Kandenko Co., Ltd." },
+ { 201, "DTF, Daten-Technik Fries" },
+ { 202, "Klimasoft, Ltd." },
+ { 203, "Toshiba Schneider Inverter Corporation" },
+ { 204, "Control Applications, Ltd." },
+ { 205, "KDT Systems Co., Ltd." },
+ { 206, "Onicon Incorporated" },
+ { 207, "Automation Displays, Inc." },
+ { 208, "Control Solutions, Inc." },
+ { 209, "Remsdaq Limited" },
+ { 210, "NTT Facilities, Inc." },
+ { 211, "VIPA GmbH" },
+ { 212, "TSC21 Association of Japan" },
+ { 213, "BBP Energie Ltee" },
+ { 214, "HRW Limited" },
+ { 215, "Lighting Control & Design, Inc." },
+ { 216, "Mercy Electronic and Electrical Industries" },
+ { 217, "Samsung SDS Co., Ltd" },
+ { 218, "Impact Facility Solutions, Inc." },
+ { 219, "Aircuity" },
+ { 220, "Control Techniques, Ltd." },
+ { 221, "Evolve Control Systems, LLC" },
+ { 222, "WAGO Kontakttechnik GmbH & Co. KG" },
+ { 223, "Cerus Industrial" },
+ { 224, "Chloride Power Protection Company" },
+ { 225, "Computrols, Inc." },
+ { 226, "Phoenix Contact GmbH & Co. KG" },
+ { 227, "Grundfos Management A/S" },
+ { 228, "Ridder Drive Systems" },
+ { 229, "Soft Device SDN BHD" },
+ { 230, "Integrated Control Technology Limited" },
+ { 231, "AIRxpert Systems, Inc." },
+ { 232, "Microtrol Limited" },
+ { 233, "Red Lion Controls" },
+ { 234, "Digital Electronics Corporation" },
+ { 235, "Ennovatis GmbH" },
+ { 236, "Serotonin Software Technologies, Inc." },
+ { 237, "LS Industrial Systems Co., Ltd." },
+ { 238, "Square D Company" },
+ { 239, "S Squared Innovations, Inc." },
+ { 240, "Aricent Ltd." },
+ { 241, "EtherMetrics, LLC" },
+ { 242, "Industrial Control Communications, Inc." },
+ { 243, "Paragon Controls, Inc." },
+ { 244, "A. O. Smith Corporation" },
+ { 245, "Contemporary Control Systems, Inc." },
+ { 246, "Intesis Software SL" },
+ { 247, "Ingenieurgesellschaft N. Hartleb mbH" },
+ { 248, "Heat-Timer Corporation" },
+ { 249, "Ingrasys Technology, Inc." },
+ { 250, "Costerm Building Automation" },
+ { 251, "Wilo AG" },
+ { 252, "Embedia Technologies Corp." },
+ { 253, "Technilog" },
+ { 254, "HR Controls Ltd. & Co. KG" },
+ { 255, "Lennox International, Inc." },
+ { 256, "RK-Tec Rauchklappen-Steuerungssysteme GmbH & Co. KG" },
+ { 257, "Thermomax, Ltd." },
+ { 258, "ELCON Electronic Control, Ltd." },
+ { 259, "Larmia Control AB" },
+ { 260, "BACnet Stack at SourceForge" },
+ { 261, "G4S Security Services A/S" },
+ { 262, "Sitek S.p.A." },
+ { 263, "Cristal Controles" },
+ { 264, "Regin AB" },
+ { 265, "Dimension Software, Inc. " },
+ { 266, "SynapSense Corporation" },
+ { 267, "Beijing Nantree Electronic Co., Ltd." },
+ { 268, "Camus Hydronics Ltd." },
+ { 269, "Kawasaki Heavy Industries, Ltd. " },
+ { 270, "Critical Environment Technologies" },
+ { 271, "ILSHIN IBS Co., Ltd." },
+ { 272, "ELESTA Energy Control AG" },
+ { 273, "KROPMAN Installatietechniek" },
+ { 274, "Baldor Electric Company" },
+ { 275, "INGA mbH" },
+ { 276, "GE Consumer & Industrial" },
+ { 277, "Functional Devices, Inc." },
+ { 278, "ESAC" },
+ { 279, "M-System Co., Ltd." },
+ { 280, "Yokota Co., Ltd." },
+ { 281, "Hitranse Technology Co., LTD" },
+ { 282, "Federspiel Controls" },
+ { 283, "Kele, Inc." },
+ { 284, "Opera Electronics, Inc." },
+ { 285, "Gentec" },
+ { 286, "Embedded Science Labs, LLC" },
+ { 287, "Parker Hannifin Corporation" },
+ { 288, "MaCaPS International Limited" },
+ { 289, "Link4 Corporation" },
+ { 290, "Romutec Steuer-u. Regelsysteme GmbH" },
+ { 291, "Pribusin, Inc." },
+ { 292, "Advantage Controls" },
+ { 293, "Critical Room Control" },
+ { 294, "LEGRAND" },
+ { 295, "Tongdy Control Technology Co., Ltd." },
+ { 296, "ISSARO Integrierte Systemtechnik" },
+ { 297, "Pro-Dev Industries" },
+ { 298, "DRI-STEEM" },
+ { 299, "Creative Electronic GmbH" },
+ { 300, "Swegon AB" },
+ { 301, "Jan Brachacek" },
+ { 302, "Hitachi Appliances, Inc." },
+ { 303, "Real Time Automation, Inc." },
+ { 304, "ITEC Hankyu-Hanshin Co." },
+ { 305, "Cyrus E&M Engineering Co., Ltd." },
+ { 306, "Racine Federated, Inc." },
+ { 307, "Verari Systems, Inc." },
+ { 308, "Elesta GmbH Building Automation" },
+ { 309, "Securiton" },
+ { 310, "OSlsoft, Inc." },
+ { 311, "Hanazeder Electronic GmbH" },
+ { 312, "Honeywell Security Deutschland, Novar GmbH" },
+ { 313, "Siemens Energy & Automation, Inc." },
+ { 314, "ETM Professional Control GmbH" },
+ { 315, "Meitav-tec, Ltd." },
+ { 316, "Janitza Electronics GmbH" },
+ { 317, "MKS Nordhausen" },
+ { 318, "De Gier Drive Systems B.V." },
+ { 319, "Cypress Envirosystems" },
+ { 320, "SMARTron s.r.o." },
+ { 321, "Verari Systems, Inc." },
+ { 322, "K-W Electronic Service, Inc." },
+ { 323, "ALFA-SMART Energy Management" },
+ { 324, "Telkonet, Inc." },
+ { 325, "Securiton GmbH" },
+ { 326, "Cemtrex, Inc." },
+ { 327, "Performance Technologies, Inc." },
+ { 328, "Xtralis (Aust) Pty Ltd" },
+ { 329, "TROX GmbH" },
+ { 330, "Beijing Hysine Technology Co., Ltd" },
+ { 331, "RCK Controls, Inc." },
+ { 332, "ACELIA" },
+ { 333, "Novar/Honeywell" },
+ { 334, "The S4 Group, Inc." },
+ { 335, "Schneider Electric" },
+ { 336, "LHA Systems" },
+ { 337, "GHM engineering Group, Inc." },
+ { 338, "Cllimalux S.A." },
+ { 339, "VAISALA Oyj" },
+ { 340, "COMPLEX (Beijing) Technology, Co., LTD." },
+ { 342, "POWERPEG NSI Limited" },
+ { 343, "BACnet Interoperability Testing Services, Inc." },
+ { 344, "Teco a.s." },
+ { 0, NULL }
+};
+
static int proto_bacapp = -1;
static int hf_bacapp_type = -1;
static int hf_bacapp_pduflags = -1;
static int hf_bacapp_tag_ProcessId = -1;
static int hf_bacapp_tag_initiatingObjectType = -1;
static int hf_bacapp_vpart = -1;
-
static int hf_bacapp_uservice = -1;
-
+static int hf_BACnetPropertyIdentifier = -1;
+static int hf_BACnetVendorIdentifier = -1;
+static int hf_BACnetRestartReason = -1;
+static int hf_bacapp_tag_IPV4 = -1;
+static int hf_bacapp_tag_IPV6 = -1;
+static int hf_bacapp_tag_PORT = -1;
+/* some more variables for segmented messages */
+static int hf_msg_fragments = -1;
+static int hf_msg_fragment = -1;
+static int hf_msg_fragment_overlap = -1;
+static int hf_msg_fragment_overlap_conflicts = -1;
+static int hf_msg_fragment_multiple_tails = -1;
+static int hf_msg_fragment_too_long_fragment = -1;
+static int hf_msg_fragment_error = -1;
+static int hf_msg_reassembled_in = -1;
+static int hf_msg_reassembled_length = -1;
+
+static gint ett_msg_fragment = -1;
+static gint ett_msg_fragments = -1;
static gint ett_bacapp = -1;
static gint ett_bacapp_control = -1;
static dissector_handle_t data_handle;
static gint32 propertyIdentifier = -1;
+static gint32 propertyArrayIndex = -1;
static guint32 object_type = 4096;
static guint8 bacapp_flags = 0;
static guint8 bacapp_seq = 0;
+static const fragment_items msg_frag_items = {
+ /* Fragment subtrees */
+ &ett_msg_fragment,
+ &ett_msg_fragments,
+ /* Fragment fields */
+ &hf_msg_fragments,
+ &hf_msg_fragment,
+ &hf_msg_fragment_overlap,
+ &hf_msg_fragment_overlap_conflicts,
+ &hf_msg_fragment_multiple_tails,
+ &hf_msg_fragment_too_long_fragment,
+ &hf_msg_fragment_error,
+ /* Reassembled in field */
+ &hf_msg_reassembled_in,
+ /* Reassembled length field */
+ &hf_msg_reassembled_length,
+ /* Tag */
+ "Message fragments"
+};
+
+/* if BACnet uses the reserved values, then patch the corresponding values here, maximum 16 values are defined */
+static const guint MaxAPDUSize [] = { 50,128,206,480,1024,1476 };
+
+static guint
+fGetMaxAPDUSize(guint8 idx)
+{
+ /* only 16 values are defined, so use & 0x0f */
+ /* check the size of the Array, deliver either the entry
+ or the first entry if idx is outside of the array (bug 3736 comment#7) */
+ if ((idx & 0x0f) >= (gint)(sizeof(MaxAPDUSize)/sizeof(guint)))
+ return MaxAPDUSize[0];
+ else
+ return MaxAPDUSize[idx & 0x0f];
+}
+
/* Used when there are ranges of reserved and proprietary enumerations */
static const char*
val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
/* from clause 20.2.1.3.2 Constructed Data */
/* returns true if the extended value is used */
-static gboolean tag_is_extended_value(guint8 tag)
+static gboolean
+tag_is_extended_value(guint8 tag)
{
return (tag & 0x07) == 5;
}
-static gboolean tag_is_opening(guint8 tag)
+static gboolean
+tag_is_opening(guint8 tag)
{
return (tag & 0x07) == 6;
}
-static gboolean tag_is_closing(guint8 tag)
+static gboolean
+tag_is_closing(guint8 tag)
{
return (tag & 0x07) == 7;
}
/* from clause 20.2.1.1 Class
class bit shall be one for context specific tags */
/* returns true if the tag is context specific */
-static gboolean tag_is_context_specific(guint8 tag)
+static gboolean
+tag_is_context_specific(guint8 tag)
{
return (tag & 0x08) != 0;
}
-static gboolean tag_is_extended_tag_number(guint8 tag)
+static gboolean
+tag_is_extended_tag_number(guint8 tag)
{
return ((tag & 0xF0) == 0xF0);
}
-static guint32 object_id_type(guint32 object_identifier)
+static guint32
+object_id_type(guint32 object_identifier)
{
return ((object_identifier >> 22) & 0x3FF);
}
-static guint32 object_id_instance(guint32 object_identifier)
+static guint32
+object_id_instance(guint32 object_identifier)
{
return (object_identifier & 0x3FFFFF);
}
fUnsigned32 (tvbuff_t *tvb, guint offset, guint32 lvt, guint32 *val)
{
gboolean valid = TRUE;
-
+
switch (lvt) {
case 1:
*val = tvb_get_guint8(tvb, offset);
valid = FALSE;
break;
}
-
+
return valid;
}
gboolean valid = FALSE;
gint64 value = 0;
guint8 data, i;
-
+
if (lvt && (lvt <= 8)) {
valid = TRUE;
data = tvb_get_guint8(tvb, offset);
}
*val = value;
}
-
+
return valid;
}
{
gboolean valid = FALSE;
gint64 value = 0;
- guint8 data, i;
+ guint8 data;
+ guint32 i;
/* we can only handle 7 bytes for a 64-bit value due to signed-ness */
if (lvt && (lvt <= 7)) {
data = tvb_get_guint8(tvb, offset);
if ((data & 0x80) != 0)
value = (-1 << 8) | data;
+ else
+ value = data;
for (i = 1; i < lvt; i++) {
data = tvb_get_guint8(tvb, offset+i);
value = (value << 8) + data;
tag = tvb_get_guint8(tvb, offset);
*tag_info = 0;
*lvt = tag & 0x07;
- /* To solve the problem of lvt values of 6/7 being indeterminate - it */
- /* can mean open/close tag or length of 6/7 after the length is */
- /* computed below - store whole tag info, not just context bit. */
+ /* To solve the problem of lvt values of 6/7 being indeterminate - it */
+ /* can mean open/close tag or length of 6/7 after the length is */
+ /* computed below - store whole tag info, not just context bit. */
if (tag_is_context_specific(tag)) *tag_info = tag & 0x0F;
*tag_no = tag >> 4;
- if (tag_is_extended_tag_number(tag)) {
+ if (tag_is_extended_tag_number(tag)) {
*tag_no = tvb_get_guint8(tvb, offset + tag_len++);
}
if (tag_is_extended_value(tag)) { /* length is more than 4 Bytes */
}
if (tree)
{
- if (tag_is_closing(tag) || tag_is_opening(tag))
- ti = proto_tree_add_text(tree, tvb, offset, tag_len,
- "%s: %u", match_strval(
- tag & 0x07, BACnetTagNames),
- *tag_no);
+ if (tag_is_opening(tag))
+ ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
+ else if (tag_is_closing(tag))
+ ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
else if (tag_is_context_specific(tag)) {
ti = proto_tree_add_text(tree, tvb, offset, tag_len,
"Context Tag: %u, Length/Value/Type: %u",
BACnetApplicationTagNumber,
ASHRAE_Reserved_Fmt),
*lvt);
+
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
/* details if needed */
proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, FALSE);
proto_tree_add_uint(subtree, hf_bacapp_tag_lvt,
tvb, lvt_offset, lvt_len, *lvt);
}
-
+
return tag_len;
}
guint64 val = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- guint tag_len;
+ guint tag_len;
proto_item *ti;
proto_tree *subtree;
/* only support up to an 8 byte (64-bit) integer */
if (fUnsigned64 (tvb, offset + tag_len, lvt, &val))
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
- "%s(Unsigned) %" PRIu64, label, val);
+ "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
else
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
"%s - %u octets (Unsigned)", label, lvt);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
+
return offset+tag_len+lvt;
}
if (fUnsigned32 (tvb, offset+tag_len, lvt, &val)) {
if (vs)
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
- "%s %s", label, val_to_split_str(val, split_val, vs,
+ "%s %s", label, val_to_split_str(val, split_val, vs,
ASHRAE_Reserved_Fmt,Vendor_Proprietary_Fmt));
else
ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
static guint
fEnumeratedTag (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label,
- const value_string *vs)
+ const value_string *vs)
{
return fEnumeratedTagSplit (tvb, tree, offset, label, vs, 0);
}
tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (fSigned64 (tvb, offset + tag_len, lvt, &val))
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
- "%s(Signed) %" PRId64, label, val);
+ "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
else
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
"%s - %u octets (Signed)", label, lvt);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
+
return offset+tag_len+lvt;
}
guint8 tag_no, tag_info;
guint32 lvt;
guint tag_len;
- gfloat f_val = 0.0;
+ gfloat f_val;
proto_item *ti;
proto_tree *subtree;
-
+
tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
"%s%f (Real)", label, f_val);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
+
return offset+tag_len+4;
}
guint8 tag_no, tag_info;
guint32 lvt;
guint tag_len;
- gdouble d_val = 0.0;
+ gdouble d_val;
proto_item *ti;
proto_tree *subtree;
-
+
tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
- "%s%lf (Double)", label, d_val);
+ "%s%f (Double)", label, d_val);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
+
return offset+tag_len+8;
}
tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
- ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
+ ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
tvb, offset, lvt+tag_len, val);
else
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
"Process Identifier - %u octets (Signed)", lvt);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
- fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
- return offset+tag_len+lvt;
+ offset += tag_len + lvt;
+
+ return offset;
}
static guint
tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (fUnsigned32 (tvb, offset+tag_len, lvt, &val))
- ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
- "%s (hh.mm.ss): %d.%02d.%02d%s",
- label,
- (val / 3600), ((val % 3600) / 60), (val % 60),
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+ "%s (hh.mm.ss): %d.%02d.%02d%s",
+ label,
+ (val / 3600), ((val % 3600) / 60), (val % 60),
val == 0 ? " (indefinite)" : "");
else
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
month = tvb_get_guint8(tvb, offset+tag_len);
weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
- ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
- val_to_str(month, months, "month (%d) not found"),
- val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
- val_to_str(dayOfWeek, days, "day of week (%d) not found"));
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
+ val_to_str(month, months, "month (%d) not found"),
+ val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
+ val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
months,
"month (%d) not found"),
day, year, val_to_str(weekday,
- days,
+ day_of_week,
"(%d) not found"));
}
else
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
"%s%s %d, any year, (Day of Week = %s)",
label, val_to_str(month, months, "month (%d) not found"),
- day, val_to_str(weekday, days, "(%d) not found"));
+ day, val_to_str(weekday, day_of_week, "(%d) not found"));
}
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
label,
hour > 12 ? hour - 12 : hour,
minute, second, msec,
- hour > 12 ? "P.M." : "A.M.",
+ hour >= 12 ? "P.M." : "A.M.",
hour, minute, second, msec);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
+
return offset+tag_len+lvt;
}
}
static guint
-fTimeValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fTimeValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
- guint32 lvt;
+ guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
return offset;
}
offset = fTime (tvb,tree,offset,"Time: ");
- offset = fApplicationTypes(tvb, tree, offset, "Value: ");
+ offset = fApplicationTypes(tvb, pinfo, tree, offset, "Value: ");
+
+ if (offset==lastoffset) break; /* exit loop if nothing happens inside */
}
return offset;
}
static guint
fCalendaryEntry (tvbuff_t *tvb, proto_tree *tree, guint offset)
{
- guint8 tag_no, tag_info;
- guint32 lvt;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
switch (fTagNo(tvb, offset)) {
case 0: /* Date */
offset = fDate (tvb, tree, offset, "Date: ");
break;
case 1: /* dateRange */
- offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
offset = fDateRange (tvb, tree, offset);
- offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
case 2: /* BACnetWeekNDay */
offset = fWeekNDay (tvb, tree, offset);
break;
default:
return offset;
- break;
}
return offset;
}
-static guint
-fTimeStamp (tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint fTimeStamp (tvbuff_t *tvb, proto_tree *tree,
+ guint offset, const gchar *label)
{
guint8 tag_no = 0, tag_info = 0;
guint32 lvt = 0;
- if (tvb_length_remaining(tvb, offset) > 0) { /* don't loop, it's a CHOICE */
+ if (tvb_reported_length_remaining(tvb, offset) > 0) { /* don't loop, it's a CHOICE */
switch (fTagNo(tvb, offset)) {
case 0: /* time */
- offset = fTime (tvb, tree, offset, "timestamp: ");
+ offset = fTime (tvb, tree, offset, label?label:"timestamp: ");
break;
case 1: /* sequenceNumber */
- offset = fUnsignedTag (tvb, tree, offset, "sequence Number: ");
+ offset = fUnsignedTag (tvb, tree, offset,
+ label?label:"sequence Number: ");
break;
case 2: /* dateTime */
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = fDateTime (tvb, tree, offset, "timestamp: ");
+ offset = fDateTime (tvb, tree, offset, label?label:"timestamp: ");
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
default:
return offset;
- break;
}
}
+
return offset;
}
-#if 0
+
static guint
-fSetpointReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fClientCOV (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
-
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
-
- switch (fTagNo(tvb, offset)) {
- case 0: /* setpointReference */
- offset = fBACnetObjectPropertyReference (tvb,tree,offset);
- break;
- default:
- return offset;
- break;
- }
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = fApplicationTypes(tvb,pinfo,tree,offset, "increment: ");
}
return offset;
}
-#endif
-#if 0
-static guint
-fClientCOV (tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
- if (tvb_length_remaining(tvb, offset) > 0) {
- offset = fApplicationTypes(tvb,tree,offset, "increment: ");
- }
- return offset;
-}
+static const value_string
+BACnetDaysOfWeek [] = {
+ {0,"Monday" },
+ {1,"Tuesday" },
+ {2,"Wednesday" },
+ {3,"Thursday" },
+ {4,"Friday" },
+ {5,"Saturday" },
+ {6,"Sunday" },
+ {0,NULL }
+};
static guint
-fDestination (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fDestination (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- if (tvb_length_remaining(tvb, offset) > 0) {
- offset = fApplicationTypesEnumerated(tvb,tree,offset,
- "valid Days: ", days);
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = fApplicationTypesEnumerated(tvb,pinfo,tree,offset,
+ "valid Days: ", BACnetDaysOfWeek);
offset = fTime (tvb,tree,offset,"from time: ");
offset = fTime (tvb,tree,offset,"to time: ");
- offset = fRecipient (tvb,tree,offset);
+ offset = fRecipient (tvb,pinfo,tree,offset);
offset = fProcessId (tvb,tree,offset);
- offset = fApplicationTypes (tvb,tree,offset,
+ offset = fApplicationTypes (tvb,pinfo,tree,offset,
"issue confirmed notifications: ");
- offset = fApplicationTypesEnumerated (tvb,tree,offset,
+ offset = fBitStringTagVS (tvb,tree,offset,
"transitions: ", BACnetEventTransitionBits);
}
return offset;
}
-#endif
static guint
fOctetString (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
{
gchar *tmp;
- guint start = offset;
+ guint start = offset;
+ guint8 tag_no, tag_info;
+ proto_tree* subtree = tree;
+ proto_item* ti = 0;
+
+ offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+
+ if (lvt > 0)
+ {
+ tmp = tvb_bytes_to_str(tvb, offset, lvt);
+ ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
+ offset += lvt;
+ }
+
+ if (ti)
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+
+ fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
+
+ return offset;
+}
+
+static guint
+fMacAddress (tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
+{
+ gchar *tmp;
+ guint start = offset;
guint8 tag_no, tag_info;
- proto_tree* subtree = tree;
- proto_item* ti = 0;
+ proto_tree* subtree = tree;
+ proto_item* ti = 0;
offset += fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
+
if (lvt > 0)
- {
- tmp = tvb_bytes_to_str(tvb, offset, lvt);
- ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
+ {
+ if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
+
+ guint32 ip = tvb_get_ipv4(tvb, offset);
+ guint16 port = tvb_get_ntohs(tvb, offset+4);
+
+ proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
+ proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
+
+ } else {
+ if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
+ struct e_in6_addr addr;
+ guint16 port = tvb_get_ntohs(tvb, offset+16);
+ tvb_get_ipv6(tvb, offset, &addr);
+
+ proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
+ proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
+
+ } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
+ tmp = tvb_bytes_to_str(tvb, offset, lvt);
+ ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
+ }
+ }
offset += lvt;
- }
+ }
if (ti)
- subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
- fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
+ fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
return offset;
}
{
guint8 tag_no, tag_info;
guint32 lvt;
- guint offs;
+ guint offs;
offset = fUnsignedTag (tvb, tree, offset, "network-number");
offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (lvt == 0) {
- proto_tree_add_text(tree, tvb, offset, offs, "mac-address: broadcast");
+ proto_tree_add_text(tree, tvb, offset, offs, "MAC-address: broadcast");
offset += offs;
} else
- offset = fOctetString (tvb, tree, offset, "mac-address: ", lvt);
+ offset = fMacAddress (tvb, tree, offset, "MAC-address: ", lvt);
+
return offset;
}
-#if 0
static guint
fSessionKey (tvbuff_t *tvb, proto_tree *tree, guint offset)
{
offset = fOctetString (tvb,tree,offset,"session key: ", 8);
return fAddress (tvb,tree,offset);
}
-#endif
static guint
-fObjectIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fObjectIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint8 tag_no, tag_info;
guint32 lvt;
ASHRAE_Reserved_Fmt,
Vendor_Proprietary_Fmt),
object_id_instance(object_id));
+ if (col_get_writable(pinfo->cinfo))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
+ val_to_split_str(object_type,
+ 128,
+ BACnetObjectType,
+ ASHRAE_Reserved_Fmt,
+ Vendor_Proprietary_Fmt),
+ object_id_instance(object_id));
+
/* here are the details of how we arrived at the above text */
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
}
static guint
-fRecipient (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRecipient (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
-
- switch (fTagNo(tvb, offset)) {
- case 0: /* device */
- offset = fObjectIdentifier (tvb, tree, offset);
- break;
- case 1: /* address */
+ fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_no < 2) {
+ if (tag_no == 0) { /* device */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ }
+ else { /* address */
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
offset = fAddress (tvb, tree, offset);
- break;
- default:
- return offset;
- break;
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
}
}
return offset;
}
static guint
-fRecipientProcess (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRecipientProcess (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb, offset)) {
case 0: /* recipient */
- offset = fRecipient (tvb, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fRecipient (tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
case 1: /* processId */
offset = fProcessId (tvb, tree, offset);
+ lastoffset = offset;
break;
default:
- return offset;
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fAddressBinding (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAddressBinding (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
return fAddress (tvb, tree, offset);
}
static guint
-fActionCommand (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fActionCommand (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_match)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
- proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ /* set the optional global properties to indicate not-used */
+ propertyArrayIndex = -1;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info) ) {
+ if (tag_no == tag_match) {
+ return offset;
+ }
+ offset += len;
subtree = tree;
continue;
}
switch (tag_no) {
-
+
case 0: /* deviceIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* objectIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* propertyIdentifier */
- offset = fPropertyIdentifier (tvb, subtree, offset);
+ offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
break;
case 3: /* propertyArrayIndex */
- offset = fUnsignedTag (tvb,subtree,offset,"Property Array Index: ");
+ offset = fPropertyArrayIndex (tvb, subtree, offset);
break;
case 4: /* propertyValue */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
- break;
- }
- FAULT;
+ offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
break;
case 5: /* priority */
offset = fUnsignedTag (tvb,subtree,offset,"Priority: ");
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
+/* BACnetActionList ::= SEQUENCE{
+ action [0] SEQUENCE OF BACnetActionCommand
+ }
+*/
static guint
-fActionList (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fActionList (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fActionCommand (tvb,tree,offset);
+ guint lastoffset = 0, len;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+ proto_tree *subtree = tree;
+ proto_item *ti;
+
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ lastoffset = offset;
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info)) {
+ offset += len;
+ subtree = tree;
+ continue;
+ }
+ if (tag_is_opening(tag_info)) {
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ offset += fTagHeaderTree (tvb, subtree, offset,
+ &tag_no, &tag_info, &lvt);
+ }
+ switch (tag_no) {
+ case 0: /* BACnetActionCommand */
+ offset = fActionCommand (tvb, pinfo, subtree, offset, tag_no);
+ break;
+ default:
+ break;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ return offset;
}
static guint
-fPropertyIdentifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fPropertyIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint8 tag_no, tag_info;
guint32 lvt;
guint tag_len;
proto_item *ti;
proto_tree *subtree;
+ const gchar *label = "Property Identifier";
propertyIdentifier = 0; /* global Variable */
tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (fUnsigned32 (tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier))
+ /* can we decode this value? */
+ if (fUnsigned32 (tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
- "property Identifier: %s",
+ "%s: %s (%u)", label,
val_to_split_str(propertyIdentifier, 512,
BACnetPropertyIdentifier,
ASHRAE_Reserved_Fmt,
- Vendor_Proprietary_Fmt));
+ Vendor_Proprietary_Fmt), propertyIdentifier);
+ if (col_get_writable(pinfo->cinfo))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_split_str(propertyIdentifier, 512,
+ BACnetPropertyIdentifier,
+ ASHRAE_Reserved_Fmt,
+ Vendor_Proprietary_Fmt));
+ } else {
+ /* property identifiers cannot be larger than 22-bits */
+ return offset;
+ }
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
+ offset+tag_len, lvt, FALSE);
+
+ return offset+tag_len+lvt;
+}
+
+static guint
+fPropertyArrayIndex (tvbuff_t *tvb, proto_tree *tree, guint offset)
+{
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+ guint tag_len;
+ proto_item *ti;
+ proto_tree *subtree;
+
+ tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (fUnsigned32 (tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+ "property Array Index (Unsigned) %u", propertyArrayIndex);
else
ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
- "Property Identifier - %u octets", lvt);
+ "property Array Index - %u octets (Unsigned)", lvt);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
{
guint8 tag_no, tag_info, character_set;
guint32 lvt, l;
- size_t inbytesleft, outbytesleft = 512;
+ gsize inbytesleft, outbytesleft = 512;
guint offs, extra = 1;
guint8 *str_val;
+ const char *coding;
guint8 bf_arr[512], *out = &bf_arr[0];
proto_item *ti;
proto_tree *subtree;
- guint start = offset;
+ guint start = offset;
- if (tvb_length_remaining(tvb, offset) > 0) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-
+
character_set = tvb_get_guint8(tvb, offset+offs);
- /* Account for code page if DBCS */
- if (character_set == 1)
- {
- extra = 3;
- }
- offset += (offs+extra);
- lvt -= (extra);
+ /* Account for code page if DBCS */
+ if (character_set == 1)
+ {
+ extra = 3;
+ }
+ offset += (offs+extra);
+ lvt -= (extra);
do {
- l = inbytesleft = min(lvt, 255);
+ inbytesleft = l = MIN(lvt, 255);
/*
* XXX - are we guaranteed that these encoding
* names correspond, on *all* platforms with
str_val = tvb_get_ephemeral_string(tvb, offset, l);
/** this decoding may be not correct for multi-byte characters, Lka */
switch (character_set) {
- case 0x00: /* ANSI_X3.4 */
+ case ANSI_X34:
fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ANSI_X3.4");
+ coding = "ANSI X3.4";
break;
- case 1: /* IBM/MICROSOFT DBCS */
+ case IBM_MS_DBCS:
out = str_val;
+ coding = "IBM MS DBCS";
break;
- case 2: /* JIS C 6226 */
+ case JIS_C_6226:
out = str_val;
+ coding = "JIS C 6226";
break;
- case 3: /* UCS-4 */
+ case ISO_10646_UCS4:
fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-4BE");
+ coding = "ISO 10646 UCS-4";
break;
- case 4: /* UCS-2 */
+ case ISO_10646_UCS2:
fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "UCS-2BE");
+ coding = "ISO 10646 UCS-2";
break;
- case 5: /* ISO8859-1 */
+ case ISO_18859_1:
fConvertXXXtoUTF8(str_val, &inbytesleft, out, &outbytesleft, "ISO8859-1");
+ coding = "ISO 8859-1";
break;
default:
out = str_val;
+ coding = "unknown";
break;
}
- ti = proto_tree_add_text(tree, tvb, offset, l, "%s'%s'", label, out);
+ ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s'%s'", label, coding, out);
lvt-=l;
offset+=l;
} while (lvt > 0);
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
- fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
+ fTagHeaderTree (tvb, subtree, start, &tag_no, &tag_info, &lvt);
proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, FALSE);
- if (character_set == 1)
- {
- proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
- }
+
+ if (character_set == 1)
+ {
+ proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
+ }
}
return offset;
}
{
guint8 tag_no, tag_info, tmp;
gint j, unused, skip;
+ guint start = offset;
guint offs;
guint32 lvt, i, numberOfBytes;
guint8 bf_arr[256];
-
+ proto_tree* subtree = tree;
+ proto_item* ti = 0;
+
offs = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
offset+=offs;
unused = tvb_get_guint8(tvb, offset); /* get the unused Bits */
+ ti = proto_tree_add_text(tree, tvb, start, offs+lvt,
+ "%s(Bit String)",
+ label);
+ if (ti) {
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ }
+ fTagHeaderTree(tvb, subtree, start, &tag_no, &tag_info, &lvt);
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ "Unused bits: %u",
+ unused);
skip = 0;
for (i = 0; i < numberOfBytes; i++) {
tmp = tvb_get_guint8(tvb, (offset)+i+1);
for (j = 0; j < 8-skip; j++) {
if (src != NULL) {
if (tmp & (1 << (7 - j)))
- proto_tree_add_text(tree, tvb,
+ proto_tree_add_text(subtree, tvb,
offset+i+1, 1,
- "%s%s = TRUE",
- label,
+ "%s = TRUE",
val_to_str((guint) (i*8 +j),
src,
ASHRAE_Reserved_Fmt));
else
- proto_tree_add_text(tree, tvb,
+ proto_tree_add_text(subtree, tvb,
offset+i+1, 1,
- "%s%s = FALSE",
- label,
+ "%s = FALSE",
val_to_str((guint) (i*8 +j),
src,
ASHRAE_Reserved_Fmt));
-
} else {
- bf_arr[min(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
+ bf_arr[MIN(255,(i*8)+j)] = tmp & (1 << (7 - j)) ? '1' : '0';
}
}
}
if (src == NULL)
{
- bf_arr[min(255,numberOfBytes*8-unused)] = 0;
- proto_tree_add_text(tree, tvb, offset, lvt, "%sB'%s'", label, bf_arr);
+ bf_arr[MIN(255,numberOfBytes*8-unused)] = 0;
+ proto_tree_add_text(subtree, tvb, offset, lvt, "B'%s'", bf_arr);
}
offset+=lvt;
-
+
return offset;
}
}
/* handles generic application types, as well as enumerated and enumerations
- with reserved and proprietarty ranges (split) */
+ with reserved and proprietarty ranges (split) */
static guint
-fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, proto_tree *tree, guint offset,
+fApplicationTypesEnumeratedSplit (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
const gchar *label, const value_string *src, guint32 split_val)
{
guint8 tag_no, tag_info;
guint32 lvt;
guint tag_len;
- if (tvb_length_remaining(tvb, offset) > 0) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-
- switch (tag_no) {
- case 0: /** NULL 20.2.2 */
- offset = fNullTag(tvb, tree, offset, label);
- break;
- case 1: /** BOOLEAN 20.2.3 */
- offset = fBooleanTag(tvb, tree, offset, label);
- break;
- case 2: /** Unsigned Integer 20.2.4 */
- offset = fUnsignedTag(tvb, tree, offset, label);
- break;
- case 3: /** Signed Integer 20.2.5 */
- offset = fSignedTag(tvb, tree, offset, label);
- break;
- case 4: /** Real 20.2.6 */
- offset = fRealTag(tvb, tree, offset, label);
- break;
- case 5: /** Double 20.2.7 */
- offset = fDoubleTag(tvb, tree, offset, label);
- break;
- case 6: /** Octet String 20.2.8 */
- offset = fOctetString (tvb, tree, offset, label, lvt);
- break;
- case 7: /** Character String 20.2.9 */
- offset = fCharacterString (tvb,tree,offset,label);
- break;
- case 8: /** Bit String 20.2.10 */
- offset = fBitStringTagVS (tvb, tree, offset, label, src);
- break;
- case 9: /** Enumerated 20.2.11 */
- offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
- break;
- case 10: /** Date 20.2.12 */
- offset = fDate (tvb, tree, offset, label);
- break;
- case 11: /** Time 20.2.13 */
- offset = fTime (tvb, tree, offset, label);
- break;
- case 12: /** BACnetObjectIdentifier 20.2.14 */
- offset = fObjectIdentifier (tvb, tree, offset);
- break;
- case 13: /* reserved for ASHRAE */
- case 14:
- case 15:
- proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
- offset+=lvt+tag_len;
- break;
- default:
- break;
+ if (!tag_is_context_specific(tag_info))
+ {
+ switch (tag_no) {
+ case 0: /** NULL 20.2.2 */
+ offset = fNullTag(tvb, tree, offset, label);
+ break;
+ case 1: /** BOOLEAN 20.2.3 */
+ offset = fBooleanTag(tvb, tree, offset, label);
+ break;
+ case 2: /** Unsigned Integer 20.2.4 */
+ offset = fUnsignedTag(tvb, tree, offset, label);
+ break;
+ case 3: /** Signed Integer 20.2.5 */
+ offset = fSignedTag(tvb, tree, offset, label);
+ break;
+ case 4: /** Real 20.2.6 */
+ offset = fRealTag(tvb, tree, offset, label);
+ break;
+ case 5: /** Double 20.2.7 */
+ offset = fDoubleTag(tvb, tree, offset, label);
+ break;
+ case 6: /** Octet String 20.2.8 */
+ offset = fOctetString (tvb, tree, offset, label, lvt);
+ break;
+ case 7: /** Character String 20.2.9 */
+ offset = fCharacterString (tvb,tree,offset,label);
+ break;
+ case 8: /** Bit String 20.2.10 */
+ offset = fBitStringTagVS (tvb, tree, offset, label, src);
+ break;
+ case 9: /** Enumerated 20.2.11 */
+ offset = fEnumeratedTagSplit (tvb, tree, offset, label, src, split_val);
+ break;
+ case 10: /** Date 20.2.12 */
+ offset = fDate (tvb, tree, offset, label);
+ break;
+ case 11: /** Time 20.2.13 */
+ offset = fTime (tvb, tree, offset, label);
+ break;
+ case 12: /** BACnetObjectIdentifier 20.2.14 */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ break;
+ case 13: /* reserved for ASHRAE */
+ case 14:
+ case 15:
+ proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s'reserved for ASHRAE'", label);
+ offset+=lvt+tag_len;
+ break;
+ default:
+ break;
+ }
+
}
}
return offset;
}
static guint
-fApplicationTypesEnumerated (tvbuff_t *tvb, proto_tree *tree, guint offset,
+fShedLevel (tvbuff_t *tvb, proto_tree *tree, guint offset)
+{
+ guint lastoffset = 0;
+
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
+
+ switch (fTagNo(tvb,offset)) {
+ case 0: /* percent */
+ offset = fUnsignedTag (tvb, tree, offset, "shed percent: ");
+ break;
+ case 1: /* level */
+ offset = fUnsignedTag (tvb, tree, offset, "shed level: ");
+ break;
+ case 2: /* amount */
+ offset = fRealTag(tvb, tree, offset, "shed amount: ");
+ break;
+ default:
+ return offset;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ return offset;
+}
+
+static guint
+fApplicationTypesEnumerated (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
const gchar *label, const value_string *vs)
{
- return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, vs, 0);
+ return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, vs, 0);
}
static guint
-fApplicationTypes (tvbuff_t *tvb, proto_tree *tree, guint offset,
+fApplicationTypes (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
const gchar *label)
{
- return fApplicationTypesEnumeratedSplit(tvb, tree, offset, label, NULL, 0);
+ return fApplicationTypesEnumeratedSplit(tvb, pinfo, tree, offset, label, NULL, 0);
}
static guint
(void)label;
tag_len = fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt);
/* cap the the suggested length in case of bad data */
- tvb_len = tvb_length_remaining(tvb, offset+tag_len);
+ tvb_len = tvb_reported_length_remaining(tvb, offset+tag_len);
if ((tvb_len >= 0) && ((guint32)tvb_len < lvt))
{
lvt = tvb_len;
subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
-
+
return offset + tag_len + lvt;
}
static guint
-fAbstractSyntaxNType (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAbstractSyntaxNType (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint8 tag_no, tag_info;
guint32 lvt;
guint lastoffset = 0, depth = 0;
char ar[256];
-
+
if (propertyIdentifier >= 0)
{
g_snprintf (ar, sizeof(ar), "%s: ",
{
g_snprintf (ar, sizeof(ar), "Abstract Type: ");
}
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) { /* closing tag, but not for me */
/* Application Tags */
switch (propertyIdentifier) {
- case 2: /* BACnetActionList */
- offset = fActionList (tvb,tree,offset);
+ case 2: /* action */
+ /* loop object is application tagged,
+ command object is context tagged */
+ if (tag_is_context_specific(tag_info)) {
+ /* BACnetActionList */
+ offset = fActionList (tvb, pinfo, tree,offset);
+ } else {
+ /* BACnetAction */
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
+ BACnetAction);
+ }
break;
case 30: /* BACnetAddressBinding */
- offset = fAddressBinding (tvb,tree,offset);
+ offset = fAddressBinding (tvb,pinfo,tree,offset);
+ break;
+ case 54: /* list of object property reference */
+ offset = fLOPR (tvb, pinfo, tree,offset);
+ break;
+ case 55: /* list-of-session-keys */
+ fSessionKey (tvb, tree, offset);
break;
case 79: /* object-type */
case 96: /* protocol-object-types-supported */
- offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, ar,
+ offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset, ar,
BACnetObjectType, 128);
break;
case 97: /* Protocol-Services-Supported */
- offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
BACnetServicesSupported);
break;
+ case 102: /* recipient-list */
+ offset = fDestination (tvb, pinfo, tree, offset);
+ break;
case 107: /* segmentation-supported */
- offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
BACnetSegmentation);
break;
case 111: /* Status-Flags */
- offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
BACnetStatusFlags);
break;
case 112: /* System-Status */
- offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
BACnetDeviceStatus);
break;
case 117: /* units */
- offset = fApplicationTypesEnumerated (tvb, tree, offset, ar,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset, ar,
BACnetEngineeringUnits);
break;
- case 87: /* priority-array */
- offset = fPriorityArray (tvb, tree, offset);
+ case 87: /* priority-array -- accessed as a BACnetARRAY */
+ if (propertyArrayIndex == 0) {
+ /* BACnetARRAY index 0 refers to the length
+ of the array, not the elements of the array */
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
+ } else {
+ offset = fPriorityArray (tvb, pinfo, tree, offset);
+ }
break;
case 38: /* exception-schedule */
if (object_type < 128)
{
- offset = fSpecialEvent (tvb,tree,offset);
- break;
+ if (propertyArrayIndex == 0) {
+ /* BACnetARRAY index 0 refers to the length
+ of the array, not the elements of the array */
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
+ } else {
+ offset = fSpecialEvent (tvb,pinfo,tree,offset);
+ }
}
- case 123: /* weekly-schedule */
+ break;
+ case 19: /* controlled-variable-reference */
+ case 60: /* manipulated-variable-reference */
+ case 109: /* Setpoint-Reference */
+ case 132: /* log-device-object-property */
+ offset = fDeviceObjectPropertyReference (tvb, pinfo, tree, offset);
+ break;
+ case 123: /* weekly-schedule -- accessed as a BACnetARRAY */
if (object_type < 128)
{
- offset = fWeeklySchedule (tvb,tree,offset);
- break;
+ if (propertyArrayIndex == 0) {
+ /* BACnetARRAY index 0 refers to the length
+ of the array, not the elements of the array */
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
+ } else {
+ offset = fWeeklySchedule (tvb, pinfo, tree, offset);
+ }
}
+ break;
+ case 127: /* client COV increment */
+ offset = fClientCOV (tvb, pinfo, tree, offset);
+ break;
+ case 131: /* log-buffer */
+ offset = fLogRecord (tvb, pinfo, tree, offset);
+ break;
+ case 159: /* member-of */
+ case 165: /* zone-members */
+ offset = fDeviceObjectReference (tvb, pinfo, tree, offset);
+ break;
+ case 196: /* last-restart-reason */
+ offset = fRestartReason (tvb, pinfo, tree, offset);
+ break;
+ case 212: /* actual-shed-level */
+ case 214: /* expected-shed-level */
+ case 218: /* requested-shed-level */
+ offset = fShedLevel (tvb, tree, offset);
+ break;
default:
if (tag_info)
{
}
else
{
- offset = fApplicationTypes (tvb, tree, offset, ar);
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, ar);
}
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset)
+fPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tag_info)
+{
+ guint8 tag_no;
+ guint32 lvt;
+
+ if (tag_is_opening(tag_info)) {
+ offset += fTagHeaderTree(tvb, tree, offset,
+ &tag_no, &tag_info, &lvt);
+ offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ offset += fTagHeaderTree(tvb, tree, offset,
+ &tag_no, &tag_info, &lvt);
+ }
+ } else {
+ proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
+ "expected Opening Tag!"); \
+ offset = tvb_length(tvb);
+ }
+
+ return offset;
+}
+
+
+static guint
+fPropertyIdentifierValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset)
{
guint lastoffset = offset;
- proto_item *tt;
- proto_tree *subtree;
guint8 tag_no, tag_info;
guint32 lvt;
-
- offset = fPropertyReference(tvb, tree, offset, tagoffset, 0);
+
+ offset = fPropertyReference(tvb, pinfo, tree, offset, tagoffset, 0);
if (offset > lastoffset)
{
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_no == tagoffset+2) { /* Value - might not be present in ReadAccessResult */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(tree, tvb, offset, 1, "propertyValue");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
- offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- }
+ offset = fPropertyValue (tvb, pinfo, tree, offset, tag_info);
}
}
return offset;
}
static guint
-fBACnetPropertyValue (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fBACnetPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- offset = fPropertyValue(tvb, tree, offset, 0);
+ offset = fPropertyIdentifierValue(tvb, pinfo, tree, offset, 0);
if (offset > lastoffset)
{
/* detect optional priority
if (tag_is_context_specific(tag_info) && (tag_no == 3))
offset = fUnsignedTag (tvb,tree,offset,"Priority: ");
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fSubscribeCOVPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+ proto_tree *subtree = tree;
+ proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
- switch (fTagNo(tvb,offset)) {
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info)) {
+ offset += len;
+ subtree = tree;
+ continue;
+ }
+
+ switch (tag_no) {
case 0: /* ProcessId */
offset = fUnsignedTag (tvb, tree, offset, "subscriber Process Id: ");
break;
case 1: /* monitored ObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 2: /* issueConfirmedNotifications */
offset = fBooleanTag (tvb, tree, offset, "issue Confirmed Notifications: ");
offset = fTimeSpan (tvb,tree,offset,"life time");
break;
case 4: /* monitoredPropertyIdentifier */
- offset = fBACnetPropertyReference (tvb, tree, offset, 0);
+ if (tag_is_opening(tag_info)) {
+ tt = proto_tree_add_text(subtree, tvb, offset, 1, "monitoredPropertyIdentifier");
+ if (tt) {
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ }
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
+ break;
+ }
+ FAULT;
break;
case 5: /* covIncrement */
offset = fRealTag (tvb, tree, offset, "COV Increment: ");
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fSubscribeCOVRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fSubscribeCOVRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fSubscribeCOVPropertyRequest(tvb, tree, offset);
+ return fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
}
static guint
-fWhoHas (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWhoHas (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb, offset)) {
case 0: /* deviceInstanceLowLimit */
offset = fUnsignedTag (tvb, tree, offset, "device Instance Low Limit: ");
offset = fUnsignedTag (tvb, tree, offset, "device Instance High Limit: ");
break;
case 2: /* BACnetObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
- break;
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ break;
case 3: /* messageText */
offset = fCharacterString (tvb,tree,offset, "Object Name: ");
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fDailySchedule (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fDailySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
-
+
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_opening(tag_info) && tag_no == 0)
{
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); /* opening context tag 0 */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) {
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
return offset;
}
-
- offset = fTimeValue (tvb, subtree, offset);
+
+ offset = fTimeValue (tvb, pinfo, subtree, offset);
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
}
else if (tag_no == 0 && lvt == 0)
}
static guint
-fWeeklySchedule (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWeeklySchedule (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- guint i=1;
+ guint i = 1; /* day of week array index */
proto_tree *subtree = tree;
proto_item *tt;
-
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+
+ if (propertyArrayIndex > 0) {
+ /* BACnetARRAY index 0 refers to the length
+ of the array, not the elements of the array.
+ BACnetARRAY index -1 is our internal flag that
+ the optional index was not used.
+ BACnetARRAY refers to this as all elements of the array.
+ If the optional index is specified for a BACnetARRAY,
+ then that specific array element is referenced. */
+ i = propertyArrayIndex;
+ }
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) {
return offset; /* outer encoding will print out closing tag */
}
- tt = proto_tree_add_text(tree, tvb, offset, 0, val_to_str(i++, days, "day of week (%d) not found"));
+ tt = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str(i++, day_of_week, "day of week (%d) not found"));
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset = fDailySchedule (tvb,subtree,offset);
+ offset = fDailySchedule (tvb, pinfo, subtree, offset);
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
fUTCTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
{
- if (tvb_length_remaining(tvb, offset) <= 0)
+ if (tvb_reported_length_remaining(tvb, offset) <= 0)
return offset;
-
+
return fDateTime (tvb, tree, offset, "UTC-Time: ");
}
static guint
fTimeSynchronizationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
{
- if (tvb_length_remaining(tvb, offset) <= 0)
+ if (tvb_reported_length_remaining(tvb, offset) <= 0)
return offset;
return fDateTime (tvb, tree, offset, NULL);
static guint
fDateRange (tvbuff_t *tvb, proto_tree *tree, guint offset)
{
- if (tvb_length_remaining(tvb, offset) <= 0)
+ if (tvb_reported_length_remaining(tvb, offset) <= 0)
return offset;
- offset = fDate (tvb,tree,offset,"Start Date: ");
+ offset = fDate (tvb,tree,offset,"Start Date: ");
return fDate (tvb, tree, offset, "End Date: ");
}
static guint
-fConfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVendorIdentifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+ guint32 val = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+ guint tag_len;
+ proto_item *ti;
+ proto_tree *subtree;
+ const gchar *label = "Vendor ID";
+
+ tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (fUnsigned32 (tvb, offset + tag_len, lvt, &val))
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+ "%s: %s (%u)", label,
+ val_to_str(val,BACnetVendorIdentifiers,"Unknown Vendor"), val);
+ else
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+ "%s - %u octets (Unsigned)", label, lvt);
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+
+ if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1 and <= 2 are supported */
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, lvt, "Wrong length indicated. Expected 1 or 2, got %u", lvt);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1 or 2, got %u", lvt);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return offset+tag_len+lvt;
+ }
+
+ proto_tree_add_item(subtree, hf_BACnetVendorIdentifier, tvb,
+ offset+tag_len, lvt, FALSE);
+
+ return offset+tag_len+lvt;
+}
+
+static guint
+fRestartReason (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+ guint32 val = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+ guint tag_len;
+ proto_item *ti;
+ proto_tree *subtree;
+ const gchar *label = "Restart Reason";
+
+ tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (fUnsigned32 (tvb, offset + tag_len, lvt, &val))
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+ "%s: %s (%u)", label,
+ val_to_str(val,BACnetRestartReason,"Unknown reason"), val);
+ else
+ ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+ "%s - %u octets (Unsigned)", label, lvt);
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+
+ if (lvt != 1) {
+ proto_item *expert_item;
+ expert_item = proto_tree_add_text(tree, tvb, 0, lvt, "Wrong length indicated. Expected 1, got %u", lvt);
+ expert_add_info_format(pinfo, expert_item, PI_MALFORMED, PI_ERROR, "Wrong length indicated. Expected 1, got %u", lvt);
+ PROTO_ITEM_SET_GENERATED(expert_item);
+ return offset+tag_len+lvt;
+ }
+
+ proto_tree_add_item(subtree, hf_BACnetRestartReason, tvb,
+ offset+tag_len, lvt, FALSE);
+
+ return offset+tag_len+lvt;
+}
+
+static guint
+fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* textMessageSourceDevice */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* messageClass */
switch (fTagNo(tvb, offset)) {
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fUnconfirmedTextMessageRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fConfirmedTextMessageRequest(tvb, tree, offset);
+ return fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
}
static guint
-fConfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
proto_item *tt;
- /* exit loop if nothing happens inside */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) {
+ /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) {
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) {
if (tag_no == 2) /* Make sure it's the expected tag */
{
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
+ offset += len;
subtree = tree;
continue;
}
switch (tag_no) {
case 0: /* vendorID */
- offset = fUnsignedTag (tvb, subtree, offset, "vendor ID: ");
+ offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* serviceNumber */
offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
propertyIdentifier = -1;
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
+ offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
break;
}
FAULT;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fConfirmedPrivateTransferRequest(tvb, tree, offset);
+ return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
}
static guint
-fConfirmedPrivateTransferAck(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedPrivateTransferAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fConfirmedPrivateTransferRequest(tvb, tree, offset);
+ return fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
}
static guint
-fLifeSafetyOperationRequest(tvbuff_t *tvb, proto_tree *tree, guint offset, const gchar *label)
+fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
}
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
-
+
switch (tag_no) {
case 0: /* subscriberProcessId */
offset = fUnsignedTag (tvb, subtree, offset, "requesting Process Id: ");
offset = fCharacterString (tvb, tree, offset, "requesting Source: ");
break;
case 2: /* request */
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"request: ", BACnetLifeSafetyOperation, 64);
break;
case 3: /* objectId */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
-static guint fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint
+fBACnetPropertyStates(tvbuff_t *tvb, proto_tree *tree, guint offset)
{
switch (fTagNo(tvb, offset))
{
offset = fBooleanTag (tvb, tree, offset, "boolean-value: ");
break;
case 1:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"binary-value: ", BACnetBinaryPV, 2);
break;
case 2:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"event-type: ", BACnetEventType, 12);
break;
case 3:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"polarity: ", BACnetPolarity, 2);
break;
case 4:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"program-change: ", BACnetProgramRequest, 5);
break;
case 5:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"program-state: ", BACnetProgramState, 5);
break;
case 6:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"reason-for-halt: ", BACnetProgramError, 5);
break;
case 7:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"reliability: ", BACnetReliability, 10);
break;
case 8:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"state: ", BACnetEventState, 64);
break;
case 9:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"system-status: ", BACnetDeviceStatus, 64);
break;
case 10:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"units: ", BACnetEngineeringUnits, 2);
break;
case 11:
offset = fUnsignedTag(tvb, tree, offset, "unsigned-value: ");
break;
case 12:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"life-safety-mode: ", BACnetLifeSafetyMode, 64);
break;
case 13:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"life-safety-state: ", BACnetLifeSafetyState, 64);
break;
default:
return offset;
}
+
+/*
+BACnetDeviceObjectPropertyValue ::= SEQUENCE {
+ deviceIdentifier [0] BACnetObjectIdentifier,
+ objectIdentifier [1] BACnetObjectIdentifier,
+ propertyIdentifier [2] BACnetPropertyIdentifier,
+ arrayIndex [3] Unsigned OPTIONAL,
+ value [4] ABSTRACT-SYNTAX.&Type
+ }
+*/
+static guint
+fDeviceObjectPropertyValue (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+ guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ lastoffset = offset;
+ /* check the tag. A closing tag means we are done */
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info)) {
+ return offset;
+ }
+ switch (tag_no) {
+ case 0: /* deviceIdentifier */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ break;
+ case 1: /* objectIdentifier */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ break;
+ case 2: /* propertyIdentifier */
+ offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
+ break;
+ case 3: /* arrayIndex - OPTIONAL */
+ offset = fUnsignedTag (tvb, tree, offset,
+ "arrayIndex: ");
+ break;
+ case 4: /* value */
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ break;
+ default:
+ return offset;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ return offset;
+}
+
+
+/*
+BACnetDeviceObjectPropertyReference ::= SEQUENCE {
+ objectIdentifier [0] BACnetObjectIdentifier,
+ propertyIdentifier [1] BACnetPropertyIdentifier,
+ propertyArrayIndex [2] Unsigned OPTIONAL, -- used only with array datatype
+ -- if omitted with an array then
+ -- the entire array is referenced
+ deviceIdentifier [3] BACnetObjectIdentifier OPTIONAL
+ }
+*/
+static guint
+fDeviceObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+ guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ lastoffset = offset;
+ /* check the tag. A closing tag means we are done */
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info)) {
+ return offset;
+ }
+ switch (tag_no) {
+ case 0: /* objectIdentifier */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ break;
+ case 1: /* propertyIdentifier */
+ offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
+ break;
+ case 2: /* arrayIndex - OPTIONAL */
+ offset = fUnsignedTag (tvb, tree, offset,
+ "arrayIndex: ");
+ break;
+ case 3: /* deviceIdentifier - OPTIONAL */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+ break;
+ default:
+ return offset;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ return offset;
+}
+
static guint
-fNotificationParameters (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fNotificationParameters (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = offset;
guint8 tag_no, tag_info;
proto_tree *subtree = tree;
proto_item *tt;
- tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters");
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters (%d) %s",
+ tag_no, val_to_str(tag_no, BACnetEventType, "invalid type"));
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- /* Opeing tag for parameter choice */
+ /* Opening tag for parameter choice */
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
switch (tag_no) {
case 0: /* change-of-bitstring */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
- offset = fBitStringTag (tvb, subtree, offset,
+ offset = fBitStringTag (tvb, subtree, offset,
"referenced-bitstring: ");
break;
case 1:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
+ lastoffset = offset;
break;
default:
- return offset;
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
case 1: /* change-of-state */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
offset = fBACnetPropertyStates(tvb, subtree, offset);
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ break;
case 1:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
lastoffset = offset;
break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
- case 2: /* change-of-value */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ case 2: /* change-of-value */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
switch (fTagNo(tvb, offset)) {
case 0:
- offset = fBitStringTag (tvb, subtree, offset,
+ offset = fBitStringTag (tvb, subtree, offset,
"changed-bits: ");
break;
case 1:
- offset = fRealTag (tvb, subtree, offset,
+ offset = fRealTag (tvb, subtree, offset,
"changed-value: ");
break;
default:
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
case 1:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
+ lastoffset = offset;
break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
- case 3: /* command-failure */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ case 3: /* command-failure */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* "command-value: " */
+ /* from BACnet Table 13-3,
+ Standard Object Property Values Returned in Notifications */
+ propertyIdentifier = 85; /* PRESENT_VALUE */
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
+ offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
case 1:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
+ break;
case 2: /* "feedback-value: " */
+ propertyIdentifier = 40; /* FEEDBACK_VALUE */
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
+ offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ lastoffset = offset;
+ break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
- case 4: /* floating-limit */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ case 4: /* floating-limit */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fRealTag (tvb, subtree, offset, "reference-value: ");
break;
case 1:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
break;
case 2:
break;
case 3:
offset = fRealTag (tvb, subtree, offset, "error-limit: ");
+ lastoffset = offset;
+ break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
- case 5: /* out-of-range */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ case 5: /* out-of-range */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fRealTag (tvb, subtree, offset, "exceeding-value: ");
break;
case 1:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
break;
case 2:
break;
case 3:
offset = fRealTag (tvb, subtree, offset, "exceeded-limit: ");
+ lastoffset = offset;
+ break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
case 6:
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- offset =fBACnetPropertyValue (tvb,subtree,offset);
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
+ offset =fBACnetPropertyValue (tvb,pinfo,subtree,offset);
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
case 7: /* buffer-ready */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
- offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-device */
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset); /* buffer-device */
break;
case 1:
- offset = fObjectIdentifier (tvb, subtree, offset); /* buffer-object */
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset); /* buffer-object */
break;
case 2:
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
offset = fDateTime (tvb, subtree, offset, "current-notification: ");
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ lastoffset = offset;
+ break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
break;
- case 8: /* change-of-life-safety */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ case 8: /* change-of-life-safety */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
- offset = fEnumeratedTagSplit (tvb, subtree, offset,
+ offset = fEnumeratedTagSplit (tvb, subtree, offset,
"new-state: ", BACnetLifeSafetyState, 256);
break;
case 1:
- offset = fEnumeratedTagSplit (tvb, subtree, offset,
- "new-mode: ", BACnetLifeSafetyState, 256);
+ offset = fEnumeratedTagSplit (tvb, subtree, offset,
+ "new-mode: ", BACnetLifeSafetyMode, 256);
break;
case 2:
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fBitStringTagVS (tvb, subtree, offset,
"status-flags: ", BACnetStatusFlags);
+ break;
case 3:
- offset = fEnumeratedTagSplit (tvb, subtree, offset,
+ offset = fEnumeratedTagSplit (tvb, subtree, offset,
"operation-expected: ", BACnetLifeSafetyOperation, 64);
+ lastoffset = offset;
+ break;
default:
- return offset;
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
- break;
+ break;
+ case 9: /* extended */
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ lastoffset = offset;
+ switch (fTagNo(tvb, offset)) {
+ case 0:
+ offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
+ break;
+ case 1:
+ offset = fUnsignedTag (tvb, subtree, offset,
+ "extended-event-type: ");
+ break;
+ case 2: /* parameters */
+ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fApplicationTypes(tvb, pinfo, subtree, offset, "parameters: ");
+ offset = fDeviceObjectPropertyValue(tvb, pinfo, subtree, offset);
+ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ lastoffset = offset;
+ break;
+ default:
+ break;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ break;
+ case 10: /* buffer ready */
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ lastoffset = offset;
+ switch (fTagNo(tvb, offset)) {
+ case 0: /* buffer-property */
+ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fDeviceObjectPropertyReference (tvb, pinfo, subtree, offset);
+ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ break;
+ case 1:
+ offset = fUnsignedTag (tvb, subtree, offset,
+ "previous-notification: ");
+ break;
+ case 2:
+ offset = fUnsignedTag (tvb, subtree, offset,
+ "current-notification: ");
+ lastoffset = offset;
+ break;
+ default:
+ break;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ break;
+ case 11: /* unsigned range */
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ lastoffset = offset;
+ switch (fTagNo(tvb, offset)) {
+ case 0:
+ offset = fUnsignedTag (tvb, subtree, offset,
+ "exceeding-value: ");
+ break;
+ case 1:
+ offset = fBitStringTagVS (tvb, subtree, offset,
+ "status-flags: ", BACnetStatusFlags);
+ break;
+ case 2:
+ offset = fUnsignedTag (tvb, subtree, offset,
+ "exceeded-limit: ");
+ lastoffset = offset;
+ break;
+ default:
+ break;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ break;
default:
break;
}
+
/* Closing tag for parameter choice */
offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* change-of-bitstring */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
return offset;
}
}
- break;
+ break;
case 1: /* change-of-state */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fTimeSpan (tvb, tree, offset, "Time Delay");
break;
case 1: /* SEQUENCE OF BACnetPropertyStates */
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"value: ", BACnetPropertyStates, 64);
break;
default:
}
}
break;
- case 2: /* change-of-value */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ case 2: /* change-of-value */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fTimeSpan (tvb, tree, offset, "Time Delay");
offset = fBitStringTag (tvb, tree, offset, "bitmask: ");
break;
case 1:
- offset = fRealTag (tvb, tree, offset,
+ offset = fRealTag (tvb, tree, offset,
"referenced Property Increment: ");
break;
default:
return offset;
}
}
- break;
- case 3: /* command-failure */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ break;
+ case 3: /* command-failure */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fTimeSpan (tvb, tree, offset, "Time Delay");
break;
case 1:
- offset = fDeviceObjectPropertyReference (tvb,tree,offset);
+ offset = fDeviceObjectPropertyReference (tvb,pinfo,tree,offset);
default:
return offset;
}
}
- break;
- case 4: /* floating-limit */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ break;
+ case 4: /* floating-limit */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fTimeSpan (tvb, tree, offset, "Time Delay");
break;
case 1:
- offset = fDeviceObjectPropertyReference (tvb,tree,offset);
+ offset = fDeviceObjectPropertyReference (tvb,pinfo,tree,offset);
break;
case 2:
offset = fRealTag (tvb, tree, offset, "low diff limit: ");
}
break;
case 5: /* out-of-range */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
return offset;
}
}
- break;
+ break;
case 6:
- offset = fBACnetPropertyValue (tvb,tree,offset);
+ offset = fBACnetPropertyValue (tvb,pinfo,tree,offset);
break;
case 7: /* buffer-ready */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
return offset;
}
}
- break;
+ break;
case 8: /* change-of-life-safety */
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0:
offset = fTimeSpan (tvb, tree, offset, "Time Delay");
break;
case 1:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"life safety alarm value: ", BACnetLifeSafetyState, 256);
break;
case 2:
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"alarm value: ", BACnetLifeSafetyState, 256);
break;
case 3:
- offset = fDeviceObjectPropertyReference (tvb, tree, offset);
+ offset = fDeviceObjectPropertyReference (tvb, pinfo, tree, offset);
break;
default:
return offset;
}
return offset;
}
+#endif
static guint
-fLogRecord (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fLogRecord (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* timestamp */
- offset = fDateTime (tvb,tree,offset,NULL);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fDate (tvb,tree,offset,"Date: ");
+ offset = fTime (tvb,tree,offset,"Time: ");
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
case 1: /* logDatum: don't loop, it's a CHOICE */
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
switch (fTagNo(tvb, offset)) {
case 0: /* logStatus */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fEnumeratedTag (tvb, tree, offset,
"log status: ", BACnetLogStatus);
break;
case 1:
offset = fNullTag(tvb, tree, offset, "null value: ");
break;
case 8:
- offset = fError (tvb,tree,offset);
+ offset = fError (tvb, pinfo, tree, offset);
break;
case 9:
offset = fRealTag (tvb, tree, offset, "time change: ");
break;
case 10: /* any Value */
- offset = fAbstractSyntaxNType (tvb, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
default:
return offset;
}
- break;
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ break;
case 2:
- offset = fEnumeratedTag (tvb, tree, offset,
- "status Flags: ", BACnetStatusFlags);
+ offset = fEnumeratedTag (tvb, tree, offset,
+ "Status Flags: ", BACnetStatusFlags);
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
-#endif
+
static guint
-fConfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb,offset)) {
case 0: /* ProcessId */
offset = fProcessId (tvb,tree,offset);
break;
case 1: /* initiating ObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 2: /* event ObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 3: /* time stamp */
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = fTimeStamp (tvb, tree, offset);
+ offset = fTimeStamp (tvb, tree, offset, NULL);
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
case 4: /* notificationClass */
offset = fUnsignedTag (tvb, tree, offset, "Priority: ");
break;
case 6: /* EventType */
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"Event Type: ", BACnetEventType, 64);
break;
case 7: /* messageText */
offset = fBooleanTag (tvb, tree, offset, "ack Required: ");
break;
case 10: /* fromState */
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"from State: ", BACnetEventState, 64);
break;
case 11: /* toState */
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"to State: ", BACnetEventState, 64);
break;
case 12: /* NotificationParameters */
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = fNotificationParameters (tvb, tree, offset);
+ offset = fNotificationParameters (tvb, pinfo, tree, offset);
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedEventNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fConfirmedEventNotificationRequest (tvb, tree, offset);
+ return fConfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
}
static guint
-fConfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info)) {
+ offset += len;
subtree = tree;
continue;
}
-
+
switch (tag_no) {
case 0: /* ProcessId */
offset = fProcessId (tvb,tree,offset);
break;
- case 1: /* initiating ObjectId */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ case 1: /* initiating DeviceId */
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* monitored ObjectId */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 3: /* time remaining */
offset = fTimeSpan (tvb, tree, offset, "Time remaining");
tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fBACnetPropertyValue (tvb, subtree, offset);
+ offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
break;
}
FAULT;
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fUnconfirmedCOVNotificationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fConfirmedCOVNotificationRequest (tvb, tree, offset);
+ return fConfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
}
static guint
-fAcknowledgeAlarmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAcknowledgeAlarmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no = 0, tag_info = 0;
guint32 lvt = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* acknowledgingProcessId */
offset = fUnsignedTag (tvb, tree, offset, "acknowledging Process Id: ");
break;
case 1: /* eventObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 2: /* eventStateAcknowledged */
- offset = fEnumeratedTagSplit (tvb, tree, offset,
+ offset = fEnumeratedTagSplit (tvb, tree, offset,
"event State Acknowledged: ", BACnetEventState, 64);
break;
case 3: /* timeStamp */
offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = fTimeStamp(tvb, tree, offset);
+ offset = fTimeStamp(tvb, tree, offset, NULL);
offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
case 4: /* acknowledgementSource */
break;
case 5: /* timeOfAcknowledgement */
offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = fTimeStamp(tvb, tree, offset);
+ offset = fTimeStamp(tvb, tree, offset, "acknowledgement timestamp: ");
offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fGetAlarmSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetAlarmSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
- offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
+ offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
"alarm State: ", BACnetEventState, 64);
- offset = fApplicationTypesEnumerated (tvb, tree, offset,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
"acknowledged Transitions: ", BACnetEventTransitionBits);
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fGetEnrollmentSummaryRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEnrollmentSummaryRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* acknowledgmentFilter */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fEnumeratedTag (tvb, tree, offset,
"acknowledgment Filter: ", BACnetAcknowledgementFilter);
break;
- case 1: /* eventObjectId */
+ case 1: /* eventObjectId - OPTIONAL */
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fRecipientProcess (tvb, pinfo, tree, offset);
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = fRecipientProcess (tvb, tree, offset);
break;
case 2: /* eventStateFilter */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fEnumeratedTag (tvb, tree, offset,
"event State Filter: ", BACnetEventStateFilter);
break;
- case 3: /* eventTypeFilter */
- offset = fEnumeratedTag (tvb, tree, offset,
+ case 3: /* eventTypeFilter - OPTIONAL */
+ offset = fEnumeratedTag (tvb, tree, offset,
"event Type Filter: ", BACnetEventType);
break;
case 4: /* priorityFilter */
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
offset = fUnsignedTag (tvb, tree, offset, "min Priority: ");
offset = fUnsignedTag (tvb, tree, offset, "max Priority: ");
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
- case 5: /* notificationClassFilter */
+ case 5: /* notificationClassFilter - OPTIONAL */
offset = fUnsignedTag (tvb, tree, offset, "notification Class Filter: ");
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fGetEnrollmentSummaryAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEnrollmentSummaryAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
- offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
+ offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
"event Type: ", BACnetEventType, 64);
- offset = fApplicationTypesEnumerated (tvb, tree, offset,
- "event State: ", BACnetEventStateFilter);
- offset = fApplicationTypes (tvb, tree, offset, "Priority: ");
- offset = fApplicationTypes (tvb, tree, offset, "Notification Class: ");
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
+ "event State: ", BACnetEventState);
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Priority: ");
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Notification Class: ");
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fGetEventInformationRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEventInformationRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
-
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- switch (fTagNo(tvb, offset)) {
- case 0: /* lastReceivedObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
- break;
- default:
- return offset;
- break;
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ if (fTagNo(tvb, offset) == 0) {
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
}
}
return offset;
}
static guint
-flistOfEventSummaries (tvbuff_t *tvb, proto_tree *tree, guint offset)
+flistOfEventSummaries (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+ proto_tree* subtree = tree;
+ proto_item* ti = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- switch (fTagNo(tvb, offset)) {
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* we are finished here if we spot a closing tag */
+ if (tag_is_closing(tag_info)) {
+ break;
+ }
+ switch (tag_no) {
case 0: /* ObjectId */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* eventState */
- offset = fEnumeratedTag (tvb, tree, offset,
- "event State: ", BACnetEventStateFilter);
+ offset = fEnumeratedTag (tvb, tree, offset,
+ "event State: ", BACnetEventState);
break;
case 2: /* acknowledgedTransitions */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fBitStringTagVS (tvb, tree, offset,
"acknowledged Transitions: ", BACnetEventTransitionBits);
break;
case 3: /* eventTimeStamps */
- offset = fTime (tvb, tree, offset, "time Stamp: ");
- offset = fTime (tvb, tree, offset, "time Stamp: ");
- offset = fTime (tvb, tree, offset, "time Stamp: ");
+ ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
+ if (ti) {
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ }
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fTimeStamp (tvb, subtree, offset,"TO-OFFNORMAL timestamp: ");
+ offset = fTimeStamp (tvb, subtree, offset,"TO-FAULT timestamp: ");
+ offset = fTimeStamp (tvb, subtree, offset,"TO-NORMAL timestamp: ");
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
case 4: /* notifyType */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fEnumeratedTag (tvb, tree, offset,
"Notify Type: ", BACnetNotifyType);
break;
case 5: /* eventEnable */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fBitStringTagVS (tvb, tree, offset,
"event Enable: ", BACnetEventTransitionBits);
break;
case 6: /* eventPriorities */
- offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
- offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
- offset = fUnsignedTag (tvb, tree, offset, "event Priority: ");
+ ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventPriorities");
+ if (ti) {
+ subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+ }
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fUnsignedTag (tvb, subtree, offset, "TO-OFFNORMAL Priority: ");
+ offset = fUnsignedTag (tvb, subtree, offset, "TO-FAULT Priority: ");
+ offset = fUnsignedTag (tvb, subtree, offset, "TO-NORMAL Priority: ");
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
default:
return offset;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
+ }
+ return offset;
+}
+
+static guint
+fLOPR (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
+{
+ guint lastoffset = 0;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
+
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
+ lastoffset = offset;
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* we are finished here if we spot a closing tag */
+ if (tag_is_closing(tag_info)) {
break;
}
+ offset = fDeviceObjectPropertyReference(tvb, pinfo, tree, offset);
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fGetEventInformationACK (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fGetEventInformationACK (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* listOfEventSummaries */
offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
- offset = flistOfEventSummaries (tvb, tree, offset);
+ offset = flistOfEventSummaries (tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
case 1: /* moreEvents */
offset = fBooleanTag (tvb, tree, offset, "more Events: ");
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fAddListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
+ offset += len;
subtree = tree;
continue;
}
-
+
switch (tag_no) {
case 0: /* ObjectId */
- offset = fBACnetObjectPropertyReference (tvb, subtree, offset);
+ offset = fBACnetObjectPropertyReference (tvb, pinfo, subtree, offset);
break;
case 3: /* listOfElements */
if (tag_is_opening(tag_info)) {
tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
+ offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
break;
}
FAULT;
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fDeleteObjectRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fDeleteObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fObjectIdentifier (tvb, tree, offset);
+ return fObjectIdentifier (tvb, pinfo, tree, offset);
}
static guint
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb, offset)) {
case 0: /* timeDuration */
offset = fUnsignedTag (tvb,tree,offset,"time Duration: ");
offset = fEnumeratedTag (tvb, tree, offset, "enable-disable: ",
BACnetEnableDisable);
break;
- case 2: /* password */
+ case 2: /* password - OPTIONAL */
offset = fCharacterString (tvb, tree, offset, "Password: ");
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb, offset)) {
case 0: /* reinitializedStateOfDevice */
- offset = fEnumeratedTag (tvb, tree, offset,
- "reinitialized State Of Device: ",
+ offset = fEnumeratedTag (tvb, tree, offset,
+ "reinitialized State Of Device: ",
BACnetReinitializedStateOfDevice);
break;
- case 1: /* password */
+ case 1: /* password - OPTIONAL */
offset = fCharacterString (tvb, tree, offset, "Password: ");
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fVtOpenRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtOpenRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- offset = fApplicationTypesEnumerated (tvb, tree, offset,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
"vtClass: ", BACnetVTClass);
- return fApplicationTypes (tvb,tree,offset,"local VT Session ID: ");
+ return fApplicationTypes (tvb, pinfo, tree,offset,"local VT Session ID: ");
}
static guint
-fVtOpenAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtOpenAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
+ return fApplicationTypes (tvb, pinfo, tree,offset,"remote VT Session ID: ");
}
static guint
-fVtCloseRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtCloseRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- offset= fApplicationTypes (tvb,tree,offset,"remote VT Session ID: ");
+ offset= fApplicationTypes (tvb, pinfo, tree,offset,"remote VT Session ID: ");
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fVtDataRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVtDataRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- offset= fApplicationTypes (tvb,tree,offset,"VT Session ID: ");
- offset = fApplicationTypes (tvb, tree, offset, "VT New Data: ");
- return fApplicationTypes (tvb,tree,offset,"VT Data Flag: ");;
+ offset= fApplicationTypes (tvb, pinfo, tree,offset,"VT Session ID: ");
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "VT New Data: ");
+ return fApplicationTypes (tvb, pinfo, tree,offset,"VT Data Flag: ");;
}
static guint
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb,offset)) {
case 0: /* BOOLEAN */
offset = fBooleanTag (tvb, tree, offset, "all New Data Accepted: ");
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb,offset)) {
case 0: /* Unsigned32 */
offset = fUnsignedTag (tvb, tree, offset, "pseudo Random Number: ");
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fAuthenticateAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAuthenticateAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fApplicationTypes (tvb, tree, offset, "modified Random Number: ");
+ return fApplicationTypes (tvb, pinfo, tree, offset, "modified Random Number: ");
}
static guint
-fRequestKeyRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRequestKeyRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- offset = fObjectIdentifier (tvb, tree, offset); /* Requesting Device Identifier */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* Requesting Device Identifier */
offset = fAddress (tvb, tree, offset);
- offset = fObjectIdentifier (tvb, tree, offset); /* Remote Device Identifier */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* Remote Device Identifier */
return fAddress (tvb, tree, offset);
}
static guint
-fRemoveListElementRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fRemoveListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
/* Same as AddListElement request after service choice */
- return fAddListElementRequest(tvb, tree, offset);
+ return fAddListElementRequest(tvb, pinfo, tree, offset);
}
static guint
-fReadPropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fBACnetObjectPropertyReference(tvb, tree, offset);
+ return fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
}
static guint
-fReadPropertyAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
- proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ /* set the optional global properties to indicate not-used */
+ propertyArrayIndex = -1;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
+ offset += len;
subtree = tree;
continue;
}
switch (tag_no) {
case 0: /* objectIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* propertyIdentifier */
- offset = fPropertyIdentifier (tvb, subtree, offset);
+ offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* propertyArrayIndex */
- offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
+ offset = fPropertyArrayIndex (tvb, subtree, offset);
break;
case 3: /* propertyValue */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
- break;
- }
- FAULT;
+ offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
break;
default:
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fWritePropertyRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWritePropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
- proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ /* set the optional global properties to indicate not-used */
+ propertyArrayIndex = -1;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* quit loop if we spot a closing tag */
if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
subtree = tree;
- continue;
+ break;
}
-
+
switch (tag_no) {
case 0: /* objectIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* propertyIdentifier */
- offset = fPropertyIdentifier (tvb, subtree, offset);
+ offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* propertyArrayIndex */
- offset = fSignedTag (tvb, subtree, offset, "property Array Index: ");
+ offset = fPropertyArrayIndex (tvb, subtree, offset);
break;
case 3: /* propertyValue */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
- break;
- }
- FAULT;
+ offset = fPropertyValue (tvb, pinfo, subtree, offset, tag_info);
break;
case 4: /* Priority (only used for write) */
- offset = fSignedTag (tvb, subtree, offset, "Priority: ");
+ offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fWriteAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fWriteAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* maybe a listOfwriteAccessSpecifications if we spot a closing tag */
+ if (tag_is_closing(tag_info)) {
+ offset += len;
continue;
}
-
+
switch (tag_no) {
case 0: /* objectIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* listOfPropertyValues */
if (tag_is_opening(tag_info)) {
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fBACnetPropertyValue (tvb, subtree, offset);
+ offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
break;
}
FAULT;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fWritePropertyMultipleRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWritePropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
if (offset >= tvb_reported_length(tvb))
return offset;
- return fWriteAccessSpecification (tvb, tree, offset);
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ return fWriteAccessSpecification (tvb, pinfo, tree, offset);
}
static guint
-fPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
+fPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 tagoffset, guint8 list)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ /* set the optional global properties to indicate not-used */
+ propertyArrayIndex = -1;
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) { /* closing Tag, but not for me */
return offset;
+ } else if (tag_is_opening(tag_info)) { /* opening Tag, but not for me */
+ return offset;
}
switch (tag_no-tagoffset) {
case 0: /* PropertyIdentifier */
- offset = fPropertyIdentifier (tvb, tree, offset);
+ offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* propertyArrayIndex */
- offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
+ offset = fPropertyArrayIndex (tvb, tree, offset);
if (list != 0) break; /* Continue decoding if this may be a list */
default:
lastoffset = offset; /* Set loop end condition */
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fBACnetPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset, guint8 list)
+fBACnetPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 list)
{
- return fPropertyReference(tvb, tree, offset, 0, list);
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ return fPropertyReference(tvb, pinfo, tree, offset, 0, list);
}
static guint
-fBACnetObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fBACnetObjectPropertyReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb,offset)) {
case 0: /* ObjectIdentifier */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* PropertyIdentifier and propertyArrayIndex */
- offset = fPropertyReference (tvb, tree, offset, 1, 0);
+ offset = fPropertyReference (tvb, pinfo, tree, offset, 1, 0);
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
default:
lastoffset = offset; /* Set loop end condition */
break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
proto_tree* subtree = tree;
proto_item* tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
if (tag_is_closing(tag_info)) {
}
switch (tag_no) {
case 0: /* ObjectIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* PropertyIdentifier */
- offset = fPropertyIdentifier (tvb, subtree, offset);
+ offset = fPropertyIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* propertyArrayIndex */
offset = fUnsignedTag (tvb, subtree, offset, "property Array Index: ");
break;
case 3: /* Value */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyValue");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
- break;
- }
- FAULT;
+ offset = fPropertyValue (tvb, subtree, offset, tag_info);
break;
case 4: /* Priority */
- offset = fSignedTag (tvb, subtree, offset, "Priority: ");
+ offset = fUnsignedTag (tvb, subtree, offset, "Priority: ");
break;
default:
break;
}
#endif
-#if 0
static guint
-fDeviceObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fPriorityArray (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
+ char i = 1, ar[256];
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
-
- switch (fTagNo(tvb,offset)) {
- case 0: /* ObjectIdentifier */
- offset = fBACnetObjectPropertyReference (tvb, tree, offset);
- break;
- case 3: /* deviceIdentifier */
- offset = fObjectIdentifier (tvb, tree, offset);
- break;
- default:
- return offset;
- }
- }
- return offset;
-}
-#endif
-
-static guint
-fPriorityArray (tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
- char i, ar[256];
-
- if (offset >= tvb_reported_length(tvb))
- return offset;
-
- for (i = 1; i <= 16; i++) {
+ if (propertyArrayIndex > 0) {
+ /* BACnetARRAY index 0 refers to the length
+ of the array, not the elements of the array.
+ BACnetARRAY index -1 is our internal flag that
+ the optional index was not used.
+ BACnetARRAY refers to this as all elements of the array.
+ If the optional index is specified for a BACnetARRAY,
+ then that specific array element is referenced. */
+ i = propertyArrayIndex;
+ }
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ /* exit loop if nothing happens inside */
+ lastoffset = offset;
g_snprintf (ar, sizeof(ar), "%s[%d]: ",
val_to_split_str(87 , 512,
BACnetPropertyIdentifier,
ASHRAE_Reserved_Fmt,
Vendor_Proprietary_Fmt),
- i);
- /* DMR Replace with fAbstractNSyntax */
- offset = fApplicationTypes(tvb, tree, offset, ar);
+ i++);
+ /* DMR Should be fAbstractNSyntax, but that's where we came from! */
+ offset = fApplicationTypes(tvb, pinfo, tree, offset, ar);
+ /* there are only 16 priority array elements */
+ if (i > 16) {
+ break;
+ }
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
+
return offset;
}
-#if 0
static guint
-fDeviceObjectReference (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fDeviceObjectReference (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+
switch (fTagNo(tvb,offset)) {
- case 0: /* deviceIdentifier */
- offset = fObjectIdentifier (tvb, tree, offset);
+ case 0: /* deviceIdentifier - OPTIONAL */
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* ObjectIdentifier */
- offset = fObjectIdentifier (tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
-#endif
static guint
-fSpecialEvent (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fSpecialEvent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
{
guint8 tag_no, tag_info;
guint32 lvt;
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* maybe a SEQUENCE of SpecialEvents if we spot a closing tag */
+ if (tag_is_closing(tag_info)) {
+ offset += len;
continue;
}
-
+
switch (tag_no) {
case 0: /* calendaryEntry */
- if (tag_is_opening(tag_info))
- {
+ if (tag_is_opening(tag_info))
+ {
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fCalendaryEntry (tvb, subtree, offset);
+ offset = fCalendaryEntry (tvb, subtree, offset);
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- }
+ }
break;
case 1: /* calendarReference */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* list of BACnetTimeValue */
if (tag_is_opening(tag_info)) {
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fTimeValue (tvb, subtree, offset);
+ offset = fTimeValue (tvb, pinfo, subtree, offset);
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
}
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fSelectionCriteria (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
+ guint8 tag_no, tag_info;
+ guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
-
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* maybe a listOfSelectionCriteria if we spot a closing tag */
+ if (tag_is_closing(tag_info)) {
+ offset += len;
+ continue;
+ }
+
switch (fTagNo(tvb,offset)) {
case 0: /* propertyIdentifier */
- offset = fPropertyIdentifier (tvb, tree, offset);
+ offset = fPropertyIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* propertyArrayIndex */
- offset = fUnsignedTag (tvb, tree, offset, "property Array Index: ");
+ offset = fPropertyArrayIndex (tvb, tree, offset);
break;
case 2: /* relationSpecifier */
- offset = fEnumeratedTag (tvb, tree, offset,
+ offset = fEnumeratedTag (tvb, tree, offset,
"relation Specifier: ", BACnetRelationSpecifier);
break;
case 3: /* comparisonValue */
- offset = fAbstractSyntaxNType (tvb, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fAbstractSyntaxNType (tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fObjectSelectionCriteria (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fObjectSelectionCriteria (tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
- continue;
+ /* quit loop if we spot a closing tag */
+ if (tag_is_closing(tag_info)) {
+ break;
}
-
+
switch (tag_no) {
case 0: /* selectionLogic */
- offset = fEnumeratedTag (tvb, subtree, offset,
+ offset = fEnumeratedTag (tvb, subtree, offset,
"selection Logic: ", BACnetSelectionLogic);
break;
case 1: /* listOfSelectionCriteria */
if (tag_is_opening(tag_info)) {
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fSelectionCriteria (tvb, subtree, offset);
+ offset = fSelectionCriteria (tvb, pinfo, subtree, offset);
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
}
FAULT;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fReadPropertyConditionalRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fReadPropertyConditionalRequest(tvbuff_t *tvb, packet_info* pinfo, proto_tree *subtree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
+
+ if (tag_is_opening(tag_info) && tag_no < 2) {
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- continue;
- }
-
- switch (tag_no) {
- case 0: /* objectSelectionCriteria */
- offset = fObjectSelectionCriteria (tvb, subtree, offset);
- break;
- case 1: /* listOfPropertyReferences */
- if (tag_is_opening(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
+ switch (tag_no) {
+ case 0: /* objectSelectionCriteria */
+ offset = fObjectSelectionCriteria (tvb, pinfo, subtree, offset);
break;
+ case 1: /* listOfPropertyReferences */
+ offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
+ break;
+ default:
+ return offset;
}
- FAULT;
- break;
- default:
- return offset;
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fReadAccessSpecification (tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fReadAccessSpecification (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
+ proto_item *tt;
+ proto_tree *subtree = tree;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no,
- &tag_info, &lvt);
- continue;
- }
-
switch (tag_no) {
case 0: /* objectIdentifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
break;
case 1: /* listOfPropertyReferences */
if (tag_is_opening(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fBACnetPropertyReference (tvb, subtree, offset, 1);
- break;
+ tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfPropertyReferences");
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fBACnetPropertyReference (tvb, pinfo, subtree, offset, 1);
+ } else if (tag_is_closing(tag_info)) {
+ offset += fTagHeaderTree (tvb, subtree, offset,
+ &tag_no, &tag_info, &lvt);
+ subtree = tree;
+ } else {
+ /* error condition: let caller handle */
+ return offset;
}
- FAULT;
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fReadAccessResult (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadAccessResult (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint lastoffset = 0, len;
guint8 tag_no;
guint8 tag_info;
guint32 lvt;
proto_tree *subtree = tree;
proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
- if (tag_no == 4 || tag_no == 5) subtree = tree; /* Value and error have extra subtree */
+ len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ /* maybe a listOfReadAccessResults if we spot a closing tag here */
+ if (tag_is_closing(tag_info)) {
+ offset += len;
+ if ((tag_no == 4 || tag_no == 5) && (subtree != tree)) subtree = subtree->parent; /* Value and error have extra subtree */
continue;
}
-
+
switch (tag_no) {
case 0: /* objectSpecifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
break;
case 1: /* list of Results */
if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfResults");
+ tt = proto_tree_add_text(tree, tvb, offset, 1, "listOfResults");
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
break;
FAULT;
break;
case 2: /* propertyIdentifier */
- offset = fPropertyValue(tvb, subtree, offset, 2);
+ offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
break;
case 5: /* propertyAccessError */
if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
+ tt = proto_tree_add_text(tree, tvb, offset, 1, "propertyAccessError");
subtree = proto_item_add_subtree(tt, ett_bacapp_value);
offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
/* Error Code follows */
- offset = fError(tvb, subtree, offset);
+ offset = fError(tvb, pinfo, subtree, offset);
break;
}
FAULT;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fReadPropertyConditionalAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyConditionalAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
/* listOfReadAccessResults */
- return fReadAccessResult (tvb, tree, offset);
+ return fReadAccessResult (tvb, pinfo, tree, offset);
}
static guint
-fObjectSpecifier (tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
- guint lastoffset = 0;
-
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- switch (fTagNo(tvb, offset)) {
- case 0: /* objectType */
- proto_tree_add_item(tree, hf_bacapp_tag_initiatingObjectType, tvb, offset++, 1, TRUE);
- break;
- case 1: /* objectIdentifier */
- offset = fObjectIdentifier (tvb, tree, offset);
- break;
- default:
- return offset;
- }
- }
- return offset;
-}
-
-static guint
-fCreateObjectRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
{
guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
- while ((tvb_length_remaining(tvb, offset) > 0) && (offset > lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
- continue;
- }
-
- switch (tag_no) {
- case 0: /* objectSpecifier */
- offset = fObjectSpecifier (tvb, subtree, offset);
- break;
- case 1: /* propertyValue */
- if (tag_is_opening(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fBACnetPropertyValue (tvb, subtree, offset);
+
+ if (tag_no < 2)
+ {
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ switch (tag_no) {
+ case 0: /* objectSpecifier */
+ switch (fTagNo(tvb, offset)) { /* choice of objectType or objectIdentifier */
+ case 0: /* objectType */
+ offset = fEnumeratedTagSplit (tvb, subtree, offset, "Object Type: ", BACnetObjectType, 128);
+ break;
+ case 1: /* objectIdentifier */
+ offset = fObjectIdentifier (tvb, pinfo, subtree, offset);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1: /* propertyValue */
+ if (tag_is_opening(tag_info)) {
+ offset = fBACnetPropertyValue (tvb, pinfo, subtree, offset);
+ break;
+ }
+ FAULT;
+ break;
+ default:
break;
}
- FAULT;
- break;
- default:
- return offset;
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fCreateObjectAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fCreateObjectAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fObjectIdentifier (tvb, tree, offset);
+ return fObjectIdentifier (tvb, pinfo, tree, offset);
}
static guint
-fReadRangeRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadRangeRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
+ offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ /* optional range choice */
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
- subtree = tree;
- continue;
- }
-
- switch (tag_no) {
- case 0: /* objectSpecifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
- break;
- case 1: /* propertyIdentifier */
- offset = fPropertyIdentifier (tvb, subtree, offset);
- break;
- case 2: /* propertyArrayIndex Optional */
- offset = fUnsignedTag (tvb, subtree, offset, "Property Array Index: ");
- break;
- case 3: /* range byPosition */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "range byPosition");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fApplicationTypes (tvb, subtree, offset, "reference Index: ");
- offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
+ if (tag_is_opening(tag_info)) {
+ tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetReadRangeOptions, "unknown range option"));
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ switch (tag_no) {
+ case 3: /* range byPosition */
+ case 6: /* range bySequenceNumber, 2004 spec */
+ offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Index: ");
+ offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Count: ");
break;
- }
- FAULT;
- break;
- case 4: /* range byTime */
- case 7: /* 2004 spec */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "range byTime");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ case 4: /* range byTime - deprecated in 2004 */
+ case 7: /* 2004 spec */
offset = fDateTime(tvb, subtree, offset, "reference Date/Time: ");
- offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
+ offset = fApplicationTypes (tvb, pinfo, subtree, offset, "reference Count: ");
break;
- }
- FAULT;
- break;
- case 5: /* range timeRange */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "range timeRange");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fApplicationTypes (tvb, subtree, offset, "beginning Time: ");
- offset = fApplicationTypes (tvb, subtree, offset, "ending Time: ");
+ case 5: /* range timeRange - deprecated in 2004 */
+ offset = fDateTime(tvb, subtree, offset, "beginning Time: ");
+ offset = fDateTime(tvb, subtree, offset, "ending Time: ");
break;
- }
- FAULT;
- break;
- case 6: /* range bySequenceNumber, 2004 spec */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "range bySequenceNumber");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fApplicationTypes (tvb, subtree, offset, "referenceIndex: ");
- offset = fApplicationTypes (tvb, subtree, offset, "reference Count: ");
+ default:
break;
- }
- FAULT;
- break;
- default:
- return offset;
+ }
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
}
}
return offset;
}
static guint
-fReadRangeAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadRangeAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- subtree = tree;
- continue;
- }
-
- switch (tag_no) {
- case 0: /* objectSpecifier */
- offset = fObjectIdentifier (tvb, subtree, offset);
- break;
- case 1: /* propertyIdentifier */
- offset = fPropertyIdentifier (tvb, subtree, offset);
- break;
- case 2: /* propertyArrayIndex Optional */
- offset = fUnsignedTag (tvb, subtree, offset, "Property Array Index: ");
- break;
- case 3: /* resultFlags */
- offset = fEnumeratedTag (tvb, tree, offset,
- "result Flags: ", BACnetResultFlags);
- break;
- case 4: /* itemCount */
- offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
- break;
- case 5: /* itemData */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fAbstractSyntaxNType (tvb, subtree, offset);
- break;
- }
- FAULT;
- break;
- case 6: /* firstSequenceNumber */
- offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
- break;
- default:
- return offset;
- }
+ /* set the optional global properties to indicate not-used */
+ propertyArrayIndex = -1;
+ /* objectIdentifier, propertyIdentifier, and
+ OPTIONAL propertyArrayIndex */
+ offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
+ /* resultFlags => BACnetResultFlags ::= BIT STRING */
+ offset = fBitStringTagVS (tvb, tree, offset,
+ "resultFlags: ",
+ BACnetResultFlags);
+ /* itemCount */
+ offset = fUnsignedTag (tvb, subtree, offset, "item Count: ");
+ /* itemData */
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_opening(tag_info)) {
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
}
+ /* firstSequenceNumber - OPTIONAL */
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: ");
+ }
+
return offset;
}
-static guint fAccessMethod(tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint
+fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
+ guint lastoffset = 0;
guint32 lvt;
guint8 tag_no, tag_info;
proto_item* tt;
fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- switch (tag_no) {
- case 0: /* streamAccess */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(tree, tvb, offset, 1, "stream Access");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fApplicationTypes (tvb, subtree, offset, "File Start Position: ");
- offset = fApplicationTypes (tvb, subtree, offset, "file Data: ");
- }
- if (bacapp_flags & 0x04) { /* More Flag is set */
- break;
- }
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- }
- break;
- case 1: /* recordAccess */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(tree, tvb, offset, 1, "record Access");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fApplicationTypes (tvb, subtree, offset, "File Start Record: ");
- offset = fApplicationTypes (tvb, subtree, offset, "Record Count: ");
- offset = fApplicationTypes (tvb, subtree, offset, "Data: ");
- }
- if (bacapp_flags & 0x04) { /* More Flag is set */
- break;
+ if (tag_is_opening(tag_info))
+ {
+ tt = proto_tree_add_text(tree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetFileAccessOption, "invalid access method"));
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fApplicationTypes (tvb, pinfo, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "invalid option"));
+ offset = fApplicationTypes (tvb, pinfo, subtree, offset, val_to_str(tag_no, BACnetFileWriteInfo, "unknown option"));
+
+ if (tag_no == 1)
+ {
+ while ((tvb_reported_length_remaining(tvb, offset) > 0)&&(offset>lastoffset))
+ { /* exit loop if nothing happens inside */
+ lastoffset = offset;
+ offset = fApplicationTypes (tvb, pinfo, subtree, offset, "Record Data: ");
+ }
}
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+
+ if ((bacapp_flags & BACAPP_MORE_SEGMENTS) == 0)
+ {
+ /* More Flag is not set, so we can look for closing tag in this segment */
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ if (tag_is_closing(tag_info)) {
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ }
}
- break;
- default:
- break;
}
-
return offset;
}
static guint
-fAtomicReadFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
guint8 tag_no, tag_info;
guint32 lvt;
proto_tree *subtree = tree;
- proto_item *tt;
-
- offset = fObjectIdentifier (tvb, tree, offset);
-
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- if (tag_is_closing(tag_info)) {
- offset += fTagHeaderTree (tvb, subtree, offset,
- &tag_no, &tag_info, &lvt);
- subtree = tree;
- continue;
- }
-
- switch (tag_no) {
- case 0: /* streamAccess */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "stream Access");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fSignedTag (tvb, subtree, offset, "File Start Position: ");
- offset = fUnsignedTag (tvb, subtree, offset, "requested Octet Count: ");
- break;
- }
- FAULT;
- break;
- case 1: /* recordAccess */
- if (tag_is_opening(tag_info)) {
- tt = proto_tree_add_text(subtree, tvb, offset, 1, "record Access");
- subtree = proto_item_add_subtree(tt, ett_bacapp_value);
- offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
- offset = fSignedTag (tvb, subtree, offset, "File Start Record: ");
- offset = fUnsignedTag (tvb, subtree, offset, "requested Record Count: ");
- break;
- }
- FAULT;
- break;
- default:
- return offset;
- }
+ proto_item *tt;
+
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset);
+
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+
+ if (tag_is_opening(tag_info))
+ {
+ tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str(tag_no, BACnetFileAccessOption, "unknown access method"));
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fSignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
+ offset = fUnsignedTag (tvb, subtree, offset, val_to_str(tag_no, BACnetFileRequestCount, "unknown option"));
+ offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt);
}
return offset;
}
static guint
-fAtomicWriteFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAtomicWriteFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- offset = fObjectIdentifier (tvb, tree, offset); /* file Identifier */
- offset = fAccessMethod(tvb, tree, offset);
+ offset = fObjectIdentifier (tvb, pinfo, tree, offset); /* file Identifier */
+ offset = fAccessMethod(tvb, pinfo, tree, offset);
return offset;
}
static guint
fAtomicWriteFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
{
- switch (fTagNo(tvb, offset)) {
- case 0: /* streamAccess */
- offset = fSignedTag (tvb, tree, offset, "File Start Position: ");
- break;
- case 1: /* recordAccess */
- offset = fSignedTag (tvb, tree, offset, "File Start Record: ");
- break;
- default:
- return offset;
- }
- return offset;
+ guint tag_no = fTagNo(tvb, offset);
+ return fSignedTag (tvb, tree, offset, val_to_str(tag_no, BACnetFileStartOption, "unknown option"));
}
static guint
-fAtomicReadFileAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fAtomicReadFileAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint8 tag_no, tag_info;
- guint32 lvt;
- proto_tree *subtree = tree;
-
- fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
- offset = fApplicationTypes (tvb, subtree, offset, "End Of File: ");
- offset = fAccessMethod(tvb, tree, offset);
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "End Of File: ");
+ offset = fAccessMethod(tvb,pinfo, tree, offset);
- return offset;
+ return offset;
}
static guint
-fReadPropertyMultipleRequest(tvbuff_t *tvb, proto_tree *subtree, guint offset)
+fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offset)
{
- return fReadAccessSpecification (tvb,subtree,offset);
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ return fReadAccessSpecification (tvb,pinfo,subtree,offset);
}
static guint
-fReadPropertyMultipleAck (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fReadPropertyMultipleAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- return fReadAccessResult (tvb,tree,offset);
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ return fReadAccessResult (tvb,pinfo,tree,offset);
}
static guint
-fConfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
+fConfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
{
- if (tvb_length_remaining(tvb,offset) <= 0)
+ if (tvb_reported_length_remaining(tvb,offset) <= 0)
return offset;
switch (service_choice) {
case 0: /* acknowledgeAlarm */
- offset = fAcknowledgeAlarmRequest (tvb, tree, offset);
+ offset = fAcknowledgeAlarmRequest (tvb, pinfo, tree, offset);
break;
case 1: /* confirmedCOVNotification */
- offset = fConfirmedCOVNotificationRequest (tvb, tree, offset);
+ offset = fConfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
break;
case 2: /* confirmedEventNotification */
- offset = fConfirmedEventNotificationRequest (tvb, tree, offset);
+ offset = fConfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
break;
case 3: /* confirmedGetAlarmSummary conveys no parameters */
break;
case 4: /* getEnrollmentSummaryRequest */
- offset = fGetEnrollmentSummaryRequest (tvb, tree, offset);
+ offset = fGetEnrollmentSummaryRequest (tvb, pinfo, tree, offset);
break;
case 5: /* subscribeCOVRequest */
- offset = fSubscribeCOVRequest(tvb, tree, offset);
+ offset = fSubscribeCOVRequest(tvb, pinfo, tree, offset);
break;
case 6: /* atomicReadFile-Request */
- offset = fAtomicReadFileRequest(tvb, tree, offset);
+ offset = fAtomicReadFileRequest(tvb, pinfo, tree, offset);
break;
case 7: /* atomicWriteFile-Request */
- offset = fAtomicWriteFileRequest(tvb, tree, offset);
+ offset = fAtomicWriteFileRequest(tvb, pinfo, tree, offset);
break;
case 8: /* AddListElement-Request */
- offset = fAddListElementRequest(tvb, tree, offset);
+ offset = fAddListElementRequest(tvb, pinfo, tree, offset);
break;
case 9: /* removeListElement-Request */
- offset = fRemoveListElementRequest(tvb, tree, offset);
+ offset = fRemoveListElementRequest(tvb, pinfo, tree, offset);
break;
case 10: /* createObjectRequest */
- offset = fCreateObjectRequest(tvb, tree, offset);
+ offset = fCreateObjectRequest(tvb, pinfo, tree, offset);
break;
case 11: /* deleteObject */
- offset = fDeleteObjectRequest(tvb, tree, offset);
+ offset = fDeleteObjectRequest(tvb, pinfo, tree, offset);
break;
case 12:
- offset = fReadPropertyRequest(tvb, tree, offset);
+ offset = fReadPropertyRequest(tvb, pinfo, tree, offset);
break;
case 13:
- offset = fReadPropertyConditionalRequest(tvb, tree, offset);
+ offset = fReadPropertyConditionalRequest(tvb, pinfo, tree, offset);
break;
case 14:
- offset = fReadPropertyMultipleRequest(tvb, tree, offset);
+ offset = fReadPropertyMultipleRequest(tvb, pinfo, tree, offset);
break;
case 15:
- offset = fWritePropertyRequest(tvb, tree, offset);
+ offset = fWritePropertyRequest(tvb, pinfo, tree, offset);
break;
case 16:
- offset = fWritePropertyMultipleRequest(tvb, tree, offset);
+ offset = fWritePropertyMultipleRequest(tvb, pinfo, tree, offset);
break;
case 17:
offset = fDeviceCommunicationControlRequest(tvb, tree, offset);
break;
case 18:
- offset = fConfirmedPrivateTransferRequest(tvb, tree, offset);
+ offset = fConfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
break;
case 19:
- offset = fConfirmedTextMessageRequest(tvb, tree, offset);
+ offset = fConfirmedTextMessageRequest(tvb, pinfo, tree, offset);
break;
case 20:
offset = fReinitializeDeviceRequest(tvb, tree, offset);
break;
case 21:
- offset = fVtOpenRequest(tvb, tree, offset);
+ offset = fVtOpenRequest(tvb, pinfo, tree, offset);
break;
case 22:
- offset = fVtCloseRequest (tvb, tree, offset);
+ offset = fVtCloseRequest (tvb, pinfo, tree, offset);
break;
case 23:
- offset = fVtDataRequest (tvb, tree, offset);
+ offset = fVtDataRequest (tvb, pinfo, tree, offset);
break;
case 24:
offset = fAuthenticateRequest (tvb, tree, offset);
break;
case 25:
- offset = fRequestKeyRequest (tvb, tree, offset);
+ offset = fRequestKeyRequest (tvb, pinfo, tree, offset);
break;
case 26:
- offset = fReadRangeRequest (tvb, tree, offset);
+ offset = fReadRangeRequest (tvb, pinfo, tree, offset);
break;
case 27:
- offset = fLifeSafetyOperationRequest(tvb, tree, offset, NULL);
+ offset = fLifeSafetyOperationRequest(tvb, pinfo, tree, offset, NULL);
break;
case 28:
- offset = fSubscribeCOVPropertyRequest(tvb, tree, offset);
+ offset = fSubscribeCOVPropertyRequest(tvb, pinfo, tree, offset);
break;
case 29:
- offset = fGetEventInformationRequest (tvb, tree, offset);
+ offset = fGetEventInformationRequest (tvb, pinfo, tree, offset);
break;
default:
return offset;
- break;
}
return offset;
}
static guint
-fConfirmedServiceAck (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
+fConfirmedServiceAck (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
{
- if (tvb_length_remaining(tvb,offset) <= 0)
+ if (tvb_reported_length_remaining(tvb,offset) <= 0)
return offset;
switch (service_choice) {
case 3: /* confirmedEventNotificationAck */
- offset = fGetAlarmSummaryAck (tvb, tree, offset);
+ offset = fGetAlarmSummaryAck (tvb, pinfo, tree, offset);
break;
case 4: /* getEnrollmentSummaryAck */
- offset = fGetEnrollmentSummaryAck (tvb, tree, offset);
+ offset = fGetEnrollmentSummaryAck (tvb, pinfo, tree, offset);
break;
case 6: /* atomicReadFile */
- offset = fAtomicReadFileAck (tvb, tree, offset);
+ offset = fAtomicReadFileAck (tvb, pinfo, tree, offset);
break;
case 7: /* atomicReadFileAck */
offset = fAtomicWriteFileAck (tvb, tree, offset);
break;
case 10: /* createObject */
- offset = fCreateObjectAck (tvb, tree, offset);
+ offset = fCreateObjectAck (tvb, pinfo, tree, offset);
break;
case 12:
- offset = fReadPropertyAck (tvb, tree, offset);
+ offset = fReadPropertyAck (tvb, pinfo, tree, offset);
break;
case 13:
- offset = fReadPropertyConditionalAck (tvb, tree, offset);
+ offset = fReadPropertyConditionalAck (tvb, pinfo, tree, offset);
break;
case 14:
- offset = fReadPropertyMultipleAck (tvb, tree, offset);
+ offset = fReadPropertyMultipleAck (tvb, pinfo, tree, offset);
break;
case 18:
- offset = fConfirmedPrivateTransferAck(tvb, tree, offset);
+ offset = fConfirmedPrivateTransferAck(tvb, pinfo, tree, offset);
break;
case 21:
- offset = fVtOpenAck (tvb, tree, offset);
+ offset = fVtOpenAck (tvb, pinfo, tree, offset);
break;
case 23:
offset = fVtDataAck (tvb, tree, offset);
break;
case 24:
- offset = fAuthenticateAck (tvb, tree, offset);
+ offset = fAuthenticateAck (tvb, pinfo, tree, offset);
break;
case 26:
- offset = fReadRangeAck (tvb, tree, offset);
+ offset = fReadRangeAck (tvb, pinfo, tree, offset);
break;
case 29:
- offset = fGetEventInformationACK (tvb, tree, offset);
+ offset = fGetEventInformationACK (tvb, pinfo, tree, offset);
break;
default:
return offset;
}
static guint
-fIAmRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fIAmRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
/* BACnetObjectIdentifier */
- offset = fApplicationTypes (tvb, tree, offset, "BACnet Object Identifier: ");
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "BACnet Object Identifier: ");
/* MaxAPDULengthAccepted */
- offset = fApplicationTypes (tvb, tree, offset, "Maximum ADPU Length Accepted: ");
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Maximum ADPU Length Accepted: ");
/* segmentationSupported */
- offset = fApplicationTypesEnumerated (tvb, tree, offset,
+ offset = fApplicationTypesEnumerated (tvb, pinfo, tree, offset,
"Segmentation Supported: ", BACnetSegmentation);
/* vendor ID */
- return fUnsignedTag (tvb, tree, offset, "Vendor ID: ");
+ return fVendorIdentifier (tvb, pinfo, tree, offset);
}
static guint
-fIHaveRequest (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fIHaveRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
/* BACnetDeviceIdentifier */
- offset = fApplicationTypes (tvb, tree, offset, "Device Identifier: ");
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Device Identifier: ");
/* BACnetObjectIdentifier */
- offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: ");
+ offset = fApplicationTypes (tvb, pinfo, tree, offset, "Object Identifier: ");
/* ObjectName */
- return fApplicationTypes (tvb, tree, offset, "Object Name: ");
+ return fApplicationTypes (tvb, pinfo, tree, offset, "Object Name: ");
}
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* DeviceInstanceRangeLowLimit Optional */
break;
default:
return offset;
- break;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fUnconfirmedServiceRequest (tvbuff_t *tvb, proto_tree *tree, guint offset, gint service_choice)
+fUnconfirmedServiceRequest (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, gint service_choice)
{
- if (tvb_length_remaining(tvb,offset) <= 0)
+ if (tvb_reported_length_remaining(tvb,offset) <= 0)
return offset;
-
+
switch (service_choice) {
case 0: /* I-Am-Request */
- offset = fIAmRequest (tvb, tree, offset);
+ offset = fIAmRequest (tvb, pinfo, tree, offset);
break;
case 1: /* i-Have Request */
- offset = fIHaveRequest (tvb, tree, offset);
+ offset = fIHaveRequest (tvb, pinfo, tree, offset);
break;
case 2: /* unconfirmedCOVNotification */
- offset = fUnconfirmedCOVNotificationRequest (tvb, tree, offset);
+ offset = fUnconfirmedCOVNotificationRequest (tvb, pinfo, tree, offset);
break;
case 3: /* unconfirmedEventNotification */
- offset = fUnconfirmedEventNotificationRequest (tvb, tree, offset);
+ offset = fUnconfirmedEventNotificationRequest (tvb, pinfo, tree, offset);
break;
case 4: /* unconfirmedPrivateTransfer */
- offset = fUnconfirmedPrivateTransferRequest(tvb, tree, offset);
+ offset = fUnconfirmedPrivateTransferRequest(tvb, pinfo, tree, offset);
break;
case 5: /* unconfirmedTextMessage */
- offset = fUnconfirmedTextMessageRequest(tvb, tree, offset);
+ offset = fUnconfirmedTextMessageRequest(tvb, pinfo, tree, offset);
break;
case 6: /* timeSynchronization */
offset = fTimeSynchronizationRequest (tvb, tree, offset);
break;
case 7: /* who-Has */
- offset = fWhoHas (tvb, tree, offset);
+ offset = fWhoHas (tvb, pinfo, tree, offset);
break;
case 8: /* who-Is */
offset = fWhoIsRequest (tvb, tree, offset);
}
static guint
-fStartConfirmed(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset, guint8 ack,
+fStartConfirmed(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset, guint8 ack,
gint *svc, proto_item **tt)
{
proto_item *tc;
if (bacapp_flags & 0x08)
*svc = (gint) tvb_get_guint8(tvb, offset+extra+2);
- proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
tc = proto_tree_add_item(bacapp_tree, hf_bacapp_pduflags, tvb, offset, 1, TRUE);
bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp_control);
- proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
- proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
+ proto_tree_add_item(bacapp_tree_control, hf_bacapp_SEG, tvb, offset, 1, TRUE);
+ proto_tree_add_item(bacapp_tree_control, hf_bacapp_MOR, tvb, offset, 1, TRUE);
if (ack == 0) /* The following are for ConfirmedRequest, not Complex ack */
{
proto_tree_add_item(bacapp_tree_control, hf_bacapp_SA, tvb, offset++, 1, TRUE);
proto_tree_add_item(bacapp_tree, hf_bacapp_max_adpu_size, tvb,
offset, 1, TRUE);
}
- offset++;
- proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
- if (bacapp_flags & 0x08) {
- bacapp_seq = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(bacapp_tree_control, hf_bacapp_sequence_number, tvb,
- offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree_control, hf_bacapp_window_size, tvb,
- offset++, 1, TRUE);
- }
- *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
- offset++, 1, TRUE);
+ offset++;
+ proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb, offset++, 1, TRUE);
+ if (bacapp_flags & 0x08) {
+ bacapp_seq = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
+ offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
+ offset++, 1, TRUE);
+ }
+ *tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
+ offset++, 1, TRUE);
return offset;
}
static guint
-fConfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fContinueConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
+{ /* BACnet-Confirmed-Request */
+ /* ASHRAE 135-2001 20.1.2 */
+
+ return fConfirmedServiceRequest (tvb, pinfo, bacapp_tree, offset, svc);
+}
+
+static guint
+fConfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Confirmed-Request */
/* ASHRAE 135-2001 20.1.2 */
gint svc;
proto_item *tt = 0;
- offset = fStartConfirmed(tvb, bacapp_tree, offset, 0, &svc, &tt);
- if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
- {
- proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
- return offset;
- }
- else
- {
- /* Service Request follows... Variable Encoding 20.2ff */
- return fConfirmedServiceRequest (tvb, bacapp_tree, offset, svc);
- }
+ offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 0, &svc, &tt);
+ return fContinueConfirmedRequestPDU(tvb, pinfo, bacapp_tree, offset, svc);
}
static guint
-fUnconfirmedRequestPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fUnconfirmedRequestPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Unconfirmed-Request-PDU */
/* ASHRAE 135-2001 20.1.3 */
gint tmp;
- proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
- tmp = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
- offset++, 1, TRUE);
- /* Service Request follows... Variable Encoding 20.2ff */
- return fUnconfirmedServiceRequest (tvb, bacapp_tree, offset, tmp);
+ tmp = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_uservice, tvb,
+ offset++, 1, TRUE);
+ /* Service Request follows... Variable Encoding 20.2ff */
+ return fUnconfirmedServiceRequest (tvb, pinfo, bacapp_tree, offset, tmp);
}
static guint
-fSimpleAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fSimpleAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Simple-Ack-PDU */
/* ASHRAE 135-2001 20.1.4 */
tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
- offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
- offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+ offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
+ offset++, 1, TRUE);
+
return offset;
}
static guint
-fComplexAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fContinueComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset, gint svc)
+{ /* BACnet-Complex-Ack-PDU */
+ /* ASHRAE 135-2001 20.1.5 */
+
+ /* Service ACK follows... */
+ return fConfirmedServiceAck (tvb, pinfo, bacapp_tree, offset, svc);
+}
+
+static guint
+fComplexAckPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Complex-Ack-PDU */
/* ASHRAE 135-2001 20.1.5 */
gint svc;
proto_item *tt = 0;
- offset = fStartConfirmed(tvb, bacapp_tree, offset, 1, &svc, &tt);
-
- if (bacapp_seq > 0) /* Can't handle continuation segments, so just treat as data */
- {
- proto_tree_add_text(bacapp_tree, tvb, offset, 0, "(continuation)");
- return offset;
- }
- else
- {
- /* Service ACK follows... */
- return fConfirmedServiceAck (tvb, bacapp_tree, offset, svc);
- }
+ offset = fStartConfirmed(tvb, pinfo, bacapp_tree, offset, 1, &svc, &tt);
+ return fContinueComplexAckPDU(tvb, pinfo, bacapp_tree, offset, svc);
}
-
static guint
-fSegmentAckPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fSegmentAckPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-SegmentAck-PDU */
/* ASHRAE 135-2001 20.1.6 */
proto_item *tc;
proto_tree *bacapp_tree_control;
- tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
- bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
-
- proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
- offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
- offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
- offset++, 1, TRUE);
+ tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
+ bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+
+ proto_tree_add_item(bacapp_tree, hf_bacapp_NAK, tvb, offset, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+ offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_sequence_number, tvb,
+ offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_window_size, tvb,
+ offset++, 1, TRUE);
return offset;
}
-static guint fContextTaggedError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+static guint
+fContextTaggedError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint8 tag_info = 0;
- guint8 parsed_tag = 0;
- guint32 lvt = 0;
- offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
- offset = fError(tvb, tree, offset);
- return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
+ guint8 tag_info = 0;
+ guint8 parsed_tag = 0;
+ guint32 lvt = 0;
+ offset += fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
+ offset = fError(tvb, pinfo, tree, offset);
+ return offset + fTagHeaderTree(tvb, tree, offset, &parsed_tag, &tag_info, &lvt);
}
static guint
-fConfirmedPrivateTransferError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
+ guint8 tag_no = 0, tag_info = 0;
+ guint32 lvt = 0;
+ proto_tree *subtree = tree;
+ proto_item *tt;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ /* exit loop if nothing happens inside */
lastoffset = offset;
- switch (fTagNo(tvb, offset)) {
+ fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt);
+ switch (tag_no) {
case 0: /* errorType */
- offset = fContextTaggedError(tvb,tree,offset);
+ offset = fContextTaggedError(tvb, pinfo, subtree, offset);
break;
case 1: /* vendorID */
- offset = fUnsignedTag (tvb,tree,offset,"vendor ID: ");
+ offset = fVendorIdentifier (tvb, pinfo, subtree, offset);
break;
case 2: /* serviceNumber */
- offset = fUnsignedTag (tvb,tree,offset,"service Number: ");
- break;
- case 3: /* errorParameters */
- offset = fAbstractSyntaxNType (tvb, tree, offset);
- break;
- default:
- return offset;
- }
- }
- return offset;
-}
-
-static guint
-fCreateObjectError(tvbuff_t *tvb, proto_tree *tree, guint offset)
-{
- guint lastoffset = 0;
-
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- switch (fTagNo(tvb, offset)) {
- case 0: /* errorType */
- offset = fContextTaggedError(tvb,tree,offset);
+ offset = fUnsignedTag (tvb, subtree, offset, "service Number: ");
break;
- case 1: /* firstFailedElementNumber */
- offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
+ case 3: /* errorParameters */
+ if (tag_is_opening(tag_info)) {
+ tt = proto_tree_add_text(subtree, tvb, offset, 1,
+ "error Parameters");
+ subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+ propertyIdentifier = -1;
+ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt);
+ offset = fAbstractSyntaxNType (tvb, pinfo, subtree, offset);
+ } else if (tag_is_closing(tag_info)) {
+ offset += fTagHeaderTree (tvb, subtree, offset,
+ &tag_no, &tag_info, &lvt);
+ subtree = tree;
+ } else {
+ /* error condition: let caller handle */
+ return offset;
+ }
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fChangeListError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fCreateObjectError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* errorType */
- offset = fContextTaggedError(tvb,tree,offset);
+ offset = fContextTaggedError(tvb, pinfo, tree, offset);
break;
case 1: /* firstFailedElementNumber */
offset = fUnsignedTag (tvb,tree,offset,"first failed element number: ");
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
-#if 0
static guint
-fVTSession(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fChangeListError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- if (tvb_length_remaining(tvb, offset) > 0) { /* don't loop */
- offset = fUnsignedTag (tvb,tree,offset, "local-VTSessionID: ");
- offset = fUnsignedTag (tvb,tree,offset, "remote-VTSessionID: ");
- offset = fAddress (tvb,tree,offset);
- }
- return offset;
+ /* Identical to CreateObjectError */
+ return fCreateObjectError(tvb, pinfo, tree, offset);
}
-#endif
static guint
-fVTCloseError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fVTCloseError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- guint lastoffset = 0;
+ guint8 tag_no = 0, tag_info = 0;
+ guint32 lvt = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
- lastoffset = offset;
- switch (fTagNo(tvb, offset)) {
- case 0: /* errorType */
- offset = fContextTaggedError(tvb,tree,offset);
- break;
- case 1: /* listOfVTSessionIdentifiers */
- offset = fUnsignedTag (tvb,tree,offset,"VT SessionID: ");
- break;
- default:
- return offset;
+ if (fTagNo(tvb, offset) == 0)
+ {
+ /* errorType */
+ offset = fContextTaggedError(tvb, pinfo, tree,offset);
+ if (fTagNo(tvb, offset) == 1)
+ {
+ /* listOfVTSessionIdentifiers [OPTIONAL] */
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fVtCloseRequest (tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
}
}
+ /* should report bad packet if initial tag wasn't 0 */
return offset;
}
static guint
-fWritePropertyMultipleError(tvbuff_t *tvb, proto_tree *tree, guint offset)
+fWritePropertyMultipleError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
guint lastoffset = 0;
+ guint8 tag_no = 0, tag_info = 0;
+ guint32 lvt = 0;
- while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */
+ col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
+ while (tvb_reported_length_remaining(tvb, offset)) { /* exit loop if nothing happens inside */
lastoffset = offset;
switch (fTagNo(tvb, offset)) {
case 0: /* errorType */
- offset = fContextTaggedError(tvb,tree,offset);
+ offset = fContextTaggedError(tvb, pinfo, tree, offset);
break;
case 1: /* firstFailedWriteAttempt */
- offset = fUnsignedTag (tvb,tree,offset,"first failed write attempt: ");
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
+ offset = fBACnetObjectPropertyReference(tvb, pinfo, tree, offset);
+ offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt);
break;
default:
return offset;
}
+ if (offset == lastoffset) break; /* nothing happened, exit loop */
}
return offset;
}
static guint
-fError (tvbuff_t *tvb, proto_tree *tree, guint offset)
+fError (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
{
- offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset,
- "error Class: ", BACnetErrorClass, 64);
- return fApplicationTypesEnumeratedSplit (tvb, tree, offset,
- "error Code: ", BACnetErrorCode, 256);
+ offset = fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
+ "error Class: ", BACnetErrorClass, 64);
+ return fApplicationTypesEnumeratedSplit (tvb, pinfo, tree, offset,
+ "error Code: ", BACnetErrorCode, 256);
}
static guint
-fBACnetError (tvbuff_t *tvb, proto_tree *tree, guint offset, guint service)
+fBACnetError (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint service)
{
- switch (service) {
- case 8: /* no break here !!!! */
- case 9:
- offset = fChangeListError (tvb, tree, offset);
- break;
- case 10:
- offset = fCreateObjectError (tvb,tree,offset);
- break;
- case 16:
- offset = fWritePropertyMultipleError (tvb,tree,offset);
- break;
- case 18:
- offset = fConfirmedPrivateTransferError (tvb,tree,offset);
- case 22:
- offset = fVTCloseError (tvb,tree,offset);
- default:
- return fError (tvb, tree, offset);
- break;
- }
- return offset;
+ switch (service) {
+ case 8: /* no break here !!!! */
+ case 9:
+ offset = fChangeListError (tvb, pinfo, tree, offset);
+ break;
+ case 10:
+ offset = fCreateObjectError (tvb, pinfo, tree, offset);
+ break;
+ case 16:
+ offset = fWritePropertyMultipleError (tvb, pinfo, tree, offset);
+ break;
+ case 18:
+ offset = fConfirmedPrivateTransferError (tvb,pinfo,tree,offset);
+ break;
+ case 22:
+ offset = fVTCloseError (tvb, pinfo, tree, offset);
+ break;
+ default:
+ return fError (tvb, pinfo, tree, offset);
+ }
+ return offset;
}
static guint
-fErrorPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fErrorPDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Error-PDU */
/* ASHRAE 135-2001 20.1.7 */
proto_item *tc, *tt;
proto_tree *bacapp_tree_control;
- guint8 tmp;
+ guint8 tmp;
- tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
- bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+ tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
+ bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
- proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
- offset++, 1, TRUE);
- tmp = tvb_get_guint8(tvb, offset);
- tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
- offset++, 1, TRUE);
- /* Error Handling follows... */
- return fBACnetError (tvb, bacapp_tree, offset, tmp);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+ offset++, 1, TRUE);
+ tmp = tvb_get_guint8(tvb, offset);
+ tt = proto_tree_add_item(bacapp_tree, hf_bacapp_service, tvb,
+ offset++, 1, TRUE);
+ /* Error Handling follows... */
+ return fBACnetError (tvb, pinfo, bacapp_tree, offset, tmp);
}
static guint
-fRejectPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fRejectPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Reject-PDU */
/* ASHRAE 135-2001 20.1.8 */
proto_item *tc;
proto_tree *bacapp_tree_control;
- tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
- bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+ tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset++, 1, TRUE);
+ bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
- proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
- offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
- offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+ offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_BACnetRejectReason, tvb,
+ offset++, 1, TRUE);
return offset;
}
static guint
-fAbortPDU(tvbuff_t *tvb, proto_tree *bacapp_tree, guint offset)
+fAbortPDU(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bacapp_tree, guint offset)
{ /* BACnet-Abort-PDU */
/* ASHRAE 135-2001 20.1.9 */
proto_item *tc;
proto_tree *bacapp_tree_control;
- tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
- bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
+ tc = proto_tree_add_item(bacapp_tree, hf_bacapp_type, tvb, offset, 1, TRUE);
+ bacapp_tree_control = proto_item_add_subtree(tc, ett_bacapp);
- proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
- offset++, 1, TRUE);
- proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
- offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_SRV, tvb, offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_bacapp_invoke_id, tvb,
+ offset++, 1, TRUE);
+ proto_tree_add_item(bacapp_tree, hf_BACnetAbortReason, tvb,
+ offset++, 1, TRUE);
return offset;
}
-void
+static guint
+do_the_dissection(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 flag, bacapp_type;
+ guint offset = 0;
+
+ flag = (gint) tvb_get_guint8(tvb, 0);
+ bacapp_type = (flag >> 4) & 0x0f;
+
+ if (tvb == NULL || tree == NULL) {
+ return 0;
+ }
+
+ /* ASHRAE 135-2001 20.1.1 */
+ switch (bacapp_type) {
+ case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
+ offset = fConfirmedRequestPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: /* BACnet-Unconfirmed-Request-PDU */
+ offset = fUnconfirmedRequestPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_SIMPLE_ACK: /* BACnet-Simple-Ack-PDU */
+ offset = fSimpleAckPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_COMPLEX_ACK: /* BACnet-Complex-Ack-PDU */
+ offset = fComplexAckPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_SEGMENT_ACK: /* BACnet-SegmentAck-PDU */
+ offset = fSegmentAckPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
+ offset = fErrorPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_REJECT: /* BACnet-Reject-PDU */
+ offset = fRejectPDU(tvb, pinfo, tree, offset);
+ break;
+ case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
+ offset = fAbortPDU(tvb, pinfo, tree, offset);
+ break;
+ }
+ return offset;
+}
+
+static void
dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- gint8 tmp, bacapp_type;
- tvbuff_t *next_tvb;
+ guint8 flag, bacapp_type;
+ guint save_fragmented = FALSE, data_offset = 0, bacapp_apdu_size = fGetMaxAPDUSize(0), fragment = FALSE;
+ tvbuff_t* new_tvb = NULL;
guint offset = 0;
- guint8 bacapp_service, bacapp_reason;
- guint8 bacapp_invoke_id;
+ guint8 bacapp_seqno = 0;
+ guint8 bacapp_service, bacapp_reason, bacapp_prop_win_size;
+ guint8 bacapp_invoke_id = 0;
proto_item *ti;
- proto_tree *bacapp_tree;
-
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
- if (check_col(pinfo->cinfo, COL_INFO))
- col_add_str(pinfo->cinfo, COL_INFO, "BACnet APDU ");
-
- tmp = (gint) tvb_get_guint8(tvb, 0);
- bacapp_type = (tmp >> 4) & 0x0f;
+ proto_tree *bacapp_tree = NULL;
+
+ gint svc;
+ proto_item *tt = 0;
+ gint8 ack = 0;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
+ col_clear (pinfo->cinfo, COL_INFO);
+
+ flag = tvb_get_guint8(tvb, 0);
+ bacapp_type = (flag >> 4) & 0x0f;
/* show some descriptive text in the INFO column */
- if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%-16s",
+ val_to_str(bacapp_type, BACnetTypeName, "# unknown APDU #"));
+
+ switch (bacapp_type)
{
- col_clear(pinfo->cinfo, COL_INFO);
- col_add_str(pinfo->cinfo, COL_INFO,
- val_to_str(bacapp_type, BACnetTypeName, "#### unknown APDU ##### "));
- switch (bacapp_type)
- {
- case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
- /* segmented messages have 2 additional bytes */
- if (tmp & BACAPP_SEGMENTED_REQUEST)
- {
- bacapp_invoke_id = tvb_get_guint8(tvb, offset + 4);
- bacapp_service = tvb_get_guint8(tvb, offset + 5);
- }
- else
- {
- bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
- bacapp_service = tvb_get_guint8(tvb, offset + 3);
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
- bacapp_invoke_id,
- val_to_str(bacapp_service,
- BACnetConfirmedServiceChoice,
- bacapp_unknown_service_str));
- break;
- case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
- bacapp_service = tvb_get_guint8(tvb, offset + 1);
- col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
- val_to_str(bacapp_service,
- BACnetUnconfirmedServiceChoice,
- bacapp_unknown_service_str));
- break;
- case BACAPP_TYPE_SIMPLE_ACK:
+ case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
+ /* segmented messages have 2 additional bytes */
+ if (flag & BACAPP_SEGMENTED_REQUEST)
+ {
+ fragment = TRUE;
+ ack = 0;
+ bacapp_apdu_size = fGetMaxAPDUSize(tvb_get_guint8(tvb, offset + 1)); /* has 16 values, reserved are 50 Bytes */
+ bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
+ bacapp_seqno = tvb_get_guint8(tvb, offset + 3);
+ bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 4);
+ bacapp_service = tvb_get_guint8(tvb, offset + 5);
+ data_offset = 6;
+
+ }
+ else
+ {
+ bacapp_invoke_id = tvb_get_guint8(tvb, offset + 2);
+ bacapp_service = tvb_get_guint8(tvb, offset + 3);
+ }
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ",
+ val_to_str(bacapp_service,
+ BACnetConfirmedServiceChoice,
+ bacapp_unknown_service_str),bacapp_invoke_id);
+ break;
+ case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST:
+ bacapp_service = tvb_get_guint8(tvb, offset + 1);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(bacapp_service,
+ BACnetUnconfirmedServiceChoice,
+ bacapp_unknown_service_str));
+ break;
+ case BACAPP_TYPE_SIMPLE_ACK:
+ bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+ bacapp_service = tvb_get_guint8(tvb, offset + 2);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+ val_to_str(bacapp_service,
+ BACnetConfirmedServiceChoice,
+ bacapp_unknown_service_str), bacapp_invoke_id);
+ break;
+ case BACAPP_TYPE_COMPLEX_ACK:
+ /* segmented messages have 2 additional bytes */
+ if (flag & BACAPP_SEGMENTED_REQUEST)
+ {
+ fragment = TRUE;
+ ack = 1;
+ bacapp_apdu_size = fGetMaxAPDUSize(0); /* has minimum of 50 Bytes */
bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
- bacapp_service = tvb_get_guint8(tvb, offset + 2);
- col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
- bacapp_invoke_id,
- val_to_str(bacapp_service,
- BACnetConfirmedServiceChoice,
- bacapp_unknown_service_str));
- break;
- case BACAPP_TYPE_COMPLEX_ACK:
- /* segmented messages have 2 additional bytes */
- if (tmp & BACAPP_SEGMENTED_REQUEST)
- {
- bacapp_invoke_id = tvb_get_guint8(tvb, offset + 3);
- bacapp_service = tvb_get_guint8(tvb, offset + 4);
- }
- else
- {
- bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
- bacapp_service = tvb_get_guint8(tvb, offset + 2);
- }
- col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
- bacapp_invoke_id,
- val_to_str(bacapp_service,
- BACnetConfirmedServiceChoice,
- bacapp_unknown_service_str));
- break;
- case BACAPP_TYPE_SEGMENT_ACK:
- /* nothing more to add */
- break;
- case BACAPP_TYPE_ERROR:
+ bacapp_seqno = tvb_get_guint8(tvb, offset + 2);
+ bacapp_prop_win_size = tvb_get_guint8(tvb, offset + 3);
+ bacapp_service = tvb_get_guint8(tvb, offset + 4);
+ data_offset = 5;
+ }
+ else
+ {
bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
bacapp_service = tvb_get_guint8(tvb, offset + 2);
- col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
- bacapp_invoke_id,
- val_to_str(bacapp_service,
- BACnetConfirmedServiceChoice,
- bacapp_unknown_service_str));
- break;
- case BACAPP_TYPE_REJECT:
- bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
- bacapp_reason = tvb_get_guint8(tvb, offset + 2);
- col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
- bacapp_invoke_id,
- val_to_split_str(bacapp_reason,
- 64,
- BACnetRejectReason,
- ASHRAE_Reserved_Fmt,
- Vendor_Proprietary_Fmt));
+ }
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+ val_to_str(bacapp_service,
+ BACnetConfirmedServiceChoice,
+ bacapp_unknown_service_str), bacapp_invoke_id);
+ break;
+ case BACAPP_TYPE_SEGMENT_ACK:
+ /* nothing more to add */
+ break;
+ case BACAPP_TYPE_ERROR:
+ bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+ bacapp_service = tvb_get_guint8(tvb, offset + 2);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+ val_to_str(bacapp_service,
+ BACnetConfirmedServiceChoice,
+ bacapp_unknown_service_str), bacapp_invoke_id);
+ break;
+ case BACAPP_TYPE_REJECT:
+ bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+ bacapp_reason = tvb_get_guint8(tvb, offset + 2);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+ val_to_split_str(bacapp_reason,
+ 64,
+ BACnetRejectReason,
+ ASHRAE_Reserved_Fmt,
+ Vendor_Proprietary_Fmt), bacapp_invoke_id);
+ break;
+ case BACAPP_TYPE_ABORT:
+ bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
+ bacapp_reason = tvb_get_guint8(tvb, offset + 2);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s[%3u] ", /* "original-invokeID" replaced */
+ val_to_split_str(bacapp_reason,
+ 64,
+ BACnetAbortReason,
+ ASHRAE_Reserved_Fmt,
+ Vendor_Proprietary_Fmt), bacapp_invoke_id);
+ break;
+ /* UNKNOWN */
+ default:
+ /* nothing more to add */
+ break;
+ }
+
+ save_fragmented = pinfo->fragmented;
+
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
+ bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
+
+ if (!fragment)
+ offset = do_the_dissection(tvb,pinfo,bacapp_tree);
+ else
+ fStartConfirmed(tvb, pinfo, bacapp_tree, offset, ack, &svc, &tt);
+ /* not resetting the offset so the remaining can be done */
+ }
+
+ if (fragment) { /* fragmented */
+ fragment_data *frag_msg = NULL;
+
+ new_tvb = NULL;
+ pinfo->fragmented = TRUE;
+
+ frag_msg = fragment_add_seq_check(tvb, data_offset, pinfo,
+ bacapp_invoke_id, /* ID for fragments belonging together */
+ msg_fragment_table, /* list of message fragments */
+ msg_reassembled_table, /* list of reassembled messages */
+ bacapp_seqno, /* fragment sequence number */
+ tvb_reported_length_remaining(tvb, data_offset), /* fragment length - to the end */
+ flag & BACAPP_MORE_SEGMENTS); /* Last fragment reached? */
+ new_tvb = process_reassembled_data(tvb, data_offset, pinfo,
+ "Reassembled BACapp", frag_msg, &msg_frag_items,
+ NULL, tree);
+
+ if (new_tvb) { /* Reassembled */
+ col_append_str(pinfo->cinfo, COL_INFO,
+ " (Message Reassembled)");
+ } else { /* Not last packet of reassembled Short Message */
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (Message fragment %u)", bacapp_seqno);
+ }
+ if (new_tvb) { /* take it all */
+ switch (bacapp_type)
+ {
+ case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST:
+ fContinueConfirmedRequestPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
break;
- case BACAPP_TYPE_ABORT:
- bacapp_invoke_id = tvb_get_guint8(tvb, offset + 1);
- bacapp_reason = tvb_get_guint8(tvb, offset + 2);
- col_append_fstr(pinfo->cinfo, COL_INFO, "[invoke:%d]: %s",
- bacapp_invoke_id,
- val_to_split_str(bacapp_reason,
- 64,
- BACnetAbortReason,
- ASHRAE_Reserved_Fmt,
- Vendor_Proprietary_Fmt));
+ case BACAPP_TYPE_COMPLEX_ACK:
+ fContinueComplexAckPDU(new_tvb, pinfo, bacapp_tree, 0, svc);
break;
- /* UNKNOWN */
- default:
- /* nothing more to add */
+ default:
+ /* do nothing */
break;
+ }
+ /* } */
}
}
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
- bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
- /* ASHRAE 135-2001 20.1.1 */
- switch (bacapp_type) {
- case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: /* BACnet-Confirmed-Service-Request */
- offset = fConfirmedRequestPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: /* BACnet-Unconfirmed-Request-PDU */
- offset = fUnconfirmedRequestPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_SIMPLE_ACK: /* BACnet-Simple-Ack-PDU */
- offset = fSimpleAckPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_COMPLEX_ACK: /* BACnet-Complex-Ack-PDU */
- offset = fComplexAckPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_SEGMENT_ACK: /* BACnet-SegmentAck-PDU */
- offset = fSegmentAckPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_ERROR: /* BACnet-Error-PDU */
- offset = fErrorPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_REJECT: /* BACnet-Reject-PDU */
- offset = fRejectPDU(tvb, bacapp_tree, offset);
- break;
- case BACAPP_TYPE_ABORT: /* BACnet-Abort-PDU */
- offset = fAbortPDU(tvb, bacapp_tree, offset);
- break;
- }
- }
-
- next_tvb = tvb_new_subset(tvb,offset,-1,tvb_length_remaining(tvb,offset));
- call_dissector(data_handle,next_tvb, pinfo, tree);
+ pinfo->fragmented = save_fragmented;
+
+}
+
+static void
+bacapp_init_routine(void)
+{
+ fragment_table_init(&msg_fragment_table);
+ reassembled_table_init(&msg_reassembled_table);
+}
+
+static guint32
+fConvertXXXtoUTF8 (gchar *in, gsize *inbytesleft, gchar *out, gsize *outbytesleft, const gchar *fromcoding)
+{
+ guint32 i;
+ GIConv icd;
+
+ if ((icd = g_iconv_open ("UTF-8", fromcoding)) != (GIConv) -1) {
+ i = (guint32) g_iconv (icd, &in, inbytesleft, &out, outbytesleft);
+ /* g_iconv incremented 'out'; now ensure it's NULL terminated */
+ out[0] = '\0';
+
+ g_iconv_close (icd);
+ return i;
+ }
+
+ uni_to_string(in,*inbytesleft,out);
+ out[*inbytesleft] = '\0';
+ *outbytesleft -= *inbytesleft;
+ *inbytesleft = 0;
+
+ return 0;
+}
+
+static void
+uni_to_string(char * data, gsize str_length, char *dest_buf)
+{
+ gint i;
+ guint16 c_char;
+ gsize length_remaining = 0;
+
+ length_remaining = str_length;
+ dest_buf[0] = '\0';
+ if(str_length == 0)
+ {
+ return;
+ }
+ for ( i = 0; i < (gint) str_length; i++ )
+ {
+ c_char = data[i];
+ if (c_char<0x20 || c_char>0x7e)
+ {
+ if (c_char != 0x00)
+ {
+ c_char = '.';
+ dest_buf[i] = c_char & 0xff;
+ }
+ else
+ {
+ i--;
+ str_length--;
+ }
+ }
+ else
+ {
+ dest_buf[i] = c_char & 0xff;
+ }
+ length_remaining--;
+
+ if(length_remaining==0)
+ {
+ dest_buf[i+1] = '\0';
+ return;
+ }
+ }
+ if (i < 0) {
+ i = 0;
+ }
+ dest_buf[i] = '\0';
+ return;
}
void
static hf_register_info hf[] = {
{ &hf_bacapp_type,
{ "APDU Type", "bacapp.type",
- FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, "APDU Type", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetTypeName), 0xf0, NULL, HFILL }
},
{ &hf_bacapp_pduflags,
{ "PDU Flags", "bacapp.pduflags",
- FT_UINT8, BASE_HEX, NULL, 0x0f, "PDU Flags", HFILL }
+ FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }
},
{ &hf_bacapp_SEG,
{ "Segmented Request", "bacapp.segmented_request",
- FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, "Segmented Request", HFILL }
+ FT_BOOLEAN, 8, TFS(&segments_follow), 0x08, NULL, HFILL }
},
{ &hf_bacapp_MOR,
{ "More Segments", "bacapp.more_segments",
},
{ &hf_bacapp_max_adpu_size,
{ "Size of Maximum ADPU accepted", "bacapp.max_adpu_size",
- FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, "Size of Maximum ADPU accepted", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetMaxAPDULengthAccepted), 0x0f, NULL, HFILL }
},
{ &hf_bacapp_response_segments,
{ "Max Response Segments accepted", "bacapp.response_segments",
- FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, "Max Response Segments accepted", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetMaxSegmentsAccepted), 0x70, NULL, HFILL }
},
{ &hf_bacapp_objectType,
{ "Object Type", "bacapp.objectType",
- FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, "Object Type", HFILL }
+ FT_UINT32, BASE_DEC, VALS(BACnetObjectType), 0xffc00000, NULL, HFILL }
},
{ &hf_bacapp_instanceNumber,
{ "Instance Number", "bacapp.instance_number",
- FT_UINT32, BASE_DEC, NULL, 0x003fffff, "Instance Number", HFILL }
+ FT_UINT32, BASE_DEC, NULL, 0x003fffff, NULL, HFILL }
+ },
+ { &hf_BACnetPropertyIdentifier,
+ { "Property Identifier", "bacapp.property_identifier",
+ FT_UINT32, BASE_DEC, VALS(BACnetPropertyIdentifier), 0, NULL, HFILL }
+ },
+ { &hf_BACnetVendorIdentifier,
+ { "Vendor Identifier", "bacapp.vendor_identifier",
+ FT_UINT16, BASE_DEC, VALS(BACnetVendorIdentifiers), 0, NULL, HFILL }
+ },
+ { &hf_BACnetRestartReason,
+ { "Restart Reason", "bacapp.restart_reason",
+ FT_UINT8, BASE_DEC, VALS(BACnetRestartReason), 0, NULL, HFILL }
},
{ &hf_bacapp_invoke_id,
{ "Invoke ID", "bacapp.invoke_id",
- FT_UINT8, BASE_DEC, NULL, 0, "Invoke ID", HFILL }
+ FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_bacapp_sequence_number,
{ "Sequence Number", "bacapp.sequence_number",
- FT_UINT8, BASE_DEC, NULL, 0, "Sequence Number", HFILL }
+ FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_bacapp_window_size,
{ "Proposed Window Size", "bacapp.window_size",
- FT_UINT8, BASE_DEC, NULL, 0, "Proposed Window Size", HFILL }
+ FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
},
{ &hf_bacapp_service,
{ "Service Choice", "bacapp.confirmed_service",
- FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, "Service Choice", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetConfirmedServiceChoice), 0x00, NULL, HFILL }
},
{ &hf_bacapp_uservice,
{ "Unconfirmed Service Choice", "bacapp.unconfirmed_service",
- FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, "Unconfirmed Service Choice", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetUnconfirmedServiceChoice), 0x00, NULL, HFILL }
},
{ &hf_bacapp_NAK,
{ "NAK", "bacapp.NAK",
- FT_BOOLEAN, 8, NULL, 0x02, "negativ ACK", HFILL }
+ FT_BOOLEAN, 8, NULL, 0x02, "negative ACK", HFILL }
},
{ &hf_bacapp_SRV,
{ "SRV", "bacapp.SRV",
},
{ &hf_BACnetRejectReason,
{ "Reject Reason", "bacapp.reject_reason",
- FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, "Reject Reason", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetRejectReason), 0x00, NULL, HFILL }
},
{ &hf_BACnetAbortReason,
{ "Abort Reason", "bacapp.abort_reason",
- FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, "Abort Reason", HFILL }
+ FT_UINT8, BASE_DEC, VALS(BACnetAbortReason), 0x00, NULL, HFILL }
},
{ &hf_bacapp_vpart,
{ "BACnet APDU variable part:", "bacapp.variable_part",
- FT_NONE, 0, NULL, 0, "BACnet APDU variable part", HFILL }
+ FT_NONE, BASE_NONE, NULL, 0, "BACnet APDU variable part", HFILL }
},
{ &hf_bacapp_tag,
{ "BACnet Tag",
"bacapp.tag",
- FT_BYTES, BASE_HEX, NULL, 0,
- "BACnet Tag", HFILL }
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
},
{ &hf_BACnetApplicationTagNumber,
{ "Application Tag Number",
"bacapp.application_tag_number",
FT_UINT8, BASE_DEC, VALS(&BACnetApplicationTagNumber), 0xF0,
- "Application Tag Number", HFILL }
+ NULL, HFILL }
},
{ &hf_BACnetContextTagNumber,
{ "Context Tag Number",
"bacapp.context_tag_number",
FT_UINT8, BASE_DEC, NULL, 0xF0,
- "Context Tag Number", HFILL }
+ NULL, HFILL }
},
{ &hf_BACnetExtendedTagNumber,
{ "Extended Tag Number",
"bacapp.extended_tag_number",
FT_UINT8, BASE_DEC, NULL, 0,
- "Extended Tag Number", HFILL }
+ NULL, HFILL }
},
{ &hf_BACnetNamedTag,
{ "Named Tag",
"bacapp.named_tag",
FT_UINT8, BASE_DEC, VALS(&BACnetTagNames), 0x07,
- "Named Tag", HFILL }
+ NULL, HFILL }
},
{ &hf_BACnetCharacterSet,
{ "String Character Set",
"bacapp.string_character_set",
FT_UINT8, BASE_DEC, VALS(&BACnetCharacterSet),0,
- "String Character Set", HFILL }
+ NULL, HFILL }
},
{ &hf_BACnetTagClass,
{ "Tag Class", "bacapp.tag_class",
- FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, "Tag Class", HFILL }
+ FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
},
{ &hf_bacapp_tag_lvt,
{ "Length Value Type",
"bacapp.LVT",
FT_UINT8, BASE_DEC, NULL, 0,
- "Length Value Type", HFILL }
+ NULL, HFILL }
},
{ &hf_bacapp_tag_value8,
{ "Tag Value",
"bacapp.tag_value8",
FT_UINT8, BASE_DEC, NULL, 0,
- "Tag Value", HFILL }
+ NULL, HFILL }
},
{ &hf_bacapp_tag_value16,
{ "Tag Value 16-bit",
"bacapp.tag_value16",
FT_UINT16, BASE_DEC, NULL, 0,
- "Tag Value 16-bit", HFILL }
+ NULL, HFILL }
},
{ &hf_bacapp_tag_value32,
{ "Tag Value 32-bit",
"bacapp.tag_value32",
FT_UINT32, BASE_DEC, NULL, 0,
- "Tag Value 32-bit", HFILL }
+ NULL, HFILL }
},
{ &hf_bacapp_tag_ProcessId,
{ "ProcessIdentifier", "bacapp.processId",
FT_UINT32, BASE_DEC, NULL, 0, "Process Identifier", HFILL }
},
+ { &hf_bacapp_tag_IPV4,
+ { "IPV4", "bacapp.IPV4",
+ FT_IPv4, BASE_NONE, NULL, 0, "IP-Address", HFILL }
+ },
+ { &hf_bacapp_tag_IPV6,
+ { "IPV6", "bacapp.IPV6",
+ FT_IPv6, BASE_NONE, NULL, 0, "IP-Address", HFILL }
+ },
+ { &hf_bacapp_tag_PORT,
+ { "Port", "bacapp.Port",
+ FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
+ },
{ &hf_bacapp_tag_initiatingObjectType,
{ "ObjectType", "bacapp.objectType",
FT_UINT16, BASE_DEC, VALS(BACnetObjectType), 0x00, "Object Type", HFILL }
},
+ {&hf_msg_fragments,
+ {"Message fragments", "bacapp.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_fragment,
+ {"Message fragment", "bacapp.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_fragment_overlap,
+ {"Message fragment overlap", "bacapp.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_fragment_overlap_conflicts,
+ {"Message fragment overlapping with conflicting data",
+ "bacapp.fragment.overlap.conflicts",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_fragment_multiple_tails,
+ {"Message has multiple tail fragments",
+ "bacapp.fragment.multiple_tails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_fragment_too_long_fragment,
+ {"Message fragment too long", "bacapp.fragment.too_long_fragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_fragment_error,
+ {"Message defragmentation error", "bacapp.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_reassembled_in,
+ {"Reassembled in", "bacapp.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
+ {&hf_msg_reassembled_length,
+ {"Reassembled BACapp length", "bacapp.reassembled.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
};
static gint *ett[] = {
&ett_bacapp,
&ett_bacapp_tag,
&ett_bacapp_list,
&ett_bacapp_value,
+ &ett_msg_fragment,
+ &ett_msg_fragments
+
};
+
proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
- "BACapp", "bacapp");
+ "BACapp", "bacapp");
proto_register_field_array(proto_bacapp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("bacapp", dissect_bacapp, proto_bacapp);
+ register_init_routine (&bacapp_init_routine);
}
data_handle = find_dissector("data");
}
-guint32
-fConvertXXXtoUTF8 (const guint8 *in, size_t *inbytesleft, guint8 *out, size_t *outbytesleft, const gchar *fromcoding)
-{ /* I don't want to let in and out be modified */
-#ifdef HAVE_CONFIG_H
-#if HAVE_ICONV_H
- guint32 i;
- iconv_t icd;
- const guint8 *inp = in;
- guint8 *outp = out;
- const guint8 **inpp = &inp;
- guint8 **outpp = &outp;
-
- if ((icd = iconv_open ("UTF-8", fromcoding)) != (iconv_t) -1) {
- i = iconv (icd, (char**) inpp, inbytesleft, (char**) outpp, outbytesleft);
- *outpp[0] = '\0';
- iconv_close (icd);
- return i;
- }
-
-#endif
-#endif
-
- memcpy (out, in, *inbytesleft);
- out[*inbytesleft] = '\0';
- *outbytesleft -= *inbytesleft;
- *inbytesleft = 0;
-
- return 0;
-}
-