# 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>
#include <epan/emem.h>
#include <epan/dissectors/packet-tcp.h>
#include <epan/conversation.h>
+#include <epan/expert.h>
/*
* See
* 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
+ *
*/
/***************************************************************************/
#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_DCTR_16 0x1404 /* 20 04 16-Bit Delta Counter */
#define AL_OBJ_CTR_32NF 0x1405 /* 20 05 32-Bit Binary Counter Without Flag */
#define AL_OBJ_CTR_16NF 0x1406 /* 20 06 16-Bit Binary Counter Without Flag */
- /* 0x1407 20 07 32-Bit Delta Counter Without Flag */
- /* 0x1408 20 08 16-Bit Delta 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 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 */
- /* 0x1503 21 03 32-Bit Frozen Delta Counter */
- /* 0x1504 21 04 16-Bit Frozen Delta Counter */
- /* 0x1505 21 05 32-Bit Frozen Counter w/ Time of Freeze */
- /* 0x1506 21 06 16-Bit Frozen Counter w/ Time of Freeze */
- /* 0x1507 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
- /* 0x1508 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
- /* 0x1509 21 09 32-Bit Frozen Counter Without Flag */
- /* 0x1510 21 10 16-Bit Frozen Counter Without Flag */
- /* 0x1511 21 11 32-Bit Frozen Delta Counter Without Flag */
- /* 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_FDCTR_32 0x1503 /* 21 03 32-Bit Frozen Delta Counter */
+#define AL_OBJ_FDCTR_16 0x1504 /* 21 04 16-Bit Frozen Delta Counter */
+#define AL_OBJ_FCTR_32T 0x1505 /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
+#define AL_OBJ_FCTR_16T 0x1506 /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
+#define AL_OBJ_FDCTR_32T 0x1507 /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
+#define AL_OBJ_FDCTR_16T 0x1508 /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
+#define AL_OBJ_FCTR_32NF 0x1509 /* 21 09 32-Bit Frozen Counter Without Flag */
+#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 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 */
- /* 0x1603 22 03 32-Bit Delta Counter Change Event w/o Time */
- /* 0x1604 22 04 16-Bit Delta Counter Change Event w/o Time */
- /* 0x1605 22 05 32-Bit Counter Change Event With Time */
- /* 0x1606 22 06 16-Bit Counter Change Event With Time */
- /* 0x1607 22 07 32-Bit Delta Counter Change Event With Time */
- /* 0x1608 22 08 16-Bit Delta Counter Change Event With Time */
- /* 0x1701 23 01 32-Bit Counter Change Event w/o Time */
- /* 0x1702 23 02 16-Bit Frozen Counter Change Event w/o Time */
- /* 0x1703 23 03 32-Bit Frozen Delta 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_DCTRC_16 0x1604 /* 22 04 16-Bit Delta Counter Change Event w/o Time */
+#define AL_OBJ_CTRC_32T 0x1605 /* 22 05 32-Bit Counter Change Event with 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 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 */
+#define AL_OBJ_FDCTRC_16 0x1704 /* 21 04 16-Bit Frozen Delta Counter Change Event */
+#define AL_OBJ_FCTRC_32T 0x1705 /* 21 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
+#define AL_OBJ_FCTRC_16T 0x1706 /* 21 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
+#define AL_OBJ_FDCTRC_32T 0x1707 /* 21 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
+#define AL_OBJ_FDCTRC_16T 0x1708 /* 21 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
/* Counter Quality Flags */
#define AL_OBJ_CTR_FLAG0 0x0001 /* Point Online (0=Offline; 1=Online) */
/***************************************************************************/
/* 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 */
/* Device Objects */
#define AL_OBJ_IIN 0x5001 /* 80 01 Internal Indications */
+/***************************************************************************/
+/* Octet String Objects */
+#define AL_OBJ_OCT 0x6E00 /* 110 xx Octet string */
+
/***************************************************************************/
/* End of Application Layer Data Object Definitions */
/***************************************************************************/
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 */
{ 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_ = {
{ 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[] = {
{ 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)" },
+ { AL_OBJ_DCTR_16, "16-Bit Binary Delta Counter (Obj:20, Var:04)" },
{ AL_OBJ_CTR_32NF, "32-Bit Binary Counter Without Flag (Obj:20, Var:05)" },
{ AL_OBJ_CTR_16NF, "16-Bit Binary Counter Without Flag (Obj:20, Var:06)" },
- { AL_OBJ_FCTR_32, "32-Bit Frozen Counter (Obj:21, Var:01)"},
- { AL_OBJ_FCTR_16, "16-Bit Frozen Counter (Obj:21, Var:02)"},
- { AL_OBJ_CTRC_ALL, "Binary Counter Change All Variations (Obj:22, Var:All)" },
+ { 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 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)" },
+ { AL_OBJ_FDCTR_16, "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
+ { AL_OBJ_FCTR_32T, "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
+ { AL_OBJ_FCTR_16T, "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
+ { AL_OBJ_FDCTR_32T, "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
+ { AL_OBJ_FDCTR_16T, "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
+ { AL_OBJ_FCTR_32NF, "32-Bit Frozen Binary Counter Without Flag (Obj:21, Var:05)" },
+ { 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 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_AI_ALL, "Analog Input All Variations (Obj:30, Var:All)" },
+ { AL_OBJ_DCTRC_32, "32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03)" },
+ { AL_OBJ_DCTRC_16, "16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04)" },
+ { AL_OBJ_CTRC_32T, "32-Bit Counter Change Event with Time (Obj:22, Var:05)" },
+ { 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 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)" },
+ { AL_OBJ_FDCTRC_16, "16-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:04)" },
+ { AL_OBJ_FCTRC_32T, "32-Bit Frozen Counter Change Event with Time (Obj:23, Var:05)" },
+ { 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 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)" },
{ 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)" },
{ 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)" },
{ 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)" },
{ AL_OBJ_CLASS2, "Class 2 Data (Obj:60, Var:03)" },
{ AL_OBJ_CLASS3, "Class 3 Data (Obj:60, Var:04)" },
{ AL_OBJ_IIN, "Internal Indications (Obj:80, Var:01)" },
+ { 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[] = {
{ 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_ = {
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;
&hf_dnp3_fragment_too_long_fragment,
&hf_dnp3_fragment_error,
&hf_dnp3_fragment_reassembled_in,
+ &hf_dnp3_fragment_reassembled_length,
"DNP 3.0 fragments"
};
/* the number of entries in the memory chunk array */
#define dnp3_conv_init_count 50
-/* define your structure here */
+/* Conversation structure */
typedef struct {
guint conv_seq_number;
} dnp3_conv_t;
-/* the GMemChunk base structure */
-static GMemChunk *dnp3_conv_vals = NULL;
-
/* The conversation sequence number */
static guint seq_number = 0;
/* desegmentation of DNP3 over TCP */
static gboolean dnp3_desegment = TRUE;
+/* Enum for different quality type fields */
+enum QUALITY_TYPE {
+ BIN_IN,
+ BIN_OUT,
+ ANA_IN,
+ ANA_OUT,
+ COUNTER
+};
+
/*****************************************************************/
/* */
/* CRC LOOKUP TABLE */
if (comma_needed) {
proto_item_append_text(item, ", ");
}
- proto_item_append_text(item, text);
+ proto_item_append_text(item, "%s", text);
return TRUE;
}
{
case AL_OBJQL_IDX_NI: /* No Index */
indexbytes = 0;
- index_item = proto_tree_add_text(item_tree, tvb, offset, 0, "Point Index: %d", *al_ptaddr);
+ index_item = proto_tree_add_text(item_tree, tvb, offset, 0, "Point Index: %u", *al_ptaddr);
PROTO_ITEM_SET_GENERATED(index_item);
break;
case AL_OBJQL_IDX_1O:
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);
}
/*****************************************************************/
/* add Point Quality Flag Sub-Tree */
/*****************************************************************/
static void
-dnp3_al_obj_quality(tvbuff_t *tvb, int offset, guint8 al_ptflags, proto_tree *point_tree, proto_item *point_item, int type)
+dnp3_al_obj_quality(tvbuff_t *tvb, int offset, guint8 al_ptflags, proto_tree *point_tree, proto_item *point_item, enum QUALITY_TYPE type)
{
proto_tree *quality_tree = NULL;
int hf0 = 0, hf1 = 0, hf2 = 0, hf3 = 0, hf4 = 0, hf5 = 0, hf6 = 0, hf7 = 0;
/* Common code */
- DISSECTOR_ASSERT(0 <= type && type <= 4);
proto_item_append_text(point_item, " (Quality: ");
quality_item = proto_tree_add_text(point_tree, tvb, offset, 1, "Quality: ");
quality_tree = proto_item_add_subtree(quality_item, ett_dnp3_al_obj_quality);
if (al_ptflags & AL_OBJ_BI_FLAG4) dnp3_append_2item_text(point_item, quality_item, ", Local Force");
switch (type) {
- case 0: /* Binary Input Quality flags */
+ case BIN_IN: /* Binary Input Quality flags */
if (al_ptflags & AL_OBJ_BI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Chatter Filter");
hf0 = hf_dnp3_al_biq_b0;
hf7 = hf_dnp3_al_biq_b7;
break;
- case 1: /* Binary Output Quality flags */
+ case BIN_OUT: /* Binary Output Quality flags */
hf0 = hf_dnp3_al_boq_b0;
hf1 = hf_dnp3_al_boq_b1;
hf2 = hf_dnp3_al_boq_b2;
hf7 = hf_dnp3_al_boq_b7;
break;
- case 2: /* Counter Quality flags */
- if (al_ptflags & AL_OBJ_CTR_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Roll-over");
- if (al_ptflags & AL_OBJ_CTR_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Discontinuity");
-
- hf0 = hf_dnp3_al_ctrq_b0;
- hf1 = hf_dnp3_al_ctrq_b1;
- hf2 = hf_dnp3_al_ctrq_b2;
- hf3 = hf_dnp3_al_ctrq_b3;
- hf4 = hf_dnp3_al_ctrq_b4;
- hf5 = hf_dnp3_al_ctrq_b5;
- hf6 = hf_dnp3_al_ctrq_b6;
- hf7 = hf_dnp3_al_ctrq_b7;
- break;
-
- case 3: /* Analog Input Quality flags */
+ case ANA_IN: /* Analog Input Quality flags */
if (al_ptflags & AL_OBJ_AI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Over-Range");
if (al_ptflags & AL_OBJ_AI_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Reference Check");
hf7 = hf_dnp3_al_aiq_b7;
break;
- case 4: /* Analog Output Quality flags */
+ case ANA_OUT: /* Analog Output Quality flags */
hf0 = hf_dnp3_al_aoq_b0;
hf1 = hf_dnp3_al_aoq_b1;
hf2 = hf_dnp3_al_aoq_b2;
hf6 = hf_dnp3_al_aoq_b6;
hf7 = hf_dnp3_al_aoq_b7;
break;
+
+ case COUNTER: /* Counter Quality flags */
+ if (al_ptflags & AL_OBJ_CTR_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Roll-over");
+ if (al_ptflags & AL_OBJ_CTR_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Discontinuity");
+
+ hf0 = hf_dnp3_al_ctrq_b0;
+ hf1 = hf_dnp3_al_ctrq_b1;
+ hf2 = hf_dnp3_al_ctrq_b2;
+ hf3 = hf_dnp3_al_ctrq_b3;
+ hf4 = hf_dnp3_al_ctrq_b4;
+ hf5 = hf_dnp3_al_ctrq_b5;
+ hf6 = hf_dnp3_al_ctrq_b6;
+ hf7 = hf_dnp3_al_ctrq_b7;
+ break;
}
if (quality_tree != NULL) {
/* Value is ms since 00:00 on 1/1/1970 */
/**********************************************************************/
static void
-dnp3_al_get_timestamp(nstime_t *timestamp, tvbuff_t *tvb, int temp_pos)
+dnp3_al_get_timestamp(nstime_t *timestamp, tvbuff_t *tvb, int data_pos)
{
guint32 hi, lo;
guint64 time_ms;
- lo = tvb_get_letohs(tvb, temp_pos);
- hi = tvb_get_letohl(tvb, temp_pos + 2);
+ lo = tvb_get_letohs(tvb, data_pos);
+ hi = tvb_get_letohl(tvb, data_pos + 2);
time_ms = (guint64)hi * 0x10000 + lo;
/* Returns: New offset pointer into tvb */
/*****************************************************************/
static int
-dnp3_al_process_object(tvbuff_t *tvb, int offset, proto_tree *robj_tree, gboolean header_only)
+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,
+ 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 item_num, al_val32, num_items=0, al_ptaddr=0, al_ctlobj_on, al_ctlobj_off;
+ guint32 al_val32, al_ptaddr=0, al_ctlobj_on, al_ctlobj_off;
nstime_t al_cto, al_reltime, al_abstime;
gboolean al_bit;
- guint temp_pos;
+ guint data_pos;
gfloat al_valflt;
gdouble al_valdbl;
- int orig_offset, rangebytes=0, indexbytes=0;
+ int item_num, num_items=0;
+ int orig_offset, start_offset, rangebytes=0, indexbytes=0;
proto_item *object_item = NULL, *point_item = NULL, *qualifier_item = NULL, *range_item = NULL;
proto_tree *object_tree = NULL, *point_tree, *qualifier_tree, *range_tree;
const gchar *ctl_code_str, *ctl_misc_str, *ctl_tc_str, *ctl_status_str;
orig_offset = offset;
/* Application Layer Objects in this Message */
+ *al_objtype =
al_obj = tvb_get_ntohs(tvb, offset);
+ /* Special handling for Octet string objects as the variation is the length of the string */
+ if ((al_obj & 0xFF00) == AL_OBJ_OCT) {
+ al_oct_len = al_obj & 0xFF;
+ al_obj = AL_OBJ_OCT;
+ }
+
/* 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;
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);
PROTO_ITEM_SET_GENERATED(range_item);
al_ptaddr = tvb_get_letohl(tvb, offset);
proto_tree_add_item(range_tree, hf_dnp3_al_range_start32, tvb, offset, 4, TRUE);
- proto_tree_add_item(range_tree, hf_dnp3_al_range_stop32, tvb, offset + 4, 2, TRUE);
+ proto_tree_add_item(range_tree, hf_dnp3_al_range_stop32, tvb, offset + 4, 4, TRUE);
rangebytes = 8;
break;
case AL_OBJQL_CODE_AA8: /* 8-bit Absolute Address in Range Field */
proto_item_set_len(range_item, rangebytes);
break;
}
- if (num_items)
- proto_item_append_text(object_item, ", %d points", num_items);
+ if (num_items > 0) {
+ proto_item_append_text(object_item, ", %d point%s", num_items, plurality(num_items, "", "s"));
+ }
proto_item_append_text(range_item, "%d", num_items);
+ if (num_items < 0) {
+ proto_item_append_text(range_item, " (bogus)");
+ expert_add_info_format(pinfo, range_item, PI_MALFORMED, PI_ERROR, "Negative number of items");
+ return tvb_length(tvb);
+ }
+
+
offset += rangebytes;
- if (!header_only) {
- bitindex = 0; /* Temp variable for cycling through points when object values are encoded into
- bits; primarily objects 0x0101, 0x0301 & 0x1001 */
+ bitindex = 0; /* Temp variable for cycling through points when object values are encoded into
+ bits; primarily objects 0x0101, 0x0301 & 0x1001 */
+ /* Only process the point information for replies or items with point index lists */
+ if (!header_only || al_objq_index > 0) {
+ start_offset = offset;
for (item_num = 0; item_num < num_items; item_num++)
{
/* Create Point item and Process Index */
- point_item = proto_tree_add_text(object_tree, tvb, offset, -1, "Point Number");
+ point_item = proto_tree_add_text(object_tree, tvb, offset, 0, "Point Number");
point_tree = proto_item_add_subtree(point_item, ett_dnp3_al_obj_point);
- temp_pos = offset;
+ data_pos = offset;
indexbytes = dnp3_al_obj_procindex(tvb, offset, al_objq_index, &al_ptaddr, point_tree);
- proto_item_append_text(point_item, " %d", al_ptaddr);
- temp_pos += indexbytes;
+ proto_item_append_text(point_item, " %u", al_ptaddr);
+ data_pos += indexbytes;
- switch (al_obj)
- {
+ if (!header_only) {
+ 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) */
-
- offset += indexbytes;
- break;
-
- case AL_OBJ_BI_1BIT: /* Single-Bit Binary Input (Obj:01, Var:01) */
- case AL_OBJ_BO: /* Binary Output (Obj:10, Var:01) */
+ 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) */
- /* Reset bit index if we've gone onto the next byte */
- if (bitindex > 7)
- {
- bitindex = 0;
- offset += (indexbytes + 1);
- }
+ offset = data_pos;
+ break;
- /* Extract the bit from the packed byte */
- al_bi_val = tvb_get_guint8(tvb, offset);
- al_bit = (al_bi_val & (1 << bitindex)) > 0;
+ case AL_OBJ_BI_1BIT: /* Single-Bit Binary Input (Obj:01, Var:01) */
+ case AL_OBJ_BO: /* Binary Output (Obj:10, Var:01) */
- proto_item_append_text(point_item, ", Value: %d", al_bit);
- proto_tree_add_boolean(point_tree, hf_dnp3_al_bit, tvb, offset, 1, al_bit);
- proto_item_set_len(point_item, indexbytes + 1);
+ /* Reset bit index if we've gone onto the next byte */
+ if (bitindex > 7)
+ {
+ bitindex = 0;
+ offset += (indexbytes + 1);
+ }
- /* If we've read the last item, then move the offset past this byte */
- if (item_num == (num_items-1))
- {
- offset += (indexbytes + 1);
- }
+ /* Extract the bit from the packed byte */
+ al_bi_val = tvb_get_guint8(tvb, offset);
+ al_bit = (al_bi_val & (1 << bitindex)) > 0;
- break;
+ proto_item_append_text(point_item, ", Value: %u", al_bit);
+ proto_tree_add_boolean(point_tree, hf_dnp3_al_bit, tvb, offset, 1, al_bit);
+ proto_item_set_len(point_item, indexbytes + 1);
- case AL_OBJ_2BI_NF: /* Double-bit Input No Flags (Obj:03, Var:01) */
+ /* If we've read the last item, then move the offset past this byte */
+ if (item_num == (num_items-1))
+ {
+ offset += (indexbytes + 1);
+ }
- if (bitindex > 3)
- {
- bitindex = 0;
- offset += (indexbytes + 1);
- }
+ break;
- /* Extract the Double-bit from the packed byte */
- al_bi_val = tvb_get_guint8(tvb, offset);
- al_2bit = ((al_bi_val >> (bitindex << 1)) & 3);
+ case AL_OBJ_2BI_NF: /* Double-bit Input No Flags (Obj:03, Var:01) */
- proto_item_append_text(point_item, ", Value: %d", al_2bit);
- proto_tree_add_uint(point_tree, hf_dnp3_al_2bit, tvb, offset, 1, al_2bit);
- proto_item_set_len(point_item, indexbytes + 1);
+ if (bitindex > 3)
+ {
+ bitindex = 0;
+ offset += (indexbytes + 1);
+ }
- /* If we've read the last item, then move the offset past this byte */
- if (item_num == (num_items-1))
- {
- offset += (indexbytes + 1);
- }
+ /* Extract the Double-bit from the packed byte */
+ al_bi_val = tvb_get_guint8(tvb, offset);
+ al_2bit = ((al_bi_val >> (bitindex << 1)) & 3);
- break;
+ proto_item_append_text(point_item, ", Value: %u", al_2bit);
+ proto_tree_add_uint(point_tree, hf_dnp3_al_2bit, tvb, offset, 1, al_2bit);
+ proto_item_set_len(point_item, indexbytes + 1);
+ /* If we've read the last item, then move the offset past this byte */
+ if (item_num == (num_items-1))
+ {
+ offset += (indexbytes + 1);
+ }
- case AL_OBJ_BI_STAT: /* Binary Input With Status (Obj:01, Var:02) */
- case AL_OBJ_BIC_NOTIME: /* Binary Input Change Without Time (Obj:02, Var:01) */
- case AL_OBJ_BO_STAT: /* Binary Output Status (Obj:10, Var:02) */
+ break;
- /* Get Point Flags */
- al_ptflags = tvb_get_guint8(tvb, offset);
- al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) > 0;
- switch (al_obj) {
- case AL_OBJ_BI_STAT:
- case AL_OBJ_BIC_NOTIME:
- dnp3_al_obj_quality(tvb, offset, al_ptflags, point_tree, point_item, 0);
- proto_item_append_text(point_item, ", Value: %d", al_bit);
- proto_item_set_len(point_item, indexbytes + 1);
- break;
- case AL_OBJ_BO_STAT:
- dnp3_al_obj_quality(tvb, offset, al_ptflags, point_tree, point_item, 1);
- proto_item_append_text(point_item, ", Value: %d", al_bit);
- proto_item_set_len(point_item, indexbytes + 1);
- break;
- }
+ case AL_OBJ_BI_STAT: /* Binary Input With Status (Obj:01, Var:02) */
+ case AL_OBJ_BIC_NOTIME: /* Binary Input Change Without Time (Obj:02, Var:01) */
+ case AL_OBJ_BO_STAT: /* Binary Output Status (Obj:10, Var:02) */
- offset += (indexbytes + 1);
- break;
+ /* Get Point Flags */
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
- case AL_OBJ_2BI_STAT: /* Double-bit Input With Status (Obj:03, Var:02) */
- case AL_OBJ_2BIC_NOTIME: /* Double-bit Input Change Without Time (Obj:04, Var:01) */
+ switch (al_obj) {
+ case AL_OBJ_BI_STAT:
+ case AL_OBJ_BIC_NOTIME:
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
+ break;
+ case AL_OBJ_BO_STAT:
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_OUT);
+ break;
+ }
+ data_pos += 1;
- /* Get Point Flags */
- al_ptflags = tvb_get_guint8(tvb, offset);
- al_2bit = (al_ptflags >> 6) & 3;
+ al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) > 0;
+ proto_item_append_text(point_item, ", Value: %u", al_bit);
- dnp3_al_obj_quality(tvb, offset, al_ptflags, point_tree, point_item, 0);
- proto_item_append_text(point_item, ", Value: %d", al_2bit);
- proto_item_set_len(point_item, indexbytes + 1);
+ proto_item_set_len(point_item, data_pos - offset);
- offset += (indexbytes + 1);
- break;
+ offset = data_pos;
+ break;
- case AL_OBJ_BIC_TIME: /* Binary Input Change w/ Time (Obj:02, Var:02) */
+ case AL_OBJ_2BI_STAT: /* Double-bit Input With Status (Obj:03, Var:02) */
+ case AL_OBJ_2BIC_NOTIME: /* Double-bit Input Change Without Time (Obj:04, Var:01) */
- /* Get Point Flags */
- al_ptflags = tvb_get_guint8(tvb, temp_pos);
- temp_pos += 1;
+ /* Get Point Flags */
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
+ data_pos += 1;
- al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
+ al_2bit = (al_ptflags >> 6) & 3;
+ proto_item_append_text(point_item, ", Value: %u", al_2bit);
+ proto_item_set_len(point_item, data_pos - offset);
- /* Get timestamp */
- dnp3_al_get_timestamp(&al_abstime, tvb, temp_pos);
+ offset = data_pos;
+ break;
- dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, 0);
- proto_item_append_text(point_item, ", Value: %d, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime));
- proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, temp_pos, 6, &al_abstime);
- proto_item_set_len(point_item, indexbytes + 7);
+ case AL_OBJ_BIC_TIME: /* Binary Input Change w/ Time (Obj:02, Var:02) */
- offset += (indexbytes + 7);
+ /* Get Point Flags */
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
+ data_pos += 1;
- break;
- case AL_OBJ_2BIC_TIME: /* Double-bit Input Change w/ Time (Obj:04, Var:02) */
+ /* Get timestamp */
+ dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
+ proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
+ data_pos += 6;
- /* Get Point Flags */
- al_ptflags = tvb_get_guint8(tvb, temp_pos);
- temp_pos += 1;
+ 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, ABSOLUTE_TIME_LOCAL, TRUE));
+ proto_item_set_len(point_item, data_pos - offset);
- al_2bit = (al_ptflags >> 6) & 3; /* bit shift 11xxxxxx -> 00000011 */
+ offset = data_pos;
+ break;
- /* Get timestamp */
- dnp3_al_get_timestamp(&al_abstime, tvb, temp_pos);
+ case AL_OBJ_2BIC_TIME: /* Double-bit Input Change w/ Time (Obj:04, Var:02) */
- dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, 0);
- proto_item_append_text(point_item, ", Value: %d, Timestamp: %s", al_2bit, abs_time_to_str(&al_abstime));
- proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, temp_pos, 6, &al_abstime);
- proto_item_set_len(point_item, indexbytes + 7);
+ /* Get Point Flags */
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, BIN_IN);
+ data_pos += 1;
- offset += (indexbytes + 7);
- break;
-
- case AL_OBJ_BIC_RTIME: /* Binary Input Change w/ Relative Time (Obj:02, Var:03) */
-
- /* Get Point Flags */
- al_ptflags = tvb_get_guint8(tvb, temp_pos);
- temp_pos += 1;
-
- al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
-
- /* Get relative time, and convert to ns_time */
- al_relms = tvb_get_letohs(tvb, temp_pos);
- al_reltime.secs = al_relms / 1000;
- al_reltime.nsecs = (al_relms % 1000) * 1000;
- /* Now add to CTO time */
- nstime_sum(&al_abstime, &al_cto, &al_reltime);
+ /* Get timestamp */
+ dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
+ proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
+ 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, ABSOLUTE_TIME_LOCAL, TRUE));
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_BIC_RTIME: /* Binary Input Change w/ Relative Time (Obj:02, Var:03) */
+
+ /* Get Point Flags */
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
+ data_pos += 1;
+
+ /* Get relative time, and convert to ns_time */
+ al_relms = tvb_get_letohs(tvb, data_pos);
+ al_reltime.secs = al_relms / 1000;
+ al_reltime.nsecs = (al_relms % 1000) * 1000;
+ /* Now add to CTO time */
+ nstime_sum(&al_abstime, &al_cto, &al_reltime);
+ proto_tree_add_time(point_tree, hf_dnp3_al_rel_timestamp, tvb, data_pos, 2, &al_reltime);
+ 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, ABSOLUTE_TIME_LOCAL, TRUE));
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_CTLOP_BLK: /* Control Relay Output Block (Obj:12, Var:01) */
+
+ al_ctlobj_code = tvb_get_guint8(tvb, data_pos);
+ data_pos += 1;
+
+ /* Bit-Mask xxxx1111 for Control Code 'Code' */
+ al_ctlobj_code_c = al_ctlobj_code & AL_OBJCTLC_CODE;
+ ctl_code_str = val_to_str(al_ctlobj_code_c, dnp3_al_ctlc_code_vals, "Ctrl Code Invalid (0x%02x)");
+
+ /* Bit-Mask xx11xxxx for Control Code Misc Values */
+ al_ctlobj_code_m = al_ctlobj_code & AL_OBJCTLC_MISC;
+ 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_const(al_ctlobj_code_tc, dnp3_al_ctlc_tc_vals, "");
+
+ /* Get "Count" Field */
+ al_ctlobj_count = tvb_get_guint8(tvb, data_pos);
+ data_pos += 1;
+
+ /* Get "On Time" Field */
+ al_ctlobj_on = tvb_get_letohl(tvb, data_pos);
+ data_pos += 4;
+
+ /* Get "Off Time" Field */
+ al_ctlobj_off = tvb_get_letohl(tvb, data_pos);
+ data_pos += 4;
+
+ 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_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)]",
+ ctl_code_str, ctl_misc_str, ctl_tc_str, al_ctlobj_code);
+
+ proto_tree_add_text(point_tree, tvb, data_pos - 11, 11,
+ " [Count: %u] [On-Time: %u] [Off-Time: %u] [Status: %s (0x%02x)]",
+ al_ctlobj_count, al_ctlobj_on, al_ctlobj_off, ctl_status_str, al_ctlobj_stat);
+
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_AO_32OPB: /* 32-Bit Analog Output Block (Obj:41, Var:01) */
+ case AL_OBJ_AO_16OPB: /* 16-Bit Analog Output Block (Obj:41, Var:02) */
+ case AL_OBJ_AO_FLTOPB: /* 32-Bit Floating Point Output Block (Obj:41, Var:03) */
+ case AL_OBJ_AO_DBLOPB: /* 64-Bit Floating Point Output Block (Obj:41, Var:04) */
+
+ switch (al_obj)
+ {
+ case AL_OBJ_AO_32OPB:
+ al_val32 = tvb_get_letohl(tvb, data_pos);
+ proto_item_append_text(point_item, ", Value: %u", al_val32);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+ case AL_OBJ_AO_16OPB:
+ al_val32 = tvb_get_letohs(tvb, data_pos);
+ proto_item_append_text(point_item, ", Value: %u", al_val32);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, TRUE);
+ data_pos += 2;
+ break;
+ case AL_OBJ_AO_FLTOPB:
+ al_valflt = tvb_get_letohieee_float(tvb, data_pos);
+ proto_item_append_text(point_item, ", Value: %g", al_valflt);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+ case AL_OBJ_AO_DBLOPB:
+ al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
+ 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;
+ }
+
+ /* Get control status */
+ al_ctlobj_stat = tvb_get_guint8(tvb, data_pos);
+ 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;
+
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_CTR_32: /* 32-Bit Binary Counter (Obj:20, Var:01) */
+ case AL_OBJ_CTR_16: /* 16-Bit Binary Counter (Obj:20, Var:02) */
+ case AL_OBJ_DCTR_32: /* 32-Bit Binary Delta Counter (Obj:20, Var:03) */
+ case AL_OBJ_DCTR_16: /* 16-Bit Binary Delta Counter (Obj:20, Var:04) */
+ case AL_OBJ_CTR_32NF: /* 32-Bit Binary Counter Without Flag (Obj:20, Var:05) */
+ case AL_OBJ_CTR_16NF: /* 16-Bit Binary Counter Without Flag (Obj:20, Var:06) */
+ case AL_OBJ_DCTR_32NF: /* 32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07) */
+ case AL_OBJ_DCTR_16NF: /* 16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08) */
+ case AL_OBJ_FCTR_32: /* 32-Bit Frozen Counter (Obj:21, Var:01) */
+ case AL_OBJ_FCTR_16: /* 16-Bit Frozen Counter (Obj:21, Var:02) */
+ case AL_OBJ_FDCTR_32: /* 21 03 32-Bit Frozen Delta Counter */
+ case AL_OBJ_FDCTR_16: /* 21 04 16-Bit Frozen Delta Counter */
+ case AL_OBJ_FCTR_32T: /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
+ case AL_OBJ_FCTR_16T: /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
+ case AL_OBJ_FDCTR_32T: /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
+ case AL_OBJ_FDCTR_16T: /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
+ case AL_OBJ_FCTR_32NF: /* 21 09 32-Bit Frozen Counter Without Flag */
+ case AL_OBJ_FCTR_16NF: /* 21 10 16-Bit Frozen Counter Without Flag */
+ case AL_OBJ_FDCTR_32NF: /* 21 11 32-Bit Frozen Delta Counter Without Flag */
+ case AL_OBJ_FDCTR_16NF: /* 21 12 16-Bit Frozen Delta Counter Without Flag */
+ case AL_OBJ_CTRC_32: /* 32-Bit Counter Change Event w/o Time (Obj:22, Var:01) */
+ case AL_OBJ_CTRC_16: /* 16-Bit Counter Change Event w/o Time (Obj:22, Var:02) */
+ case AL_OBJ_DCTRC_32: /* 32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03) */
+ case AL_OBJ_DCTRC_16: /* 16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04) */
+ case AL_OBJ_CTRC_32T: /* 32-Bit Counter Change Event with Time (Obj:22, Var:05) */
+ case AL_OBJ_CTRC_16T: /* 16-Bit Counter Change Event with Time (Obj:22, Var:06) */
+ case AL_OBJ_DCTRC_32T: /* 32-Bit Delta Counter Change Event with Time (Obj:22, Var:07) */
+ case AL_OBJ_DCTRC_16T: /* 16-Bit Delta Counter Change Event with Time (Obj:22, Var:08) */
+ case AL_OBJ_FCTRC_32: /* 21 01 32-Bit Frozen Counter Change Event */
+ case AL_OBJ_FCTRC_16: /* 21 02 16-Bit Frozen Counter Change Event */
+ case AL_OBJ_FDCTRC_32: /* 21 03 32-Bit Frozen Delta Counter Change Event */
+ case AL_OBJ_FDCTRC_16: /* 21 04 16-Bit Frozen Delta Counter Change Event */
+ case AL_OBJ_FCTRC_32T: /* 21 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
+ case AL_OBJ_FCTRC_16T: /* 21 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
+ case AL_OBJ_FDCTRC_32T: /* 21 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
+ case AL_OBJ_FDCTRC_16T: /* 21 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
+
+ /* Get Point Flags for those types that have them, it's easier to block out those that don't have flags */
+ switch (al_obj)
+ {
+ case AL_OBJ_CTR_32NF:
+ case AL_OBJ_CTR_16NF:
+ case AL_OBJ_DCTR_32NF:
+ case AL_OBJ_DCTR_16NF:
+ case AL_OBJ_FCTR_32NF:
+ case AL_OBJ_FCTR_16NF:
+ case AL_OBJ_FDCTR_32NF:
+ case AL_OBJ_FDCTR_16NF:
+ break;
+
+ default:
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, COUNTER);
+ data_pos += 1;
+ break;
+ }
+
+ /* Get Counter values */
+ switch (al_obj)
+ {
+ case AL_OBJ_CTR_32:
+ case AL_OBJ_DCTR_32:
+ case AL_OBJ_CTR_32NF:
+ case AL_OBJ_DCTR_32NF:
+ case AL_OBJ_FCTR_32:
+ case AL_OBJ_FDCTR_32:
+ case AL_OBJ_FCTR_32T:
+ case AL_OBJ_FDCTR_32T:
+ case AL_OBJ_FCTR_32NF:
+ case AL_OBJ_FDCTR_32NF:
+ case AL_OBJ_CTRC_32:
+ case AL_OBJ_DCTRC_32:
+ case AL_OBJ_CTRC_32T:
+ case AL_OBJ_DCTRC_32T:
+ case AL_OBJ_FCTRC_32:
+ case AL_OBJ_FDCTRC_32:
+ case AL_OBJ_FCTRC_32T:
+ case AL_OBJ_FDCTRC_32T:
+
+ al_val32 = tvb_get_letohl(tvb, data_pos);
+ proto_item_append_text(point_item, ", Count: %u", al_val32);
+ proto_tree_add_item(point_tree, hf_dnp3_al_cnt32, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+
+ case AL_OBJ_CTR_16:
+ case AL_OBJ_DCTR_16:
+ case AL_OBJ_CTR_16NF:
+ case AL_OBJ_DCTR_16NF:
+ case AL_OBJ_FCTR_16:
+ case AL_OBJ_FDCTR_16:
+ case AL_OBJ_FCTR_16T:
+ case AL_OBJ_FDCTR_16T:
+ case AL_OBJ_FCTR_16NF:
+ case AL_OBJ_FDCTR_16NF:
+ case AL_OBJ_CTRC_16:
+ case AL_OBJ_DCTRC_16:
+ case AL_OBJ_CTRC_16T:
+ case AL_OBJ_DCTRC_16T:
+ case AL_OBJ_FCTRC_16:
+ case AL_OBJ_FDCTRC_16:
+ case AL_OBJ_FCTRC_16T:
+ case AL_OBJ_FDCTRC_16T:
+
+ al_val16 = tvb_get_letohs(tvb, data_pos);
+ proto_item_append_text(point_item, ", Count: %u", al_val16);
+ proto_tree_add_item(point_tree, hf_dnp3_al_cnt16, tvb, data_pos, 2, TRUE);
+ data_pos += 2;
+ break;
+ }
+
+ /* Get the time for those points that have it */
+ switch (al_obj)
+ {
+ case AL_OBJ_FCTR_32T:
+ case AL_OBJ_FCTR_16T:
+ case AL_OBJ_FDCTR_32T:
+ case AL_OBJ_FDCTR_16T:
+ case AL_OBJ_CTRC_32T:
+ case AL_OBJ_CTRC_16T:
+ case AL_OBJ_DCTRC_32T:
+ case AL_OBJ_DCTRC_16T:
+ case AL_OBJ_FCTRC_32T:
+ case AL_OBJ_FCTRC_16T:
+ 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, ABSOLUTE_TIME_LOCAL, TRUE));
+ proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
+ data_pos += 6;
+ break;
+ }
+
+ proto_item_set_len(point_item, data_pos - offset);
+ offset = data_pos;
+
+ break;
+
+ case AL_OBJ_AI_32: /* 32-Bit Analog Input (Obj:30, Var:01) */
+ case AL_OBJ_AI_16: /* 16-Bit Analog Input (Obj:30, Var:02) */
+ case AL_OBJ_AI_32NF: /* 32-Bit Analog Input Without Flag (Obj:30, Var:03) */
+ case AL_OBJ_AI_16NF: /* 16-Bit Analog Input Without Flag (Obj:30, Var:04) */
+ case AL_OBJ_AI_FLT: /* 32-Bit Floating Point Input (Obj:30, Var:05) */
+ case AL_OBJ_AI_DBL: /* 64-Bit Floating Point Input (Obj:30, Var:06) */
+ case AL_OBJ_AIF_FLT: /* 32-Bit Frozen Floating Point Input (Obj:31, Var:07) */
+ case AL_OBJ_AIF_DBL: /* 64-Bit Frozen Floating Point Input (Obj:31, Var:08) */
+ case AL_OBJ_AIC_32NT: /* 32-Bit Analog Change Event w/o Time (Obj:32, Var:01) */
+ case AL_OBJ_AIC_16NT: /* 16-Bit Analog Change Event w/o Time (Obj:32, Var:02) */
+ case AL_OBJ_AIC_32T: /* 32-Bit Analog Change Event with Time (Obj:32, Var:03) */
+ case AL_OBJ_AIC_16T: /* 16-Bit Analog Change Event with Time (Obj:32, Var:04) */
+ case AL_OBJ_AIC_FLTNT: /* 32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05) */
+ case AL_OBJ_AIC_DBLNT: /* 64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06) */
+ case AL_OBJ_AIC_FLTT: /* 32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07) */
+ case AL_OBJ_AIC_DBLT: /* 64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08) */
+ case AL_OBJ_AIFC_FLTNT: /* 32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05) */
+ 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:
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_IN);
+ data_pos += 1;
+ break;
+ }
+
+ switch (al_obj)
+ {
+ case AL_OBJ_AI_32:
+ 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);
+ proto_tree_add_item(point_tree, hf_dnp3_al_ana32, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+
+ case AL_OBJ_AI_16:
+ 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);
+ proto_tree_add_item(point_tree, hf_dnp3_al_ana16, tvb, data_pos, 2, TRUE);
+ data_pos += 2;
+ break;
+
+ case AL_OBJ_AI_FLT:
+ case AL_OBJ_AIF_FLT:
+ case AL_OBJ_AIC_FLTNT:
+ 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);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaflt, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+
+ case AL_OBJ_AI_DBL:
+ case AL_OBJ_AIF_DBL:
+ case AL_OBJ_AIC_DBLNT:
+ case AL_OBJ_AIC_DBLT:
+ case AL_OBJ_AIFC_DBLNT:
+ case AL_OBJ_AIFC_DBLT:
+
+ al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
+ 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;
+ }
+
+ /* Get timestamp */
+ switch (al_obj)
+ {
+ case AL_OBJ_AIC_32T:
+ case AL_OBJ_AIC_16T:
+ case AL_OBJ_AIC_FLTT:
+ case AL_OBJ_AIC_DBLT:
+ 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, ABSOLUTE_TIME_LOCAL, TRUE));
+ proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
+ data_pos += 6;
+ break;
+ }
+
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_AO_32: /* 32-Bit Analog Output Status (Obj:40, Var:01) */
+ case AL_OBJ_AO_16: /* 16-Bit Analog Output Status (Obj:40, Var:02) */
+ case AL_OBJ_AO_FLT: /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
+ case AL_OBJ_AO_DBL: /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
+
+ /* Get Point Flags */
+ al_ptflags = tvb_get_guint8(tvb, data_pos);
+ dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_OUT);
+ data_pos += 1;
+
+ switch (al_obj)
+ {
+ case AL_OBJ_AO_32: /* 32-Bit Analog Output Status (Obj:40, Var:01) */
+
+ al_val32 = tvb_get_letohl(tvb, data_pos);
+ proto_item_append_text(point_item, ", Value: %u", al_val32);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+
+ case AL_OBJ_AO_16: /* 16-Bit Analog Output Status (Obj:40, Var:02) */
+
+ al_val16 = tvb_get_letohs(tvb, data_pos);
+ proto_item_append_text(point_item, ", Value: %u", al_val16);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, TRUE);
+ data_pos += 2;
+ break;
+
+ case AL_OBJ_AO_FLT: /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
+
+ al_valflt = tvb_get_letohieee_float(tvb, data_pos);
+ proto_item_append_text(point_item, ", Value: %g", al_valflt);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, TRUE);
+ data_pos += 4;
+ break;
+
+ 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: %g", al_valdbl);
+ proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, TRUE);
+ data_pos += 8;
+ break;
+ }
+
+ proto_item_set_len(point_item, data_pos - offset);
+ offset = data_pos;
+
+ break;
+
+ case AL_OBJ_TD: /* Time and Date (Obj:50, Var:01) */
+ case AL_OBJ_TDCTO: /* Time and Date CTO (Obj:51, Var:01) */
+
+ dnp3_al_get_timestamp(&al_cto, tvb, data_pos);
+ proto_tree_add_time(object_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_cto);
+ data_pos += 6;
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_TDELAYF: /* Time Delay - Fine (Obj:52, Var:02) */
+
+ al_val16 = tvb_get_letohs(tvb, data_pos);
+ proto_tree_add_text(object_tree, tvb, data_pos, 2, "Time Delay: %u ms", al_val16);
+ data_pos += 2;
+ proto_item_set_len(point_item, data_pos - offset);
+
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_CLASS0: /* Class Data Objects */
+ case AL_OBJ_CLASS1:
+ case AL_OBJ_CLASS2:
+ case AL_OBJ_CLASS3:
+
+ /* No data here */
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_IIN: /* IIN Data Object */
+
+ /* Single byte of data here */
+ proto_tree_add_text(object_tree, tvb, data_pos, 1, "Value: %u", tvb_get_guint8(tvb, data_pos));
+ data_pos += 1;
+ proto_item_set_len(point_item, data_pos - offset);
- dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, 0);
- proto_item_append_text(point_item, ", Value: %d, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime));
- proto_tree_add_time(point_tree, hf_dnp3_al_rel_timestamp, tvb, temp_pos, 2, &al_reltime);
- proto_item_set_len(point_item, indexbytes + 3);
-
- offset += (indexbytes + 3);
-
- break;
-
- case AL_OBJ_CTLOP_BLK: /* Control Relay Output Block (Obj:12, Var:01) */
-
- al_ctlobj_code = tvb_get_guint8(tvb, temp_pos);
- temp_pos += 1;
-
- /* Bit-Mask xxxx1111 for Control Code 'Code' */
- al_ctlobj_code_c = al_ctlobj_code & AL_OBJCTLC_CODE;
- ctl_code_str = val_to_str(al_ctlobj_code_c, dnp3_al_ctlc_code_vals, "Ctrl Code Invalid (0x%02x)");
-
- /* 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, "");
-
- /* 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, "");
-
- /* Get "Count" Field */
- al_ctlobj_count = tvb_get_guint8(tvb, temp_pos);
- temp_pos += 1;
-
- /* Get "On Time" Field */
- al_ctlobj_on = tvb_get_letohl(tvb, temp_pos);
- temp_pos += 4;
-
- /* Get "Off Time" Field */
- al_ctlobj_off = tvb_get_letohl(tvb, temp_pos);
- temp_pos += 4;
-
- al_ctlobj_stat = tvb_get_guint8(tvb, temp_pos);
- proto_tree_add_item(point_item, hf_dnp3_al_ctrlstatus, tvb, temp_pos, 1, TRUE);
- ctl_status_str = val_to_str(al_ctlobj_stat, dnp3_al_ctl_status_vals, "Invalid Status (0x%02x)");
- temp_pos += 1;
-
- proto_item_append_text(point_item, ", Control Code: [%s,%s,%s (0x%02x)]",
- ctl_code_str, ctl_misc_str, ctl_tc_str, al_ctlobj_code);
-
- proto_tree_add_text(point_tree, tvb, offset, (indexbytes+11),
- " [Count: %d] [On-Time: %d] [Off-Time: %d] [Status: %s (0x%02x)]",
- al_ctlobj_count, al_ctlobj_on, al_ctlobj_off, ctl_status_str, al_ctlobj_stat);
-
- proto_item_set_len(point_item, temp_pos - offset);
- offset = temp_pos;
-
- break;
-
- case AL_OBJ_AO_32OPB: /* 32-Bit Analog Output Block (Obj:41, Var:01) */
- case AL_OBJ_AO_16OPB: /* 16-Bit Analog Output Block (Obj:41, Var:02) */
- case AL_OBJ_AO_FLTOPB: /* 32-Bit Floating Point Output Block (Obj:41, Var:03) */
- case AL_OBJ_AO_DBLOPB: /* 64-Bit Floating Point Output Block (Obj:41, Var:04) */
-
- switch (al_obj)
- {
- case AL_OBJ_AO_32OPB:
- al_val32 = tvb_get_letohl(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val32);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
- case AL_OBJ_AO_16OPB:
- al_val32 = tvb_get_letohs(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val32);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, temp_pos, 2, TRUE);
- temp_pos += 2;
- break;
- case AL_OBJ_AO_FLTOPB:
- al_valflt = tvb_get_letohieee_float(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %g", al_valflt);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
- case AL_OBJ_AO_DBLOPB:
- al_valdbl = tvb_get_letohieee_double(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, temp_pos, 8, TRUE);
- temp_pos += 8;
- break;
- }
-
- /* Get control status */
- al_ctlobj_stat = tvb_get_guint8(tvb, temp_pos);
- ctl_status_str = val_to_str(al_ctlobj_stat, dnp3_al_ctl_status_vals, "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, temp_pos, 1, TRUE);
- temp_pos += 1;
-
- proto_item_set_len(point_item, temp_pos - offset);
- offset = temp_pos;
-
- break;
-
- case AL_OBJ_CTR_32: /* 32-Bit Binary Counter (Obj:20, Var:01) */
- case AL_OBJ_CTR_16: /* 16-Bit Binary Counter (Obj:20, Var:02) */
- case AL_OBJ_CTR_32NF: /* 32-Bit Binary Counter Without Flag (Obj:20, Var:05) */
- case AL_OBJ_CTR_16NF: /* 16-Bit Binary Counter Without Flag (Obj:20, Var:06) */
- case AL_OBJ_FCTR_32: /* 32-Bit Frozen Counter (Obj:21, Var:01) */
- case AL_OBJ_FCTR_16: /* 16-Bit Frozen Counter (Obj:21, Var:02) */
- case AL_OBJ_CTRC_32: /* 32-Bit Counter Change Event w/o Time (Obj:22, Var:01) */
- case AL_OBJ_CTRC_16: /* 16-Bit Counter Change Event w/o Time (Obj:22, Var:02) */
-
- /* Get Point Flags for those types that have them */
- switch (al_obj)
- {
- case AL_OBJ_CTR_32NF:
- case AL_OBJ_CTR_16NF:
- break;
-
- default:
- al_ptflags = tvb_get_guint8(tvb, temp_pos);
- dnp3_al_obj_quality(tvb, temp_pos, al_ptflags, point_tree, point_item, 2);
- temp_pos += 1;
- break;
- }
-
- switch (al_obj)
- {
- case AL_OBJ_CTR_32:
- case AL_OBJ_CTR_32NF:
- case AL_OBJ_FCTR_32:
- case AL_OBJ_CTRC_32:
-
- al_val32 = tvb_get_letohl(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val32);
- proto_tree_add_item(point_tree, hf_dnp3_al_cnt32, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
-
- case AL_OBJ_CTR_16:
- case AL_OBJ_CTR_16NF:
- case AL_OBJ_FCTR_16:
- case AL_OBJ_CTRC_16:
-
- al_val16 = tvb_get_letohs(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val16);
- proto_tree_add_item(point_tree, hf_dnp3_al_cnt16, tvb, temp_pos, 2, TRUE);
- temp_pos += 2;
- break;
- }
- proto_item_set_len(point_item, temp_pos - offset);
- offset = temp_pos;
-
- break;
-
- case AL_OBJ_AI_32: /* 32-Bit Analog Input (Obj:30, Var:01) */
- case AL_OBJ_AI_16: /* 16-Bit Analog Input (Obj:30, Var:02) */
- case AL_OBJ_AI_32NF: /* 32-Bit Analog Input Without Flag (Obj:30, Var:03) */
- case AL_OBJ_AI_16NF: /* 16-Bit Analog Input Without Flag (Obj:30, Var:04) */
- case AL_OBJ_AI_FLT: /* 32-Bit Floating Point Input (Obj:30, Var:05) */
- case AL_OBJ_AI_DBL: /* 64-Bit Floating Point Input (Obj:30, Var:06) */
- case AL_OBJ_AIF_FLT: /* 32-Bit Frozen Floating Point Input (Obj:31, Var:07) */
- case AL_OBJ_AIF_DBL: /* 64-Bit Frozen Floating Point Input (Obj:31, Var:08) */
- case AL_OBJ_AIC_32NT: /* 32-Bit Analog Change Event w/o Time (Obj:32, Var:01) */
- case AL_OBJ_AIC_16NT: /* 16-Bit Analog Change Event w/o Time (Obj:32, Var:02) */
- case AL_OBJ_AIC_32T: /* 32-Bit Analog Change Event with Time (Obj:32, Var:03) */
- case AL_OBJ_AIC_16T: /* 16-Bit Analog Change Event with Time (Obj:32, Var:04) */
- case AL_OBJ_AIC_FLTNT: /* 32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05) */
- case AL_OBJ_AIC_DBLNT: /* 64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06) */
- case AL_OBJ_AIC_FLTT: /* 32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07) */
- case AL_OBJ_AIC_DBLT: /* 64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08) */
- case AL_OBJ_AIFC_FLTNT: /* 32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05) */
- 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) */
-
- /* Get Point Flags for those types that have them */
- switch (al_obj)
- {
- case AL_OBJ_AI_32NF:
- case AL_OBJ_AI_16NF:
- break;
-
- default:
- al_ptflags = tvb_get_guint8(tvb, temp_pos);
- dnp3_al_obj_quality(tvb, temp_pos, al_ptflags, point_tree, point_item, 3);
- temp_pos += 1;
- break;
- }
-
- switch (al_obj)
- {
- case AL_OBJ_AI_32:
- case AL_OBJ_AI_32NF:
- case AL_OBJ_AIC_32NT:
- case AL_OBJ_AIC_32T:
-
- al_val32 = tvb_get_letohl(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val32);
- proto_tree_add_item(point_tree, hf_dnp3_al_ana32, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
-
- case AL_OBJ_AI_16:
- case AL_OBJ_AI_16NF:
- case AL_OBJ_AIC_16NT:
- case AL_OBJ_AIC_16T:
-
- al_val16 = tvb_get_letohs(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val16);
- proto_tree_add_item(point_tree, hf_dnp3_al_ana16, tvb, temp_pos, 2, TRUE);
- temp_pos += 2;
- break;
-
- case AL_OBJ_AI_FLT:
- case AL_OBJ_AIF_FLT:
- case AL_OBJ_AIC_FLTNT:
- case AL_OBJ_AIC_FLTT:
- case AL_OBJ_AIFC_FLTNT:
- case AL_OBJ_AIFC_FLTT:
-
- al_valflt = tvb_get_letohieee_float(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %g", al_valflt);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaflt, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
-
- case AL_OBJ_AI_DBL:
- case AL_OBJ_AIF_DBL:
- case AL_OBJ_AIC_DBLNT:
- case AL_OBJ_AIC_DBLT:
- case AL_OBJ_AIFC_DBLNT:
- case AL_OBJ_AIFC_DBLT:
-
- al_valdbl = tvb_get_letohieee_double(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
- proto_tree_add_item(point_tree, hf_dnp3_al_anadbl, tvb, temp_pos, 8, TRUE);
- temp_pos += 8;
- break;
- }
-
- /* Get timestamp */
- switch (al_obj)
- {
- case AL_OBJ_AIC_32T:
- case AL_OBJ_AIC_16T:
- case AL_OBJ_AIC_FLTT:
- case AL_OBJ_AIC_DBLT:
- case AL_OBJ_AIFC_FLTT:
- case AL_OBJ_AIFC_DBLT:
- dnp3_al_get_timestamp(&al_abstime, tvb, temp_pos);
- proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime));
- proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, temp_pos, 6, &al_abstime);
- temp_pos += 6;
- break;
- }
-
- proto_item_set_len(point_item, temp_pos - offset);
- offset = temp_pos;
-
- break;
-
- case AL_OBJ_AO_32: /* 32-Bit Analog Output Status (Obj:40, Var:01) */
- case AL_OBJ_AO_16: /* 16-Bit Analog Output Status (Obj:40, Var:02) */
- case AL_OBJ_AO_FLT: /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
- case AL_OBJ_AO_DBL: /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
-
- /* Get Point Flags */
- al_ptflags = tvb_get_guint8(tvb, temp_pos);
- dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, 4);
- temp_pos += 1;
-
- switch (al_obj)
- {
- case AL_OBJ_AO_32: /* 32-Bit Analog Output Status (Obj:40, Var:01) */
-
- al_val32 = tvb_get_letohl(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val32);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
-
- case AL_OBJ_AO_16: /* 16-Bit Analog Output Status (Obj:40, Var:02) */
-
- al_val16 = tvb_get_letohs(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %d", al_val16);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, temp_pos, 2, TRUE);
- temp_pos += 2;
- break;
-
- case AL_OBJ_AO_FLT: /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
-
- al_valflt = tvb_get_letohieee_float(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %g", al_valflt);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, temp_pos, 4, TRUE);
- temp_pos += 4;
- break;
-
- case AL_OBJ_AO_DBL: /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
-
- al_valdbl = tvb_get_letohieee_double(tvb, temp_pos);
- proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
- proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, temp_pos, 8, TRUE);
- temp_pos += 8;
- break;
- }
-
- proto_item_set_len(point_item, temp_pos - offset);
- offset = temp_pos;
-
- break;
-
- case AL_OBJ_TD: /* Time and Date (Obj:50, Var:01) */
- case AL_OBJ_TDCTO: /* Time and Date CTO (Obj:51, Var:01) */
-
- dnp3_al_get_timestamp(&al_cto, tvb, offset);
- proto_tree_add_time(object_tree, hf_dnp3_al_timestamp, tvb, offset, 6, &al_cto);
- offset += (indexbytes + 6);
- break;
-
- case AL_OBJ_TDELAYF: /* Time Delay - Fine (Obj:52, Var:02) */
-
- al_val16 = tvb_get_letohs(tvb, offset);
- proto_tree_add_text(object_tree, tvb, offset, (indexbytes + 2),"Time Delay: %d ms", al_val16);
- offset += (indexbytes + 2);
- break;
-
- case AL_OBJ_CLASS0: /* Class Data Objects */
- case AL_OBJ_CLASS1:
- case AL_OBJ_CLASS2:
- case AL_OBJ_CLASS3:
-
- /* Process Index */
- offset += indexbytes;
- break;
-
- case AL_OBJ_IIN: /* IIN Data Object */
-
- /* Process Index */
- offset += indexbytes;
- break;
-
- default: /* In case of unknown object */
-
- proto_tree_add_text(object_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
- "Unknown Data Chunk, %d Bytes", tvb_reported_length_remaining(tvb, offset));
- offset = tvb_length(tvb); /* Finish decoding if unknown object is encountered... */
- break;
- }
- /* Increment the bit index for next time */
- bitindex++;
+ offset = data_pos;
+ break;
+
+ case AL_OBJ_OCT: /* Octet string */
+
+ /* read the number of bytes defined by the variation */
+ if (al_oct_len > 0) {
+ proto_tree_add_text(object_tree, tvb, data_pos, al_oct_len, "Octet String (%u bytes)", al_oct_len);
+ data_pos += al_oct_len;
+ proto_item_set_len(point_item, data_pos - offset);
+ }
- /* And increment the poit address, may be overwritten bu an index value */
- al_ptaddr++;
+ offset = data_pos;
+ break;
+
+ default: /* In case of unknown object */
+
+ proto_tree_add_text(object_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ "Unknown Data Chunk, %u Bytes", tvb_reported_length_remaining(tvb, offset));
+ offset = tvb_length(tvb); /* Finish decoding if unknown object is encountered... */
+ break;
+ }
+ /* Increment the bit index for next time */
+ bitindex++;
+
+ /* And increment the point address, may be overwritten by an index value */
+ al_ptaddr++;
+ }
+ if (start_offset > offset) {
+ expert_add_info_format(pinfo, point_item, PI_MALFORMED, PI_ERROR, "Invalid length");
+ offset = tvb_length(tvb); /* Finish decoding if unknown object is encountered... */
+ }
}
}
proto_item_set_len(object_item, offset - orig_offset);
return offset;
-
}
/*****************************************************************/
/* Application Layer Dissector */
/*****************************************************************/
static int
-dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- guint8 al_ctl, al_seq, al_func;
- guint16 bytes;
- gboolean al_fir, al_fin, al_con;
+ guint8 al_ctl, al_seq, al_func, al_class = 0, i;
+ guint16 bytes, obj_type;
+ 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;
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)");
-
- if (tree) {
- /* format up the text representation */
- ti = proto_tree_add_text(tree, tvb, offset, data_len, "Application Layer: (");
- if (al_ctl & DNP3_AL_FIR) proto_item_append_text(ti, "FIR, ");
- if (al_ctl & DNP3_AL_FIN) proto_item_append_text(ti, "FIN, ");
- if (al_ctl & DNP3_AL_CON) proto_item_append_text(ti, "CON, ");
- proto_item_append_text(ti, "Sequence %d, %s)", al_seq, func_code_str);
-
- /* Add the al tree branch */
- al_tree = proto_item_add_subtree(ti, ett_dnp3_al);
-
- /* Application Layer control byte subtree */
- tc = proto_tree_add_uint_format(al_tree, hf_dnp3_al_ctl, tvb, offset, 1, al_ctl,
- "Control: 0x%02x (", al_ctl);
- 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, ");
- proto_item_append_text(tc, "Sequence %d)", 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_item(field_tree, hf_dnp3_al_seq, tvb, offset, 1, FALSE);
- offset += 1;
+ func_code_str = val_to_str_ext(al_func, &dnp3_al_func_vals_ext, "Unknown function (0x%02x)");
- /* If this packet is NOT the final Application Layer Message, exit and continue
- 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;
- } */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", func_code_str);
+ col_set_fence(pinfo->cinfo, COL_INFO);
+
+ /* format up the text representation */
+ ti = proto_tree_add_text(tree, tvb, offset, data_len, "Application Layer: (");
+ if (al_ctl & DNP3_AL_FIR) proto_item_append_text(ti, "FIR, ");
+ if (al_ctl & DNP3_AL_FIN) proto_item_append_text(ti, "FIN, ");
+ if (al_ctl & DNP3_AL_CON) proto_item_append_text(ti, "CON, ");
+ proto_item_append_text(ti, "Sequence %u, %s)", al_seq, func_code_str);
+
+ /* Add the al tree branch */
+ al_tree = proto_item_add_subtree(ti, ett_dnp3_al);
+
+ /* Application Layer control byte subtree */
+ tc = proto_tree_add_uint_format(al_tree, hf_dnp3_al_ctl, tvb, offset, 1, al_ctl,
+ "Control: 0x%02x (", al_ctl);
+ 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;
- /* Application Layer Function Code Byte */
- proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
- "Function Code: %s (0x%02x)", func_code_str, al_func);
- offset += 1;
+#if 0
+ /* If this packet is NOT the final Application Layer Message, exit and continue
+ 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
- switch (al_func) {
+ /* Application Layer Function Code Byte */
+ proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
+ "Function Code: %s (0x%02x)", func_code_str, al_func);
+ offset += 1;
- case AL_FUNC_READ: /* Read Function Code 0x01 */
+ switch (al_func) {
- /* Create Read Request Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "READ Request Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ case AL_FUNC_READ: /* Read Function Code 0x01 */
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, TRUE);
- }
+ /* Create Read Request Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "READ Request Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, TRUE, &obj_type);
+
+ /* Update class type for each object that was a class read */
+ switch(obj_type) {
+ case AL_OBJ_CLASS0:
+ case AL_OBJ_CLASS1:
+ case AL_OBJ_CLASS2:
+ case AL_OBJ_CLASS3:
+ al_class |= (1 << ((obj_type & 0x0f) - 1));
+ break;
+ default:
break;
+ }
+ }
- case AL_FUNC_WRITE: /* Write Function Code 0x02 */
+ /* Update the col info if there were class reads */
+ if (check_col(pinfo->cinfo, COL_INFO) && (al_class > 0)) {
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Class ");
+ for (i = 0; i < 4; i++) {
+ if (al_class & (1 << i)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%u", i);
+ }
+ }
+ }
- /* Create Write Request Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "WRITE Request Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ break;
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE);
- }
+ case AL_FUNC_WRITE: /* Write Function Code 0x02 */
- break;
+ /* Create Write Request Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "WRITE Request Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
- case AL_FUNC_SELECT: /* Select Function Code 0x03 */
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type);
+ }
- /* Create Select Request Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "SELECT Request Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ break;
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE);
- }
+ case AL_FUNC_SELECT: /* Select Function Code 0x03 */
- break;
+ /* Create Select Request Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "SELECT Request Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
- case AL_FUNC_OPERATE: /* Operate Function Code 0x04 */
- /* Functionally identical to 'SELECT' Function Code */
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type);
+ }
- /* Create Operate Request Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "OPERATE Request Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ break;
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE);
- }
+ case AL_FUNC_OPERATE: /* Operate Function Code 0x04 */
+ /* Functionally identical to 'SELECT' Function Code */
- break;
+ /* Create Operate Request Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "OPERATE Request Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
- case AL_FUNC_DIROP: /* Direct Operate Function Code 0x05 */
- /* Functionally identical to 'SELECT' Function Code */
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type);
+ }
- /* Create Direct Operate Request Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "DIRECT OPERATE Request Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ break;
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE);
- }
+ case AL_FUNC_DIROP: /* Direct Operate Function Code 0x05 */
+ /* Functionally identical to 'SELECT' Function Code */
- break;
+ /* Create Direct Operate Request Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "DIRECT OPERATE Request Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
- case AL_FUNC_ENSPMSG: /* Enable Spontaneous Messages Function Code 0x14 */
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type);
+ }
- /* Create Enable Spontaneous Messages Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Enable Spontaneous Msg's Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ break;
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE);
- }
+ case AL_FUNC_ENSPMSG: /* Enable Spontaneous Messages Function Code 0x14 */
- break;
+ /* Create Enable Spontaneous Messages Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Enable Spontaneous Msg's Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
- case AL_FUNC_DELAYMST: /* Delay Measurement Function Code 0x17 */
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type);
+ }
- break;
+ break;
- case AL_FUNC_RESPON: /* Response Function Code 0x81 */
- case AL_FUNC_UNSOLI: /* Unsolicited Response Function Code 0x82 */
+ case AL_FUNC_DELAYMST: /* Delay Measurement Function Code 0x17 */
- /* Application Layer IIN bits req'd if message is a response */
- dnp3_al_process_iin(tvb, offset, al_tree);
- offset += 2;
+ break;
- /* Ensure there is actual data remaining in the message.
- A response will not contain data following the IIN bits,
- if there is none available */
- bytes = tvb_reported_length_remaining(tvb, offset);
- if (bytes > 0)
- {
- /* Create Response Data Objects Tree */
- t_robj = proto_tree_add_text(al_tree, tvb, offset, -1,"RESPONSE Data Objects");
- robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
+ case AL_FUNC_RESPON: /* Response Function Code 0x81 */
+ case AL_FUNC_UNSOLI: /* Unsolicited Response Function Code 0x82 */
- /* Process Data Object Details */
- while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
- offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE);
- }
-
- break;
- }
+ /* Application Layer IIN bits req'd if message is a response */
+ dnp3_al_process_iin(tvb, offset, al_tree);
+ offset += 2;
- default: /* Unknown Function */
+ /* Ensure there is actual data remaining in the message.
+ A response will not contain data following the IIN bits,
+ if there is none available */
+ bytes = tvb_reported_length_remaining(tvb, offset);
+ if (bytes > 0)
+ {
+ /* Create Response Data Objects Tree */
+ t_robj = proto_tree_add_text(al_tree, tvb, offset, -1,"RESPONSE Data Objects");
+ robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
- break;
+ /* Process Data Object Details */
+ while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
+ offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type);
}
+
+ break;
}
- else
- {
- offset += 2; /* No tree, correct offset */
+
+ default: /* Unknown Function */
+
+ break;
}
return 0;
{
/* Set up structures needed to add the protocol subtree and manage it */
- proto_item *ti = NULL, *tdl, *tc, *al_chunks;
+ proto_item *ti = NULL, *tdl, *tc, *al_chunks, *hidden_item;
proto_tree *dnp3_tree = NULL, *dl_tree = NULL, *tr_tree = NULL, *field_tree = NULL, *al_tree = NULL;
int offset = 0, temp_offset = 0, al_result = 0;
gboolean dl_prm, tr_fir, tr_fin;
/* 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;
"Unknown function (0x%02x)");
if (check_col(pinfo->cinfo, COL_INFO))
- col_append_fstr(pinfo->cinfo, COL_INFO, "len=%d, from %d to %d, %s",
+ col_append_fstr(pinfo->cinfo, COL_INFO, "len=%u, from %u to %u, %s",
dl_len, dl_src, dl_dst, func_code_str);
- if (tree) {
-
- /* create display subtree for the protocol */
- ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, FALSE);
- dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, FALSE);
+ dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);
+
+ /* Create Subtree for Data Link Layer */
+ tdl = proto_tree_add_text(dnp3_tree, tvb, offset, DNP_HDR_LEN,
+ "Data Link Layer, Len: %u, From: %u, To: %u, ", dl_len, dl_src, dl_dst);
+ if (dl_prm) {
+ if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
+ if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
+ if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tdl, "FCB, ");
+ if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tdl, "FCV, ");
+ }
+ else {
+ if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
+ if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
+ 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, "%s", func_code_str);
+ dl_tree = proto_item_add_subtree(tdl, ett_dnp3_dl);
- /* Create Subtree for Data Link Layer */
- tdl = proto_tree_add_text(dnp3_tree, tvb, offset, DNP_HDR_LEN,
- "Data Link Layer, Len: %d, From: %d, To: %d, ", dl_len, dl_src, dl_dst);
- if (dl_prm) {
- if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
- if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
- if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tdl, "FCB, ");
- if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tdl, "FCV, ");
- }
- else {
- if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
- if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
- 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);
- dl_tree = proto_item_add_subtree(tdl, ett_dnp3_dl);
+ /* start bytes */
+ proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, FALSE);
+ offset += 2;
- /* start bytes */
- proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, FALSE);
- offset += 2;
+ /* add length field */
+ proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, FALSE);
+ offset += 1;
- /* add length field */
- proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, FALSE);
+ /* Add Control Byte Subtree */
+ tc = proto_tree_add_uint_format(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
+ "Control: 0x%02x (", dl_ctl);
+ /* Add Text to Control Byte Subtree Header */
+ if (dl_prm) {
+ if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
+ if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
+ if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tc, "FCB, ");
+ if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tc, "FCV, ");
+ }
+ else {
+ if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
+ if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
+ if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tc, "RES, ");
+ if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tc, "DFC, ");
+ }
+ proto_item_append_text(tc, "%s)", func_code_str );
+ field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);
+
+ /* Add Control Byte Subtree Items */
+ if (dl_prm) {
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, FALSE);
+ }
+ else {
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, FALSE);
+ }
offset += 1;
- /* Add Control Byte Subtree */
- tc = proto_tree_add_uint_format(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
- "Control: 0x%02x (", dl_ctl);
- /* Add Text to Control Byte Subtree Header */
- if (dl_prm) {
- if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
- if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
- if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tc, "FCB, ");
- if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tc, "FCV, ");
- }
- else {
- if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
- if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
- if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tc, "RES, ");
- if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tc, "DFC, ");
- }
- proto_item_append_text(tc, "%s)", func_code_str );
- field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);
-
- /* Add Control Byte Subtree Items */
- if (dl_prm) {
- proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, FALSE);
- }
- else {
- proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, TRUE);
- proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, FALSE);
- }
- offset += 1;
-
- /* add destination and source addresses */
- proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, TRUE);
- offset += 2;
- proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, TRUE);
- offset += 2;
-
- /* and header CRC */
- dl_crc = tvb_get_letohs(tvb, offset);
- calc_dl_crc = calculateCRC(tvb_get_ptr(tvb, 0, DNP_HDR_LEN - 2), DNP_HDR_LEN - 2);
- if (dl_crc == calc_dl_crc)
- proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
- dl_crc, "CRC: 0x%04x [correct]", dl_crc);
- else
- {
- proto_tree_add_boolean_hidden(dl_tree, hf_dnp_hdr_CRC_bad, tvb,
- offset, 2, TRUE);
- proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb,
- offset, 2, dl_crc, "CRC: 0x%04x [incorrect, should be 0x%04x]",
- dl_crc, calc_dl_crc);
- }
- offset += 2;
- }
+ /* add destination and source addresses */
+ proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* and header CRC */
+ dl_crc = tvb_get_letohs(tvb, offset);
+ calc_dl_crc = calculateCRC(tvb_get_ptr(tvb, 0, DNP_HDR_LEN - 2), DNP_HDR_LEN - 2);
+ if (dl_crc == calc_dl_crc)
+ proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
+ dl_crc, "CRC: 0x%04x [correct]", dl_crc);
else
{
- offset += 10; /* No tree so correct offset */
+ hidden_item = proto_tree_add_boolean(dl_tree, hf_dnp_hdr_CRC_bad, tvb,
+ offset, 2, TRUE);
+ PROTO_ITEM_SET_HIDDEN(hidden_item);
+ proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
+ dl_crc, "CRC: 0x%04x [incorrect, should be 0x%04x]",
+ dl_crc, calc_dl_crc);
}
+ offset += 2;
/* If the DataLink function is 'Request Link Status' or 'Status of Link',
or 'Reset Link' we don't expect any Transport or Application Layer Data
tr_fir = tr_ctl & DNP3_TR_FIR;
tr_fin = tr_ctl & DNP3_TR_FIN;
- if (tree)
- {
- /* Add Transport Layer Tree */
- tc = proto_tree_add_uint_format(dnp3_tree, hf_dnp3_tr_ctl, tvb, offset, 1, tr_ctl,
- "Transport Layer: 0x%02x (", tr_ctl);
- if (tr_fir) proto_item_append_text(tc, "FIR, ");
- if (tr_fin) proto_item_append_text(tc, "FIN, ");
- proto_item_append_text(tc, "Sequence %d)", tr_seq);
-
- tr_tree = proto_item_add_subtree(tc, ett_dnp3_tr_ctl);
- proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fin, tvb, offset, 1, tr_ctl);
- proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fir, tvb, offset, 1, tr_ctl);
- proto_tree_add_item(tr_tree, hf_dnp3_tr_seq, tvb, offset, 1, FALSE);
- }
+ /* Add Transport Layer Tree */
+ tc = proto_tree_add_uint_format(dnp3_tree, hf_dnp3_tr_ctl, tvb, offset, 1, tr_ctl,
+ "Transport Layer: 0x%02x (", tr_ctl);
+ if (tr_fir) proto_item_append_text(tc, "FIR, ");
+ if (tr_fin) proto_item_append_text(tc, "FIN, ");
+ proto_item_append_text(tc, "Sequence %u)", tr_seq);
+
+ tr_tree = proto_item_add_subtree(tc, ett_dnp3_tr_ctl);
+ proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fin, tvb, offset, 1, tr_ctl);
+ proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fir, tvb, offset, 1, tr_ctl);
+ proto_tree_add_item(tr_tree, hf_dnp3_tr_seq, tvb, offset, 1, FALSE);
/* Allocate AL chunk tree */
- if (tree != NULL)
- {
- al_chunks = proto_tree_add_text(tr_tree, tvb, offset + 1, -1, "Application data chunks");
- al_tree = proto_item_add_subtree(al_chunks, ett_dnp3_al_data);
- }
+ al_chunks = proto_tree_add_text(tr_tree, tvb, offset + 1, -1, "Application data chunks");
+ al_tree = proto_item_add_subtree(al_chunks, ett_dnp3_al_data);
/* extract the application layer data, validating the CRCs */
/* 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 */
crc_OK = calc_crc == act_crc;
if (crc_OK)
{
- if (tree)
- {
- proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
- "Application Chunk %d Len: %d CRC 0x%04x",
- i, chk_size, act_crc);
- }
+ proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
+ "Application Chunk %u Len: %u CRC 0x%04x",
+ i, chk_size, act_crc);
data_len -= chk_size;
}
else
{
- if (tree)
- {
- proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
- "Application Chunk %d Len: %d Bad CRC got 0x%04x expected 0x%04x",
- i, chk_size, act_crc, calc_crc);
- }
+ proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
+ "Application Chunk %u Len: %u Bad CRC got 0x%04x expected 0x%04x",
+ i, chk_size, act_crc, calc_crc);
data_len = 0;
break;
}
/* 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;
/* A fragmented packet */
pinfo->fragmented = TRUE;
- /* look up the conversation */
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
- pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ /* Look up the conversation to get the fragment reassembly id */
+ conversation = find_or_create_conversation(pinfo);
- /* if conversation found get the data pointer that you stored */
- if (conversation && (!tr_fir || (conversation->setup_frame == pinfo->fd->num)))
- conv_data_ptr = (dnp3_conv_t*)conversation_get_proto_data(conversation, proto_dnp3);
+ conv_data_ptr = (dnp3_conv_t*)conversation_get_proto_data(conversation, proto_dnp3);
- else {
- /* new conversation create local data structure */
- conv_data_ptr = g_mem_chunk_alloc(dnp3_conv_vals);
+ if (conv_data_ptr == NULL) {
+ /* New data structure required */
+ conv_data_ptr = se_alloc(sizeof(dnp3_conv_t));
- /*** Increment static global ***/
+ /*** Increment static global fragment reassembly id ***/
conv_data_ptr->conv_seq_number = seq_number++;
- /* create the conversation with your data pointer */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
- pinfo->srcport, pinfo->destport, 0);
conversation_add_proto_data(conversation, proto_dnp3, (void *)conv_data_ptr);
}
conv_seq_number = conv_data_ptr->conv_seq_number;
/*
- * If we've already seen this frame, look it up in the
- * table of reassembled packets, otherwise add it to
+ * Add the frame to
* whatever reassembly is in progress, if any, and see
* if it's done.
*/
- frag_msg = fragment_add_seq_check(al_tvb, 0, pinfo, conv_seq_number,
- al_fragment_table,
- al_reassembled_table,
- tr_seq,
- tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
- !tr_fin);
+
+ frag_msg = fragment_add_seq_next(al_tvb, 0, pinfo, conv_seq_number,
+ al_fragment_table,
+ al_reassembled_table,
+ tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
+ !tr_fin);
next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
"Reassembled DNP 3.0 Application Layer message", frag_msg, &dnp3_frag_items,
&update_col_info, tr_tree);
- if (frag_msg) { /* Reassembled */
+ if (next_tvb) { /* Reassembled */
/* We have the complete payload */
if (check_col (pinfo->cinfo, COL_INFO))
- col_append_str (pinfo->cinfo, COL_INFO,
- " (Application Layer Message reassembled)");
+ col_set_str(pinfo->cinfo, COL_INFO, "Reassembled Application Layer");
+ col_set_fence(pinfo->cinfo, COL_INFO);
}
else
{
/* We don't have the complete reassembled payload. */
- next_tvb = NULL;
if (check_col (pinfo->cinfo, COL_INFO))
- col_append_fstr (pinfo->cinfo, COL_INFO,
- " (Application Layer Message %u unreassembled)", tr_seq);
+ col_add_fstr (pinfo->cinfo, COL_INFO,
+ "Application Layer fragment %u", tr_seq);
+ col_set_fence(pinfo->cinfo, COL_INFO);
}
}
/* No reassembly required */
next_tvb = al_tvb;
add_new_data_source(pinfo, next_tvb, "DNP 3.0 Application Layer message");
+ col_clear(pinfo->cinfo, COL_INFO);
}
pinfo->fragmented = save_fragmented;
}
{
/* CRC error - throw away the data. */
next_tvb = NULL;
- if (tree)
- proto_tree_add_text(dnp3_tree, tvb, 11, -1, "CRC failed, %d chunks", i);
+ g_free(tmp);
+ proto_tree_add_text(dnp3_tree, tvb, 11, -1, "CRC failed, %u chunks", i);
}
if (next_tvb)
static int
dissect_dnp3_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- gint length = tvb_length_remaining(tvb, 0);
+ gint length = tvb_length(tvb);
/* Check for a dnp packet. It should begin with 0x0564 */
if(length < DNP_HDR_LEN || tvb_get_ntohs(tvb, 0) != 0x0564) {
static int
dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- gint length = tvb_length_remaining(tvb, 0);
+ gint length = tvb_length(tvb);
/* Check for a dnp packet. It should begin with 0x0564 */
if(length < DNP_HDR_LEN || tvb_get_ntohs(tvb, 0) != 0x0564) {
/* Not a DNP 3.0 packet, just happened to use the same port */
return length;
}
-static void
-dnp3_init(void)
-{
- /* destroy memory chunks if needed */
-
- if (dnp3_conv_vals)
- g_mem_chunk_destroy(dnp3_conv_vals);
-
- /* now create memory chunks */
-
- dnp3_conv_vals = g_mem_chunk_new("dnp3_proto_vals",
- sizeof(dnp3_conv_t),
- dnp3_conv_init_count * sizeof(dnp3_conv_t),
- G_ALLOC_AND_FREE);
-}
-
static void
al_defragment_init(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 }},
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 }},
{ "Source", "dnp3.src", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Address", HFILL }},
{ &hf_dnp_hdr_CRC,
- { "CRC", "dnp.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", "dnp.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 }},
{ "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 }},
{ "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 }},
{ "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 }},
{ "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 }},
{ &hf_dnp3_fragment,
- { "DNP 3.0 AL Fragment", "al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragment", HFILL }},
+ { "DNP 3.0 AL Fragment", "dnp3.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragment", HFILL }},
{ &hf_dnp3_fragments,
- { "DNP 3.0 AL Fragments", "al.fragments", FT_NONE, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragments", HFILL }},
+ { "DNP 3.0 AL Fragments", "dnp3.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragments", HFILL }},
{ &hf_dnp3_fragment_overlap,
- { "Fragment overlap", "al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+ { "Fragment overlap", "dnp3.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
{ &hf_dnp3_fragment_overlap_conflict,
- { "Conflicting data in fragment overlap", "al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ { "Conflicting data in fragment overlap", "dnp3.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Overlapping fragments contained conflicting data", HFILL }},
{ &hf_dnp3_fragment_multiple_tails,
- { "Multiple tail fragments found", "al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ { "Multiple tail fragments found", "dnp3.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Several tails were found when defragmenting the packet", HFILL }},
{ &hf_dnp3_fragment_too_long_fragment,
- { "Fragment too long", "al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ { "Fragment too long", "dnp3.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"Fragment contained data past end of packet", HFILL }},
{ &hf_dnp3_fragment_error,
- { "Defragmentation error", "al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ { "Defragmentation error", "dnp3.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
"Defragmentation error due to illegal fragments", HFILL }},
{ &hf_dnp3_fragment_reassembled_in,
- { "Reassembled PDU In Frame", "al.fragment.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
- "This PDU is reassembled in this frame", HFILL }}
+ { "Reassembled PDU In Frame", "dnp3.al.fragment.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "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 */
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",
"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)
{
dissector_add("tcp.port", TCP_PORT_DNP, dnp3_tcp_handle);
dissector_add("udp.port", UDP_PORT_DNP, dnp3_udp_handle);
}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */
+