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
This commit is contained in:
Dirk Römmen 2021-04-11 20:59:36 +02:00 committed by Wireshark GitLab Utility
parent df508537be
commit a1a2b53663
5 changed files with 1188 additions and 32 deletions

View File

@ -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);
@ -13441,6 +13643,42 @@ fAuditLogQueryAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
return offset;
}
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)
{
@ -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 }

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}
/*

View File

@ -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");