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