diff options
author | Dirk Römmen <dro@cslab.de> | 2021-04-11 20:59:36 +0200 |
---|---|---|
committer | Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2021-05-19 13:21:48 +0000 |
commit | a1a2b536633bce719b6b66f03e49cdf927da70eb (patch) | |
tree | cd9b7d90a79554350f59ababb3ad0985ddb703c2 | |
parent | df508537be8f5a673631e40d023cd6ae31fd7b6c (diff) | |
download | wireshark-a1a2b536633bce719b6b66f03e49cdf927da70eb.tar.gz wireshark-a1a2b536633bce719b6b66f03e49cdf927da70eb.tar.bz2 wireshark-a1a2b536633bce719b6b66f03e49cdf927da70eb.zip |
BACnet: BACnet revision 22 secure connect datalink implementation.
- Implements the BACnet /SC datalink using encrypted TLS communication
over TCP/IP and the websocket protocol.
- Updated list of vendor ID's
- Added new BACnet services Who-Am-I / You-Are
- Some corrections for revision 22.
- Fixed bug issue #17142
-rw-r--r-- | epan/dissectors/packet-bacapp.c | 287 | ||||
-rw-r--r-- | epan/dissectors/packet-bacapp.h | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-bacnet.c | 1 | ||||
-rw-r--r-- | epan/dissectors/packet-bvlc.c | 891 | ||||
-rw-r--r-- | epan/dissectors/packet-http.c | 39 |
5 files changed, 1188 insertions, 32 deletions
diff --git a/epan/dissectors/packet-bacapp.c b/epan/dissectors/packet-bacapp.c index d32606dd71..ee2e10d507 100644 --- a/epan/dissectors/packet-bacapp.c +++ b/epan/dissectors/packet-bacapp.c @@ -2958,6 +2958,11 @@ BACnetLifeSafetyMode [] = { { 12, "disabled"}, { 13, "atomic-release-disabled"}, { 14, "default"}, + { 15, "activated-oeo-alarm"}, + { 16, "activated-oeo-evacuate"}, + { 17, "activated-oeo-phase1-recall"}, + { 18, "activated-oeo-unavailable"}, + { 19, "deactivated"}, { 0, NULL} /* Enumerated values 0-255 are reserved for definition by ASHRAE. Enumerated values 256-65535 may be used by others subject to @@ -3008,6 +3013,17 @@ BACnetLifeSafetyState [] = { { 21, "general-alarm"}, { 22, "supervisory"}, { 23, "test-supervisory"}, + { 24, "non-default-mode"}, + { 25, "oeo-unavailable"}, + { 26, "oeo-alarm"}, + { 27, "oeo-phase1-recall"}, + { 28, "oeo-evacuate"}, + { 29, "oeo-unaffected"}, + { 30, "test-oeo-unavailable"}, + { 31, "test-oeo-alarm"}, + { 32, "test-oeo-phase1-recall"}, + { 33, "test-oeo-evacuate"}, + { 34, "test-oeo-unaffected"}, { 0, NULL} /* Enumerated values 0-255 are reserved for definition by ASHRAE. Enumerated values 256-65535 may be used by others subject to @@ -3317,6 +3333,8 @@ BACnetUnconfirmedServiceChoice [] = { { 10, "writeGroup"}, { 11, "unconfirmedCovNotificationMultiple"}, { 12, "unconfirmedAuditNotification"}, + { 13, "who-am-I" }, + { 14, "you-are" }, { 0, NULL} }; @@ -3377,7 +3395,7 @@ BACnetObjectType [] = { { 52, "alert-enrollment"}, { 53, "channel"}, { 54, "lighting-output"}, - { 55, "reserved-obj-type-55"}, + { 55, "binary-lighting-output"}, { 56, "network-port"}, { 57, "elevator-group"}, { 58, "escalator"}, @@ -3654,6 +3672,16 @@ BACnetEngineeringUnits [] = { { 47810, "thousand-cubic-feet-per-day"}, { 47811, "thousand-standard-cubic-feet-per-day"}, { 47812, "pounds-mass-per-day"}, + { 47813, "reserved-unit-47813"}, + { 47814, "millirems"}, + { 47815, "millirems-per-hour"}, + { 47816, "degrees-lovibond"}, + { 47817, "alcohol-by-volume"}, + { 47818, "international-bittering-units"}, + { 47819, "european-bitterness-units"}, + { 47820, "degrees-plato"}, + { 47821, "specific-gravity"}, + { 47822, "european-brewing-convention"}, { 0, NULL} /* Enumerated values 0-255 are reserved for definition by ASHRAE. Enumerated values 256-65535 may be used by others subject to @@ -3801,6 +3829,10 @@ BACnetErrorCode [] = { { 136, "abort-security-error"}, { 137, "duplicate-entry"}, { 138, "invalid-value-in-this-state"}, + { 139, "invalid-operation-in-this-state"}, + { 140, "list-item-not-numbered"}, + { 141, "list-item-not-timestamped"}, + { 142, "invalid-data-encoding"}, { 0, NULL} /* Enumerated values 0-255 are reserved for definition by ASHRAE. Enumerated values 256-65535 may be used by others subject to the @@ -4301,6 +4333,8 @@ BACnetPropertyIdentifier [] = { { 503, "maximum-send-delay"}, { 504, "monitored-objects"}, { 505, "send-now"}, + { 506, "floor-number"}, + { 507, "device-uuid"}, { 0, NULL} /* Enumerated values 0-511 are reserved for definition by ASHRAE. Enumerated values 512-4194303 may be used by others subject to @@ -4636,6 +4670,9 @@ BACnetServicesSupported [] = { { 41, "subscribe-cov-property-multiple"}, { 42, "confirmed-cov-notification-multiple"}, { 43, "unconfirmed-cov-notification-multiple"}, + { 44, "confirmed-audit-notification" }, + { 45, "audit-log-query" }, + { 46, "unconfirmed-audit-notification" }, { 0, NULL} }; @@ -4964,7 +5001,7 @@ BACnetSuccessFilter [] = { /* These values are (manually) transferred from * http://www.bacnet.org/VendorID/BACnet Vendor IDs.htm - * Version: "As of September 6, 2019" + * Version: "As of May 03, 2021" */ static const value_string @@ -6145,6 +6182,138 @@ BACnetVendorIdentifiers [] = { { 1174, "DAS Integrator Pte Ltd" }, { 1175, "CREVIS Co., Ltd" }, { 1176, "iSquared software inc." }, + { 1177, "KTG GmbH" }, + { 1178, "POK Group Oy" }, + { 1179, "Adiscom" }, + { 1180, "Incusense" }, + { 1181, "75F" }, + { 1182, "Anord Mardix, Inc." }, + { 1183, "HOSCH Gebäudeautomation" }, + { 1184, "BOSCH Software Innovations GmbH" }, + { 1185, "Royal Boon Edam International B.V." }, + { 1186, "Clack Corporation" }, + { 1187, "Unitex Controls LLC" }, + { 1188, "KTC Göteborg AB" }, + { 1189, "Interzon AB" }, + { 1190, "ISDE ING SL" }, + { 1191, "ABM automation building messaging GmbH" }, + { 1192, "Kentec Electronics Ltd" }, + { 1193, "Emerson Commercial and Residential Solutions" }, + { 1194, "Powerside" }, + { 1195, "SMC Group" }, + { 1196, "EOS Weather Instruments" }, + { 1197, "Zonex Systems" }, + { 1198, "Generex Systems Computervertriebsgesellschaft mbH" }, + { 1199, "Energy Wall LLC" }, + { 1200, "Thermofin" }, + { 1201, "SDATAWAY SA" }, + { 1202, "Biddle Air Systems Limited" }, + { 1203, "Kessler" }, + { 1204, "Thermoscreens" }, + { 1205, "Modio" }, + { 1206, "Newron Solutions" }, + { 1207, "Unitronics" }, + { 1208, "TRILUX GmbH & Co. KG" }, + { 1209, "Kollmorgen Steuerungstechnik GmbH" }, + { 1210, "Bosch Rexroth AG" }, + { 1211, "Alarko Carrier" }, + { 1212, "Verdigris Technologies" }, + { 1213, "Shanghai SIIC-Longchuang Smarter Energy Technology Co., Ltd." }, + { 1214, "Quinda Co." }, + { 1215, "GRUNER AG" }, + { 1216, "BACMOVE" }, + { 1217, "PSIDAC AB" }, + { 1218, "ISICON-Control Automation" }, + { 1219, "Big Ass Fans" }, + { 1220, "din" }, + { 1221, "Teldio" }, + { 1222, "MIKROKLIMA s.r.o." }, + { 1223, "Density" }, + { 1224, "ICONAG-Leittechnik GmbH" }, + { 1225, "Awair" }, + { 1226, "T&D Engineering, Ltd" }, + { 1227, "Sistemas Digitales" }, + { 1228, "Loxone Electronics GmbH" }, + { 1229, "ActronAir" }, + { 1230, "Inductive Automation" }, + { 1231, "Thor Engineering GmbH" }, + { 1232, "Berner International, LLC" }, + { 1233, "Potsdam Sensors LLC" }, + { 1234, "Kohler Mira Ltd" }, + { 1235, "Tecomon GmbH" }, + { 1236, "Two Dimensional Instruments, LLC" }, + { 1237, "LEFA Technologies Pte. Ltd" }, + { 1238, "EATON CEAG Notlichtsysteme GmbH" }, + { 1239, "Commbox Tecnologia" }, + { 1240, "IPVideo Corporation" }, + { 1241, "Bender GmbH & Co. KG" }, + { 1242, "Rhymebus Corporation" }, + { 1243, "Axon Systems Ltd" }, + { 1244, "Engineered Air" }, + { 1245, "Elipse Software Ltd" }, + { 1246, "Simatix Building Technologies Pvt. Ltd." }, + { 1247, "W.A. Benjamin Electric Co." }, + { 1248, "TROX Air Conditioning Components (Suzhou) Co. Ltd." }, + { 1249, "SC Medical Pty Ltd." }, + { 1250, "Elcanic A/S" }, + { 1251, "Obeo AS" }, + { 1252, "Tapa, Inc." }, + { 1253, "ASE Smart Energy, Inc." }, + { 1254, "Performance Services, Inc." }, + { 1255, "Veridify Security" }, + { 1256, "CD Innovation LTD" }, + { 1257, "Ben Peoples Industries, LLC" }, + { 1258, "UNICOMM Sp. z o.o" }, + { 1259, "Thing Technologies GmbH" }, + { 1260, "Beijing HaiLin Energy Saving Technology, Inc." }, + { 1261, "Digital Realty" }, + { 1262, "Agrowtek Inc." }, + { 1263, "DSP Innovation BV " }, + { 1264, "STV Electronic GmbH" }, + { 1265, "Elmeasure India Pvt Ltd." }, + { 1266, "Pineshore Energy LLC." }, + { 1267, "Brasch Environmental Technologies, LLC." }, + { 1268, "Lion Controls Co., LTD" }, + { 1269, "Sinux" }, + { 1270, "Avnet Inc." }, + { 1271, "Somfy Activites SA" }, + { 1272, "Amico" }, + { 1273, "SageGlass" }, + { 1274, "AuVerte" }, + { 1275, "Agile Connects Pvt. Ltd." }, + { 1276, "Locimation Pty Ltd." }, + { 1277, "Envio Systems GmbH" }, + { 1278, "Voytech Systems Limited" }, + { 1279, "Davidsmeyer und Paul GmbH" }, + { 1280, "Lusher Engineering Services" }, + { 1281, "CHNT Nanjing Techsel Intelligent Company LTD." }, + { 1282, "Threetronics Pty Ltd." }, + { 1283, "SkyFoundry, LLC." }, + { 1284, "HanilProTech" }, + { 1285, "Sensorscall" }, + { 1286, "Shanghai Jingpu Information Technology, Co., Ltd." }, + { 1287, "Lichtmanufaktur Berlin GmbH" }, + { 1288, "Eco Parking Technologies" }, + { 1289, "Envision Digital International Pte Ltd." }, + { 1290, "Antony Developpement Electronique" }, + { 1291, "i2systems" }, + { 1292, "Thureon International Limited" }, + { 1293, "Pulsafeeder" }, + { 1294, "MegaChips Corporation" }, + { 1295, "TES Controls" }, + { 1296, "Cermate" }, + { 1297, "Grand Valley State University" }, + { 1298, "Symcon Gmbh" }, + { 1299, "The Chicago Faucet Company" }, + { 1300, "Geberit AG" }, + { 1301, "Rex Controls" }, + { 1302, "IVMS GmbH" }, + { 1303, "MNPP Saturn Ltd." }, + { 1304, "Regal Beloit" }, + { 1305, "ACS-Air Conditioning Solutions" }, + { 1306, "GBX Technology, LLC" }, + { 1307, "Kaiterra" }, + { 1308, "ThinKuan loT Technology (Shanghai) Co., Ltd" }, { 0, NULL } }; static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers); @@ -6204,6 +6373,7 @@ static int hf_bacapp_present_value_bool = -1; static int hf_bacapp_present_value_unsigned = -1; static int hf_bacapp_present_value_signed = -1; static int hf_bacapp_present_value_real = -1; +static int hf_bacapp_present_value_double = -1; static int hf_bacapp_present_value_octet_string = -1; static int hf_bacapp_present_value_char_string = -1; static int hf_bacapp_present_value_bit_string = -1; @@ -7041,7 +7211,7 @@ fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, break; case BACAPP_PRESENT_VALUE_DOUBLE: double_val = tvb_get_ntohieee_double(tvb, offset+tag_len); - tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_real, tvb, offset, lvt+tag_len, double_val); + tree_item = proto_tree_add_double(tree, hf_bacapp_present_value_double, tvb, offset, lvt+tag_len, double_val); curr_offset += tag_len + lvt; break; case BACAPP_PRESENT_VALUE_OCTET_STRING: @@ -7050,10 +7220,10 @@ fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, curr_offset += tag_len + lvt; break; case BACAPP_PRESENT_VALUE_CHARACTER_STRING: - curr_offset += fCharacterStringBase(tvb, pinfo, tree, offset, NULL, TRUE, FALSE); + curr_offset = fCharacterStringBase(tvb, pinfo, tree, offset, NULL, TRUE, FALSE); break; case BACAPP_PRESENT_VALUE_BIT_STRING: - curr_offset += fBitStringTagVSBase(tvb, pinfo, tree, offset, NULL, NULL, TRUE); + curr_offset = fBitStringTagVSBase(tvb, pinfo, tree, offset, NULL, NULL, TRUE); break; case BACAPP_PRESENT_VALUE_ENUM: if (fUnsigned32(tvb, offset+tag_len, lvt, &enum_index)) { @@ -7073,6 +7243,12 @@ fPresentValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, } curr_offset += tag_len + lvt; break; + case BACAPP_PRESENT_VALUE_DATE: + curr_offset = fDate(tvb, pinfo, tree, offset, "Date: "); + break; + case BACAPP_PRESENT_VALUE_TIME: + curr_offset = fTime(tvb, pinfo, tree, offset, "Time: "); + break; case BACAPP_PRESENT_VALUE_OBJECT_IDENTIFIER: object_id = tvb_get_ntohl(tvb, offset+tag_len); object_type = object_id_type(object_id); @@ -7504,7 +7680,7 @@ fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, c offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt); /* just add the label, with the tagHeader information in its subtree */ - subtree = proto_tree_add_subtree(tree, tvb, offset, 6, ett_bacapp_tag, NULL, label); + subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, label); if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */ proto_tree_add_item(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ENC_BIG_ENDIAN); @@ -8819,6 +8995,9 @@ fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint case 100: /* reason-for-halt */ offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetProgramError); break; + case 157: /* last-restore-time */ + offset = fTimeStamp(tvb, pinfo, tree, offset, ar); + break; case 160: /* mode */ case 175: /* accepted-modes */ offset = fApplicationTypesEnumerated(tvb, pinfo, tree, offset, ar, BACnetLifeSafetyMode); @@ -9185,6 +9364,14 @@ fAbstractSyntaxNType(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint { offset = fPresentValue(tvb, pinfo, tree, offset, BACnetShedState, 0, BACAPP_PRESENT_VALUE_ENUM); } + else if (object_type == 43) /* date-time-pattern-value */ + { + offset = fDateTime(tvb, pinfo, tree, offset, ar); + } + else if (object_type == 44) /* date-time-value */ + { + offset = fDateTime(tvb, pinfo, tree, offset, ar); + } else { if (!tag_info) { @@ -9791,16 +9978,18 @@ fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset static guint fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) { - guint lastoffset = 0; + guint8 tag_no, tag_info; + guint32 lvt; + guint lastoffset = 0; while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */ lastoffset = offset; switch (fTagNo(tvb, offset)) { - case 0: /* textMessageSourceDevice */ offset = fObjectIdentifier(tvb, pinfo, tree, offset, "DeviceIdentifier: "); break; case 1: /* messageClass */ + offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); switch (fTagNo(tvb, offset)) { case 0: /* numeric */ offset = fUnsignedTag(tvb, pinfo, tree, offset, "message Class: "); @@ -9809,6 +9998,7 @@ fConfirmedTextMessageRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree offset = fCharacterString(tvb, pinfo, tree, offset, "message Class: "); break; } + offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); break; case 2: /* messagePriority */ offset = fEnumeratedTag(tvb, pinfo, tree, offset, "message Priority: ", @@ -11368,8 +11558,20 @@ fFaultParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse if (tag_is_closing(tag_info)) { break; } - offset = fApplicationTypes(tvb, pinfo, subtree, offset, "min-normal-value: "); - offset = fApplicationTypes(tvb, pinfo, subtree, offset, "max-normal-value: "); + switch (fTagNo(tvb, offset)) { + case 0: + offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); + offset = fApplicationTypes(tvb, pinfo, subtree, offset, "min-normal-value: "); + offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); + break; + case 1: + offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); + offset = fApplicationTypes(tvb, pinfo, subtree, offset, "max-normal-value: "); + offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); + break; + default: + break; + } } break; case 7: /* fault-listed */ @@ -13246,8 +13448,8 @@ fAuditLogQueryByTargetParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree * offset = fUnsignedTag(tvb, pinfo, tree, offset, "target-priority: "); break; case 6: /* target-operation */ - offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, - "target-operation: ", BACnetAuditOperation, 64); + offset = fBitStringTagVS(tvb, pinfo, tree, offset, + "target-operation: ", BACnetAuditOperation); break; case 7: /* successful-action */ offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, @@ -13288,8 +13490,8 @@ fAuditLogQueryBySourceParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree * offset = fObjectIdentifier(tvb, pinfo, tree, offset, "ObjectIdentifier: "); break; case 3: /* source-operation */ - offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, - "source-operation: ", BACnetAuditOperation, 64); + offset = fBitStringTagVS(tvb, pinfo, tree, offset, + "source-operation: ", BACnetAuditOperation); break; case 4: /* successful-action */ offset = fEnumeratedTagSplit(tvb, pinfo, tree, offset, @@ -13395,7 +13597,7 @@ fAuditLogRecordResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset = fUnsignedTag(tvb, pinfo, tree, offset, "sequence-number: "); break; case 1: /* log-record */ - subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "log-record: "); + subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "log-record: "); offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); offset = fAuditLogRecord(tvb, pinfo, subtree, offset); offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); @@ -13442,6 +13644,42 @@ fAuditLogQueryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off } static guint +fWhoAmIRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) +{ + guint lastoffset = 0; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */ + lastoffset = offset; + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: "); + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: "); + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: "); + if (offset <= lastoffset) break; /* nothing happened, exit loop */ + } + return offset; +} + +static guint +fYouAreRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) +{ + guint lastoffset = 0; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */ + lastoffset = offset; + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Vendor ID: "); + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Model name: "); + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Serial number: "); + if(tvb_reported_length_remaining(tvb, offset) > 0) { + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device Identifier: "); + } + if(tvb_reported_length_remaining(tvb, offset) > 0) { + offset = fApplicationTypes(tvb, pinfo, tree, offset, "Device MAC address: "); + } + if (offset <= lastoffset) break; /* nothing happened, exit loop */ + } + return offset; +} + +static guint fAuthenticateRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) { guint lastoffset = 0; @@ -14088,17 +14326,16 @@ fSecurityKeySet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse static guint fSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset) { - guint lastoffset = 0, len; + guint lastoffset = 0; guint8 tag_no, tag_info; guint32 lvt; while (tvb_reported_length_remaining(tvb, offset) > 0) { /* exit loop if nothing happens inside */ lastoffset = offset; - len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt); - /* maybe a listOfSelectionCriteria if we spot a closing tag */ + fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt); + /* quit loop if we spot a closing tag */ if (tag_is_closing(tag_info)) { - offset += len; - continue; + break; } switch (fTagNo(tvb, offset)) { @@ -14857,6 +15094,12 @@ fUnconfirmedServiceRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, case 12: offset = fUnconfirmedAuditNotificationRequest(tvb, pinfo, tree, offset); break; + case 13: + offset = fWhoAmIRequest(tvb, pinfo, tree, offset); + break; + case 14: + offset = fYouAreRequest(tvb, pinfo, tree, offset); + break; default: break; } @@ -15729,6 +15972,10 @@ proto_register_bacapp(void) { "Present Value (real)", "bacapp.present_value.real", FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL } }, + { &hf_bacapp_present_value_double, + { "Present Value (double)", "bacapp.present_value.double", + FT_DOUBLE, BASE_NONE, NULL, 0, NULL, HFILL } + }, { &hf_bacapp_present_value_octet_string, { "Present Value (octet string)", "bacapp.present_value.octet_string", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } diff --git a/epan/dissectors/packet-bacapp.h b/epan/dissectors/packet-bacapp.h index cf7030d141..0c7dcfd8fd 100644 --- a/epan/dissectors/packet-bacapp.h +++ b/epan/dissectors/packet-bacapp.h @@ -38,6 +38,8 @@ typedef enum BacappPresentValueType { BACAPP_PRESENT_VALUE_CHARACTER_STRING, BACAPP_PRESENT_VALUE_BIT_STRING, BACAPP_PRESENT_VALUE_ENUM, + BACAPP_PRESENT_VALUE_DATE, + BACAPP_PRESENT_VALUE_TIME, BACAPP_PRESENT_VALUE_OBJECT_IDENTIFIER } BacappPresentValueType; diff --git a/epan/dissectors/packet-bacnet.c b/epan/dissectors/packet-bacnet.c index 6427114200..9622113ba5 100644 --- a/epan/dissectors/packet-bacnet.c +++ b/epan/dissectors/packet-bacnet.c @@ -1716,6 +1716,7 @@ proto_reg_handoff_bacnet(void) dissector_add_uint("bvlc.function_ipv6", 0x02, bacnet_handle); dissector_add_uint("bvlc.function_ipv6", 0x0c, bacnet_handle); dissector_add_uint("bvlc.function_ipv6", 0x08, bacnet_handle); + dissector_add_uint("bscvlc.function", 0x01, bacnet_handle); dissector_add_uint("llc.dsap", SAP_BACNET, bacnet_handle); bacapp_handle = find_dissector_add_dependency("bacapp", proto_bacnet); } diff --git a/epan/dissectors/packet-bvlc.c b/epan/dissectors/packet-bvlc.c index 33db6bebbe..852a45bff8 100644 --- a/epan/dissectors/packet-bvlc.c +++ b/epan/dissectors/packet-bvlc.c @@ -32,6 +32,7 @@ void proto_reg_handoff_bvlc(void); #define BAC_WRAPPER_SECURE_BY_RTR 0x01 static int proto_bvlc = -1; +static int proto_bscvlc = -1; static int hf_bvlc_type = -1; static int hf_bvlc_function = -1; static int hf_bvlc_ipv6_function = -1; @@ -53,28 +54,79 @@ static int hf_bvlc_virt_source = -1; static int hf_bvlc_virt_dest = -1; static int hf_bvlc_orig_source_addr = -1; static int hf_bvlc_orig_source_port = -1; +static int hf_bscvlc_control = -1; +static int hf_bscvlc_control_data_option = -1; +static int hf_bscvlc_control_destination_option = -1; +static int hf_bscvlc_control_destination_address = -1; +static int hf_bscvlc_control_origin_address = -1; +static int hf_bscvlc_control_reserved = -1; +static int hf_bscvlc_header = -1; +static int hf_bscvlc_header_marker = -1; +static int hf_bscvlc_header_length = -1; +static int hf_bscvlc_header_data = -1; +static int hf_bscvlc_header_opt_type = -1; +static int hf_bscvlc_header_opt_data = -1; +static int hf_bscvlc_header_opt_must_understand = -1; +static int hf_bscvlc_header_opt_more = -1; +static int hf_bscvlc_vendor_id = -1; +static int hf_bscvlc_proprietary_opt_type = -1; +static int hf_bscvlc_proprietary_data = -1; +static int hf_bscvlc_hub_conn_state = -1; +static int hf_bscvlc_accept_conns = -1; +static int hf_bscvlc_max_bvlc_length = -1; +static int hf_bscvlc_max_npdu_length = -1; +static int hf_bscvlc_function = -1; +static int hf_bscvlc_result = -1; +static int hf_bscvlc_error_class = -1; +static int hf_bscvlc_error_code = -1; +static int hf_bscvlc_result_data = -1; +static int hf_bscvlc_uris = -1; +static int hf_bscvlc_msg_id = -1; +static int hf_bscvlc_orig_vmac = -1; +static int hf_bscvlc_dest_vmac = -1; +static int hf_bscvlc_connect_vmac = -1; +static int hf_bscvlc_connect_uuid = -1; static dissector_table_t bvlc_dissector_table; +static dissector_table_t bscvlc_dissector_table; static dissector_table_t bvlc_ipv6_dissector_table; static dissector_handle_t bvlc_handle = NULL; +static dissector_handle_t bscvlc_handle = NULL; static const value_string bvlc_function_names[] = { - { 0x00, "BVLC-Result", }, - { 0x01, "Write-Broadcast-Distribution-Table", }, - { 0x02, "Read-Broadcast-Distribution-Table", }, - { 0x03, "Read-Broadcast-Distribution-Table-Ack", }, - { 0x04, "Forwarded-NPDU", }, - { 0x05, "Register-Foreign-Device", }, - { 0x06, "Read-Foreign-Device-Table", }, - { 0x07, "Read-Foreign-Device-Table-Ack", }, - { 0x08, "Delete-Foreign-Device-Table-Entry", }, - { 0x09, "Distribute-Broadcast-To-Network", }, - { 0x0a, "Original-Unicast-NPDU", }, + { 0x00, "BVLC-Result" }, + { 0x01, "Write-Broadcast-Distribution-Table" }, + { 0x02, "Read-Broadcast-Distribution-Table" }, + { 0x03, "Read-Broadcast-Distribution-Table-Ack" }, + { 0x04, "Forwarded-NPDU" }, + { 0x05, "Register-Foreign-Device" }, + { 0x06, "Read-Foreign-Device-Table" }, + { 0x07, "Read-Foreign-Device-Table-Ack" }, + { 0x08, "Delete-Foreign-Device-Table-Entry" }, + { 0x09, "Distribute-Broadcast-To-Network" }, + { 0x0a, "Original-Unicast-NPDU" }, { 0x0b, "Original-Broadcast-NPDU" }, { 0x0c, "Secured-BVLL" }, { 0, NULL } }; +static const value_string bscvlc_function_names[] = { + { 0x00, "BVLC-Result" }, + { 0x01, "Encapsulated-NPDU" }, + { 0x02, "Address-Resolution" }, + { 0x03, "Address-Resolution-ACK" }, + { 0x04, "Advertisement" }, + { 0x05, "Advertisement-Solicitation" }, + { 0x06, "Connect-Request" }, + { 0x07, "Connect-Accept" }, + { 0x08, "Disconnect-Request" }, + { 0x09, "Disconnect-ACK" }, + { 0x0A, "Heartbeat-Request" }, + { 0x0B, "Heartbeat-ACK" }, + { 0x0C, "Proprietary-Message" }, + { 0, NULL } +}; + static const value_string bvlc_result_names[] = { { 0x00, "Successful completion" }, { 0x10, "Write-Broadcast-Distribution-Table NAK" }, @@ -86,6 +138,12 @@ static const value_string bvlc_result_names[] = { { 0, NULL } }; +static const value_string bscvlc_result_names[] = { + { 0x00, "Successful completion (ACK)" }, + { 0x01, "Completion failed (NAK)" }, + { 0, NULL } +}; + static const value_string bvlc_ipv6_function_names[] = { { 0x00, "BVLC-Result", }, { 0x01, "Original-Unicast-NPDU", }, @@ -113,7 +171,29 @@ static const value_string bvlc_ipv6_result_names[] = { { 0, NULL } }; +static const value_string bscvlc_header_type_names[] = { + { 0x01, "Secure Path" }, + { 0x1F, "Proprietary Header Option" }, + { 0, NULL } +}; + +static const value_string bscvlc_hub_conn_state_names[] = { + { 0x00, "No hub connection" }, + { 0x01, "Connected to primary hub" }, + { 0x02, "Connected to failover hub" }, + { 0, NULL } +}; + +static const value_string bscvlc_hub_accept_conns_names[] = { + { 0x00, "The node does not support accepting direct connections" }, + { 0x01, "The node supports accepting direct connections" }, + { 0, NULL } +}; + static gint ett_bvlc = -1; +static gint ett_bscvlc = -1; +static gint ett_bscvlc_ctrl = -1; +static gint ett_bscvlc_hdr = -1; static gint ett_bdt = -1; static gint ett_fdt = -1; @@ -126,6 +206,245 @@ static const value_string bvlc_types[] = { { 0, NULL } }; +#define BSCVLC_CONTROL_DATA_OPTION 0x01 +#define BSCVLC_CONTROL_DEST_OPTION 0x02 +#define BSCVLC_CONTROL_DEST_ADDRESS 0x04 +#define BSCVLC_CONTROL_ORIG_ADDRESS 0x08 +#define BSCVLC_CONTROL_RESERVED 0xF0 + +static const true_false_string control_data_option_set_high = { + "Data Options field is present.", + "Data Options field is absent." +}; + +static const true_false_string control_destination_option_set_high = { + "Destination Options field is present.", + "Destination Options field is absent." +}; + +static const true_false_string control_destination_address_set_high = { + "Destination Virtual Address is present.", + "Destination Virtual Address is absent." +}; + +static const true_false_string control_orig_address_set_high = { + "Originating Virtual Address is present.", + "Originating Virtual Address is absent." +}; + +static const true_false_string control_reserved_set_high = { + "Shall be zero, but is not.", + "Shall be zero and is zero." +}; + +#define BSCVLC_HEADER_OPTION_TYPE 0x1F +#define BSCVLC_HEADER_OPTION_DATA 0x20 +#define BSCVLC_HEADER_OPTION_MUST_UNDERSTAND 0x40 +#define BSCVLC_HEADER_OPTION_MORE_OPTIONS 0x80 + +#define BSCVLC_HEADER_TYPE_SECURE_PATH 0x01 +#define BSCVLC_HEADER_TYPE_PROPRIETARY 0x1F + + +static const true_false_string header_opt_data_set_high = { + "The 'Header Length' and 'Header Data' fields are present.", + "The 'Header Length' and 'Header Data' fields are absent." +}; + +static const true_false_string header_opt_must_understand_set_high = { + "This header option must be understood for consuming the message.", + "This header option can be ignored if not understood." +}; + +static const true_false_string header_opt_more_set_high = { + "Another header option follows in the current header option list.", + "This is the last header option in the current header option list." +}; + +static const value_string +BACnetErrorClass [] = { + { 0, "device" }, + { 1, "object" }, + { 2, "property" }, + { 3, "resources" }, + { 4, "security" }, + { 5, "services" }, + { 6, "vt" }, + { 7, "communication" }, + { 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. */ +}; + +static const value_string +BACnetErrorCode[] = { + { 0, "other"}, + { 1, "authentication-failed"}, + { 2, "configuration-in-progress"}, + { 3, "device-busy"}, + { 4, "dynamic-creation-not-supported"}, + { 5, "file-access-denied"}, + { 6, "incompatible-security-levels"}, + { 7, "inconsistent-parameters"}, + { 8, "inconsistent-selection-criterion"}, + { 9, "invalid-data-type"}, + { 10, "invalid-file-access-method"}, + { 11, "invalid-file-start-position"}, + { 12, "invalid-operator-name"}, + { 13, "invalid-parameter-data-type"}, + { 14, "invalid-time-stamp"}, + { 15, "key-generation-error"}, + { 16, "missing-required-parameter"}, + { 17, "no-objects-of-specified-type"}, + { 18, "no-space-for-object"}, + { 19, "no-space-to-add-list-element"}, + { 20, "no-space-to-write-property"}, + { 21, "no-vt-sessions-available"}, + { 22, "property-is-not-a-list"}, + { 23, "object-deletion-not-permitted"}, + { 24, "object-identifier-already-exists"}, + { 25, "operational-problem"}, + { 26, "password-failure"}, + { 27, "read-access-denied"}, + { 28, "security-not-supported"}, + { 29, "service-request-denied"}, + { 30, "timeout"}, + { 31, "unknown-object"}, + { 32, "unknown-property"}, + { 33, "removed enumeration"}, + { 34, "unknown-vt-class"}, + { 35, "unknown-vt-session"}, + { 36, "unsupported-object-type"}, + { 37, "value-out-of-range"}, + { 38, "vt-session-already-closed"}, + { 39, "vt-session-termination-failure"}, + { 40, "write-access-denied"}, + { 41, "character-set-not-supported"}, + { 42, "invalid-array-index"}, + { 43, "cov-subscription-failed"}, + { 44, "not-cov-property"}, + { 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"}, + { 51, "abort - buffer - overflow" }, + { 52, "abort - invalid - apdu - in - this - state" }, + { 53, "abort - preempted - by - higher - priority - task" }, + { 54, "abort - segmentation - not - supported" }, + { 55, "abort - proprietary" }, + { 56, "abort - other" }, + { 57, "reject - invalid - tag" }, + { 58, "reject - network - down" }, + { 59, "reject - buffer - overflow" }, + { 60, "reject - inconsistent - parameters" }, + { 61, "reject - invalid - parameter - data - type" }, + { 62, "reject - invalid - tag" }, + { 63, "reject - missing - required - parameter" }, + { 64, "reject - parameter - out - of - range" }, + { 65, "reject - too - many - arguments" }, + { 66, "reject - undefined - enumeration" }, + { 67, "reject - unrecognized - service" }, + { 68, "reject - proprietary" }, + { 69, "reject - other" }, + { 70, "unknown - device" }, + { 71, "unknown - route" }, + { 72, "value - not - initialized" }, + { 73, "invalid-event-state"}, + { 74, "no-alarm-configured"}, + { 75, "log-buffer-full"}, + { 76, "logged-value-purged"}, + { 77, "no-property-specified"}, + { 78, "not-configured-for-triggered-logging"}, + { 79, "unknown-subscription"}, + { 80, "parameter-out-of-range"}, + { 81, "list-element-not-found"}, + { 82, "busy"}, + { 83, "communication-disabled"}, + { 84, "success"}, + { 85, "access-denied"}, + { 86, "bad-destination-address"}, + { 87, "bad-destination-device-id"}, + { 88, "bad-signature"}, + { 89, "bad-source-address"}, + { 90, "bad-timestamp"}, + { 91, "cannot-use-key"}, + { 92, "cannot-verify-message-id"}, + { 93, "correct-key-revision"}, + { 94, "destination-device-id-required"}, + { 95, "duplicate-message"}, + { 96, "encryption-not-configured"}, + { 97, "encryption-required"}, + { 98, "incorrect-key"}, + { 99, "invalid-key-data"}, + { 100, "key-update-in-progress"}, + { 101, "malformed-message"}, + { 102, "not-key-server"}, + { 103, "security-not-configured"}, + { 104, "source-security-required"}, + { 105, "too-many-keys"}, + { 106, "unknown-authentication-type"}, + { 107, "unknown-key"}, + { 108, "unknown-key-revision"}, + { 109, "unknown-source-message"}, + { 110, "not-router-to-dnet"}, + { 111, "router-busy"}, + { 112, "unknown-network-message"}, + { 113, "message-too-long"}, + { 114, "security-error"}, + { 115, "addressing-error"}, + { 116, "write-bdt-failed"}, + { 117, "read-bdt-failed"}, + { 118, "register-foreign-device-failed"}, + { 119, "read-fdt-failed"}, + { 120, "delete-fdt-entry-failed"}, + { 121, "distribute-broadcast-failed"}, + { 122, "unknown-file-size"}, + { 123, "abort-apdu-too-long"}, + { 124, "abort-application-exceeded-reply-time"}, + { 125, "abort-out-of-resources"}, + { 126, "abort-tsm-timeout"}, + { 127, "abort-window-size-out-of-range"}, + { 128, "file-full"}, + { 129, "inconsistent-configuration"}, + { 130, "inconsistent-object-type"}, + { 131, "internal-error"}, + { 132, "not-configured"}, + { 133, "out-of-memory"}, + { 134, "value-too-long"}, + { 135, "abort-insufficient-security"}, + { 136, "abort-security-error"}, + { 137, "duplicate-entry"}, + { 138, "invalid-value-in-this-state"}, + { 139, "invalid-operation-in-this-state"}, + { 140, "list-item-not-numbered"}, + { 141, "list-item-not-timestamped"}, + { 142, "invalid-data-encoding"}, + { 0, NULL} +/* 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. */ +}; + +static int * const bscvlc_control_flags[] = { + &hf_bscvlc_control_data_option, + &hf_bscvlc_control_destination_option, + &hf_bscvlc_control_destination_address, + &hf_bscvlc_control_origin_address, + &hf_bscvlc_control_reserved, + NULL +}; + +static int * const bscvlc_header_flags[] = { + &hf_bscvlc_header_opt_type, + &hf_bscvlc_header_opt_data, + &hf_bscvlc_header_opt_must_understand, + &hf_bscvlc_header_opt_more, + NULL +}; + static int dissect_ipv4_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { @@ -175,6 +494,10 @@ dissect_ipv4_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat return 0; /* reject */ } + /* Put the BVLC Type in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " BVLC Function %s ", + val_to_str_const(bvlc_function, bvlc_function_names, "unknown")); + ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0, bvlc_length, ENC_NA); bvlc_tree = proto_item_add_subtree(ti, ett_bvlc); proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1, @@ -381,6 +704,10 @@ dissect_ipv6_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat return 0; /* reject */ } + /* Put the BVLC Type in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " BVLC Function %s ", + val_to_str_const(bvlc_function, bvlc_function_names, "unknown")); + ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0, bvlc_length, ENC_NA); bvlc_tree = proto_item_add_subtree(ti, ett_bvlc); @@ -428,7 +755,6 @@ dissect_ipv6_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat offset += 3; break; case 0x04: /* Forwarded-Address-Resolution */ - case 0x08: /* Forwarded-NPDU */ proto_tree_add_item(bvlc_tree, hf_bvlc_virt_dest, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3; @@ -439,6 +765,14 @@ dissect_ipv6_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; break; + case 0x08: /* Forwarded-NPDU */ + proto_tree_add_item(bvlc_tree, hf_bvlc_orig_source_addr, + tvb, offset, 16, ENC_NA); + offset += 16; + proto_tree_add_item(bvlc_tree, hf_bvlc_orig_source_port, + tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + break; case 0x06: /* Virtual-Address-Resolution */ break; case 0x09: /* Register-Foreign-Device */ @@ -516,6 +850,362 @@ dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ return ret; } +static int +dissect_bscvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + proto_item *ti; + proto_tree *bvlc_tree; + tvbuff_t *next_tvb; + gint offset; + gint start; + gint bvlc_length; + gint packet_length; + gint npdu_length; + guint8 bvlc_function; + guint8 bvlc_control; + guint8 bvlc_result; + guint8 hdr_byte; + gint8 mac_buffer[16]; + guint bvlc_message_id; + guint idx; + gboolean bMoreFlag; + gboolean bDataFlag; + proto_tree *subtree; + + /* Calculate length of BSCVLC block to get remaining payload length */ + offset = 0; + + packet_length = tvb_reported_length_remaining(tvb, offset); + if(packet_length < 4) + return 0; /* reject */ + + /* Fix part of the header first */ + bvlc_function = tvb_get_guint8(tvb, offset++); + bvlc_control = tvb_get_guint8(tvb, offset++); + bvlc_message_id = tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN); + offset += 2; + + /* Variable part of the header next */ + bvlc_length = offset; + + if ((bvlc_control & BSCVLC_CONTROL_ORIG_ADDRESS) != 0) + bvlc_length += 6; + + if ((bvlc_control & BSCVLC_CONTROL_DEST_ADDRESS) != 0) + bvlc_length += 6; + + if ((bvlc_control & BSCVLC_CONTROL_DEST_OPTION) != 0) + { + bMoreFlag = TRUE; + + while(tvb_reported_length_remaining(tvb, bvlc_length) > 0 && + (hdr_byte = tvb_get_guint8(tvb, bvlc_length)) != 0 && bMoreFlag) + { + /* get flags and type... */ + bMoreFlag= (hdr_byte & BSCVLC_HEADER_OPTION_MORE_OPTIONS); + bDataFlag= (hdr_byte & BSCVLC_HEADER_OPTION_DATA); + bvlc_length++; + + if(bDataFlag) + { + npdu_length = (gint)(tvb_get_guint8(tvb, bvlc_length++) << 8); + npdu_length += (gint)tvb_get_guint8(tvb, bvlc_length++); + bvlc_length += npdu_length; + } + } + } + + if ((bvlc_control & BSCVLC_CONTROL_DATA_OPTION) != 0) + { + bMoreFlag = TRUE; + + while(tvb_reported_length_remaining(tvb, bvlc_length) > 0 && + (hdr_byte = tvb_get_guint8(tvb, bvlc_length)) != 0 && bMoreFlag) + { + /* get flags and type... */ + bMoreFlag= (hdr_byte & BSCVLC_HEADER_OPTION_MORE_OPTIONS); + bDataFlag= (hdr_byte & BSCVLC_HEADER_OPTION_DATA); + bvlc_length++; + + if(bDataFlag) + { + npdu_length = (gint)(tvb_get_guint8(tvb, bvlc_length++) << 8); + npdu_length += (gint)tvb_get_guint8(tvb, bvlc_length++); + bvlc_length += npdu_length; + } + } + } + + /* Now add the BSCVLC payload size for specified function */ + switch (bvlc_function) + { + case 0x00: /* BVLC-Result */ + case 0x03: /* Address-Resolution-ACK */ + case 0x0C: /* Proprietary-Message */ + /* complete packet length because of optional present variable length error data + but no length encoded for it in the structure of this frame */ + bvlc_length = packet_length; + break; + case 0x02: /* Address-Resolution */ + case 0x05: /* Advertisement-Solicitation */ + case 0x08: /* Disconnect-Request */ + case 0x09: /* Disconnect-ACK */ + case 0x0A: /* Heartbeat-Request */ + case 0x0B: /* Heartbeat-ACK */ + /* No additional payload here */ + break; + case 0x04: /* Advertisement */ + bvlc_length += 6; + break; + case 0x06: /* Connect-Request */ + case 0x07: /* Connect-Accept */ + bvlc_length += 26; + break; + case 0x01: /* Encapsulated-NPDU */ + default: + /* The additional payload will be decoded elsewhere */ + break; + } + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSCVLC"); + col_set_str(pinfo->cinfo, COL_INFO, "BACnet Secure Conect Virtual Link Control"); + + /* Put the BSCVLC Type and Message ID in the info column */ + col_append_fstr(pinfo->cinfo, COL_INFO, " BSCVLC Function %s Message-ID %u", + val_to_str_const(bvlc_function, bscvlc_function_names, "unknown"), bvlc_message_id); + + /* Fill the tree... */ + offset = 0; + ti = proto_tree_add_item(tree, proto_bscvlc, tvb, 0, bvlc_length, ENC_NA); + bvlc_tree = proto_item_add_subtree(ti, ett_bvlc); + + proto_tree_add_uint(bvlc_tree, hf_bscvlc_function, tvb, + offset, 1, bvlc_function); + offset++; + proto_tree_add_bitmask(bvlc_tree, tvb, offset, hf_bscvlc_control, + ett_bscvlc_ctrl, bscvlc_control_flags, ENC_NA); + offset ++; + proto_tree_add_uint(bvlc_tree, hf_bscvlc_msg_id, tvb, + offset, 2, bvlc_message_id); + offset += 2; + + if ((bvlc_control & BSCVLC_CONTROL_ORIG_ADDRESS) != 0) + { + for(idx = 0; idx < 6; idx++) + g_snprintf(&mac_buffer[idx * 2], sizeof(mac_buffer) - (idx * 2), "%02X", tvb_get_guint8(tvb, offset + idx)); + col_append_fstr(pinfo->cinfo, COL_INFO, " SMAC %s", mac_buffer); + + proto_tree_add_item(bvlc_tree, hf_bscvlc_orig_vmac, tvb, offset, 6, ENC_NA); + offset += 6; + } + + if ((bvlc_control & BSCVLC_CONTROL_DEST_ADDRESS) != 0) + { + for(idx = 0; idx < 6; idx++) + g_snprintf(&mac_buffer[idx * 2], sizeof(mac_buffer) - (idx * 2), "%02X", tvb_get_guint8(tvb, offset + idx)); + col_append_fstr(pinfo->cinfo, COL_INFO, " DMAC %s", mac_buffer); + + proto_tree_add_item(bvlc_tree, hf_bscvlc_dest_vmac, tvb, offset, 6, ENC_NA); + offset += 6; + } + + if ((bvlc_control & BSCVLC_CONTROL_DEST_OPTION) != 0) + { + bMoreFlag = TRUE; + + while(tvb_reported_length_remaining(tvb, offset) > 0 && + (hdr_byte = tvb_get_guint8(tvb, offset)) != 0 && bMoreFlag) + { + /* get flags and type... */ + bMoreFlag= (hdr_byte & BSCVLC_HEADER_OPTION_MORE_OPTIONS); + bDataFlag= (hdr_byte & BSCVLC_HEADER_OPTION_DATA); + start = offset; + + offset++; + + if(bDataFlag) + { + npdu_length = (gint)(tvb_get_guint8(tvb, offset++) << 8); + npdu_length += (gint)tvb_get_guint8(tvb, offset++); + offset += npdu_length; + } + + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, start, offset - start, + ett_bscvlc_hdr, NULL, "%s", "Destination Options"); + proto_tree_add_bitmask_value(subtree, tvb, start, hf_bscvlc_header, + ett_bscvlc_hdr, bscvlc_header_flags, hdr_byte); + + if(bDataFlag) + { + proto_tree_add_item(subtree, hf_bscvlc_header_length, tvb, start + 1, 2, ENC_NA); + proto_tree_add_item(subtree, hf_bscvlc_header_data, tvb, start + 3, npdu_length, ENC_NA); + } + } + } + + if ((bvlc_control & BSCVLC_CONTROL_DATA_OPTION) != 0) + { + bMoreFlag = TRUE; + + while(tvb_reported_length_remaining(tvb, offset) > 0 && + (hdr_byte = tvb_get_guint8(tvb, offset)) != 0 && bMoreFlag) + { + /* get flags and type... */ + bMoreFlag= (hdr_byte & BSCVLC_HEADER_OPTION_MORE_OPTIONS); + bDataFlag= (hdr_byte & BSCVLC_HEADER_OPTION_DATA); + start = offset; + + offset++; + + if(bDataFlag) + { + npdu_length = (gint)(tvb_get_guint8(tvb, offset++) << 8); + npdu_length += (gint)tvb_get_guint8(tvb, offset++); + offset += npdu_length; + } + + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, start, offset - start, + ett_bscvlc_hdr, NULL, "%s", "Data Options"); + proto_tree_add_bitmask_value(subtree, tvb, start, hf_bscvlc_header, + ett_bscvlc_hdr, bscvlc_header_flags, hdr_byte); + + if(bDataFlag) + { + proto_tree_add_item(subtree, hf_bscvlc_header_length, tvb, start + 1, 2, ENC_NA); + proto_tree_add_item(subtree, hf_bscvlc_header_data, tvb, start + 3, npdu_length, ENC_NA); + } + } + } + + switch (bvlc_function) + { + case 0x02: /* Address-Resolution */ + case 0x05: /* Advertisement-Solicitation */ + case 0x08: /* Disconnect-Request */ + case 0x09: /* Disconnect-ACK */ + case 0x0A: /* Heartbeat-Request */ + case 0x0B: /* Heartbeat-ACK */ + break; + case 0x00: /* BVLC-Result */ + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset, + ett_bscvlc_hdr, NULL, "%s", "BVLC-Result"); + proto_tree_add_item(subtree, hf_bscvlc_function, tvb, + offset, 1, ENC_NA); + offset++; + proto_tree_add_item(subtree, hf_bscvlc_result, tvb, + offset, 1, ENC_NA); + bvlc_result = tvb_get_guint8(tvb, offset); + offset++; + + col_append_fstr(pinfo->cinfo, COL_INFO, " %s", + val_to_str_const(bvlc_result, bscvlc_result_names, "unknown")); + + if(bvlc_result) + { + proto_tree_add_item(subtree, hf_bscvlc_header_marker, tvb, + offset, 1, ENC_NA); + offset++; + proto_tree_add_item(subtree, hf_bscvlc_error_class, tvb, + offset, 2, ENC_NA); + offset += 2; + proto_tree_add_item(subtree, hf_bscvlc_error_code, tvb, + offset, 2, ENC_NA); + offset += 2; + proto_tree_add_item(subtree, hf_bscvlc_result_data, tvb, + offset, packet_length - offset, ENC_NA); + } + /* Force and of packet */ + offset = packet_length; + break; + case 0x03: /* Address-Resolution-ACK */ + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset, + ett_bscvlc_hdr, NULL, "%s", "Address-Resolution-ACK"); + proto_tree_add_item(subtree, hf_bscvlc_uris, tvb, + offset, packet_length - offset, ENC_NA); + /* Force and of packet */ + offset = packet_length; + break; + case 0x04: /* Advertisement */ + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset, + ett_bscvlc_hdr, NULL, "%s", "Advertisement"); + proto_tree_add_item(subtree, hf_bscvlc_hub_conn_state, tvb, + offset, 1, ENC_NA); + offset++; + proto_tree_add_item(subtree, hf_bscvlc_accept_conns, tvb, + offset, 1, ENC_NA); + offset++; + proto_tree_add_item(subtree, hf_bscvlc_max_bvlc_length, tvb, + offset, 2, ENC_NA); + offset += 2; + proto_tree_add_item(subtree, hf_bscvlc_max_npdu_length, tvb, + offset, 2, ENC_NA); + offset += 2; + break; + case 0x06: /* Connect-Request */ + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset, + ett_bscvlc_hdr, NULL, "%s", "Connect-Request"); + proto_tree_add_item(subtree, hf_bscvlc_connect_vmac, tvb, + offset, 6, ENC_NA); + offset += 6; + proto_tree_add_item(subtree, hf_bscvlc_connect_uuid, tvb, + offset, 16, ENC_NA); + offset += 16; + proto_tree_add_item(subtree, hf_bscvlc_max_bvlc_length, tvb, + offset, 2, ENC_NA); + offset += 2; + proto_tree_add_item(subtree, hf_bscvlc_max_npdu_length, tvb, + offset, 2, ENC_NA); + offset += 2; + break; + case 0x07: /* Connect-Accept */ + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset, + ett_bscvlc_hdr, NULL, "%s", "Connect-Accept"); + proto_tree_add_item(subtree, hf_bscvlc_connect_vmac, tvb, + offset, 6, ENC_NA); + offset += 6; + proto_tree_add_item(subtree, hf_bscvlc_connect_uuid, tvb, + offset, 16, ENC_NA); + offset += 16; + proto_tree_add_item(subtree, hf_bscvlc_max_bvlc_length, tvb, + offset, 2, ENC_NA); + offset += 2; + proto_tree_add_item(subtree, hf_bscvlc_max_npdu_length, tvb, + offset, 2, ENC_NA); + offset += 2; + break; + case 0x0C: /* Proprietary-Message */ + subtree = proto_tree_add_subtree_format(bvlc_tree, tvb, offset, packet_length - offset, + ett_bscvlc_hdr, NULL, "%s", "Proprietary-Message"); + proto_tree_add_item(subtree, hf_bscvlc_vendor_id, tvb, + offset, 2, ENC_NA); + offset += 2; + proto_tree_add_item(subtree, hf_bscvlc_proprietary_opt_type, tvb, + offset, 1, ENC_NA); + offset++; + proto_tree_add_item(subtree, hf_bscvlc_proprietary_data, tvb, + offset, packet_length - offset, ENC_NA); + /* Force and of packet */ + offset = packet_length; + break; + case 0x01: /* Encapsulated-NPDU */ + default: + /* Here we assume additional payload belongs to upper layers and will be decoded later */ + break; + } + + /* Let the remaining frame to be decoded elsewhere */ + npdu_length = packet_length - offset; + next_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, npdu_length); + /* Code from Guy Harris */ + if (!dissector_try_uint(bscvlc_dissector_table, + bvlc_function, next_tvb, pinfo, tree)) { + /* Unknown function - dissect the paylod as data */ + call_data_dissector(next_tvb, pinfo, tree); + } + + return tvb_reported_length(tvb); +} + void proto_register_bvlc(void) { @@ -633,6 +1323,172 @@ proto_register_bvlc(void) &ett_fdt, }; + static hf_register_info bsc_hf[] = { + { &hf_bscvlc_control, + { "Control", "bscvlc.control", + FT_UINT8, BASE_HEX, NULL, 0, + "BSCVLC Control", HFILL } + }, + { &hf_bscvlc_control_data_option, + { "Data Option", "bscvlc.control_data_option", + FT_BOOLEAN, 8, TFS(&control_data_option_set_high), + BSCVLC_CONTROL_DATA_OPTION, "BSCVLC Control", HFILL } + }, + { &hf_bscvlc_control_destination_option, + { "Destination Option", "bscvlc.control_dest_option", + FT_BOOLEAN, 8, TFS(&control_destination_option_set_high), + BSCVLC_CONTROL_DEST_OPTION, "BSCVLC Control", HFILL } + }, + { &hf_bscvlc_control_destination_address, + { "Destination Address","bscvlc.control_dest_address", + FT_BOOLEAN, 8, TFS(&control_destination_address_set_high), + BSCVLC_CONTROL_DEST_ADDRESS, "BSCVLC Control", HFILL } + }, + { &hf_bscvlc_control_origin_address, + { "Origin Address", "bscvlc.control_orig_address", + FT_BOOLEAN, 8, TFS(&control_orig_address_set_high), + BSCVLC_CONTROL_ORIG_ADDRESS, "BSCVLC Control", HFILL } + }, + { &hf_bscvlc_control_reserved, + { "Reserved", "bscvlc.control_reserved", + FT_BOOLEAN, 8, TFS(&control_reserved_set_high), + BSCVLC_CONTROL_RESERVED, "BSCVLC Control", HFILL } + }, + { &hf_bscvlc_header, + { "Header Data Length", "bscvlc.header", + FT_UINT8, BASE_HEX, NULL, 0, + "BSCVLC Header Control Data", HFILL } + }, + { &hf_bscvlc_header_marker, + { "Header Error Marker","bscvlc.header_error_marker", + FT_UINT8, BASE_HEX, NULL, 0, + "BSCVLC Header Error Marker", HFILL } + }, + { &hf_bscvlc_header_length, + { "Header Data Length", "bscvlc.header_length", + FT_UINT16, BASE_DEC, NULL, 0, + "BSCVLC Header Data Length", HFILL } + }, + { &hf_bscvlc_header_data, + { "Header Data", "bscvlc.header_data", + FT_BYTES, BASE_NONE, NULL, 0, + "BSCVLC Header Option", HFILL } + }, + { &hf_bscvlc_header_opt_type, + { "Header Type", "bscvlc.header_type", + FT_UINT8, BASE_HEX, VALS(bscvlc_header_type_names), + BSCVLC_HEADER_OPTION_TYPE, "BSCVLC Header Option", HFILL } + }, + { &hf_bscvlc_header_opt_data, + { "Header Data", "bscvlc.header_data_present", + FT_BOOLEAN, 8, TFS(&header_opt_data_set_high), + BSCVLC_HEADER_OPTION_DATA, "BSCVLC Header Option", HFILL } + }, + { &hf_bscvlc_header_opt_must_understand, + { "Header Must Understand","bscvlc.header_understand", + FT_BOOLEAN, 8, TFS(&header_opt_must_understand_set_high), + BSCVLC_HEADER_OPTION_MUST_UNDERSTAND, "BSCVLC Header Option", HFILL } + }, + { &hf_bscvlc_header_opt_more, + { "Header More", "bscvlc.header_more", + FT_BOOLEAN, 8, TFS(&header_opt_more_set_high), + BSCVLC_HEADER_OPTION_MORE_OPTIONS, "BSCVLC Header Option", HFILL } + }, + { &hf_bscvlc_vendor_id, + { "Vendor ID", "bscvlc.vendor_id", + FT_UINT16, BASE_HEX, NULL, 0, + "BSCVLC Vendor ID", HFILL } + }, + { &hf_bscvlc_proprietary_opt_type, + { "Proprietary Type", "bscvlc.proprietary_type", + FT_UINT8, BASE_HEX, NULL, 0, + "BSCVLC Proprietary Type", HFILL } + }, + { &hf_bscvlc_proprietary_data, + { "Proprietary Data", "bscvlc.proprietary_data", + FT_BYTES, BASE_NONE, NULL, 0, + "BSCVLC Proprietary Data", HFILL } + }, + { &hf_bscvlc_hub_conn_state, + { "Hub Connection Status","bscvlc.hub_conn_state", + FT_UINT8, BASE_HEX, VALS(bscvlc_hub_conn_state_names), 0, + "BSCVLC Hub Connection Status", HFILL } + }, + { &hf_bscvlc_accept_conns, + { "Hub Accepts Connections","bscvlc.accept_conns", + FT_UINT8, BASE_HEX, VALS(bscvlc_hub_accept_conns_names), 0, + "BSCVLC Accepts Connections", HFILL } + }, + { &hf_bscvlc_max_bvlc_length, + { "Max. BVLC Length", "bscvlc.max_bvlc_length", + FT_UINT16, BASE_DEC, NULL, 0, + "Max Supported BVLC Length", HFILL } + }, + { &hf_bscvlc_max_npdu_length, + { "Max. NPDU Length", "bscvlc.max_npdu_length", + FT_UINT16, BASE_DEC, NULL, 0, + "Max Supported NPDU Length", HFILL } + }, + { &hf_bscvlc_function, + { "Function", "bscvlc.function", + FT_UINT8, BASE_HEX, VALS(bscvlc_function_names), 0, + "BSCVLC Function", HFILL } + }, + { &hf_bscvlc_result, + { "Result", "bscvlc.result", + FT_UINT8, BASE_HEX, VALS(bscvlc_result_names), 0, + "Result Code", HFILL } + }, + { &hf_bscvlc_error_class, + { "Error Class", "bscvlc.error_class", + FT_UINT32, BASE_DEC, VALS(BACnetErrorClass), 0, NULL, HFILL } + }, + { &hf_bscvlc_error_code, + { "Error Code", "bscvlc.error_code", + FT_UINT32, BASE_DEC, VALS(BACnetErrorCode), 0, NULL, HFILL } + }, + { &hf_bscvlc_result_data, + { "Result Data", "bscvlc.result_data", + FT_BYTES, BASE_NONE, NULL, 0, + "BSCVLC Result Data", HFILL } + }, + { &hf_bscvlc_uris, + { "URI's", "bscvlc.uris", + FT_BYTES, BASE_NONE, NULL, 0, + "BSCVLC Address URI's", HFILL } + }, + { &hf_bscvlc_msg_id, + { "Message ID", "bscvlc.msgid", + FT_UINT16, BASE_DEC, NULL, 0, + "BSCVLC Message ID", HFILL } + }, + { &hf_bscvlc_orig_vmac, + { "SVMAC", "bscvlc.orig_virtual_address", + FT_BYTES, BASE_NONE, NULL, 0, + "ORIG VMAC", HFILL } + }, + { &hf_bscvlc_dest_vmac, + { "DVMAC", "bscvlc.dest_virtual_address", + FT_BYTES, BASE_NONE, NULL, 0, + "DEST VMAC", HFILL } + }, + { &hf_bscvlc_connect_vmac, + { "Connecting VMAC", "bscvlc.connect_virtual_address", + FT_BYTES, BASE_NONE, NULL, 0, + "BSCVLC Connecting VMAC", HFILL } + }, + { &hf_bscvlc_connect_uuid, + { "Connecting UUID", "bscvlc.connect_uuid", + FT_BYTES, BASE_NONE, NULL, 0, + "BSCVLC Connecting UUID", HFILL } + }, + }; + + static gint *bsc_ett[] = { + &ett_bscvlc, + &ett_bscvlc_ctrl, + &ett_bscvlc_hdr + }; proto_bvlc = proto_register_protocol("BACnet Virtual Link Control", "BVLC", "bvlc"); @@ -643,12 +1499,23 @@ proto_register_bvlc(void) bvlc_dissector_table = register_dissector_table("bvlc.function", "BVLC Function", proto_bvlc, FT_UINT8, BASE_HEX); bvlc_ipv6_dissector_table = register_dissector_table("bvlc.function_ipv6", "BVLC Function IPV6", proto_bvlc, FT_UINT8, BASE_HEX); + + proto_bscvlc = proto_register_protocol("BACnet Secure Connect Virtual Link Control", "BSCVLC", "bscvlc"); + + proto_register_field_array(proto_bscvlc, bsc_hf, array_length(bsc_hf)); + proto_register_subtree_array(bsc_ett, array_length(bsc_ett)); + + bscvlc_handle = register_dissector("bscvlc", dissect_bscvlc, proto_bscvlc); + + bscvlc_dissector_table = register_dissector_table("bscvlc.function", "BSCVLC Function", proto_bscvlc, FT_UINT8, BASE_HEX); } void proto_reg_handoff_bvlc(void) { dissector_add_uint_with_preference("udp.port", BVLC_UDP_PORT, bvlc_handle); + dissector_add_string("ws.protocol", "hub.bsc.bacnet.org", bscvlc_handle); + dissector_add_string("ws.protocol", "dc.bsc.bacnet.org", bscvlc_handle); } /* diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c index 94a3977b6c..2de6afe3ca 100644 --- a/epan/dissectors/packet-http.c +++ b/epan/dissectors/packet-http.c @@ -3783,6 +3783,44 @@ dissect_http_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data return tvb_captured_length(tvb); } +static gboolean +dissect_http_heur_tls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + gint offset = 0, next_offset, linelen; + conversation_t *conversation; + http_conv_t *conv_data; + + conversation = find_or_create_conversation(pinfo); + conv_data = (http_conv_t *)conversation_get_proto_data(conversation, proto_http); + /* A http conversation was previously started, assume it is still active */ + if (conv_data) { + dissect_http_tls(tvb, pinfo, tree, data); + return TRUE; + } + + /* Check if we have a line terminated by CRLF + * Return the length of the line (not counting the line terminator at + * the end), or, if we don't find a line terminator: + * + * if "deseg" is true, return -1; + */ + linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE); + if((linelen == -1)||(linelen == 8)){ + return FALSE; + } + + /* Check if the line start or ends with the HTTP token */ + if((tvb_strncaseeql(tvb, linelen-8, "HTTP/1.", 7) != 0) && (tvb_strncaseeql(tvb, 0, "HTTP/1.", 7) != 0)) { + /* we couldn't find the Magic Hello HTTP/1.X. */ + return FALSE; + } + + conv_data = wmem_new0(wmem_file_scope(), http_conv_t); + conversation_add_proto_data(conversation, proto_http2, conv_data); + dissect_http_tls(tvb, pinfo, tree, data); + return TRUE; +} + static int dissect_http_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { @@ -4433,6 +4471,7 @@ proto_reg_handoff_message_http(void) dissector_add_string("media_type", "message/http", message_http_handle); heur_dissector_add("tcp", dissect_http_heur_tcp, "HTTP over TCP", "http_tcp", proto_http, HEURISTIC_ENABLE); + heur_dissector_add("tls", dissect_http_heur_tls, "HTTP over TLS", "http_tls", proto_http, HEURISTIC_ENABLE); proto_http2 = proto_get_id_by_filter_name("http2"); |