Use MAC address documentation range in filter examples
[metze/wireshark/wip.git] / epan / dissectors / packet-bacapp.c
index 7ea921719779921a25829252ddcaca095b513a84..1abf510e8c781d4d57b56af36923bd004779b393 100644 (file)
@@ -6,8 +6,6 @@
  * Enhanced by Felix Kraemer, 2010, <sauter-cumulus[AT]de.sauter-bc.com>,
  *  Sauter-Cumulus GmbH, Freiburg
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald[AT]wireshark.org>
  * Copyright 1998 Gerald Combs
 
 #include "config.h"
 
-#include <glib.h>
-
 #include <epan/packet.h>
 #include <epan/to_str.h>
-#include <epan/wmem/wmem.h>
 #include <epan/reassemble.h>
 #include <epan/expert.h>
 #include <epan/stats_tree.h>
@@ -43,11 +38,6 @@ static int bacapp_tap = -1;
 
 /* formerly bacapp.h  contains definitions and forward declarations */
 
-#ifndef FAULT
-#define FAULT           proto_tree_add_text(subtree, tvb, offset, tvb_length(tvb) - offset, "something is going wrong here !!"); \
-    offset = tvb_length(tvb);
-#endif
-
 /* BACnet PDU Types */
 #define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST                   0
 #define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST                 1
@@ -758,7 +748,7 @@ fReadPropertyMultipleRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subt
  *  listOfReadAccessResults SEQUENCE OF ReadAccessResult
  * }
  * @param tvb the tv buffer of the current data
- * @parma pinfo
+ * @param pinfo the packet info of the current data
  * @param tree the tree to append this item to
  * @param offset the offset in the tvb
  * @return offset modified
@@ -2321,8 +2311,8 @@ fApplicationTypesEnumerated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
     const gchar *label, const value_string *vs);
 
 static const char *bacapp_unknown_service_str = "unknown service";  /* Usage: no format specifiers */
-static const char *ASHRAE_Reserved_Fmt = "(%d) Reserved for Use by ASHRAE";
-static const char *Vendor_Proprietary_Fmt = "(%d) Vendor Proprietary Value";
+static const char ASHRAE_Reserved_Fmt[] = "(%d) Reserved for Use by ASHRAE";
+static const char Vendor_Proprietary_Fmt[] = "(%d) Vendor Proprietary Value";
 
 static const value_string
 BACnetTypeName[] = {
@@ -3167,7 +3157,7 @@ BACnetPropertyIdentifier [] = {
     {   6, "alarm-value"},
     {   7, "alarm-values"},
     {   8, "all"},
-    {   9, "all-write-successful"},
+    {   9, "all-writes-successful"},
     {  10, "apdu-segment-timeout"},
     {  11, "apdu-timeout"},
     {  12, "application-software-version"},
@@ -3205,7 +3195,7 @@ BACnetPropertyIdentifier [] = {
     {  44, "firmware-revision"},
     {  45, "high-limit"},
     {  46, "inactive-text"},
-    {  47, "in-progress"},
+    {  47, "in-process"},
     {  48, "instance-of"},
     {  49, "integral-constant"},
     {  50, "integral-constant-units"},
@@ -4103,12 +4093,12 @@ BACnetVendorIdentifiers [] = {
     {  70, "RLE Technologies" },
     {  71, "Cardkey Systems" },
     {  72, "SECOM Co., Ltd." },
-    {  73, "ABB Gebaudetechnik AG Bereich NetServ" },
+    {  73, "ABB Gebaeudetechnik AG Bereich NetServ" },
     {  74, "KNX Association cvba" },
     {  75, "Institute of Electrical Installation Engineers of Japan (IEIEJ)" },
     {  76, "Nohmi Bosai, Ltd." },
     {  77, "Carel S.p.A." },
-    {  78, "AirSense Technology, Inc." },
+    {  78, "UTC Fire & Security Espana, S.L." },
     {  79, "Hochiki Corporation" },
     {  80, "Fr. Sauter AG" },
     {  81, "Matsushita Electric Works, Ltd." },
@@ -4139,7 +4129,7 @@ BACnetVendorIdentifiers [] = {
     { 106, "Meidensha Corporation" },
     { 107, "JCI Systems Integration Services" },
     { 108, "Freedom Corporation" },
-    { 109, "Neuberger Gebaudeautomation GmbH" },
+    { 109, "Neuberger Gebaeudeautomation GmbH" },
     { 110, "Sitronix" },
     { 111, "Leviton Manufacturing" },
     { 112, "Fujitsu Limited" },
@@ -4186,7 +4176,7 @@ BACnetVendorIdentifiers [] = {
     { 153, "National Environmental Product" },
     { 154, "Unitec Corporation" },
     { 155, "Kanden Engineering Company" },
-    { 156, "Messner Gebaudetechnik GmbH" },
+    { 156, "Messner Gebaeudetechnik GmbH" },
     { 157, "Integrated.CH" },
     { 158, "Price Industries" },
     { 159, "SE-Elektronic GmbH" },
@@ -4195,7 +4185,7 @@ BACnetVendorIdentifiers [] = {
     { 162, "ASI Controls" },
     { 163, "SysMik GmbH Dresden" },
     { 164, "HSC Regelungstechnik GmbH" },
-    { 165, "Smart Temp Australia Pty. Ltd." },
+    { 165, "Smart Temp Australia Pty.  Ltd." },
     { 166, "Cooper Controls" },
     { 167, "Duksan Mecasys Co., Ltd." },
     { 168, "Fuji IT Co., Ltd." },
@@ -4207,6 +4197,7 @@ BACnetVendorIdentifiers [] = {
     { 174, "Building Control Integrators" },
     { 175, "ITG Worldwide (M) Sdn Bhd" },
     { 176, "Lutron Electronics Co., Inc." },
+    { 177, "Cooper-Atkins Corporation" },
     { 178, "LOYTEC Electronics GmbH" },
     { 179, "ProLon" },
     { 180, "Mega Controls Limited" },
@@ -4217,7 +4208,7 @@ BACnetVendorIdentifiers [] = {
     { 185, "Hermos AG" },
     { 186, "CEZIM" },
     { 187, "Softing" },
-    { 188, "Lynxspring" },
+    { 188, "Lynxspring, Inc." },
     { 189, "Schneider Toshiba Inverter Europe" },
     { 190, "Danfoss Drives A/S" },
     { 191, "Eaton Corporation" },
@@ -4226,7 +4217,7 @@ BACnetVendorIdentifiers [] = {
     { 194, "Noveo, Inc." },
     { 195, "AMEV" },
     { 196, "Yokogawa Electric Corporation" },
-    { 197, "GFR Gesellschaft fur Regelungstechnik" },
+    { 197, "GFR Gesellschaft fuer Regelungstechnik" },
     { 198, "Exact Logic" },
     { 199, "Mass Electronics Pty Ltd dba Innotech Control Systems Australia" },
     { 200, "Kandenko Co., Ltd." },
@@ -4335,7 +4326,7 @@ BACnetVendorIdentifiers [] = {
     { 303, "Real Time Automation, Inc." },
     { 304, "ITEC Hankyu-Hanshin Co." },
     { 305, "Cyrus E&M Engineering Co., Ltd." },
-    { 306, "Racine Federated, Inc." },
+    { 306, "Badger Meter" },
     { 307, "Cirrascale Corporation" },
     { 308, "Elesta GmbH Building Automation" },
     { 309, "Securiton" },
@@ -4429,7 +4420,7 @@ BACnetVendorIdentifiers [] = {
     { 397, "EGauge Systems, LLC" },
     { 398, "Quantum Automation (ASIA) PTE, Ltd." },
     { 399, "Toshiba Lighting & Technology Corp." },
-    { 400, "SPIN Engenharia de Automaca Ltda." },
+    { 400, "SPIN Engenharia de Automacao Ltda." },
     { 401, "Logistics Systems & Software Services India PVT. Ltd." },
     { 402, "Delta Controls Integration Products" },
     { 403, "Focus Media" },
@@ -4457,7 +4448,7 @@ BACnetVendorIdentifiers [] = {
     { 425, "Triacta Power Technologies, Inc." },
     { 426, "Globestar Systems" },
     { 427, "MLB Advanced Media, LP" },
-    { 428, "SWG Stuckmann Wirtschaftliche Gebaudesysteme GmbH" },
+    { 428, "SWG Stuckmann Wirtschaftliche Gebaeudesysteme GmbH" },
     { 429, "SensorSwitch" },
     { 430, "Multitek Power Limited" },
     { 431, "Aquametro AG" },
@@ -4492,7 +4483,7 @@ BACnetVendorIdentifiers [] = {
     { 460, "Log-One Ltd." },
     { 461, "TECO Electric & Machinery Co., Ltd." },
     { 462, "ConnectEx, Inc." },
-    { 463, "Turbo DDC Sudwest" },
+    { 463, "Turbo DDC Suedwest" },
     { 464, "Quatrosense Environmental Ltd." },
     { 465, "Fifth Light Technology Ltd." },
     { 466, "Scientific Solutions, Ltd." },
@@ -4669,7 +4660,7 @@ BACnetVendorIdentifiers [] = {
     { 638, "Conditionaire International Pty. Limited" },
     { 639, "Quebec, Inc." },
     { 640, "Homerun Holdings" },
-    { 641, "RFM, Inc." },
+    { 641, "Murata Americas" },
     { 642, "Comptek" },
     { 643, "Westco Systems, Inc." },
     { 644, "Advancis Software & Services GmbH" },
@@ -4710,7 +4701,7 @@ BACnetVendorIdentifiers [] = {
     { 680, "ISM EuroCenter S.A." },
     { 681, "TDIS" },
     { 682, "Trade FIDES" },
-    { 683, "Knurr GmbH (Emerson Network Power)" },
+    { 683, "Knuerr GmbH (Emerson Network Power)" },
     { 684, "Resource Data Management" },
     { 685, "Abies Technology, Inc." },
     { 686, "Amalva" },
@@ -4722,16 +4713,96 @@ BACnetVendorIdentifiers [] = {
     { 692, "Ruskin Manufacturing" },
     { 693, "Calon Associates Limited" },
     { 694, "Contec Co., Ltd." },
-    { 695, "iT GmbH"},
-    { 696, "Autani Corporation"},
-    { 697, "Christian Fortin"},
-    { 698, "HDL"},
-    { 699, "IPID Sp. Z.O.O Limited"},
-    { 700, "Fuji Electric Co., Ltd"},
-    { 701, "View, Inc."},
-    { 702, "Samsung S1 Corporation"},
-    { 703, "New Lift"},
-    { 704, "VRT Systems"},
+    { 695, "iT GmbH" },
+    { 696, "Autani Corporation" },
+    { 697, "Christian Fortin" },
+    { 698, "HDL" },
+    { 699, "IPID Sp. Z.O.O Limited" },
+    { 700, "Fuji Electric Co., Ltd" },
+    { 701, "View, Inc." },
+    { 702, "Samsung S1 Corporation" },
+    { 703, "New Lift" },
+    { 704, "VRT Systems" },
+    { 705, "Motion Control Engineering, Inc." },
+    { 706, "Weiss Klimatechnik GmbH" },
+    { 707, "Elkon" },
+    { 708, "Eliwell Controls S.r.l." },
+    { 709, "Japan Computer Technos Corp" },
+    { 710, "Rational Network ehf" },
+    { 711, "Magnum Energy Solutions, LLC" },
+    { 712, "MelRok" },
+    { 713, "VAE Group" },
+    { 714, "LGCNS" },
+    { 715, "Berghof Automationstechnik GmbH" },
+    { 716, "Quark Communications, Inc." },
+    { 717, "Sontex" },
+    { 718, "mivune AG" },
+    { 719, "Panduit" },
+    { 720, "Smart Controls, LLC" },
+    { 721, "Compu-Aire, Inc." },
+    { 722, "Sierra" },
+    { 723, "ProtoSense Technologies" },
+    { 724, "Eltrac Technologies Pvt Ltd" },
+    { 725, "Bektas Invisible Controls GmbH" },
+    { 726, "Entelec" },
+    { 727, "Innexiv" },
+    { 728, "Covenant" },
+    { 729, "Davitor AB" },
+    { 730, "TongFang Technovator" },
+    { 731, "Building Robotics, Inc." },
+    { 732, "HSS-MSR UG" },
+    { 733, "FramTack LLC" },
+    { 734, "B. L. Acoustics, Ltd." },
+    { 735, "Traxxon Rock Drills, Ltd" },
+    { 736, "Franke" },
+    { 737, "Wurm GmbH & Co" },
+    { 738, "AddENERGIE" },
+    { 739, "Mirle Automation Corporation" },
+    { 740, "Ibis Networks" },
+    { 741, "ID-KARTA s.r.o." },
+    { 742, "Anaren, Inc." },
+    { 743, "Span, Incorporated" },
+    { 744, "Bosch Thermotechnology Corp" },
+    { 745, "DRC Technology S.A." },
+    { 746, "Shanghai Energy Building Technology Co, Ltd" },
+    { 747, "Fraport AG" },
+    { 748, "Flowgroup" },
+    { 749, "Skytron Energy, GmbH" },
+    { 750, "ALTEL Wicha, Golda Sp. J." },
+    { 751, "Drupal" },
+    { 752, "Axiomatic Technology, Ltd" },
+    { 753, "Bohnke + Partner" },
+    { 754, "Function 1" },
+    { 755, "Optergy Pty, Ltd" },
+    { 756, "LSI Virticus" },
+    { 757, "Konzeptpark GmbH" },
+    { 758, "Hubbell Building Automation, Inc." },
+    { 759, "eCurv, Inc." },
+    { 760, "Agnosys GmbH" },
+    { 761, "Shanghai Sunfull Automation Co., LTD" },
+    { 762, "Kurz Instruments, Inc." },
+    { 763, "Cias Elettronica S.r.l." },
+    { 764, "Multiaqua, Inc." },
+    { 765, "BlueBox" },
+    { 766, "Sensidyne" },
+    { 767, "Viessmann Elektronik GmbH" },
+    { 768, "ADFweb.com srl" },
+    { 769, "Gaylord Industries" },
+    { 770, "Majur Ltd." },
+    { 771, "Shanghai Huilin Technology Co., Ltd." },
+    { 772, "Exotronic" },
+    { 773, "Safecontrol spol s.r.o." },
+    { 774, "Amatis" },
+    { 775, "Universal Electric Corporation" },
+    { 776, "iBACnet" },
+    { 778, "Smartrise Engineering, Inc." },
+    { 779, "Miratron, Inc." },
+    { 780, "SmartEdge" },
+    { 781, "Mitsubishi Electric Australia Pty Ltd" },
+    { 782, "Triangle Research International Ptd Ltd" },
+    { 783, "Produal Oy" },
+    { 784, "Milestone Systems A/S" },
+    { 785, "Trustbridge" },
     { 0, NULL }
 };
 static value_string_ext BACnetVendorIdentifiers_ext = VALUE_STRING_EXT_INIT(BACnetVendorIdentifiers);
@@ -4762,6 +4833,7 @@ static int hf_BACnetExtendedTagNumber = -1;
 static int hf_BACnetNamedTag = -1;
 static int hf_BACnetTagClass = -1;
 static int hf_BACnetCharacterSet = -1;
+static int hf_BACnetCodePage = -1;
 static int hf_bacapp_tag_lvt = -1;
 static int hf_bacapp_tag_ProcessId = -1;
 static int hf_bacapp_uservice = -1;
@@ -4793,6 +4865,7 @@ static gint ett_bacapp_list = -1;
 static gint ett_bacapp_value = -1;
 
 static expert_field ei_bacapp_bad_length = EI_INIT;
+static expert_field ei_bacapp_bad_tag = EI_INIT;
 
 static gint32 propertyIdentifier = -1;
 static gint32 propertyArrayIndex = -1;
@@ -4823,6 +4896,17 @@ bacapp_packet_stats_tree_init(stats_tree* st)
     st_node_packets_by_ip_dst = stats_tree_create_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
 }
 
+static gchar *
+bacapp_get_address_label(const char *tag, address *addr)
+{
+    gchar *addr_str, *label_str;
+
+    addr_str = address_to_str(NULL, addr);
+    label_str = wmem_strconcat(NULL, tag, addr_str, NULL);
+    wmem_free(NULL, addr_str);
+    return label_str;
+}
+
 static int
 bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p)
 {
@@ -4840,8 +4924,8 @@ bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt
     gchar *srcstr;
     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
 
-    srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
-    dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
+    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
+    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
 
     tick_stat_node(st, st_str_packets_by_ip, 0, TRUE);
     packets_for_this_dst = tick_stat_node(st, st_str_packets_by_ip_dst, st_node_packets_by_ip, TRUE);
@@ -4861,6 +4945,9 @@ bacapp_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt
         }
     }
 
+    wmem_free(NULL, srcstr);
+    wmem_free(NULL, dststr);
+
     return 1;
 }
 
@@ -4886,8 +4973,8 @@ bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* ed
 
     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
 
-    srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
-    dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
+    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
+    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
 
     tick_stat_node(st, st_str_packets_by_service, 0, TRUE);
     if (binfo->service_type) {
@@ -4900,6 +4987,9 @@ bacapp_stats_tree_service(stats_tree* st, packet_info* pinfo, epan_dissect_t* ed
         }
     }
 
+    wmem_free(NULL, srcstr);
+    wmem_free(NULL, dststr);
+
     return 1;
 }
 
@@ -4924,8 +5014,8 @@ bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* e
     gchar *srcstr;
     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
 
-    srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
-    dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
+    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
+    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
 
     tick_stat_node(st, st_str_packets_by_objectid, 0, TRUE);
     if (binfo->object_ident) {
@@ -4938,6 +5028,9 @@ bacapp_stats_tree_objectid(stats_tree* st, packet_info* pinfo, epan_dissect_t* e
         }
     }
 
+    wmem_free(NULL, srcstr);
+    wmem_free(NULL, dststr);
+
     return 1;
 }
 
@@ -4962,8 +5055,8 @@ bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t*
     gchar *srcstr;
     const bacapp_info_value_t *binfo = (const bacapp_info_value_t *)p;
 
-    srcstr = wmem_strconcat(wmem_packet_scope(), "Src: ", ep_address_to_str(&pinfo->src), NULL);
-    dststr = wmem_strconcat(wmem_packet_scope(), "Dst: ", ep_address_to_str(&pinfo->dst), NULL);
+    srcstr = bacapp_get_address_label("Src: ", &pinfo->src);
+    dststr = bacapp_get_address_label("Dst: ", &pinfo->dst);
 
     tick_stat_node(st, st_str_packets_by_instanceid, 0, TRUE);
     if (binfo->object_ident) {
@@ -4975,6 +5068,10 @@ bacapp_stats_tree_instanceid(stats_tree* st, packet_info* pinfo, epan_dissect_t*
             tick_stat_node(st, binfo->object_ident, servicetype, FALSE);
         }
     }
+
+    wmem_free(NULL, srcstr);
+    wmem_free(NULL, dststr);
+
     return 1;
 }
 
@@ -4993,7 +5090,7 @@ register_bacapp_stat_trees(void)
         bacapp_stats_tree_instanceid, bacapp_instanceid_stats_tree_init, NULL);
 }
 
-/* 'data' must be ep_ allocated */
+/* 'data' must be allocated with wmem packet scope */
 static gint
 updateBacnetInfoValue(gint whichval, const gchar *data)
 {
@@ -5058,6 +5155,11 @@ fGetMaxAPDUSize(guint8 idx)
 }
 #endif
 
+static const char*
+val_to_split_str(guint32 val, guint32 split_val, const value_string *vs,
+    const char *fmt, const char *split_fmt)
+    G_GNUC_PRINTF(4, 0)
+    G_GNUC_PRINTF(5, 0);
 
 /* Used when there are ranges of reserved and proprietary enumerations */
 static const char*
@@ -5242,24 +5344,26 @@ fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
     if (tree) {
         proto_tree *subtree;
-        if (tag_is_opening(tag))
-            ti = proto_tree_add_text(tree, tvb, offset, tag_len, "{[%u]", *tag_no );
-        else if (tag_is_closing(tag))
-            ti = proto_tree_add_text(tree, tvb, offset, tag_len, "}[%u]", *tag_no );
-        else if (tag_is_context_specific(tag)) {
-            ti = proto_tree_add_text(tree, tvb, offset, tag_len,
-                                     "Context Tag: %u, Length/Value/Type: %u",
-                                     *tag_no, *lvt);
-        } else
-            ti = proto_tree_add_text(tree, tvb, offset, tag_len,
-                                     "Application Tag: %s, Length/Value/Type: %u",
-                                     val_to_str(*tag_no,
-                                                BACnetApplicationTagNumber,
-                                                ASHRAE_Reserved_Fmt),
-                                     *lvt);
+        if (tag_is_opening(tag)) {
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
+                    ett_bacapp_tag, &ti, "{[%u]", *tag_no );
+        } else if (tag_is_closing(tag)) {
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
+                    ett_bacapp_tag, &ti, "}[%u]", *tag_no );
+        } else if (tag_is_context_specific(tag)) {
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
+                    ett_bacapp_tag, &ti,
+                    "Context Tag: %u, Length/Value/Type: %u", *tag_no, *lvt);
+        } else {
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_len,
+                    ett_bacapp_tag, &ti,
+                    "Application Tag: %s, Length/Value/Type: %u",
+                    val_to_str(*tag_no, BACnetApplicationTagNumber,
+                        ASHRAE_Reserved_Fmt),
+                    *lvt);
+        }
 
         /* details if needed */
-        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
         proto_tree_add_item(subtree, hf_BACnetTagClass, tvb, offset, 1, ENC_BIG_ENDIAN);
         if (tag_is_extended_tag_number(tag)) {
             proto_tree_add_uint_format(subtree,
@@ -5294,10 +5398,10 @@ fTagHeaderTree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                 tvb, lvt_offset, lvt_len, *lvt);
     } /* if (tree) */
 
-    if (*lvt > tvb_length(tvb)) {
+    if (*lvt > tvb_reported_length(tvb)) {
         expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
                                "LVT length too long: %d > %d", *lvt,
-                               tvb_length(tvb));
+                               tvb_reported_length(tvb));
         *lvt = 1;
     }
 
@@ -5316,11 +5420,9 @@ fNullTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, cons
 {
     guint8      tag_no, tag_info;
     guint32     lvt;
-    proto_item *ti;
     proto_tree *subtree;
 
-    ti      = proto_tree_add_text(tree, tvb, offset, 1, "%sNULL", label);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "%sNULL", label);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset + 1;
@@ -5331,7 +5433,6 @@ fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, c
 {
     guint8      tag_no, tag_info;
     guint32     lvt      = 0;
-    proto_item *ti;
     proto_tree *subtree;
     guint       bool_len = 1;
 
@@ -5341,9 +5442,8 @@ fBooleanTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, c
         ++bool_len;
     }
 
-    ti = proto_tree_add_text(tree, tvb, offset, bool_len,
-                             "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset, bool_len,
+                             ett_bacapp_tag, NULL, "%s%s", label, lvt == 0 ? "FALSE" : "TRUE");
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset + bool_len;
@@ -5356,18 +5456,16 @@ fUnsignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     /* only support up to an 8 byte (64-bit) integer */
     if (fUnsigned64(tvb, offset + tag_len, lvt, &val))
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "%s(Unsigned) %" G_GINT64_MODIFIER "u", label, val);
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s - %u octets (Unsigned)", label, lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "%s - %u octets (Unsigned)", label, lvt);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5410,24 +5508,23 @@ fEnumeratedTagSplit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     /* only support up to a 4 byte (32-bit) enumeration */
     if (fUnsigned32(tvb, offset+tag_len, lvt, &val)) {
         if (vs)
-            ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-                "%s %s", label, val_to_split_str(val, split_val, vs,
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+                ett_bacapp_tag, NULL, "%s %s", label, val_to_split_str(val, split_val, vs,
                 ASHRAE_Reserved_Fmt, Vendor_Proprietary_Fmt));
         else
-            ti =proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-                "%s %u", label, val);
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+                ett_bacapp_tag, NULL, "%s %u", label, val);
     } else {
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s - %u octets (enumeration)", label, lvt);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "%s - %u octets (enumeration)", label, lvt);
     }
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5447,17 +5544,15 @@ fSignedTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, co
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (fSigned64(tvb, offset + tag_len, lvt, &val))
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "%s(Signed) %" G_GINT64_MODIFIER "d", label, val);
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s - %u octets (Signed)", label, lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "%s - %u octets (Signed)", label, lvt);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5470,14 +5565,12 @@ fRealTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, cons
     guint32     lvt;
     guint       tag_len;
     gfloat      f_val;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     f_val = tvb_get_ntohieee_float(tvb, offset+tag_len);
-    ti = proto_tree_add_text(tree, tvb, offset, 4+tag_len,
-        "%s%f (Real)", label, f_val);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 4+tag_len,
+        ett_bacapp_tag, NULL, "%s%f (Real)", label, f_val);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+4;
@@ -5490,14 +5583,12 @@ fDoubleTag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, co
     guint32 lvt;
     guint tag_len;
     gdouble d_val;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     d_val = tvb_get_ntohieee_double(tvb, offset+tag_len);
-    ti = proto_tree_add_text(tree, tvb, offset, 8+tag_len,
-        "%s%f (Double)", label, d_val);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset, 8+tag_len,
+        ett_bacapp_tag, NULL, "%s%f (Double)", label, d_val);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+8;
@@ -5514,12 +5605,16 @@ fProcessId(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
+    {
         ti = proto_tree_add_uint(tree, hf_bacapp_tag_ProcessId,
             tvb, offset, lvt+tag_len, val);
+        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    }
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "Process Identifier - %u octets (Signed)", lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    {
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "Process Identifier - %u octets (Signed)", lvt);
+    }
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
     offset += tag_len + lvt;
 
@@ -5531,21 +5626,21 @@ fTimeSpan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, con
 {
     guint32     val = 0, lvt;
     guint8      tag_no, tag_info;
-    proto_item *ti;
     proto_tree *subtree;
     guint       tag_len;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (fUnsigned32(tvb, offset+tag_len, lvt, &val))
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-        "%s (hh.mm.ss): %d.%02d.%02d%s",
-        label,
-        (val / 3600), ((val % 3600) / 60), (val % 60),
-        val == 0 ? " (indefinite)" : "");
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
+            "%s (hh.mm.ss): %d.%02d.%02d%s",
+            label,
+            (val / 3600), ((val % 3600) / 60), (val % 60),
+            val == 0 ? " (indefinite)" : "");
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
             "%s - %u octets (Signed)", label, lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5558,18 +5653,17 @@ fWeekNDay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     month = tvb_get_guint8(tvb, offset+tag_len);
     weekOfMonth = tvb_get_guint8(tvb, offset+tag_len+1);
     dayOfWeek = tvb_get_guint8(tvb, offset+tag_len+2);
-    ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len, "%s %s, %s",
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+                 ett_bacapp_tag, NULL, "%s %s, %s",
                  val_to_str(month, months, "month (%d) not found"),
                  val_to_str(weekOfMonth, weekofmonth, "week of month (%d) not found"),
                  val_to_str(dayOfWeek, day_of_week, "day of week (%d) not found"));
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5582,7 +5676,6 @@ fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const g
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
@@ -5591,12 +5684,14 @@ fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const g
     day     = tvb_get_guint8(tvb, offset+tag_len+2);
     weekday = tvb_get_guint8(tvb, offset+tag_len+3);
     if ((year == 255) && (day == 255) && (month == 255) && (weekday == 255)) {
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
             "%sany", label);
     }
     else if (year != 255) {
         year += 1900;
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
             "%s%s %d, %d, (Day of Week = %s)",
             label, val_to_str(month,
                 months,
@@ -5605,12 +5700,12 @@ fDate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const g
                 day_of_week,
                 "(%d) not found"));
     } else {
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
             "%s%s %d, any year, (Day of Week = %s)",
             label, val_to_str(month, months, "month (%d) not found"),
             day, val_to_str(weekday, day_of_week, "(%d) not found"));
     }
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5622,7 +5717,6 @@ fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const g
     guint32     hour, minute, second, msec, lvt;
     guint8      tag_no, tag_info;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
@@ -5631,17 +5725,18 @@ fTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const g
     second  = tvb_get_guint8(tvb, offset+tag_len+2);
     msec    = tvb_get_guint8(tvb, offset+tag_len+3);
     if ((hour == 255) && (minute == 255) && (second == 255) && (msec == 255))
-        ti = proto_tree_add_text(tree, tvb, offset,
-            lvt+tag_len, "%sany", label);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset,
+            lvt+tag_len, ett_bacapp_tag, NULL,
+            "%sany", label);
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
             "%s%d:%02d:%02d.%d %s = %02d:%02d:%02d.%d",
             label,
             hour > 12 ? hour - 12 : hour,
             minute, second, msec,
             hour >= 12 ? "P.M." : "A.M.",
             hour, minute, second, msec);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -5651,11 +5746,9 @@ static guint
 fDateTime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label)
 {
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     if (label != NULL) {
-        tt = proto_tree_add_text(subtree, tvb, offset, 10, "%s", label);
-        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+        subtree = proto_tree_add_subtree(subtree, tvb, offset, 10, ett_bacapp_value, NULL, label);
     }
     offset = fDate(tvb, pinfo, subtree, offset, "Date: ");
     return fTime(tvb, pinfo, subtree, offset, "Time: ");
@@ -5712,13 +5805,10 @@ fEventTimeStamps( tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint
 {
     guint32     lvt     = 0;
     proto_tree* subtree = tree;
-    proto_item* ti      = 0;
 
     if (tvb_reported_length_remaining(tvb, offset) > 0) {
-        ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
-        if (ti) {
-            subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-        }
+        subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
+
         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
         offset = fTimeStamp(tvb, pinfo, subtree, offset, "TO-NORMAL timestamp: ");
@@ -5802,19 +5892,16 @@ fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
     guint       start   = offset;
     guint8      tag_no, tag_info;
     proto_tree *subtree = tree;
-    proto_item *ti      = 0;
 
     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
 
     if (lvt > 0) {
-        tmp = tvb_bytes_to_ep_str(tvb, offset, lvt);
-        ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s %s", label, tmp);
+        tmp = tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, lvt);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt,
+                    ett_bacapp_tag, NULL, "%s %s", label, tmp);
         offset += lvt;
     }
 
-    if (ti)
-        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-
     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
 
     return offset;
@@ -5823,44 +5910,26 @@ fOctetString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset,
 static guint
 fMacAddress(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, const gchar *label, guint32 lvt)
 {
-    gchar *tmp;
     guint start = offset;
     guint8 tag_no, tag_info;
     proto_tree* subtree = tree;
-    proto_item* ti;
 
     offset += fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
 
-    ti = proto_tree_add_text(tree, tvb, offset, 6, "%s", label); /* just add the label, with the tagHeader information in its subtree */
-
-    if (lvt > 0) {
-        if (lvt == 6) { /* we have 6 Byte IP Address with 4 Octets IPv4 and 2 Octets Port Information */
-
-            guint32 ip   = tvb_get_ipv4(tvb, offset);
-            guint16 port = tvb_get_ntohs(tvb, offset+4);
-
-            proto_tree_add_ipv4(tree, hf_bacapp_tag_IPV4, tvb, offset, 4, ip);
-            proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, port);
-
-        } else {
-            if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
-            struct e_in6_addr addr;
-            guint16 port =  tvb_get_ntohs(tvb, offset+16);
-            tvb_get_ipv6(tvb, offset, &addr);
-
-            proto_tree_add_ipv6(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, (const guint8 *) &addr);
-            proto_tree_add_uint(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, port);
-
-            } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
-                tmp = tvb_bytes_to_ep_str(tvb, offset, lvt);
-                ti = proto_tree_add_text(tree, tvb, offset, lvt, "%s", tmp);
-            }
-        }
-        offset += 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);
+
+    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);
+        proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+4, 2, ENC_BIG_ENDIAN);
+    } else if (lvt == 18) { /* we have 18 Byte IP Address with 16 Octets IPv6 and 2 Octets Port Information */
+        proto_tree_add_item(tree, hf_bacapp_tag_IPV6, tvb, offset, 16, ENC_NA);
+        proto_tree_add_item(tree, hf_bacapp_tag_PORT, tvb, offset+16, 2, ENC_BIG_ENDIAN);
+    } else { /* we have 1 Byte MS/TP Address or anything else interpreted as an address */
+        subtree = proto_tree_add_subtree(tree, tvb, offset, lvt,
+                ett_bacapp_tag, NULL, tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, lvt));
     }
-
-    if (ti)
-        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+    offset += lvt;
 
     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
 
@@ -5898,21 +5967,21 @@ fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_length;
-    proto_item *ti;
     proto_tree *subtree;
     guint32     object_id;
 
     tag_length  = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     object_id   = tvb_get_ntohl(tvb, offset+tag_length);
     object_type = object_id_type(object_id);
-    ti = proto_tree_add_text(tree, tvb, offset, tag_length + 4,
-        "ObjectIdentifier: %s, %u",
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset, tag_length + 4,
+        ett_bacapp_tag, NULL, "ObjectIdentifier: %s, %u",
         val_to_split_str(object_type,
             128,
             BACnetObjectType,
             ASHRAE_Reserved_Fmt,
             Vendor_Proprietary_Fmt),
         object_id_instance(object_id));
+
     if (col_get_writable(pinfo->cinfo))
         col_append_fstr(pinfo->cinfo, COL_INFO, "%s,%u ",
             val_to_split_str(object_type,
@@ -5934,7 +6003,6 @@ fObjectIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
                     object_id_instance(object_id)));
 
     /* here are the details of how we arrived at the above text */
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
     offset += tag_length;
     proto_tree_add_item(subtree, hf_bacapp_objectType, tvb, offset, 4, ENC_BIG_ENDIAN);
@@ -5971,12 +6039,10 @@ fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *orgtree    = tree;
-    proto_item *tt;
     proto_tree *subtree;
 
     /* beginning of new item - indent and label */
-    tt   = proto_tree_add_text(orgtree, tvb, offset, 1, "Recipient Process" );
-    tree = proto_item_add_subtree(tt, ett_bacapp_value);
+    tree = proto_tree_add_subtree(orgtree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient Process" );
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
         lastoffset = offset;
@@ -5984,8 +6050,7 @@ fRecipientProcess(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
         switch (fTagNo(tvb, offset)) {
         case 0: /* recipient */
             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context open */
-            tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
-            subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
             offset  = fRecipient(tvb, pinfo, subtree, offset);
             offset += fTagHeaderTree(tvb, pinfo, tree, offset, &tag_no, &tag_info, &lvt); /* show context close */
             break;
@@ -6008,7 +6073,6 @@ fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offs
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree;
-    proto_item *tt;
     proto_tree *orgtree    = tree;
     guint       itemno     = 1;
 
@@ -6022,19 +6086,19 @@ fCOVSubscription(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offs
 
         case 0: /* recipient */
                 /* beginning of new item in list */
-                tt = proto_tree_add_text(orgtree, tvb, offset, 1, "Subscription %d",itemno);    /* add tree label and indent */
+                tree = proto_tree_add_subtree_format(orgtree, tvb, offset, 1,
+                    ett_bacapp_value, NULL, "Subscription %d",itemno);    /* add tree label and indent */
                 itemno = itemno + 1;
-                tree = proto_item_add_subtree(tt, ett_bacapp_value);
 
-                tt = proto_tree_add_text(tree, tvb, offset, 1, "Recipient");    /* add tree label and indent */
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
+                    ett_bacapp_value, NULL, "Recipient");    /* add tree label and indent */
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt); /* show context open */
                 offset  = fRecipientProcess(tvb, pinfo, subtree, offset);
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);  /* show context close */
             break;
         case 1: /* MonitoredPropertyReference */
-                tt = proto_tree_add_text(tree, tvb, offset, 1, "Monitored Property Reference");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(tree, tvb, offset, 1,
+                    ett_bacapp_value, NULL, "Monitored Property Reference");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
@@ -6134,7 +6198,6 @@ fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree    = tree;
-    proto_item *ti;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {
         lastoffset = offset;
@@ -6147,8 +6210,7 @@ fActionList(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
             continue;
         }
         if (tag_is_opening(tag_info)) {
-            ti = proto_tree_add_text(tree, tvb, offset, 1, "Action List");
-            subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+            subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_tag, NULL, "Action List");
             offset += fTagHeaderTree(tvb, pinfo, subtree, offset,
                 &tag_no, &tag_info, &lvt);
         }
@@ -6170,7 +6232,6 @@ fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint o
     guint8       tag_no, tag_info;
     guint32      lvt;
     guint        tag_len;
-    proto_item  *ti;
     proto_tree  *subtree;
     const gchar *label = "Property Identifier";
 
@@ -6178,7 +6239,8 @@ fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint o
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     /* can we decode this value? */
     if (fUnsigned32(tvb, offset+tag_len, lvt, (guint32 *)&propertyIdentifier)) {
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL,
             "%s: %s (%u)", label,
             val_to_split_str(propertyIdentifier, 512,
                 BACnetPropertyIdentifier,
@@ -6194,7 +6256,7 @@ fPropertyIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint o
         /* property identifiers cannot be larger than 22-bits */
         return offset;
     }
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
     proto_tree_add_item(subtree, hf_BACnetPropertyIdentifier, tvb,
         offset+tag_len, lvt, ENC_BIG_ENDIAN);
@@ -6208,17 +6270,15 @@ fPropertyArrayIndex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint o
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (fUnsigned32(tvb, offset + tag_len, lvt, (guint32 *)&propertyArrayIndex))
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "property Array Index (Unsigned) %u", propertyArrayIndex);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "property Array Index (Unsigned) %u", propertyArrayIndex);
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "property Array Index - %u octets (Unsigned)", lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, NULL, "property Array Index - %u octets (Unsigned)", lvt);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset+tag_len+lvt;
@@ -6229,24 +6289,26 @@ fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offs
 {
     guint8      tag_no, tag_info, character_set;
     guint32     lvt, l;
-    guint       offs, extra = 1;
+    guint       offs;
     const char *coding;
-    guint8      bf_arr[512], *out;
-    proto_item *ti;
+    guint8     *out;
     proto_tree *subtree;
     guint       start = offset;
 
     if (tvb_reported_length_remaining(tvb, offset) > 0) {
 
         offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
+        offset += offs;
+
+        character_set = tvb_get_guint8(tvb, offset);
+        offset++;
+        lvt--;
 
-        character_set = tvb_get_guint8(tvb, offset+offs);
         /* Account for code page if DBCS */
-        if (character_set == 1) {
-            extra = 3;
+        if (character_set == IBM_MS_DBCS) {
+            offset += 2;
+            lvt -= 2;
         }
-        offset += (offs+extra);
-        lvt -= (extra);
 
         do {
             l = MIN(lvt, 256);
@@ -6273,11 +6335,11 @@ fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offs
                 coding = "UTF-8";
                 break;
             case IBM_MS_DBCS:
-                out = tvb_get_string(wmem_packet_scope(), tvb, offset, l);
+                out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
                 coding = "IBM MS DBCS";
                 break;
             case JIS_C_6226:
-                out = tvb_get_string(wmem_packet_scope(), tvb, offset, l);
+                out = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, l, ENC_ASCII);
                 coding = "JIS C 6226";
                 break;
             case ISO_10646_UCS4:
@@ -6298,18 +6360,17 @@ fCharacterString(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offs
                 coding = "unknown";
                 break;
             }
-            ti = proto_tree_add_text(tree, tvb, offset, l, "%s%s '%s'", label, coding, out);
+            subtree = proto_tree_add_subtree_format(tree, tvb, offset, l, ett_bacapp_tag, NULL,
+                                        "%s%s '%s'", label, coding, out);
             lvt    -= l;
             offset += l;
         } while (lvt > 0);
 
-        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-
         fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
         proto_tree_add_item(subtree, hf_BACnetCharacterSet, tvb, start+offs, 1, ENC_BIG_ENDIAN);
 
-        if (character_set == 1) {
-            proto_tree_add_text(subtree, tvb, start+offs+1, 2, "Code Page: %d", tvb_get_ntohs(tvb, start+offs+1));
+        if (character_set == IBM_MS_DBCS) {
+            proto_tree_add_item(subtree, hf_BACnetCodePage, tvb, start+offs+1, 2, ENC_BIG_ENDIAN);
         }
         /* XXX - put the string value here */
     }
@@ -6327,17 +6388,15 @@ fBitStringTagVS(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse
     guint32     lvt, i, numberOfBytes;
     guint8      bf_arr[256];
     proto_tree* subtree = tree;
-    proto_item* ti;
 
     offs = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     numberOfBytes = lvt-1; /* Ignore byte for unused bit count */
     offset += offs;
     unused  = tvb_get_guint8(tvb, offset); /* get the unused Bits */
-    ti      = proto_tree_add_text(tree, tvb, start, offs+lvt,
+    subtree = proto_tree_add_subtree_format(tree, tvb, start, offs+lvt,
+                                  ett_bacapp_tag, NULL,
                                   "%s(Bit String)", label);
-    if (ti) {
-        subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-    }
+
     fTagHeaderTree(tvb, pinfo, subtree, start, &tag_no, &tag_info, &lvt);
     proto_tree_add_text(subtree, tvb, offset, 1,
                 "Unused bits: %u", unused);
@@ -6499,7 +6558,6 @@ fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint o
     guint8      tag_no, tag_info;
     guint32     lvt;
     guint       tag_len;
-    proto_item *ti;
     proto_tree *subtree;
     gint        tvb_len;
 
@@ -6510,10 +6568,9 @@ fContextTaggedValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint o
     if ((tvb_len >= 0) && ((guint32)tvb_len < lvt)) {
         lvt = tvb_len;
     }
-    ti = proto_tree_add_text(tree, tvb, offset+tag_len, lvt,
-        "Context Value (as %u DATA octets)", lvt);
+    subtree = proto_tree_add_subtree_format(tree, tvb, offset+tag_len, lvt,
+        ett_bacapp_tag, NULL, "Context Value (as %u DATA octets)", lvt);
 
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     return offset + tag_len + lvt;
@@ -6977,14 +7034,14 @@ fPropertyValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset
         offset += fTagHeaderTree(tvb, pinfo, tree, offset,
                                  &tag_no, &tag_info, &lvt);
         offset  = fAbstractSyntaxNType(tvb, pinfo, tree, offset);
-        if (tvb_length_remaining(tvb, offset) > 0) {
+        if (tvb_reported_length_remaining(tvb, offset) > 0) {
             offset += fTagHeaderTree(tvb, pinfo, tree, offset,
                                      &tag_no, &tag_info, &lvt);
         }
     } else {
-        proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
+        proto_tree_add_text(tree, tvb, offset, tvb_reported_length(tvb) - offset,
                             "expected Opening Tag!");
-        offset = tvb_length(tvb);
+        offset = tvb_reported_length(tvb);
     }
 
     return offset;
@@ -7037,7 +7094,6 @@ fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
         lastoffset = offset;
@@ -7063,15 +7119,12 @@ fSubscribeCOVPropertyRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
             break;
         case 4: /* monitoredPropertyIdentifier */
             if (tag_is_opening(tag_info)) {
-                tt = proto_tree_add_text(subtree, tvb, offset, 1, "monitoredPropertyIdentifier");
-                if (tt) {
-                    subtree = proto_item_add_subtree(tt, ett_bacapp_value);
-                }
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "monitoredPropertyIdentifier");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         case 5: /* covIncrement */
             offset = fRealTag(tvb, pinfo, tree, offset, "COV Increment: ");
@@ -7157,7 +7210,6 @@ fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse
     guint32     lvt;
     guint       i = 1; /* day of week array index */
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     if (propertyArrayIndex > 0) {
         /* BACnetARRAY index 0 refers to the length
@@ -7175,8 +7227,8 @@ fWeeklySchedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse
         if (tag_is_closing(tag_info)) {
             return offset; /* outer encoding will print out closing tag */
         }
-        tt = proto_tree_add_text(tree, tvb, offset, 0, "%s", val_to_str(i++, day_of_week, "day of week (%d) not found"));
-        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+        subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_bacapp_value, NULL,
+                                val_to_str(i++, day_of_week, "day of week (%d) not found"));
         offset = fDailySchedule(tvb, pinfo, subtree, offset);
         if (offset == lastoffset) break;     /* nothing happened, exit loop */
     }
@@ -7224,19 +7276,18 @@ fVendorIdentifier(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s: %s (%u)",
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, &ti, "%s: %s (%u)",
             label,
             val_to_str_ext_const(val, &BACnetVendorIdentifiers_ext, "Unknown Vendor"),
             val);
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s - %u octets (Unsigned)", label, lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     if ((lvt < 1) || (lvt > 2)) { /* vendorIDs >= 1  and <= 2 are supported */
-        proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
+        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
                                 "Wrong length indicated. Expected 1 or 2, got %u", lvt);
         return offset+tag_len+lvt;
     }
@@ -7260,17 +7311,16 @@ fRestartReason(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset
 
     tag_len = fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (fUnsigned32(tvb, offset + tag_len, lvt, &val))
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s: %s (%u)", label,
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, &ti, "%s: %s (%u)", label,
             val_to_str_const(val, BACnetRestartReason, "Unknown reason"), val);
     else
-        ti = proto_tree_add_text(tree, tvb, offset, lvt+tag_len,
-            "%s - %u octets (Unsigned)", label, lvt);
-    subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
+        subtree = proto_tree_add_subtree_format(tree, tvb, offset, lvt+tag_len,
+            ett_bacapp_tag, &ti, "%s - %u octets (Unsigned)", label, lvt);
     fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
     if (lvt != 1) {
-        proto_tree_add_expert_format(tree, pinfo, &ei_bacapp_bad_length, tvb, 0, lvt,
+        expert_add_info_format(pinfo, ti, &ei_bacapp_bad_length,
                                 "Wrong length indicated. Expected 1, got %u", lvt);
         return offset+tag_len+lvt;
     }
@@ -7331,7 +7381,6 @@ fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
     tvbuff_t   *next_tvb;
     guint       vendor_identifier = 0;
     guint       service_number = 0;
@@ -7346,7 +7395,7 @@ fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
     if (dissector_try_uint(bacapp_dissector_table,
         vendor_identifier, next_tvb, pinfo, tree)) {
         /* we parsed it so skip over length and we are done */
-        offset += tvb_length(next_tvb);
+        offset += tvb_reported_length(next_tvb);
         return offset;
     }
 
@@ -7376,13 +7425,13 @@ fConfirmedPrivateTransferRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
             break;
         case 2: /*serviceParameters */
             if (tag_is_opening(tag_info)) {
-                tt = proto_tree_add_text(subtree, tvb, offset, 1, "service Parameters");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
+                        ett_bacapp_value, NULL, "service Parameters");
                 propertyIdentifier = -1;
                 offset = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         default:
             return offset;
@@ -7412,11 +7461,9 @@ fLifeSafetyOperationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     if (label != NULL) {
-        tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", label);
-        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, label);
     }
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
@@ -7646,12 +7693,11 @@ fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gui
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
-    tt = proto_tree_add_text(subtree, tvb, offset, 0, "notification parameters (%d) %s",
+    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
+        ett_bacapp_value, NULL, "notification parameters (%d) %s",
         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
-    subtree = proto_item_add_subtree(tt, ett_bacapp_value);
     /* Opening tag for parameter choice */
     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
@@ -8011,8 +8057,49 @@ fNotificationParameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gui
         }
         break;
     case 17: /* change-of-characterstring */
+        while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
+            lastoffset = offset;
+            switch (fTagNo(tvb, offset)) {
+            case 0:
+                 /* changed-value (CharacterString) */
+                offset  = fCharacterString(tvb, pinfo, subtree, offset, "changed-value: ");
+                break;
+            case 1:
+                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
+                    "status-flags: ", BACnetStatusFlags);
+                break;
+            case 2:
+                /* alarm-value (CharacterString) */
+                offset  = fCharacterString(tvb, pinfo, subtree, offset, "alarm-value: ");
+                lastoffset = offset;
+                break;
+            default:
+                break;
+            }
+            if (offset == lastoffset) break;     /* nothing happened, exit loop */
+        }
         break;
     case 18: /* change-of-status-flags */
+        while (tvb_reported_length_remaining(tvb, offset) > 0) {
+            /* exit loop if nothing happens inside */
+            lastoffset = offset;
+            switch (fTagNo(tvb, offset)) {
+            case 0:
+                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
+                offset = fApplicationTypesEnumerated(tvb, pinfo, subtree, offset,
+                    "present-value: ", BACnetStatusFlags);
+                offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
+                break;
+            case 1:
+                offset = fBitStringTagVS(tvb, pinfo, subtree, offset,
+                    "referenced-flags: ", BACnetStatusFlags);
+                lastoffset = offset;
+                break;
+            default:
+                break;
+            }
+            if (offset == lastoffset) break;     /* nothing happened, exit loop */
+        }
         break;
         /* todo: add new parameters here ... */
     default:
@@ -8033,12 +8120,12 @@ fEventParameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
-    tt = proto_tree_add_text(subtree, tvb, offset, 0, "event parameters (%d) %s",
+    subtree = proto_tree_add_subtree_format(subtree, tvb, offset, 0,
+        ett_bacapp_value, NULL, "event parameters (%d) %s",
         tag_no, val_to_str_const(tag_no, BACnetEventType, "invalid type"));
-    subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+
     /* Opening tag for parameter choice */
     offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
 
@@ -8476,7 +8563,6 @@ fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
         lastoffset = offset;
@@ -8494,8 +8580,7 @@ fEventLogRecord(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offse
                 offset = fBitStringTagVS(tvb, pinfo, tree, offset, "log status:", BACnetLogStatus);
                 break;
             case 1: /* todo: move this to new method fConfirmedEventNotificationRequestTag... */
-                tt = proto_tree_add_text(tree, tvb, offset, 1, "notification: ");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "notification: ");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fConfirmedEventNotificationRequest(tvb, pinfo, subtree, offset);
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
@@ -8758,7 +8843,6 @@ fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree    = tree;
-    proto_item *tt;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
         lastoffset = offset;
@@ -8784,13 +8868,12 @@ fConfirmedCOVNotificationRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
             break;
         case 4: /* List of Values */
             if (tag_is_opening(tag_info)) {
-                tt = proto_tree_add_text(subtree, tvb, offset, 1, "list of Values");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "list of Values");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         default:
             return offset;
@@ -8947,7 +9030,6 @@ flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree* subtree = tree;
-    proto_item* ti = 0;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
         lastoffset = offset;
@@ -8969,10 +9051,7 @@ flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint
                 "acknowledged Transitions: ", BACnetEventTransitionBits);
             break;
         case 3: /* eventTimeStamps */
-            ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventTimeStamps");
-            if (ti) {
-                subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-            }
+            subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventTimeStamps");
             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-OFFNORMAL timestamp: ");
             offset  = fTimeStamp(tvb, pinfo, subtree, offset, "TO-FAULT timestamp: ");
@@ -8988,10 +9067,7 @@ flistOfEventSummaries(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint
                 "event Enable: ", BACnetEventTransitionBits);
             break;
         case 6: /* eventPriorities */
-            ti = proto_tree_add_text(tree, tvb, offset, lvt, "eventPriorities");
-            if (ti) {
-                subtree = proto_item_add_subtree(ti, ett_bacapp_tag);
-            }
+            subtree = proto_tree_add_subtree(tree, tvb, offset, lvt, ett_bacapp_tag, NULL, "eventPriorities");
             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-OFFNORMAL Priority: ");
             offset  = fUnsignedTag(tvb, pinfo, subtree, offset, "TO-FAULT Priority: ");
@@ -9060,7 +9136,6 @@ fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree    = tree;
-    proto_item *tt;
 
     col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
 
@@ -9079,13 +9154,12 @@ fAddListElementRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
             break;
         case 3: /* listOfElements */
             if (tag_is_opening(tag_info)) {
-                tt = proto_tree_add_text(subtree, tvb, offset, 1, "listOfElements");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfElements");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         default:
             return offset;
@@ -9376,9 +9450,9 @@ fWriteAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree
             if (tag_is_opening(tag_info)) {
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         default:
             return offset;
@@ -9569,23 +9643,15 @@ fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offs
 {
     guint8 tag_no, tag_info;
     guint32 lvt;
-    guint lastoffset = 0, len;
-    gboolean closing_found = FALSE;  /* tracks when we are done decoding the fSpecialEvent entries */
+    guint lastoffset = 0;
 
     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 SEQUENCE of SpecialEvents if we spot a closing tag */
+        fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
+        /* quit loop if we spot an un-matched closing tag */
         if (tag_is_closing(tag_info)) {
-            /* if we find 2 closing tags in succession we need to exit without incrementing the offset again */
-            /* This handles the special case where we have a special event entry in an RPM-ACK msg           */
-            if ( closing_found == TRUE )
-                break;
-            offset += len;
-            closing_found = TRUE;
-            continue;
+            break;
         }
-
         switch (tag_no) {
         case 0: /* calendarEntry */
             if (tag_is_opening(tag_info)) {
@@ -9602,9 +9668,9 @@ fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offs
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fTimeValue(tvb, pinfo, subtree, offset);
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         case 3: /* eventPriority */
             offset = fUnsignedTag(tvb, pinfo, subtree, offset, "event priority: ");
@@ -9612,7 +9678,6 @@ fSpecialEvent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, guint offs
         default:
             return offset;
         }
-        closing_found = FALSE; /* reset our closing tag status, we processed another open tag */
         if (offset == lastoffset) break;     /* nothing happened, exit loop */
     }
     return offset;
@@ -9683,9 +9748,9 @@ fObjectSelectionCriteria(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree,
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fSelectionCriteria(tvb, pinfo, subtree, offset);
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         default:
             return offset;
@@ -9732,7 +9797,6 @@ fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gu
     guint       lastoffset = 0;
     guint8      tag_no, tag_info;
     guint32     lvt;
-    proto_item *tt;
     proto_tree *subtree = tree;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
@@ -9744,8 +9808,7 @@ fReadAccessSpecification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gu
             break;
         case 1: /* listOfPropertyReferences */
             if (tag_is_opening(tag_info)) {
-                tt      = proto_tree_add_text(subtree, tvb, offset, 1, "listOfPropertyReferences");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfPropertyReferences");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fBACnetPropertyReference(tvb, pinfo, subtree, offset, 1);
             } else if (tag_is_closing(tag_info)) {
@@ -9773,7 +9836,6 @@ fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
     guint8      tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     while (tvb_reported_length_remaining(tvb, offset) > 0) {  /* exit loop if nothing happens inside */
         lastoffset = offset;
@@ -9791,26 +9853,24 @@ fReadAccessResult(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
             break;
         case 1: /* list of Results */
             if (tag_is_opening(tag_info)) {
-                tt = proto_tree_add_text(tree, tvb, offset, 1, "listOfResults");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL, "listOfResults");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         case 2: /* propertyIdentifier */
             offset = fPropertyIdentifierValue(tvb, pinfo, subtree, offset, 2);
             break;
         case 5: /* propertyAccessError */
             if (tag_is_opening(tag_info)) {
-                tt      = proto_tree_add_text(subtree, tvb, offset, 1, "propertyAccessError");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "propertyAccessError");
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 /* Error Code follows */
                 offset  = fError(tvb, pinfo, subtree, offset);
-                break;
+            } else {
+                expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
             }
-            FAULT;
             break;
         default:
             return offset;
@@ -9858,9 +9918,9 @@ fCreateObjectRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *subtree, gui
             case 1: /* propertyValue */
                 if (tag_is_opening(tag_info)) {
                     offset = fBACnetPropertyValue(tvb, pinfo, subtree, offset);
-                    break;
+                } else {
+                    expert_add_info(pinfo, subtree, &ei_bacapp_bad_tag);
                 }
-                FAULT;
                 break;
             default:
                 break;
@@ -9884,7 +9944,6 @@ fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     offset = fBACnetObjectPropertyReference(tvb, pinfo, subtree, offset);
 
@@ -9892,8 +9951,8 @@ fReadRangeRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint off
         /* optional range choice */
         fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
         if (tag_is_opening(tag_info)) {
-            tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
-            subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+            subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
+                val_to_str_const(tag_no, BACnetReadRangeOptions, "unknown range option"));
             offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
             switch (tag_no) {
             case 3: /* range byPosition */
@@ -9925,7 +9984,6 @@ fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     /* set the optional global properties to indicate not-used */
     propertyArrayIndex = -1;
@@ -9942,8 +10000,7 @@ fReadRangeAck(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
     if (tag_is_opening(tag_info)) {
         col_set_writable(pinfo->cinfo, FALSE); /* don't set all infos into INFO column */
-        tt = proto_tree_add_text(subtree, tvb, offset, 1, "itemData");
-        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL, "itemData");
         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
         offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
@@ -9962,14 +10019,13 @@ fAccessMethod(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset)
     guint       lastoffset = 0;
     guint32     lvt;
     guint8      tag_no, tag_info;
-    proto_item* tt;
     proto_tree* subtree = NULL;
 
     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
 
     if (tag_is_opening(tag_info)) {
-        tt = proto_tree_add_text(tree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
-        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+        subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_bacapp_value, NULL,
+            val_to_str_const(tag_no, BACnetFileAccessOption, "invalid access method"));
         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "invalid option"));
         offset  = fApplicationTypes(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileWriteInfo, "unknown option"));
@@ -9999,15 +10055,14 @@ fAtomicReadFileRequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
     guint8      tag_no, tag_info;
     guint32     lvt;
     proto_tree *subtree = tree;
-    proto_item *tt;
 
     offset = fObjectIdentifier(tvb, pinfo, tree, offset);
 
     fTagHeader(tvb, pinfo, offset, &tag_no, &tag_info, &lvt);
 
     if (tag_is_opening(tag_info)) {
-        tt = proto_tree_add_text(subtree, tvb, offset, 1, "%s", val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
-        subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+        subtree = proto_tree_add_subtree(subtree, tvb, offset, 1, ett_bacapp_value, NULL,
+                        val_to_str_const(tag_no, BACnetFileAccessOption, "unknown access method"));
         offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
         offset  = fSignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileStartOption, "unknown option"));
         offset  = fUnsignedTag(tvb, pinfo, subtree, offset, val_to_str_const(tag_no, BACnetFileRequestCount, "unknown option"));
@@ -10485,7 +10540,6 @@ fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr
     guint8      tag_no            = 0, tag_info = 0;
     guint32     lvt               = 0;
     proto_tree *subtree           = tree;
-    proto_item *tt;
 
     guint       vendor_identifier = 0;
     guint       service_number    = 0;
@@ -10513,9 +10567,8 @@ fConfirmedPrivateTransferError(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr
             break;
         case 3: /* errorParameters */
             if (tag_is_opening(tag_info)) {
-                tt = proto_tree_add_text(subtree, tvb, offset, 1,
-                    "error Parameters");
-                subtree = proto_item_add_subtree(tt, ett_bacapp_value);
+                subtree = proto_tree_add_subtree(subtree, tvb, offset, 1,
+                    ett_bacapp_value, NULL, "error Parameters");
                 propertyIdentifier = -1;
                 offset += fTagHeaderTree(tvb, pinfo, subtree, offset, &tag_no, &tag_info, &lvt);
                 offset  = fAbstractSyntaxNType(tvb, pinfo, subtree, offset);
@@ -11021,6 +11074,12 @@ bacapp_init_routine(void)
                           &addresses_reassembly_table_functions);
 }
 
+static void
+bacapp_cleanup_routine(void)
+{
+    reassembly_table_destroy(&msg_reassembly_table);
+}
+
 void
 proto_register_bacapp(void)
 {
@@ -11147,6 +11206,12 @@ proto_register_bacapp(void)
             FT_UINT8, BASE_DEC, VALS(BACnetCharacterSet), 0,
             NULL, HFILL }
         },
+        { &hf_BACnetCodePage,
+          { "Code Page",
+            "bacapp.code_page",
+            FT_UINT16, BASE_DEC, NULL, 0,
+            NULL, HFILL }
+        },
         { &hf_BACnetTagClass,
           { "Tag Class",           "bacapp.tag_class",
             FT_BOOLEAN, 8, TFS(&BACnetTagClass), 0x08, NULL, HFILL }
@@ -11219,6 +11284,7 @@ proto_register_bacapp(void)
 
     static ei_register_info ei[] = {
         { &ei_bacapp_bad_length, { "bacapp.bad_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated", EXPFILL }},
+        { &ei_bacapp_bad_tag, { "bacapp.bad_tag", PI_MALFORMED, PI_ERROR, "Wrong tag found", EXPFILL }},
     };
 
     expert_module_t* expert_bacapp;
@@ -11232,6 +11298,7 @@ proto_register_bacapp(void)
     expert_register_field_array(expert_bacapp, ei, array_length(ei));
     register_dissector("bacapp", dissect_bacapp, proto_bacapp);
     register_init_routine(&bacapp_init_routine);
+    register_cleanup_routine(&bacapp_cleanup_routine);
 
     bacapp_dissector_table = register_dissector_table("bacapp.vendor_identifier",
                                                       "BACapp Vendor Identifier",