From Rob Casey:
[obnox/wireshark/wip.git] / epan / dissectors / packet-dnp.c
index 194fa6b7dd02e254020c7cfbefe1a9a27241da8f..8b4de4dcba5365351f10ca8b1b356ab5508bfc11 100644 (file)
 # include "config.h"
 #endif
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 #include <math.h>
 #include <glib.h>
-#include <time.h>
 
 #include <epan/packet.h>
 #include <epan/prefs.h>
  * Application Layer Decoding based on information available in
  * DNP3 Basic 4 Documentation Set, specifically the document:
  * "DNP V3.00 Application Layer" v0.03 P009-0PD.APP & Technical Bulletins
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * Several command codes were missing, causing the dissector to abort decoding
+ * on valid packets.  Those commands have been added.
+ *
+ * The semantics of Variation 0 have been cleaned up.  Variation 0 is the
+ * "Default Variation".  It is used only in Master -> Slave read commands
+ * to request the data in whatever variation the Slave is configured to use by
+ * default. Decoder strings have been added to the Binary Output and
+ * Analog Output objects (10 and 40) so that group read commands will
+ * decode properly.
+ *
+ * Roy M. Silvernail <roy@rant-central.com> 01/05/2009
+ *
  */
 
 /***************************************************************************/
@@ -81,9 +93,9 @@
 #define DNP3_CTL_DFC    0x10
 #define DNP3_CTL_FUNC   0x0f
 
-#define DNP3_TR_FIR   0x40
-#define DNP3_TR_FIN   0x80
-#define DNP3_TR_SEQ   0x3f
+#define DNP3_TR_FIR     0x40
+#define DNP3_TR_FIN     0x80
+#define DNP3_TR_SEQ     0x3f
 
 #define AL_MAX_CHUNK_SIZE 16
 
 /***************************************************************************/
 /* Application Layer Bit-Masks */
 /***************************************************************************/
+#define DNP3_AL_UNS   0x10
 #define DNP3_AL_CON   0x20
 #define DNP3_AL_FIN   0x40
 #define DNP3_AL_FIR   0x80
-#define DNP3_AL_SEQ   0x1f
+#define DNP3_AL_SEQ   0x0f
 #define DNP3_AL_FUNC  0xff
 
 /***************************************************************************/
 #define AL_FUNC_DISSPMSG   0x15    /* 21  - Disable Spontaneous Msg */
 #define AL_FUNC_ASSIGNCL   0x16    /* 22  - Assign Classes */
 #define AL_FUNC_DELAYMST   0x17    /* 23  - Delay Measurement */
+#define AL_FUNC_RECCT      0x18    /* 24  - Record Current Time */
+#define AL_FUNC_OPENFILE   0x19    /* 25  - Open File */
+#define AL_FUNC_CLOSEFILE  0x1A    /* 26  - Close File */
+#define AL_FUNC_DELETEFILE 0x1B    /* 27  - Delete File */
+#define AL_FUNC_GETFILEINF 0x1C    /* 28  - Get File Info */
+#define AL_FUNC_AUTHFILE   0x1D    /* 29  - Authenticate File */
+#define AL_FUNC_ABORTFILE  0x1E    /* 30  - Abort File */
+#define AL_FUNC_ACTCNF     0x1F    /* 31  - Activate Config */
+#define AL_FUNC_AUTHREQ    0x20    /* 32  - Authentication Request */
+#define AL_FUNC_AUTHERR    0x21    /* 33  - Authentication Error */
 #define AL_FUNC_RESPON     0x81    /* 129 - Response */
 #define AL_FUNC_UNSOLI     0x82    /* 130 - Unsolicited Response */
+#define AL_FUNC_AUTHRESP   0x83    /* 131 - Authentication Response */
 
 /***************************************************************************/
 /* Application Layer Internal Indication (IIN) bits */
 /* Application Layer Data Object Qualifier */
 /***************************************************************************/
 /* Bit-Masks */
-#define AL_OBJQ_INDEX      0x70     /* x111xxxx Masks Index from Qualifier */
-#define AL_OBJQ_CODE       0x0F     /* xxxx1111 Masks Code from Qualifier */
+#define AL_OBJQ_INDEX          0x70     /* x111xxxx Masks Index from Qualifier */
+#define AL_OBJQ_CODE           0x0F     /* xxxx1111 Masks Code from Qualifier */
 
 /* Index Size (3-bits x111xxxx)            */
 /* When Qualifier Code != 11               */
-#define AL_OBJQL_IDX_NI    0x00    /* Objects are Packed with no index */
-#define AL_OBJQL_IDX_1O    0x01    /* Objects are prefixed w/ 1-octet index */
-#define AL_OBJQL_IDX_2O    0x02    /* Objects are prefixed w/ 2-octet index */
-#define AL_OBJQL_IDX_4O    0x03    /* Objects are prefixed w/ 4-octet index */
-#define AL_OBJQL_IDX_1OS   0x04    /* Objects are prefixed w/ 1-octet object size */
-#define AL_OBJQL_IDX_2OS   0x05    /* Objects are prefixed w/ 2-octet object size */
-#define AL_OBJQL_IDX_4OS   0x06    /* Objects are prefixed w/ 4-octet object size */
+#define AL_OBJQL_IDX_NI        0x00    /* Objects are Packed with no index */
+#define AL_OBJQL_IDX_1O        0x01    /* Objects are prefixed w/ 1-octet index */
+#define AL_OBJQL_IDX_2O        0x02    /* Objects are prefixed w/ 2-octet index */
+#define AL_OBJQL_IDX_4O        0x03    /* Objects are prefixed w/ 4-octet index */
+#define AL_OBJQL_IDX_1OS       0x04    /* Objects are prefixed w/ 1-octet object size */
+#define AL_OBJQL_IDX_2OS       0x05    /* Objects are prefixed w/ 2-octet object size */
+#define AL_OBJQL_IDX_4OS       0x06    /* Objects are prefixed w/ 4-octet object size */
 
 /* When Qualifier Code == 11 */
 #define AL_OBJQL_IDX11_1OIS    0x01    /* 1 octet identifier size */
 /* Application Layer Data Object Definitions                               */
 /***************************************************************************/
 /* Binary Input Objects */
-#define AL_OBJ_BI_ALL      0x0100   /* 01 00 Binary Input All Variations */
+#define AL_OBJ_BI_ALL      0x0100   /* 01 00 Binary Input Default Variation */
 #define AL_OBJ_BI_1BIT     0x0101   /* 01 01 Single-bit Binary Input */
 #define AL_OBJ_BI_STAT     0x0102   /* 01 02 Binary Input With Status */
-#define AL_OBJ_BIC_ALL     0x0200   /* 02 00 Binary Input Change All Variations */
+#define AL_OBJ_BIC_ALL     0x0200   /* 02 00 Binary Input Change Default Variation */
 #define AL_OBJ_BIC_NOTIME  0x0201   /* 02 01 Binary Input Change Without Time */
 #define AL_OBJ_BIC_TIME    0x0202   /* 02 02 Binary Input Change With Time */
 #define AL_OBJ_BIC_RTIME   0x0203   /* 02 03 Binary Input Change With Relative Time */
 
 /* Double-bit Input Objects */
-#define AL_OBJ_2BI_ALL     0x0300   /* 03 00 Double-bit Input All Variations */
+#define AL_OBJ_2BI_ALL     0x0300   /* 03 00 Double-bit Input Default Variation */
 #define AL_OBJ_2BI_NF      0x0301   /* 03 01 Double-bit Input No Flags */
 #define AL_OBJ_2BI_STAT    0x0302   /* 03 02 Double-bit Input With Status */
 #define AL_OBJ_2BIC_NOTIME 0x0401   /* 04 01 Double-bit Input Change Without Time */
 
 /***************************************************************************/
 /* Binary Output Objects */
+#define AL_OBJ_BO_ALL      0x0A00   /* 10 00 Binary Output Default Variation */
 #define AL_OBJ_BO          0x0A01   /* 10 01 Binary Output */
 #define AL_OBJ_BO_STAT     0x0A02   /* 10 02 Binary Output Status */
 #define AL_OBJ_CTLOP_BLK   0x0C01   /* 12 01 Control Relay Output Block */
 
 /***************************************************************************/
 /* Counter Objects */
-#define AL_OBJ_CTR_ALL     0x1400   /* 20 00 Binary Counter All Variations */
+#define AL_OBJ_CTR_ALL     0x1400   /* 20 00 Binary Counter Default Variation */
 #define AL_OBJ_CTR_32      0x1401   /* 20 01 32-Bit Binary Counter */
 #define AL_OBJ_CTR_16      0x1402   /* 20 02 16-Bit Binary Counter */
 #define AL_OBJ_DCTR_32     0x1403   /* 20 03 32-Bit Delta Counter */
 #define AL_OBJ_CTR_16NF    0x1406   /* 20 06 16-Bit Binary Counter Without Flag */
 #define AL_OBJ_DCTR_32NF   0x1407   /* 20 07 32-Bit Delta Counter Without Flag */
 #define AL_OBJ_DCTR_16NF   0x1408   /* 20 08 16-Bit Delta Counter Without Flag */
-#define AL_OBJ_FCTR_ALL    0x1500   /* 21 00 Frozen Binary Counter All Variations */
+#define AL_OBJ_FCTR_ALL    0x1500   /* 21 00 Frozen Binary Counter Default Variation */
 #define AL_OBJ_FCTR_32     0x1501   /* 21 01 32-Bit Frozen Counter */
 #define AL_OBJ_FCTR_16     0x1502   /* 21 02 16-Bit Frozen Counter */
 #define AL_OBJ_FDCTR_32    0x1503   /* 21 03 32-Bit Frozen Delta Counter */
 #define AL_OBJ_FCTR_16NF   0x1510   /* 21 10 16-Bit Frozen Counter Without Flag */
 #define AL_OBJ_FDCTR_32NF  0x1511   /* 21 11 32-Bit Frozen Delta Counter Without Flag */
 #define AL_OBJ_FDCTR_16NF  0x1512   /* 21 12 16-Bit Frozen Delta Counter Without Flag */
-#define AL_OBJ_CTRC_ALL    0x1600   /* 22 00 Counter Change Event All Variations */
+#define AL_OBJ_CTRC_ALL    0x1600   /* 22 00 Counter Change Event Default Variation */
 #define AL_OBJ_CTRC_32     0x1601   /* 22 01 32-Bit Counter Change Event w/o Time */
 #define AL_OBJ_CTRC_16     0x1602   /* 22 02 16-Bit Counter Change Event w/o Time */
 #define AL_OBJ_DCTRC_32    0x1603   /* 22 03 32-Bit Delta Counter Change Event w/o Time */
 #define AL_OBJ_CTRC_16T    0x1606   /* 22 06 16-Bit Counter Change Event with Time */
 #define AL_OBJ_DCTRC_32T   0x1607   /* 22 07 32-Bit Delta Counter Change Event with Time */
 #define AL_OBJ_DCTRC_16T   0x1608   /* 22 08 16-Bit Delta Counter Change Event with Time */
-#define AL_OBJ_FCTRC_ALL   0x1700   /* 21 00 Frozen Binary Counter Change Event All Variations */
+#define AL_OBJ_FCTRC_ALL   0x1700   /* 21 00 Frozen Binary Counter Change Event Default Variation */
 #define AL_OBJ_FCTRC_32    0x1701   /* 21 01 32-Bit Frozen Counter Change Event */
 #define AL_OBJ_FCTRC_16    0x1702   /* 21 02 16-Bit Frozen Counter Change Event */
 #define AL_OBJ_FDCTRC_32   0x1703   /* 21 03 32-Bit Frozen Delta Counter Change Event */
 
 /***************************************************************************/
 /* Analog Input Objects */
-#define AL_OBJ_AI_ALL      0x1E00   /* 30 00 Analog Input All Variations */
+#define AL_OBJ_AI_ALL      0x1E00   /* 30 00 Analog Input Default Variation */
 #define AL_OBJ_AI_32       0x1E01   /* 30 01 32-Bit Analog Input */
 #define AL_OBJ_AI_16       0x1E02   /* 30 02 16-Bit Analog Input */
 #define AL_OBJ_AI_32NF     0x1E03   /* 30 03 32-Bit Analog Input Without Flag */
                         /* 0x1F06      31 06 16-Bit Frozen Analog Input Without Flag */
 #define AL_OBJ_AIF_FLT     0x1F07   /* 31 07 32-Bit Frozen Floating Point Input */
 #define AL_OBJ_AIF_DBL     0x1F08   /* 31 08 64-Bit Frozen Floating Point Input */
-#define AL_OBJ_AIC_ALL     0x2000   /* 32 00 Analog Input Change All Variations */
+#define AL_OBJ_AIC_ALL     0x2000   /* 32 00 Analog Input Change Default Variation */
 #define AL_OBJ_AIC_32NT    0x2001   /* 32 01 32-Bit Analog Change Event w/o Time */
 #define AL_OBJ_AIC_16NT    0x2002   /* 32 02 16-Bit Analog Change Event w/o Time */
 #define AL_OBJ_AIC_32T     0x2003   /* 32 03 32-Bit Analog Change Event w/ Time */
 #define AL_OBJ_AIFC_FLTT   0x2107   /* 33 07 32-Bit Floating Point Frozen Change Event w/ Time*/
 #define AL_OBJ_AIFC_DBLT   0x2108   /* 33 08 64-Bit Floating Point Frozen Change Event w/ Time*/
 
-
 /* Analog Input Quality Flags */
 #define AL_OBJ_AI_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
 #define AL_OBJ_AI_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
 #define AL_OBJ_AI_FLAG6    0x0040   /* Reference Check (0=Normal; 1=Error) */
 #define AL_OBJ_AI_FLAG7    0x0080   /* Reserved */
 
+#define AL_OBJ_AIDB_ALL    0x2200   /* 34 00 Analog Input Deadband Default Variation */
+#define AL_OBJ_AIDB_16     0x2201   /* 34 01 16-Bit Analog Input Deadband */
+#define AL_OBJ_AIDB_32     0x2202   /* 34 02 32-Bit Analog Input Deadband */
+#define AL_OBJ_AIDB_FLT    0x2203   /* 34 03 Floating Point Analog Input Deadband */
+
 /***************************************************************************/
 /* Analog Output Objects */
+#define AL_OBJ_AO_ALL      0x2800   /* 40 00 Analog Output Default Variation */
 #define AL_OBJ_AO_32       0x2801   /* 40 01 32-Bit Analog Output Status */
 #define AL_OBJ_AO_16       0x2802   /* 40 02 16-Bit Analog Output Status */
 #define AL_OBJ_AO_FLT      0x2803   /* 40 03 32-Bit Floating Point Output Status */
 
 /***************************************************************************/
 /* Time Objects */
+#define AL_OBJ_TD_ALL      0x3200   /* 50 00 Time and Date Default Variation */
 #define AL_OBJ_TD          0x3201   /* 50 01 Time and Date */
 #define AL_OBJ_TDI         0x3202   /* 50 02 Time and Date w/ Interval */
+#define AL_OBJ_TDR         0x3203   /* 50 03 Last Recorded Time and Date */
 #define AL_OBJ_TDCTO       0x3301   /* 51 01 Time and Date CTO */
 #define AL_OBJ_UTDCTO      0x3302   /* 51 02 Unsynchronized Time and Date CTO */
 #define AL_OBJ_TDELAYC     0x3401   /* 52 01 Time Delay Coarse */
@@ -459,6 +491,7 @@ static int hf_dnp3_al_ctl = -1;
 static int hf_dnp3_al_fir = -1;
 static int hf_dnp3_al_fin = -1;
 static int hf_dnp3_al_con = -1;
+static int hf_dnp3_al_uns = -1;
 static int hf_dnp3_al_seq = -1;
 static int hf_dnp3_al_func = -1;
 /* Added for Application Layer Decoding */
@@ -631,10 +664,22 @@ static const value_string dnp3_al_func_vals[] = {
   { AL_FUNC_DISSPMSG,   "Disable Spontaneous Messages" },
   { AL_FUNC_ASSIGNCL,   "Assign Classes" },
   { AL_FUNC_DELAYMST,   "Delay Measurement" },
+  { AL_FUNC_RECCT,      "Record Current Time" },
+  { AL_FUNC_OPENFILE,   "Open File" },
+  { AL_FUNC_CLOSEFILE,  "Close File" },
+  { AL_FUNC_DELETEFILE, "Delete File" },
+  { AL_FUNC_GETFILEINF, "Get File Info" },
+  { AL_FUNC_AUTHFILE,   "Authenticate File" },
+  { AL_FUNC_ABORTFILE,  "Abort File" },
+  { AL_FUNC_ACTCNF,     "Activate Config" },
+  { AL_FUNC_AUTHREQ,    "Authentication Request" },
+  { AL_FUNC_AUTHERR,    "Authentication Error" },
   { AL_FUNC_RESPON,     "Response" },
   { AL_FUNC_UNSOLI,     "Unsolicited Response" },
+  { AL_FUNC_AUTHRESP,   "Authentication Response" },
   { 0, NULL }
 };
+static value_string_ext dnp3_al_func_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_func_vals);
 
 /* Application Layer Internal Indication (IIN) bit Values */
 static const value_string dnp3_al_iin_vals[] _U_ = {
@@ -665,6 +710,7 @@ static const value_string dnp3_al_objq_index_vals[] = {
   { AL_OBJQL_IDX_4OS,   "4-Octet Object Size" },
   { 0, NULL }
 };
+static value_string_ext dnp3_al_objq_index_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_objq_index_vals);
 
 /* Application Layer Object Qualifier Code Values */
 static const value_string dnp3_al_objq_code_vals[] = {
@@ -678,29 +724,32 @@ static const value_string dnp3_al_objq_code_vals[] = {
   { AL_OBJQL_CODE_SF8,      "8-bit Single Field Quantity" },
   { AL_OBJQL_CODE_SF16,     "16-bit Single Field Quantity" },
   { AL_OBJQL_CODE_SF32,     "32-bit Single Field Quantity" },
+  { 10,                     "Reserved" },
   { AL_OBJQL_CODE_FF,       "Free-format Qualifier" },
   { 0, NULL }
 };
+static value_string_ext dnp3_al_objq_code_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_objq_code_vals);
 
 /* Application Layer Data Object Values */
 static const value_string dnp3_al_obj_vals[] = {
-  { AL_OBJ_BI_ALL,     "Binary Input All Variations (Obj:01, Var:All)" },
+  { AL_OBJ_BI_ALL,     "Binary Input Default Variation (Obj:01, Var:Default)" },
   { AL_OBJ_BI_1BIT,    "Single-Bit Binary Input (Obj:01, Var:01)" },
   { AL_OBJ_BI_STAT,    "Binary Input With Status (Obj:01, Var:02)" },
-  { AL_OBJ_BIC_ALL,    "Binary Input Change All Variations (Obj:02, Var:All)" },
+  { AL_OBJ_BIC_ALL,    "Binary Input Change Default Variation (Obj:02, Var:Default)" },
   { AL_OBJ_BIC_NOTIME, "Binary Input Change Without Time (Obj:02, Var:01)" },
   { AL_OBJ_BIC_TIME,   "Binary Input Change With Time (Obj:02, Var:02)" },
   { AL_OBJ_BIC_RTIME,  "Binary Input Change With Relative Time (Obj:02, Var:03)" },
-  { AL_OBJ_2BI_ALL,    "Double-bit Input All Variations (Obj:03, Var:All)" },
+  { AL_OBJ_2BI_ALL,    "Double-bit Input Default Variation (Obj:03, Var:Default)" },
   { AL_OBJ_2BI_NF,     "Double-bit Input No Flags (Obj:03, Var:01)" },
   { AL_OBJ_2BI_STAT,   "Double-bit Input With Status (Obj:03, Var:02)" },
   { AL_OBJ_2BIC_NOTIME, "Double-bit Input Change Without Time (Obj:04, Var:01)" },
   { AL_OBJ_2BIC_TIME,  "Double-bit Input Change With Time (Obj:04, Var:02)" },
   { AL_OBJ_2BIC_RTIME, "Double-bit Input Change With Relative Time (Obj:04, Var:03)" },
+  { AL_OBJ_BO_ALL,     "Binary Output Default Variation (Obj:10, Var:Default)" },
   { AL_OBJ_BO,         "Binary Output (Obj:10, Var:01)" },
   { AL_OBJ_BO_STAT,    "Binary Output Status (Obj:10, Var:02)" },
   { AL_OBJ_CTLOP_BLK,  "Control Relay Output Block (Obj:12, Var:01)" },
-  { AL_OBJ_CTR_ALL,    "Binary Counter All Variations (Obj:20, Var:All)" },
+  { AL_OBJ_CTR_ALL,    "Binary Counter Default Variation (Obj:20, Var:Default)" },
   { AL_OBJ_CTR_32,     "32-Bit Binary Counter (Obj:20, Var:01)" },
   { AL_OBJ_CTR_16,     "16-Bit Binary Counter (Obj:20, Var:02)" },
   { AL_OBJ_DCTR_32,    "32-Bit Binary Delta Counter (Obj:20, Var:03)" },
@@ -709,7 +758,7 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_CTR_16NF,   "16-Bit Binary Counter Without Flag (Obj:20, Var:06)" },
   { AL_OBJ_DCTR_32NF,  "32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07)" },
   { AL_OBJ_DCTR_16NF,  "16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08)" },
-  { AL_OBJ_FCTR_ALL,   "Frozen Binary Counter All Variations (Obj:21, Var:All)" },
+  { AL_OBJ_FCTR_ALL,   "Frozen Binary Counter Default Variation (Obj:21, Var:Default)" },
   { AL_OBJ_FCTR_32,    "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
   { AL_OBJ_FCTR_16,    "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
   { AL_OBJ_FDCTR_32,   "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
@@ -722,7 +771,7 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_FCTR_16NF,  "16-Bit Frozen Binary Counter Without Flag (Obj:21, Var:06)" },
   { AL_OBJ_FDCTR_32NF, "32-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:07)" },
   { AL_OBJ_FDCTR_16NF, "16-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:08)" },
-  { AL_OBJ_CTRC_ALL,   "Binary Counter Change All Variations (Obj:22, Var:All)" },
+  { AL_OBJ_CTRC_ALL,   "Binary Counter Change Default Variation (Obj:22, Var:Default)" },
   { AL_OBJ_CTRC_32,    "32-Bit Counter Change Event w/o Time (Obj:22, Var:01)" },
   { AL_OBJ_CTRC_16,    "16-Bit Counter Change Event w/o Time (Obj:22, Var:02)" },
   { AL_OBJ_DCTRC_32,   "32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03)" },
@@ -731,7 +780,7 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_CTRC_16T,   "16-Bit Counter Change Event with Time (Obj:22, Var:06)" },
   { AL_OBJ_DCTRC_32T,  "32-Bit Delta Counter Change Event with Time (Obj:22, Var:07)" },
   { AL_OBJ_DCTRC_16T,  "16-Bit Delta Counter Change Event with Time (Obj:22, Var:08)" },
-  { AL_OBJ_FCTRC_ALL,  "Frozen Binary Counter Change All Variations (Obj:23, Var:All)" },
+  { AL_OBJ_FCTRC_ALL,  "Frozen Binary Counter Change Default Variation (Obj:23, Var:Default)" },
   { AL_OBJ_FCTRC_32,   "32-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:01)" },
   { AL_OBJ_FCTRC_16,   "16-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:02)" },
   { AL_OBJ_FDCTRC_32,  "32-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:03)" },
@@ -740,7 +789,7 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_FCTRC_16T,  "16-Bit Frozen Counter Change Event with Time (Obj:23, Var:06)" },
   { AL_OBJ_FDCTRC_32T, "32-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:07)" },
   { AL_OBJ_FDCTRC_16T, "16-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:08)" },
-  { AL_OBJ_AI_ALL,     "Analog Input All Variations (Obj:30, Var:All)" },
+  { AL_OBJ_AI_ALL,     "Analog Input Default Variation (Obj:30, Var:Default)" },
   { AL_OBJ_AI_32,      "32-Bit Analog Input (Obj:30, Var:01)" },
   { AL_OBJ_AI_16,      "16-Bit Analog Input (Obj:30, Var:02)" },
   { AL_OBJ_AI_32NF,    "32-Bit Analog Input Without Flag (Obj:30, Var:03)" },
@@ -749,7 +798,7 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_AI_DBL,     "64-Bit Floating Point Input (Obj:30, Var:06)" },
   { AL_OBJ_AIF_FLT,    "32-Bit Frozen Floating Point Input (Obj:31, Var:07)" },
   { AL_OBJ_AIF_DBL,    "64-Bit Frozen Floating Point Input (Obj:31, Var:08)" },
-  { AL_OBJ_AIC_ALL,    "Analog Input Change All Variations (Obj:32, Var:All)" },
+  { AL_OBJ_AIC_ALL,    "Analog Input Change Default Variation (Obj:32, Var:Default)" },
   { AL_OBJ_AIC_32NT,   "32-Bit Analog Change Event w/o Time (Obj:32, Var:01)" },
   { AL_OBJ_AIC_16NT,   "16-Bit Analog Change Event w/o Time (Obj:32, Var:02)" },
   { AL_OBJ_AIC_32T,    "32-Bit Analog Change Event with Time (Obj:32, Var:03)" },
@@ -762,6 +811,11 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_AIFC_DBLNT, "64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06)" },
   { AL_OBJ_AIFC_FLTT,  "32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07)" },
   { AL_OBJ_AIFC_DBLT,  "64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08)" },
+  { AL_OBJ_AIDB_ALL,   "Analog Input Deadband Default Variation (Obj:34, Var:Default)" },
+  { AL_OBJ_AIDB_16,    "16-Bit Analog Input Deadband (Obj:34, Var:01)" },
+  { AL_OBJ_AIDB_32,    "32-Bit Analog Input Deadband (Obj:34, Var:02)" },
+  { AL_OBJ_AIDB_FLT,   "32-Bit Floating Point Analog Input Deadband (Obj:34, Var:03)" },
+  { AL_OBJ_AO_ALL,     "Analog Output Default Variation (Obj:40, Var:Default)" },
   { AL_OBJ_AO_32,      "32-Bit Analog Output Status (Obj:40, Var:01)" },
   { AL_OBJ_AO_16,      "16-Bit Analog Output Status (Obj:40, Var:02)" },
   { AL_OBJ_AO_FLT,     "32-Bit Floating Point Output Status (Obj:40, Var:03)" },
@@ -770,7 +824,10 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_AO_16OPB,   "16-Bit Analog Output Block (Obj:41, Var:02)" },
   { AL_OBJ_AO_FLTOPB,  "32-Bit Floating Point Output Block (Obj:41, Var:03)" },
   { AL_OBJ_AO_DBLOPB,  "64-Bit Floating Point Output Block (Obj:41, Var:04)" },
+  { AL_OBJ_TD_ALL,     "Time and Date Default Variations (Obj:50, Var:Default)" },
   { AL_OBJ_TD,         "Time and Date (Obj:50, Var:01)" },
+  { AL_OBJ_TDI,        "Time and Date w/Interval (Obj:50, Var:02)" },
+  { AL_OBJ_TDR,        "Last Recorded Time and Date (Obj:50, Var:03)" },
   { AL_OBJ_TDCTO,      "Time and Date CTO (Obj:51, Var:01)" },
   { AL_OBJ_TDELAYF,    "Time Delay - Fine (Obj:52, Var:02)" },
   { AL_OBJ_CLASS0,     "Class 0 Data (Obj:60, Var:01)" },
@@ -781,6 +838,7 @@ static const value_string dnp3_al_obj_vals[] = {
   { AL_OBJ_OCT,        "Octet String (Obj:110)" },
   { 0, NULL }
 };
+static value_string_ext dnp3_al_obj_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_obj_vals);
 
 /* Application Layer Control Code 'Code' Values */
 static const value_string dnp3_al_ctlc_code_vals[] = {
@@ -822,6 +880,7 @@ static const value_string dnp3_al_ctl_status_vals[] = {
   { AL_OBJCTL_STAT10,    "Req. Not Accepted; Local automation proc active" },
   { 0, NULL }
 };
+static value_string_ext dnp3_al_ctl_status_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_ctl_status_vals);
 
 /* Application Layer Binary Input Quality Flag Values */
 static const value_string dnp3_al_biflag_vals[] _U_ = {
@@ -891,6 +950,7 @@ static int   hf_dnp3_fragment_multiple_tails = -1;
 static int   hf_dnp3_fragment_too_long_fragment = -1;
 static int   hf_dnp3_fragment_error = -1;
 static int   hf_dnp3_fragment_reassembled_in = -1;
+static int   hf_dnp3_fragment_reassembled_length = -1;
 static gint ett_dnp3_fragment  = -1;
 static gint ett_dnp3_fragments = -1;
 
@@ -905,6 +965,7 @@ static const fragment_items dnp3_frag_items = {
   &hf_dnp3_fragment_too_long_fragment,
   &hf_dnp3_fragment_error,
   &hf_dnp3_fragment_reassembled_in,
+  &hf_dnp3_fragment_reassembled_length,
   "DNP 3.0 fragments"
 };
 
@@ -1011,7 +1072,7 @@ add_item_text(proto_item *item, const gchar *text, gboolean comma_needed)
   if (comma_needed) {
     proto_item_append_text(item, ", ");
   }
-  proto_item_append_text(item, text);
+  proto_item_append_text(item, "%s", text);
   return TRUE;
 }
 
@@ -1104,8 +1165,8 @@ dnp3_al_obj_procindex(tvbuff_t *tvb, int offset, guint8 al_objq_index, guint32 *
 static void
 dnp3_append_2item_text(proto_item *item1, proto_item *item2, const gchar *text)
 {
-  proto_item_append_text(item1, text);
-  proto_item_append_text(item2, text);
+  proto_item_append_text(item1, "%s", text);
+  proto_item_append_text(item2, "%s", text);
 }
 
 /*****************************************************************/
@@ -1248,7 +1309,7 @@ static int
 dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *robj_tree, gboolean header_only, guint16 *al_objtype)
 {
 
-  guint8        al_2bit, al_objq, al_objq_index, al_objq_code, al_ptflags, al_ctlobj_code, al_oct_len,
+  guint8        al_2bit, al_objq, al_objq_index, al_objq_code, al_ptflags, al_ctlobj_code, al_oct_len=0,
                 al_ctlobj_code_c, al_ctlobj_code_m, al_ctlobj_code_tc, al_ctlobj_count, al_bi_val, bitindex=0;
   guint16       al_obj, al_val16=0, al_ctlobj_stat, al_relms;
   guint32       al_val32, al_ptaddr=0, al_ctlobj_on, al_ctlobj_off;
@@ -1277,7 +1338,9 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
 
   /* Create Data Objects Detail Tree */
   object_item = proto_tree_add_uint_format(robj_tree, hf_dnp3_al_obj, tvb, offset, 2, al_obj,
-     "Object(s): %s (0x%04x)", val_to_str(al_obj, dnp3_al_obj_vals, "Unknown Object - Abort Decoding..."), al_obj);
+                                           "Object(s): %s (0x%04x)",
+                                           val_to_str_ext_const(al_obj, &dnp3_al_obj_vals_ext, "Unknown Object - Abort Decoding..."),
+                                           al_obj);
   object_tree = proto_item_add_subtree(object_item, ett_dnp3_al_obj);
 
   offset += 2;
@@ -1289,8 +1352,8 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
   al_objq_code = al_objq & AL_OBJQ_CODE;
 
   qualifier_item = proto_tree_add_text(object_tree, tvb, offset, 1, "Qualifier Field, Prefix: %s, Code: %s",
-    val_to_str(al_objq_index, dnp3_al_objq_index_vals, "Unknown Index Type"),
-    val_to_str(al_objq_code, dnp3_al_objq_code_vals, "Unknown Code Type"));
+    val_to_str_ext_const(al_objq_index, &dnp3_al_objq_index_vals_ext, "Unknown Index Type"),
+    val_to_str_ext_const(al_objq_code, &dnp3_al_objq_code_vals_ext, "Unknown Code Type"));
   qualifier_tree = proto_item_add_subtree(qualifier_item, ett_dnp3_al_obj_qualifier);
   proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_index, tvb, offset, 1, FALSE);
   proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_code, tvb, offset, 1, FALSE);
@@ -1402,13 +1465,14 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
         switch (al_obj)
         {
 
-          case AL_OBJ_BI_ALL:      /* Binary Input All Var (Obj:01, Var:All) */
-          case AL_OBJ_BIC_ALL:     /* Binary Input Change All Var (Obj:02, Var:All) */
-          case AL_OBJ_2BI_ALL:     /* Double-bit Input All Var (Obj:03, Var:All) */
-          case AL_OBJ_CTR_ALL:     /* Binary Counter All Var (Obj:20, Var:All) */
-          case AL_OBJ_CTRC_ALL:    /* Binary Counter Change All Var (Obj:22 Var:All) */
-          case AL_OBJ_AI_ALL:      /* Analog Input All Var (Obj:30, Var:All) */
-          case AL_OBJ_AIC_ALL:     /* Analog Input Change All Var (Obj:32 Var:All) */
+          case AL_OBJ_BI_ALL:      /* Binary Input Default Variation (Obj:01, Var:Default) */
+          case AL_OBJ_BIC_ALL:     /* Binary Input Change Default Variation (Obj:02, Var:Default) */
+          case AL_OBJ_2BI_ALL:     /* Double-bit Input Default Variation (Obj:03, Var:Default) */
+          case AL_OBJ_CTR_ALL:     /* Binary Counter Default Variation (Obj:20, Var:Default) */
+          case AL_OBJ_CTRC_ALL:    /* Binary Counter Change Default Variation (Obj:22 Var:Default) */
+          case AL_OBJ_AI_ALL:      /* Analog Input Default Variation (Obj:30, Var:Default) */
+          case AL_OBJ_AIC_ALL:     /* Analog Input Change Default Variation (Obj:32 Var:Default) */
+          case AL_OBJ_AIDB_ALL:    /* Analog Input Deadband Default Variation (Obj:34, Var:Default) */
 
             offset = data_pos;
             break;
@@ -1519,7 +1583,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
             data_pos += 6;
 
             al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
-            proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime));
+            proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime, ABSOLUTE_TIME_LOCAL, TRUE));
             proto_item_set_len(point_item, data_pos - offset);
 
             offset = data_pos;
@@ -1539,7 +1603,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
             data_pos += 6;
 
             al_2bit = (al_ptflags >> 6) & 3; /* bit shift 11xxxxxx -> 00000011 */
-            proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_2bit, abs_time_to_str(&al_abstime));
+            proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_2bit, abs_time_to_str(&al_abstime, ABSOLUTE_TIME_LOCAL, TRUE));
             proto_item_set_len(point_item, data_pos - offset);
 
             offset = data_pos;
@@ -1562,7 +1626,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
             data_pos += 2;
 
             al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
-            proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime));
+            proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime, ABSOLUTE_TIME_LOCAL, TRUE));
             proto_item_set_len(point_item, data_pos - offset);
 
             offset = data_pos;
@@ -1579,11 +1643,11 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
 
             /* Bit-Mask xx11xxxx for Control Code Misc Values */
             al_ctlobj_code_m = al_ctlobj_code & AL_OBJCTLC_MISC;
-            ctl_misc_str = val_to_str(al_ctlobj_code_m, dnp3_al_ctlc_misc_vals, "");
+            ctl_misc_str = val_to_str_const(al_ctlobj_code_m, dnp3_al_ctlc_misc_vals, "");
 
             /* Bit-Mask 11xxxxxx for Control Code 'Trip/Close' */
             al_ctlobj_code_tc = al_ctlobj_code & AL_OBJCTLC_TC;
-            ctl_tc_str = val_to_str(al_ctlobj_code_tc, dnp3_al_ctlc_tc_vals, "");
+            ctl_tc_str = val_to_str_const(al_ctlobj_code_tc, dnp3_al_ctlc_tc_vals, "");
 
             /* Get "Count" Field */
             al_ctlobj_count = tvb_get_guint8(tvb, data_pos);
@@ -1599,7 +1663,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
 
             al_ctlobj_stat = tvb_get_guint8(tvb, data_pos);
             proto_tree_add_item(point_item, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, TRUE);
-            ctl_status_str = val_to_str(al_ctlobj_stat, dnp3_al_ctl_status_vals, "Invalid Status (0x%02x)");
+            ctl_status_str = val_to_str_ext(al_ctlobj_stat, &dnp3_al_ctl_status_vals_ext, "Invalid Status (0x%02x)");
             data_pos += 1;
 
             proto_item_append_text(point_item, ", Control Code: [%s,%s,%s (0x%02x)]",
@@ -1641,7 +1705,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
                 break;
               case AL_OBJ_AO_DBLOPB:
                 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
-                proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
+                proto_item_append_text(point_item, ", Value: %g", al_valdbl);
                 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, TRUE);
                 data_pos += 8;
                 break;
@@ -1649,7 +1713,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
 
             /* Get control status */
             al_ctlobj_stat = tvb_get_guint8(tvb, data_pos);
-            ctl_status_str = val_to_str(al_ctlobj_stat, dnp3_al_ctl_status_vals, "Invalid Status (0x%02x)");
+            ctl_status_str = val_to_str_ext(al_ctlobj_stat, &dnp3_al_ctl_status_vals_ext, "Invalid Status (0x%02x)");
             proto_item_append_text(point_item, " [Status: %s (0x%02x)]", ctl_status_str, al_ctlobj_stat);
             proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, TRUE);
             data_pos += 1;
@@ -1786,7 +1850,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_FDCTRC_32T:
               case AL_OBJ_FDCTRC_16T:
                 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
-                proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime));
+                proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime, ABSOLUTE_TIME_LOCAL, TRUE));
                 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
                 data_pos += 6;
                 break;
@@ -1817,12 +1881,18 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
           case AL_OBJ_AIFC_DBLNT:   /* 64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06) */
           case AL_OBJ_AIFC_FLTT:    /* 32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07) */
           case AL_OBJ_AIFC_DBLT:    /* 64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08) */
+          case AL_OBJ_AIDB_16:      /* 16-Bit Analog Input Deadband (Obj:34, Var:01) */
+          case AL_OBJ_AIDB_32:      /* 32-Bit Analog Input Deadband (Obj:34, Var:02) */
+          case AL_OBJ_AIDB_FLT:     /* 32-Bit Floating Point Analog Input Deadband (Obj:34, Var:03) */
 
             /* Get Point Flags for those types that have them */
             switch (al_obj)
             {
               case AL_OBJ_AI_32NF:
               case AL_OBJ_AI_16NF:
+              case AL_OBJ_AIDB_16:
+              case AL_OBJ_AIDB_32:
+              case AL_OBJ_AIDB_FLT:
                 break;
 
               default:
@@ -1838,6 +1908,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_AI_32NF:
               case AL_OBJ_AIC_32NT:
               case AL_OBJ_AIC_32T:
+              case AL_OBJ_AIDB_32:
 
                 al_val32 = tvb_get_letohl(tvb, data_pos);
                 proto_item_append_text(point_item, ", Value: %u", al_val32);
@@ -1849,6 +1920,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_AI_16NF:
               case AL_OBJ_AIC_16NT:
               case AL_OBJ_AIC_16T:
+              case AL_OBJ_AIDB_16:
 
                 al_val16 = tvb_get_letohs(tvb, data_pos);
                 proto_item_append_text(point_item, ", Value: %u", al_val16);
@@ -1862,6 +1934,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_AIC_FLTT:
               case AL_OBJ_AIFC_FLTNT:
               case AL_OBJ_AIFC_FLTT:
+              case AL_OBJ_AIDB_FLT:
 
                 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
                 proto_item_append_text(point_item, ", Value: %g", al_valflt);
@@ -1877,7 +1950,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_AIFC_DBLT:
 
                 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
-                proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
+                proto_item_append_text(point_item, ", Value: %g", al_valdbl);
                 proto_tree_add_item(point_tree, hf_dnp3_al_anadbl, tvb, data_pos, 8, TRUE);
                 data_pos += 8;
                 break;
@@ -1893,7 +1966,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_AIFC_FLTT:
               case AL_OBJ_AIFC_DBLT:
                 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
-                proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime));
+                proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime, ABSOLUTE_TIME_LOCAL, TRUE));
                 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
                 data_pos += 6;
                 break;
@@ -1943,7 +2016,7 @@ dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree
               case AL_OBJ_AO_DBL:     /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
 
                 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
-                proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
+                proto_item_append_text(point_item, ", Value: %g", al_valdbl);
                 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, TRUE);
                 data_pos += 8;
                 break;
@@ -2038,7 +2111,7 @@ dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
   guint8        al_ctl, al_seq, al_func, al_class = 0, i;
   guint16       bytes, obj_type;
-  gboolean      al_fir, al_fin, al_con;
+  gboolean      al_fir, al_fin, al_con, al_uns;
   guint         data_len = 0, offset = 0;
   proto_item   *ti = NULL, *tc, *t_robj;
   proto_tree   *al_tree = NULL, *field_tree = NULL, *robj_tree = NULL;
@@ -2052,8 +2125,9 @@ dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   al_fir = al_ctl & DNP3_AL_FIR;
   al_fin = al_ctl & DNP3_AL_FIN;
   al_con = al_ctl & DNP3_AL_CON;
+  al_uns = al_ctl & DNP3_AL_UNS;
   al_func = tvb_get_guint8(tvb, (offset+1));
-  func_code_str = val_to_str(al_func, dnp3_al_func_vals, "Unknown function (0x%02x)");
+  func_code_str = val_to_str_ext(al_func, &dnp3_al_func_vals_ext, "Unknown function (0x%02x)");
 
   if (check_col(pinfo->cinfo, COL_INFO))
     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", func_code_str);
@@ -2075,22 +2149,26 @@ dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   if (al_ctl & DNP3_AL_FIR)  proto_item_append_text(tc, "FIR, ");
   if (al_ctl & DNP3_AL_FIN)  proto_item_append_text(tc, "FIN, ");
   if (al_ctl & DNP3_AL_CON)  proto_item_append_text(tc, "CON, ");
+  if (al_ctl & DNP3_AL_UNS)  proto_item_append_text(tc, "UNS, ");
   proto_item_append_text(tc, "Sequence %u)", al_seq);
 
   field_tree = proto_item_add_subtree(tc, ett_dnp3_al_ctl);
   proto_tree_add_boolean(field_tree, hf_dnp3_al_fir, tvb, offset, 1, al_ctl);
   proto_tree_add_boolean(field_tree, hf_dnp3_al_fin, tvb, offset, 1, al_ctl);
   proto_tree_add_boolean(field_tree, hf_dnp3_al_con, tvb, offset, 1, al_ctl);
+  proto_tree_add_boolean(field_tree, hf_dnp3_al_uns, tvb, offset, 1, al_ctl);
   proto_tree_add_item(field_tree, hf_dnp3_al_seq, tvb, offset, 1, FALSE);
   offset += 1;
 
+#if 0
   /* If this packet is NOT the final Application Layer Message, exit and continue
-  processing the remaining data in the fragment.
+     processing the remaining data in the fragment. */
   if (!al_fin)
   {
   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Buffering User Data Until Final Frame is Received..");
   return 1;
-  } */
+  }
+#endif
 
   /* Application Layer Function Code Byte  */
   proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
@@ -2269,11 +2347,9 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
 
 /* Make entries in Protocol column and Info column on summary display */
-  if (check_col(pinfo->cinfo, COL_PROTOCOL))
-    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
+  col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
 
-  if (check_col(pinfo->cinfo, COL_INFO))
-    col_clear(pinfo->cinfo, COL_INFO);
+  col_clear(pinfo->cinfo, COL_INFO);
 
   /* Skip "0x0564" header bytes */
   temp_offset += 2;
@@ -2317,7 +2393,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tdl, "RES, ");
     if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tdl, "DFC, ");
   }
-  proto_item_append_text(tdl, func_code_str);
+  proto_item_append_text(tdl, "%s", func_code_str);
   dl_tree = proto_item_add_subtree(tdl, ett_dnp3_dl);
 
   /* start bytes */
@@ -2419,7 +2495,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     /* XXX - check for dl_len <= 5 */
     data_len = dl_len - 5;
-    tmp = ep_alloc(data_len);
+    tmp = g_malloc(data_len);
     tmp_ptr = tmp;
     i = 0;
     data_offset = 1;  /* skip the transport layer byte when assembling chunks */
@@ -2460,8 +2536,8 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     /* if all crc OK, set up new tvb */
     if (crc_OK)
     {
-      al_tvb = tvb_new_real_data(tmp, tmp_ptr-tmp, tmp_ptr-tmp);
-      tvb_set_child_real_data_tvbuff(tvb, al_tvb);
+      al_tvb = tvb_new_child_real_data(tvb, tmp, (guint) (tmp_ptr-tmp), (gint) (tmp_ptr-tmp));
+      tvb_set_free_cb(al_tvb, g_free);
 
       /* Check for fragmented packet */
       save_fragmented = pinfo->fragmented;
@@ -2471,14 +2547,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         pinfo->fragmented = TRUE;
 
         /* Look up the conversation to get the fragment reassembly id */
-        conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-          pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
-
-        if (conversation == NULL) {
-          /* No conversation yet, so make one */
-          conversation = conversation_new(pinfo->fd->num,  &pinfo->src, &pinfo->dst, pinfo->ptype,
-            pinfo->srcport, pinfo->destport, 0);
-        }
+        conversation = find_or_create_conversation(pinfo);
 
         conv_data_ptr = (dnp3_conv_t*)conversation_get_proto_data(conversation, proto_dnp3);
 
@@ -2512,8 +2581,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         if (next_tvb) { /* Reassembled */
           /* We have the complete payload */
           if (check_col (pinfo->cinfo, COL_INFO))
-            col_add_str (pinfo->cinfo, COL_INFO,
-                "Reassembled Application Layer");
+            col_set_str(pinfo->cinfo, COL_INFO, "Reassembled Application Layer");
             col_set_fence(pinfo->cinfo, COL_INFO);
         }
         else
@@ -2531,8 +2599,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         /* No reassembly required */
         next_tvb = al_tvb;
         add_new_data_source(pinfo, next_tvb, "DNP 3.0 Application Layer message");
-        if (check_col (pinfo->cinfo, COL_INFO))
-          col_clear (pinfo->cinfo, COL_INFO);
+        col_clear(pinfo->cinfo, COL_INFO);
       }
       pinfo->fragmented = save_fragmented;
     }
@@ -2540,6 +2607,7 @@ dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     {
       /* CRC error - throw away the data. */
       next_tvb = NULL;
+      g_free(tmp);
       proto_tree_add_text(dnp3_tree, tvb, 11, -1, "CRC failed, %u chunks", i);
     }
 
@@ -2599,11 +2667,6 @@ dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   return length;
 }
 
-static void
-dnp3_init(void)
-{
-}
-
 static void
 al_defragment_init(void)
 {
@@ -2620,7 +2683,7 @@ proto_register_dnp3(void)
 /* Setup list of header fields */
   static hf_register_info hf[] = {
     { &hf_dnp3_start,
-    { "Start Bytes", "dnp3.start", FT_UINT16, BASE_HEX, NULL, 0x0, "Start Bytes", HFILL }},
+    { "Start Bytes", "dnp3.start", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp3_len,
     { "Length", "dnp3.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Frame Data Length", HFILL }},
@@ -2637,19 +2700,19 @@ proto_register_dnp3(void)
       VALS(dnp3_ctl_func_sec_vals), DNP3_CTL_FUNC, "Frame Control Function Code", HFILL }},
 
     { &hf_dnp3_ctl_dir,
-    { "Direction", "dnp3.ctl.dir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DIR, "", HFILL }},
+    { "Direction", "dnp3.ctl.dir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DIR, NULL, HFILL }},
 
     { &hf_dnp3_ctl_prm,
-    { "Primary", "dnp3.ctl.prm", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_PRM, "", HFILL }},
+    { "Primary", "dnp3.ctl.prm", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_PRM, NULL, HFILL }},
 
     { &hf_dnp3_ctl_fcb,
-    { "Frame Count Bit", "dnp3.ctl.fcb", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCB, "", HFILL }},
+    { "Frame Count Bit", "dnp3.ctl.fcb", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCB, NULL, HFILL }},
 
     { &hf_dnp3_ctl_fcv,
-    { "Frame Count Valid", "dnp3.ctl.fcv", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCV, "", HFILL }},
+    { "Frame Count Valid", "dnp3.ctl.fcv", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCV, NULL, HFILL }},
 
     { &hf_dnp3_ctl_dfc,
-    { "Data Flow Control", "dnp3.ctl.dfc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DFC, "", HFILL }},
+    { "Data Flow Control", "dnp3.ctl.dfc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DFC, NULL, HFILL }},
 
     { &hf_dnp3_dst,
     { "Destination", "dnp3.dst", FT_UINT16, BASE_DEC, NULL, 0x0, "Destination Address", HFILL }},
@@ -2658,19 +2721,19 @@ proto_register_dnp3(void)
     { "Source", "dnp3.src", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Address", HFILL }},
 
     { &hf_dnp_hdr_CRC,
-    { "CRC", "dnp3.hdr.CRC", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+    { "CRC", "dnp3.hdr.CRC", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp_hdr_CRC_bad,
-    { "Bad CRC", "dnp3.hdr.CRC_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+    { "Bad CRC", "dnp3.hdr.CRC_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp3_tr_ctl,
-    { "Transport Control", "dnp3.tr.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Tranport Layer Control Byte", HFILL }},
+    { "Transport Control", "dnp3.tr.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Transport Layer Control Byte", HFILL }},
 
     { &hf_dnp3_tr_fin,
-    { "Final", "dnp3.tr.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIN, "", HFILL }},
+    { "Final", "dnp3.tr.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIN, NULL, HFILL }},
 
     { &hf_dnp3_tr_fir,
-    { "First", "dnp3.tr.fir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIR, "", HFILL }},
+    { "First", "dnp3.tr.fir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIR, NULL, HFILL }},
 
     { &hf_dnp3_tr_seq,
     { "Sequence", "dnp3.tr.seq", FT_UINT8, BASE_DEC, NULL, DNP3_TR_SEQ, "Frame Sequence Number", HFILL }},
@@ -2679,71 +2742,74 @@ proto_register_dnp3(void)
     { "Application Control", "dnp3.al.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Application Layer Control Byte", HFILL }},
 
     { &hf_dnp3_al_fir,
-    { "First", "dnp3.al.fir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIR, "", HFILL }},
+    { "First", "dnp3.al.fir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIR, NULL, HFILL }},
 
     { &hf_dnp3_al_fin,
-    { "Final", "dnp3.al.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIN, "", HFILL }},
+    { "Final", "dnp3.al.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIN, NULL, HFILL }},
 
     { &hf_dnp3_al_con,
-    { "Confirm", "dnp3.al.con", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_CON, "", HFILL }},
+    { "Confirm", "dnp3.al.con", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_CON, NULL, HFILL }},
+
+    { &hf_dnp3_al_uns,
+    { "Unsolicited", "dnp3.al.uns", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_UNS, NULL, HFILL }},
 
     { &hf_dnp3_al_seq,
     { "Sequence", "dnp3.al.seq", FT_UINT8, BASE_DEC, NULL, DNP3_AL_SEQ, "Frame Sequence Number", HFILL }},
 
     { &hf_dnp3_al_func,
-    { "Application Layer Function Code", "dnp3.al.func", FT_UINT8, BASE_DEC,
-      VALS(dnp3_al_func_vals), DNP3_AL_FUNC, "Application Function Code", HFILL }},
+    { "Application Layer Function Code", "dnp3.al.func", FT_UINT8, BASE_DEC|BASE_EXT_STRING,
+      &dnp3_al_func_vals_ext, DNP3_AL_FUNC, "Application Function Code", HFILL }},
 
     { &hf_dnp3_al_iin,
     { "Application Layer IIN bits", "dnp3.al.iin", FT_UINT16, BASE_DEC, NULL, 0x0, "Application Layer IIN", HFILL }},
 
     { &hf_dnp3_al_iin_bmsg,
-    { "Broadcast Msg Rx", "dnp3.al.iin.bmsg", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_BMSG, "", HFILL }},
+    { "Broadcast Msg Rx", "dnp3.al.iin.bmsg", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_BMSG, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_cls1d,
-    { "Class 1 Data Available", "dnp3.al.iin.cls1d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS1D, "", HFILL }},
+    { "Class 1 Data Available", "dnp3.al.iin.cls1d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS1D, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_cls2d,
-    { "Class 2 Data Available", "dnp3.al.iin.cls2d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS2D, "", HFILL }},
+    { "Class 2 Data Available", "dnp3.al.iin.cls2d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS2D, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_cls3d,
-    { "Class 3 Data Available", "dnp3.al.iin.cls3d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS3D, "", HFILL }},
+    { "Class 3 Data Available", "dnp3.al.iin.cls3d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS3D, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_tsr,
-    { "Time Sync Required", "dnp3.al.iin.tsr", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_TSR, "", HFILL }},
+    { "Time Sync Required", "dnp3.al.iin.tsr", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_TSR, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_dol,
-    { "Digital Outputs in Local", "dnp3.al.iin.dol", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DOL, "", HFILL }},
+    { "Digital Outputs in Local", "dnp3.al.iin.dol", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DOL, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_dt,
-    { "Device Trouble", "dnp3.al.iin.dt", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DT, "", HFILL }},
+    { "Device Trouble", "dnp3.al.iin.dt", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DT, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_rst,
-    { "Device Restart", "dnp3.al.iin.rst", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_RST, "", HFILL }},
+    { "Device Restart", "dnp3.al.iin.rst", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_RST, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_obju,
-    { "Requested Objects Unknown", "dnp3.al.iin.obju", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OBJU, "", HFILL }},
+    { "Requested Objects Unknown", "dnp3.al.iin.obju", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OBJU, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_pioor,
-    { "Parameters Invalid or Out of Range", "dnp3.al.iin.pioor", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_PIOOR, "", HFILL }},
+    { "Parameters Invalid or Out of Range", "dnp3.al.iin.pioor", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_PIOOR, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_ebo,
-    { "Event Buffer Overflow", "dnp3.al.iin.ebo", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_EBO, "", HFILL }},
+    { "Event Buffer Overflow", "dnp3.al.iin.ebo", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_EBO, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_oae,
-    { "Operation Already Executing", "dnp3.al.iin.oae", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OAE, "", HFILL }},
+    { "Operation Already Executing", "dnp3.al.iin.oae", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OAE, NULL, HFILL }},
 
     { &hf_dnp3_al_iin_cc,
-    { "Configuration Corrupt", "dnp3.al.iin.cc", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CC, "", HFILL }},
+    { "Configuration Corrupt", "dnp3.al.iin.cc", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CC, NULL, HFILL }},
 
     { &hf_dnp3_al_obj,
-    { "Object", "dnp3.al.obj", FT_UINT16, BASE_HEX, VALS(dnp3_al_obj_vals), 0x0, "Application Layer Object", HFILL }},
+    { "Object", "dnp3.al.obj", FT_UINT16, BASE_HEX|BASE_EXT_STRING, &dnp3_al_obj_vals_ext, 0x0, "Application Layer Object", HFILL }},
 
     { &hf_dnp3_al_objq_index,
-    { "Index Prefix", "dnp3.al.objq.index", FT_UINT8, BASE_DEC, VALS(dnp3_al_objq_index_vals), AL_OBJQ_INDEX, "Object Index Prefixing", HFILL }},
+    { "Index Prefix", "dnp3.al.objq.index", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_objq_index_vals_ext, AL_OBJQ_INDEX, "Object Index Prefixing", HFILL }},
 
     { &hf_dnp3_al_objq_code,
-    { "Qualifier Code", "dnp3.al.objq.code", FT_UINT8, BASE_DEC, VALS(dnp3_al_objq_code_vals), AL_OBJQ_CODE, "Object Qualifier Code", HFILL }},
+    { "Qualifier Code", "dnp3.al.objq.code", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_objq_code_vals_ext, AL_OBJQ_CODE, "Object Qualifier Code", HFILL }},
 
     { &hf_dnp3_al_range_start8,
     { "Start (8 bit)", "dnp3.al.range.start", FT_UINT8, BASE_DEC, NULL, 0x0, "Object Start Index", HFILL }},
@@ -2791,10 +2857,10 @@ proto_register_dnp3(void)
     { "Index (32 bit)", "dnp3.al.index", FT_UINT32, BASE_DEC, NULL, 0x0, "Object Index", HFILL }},
 
     { &hf_dnp3_al_ptnum,
-    { "Object Point Number", "dnp3.al.ptnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Point Number", HFILL }},
+    { "Object Point Number", "dnp3.al.ptnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp3_al_bit,
-    { "Value (bit)", "dnp3.al.bit", FT_BOOLEAN, BASE_NONE, TFS(&tfs_on_off), 0x1, "Digital Value (1 bit)", HFILL }},
+    { "Value (bit)", "dnp3.al.bit", FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x1, "Digital Value (1 bit)", HFILL }},
 
     { &hf_dnp3_al_2bit,
     { "Value (two bit)", "dnp3.al.2bit", FT_UINT8, BASE_DEC, NULL, 0x0, "Digital Value (2 bit)", HFILL }},
@@ -2806,22 +2872,22 @@ proto_register_dnp3(void)
     { "Value (32 bit)", "dnp3.al.ana", FT_UINT32, BASE_DEC, NULL, 0x0, "Analog Value (32 bit)", HFILL }},
 
     { &hf_dnp3_al_anaflt,
-    { "Value (float)", "dnp3.al.ana", FT_FLOAT, BASE_DEC, NULL, 0x0, "Analog Value (float)", HFILL }},
+    { "Value (float)", "dnp3.al.ana", FT_FLOAT, BASE_NONE, NULL, 0x0, "Analog Value (float)", HFILL }},
 
     { &hf_dnp3_al_anadbl,
-    { "Value (double)", "dnp3.al.ana", FT_DOUBLE, BASE_DEC, NULL, 0x0, "Analog Value (double)", HFILL }},
+    { "Value (double)", "dnp3.al.ana", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Analog Value (double)", HFILL }},
 
     { &hf_dnp3_al_anaout16,
-    { "Output Value (16 bit)", "dnp3.al.anaout", FT_UINT16, BASE_DEC, NULL, 0x0, "Output Value (16 bit)", HFILL }},
+    { "Output Value (16 bit)", "dnp3.al.anaout", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp3_al_anaout32,
-    { "Output Value (32 bit)", "dnp3.al.anaout", FT_UINT32, BASE_DEC, NULL, 0x0, "Output Value (32 bit)", HFILL }},
+    { "Output Value (32 bit)", "dnp3.al.anaout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp3_al_anaoutflt,
-    { "Output Value (float)", "dnp3.al.anaout", FT_FLOAT, BASE_DEC, NULL, 0x0, "Output Value (float)", HFILL }},
+    { "Output Value (float)", "dnp3.al.anaout", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }},
 
     { &hf_dnp3_al_anaoutdbl,
-    { "Output (double)", "dnp3.al.anaout", FT_DOUBLE, BASE_DEC, NULL, 0x0, "Output Value (double)", HFILL }},
+    { "Output (double)", "dnp3.al.anaout", FT_DOUBLE, BASE_NONE, NULL, 0x0, "Output Value (double)", HFILL }},
 
     { &hf_dnp3_al_cnt16,
     { "Counter (16 bit)", "dnp3.al.cnt", FT_UINT16, BASE_DEC, NULL, 0x0, "Counter Value (16 bit)", HFILL }},
@@ -2830,130 +2896,130 @@ proto_register_dnp3(void)
     { "Counter (32 bit)", "dnp3.al.cnt", FT_UINT32, BASE_DEC, NULL, 0x0, "Counter Value (32 bit)", HFILL }},
 
     { &hf_dnp3_al_ctrlstatus,
-    { "Control Status", "dnp3.al.ctrlstatus", FT_UINT8, BASE_DEC, dnp3_al_ctl_status_vals, 0xff, "Control Status", HFILL }},
+    { "Control Status", "dnp3.al.ctrlstatus", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_ctl_status_vals_ext, 0xff, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b0,
-    { "Online", "dnp3.al.biq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG0, "", HFILL }},
+    { "Online", "dnp3.al.biq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG0, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b1,
-    { "Restart", "dnp3.al.biq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG1, "", HFILL }},
+    { "Restart", "dnp3.al.biq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG1, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b2,
-    { "Comm Fail", "dnp3.al.biq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG2, "", HFILL }},
+    { "Comm Fail", "dnp3.al.biq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG2, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b3,
-    { "Remote Force", "dnp3.al.biq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG3, "", HFILL }},
+    { "Remote Force", "dnp3.al.biq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG3, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b4,
-    { "Local Force", "dnp3.al.biq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG4, "", HFILL }},
+    { "Local Force", "dnp3.al.biq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG4, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b5,
-    { "Chatter Filter", "dnp3.al.biq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG5, "", HFILL }},
+    { "Chatter Filter", "dnp3.al.biq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG5, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b6,
-    { "Reserved", "dnp3.al.biq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG6, "", HFILL }},
+    { "Reserved", "dnp3.al.biq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG6, NULL, HFILL }},
 
     { &hf_dnp3_al_biq_b7,
-    { "Point Value", "dnp3.al.biq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG7, "", HFILL }},
+    { "Point Value", "dnp3.al.biq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG7, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b0,
-    { "Online", "dnp3.al.boq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG0, "", HFILL }},
+    { "Online", "dnp3.al.boq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG0, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b1,
-    { "Restart", "dnp3.al.boq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG1, "", HFILL }},
+    { "Restart", "dnp3.al.boq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG1, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b2,
-    { "Comm Fail", "dnp3.al.boq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG2, "", HFILL }},
+    { "Comm Fail", "dnp3.al.boq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG2, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b3,
-    { "Remote Force", "dnp3.al.boq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG3, "", HFILL }},
+    { "Remote Force", "dnp3.al.boq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG3, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b4,
-    { "Local Force", "dnp3.al.boq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG4, "", HFILL }},
+    { "Local Force", "dnp3.al.boq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG4, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b5,
-    { "Reserved", "dnp3.al.boq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG5, "", HFILL }},
+    { "Reserved", "dnp3.al.boq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG5, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b6,
-    { "Reserved", "dnp3.al.boq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG6, "", HFILL }},
+    { "Reserved", "dnp3.al.boq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG6, NULL, HFILL }},
 
     { &hf_dnp3_al_boq_b7,
-    { "Point Value", "dnp3.al.boq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG7, "", HFILL }},
+    { "Point Value", "dnp3.al.boq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG7, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b0,
-    { "Online", "dnp3.al.ctrq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG0, "", HFILL }},
+    { "Online", "dnp3.al.ctrq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG0, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b1,
-    { "Restart", "dnp3.al.ctrq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG1, "", HFILL }},
+    { "Restart", "dnp3.al.ctrq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG1, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b2,
-    { "Comm Fail", "dnp3.al.ctrq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG2, "", HFILL }},
+    { "Comm Fail", "dnp3.al.ctrq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG2, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b3,
-    { "Remote Force", "dnp3.al.ctrq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG3, "", HFILL }},
+    { "Remote Force", "dnp3.al.ctrq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG3, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b4,
-    { "Local Force", "dnp3.al.ctrq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG4, "", HFILL }},
+    { "Local Force", "dnp3.al.ctrq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG4, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b5,
-    { "Roll-Over", "dnp3.al.ctrq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG5, "", HFILL }},
+    { "Roll-Over", "dnp3.al.ctrq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG5, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b6,
-    { "Discontinuity", "dnp3.al.ctrq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG6, "", HFILL }},
+    { "Discontinuity", "dnp3.al.ctrq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG6, NULL, HFILL }},
 
     { &hf_dnp3_al_ctrq_b7,
-    { "Reserved", "dnp3.al.ctrq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG7, "", HFILL }},
+    { "Reserved", "dnp3.al.ctrq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG7, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b0,
-    { "Online", "dnp3.al.aiq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG0, "", HFILL }},
+    { "Online", "dnp3.al.aiq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG0, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b1,
-    { "Restart", "dnp3.al.aiq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG1, "", HFILL }},
+    { "Restart", "dnp3.al.aiq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG1, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b2,
-    { "Comm Fail", "dnp3.al.aiq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG2, "", HFILL }},
+    { "Comm Fail", "dnp3.al.aiq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG2, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b3,
-    { "Remote Force", "dnp3.al.aiq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG3, "", HFILL }},
+    { "Remote Force", "dnp3.al.aiq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG3, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b4,
-    { "Local Force", "dnp3.al.aiq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG4, "", HFILL }},
+    { "Local Force", "dnp3.al.aiq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG4, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b5,
-    { "Over-Range", "dnp3.al.aiq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG5, "", HFILL }},
+    { "Over-Range", "dnp3.al.aiq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG5, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b6,
-    { "Reference Check", "dnp3.al.aiq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG6, "", HFILL }},
+    { "Reference Check", "dnp3.al.aiq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG6, NULL, HFILL }},
 
     { &hf_dnp3_al_aiq_b7,
-    { "Reserved", "dnp3.al.aiq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG7, "", HFILL }},
+    { "Reserved", "dnp3.al.aiq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG7, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b0,
-    { "Online", "dnp3.al.aoq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG0, "", HFILL }},
+    { "Online", "dnp3.al.aoq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG0, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b1,
-    { "Restart", "dnp3.al.aoq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG1, "", HFILL }},
+    { "Restart", "dnp3.al.aoq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG1, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b2,
-    { "Comm Fail", "dnp3.al.aoq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG2, "", HFILL }},
+    { "Comm Fail", "dnp3.al.aoq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG2, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b3,
-    { "Remote Force", "dnp3.al.aoq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG3, "", HFILL }},
+    { "Remote Force", "dnp3.al.aoq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG3, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b4,
-    { "Local Force", "dnp3.al.aoq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG4, "", HFILL }},
+    { "Local Force", "dnp3.al.aoq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG4, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b5,
-    { "Reserved", "dnp3.al.aoq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG5, "", HFILL }},
+    { "Reserved", "dnp3.al.aoq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG5, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b6,
-    { "Reserved", "dnp3.al.aoq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG6, "", HFILL }},
+    { "Reserved", "dnp3.al.aoq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG6, NULL, HFILL }},
 
     { &hf_dnp3_al_aoq_b7,
-    { "Reserved", "dnp3.al.aoq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG7, "", HFILL }},
+    { "Reserved", "dnp3.al.aoq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG7, NULL, HFILL }},
 
     { &hf_dnp3_al_timestamp,
-    { "Timestamp", "dnp3.al.timestamp", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0, "Object Timestamp", HFILL }},
+    { "Timestamp", "dnp3.al.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Object Timestamp", HFILL }},
 
     { &hf_dnp3_al_rel_timestamp,
     { "Relative Timestamp", "dnp3.al.reltimestamp", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "Object Relative Timestamp", HFILL }},
@@ -2985,7 +3051,11 @@ proto_register_dnp3(void)
 
     { &hf_dnp3_fragment_reassembled_in,
     { "Reassembled PDU In Frame", "dnp3.al.fragment.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
-      "This PDU is reassembled in this frame", HFILL }}
+      "This PDU is reassembled in this frame", HFILL }},
+
+    { &hf_dnp3_fragment_reassembled_length,
+    { "Reassembled DNP length", "dnp3.al.fragment.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
+      "The total length of the reassembled payload", HFILL }}
   };
 
 /* Setup protocol subtree array */
@@ -3010,7 +3080,7 @@ proto_register_dnp3(void)
   module_t *dnp3_module;
 
 /* Register protocol init routine */
-  register_init_routine(&dnp3_init);
+  register_init_routine(&al_defragment_init);
 
 /* Register the protocol name and description */
   proto_dnp3 = proto_register_protocol("Distributed Network Protocol 3.0",
@@ -3026,15 +3096,9 @@ proto_register_dnp3(void)
     "Whether the DNP3 dissector should reassemble messages spanning multiple TCP segments."
     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
     &dnp3_desegment);
-
-  al_defragment_init();
 }
 
 
-/* If this dissector uses sub-dissector registration add a registration routine.
-   This format is required because a script is used to find these routines and
-   create the code that calls these routines.
-*/
 void
 proto_reg_handoff_dnp3(void)
 {
@@ -3053,10 +3117,10 @@ proto_reg_handoff_dnp3(void)
  * Local Variables:
  * c-basic-offset: 2
  * tab-width: 8
- * indent-tabs-mode: tabs
+ * indent-tabs-mode: nil
  * End:
  *
- * ex: set shiftwidth=2 tabstop=8 noexpandtab
- * :indentSize=2:tabSize=8:noTabs=false:
+ * ex: set shiftwidth=2 tabstop=8 expandtab
+ * :indentSize=2:tabSize=8:noTabs=true:
  */