1 /* packet-dnp.c
2  * Routines for DNP dissection
3  * Copyright 2003, 2006, 2007, 2013 Graham Bloice <graham.bloice<at>trihedral.com>
4  *
5  * DNP3.0 Application Layer Object dissection added by Chris Bontje (cbontje<at>gmail.com)
6  * Device attribute dissection added by Chris Bontje
7  * Copyright 2005, 2013
8  *
9  * Major updates: tcp and application layer defragmentation, more object dissections by Graham Bloice
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * SPDX-License-Identifier: GPL-2.0-or-later
16  */
17 
18 #include "config.h"
19 
20 #include <math.h>
21 
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/reassemble.h>
25 #include "packet-tcp.h"
26 #include "packet-udp.h"
27 #include <epan/expert.h>
28 #include <epan/to_str.h>
29 #include <epan/crc16-tvb.h>
30 #include <wsutil/crc16.h>
31 #include <wsutil/str_util.h>
32 #include "packet-tls.h"
33 
34 /*
35  * See
36  *
37  * http://www.dnp.org/
38  *
39  * although note that you have to join the DNP organization to get to
40  * see the protocol specs online - otherwise, you have to buy a
41  * dead-tree version.
42  *
43  * ...Application Layer Notes...
44  *
45  * Application Layer Decoding based on information available in
46  * DNP3 Basic 4 Documentation Set, specifically the document:
47  * "DNP V3.00 Application Layer" v0.03 P009-0PD.APP & Technical Bulletins
48  *
49  * ---------------------------------------------------------------------------
50  *
51  * Several command codes were missing, causing the dissector to abort decoding
52  * on valid packets.  Those commands have been added.
53  *
54  * The semantics of Variation 0 have been cleaned up.  Variation 0 is the
55  * "Default Variation".  It is used only in Master -> Slave read commands
56  * to request the data in whatever variation the Slave is configured to use by
57  * default. Decoder strings have been added to the Binary Output and
58  * Analog Output objects (10 and 40) so that group read commands will
59  * decode properly.
60  *
61  * Roy M. Silvernail <roy@rant-central.com> 01/05/2009
62  *
63  */
64 
65 /***************************************************************************/
66 /* DNP 3.0 Constants */
67 /***************************************************************************/
68 #define DNP_HDR_LEN     10
69 #define TCP_PORT_DNP    20000
70 #define UDP_PORT_DNP    20000
71 #define TCP_PORT_DNP_TLS    19999
72 
73 /***************************************************************************/
74 /* Datalink and Transport Layer Bit-Masks */
75 /***************************************************************************/
76 #define DNP3_CTL_DIR    0x80
77 #define DNP3_CTL_PRM    0x40
78 #define DNP3_CTL_FCB    0x20
79 #define DNP3_CTL_FCV    0x10
80 #define DNP3_CTL_RES    0x20
81 #define DNP3_CTL_DFC    0x10
82 #define DNP3_CTL_FUNC   0x0f
83 
84 #define DNP3_TR_FIR     0x40
85 #define DNP3_TR_FIN     0x80
86 #define DNP3_TR_SEQ     0x3f
87 
88 #define AL_MAX_CHUNK_SIZE 16
89 
90 /***************************************************************************/
91 /* Data Link Function codes */
92 /***************************************************************************/
93 /* Primary to Secondary */
94 #define DL_FUNC_RESET_LINK  0x00
95 #define DL_FUNC_RESET_PROC  0x01
96 #define DL_FUNC_TEST_LINK   0x02
97 #define DL_FUNC_USER_DATA   0x03
98 #define DL_FUNC_UNC_DATA    0x04
99 #define DL_FUNC_LINK_STAT   0x09
100 
101 /* Secondary to Primary */
102 #define DL_FUNC_ACK         0x00
103 #define DL_FUNC_NACK        0x01
104 #define DL_FUNC_STAT_LINK   0x0B
105 #define DL_FUNC_NO_FUNC     0x0E
106 #define DL_FUNC_NOT_IMPL    0x0F
107 
108 /***************************************************************************/
109 /* Application Layer Bit-Masks */
110 /***************************************************************************/
111 #define DNP3_AL_UNS   0x10
112 #define DNP3_AL_CON   0x20
113 #define DNP3_AL_FIN   0x40
114 #define DNP3_AL_FIR   0x80
115 #define DNP3_AL_SEQ   0x0f
116 #define DNP3_AL_FUNC  0xff
117 
118 /***************************************************************************/
119 /* Application Layer Function codes */
120 /***************************************************************************/
121 #define AL_FUNC_CONFIRM    0x00    /* 00  - Confirm */
122 #define AL_FUNC_READ       0x01    /* 01  - Read */
123 #define AL_FUNC_WRITE      0x02    /* 02  - Write */
124 #define AL_FUNC_SELECT     0x03    /* 03  - Select */
125 #define AL_FUNC_OPERATE    0x04    /* 04  - Operate */
126 #define AL_FUNC_DIROP      0x05    /* 05  - Direct Operate */
127 #define AL_FUNC_DIROPNACK  0x06    /* 06  - Direct Operate No ACK */
128 #define AL_FUNC_FRZ        0x07    /* 07  - Immediate Freeze */
129 #define AL_FUNC_FRZNACK    0x08    /* 08  - Immediate Freeze No ACK */
130 #define AL_FUNC_FRZCLR     0x09    /* 09  - Freeze and Clear */
131 #define AL_FUNC_FRZCLRNACK 0x0A    /* 10  - Freeze and Clear No ACK */
132 #define AL_FUNC_FRZT       0x0B    /* 11  - Freeze With Time */
133 #define AL_FUNC_FRZTNACK   0x0C    /* 12  - Freeze With Time No ACK */
134 #define AL_FUNC_COLDRST    0x0D    /* 13  - Cold Restart */
135 #define AL_FUNC_WARMRST    0x0E    /* 14  - Warm Restart */
136 #define AL_FUNC_INITDATA   0x0F    /* 15  - Initialize Data */
137 #define AL_FUNC_INITAPP    0x10    /* 16  - Initialize Application */
138 #define AL_FUNC_STARTAPP   0x11    /* 17  - Start Application */
139 #define AL_FUNC_STOPAPP    0x12    /* 18  - Stop Application */
140 #define AL_FUNC_SAVECFG    0x13    /* 19  - Save Configuration */
141 #define AL_FUNC_ENSPMSG    0x14    /* 20  - Enable Spontaneous Msg */
142 #define AL_FUNC_DISSPMSG   0x15    /* 21  - Disable Spontaneous Msg */
143 #define AL_FUNC_ASSIGNCL   0x16    /* 22  - Assign Classes */
144 #define AL_FUNC_DELAYMST   0x17    /* 23  - Delay Measurement */
145 #define AL_FUNC_RECCT      0x18    /* 24  - Record Current Time */
146 #define AL_FUNC_OPENFILE   0x19    /* 25  - Open File */
147 #define AL_FUNC_CLOSEFILE  0x1A    /* 26  - Close File */
148 #define AL_FUNC_DELETEFILE 0x1B    /* 27  - Delete File */
149 #define AL_FUNC_GETFILEINF 0x1C    /* 28  - Get File Info */
150 #define AL_FUNC_AUTHFILE   0x1D    /* 29  - Authenticate File */
151 #define AL_FUNC_ABORTFILE  0x1E    /* 30  - Abort File */
152 #define AL_FUNC_ACTCNF     0x1F    /* 31  - Activate Config */
153 #define AL_FUNC_AUTHREQ    0x20    /* 32  - Authentication Request */
154 #define AL_FUNC_AUTHERR    0x21    /* 33  - Authentication Error */
155 #define AL_FUNC_RESPON     0x81    /* 129 - Response */
156 #define AL_FUNC_UNSOLI     0x82    /* 130 - Unsolicited Response */
157 #define AL_FUNC_AUTHRESP   0x83    /* 131 - Authentication Response */
158 
159 /***************************************************************************/
160 /* Application Layer Internal Indication (IIN) bits */
161 /* 2 Bytes, message formatting: [First Octet] | [Second Octet] */
162 /***************************************************************************/
163 /* Octet 1 */
164 #define AL_IIN_BMSG        0x0100   /* Bit 0 - Broadcast message rx'd */
165 #define AL_IIN_CLS1D       0x0200   /* Bit 1 - Class 1 Data Available */
166 #define AL_IIN_CLS2D       0x0400   /* Bit 2 - Class 2 Data Available */
167 #define AL_IIN_CLS3D       0x0800   /* Bit 3 - Class 3 Data Available */
168 #define AL_IIN_TSR         0x1000   /* Bit 4 - Time Sync Req'd from Master */
169 #define AL_IIN_DOL         0x2000   /* Bit 5 - Outputs in Local Mode */
170 #define AL_IIN_DT          0x4000   /* Bit 6 - Device Trouble */
171 #define AL_IIN_RST         0x8000   /* Bit 7 - Device Restart */
172 
173 /* Octet 2 */
174 #define AL_IIN_FCNI        0x0001   /* Bit 0 - Function code not implemented */
175 #define AL_IIN_OBJU        0x0002   /* Bit 1 - Requested Objects Unknown */
176 #define AL_IIN_PIOOR       0x0004   /* Bit 2 - Parameters Invalid or Out of Range */
177 #define AL_IIN_EBO         0x0008   /* Bit 3 - Event Buffer Overflow */
178 #define AL_IIN_OAE         0x0010   /* Bit 4 - Operation Already Executing */
179 #define AL_IIN_CC          0x0020   /* Bit 5 - Device Configuration Corrupt */
180                         /* 0x0040      Bit 6 - Reserved */
181                         /* 0x0080      Bit 7 - Reserved */
182 
183 /***************************************************************************/
184 /* Application Layer Data Object Qualifier */
185 /***************************************************************************/
186 /* Bit-Masks */
187 #define AL_OBJQ_PREFIX         0x70    /* x111xxxx Masks Prefix from Qualifier */
188 #define AL_OBJQ_RANGE          0x0F    /* xxxx1111 Masks Range from Qualifier */
189 
190 /* Index Size (3-bits x111xxxx) */
191 /* When Qualifier Code != 11    */
192 #define AL_OBJQL_PREFIX_NI     0x00    /* Objects are Packed with no index */
193 #define AL_OBJQL_PREFIX_1O     0x01    /* Objects are prefixed w/ 1-octet index */
194 #define AL_OBJQL_PREFIX_2O     0x02    /* Objects are prefixed w/ 2-octet index */
195 #define AL_OBJQL_PREFIX_4O     0x03    /* Objects are prefixed w/ 4-octet index */
196 #define AL_OBJQL_PREFIX_1OS    0x04    /* Objects are prefixed w/ 1-octet object size */
197 #define AL_OBJQL_PREFIX_2OS    0x05    /* Objects are prefixed w/ 2-octet object size */
198 #define AL_OBJQL_PREFIX_4OS    0x06    /* Objects are prefixed w/ 4-octet object size */
199 
200 /* When Qualifier Code == 11 */
201 #define AL_OBJQL_IDX11_1OIS    0x01    /* 1 octet identifier size */
202 #define AL_OBJQL_IDX11_2OIS    0x02    /* 2 octet identifier size */
203 #define AL_OBJQL_IDX11_4OIS    0x03    /* 4 octet identifier size */
204 
205 /* Qualifier Code (4-bits) */
206 /* 4-bits ( xxxx1111 ) */
207 #define AL_OBJQL_RANGE_SSI8    0x00    /* 00 8-bit Start and Stop Indices in Range Field */
208 #define AL_OBJQL_RANGE_SSI16   0x01    /* 01 16-bit Start and Stop Indices in Range Field */
209 #define AL_OBJQL_RANGE_SSI32   0x02    /* 02 32-bit Start and Stop Indices in Range Field */
210 #define AL_OBJQL_RANGE_AA8     0x03    /* 03 8-bit Absolute Address in Range Field */
211 #define AL_OBJQL_RANGE_AA16    0x04    /* 04 16-bit Absolute Address in Range Field */
212 #define AL_OBJQL_RANGE_AA32    0x05    /* 05 32-bit Absolute Address in Range Field */
213 #define AL_OBJQL_RANGE_R0      0x06    /* 06 Length of Range field is 0 (no range field) */
214 #define AL_OBJQL_RANGE_SF8     0x07    /* 07 8-bit Single Field Quantity */
215 #define AL_OBJQL_RANGE_SF16    0x08    /* 08 16-bit Single Field Quantity */
216 #define AL_OBJQL_RANGE_SF32    0x09    /* 09 32-bit Single Field Quantity */
217                            /*  0x0A       10 Reserved  */
218 #define AL_OBJQL_RANGE_FF      0x0B    /* 11 Free-format Qualifier, range field has 1 octet count of objects */
219                            /*  0x0C       12 Reserved  */
220                            /*  0x0D       13 Reserved  */
221                            /*  0x0E       14 Reserved  */
222                            /*  0x0F       15 Reserved  */
223 
224 /***************************************************************************/
225 /* Application Layer Data Object Definitions                               */
226 /***************************************************************************/
227 
228 /* Masks for Object group and variation */
229 #define AL_OBJ_GRP_MASK 0xFF00
230 #define AL_OBJ_VAR_MASK 0x00FF
231 
232 /* Accessors for group and mask */
233 #define AL_OBJ_GROUP(GV)        ((GV & AL_OBJ_GRP_MASK) >> 8)
234 #define AL_OBJ_VARIATION(GV)    (GV & AL_OBJ_VAR_MASK)
235 
236 /* Data Type values */
237 #define AL_DATA_TYPE_NONE         0x0
238 #define AL_DATA_TYPE_VSTR         0x1
239 #define AL_DATA_TYPE_UINT         0x2
240 #define AL_DATA_TYPE_INT          0x3
241 #define AL_DATA_TYPE_FLT          0x4
242 #define AL_DATA_TYPE_OSTR         0x5
243 #define AL_DATA_TYPE_BSTR         0x6
244 #define AL_DATA_TYPE_TIME         0x7
245 #define AL_DATA_TYPE_UNCD         0x8
246 #define AL_DATA_TYPE_U8BS8LIST    0xFE
247 #define AL_DATA_TYPE_U8BS8EXLIST  0xFF
248 
249 /* Device Attributes */
250 #define AL_OBJ_DA_GRP           0x0000   /* 00 00 Device Attributes Group and null variation */
251 #define AL_OBJ_DA_CFG_ID        0x00C4   /* 00 196 Device Attributes - Configuration ID */
252 #define AL_OBJ_DA_CFG_VER       0x00C5   /* 00 197 Device Attributes - Configuration version */
253 #define AL_OBJ_DA_CFG_BLD_DATE  0x00C6   /* 00 198 Device Attributes - Configuration build date */
254 #define AL_OBJ_DA_CFG_CHG_DATE  0x00C7   /* 00 199 Device Attributes - Configuration last change date */
255 #define AL_OBJ_DA_CFG_SIG       0x00C8   /* 00 200 Device Attributes - Configuration signature */
256 #define AL_OBJ_DA_CFG_SIG_ALG   0x00C9   /* 00 201 Device Attributes - Configuration signature algorithm */
257 #define AL_OBJ_DA_MRID          0x00CA   /* 00 202 Device Attributes - Master Resource ID (mRID) */
258 #define AL_OBJ_DA_ALT           0x00CB   /* 00 203 Device Attributes - Device altitude */
259 #define AL_OBJ_DA_LONG          0x00CC   /* 00 204 Device Attributes - Device longitude */
260 #define AL_OBJ_DA_LAT           0x00CD   /* 00 205 Device Attributes - Device latitude */
261 #define AL_OBJ_DA_SEC_OP        0x00CE   /* 00 206 Device Attributes - User-assigned secondary operator name */
262 #define AL_OBJ_DA_PRM_OP        0x00CF   /* 00 207 Device Attributes - User-assigned primary operator name */
263 #define AL_OBJ_DA_SYS_NAME      0x00D0   /* 00 208 Device Attributes - User-assigned system name */
264 #define AL_OBJ_DA_SEC_VER       0x00D1   /* 00 209 Device Attributes - Secure authentication version */
265 #define AL_OBJ_DA_SEC_STAT      0x00D2   /* 00 210 Device Attributes - Number of security statistics per association */
266 #define AL_OBJ_DA_USR_ATTR      0x00D3   /* 00 211 Device Attributes - Identifier of support for user-specific attributes */
267 #define AL_OBJ_DA_MSTR_DSP      0x00D4   /* 00 212 Device Attributes - Number of master-defined data set prototypes  */
268 #define AL_OBJ_DA_OS_DSP        0x00D5   /* 00 213 Device Attributes - Number of outstation-defined data set prototypes */
269 #define AL_OBJ_DA_MSTR_DS       0x00D6   /* 00 214 Device Attributes - Number of master-defined data sets  */
270 #define AL_OBJ_DA_OS_DS         0x00D7   /* 00 215 Device Attributes - Number of outstation-defined data sets  */
271 #define AL_OBJ_DA_BO_REQ        0x00D8   /* 00 216 Device Attributes - Max number of binary outputs per request  */
272 #define AL_OBJ_DA_LOC_TA        0x00D9   /* 00 217 Device Attributes - Local timing accuracy             */
273 #define AL_OBJ_DA_DUR_TA        0x00DA   /* 00 218 Device Attributes - Duration of timing accuracy       */
274 #define AL_OBJ_DA_AO_EVT        0x00DB   /* 00 219 Device Attributes - Support for analog output events  */
275 #define AL_OBJ_DA_MAX_AO        0x00DC   /* 00 220 Device Attributes - Max analog output index           */
276 #define AL_OBJ_DA_NUM_AO        0x00DD   /* 00 221 Device Attributes - Number of analog outputs          */
277 #define AL_OBJ_DA_BO_EVT        0x00DE   /* 00 222 Device Attributes - Support for binary output events  */
278 #define AL_OBJ_DA_MAX_BO        0x00DF   /* 00 223 Device Attributes - Max binary output index           */
279 #define AL_OBJ_DA_NUM_BO        0x00E0   /* 00 224 Device Attributes - Number of binary outputs          */
280 #define AL_OBJ_DA_FCTR_EVT      0x00E1   /* 00 225 Device Attributes - Support for frozen counter events */
281 #define AL_OBJ_DA_FCTR          0x00E2   /* 00 226 Device Attributes - Support for frozen counters       */
282 #define AL_OBJ_DA_CTR_EVT       0x00E3   /* 00 227 Device Attributes - Support for counter events        */
283 #define AL_OBJ_DA_MAX_CTR       0x00E4   /* 00 228 Device Attributes - Max counter index                 */
284 #define AL_OBJ_DA_NUM_CTR       0x00E5   /* 00 229 Device Attributes - Number of counter points          */
285 #define AL_OBJ_DA_AIF           0x00E6   /* 00 230 Device Attributes - Support for frozen analog inputs  */
286 #define AL_OBJ_DA_AI_EVT        0x00E7   /* 00 231 Device Attributes - Support for analog input events   */
287 #define AL_OBJ_DA_MAX_AI        0x00E8   /* 00 232 Device Attributes - Maximum analog input index        */
288 #define AL_OBJ_DA_NUM_AI        0x00E9   /* 00 233 Device Attributes - Number of analog input points     */
289 #define AL_OBJ_DA_2BI_EVT       0x00EA   /* 00 234 Device Attributes - Support for Double-Bit BI Events  */
290 #define AL_OBJ_DA_MAX_2BI       0x00EB   /* 00 235 Device Attributes - Max Double-bit BI Point Index     */
291 #define AL_OBJ_DA_NUM_2BI       0x00EC   /* 00 236 Device Attributes - Number of Double-bit BI Points    */
292 #define AL_OBJ_DA_BI_EVT        0x00ED   /* 00 237 Device Attributes - Support for Binary Input Events   */
293 #define AL_OBJ_DA_MAX_BI        0x00EE   /* 00 238 Device Attributes - Max Binary Input Point Index      */
294 #define AL_OBJ_DA_NUM_BI        0x00EF   /* 00 239 Device Attributes - Number of Binary Input Points     */
295 #define AL_OBJ_DA_MXTX_FR       0x00F0   /* 00 240 Device Attributes - Maximum Transmit Fragment Size    */
296 #define AL_OBJ_DA_MXRX_FR       0x00F1   /* 00 241 Device Attributes - Maximum Receive Fragment Size     */
297 #define AL_OBJ_DA_SWVER         0x00F2   /* 00 242 Device Attributes - Device Manufacturers SW Version   */
298 #define AL_OBJ_DA_HWVER         0x00F3   /* 00 243 Device Attributes - Device Manufacturers HW Version   */
299 #define AL_OBJ_DA_OWNER         0x00F4   /* 00 244 Device Attributes - User-assigned owner name          */
300 #define AL_OBJ_DA_LOC           0x00F5   /* 00 245 Device Attributes - User-Assigned Location            */
301 #define AL_OBJ_DA_ID            0x00F6   /* 00 246 Device Attributes - User-Assigned ID code/number      */
302 #define AL_OBJ_DA_DEVNAME       0x00F7   /* 00 247 Device Attributes - User-Assigned Device Name         */
303 #define AL_OBJ_DA_SERNUM        0x00F8   /* 00 248 Device Attributes - Device Serial Number              */
304 #define AL_OBJ_DA_CONF          0x00F9   /* 00 249 Device Attributes - DNP Subset and Conformance        */
305 #define AL_OBJ_DA_PROD          0x00FA   /* 00 250 Device Attributes - Device Product Name and Model     */
306                                          /* 00 251 Future Assignment                                     */
307 #define AL_OBJ_DA_MFG           0x00FC   /* 00 252 Device Attributes - Device Manufacturers Name         */
308                                          /* 00 253 Future Assignment                                     */
309 #define AL_OBJ_DA_ALL           0x00FE   /* 00 254 Device Attributes - Non-specific All-attributes Req   */
310 #define AL_OBJ_DA_LVAR          0x00FF   /* 00 255 Device Attributes - List of Attribute Variations      */
311 
312 /* Binary Input Objects */
313 #define AL_OBJ_BI_ALL      0x0100   /* 01 00 Binary Input Default Variation */
314 #define AL_OBJ_BI_1BIT     0x0101   /* 01 01 Single-bit Binary Input */
315 #define AL_OBJ_BI_STAT     0x0102   /* 01 02 Binary Input With Status */
316 #define AL_OBJ_BIC_ALL     0x0200   /* 02 00 Binary Input Change Default Variation */
317 #define AL_OBJ_BIC_NOTIME  0x0201   /* 02 01 Binary Input Change Without Time */
318 #define AL_OBJ_BIC_TIME    0x0202   /* 02 02 Binary Input Change With Time */
319 #define AL_OBJ_BIC_RTIME   0x0203   /* 02 03 Binary Input Change With Relative Time */
320 
321 /* Double-bit Input Objects */
322 #define AL_OBJ_2BI_ALL     0x0300   /* 03 00 Double-bit Input Default Variation */
323 #define AL_OBJ_2BI_NF      0x0301   /* 03 01 Double-bit Input No Flags */
324 #define AL_OBJ_2BI_STAT    0x0302   /* 03 02 Double-bit Input With Status */
325 #define AL_OBJ_2BIC_ALL    0x0400   /* 04 00 Double-bit Input Change Default Variation */
326 #define AL_OBJ_2BIC_NOTIME 0x0401   /* 04 01 Double-bit Input Change Without Time */
327 #define AL_OBJ_2BIC_TIME   0x0402   /* 04 02 Double-bit Input Change With Time */
328 #define AL_OBJ_2BIC_RTIME  0x0403   /* 04 03 Double-bit Input Change With Relative Time */
329 
330 /* Binary Input Quality Flags */
331 #define AL_OBJ_BI_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
332 #define AL_OBJ_BI_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
333 #define AL_OBJ_BI_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
334 #define AL_OBJ_BI_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
335 #define AL_OBJ_BI_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
336 #define AL_OBJ_BI_FLAG5    0x0020   /* Chatter Filter (0=Normal; 1=Filter On) */
337 #define AL_OBJ_BI_FLAG6    0x0040   /* Double-bit LSB (0=Off; 1=On) */
338 #define AL_OBJ_BI_FLAG7    0x0080   /* Point State (0=Off; 1=On) or Double-bit MSB */
339 
340 /***************************************************************************/
341 /* Binary Output Objects */
342 #define AL_OBJ_BO_ALL      0x0A00   /* 10 00 Binary Output Default Variation */
343 #define AL_OBJ_BO          0x0A01   /* 10 01 Binary Output */
344 #define AL_OBJ_BO_STAT     0x0A02   /* 10 02 Binary Output Status */
345 #define AL_OBJ_BOC_ALL     0x0B00   /* 11 00 Binary Output Change Default Variation */
346 #define AL_OBJ_BOC_NOTIME  0x0B01   /* 11 01 Binary Output Change Without Time */
347 #define AL_OBJ_BOC_TIME    0x0B02   /* 11 02 Binary Output Change With Time */
348 #define AL_OBJ_CTLOP_BLK   0x0C01   /* 12 01 Control Relay Output Block */
349 #define AL_OBJ_CTL_PCB     0x0C02   /* 12 02 Pattern Control Block */
350 #define AL_OBJ_CTL_PMASK   0x0C03   /* 12 03 Pattern Mask */
351 #define AL_OBJ_BOE_NOTIME  0x0D01   /* 13 01 Binary Output Command Event Without Time */
352 #define AL_OBJ_BOE_TIME    0x0D02   /* 13 02 Binary Output Command Event With Time */
353 
354 #define AL_OBJCTLC_CODE    0x0F    /* Bit-Mask xxxx1111 for Control Code 'Code' */
355 #define AL_OBJCTLC_MISC    0x30    /* Bit-Mask xx11xxxx for Control Code Queue (obsolete) and Clear Fields */
356 #define AL_OBJCTLC_TC      0xC0    /* Bit-Mask 11xxxxxx for Control Code 'Trip/Close' */
357 
358 #define AL_OBJCTLC_CODE0   0x00    /* xxxx0000 NUL Operation; only process R attribute */
359 #define AL_OBJCTLC_CODE1   0x01    /* xxxx0001 Pulse On ^On-Time -> vOff-Time, remain off */
360 #define AL_OBJCTLC_CODE2   0x02    /* xxxx0010 Pulse Off vOff-Time -> ^On-Time, remain on */
361 #define AL_OBJCTLC_CODE3   0x03    /* xxxx0011 Latch On */
362 #define AL_OBJCTLC_CODE4   0x04    /* xxxx0100 Latch Off */
363                         /* 0x05-0x15  Reserved */
364 
365 #define AL_OBJCTLC_NOTSET  0x00    /* xx00xxxx for Control Code, Clear and Queue not set */
366 #define AL_OBJCTLC_QUEUE   0x01    /* xxx1xxxx for Control Code, Clear Field 'Queue' */
367 #define AL_OBJCTLC_CLEAR   0x02    /* xx1xxxxx for Control Code, Clear Field 'Clear' */
368 #define AL_OBJCTLC_BOTHSET 0x03    /* xx11xxxx for Control Code, Clear and Queue both set */
369 
370 #define AL_OBJCTLC_TC0     0x00    /* 00xxxxxx NUL */
371 #define AL_OBJCTLC_TC1     0x01    /* 01xxxxxx Close */
372 #define AL_OBJCTLC_TC2     0x02    /* 10xxxxxx Trip */
373 #define AL_OBJCTLC_TC3     0x03    /* 11xxxxxx Reserved */
374 
375 #define AL_OBJCTL_STAT0    0x00    /* Request Accepted, Initiated or Queued */
376 #define AL_OBJCTL_STAT1    0x01    /* Request Not Accepted; Arm-timer expired */
377 #define AL_OBJCTL_STAT2    0x02    /* Request Not Accepted; No 'SELECT' rx'd */
378 #define AL_OBJCTL_STAT3    0x03    /* Request Not Accepted; Format errors in ctrl request */
379 #define AL_OBJCTL_STAT4    0x04    /* Control Operation Not Supported for this point */
380 #define AL_OBJCTL_STAT5    0x05    /* Request Not Accepted; Ctrl Queue full or pt. active */
381 #define AL_OBJCTL_STAT6    0x06    /* Request Not Accepted; Ctrl HW Problems */
382 #define AL_OBJCTL_STAT7    0x07    /* Request Not Accepted; Local/Remote switch in Local*/
383 #define AL_OBJCTL_STAT8    0x08    /* Request Not Accepted; Too many operations requested */
384 #define AL_OBJCTL_STAT9    0x09    /* Request Not Accepted; Insufficient authorization */
385 #define AL_OBJCTL_STAT10   0x0A    /* Request Not Accepted; Local automation proc active */
386 #define AL_OBJCTL_STAT11   0x0B    /* Request Not Accepted; Processing limited */
387 #define AL_OBJCTL_STAT12   0x0C    /* Request Not Accepted; Out of range value */
388 #define AL_OBJCTL_STAT126  0x7E    /* Non Participating (NOP request) */
389 #define AL_OBJCTL_STAT127  0x7F    /* Request Not Accepted; Undefined error */
390 
391 #define AL_OBJCTL_STATUS_MASK 0x7F
392 
393 /* Binary Output Quality Flags */
394 #define AL_OBJ_BO_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
395 #define AL_OBJ_BO_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
396 #define AL_OBJ_BO_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
397 #define AL_OBJ_BO_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
398 #define AL_OBJ_BO_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
399 #define AL_OBJ_BO_FLAG5    0x0020   /* Reserved */
400 #define AL_OBJ_BO_FLAG6    0x0040   /* Reserved */
401 #define AL_OBJ_BO_FLAG7    0x0080   /* Point State (0=Off; 1=On) */
402 
403 /***************************************************************************/
404 /* Counter Objects */
405 #define AL_OBJ_CTR_ALL     0x1400   /* 20 00 Binary Counter Default Variation */
406 #define AL_OBJ_CTR_32      0x1401   /* 20 01 32-Bit Binary Counter */
407 #define AL_OBJ_CTR_16      0x1402   /* 20 02 16-Bit Binary Counter */
408 #define AL_OBJ_DCTR_32     0x1403   /* 20 03 32-Bit Delta Counter */
409 #define AL_OBJ_DCTR_16     0x1404   /* 20 04 16-Bit Delta Counter */
410 #define AL_OBJ_CTR_32NF    0x1405   /* 20 05 32-Bit Binary Counter Without Flag */
411 #define AL_OBJ_CTR_16NF    0x1406   /* 20 06 16-Bit Binary Counter Without Flag */
412 #define AL_OBJ_DCTR_32NF   0x1407   /* 20 07 32-Bit Delta Counter Without Flag */
413 #define AL_OBJ_DCTR_16NF   0x1408   /* 20 08 16-Bit Delta Counter Without Flag */
414 #define AL_OBJ_FCTR_ALL    0x1500   /* 21 00 Frozen Binary Counter Default Variation */
415 #define AL_OBJ_FCTR_32     0x1501   /* 21 01 32-Bit Frozen Counter */
416 #define AL_OBJ_FCTR_16     0x1502   /* 21 02 16-Bit Frozen Counter */
417 #define AL_OBJ_FDCTR_32    0x1503   /* 21 03 32-Bit Frozen Delta Counter */
418 #define AL_OBJ_FDCTR_16    0x1504   /* 21 04 16-Bit Frozen Delta Counter */
419 #define AL_OBJ_FCTR_32T    0x1505   /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
420 #define AL_OBJ_FCTR_16T    0x1506   /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
421 #define AL_OBJ_FDCTR_32T   0x1507   /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
422 #define AL_OBJ_FDCTR_16T   0x1508   /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
423 #define AL_OBJ_FCTR_32NF   0x1509   /* 21 09 32-Bit Frozen Counter Without Flag */
424 #define AL_OBJ_FCTR_16NF   0x150A   /* 21 10 16-Bit Frozen Counter Without Flag */
425 #define AL_OBJ_FDCTR_32NF  0x150B   /* 21 11 32-Bit Frozen Delta Counter Without Flag */
426 #define AL_OBJ_FDCTR_16NF  0x150C   /* 21 12 16-Bit Frozen Delta Counter Without Flag */
427 #define AL_OBJ_CTRC_ALL    0x1600   /* 22 00 Counter Change Event Default Variation */
428 #define AL_OBJ_CTRC_32     0x1601   /* 22 01 32-Bit Counter Change Event w/o Time */
429 #define AL_OBJ_CTRC_16     0x1602   /* 22 02 16-Bit Counter Change Event w/o Time */
430 #define AL_OBJ_DCTRC_32    0x1603   /* 22 03 32-Bit Delta Counter Change Event w/o Time */
431 #define AL_OBJ_DCTRC_16    0x1604   /* 22 04 16-Bit Delta Counter Change Event w/o Time */
432 #define AL_OBJ_CTRC_32T    0x1605   /* 22 05 32-Bit Counter Change Event with Time */
433 #define AL_OBJ_CTRC_16T    0x1606   /* 22 06 16-Bit Counter Change Event with Time */
434 #define AL_OBJ_DCTRC_32T   0x1607   /* 22 07 32-Bit Delta Counter Change Event with Time */
435 #define AL_OBJ_DCTRC_16T   0x1608   /* 22 08 16-Bit Delta Counter Change Event with Time */
436 #define AL_OBJ_FCTRC_ALL   0x1700   /* 23 00 Frozen Binary Counter Change Event Default Variation */
437 #define AL_OBJ_FCTRC_32    0x1701   /* 23 01 32-Bit Frozen Counter Change Event */
438 #define AL_OBJ_FCTRC_16    0x1702   /* 23 02 16-Bit Frozen Counter Change Event */
439 #define AL_OBJ_FDCTRC_32   0x1703   /* 23 03 32-Bit Frozen Delta Counter Change Event */
440 #define AL_OBJ_FDCTRC_16   0x1704   /* 23 04 16-Bit Frozen Delta Counter Change Event */
441 #define AL_OBJ_FCTRC_32T   0x1705   /* 23 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
442 #define AL_OBJ_FCTRC_16T   0x1706   /* 23 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
443 #define AL_OBJ_FDCTRC_32T  0x1707   /* 23 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
444 #define AL_OBJ_FDCTRC_16T  0x1708   /* 23 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
445 
446 /* Counter Quality Flags */
447 #define AL_OBJ_CTR_FLAG0   0x0001   /* Point Online (0=Offline; 1=Online) */
448 #define AL_OBJ_CTR_FLAG1   0x0002   /* Restart (0=Normal; 1=Restart) */
449 #define AL_OBJ_CTR_FLAG2   0x0004   /* Comms Lost (0=Normal; 1=Lost) */
450 #define AL_OBJ_CTR_FLAG3   0x0008   /* Remote Force (0=Normal; 1=Forced) */
451 #define AL_OBJ_CTR_FLAG4   0x0010   /* Local Force (0=Normal; 1=Forced) */
452 #define AL_OBJ_CTR_FLAG5   0x0020   /* Roll-over (0=Normal; 1=Roll-Over) */
453 #define AL_OBJ_CTR_FLAG6   0x0040   /* Discontinuity (0=Normal; 1=Discontinuity) */
454 #define AL_OBJ_CTR_FLAG7   0x0080   /* Reserved */
455 
456 /***************************************************************************/
457 /* Analog Input Objects */
458 #define AL_OBJ_AI_ALL      0x1E00   /* 30 00 Analog Input Default Variation */
459 #define AL_OBJ_AI_32       0x1E01   /* 30 01 32-Bit Analog Input */
460 #define AL_OBJ_AI_16       0x1E02   /* 30 02 16-Bit Analog Input */
461 #define AL_OBJ_AI_32NF     0x1E03   /* 30 03 32-Bit Analog Input Without Flag */
462 #define AL_OBJ_AI_16NF     0x1E04   /* 30 04 16-Bit Analog Input Without Flag */
463 #define AL_OBJ_AI_FLT      0x1E05   /* 30 05 32-Bit Floating Point Input */
464 #define AL_OBJ_AI_DBL      0x1E06   /* 30 06 64-Bit Floating Point Input */
465                         /* 0x1F01      31 01 32-Bit Frozen Analog Input */
466                         /* 0x1F02      31 02 16-Bit Frozen Analog Input */
467                         /* 0x1F03      31 03 32-Bit Frozen Analog Input w/ Time of Freeze */
468                         /* 0x1F04      31 04 16-Bit Frozen Analog Input w/ Time of Freeze */
469                         /* 0x1F05      31 05 32-Bit Frozen Analog Input Without Flag */
470                         /* 0x1F06      31 06 16-Bit Frozen Analog Input Without Flag */
471 #define AL_OBJ_AIF_FLT     0x1F07   /* 31 07 32-Bit Frozen Floating Point Input */
472 #define AL_OBJ_AIF_DBL     0x1F08   /* 31 08 64-Bit Frozen Floating Point Input */
473 #define AL_OBJ_AIC_ALL     0x2000   /* 32 00 Analog Input Change Default Variation */
474 #define AL_OBJ_AIC_32NT    0x2001   /* 32 01 32-Bit Analog Change Event w/o Time */
475 #define AL_OBJ_AIC_16NT    0x2002   /* 32 02 16-Bit Analog Change Event w/o Time */
476 #define AL_OBJ_AIC_32T     0x2003   /* 32 03 32-Bit Analog Change Event w/ Time */
477 #define AL_OBJ_AIC_16T     0x2004   /* 32 04 16-Bit Analog Change Event w/ Time */
478 #define AL_OBJ_AIC_FLTNT   0x2005   /* 32 05 32-Bit Floating Point Change Event w/o Time*/
479 #define AL_OBJ_AIC_DBLNT   0x2006   /* 32 06 64-Bit Floating Point Change Event w/o Time*/
480 #define AL_OBJ_AIC_FLTT    0x2007   /* 32 07 32-Bit Floating Point Change Event w/ Time*/
481 #define AL_OBJ_AIC_DBLT    0x2008   /* 32 08 64-Bit Floating Point Change Event w/ Time*/
482                         /* 0x2101      33 01 32-Bit Frozen Analog Event w/o Time */
483                         /* 0x2102      33 02 16-Bit Frozen Analog Event w/o Time */
484                         /* 0x2103      33 03 32-Bit Frozen Analog Event w/ Time */
485                         /* 0x2104      33 04 16-Bit Frozen Analog Event w/ Time */
486 #define AL_OBJ_AIFC_FLTNT  0x2105   /* 33 05 32-Bit Floating Point Frozen Change Event w/o Time*/
487 #define AL_OBJ_AIFC_DBLNT  0x2106   /* 33 06 64-Bit Floating Point Frozen Change Event w/o Time*/
488 #define AL_OBJ_AIFC_FLTT   0x2107   /* 33 07 32-Bit Floating Point Frozen Change Event w/ Time*/
489 #define AL_OBJ_AIFC_DBLT   0x2108   /* 33 08 64-Bit Floating Point Frozen Change Event w/ Time*/
490 
491 /* Analog Input Quality Flags */
492 #define AL_OBJ_AI_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
493 #define AL_OBJ_AI_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
494 #define AL_OBJ_AI_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
495 #define AL_OBJ_AI_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
496 #define AL_OBJ_AI_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
497 #define AL_OBJ_AI_FLAG5    0x0020   /* Over-Range (0=Normal; 1=Over-Range) */
498 #define AL_OBJ_AI_FLAG6    0x0040   /* Reference Check (0=Normal; 1=Error) */
499 #define AL_OBJ_AI_FLAG7    0x0080   /* Reserved */
500 
501 #define AL_OBJ_AIDB_ALL    0x2200   /* 34 00 Analog Input Deadband Default Variation */
502 #define AL_OBJ_AIDB_16     0x2201   /* 34 01 16-Bit Analog Input Deadband */
503 #define AL_OBJ_AIDB_32     0x2202   /* 34 02 32-Bit Analog Input Deadband */
504 #define AL_OBJ_AIDB_FLT    0x2203   /* 34 03 Floating Point Analog Input Deadband */
505 
506 /***************************************************************************/
507 /* Analog Output Objects */
508 #define AL_OBJ_AO_ALL      0x2800   /* 40 00 Analog Output Default Variation */
509 #define AL_OBJ_AO_32       0x2801   /* 40 01 32-Bit Analog Output Status */
510 #define AL_OBJ_AO_16       0x2802   /* 40 02 16-Bit Analog Output Status */
511 #define AL_OBJ_AO_FLT      0x2803   /* 40 03 32-Bit Floating Point Output Status */
512 #define AL_OBJ_AO_DBL      0x2804   /* 40 04 64-Bit Floating Point Output Status */
513 #define AL_OBJ_AO_32OPB    0x2901   /* 41 01 32-Bit Analog Output Block */
514 #define AL_OBJ_AO_16OPB    0x2902   /* 41 02 16-Bit Analog Output Block */
515 #define AL_OBJ_AO_FLTOPB   0x2903   /* 41 03 32-Bit Floating Point Output Block */
516 #define AL_OBJ_AO_DBLOPB   0x2904   /* 41 04 64-Bit Floating Point Output Block */
517 #define AL_OBJ_AOC_ALL     0x2A00   /* 42 00 Analog Output Event Default Variation */
518 #define AL_OBJ_AOC_32NT    0x2A01   /* 42 01 32-Bit Analog Output Event w/o Time */
519 #define AL_OBJ_AOC_16NT    0x2A02   /* 42 02 16-Bit Analog Output Event w/o Time */
520 #define AL_OBJ_AOC_32T     0x2A03   /* 42 03 32-Bit Analog Output Event w/ Time */
521 #define AL_OBJ_AOC_16T     0x2A04   /* 42 04 16-Bit Analog Output Event w/ Time */
522 #define AL_OBJ_AOC_FLTNT   0x2A05   /* 42 05 32-Bit Floating Point Output Event w/o Time */
523 #define AL_OBJ_AOC_DBLNT   0x2A06   /* 42 06 64-Bit Floating Point Output Event w/o Time */
524 #define AL_OBJ_AOC_FLTT    0x2A07   /* 42 07 32-Bit Floating Point Output Event w/ Time */
525 #define AL_OBJ_AOC_DBLT    0x2A08   /* 42 08 64-Bit Floating Point Output Event w/ Time */
526 #define AL_OBJ_AOC_32EVNT  0x2B01   /* 43 01 32-Bit Analog Output Command Event w/o Time */
527 #define AL_OBJ_AOC_16EVNT  0x2B02   /* 43 02 16-Bit Analog Output Command Event w/o Time */
528 #define AL_OBJ_AOC_32EVTT  0x2B03   /* 43 03 32-Bit Analog Output Command Event w/ Time */
529 #define AL_OBJ_AOC_16EVTT  0x2B04   /* 43 04 16-Bit Analog Output Command Event w/ Time */
530 #define AL_OBJ_AOC_FLTEVNT 0x2B05   /* 43 05 32-Bit Floating Point Analog Output Command Event w/o Time */
531 #define AL_OBJ_AOC_DBLEVNT 0x2B06   /* 43 06 64-Bit Floating PointAnalog Output Command Event w/o Time */
532 #define AL_OBJ_AOC_FLTEVTT 0x2B07   /* 43 07 32-Bit Floating Point Analog Output Command Event w/ Time */
533 #define AL_OBJ_AOC_DBLEVTT 0x2B08   /* 43 08 64-Bit Floating PointAnalog Output Command Event w/ Time */
534 
535 /* Analog Output Quality Flags */
536 #define AL_OBJ_AO_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
537 #define AL_OBJ_AO_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
538 #define AL_OBJ_AO_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
539 #define AL_OBJ_AO_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
540 #define AL_OBJ_AO_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
541 #define AL_OBJ_AO_FLAG5    0x0020   /* Reserved */
542 #define AL_OBJ_AO_FLAG6    0x0040   /* Reserved */
543 #define AL_OBJ_AO_FLAG7    0x0080   /* Reserved */
544 
545 /***************************************************************************/
546 /* Time Objects */
547 #define AL_OBJ_TD_ALL      0x3200   /* 50 00 Time and Date Default Variation */
548 #define AL_OBJ_TD          0x3201   /* 50 01 Time and Date */
549 #define AL_OBJ_TDI         0x3202   /* 50 02 Time and Date w/ Interval */
550 #define AL_OBJ_TDR         0x3203   /* 50 03 Last Recorded Time and Date */
551 #define AL_OBJ_TDCTO       0x3301   /* 51 01 Time and Date CTO */
552 #define AL_OBJ_UTDCTO      0x3302   /* 51 02 Unsynchronized Time and Date CTO */
553 #define AL_OBJ_TDELAYC     0x3401   /* 52 01 Time Delay Coarse */
554 #define AL_OBJ_TDELAYF     0x3402   /* 52 02 Time Delay Fine */
555 
556 /***************************************************************************/
557 /* Class Data Objects */
558 #define AL_OBJ_CLASS0      0x3C01   /* 60 01 Class 0 Data */
559 #define AL_OBJ_CLASS1      0x3C02   /* 60 02 Class 1 Data */
560 #define AL_OBJ_CLASS2      0x3C03   /* 60 03 Class 2 Data */
561 #define AL_OBJ_CLASS3      0x3C04   /* 60 04 Class 3 Data */
562 
563 /***************************************************************************/
564 /* File Objects */
565 #define AL_OBJ_FILE_CMD         0x4603   /* 70 03 File Control - Command */
566 #define AL_OBJ_FILE_STAT        0x4604   /* 70 04 File Control - Status */
567 #define AL_OBJ_FILE_TRANS       0x4605   /* 70 05 File Control - Transport */
568 #define AL_OBJ_FILE_TRAN_ST     0x4606   /* 70 05 File Control - Transport Status */
569 
570 /* File Control Mode flags */
571 #define AL_OBJ_FILE_MODE_NULL   0x00   /* NULL */
572 #define AL_OBJ_FILE_MODE_READ   0x01   /* READ */
573 #define AL_OBJ_FILE_MODE_WRITE  0x02   /* WRITE */
574 #define AL_OBJ_FILE_MODE_APPEND 0x03   /* APPEND */
575 
576 
577 /***************************************************************************/
578 /* Device Objects */
579 #define AL_OBJ_IIN         0x5001   /* 80 01 Internal Indications */
580 
581 /***************************************************************************/
582 /* Data Sets */
583 #define AL_OBJ_DS_PROTO    0x5501   /* 85 01 Data-Set Prototype, with UUID  */
584 #define AL_OBJ_DSD_CONT    0x5601   /* 86 01 Data-Set Descriptor, Data-Set Contents  */
585 #define AL_OBJ_DSD_CHAR    0x5602   /* 86 02 Data-Set Descriptor, Characteristics  */
586 #define AL_OBJ_DSD_PIDX    0x5603   /* 86 03 Data-Set Descriptor, Point Index Attributes  */
587 #define AL_OBJ_DS_PV       0x5701   /* 87 01 Data-Set, Present Value  */
588 #define AL_OBJ_DS_SS       0x5801   /* 88 01 Data-Set, Snapshot  */
589 
590 /***************************************************************************/
591 /* Octet String Objects */
592 #define AL_OBJ_OCT         0x6E00   /* 110 xx Octet string */
593 #define AL_OBJ_OCT_EVT     0x6F00   /* 111 xx Octet string event */
594 
595 /***************************************************************************/
596 /* Virtual Terminal Objects */
597 #define AL_OBJ_VT_OBLK     0x7000   /* 112 xx Virtual Terminal Output Block */
598 #define AL_OBJ_VT_EVTD     0x7100   /* 113 xx Virtual Terminal Event Data */
599 
600 
601 /***************************************************************************/
602 /* End of Application Layer Data Object Definitions */
603 /***************************************************************************/
604 
605 void proto_register_dnp3(void);
606 void proto_reg_handoff_dnp3(void);
607 
608 /* Initialize the protocol and registered fields */
609 static int proto_dnp3 = -1;
610 static int hf_dnp3_start = -1;
611 static int hf_dnp3_len = -1;
612 static int hf_dnp3_ctl = -1;
613 static int hf_dnp3_ctl_prifunc = -1;
614 static int hf_dnp3_ctl_secfunc = -1;
615 static int hf_dnp3_ctl_dir = -1;
616 static int hf_dnp3_ctl_prm = -1;
617 static int hf_dnp3_ctl_fcb = -1;
618 static int hf_dnp3_ctl_fcv = -1;
619 static int hf_dnp3_ctl_dfc = -1;
620 static int hf_dnp3_dst = -1;
621 static int hf_dnp3_src = -1;
622 static int hf_dnp3_addr = -1;
623 static int hf_dnp3_data_hdr_crc = -1;
624 static int hf_dnp3_data_hdr_crc_status = -1;
625 static int hf_dnp3_tr_ctl = -1;
626 static int hf_dnp3_tr_fin = -1;
627 static int hf_dnp3_tr_fir = -1;
628 static int hf_dnp3_tr_seq = -1;
629 static int hf_dnp3_data_chunk = -1;
630 static int hf_dnp3_data_chunk_len = -1;
631 static int hf_dnp3_data_chunk_crc = -1;
632 static int hf_dnp3_data_chunk_crc_status = -1;
633 
634 /* Added for Application Layer Decoding */
635 static int hf_dnp3_al_ctl = -1;
636 static int hf_dnp3_al_fir = -1;
637 static int hf_dnp3_al_fin = -1;
638 static int hf_dnp3_al_con = -1;
639 static int hf_dnp3_al_uns = -1;
640 static int hf_dnp3_al_seq = -1;
641 static int hf_dnp3_al_func = -1;
642 static int hf_dnp3_al_iin = -1;
643 static int hf_dnp3_al_iin_bmsg = -1;
644 static int hf_dnp3_al_iin_cls1d = -1;
645 static int hf_dnp3_al_iin_cls2d = -1;
646 static int hf_dnp3_al_iin_cls3d = -1;
647 static int hf_dnp3_al_iin_tsr = -1;
648 static int hf_dnp3_al_iin_dol = -1;
649 static int hf_dnp3_al_iin_dt = -1;
650 static int hf_dnp3_al_iin_rst = -1;
651 static int hf_dnp3_al_iin_fcni = -1;
652 static int hf_dnp3_al_iin_obju = -1;
653 static int hf_dnp3_al_iin_pioor = -1;
654 static int hf_dnp3_al_iin_ebo = -1;
655 static int hf_dnp3_al_iin_oae = -1;
656 static int hf_dnp3_al_iin_cc = -1;
657 static int hf_dnp3_al_obj = -1;
658 static int hf_dnp3_al_objq_prefix = -1;
659 static int hf_dnp3_al_objq_range = -1;
660 static int hf_dnp3_al_range_start8 = -1;
661 static int hf_dnp3_al_range_stop8 = -1;
662 static int hf_dnp3_al_range_start16 = -1;
663 static int hf_dnp3_al_range_stop16 = -1;
664 static int hf_dnp3_al_range_start32 = -1;
665 static int hf_dnp3_al_range_stop32 = -1;
666 static int hf_dnp3_al_range_abs8 = -1;
667 static int hf_dnp3_al_range_abs16 = -1;
668 static int hf_dnp3_al_range_abs32 = -1;
669 static int hf_dnp3_al_range_quant8 = -1;
670 static int hf_dnp3_al_range_quant16 = -1;
671 static int hf_dnp3_al_range_quant32 = -1;
672 static int hf_dnp3_al_index8 = -1;
673 static int hf_dnp3_al_index16 = -1;
674 static int hf_dnp3_al_index32 = -1;
675 static int hf_dnp3_al_size8 = -1;
676 static int hf_dnp3_al_size16 = -1;
677 static int hf_dnp3_al_size32 = -1;
678 static int hf_dnp3_bocs_bit = -1;
679 
680 /*static int hf_dnp3_al_objq = -1;
681   static int hf_dnp3_al_nobj = -1; */
682 /* XXX - unused
683 static int hf_dnp3_al_ptnum = -1; */
684 static int hf_dnp3_al_biq_b0 = -1;
685 static int hf_dnp3_al_biq_b1 = -1;
686 static int hf_dnp3_al_biq_b2 = -1;
687 static int hf_dnp3_al_biq_b3 = -1;
688 static int hf_dnp3_al_biq_b4 = -1;
689 static int hf_dnp3_al_biq_b5 = -1;
690 static int hf_dnp3_al_biq_b6 = -1;
691 static int hf_dnp3_al_biq_b7 = -1;
692 static int hf_dnp3_al_boq_b0 = -1;
693 static int hf_dnp3_al_boq_b1 = -1;
694 static int hf_dnp3_al_boq_b2 = -1;
695 static int hf_dnp3_al_boq_b3 = -1;
696 static int hf_dnp3_al_boq_b4 = -1;
697 static int hf_dnp3_al_boq_b5 = -1;
698 static int hf_dnp3_al_boq_b6 = -1;
699 static int hf_dnp3_al_boq_b7 = -1;
700 static int hf_dnp3_al_ctrq_b0 = -1;
701 static int hf_dnp3_al_ctrq_b1 = -1;
702 static int hf_dnp3_al_ctrq_b2 = -1;
703 static int hf_dnp3_al_ctrq_b3 = -1;
704 static int hf_dnp3_al_ctrq_b4 = -1;
705 static int hf_dnp3_al_ctrq_b5 = -1;
706 static int hf_dnp3_al_ctrq_b6 = -1;
707 static int hf_dnp3_al_ctrq_b7 = -1;
708 static int hf_dnp3_al_aiq_b0 = -1;
709 static int hf_dnp3_al_aiq_b1 = -1;
710 static int hf_dnp3_al_aiq_b2 = -1;
711 static int hf_dnp3_al_aiq_b3 = -1;
712 static int hf_dnp3_al_aiq_b4 = -1;
713 static int hf_dnp3_al_aiq_b5 = -1;
714 static int hf_dnp3_al_aiq_b6 = -1;
715 static int hf_dnp3_al_aiq_b7 = -1;
716 static int hf_dnp3_al_aoq_b0 = -1;
717 static int hf_dnp3_al_aoq_b1 = -1;
718 static int hf_dnp3_al_aoq_b2 = -1;
719 static int hf_dnp3_al_aoq_b3 = -1;
720 static int hf_dnp3_al_aoq_b4 = -1;
721 static int hf_dnp3_al_aoq_b5 = -1;
722 static int hf_dnp3_al_aoq_b6 = -1;
723 static int hf_dnp3_al_aoq_b7 = -1;
724 static int hf_dnp3_al_timestamp = -1;
725 static int hf_dnp3_al_file_perms = -1;
726 static int hf_dnp3_al_file_perms_read_owner = -1;
727 static int hf_dnp3_al_file_perms_write_owner = -1;
728 static int hf_dnp3_al_file_perms_exec_owner = -1;
729 static int hf_dnp3_al_file_perms_read_group = -1;
730 static int hf_dnp3_al_file_perms_write_group = -1;
731 static int hf_dnp3_al_file_perms_exec_group = -1;
732 static int hf_dnp3_al_file_perms_read_world = -1;
733 static int hf_dnp3_al_file_perms_write_world = -1;
734 static int hf_dnp3_al_file_perms_exec_world = -1;
735 static int hf_dnp3_al_rel_timestamp = -1;
736 static int hf_dnp3_al_ana16 = -1;
737 static int hf_dnp3_al_ana32 = -1;
738 static int hf_dnp3_al_anaflt = -1;
739 static int hf_dnp3_al_anadbl = -1;
740 static int hf_dnp3_al_bit = -1;
741 static int hf_dnp3_al_2bit = -1;
742 static int hf_dnp3_al_cnt16 = -1;
743 static int hf_dnp3_al_cnt32 = -1;
744 static int hf_dnp3_al_ctrlstatus = -1;
745 static int hf_dnp3_al_anaout16 = -1;
746 static int hf_dnp3_al_anaout32 = -1;
747 static int hf_dnp3_al_anaoutflt = -1;
748 static int hf_dnp3_al_anaoutdbl = -1;
749 static int hf_dnp3_al_file_mode = -1;
750 static int hf_dnp3_al_file_auth = -1;
751 static int hf_dnp3_al_file_size = -1;
752 static int hf_dnp3_al_file_maxblk = -1;
753 static int hf_dnp3_al_file_reqID = -1;
754 static int hf_dnp3_al_file_handle = -1;
755 static int hf_dnp3_al_file_status = -1;
756 static int hf_dnp3_al_file_blocknum = -1;
757 static int hf_dnp3_al_file_lastblock = -1;
758 static int hf_dnp3_al_file_data = -1;
759 static int hf_dnp3_ctlobj_code_c = -1;
760 static int hf_dnp3_ctlobj_code_m = -1;
761 static int hf_dnp3_ctlobj_code_tc = -1;
762 static int hf_dnp3_al_datatype = -1;
763 static int hf_dnp3_al_da_length = -1;
764 static int hf_dnp3_al_da_uint8 = -1;
765 static int hf_dnp3_al_da_uint16 = -1;
766 static int hf_dnp3_al_da_uint32 = -1;
767 static int hf_dnp3_al_da_int8 = -1;
768 static int hf_dnp3_al_da_int16 = -1;
769 static int hf_dnp3_al_da_int32 = -1;
770 static int hf_dnp3_al_da_flt = -1;
771 static int hf_dnp3_al_da_dbl = -1;
772 
773 /* Generated from convert_proto_tree_add_text.pl */
774 static int hf_dnp3_al_point_index = -1;
775 static int hf_dnp3_al_da_value = -1;
776 static int hf_dnp3_al_count = -1;
777 static int hf_dnp3_al_on_time = -1;
778 static int hf_dnp3_al_off_time = -1;
779 static int hf_dnp3_al_time_delay = -1;
780 static int hf_dnp3_al_file_string_offset = -1;
781 static int hf_dnp3_al_file_string_length = -1;
782 static int hf_dnp3_al_file_name = -1;
783 static int hf_dnp3_al_octet_string = -1;
784 static int hf_dnp3_unknown_data_chunk = -1;
785 
786 /***************************************************************************/
787 /* Value String Look-Ups */
788 /***************************************************************************/
789 static const value_string dnp3_ctl_func_pri_vals[] = {
790   { DL_FUNC_RESET_LINK, "Reset of Remote Link" },
791   { DL_FUNC_RESET_PROC, "Reset of User Process" },
792   { DL_FUNC_TEST_LINK,  "Test Function For Link" },
793   { DL_FUNC_USER_DATA,  "User Data" },
794   { DL_FUNC_UNC_DATA,   "Unconfirmed User Data" },
795   { DL_FUNC_LINK_STAT,  "Request Link Status" },
796   { 0, NULL }
797 };
798 
799 static const value_string dnp3_ctl_func_sec_vals[] = {
800   { DL_FUNC_ACK,        "ACK" },
801   { DL_FUNC_NACK,       "NACK" },
802   { DL_FUNC_STAT_LINK,  "Status of Link" },
803   { DL_FUNC_NO_FUNC,    "Link Service Not Functioning" },
804   { DL_FUNC_NOT_IMPL,   "Link Service Not Used or Implemented" },
805   { 0,  NULL }
806 };
807 
808 #if 0
809 static const value_string dnp3_ctl_flags_pri_vals[] = {
810   { DNP3_CTL_DIR, "DIR" },
811   { DNP3_CTL_PRM, "PRM" },
812   { DNP3_CTL_FCB, "FCB" },
813   { DNP3_CTL_FCV, "FCV" },
814   { 0,  NULL }
815 };
816 #endif
817 
818 #if 0
819 static const value_string dnp3_ctl_flags_sec_vals[]= {
820   { DNP3_CTL_DIR, "DIR" },
821   { DNP3_CTL_PRM, "PRM" },
822   { DNP3_CTL_RES, "RES" },
823   { DNP3_CTL_DFC, "DFC" },
824   { 0,  NULL }
825 };
826 #endif
827 
828 #if 0
829 static const value_string dnp3_tr_flags_vals[] = {
830   { DNP3_TR_FIN,  "FIN" },
831   { DNP3_TR_FIR,  "FIR" },
832   { 0,  NULL }
833 };
834 #endif
835 
836 #if 0
837 static const value_string dnp3_al_flags_vals[] = {
838   { DNP3_AL_FIR,  "FIR" },
839   { DNP3_AL_FIN,  "FIN" },
840   { DNP3_AL_CON,  "CON" },
841   { DNP3_AL_UNS,  "UNS" },
842   { 0,  NULL }
843 };
844 #endif
845 
846 /* Application Layer Function Code Values */
847 static const value_string dnp3_al_func_vals[] = {
848   { AL_FUNC_CONFIRM,    "Confirm" },
849   { AL_FUNC_READ,       "Read" },
850   { AL_FUNC_WRITE,      "Write" },
851   { AL_FUNC_SELECT,     "Select" },
852   { AL_FUNC_OPERATE,    "Operate" },
853   { AL_FUNC_DIROP,      "Direct Operate" },
854   { AL_FUNC_DIROPNACK,  "Direct Operate No Ack" },
855   { AL_FUNC_FRZ,        "Immediate Freeze" },
856   { AL_FUNC_FRZNACK,    "Immediate Freeze No Ack" },
857   { AL_FUNC_FRZCLR,     "Freeze and Clear" },
858   { AL_FUNC_FRZCLRNACK, "Freeze and Clear No ACK" },
859   { AL_FUNC_FRZT,       "Freeze With Time" },
860   { AL_FUNC_FRZTNACK,   "Freeze With Time No ACK" },
861   { AL_FUNC_COLDRST,    "Cold Restart" },
862   { AL_FUNC_WARMRST,    "Warm Restart" },
863   { AL_FUNC_INITDATA,   "Initialize Data" },
864   { AL_FUNC_INITAPP,    "Initialize Application" },
865   { AL_FUNC_STARTAPP,   "Start Application" },
866   { AL_FUNC_STOPAPP,    "Stop Application" },
867   { AL_FUNC_SAVECFG,    "Save Configuration" },
868   { AL_FUNC_ENSPMSG,    "Enable Spontaneous Messages" },
869   { AL_FUNC_DISSPMSG,   "Disable Spontaneous Messages" },
870   { AL_FUNC_ASSIGNCL,   "Assign Classes" },
871   { AL_FUNC_DELAYMST,   "Delay Measurement" },
872   { AL_FUNC_RECCT,      "Record Current Time" },
873   { AL_FUNC_OPENFILE,   "Open File" },
874   { AL_FUNC_CLOSEFILE,  "Close File" },
875   { AL_FUNC_DELETEFILE, "Delete File" },
876   { AL_FUNC_GETFILEINF, "Get File Info" },
877   { AL_FUNC_AUTHFILE,   "Authenticate File" },
878   { AL_FUNC_ABORTFILE,  "Abort File" },
879   { AL_FUNC_ACTCNF,     "Activate Config" },
880   { AL_FUNC_AUTHREQ,    "Authentication Request" },
881   { AL_FUNC_AUTHERR,    "Authentication Error" },
882   { AL_FUNC_RESPON,     "Response" },
883   { AL_FUNC_UNSOLI,     "Unsolicited Response" },
884   { AL_FUNC_AUTHRESP,   "Authentication Response" },
885   { 0, NULL }
886 };
887 static value_string_ext dnp3_al_func_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_func_vals);
888 
889 /* Application Layer Internal Indication (IIN) bit Values */
890 static const value_string dnp3_al_iin_vals[] = {
891   { AL_IIN_BMSG,    "Broadcast message Rx'd" },
892   { AL_IIN_CLS1D,   "Class 1 Data Available" },
893   { AL_IIN_CLS2D,   "Class 2 Data Available" },
894   { AL_IIN_CLS3D,   "Class 3 Data Available" },
895   { AL_IIN_TSR,     "Time Sync Required from Master" },
896   { AL_IIN_DOL,     "Outputs in Local Mode" },
897   { AL_IIN_DT,      "Device Trouble" },
898   { AL_IIN_RST,     "Device Restart" },
899   { AL_IIN_FCNI,    "Function Code not implemented" },
900   { AL_IIN_OBJU,    "Requested Objects Unknown" },
901   { AL_IIN_PIOOR,   "Parameters Invalid or Out of Range" },
902   { AL_IIN_EBO,     "Event Buffer Overflow" },
903   { AL_IIN_OAE,     "Operation Already Executing" },
904   { AL_IIN_CC,      "Device Configuration Corrupt" },
905   { 0, NULL }
906 };
907 
908 /* Application Layer Object Qualifier Prefix Values When Qualifier Code != 11 */
909 static const value_string dnp3_al_objq_prefix_vals[] = {
910   { AL_OBJQL_PREFIX_NI,    "None" },
911   { AL_OBJQL_PREFIX_1O,    "1-Octet Index Prefix" },
912   { AL_OBJQL_PREFIX_2O,    "2-Octet Index Prefix" },
913   { AL_OBJQL_PREFIX_4O,    "4-Octet Index Prefix" },
914   { AL_OBJQL_PREFIX_1OS,   "1-Octet Object Size Prefix" },
915   { AL_OBJQL_PREFIX_2OS,   "2-Octet Object Size Prefix" },
916   { AL_OBJQL_PREFIX_4OS,   "4-Octet Object Size Prefix" },
917   { 0, NULL }
918 };
919 static value_string_ext dnp3_al_objq_prefix_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_objq_prefix_vals);
920 
921 /* Application Layer Object Qualifier Range Values */
922 static const value_string dnp3_al_objq_range_vals[] = {
923   { AL_OBJQL_RANGE_SSI8,    "8-bit Start and Stop Indices" },
924   { AL_OBJQL_RANGE_SSI16,   "16-bit Start and Stop Indices" },
925   { AL_OBJQL_RANGE_SSI32,   "32-bit Start and Stop Indices" },
926   { AL_OBJQL_RANGE_AA8,     "8-bit Absolute Address in Range Field" },
927   { AL_OBJQL_RANGE_AA16,    "16-bit Absolute Address in Range Field" },
928   { AL_OBJQL_RANGE_AA32,    "32-bit Absolute Address in Range Field" },
929   { AL_OBJQL_RANGE_R0,      "No Range Field" },
930   { AL_OBJQL_RANGE_SF8,     "8-bit Single Field Quantity" },
931   { AL_OBJQL_RANGE_SF16,    "16-bit Single Field Quantity" },
932   { AL_OBJQL_RANGE_SF32,    "32-bit Single Field Quantity" },
933   { 10,                     "Reserved" },
934   { AL_OBJQL_RANGE_FF,      "Free-format Qualifier" },
935   { 0, NULL }
936 };
937 static value_string_ext dnp3_al_objq_range_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_objq_range_vals);
938 
939 /* Application Layer Data Object Values */
940 static const value_string dnp3_al_obj_vals[] = {
941   { AL_OBJ_DA_CFG_ID,      "Device Attributes - Configuration ID (Obj:00, Var:196)" },
942   { AL_OBJ_DA_CFG_VER,     "Device Attributes - Configuration version (Obj:00, Var:197)" },
943   { AL_OBJ_DA_CFG_BLD_DATE,"Device Attributes - Configuration build date (Obj:00, Var:198)" },
944   { AL_OBJ_DA_CFG_CHG_DATE,"Device Attributes - Configuration last change date (Obj:00, Var:199)" },
945   { AL_OBJ_DA_CFG_SIG,     "Device Attributes - Configuration signature (Obj:00, Var:200)" },
946   { AL_OBJ_DA_CFG_SIG_ALG, "Device Attributes - Configuration signature algorithm (Obj:00, Var:201)" },
947   { AL_OBJ_DA_MRID,        "Device Attributes - Master Resource ID (mRID) (Obj:00, Var:202)" },
948   { AL_OBJ_DA_ALT,         "Device Attributes - Device altitude (Obj:00, Var:203)" },
949   { AL_OBJ_DA_LONG,        "Device Attributes - Device longitude (Obj:00, Var:204)" },
950   { AL_OBJ_DA_LAT,         "Device Attributes - Device latitude (Obj:00, Var:205)" },
951   { AL_OBJ_DA_SEC_OP,      "Device Attributes - User-assigned secondary operator name (Obj:00, Var:206)" },
952   { AL_OBJ_DA_PRM_OP,      "Device Attributes - User-assigned primary operator name (Obj:00, Var:207)" },
953   { AL_OBJ_DA_SYS_NAME,    "Device Attributes - User-assigned system name (Obj:00, Var:208)" },
954   { AL_OBJ_DA_SEC_VER,     "Device Attributes - Secure authentication version (Obj:00, Var:209)" },
955   { AL_OBJ_DA_SEC_STAT,    "Device Attributes - Number of security statistics per association (Obj:00, Var:210)" },
956   { AL_OBJ_DA_USR_ATTR,    "Device Attributes - Identifier of support for user-specific attributes (Obj:00, Var:211)" },
957   { AL_OBJ_DA_MSTR_DSP,    "Device Attributes - Number of master-defined data set prototypes (Obj:00, Var:212)" },
958   { AL_OBJ_DA_OS_DSP,      "Device Attributes - Number of outstation-defined data set prototypes (Obj:00, Var:213)" },
959   { AL_OBJ_DA_MSTR_DS,     "Device Attributes - Number of master-defined data sets (Obj:00, Var:214)" },
960   { AL_OBJ_DA_OS_DS,       "Device Attributes - Number of outstation-defined data sets (Obj:00, Var:215)" },
961   { AL_OBJ_DA_BO_REQ,      "Device Attributes - Max number of binary outputs per request (Obj:00, Var:216)" },
962   { AL_OBJ_DA_LOC_TA,      "Device Attributes - Local timing accuracy (Obj:00, Var:217)" },
963   { AL_OBJ_DA_DUR_TA,      "Device Attributes - Duration of timing accuracy (Obj:00, Var:218)" },
964   { AL_OBJ_DA_AO_EVT,      "Device Attributes - Support for analog output events (Obj:00, Var:219)" },
965   { AL_OBJ_DA_MAX_AO,      "Device Attributes - Max analog output index (Obj:00, Var:220)" },
966   { AL_OBJ_DA_NUM_AO,      "Device Attributes - Number of analog outputs (Obj:00, Var:221)" },
967   { AL_OBJ_DA_BO_EVT,      "Device Attributes - Support for binary output events (Obj:00, Var:222)" },
968   { AL_OBJ_DA_MAX_BO,      "Device Attributes - Max binary output index (Obj:00, Var:223)" },
969   { AL_OBJ_DA_NUM_BO,      "Device Attributes - Number of binary outputs (Obj:00, Var:224)" },
970   { AL_OBJ_DA_FCTR_EVT,    "Device Attributes - Support for frozen counter events (Obj:00, Var:225)" },
971   { AL_OBJ_DA_FCTR,        "Device Attributes - Support for frozen counters (Obj:00, Var:226)" },
972   { AL_OBJ_DA_CTR_EVT,     "Device Attributes - Support for counter events (Obj:00, Var:227)" },
973   { AL_OBJ_DA_MAX_CTR,     "Device Attributes - Max counter index (Obj:00, Var:228)" },
974   { AL_OBJ_DA_NUM_CTR,     "Device Attributes - Number of counter points (Obj:00, Var:229)" },
975   { AL_OBJ_DA_AIF,         "Device Attributes - Support for frozen analog inputs (Obj:00, Var:230)" },
976   { AL_OBJ_DA_AI_EVT,      "Device Attributes - Support for analog input events (Obj:00, Var:231)" },
977   { AL_OBJ_DA_MAX_AI,      "Device Attributes - Maximum analog input index (Obj:00, Var:232)" },
978   { AL_OBJ_DA_NUM_AI,      "Device Attributes - Number of analog input points (Obj:00, Var:233)" },
979   { AL_OBJ_DA_2BI_EVT,     "Device Attributes - Support for Double-Bit BI Events (Obj:00, Var:234)" },
980   { AL_OBJ_DA_MAX_2BI,     "Device Attributes - Max Double-bit BI Point Index (Obj:00, Var:235)" },
981   { AL_OBJ_DA_NUM_2BI,     "Device Attributes - Number of Double-bit BI Points (Obj:00, Var:236)" },
982   { AL_OBJ_DA_BI_EVT,      "Device Attributes - Support for Binary Input Events (Obj:00, Var:237)" },
983   { AL_OBJ_DA_MAX_BI,      "Device Attributes - Max Binary Input Point Index (Obj:00, Var:238)" },
984   { AL_OBJ_DA_NUM_BI,      "Device Attributes - Number of Binary Input Points (Obj:00, Var:239)" },
985   { AL_OBJ_DA_MXTX_FR,     "Device Attributes - Maximum Transmit Fragment Size (Obj:00, Var:240)" },
986   { AL_OBJ_DA_MXRX_FR,     "Device Attributes - Maximum Receive Fragment Size (Obj:00, Var:241)" },
987   { AL_OBJ_DA_SWVER,       "Device Attributes - Device Manufacturers SW Version (Obj:00, Var:242)" },
988   { AL_OBJ_DA_HWVER,       "Device Attributes - Device Manufacturers HW Version (Obj:00, Var:243)" },
989   { AL_OBJ_DA_LOC,         "Device Attributes - User-Assigned Location (Obj:00, Var:245)" },
990   { AL_OBJ_DA_ID,          "Device Attributes - User-Assigned ID code/number (Obj:00, Var:246)" },
991   { AL_OBJ_DA_DEVNAME,     "Device Attributes - User-Assigned Device Name (Obj:00, Var:247)" },
992   { AL_OBJ_DA_SERNUM,      "Device Attributes - Device Serial Number (Obj:00, Var:248)" },
993   { AL_OBJ_DA_CONF,        "Device Attributes - DNP Subset and Conformance (Obj:00, Var:249)" },
994   { AL_OBJ_DA_PROD,        "Device Attributes - Device Product Name and Model (Obj:00, Var:250)" },
995   { AL_OBJ_DA_MFG,         "Device Attributes - Device Manufacturers Name (Obj:00, Var:252)" },
996   { AL_OBJ_DA_ALL,         "Device Attributes - Non-specific All-attributes Request (Obj:00, Var:254)" },
997   { AL_OBJ_DA_LVAR,        "Device Attributes - List of Attribute Variations (Obj:00, Var:255)" },
998   { AL_OBJ_BI_ALL,         "Binary Input Default Variation (Obj:01, Var:Default)" },
999   { AL_OBJ_BI_1BIT,        "Single-Bit Binary Input (Obj:01, Var:01)" },
1000   { AL_OBJ_BI_STAT,        "Binary Input With Status (Obj:01, Var:02)" },
1001   { AL_OBJ_BIC_ALL,        "Binary Input Change Default Variation (Obj:02, Var:Default)" },
1002   { AL_OBJ_BIC_NOTIME,     "Binary Input Change Without Time (Obj:02, Var:01)" },
1003   { AL_OBJ_BIC_TIME,       "Binary Input Change With Time (Obj:02, Var:02)" },
1004   { AL_OBJ_BIC_RTIME,      "Binary Input Change With Relative Time (Obj:02, Var:03)" },
1005   { AL_OBJ_2BI_ALL,        "Double-bit Input Default Variation (Obj:03, Var:Default)" },
1006   { AL_OBJ_2BI_NF,         "Double-bit Input No Flags (Obj:03, Var:01)" },
1007   { AL_OBJ_2BI_STAT,       "Double-bit Input With Status (Obj:03, Var:02)" },
1008   { AL_OBJ_2BIC_ALL,       "Double-bit Input Change Default Variation (Obj:04, Var:Default)" },
1009   { AL_OBJ_2BIC_NOTIME,    "Double-bit Input Change Without Time (Obj:04, Var:01)" },
1010   { AL_OBJ_2BIC_TIME,      "Double-bit Input Change With Time (Obj:04, Var:02)" },
1011   { AL_OBJ_2BIC_RTIME,     "Double-bit Input Change With Relative Time (Obj:04, Var:03)" },
1012   { AL_OBJ_BO_ALL,         "Binary Output Default Variation (Obj:10, Var:Default)" },
1013   { AL_OBJ_BO,             "Binary Output (Obj:10, Var:01)" },
1014   { AL_OBJ_BO_STAT,        "Binary Output Status (Obj:10, Var:02)" },
1015   { AL_OBJ_BOC_ALL,        "Binary Output Change Default Variation (Obj:11, Var:Default)" },
1016   { AL_OBJ_BOC_NOTIME,     "Binary Output Change Without Time (Obj:11, Var:01)" },
1017   { AL_OBJ_BOC_TIME,       "Binary Output Change With Time (Obj:11, Var:02)" },
1018   { AL_OBJ_CTLOP_BLK,      "Control Relay Output Block (Obj:12, Var:01)" },
1019   { AL_OBJ_CTL_PCB,        "Pattern Control Block (Obj:12, Var:02)" },
1020   { AL_OBJ_CTL_PMASK,      "Pattern Mask (Obj:12, Var:03)" },
1021   { AL_OBJ_BOE_NOTIME,     "Binary Command Event Without Time (Obj 13, Var:01)" },
1022   { AL_OBJ_BOE_TIME,       "Binary Command Event With Time (Obj 13, Var:02)" },
1023   { AL_OBJ_CTR_ALL,        "Binary Counter Default Variation (Obj:20, Var:Default)" },
1024   { AL_OBJ_CTR_32,         "32-Bit Binary Counter (Obj:20, Var:01)" },
1025   { AL_OBJ_CTR_16,         "16-Bit Binary Counter (Obj:20, Var:02)" },
1026   { AL_OBJ_DCTR_32,        "32-Bit Binary Delta Counter (Obj:20, Var:03)" },
1027   { AL_OBJ_DCTR_16,        "16-Bit Binary Delta Counter (Obj:20, Var:04)" },
1028   { AL_OBJ_CTR_32NF,       "32-Bit Binary Counter Without Flag (Obj:20, Var:05)" },
1029   { AL_OBJ_CTR_16NF,       "16-Bit Binary Counter Without Flag (Obj:20, Var:06)" },
1030   { AL_OBJ_DCTR_32NF,      "32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07)" },
1031   { AL_OBJ_DCTR_16NF,      "16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08)" },
1032   { AL_OBJ_FCTR_ALL,       "Frozen Binary Counter Default Variation (Obj:21, Var:Default)" },
1033   { AL_OBJ_FCTR_32,        "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
1034   { AL_OBJ_FCTR_16,        "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
1035   { AL_OBJ_FDCTR_32,       "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
1036   { AL_OBJ_FDCTR_16,       "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
1037   { AL_OBJ_FCTR_32T,       "32-Bit Frozen Binary Counter With Flag and Time (Obj:21, Var:05)" },
1038   { AL_OBJ_FCTR_16T,       "16-Bit Frozen Binary Counter With Flag and Time (Obj:21, Var:06)" },
1039   { AL_OBJ_FDCTR_32T,      "32-Bit Frozen Binary Delta Counter With Flag and Time (Obj:21, Var:07)" },
1040   { AL_OBJ_FDCTR_16T,      "16-Bit Frozen Binary Delta Counter With Flag and Time (Obj:21, Var:08)" },
1041   { AL_OBJ_FCTR_32NF,      "32-Bit Frozen Binary Counter Without Flag (Obj:21, Var:09)" },
1042   { AL_OBJ_FCTR_16NF,      "16-Bit Frozen Binary Counter Without Flag (Obj:21, Var:10)" },
1043   { AL_OBJ_FDCTR_32NF,     "32-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:11)" },
1044   { AL_OBJ_FDCTR_16NF,     "16-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:12)" },
1045   { AL_OBJ_CTRC_ALL,       "Binary Counter Change Default Variation (Obj:22, Var:Default)" },
1046   { AL_OBJ_CTRC_32,        "32-Bit Counter Change Event w/o Time (Obj:22, Var:01)" },
1047   { AL_OBJ_CTRC_16,        "16-Bit Counter Change Event w/o Time (Obj:22, Var:02)" },
1048   { AL_OBJ_DCTRC_32,       "32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03)" },
1049   { AL_OBJ_DCTRC_16,       "16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04)" },
1050   { AL_OBJ_CTRC_32T,       "32-Bit Counter Change Event with Time (Obj:22, Var:05)" },
1051   { AL_OBJ_CTRC_16T,       "16-Bit Counter Change Event with Time (Obj:22, Var:06)" },
1052   { AL_OBJ_DCTRC_32T,      "32-Bit Delta Counter Change Event with Time (Obj:22, Var:07)" },
1053   { AL_OBJ_DCTRC_16T,      "16-Bit Delta Counter Change Event with Time (Obj:22, Var:08)" },
1054   { AL_OBJ_FCTRC_ALL,      "Frozen Binary Counter Change Default Variation (Obj:23, Var:Default)" },
1055   { AL_OBJ_FCTRC_32,       "32-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:01)" },
1056   { AL_OBJ_FCTRC_16,       "16-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:02)" },
1057   { AL_OBJ_FDCTRC_32,      "32-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:03)" },
1058   { AL_OBJ_FDCTRC_16,      "16-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:04)" },
1059   { AL_OBJ_FCTRC_32T,      "32-Bit Frozen Counter Change Event with Time (Obj:23, Var:05)" },
1060   { AL_OBJ_FCTRC_16T,      "16-Bit Frozen Counter Change Event with Time (Obj:23, Var:06)" },
1061   { AL_OBJ_FDCTRC_32T,     "32-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:07)" },
1062   { AL_OBJ_FDCTRC_16T,     "16-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:08)" },
1063   { AL_OBJ_AI_ALL,         "Analog Input Default Variation (Obj:30, Var:Default)" },
1064   { AL_OBJ_AI_32,          "32-Bit Analog Input (Obj:30, Var:01)" },
1065   { AL_OBJ_AI_16,          "16-Bit Analog Input (Obj:30, Var:02)" },
1066   { AL_OBJ_AI_32NF,        "32-Bit Analog Input Without Flag (Obj:30, Var:03)" },
1067   { AL_OBJ_AI_16NF,        "16-Bit Analog Input Without Flag (Obj:30, Var:04)" },
1068   { AL_OBJ_AI_FLT,         "32-Bit Floating Point Input (Obj:30, Var:05)" },
1069   { AL_OBJ_AI_DBL,         "64-Bit Floating Point Input (Obj:30, Var:06)" },
1070   { AL_OBJ_AIF_FLT,        "32-Bit Frozen Floating Point Input (Obj:31, Var:07)" },
1071   { AL_OBJ_AIF_DBL,        "64-Bit Frozen Floating Point Input (Obj:31, Var:08)" },
1072   { AL_OBJ_AIC_ALL,        "Analog Input Change Default Variation (Obj:32, Var:Default)" },
1073   { AL_OBJ_AIC_32NT,       "32-Bit Analog Change Event w/o Time (Obj:32, Var:01)" },
1074   { AL_OBJ_AIC_16NT,       "16-Bit Analog Change Event w/o Time (Obj:32, Var:02)" },
1075   { AL_OBJ_AIC_32T,        "32-Bit Analog Change Event with Time (Obj:32, Var:03)" },
1076   { AL_OBJ_AIC_16T,        "16-Bit Analog Change Event with Time (Obj:32, Var:04)" },
1077   { AL_OBJ_AIC_FLTNT,      "32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05)" },
1078   { AL_OBJ_AIC_DBLNT,      "64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06)" },
1079   { AL_OBJ_AIC_FLTT,       "32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07)" },
1080   { AL_OBJ_AIC_DBLT,       "64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08)" },
1081   { AL_OBJ_AIFC_FLTNT,     "32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05)" },
1082   { AL_OBJ_AIFC_DBLNT,     "64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06)" },
1083   { AL_OBJ_AIFC_FLTT,      "32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07)" },
1084   { AL_OBJ_AIFC_DBLT,      "64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08)" },
1085   { AL_OBJ_AIDB_ALL,       "Analog Input Deadband Default Variation (Obj:34, Var:Default)" },
1086   { AL_OBJ_AIDB_16,        "16-Bit Analog Input Deadband (Obj:34, Var:01)" },
1087   { AL_OBJ_AIDB_32,        "32-Bit Analog Input Deadband (Obj:34, Var:02)" },
1088   { AL_OBJ_AIDB_FLT,       "32-Bit Floating Point Analog Input Deadband (Obj:34, Var:03)" },
1089   { AL_OBJ_AO_ALL,         "Analog Output Default Variation (Obj:40, Var:Default)" },
1090   { AL_OBJ_AO_32,          "32-Bit Analog Output Status (Obj:40, Var:01)" },
1091   { AL_OBJ_AO_16,          "16-Bit Analog Output Status (Obj:40, Var:02)" },
1092   { AL_OBJ_AO_FLT,         "32-Bit Floating Point Output Status (Obj:40, Var:03)" },
1093   { AL_OBJ_AO_DBL,         "64-Bit Floating Point Output Status (Obj:40, Var:04)" },
1094   { AL_OBJ_AO_32OPB,       "32-Bit Analog Output Block (Obj:41, Var:01)" },
1095   { AL_OBJ_AO_16OPB,       "16-Bit Analog Output Block (Obj:41, Var:02)" },
1096   { AL_OBJ_AO_FLTOPB,      "32-Bit Floating Point Output Block (Obj:41, Var:03)" },
1097   { AL_OBJ_AO_DBLOPB,      "64-Bit Floating Point Output Block (Obj:41, Var:04)" },
1098   { AL_OBJ_AOC_ALL,        "Analog Output Event Default Variation (Obj:42, Var:Default)" },
1099   { AL_OBJ_AOC_32NT,       "32-Bit Analog Output Event w/o Time (Obj:42, Var:01)" },
1100   { AL_OBJ_AOC_16NT,       "16-Bit Analog Output Event w/o Time (Obj:42, Var:02)" },
1101   { AL_OBJ_AOC_32T,        "32-Bit Analog Output Event with Time (Obj:42, Var:03)" },
1102   { AL_OBJ_AOC_16T,        "16-Bit Analog Output Event with Time (Obj:42, Var:04)" },
1103   { AL_OBJ_AOC_FLTNT,      "32-Bit Floating Point Output Event w/o Time (Obj:42, Var:05)" },
1104   { AL_OBJ_AOC_DBLNT,      "64-Bit Floating Point Output Event w/o Time (Obj:42, Var:06)" },
1105   { AL_OBJ_AOC_FLTT,       "32-Bit Floating Point Output Event w/ Time (Obj:42, Var:07)" },
1106   { AL_OBJ_AOC_DBLT,       "64-Bit Floating Point Output Event w/ Time (Obj:42, Var:08)" },
1107   { AL_OBJ_AOC_32EVNT,     "32-Bit Analog Output Event w/o Time (Obj:43, Var:01)" },
1108   { AL_OBJ_AOC_16EVNT,     "16-Bit Analog Output Event w/o Time (Obj:43, Var:02)" },
1109   { AL_OBJ_AOC_32EVTT,     "32-Bit Analog Output Event with Time (Obj:43, Var:03)" },
1110   { AL_OBJ_AOC_16EVTT,     "16-Bit Analog Output Event with Time (Obj:43, Var:04)" },
1111   { AL_OBJ_AOC_FLTEVNT,    "32-Bit Floating Point Output Event w/o Time (Obj:43, Var:05)" },
1112   { AL_OBJ_AOC_DBLEVNT,    "64-Bit Floating Point Output Event w/o Time (Obj:43, Var:06)" },
1113   { AL_OBJ_AOC_FLTEVTT,    "32-Bit Floating Point Output Event w/ Time (Obj:43, Var:07)" },
1114   { AL_OBJ_AOC_DBLEVTT,    "64-Bit Floating Point Output Event w/ Time (Obj:43, Var:08)" },
1115   { AL_OBJ_TD_ALL,         "Time and Date Default Variations (Obj:50, Var:Default)" },
1116   { AL_OBJ_TD,             "Time and Date (Obj:50, Var:01)" },
1117   { AL_OBJ_TDI,            "Time and Date w/Interval (Obj:50, Var:02)" },
1118   { AL_OBJ_TDR,            "Last Recorded Time and Date (Obj:50, Var:03)" },
1119   { AL_OBJ_TDCTO,          "Time and Date CTO (Obj:51, Var:01)" },
1120   { AL_OBJ_TDELAYF,        "Time Delay - Fine (Obj:52, Var:02)" },
1121   { AL_OBJ_CLASS0,         "Class 0 Data (Obj:60, Var:01)" },
1122   { AL_OBJ_CLASS1,         "Class 1 Data (Obj:60, Var:02)" },
1123   { AL_OBJ_CLASS2,         "Class 2 Data (Obj:60, Var:03)" },
1124   { AL_OBJ_CLASS3,         "Class 3 Data (Obj:60, Var:04)" },
1125   { AL_OBJ_FILE_CMD,       "File Control - File Command (Obj:70, Var:03)" },
1126   { AL_OBJ_FILE_STAT,      "File Control - File Status (Obj:70, Var:04)" },
1127   { AL_OBJ_FILE_TRANS,     "File Control - File Transport (Obj:70, Var:05)" },
1128   { AL_OBJ_FILE_TRAN_ST,   "File Control - File Transport Status (Obj:70, Var:06)" },
1129   { AL_OBJ_IIN,            "Internal Indications (Obj:80, Var:01)" },
1130   { AL_OBJ_DS_PROTO,       "Data-Set Prototype, with UUID (Obj:85, Var:01)" },
1131   { AL_OBJ_DSD_CONT,       "Data-Set Descriptor, Data-Set Contents (Obj:86, Var:01)" },
1132   { AL_OBJ_DSD_CHAR,       "Data-Set Descriptor, Characteristics (Obj:86, Var:02)" },
1133   { AL_OBJ_DSD_PIDX,       "Data-Set Descriptor, Point Index Attributes (Obj:86, Var:03)" },
1134   { AL_OBJ_DS_PV,          "Data-Set, Present Value (Obj:87, Var:01)" },
1135   { AL_OBJ_DS_SS,          "Data-Set, Snapshot (Obj:88, Var:01)" },
1136   { AL_OBJ_OCT,            "Octet String (Obj:110)" },
1137   { AL_OBJ_OCT_EVT,        "Octet String Event (Obj:111)" },
1138   { AL_OBJ_VT_OBLK,        "Virtual Terminal Output Block (Obj:112)" },
1139   { AL_OBJ_VT_EVTD,        "Virtual Terminal Event Data (Obj:113)" },
1140   { 0, NULL }
1141 };
1142 static value_string_ext dnp3_al_obj_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_obj_vals);
1143 
1144 /* Application Layer Control Code 'Operation Type' Values */
1145 static const value_string dnp3_al_ctlc_code_vals[] = {
1146   { AL_OBJCTLC_CODE0,     "NUL Operation" },
1147   { AL_OBJCTLC_CODE1,     "Pulse On" },
1148   { AL_OBJCTLC_CODE2,     "Pulse Off" },
1149   { AL_OBJCTLC_CODE3,     "Latch On" },
1150   { AL_OBJCTLC_CODE4,     "Latch Off" },
1151   { 0, NULL }
1152 };
1153 
1154 /* Application Layer Control Code 'Clear Field' Values */
1155 static const value_string dnp3_al_ctlc_misc_vals[] = {
1156   { AL_OBJCTLC_QUEUE,     "Queue" },
1157   { AL_OBJCTLC_CLEAR,     "Clear" },
1158   { AL_OBJCTLC_NOTSET,    "Not Set" },
1159   { AL_OBJCTLC_BOTHSET,   "Queue and Clear" },
1160   { 0, NULL }
1161 };
1162 
1163 /* Application Layer Control Code 'Trip Close Code' Values */
1164 static const value_string dnp3_al_ctlc_tc_vals[] = {
1165   { AL_OBJCTLC_TC0,     "NUL" },
1166   { AL_OBJCTLC_TC1,     "Close" },
1167   { AL_OBJCTLC_TC2,     "Trip" },
1168   { AL_OBJCTLC_TC3,     "Reserved" },
1169   { 0, NULL }
1170 };
1171 
1172 /* Application Layer Control Status Values */
1173 static const value_string dnp3_al_ctl_status_vals[] = {
1174   { AL_OBJCTL_STAT0,     "Req. Accepted/Init/Queued" },
1175   { AL_OBJCTL_STAT1,     "Req. Not Accepted; Arm-Timer Expired" },
1176   { AL_OBJCTL_STAT2,     "Req. Not Accepted; No 'SELECT' Received" },
1177   { AL_OBJCTL_STAT3,     "Req. Not Accepted; Format Err. in Ctl Req." },
1178   { AL_OBJCTL_STAT4,     "Ctl Oper. Not Supported For This Point" },
1179   { AL_OBJCTL_STAT5,     "Req. Not Accepted; Ctrl Queue Full/Point Active" },
1180   { AL_OBJCTL_STAT6,     "Req. Not Accepted; Ctrl Hardware Problems" },
1181   { AL_OBJCTL_STAT7,     "Req. Not Accepted; Local/Remote switch in Local" },
1182   { AL_OBJCTL_STAT8,     "Req. Not Accepted; Too many operations" },
1183   { AL_OBJCTL_STAT9,     "Req. Not Accepted; Insufficient authorization" },
1184   { AL_OBJCTL_STAT10,    "Req. Not Accepted; Local automation proc active" },
1185   { AL_OBJCTL_STAT11,    "Req. Not Accepted; Processing limited" },
1186   { AL_OBJCTL_STAT12,    "Req. Not Accepted; Out of range value" },
1187   { AL_OBJCTL_STAT126,   "Req. Not Accepted; Non-participating (NOP request)" },
1188   { AL_OBJCTL_STAT127,   "Req. Not Accepted; Undefined error" },
1189   { 0, NULL }
1190 };
1191 static value_string_ext dnp3_al_ctl_status_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_ctl_status_vals);
1192 
1193 #if 0
1194 /* Application Layer Binary Input Quality Flag Values */
1195 static const value_string dnp3_al_biflag_vals[] = {
1196   { AL_OBJ_BI_FLAG0, "Online" },
1197   { AL_OBJ_BI_FLAG1, "Restart" },
1198   { AL_OBJ_BI_FLAG2, "Comm Fail" },
1199   { AL_OBJ_BI_FLAG3, "Remote Forced" },
1200   { AL_OBJ_BI_FLAG4, "Locally Forced" },
1201   { AL_OBJ_BI_FLAG5, "Chatter Filter" },
1202   { 0, NULL }
1203 };
1204 #endif
1205 
1206 #if 0
1207 /* Application Layer Counter Quality Flag Values */
1208 static const value_string dnp3_al_ctrflag_vals[] = {
1209   { AL_OBJ_CTR_FLAG0, "Online" },
1210   { AL_OBJ_CTR_FLAG1, "Restart" },
1211   { AL_OBJ_CTR_FLAG2, "Comm Fail" },
1212   { AL_OBJ_CTR_FLAG3, "Remote Forced" },
1213   { AL_OBJ_CTR_FLAG4, "Locally Forced" },
1214   { AL_OBJ_CTR_FLAG5, "Roll-Over" },
1215   { AL_OBJ_CTR_FLAG6, "Discontinuity" },
1216   { 0, NULL }
1217 };
1218 #endif
1219 
1220 #if 0
1221 /* Application Layer Analog Input Quality Flag Values */
1222 static const value_string dnp3_al_aiflag_vals[] = {
1223   { AL_OBJ_AI_FLAG0, "Online" },
1224   { AL_OBJ_AI_FLAG1, "Restart" },
1225   { AL_OBJ_AI_FLAG2, "Comm Fail" },
1226   { AL_OBJ_AI_FLAG3, "Remote Forced" },
1227   { AL_OBJ_AI_FLAG4, "Locally Forced" },
1228   { AL_OBJ_AI_FLAG5, "Over-Range" },
1229   { AL_OBJ_AI_FLAG6, "Ref. Error" },
1230   { 0, NULL }
1231 };
1232 #endif
1233 
1234 /* Application Layer File Control Mode values */
1235 static const value_string dnp3_al_file_mode_vals[] = {
1236   { AL_OBJ_FILE_MODE_NULL,    "NULL" },
1237   { AL_OBJ_FILE_MODE_READ,    "READ" },
1238   { AL_OBJ_FILE_MODE_WRITE,   "WRITE" },
1239   { AL_OBJ_FILE_MODE_APPEND,  "APPEND" },
1240   { 0, NULL }
1241 };
1242 
1243 /* Application Layer File Control Status values */
1244 static const value_string dnp3_al_file_status_vals[] = {
1245   { 0,    "SUCCESS" },
1246   { 1,    "PERMISSION DENIED" },
1247   { 2,    "INVALID MODE" },
1248   { 3,    "FILE NOT FOUND" },
1249   { 4,    "FILE LOCKED" },
1250   { 5,    "TOO MANY OPEN" },
1251   { 6,    "INVALID HANDLE" },
1252   { 7,    "WRITE BLOCK SIZE" },
1253   { 8,    "COMM LOST" },
1254   { 9,    "CANNOT ABORT" },
1255   { 16,   "NOT OPENED" },
1256   { 17,   "HANDLE EXPIRED" },
1257   { 18,   "BUFFER OVERRUN" },
1258   { 19,   "FATAL" },
1259   { 20,   "BLOCK SEQUENCE" },
1260   { 255,  "UNDEFINED" },
1261   { 0, NULL }
1262 };
1263 static value_string_ext dnp3_al_file_status_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_file_status_vals);
1264 
1265 /* Application Layer Data Type values */
1266 static const value_string dnp3_al_data_type_vals[] = {
1267   { AL_DATA_TYPE_NONE,        "NONE (Placeholder)" },
1268   { AL_DATA_TYPE_VSTR,        "VSTR (Visible ASCII String)" },
1269   { AL_DATA_TYPE_UINT,        "UINT (Unsigned Integer)" },
1270   { AL_DATA_TYPE_INT,         "INT (Signed Integer)" },
1271   { AL_DATA_TYPE_FLT,         "FLT (Floating Point)" },
1272   { AL_DATA_TYPE_OSTR,        "OSTR (Octet String)" },
1273   { AL_DATA_TYPE_BSTR,        "BSTR (Bit String)" },
1274   { AL_DATA_TYPE_TIME,        "TIME (DNP3 Time UINT48)" },
1275   { AL_DATA_TYPE_UNCD,        "UNCD (Unicode String)" },
1276   { AL_DATA_TYPE_U8BS8LIST,   "U8BS8LIST (List of UINT8 - BSTR8 pairs)" },
1277   { AL_DATA_TYPE_U8BS8EXLIST, "U8BS8EXLIST (Extended List of UINT8 - BSTR8 pairs)" },
1278   { 0, NULL }
1279 };
1280 
1281 /* Application Layer Read Object Type values */
1282 static const value_string dnp3_al_read_obj_vals[] = {
1283   { (AL_OBJ_DA_GRP    & 0xFF00),  "Device Attribute"            },
1284   { (AL_OBJ_BI_ALL    & 0xFF00),  "Binary Input"                },
1285   { (AL_OBJ_BIC_ALL   & 0xFF00),  "Binary Input Change"         },
1286   { (AL_OBJ_2BI_ALL   & 0xFF00),  "Double-bit Input"            },
1287   { (AL_OBJ_2BIC_ALL  & 0xFF00),  "Double-bit Input Change"     },
1288   { (AL_OBJ_BO_ALL    & 0xFF00),  "Binary Output"               },
1289   { (AL_OBJ_BOC_ALL   & 0xFF00),  "Binary Output Change"        },
1290   { (AL_OBJ_CTR_ALL   & 0xFF00),  "Counter"                     },
1291   { (AL_OBJ_FCTR_ALL  & 0xFF00),  "Frozen Counter"              },
1292   { (AL_OBJ_CTRC_ALL  & 0xFF00),  "Counter Change"              },
1293   { (AL_OBJ_FCTRC_ALL & 0xFF00),  "Frozen Counter Change"       },
1294   { (AL_OBJ_AI_ALL    & 0xFF00),  "Analog Input"                },
1295   { (AL_OBJ_AIC_ALL   & 0xFF00),  "Analog Input Change"         },
1296   { (AL_OBJ_AO_ALL    & 0xFF00),  "Analog Output"               },
1297   { (AL_OBJ_AOC_ALL   & 0xFF00),  "Analog Output Change"        },
1298   { (AL_OBJ_TD_ALL    & 0xFF00),  "Time and Date"               },
1299   { (AL_OBJ_FILE_CMD  & 0xFF00),  "File Control"                },
1300   { (AL_OBJ_IIN       & 0xFF00),  "Internal Indications"        },
1301   { (AL_OBJ_OCT       & 0xFF00),  "Octet String"                },
1302   { (AL_OBJ_OCT_EVT   & 0xFF00),  "Octet String Event"          },
1303   { (AL_OBJ_VT_EVTD   & 0xFF00),  "Virtual Terminal Event Data" },
1304   { 0, NULL }
1305 };
1306 
1307 static value_string_ext dnp3_al_read_obj_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_read_obj_vals);
1308 
1309 /* Application Layer Write Object Type values */
1310 static const value_string dnp3_al_write_obj_vals[] = {
1311   { (AL_OBJ_TD_ALL   & 0xFF00),  "Time and Date"                 },
1312   { (AL_OBJ_FILE_CMD & 0xFF00),  "File Control"                  },
1313   { (AL_OBJ_IIN      & 0xFF00),  "Internal Indications"          },
1314   { (AL_OBJ_OCT      & 0xFF00),  "Octet String"                  },
1315   { (AL_OBJ_OCT_EVT  & 0xFF00),  "Octet String Event"            },
1316   { (AL_OBJ_VT_OBLK  & 0xFF00),  "Virtual Terminal Output Block" },
1317   { 0, NULL }
1318 };
1319 
1320 static value_string_ext dnp3_al_write_obj_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_write_obj_vals);
1321 
1322 /* Initialize the subtree pointers */
1323 static gint ett_dnp3 = -1;
1324 static gint ett_dnp3_dl = -1;
1325 static gint ett_dnp3_dl_ctl = -1;
1326 static gint ett_dnp3_tr_ctl = -1;
1327 static gint ett_dnp3_dl_data = -1;
1328 static gint ett_dnp3_dl_chunk = -1;
1329 static gint ett_dnp3_al = -1;
1330 static gint ett_dnp3_al_ctl = -1;
1331 static gint ett_dnp3_al_obj_point_tcc = -1;
1332 
1333 /* Added for Application Layer Decoding */
1334 static gint ett_dnp3_al_iin = -1;
1335 static gint ett_dnp3_al_obj = -1;
1336 static gint ett_dnp3_al_obj_qualifier = -1;
1337 static gint ett_dnp3_al_obj_range = -1;
1338 static gint ett_dnp3_al_objdet = -1;
1339 static gint ett_dnp3_al_obj_quality = -1;
1340 static gint ett_dnp3_al_obj_point = -1;
1341 static gint ett_dnp3_al_obj_point_perms = -1;
1342 
1343 static expert_field ei_dnp_num_items_neg = EI_INIT;
1344 static expert_field ei_dnp_invalid_length = EI_INIT;
1345 static expert_field ei_dnp_iin_abnormal = EI_INIT;
1346 static expert_field ei_dnp3_data_hdr_crc_incorrect = EI_INIT;
1347 static expert_field ei_dnp3_data_chunk_crc_incorrect = EI_INIT;
1348 static expert_field ei_dnp3_unknown_object = EI_INIT;
1349 static expert_field ei_dnp3_unknown_group0_variation = EI_INIT;
1350 static expert_field ei_dnp3_num_items_invalid = EI_INIT;
1351 /* Generated from convert_proto_tree_add_text.pl */
1352 #if 0
1353 static expert_field ei_dnp3_buffering_user_data_until_final_frame_is_received = EI_INIT;
1354 #endif
1355 
1356 /* Tables for reassembly of fragments. */
1357 static reassembly_table al_reassembly_table;
1358 
1359 /* ************************************************************************* */
1360 /*                   Header values for reassembly                            */
1361 /* ************************************************************************* */
1362 static int   hf_al_frag_data   = -1;
1363 static int   hf_dnp3_fragment  = -1;
1364 static int   hf_dnp3_fragments = -1;
1365 static int   hf_dnp3_fragment_overlap = -1;
1366 static int   hf_dnp3_fragment_overlap_conflict = -1;
1367 static int   hf_dnp3_fragment_multiple_tails = -1;
1368 static int   hf_dnp3_fragment_too_long_fragment = -1;
1369 static int   hf_dnp3_fragment_error = -1;
1370 static int   hf_dnp3_fragment_count = -1;
1371 static int   hf_dnp3_fragment_reassembled_in = -1;
1372 static int   hf_dnp3_fragment_reassembled_length = -1;
1373 static gint ett_dnp3_fragment  = -1;
1374 static gint ett_dnp3_fragments = -1;
1375 
1376 static dissector_handle_t dnp3_tcp_handle;
1377 static dissector_handle_t dnp3_udp_handle;
1378 
1379 static const fragment_items dnp3_frag_items = {
1380   &ett_dnp3_fragment,
1381   &ett_dnp3_fragments,
1382   &hf_dnp3_fragments,
1383   &hf_dnp3_fragment,
1384   &hf_dnp3_fragment_overlap,
1385   &hf_dnp3_fragment_overlap_conflict,
1386   &hf_dnp3_fragment_multiple_tails,
1387   &hf_dnp3_fragment_too_long_fragment,
1388   &hf_dnp3_fragment_error,
1389   &hf_dnp3_fragment_count,
1390   &hf_dnp3_fragment_reassembled_in,
1391   &hf_dnp3_fragment_reassembled_length,
1392   /* Reassembled data field */
1393   NULL,
1394   "DNP 3.0 fragments"
1395 };
1396 
1397 /* desegmentation of DNP3 over TCP */
1398 static gboolean dnp3_desegment = TRUE;
1399 
1400 /* Enum for different quality type fields */
1401 enum QUALITY_TYPE {
1402   BIN_IN,
1403   BIN_OUT,
1404   ANA_IN,
1405   ANA_OUT,
1406   COUNTER
1407 };
1408 
1409 /* calculates crc given a buffer of characters and a length of buffer */
1410 static guint16
calculateCRC(const void * buf,guint len)1411 calculateCRC(const void *buf, guint len) {
1412   guint16 crc = crc16_0x3D65_seed((const guint8 *)buf, len, 0);
1413   return ~crc;
1414 }
1415 
1416 /* calculates crc given a tvbuff, offset, and length */
1417 static guint16
calculateCRCtvb(tvbuff_t * tvb,guint offset,guint len)1418 calculateCRCtvb(tvbuff_t *tvb, guint offset, guint len) {
1419   guint16 crc = crc16_0x3D65_tvb_offset_seed(tvb, offset, len, 0);
1420   return ~crc;
1421 }
1422 
1423 /*****************************************************************/
1424 /*  Application Layer Process Internal Indications (IIN)         */
1425 /*****************************************************************/
1426 static void
dnp3_al_process_iin(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * al_tree)1427 dnp3_al_process_iin(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *al_tree)
1428 {
1429   guint16     al_iin;
1430   proto_item *tiin;
1431   static int* const indications[] = {
1432       &hf_dnp3_al_iin_rst,
1433       &hf_dnp3_al_iin_dt,
1434       &hf_dnp3_al_iin_dol,
1435       &hf_dnp3_al_iin_tsr,
1436       &hf_dnp3_al_iin_cls3d,
1437       &hf_dnp3_al_iin_cls2d,
1438       &hf_dnp3_al_iin_cls1d,
1439       &hf_dnp3_al_iin_bmsg,
1440       &hf_dnp3_al_iin_cc,
1441       &hf_dnp3_al_iin_oae,
1442       &hf_dnp3_al_iin_ebo,
1443       &hf_dnp3_al_iin_pioor,
1444       &hf_dnp3_al_iin_obju,
1445       &hf_dnp3_al_iin_fcni,
1446       NULL
1447   };
1448 
1449   tiin = proto_tree_add_bitmask(al_tree, tvb, offset, hf_dnp3_al_iin, ett_dnp3_al_iin, indications, ENC_BIG_ENDIAN);
1450   al_iin = tvb_get_ntohs(tvb, offset);
1451 
1452   /* If IIN indicates an abnormal condition, add expert info */
1453   if ((al_iin & AL_IIN_DT) || (al_iin & AL_IIN_CC) || (al_iin & AL_IIN_OAE) || (al_iin & AL_IIN_EBO) ||
1454       (al_iin & AL_IIN_PIOOR) || (al_iin & AL_IIN_OBJU) || (al_iin & AL_IIN_FCNI)) {
1455       expert_add_info(pinfo, tiin, &ei_dnp_iin_abnormal);
1456   }
1457 }
1458 
1459 /**************************************************************/
1460 /* Function to determine Application Layer Object Prefix size */
1461 /* and Point address.                                         */
1462 /**************************************************************/
1463 static int
dnp3_al_obj_procprefix(tvbuff_t * tvb,int offset,guint8 al_objq_prefix,guint32 * al_ptaddr,proto_tree * item_tree)1464 dnp3_al_obj_procprefix(tvbuff_t *tvb, int offset, guint8 al_objq_prefix, guint32 *al_ptaddr, proto_tree *item_tree)
1465 {
1466   int         prefixbytes = 0;
1467   proto_item *prefix_item;
1468 
1469   switch (al_objq_prefix)
1470   {
1471     case AL_OBJQL_PREFIX_NI:        /* No Prefix */
1472       prefixbytes = 0;
1473       prefix_item = proto_tree_add_uint(item_tree, hf_dnp3_al_point_index, tvb, offset, 0, *al_ptaddr);
1474       proto_item_set_generated(prefix_item);
1475       break;
1476     case AL_OBJQL_PREFIX_1O:
1477       *al_ptaddr = tvb_get_guint8(tvb, offset);
1478       proto_tree_add_item(item_tree, hf_dnp3_al_index8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1479       prefixbytes = 1;
1480       break;
1481     case AL_OBJQL_PREFIX_2O:
1482       *al_ptaddr = tvb_get_letohs(tvb, offset);
1483       proto_tree_add_item(item_tree, hf_dnp3_al_index16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1484       prefixbytes = 2;
1485       break;
1486     case AL_OBJQL_PREFIX_4O:
1487       *al_ptaddr = tvb_get_letohl(tvb, offset);
1488       proto_tree_add_item(item_tree, hf_dnp3_al_index32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1489       prefixbytes = 4;
1490       break;
1491     case AL_OBJQL_PREFIX_1OS:
1492       *al_ptaddr = tvb_get_guint8(tvb, offset);
1493       proto_tree_add_item(item_tree, hf_dnp3_al_size8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1494       prefixbytes = 1;
1495       break;
1496     case AL_OBJQL_PREFIX_2OS:
1497       *al_ptaddr = tvb_get_letohs(tvb, offset);
1498       proto_tree_add_item(item_tree, hf_dnp3_al_size16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1499       prefixbytes = 2;
1500       break;
1501     case AL_OBJQL_PREFIX_4OS:
1502       *al_ptaddr = tvb_get_letohl(tvb, offset);
1503       proto_tree_add_item(item_tree, hf_dnp3_al_size32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1504       prefixbytes = 4;
1505       break;
1506   }
1507   return prefixbytes;
1508 }
1509 
1510 /*****************************************************************/
1511 /* Function to add the same string to two separate tree items    */
1512 /*****************************************************************/
1513 static void
dnp3_append_2item_text(proto_item * item1,proto_item * item2,const gchar * text)1514 dnp3_append_2item_text(proto_item *item1, proto_item *item2, const gchar *text)
1515 {
1516   proto_item_append_text(item1, "%s", text);
1517   proto_item_append_text(item2, "%s", text);
1518 }
1519 
1520 /*****************************************************************/
1521 /* Function to Determine Application Layer Point Quality Flags & */
1522 /* add Point Quality Flag Sub-Tree                               */
1523 /*****************************************************************/
1524 static void
dnp3_al_obj_quality(tvbuff_t * tvb,int offset,guint8 al_ptflags,proto_tree * point_tree,proto_item * point_item,enum QUALITY_TYPE type)1525 dnp3_al_obj_quality(tvbuff_t *tvb, int offset, guint8 al_ptflags, proto_tree *point_tree, proto_item *point_item, enum QUALITY_TYPE type)
1526 {
1527 
1528   proto_tree *quality_tree;
1529   proto_item *quality_item;
1530   int         hf0 = 0, hf1 = 0, hf2 = 0, hf3 = 0, hf4 = 0, hf5 = 0, hf6 = 0, hf7 = 0;
1531 
1532   /* Common code */
1533   proto_item_append_text(point_item, " (Quality: ");
1534   quality_tree = proto_tree_add_subtree(point_tree, tvb, offset, 1, ett_dnp3_al_obj_quality, &quality_item, "Quality: ");
1535 
1536   if (al_ptflags & AL_OBJ_BI_FLAG0) {
1537     dnp3_append_2item_text(point_item, quality_item, "Online");
1538   }
1539   else {
1540     dnp3_append_2item_text(point_item, quality_item, "Offline");
1541   }
1542   if (al_ptflags & AL_OBJ_BI_FLAG1) dnp3_append_2item_text(point_item, quality_item, ", Restart");
1543   if (al_ptflags & AL_OBJ_BI_FLAG2) dnp3_append_2item_text(point_item, quality_item, ", Comm Fail");
1544   if (al_ptflags & AL_OBJ_BI_FLAG3) dnp3_append_2item_text(point_item, quality_item, ", Remote Force");
1545   if (al_ptflags & AL_OBJ_BI_FLAG4) dnp3_append_2item_text(point_item, quality_item, ", Local Force");
1546 
1547   switch (type) {
1548     case BIN_IN: /* Binary Input Quality flags */
1549       if (al_ptflags & AL_OBJ_BI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Chatter Filter");
1550 
1551       hf0 = hf_dnp3_al_biq_b0;
1552       hf1 = hf_dnp3_al_biq_b1;
1553       hf2 = hf_dnp3_al_biq_b2;
1554       hf3 = hf_dnp3_al_biq_b3;
1555       hf4 = hf_dnp3_al_biq_b4;
1556       hf5 = hf_dnp3_al_biq_b5;
1557       hf6 = hf_dnp3_al_biq_b6;
1558       hf7 = hf_dnp3_al_biq_b7;
1559       break;
1560 
1561     case BIN_OUT: /* Binary Output Quality flags */
1562       hf0 = hf_dnp3_al_boq_b0;
1563       hf1 = hf_dnp3_al_boq_b1;
1564       hf2 = hf_dnp3_al_boq_b2;
1565       hf3 = hf_dnp3_al_boq_b3;
1566       hf4 = hf_dnp3_al_boq_b4;
1567       hf5 = hf_dnp3_al_boq_b5;
1568       hf6 = hf_dnp3_al_boq_b6;
1569       hf7 = hf_dnp3_al_boq_b7;
1570       break;
1571 
1572     case ANA_IN: /* Analog Input Quality flags */
1573       if (al_ptflags & AL_OBJ_AI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Over-Range");
1574       if (al_ptflags & AL_OBJ_AI_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Reference Check");
1575 
1576       hf0 = hf_dnp3_al_aiq_b0;
1577       hf1 = hf_dnp3_al_aiq_b1;
1578       hf2 = hf_dnp3_al_aiq_b2;
1579       hf3 = hf_dnp3_al_aiq_b3;
1580       hf4 = hf_dnp3_al_aiq_b4;
1581       hf5 = hf_dnp3_al_aiq_b5;
1582       hf6 = hf_dnp3_al_aiq_b6;
1583       hf7 = hf_dnp3_al_aiq_b7;
1584       break;
1585 
1586     case ANA_OUT: /* Analog Output Quality flags */
1587       hf0 = hf_dnp3_al_aoq_b0;
1588       hf1 = hf_dnp3_al_aoq_b1;
1589       hf2 = hf_dnp3_al_aoq_b2;
1590       hf3 = hf_dnp3_al_aoq_b3;
1591       hf4 = hf_dnp3_al_aoq_b4;
1592       hf5 = hf_dnp3_al_aoq_b5;
1593       hf6 = hf_dnp3_al_aoq_b6;
1594       hf7 = hf_dnp3_al_aoq_b7;
1595       break;
1596 
1597     case COUNTER: /* Counter Quality flags */
1598       if (al_ptflags & AL_OBJ_CTR_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Roll-over");
1599       if (al_ptflags & AL_OBJ_CTR_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Discontinuity");
1600 
1601       hf0 = hf_dnp3_al_ctrq_b0;
1602       hf1 = hf_dnp3_al_ctrq_b1;
1603       hf2 = hf_dnp3_al_ctrq_b2;
1604       hf3 = hf_dnp3_al_ctrq_b3;
1605       hf4 = hf_dnp3_al_ctrq_b4;
1606       hf5 = hf_dnp3_al_ctrq_b5;
1607       hf6 = hf_dnp3_al_ctrq_b6;
1608       hf7 = hf_dnp3_al_ctrq_b7;
1609       break;
1610   }
1611 
1612   if (quality_tree != NULL) {
1613     proto_tree_add_item(quality_tree, hf7, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1614     proto_tree_add_item(quality_tree, hf6, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1615     proto_tree_add_item(quality_tree, hf5, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1616     proto_tree_add_item(quality_tree, hf4, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1617     proto_tree_add_item(quality_tree, hf3, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1618     proto_tree_add_item(quality_tree, hf2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1619     proto_tree_add_item(quality_tree, hf1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1620     proto_tree_add_item(quality_tree, hf0, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1621   }
1622   proto_item_append_text(point_item, ")");
1623 }
1624 
1625 /**********************************************************************/
1626 /* Function to convert DNP3 timestamp to nstime_t value               */
1627 /**********************************************************************/
1628 /* 48-bit Time Format                                                 */
1629 /* MSB      FF       EE       DD       CC       BB       AA      LSB  */
1630 /*       ffffffff eeeeeeee dddddddd cccccccc bbbbbbbb aaaaaaaa        */
1631 /*       47    40 39    32 31    24 23    16 15     8 7      0        */
1632 /*                                                                    */
1633 /* Value is ms since 00:00 on 1/1/1970                                */
1634 /**********************************************************************/
1635 static void
dnp3_al_get_timestamp(nstime_t * timestamp,tvbuff_t * tvb,int data_pos)1636 dnp3_al_get_timestamp(nstime_t *timestamp, tvbuff_t *tvb, int data_pos)
1637 {
1638 
1639   guint32 hi, lo;
1640   guint64 time_ms;
1641 
1642   lo = tvb_get_letohs(tvb, data_pos);
1643   hi = tvb_get_letohl(tvb, data_pos + 2);
1644 
1645   time_ms = (guint64)hi * 0x10000 + lo;
1646 
1647   timestamp->secs  = (long)(time_ms / 1000);
1648   timestamp->nsecs = (int)(time_ms % 1000) * 1000000;
1649 }
1650 
1651 static gboolean
dnp3_al_empty_obj(guint16 al_obj)1652 dnp3_al_empty_obj(guint16 al_obj)
1653 {
1654 
1655   /* return a TRUE if we expect an empty object (default var, class object, etc) */
1656   switch (al_obj)
1657   {
1658     case AL_OBJ_BI_ALL:      /* Binary Input Default Variation (Obj:01, Var:Default) */
1659     case AL_OBJ_BIC_ALL:     /* Binary Input Change Default Variation (Obj:02, Var:Default) */
1660     case AL_OBJ_BOC_ALL:     /* Binary Output Event Default Variation (Obj:11, Var:Default) */
1661     case AL_OBJ_2BI_ALL:     /* Double-bit Input Default Variation (Obj:03, Var:Default) */
1662     case AL_OBJ_2BIC_ALL:    /* Double-bit Input Change Default Variation (Obj:04, Var:Default) */
1663     case AL_OBJ_CTR_ALL:     /* Binary Counter Default Variation (Obj:20, Var:Default) */
1664     case AL_OBJ_CTRC_ALL:    /* Binary Counter Change Default Variation (Obj:22 Var:Default) */
1665     case AL_OBJ_AI_ALL:      /* Analog Input Default Variation (Obj:30, Var:Default) */
1666     case AL_OBJ_AIC_ALL:     /* Analog Input Change Default Variation (Obj:32 Var:Default) */
1667     case AL_OBJ_AIDB_ALL:    /* Analog Input Deadband Default Variation (Obj:34, Var:Default) */
1668     case AL_OBJ_AOC_ALL:     /* Analog Output Event Default Variation (Obj:42 Var:Default) */
1669     case AL_OBJ_CLASS0:      /* Class Data Objects */
1670     case AL_OBJ_CLASS1:
1671     case AL_OBJ_CLASS2:
1672     case AL_OBJ_CLASS3:
1673       return TRUE;
1674       break;
1675     default:
1676       return FALSE;
1677       break;
1678   }
1679 }
1680 
1681 /*****************************************************************/
1682 /*  Desc:    Application Layer Process Object Details            */
1683 /*  Returns: New offset pointer into tvb                         */
1684 /*****************************************************************/
1685 static int
dnp3_al_process_object(tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * robj_tree,gboolean header_only,guint16 * al_objtype,nstime_t * al_cto)1686 dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset,
1687                        proto_tree *robj_tree, gboolean header_only,
1688                        guint16 *al_objtype, nstime_t *al_cto)
1689 {
1690 
1691   guint8      al_objq, al_objq_prefix, al_objq_range, al_oct_len = 0, bitindex;
1692   guint16     al_obj, temp;
1693   guint32     al_ptaddr = 0;
1694   int         num_items = 0;
1695   int         orig_offset, rangebytes = 0;
1696   proto_item *object_item, *range_item;
1697   proto_tree *object_tree, *qualifier_tree, *range_tree;
1698 
1699   orig_offset = offset;
1700 
1701   /* Application Layer Objects in this Message */
1702   *al_objtype =
1703   al_obj = tvb_get_ntohs(tvb, offset);
1704 
1705   /* Special handling for Octet string objects as the variation is the length of the string */
1706   temp = al_obj & 0xFF00;
1707   if ((temp == AL_OBJ_OCT) || (temp == AL_OBJ_OCT_EVT )) {
1708     al_oct_len = al_obj & 0xFF;
1709     al_obj = temp;
1710   }
1711 
1712   /* Create Data Objects Detail Tree */
1713   if (AL_OBJ_GROUP(al_obj) == 0x0) {
1714     object_item = proto_tree_add_uint_format(robj_tree, hf_dnp3_al_obj, tvb, offset, 2, al_obj,
1715                                              "Object(s): %s (0x%04x)",
1716                                              val_to_str_ext_const(al_obj, &dnp3_al_obj_vals_ext, "Unknown group 0 Variation"),
1717                                              al_obj);
1718     if (try_val_to_str_ext(al_obj, &dnp3_al_obj_vals_ext) == NULL) {
1719       expert_add_info(pinfo, object_item, &ei_dnp3_unknown_group0_variation);
1720     }
1721   }
1722   else if ((AL_OBJ_GROUP(al_obj) == AL_OBJ_GROUP(AL_OBJ_OCT)) || (AL_OBJ_GROUP(al_obj) == AL_OBJ_GROUP(AL_OBJ_OCT_EVT))) {
1723     /* For octet strings the variation is the length */
1724     object_item = proto_tree_add_uint_format(robj_tree, hf_dnp3_al_obj, tvb, offset, 2, al_obj,
1725                                              "Object(s): %s (0x%04x), Length: %d",
1726                                              val_to_str_ext_const(al_obj, &dnp3_al_obj_vals_ext, "Unknown Object\\Variation"),
1727                                              al_obj, al_oct_len);
1728   }
1729   else {
1730     object_item = proto_tree_add_uint_format(robj_tree, hf_dnp3_al_obj, tvb, offset, 2, al_obj,
1731                                              "Object(s): %s (0x%04x)",
1732                                              val_to_str_ext_const(al_obj, &dnp3_al_obj_vals_ext, "Unknown Object\\Variation"),
1733                                              al_obj);
1734     if (try_val_to_str_ext(al_obj, &dnp3_al_obj_vals_ext) == NULL) {
1735       expert_add_info(pinfo, object_item, &ei_dnp3_unknown_object);
1736     }
1737   }
1738   object_tree = proto_item_add_subtree(object_item, ett_dnp3_al_obj);
1739 
1740   offset += 2;
1741 
1742   /* Object Qualifier */
1743   al_objq = tvb_get_guint8(tvb, offset);
1744   al_objq_prefix = al_objq & AL_OBJQ_PREFIX;
1745   al_objq_prefix = al_objq_prefix >> 4;
1746   al_objq_range = al_objq & AL_OBJQ_RANGE;
1747 
1748   qualifier_tree = proto_tree_add_subtree_format(object_tree, tvb, offset, 1, ett_dnp3_al_obj_qualifier, NULL,
1749     "Qualifier Field, Prefix: %s, Range: %s",
1750     val_to_str_ext_const(al_objq_prefix, &dnp3_al_objq_prefix_vals_ext, "Unknown Prefix Type"),
1751     val_to_str_ext_const(al_objq_range, &dnp3_al_objq_range_vals_ext, "Unknown Range Type"));
1752   proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_prefix, tvb, offset, 1, ENC_BIG_ENDIAN);
1753   proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_range, tvb, offset, 1, ENC_BIG_ENDIAN);
1754 
1755   offset += 1;
1756 
1757   /* Create (possibly synthesized) number of items and range field tree */
1758   range_tree = proto_tree_add_subtree(object_tree, tvb, offset, 0, ett_dnp3_al_obj_range, &range_item, "Number of Items: ");
1759 
1760   switch (al_objq_range)
1761   {
1762     case AL_OBJQL_RANGE_SSI8:           /* 8-bit Start and Stop Indices in Range Field */
1763       num_items = ( tvb_get_guint8(tvb, offset+1) - tvb_get_guint8(tvb, offset) + 1);
1764       proto_item_set_generated(range_item);
1765       al_ptaddr = tvb_get_guint8(tvb, offset);
1766       proto_tree_add_item(range_tree, hf_dnp3_al_range_start8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1767       proto_tree_add_item(range_tree, hf_dnp3_al_range_stop8, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1768       rangebytes = 2;
1769       break;
1770     case AL_OBJQL_RANGE_SSI16:          /* 16-bit Start and Stop Indices in Range Field */
1771       num_items = ( tvb_get_letohs(tvb, offset+2) - tvb_get_letohs(tvb, (offset)) + 1);
1772       proto_item_set_generated(range_item);
1773       al_ptaddr = tvb_get_letohs(tvb, offset);
1774       proto_tree_add_item(range_tree, hf_dnp3_al_range_start16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1775       proto_tree_add_item(range_tree, hf_dnp3_al_range_stop16, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
1776       rangebytes = 4;
1777       break;
1778     case AL_OBJQL_RANGE_SSI32:          /* 32-bit Start and Stop Indices in Range Field */
1779       num_items = ( tvb_get_letohl(tvb, offset+4) - tvb_get_letohl(tvb, offset) + 1);
1780       proto_item_set_generated(range_item);
1781       al_ptaddr = tvb_get_letohl(tvb, offset);
1782       proto_tree_add_item(range_tree, hf_dnp3_al_range_start32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1783       proto_tree_add_item(range_tree, hf_dnp3_al_range_stop32, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
1784       rangebytes = 8;
1785       break;
1786     case AL_OBJQL_RANGE_AA8:            /* 8-bit Absolute Address in Range Field */
1787       num_items = 1;
1788       proto_item_set_generated(range_item);
1789       al_ptaddr = tvb_get_guint8(tvb, offset);
1790       proto_tree_add_item(range_tree, hf_dnp3_al_range_abs8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1791       rangebytes = 1;
1792       break;
1793     case AL_OBJQL_RANGE_AA16:           /* 16-bit Absolute Address in Range Field */
1794       num_items = 1;
1795       proto_item_set_generated(range_item);
1796       al_ptaddr = tvb_get_letohs(tvb, offset);
1797       proto_tree_add_item(range_tree, hf_dnp3_al_range_abs16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1798       rangebytes = 2;
1799       break;
1800     case AL_OBJQL_RANGE_AA32:           /* 32-bit Absolute Address in Range Field */
1801       num_items = 1;
1802       proto_item_set_generated(range_item);
1803       al_ptaddr = tvb_get_letohl(tvb, offset);
1804       proto_tree_add_item(range_tree, hf_dnp3_al_range_abs32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1805       rangebytes = 4;
1806       break;
1807     case AL_OBJQL_RANGE_SF8:            /* 8-bit Single Field Quantity in Range Field */
1808       num_items = tvb_get_guint8(tvb, offset);
1809       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1810       rangebytes = 1;
1811       proto_item_set_len(range_item, rangebytes);
1812       break;
1813     case AL_OBJQL_RANGE_SF16:           /* 16-bit Single Field Quantity in Range Field */
1814       num_items = tvb_get_letohs(tvb, offset);
1815       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1816       rangebytes = 2;
1817       proto_item_set_len(range_item, rangebytes);
1818       break;
1819     case AL_OBJQL_RANGE_SF32:           /* 32-bit Single Field Quantity in Range Field */
1820       num_items = tvb_get_letohl(tvb, offset);
1821       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1822       rangebytes = 4;
1823       proto_item_set_len(range_item, rangebytes);
1824       break;
1825     case AL_OBJQL_RANGE_FF:            /* 8 bit object count in Range Field */
1826       num_items = tvb_get_guint8(tvb, offset);
1827       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1828       rangebytes = 1;
1829       proto_item_set_len(range_item, rangebytes);
1830   }
1831   if (num_items > 0) {
1832     proto_item_append_text(object_item, ", %d point%s", num_items, plurality(num_items, "", "s"));
1833   }
1834   proto_item_append_text(range_item, "%d", num_items);
1835 
1836   /* A negative number of items is an error */
1837   if (num_items < 0) {
1838     proto_item_append_text(range_item, " (bogus)");
1839     expert_add_info(pinfo, range_item, &ei_dnp_num_items_neg);
1840     return tvb_captured_length(tvb);
1841   }
1842 
1843   /* Move offset past any range field */
1844   offset += rangebytes;
1845 
1846   bitindex = 0; /* Temp variable for cycling through points when object values are encoded into
1847                    bits; primarily objects 0x0101, 0x0301 & 0x1001 */
1848 
1849   /* Only process the point information for replies or items with point index lists */
1850   if (!header_only || al_objq_prefix > 0) {
1851     int item_num;
1852     int start_offset;
1853 
1854     start_offset = offset;
1855     for (item_num = 0; item_num < num_items; item_num++)
1856     {
1857       proto_item *point_item;
1858       proto_tree *point_tree;
1859       guint       data_pos;
1860       int         prefixbytes;
1861 
1862       /* Create Point item and process prefix */
1863       if (al_objq_prefix <= AL_OBJQL_PREFIX_4O) {
1864         point_tree = proto_tree_add_subtree(object_tree, tvb, offset, -1, ett_dnp3_al_obj_point, &point_item, "Point Number");
1865       }
1866       else {
1867         point_tree = proto_tree_add_subtree(object_tree, tvb, offset, -1, ett_dnp3_al_obj_point, &point_item, "Object: Size");
1868       }
1869 
1870       data_pos   = offset;
1871       prefixbytes = dnp3_al_obj_procprefix(tvb, offset, al_objq_prefix, &al_ptaddr, point_tree);
1872 
1873       /* If this is an 'empty' object type and the num_items field is not equal to zero,
1874          then the packet is potentially malicious */
1875       if ((num_items != 0) && (dnp3_al_empty_obj(al_obj))) {
1876         proto_item_append_text(range_item, " (bogus)");
1877         expert_add_info(pinfo, range_item, &ei_dnp3_num_items_invalid);
1878         num_items = 0;
1879       }
1880 
1881       proto_item_append_text(point_item, " %u", al_ptaddr);
1882       proto_item_set_len(point_item, prefixbytes);
1883       data_pos += prefixbytes;
1884 
1885       if (!header_only || (AL_OBJQL_PREFIX_1OS <= al_objq_prefix && al_objq_prefix <= AL_OBJQL_PREFIX_4OS)) {
1886         /* Process the object values */
1887         guint8       al_2bit, al_ptflags, al_bi_val, al_tcc_code;
1888         gint16       al_val_int16;
1889         guint16      al_val_uint16, al_ctlobj_stat;
1890         guint16      al_relms, al_filename_len, al_file_ctrl_mode;
1891         gint32       al_val_int32;
1892         guint32      al_val_uint32, file_data_size;
1893         nstime_t     al_reltime, al_abstime;
1894         gboolean     al_bit;
1895         gfloat       al_valflt;
1896         gdouble      al_valdbl;
1897         const gchar *ctl_status_str;
1898 
1899         /* Device Attributes (g0) all have a type code, use that rather than the individual variation */
1900         if (AL_OBJ_GROUP(al_obj) == 0x0) {
1901           guint32 data_type;
1902           guint8 da_len;
1903 
1904           /* Add and retrieve the data type */
1905           proto_tree_add_item_ret_uint(point_tree, hf_dnp3_al_datatype, tvb, data_pos, 1, ENC_LITTLE_ENDIAN, &data_type);
1906           data_pos++;
1907 
1908           /* If a valid data type process it */
1909           if (try_val_to_str(data_type, dnp3_al_data_type_vals) != NULL) {
1910             switch(data_type) {
1911               case AL_DATA_TYPE_NONE:
1912                 break;
1913               case AL_DATA_TYPE_VSTR:
1914                 da_len = tvb_get_guint8(tvb, data_pos);
1915                 proto_tree_add_item(point_tree, hf_dnp3_al_da_length, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
1916                 data_pos++;
1917                 const guint8* da_value;
1918                 proto_tree_add_item_ret_string(point_tree, hf_dnp3_al_da_value, tvb, data_pos, da_len, ENC_ASCII|ENC_NA, pinfo->pool, &da_value);
1919                 proto_item_append_text(object_item, ", Value: %s", da_value);
1920                 data_pos += da_len;
1921                 break;
1922               case AL_DATA_TYPE_UINT:
1923                 da_len = tvb_get_guint8(tvb, data_pos);
1924                 proto_tree_add_item(point_tree, hf_dnp3_al_da_length, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
1925                 data_pos++;
1926                 if (da_len == 1) {
1927                   proto_tree_add_item(point_tree, hf_dnp3_al_da_uint8, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
1928                   proto_item_append_text(object_item, ", Value: %u", tvb_get_guint8(tvb, data_pos));
1929                   data_pos++;
1930                 }
1931                 else if (da_len == 2) {
1932                   proto_tree_add_item(point_tree, hf_dnp3_al_da_uint16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
1933                   proto_item_append_text(object_item, ", Value: %u", tvb_get_letohs(tvb, data_pos));
1934                   data_pos += 2;
1935                 }
1936                 else if (da_len == 4) {
1937                   proto_tree_add_item(point_tree, hf_dnp3_al_da_uint32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
1938                   proto_item_append_text(object_item, ", Value: %u", tvb_get_letohl(tvb, data_pos));
1939                   data_pos += 4;
1940                 }
1941                 break;
1942               case AL_DATA_TYPE_INT:
1943                 da_len = tvb_get_guint8(tvb, data_pos);
1944                 proto_tree_add_item(point_tree, hf_dnp3_al_da_length, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
1945                 data_pos++;
1946                 if (da_len == 1) {
1947                   proto_tree_add_item(point_tree, hf_dnp3_al_da_int8, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
1948                   proto_item_append_text(object_item, ", Value: %d", tvb_get_guint8(tvb, data_pos));
1949                   data_pos++;
1950                 }
1951                 else if (da_len == 2) {
1952                   proto_tree_add_item(point_tree, hf_dnp3_al_da_int16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
1953                   proto_item_append_text(object_item, ", Value: %d", tvb_get_letohs(tvb, data_pos));
1954                   data_pos += 2;
1955                 }
1956                 else if (da_len == 4) {
1957                   proto_tree_add_item(point_tree, hf_dnp3_al_da_int32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
1958                   proto_item_append_text(object_item, ", Value: %d", tvb_get_letohl(tvb, data_pos));
1959                   data_pos += 4;
1960                 }
1961                 break;
1962               case AL_DATA_TYPE_FLT:
1963                 da_len = tvb_get_guint8(tvb, data_pos);
1964                 proto_tree_add_item(point_tree, hf_dnp3_al_da_length, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
1965                 data_pos++;
1966                 if (da_len == 4) {
1967                   proto_tree_add_item(point_tree, hf_dnp3_al_da_flt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
1968                   proto_item_append_text(object_item, ", Value: %g", tvb_get_letohieee_float(tvb, data_pos));
1969                   data_pos += 4;
1970                 }
1971                 else if (da_len == 8) {
1972                   proto_tree_add_item(point_tree, hf_dnp3_al_da_dbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
1973                   proto_item_append_text(object_item, ", Value: %g", tvb_get_letohieee_double(tvb, data_pos));
1974                   data_pos += 8;
1975                 }
1976                 break;
1977               case AL_DATA_TYPE_OSTR:
1978                 break;
1979               case AL_DATA_TYPE_BSTR:
1980                 break;
1981               case AL_DATA_TYPE_TIME:
1982                 break;
1983               case AL_DATA_TYPE_UNCD:
1984                 break;
1985               case AL_DATA_TYPE_U8BS8LIST:
1986                 break;
1987               case AL_DATA_TYPE_U8BS8EXLIST:
1988                 break;
1989             }
1990           }
1991           offset = data_pos;
1992         }
1993         else {
1994 
1995           /* All other objects are handled here, by their variations */
1996           switch (al_obj)
1997           {
1998 
1999             /* There is nothing to handle for the default variations */
2000             case AL_OBJ_BI_ALL:      /* Binary Input Default Variation (Obj:01, Var:Default) */
2001             case AL_OBJ_BIC_ALL:     /* Binary Input Change Default Variation (Obj:02, Var:Default) */
2002             case AL_OBJ_BOC_ALL:     /* Binary Output Event Default Variation (Obj:11, Var:Default) */
2003             case AL_OBJ_2BI_ALL:     /* Double-bit Input Default Variation (Obj:03, Var:Default) */
2004             case AL_OBJ_2BIC_ALL:    /* Double-bit Input Change Default Variation (Obj:04, Var:Default) */
2005             case AL_OBJ_CTR_ALL:     /* Binary Counter Default Variation (Obj:20, Var:Default) */
2006             case AL_OBJ_CTRC_ALL:    /* Binary Counter Change Default Variation (Obj:22 Var:Default) */
2007             case AL_OBJ_AI_ALL:      /* Analog Input Default Variation (Obj:30, Var:Default) */
2008             case AL_OBJ_AIC_ALL:     /* Analog Input Change Default Variation (Obj:32 Var:Default) */
2009             case AL_OBJ_AIDB_ALL:    /* Analog Input Deadband Default Variation (Obj:34, Var:Default) */
2010             case AL_OBJ_AOC_ALL:     /* Analog Output Event Default Variation (Obj:42 Var:Default) */
2011 
2012               offset = data_pos;
2013               break;
2014 
2015             /* Bit-based Data objects here */
2016             case AL_OBJ_BI_1BIT:    /* Single-Bit Binary Input (Obj:01, Var:01) */
2017             case AL_OBJ_BO:         /* Binary Output (Obj:10, Var:01) */
2018             case AL_OBJ_CTL_PMASK:  /* Pattern Mask (Obj:12, Var:03) */
2019             case AL_OBJ_IIN:        /* Internal Indications - IIN (Obj: 80, Var:01) */
2020 
2021               /* Extract the bit from the packed byte */
2022               al_bi_val = tvb_get_guint8(tvb, data_pos);
2023               al_bit = (al_bi_val & 1) > 0;
2024               if (al_obj == AL_OBJ_IIN) {
2025                 /* For an IIN bit, work out the IIN constant value for the bit position to get the name of the bit */
2026                 guint16 iin_bit = 0;
2027                 if (al_ptaddr < 8) {
2028                   iin_bit = 0x100 << al_ptaddr;
2029                 }
2030                 else {
2031                   iin_bit = 1 << (al_ptaddr - 8);
2032                 }
2033                 proto_item_append_text(point_item, " (%s), Value: %u",
2034                                        val_to_str_const(iin_bit, dnp3_al_iin_vals, "Invalid IIN bit"), al_bit);
2035               }
2036               else
2037               {
2038                 if (al_objq_prefix != AL_OBJQL_PREFIX_NI) {
2039                   /* Each item has an index prefix, in this case bump
2040                      the bitindex to force the correct offset adjustment */
2041                   bitindex = 7;
2042                 }
2043                 else {
2044                   /* Regular packed bits, get the value at the appropriate bit index */
2045                   al_bit = (al_bi_val & (1 << bitindex)) > 0;
2046                 }
2047                 proto_item_append_text(point_item, ", Value: %u", al_bit);
2048               }
2049               proto_tree_add_boolean(point_tree, hf_dnp3_al_bit, tvb, data_pos, 1, al_bit);
2050               proto_item_set_len(point_item, prefixbytes + 1);
2051 
2052               /* Increment the bit index for next cycle */
2053               bitindex++;
2054 
2055               /* If we have counted 8 bits or read the last item,
2056                  reset bit index and move onto the next byte */
2057               if ((bitindex > 7) || (item_num == (num_items-1)))
2058               {
2059                 bitindex = 0;
2060                 offset += (prefixbytes + 1);
2061               }
2062               break;
2063 
2064             case AL_OBJ_2BI_NF:    /* Double-bit Input No Flags (Obj:03, Var:01) */
2065 
2066               if (bitindex > 3)
2067               {
2068                 bitindex = 0;
2069                 offset += (prefixbytes + 1);
2070               }
2071 
2072               /* Extract the Double-bit from the packed byte */
2073               al_bi_val = tvb_get_guint8(tvb, offset);
2074               al_2bit = ((al_bi_val >> (bitindex << 1)) & 3);
2075 
2076               proto_item_append_text(point_item, ", Value: %u", al_2bit);
2077               proto_tree_add_uint(point_tree, hf_dnp3_al_2bit, tvb, offset, 1, al_2bit);
2078               proto_item_set_len(point_item, prefixbytes + 1);
2079 
2080               /* If we've read the last item, then move the offset past this byte */
2081               if (item_num == (num_items-1))
2082               {
2083                 offset += (prefixbytes + 1);
2084               }
2085 
2086               /* Increment the bit index for next cycle */
2087               bitindex++;
2088               break;
2089 
2090             case AL_OBJ_BI_STAT:    /* Binary Input With Status (Obj:01, Var:02) */
2091             case AL_OBJ_BIC_NOTIME: /* Binary Input Change Without Time (Obj:02, Var:01) */
2092             case AL_OBJ_BO_STAT:    /* Binary Output Status (Obj:10, Var:02) */
2093             case AL_OBJ_BOC_NOTIME: /* Binary Output Change Without Time (Obj:11, Var:01) */
2094 
2095               /* Get Point Flags */
2096               al_ptflags = tvb_get_guint8(tvb, data_pos);
2097 
2098               switch (al_obj) {
2099                 case AL_OBJ_BI_STAT:
2100                 case AL_OBJ_BIC_NOTIME:
2101                   dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2102                   break;
2103                 case AL_OBJ_BO_STAT:
2104                 case AL_OBJ_BOC_NOTIME:
2105                   dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_OUT);
2106                   break;
2107               }
2108               data_pos += 1;
2109 
2110               al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) > 0;
2111               proto_item_append_text(point_item, ", Value: %u", al_bit);
2112 
2113               proto_item_set_len(point_item, data_pos - offset);
2114 
2115               offset = data_pos;
2116               break;
2117 
2118             case AL_OBJ_2BI_STAT:    /* Double-bit Input With Status (Obj:03, Var:02) */
2119             case AL_OBJ_2BIC_NOTIME: /* Double-bit Input Change Without Time (Obj:04, Var:01) */
2120 
2121               /* Get Point Flags */
2122               al_ptflags = tvb_get_guint8(tvb, data_pos);
2123               dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2124               data_pos += 1;
2125 
2126               al_2bit = (al_ptflags >> 6) & 3;
2127               proto_item_append_text(point_item, ", Value: %u", al_2bit);
2128               proto_item_set_len(point_item, data_pos - offset);
2129 
2130               offset = data_pos;
2131               break;
2132 
2133             case AL_OBJ_BIC_TIME:   /* Binary Input Change w/ Time (Obj:02, Var:02)  */
2134             case AL_OBJ_BOC_TIME:   /* Binary Output Change w/ Time (Obj:11, Var:02)  */
2135 
2136               /* Get Point Flags */
2137               al_ptflags = tvb_get_guint8(tvb, data_pos);
2138               switch (al_obj) {
2139                 case AL_OBJ_BIC_TIME:
2140                   dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2141                   break;
2142                 case AL_OBJ_BOC_TIME:
2143                   dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_OUT);
2144                   break;
2145               }
2146               data_pos += 1;
2147 
2148               /* Get timestamp */
2149               dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2150               proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2151               data_pos += 6;
2152 
2153               al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
2154               proto_item_append_text(point_item, ", Value: %u, Timestamp: %s",
2155                                      al_bit, abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2156               proto_item_set_len(point_item, data_pos - offset);
2157 
2158               offset = data_pos;
2159               break;
2160 
2161             case AL_OBJ_2BIC_TIME:   /* Double-bit Input Change w/ Time (Obj:04, Var:02)  */
2162 
2163               /* Get Point Flags */
2164               al_ptflags = tvb_get_guint8(tvb, data_pos);
2165               dnp3_al_obj_quality(tvb, (offset+prefixbytes), al_ptflags, point_tree, point_item, BIN_IN);
2166               data_pos += 1;
2167 
2168 
2169               /* Get timestamp */
2170               dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2171               proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2172               data_pos += 6;
2173 
2174               al_2bit = (al_ptflags >> 6) & 3; /* bit shift 11xxxxxx -> 00000011 */
2175               proto_item_append_text(point_item, ", Value: %u, Timestamp: %s",
2176                                      al_2bit, abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2177               proto_item_set_len(point_item, data_pos - offset);
2178 
2179               offset = data_pos;
2180               break;
2181 
2182             case AL_OBJ_BIC_RTIME:   /* Binary Input Change w/ Relative Time (Obj:02, Var:03)  */
2183 
2184               /* Get Point Flags */
2185               al_ptflags = tvb_get_guint8(tvb, data_pos);
2186               dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2187               data_pos += 1;
2188 
2189               /* Get relative time in ms, and convert to ns_time */
2190               al_relms = tvb_get_letohs(tvb, data_pos);
2191               al_reltime.secs = al_relms / 1000;
2192               al_reltime.nsecs = (al_relms % 1000) * 1000000;
2193               /* Now add to CTO time */
2194               nstime_sum(&al_abstime, al_cto, &al_reltime);
2195               proto_tree_add_time(point_tree, hf_dnp3_al_rel_timestamp, tvb, data_pos, 2, &al_reltime);
2196               data_pos += 2;
2197 
2198               al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
2199               proto_item_append_text(point_item, ", Value: %u, Timestamp: %s",
2200                                      al_bit, abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2201               proto_item_set_len(point_item, data_pos - offset);
2202 
2203               offset = data_pos;
2204               break;
2205 
2206             case AL_OBJ_CTLOP_BLK: /* Control Relay Output Block (Obj:12, Var:01) */
2207             case AL_OBJ_CTL_PCB: /* Pattern Control Block (Obj:12, Var:02) */
2208             {
2209               proto_tree  *tcc_tree;
2210 
2211               /* Add a expand/collapse for TCC */
2212               al_tcc_code = tvb_get_guint8(tvb, data_pos);
2213               tcc_tree = proto_tree_add_subtree_format(point_tree, tvb, data_pos, 1,
2214                           ett_dnp3_al_obj_point_tcc, NULL, "Control Code [0x%02x]",al_tcc_code);
2215 
2216               /* Add the Control Code to the Point number list for quick visual reference as to the operation */
2217               proto_item_append_text(point_item, " [%s]", val_to_str_const((al_tcc_code & AL_OBJCTLC_CODE),
2218                                                                            dnp3_al_ctlc_code_vals,
2219                                                                            "Invalid Operation"));
2220 
2221               /* Add Trip/Close qualifier (if applicable) to previously appended quick visual reference */
2222               proto_item_append_text(point_item, " [%s]", val_to_str_const((al_tcc_code & AL_OBJCTLC_TC) >> 6,
2223                                                                            dnp3_al_ctlc_tc_vals,
2224                                                                            "Invalid Qualifier"));
2225 
2226 
2227 
2228               /* Control Code 'Operation Type' */
2229               proto_tree_add_item(tcc_tree, hf_dnp3_ctlobj_code_c, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2230 
2231               /* Control Code Misc Values */
2232               proto_tree_add_item(tcc_tree, hf_dnp3_ctlobj_code_m, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2233 
2234               /* Control Code 'Trip Close Code' */
2235               proto_tree_add_item(tcc_tree, hf_dnp3_ctlobj_code_tc, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2236               data_pos += 1;
2237 
2238               /* Get "Count" Field */
2239               proto_tree_add_item(point_tree, hf_dnp3_al_count, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2240               data_pos += 1;
2241 
2242               /* Get "On Time" Field */
2243               proto_tree_add_item(point_tree, hf_dnp3_al_on_time, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2244               data_pos += 4;
2245 
2246               /* Get "Off Time" Field */
2247               proto_tree_add_item(point_tree, hf_dnp3_al_off_time, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2248               data_pos += 4;
2249 
2250               /* Get "Control Status" Field */
2251               proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2252               data_pos += 1;
2253 
2254               proto_item_set_len(point_item, data_pos - offset);
2255 
2256               offset = data_pos;
2257               break;
2258             }
2259 
2260             case AL_OBJ_BOE_NOTIME: /* Binary Command Event (Obj:13, Var:01) */
2261             case AL_OBJ_BOE_TIME:   /* Binary Command Event with time (Obj:13, Var:02) */
2262             case AL_OBJ_AOC_32EVNT:   /* 32-bit Analog Command Event (Obj:43, Var:01) */
2263             case AL_OBJ_AOC_16EVNT:   /* 16-bit Analog Command Event (Obj:43, Var:02) */
2264             case AL_OBJ_AOC_32EVTT:   /* 32-bit Analog Command Event with time (Obj:43, Var:03) */
2265             case AL_OBJ_AOC_16EVTT:   /* 16-bit Analog Command Event with time (Obj:43, Var:04) */
2266             case AL_OBJ_AOC_FLTEVNT:   /* 32-bit Floating Point Analog Command Event (Obj:43, Var:05) */
2267             case AL_OBJ_AOC_DBLEVNT:   /* 64-bit Floating Point Analog Command Event (Obj:43, Var:06) */
2268             case AL_OBJ_AOC_FLTEVTT:   /* 32-bit Floating Point Analog Command Event with time (Obj:43, Var:07) */
2269             case AL_OBJ_AOC_DBLEVTT:   /* 64-bit Floating Point Analog Command Event with time (Obj:43, Var:08) */
2270             {
2271               /* Get the status code */
2272               al_ctlobj_stat = tvb_get_guint8(tvb, data_pos) & AL_OBJCTL_STATUS_MASK;
2273               ctl_status_str = val_to_str_ext(al_ctlobj_stat, &dnp3_al_ctl_status_vals_ext, "Invalid Status (0x%02x)");
2274               proto_item_append_text(point_item, " [Status: %s (0x%02x)]", ctl_status_str, al_ctlobj_stat);
2275               proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2276 
2277               /* Get the command value */
2278               switch(al_obj)
2279               {
2280                 case AL_OBJ_BOE_NOTIME:
2281                 case AL_OBJ_BOE_TIME:
2282                   proto_tree_add_item(point_tree, hf_dnp3_bocs_bit, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2283                   data_pos += 1;
2284                   break;
2285                 case AL_OBJ_AOC_32EVNT:
2286                 case AL_OBJ_AOC_32EVTT:
2287                   data_pos += 1; /* Step past status */
2288                   al_val_int32 = tvb_get_letohl(tvb, data_pos);
2289                   proto_item_append_text(point_item, ", Value: %d", al_val_int32);
2290                   proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2291                   break;
2292                 case AL_OBJ_AOC_16EVNT:
2293                 case AL_OBJ_AOC_16EVTT:
2294                   data_pos += 1; /* Step past status */
2295                   al_val_int16 = tvb_get_letohs(tvb, data_pos);
2296                   proto_item_append_text(point_item, ", Value: %d", al_val_int16);
2297                   proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2298                   data_pos += 2;
2299                   break;
2300                 case AL_OBJ_AOC_FLTEVNT:
2301                 case AL_OBJ_AOC_FLTEVTT:
2302                   data_pos += 1; /* Step past status */
2303                   al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2304                   proto_item_append_text(point_item, ", Value: %g", al_valflt);
2305                   proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2306                   data_pos += 4;
2307                   break;
2308                 case AL_OBJ_AOC_DBLEVNT:
2309                 case AL_OBJ_AOC_DBLEVTT:
2310                   data_pos += 1; /* Step past status */
2311                   al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2312                   proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2313                   proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2314                   data_pos += 8;
2315                   break;
2316               }
2317 
2318               /* Get the timestamp */
2319               switch(al_obj)
2320               {
2321                 case AL_OBJ_BOE_TIME:   /* Binary Command Event with time (Obj:13, Var:02) */
2322                 case AL_OBJ_AOC_32EVTT:   /* 32-bit Analog Command Event with time (Obj:43, Var:03) */
2323                 case AL_OBJ_AOC_16EVTT:   /* 16-bit Analog Command Event with time (Obj:43, Var:04) */
2324                 case AL_OBJ_AOC_FLTEVTT:   /* 32-bit Floating Point Analog Command Event with time (Obj:43, Var:07) */
2325                 case AL_OBJ_AOC_DBLEVTT:   /* 64-bit Floating Point Analog Command Event with time (Obj:43, Var:08) */
2326                   dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2327                   proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2328                   proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2329                   data_pos += 6;
2330                 break;
2331               }
2332 
2333               proto_item_set_len(point_item, data_pos - offset);
2334               offset = data_pos;
2335               break;
2336             }
2337 
2338             case AL_OBJ_AO_32OPB:   /* 32-Bit Analog Output Block (Obj:41, Var:01) */
2339             case AL_OBJ_AO_16OPB:   /* 16-Bit Analog Output Block (Obj:41, Var:02) */
2340             case AL_OBJ_AO_FLTOPB:  /* 32-Bit Floating Point Output Block (Obj:41, Var:03) */
2341             case AL_OBJ_AO_DBLOPB:  /* 64-Bit Floating Point Output Block (Obj:41, Var:04) */
2342 
2343               switch (al_obj)
2344               {
2345                 case AL_OBJ_AO_32OPB:
2346                   al_val_int32 = tvb_get_letohl(tvb, data_pos);
2347                   proto_item_append_text(point_item, ", Value: %d", al_val_int32);
2348                   proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2349                   data_pos += 4;
2350                   break;
2351                 case AL_OBJ_AO_16OPB:
2352                   al_val_int16 = tvb_get_letohs(tvb, data_pos);
2353                   proto_item_append_text(point_item, ", Value: %d", al_val_int16);
2354                   proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2355                   data_pos += 2;
2356                   break;
2357                 case AL_OBJ_AO_FLTOPB:
2358                   al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2359                   proto_item_append_text(point_item, ", Value: %g", al_valflt);
2360                   proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2361                   data_pos += 4;
2362                   break;
2363                 case AL_OBJ_AO_DBLOPB:
2364                   al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2365                   proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2366                   proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2367                   data_pos += 8;
2368                   break;
2369               }
2370 
2371               /* Get control status */
2372               al_ctlobj_stat = tvb_get_guint8(tvb, data_pos) & AL_OBJCTL_STATUS_MASK;
2373               ctl_status_str = val_to_str_ext(al_ctlobj_stat, &dnp3_al_ctl_status_vals_ext, "Invalid Status (0x%02x)");
2374               proto_item_append_text(point_item, " [Status: %s (0x%02x)]", ctl_status_str, al_ctlobj_stat);
2375               proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2376               data_pos += 1;
2377 
2378               proto_item_set_len(point_item, data_pos - offset);
2379 
2380               offset = data_pos;
2381               break;
2382 
2383             case AL_OBJ_CTR_32:     /* 32-Bit Binary Counter (Obj:20, Var:01) */
2384             case AL_OBJ_CTR_16:     /* 16-Bit Binary Counter (Obj:20, Var:02) */
2385             case AL_OBJ_DCTR_32:    /* 32-Bit Binary Delta Counter (Obj:20, Var:03) */
2386             case AL_OBJ_DCTR_16:    /* 16-Bit Binary Delta Counter (Obj:20, Var:04) */
2387             case AL_OBJ_CTR_32NF:   /* 32-Bit Binary Counter Without Flag (Obj:20, Var:05) */
2388             case AL_OBJ_CTR_16NF:   /* 16-Bit Binary Counter Without Flag (Obj:20, Var:06) */
2389             case AL_OBJ_DCTR_32NF:  /* 32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07) */
2390             case AL_OBJ_DCTR_16NF:  /* 16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08) */
2391             case AL_OBJ_FCTR_32:    /* 32-Bit Frozen Counter (Obj:21, Var:01) */
2392             case AL_OBJ_FCTR_16:    /* 16-Bit Frozen Counter (Obj:21, Var:02) */
2393             case AL_OBJ_FDCTR_32:   /* 21 03 32-Bit Frozen Delta Counter */
2394             case AL_OBJ_FDCTR_16:   /* 21 04 16-Bit Frozen Delta Counter */
2395             case AL_OBJ_FCTR_32T:   /* 32-Bit Frozen Counter w/ Time of Freeze (Obj:21 Var:05 ) */
2396             case AL_OBJ_FCTR_16T:   /* 16-Bit Frozen Counter w/ Time of Freeze (Obj:21 Var:06) */
2397             case AL_OBJ_FDCTR_32T:  /* 32-Bit Frozen Delta Counter w/ Time of Freeze (Obj:21 Var:07) */
2398             case AL_OBJ_FDCTR_16T:  /* 16-Bit Frozen Delta Counter w/ Time of Freeze (Obj:21 Var:08) */
2399             case AL_OBJ_FCTR_32NF:  /* 32-Bit Frozen Counter Without Flag (Obj:21 Var:09) */
2400             case AL_OBJ_FCTR_16NF:  /* 16-Bit Frozen Counter Without Flag (Obj:21 Var:10) */
2401             case AL_OBJ_FDCTR_32NF: /* 32-Bit Frozen Delta Counter Without Flag (Obj:21 Var:11) */
2402             case AL_OBJ_FDCTR_16NF: /* 16-Bit Frozen Delta Counter Without Flag (Obj:21 Var:12) */
2403             case AL_OBJ_CTRC_32:    /* 32-Bit Counter Change Event w/o Time (Obj:22, Var:01) */
2404             case AL_OBJ_CTRC_16:    /* 16-Bit Counter Change Event w/o Time (Obj:22, Var:02) */
2405             case AL_OBJ_DCTRC_32:   /* 32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03) */
2406             case AL_OBJ_DCTRC_16:   /* 16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04) */
2407             case AL_OBJ_CTRC_32T:   /* 32-Bit Counter Change Event with Time (Obj:22, Var:05) */
2408             case AL_OBJ_CTRC_16T:   /* 16-Bit Counter Change Event with Time (Obj:22, Var:06) */
2409             case AL_OBJ_DCTRC_32T:  /* 32-Bit Delta Counter Change Event with Time (Obj:22, Var:07) */
2410             case AL_OBJ_DCTRC_16T:  /* 16-Bit Delta Counter Change Event with Time (Obj:22, Var:08) */
2411             case AL_OBJ_FCTRC_32:   /* 32-Bit Frozen Counter Change Event (Obj:23 Var:01) */
2412             case AL_OBJ_FCTRC_16:   /* 16-Bit Frozen Counter Change Event (Obj:23 Var:02) */
2413             case AL_OBJ_FDCTRC_32:  /* 32-Bit Frozen Delta Counter Change Event (Obj:23 Var:03) */
2414             case AL_OBJ_FDCTRC_16:  /* 16-Bit Frozen Delta Counter Change Event (Obj:23 Var:04) */
2415             case AL_OBJ_FCTRC_32T:  /* 32-Bit Frozen Counter Change Event w/ Time of Freeze (Obj:23 Var:05) */
2416             case AL_OBJ_FCTRC_16T:  /* 16-Bit Frozen Counter Change Event w/ Time of Freeze (Obj:23 Var:06) */
2417             case AL_OBJ_FDCTRC_32T: /* 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze (Obj:23 Var:07) */
2418             case AL_OBJ_FDCTRC_16T: /* 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze (Obj:23 Var:08) */
2419 
2420               /* Get Point Flags for those types that have them, it's easier to block out those that don't have flags */
2421               switch (al_obj)
2422               {
2423                 case AL_OBJ_CTR_32NF:
2424                 case AL_OBJ_CTR_16NF:
2425                 case AL_OBJ_DCTR_32NF:
2426                 case AL_OBJ_DCTR_16NF:
2427                 case AL_OBJ_FCTR_32NF:
2428                 case AL_OBJ_FCTR_16NF:
2429                 case AL_OBJ_FDCTR_32NF:
2430                 case AL_OBJ_FDCTR_16NF:
2431                   break;
2432 
2433                 default:
2434                   al_ptflags = tvb_get_guint8(tvb, data_pos);
2435                   dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, COUNTER);
2436                   data_pos += 1;
2437                   break;
2438               }
2439 
2440               /* Get Counter values */
2441               switch (al_obj)
2442               {
2443                 case AL_OBJ_CTR_32:
2444                 case AL_OBJ_DCTR_32:
2445                 case AL_OBJ_CTR_32NF:
2446                 case AL_OBJ_DCTR_32NF:
2447                 case AL_OBJ_FCTR_32:
2448                 case AL_OBJ_FDCTR_32:
2449                 case AL_OBJ_FCTR_32T:
2450                 case AL_OBJ_FDCTR_32T:
2451                 case AL_OBJ_FCTR_32NF:
2452                 case AL_OBJ_FDCTR_32NF:
2453                 case AL_OBJ_CTRC_32:
2454                 case AL_OBJ_DCTRC_32:
2455                 case AL_OBJ_CTRC_32T:
2456                 case AL_OBJ_DCTRC_32T:
2457                 case AL_OBJ_FCTRC_32:
2458                 case AL_OBJ_FDCTRC_32:
2459                 case AL_OBJ_FCTRC_32T:
2460                 case AL_OBJ_FDCTRC_32T:
2461 
2462                   al_val_uint32 = tvb_get_letohl(tvb, data_pos);
2463                   proto_item_append_text(point_item, ", Count: %u", al_val_uint32);
2464                   proto_tree_add_item(point_tree, hf_dnp3_al_cnt32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2465                   data_pos += 4;
2466                   break;
2467 
2468                 case AL_OBJ_CTR_16:
2469                 case AL_OBJ_DCTR_16:
2470                 case AL_OBJ_CTR_16NF:
2471                 case AL_OBJ_DCTR_16NF:
2472                 case AL_OBJ_FCTR_16:
2473                 case AL_OBJ_FDCTR_16:
2474                 case AL_OBJ_FCTR_16T:
2475                 case AL_OBJ_FDCTR_16T:
2476                 case AL_OBJ_FCTR_16NF:
2477                 case AL_OBJ_FDCTR_16NF:
2478                 case AL_OBJ_CTRC_16:
2479                 case AL_OBJ_DCTRC_16:
2480                 case AL_OBJ_CTRC_16T:
2481                 case AL_OBJ_DCTRC_16T:
2482                 case AL_OBJ_FCTRC_16:
2483                 case AL_OBJ_FDCTRC_16:
2484                 case AL_OBJ_FCTRC_16T:
2485                 case AL_OBJ_FDCTRC_16T:
2486 
2487                   al_val_uint16 = tvb_get_letohs(tvb, data_pos);
2488                   proto_item_append_text(point_item, ", Count: %u", al_val_uint16);
2489                   proto_tree_add_item(point_tree, hf_dnp3_al_cnt16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2490                   data_pos += 2;
2491                   break;
2492               }
2493 
2494               /* Get the time for those points that have it */
2495               switch (al_obj)
2496               {
2497                 case AL_OBJ_FCTR_32T:
2498                 case AL_OBJ_FCTR_16T:
2499                 case AL_OBJ_FDCTR_32T:
2500                 case AL_OBJ_FDCTR_16T:
2501                 case AL_OBJ_CTRC_32T:
2502                 case AL_OBJ_CTRC_16T:
2503                 case AL_OBJ_DCTRC_32T:
2504                 case AL_OBJ_DCTRC_16T:
2505                 case AL_OBJ_FCTRC_32T:
2506                 case AL_OBJ_FCTRC_16T:
2507                 case AL_OBJ_FDCTRC_32T:
2508                 case AL_OBJ_FDCTRC_16T:
2509                   dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2510                   proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2511                   proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2512                   data_pos += 6;
2513                   break;
2514               }
2515 
2516               proto_item_set_len(point_item, data_pos - offset);
2517               offset = data_pos;
2518               break;
2519 
2520             case AL_OBJ_AI_32:        /* 32-Bit Analog Input (Obj:30, Var:01) */
2521             case AL_OBJ_AI_16:        /* 16-Bit Analog Input (Obj:30, Var:02) */
2522             case AL_OBJ_AI_32NF:      /* 32-Bit Analog Input Without Flag (Obj:30, Var:03) */
2523             case AL_OBJ_AI_16NF:      /* 16-Bit Analog Input Without Flag (Obj:30, Var:04) */
2524             case AL_OBJ_AI_FLT:       /* 32-Bit Floating Point Input (Obj:30, Var:05) */
2525             case AL_OBJ_AI_DBL:       /* 64-Bit Floating Point Input (Obj:30, Var:06) */
2526             case AL_OBJ_AIF_FLT:      /* 32-Bit Frozen Floating Point Input (Obj:31, Var:07) */
2527             case AL_OBJ_AIF_DBL:      /* 64-Bit Frozen Floating Point Input (Obj:31, Var:08) */
2528             case AL_OBJ_AIC_32NT:     /* 32-Bit Analog Change Event w/o Time (Obj:32, Var:01) */
2529             case AL_OBJ_AIC_16NT:     /* 16-Bit Analog Change Event w/o Time (Obj:32, Var:02) */
2530             case AL_OBJ_AIC_32T:      /* 32-Bit Analog Change Event with Time (Obj:32, Var:03) */
2531             case AL_OBJ_AIC_16T:      /* 16-Bit Analog Change Event with Time (Obj:32, Var:04) */
2532             case AL_OBJ_AIC_FLTNT:    /* 32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05) */
2533             case AL_OBJ_AIC_DBLNT:    /* 64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06) */
2534             case AL_OBJ_AIC_FLTT:     /* 32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07) */
2535             case AL_OBJ_AIC_DBLT:     /* 64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08) */
2536             case AL_OBJ_AIFC_FLTNT:   /* 32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05) */
2537             case AL_OBJ_AIFC_DBLNT:   /* 64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06) */
2538             case AL_OBJ_AIFC_FLTT:    /* 32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07) */
2539             case AL_OBJ_AIFC_DBLT:    /* 64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08) */
2540             case AL_OBJ_AIDB_16:      /* 16-Bit Analog Input Deadband (Obj:34, Var:01) */
2541             case AL_OBJ_AIDB_32:      /* 32-Bit Analog Input Deadband (Obj:34, Var:02) */
2542             case AL_OBJ_AIDB_FLT:     /* 32-Bit Floating Point Analog Input Deadband (Obj:34, Var:03) */
2543 
2544               /* Get Point Flags for those types that have them */
2545               switch (al_obj)
2546               {
2547                 case AL_OBJ_AI_32NF:
2548                 case AL_OBJ_AI_16NF:
2549                 case AL_OBJ_AIDB_16:
2550                 case AL_OBJ_AIDB_32:
2551                 case AL_OBJ_AIDB_FLT:
2552                   break;
2553 
2554                 default:
2555                   al_ptflags = tvb_get_guint8(tvb, data_pos);
2556                   dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_IN);
2557                   data_pos += 1;
2558                   break;
2559               }
2560 
2561               switch (al_obj)
2562               {
2563                 case AL_OBJ_AI_32:
2564                 case AL_OBJ_AI_32NF:
2565                 case AL_OBJ_AIC_32NT:
2566                 case AL_OBJ_AIC_32T:
2567                 case AL_OBJ_AIDB_32:
2568 
2569                   al_val_int32 = tvb_get_letohl(tvb, data_pos);
2570                   proto_item_append_text(point_item, ", Value: %d", al_val_int32);
2571                   proto_tree_add_item(point_tree, hf_dnp3_al_ana32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2572                   data_pos += 4;
2573                   break;
2574 
2575                 case AL_OBJ_AI_16:
2576                 case AL_OBJ_AI_16NF:
2577                 case AL_OBJ_AIC_16NT:
2578                 case AL_OBJ_AIC_16T:
2579                 case AL_OBJ_AIDB_16:
2580 
2581                   al_val_int16 = tvb_get_letohs(tvb, data_pos);
2582                   proto_item_append_text(point_item, ", Value: %d", al_val_int16);
2583                   proto_tree_add_item(point_tree, hf_dnp3_al_ana16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2584                   data_pos += 2;
2585                   break;
2586 
2587                 case AL_OBJ_AI_FLT:
2588                 case AL_OBJ_AIF_FLT:
2589                 case AL_OBJ_AIC_FLTNT:
2590                 case AL_OBJ_AIC_FLTT:
2591                 case AL_OBJ_AIFC_FLTNT:
2592                 case AL_OBJ_AIFC_FLTT:
2593                 case AL_OBJ_AIDB_FLT:
2594 
2595                   al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2596                   proto_item_append_text(point_item, ", Value: %g", al_valflt);
2597                   proto_tree_add_item(point_tree, hf_dnp3_al_anaflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2598                   data_pos += 4;
2599                   break;
2600 
2601                 case AL_OBJ_AI_DBL:
2602                 case AL_OBJ_AIF_DBL:
2603                 case AL_OBJ_AIC_DBLNT:
2604                 case AL_OBJ_AIC_DBLT:
2605                 case AL_OBJ_AIFC_DBLNT:
2606                 case AL_OBJ_AIFC_DBLT:
2607 
2608                   al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2609                   proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2610                   proto_tree_add_item(point_tree, hf_dnp3_al_anadbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2611                   data_pos += 8;
2612                   break;
2613               }
2614 
2615               /* Get timestamp */
2616               switch (al_obj)
2617               {
2618                 case AL_OBJ_AIC_32T:
2619                 case AL_OBJ_AIC_16T:
2620                 case AL_OBJ_AIC_FLTT:
2621                 case AL_OBJ_AIC_DBLT:
2622                 case AL_OBJ_AIFC_FLTT:
2623                 case AL_OBJ_AIFC_DBLT:
2624                   dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2625                   proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2626                   proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2627                   data_pos += 6;
2628                   break;
2629               }
2630 
2631               proto_item_set_len(point_item, data_pos - offset);
2632 
2633               offset = data_pos;
2634               break;
2635 
2636             case AL_OBJ_AO_32:     /* 32-Bit Analog Output Status (Obj:40, Var:01) */
2637             case AL_OBJ_AO_16:     /* 16-Bit Analog Output Status (Obj:40, Var:02) */
2638             case AL_OBJ_AO_FLT:    /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
2639             case AL_OBJ_AO_DBL:    /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
2640             case AL_OBJ_AOC_32NT:  /* 32-Bit Analog Output Event w/o Time (Obj:42, Var:01) */
2641             case AL_OBJ_AOC_16NT:  /* 16-Bit Analog Output Event w/o Time (Obj:42, Var:02) */
2642             case AL_OBJ_AOC_32T:   /* 32-Bit Analog Output Event with Time (Obj:42, Var:03) */
2643             case AL_OBJ_AOC_16T:   /* 16-Bit Analog Output Event with Time (Obj:42, Var:04) */
2644             case AL_OBJ_AOC_FLTNT: /* 32-Bit Floating Point Output Event w/o Time (Obj:42, Var:05) */
2645             case AL_OBJ_AOC_DBLNT: /* 64-Bit Floating Point Output Event w/o Time (Obj:42, Var:06) */
2646             case AL_OBJ_AOC_FLTT:  /* 32-Bit Floating Point Output Event w/ Time (Obj:42, Var:07) */
2647             case AL_OBJ_AOC_DBLT:  /* 64-Bit Floating Point Output Event w/ Time (Obj:42, Var:08) */
2648 
2649               /* Get Point Flags */
2650               al_ptflags = tvb_get_guint8(tvb, data_pos);
2651               dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_OUT);
2652               data_pos += 1;
2653 
2654               switch (al_obj)
2655               {
2656                 case AL_OBJ_AO_32:     /* 32-Bit Analog Output Status (Obj:40, Var:01) */
2657                 case AL_OBJ_AOC_32NT:  /* 32-Bit Analog Output Event w/o Time (Obj:42, Var:01) */
2658                 case AL_OBJ_AOC_32T:   /* 32-Bit Analog Output Event with Time (Obj:42, Var:03) */
2659 
2660                   al_val_int32 = tvb_get_letohl(tvb, data_pos);
2661                   proto_item_append_text(point_item, ", Value: %d", al_val_int32);
2662                   proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2663                   data_pos += 4;
2664                   break;
2665 
2666                 case AL_OBJ_AO_16:     /* 16-Bit Analog Output Status (Obj:40, Var:02) */
2667                 case AL_OBJ_AOC_16NT:  /* 16-Bit Analog Output Event w/o Time (Obj:42, Var:02) */
2668                 case AL_OBJ_AOC_16T:   /* 16-Bit Analog Output Event with Time (Obj:42, Var:04) */
2669 
2670                   al_val_int16 = tvb_get_letohs(tvb, data_pos);
2671                   proto_item_append_text(point_item, ", Value: %d", al_val_int16);
2672                   proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2673                   data_pos += 2;
2674                   break;
2675 
2676                 case AL_OBJ_AO_FLT:     /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
2677                 case AL_OBJ_AOC_FLTNT:  /* 32-Bit Floating Point Output Event w/o Time (Obj:42, Var:05) */
2678                 case AL_OBJ_AOC_FLTT:   /* 32-Bit Floating Point Output Event w/ Time (Obj:42, Var:07) */
2679 
2680                   al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2681                   proto_item_append_text(point_item, ", Value: %g", al_valflt);
2682                   proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2683                   data_pos += 4;
2684                   break;
2685 
2686                 case AL_OBJ_AO_DBL:     /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
2687                 case AL_OBJ_AOC_DBLNT:  /* 64-Bit Floating Point Output Event w/o Time (Obj:42, Var:06) */
2688                 case AL_OBJ_AOC_DBLT:   /* 64-Bit Floating Point Output Event w/ Time (Obj:42, Var:08) */
2689 
2690                   al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2691                   proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2692                   proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2693                   data_pos += 8;
2694                   break;
2695               }
2696 
2697               /* Get timestamp */
2698               switch (al_obj)
2699               {
2700                 case AL_OBJ_AOC_32T:
2701                 case AL_OBJ_AOC_16T:
2702                 case AL_OBJ_AOC_FLTT:
2703                 case AL_OBJ_AOC_DBLT:
2704                   dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2705                   proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(pinfo->pool, &al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2706                   proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2707                   data_pos += 6;
2708                   break;
2709               }
2710 
2711               proto_item_set_len(point_item, data_pos - offset);
2712               offset = data_pos;
2713               break;
2714 
2715             case AL_OBJ_TD:    /* Time and Date (Obj:50, Var:01) */
2716             case AL_OBJ_TDR:   /* Time and Date at Last Recorded Time (Obj:50, Var:03) */
2717             case AL_OBJ_TDCTO: /* Time and Date CTO (Obj:51, Var:01) */
2718 
2719               dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2720               proto_tree_add_time(object_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2721               data_pos += 6;
2722               proto_item_set_len(point_item, data_pos - offset);
2723 
2724               if (al_obj == AL_OBJ_TDCTO) {
2725                 /* Copy the time object to the CTO for any other relative time objects in this response */
2726                 nstime_copy(al_cto, &al_abstime);
2727               }
2728 
2729               offset = data_pos;
2730               break;
2731 
2732             case AL_OBJ_TDELAYF: /* Time Delay - Fine (Obj:52, Var:02) */
2733 
2734               proto_tree_add_item(object_tree, hf_dnp3_al_time_delay, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2735               data_pos += 2;
2736               proto_item_set_len(point_item, data_pos - offset);
2737 
2738               offset = data_pos;
2739               break;
2740 
2741             case AL_OBJ_CLASS0:  /* Class Data Objects */
2742             case AL_OBJ_CLASS1:
2743             case AL_OBJ_CLASS2:
2744             case AL_OBJ_CLASS3:
2745 
2746               /* No data here */
2747               offset = data_pos;
2748               break;
2749 
2750             case AL_OBJ_FILE_CMD: /* File Control - File Command (Obj:70, Var:03) */
2751               /* File name offset and length */
2752               proto_tree_add_item(point_tree, hf_dnp3_al_file_string_offset, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2753               data_pos += 2;
2754               al_filename_len = tvb_get_letohs(tvb, data_pos);
2755               proto_tree_add_item(point_tree, hf_dnp3_al_file_string_length, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2756               data_pos += 2;
2757 
2758               /* Grab the mode as it determines if some of the following fields are relevant */
2759               al_file_ctrl_mode = tvb_get_letohs(tvb, data_pos + 16);
2760 
2761               /* Creation Time */
2762               if (al_file_ctrl_mode == AL_OBJ_FILE_MODE_WRITE) {
2763                 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2764                 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2765               }
2766               data_pos += 6;
2767 
2768               /* Perms */
2769               if (al_file_ctrl_mode == AL_OBJ_FILE_MODE_WRITE) {
2770                 proto_item *perms_item;
2771                 proto_tree *perms_tree;
2772 
2773                 perms_item = proto_tree_add_item(point_tree, hf_dnp3_al_file_perms, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2774 
2775                 perms_tree = proto_item_add_subtree(perms_item, ett_dnp3_al_obj_point_perms);
2776                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_read_owner,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
2777                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_write_owner, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2778                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_exec_owner,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
2779                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_read_group,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
2780                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_write_group, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2781                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_exec_group,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
2782                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_read_world,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
2783                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_write_world, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2784                 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_exec_world,  tvb, offset, 2, ENC_LITTLE_ENDIAN);
2785               }
2786               data_pos += 2;
2787 
2788               /* Auth Key */
2789               proto_tree_add_item(point_tree, hf_dnp3_al_file_auth, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2790               data_pos += 4;
2791 
2792               /* File Size */
2793               if (al_file_ctrl_mode == AL_OBJ_FILE_MODE_WRITE || al_file_ctrl_mode == AL_OBJ_FILE_MODE_APPEND) {
2794                 proto_tree_add_item(point_tree, hf_dnp3_al_file_size, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2795               }
2796               data_pos += 4;
2797 
2798               /* Mode */
2799               proto_tree_add_item(point_tree, hf_dnp3_al_file_mode, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2800               data_pos += 2;
2801 
2802               /* Max Block Size */
2803               proto_tree_add_item(point_tree, hf_dnp3_al_file_maxblk, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2804               data_pos += 2;
2805 
2806               /* Request ID */
2807               proto_tree_add_item(point_tree, hf_dnp3_al_file_reqID, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2808               data_pos += 2;
2809 
2810               /* Filename */
2811               if (al_filename_len > 0) {
2812                 proto_tree_add_item(point_tree, hf_dnp3_al_file_name, tvb, data_pos, al_filename_len, ENC_ASCII|ENC_NA);
2813               }
2814               data_pos += al_filename_len;
2815               proto_item_set_len(point_item, data_pos - offset);
2816 
2817               offset = data_pos;
2818               break;
2819 
2820             case AL_OBJ_FILE_STAT: /* File Control - File Status (Obj:70, Var:04) */
2821 
2822               /* File Handle */
2823               proto_tree_add_item(point_tree, hf_dnp3_al_file_handle, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2824               data_pos += 4;
2825 
2826               /* File Size */
2827               proto_tree_add_item(point_tree, hf_dnp3_al_file_size,   tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2828               data_pos += 4;
2829 
2830               /* Max Block Size */
2831               proto_tree_add_item(point_tree, hf_dnp3_al_file_maxblk, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2832               data_pos += 2;
2833 
2834               /* Request ID */
2835               proto_tree_add_item(point_tree, hf_dnp3_al_file_reqID,  tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2836               data_pos += 2;
2837 
2838               /* Status code */
2839               proto_tree_add_item(point_tree, hf_dnp3_al_file_status, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2840               data_pos += 1;
2841 
2842               /* Optional text */
2843               file_data_size = al_ptaddr - (data_pos - offset - prefixbytes);
2844               if ((file_data_size) > 0) {
2845                 proto_tree_add_item(point_tree, hf_dnp3_al_file_data, tvb, data_pos, file_data_size, ENC_NA);
2846                 data_pos += file_data_size;
2847               }
2848 
2849               proto_item_set_len(point_item, data_pos - offset);
2850 
2851               offset = data_pos;
2852               break;
2853 
2854             case AL_OBJ_FILE_TRANS: /* File Control - File Transport (Obj:70, Var:05) */
2855 
2856               /* File Handle */
2857               proto_tree_add_item(point_tree, hf_dnp3_al_file_handle, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2858               data_pos += 4;
2859 
2860               /* File block (bits 0 - 30) and last block flag (bit 31) */
2861               proto_tree_add_item(point_tree, hf_dnp3_al_file_blocknum,  tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2862               proto_tree_add_item(point_tree, hf_dnp3_al_file_lastblock, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2863               data_pos += 4;
2864 
2865               /* File data */
2866               file_data_size = al_ptaddr - (data_pos - offset - prefixbytes);
2867               if ((file_data_size) > 0) {
2868                 proto_tree_add_item(point_tree, hf_dnp3_al_file_data, tvb, data_pos, file_data_size, ENC_NA);
2869                 data_pos += file_data_size;
2870               }
2871 
2872               proto_item_set_len(point_item, data_pos - offset);
2873 
2874               offset = data_pos;
2875               break;
2876 
2877             case AL_OBJ_FILE_TRAN_ST: /* File Control Tansport Status (Obj:70, Var:06) */
2878 
2879               /* File Handle */
2880               proto_tree_add_item(point_tree, hf_dnp3_al_file_handle, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2881               data_pos += 4;
2882 
2883               /* File block (bits 0 - 30) and last block flag (bit 31) */
2884               proto_tree_add_item(point_tree, hf_dnp3_al_file_blocknum,  tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2885               proto_tree_add_item(point_tree, hf_dnp3_al_file_lastblock, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2886               data_pos += 4;
2887 
2888               /* Status code */
2889               proto_tree_add_item(point_tree, hf_dnp3_al_file_status, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2890               data_pos += 1;
2891 
2892               /* Optional text */
2893               file_data_size = al_ptaddr - (data_pos - offset - prefixbytes);
2894               if ((file_data_size) > 0) {
2895                 proto_tree_add_item(point_tree, hf_dnp3_al_file_data, tvb, data_pos, file_data_size, ENC_NA);
2896                 data_pos += file_data_size;
2897               }
2898 
2899               proto_item_set_len(point_item, data_pos - offset);
2900 
2901               offset = data_pos;
2902               break;
2903 
2904             case AL_OBJ_OCT:      /* Octet string */
2905             case AL_OBJ_OCT_EVT:  /* Octet string event */
2906 
2907               /* read the number of bytes defined by the variation */
2908               if (al_oct_len > 0) {
2909                 proto_tree_add_item(object_tree, hf_dnp3_al_octet_string, tvb, data_pos, al_oct_len, ENC_NA);
2910                 data_pos += al_oct_len;
2911                 proto_item_set_len(point_item, data_pos - offset);
2912               }
2913 
2914               offset = data_pos;
2915               break;
2916 
2917             default:             /* In case of unknown object */
2918 
2919               proto_tree_add_item(object_tree, hf_dnp3_unknown_data_chunk, tvb, offset, -1, ENC_NA);
2920               offset = tvb_captured_length(tvb); /* Finish decoding if unknown object is encountered... */
2921               break;
2922           }
2923         }
2924 
2925         /* And increment the point address, may be overwritten by an index value */
2926         al_ptaddr++;
2927       }
2928       else {
2929         /* No objects, just prefixes, move past prefix values */
2930         offset = data_pos;
2931       }
2932       if (start_offset > offset) {
2933         expert_add_info(pinfo, point_item, &ei_dnp_invalid_length);
2934         offset = tvb_captured_length(tvb); /* Finish decoding if unknown object is encountered... */
2935       }
2936     }
2937   }
2938   proto_item_set_len(object_item, offset - orig_offset);
2939 
2940   return offset;
2941 }
2942 
2943 /*****************************************************************/
2944 /* Application Layer Dissector */
2945 /*****************************************************************/
2946 static int
dissect_dnp3_al(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)2947 dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2948 {
2949   guint8        al_ctl, al_seq, al_func, al_class = 0, i;
2950   guint16       bytes, obj_type = 0;
2951   guint         data_len = 0, offset = 0;
2952   proto_item   *ti, *tc;
2953   proto_tree   *al_tree, *robj_tree;
2954   const gchar  *func_code_str, *obj_type_str;
2955   nstime_t      al_cto;
2956   static int * const control_flags[] = {
2957     &hf_dnp3_al_fir,
2958     &hf_dnp3_al_fin,
2959     &hf_dnp3_al_con,
2960     &hf_dnp3_al_uns,
2961     &hf_dnp3_al_seq,
2962     NULL
2963   };
2964 
2965   nstime_set_zero (&al_cto);
2966 
2967   data_len = tvb_captured_length(tvb);
2968 
2969   /* Handle the control byte and function code */
2970   al_ctl = tvb_get_guint8(tvb, offset);
2971   al_seq = al_ctl & DNP3_AL_SEQ;
2972   al_func = tvb_get_guint8(tvb, (offset+1));
2973   func_code_str = val_to_str_ext(al_func, &dnp3_al_func_vals_ext, "Unknown function (0x%02x)");
2974 
2975   /* Clear out lower layer info */
2976   col_clear(pinfo->cinfo, COL_INFO);
2977   col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, func_code_str);
2978   col_set_fence(pinfo->cinfo, COL_INFO);
2979 
2980   /* format up the text representation */
2981   al_tree = proto_tree_add_subtree(tree, tvb, offset, data_len, ett_dnp3_al, &ti, "Application Layer: (");
2982   if (al_ctl & DNP3_AL_FIR)  proto_item_append_text(ti, "FIR, ");
2983   if (al_ctl & DNP3_AL_FIN)  proto_item_append_text(ti, "FIN, ");
2984   if (al_ctl & DNP3_AL_CON)  proto_item_append_text(ti, "CON, ");
2985   if (al_ctl & DNP3_AL_UNS)  proto_item_append_text(ti, "UNS, ");
2986   proto_item_append_text(ti, "Sequence %u, %s)", al_seq, func_code_str);
2987 
2988   /* Application Layer control byte subtree */
2989   tc = proto_tree_add_bitmask(al_tree, tvb, offset, hf_dnp3_al_ctl, ett_dnp3_al_ctl, control_flags, ENC_BIG_ENDIAN);
2990   proto_item_append_text(tc, "(");
2991   if (al_ctl & DNP3_AL_FIR)  proto_item_append_text(tc, "FIR, ");
2992   if (al_ctl & DNP3_AL_FIN)  proto_item_append_text(tc, "FIN, ");
2993   if (al_ctl & DNP3_AL_CON)  proto_item_append_text(tc, "CON, ");
2994   if (al_ctl & DNP3_AL_UNS)  proto_item_append_text(tc, "UNS, ");
2995   proto_item_append_text(tc, "Sequence %u)", al_seq);
2996   offset += 1;
2997 
2998 #if 0
2999   /* If this packet is NOT the final Application Layer Message, exit and continue
3000      processing the remaining data in the fragment. */
3001   if (!(al_ctl & DNP3_AL_FIN)) {
3002     t_robj = proto_tree_add_expert(al_tree, pinfo, &ei_dnp3_buffering_user_data_until_final_frame_is_received, tvb, offset, -1);
3003     return 1;
3004   }
3005 #endif
3006 
3007   /* Application Layer Function Code Byte  */
3008   proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
3009     "Function Code: %s (0x%02x)", func_code_str, al_func);
3010   offset += 1;
3011 
3012   switch (al_func)
3013   {
3014     case AL_FUNC_READ:     /* Read Function Code 0x01 */
3015 
3016       /* Create Read Request Data Objects Tree */
3017       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "READ Request Data Objects");
3018 
3019       /* Process Data Object Details */
3020       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3021         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, TRUE, &obj_type, &al_cto);
3022 
3023         /* Update class type for each object that was a class read */
3024         switch(obj_type) {
3025           case AL_OBJ_CLASS0:
3026           case AL_OBJ_CLASS1:
3027           case AL_OBJ_CLASS2:
3028           case AL_OBJ_CLASS3:
3029             al_class |= (1 << ((obj_type & 0x0f) - 1));
3030             break;
3031           default:
3032             /* For reads for specific object types, bit-mask out the first byte and add the generic obj description to the column info */
3033             obj_type_str = val_to_str_ext((obj_type & 0xFF00), &dnp3_al_read_obj_vals_ext, "Unknown Object Type");
3034             col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, obj_type_str);
3035             break;
3036         }
3037 
3038       }
3039 
3040       /* Update the col info if there were class reads */
3041       if (al_class != 0) {
3042         col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Class ");
3043         for (i = 0; i < 4; i++) {
3044           if (al_class & (1 << i)) {
3045             col_append_fstr(pinfo->cinfo, COL_INFO, "%u", i);
3046           }
3047         }
3048       }
3049 
3050       break;
3051 
3052     case AL_FUNC_WRITE:     /* Write Function Code 0x02 */
3053 
3054       /* Create Write Request Data Objects Tree */
3055       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "WRITE Request Data Objects");
3056 
3057       /* Process Data Object Details */
3058       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3059         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3060 
3061         /* For writes for specific object types, bit-mask out the first byte and add the generic obj description to the column info */
3062         obj_type_str = val_to_str_ext((obj_type & 0xFF00), &dnp3_al_write_obj_vals_ext, "Unknown Object Type");
3063         col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, obj_type_str);
3064 
3065       }
3066 
3067       break;
3068 
3069     case AL_FUNC_SELECT:     /* Select Function Code 0x03 */
3070 
3071       /* Create Select Request Data Objects Tree */
3072       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "SELECT Request Data Objects");
3073 
3074       /* Process Data Object Details */
3075       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3076         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3077       }
3078 
3079       break;
3080 
3081     case AL_FUNC_OPERATE:    /* Operate Function Code 0x04 */
3082       /* Functionally identical to 'SELECT' Function Code */
3083 
3084       /* Create Operate Request Data Objects Tree */
3085       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "OPERATE Request Data Objects");
3086 
3087       /* Process Data Object Details */
3088       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3089         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3090       }
3091 
3092       break;
3093 
3094     case AL_FUNC_DIROP:        /* Direct Operate Function Code 0x05 */
3095     case AL_FUNC_DIROPNACK:    /* Direct Operate No ACK Function Code 0x06 */
3096       /* Functionally identical to 'SELECT' Function Code */
3097 
3098       /* Create Direct Operate Request Data Objects Tree */
3099       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "DIRECT OPERATE Request Data Objects");
3100 
3101       /* Process Data Object Details */
3102       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3103         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3104       }
3105 
3106       break;
3107 
3108     case AL_FUNC_FRZ:        /* Immediate Freeze Function Code 0x07 */
3109     case AL_FUNC_FRZNACK:    /* Immediate Freeze No ACK Function Code 0x08 */
3110     case AL_FUNC_FRZCLR:     /* Freeze and Clear Function Code 0x09 */
3111     case AL_FUNC_FRZCLRNACK: /* Freeze and Clear No ACK Function Code 0x0A */
3112 
3113       /* Create Freeze Request Data Objects Tree */
3114       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "Freeze Request Data Objects");
3115 
3116       /* Process Data Object Details */
3117       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3118         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, TRUE, &obj_type, &al_cto);
3119       }
3120 
3121       break;
3122 
3123     case AL_FUNC_ENSPMSG:   /* Enable Spontaneous Messages Function Code 0x14 */
3124 
3125       /* Create Enable Spontaneous Messages Data Objects Tree */
3126       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "Enable Spontaneous Msg's Data Objects");
3127 
3128       /* Process Data Object Details */
3129       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3130         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3131       }
3132 
3133       break;
3134 
3135     case AL_FUNC_DISSPMSG:   /* Disable Spontaneous Messages Function Code 0x15 */
3136 
3137       /* Create Disable Spontaneous Messages Data Objects Tree */
3138       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "Disable Spontaneous Msg's Data Objects");
3139 
3140       /* Process Data Object Details */
3141       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3142         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3143       }
3144 
3145       break;
3146 
3147     case AL_FUNC_DELAYMST:  /* Delay Measurement Function Code 0x17 */
3148 
3149       break;
3150 
3151     case AL_FUNC_OPENFILE:        /* Open File Function Code 0x19 */
3152     case AL_FUNC_CLOSEFILE:       /* Close File Function Code 0x1A */
3153     case AL_FUNC_DELETEFILE:      /* Delete File Function Code 0x1B */
3154 
3155       /* Create File Data Objects Tree */
3156       robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "File Data Objects");
3157 
3158       /* Process Data Object Details */
3159       while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
3160         offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3161       }
3162 
3163       break;
3164 
3165     case AL_FUNC_RESPON:   /* Response Function Code 0x81 */
3166     case AL_FUNC_UNSOLI:   /* Unsolicited Response Function Code 0x82 */
3167 
3168       /* Application Layer IIN bits req'd if message is a response */
3169       dnp3_al_process_iin(tvb, pinfo, offset, al_tree);
3170       offset += 2;
3171 
3172       /* Ensure there is actual data remaining in the message.
3173          A response will not contain data following the IIN bits,
3174          if there is none available */
3175       bytes = tvb_reported_length_remaining(tvb, offset);
3176       if (bytes > 0)
3177       {
3178         /* Create Response Data Objects Tree */
3179         robj_tree = proto_tree_add_subtree(al_tree, tvb, offset, -1, ett_dnp3_al_objdet, NULL, "RESPONSE Data Objects");
3180 
3181         /* Process Data Object Details */
3182         while (offset <= (data_len-2)) {  /* 2 octet object code + CRC32 */
3183           offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3184         }
3185 
3186         break;
3187       }
3188 
3189     default:    /* Unknown Function */
3190 
3191       break;
3192   }
3193 
3194   return 0;
3195 }
3196 
3197 /*****************************************************************/
3198 /* Data Link and Transport layer dissector */
3199 /*****************************************************************/
3200 static int
dissect_dnp3_message(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)3201 dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3202 {
3203   proto_item  *ti, *tdl, *tc, *hidden_item;
3204   proto_tree  *dnp3_tree, *dl_tree, *field_tree;
3205   int          offset = 0, temp_offset = 0;
3206   gboolean     dl_prm;
3207   guint8       dl_len, dl_ctl, dl_func;
3208   const gchar *func_code_str;
3209   guint16      dl_dst, dl_src, calc_dl_crc;
3210 
3211   /* Make entries in Protocol column and Info column on summary display */
3212   col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
3213   col_clear(pinfo->cinfo, COL_INFO);
3214 
3215   /* Skip "0x0564" header bytes */
3216   temp_offset += 2;
3217 
3218   dl_len = tvb_get_guint8(tvb, temp_offset);
3219   temp_offset += 1;
3220 
3221   dl_ctl = tvb_get_guint8(tvb, temp_offset);
3222   temp_offset += 1;
3223 
3224   dl_dst = tvb_get_letohs(tvb, temp_offset);
3225   temp_offset += 2;
3226 
3227   dl_src = tvb_get_letohs(tvb, temp_offset);
3228 
3229   dl_func = dl_ctl & DNP3_CTL_FUNC;
3230   dl_prm = dl_ctl & DNP3_CTL_PRM;
3231   func_code_str = val_to_str(dl_func, dl_prm ? dnp3_ctl_func_pri_vals : dnp3_ctl_func_sec_vals,
3232            "Unknown function (0x%02x)");
3233 
3234   /* Make sure source and dest are always in the info column */
3235   col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
3236   col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "len=%u, %s", dl_len, func_code_str);
3237 
3238   /* create display subtree for the protocol */
3239   ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, ENC_NA);
3240   dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);
3241 
3242   /* Create Subtree for Data Link Layer */
3243   dl_tree = proto_tree_add_subtree_format(dnp3_tree, tvb, offset, DNP_HDR_LEN, ett_dnp3_dl, &tdl,
3244         "Data Link Layer, Len: %u, From: %u, To: %u, ", dl_len, dl_src, dl_dst);
3245   if (dl_prm) {
3246     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
3247     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
3248     if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tdl, "FCB, ");
3249     if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tdl, "FCV, ");
3250   }
3251   else {
3252     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
3253     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
3254     if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tdl, "RES, ");
3255     if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tdl, "DFC, ");
3256   }
3257   proto_item_append_text(tdl, "%s", func_code_str);
3258 
3259   /* start bytes */
3260   proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, ENC_BIG_ENDIAN);
3261   offset += 2;
3262 
3263   /* add length field */
3264   proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, ENC_BIG_ENDIAN);
3265   offset += 1;
3266 
3267   /* Add Control Byte Subtree */
3268   tc = proto_tree_add_uint_format_value(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
3269           "0x%02x (", dl_ctl);
3270   /* Add Text to Control Byte Subtree Header */
3271   if (dl_prm) {
3272     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
3273     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
3274     if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tc, "FCB, ");
3275     if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tc, "FCV, ");
3276   }
3277   else {
3278     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
3279     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
3280     if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tc, "RES, ");
3281     if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tc, "DFC, ");
3282   }
3283   proto_item_append_text(tc, "%s)", func_code_str );
3284   field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);
3285 
3286   /* Add Control Byte Subtree Items */
3287   if (dl_prm) {
3288     proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3289     proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3290     proto_tree_add_item(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3291     proto_tree_add_item(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3292     proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, ENC_BIG_ENDIAN);
3293   }
3294   else {
3295     proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3296     proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3297     proto_tree_add_item(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3298     proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, ENC_BIG_ENDIAN);
3299   }
3300     offset += 1;
3301 
3302   /* add destination and source addresses */
3303   proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3304   hidden_item = proto_tree_add_item(dl_tree, hf_dnp3_addr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3305   proto_item_set_hidden(hidden_item);
3306   offset += 2;
3307   proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3308   hidden_item = proto_tree_add_item(dl_tree, hf_dnp3_addr, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3309   proto_item_set_hidden(hidden_item);
3310   offset += 2;
3311 
3312   /* and header CRC */
3313   calc_dl_crc = calculateCRCtvb(tvb, 0, DNP_HDR_LEN - 2);
3314   proto_tree_add_checksum(dl_tree, tvb, offset, hf_dnp3_data_hdr_crc,
3315                           hf_dnp3_data_hdr_crc_status, &ei_dnp3_data_hdr_crc_incorrect,
3316                           pinfo, calc_dl_crc, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
3317   offset += 2;
3318 
3319   /* If the DataLink function is 'Request Link Status' or 'Status of Link',
3320      or 'Reset Link' we don't expect any Transport or Application Layer Data
3321      NOTE: This code should probably check what DOES have TR or AL data */
3322   if ((dl_func != DL_FUNC_LINK_STAT) && (dl_func != DL_FUNC_STAT_LINK) &&
3323       (dl_func != DL_FUNC_RESET_LINK) && (dl_func != DL_FUNC_ACK))
3324   {
3325     proto_tree *data_tree;
3326     proto_item *data_ti;
3327     guint8      tr_ctl, tr_seq;
3328     gboolean    tr_fir, tr_fin;
3329     guint8     *al_buffer, *al_buffer_ptr;
3330     guint8      data_len;
3331     int         data_start = offset;
3332     int         tl_offset;
3333     gboolean    crc_OK = FALSE;
3334     tvbuff_t   *next_tvb;
3335     guint       i;
3336     static int * const transport_flags[] = {
3337       &hf_dnp3_tr_fin,
3338       &hf_dnp3_tr_fir,
3339       &hf_dnp3_tr_seq,
3340       NULL
3341     };
3342 
3343     /* get the transport layer byte */
3344     tr_ctl = tvb_get_guint8(tvb, offset);
3345     tr_seq = tr_ctl & DNP3_TR_SEQ;
3346     tr_fir = tr_ctl & DNP3_TR_FIR;
3347     tr_fin = tr_ctl & DNP3_TR_FIN;
3348 
3349     /* Add Transport Layer Tree */
3350     tc = proto_tree_add_bitmask(dnp3_tree, tvb, offset, hf_dnp3_tr_ctl, ett_dnp3_tr_ctl, transport_flags, ENC_BIG_ENDIAN);
3351     proto_item_append_text(tc, "(");
3352     if (tr_fir) proto_item_append_text(tc, "FIR, ");
3353     if (tr_fin) proto_item_append_text(tc, "FIN, ");
3354     proto_item_append_text(tc, "Sequence %u)", tr_seq);
3355 
3356     /* Add data chunk tree */
3357     data_tree = proto_tree_add_subtree(dnp3_tree, tvb, offset, -1, ett_dnp3_dl_data, &data_ti, "Data Chunks");
3358 
3359     /* extract the application layer data, validating the CRCs */
3360 
3361     /* XXX - check for dl_len <= 5 */
3362     data_len = dl_len - 5;
3363     al_buffer = (guint8 *)wmem_alloc(pinfo->pool, data_len);
3364     al_buffer_ptr = al_buffer;
3365     i = 0;
3366     tl_offset = 1;  /* skip the initial transport layer byte when assembling chunks for the application layer tvb */
3367     while (data_len > 0)
3368     {
3369       guint8        chk_size;
3370       const guint8 *chk_ptr;
3371       proto_tree   *chk_tree;
3372       proto_item   *chk_len_ti;
3373       guint16       calc_crc, act_crc;
3374 
3375       chk_size = MIN(data_len, AL_MAX_CHUNK_SIZE);
3376       chk_ptr  = tvb_get_ptr(tvb, offset, chk_size);
3377       memcpy(al_buffer_ptr, chk_ptr + tl_offset, chk_size - tl_offset);
3378       al_buffer_ptr += chk_size - tl_offset;
3379 
3380       chk_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, chk_size + 2, ett_dnp3_dl_chunk, NULL, "Data Chunk: %u", i);
3381       proto_tree_add_item(chk_tree, hf_dnp3_data_chunk, tvb, offset, chk_size, ENC_NA);
3382       chk_len_ti = proto_tree_add_uint(chk_tree, hf_dnp3_data_chunk_len, tvb, offset, 0, chk_size);
3383       proto_item_set_generated(chk_len_ti);
3384 
3385       offset  += chk_size;
3386 
3387       calc_crc = calculateCRC(chk_ptr, chk_size);
3388       proto_tree_add_checksum(chk_tree, tvb, offset, hf_dnp3_data_chunk_crc,
3389                               hf_dnp3_data_chunk_crc_status, &ei_dnp3_data_chunk_crc_incorrect,
3390                               pinfo, calc_crc, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
3391       act_crc  = tvb_get_letohs(tvb, offset);
3392       offset  += 2;
3393       crc_OK   = calc_crc == act_crc;
3394       if (!crc_OK)
3395       {
3396         /* Don't trust the rest of the data, get out of here */
3397         break;
3398       }
3399       data_len -= chk_size;
3400       i++;
3401       tl_offset = 0;  /* copy all the data in the rest of the chunks */
3402     }
3403     proto_item_set_len(data_ti, offset - data_start);
3404 
3405     /* if crc OK, set up new tvb */
3406     if (crc_OK)
3407     {
3408       tvbuff_t *al_tvb;
3409       gboolean  save_fragmented;
3410 
3411       al_tvb = tvb_new_child_real_data(tvb, al_buffer, (guint) (al_buffer_ptr-al_buffer), (gint) (al_buffer_ptr-al_buffer));
3412 
3413       /* Check for fragmented packet */
3414       save_fragmented = pinfo->fragmented;
3415 
3416       /* Reassemble AL fragments */
3417       static guint al_max_fragments = 60;
3418       static guint al_fragment_aging = 64; /* sequence numbers only 6 bit */
3419       fragment_head *frag_al = NULL;
3420       pinfo->fragmented = TRUE;
3421       if (!pinfo->fd->visited)
3422       {
3423         frag_al = fragment_add_seq_single_aging(&al_reassembly_table,
3424             al_tvb, 0, pinfo, tr_seq, NULL,
3425             tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
3426             tr_fir, tr_fin,
3427             al_max_fragments, al_fragment_aging);
3428       }
3429       else
3430       {
3431         frag_al = fragment_get_reassembled_id(&al_reassembly_table, pinfo, tr_seq);
3432       }
3433       next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
3434           "Reassembled DNP 3.0 Application Layer message", frag_al, &dnp3_frag_items,
3435           NULL, dnp3_tree);
3436 
3437       if (frag_al)
3438       {
3439         if (pinfo->num == frag_al->reassembled_in && pinfo->curr_layer_num == frag_al->reas_in_layer_num)
3440         {
3441           /* As a complete AL message will have cleared the info column,
3442              make sure source and dest are always in the info column */
3443           //col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
3444           //col_set_fence(pinfo->cinfo, COL_INFO);
3445           dissect_dnp3_al(next_tvb, pinfo, dnp3_tree);
3446         }
3447         else
3448         {
3449           /* Lock any column info set by the DL and TL */
3450           col_set_fence(pinfo->cinfo, COL_INFO);
3451           col_append_fstr(pinfo->cinfo, COL_INFO,
3452               " (Application Layer fragment %u, reassembled in packet %u)",
3453               tr_seq, frag_al->reassembled_in);
3454           proto_tree_add_item(dnp3_tree, hf_al_frag_data, al_tvb, 0, -1, ENC_NA);
3455         }
3456       }
3457       else
3458       {
3459         col_append_fstr(pinfo->cinfo, COL_INFO,
3460             " (Application Layer Unreassembled fragment %u)",
3461             tr_seq);
3462         proto_tree_add_item(dnp3_tree, hf_al_frag_data, al_tvb, 0, -1, ENC_NA);
3463       }
3464 
3465       pinfo->fragmented = save_fragmented;
3466     }
3467     else
3468     {
3469       /* CRC error - throw away the data. */
3470       wmem_free(pinfo->pool, al_buffer);
3471       next_tvb = NULL;
3472     }
3473   }
3474 
3475   /* Set the length of the message */
3476   proto_item_set_len(ti, offset);
3477   return offset;
3478 }
3479 
3480 static gboolean
check_dnp3_header(tvbuff_t * tvb,gboolean dnp3_heuristics)3481 check_dnp3_header(tvbuff_t *tvb, gboolean dnp3_heuristics)
3482 {
3483   /* Assume the CRC will be bad */
3484   gboolean goodCRC = FALSE;
3485 
3486   /* How big is the actual buffer */
3487   gint length = tvb_captured_length(tvb);
3488 
3489   /* Calculate the header CRC if the bytes are available */
3490   if (length >= DNP_HDR_LEN) {
3491     guint16 calc_crc = calculateCRCtvb(tvb, 0, DNP_HDR_LEN - 2);
3492     goodCRC = (calc_crc == tvb_get_letohs(tvb, 8));
3493   }
3494 
3495   /* For a heuristic match we must have at least a header, beginning with 0x0564
3496      and a valid header CRC */
3497   if (dnp3_heuristics) {
3498     if ( !goodCRC || (tvb_get_ntohs(tvb, 0) != 0x0564)) {
3499       return FALSE;
3500     }
3501   }
3502   else {
3503     /* For a non-heuristic match, at least the first byte is 0x05 and if available
3504        the second byte is 64 and if available the CRC is valid */
3505     if (tvb_get_guint8(tvb, 0) != 0x05) {
3506       return FALSE;
3507     }
3508     if ((length > 1) && (tvb_get_guint8(tvb, 1) != 0x64)) {
3509       return FALSE;
3510     }
3511     if ((length >= DNP_HDR_LEN) && !goodCRC) {
3512       return FALSE;
3513     }
3514   }
3515   return TRUE;
3516 }
3517 
3518 static guint
get_dnp3_message_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)3519 get_dnp3_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
3520                      int offset, void *data _U_)
3521 {
3522   guint16 message_len;  /* need 16 bits as total can exceed 255 */
3523   guint16 data_crc;     /* No. of user data CRC bytes */
3524 
3525   message_len = tvb_get_guint8(tvb, offset + 2);
3526 
3527   /* Add in 2 bytes for header start octets,
3528             1 byte for len itself,
3529             2 bytes for header CRC
3530             data CRC bytes (2 bytes per 16 bytes of data
3531   */
3532 
3533   data_crc = (guint16)(ceil((message_len - 5) / 16.0)) * 2;
3534   message_len += 2 + 1 + 2 + data_crc;
3535   return message_len;
3536 }
3537 
3538 static int
dissect_dnp3_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3539 dissect_dnp3_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3540 {
3541   if (!check_dnp3_header(tvb, FALSE)) {
3542     return 0;
3543   }
3544 
3545   tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DNP_HDR_LEN,
3546                    get_dnp3_message_len, dissect_dnp3_message, data);
3547 
3548   return tvb_captured_length(tvb);
3549 }
3550 
3551 static gboolean
dissect_dnp3_tcp_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3552 dissect_dnp3_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3553 {
3554   if (!check_dnp3_header(tvb, TRUE)) {
3555     return FALSE;
3556   }
3557 
3558   tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DNP_HDR_LEN,
3559                    get_dnp3_message_len, dissect_dnp3_message, data);
3560 
3561   return TRUE;
3562 }
3563 
3564 static gboolean
dnp3_udp_check_header(packet_info * pinfo _U_,tvbuff_t * tvb,int offset _U_,void * data _U_)3565 dnp3_udp_check_header(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_, void *data _U_)
3566 {
3567     return check_dnp3_header(tvb, FALSE);
3568 }
3569 
3570 static gboolean
dnp3_udp_check_header_heur(packet_info * pinfo _U_,tvbuff_t * tvb,int offset _U_,void * data _U_)3571 dnp3_udp_check_header_heur(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_, void *data _U_)
3572 {
3573     return check_dnp3_header(tvb, TRUE);
3574 }
3575 
3576 static int
dissect_dnp3_udp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3577 dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3578 {
3579   return udp_dissect_pdus(tvb, pinfo, tree, DNP_HDR_LEN, dnp3_udp_check_header,
3580                    get_dnp3_message_len, dissect_dnp3_message, data);
3581 }
3582 
3583 static gboolean
dissect_dnp3_udp_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)3584 dissect_dnp3_udp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3585 {
3586   return (udp_dissect_pdus(tvb, pinfo, tree, DNP_HDR_LEN, dnp3_udp_check_header_heur,
3587                    get_dnp3_message_len, dissect_dnp3_message, data) != 0);
3588 
3589 }
3590 
3591 /* Register the protocol with Wireshark */
3592 
3593 void
proto_register_dnp3(void)3594 proto_register_dnp3(void)
3595 {
3596 
3597 /* Setup list of header fields */
3598   static hf_register_info hf[] = {
3599     { &hf_dnp3_start,
3600       { "Start Bytes", "dnp3.start",
3601         FT_UINT16, BASE_HEX, NULL, 0x0,
3602         NULL, HFILL }
3603     },
3604 
3605     { &hf_dnp3_len,
3606       { "Length", "dnp3.len",
3607         FT_UINT8, BASE_DEC, NULL, 0x0,
3608         "Frame Data Length", HFILL }
3609     },
3610 
3611     { &hf_dnp3_ctl,
3612       { "Control", "dnp3.ctl",
3613         FT_UINT8, BASE_HEX, NULL, 0x0,
3614         "Frame Control Byte", HFILL }
3615     },
3616 
3617     { &hf_dnp3_ctl_prifunc,
3618       { "Control Function Code", "dnp3.ctl.prifunc",
3619         FT_UINT8, BASE_DEC, VALS(dnp3_ctl_func_pri_vals), DNP3_CTL_FUNC,
3620         "Frame Control Function Code", HFILL }
3621     },
3622 
3623     { &hf_dnp3_ctl_secfunc,
3624       { "Control Function Code", "dnp3.ctl.secfunc",
3625         FT_UINT8, BASE_DEC, VALS(dnp3_ctl_func_sec_vals), DNP3_CTL_FUNC,
3626         "Frame Control Function Code", HFILL }
3627     },
3628 
3629     { &hf_dnp3_ctlobj_code_c,
3630       { "Operation Type", "dnp3.ctl.op",
3631         FT_UINT8, BASE_DEC, VALS(dnp3_al_ctlc_code_vals), AL_OBJCTLC_CODE,
3632         "Control Code, Operation Type", HFILL }
3633     },
3634 
3635     { &hf_dnp3_ctlobj_code_m,
3636       { "Queue / Clear Field", "dnp3.ctl.clr",
3637         FT_UINT8, BASE_DEC, VALS(dnp3_al_ctlc_misc_vals), AL_OBJCTLC_MISC,
3638         "Control Code, Clear Field", HFILL }
3639     },
3640 
3641     { &hf_dnp3_ctlobj_code_tc,
3642       { "Trip Control Code", "dnp3.ctl.trip",
3643         FT_UINT8, BASE_DEC, VALS(dnp3_al_ctlc_tc_vals), AL_OBJCTLC_TC,
3644         "Control Code, Trip Close Control", HFILL }
3645     },
3646 
3647     { &hf_dnp3_ctl_dir,
3648       { "Direction", "dnp3.ctl.dir",
3649         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DIR,
3650         NULL, HFILL }
3651     },
3652 
3653     { &hf_dnp3_ctl_prm,
3654       { "Primary", "dnp3.ctl.prm",
3655         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_PRM,
3656         NULL, HFILL }
3657     },
3658 
3659     { &hf_dnp3_ctl_fcb,
3660       { "Frame Count Bit", "dnp3.ctl.fcb",
3661         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCB,
3662         NULL, HFILL }
3663     },
3664 
3665     { &hf_dnp3_ctl_fcv,
3666       { "Frame Count Valid", "dnp3.ctl.fcv",
3667         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCV,
3668         NULL, HFILL }
3669     },
3670 
3671     { &hf_dnp3_ctl_dfc,
3672       { "Data Flow Control", "dnp3.ctl.dfc",
3673         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DFC,
3674         NULL, HFILL }
3675     },
3676 
3677     { &hf_dnp3_dst,
3678       { "Destination", "dnp3.dst",
3679         FT_UINT16, BASE_DEC, NULL, 0x0,
3680         "Destination Address", HFILL }
3681     },
3682 
3683     { &hf_dnp3_src,
3684       { "Source", "dnp3.src",
3685         FT_UINT16, BASE_DEC, NULL, 0x0,
3686         "Source Address", HFILL }
3687     },
3688 
3689     { &hf_dnp3_addr,
3690       { "Address", "dnp3.addr",
3691         FT_UINT16, BASE_DEC, NULL, 0x0,
3692         "Source or Destination Address", HFILL }
3693     },
3694 
3695     { &hf_dnp3_data_hdr_crc,
3696       { "Data Link Header checksum", "dnp3.hdr.CRC",
3697         FT_UINT16, BASE_HEX, NULL, 0x0,
3698         NULL, HFILL }
3699     },
3700 
3701     { &hf_dnp3_data_hdr_crc_status,
3702         { "Data Link Header Checksum Status", "dnp.hdr.CRC.status",
3703         FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
3704         NULL, HFILL }
3705     },
3706 
3707     { &hf_dnp3_tr_ctl,
3708       { "Transport Control", "dnp3.tr.ctl",
3709         FT_UINT8, BASE_HEX, NULL, 0x0,
3710         "Transport Layer Control Byte", HFILL }
3711     },
3712 
3713     { &hf_dnp3_tr_fin,
3714       { "Final", "dnp3.tr.fin",
3715         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIN,
3716         NULL, HFILL }
3717     },
3718 
3719     { &hf_dnp3_tr_fir,
3720       { "First", "dnp3.tr.fir",
3721         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIR,
3722         NULL, HFILL }
3723     },
3724 
3725     { &hf_dnp3_tr_seq,
3726       { "Sequence", "dnp3.tr.seq",
3727         FT_UINT8, BASE_DEC, NULL, DNP3_TR_SEQ,
3728         "Frame Sequence Number", HFILL }
3729     },
3730 
3731     { &hf_dnp3_data_chunk,
3732       { "Data Chunk", "dnp.data_chunk",
3733         FT_BYTES, BASE_NONE, NULL, 0x0,
3734         NULL, HFILL }
3735     },
3736 
3737     { &hf_dnp3_data_chunk_len,
3738       { "Data Chunk length", "dnp.data_chunk_len",
3739         FT_UINT16, BASE_DEC, NULL, 0x0,
3740         NULL, HFILL }
3741     },
3742 
3743     { &hf_dnp3_data_chunk_crc,
3744       { "Data Chunk checksum", "dnp.data_chunk.CRC",
3745         FT_UINT16, BASE_HEX, NULL, 0x0,
3746         NULL, HFILL }
3747     },
3748 
3749     { &hf_dnp3_data_chunk_crc_status,
3750         { "Data Chunk Checksum Status", "dnp.data_chunk.CRC.status",
3751         FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
3752         NULL, HFILL }
3753     },
3754 
3755     { &hf_dnp3_al_ctl,
3756       { "Application Control", "dnp3.al.ctl",
3757         FT_UINT8, BASE_HEX, NULL, 0x0,
3758         "Application Layer Control Byte", HFILL }
3759     },
3760 
3761     { &hf_dnp3_al_fir,
3762       { "First", "dnp3.al.fir",
3763         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIR,
3764         NULL, HFILL }
3765     },
3766 
3767     { &hf_dnp3_al_fin,
3768       { "Final", "dnp3.al.fin",
3769         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIN,
3770         NULL, HFILL }
3771     },
3772 
3773     { &hf_dnp3_al_con,
3774       { "Confirm", "dnp3.al.con",
3775         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_CON,
3776         NULL, HFILL }
3777     },
3778 
3779     { &hf_dnp3_al_uns,
3780       { "Unsolicited", "dnp3.al.uns",
3781         FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_UNS,
3782         NULL, HFILL }
3783     },
3784 
3785     { &hf_dnp3_al_seq,
3786       { "Sequence", "dnp3.al.seq",
3787         FT_UINT8, BASE_DEC, NULL, DNP3_AL_SEQ,
3788         "Frame Sequence Number", HFILL }
3789     },
3790 
3791     { &hf_dnp3_al_func,
3792       { "Application Layer Function Code", "dnp3.al.func",
3793         FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_func_vals_ext, DNP3_AL_FUNC,
3794         "Application Function Code", HFILL }
3795     },
3796 
3797     { &hf_dnp3_al_iin,
3798       { "Internal Indications", "dnp3.al.iin",
3799         FT_UINT16, BASE_HEX, NULL, 0x0,
3800         "Application Layer IIN", HFILL }
3801     },
3802 
3803     { &hf_dnp3_al_iin_bmsg,
3804       { "Broadcast Msg Rx", "dnp3.al.iin.bmsg",
3805         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_BMSG,
3806         NULL, HFILL }
3807     },
3808 
3809     { &hf_dnp3_al_iin_cls1d,
3810       { "Class 1 Data Available", "dnp3.al.iin.cls1d",
3811         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS1D,
3812         NULL, HFILL }
3813     },
3814 
3815     { &hf_dnp3_al_iin_cls2d,
3816       { "Class 2 Data Available", "dnp3.al.iin.cls2d",
3817         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS2D,
3818         NULL, HFILL }
3819     },
3820 
3821     { &hf_dnp3_al_iin_cls3d,
3822       { "Class 3 Data Available", "dnp3.al.iin.cls3d",
3823         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS3D,
3824         NULL, HFILL }
3825     },
3826 
3827     { &hf_dnp3_al_iin_tsr,
3828       { "Time Sync Required", "dnp3.al.iin.tsr",
3829         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_TSR,
3830         NULL, HFILL }
3831     },
3832 
3833     { &hf_dnp3_al_iin_dol,
3834       { "Digital Outputs in Local", "dnp3.al.iin.dol",
3835         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DOL,
3836         NULL, HFILL }
3837     },
3838 
3839     { &hf_dnp3_al_iin_dt,
3840       { "Device Trouble", "dnp3.al.iin.dt",
3841         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DT,
3842         NULL, HFILL }
3843     },
3844 
3845     { &hf_dnp3_al_iin_rst,
3846       { "Device Restart", "dnp3.al.iin.rst",
3847         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_RST,
3848         NULL, HFILL }
3849     },
3850 
3851     { &hf_dnp3_al_iin_fcni,
3852       { "Function Code not implemented", "dnp3.al.iin.fcni",
3853         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_FCNI,
3854         NULL, HFILL }
3855     },
3856 
3857     { &hf_dnp3_al_iin_obju,
3858       { "Requested Objects Unknown", "dnp3.al.iin.obju",
3859         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OBJU,
3860         NULL, HFILL }
3861     },
3862 
3863     { &hf_dnp3_al_iin_pioor,
3864       { "Parameters Invalid or Out of Range", "dnp3.al.iin.pioor",
3865         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_PIOOR,
3866         NULL, HFILL }
3867     },
3868 
3869     { &hf_dnp3_al_iin_ebo,
3870       { "Event Buffer Overflow", "dnp3.al.iin.ebo",
3871         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_EBO,
3872         NULL, HFILL }
3873     },
3874 
3875     { &hf_dnp3_al_iin_oae,
3876       { "Operation Already Executing", "dnp3.al.iin.oae",
3877         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OAE,
3878         NULL, HFILL }
3879     },
3880 
3881     { &hf_dnp3_al_iin_cc,
3882       { "Configuration Corrupt", "dnp3.al.iin.cc",
3883         FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CC,
3884         NULL, HFILL }
3885     },
3886 
3887     { &hf_dnp3_al_obj,
3888       { "Object", "dnp3.al.obj",
3889         FT_UINT16, BASE_HEX|BASE_EXT_STRING, &dnp3_al_obj_vals_ext, 0x0,
3890         "Application Layer Object", HFILL }
3891     },
3892 
3893     { &hf_dnp3_al_objq_prefix,
3894       { "Prefix Code", "dnp3.al.objq.prefix",
3895         FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_objq_prefix_vals_ext, AL_OBJQ_PREFIX,
3896         "Object Prefix Code", HFILL }
3897     },
3898 
3899     { &hf_dnp3_al_objq_range,
3900       { "Range Code", "dnp3.al.objq.range",
3901         FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_objq_range_vals_ext, AL_OBJQ_RANGE,
3902         "Object Range Specifier Code", HFILL }
3903     },
3904 
3905     { &hf_dnp3_al_range_start8,
3906       { "Start (8 bit)", "dnp3.al.range.start",
3907         FT_UINT8, BASE_DEC, NULL, 0x0,
3908         "Object Start Index", HFILL }
3909     },
3910 
3911     { &hf_dnp3_al_range_stop8,
3912       { "Stop (8 bit)", "dnp3.al.range.stop",
3913         FT_UINT8, BASE_DEC, NULL, 0x0,
3914         "Object Stop Index", HFILL }
3915     },
3916 
3917     { &hf_dnp3_al_range_start16,
3918       { "Start (16 bit)", "dnp3.al.range.start",
3919         FT_UINT16, BASE_DEC, NULL, 0x0,
3920         "Object Start Index", HFILL }
3921     },
3922 
3923     { &hf_dnp3_al_range_stop16,
3924       { "Stop (16 bit)", "dnp3.al.range.stop",
3925         FT_UINT16, BASE_DEC, NULL, 0x0,
3926         "Object Stop Index", HFILL }
3927     },
3928 
3929     { &hf_dnp3_al_range_start32,
3930       { "Start (32 bit)", "dnp3.al.range.start",
3931         FT_UINT32, BASE_DEC, NULL, 0x0,
3932         "Object Start Index", HFILL }
3933     },
3934 
3935     { &hf_dnp3_al_range_stop32,
3936       { "Stop (32 bit)", "dnp3.al.range.stop",
3937         FT_UINT32, BASE_DEC, NULL, 0x0,
3938         "Object Stop Index", HFILL }
3939     },
3940 
3941     { &hf_dnp3_al_range_abs8,
3942       { "Address (8 bit)", "dnp3.al.range.abs",
3943         FT_UINT8, BASE_DEC, NULL, 0x0,
3944         "Object Absolute Address", HFILL }
3945     },
3946 
3947     { &hf_dnp3_al_range_abs16,
3948       { "Address (16 bit)", "dnp3.al.range.abs",
3949         FT_UINT16, BASE_DEC, NULL, 0x0,
3950         "Object Absolute Address", HFILL }
3951     },
3952 
3953     { &hf_dnp3_al_range_abs32,
3954       { "Address (32 bit)", "dnp3.al.range.abs",
3955         FT_UINT32, BASE_DEC, NULL, 0x0,
3956         "Object Absolute Address", HFILL }
3957     },
3958 
3959     { &hf_dnp3_al_range_quant8,
3960       { "Quantity (8 bit)", "dnp3.al.range.quantity",
3961         FT_UINT8, BASE_DEC, NULL, 0x0,
3962         "Object Quantity", HFILL }
3963     },
3964 
3965     { &hf_dnp3_al_range_quant16,
3966       { "Quantity (16 bit)", "dnp3.al.range.quantity",
3967         FT_UINT16, BASE_DEC, NULL, 0x0,
3968         "Object Quantity", HFILL }
3969     },
3970 
3971     { &hf_dnp3_al_range_quant32,
3972       { "Quantity (32 bit)", "dnp3.al.range.quantity",
3973         FT_UINT32, BASE_DEC, NULL, 0x0,
3974         "Object Quantity", HFILL }
3975     },
3976 
3977     { &hf_dnp3_al_index8,
3978       { "Index (8 bit)", "dnp3.al.index",
3979         FT_UINT8, BASE_DEC, NULL, 0x0,
3980         "Object Index", HFILL }
3981     },
3982 
3983     { &hf_dnp3_al_index16,
3984       { "Index (16 bit)", "dnp3.al.index",
3985         FT_UINT16, BASE_DEC, NULL, 0x0,
3986         "Object Index", HFILL }
3987     },
3988 
3989     { &hf_dnp3_al_index32,
3990       { "Index (32 bit)", "dnp3.al.index",
3991         FT_UINT32, BASE_DEC, NULL, 0x0,
3992         "Object Index", HFILL }
3993     },
3994 
3995 #if 0
3996     { &hf_dnp3_al_ptnum,
3997       { "Object Point Number", "dnp3.al.ptnum",
3998         FT_UINT16, BASE_DEC, NULL, 0x0,
3999         NULL, HFILL }
4000     },
4001 #endif
4002 
4003     { &hf_dnp3_al_size8,
4004       { "Size (8 bit)", "dnp3.al.size",
4005           FT_UINT8, BASE_DEC, NULL, 0x0,
4006           "Object Size", HFILL }
4007     },
4008 
4009     { &hf_dnp3_al_size16,
4010       { "Size (16 bit)", "dnp3.al.size",
4011           FT_UINT16, BASE_DEC, NULL, 0x0,
4012           "Object Size", HFILL }
4013     },
4014 
4015     { &hf_dnp3_al_size32,
4016       { "Size (32 bit)", "dnp3.al.size",
4017           FT_UINT32, BASE_DEC, NULL, 0x0,
4018           "Object Size", HFILL }
4019     },
4020 
4021     { &hf_dnp3_bocs_bit,
4022       { "Commanded State", "dnp3.al.bocs",
4023           FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x80,
4024           "Binary Output Commanded state", HFILL }
4025     },
4026 
4027     { &hf_dnp3_al_bit,
4028       { "Value (bit)", "dnp3.al.bit",
4029           FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x1,
4030           "Digital Value (1 bit)", HFILL }
4031     },
4032 
4033     { &hf_dnp3_al_2bit,
4034       { "Value (two bit)", "dnp3.al.2bit",
4035           FT_UINT8, BASE_DEC, NULL, 0x0,
4036           "Digital Value (2 bit)", HFILL }
4037     },
4038 
4039     { &hf_dnp3_al_ana16,
4040       { "Value (16 bit)", "dnp3.al.ana.int",
4041           FT_INT16, BASE_DEC, NULL, 0x0,
4042           "Analog Value (16 bit)", HFILL }
4043     },
4044 
4045     { &hf_dnp3_al_ana32,
4046       { "Value (32 bit)", "dnp3.al.ana.int",
4047           FT_INT32, BASE_DEC, NULL, 0x0,
4048           "Analog Value (32 bit)", HFILL }
4049     },
4050 
4051     { &hf_dnp3_al_anaflt,
4052       { "Value (float)", "dnp3.al.ana.float",
4053           FT_FLOAT, BASE_NONE, NULL, 0x0,
4054           "Analog Value (float)", HFILL }
4055     },
4056 
4057     { &hf_dnp3_al_anadbl,
4058       { "Value (double)", "dnp3.al.ana.double",
4059           FT_DOUBLE, BASE_NONE, NULL, 0x0,
4060           "Analog Value (double)", HFILL }
4061     },
4062 
4063     { &hf_dnp3_al_anaout16,
4064       { "Output Value (16 bit)", "dnp3.al.anaout.int",
4065           FT_INT16, BASE_DEC, NULL, 0x0,
4066           NULL, HFILL }
4067     },
4068 
4069     { &hf_dnp3_al_anaout32,
4070       { "Output Value (32 bit)", "dnp3.al.anaout.int",
4071           FT_INT32, BASE_DEC, NULL, 0x0,
4072           NULL, HFILL }
4073     },
4074 
4075     { &hf_dnp3_al_anaoutflt,
4076       { "Output Value (float)", "dnp3.al.anaout.float",
4077           FT_FLOAT, BASE_NONE, NULL, 0x0,
4078           NULL, HFILL }
4079     },
4080 
4081     { &hf_dnp3_al_anaoutdbl,
4082       { "Output (double)", "dnp3.al.anaout.double",
4083           FT_DOUBLE, BASE_NONE, NULL, 0x0,
4084           "Output Value (double)", HFILL }
4085     },
4086 
4087     { &hf_dnp3_al_cnt16,
4088       { "Counter (16 bit)", "dnp3.al.cnt",
4089           FT_UINT16, BASE_DEC, NULL, 0x0,
4090           "Counter Value (16 bit)", HFILL }
4091     },
4092 
4093     { &hf_dnp3_al_cnt32,
4094       { "Counter (32 bit)", "dnp3.al.cnt",
4095           FT_UINT32, BASE_DEC, NULL, 0x0,
4096           "Counter Value (32 bit)", HFILL }
4097     },
4098 
4099     { &hf_dnp3_al_ctrlstatus,
4100       { "Control Status", "dnp3.al.ctrlstatus",
4101           FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_ctl_status_vals_ext, AL_OBJCTL_STATUS_MASK,
4102           NULL, HFILL }
4103     },
4104 
4105     { &hf_dnp3_al_file_mode,
4106       { "File Control Mode", "dnp3.al.file.mode",
4107           FT_UINT16, BASE_DEC, VALS(dnp3_al_file_mode_vals), 0x0,
4108           NULL, HFILL }
4109     },
4110 
4111     { &hf_dnp3_al_file_auth,
4112       { "File Authentication Key", "dnp3.al.file.auth",
4113           FT_UINT32, BASE_HEX, NULL, 0x0,
4114           NULL, HFILL }
4115     },
4116 
4117     { &hf_dnp3_al_file_size,
4118       { "File Size", "dnp3.al.file.size",
4119           FT_UINT32, BASE_HEX, NULL, 0x0,
4120           NULL, HFILL }
4121     },
4122 
4123     { &hf_dnp3_al_file_maxblk,
4124       { "File Max Block Size", "dnp3.al.file.maxblock",
4125           FT_UINT16, BASE_DEC, NULL, 0x0,
4126           NULL, HFILL }
4127     },
4128 
4129     { &hf_dnp3_al_file_reqID,
4130       { "File Request Identifier", "dnp3.al.file.reqID",
4131           FT_UINT16, BASE_DEC, NULL, 0x0,
4132           NULL, HFILL }
4133     },
4134 
4135     { &hf_dnp3_al_file_status,
4136       { "File Control Status", "dnp3.al.file.status",
4137           FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_file_status_vals_ext, 0x0,
4138           NULL, HFILL }
4139     },
4140 
4141     { &hf_dnp3_al_file_handle,
4142       { "File Handle", "dnp3.al.file.handle",
4143           FT_UINT32, BASE_HEX, NULL, 0x0,
4144           NULL, HFILL }
4145     },
4146 
4147     { &hf_dnp3_al_file_blocknum,
4148       { "File Block Number", "dnp3.al.file.blocknum",
4149           FT_UINT32, BASE_HEX, NULL, 0x7fffffff,
4150           NULL, HFILL }
4151     },
4152 
4153     { &hf_dnp3_al_file_lastblock,
4154       { "File Last Block", "dnp3.al.file.lastblock",
4155           FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x80000000,
4156           NULL, HFILL }
4157     },
4158 
4159     { &hf_dnp3_al_file_data,
4160       { "File Data", "dnp3.al.file.data",
4161           FT_BYTES, BASE_NONE, NULL, 0x0,
4162           NULL, HFILL }
4163     },
4164 
4165     { &hf_dnp3_al_biq_b0,
4166       { "Online", "dnp3.al.biq.b0",
4167           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG0,
4168           NULL, HFILL }
4169     },
4170 
4171     { &hf_dnp3_al_biq_b1,
4172       { "Restart", "dnp3.al.biq.b1",
4173           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG1,
4174           NULL, HFILL }
4175     },
4176 
4177     { &hf_dnp3_al_biq_b2,
4178       { "Comm Fail", "dnp3.al.biq.b2",
4179           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG2,
4180           NULL, HFILL }
4181     },
4182 
4183     { &hf_dnp3_al_biq_b3,
4184       { "Remote Force", "dnp3.al.biq.b3",
4185           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG3,
4186           NULL, HFILL }
4187     },
4188 
4189     { &hf_dnp3_al_biq_b4,
4190       { "Local Force", "dnp3.al.biq.b4",
4191           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG4,
4192           NULL, HFILL }
4193     },
4194 
4195     { &hf_dnp3_al_biq_b5,
4196       { "Chatter Filter", "dnp3.al.biq.b5",
4197           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG5,
4198           NULL, HFILL }
4199     },
4200 
4201     { &hf_dnp3_al_biq_b6,
4202       { "Reserved", "dnp3.al.biq.b6",
4203           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG6,
4204           NULL, HFILL }
4205     },
4206 
4207     { &hf_dnp3_al_biq_b7,
4208       { "Point Value", "dnp3.al.biq.b7",
4209           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG7,
4210           NULL, HFILL }
4211     },
4212 
4213     { &hf_dnp3_al_boq_b0,
4214       { "Online", "dnp3.al.boq.b0",
4215           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG0,
4216           NULL, HFILL }
4217     },
4218 
4219     { &hf_dnp3_al_boq_b1,
4220       { "Restart", "dnp3.al.boq.b1",
4221           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG1,
4222           NULL, HFILL }
4223     },
4224 
4225     { &hf_dnp3_al_boq_b2,
4226       { "Comm Fail", "dnp3.al.boq.b2",
4227           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG2,
4228           NULL, HFILL }
4229     },
4230 
4231     { &hf_dnp3_al_boq_b3,
4232       { "Remote Force", "dnp3.al.boq.b3",
4233           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG3,
4234           NULL, HFILL }
4235     },
4236 
4237     { &hf_dnp3_al_boq_b4,
4238       { "Local Force", "dnp3.al.boq.b4",
4239           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG4,
4240           NULL, HFILL }
4241     },
4242 
4243     { &hf_dnp3_al_boq_b5,
4244       { "Reserved", "dnp3.al.boq.b5",
4245           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG5,
4246           NULL, HFILL }
4247     },
4248 
4249     { &hf_dnp3_al_boq_b6,
4250       { "Reserved", "dnp3.al.boq.b6",
4251           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG6,
4252           NULL, HFILL }
4253     },
4254 
4255     { &hf_dnp3_al_boq_b7,
4256       { "Point Value", "dnp3.al.boq.b7",
4257           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG7,
4258           NULL, HFILL }
4259     },
4260 
4261     { &hf_dnp3_al_ctrq_b0,
4262       { "Online", "dnp3.al.ctrq.b0",
4263           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG0,
4264           NULL, HFILL }
4265     },
4266 
4267     { &hf_dnp3_al_ctrq_b1,
4268       { "Restart", "dnp3.al.ctrq.b1",
4269           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG1,
4270           NULL, HFILL }
4271     },
4272 
4273     { &hf_dnp3_al_ctrq_b2,
4274       { "Comm Fail", "dnp3.al.ctrq.b2",
4275           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG2,
4276           NULL, HFILL }
4277     },
4278 
4279     { &hf_dnp3_al_ctrq_b3,
4280       { "Remote Force", "dnp3.al.ctrq.b3",
4281           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG3,
4282           NULL, HFILL }
4283     },
4284 
4285     { &hf_dnp3_al_ctrq_b4,
4286       { "Local Force", "dnp3.al.ctrq.b4",
4287           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG4,
4288           NULL, HFILL }
4289     },
4290 
4291     { &hf_dnp3_al_ctrq_b5,
4292       { "Roll-Over", "dnp3.al.ctrq.b5",
4293           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG5,
4294           NULL, HFILL }
4295     },
4296 
4297     { &hf_dnp3_al_ctrq_b6,
4298       { "Discontinuity", "dnp3.al.ctrq.b6",
4299           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG6,
4300           NULL, HFILL }
4301     },
4302 
4303     { &hf_dnp3_al_ctrq_b7,
4304       { "Reserved", "dnp3.al.ctrq.b7",
4305           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG7,
4306           NULL, HFILL }
4307     },
4308 
4309     { &hf_dnp3_al_aiq_b0,
4310       { "Online", "dnp3.al.aiq.b0",
4311           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG0,
4312           NULL, HFILL }
4313     },
4314 
4315     { &hf_dnp3_al_aiq_b1,
4316       { "Restart", "dnp3.al.aiq.b1",
4317           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG1,
4318           NULL, HFILL }
4319     },
4320 
4321     { &hf_dnp3_al_aiq_b2,
4322       { "Comm Fail", "dnp3.al.aiq.b2",
4323           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG2,
4324           NULL, HFILL }
4325     },
4326 
4327     { &hf_dnp3_al_aiq_b3,
4328       { "Remote Force", "dnp3.al.aiq.b3",
4329           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG3,
4330           NULL, HFILL }
4331     },
4332 
4333     { &hf_dnp3_al_aiq_b4,
4334       { "Local Force", "dnp3.al.aiq.b4",
4335           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG4,
4336           NULL, HFILL }
4337     },
4338 
4339     { &hf_dnp3_al_aiq_b5,
4340       { "Over-Range", "dnp3.al.aiq.b5",
4341           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG5,
4342           NULL, HFILL }
4343     },
4344 
4345     { &hf_dnp3_al_aiq_b6,
4346       { "Reference Check", "dnp3.al.aiq.b6",
4347           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG6,
4348           NULL, HFILL }
4349     },
4350 
4351     { &hf_dnp3_al_aiq_b7,
4352       { "Reserved", "dnp3.al.aiq.b7",
4353           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG7,
4354           NULL, HFILL }
4355     },
4356 
4357     { &hf_dnp3_al_aoq_b0,
4358       { "Online", "dnp3.al.aoq.b0",
4359           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG0,
4360           NULL, HFILL }
4361     },
4362 
4363     { &hf_dnp3_al_aoq_b1,
4364       { "Restart", "dnp3.al.aoq.b1",
4365           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG1,
4366           NULL, HFILL }
4367     },
4368 
4369     { &hf_dnp3_al_aoq_b2,
4370       { "Comm Fail", "dnp3.al.aoq.b2",
4371           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG2,
4372           NULL, HFILL }
4373     },
4374 
4375     { &hf_dnp3_al_aoq_b3,
4376       { "Remote Force", "dnp3.al.aoq.b3",
4377           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG3,
4378           NULL, HFILL }
4379     },
4380 
4381     { &hf_dnp3_al_aoq_b4,
4382       { "Local Force", "dnp3.al.aoq.b4",
4383           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG4,
4384           NULL, HFILL }
4385     },
4386 
4387     { &hf_dnp3_al_aoq_b5,
4388       { "Reserved", "dnp3.al.aoq.b5",
4389           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG5,
4390           NULL, HFILL }
4391     },
4392 
4393     { &hf_dnp3_al_aoq_b6,
4394       { "Reserved", "dnp3.al.aoq.b6",
4395           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG6,
4396           NULL, HFILL }
4397     },
4398 
4399     { &hf_dnp3_al_aoq_b7,
4400       { "Reserved", "dnp3.al.aoq.b7",
4401           FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG7,
4402           NULL, HFILL }
4403     },
4404 
4405     { &hf_dnp3_al_timestamp,
4406       { "Timestamp", "dnp3.al.timestamp",
4407           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
4408           "Object Timestamp", HFILL }
4409     },
4410 
4411     { &hf_dnp3_al_file_perms,
4412       { "Permissions", "dnp3.al.file.perms",
4413           FT_UINT16, BASE_OCT, NULL, 0x0,
4414           NULL, HFILL }
4415     },
4416 
4417     { &hf_dnp3_al_file_perms_read_owner,
4418       { "Read permission for owner", "dnp3.al.file.perms.read_owner",
4419           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0400,
4420           NULL, HFILL }
4421     },
4422 
4423     { &hf_dnp3_al_file_perms_write_owner,
4424       { "Write permission for owner", "dnp3.al.file.perms.write_owner",
4425           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0200,
4426           NULL, HFILL }
4427     },
4428 
4429     { &hf_dnp3_al_file_perms_exec_owner,
4430       { "Execute permission for owner", "dnp3.al.file.perms.exec_owner",
4431           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0100,
4432           NULL, HFILL }
4433     },
4434 
4435     { &hf_dnp3_al_file_perms_read_group,
4436       { "Read permission for group", "dnp3.al.file.perms.read_group",
4437           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 040,
4438           NULL, HFILL }
4439     },
4440 
4441     { &hf_dnp3_al_file_perms_write_group,
4442       { "Write permission for group", "dnp3.al.file.perms.write_group",
4443           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 020,
4444           NULL, HFILL }
4445     },
4446 
4447     { &hf_dnp3_al_file_perms_exec_group,
4448       { "Execute permission for group", "dnp3.al.file.perms.exec_group",
4449           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 010,
4450           NULL, HFILL }
4451     },
4452 
4453     { &hf_dnp3_al_file_perms_read_world,
4454       { "Read permission for world", "dnp3.al.file.perms.read_world",
4455           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 04,
4456           NULL, HFILL }
4457     },
4458 
4459     { &hf_dnp3_al_file_perms_write_world,
4460       { "Write permission for world", "dnp3.al.file.perms.write_world",
4461           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 02,
4462           NULL, HFILL }
4463     },
4464 
4465     { &hf_dnp3_al_file_perms_exec_world,
4466       { "Execute permission for world", "dnp3.al.file.perms.exec_world",
4467           FT_BOOLEAN, 16, TFS(&tfs_yes_no), 01,
4468           NULL, HFILL }
4469     },
4470 
4471     { &hf_dnp3_al_rel_timestamp,
4472       { "Relative Timestamp", "dnp3.al.reltimestamp",
4473           FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
4474           "Object Relative Timestamp", HFILL }
4475     },
4476 
4477     { &hf_dnp3_al_datatype,
4478       { "Data Type", "dnp3.al.datatype",
4479           FT_UINT8, BASE_HEX, VALS(dnp3_al_data_type_vals), 0,
4480           NULL, HFILL }
4481     },
4482 
4483     { &hf_dnp3_al_da_length,
4484       { "Device Attribute Length", "dnp3.al.da.length",
4485           FT_UINT8, BASE_DEC, NULL, 0,
4486           NULL, HFILL }
4487     },
4488 
4489     { &hf_dnp3_al_da_uint8,
4490       { "Device Attribute 8-Bit Unsigned Integer Value", "dnp3.al.da.uint8",
4491           FT_UINT8, BASE_DEC, NULL, 0,
4492           NULL, HFILL }
4493     },
4494 
4495     { &hf_dnp3_al_da_uint16,
4496       { "Device Attribute 16-Bit Unsigned Integer Value", "dnp3.al.da.uint16",
4497           FT_UINT16, BASE_DEC, NULL, 0,
4498           NULL, HFILL }
4499     },
4500 
4501     { &hf_dnp3_al_da_uint32,
4502       { "Device Attribute 32-Bit Unsigned Integer Value", "dnp3.al.da.uint32",
4503           FT_UINT32, BASE_DEC, NULL, 0,
4504           NULL, HFILL }
4505     },
4506 
4507     { &hf_dnp3_al_da_int8,
4508       { "Device Attribute 8-Bit Integer Value", "dnp3.al.da.int8",
4509           FT_INT8, BASE_DEC, NULL, 0,
4510           NULL, HFILL }
4511     },
4512 
4513     { &hf_dnp3_al_da_int16,
4514       { "Device Attribute 16-Bit Integer Value", "dnp3.al.da.int16",
4515           FT_INT16, BASE_DEC, NULL, 0,
4516           NULL, HFILL }
4517     },
4518 
4519     { &hf_dnp3_al_da_int32,
4520       { "Device Attribute 32-Bit Integer Value", "dnp3.al.da.int32",
4521           FT_INT32, BASE_DEC, NULL, 0,
4522           NULL, HFILL }
4523     },
4524 
4525     { &hf_dnp3_al_da_flt,
4526       { "Device Attribute Float Value", "dnp3.al.da.float",
4527           FT_FLOAT, BASE_NONE, NULL, 0,
4528           NULL, HFILL }
4529     },
4530 
4531     { &hf_dnp3_al_da_dbl,
4532       { "Device Attribute Double Value", "dnp3.al.da.double",
4533           FT_DOUBLE, BASE_NONE, NULL, 0,
4534           NULL, HFILL }
4535     },
4536 
4537     { &hf_al_frag_data,
4538       {"DNP3.0 AL Fragment Data", "dnp3.al.frag_data",
4539           FT_BYTES, BASE_NONE, NULL, 0x00,
4540           "DNP 3.0 Application Layer Fragment Data", HFILL }},
4541 
4542     { &hf_dnp3_fragment,
4543       { "DNP 3.0 AL Fragment", "dnp3.al.fragment",
4544           FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4545           "DNP 3.0 Application Layer Fragment", HFILL }
4546     },
4547 
4548     { &hf_dnp3_fragments,
4549       { "DNP 3.0 AL Fragments", "dnp3.al.fragments",
4550           FT_NONE, BASE_NONE, NULL, 0x0,
4551           "DNP 3.0 Application Layer Fragments", HFILL }
4552     },
4553 
4554     { &hf_dnp3_fragment_overlap,
4555       { "Fragment overlap", "dnp3.al.fragment.overlap",
4556           FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4557           "Fragment overlaps with other fragments", HFILL }
4558     },
4559 
4560     { &hf_dnp3_fragment_overlap_conflict,
4561       { "Conflicting data in fragment overlap", "dnp3.al.fragment.overlap.conflict",
4562           FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4563           "Overlapping fragments contained conflicting data", HFILL }
4564     },
4565 
4566     { &hf_dnp3_fragment_multiple_tails,
4567       { "Multiple tail fragments found", "dnp3.al.fragment.multipletails",
4568           FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4569           "Several tails were found when defragmenting the packet", HFILL }
4570     },
4571 
4572     { &hf_dnp3_fragment_too_long_fragment,
4573       { "Fragment too long", "dnp3.al.fragment.toolongfragment",
4574           FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4575           "Fragment contained data past end of packet", HFILL }
4576     },
4577 
4578     { &hf_dnp3_fragment_error,
4579       { "Defragmentation error", "dnp3.al.fragment.error",
4580         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4581         "Defragmentation error due to illegal fragments", HFILL }
4582     },
4583 
4584     { &hf_dnp3_fragment_count,
4585       { "Fragment count", "dnp3.al.fragment.count",
4586         FT_UINT32, BASE_DEC, NULL, 0x0,
4587         NULL, HFILL }
4588     },
4589 
4590     { &hf_dnp3_fragment_reassembled_in,
4591       { "Reassembled PDU In Frame", "dnp3.al.fragment.reassembled_in",
4592         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4593         "This PDU is reassembled in this frame", HFILL }
4594     },
4595 
4596     { &hf_dnp3_fragment_reassembled_length,
4597       { "Reassembled DNP length", "dnp3.al.fragment.reassembled.length",
4598         FT_UINT32, BASE_DEC, NULL, 0x0,
4599         "The total length of the reassembled payload", HFILL }
4600     },
4601     /* Generated from convert_proto_tree_add_text.pl */
4602     { &hf_dnp3_al_point_index, { "Point Index", "dnp3.al.point_index", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4603     { &hf_dnp3_al_da_value, { "Value", "dnp3.al.da.value", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4604     { &hf_dnp3_al_count, { "Count", "dnp3.al.count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4605     { &hf_dnp3_al_on_time, { "On Time", "dnp3.al.on_time", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4606     { &hf_dnp3_al_off_time, { "Off Time", "dnp3.al.off_time", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4607     { &hf_dnp3_al_time_delay, { "Time Delay", "dnp3.al.time_delay", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &units_milliseconds, 0x0, NULL, HFILL }},
4608     { &hf_dnp3_al_file_string_offset, { "File String Offset", "dnp3.al.file_string_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4609     { &hf_dnp3_al_file_string_length, { "File String Length", "dnp3.al.file_string_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
4610     { &hf_dnp3_al_file_name, { "File Name", "dnp3.al.file_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4611     { &hf_dnp3_al_octet_string, { "Octet String", "dnp3.al.octet_string", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4612     { &hf_dnp3_unknown_data_chunk, { "Unknown Data Chunk", "dnp3.al.unknown_data_chunk", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4613 
4614   };
4615 
4616 /* Setup protocol subtree array */
4617   static gint *ett[] = {
4618     &ett_dnp3,
4619     &ett_dnp3_dl,
4620     &ett_dnp3_dl_ctl,
4621     &ett_dnp3_tr_ctl,
4622     &ett_dnp3_dl_data,
4623     &ett_dnp3_dl_chunk,
4624     &ett_dnp3_al,
4625     &ett_dnp3_al_ctl,
4626     &ett_dnp3_al_obj_point_tcc,
4627     &ett_dnp3_al_iin,
4628     &ett_dnp3_al_obj,
4629     &ett_dnp3_al_obj_qualifier,
4630     &ett_dnp3_al_obj_range,
4631     &ett_dnp3_al_objdet,
4632     &ett_dnp3_al_obj_quality,
4633     &ett_dnp3_al_obj_point,
4634     &ett_dnp3_al_obj_point_perms,
4635     &ett_dnp3_fragment,
4636     &ett_dnp3_fragments
4637   };
4638   static ei_register_info ei[] = {
4639      { &ei_dnp_num_items_neg, { "dnp3.num_items_neg", PI_MALFORMED, PI_ERROR, "Negative number of items", EXPFILL }},
4640      { &ei_dnp_invalid_length, { "dnp3.invalid_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
4641      { &ei_dnp_iin_abnormal, { "dnp3.iin_abnormal", PI_PROTOCOL, PI_WARN, "IIN Abnormality", EXPFILL }},
4642      { &ei_dnp3_data_hdr_crc_incorrect, { "dnp3.hdr.CRC.incorrect", PI_CHECKSUM, PI_WARN, "Data Link Header Checksum incorrect", EXPFILL }},
4643      { &ei_dnp3_data_chunk_crc_incorrect, { "dnp3.data_chunk.CRC.incorrect", PI_CHECKSUM, PI_WARN, "Data Chunk Checksum incorrect", EXPFILL }},
4644      { &ei_dnp3_unknown_object, { "dnp3.unknown_object", PI_PROTOCOL, PI_WARN, "Unknown Object\\Variation", EXPFILL }},
4645      { &ei_dnp3_unknown_group0_variation, { "dnp3.unknown_group0_variation", PI_PROTOCOL, PI_WARN, "Unknown Group 0 Variation", EXPFILL }},
4646      { &ei_dnp3_num_items_invalid, { "dnp3.num_items_invalid", PI_MALFORMED, PI_ERROR, "Number of items is invalid for normally empty object.  Potentially malicious packet", EXPFILL }},
4647       /* Generated from convert_proto_tree_add_text.pl */
4648 #if 0
4649       { &ei_dnp3_buffering_user_data_until_final_frame_is_received, { "dnp3.buffering_user_data_until_final_frame_is_received", PI_PROTOCOL, PI_WARN, "Buffering User Data Until Final Frame is Received..", EXPFILL }},
4650 #endif
4651     };
4652 
4653   module_t *dnp3_module;
4654   expert_module_t* expert_dnp3;
4655 
4656   reassembly_table_register(&al_reassembly_table,
4657                         &addresses_reassembly_table_functions);
4658 
4659 /* Register the protocol name and description */
4660   proto_dnp3 = proto_register_protocol("Distributed Network Protocol 3.0", "DNP 3.0", "dnp3");
4661 
4662 /* Register the dissector so it may be used as a User DLT payload protocol */
4663   dnp3_tcp_handle = register_dissector("dnp3.tcp", dissect_dnp3_tcp, proto_dnp3);
4664   dnp3_udp_handle = register_dissector("dnp3.udp", dissect_dnp3_udp, proto_dnp3);
4665 
4666 /* Required function calls to register the header fields and subtrees used */
4667   proto_register_field_array(proto_dnp3, hf, array_length(hf));
4668   proto_register_subtree_array(ett, array_length(ett));
4669   expert_dnp3 = expert_register_protocol(proto_dnp3);
4670   expert_register_field_array(expert_dnp3, ei, array_length(ei));
4671 
4672   dnp3_module = prefs_register_protocol(proto_dnp3, NULL);
4673   prefs_register_obsolete_preference(dnp3_module, "heuristics");
4674   prefs_register_bool_preference(dnp3_module, "desegment",
4675     "Reassemble DNP3 messages spanning multiple TCP segments",
4676     "Whether the DNP3 dissector should reassemble messages spanning multiple TCP segments."
4677     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4678     &dnp3_desegment);
4679 }
4680 
4681 void
proto_reg_handoff_dnp3(void)4682 proto_reg_handoff_dnp3(void)
4683 {
4684   /* register as heuristic dissector for both TCP and UDP */
4685   heur_dissector_add("tcp", dissect_dnp3_tcp_heur, "DNP 3.0 over TCP", "dnp3_tcp", proto_dnp3, HEURISTIC_DISABLE);
4686   heur_dissector_add("udp", dissect_dnp3_udp_heur, "DNP 3.0 over UDP", "dnp3_udp", proto_dnp3, HEURISTIC_DISABLE);
4687 
4688   dissector_add_uint_with_preference("tcp.port", TCP_PORT_DNP, dnp3_tcp_handle);
4689   dissector_add_uint_with_preference("udp.port", UDP_PORT_DNP, dnp3_udp_handle);
4690   dissector_add_for_decode_as("rtacser.data", dnp3_udp_handle);
4691 
4692   ssl_dissector_add(TCP_PORT_DNP_TLS, dnp3_tcp_handle);
4693 }
4694 
4695 /*
4696  * Editor modelines
4697  *
4698  * Local Variables:
4699  * c-basic-offset: 2
4700  * tab-width: 8
4701  * indent-tabs-mode: nil
4702  * End:
4703  *
4704  * ex: set shiftwidth=2 tabstop=8 expandtab:
4705  * :indentSize=2:tabSize=8:noTabs=true:
4706  */
4707 
4708