Wireshark-dev: [Wireshark-dev] Patch for BACnet (packet-bacapp.c/.h)
From: David Richards <d_m_richards@xxxxxxxxxxx>
Date: Tue, 03 Oct 2006 03:20:43 -0500
Here is a patch for BACnet. It contains numerous changes, most notably: 1) BACnetStatusFlags is bit string, not enum, in NotificationParameters 2) Fixes many places where enclosing context tags were not handled properly.3) Simplify tag decoding logic. Change to explicit decoding in many instances rather
than read tags in a loop and do a switch based on tag number. Looping ignores out-of-order and other types of tagging errors.Could someone please commit these changes. I used TortoiseSVN "Create Patch" to generate this file. If there's a problem with it let me know.
Thanks, Dave Richards
Index: packet-bacapp.c =================================================================== --- packet-bacapp.c (revision 19401) +++ packet-bacapp.c (working copy) @@ -156,7 +156,39 @@ {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"}, {1,"buffer-overflow"}, @@ -1204,6 +1236,16 @@ { 0, NULL } }; +static const value_string +BACnetReadRangeOptions[] = { + { 3, "range byPosition" }, + { 4, "range byTime" }, + { 5, "range timeRange" }, + { 6, "range bySequenceNumber" }, + { 7, "range byTime" }, + { 0, NULL } +}; + static int proto_bacapp = -1; static int hf_bacapp_type = -1; static int hf_bacapp_pduflags = -1; @@ -1673,9 +1715,9 @@ 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); + offset += tag_len + lvt; - return offset+tag_len+lvt; + return offset; } static guint @@ -1984,14 +2026,12 @@ 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) @@ -2028,21 +2068,18 @@ static guint fRecipient (tvbuff_t *tvb, 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 */ + fTagHeader(tvb, offset, &tag_no, &tag_info, &lvt); + if (tag_no < 2) { + if (tag_no == 0) { /* device */ offset = fObjectIdentifier (tvb, tree, offset); - break; - case 1: /* address */ + } + 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; @@ -2052,19 +2089,23 @@ fRecipientProcess (tvbuff_t *tvb, 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: /* recipient */ + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); offset = fRecipient (tvb, 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; } } @@ -2333,55 +2374,58 @@ if (tvb_length_remaining(tvb, offset) > 0) { tag_len = fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt); + 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, 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; + } - 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; } } return offset; @@ -2463,6 +2507,9 @@ case 30: /* BACnetAddressBinding */ offset = fAddressBinding (tvb,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, @@ -2495,14 +2542,18 @@ if (object_type < 128) { offset = fSpecialEvent (tvb,tree,offset); - break; } + break; case 123: /* weekly-schedule */ if (object_type < 128) { offset = fWeeklySchedule (tvb,tree,offset); - break; } + break; + case 159: /* member-of */ + case 165: /* zone-members */ + fDeviceObjectReference (tvb, tree, offset); + break; default: if (tag_info) { @@ -2638,7 +2689,7 @@ break; case 2: /* BACnetObjectId */ offset = fObjectIdentifier (tvb, tree, offset); - break; + break; case 3: /* messageText */ offset = fCharacterString (tvb,tree,offset, "Object Name: "); break; @@ -2966,7 +3017,7 @@ "referenced-bitstring: "); break; case 1: - offset = fEnumeratedTag (tvb, subtree, offset, + offset = fBitStringTagVS (tvb, subtree, offset, "status-flags: ", BACnetStatusFlags); break; default: @@ -2984,7 +3035,7 @@ offset = fBACnetPropertyStates(tvb, subtree, offset); offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt); case 1: - offset = fEnumeratedTag (tvb, subtree, offset, + offset = fBitStringTagVS (tvb, subtree, offset, "status-flags: ", BACnetStatusFlags); lastoffset = offset; break; @@ -3014,7 +3065,7 @@ 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; default: @@ -3032,7 +3083,7 @@ 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); case 2: /* "feedback-value: " */ offset += fTagHeaderTree(tvb, subtree, offset, &tag_no, &tag_info, &lvt); @@ -3051,7 +3102,7 @@ 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: @@ -3072,7 +3123,7 @@ 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: @@ -3128,7 +3179,7 @@ "new-mode: ", BACnetLifeSafetyState, 256); break; case 2: - offset = fEnumeratedTag (tvb, subtree, offset, + offset = fBitStringTagVS (tvb, subtree, offset, "status-flags: ", BACnetStatusFlags); case 3: offset = fEnumeratedTagSplit (tvb, subtree, offset, @@ -3328,14 +3379,19 @@ fLogRecord (tvbuff_t *tvb, 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: /* timestamp */ + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); offset = fDateTime (tvb,tree,offset,NULL); + 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, @@ -3369,11 +3425,14 @@ offset = fRealTag (tvb, tree, offset, "time change: "); break; case 10: /* any Value */ + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); offset = fAbstractSyntaxNType (tvb, tree, offset); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); break; default: return offset; } + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); break; case 2: offset = fEnumeratedTag (tvb, tree, offset, @@ -3473,6 +3532,7 @@ if (tag_is_closing(tag_info)) { offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); + lastoffset = offset; subtree = tree; continue; } @@ -3481,7 +3541,7 @@ case 0: /* ProcessId */ offset = fProcessId (tvb,tree,offset); break; - case 1: /* initiating ObjectId */ + case 1: /* initiating DeviceId */ offset = fObjectIdentifier (tvb, subtree, offset); break; case 2: /* monitored ObjectId */ @@ -3585,23 +3645,26 @@ 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, tree, offset); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); break; case 2: /* eventStateFilter */ offset = fEnumeratedTag (tvb, tree, offset, "event State Filter: ", BACnetEventStateFilter); break; - case 3: /* eventTypeFilter */ + 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: @@ -3620,10 +3683,10 @@ while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */ lastoffset = offset; offset = fApplicationTypes (tvb, tree, offset, "Object Identifier: "); - offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, + offset = fApplicationTypesEnumeratedSplit (tvb, tree, offset, "event Type: ", BACnetEventType, 64); - offset = fApplicationTypesEnumerated (tvb, tree, offset, - "event State: ", BACnetEventStateFilter); + offset = fApplicationTypesEnumerated (tvb, tree, offset, + "event State: ", BACnetEventState); offset = fApplicationTypes (tvb, tree, offset, "Priority: "); offset = fApplicationTypes (tvb, tree, offset, "Notification Class: "); } @@ -3634,17 +3697,9 @@ static guint fGetEventInformationRequest (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: /* lastReceivedObjectId */ + if (tvb_length_remaining(tvb, offset) > 0) { + if (fTagNo(tvb, offset) == 0) { offset = fObjectIdentifier (tvb, tree, offset); - break; - default: - return offset; - break; } } return offset; @@ -3654,6 +3709,8 @@ flistOfEventSummaries (tvbuff_t *tvb, 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; @@ -3670,9 +3727,11 @@ "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: "); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); + offset = fTimeStamp (tvb, tree, offset); + offset = fTimeStamp (tvb, tree, offset); + offset = fTimeStamp (tvb, tree, offset); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); break; case 4: /* notifyType */ offset = fEnumeratedTag (tvb, tree, offset, @@ -3683,9 +3742,12 @@ "event Enable: ", BACnetEventTransitionBits); break; case 6: /* eventPriorities */ + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); offset = fUnsignedTag (tvb, tree, offset, "event Priority: "); offset = fUnsignedTag (tvb, tree, offset, "event Priority: "); offset = fUnsignedTag (tvb, tree, offset, "event Priority: "); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); + lastoffset = offset; break; default: return offset; @@ -3708,6 +3770,7 @@ case 0: /* listOfEventSummaries */ offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); offset = flistOfEventSummaries (tvb, tree, offset); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); break; case 1: /* moreEvents */ offset = fBooleanTag (tvb, tree, offset, "more Events: "); @@ -3783,7 +3846,7 @@ offset = fEnumeratedTag (tvb, tree, offset, "enable-disable: ", BACnetEnableDisable); break; - case 2: /* password */ + case 2: /* password - OPTIONAL */ offset = fCharacterString (tvb, tree, offset, "Password: "); break; default: @@ -3808,7 +3871,7 @@ "reinitialized State Of Device: ", BACnetReinitializedStateOfDevice); break; - case 1: /* password */ + case 1: /* password - OPTIONAL */ offset = fCharacterString (tvb, tree, offset, "Password: "); break; default: @@ -4177,7 +4240,6 @@ } #endif -#if 0 static guint fDeviceObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset) { @@ -4190,7 +4252,7 @@ case 0: /* ObjectIdentifier */ offset = fBACnetObjectPropertyReference (tvb, tree, offset); break; - case 3: /* deviceIdentifier */ + case 3: /* deviceIdentifier - OPTIONAL */ offset = fObjectIdentifier (tvb, tree, offset); break; default: @@ -4199,7 +4261,6 @@ } return offset; } -#endif static guint fPriorityArray (tvbuff_t *tvb, proto_tree *tree, guint offset) @@ -4216,13 +4277,12 @@ ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt), i); - /* DMR Replace with fAbstractNSyntax */ + /* DMR Should be fAbstractNSyntax, but that's where we came from! */ offset = fApplicationTypes(tvb, tree, offset, ar); } return offset; } -#if 0 static guint fDeviceObjectReference (tvbuff_t *tvb, proto_tree *tree, guint offset) { @@ -4232,7 +4292,7 @@ lastoffset = offset; switch (fTagNo(tvb,offset)) { - case 0: /* deviceIdentifier */ + case 0: /* deviceIdentifier - OPTIONAL */ offset = fObjectIdentifier (tvb, tree, offset); break; case 1: /* ObjectIdentifier */ @@ -4244,7 +4304,6 @@ } return offset; } -#endif static guint fSpecialEvent (tvbuff_t *tvb, proto_tree *subtree, guint offset) @@ -4295,10 +4354,16 @@ fSelectionCriteria (tvbuff_t *tvb, 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; - + fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt); + if (tag_is_closing(tag_info)) { /* stop when we hit outer closing tag */ + continue; + } + switch (fTagNo(tvb,offset)) { case 0: /* propertyIdentifier */ offset = fPropertyIdentifier (tvb, tree, offset); @@ -4311,7 +4376,9 @@ "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, tree, offset); + offset += fTagHeaderTree (tvb, tree, offset, &tag_no, &tag_info, &lvt); break; default: return offset; @@ -4330,9 +4397,7 @@ 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); + if (tag_is_closing(tag_info)) { /* stop when we hit outer closing tag */ continue; } @@ -4345,6 +4410,7 @@ if (tag_is_opening(tag_info)) { offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); offset = fSelectionCriteria (tvb, subtree, offset); + offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); break; } FAULT; @@ -4367,25 +4433,20 @@ 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); - 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); + if (tag_is_opening(tag_info) && tag_no < 2) { + offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); + switch (tag_no) { + case 0: /* objectSelectionCriteria */ + offset = fObjectSelectionCriteria (tvb, subtree, offset); + break; + case 1: /* listOfPropertyReferences */ offset = fBACnetPropertyReference (tvb, subtree, offset, 1); break; + default: + return offset; } - FAULT; - break; - default: - return offset; + offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); } } return offset; @@ -4490,27 +4551,6 @@ 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) { guint lastoffset = 0; @@ -4520,26 +4560,34 @@ 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); - 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, subtree, offset); + break; + default: + break; + } break; + case 1: /* propertyValue */ + if (tag_is_opening(tag_info)) { + offset = fBACnetPropertyValue (tvb, subtree, offset); + break; + } + FAULT; + break; + default: + break; } - FAULT; - break; - default: - return offset; + offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); } } return offset; @@ -4554,80 +4602,38 @@ static guint fReadRangeRequest (tvbuff_t *tvb, 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; - } + offset = fBACnetObjectPropertyReference(tvb, subtree, offset); + fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt); + /* optional range choice */ + if (tag_is_opening(tag_info)) { + tt = proto_tree_add_text(subtree, tvb, offset, 1, 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 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: "); - break; - } - FAULT; + case 6: /* range bySequenceNumber, 2004 spec */ + offset = fApplicationTypes (tvb, subtree, offset, "reference Index: "); + offset = fApplicationTypes (tvb, subtree, offset, "reference Count: "); 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); - offset = fDateTime(tvb, subtree, offset, "reference Date/Time: "); - offset = fApplicationTypes (tvb, subtree, offset, "reference Count: "); - break; - } - FAULT; + 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: "); 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: "); - break; - } - FAULT; + case 5: /* range timeRange - deprecated in 2004 */ + offset = fDateTime(tvb, subtree, offset, "beginning Time: "); + offset = fDateTime(tvb, subtree, offset, "ending Time: "); 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: "); - break; - } - FAULT; - break; default: - return offset; + break; } + offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); } return offset; } @@ -4635,60 +4641,39 @@ static guint fReadRangeAck (tvbuff_t *tvb, 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; - } + offset = fBACnetObjectPropertyReference(tvb, subtree, offset); + + /* resultFlags */ + offset = fEnumeratedTag (tvb, tree, offset, "result Flags: ", BACnetResultFlags); + + /* itemCount */ + offset = fUnsignedTag (tvb, subtree, offset, "item Count: "); - 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; - } + fTagHeader (tvb, offset, &tag_no, &tag_info, &lvt); + /* 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); + offset += fTagHeaderTree (tvb, subtree, offset, &tag_no, &tag_info, &lvt); } + + if (fTagNo(tvb, offset) == 6) { /* firstSequenceNumber - OPTIONAL */ + offset = fUnsignedTag (tvb, subtree, offset, "first Sequence Number: "); + } + return offset; } static guint fAccessMethod(tvbuff_t *tvb, proto_tree *tree, guint offset) { + guint lastoffset = 0; guint32 lvt; guint8 tag_no, tag_info; proto_item* tt; @@ -4696,51 +4681,38 @@ 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 (tag_is_opening(tag_info)) + { + tt = proto_tree_add_text(tree, tvb, offset, 1, 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, subtree, offset, val_to_str(tag_no, BACnetFileStartOption, "invalid option")); + offset = fApplicationTypes (tvb, subtree, offset, val_to_str(tag_no, BACnetFileWriteInfo, "unknown option")); + + if (tag_no == 1) + { + while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) + { /* exit loop if nothing happens inside */ + lastoffset = offset; + offset = fApplicationTypes (tvb, subtree, offset, "Record 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; - } - 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; - } + 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); + } + } + } return offset; } static guint fAtomicReadFileRequest(tvbuff_t *tvb, proto_tree *tree, guint offset) { - guint lastoffset = 0; guint8 tag_no, tag_info; guint32 lvt; proto_tree *subtree = tree; @@ -4748,42 +4720,16 @@ 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; - } + 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(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; - } + if (tag_is_opening(tag_info)) + { + tt = proto_tree_add_text(subtree, tvb, offset, 1, 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; } @@ -4801,28 +4747,14 @@ 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) { - 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 = fApplicationTypes (tvb, tree, offset, "End Of File: "); offset = fAccessMethod(tvb, tree, offset); return offset; @@ -5253,6 +5185,8 @@ fConfirmedPrivateTransferError(tvbuff_t *tvb, proto_tree *tree, guint offset) { guint lastoffset = 0; + guint8 tag_no = 0, tag_info = 0; + guint lvt = 0; while ((tvb_length_remaining(tvb, offset) > 0)&&(offset>lastoffset)) { /* exit loop if nothing happens inside */ lastoffset = offset; @@ -5267,7 +5201,9 @@ offset = fUnsignedTag (tvb,tree,offset,"service Number: "); break; case 3: /* errorParameters */ - offset = fAbstractSyntaxNType (tvb, tree, offset); + offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt); + offset = fAbstractSyntaxNType (tvb, tree, offset); + offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt); break; default: return offset; @@ -5300,55 +5236,29 @@ static guint fChangeListError(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); - break; - case 1: /* firstFailedElementNumber */ - offset = fUnsignedTag (tvb,tree,offset,"first failed element number: "); - break; - default: - return offset; - } - } - return offset; + /* Identical to CreateObjectError */ + return fCreateObjectError(tvb, tree, offset); } -#if 0 static guint -fVTSession(tvbuff_t *tvb, 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; -} -#endif - -static guint fVTCloseError(tvbuff_t *tvb, 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,tree,offset); + if (fTagNo(tvb, offset) == 1) + { + /* listOfVTSessionIdentifiers [OPTIONAL] */ + offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt); + offset = fVtCloseRequest (tvb, tree, offset); + offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt); } } + /* should report bad packet if initial tag wasn't 0 */ return offset; } @@ -5356,6 +5266,8 @@ fWritePropertyMultipleError(tvbuff_t *tvb, 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; @@ -5364,7 +5276,9 @@ offset = fContextTaggedError(tvb,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, tree, offset); + offset += fTagHeaderTree(tvb, tree, offset, &tag_no, &tag_info, &lvt); break; default: return offset; Index: packet-bacapp.h =================================================================== --- packet-bacapp.h (revision 19401) +++ packet-bacapp.h (working copy) @@ -1483,7 +1483,6 @@ fDeviceObjectPropertyReference (tvbuff_t *tvb, proto_tree *tree, guint offset); #endif -#if 0 /** * BACnetDeviceObjectReference ::= SEQUENCE { * deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL, @@ -1496,7 +1495,6 @@ */ static guint fDeviceObjectReference (tvbuff_t *tvb, proto_tree *tree, guint offset); -#endif #if 0 /** @@ -2012,19 +2010,6 @@ fObjectSelectionCriteria (tvbuff_t *tvb, proto_tree *subtree, guint offset); /** - * ObjectSpecifier ::= CHOICE { - * objectType [0] BACnetObjectType, - * objectIdentifier [1] BACnetObjectIdentifier - * } - * @param tvb - * @param tree - * @param offset - * @return modified offset - */ -static guint -fObjectSpecifier (tvbuff_t *tvb, proto_tree *tree, guint offset); - -/** * BACnet-Error ::= SEQUENCE { * error-class ENUMERATED {}, * error-code ENUMERATED {}
- Follow-Ups:
- Re: [Wireshark-dev] Patch for BACnet (packet-bacapp.c/.h)
- From: Anders Broman
- Re: [Wireshark-dev] Patch for BACnet (packet-bacapp.c/.h)
- Prev by Date: Re: [Wireshark-dev] [Patch] update to packet-newmail.c
- Next by Date: Re: [Wireshark-dev] RTP-MIDI
- Previous by thread: [Wireshark-dev] Fwd: Patch for packet-vnc.c
- Next by thread: Re: [Wireshark-dev] Patch for BACnet (packet-bacapp.c/.h)
- Index(es):