HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-dnp.c
blob97d72dfbf28c8b1964a1feddf33526711441a82b
1 /* packet-dnp.c
2 * Routines for DNP dissection
3 * Copyright 2003, 2006, 2007, 2013 Graham Bloice <graham.bloice<at>trihedral.com>
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
9 * Major updates: tcp and application layer defragmentation, more object dissections by Graham Bloice
11 * $Id$
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include "config.h"
34 #include <string.h>
35 #include <math.h>
37 #include <glib.h>
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
41 #include <epan/reassemble.h>
42 #include <epan/wmem/wmem.h>
43 #include <epan/dissectors/packet-tcp.h>
44 #include <epan/conversation.h>
45 #include <epan/expert.h>
48 * See
50 * http://www.dnp.org/
52 * although note that you have to join the DNP organization to get to
53 * see the protocol specs online - otherwise, you have to buy a
54 * dead-tree version.
56 * ...Application Layer Notes...
58 * Application Layer Decoding based on information available in
59 * DNP3 Basic 4 Documentation Set, specifically the document:
60 * "DNP V3.00 Application Layer" v0.03 P009-0PD.APP & Technical Bulletins
62 * ---------------------------------------------------------------------------
64 * Several command codes were missing, causing the dissector to abort decoding
65 * on valid packets. Those commands have been added.
67 * The semantics of Variation 0 have been cleaned up. Variation 0 is the
68 * "Default Variation". It is used only in Master -> Slave read commands
69 * to request the data in whatever variation the Slave is configured to use by
70 * default. Decoder strings have been added to the Binary Output and
71 * Analog Output objects (10 and 40) so that group read commands will
72 * decode properly.
74 * Roy M. Silvernail <roy@rant-central.com> 01/05/2009
78 /***************************************************************************/
79 /* DNP 3.0 Constants */
80 /***************************************************************************/
81 #define DNP_HDR_LEN 10
82 #define TCP_PORT_DNP 20000
83 #define UDP_PORT_DNP 20000
85 /***************************************************************************/
86 /* Datalink and Transport Layer Bit-Masks */
87 /***************************************************************************/
88 #define DNP3_CTL_DIR 0x80
89 #define DNP3_CTL_PRM 0x40
90 #define DNP3_CTL_FCB 0x20
91 #define DNP3_CTL_FCV 0x10
92 #define DNP3_CTL_RES 0x20
93 #define DNP3_CTL_DFC 0x10
94 #define DNP3_CTL_FUNC 0x0f
96 #define DNP3_TR_FIR 0x40
97 #define DNP3_TR_FIN 0x80
98 #define DNP3_TR_SEQ 0x3f
100 #define AL_MAX_CHUNK_SIZE 16
102 /***************************************************************************/
103 /* Data Link Function codes */
104 /***************************************************************************/
105 /* Primary to Secondary */
106 #define DL_FUNC_RESET_LINK 0x00
107 #define DL_FUNC_RESET_PROC 0x01
108 #define DL_FUNC_TEST_LINK 0x02
109 #define DL_FUNC_USER_DATA 0x03
110 #define DL_FUNC_UNC_DATA 0x04
111 #define DL_FUNC_LINK_STAT 0x09
113 /* Secondary to Primary */
114 #define DL_FUNC_ACK 0x00
115 #define DL_FUNC_NACK 0x01
116 #define DL_FUNC_STAT_LINK 0x0B
117 #define DL_FUNC_NO_FUNC 0x0E
118 #define DL_FUNC_NOT_IMPL 0x0F
120 /***************************************************************************/
121 /* Application Layer Bit-Masks */
122 /***************************************************************************/
123 #define DNP3_AL_UNS 0x10
124 #define DNP3_AL_CON 0x20
125 #define DNP3_AL_FIN 0x40
126 #define DNP3_AL_FIR 0x80
127 #define DNP3_AL_SEQ 0x0f
128 #define DNP3_AL_FUNC 0xff
130 /***************************************************************************/
131 /* Application Layer Function codes */
132 /***************************************************************************/
133 #define AL_FUNC_CONFIRM 0x00 /* 00 - Confirm */
134 #define AL_FUNC_READ 0x01 /* 01 - Read */
135 #define AL_FUNC_WRITE 0x02 /* 02 - Write */
136 #define AL_FUNC_SELECT 0x03 /* 03 - Select */
137 #define AL_FUNC_OPERATE 0x04 /* 04 - Operate */
138 #define AL_FUNC_DIROP 0x05 /* 05 - Direct Operate */
139 #define AL_FUNC_DIROPNACK 0x06 /* 06 - Direct Operate No ACK */
140 #define AL_FUNC_FRZ 0x07 /* 07 - Immediate Freeze */
141 #define AL_FUNC_FRZNACK 0x08 /* 08 - Immediate Freeze No ACK */
142 #define AL_FUNC_FRZCLR 0x09 /* 09 - Freeze and Clear */
143 #define AL_FUNC_FRZCLRNACK 0x0A /* 10 - Freeze and Clear No ACK */
144 #define AL_FUNC_FRZT 0x0B /* 11 - Freeze With Time */
145 #define AL_FUNC_FRZTNACK 0x0C /* 12 - Freeze With Time No ACK */
146 #define AL_FUNC_COLDRST 0x0D /* 13 - Cold Restart */
147 #define AL_FUNC_WARMRST 0x0E /* 14 - Warm Restart */
148 #define AL_FUNC_INITDATA 0x0F /* 15 - Initialize Data */
149 #define AL_FUNC_INITAPP 0x10 /* 16 - Initialize Application */
150 #define AL_FUNC_STARTAPP 0x11 /* 17 - Start Application */
151 #define AL_FUNC_STOPAPP 0x12 /* 18 - Stop Application */
152 #define AL_FUNC_SAVECFG 0x13 /* 19 - Save Configuration */
153 #define AL_FUNC_ENSPMSG 0x14 /* 20 - Enable Spontaneous Msg */
154 #define AL_FUNC_DISSPMSG 0x15 /* 21 - Disable Spontaneous Msg */
155 #define AL_FUNC_ASSIGNCL 0x16 /* 22 - Assign Classes */
156 #define AL_FUNC_DELAYMST 0x17 /* 23 - Delay Measurement */
157 #define AL_FUNC_RECCT 0x18 /* 24 - Record Current Time */
158 #define AL_FUNC_OPENFILE 0x19 /* 25 - Open File */
159 #define AL_FUNC_CLOSEFILE 0x1A /* 26 - Close File */
160 #define AL_FUNC_DELETEFILE 0x1B /* 27 - Delete File */
161 #define AL_FUNC_GETFILEINF 0x1C /* 28 - Get File Info */
162 #define AL_FUNC_AUTHFILE 0x1D /* 29 - Authenticate File */
163 #define AL_FUNC_ABORTFILE 0x1E /* 30 - Abort File */
164 #define AL_FUNC_ACTCNF 0x1F /* 31 - Activate Config */
165 #define AL_FUNC_AUTHREQ 0x20 /* 32 - Authentication Request */
166 #define AL_FUNC_AUTHERR 0x21 /* 33 - Authentication Error */
167 #define AL_FUNC_RESPON 0x81 /* 129 - Response */
168 #define AL_FUNC_UNSOLI 0x82 /* 130 - Unsolicited Response */
169 #define AL_FUNC_AUTHRESP 0x83 /* 131 - Authentication Response */
171 /***************************************************************************/
172 /* Application Layer Internal Indication (IIN) bits */
173 /* 2 Bytes, message formatting: [First Octet] | [Second Octet] */
174 /***************************************************************************/
175 /* Octet 1 */
176 #define AL_IIN_BMSG 0x0100 /* Bit 0 - Broadcast message rx'd */
177 #define AL_IIN_CLS1D 0x0200 /* Bit 1 - Class 1 Data Available */
178 #define AL_IIN_CLS2D 0x0400 /* Bit 2 - Class 2 Data Available */
179 #define AL_IIN_CLS3D 0x0800 /* Bit 3 - Class 3 Data Available */
180 #define AL_IIN_TSR 0x1000 /* Bit 4 - Time Sync Req'd from Master */
181 #define AL_IIN_DOL 0x2000 /* Bit 5 - Outputs in Local Mode */
182 #define AL_IIN_DT 0x4000 /* Bit 6 - Device Trouble */
183 #define AL_IIN_RST 0x8000 /* Bit 7 - Device Restart */
185 /* Octet 2 */
186 #define AL_IIN_FCNI 0x0001 /* Bit 0 - Function code not implemented */
187 #define AL_IIN_OBJU 0x0002 /* Bit 1 - Requested Objects Unknown */
188 #define AL_IIN_PIOOR 0x0004 /* Bit 2 - Parameters Invalid or Out of Range */
189 #define AL_IIN_EBO 0x0008 /* Bit 3 - Event Buffer Overflow */
190 #define AL_IIN_OAE 0x0010 /* Bit 4 - Operation Already Executing */
191 #define AL_IIN_CC 0x0020 /* Bit 5 - Device Configuration Corrupt */
192 /* 0x0040 Bit 6 - Reserved */
193 /* 0x0080 Bit 7 - Reserved */
195 /***************************************************************************/
196 /* Application Layer Data Object Qualifier */
197 /***************************************************************************/
198 /* Bit-Masks */
199 #define AL_OBJQ_INDEX 0x70 /* x111xxxx Masks Index from Qualifier */
200 #define AL_OBJQ_CODE 0x0F /* xxxx1111 Masks Code from Qualifier */
202 /* Index Size (3-bits x111xxxx) */
203 /* When Qualifier Code != 11 */
204 #define AL_OBJQL_IDX_NI 0x00 /* Objects are Packed with no index */
205 #define AL_OBJQL_IDX_1O 0x01 /* Objects are prefixed w/ 1-octet index */
206 #define AL_OBJQL_IDX_2O 0x02 /* Objects are prefixed w/ 2-octet index */
207 #define AL_OBJQL_IDX_4O 0x03 /* Objects are prefixed w/ 4-octet index */
208 #define AL_OBJQL_IDX_1OS 0x04 /* Objects are prefixed w/ 1-octet object size */
209 #define AL_OBJQL_IDX_2OS 0x05 /* Objects are prefixed w/ 2-octet object size */
210 #define AL_OBJQL_IDX_4OS 0x06 /* Objects are prefixed w/ 4-octet object size */
212 /* When Qualifier Code == 11 */
213 #define AL_OBJQL_IDX11_1OIS 0x01 /* 1 octet identifier size */
214 #define AL_OBJQL_IDX11_2OIS 0x02 /* 2 octet identifier size */
215 #define AL_OBJQL_IDX11_4OIS 0x03 /* 4 octet identifier size */
217 /* Qualifier Code (4-bits) */
218 /* 4-bits ( xxxx1111 ) */
219 #define AL_OBJQL_CODE_SSI8 0x00 /* 00 8-bit Start and Stop Indices in Range Field */
220 #define AL_OBJQL_CODE_SSI16 0x01 /* 01 16-bit Start and Stop Indices in Range Field */
221 #define AL_OBJQL_CODE_SSI32 0x02 /* 02 32-bit Start and Stop Indices in Range Field */
222 #define AL_OBJQL_CODE_AA8 0x03 /* 03 8-bit Absolute Address in Range Field */
223 #define AL_OBJQL_CODE_AA16 0x04 /* 04 16-bit Absolute Address in Range Field */
224 #define AL_OBJQL_CODE_AA32 0x05 /* 05 32-bit Absolute Address in Range Field */
225 #define AL_OBJQL_CODE_R0 0x06 /* 06 Length of Range field is 0 (no range field) */
226 #define AL_OBJQL_CODE_SF8 0x07 /* 07 8-bit Single Field Quantity */
227 #define AL_OBJQL_CODE_SF16 0x08 /* 08 16-bit Single Field Quantity */
228 #define AL_OBJQL_CODE_SF32 0x09 /* 09 32-bit Single Field Quantity */
229 /* 0x0A 10 Reserved */
230 #define AL_OBJQL_CODE_FF 0x0B /* 11 Free-format Qualifier, range field has 1 octet count of objects */
231 /* 0x0C 12 Reserved */
232 /* 0x0D 13 Reserved */
233 /* 0x0E 14 Reserved */
234 /* 0x0F 15 Reserved */
236 /***************************************************************************/
237 /* Application Layer Data Object Definitions */
238 /***************************************************************************/
239 /* Device Attributes */
240 #define AL_OBJ_DA_GRP 0x0000 /* 00 00 Device Attributes Group and null variation */
241 #define AL_OBJ_DA_USR_ATTR 0x00D3 /* 00 211 Device Attributes - Identifier of support for user-specific attributes */
242 #define AL_OBJ_DA_MSTR_DSP 0x00D4 /* 00 212 Device Attributes - Number of master-defined data set prototypes */
243 #define AL_OBJ_DA_OS_DSP 0x00D5 /* 00 213 Device Attributes - Number of outstation-defined data set prototypes */
244 #define AL_OBJ_DA_MSTR_DS 0x00D6 /* 00 214 Device Attributes - Number of master-defined data sets */
245 #define AL_OBJ_DA_OS_DS 0x00D7 /* 00 215 Device Attributes - Number of outstation-defined data sets */
246 #define AL_OBJ_DA_BO_REQ 0x00D8 /* 00 216 Device Attributes - Max number of binary outputs per request */
247 #define AL_OBJ_DA_LOC_TA 0x00D9 /* 00 217 Device Attributes - Local timing accuracy */
248 #define AL_OBJ_DA_DUR_TA 0x00DA /* 00 218 Device Attributes - Duration of timing accuraccy */
249 #define AL_OBJ_DA_AO_EVT 0x00DB /* 00 219 Device Attributes - Support for analog output events */
250 #define AL_OBJ_DA_MAX_AO 0x00DC /* 00 220 Device Attributes - Max analog output index */
251 #define AL_OBJ_DA_NUM_AO 0x00DD /* 00 221 Device Attributes - Number of analog outputs */
252 #define AL_OBJ_DA_BO_EVT 0x00DE /* 00 222 Device Attributes - Support for binary output events */
253 #define AL_OBJ_DA_MAX_BO 0x00DF /* 00 223 Device Attributes - Max binary output index */
254 #define AL_OBJ_DA_NUM_BO 0x00E0 /* 00 224 Device Attributes - Number of binary outputs */
255 #define AL_OBJ_DA_FCTR_EVT 0x00E1 /* 00 225 Device Attributes - Support for frozen counter events */
256 #define AL_OBJ_DA_FCTR 0x00E2 /* 00 226 Device Attributes - Support for frozen counters */
257 #define AL_OBJ_DA_CTR_EVT 0x00E3 /* 00 227 Device Attributes - Support for counter events */
258 #define AL_OBJ_DA_MAX_CTR 0x00E4 /* 00 228 Device Attributes - Max counter index */
259 #define AL_OBJ_DA_NUM_CTR 0x00E5 /* 00 229 Device Attributes - Number of counter points */
260 #define AL_OBJ_DA_AIF 0x00E6 /* 00 230 Device Attributes - Support for frozen analog inputs */
261 #define AL_OBJ_DA_AI_EVT 0x00E7 /* 00 231 Device Attributes - Support for analog input events */
262 #define AL_OBJ_DA_MAX_AI 0x00E8 /* 00 232 Device Attributes - Maximum analog input index */
263 #define AL_OBJ_DA_NUM_AI 0x00E9 /* 00 233 Device Attributes - Number of analog input points */
264 #define AL_OBJ_DA_2BI_EVT 0x00EA /* 00 234 Device Attributes - Support for Double-Bit BI Events */
265 #define AL_OBJ_DA_MAX_2BI 0x00EB /* 00 235 Device Attributes - Max Double-bit BI Point Index */
266 #define AL_OBJ_DA_NUM_2BI 0x00EC /* 00 236 Device Attributes - Number of Double-bit BI Points */
267 #define AL_OBJ_DA_BI_EVT 0x00ED /* 00 237 Device Attributes - Support for Binary Input Events */
268 #define AL_OBJ_DA_MAX_BI 0x00EE /* 00 238 Device Attributes - Max Binary Input Point Index */
269 #define AL_OBJ_DA_NUM_BI 0x00EF /* 00 239 Device Attributes - Number of Binary Input Points */
270 #define AL_OBJ_DA_MXTX_FR 0x00F0 /* 00 240 Device Attributes - Maximum Transmit Fragment Size */
271 #define AL_OBJ_DA_MXRX_FR 0x00F1 /* 00 241 Device Attributes - Maximum Receive Fragment Size */
272 #define AL_OBJ_DA_SWVER 0x00F2 /* 00 242 Device Attributes - Device Manufacturers SW Version */
273 #define AL_OBJ_DA_HWVER 0x00F3 /* 00 243 Device Attributes - Device Manufacturers HW Version */
274 /* 00 244 Future Assignment */
275 #define AL_OBJ_DA_LOC 0x00F5 /* 00 245 Device Attributes - User-Assigned Location */
276 #define AL_OBJ_DA_ID 0x00F6 /* 00 246 Device Attributes - User-Assigned ID code/number */
277 #define AL_OBJ_DA_DEVNAME 0x00F7 /* 00 247 Device Attributes - User-Assigned Device Name */
278 #define AL_OBJ_DA_SERNUM 0x00F8 /* 00 248 Device Attributes - Device Serial Number */
279 #define AL_OBJ_DA_CONF 0x00F9 /* 00 249 Device Attributes - DNP Subset and Conformance */
280 #define AL_OBJ_DA_PROD 0x00FA /* 00 250 Device Attributes - Device Product Name and Model */
281 /* 00 251 Future Assignment */
282 #define AL_OBJ_DA_MFG 0x00FC /* 00 252 Device Attributes - Device Manufacturers Name */
283 /* 00 253 Future Assignment */
284 #define AL_OBJ_DA_ALL 0x00FE /* 00 254 Device Attributes - Non-specific All-attributes Req */
285 #define AL_OBJ_DA_LVAR 0x00FF /* 00 255 Device Attributes - List of Attribute Variations */
287 /* Binary Input Objects */
288 #define AL_OBJ_BI_ALL 0x0100 /* 01 00 Binary Input Default Variation */
289 #define AL_OBJ_BI_1BIT 0x0101 /* 01 01 Single-bit Binary Input */
290 #define AL_OBJ_BI_STAT 0x0102 /* 01 02 Binary Input With Status */
291 #define AL_OBJ_BIC_ALL 0x0200 /* 02 00 Binary Input Change Default Variation */
292 #define AL_OBJ_BIC_NOTIME 0x0201 /* 02 01 Binary Input Change Without Time */
293 #define AL_OBJ_BIC_TIME 0x0202 /* 02 02 Binary Input Change With Time */
294 #define AL_OBJ_BIC_RTIME 0x0203 /* 02 03 Binary Input Change With Relative Time */
296 /* Double-bit Input Objects */
297 #define AL_OBJ_2BI_ALL 0x0300 /* 03 00 Double-bit Input Default Variation */
298 #define AL_OBJ_2BI_NF 0x0301 /* 03 01 Double-bit Input No Flags */
299 #define AL_OBJ_2BI_STAT 0x0302 /* 03 02 Double-bit Input With Status */
300 #define AL_OBJ_2BIC_ALL 0x0400 /* 04 00 Double-bit Input Change Default Variation */
301 #define AL_OBJ_2BIC_NOTIME 0x0401 /* 04 01 Double-bit Input Change Without Time */
302 #define AL_OBJ_2BIC_TIME 0x0402 /* 04 02 Double-bit Input Change With Time */
303 #define AL_OBJ_2BIC_RTIME 0x0403 /* 04 03 Double-bit Input Change With Relative Time */
305 /* Binary Input Quality Flags */
306 #define AL_OBJ_BI_FLAG0 0x0001 /* Point Online (0=Offline; 1=Online) */
307 #define AL_OBJ_BI_FLAG1 0x0002 /* Restart (0=Normal; 1=Restart) */
308 #define AL_OBJ_BI_FLAG2 0x0004 /* Comms Lost (0=Normal; 1=Lost) */
309 #define AL_OBJ_BI_FLAG3 0x0008 /* Remote Force (0=Normal; 1=Forced) */
310 #define AL_OBJ_BI_FLAG4 0x0010 /* Local Force (0=Normal; 1=Forced) */
311 #define AL_OBJ_BI_FLAG5 0x0020 /* Chatter Filter (0=Normal; 1=Filter On) */
312 #define AL_OBJ_BI_FLAG6 0x0040 /* Double-bit LSB (0=Off; 1=On) */
313 #define AL_OBJ_BI_FLAG7 0x0080 /* Point State (0=Off; 1=On) or Double-bit MSB */
315 /***************************************************************************/
316 /* Binary Output Objects */
317 #define AL_OBJ_BO_ALL 0x0A00 /* 10 00 Binary Output Default Variation */
318 #define AL_OBJ_BO 0x0A01 /* 10 01 Binary Output */
319 #define AL_OBJ_BO_STAT 0x0A02 /* 10 02 Binary Output Status */
320 #define AL_OBJ_BOC_ALL 0x0B00 /* 11 00 Binary Output Change Default Variation */
321 #define AL_OBJ_BOC_NOTIME 0x0B01 /* 11 01 Binary Output Change Without Time */
322 #define AL_OBJ_BOC_TIME 0x0B02 /* 11 02 Binary Output Change With Time */
323 #define AL_OBJ_CTLOP_BLK 0x0C01 /* 12 01 Control Relay Output Block */
324 /* 0x0C02 12 02 Pattern Control Block */
325 /* 0x0C03 12 03 Pattern Mask */
327 #define AL_OBJCTLC_CODE 0x0F /* Bit-Mask xxxx1111 for Control Code 'Code' */
328 #define AL_OBJCTLC_MISC 0x30 /* Bit-Mask xx11xxxx for Control Code Queue (obsolete) and Clear Fields */
329 #define AL_OBJCTLC_TC 0xC0 /* Bit-Mask 11xxxxxx for Control Code 'Trip/Close' */
331 #define AL_OBJCTLC_CODE0 0x00 /* xxxx0000 NUL Operation; only process R attribute */
332 #define AL_OBJCTLC_CODE1 0x01 /* xxxx0001 Pulse On ^On-Time -> vOff-Time, remain off */
333 #define AL_OBJCTLC_CODE2 0x02 /* xxxx0010 Pulse Off vOff-Time -> ^On-Time, remain on */
334 #define AL_OBJCTLC_CODE3 0x03 /* xxxx0011 Latch On */
335 #define AL_OBJCTLC_CODE4 0x04 /* xxxx0100 Latch Off */
336 /* 0x05-0x15 Reserved */
338 #define AL_OBJCTLC_NOTSET 0x00 /* xx00xxxx for Control Code, Clear and Queue not set */
339 #define AL_OBJCTLC_QUEUE 0x01 /* xxx1xxxx for Control Code, Clear Field 'Queue' */
340 #define AL_OBJCTLC_CLEAR 0x02 /* xx1xxxxx for Control Code, Clear Field 'Clear' */
341 #define AL_OBJCTLC_BOTHSET 0x03 /* xx11xxxx for Control Code, Clear and Queue both set */
343 #define AL_OBJCTLC_TC0 0x00 /* 00xxxxxx NUL */
344 #define AL_OBJCTLC_TC1 0x01 /* 01xxxxxx Close */
345 #define AL_OBJCTLC_TC2 0x02 /* 10xxxxxx Trip */
346 #define AL_OBJCTLC_TC3 0x03 /* 11xxxxxx Reserved */
348 #define AL_OBJCTL_STAT0 0x00 /* Request Accepted, Initiated or Queued */
349 #define AL_OBJCTL_STAT1 0x01 /* Request Not Accepted; Arm-timer expired */
350 #define AL_OBJCTL_STAT2 0x02 /* Request Not Accepted; No 'SELECT' rx'd */
351 #define AL_OBJCTL_STAT3 0x03 /* Request Not Accepted; Format errors in ctrl request */
352 #define AL_OBJCTL_STAT4 0x04 /* Control Operation Not Supported for this point */
353 #define AL_OBJCTL_STAT5 0x05 /* Request Not Accepted; Ctrl Queue full or pt. active */
354 #define AL_OBJCTL_STAT6 0x06 /* Request Not Accepted; Ctrl HW Problems */
355 #define AL_OBJCTL_STAT7 0x07 /* Request Not Accepted; Local/Remote switch in Local*/
356 #define AL_OBJCTL_STAT8 0x08 /* Request Not Accepted; Too many operations requested */
357 #define AL_OBJCTL_STAT9 0x09 /* Request Not Accepted; Insufficient authorization */
358 #define AL_OBJCTL_STAT10 0x0A /* Request Not Accepted; Local automation proc active */
360 /* Binary Output Quality Flags */
361 #define AL_OBJ_BO_FLAG0 0x0001 /* Point Online (0=Offline; 1=Online) */
362 #define AL_OBJ_BO_FLAG1 0x0002 /* Restart (0=Normal; 1=Restart) */
363 #define AL_OBJ_BO_FLAG2 0x0004 /* Comms Lost (0=Normal; 1=Lost) */
364 #define AL_OBJ_BO_FLAG3 0x0008 /* Remote Force (0=Normal; 1=Forced) */
365 #define AL_OBJ_BO_FLAG4 0x0010 /* Local Force (0=Normal; 1=Forced) */
366 #define AL_OBJ_BO_FLAG5 0x0020 /* Reserved */
367 #define AL_OBJ_BO_FLAG6 0x0040 /* Reserved */
368 #define AL_OBJ_BO_FLAG7 0x0080 /* Point State (0=Off; 1=On) */
370 /***************************************************************************/
371 /* Counter Objects */
372 #define AL_OBJ_CTR_ALL 0x1400 /* 20 00 Binary Counter Default Variation */
373 #define AL_OBJ_CTR_32 0x1401 /* 20 01 32-Bit Binary Counter */
374 #define AL_OBJ_CTR_16 0x1402 /* 20 02 16-Bit Binary Counter */
375 #define AL_OBJ_DCTR_32 0x1403 /* 20 03 32-Bit Delta Counter */
376 #define AL_OBJ_DCTR_16 0x1404 /* 20 04 16-Bit Delta Counter */
377 #define AL_OBJ_CTR_32NF 0x1405 /* 20 05 32-Bit Binary Counter Without Flag */
378 #define AL_OBJ_CTR_16NF 0x1406 /* 20 06 16-Bit Binary Counter Without Flag */
379 #define AL_OBJ_DCTR_32NF 0x1407 /* 20 07 32-Bit Delta Counter Without Flag */
380 #define AL_OBJ_DCTR_16NF 0x1408 /* 20 08 16-Bit Delta Counter Without Flag */
381 #define AL_OBJ_FCTR_ALL 0x1500 /* 21 00 Frozen Binary Counter Default Variation */
382 #define AL_OBJ_FCTR_32 0x1501 /* 21 01 32-Bit Frozen Counter */
383 #define AL_OBJ_FCTR_16 0x1502 /* 21 02 16-Bit Frozen Counter */
384 #define AL_OBJ_FDCTR_32 0x1503 /* 21 03 32-Bit Frozen Delta Counter */
385 #define AL_OBJ_FDCTR_16 0x1504 /* 21 04 16-Bit Frozen Delta Counter */
386 #define AL_OBJ_FCTR_32T 0x1505 /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
387 #define AL_OBJ_FCTR_16T 0x1506 /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
388 #define AL_OBJ_FDCTR_32T 0x1507 /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
389 #define AL_OBJ_FDCTR_16T 0x1508 /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
390 #define AL_OBJ_FCTR_32NF 0x1509 /* 21 09 32-Bit Frozen Counter Without Flag */
391 #define AL_OBJ_FCTR_16NF 0x150A /* 21 10 16-Bit Frozen Counter Without Flag */
392 #define AL_OBJ_FDCTR_32NF 0x150B /* 21 11 32-Bit Frozen Delta Counter Without Flag */
393 #define AL_OBJ_FDCTR_16NF 0x150C /* 21 12 16-Bit Frozen Delta Counter Without Flag */
394 #define AL_OBJ_CTRC_ALL 0x1600 /* 22 00 Counter Change Event Default Variation */
395 #define AL_OBJ_CTRC_32 0x1601 /* 22 01 32-Bit Counter Change Event w/o Time */
396 #define AL_OBJ_CTRC_16 0x1602 /* 22 02 16-Bit Counter Change Event w/o Time */
397 #define AL_OBJ_DCTRC_32 0x1603 /* 22 03 32-Bit Delta Counter Change Event w/o Time */
398 #define AL_OBJ_DCTRC_16 0x1604 /* 22 04 16-Bit Delta Counter Change Event w/o Time */
399 #define AL_OBJ_CTRC_32T 0x1605 /* 22 05 32-Bit Counter Change Event with Time */
400 #define AL_OBJ_CTRC_16T 0x1606 /* 22 06 16-Bit Counter Change Event with Time */
401 #define AL_OBJ_DCTRC_32T 0x1607 /* 22 07 32-Bit Delta Counter Change Event with Time */
402 #define AL_OBJ_DCTRC_16T 0x1608 /* 22 08 16-Bit Delta Counter Change Event with Time */
403 #define AL_OBJ_FCTRC_ALL 0x1700 /* 21 00 Frozen Binary Counter Change Event Default Variation */
404 #define AL_OBJ_FCTRC_32 0x1701 /* 21 01 32-Bit Frozen Counter Change Event */
405 #define AL_OBJ_FCTRC_16 0x1702 /* 21 02 16-Bit Frozen Counter Change Event */
406 #define AL_OBJ_FDCTRC_32 0x1703 /* 21 03 32-Bit Frozen Delta Counter Change Event */
407 #define AL_OBJ_FDCTRC_16 0x1704 /* 21 04 16-Bit Frozen Delta Counter Change Event */
408 #define AL_OBJ_FCTRC_32T 0x1705 /* 21 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
409 #define AL_OBJ_FCTRC_16T 0x1706 /* 21 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
410 #define AL_OBJ_FDCTRC_32T 0x1707 /* 21 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
411 #define AL_OBJ_FDCTRC_16T 0x1708 /* 21 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
413 /* Counter Quality Flags */
414 #define AL_OBJ_CTR_FLAG0 0x0001 /* Point Online (0=Offline; 1=Online) */
415 #define AL_OBJ_CTR_FLAG1 0x0002 /* Restart (0=Normal; 1=Restart) */
416 #define AL_OBJ_CTR_FLAG2 0x0004 /* Comms Lost (0=Normal; 1=Lost) */
417 #define AL_OBJ_CTR_FLAG3 0x0008 /* Remote Force (0=Normal; 1=Forced) */
418 #define AL_OBJ_CTR_FLAG4 0x0010 /* Local Force (0=Normal; 1=Forced) */
419 #define AL_OBJ_CTR_FLAG5 0x0020 /* Roll-over (0=Normal; 1=Roll-Over) */
420 #define AL_OBJ_CTR_FLAG6 0x0040 /* Discontinuity (0=Normal; 1=Discontinuity) */
421 #define AL_OBJ_CTR_FLAG7 0x0080 /* Reserved */
423 /***************************************************************************/
424 /* Analog Input Objects */
425 #define AL_OBJ_AI_ALL 0x1E00 /* 30 00 Analog Input Default Variation */
426 #define AL_OBJ_AI_32 0x1E01 /* 30 01 32-Bit Analog Input */
427 #define AL_OBJ_AI_16 0x1E02 /* 30 02 16-Bit Analog Input */
428 #define AL_OBJ_AI_32NF 0x1E03 /* 30 03 32-Bit Analog Input Without Flag */
429 #define AL_OBJ_AI_16NF 0x1E04 /* 30 04 16-Bit Analog Input Without Flag */
430 #define AL_OBJ_AI_FLT 0x1E05 /* 30 05 32-Bit Floating Point Input */
431 #define AL_OBJ_AI_DBL 0x1E06 /* 30 06 64-Bit Floating Point Input */
432 /* 0x1F01 31 01 32-Bit Frozen Analog Input */
433 /* 0x1F02 31 02 16-Bit Frozen Analog Input */
434 /* 0x1F03 31 03 32-Bit Frozen Analog Input w/ Time of Freeze */
435 /* 0x1F04 31 04 16-Bit Frozen Analog Input w/ Time of Freeze */
436 /* 0x1F05 31 05 32-Bit Frozen Analog Input Without Flag */
437 /* 0x1F06 31 06 16-Bit Frozen Analog Input Without Flag */
438 #define AL_OBJ_AIF_FLT 0x1F07 /* 31 07 32-Bit Frozen Floating Point Input */
439 #define AL_OBJ_AIF_DBL 0x1F08 /* 31 08 64-Bit Frozen Floating Point Input */
440 #define AL_OBJ_AIC_ALL 0x2000 /* 32 00 Analog Input Change Default Variation */
441 #define AL_OBJ_AIC_32NT 0x2001 /* 32 01 32-Bit Analog Change Event w/o Time */
442 #define AL_OBJ_AIC_16NT 0x2002 /* 32 02 16-Bit Analog Change Event w/o Time */
443 #define AL_OBJ_AIC_32T 0x2003 /* 32 03 32-Bit Analog Change Event w/ Time */
444 #define AL_OBJ_AIC_16T 0x2004 /* 32 04 16-Bit Analog Change Event w/ Time */
445 #define AL_OBJ_AIC_FLTNT 0x2005 /* 32 05 32-Bit Floating Point Change Event w/o Time*/
446 #define AL_OBJ_AIC_DBLNT 0x2006 /* 32 06 64-Bit Floating Point Change Event w/o Time*/
447 #define AL_OBJ_AIC_FLTT 0x2007 /* 32 07 32-Bit Floating Point Change Event w/ Time*/
448 #define AL_OBJ_AIC_DBLT 0x2008 /* 32 08 64-Bit Floating Point Change Event w/ Time*/
449 /* 0x2101 33 01 32-Bit Frozen Analog Event w/o Time */
450 /* 0x2102 33 02 16-Bit Frozen Analog Event w/o Time */
451 /* 0x2103 33 03 32-Bit Frozen Analog Event w/ Time */
452 /* 0x2104 33 04 16-Bit Frozen Analog Event w/ Time */
453 #define AL_OBJ_AIFC_FLTNT 0x2105 /* 33 05 32-Bit Floating Point Frozen Change Event w/o Time*/
454 #define AL_OBJ_AIFC_DBLNT 0x2106 /* 33 06 64-Bit Floating Point Frozen Change Event w/o Time*/
455 #define AL_OBJ_AIFC_FLTT 0x2107 /* 33 07 32-Bit Floating Point Frozen Change Event w/ Time*/
456 #define AL_OBJ_AIFC_DBLT 0x2108 /* 33 08 64-Bit Floating Point Frozen Change Event w/ Time*/
458 /* Analog Input Quality Flags */
459 #define AL_OBJ_AI_FLAG0 0x0001 /* Point Online (0=Offline; 1=Online) */
460 #define AL_OBJ_AI_FLAG1 0x0002 /* Restart (0=Normal; 1=Restart) */
461 #define AL_OBJ_AI_FLAG2 0x0004 /* Comms Lost (0=Normal; 1=Lost) */
462 #define AL_OBJ_AI_FLAG3 0x0008 /* Remote Force (0=Normal; 1=Forced) */
463 #define AL_OBJ_AI_FLAG4 0x0010 /* Local Force (0=Normal; 1=Forced) */
464 #define AL_OBJ_AI_FLAG5 0x0020 /* Over-Range (0=Normal; 1=Over-Range) */
465 #define AL_OBJ_AI_FLAG6 0x0040 /* Reference Check (0=Normal; 1=Error) */
466 #define AL_OBJ_AI_FLAG7 0x0080 /* Reserved */
468 #define AL_OBJ_AIDB_ALL 0x2200 /* 34 00 Analog Input Deadband Default Variation */
469 #define AL_OBJ_AIDB_16 0x2201 /* 34 01 16-Bit Analog Input Deadband */
470 #define AL_OBJ_AIDB_32 0x2202 /* 34 02 32-Bit Analog Input Deadband */
471 #define AL_OBJ_AIDB_FLT 0x2203 /* 34 03 Floating Point Analog Input Deadband */
473 /***************************************************************************/
474 /* Analog Output Objects */
475 #define AL_OBJ_AO_ALL 0x2800 /* 40 00 Analog Output Default Variation */
476 #define AL_OBJ_AO_32 0x2801 /* 40 01 32-Bit Analog Output Status */
477 #define AL_OBJ_AO_16 0x2802 /* 40 02 16-Bit Analog Output Status */
478 #define AL_OBJ_AO_FLT 0x2803 /* 40 03 32-Bit Floating Point Output Status */
479 #define AL_OBJ_AO_DBL 0x2804 /* 40 04 64-Bit Floating Point Output Status */
480 #define AL_OBJ_AO_32OPB 0x2901 /* 41 01 32-Bit Analog Output Block */
481 #define AL_OBJ_AO_16OPB 0x2902 /* 41 02 16-Bit Analog Output Block */
482 #define AL_OBJ_AO_FLTOPB 0x2903 /* 41 03 32-Bit Floating Point Output Block */
483 #define AL_OBJ_AO_DBLOPB 0x2904 /* 41 04 64-Bit Floating Point Output Block */
484 #define AL_OBJ_AOC_ALL 0x2A00 /* 42 00 Analog Output Event Default Variation */
485 #define AL_OBJ_AOC_32NT 0x2A01 /* 42 01 32-Bit Analog Output Event w/o Time */
486 #define AL_OBJ_AOC_16NT 0x2A02 /* 42 02 16-Bit Analog Output Event w/o Time */
487 #define AL_OBJ_AOC_32T 0x2A03 /* 42 03 32-Bit Analog Output Event w/ Time */
488 #define AL_OBJ_AOC_16T 0x2A04 /* 42 04 16-Bit Analog Output Event w/ Time */
489 #define AL_OBJ_AOC_FLTNT 0x2A05 /* 42 05 32-Bit Floating Point Output Event w/o Time*/
490 #define AL_OBJ_AOC_DBLNT 0x2A06 /* 42 06 64-Bit Floating Point Output Event w/o Time*/
491 #define AL_OBJ_AOC_FLTT 0x2A07 /* 42 07 32-Bit Floating Point Output Event w/ Time*/
492 #define AL_OBJ_AOC_DBLT 0x2A08 /* 42 08 64-Bit Floating Point Output Event w/ Time*/
494 /* Analog Output Quality Flags */
495 #define AL_OBJ_AO_FLAG0 0x0001 /* Point Online (0=Offline; 1=Online) */
496 #define AL_OBJ_AO_FLAG1 0x0002 /* Restart (0=Normal; 1=Restart) */
497 #define AL_OBJ_AO_FLAG2 0x0004 /* Comms Lost (0=Normal; 1=Lost) */
498 #define AL_OBJ_AO_FLAG3 0x0008 /* Remote Force (0=Normal; 1=Forced) */
499 #define AL_OBJ_AO_FLAG4 0x0010 /* Local Force (0=Normal; 1=Forced) */
500 #define AL_OBJ_AO_FLAG5 0x0020 /* Reserved */
501 #define AL_OBJ_AO_FLAG6 0x0040 /* Reserved */
502 #define AL_OBJ_AO_FLAG7 0x0080 /* Reserved */
504 /***************************************************************************/
505 /* Time Objects */
506 #define AL_OBJ_TD_ALL 0x3200 /* 50 00 Time and Date Default Variation */
507 #define AL_OBJ_TD 0x3201 /* 50 01 Time and Date */
508 #define AL_OBJ_TDI 0x3202 /* 50 02 Time and Date w/ Interval */
509 #define AL_OBJ_TDR 0x3203 /* 50 03 Last Recorded Time and Date */
510 #define AL_OBJ_TDCTO 0x3301 /* 51 01 Time and Date CTO */
511 #define AL_OBJ_UTDCTO 0x3302 /* 51 02 Unsynchronized Time and Date CTO */
512 #define AL_OBJ_TDELAYC 0x3401 /* 52 01 Time Delay Coarse */
513 #define AL_OBJ_TDELAYF 0x3402 /* 52 02 Time Delay Fine */
515 /***************************************************************************/
516 /* Class Data Objects */
517 #define AL_OBJ_CLASS0 0x3C01 /* 60 01 Class 0 Data */
518 #define AL_OBJ_CLASS1 0x3C02 /* 60 02 Class 1 Data */
519 #define AL_OBJ_CLASS2 0x3C03 /* 60 03 Class 2 Data */
520 #define AL_OBJ_CLASS3 0x3C04 /* 60 04 Class 3 Data */
522 /***************************************************************************/
523 /* File Objects */
524 #define AL_OBJ_FILE_CMD 0x4603 /* 70 03 File Control - Command */
525 #define AL_OBJ_FILE_STAT 0x4604 /* 70 04 File Control - Status */
526 #define AL_OBJ_FILE_TRANS 0x4605 /* 70 05 File Control - Transport */
527 #define AL_OBJ_FILE_TRAN_ST 0x4606 /* 70 05 File Control - Transport Status */
529 /* File Control Mode flags */
530 #define AL_OBJ_FILE_MODE_NULL 0x00 /* NULL */
531 #define AL_OBJ_FILE_MODE_READ 0x01 /* READ */
532 #define AL_OBJ_FILE_MODE_WRITE 0x02 /* WRITE */
533 #define AL_OBJ_FILE_MODE_APPEND 0x03 /* APPEND */
536 /***************************************************************************/
537 /* Device Objects */
538 #define AL_OBJ_IIN 0x5001 /* 80 01 Internal Indications */
540 /***************************************************************************/
541 /* Data Sets */
542 #define AL_OBJ_DS_PROTO 0x5501 /* 85 01 Data-Set Prototype, with UUID */
543 #define AL_OBJ_DSD_CONT 0x5601 /* 86 01 Data-Set Descriptor, Data-Set Contents */
544 #define AL_OBJ_DSD_CHAR 0x5602 /* 86 02 Data-Set Descriptor, Characteristics */
545 #define AL_OBJ_DSD_PIDX 0x5603 /* 86 03 Data-Set Descriptor, Point Index Attributes */
546 #define AL_OBJ_DS_PV 0x5701 /* 87 01 Data-Set, Present Value */
547 #define AL_OBJ_DS_SS 0x5801 /* 88 01 Data-Set, Snapshot */
549 /***************************************************************************/
550 /* Octet String Objects */
551 #define AL_OBJ_OCT 0x6E00 /* 110 xx Octet string */
552 #define AL_OBJ_OCT_EVT 0x6F00 /* 110 xx Octet string event */
554 /***************************************************************************/
555 /* Virtual Terminal Objects */
556 #define AL_OBJ_VT_OBLK 0x7000 /* 112 xx Virtual Terminal Output Block */
557 #define AL_OBJ_VT_EVTD 0x7100 /* 113 xx Virtual Terminal Event Data */
559 /***************************************************************************/
560 /* End of Application Layer Data Object Definitions */
561 /***************************************************************************/
563 void proto_register_dnp3(void);
564 void proto_reg_handoff_dnp3(void);
566 /* Initialize the protocol and registered fields */
567 static int proto_dnp3 = -1;
568 static int hf_dnp3_start = -1;
569 static int hf_dnp3_len = -1;
570 static int hf_dnp3_ctl = -1;
571 static int hf_dnp3_ctl_prifunc = -1;
572 static int hf_dnp3_ctl_secfunc = -1;
573 static int hf_dnp3_ctl_dir = -1;
574 static int hf_dnp3_ctl_prm = -1;
575 static int hf_dnp3_ctl_fcb = -1;
576 static int hf_dnp3_ctl_fcv = -1;
577 static int hf_dnp3_ctl_dfc = -1;
578 static int hf_dnp3_dst = -1;
579 static int hf_dnp3_src = -1;
580 static int hf_dnp_hdr_CRC = -1;
581 static int hf_dnp_hdr_CRC_bad = -1;
582 static int hf_dnp3_tr_ctl = -1;
583 static int hf_dnp3_tr_fin = -1;
584 static int hf_dnp3_tr_fir = -1;
585 static int hf_dnp3_tr_seq = -1;
586 static int hf_dnp3_al_ctl = -1;
587 static int hf_dnp3_al_fir = -1;
588 static int hf_dnp3_al_fin = -1;
589 static int hf_dnp3_al_con = -1;
590 static int hf_dnp3_al_uns = -1;
591 static int hf_dnp3_al_seq = -1;
592 static int hf_dnp3_al_func = -1;
593 /* Added for Application Layer Decoding */
594 static int hf_dnp3_al_iin = -1;
595 static int hf_dnp3_al_iin_bmsg = -1;
596 static int hf_dnp3_al_iin_cls1d = -1;
597 static int hf_dnp3_al_iin_cls2d = -1;
598 static int hf_dnp3_al_iin_cls3d = -1;
599 static int hf_dnp3_al_iin_tsr = -1;
600 static int hf_dnp3_al_iin_dol = -1;
601 static int hf_dnp3_al_iin_dt = -1;
602 static int hf_dnp3_al_iin_rst = -1;
603 static int hf_dnp3_al_iin_fcni = -1;
604 static int hf_dnp3_al_iin_obju = -1;
605 static int hf_dnp3_al_iin_pioor = -1;
606 static int hf_dnp3_al_iin_ebo = -1;
607 static int hf_dnp3_al_iin_oae = -1;
608 static int hf_dnp3_al_iin_cc = -1;
609 static int hf_dnp3_al_obj = -1;
610 static int hf_dnp3_al_objq_index = -1;
611 static int hf_dnp3_al_objq_code = -1;
612 static int hf_dnp3_al_range_start8 = -1;
613 static int hf_dnp3_al_range_stop8 = -1;
614 static int hf_dnp3_al_range_start16 = -1;
615 static int hf_dnp3_al_range_stop16 = -1;
616 static int hf_dnp3_al_range_start32 = -1;
617 static int hf_dnp3_al_range_stop32 = -1;
618 static int hf_dnp3_al_range_abs8 = -1;
619 static int hf_dnp3_al_range_abs16 = -1;
620 static int hf_dnp3_al_range_abs32 = -1;
621 static int hf_dnp3_al_range_quant8 = -1;
622 static int hf_dnp3_al_range_quant16 = -1;
623 static int hf_dnp3_al_range_quant32 = -1;
624 static int hf_dnp3_al_index8 = -1;
625 static int hf_dnp3_al_index16 = -1;
626 static int hf_dnp3_al_index32 = -1;
627 static int hf_dnp3_al_size8 = -1;
628 static int hf_dnp3_al_size16 = -1;
629 static int hf_dnp3_al_size32 = -1;
631 /*static int hf_dnp3_al_objq = -1;
632 static int hf_dnp3_al_nobj = -1; */
633 /* XXX - unused
634 static int hf_dnp3_al_ptnum = -1; */
635 static int hf_dnp3_al_biq_b0 = -1;
636 static int hf_dnp3_al_biq_b1 = -1;
637 static int hf_dnp3_al_biq_b2 = -1;
638 static int hf_dnp3_al_biq_b3 = -1;
639 static int hf_dnp3_al_biq_b4 = -1;
640 static int hf_dnp3_al_biq_b5 = -1;
641 static int hf_dnp3_al_biq_b6 = -1;
642 static int hf_dnp3_al_biq_b7 = -1;
643 static int hf_dnp3_al_boq_b0 = -1;
644 static int hf_dnp3_al_boq_b1 = -1;
645 static int hf_dnp3_al_boq_b2 = -1;
646 static int hf_dnp3_al_boq_b3 = -1;
647 static int hf_dnp3_al_boq_b4 = -1;
648 static int hf_dnp3_al_boq_b5 = -1;
649 static int hf_dnp3_al_boq_b6 = -1;
650 static int hf_dnp3_al_boq_b7 = -1;
651 static int hf_dnp3_al_ctrq_b0 = -1;
652 static int hf_dnp3_al_ctrq_b1 = -1;
653 static int hf_dnp3_al_ctrq_b2 = -1;
654 static int hf_dnp3_al_ctrq_b3 = -1;
655 static int hf_dnp3_al_ctrq_b4 = -1;
656 static int hf_dnp3_al_ctrq_b5 = -1;
657 static int hf_dnp3_al_ctrq_b6 = -1;
658 static int hf_dnp3_al_ctrq_b7 = -1;
659 static int hf_dnp3_al_aiq_b0 = -1;
660 static int hf_dnp3_al_aiq_b1 = -1;
661 static int hf_dnp3_al_aiq_b2 = -1;
662 static int hf_dnp3_al_aiq_b3 = -1;
663 static int hf_dnp3_al_aiq_b4 = -1;
664 static int hf_dnp3_al_aiq_b5 = -1;
665 static int hf_dnp3_al_aiq_b6 = -1;
666 static int hf_dnp3_al_aiq_b7 = -1;
667 static int hf_dnp3_al_aoq_b0 = -1;
668 static int hf_dnp3_al_aoq_b1 = -1;
669 static int hf_dnp3_al_aoq_b2 = -1;
670 static int hf_dnp3_al_aoq_b3 = -1;
671 static int hf_dnp3_al_aoq_b4 = -1;
672 static int hf_dnp3_al_aoq_b5 = -1;
673 static int hf_dnp3_al_aoq_b6 = -1;
674 static int hf_dnp3_al_aoq_b7 = -1;
675 static int hf_dnp3_al_timestamp = -1;
676 static int hf_dnp3_al_file_perms = -1;
677 static int hf_dnp3_al_file_perms_read_owner = -1;
678 static int hf_dnp3_al_file_perms_write_owner = -1;
679 static int hf_dnp3_al_file_perms_exec_owner = -1;
680 static int hf_dnp3_al_file_perms_read_group = -1;
681 static int hf_dnp3_al_file_perms_write_group = -1;
682 static int hf_dnp3_al_file_perms_exec_group = -1;
683 static int hf_dnp3_al_file_perms_read_world = -1;
684 static int hf_dnp3_al_file_perms_write_world = -1;
685 static int hf_dnp3_al_file_perms_exec_world = -1;
686 static int hf_dnp3_al_rel_timestamp = -1;
687 static int hf_dnp3_al_ana16 = -1;
688 static int hf_dnp3_al_ana32 = -1;
689 static int hf_dnp3_al_anaflt = -1;
690 static int hf_dnp3_al_anadbl = -1;
691 static int hf_dnp3_al_bit = -1;
692 static int hf_dnp3_al_2bit = -1;
693 static int hf_dnp3_al_cnt16 = -1;
694 static int hf_dnp3_al_cnt32 = -1;
695 static int hf_dnp3_al_ctrlstatus = -1;
696 static int hf_dnp3_al_anaout16 = -1;
697 static int hf_dnp3_al_anaout32 = -1;
698 static int hf_dnp3_al_anaoutflt = -1;
699 static int hf_dnp3_al_anaoutdbl = -1;
700 static int hf_dnp3_al_file_mode = -1;
701 static int hf_dnp3_al_file_auth = -1;
702 static int hf_dnp3_al_file_size = -1;
703 static int hf_dnp3_al_file_maxblk = -1;
704 static int hf_dnp3_al_file_reqID = -1;
705 static int hf_dnp3_al_file_handle = -1;
706 static int hf_dnp3_al_file_status = -1;
707 static int hf_dnp3_al_file_blocknum = -1;
708 static int hf_dnp3_al_file_lastblock = -1;
709 static int hf_dnp3_al_file_data = -1;
710 static int hf_dnp3_ctlobj_code_c = -1;
711 static int hf_dnp3_ctlobj_code_m = -1;
712 static int hf_dnp3_ctlobj_code_tc = -1;
713 static int hf_dnp3_al_datatype = -1;
714 static int hf_dnp3_al_da_length = -1;
715 static int hf_dnp3_al_da_int8 = -1;
716 static int hf_dnp3_al_da_int32 = -1;
718 /***************************************************************************/
719 /* Value String Look-Ups */
720 /***************************************************************************/
721 static const value_string dnp3_ctl_func_pri_vals[] = {
722 { DL_FUNC_RESET_LINK, "Reset of Remote Link" },
723 { DL_FUNC_RESET_PROC, "Reset of User Process" },
724 { DL_FUNC_TEST_LINK, "Test Function For Link" },
725 { DL_FUNC_USER_DATA, "User Data" },
726 { DL_FUNC_UNC_DATA, "Unconfirmed User Data" },
727 { DL_FUNC_LINK_STAT, "Request Link Status" },
728 { 0, NULL }
731 static const value_string dnp3_ctl_func_sec_vals[] = {
732 { DL_FUNC_ACK, "ACK" },
733 { DL_FUNC_NACK, "NACK" },
734 { DL_FUNC_STAT_LINK, "Status of Link" },
735 { DL_FUNC_NO_FUNC, "Link Service Not Functioning" },
736 { DL_FUNC_NOT_IMPL, "Link Service Not Used or Implemented" },
737 { 0, NULL }
740 #if 0
741 static const value_string dnp3_ctl_flags_pri_vals[] = {
742 { DNP3_CTL_DIR, "DIR" },
743 { DNP3_CTL_PRM, "PRM" },
744 { DNP3_CTL_FCB, "FCB" },
745 { DNP3_CTL_FCV, "FCV" },
746 { 0, NULL }
748 #endif
750 #if 0
751 static const value_string dnp3_ctl_flags_sec_vals[]= {
752 { DNP3_CTL_DIR, "DIR" },
753 { DNP3_CTL_PRM, "PRM" },
754 { DNP3_CTL_RES, "RES" },
755 { DNP3_CTL_DFC, "DFC" },
756 { 0, NULL }
758 #endif
760 #if 0
761 static const value_string dnp3_tr_flags_vals[] = {
762 { DNP3_TR_FIN, "FIN" },
763 { DNP3_TR_FIR, "FIR" },
764 { 0, NULL }
766 #endif
768 #if 0
769 static const value_string dnp3_al_flags_vals[] = {
770 { DNP3_AL_FIR, "FIR" },
771 { DNP3_AL_FIN, "FIN" },
772 { DNP3_AL_CON, "CON" },
773 { DNP3_AL_UNS, "UNS" },
774 { 0, NULL }
776 #endif
778 /* Application Layer Function Code Values */
779 static const value_string dnp3_al_func_vals[] = {
780 { AL_FUNC_CONFIRM, "Confirm" },
781 { AL_FUNC_READ, "Read" },
782 { AL_FUNC_WRITE, "Write" },
783 { AL_FUNC_SELECT, "Select" },
784 { AL_FUNC_OPERATE, "Operate" },
785 { AL_FUNC_DIROP, "Direct Operate" },
786 { AL_FUNC_DIROPNACK, "Direct Operate No Ack" },
787 { AL_FUNC_FRZ, "Immediate Freeze" },
788 { AL_FUNC_FRZNACK, "Immediate Freeze No Ack" },
789 { AL_FUNC_FRZCLR, "Freeze and Clear" },
790 { AL_FUNC_FRZCLRNACK, "Freeze and Clear No ACK" },
791 { AL_FUNC_FRZT, "Freeze With Time" },
792 { AL_FUNC_FRZTNACK, "Freeze With Time No ACK" },
793 { AL_FUNC_COLDRST, "Cold Restart" },
794 { AL_FUNC_WARMRST, "Warm Restart" },
795 { AL_FUNC_INITDATA, "Initialize Data" },
796 { AL_FUNC_INITAPP, "Initialize Application" },
797 { AL_FUNC_STARTAPP, "Start Application" },
798 { AL_FUNC_STOPAPP, "Stop Application" },
799 { AL_FUNC_SAVECFG, "Save Configuration" },
800 { AL_FUNC_ENSPMSG, "Enable Spontaneous Messages" },
801 { AL_FUNC_DISSPMSG, "Disable Spontaneous Messages" },
802 { AL_FUNC_ASSIGNCL, "Assign Classes" },
803 { AL_FUNC_DELAYMST, "Delay Measurement" },
804 { AL_FUNC_RECCT, "Record Current Time" },
805 { AL_FUNC_OPENFILE, "Open File" },
806 { AL_FUNC_CLOSEFILE, "Close File" },
807 { AL_FUNC_DELETEFILE, "Delete File" },
808 { AL_FUNC_GETFILEINF, "Get File Info" },
809 { AL_FUNC_AUTHFILE, "Authenticate File" },
810 { AL_FUNC_ABORTFILE, "Abort File" },
811 { AL_FUNC_ACTCNF, "Activate Config" },
812 { AL_FUNC_AUTHREQ, "Authentication Request" },
813 { AL_FUNC_AUTHERR, "Authentication Error" },
814 { AL_FUNC_RESPON, "Response" },
815 { AL_FUNC_UNSOLI, "Unsolicited Response" },
816 { AL_FUNC_AUTHRESP, "Authentication Response" },
817 { 0, NULL }
819 static value_string_ext dnp3_al_func_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_func_vals);
821 #if 0
822 /* Application Layer Internal Indication (IIN) bit Values */
823 static const value_string dnp3_al_iin_vals[] = {
824 { AL_IIN_BMSG, "Broadcast message Rx'd" },
825 { AL_IIN_CLS1D, "Class 1 Data Available" },
826 { AL_IIN_CLS2D, "Class 2 Data Available" },
827 { AL_IIN_CLS3D, "Class 3 Data Available" },
828 { AL_IIN_TSR, "Time Sync Required from Master" },
829 { AL_IIN_DOL, "Outputs in Local Mode" },
830 { AL_IIN_DT, "Device Trouble" },
831 { AL_IIN_RST, "Device Restart" },
832 { AL_IIN_FCNI, "Function Code not implemented" },
833 { AL_IIN_OBJU, "Requested Objects Unknown" },
834 { AL_IIN_PIOOR, "Parameters Invalid or Out of Range" },
835 { AL_IIN_EBO, "Event Buffer Overflow" },
836 { AL_IIN_OAE, "Operation Already Executing" },
837 { AL_IIN_CC, "Device Configuration Corrupt" },
838 { 0, NULL }
840 #endif
842 /* Application Layer Object Qualifier Index Values When Qualifier Code != 11 */
843 static const value_string dnp3_al_objq_index_vals[] = {
844 { AL_OBJQL_IDX_NI, "None" },
845 { AL_OBJQL_IDX_1O, "1-Octet Indexing" },
846 { AL_OBJQL_IDX_2O, "2-Octet Indexing" },
847 { AL_OBJQL_IDX_4O, "4-Octet Indexing" },
848 { AL_OBJQL_IDX_1OS, "1-Octet Object Size" },
849 { AL_OBJQL_IDX_2OS, "2-Octet Object Size" },
850 { AL_OBJQL_IDX_4OS, "4-Octet Object Size" },
851 { 0, NULL }
853 static value_string_ext dnp3_al_objq_index_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_objq_index_vals);
855 /* Application Layer Object Qualifier Code Values */
856 static const value_string dnp3_al_objq_code_vals[] = {
857 { AL_OBJQL_CODE_SSI8, "8-bit Start and Stop Indices" },
858 { AL_OBJQL_CODE_SSI16, "16-bit Start and Stop Indices" },
859 { AL_OBJQL_CODE_SSI32, "32-bit Start and Stop Indices" },
860 { AL_OBJQL_CODE_AA8, "8-bit Absolute Address in Range Field" },
861 { AL_OBJQL_CODE_AA16, "16-bit Absolute Address in Range Field" },
862 { AL_OBJQL_CODE_AA32, "32-bit Absolute Address in Range Field" },
863 { AL_OBJQL_CODE_R0, "No Range Field" },
864 { AL_OBJQL_CODE_SF8, "8-bit Single Field Quantity" },
865 { AL_OBJQL_CODE_SF16, "16-bit Single Field Quantity" },
866 { AL_OBJQL_CODE_SF32, "32-bit Single Field Quantity" },
867 { 10, "Reserved" },
868 { AL_OBJQL_CODE_FF, "Free-format Qualifier" },
869 { 0, NULL }
871 static value_string_ext dnp3_al_objq_code_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_objq_code_vals);
873 /* Application Layer Data Object Values */
874 static const value_string dnp3_al_obj_vals[] = {
875 { AL_OBJ_DA_USR_ATTR,"Device Attributes - Identifier of support for user-specific attributes (Obj:00, Var:211)" },
876 { AL_OBJ_DA_MSTR_DSP,"Device Attributes - Number of master-defined data set prototypes (Obj:00, Var:212)" },
877 { AL_OBJ_DA_OS_DSP, "Device Attributes - Number of outstation-defined data set prototypes (Obj:00, Var:213)" },
878 { AL_OBJ_DA_MSTR_DS, "Device Attributes - Number of master-defined data sets (Obj:00, Var:214)" },
879 { AL_OBJ_DA_OS_DS, "Device Attributes - Number of outstation-defined data sets (Obj:00, Var:215)" },
880 { AL_OBJ_DA_BO_REQ, "Device Attributes - Max number of binary outputs per request (Obj:00, Var:216)" },
881 { AL_OBJ_DA_LOC_TA, "Device Attributes - Local timing accuracy (Obj:00, Var:217)" },
882 { AL_OBJ_DA_DUR_TA, "Device Attributes - Duration of timing accuraccy (Obj:00, Var:218)" },
883 { AL_OBJ_DA_AO_EVT, "Device Attributes - Support for analog output events (Obj:00, Var:219)" },
884 { AL_OBJ_DA_MAX_AO, "Device Attributes - Max analog output index (Obj:00, Var:220)" },
885 { AL_OBJ_DA_NUM_AO, "Device Attributes - Number of analog outputs (Obj:00, Var:221)" },
886 { AL_OBJ_DA_BO_EVT, "Device Attributes - Support for binary output events (Obj:00, Var:222)" },
887 { AL_OBJ_DA_MAX_BO, "Device Attributes - Max binary output index (Obj:00, Var:223)" },
888 { AL_OBJ_DA_NUM_BO, "Device Attributes - Number of binary outputs (Obj:00, Var:224)" },
889 { AL_OBJ_DA_FCTR_EVT,"Device Attributes - Support for frozen counter events (Obj:00, Var:225)" },
890 { AL_OBJ_DA_FCTR, "Device Attributes - Support for frozen counters (Obj:00, Var:226)" },
891 { AL_OBJ_DA_CTR_EVT, "Device Attributes - Support for counter events (Obj:00, Var:227)" },
892 { AL_OBJ_DA_MAX_CTR, "Device Attributes - Max counter index (Obj:00, Var:228)" },
893 { AL_OBJ_DA_NUM_CTR, "Device Attributes - Number of counter points (Obj:00, Var:229)" },
894 { AL_OBJ_DA_AIF, "Device Attributes - Support for frozen analog inputs (Obj:00, Var:230)" },
895 { AL_OBJ_DA_AI_EVT, "Device Attributes - Support for analog input events (Obj:00, Var:231)" },
896 { AL_OBJ_DA_MAX_AI, "Device Attributes - Maximum analog input index (Obj:00, Var:232)" },
897 { AL_OBJ_DA_NUM_AI, "Device Attributes - Number of analog input points (Obj:00, Var:233)" },
898 { AL_OBJ_DA_2BI_EVT, "Device Attributes - Support for Double-Bit BI Events (Obj:00, Var:234)" },
899 { AL_OBJ_DA_MAX_2BI, "Device Attributes - Max Double-bit BI Point Index (Obj:00, Var:235)" },
900 { AL_OBJ_DA_NUM_2BI, "Device Attributes - Number of Double-bit BI Points (Obj:00, Var:236)" },
901 { AL_OBJ_DA_BI_EVT, "Device Attributes - Support for Binary Input Events (Obj:00, Var:237)" },
902 { AL_OBJ_DA_MAX_BI, "Device Attributes - Max Binary Input Point Index (Obj:00, Var:238)" },
903 { AL_OBJ_DA_NUM_BI, "Device Attributes - Number of Binary Input Points (Obj:00, Var:239)" },
904 { AL_OBJ_DA_MXTX_FR, "Device Attributes - Maximum Transmit Fragment Size (Obj:00, Var:240)" },
905 { AL_OBJ_DA_MXRX_FR, "Device Attributes - Maximum Receive Fragment Size (Obj:00, Var:241)" },
906 { AL_OBJ_DA_SWVER, "Device Attributes - Device Manufacturers SW Version (Obj:00, Var:242)" },
907 { AL_OBJ_DA_HWVER, "Device Attributes - Device Manufacturers HW Version (Obj:00, Var:243)" },
908 { AL_OBJ_DA_LOC, "Device Attributes - User-Assigned Location (Obj:00, Var:245)" },
909 { AL_OBJ_DA_ID, "Device Attributes - User-Assigned ID code/number (Obj:00, Var:246)" },
910 { AL_OBJ_DA_DEVNAME, "Device Attributes - User-Assigned Device Name (Obj:00, Var:247)" },
911 { AL_OBJ_DA_SERNUM, "Device Attributes - Device Serial Number (Obj:00, Var:248)" },
912 { AL_OBJ_DA_CONF, "Device Attributes - DNP Subset and Conformance (Obj:00, Var:249)" },
913 { AL_OBJ_DA_PROD, "Device Attributes - Device Product Name and Model (Obj:00, Var:250)" },
914 { AL_OBJ_DA_MFG, "Device Attributes - Device Manufacturers Name (Obj:00, Var:252)" },
915 { AL_OBJ_DA_ALL, "Device Attributes - Non-specific All-attributes Request (Obj:00, Var:254)" },
916 { AL_OBJ_DA_LVAR, "Device Attributes - List of Attribute Variations (Obj:00, Var:255)" },
917 { AL_OBJ_BI_ALL, "Binary Input Default Variation (Obj:01, Var:Default)" },
918 { AL_OBJ_BI_1BIT, "Single-Bit Binary Input (Obj:01, Var:01)" },
919 { AL_OBJ_BI_STAT, "Binary Input With Status (Obj:01, Var:02)" },
920 { AL_OBJ_BIC_ALL, "Binary Input Change Default Variation (Obj:02, Var:Default)" },
921 { AL_OBJ_BIC_NOTIME, "Binary Input Change Without Time (Obj:02, Var:01)" },
922 { AL_OBJ_BIC_TIME, "Binary Input Change With Time (Obj:02, Var:02)" },
923 { AL_OBJ_BIC_RTIME, "Binary Input Change With Relative Time (Obj:02, Var:03)" },
924 { AL_OBJ_2BI_ALL, "Double-bit Input Default Variation (Obj:03, Var:Default)" },
925 { AL_OBJ_2BI_NF, "Double-bit Input No Flags (Obj:03, Var:01)" },
926 { AL_OBJ_2BI_STAT, "Double-bit Input With Status (Obj:03, Var:02)" },
927 { AL_OBJ_2BIC_ALL, "Double-bit Input Change Default Variation (Obj:04, Var:Default)" },
928 { AL_OBJ_2BIC_NOTIME, "Double-bit Input Change Without Time (Obj:04, Var:01)" },
929 { AL_OBJ_2BIC_TIME, "Double-bit Input Change With Time (Obj:04, Var:02)" },
930 { AL_OBJ_2BIC_RTIME, "Double-bit Input Change With Relative Time (Obj:04, Var:03)" },
931 { AL_OBJ_BO_ALL, "Binary Output Default Variation (Obj:10, Var:Default)" },
932 { AL_OBJ_BO, "Binary Output (Obj:10, Var:01)" },
933 { AL_OBJ_BO_STAT, "Binary Output Status (Obj:10, Var:02)" },
934 { AL_OBJ_BOC_ALL, "Binary Output Change Default Variation (Obj:11, Var:Default)" },
935 { AL_OBJ_BOC_NOTIME, "Binary Output Change Without Time (Obj:11, Var:01)" },
936 { AL_OBJ_BOC_TIME, "Binary Output Change With Time (Obj:11, Var:02)" },
937 { AL_OBJ_CTLOP_BLK, "Control Relay Output Block (Obj:12, Var:01)" },
938 { AL_OBJ_CTR_ALL, "Binary Counter Default Variation (Obj:20, Var:Default)" },
939 { AL_OBJ_CTR_32, "32-Bit Binary Counter (Obj:20, Var:01)" },
940 { AL_OBJ_CTR_16, "16-Bit Binary Counter (Obj:20, Var:02)" },
941 { AL_OBJ_DCTR_32, "32-Bit Binary Delta Counter (Obj:20, Var:03)" },
942 { AL_OBJ_DCTR_16, "16-Bit Binary Delta Counter (Obj:20, Var:04)" },
943 { AL_OBJ_CTR_32NF, "32-Bit Binary Counter Without Flag (Obj:20, Var:05)" },
944 { AL_OBJ_CTR_16NF, "16-Bit Binary Counter Without Flag (Obj:20, Var:06)" },
945 { AL_OBJ_DCTR_32NF, "32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07)" },
946 { AL_OBJ_DCTR_16NF, "16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08)" },
947 { AL_OBJ_FCTR_ALL, "Frozen Binary Counter Default Variation (Obj:21, Var:Default)" },
948 { AL_OBJ_FCTR_32, "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
949 { AL_OBJ_FCTR_16, "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
950 { AL_OBJ_FDCTR_32, "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
951 { AL_OBJ_FDCTR_16, "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
952 { AL_OBJ_FCTR_32T, "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
953 { AL_OBJ_FCTR_16T, "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
954 { AL_OBJ_FDCTR_32T, "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
955 { AL_OBJ_FDCTR_16T, "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
956 { AL_OBJ_FCTR_32NF, "32-Bit Frozen Binary Counter Without Flag (Obj:21, Var:05)" },
957 { AL_OBJ_FCTR_16NF, "16-Bit Frozen Binary Counter Without Flag (Obj:21, Var:06)" },
958 { AL_OBJ_FDCTR_32NF, "32-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:07)" },
959 { AL_OBJ_FDCTR_16NF, "16-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:08)" },
960 { AL_OBJ_CTRC_ALL, "Binary Counter Change Default Variation (Obj:22, Var:Default)" },
961 { AL_OBJ_CTRC_32, "32-Bit Counter Change Event w/o Time (Obj:22, Var:01)" },
962 { AL_OBJ_CTRC_16, "16-Bit Counter Change Event w/o Time (Obj:22, Var:02)" },
963 { AL_OBJ_DCTRC_32, "32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03)" },
964 { AL_OBJ_DCTRC_16, "16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04)" },
965 { AL_OBJ_CTRC_32T, "32-Bit Counter Change Event with Time (Obj:22, Var:05)" },
966 { AL_OBJ_CTRC_16T, "16-Bit Counter Change Event with Time (Obj:22, Var:06)" },
967 { AL_OBJ_DCTRC_32T, "32-Bit Delta Counter Change Event with Time (Obj:22, Var:07)" },
968 { AL_OBJ_DCTRC_16T, "16-Bit Delta Counter Change Event with Time (Obj:22, Var:08)" },
969 { AL_OBJ_FCTRC_ALL, "Frozen Binary Counter Change Default Variation (Obj:23, Var:Default)" },
970 { AL_OBJ_FCTRC_32, "32-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:01)" },
971 { AL_OBJ_FCTRC_16, "16-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:02)" },
972 { AL_OBJ_FDCTRC_32, "32-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:03)" },
973 { AL_OBJ_FDCTRC_16, "16-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:04)" },
974 { AL_OBJ_FCTRC_32T, "32-Bit Frozen Counter Change Event with Time (Obj:23, Var:05)" },
975 { AL_OBJ_FCTRC_16T, "16-Bit Frozen Counter Change Event with Time (Obj:23, Var:06)" },
976 { AL_OBJ_FDCTRC_32T, "32-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:07)" },
977 { AL_OBJ_FDCTRC_16T, "16-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:08)" },
978 { AL_OBJ_AI_ALL, "Analog Input Default Variation (Obj:30, Var:Default)" },
979 { AL_OBJ_AI_32, "32-Bit Analog Input (Obj:30, Var:01)" },
980 { AL_OBJ_AI_16, "16-Bit Analog Input (Obj:30, Var:02)" },
981 { AL_OBJ_AI_32NF, "32-Bit Analog Input Without Flag (Obj:30, Var:03)" },
982 { AL_OBJ_AI_16NF, "16-Bit Analog Input Without Flag (Obj:30, Var:04)" },
983 { AL_OBJ_AI_FLT, "32-Bit Floating Point Input (Obj:30, Var:05)" },
984 { AL_OBJ_AI_DBL, "64-Bit Floating Point Input (Obj:30, Var:06)" },
985 { AL_OBJ_AIF_FLT, "32-Bit Frozen Floating Point Input (Obj:31, Var:07)" },
986 { AL_OBJ_AIF_DBL, "64-Bit Frozen Floating Point Input (Obj:31, Var:08)" },
987 { AL_OBJ_AIC_ALL, "Analog Input Change Default Variation (Obj:32, Var:Default)" },
988 { AL_OBJ_AIC_32NT, "32-Bit Analog Change Event w/o Time (Obj:32, Var:01)" },
989 { AL_OBJ_AIC_16NT, "16-Bit Analog Change Event w/o Time (Obj:32, Var:02)" },
990 { AL_OBJ_AIC_32T, "32-Bit Analog Change Event with Time (Obj:32, Var:03)" },
991 { AL_OBJ_AIC_16T, "16-Bit Analog Change Event with Time (Obj:32, Var:04)" },
992 { AL_OBJ_AIC_FLTNT, "32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05)" },
993 { AL_OBJ_AIC_DBLNT, "64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06)" },
994 { AL_OBJ_AIC_FLTT, "32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07)" },
995 { AL_OBJ_AIC_DBLT, "64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08)" },
996 { AL_OBJ_AIFC_FLTNT, "32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05)" },
997 { AL_OBJ_AIFC_DBLNT, "64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06)" },
998 { AL_OBJ_AIFC_FLTT, "32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07)" },
999 { AL_OBJ_AIFC_DBLT, "64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08)" },
1000 { AL_OBJ_AIDB_ALL, "Analog Input Deadband Default Variation (Obj:34, Var:Default)" },
1001 { AL_OBJ_AIDB_16, "16-Bit Analog Input Deadband (Obj:34, Var:01)" },
1002 { AL_OBJ_AIDB_32, "32-Bit Analog Input Deadband (Obj:34, Var:02)" },
1003 { AL_OBJ_AIDB_FLT, "32-Bit Floating Point Analog Input Deadband (Obj:34, Var:03)" },
1004 { AL_OBJ_AO_ALL, "Analog Output Default Variation (Obj:40, Var:Default)" },
1005 { AL_OBJ_AO_32, "32-Bit Analog Output Status (Obj:40, Var:01)" },
1006 { AL_OBJ_AO_16, "16-Bit Analog Output Status (Obj:40, Var:02)" },
1007 { AL_OBJ_AO_FLT, "32-Bit Floating Point Output Status (Obj:40, Var:03)" },
1008 { AL_OBJ_AO_DBL, "64-Bit Floating Point Output Status (Obj:40, Var:04)" },
1009 { AL_OBJ_AO_32OPB, "32-Bit Analog Output Block (Obj:41, Var:01)" },
1010 { AL_OBJ_AO_16OPB, "16-Bit Analog Output Block (Obj:41, Var:02)" },
1011 { AL_OBJ_AO_FLTOPB, "32-Bit Floating Point Output Block (Obj:41, Var:03)" },
1012 { AL_OBJ_AO_DBLOPB, "64-Bit Floating Point Output Block (Obj:41, Var:04)" },
1013 { AL_OBJ_AOC_ALL, "Analog Output Event Default Variation (Obj:42, Var:Default)" },
1014 { AL_OBJ_AOC_32NT, "32-Bit Analog Output Event w/o Time (Obj:42, Var:01)" },
1015 { AL_OBJ_AOC_16NT, "16-Bit Analog Output Event w/o Time (Obj:42, Var:02)" },
1016 { AL_OBJ_AOC_32T, "32-Bit Analog Output Event with Time (Obj:42, Var:03)" },
1017 { AL_OBJ_AOC_16T, "16-Bit Analog Output Event with Time (Obj:42, Var:04)" },
1018 { AL_OBJ_AOC_FLTNT, "32-Bit Floating Point Output Event w/o Time (Obj:42, Var:05)" },
1019 { AL_OBJ_AOC_DBLNT, "64-Bit Floating Point Output Event w/o Time (Obj:42, Var:06)" },
1020 { AL_OBJ_AOC_FLTT, "32-Bit Floating Point Output Event w/ Time (Obj:42, Var:07)" },
1021 { AL_OBJ_AOC_DBLT, "64-Bit Floating Point Output Event w/ Time (Obj:42, Var:08)" },
1022 { AL_OBJ_TD_ALL, "Time and Date Default Variations (Obj:50, Var:Default)" },
1023 { AL_OBJ_TD, "Time and Date (Obj:50, Var:01)" },
1024 { AL_OBJ_TDI, "Time and Date w/Interval (Obj:50, Var:02)" },
1025 { AL_OBJ_TDR, "Last Recorded Time and Date (Obj:50, Var:03)" },
1026 { AL_OBJ_TDCTO, "Time and Date CTO (Obj:51, Var:01)" },
1027 { AL_OBJ_TDELAYF, "Time Delay - Fine (Obj:52, Var:02)" },
1028 { AL_OBJ_CLASS0, "Class 0 Data (Obj:60, Var:01)" },
1029 { AL_OBJ_CLASS1, "Class 1 Data (Obj:60, Var:02)" },
1030 { AL_OBJ_CLASS2, "Class 2 Data (Obj:60, Var:03)" },
1031 { AL_OBJ_CLASS3, "Class 3 Data (Obj:60, Var:04)" },
1032 { AL_OBJ_FILE_CMD, "File Control - File Command (Obj:70, Var:03)" },
1033 { AL_OBJ_FILE_STAT, "File Control - File Status (Obj:70, Var:04)" },
1034 { AL_OBJ_FILE_TRANS, "File Control - File Transport (Obj:70, Var:05)" },
1035 { AL_OBJ_FILE_TRAN_ST, "File Control - File Transport Status (Obj:70, Var:06)" },
1036 { AL_OBJ_IIN, "Internal Indications (Obj:80, Var:01)" },
1037 { AL_OBJ_DS_PROTO, "Data-Set Prototype, with UUID (Obj:85, Var:01)" },
1038 { AL_OBJ_DSD_CONT, "Data-Set Descriptor, Data-Set Contents (Obj:86, Var:01)" },
1039 { AL_OBJ_DSD_CHAR, "Data-Set Descriptor, Characteristics (Obj:86, Var:02)" },
1040 { AL_OBJ_DSD_PIDX, "Data-Set Descriptor, Point Index Attributes (Obj:86, Var:03)" },
1041 { AL_OBJ_DS_PV, "Data-Set, Present Value (Obj:87, Var:01)" },
1042 { AL_OBJ_DS_SS, "Data-Set, Snapshot (Obj:88, Var:01)" },
1043 { AL_OBJ_OCT, "Octet String (Obj:110)" },
1044 { AL_OBJ_OCT_EVT, "Octet String Event (Obj:111)" },
1045 { AL_OBJ_VT_OBLK, "Virtual Terminal Output Block (Obj:112)" },
1046 { AL_OBJ_VT_EVTD, "Virtual Terminal Event Data (Obj:113)" },
1047 { 0, NULL }
1049 static value_string_ext dnp3_al_obj_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_obj_vals);
1051 /* Application Layer Control Code 'Operation Type' Values */
1052 static const value_string dnp3_al_ctlc_code_vals[] = {
1053 { AL_OBJCTLC_CODE0, "NUL Operation" },
1054 { AL_OBJCTLC_CODE1, "Pulse On" },
1055 { AL_OBJCTLC_CODE2, "Pulse Off" },
1056 { AL_OBJCTLC_CODE3, "Latch On" },
1057 { AL_OBJCTLC_CODE4, "Latch Off" },
1058 { 0, NULL }
1061 /* Application Layer Control Code 'Clear Field' Values */
1062 static const value_string dnp3_al_ctlc_misc_vals[] = {
1063 { AL_OBJCTLC_QUEUE, "Queue" },
1064 { AL_OBJCTLC_CLEAR, "Clear" },
1065 { AL_OBJCTLC_NOTSET, "Not Set" },
1066 { AL_OBJCTLC_BOTHSET, "Queue and Clear" },
1067 { 0, NULL }
1070 /* Application Layer Control Code 'Trip Close Code' Values */
1071 static const value_string dnp3_al_ctlc_tc_vals[] = {
1072 { AL_OBJCTLC_TC0, "NUL" },
1073 { AL_OBJCTLC_TC1, "Close" },
1074 { AL_OBJCTLC_TC2, "Trip" },
1075 { AL_OBJCTLC_TC3, "Reserved" },
1076 { 0, NULL }
1079 /* Application Layer Control Status Values */
1080 static const value_string dnp3_al_ctl_status_vals[] = {
1081 { AL_OBJCTL_STAT0, "Req. Accepted/Init/Queued" },
1082 { AL_OBJCTL_STAT1, "Req. Not Accepted; Arm-Timer Expired" },
1083 { AL_OBJCTL_STAT2, "Req. Not Accepted; No 'SELECT' Received" },
1084 { AL_OBJCTL_STAT3, "Req. Not Accepted; Format Err. in Ctl Req." },
1085 { AL_OBJCTL_STAT4, "Ctl Oper. Not Supported For This Point" },
1086 { AL_OBJCTL_STAT5, "Req. Not Accepted; Ctrl Queue Full/Point Active" },
1087 { AL_OBJCTL_STAT6, "Req. Not Accepted; Ctrl Hardware Problems" },
1088 { AL_OBJCTL_STAT7, "Req. Not Accepted; Local/Remote switch in Local" },
1089 { AL_OBJCTL_STAT8, "Req. Not Accepted; Too many operations" },
1090 { AL_OBJCTL_STAT9, "Req. Not Accepted; Insufficient authorization" },
1091 { AL_OBJCTL_STAT10, "Req. Not Accepted; Local automation proc active" },
1092 { 0, NULL }
1094 static value_string_ext dnp3_al_ctl_status_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_ctl_status_vals);
1096 #if 0
1097 /* Application Layer Binary Input Quality Flag Values */
1098 static const value_string dnp3_al_biflag_vals[] = {
1099 { AL_OBJ_BI_FLAG0, "Online" },
1100 { AL_OBJ_BI_FLAG1, "Restart" },
1101 { AL_OBJ_BI_FLAG2, "Comm Fail" },
1102 { AL_OBJ_BI_FLAG3, "Remote Forced" },
1103 { AL_OBJ_BI_FLAG4, "Locally Forced" },
1104 { AL_OBJ_BI_FLAG5, "Chatter Filter" },
1105 { 0, NULL }
1107 #endif
1109 #if 0
1110 /* Application Layer Counter Quality Flag Values */
1111 static const value_string dnp3_al_ctrflag_vals[] = {
1112 { AL_OBJ_CTR_FLAG0, "Online" },
1113 { AL_OBJ_CTR_FLAG1, "Restart" },
1114 { AL_OBJ_CTR_FLAG2, "Comm Fail" },
1115 { AL_OBJ_CTR_FLAG3, "Remote Forced" },
1116 { AL_OBJ_CTR_FLAG4, "Locally Forced" },
1117 { AL_OBJ_CTR_FLAG5, "Roll-Over" },
1118 { AL_OBJ_CTR_FLAG6, "Discontinuity" },
1119 { 0, NULL }
1121 #endif
1123 #if 0
1124 /* Application Layer Analog Input Quality Flag Values */
1125 static const value_string dnp3_al_aiflag_vals[] = {
1126 { AL_OBJ_AI_FLAG0, "Online" },
1127 { AL_OBJ_AI_FLAG1, "Restart" },
1128 { AL_OBJ_AI_FLAG2, "Comm Fail" },
1129 { AL_OBJ_AI_FLAG3, "Remote Forced" },
1130 { AL_OBJ_AI_FLAG4, "Locally Forced" },
1131 { AL_OBJ_AI_FLAG5, "Over-Range" },
1132 { AL_OBJ_AI_FLAG6, "Ref. Error" },
1133 { 0, NULL }
1135 #endif
1137 /* Application Layer File Control Mode values */
1138 static const value_string dnp3_al_file_mode_vals[] = {
1139 { AL_OBJ_FILE_MODE_NULL, "NULL" },
1140 { AL_OBJ_FILE_MODE_READ, "READ" },
1141 { AL_OBJ_FILE_MODE_WRITE, "WRITE" },
1142 { AL_OBJ_FILE_MODE_APPEND, "APPEND" },
1143 { 0, NULL }
1146 /* Application Layer File Control Status values */
1147 static const value_string dnp3_al_file_status_vals[] = {
1148 { 0, "SUCCESS" },
1149 { 1, "PERMISSION DENIED" },
1150 { 2, "INVALID MODE" },
1151 { 3, "FILE NOT FOUND" },
1152 { 4, "FILE LOCKED" },
1153 { 5, "TOO MANY OPEN" },
1154 { 6, "INVALID HANDLE" },
1155 { 7, "WRITE BLOCK SIZE" },
1156 { 8, "COMM LOST" },
1157 { 9, "CANNOT ABORT" },
1158 { 16, "NOT OPENED" },
1159 { 17, "HANDLE EXPIRED" },
1160 { 18, "BUFFER OVERRUN" },
1161 { 19, "FATAL" },
1162 { 20, "BLOCK SEQUENCE" },
1163 { 255, "UNDEFINED" },
1164 { 0, NULL }
1166 static value_string_ext dnp3_al_file_status_vals_ext = VALUE_STRING_EXT_INIT(dnp3_al_file_status_vals);
1168 /* Application Layer Data Type values */
1169 static const value_string dnp3_al_data_type_vals[] = {
1170 { 0x00, "NONE (Placeholder)" },
1171 { 0x01, "VSTR (Visible ASCII String)" },
1172 { 0x02, "UINT (Unsigned Integer)" },
1173 { 0x03, "INT (Signed Integer)" },
1174 { 0x04, "FLT (Floating Point)" },
1175 { 0x05, "OSTR (Octet String)" },
1176 { 0x06, "BSTR (Bit String)" },
1177 { 0x07, "TIME (DNP3 Time UINT48)" },
1178 { 0x08, "UNCD (Unicode String)" },
1179 { 0xFE, "U8BS8LIST (List of UINT8 - BSTR8 pairs)" },
1180 { 0xFF, "U8BS8EXLIST (Extended List of UINT8 - BSTR8 pairs)" },
1181 { 0, NULL }
1185 /* Initialize the subtree pointers */
1186 static gint ett_dnp3 = -1;
1187 static gint ett_dnp3_dl = -1;
1188 static gint ett_dnp3_dl_ctl = -1;
1189 static gint ett_dnp3_tr_ctl = -1;
1190 static gint ett_dnp3_al_data = -1;
1191 static gint ett_dnp3_al = -1;
1192 static gint ett_dnp3_al_ctl = -1;
1193 static gint ett_dnp3_al_obj_point_tcc = -1;
1195 /* Added for Application Layer Decoding */
1196 static gint ett_dnp3_al_iin = -1;
1197 static gint ett_dnp3_al_obj = -1;
1198 static gint ett_dnp3_al_obj_qualifier = -1;
1199 static gint ett_dnp3_al_obj_range = -1;
1200 static gint ett_dnp3_al_objdet = -1;
1201 static gint ett_dnp3_al_obj_quality = -1;
1202 static gint ett_dnp3_al_obj_point = -1;
1203 static gint ett_dnp3_al_obj_point_perms = -1;
1205 static expert_field ei_dnp_num_items_neg = EI_INIT;
1206 static expert_field ei_dnp_invalid_length = EI_INIT;
1207 static expert_field ei_dnp_iin_abnormal = EI_INIT;
1209 /* Tables for reassembly of fragments. */
1210 static reassembly_table al_reassembly_table;
1211 static GHashTable *dl_conversation_table = NULL;
1213 /* Data-Link-Layer Conversation Key Structure */
1214 typedef struct _dl_conversation_key
1216 guint32 conversation; /* TCP / UDP conversation index */
1217 guint16 src; /* DNP3.0 Source Address */
1218 guint16 dst; /* DNP3.0 Destination Address */
1219 } dl_conversation_key_t;
1221 /* Data-Link-Layer conversation key equality function */
1222 static gboolean
1223 dl_conversation_equal(gconstpointer v, gconstpointer w)
1225 const dl_conversation_key_t* v1 = (const dl_conversation_key_t*)v;
1226 const dl_conversation_key_t* v2 = (const dl_conversation_key_t*)w;
1228 if ((v1->conversation == v2->conversation) &&
1229 (v1->src == v2->src) &&
1230 (v1->dst == v2->dst))
1232 return TRUE;
1235 return FALSE;
1238 /* Data-Link-Layer conversation key hash function */
1239 static guint
1240 dl_conversation_hash(gconstpointer v)
1242 const dl_conversation_key_t *key = (const dl_conversation_key_t*)v;
1243 guint val;
1245 val = key->conversation + (key->src << 16) + key->dst;
1247 return val;
1250 /* ************************************************************************* */
1251 /* Header values for reassembly */
1252 /* ************************************************************************* */
1253 static int hf_dnp3_fragment = -1;
1254 static int hf_dnp3_fragments = -1;
1255 static int hf_dnp3_fragment_overlap = -1;
1256 static int hf_dnp3_fragment_overlap_conflict = -1;
1257 static int hf_dnp3_fragment_multiple_tails = -1;
1258 static int hf_dnp3_fragment_too_long_fragment = -1;
1259 static int hf_dnp3_fragment_error = -1;
1260 static int hf_dnp3_fragment_count = -1;
1261 static int hf_dnp3_fragment_reassembled_in = -1;
1262 static int hf_dnp3_fragment_reassembled_length = -1;
1263 static gint ett_dnp3_fragment = -1;
1264 static gint ett_dnp3_fragments = -1;
1266 static const fragment_items dnp3_frag_items = {
1267 &ett_dnp3_fragment,
1268 &ett_dnp3_fragments,
1269 &hf_dnp3_fragments,
1270 &hf_dnp3_fragment,
1271 &hf_dnp3_fragment_overlap,
1272 &hf_dnp3_fragment_overlap_conflict,
1273 &hf_dnp3_fragment_multiple_tails,
1274 &hf_dnp3_fragment_too_long_fragment,
1275 &hf_dnp3_fragment_error,
1276 &hf_dnp3_fragment_count,
1277 &hf_dnp3_fragment_reassembled_in,
1278 &hf_dnp3_fragment_reassembled_length,
1279 /* Reassembled data field */
1280 NULL,
1281 "DNP 3.0 fragments"
1284 /* Conversation stuff, used for tracking application message fragments */
1285 /* the number of entries in the memory chunk array */
1286 #define dnp3_conv_init_count 50
1288 /* Conversation structure */
1289 typedef struct {
1290 guint conv_seq_number;
1291 } dnp3_conv_t;
1293 /* The conversation sequence number */
1294 static guint seq_number = 0;
1296 /* Heuristically detect DNP3 over TCP/UDP */
1297 static gboolean dnp3_heuristics = FALSE;
1298 /* desegmentation of DNP3 over TCP */
1299 static gboolean dnp3_desegment = TRUE;
1301 /* Enum for different quality type fields */
1302 enum QUALITY_TYPE {
1303 BIN_IN,
1304 BIN_OUT,
1305 ANA_IN,
1306 ANA_OUT,
1307 COUNTER
1310 /*****************************************************************/
1311 /* */
1312 /* CRC LOOKUP TABLE */
1313 /* ================ */
1314 /* The following CRC lookup table was generated automagically */
1315 /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
1316 /* Program V1.0 using the following model parameters: */
1317 /* */
1318 /* Width : 2 bytes. */
1319 /* Poly : 0x3D65 */
1320 /* Reverse : TRUE. */
1321 /* */
1322 /* For more information on the Rocksoft^tm Model CRC Algorithm, */
1323 /* see the document titled "A Painless Guide to CRC Error */
1324 /* Detection Algorithms" by Ross Williams */
1325 /* (ross@guest.adelaide.edu.au.). This document is likely to be */
1326 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
1327 /* */
1328 /*****************************************************************/
1330 static guint16 crctable[256] =
1332 0x0000, 0x365E, 0x6CBC, 0x5AE2, 0xD978, 0xEF26, 0xB5C4, 0x839A,
1333 0xFF89, 0xC9D7, 0x9335, 0xA56B, 0x26F1, 0x10AF, 0x4A4D, 0x7C13,
1334 0xB26B, 0x8435, 0xDED7, 0xE889, 0x6B13, 0x5D4D, 0x07AF, 0x31F1,
1335 0x4DE2, 0x7BBC, 0x215E, 0x1700, 0x949A, 0xA2C4, 0xF826, 0xCE78,
1336 0x29AF, 0x1FF1, 0x4513, 0x734D, 0xF0D7, 0xC689, 0x9C6B, 0xAA35,
1337 0xD626, 0xE078, 0xBA9A, 0x8CC4, 0x0F5E, 0x3900, 0x63E2, 0x55BC,
1338 0x9BC4, 0xAD9A, 0xF778, 0xC126, 0x42BC, 0x74E2, 0x2E00, 0x185E,
1339 0x644D, 0x5213, 0x08F1, 0x3EAF, 0xBD35, 0x8B6B, 0xD189, 0xE7D7,
1340 0x535E, 0x6500, 0x3FE2, 0x09BC, 0x8A26, 0xBC78, 0xE69A, 0xD0C4,
1341 0xACD7, 0x9A89, 0xC06B, 0xF635, 0x75AF, 0x43F1, 0x1913, 0x2F4D,
1342 0xE135, 0xD76B, 0x8D89, 0xBBD7, 0x384D, 0x0E13, 0x54F1, 0x62AF,
1343 0x1EBC, 0x28E2, 0x7200, 0x445E, 0xC7C4, 0xF19A, 0xAB78, 0x9D26,
1344 0x7AF1, 0x4CAF, 0x164D, 0x2013, 0xA389, 0x95D7, 0xCF35, 0xF96B,
1345 0x8578, 0xB326, 0xE9C4, 0xDF9A, 0x5C00, 0x6A5E, 0x30BC, 0x06E2,
1346 0xC89A, 0xFEC4, 0xA426, 0x9278, 0x11E2, 0x27BC, 0x7D5E, 0x4B00,
1347 0x3713, 0x014D, 0x5BAF, 0x6DF1, 0xEE6B, 0xD835, 0x82D7, 0xB489,
1348 0xA6BC, 0x90E2, 0xCA00, 0xFC5E, 0x7FC4, 0x499A, 0x1378, 0x2526,
1349 0x5935, 0x6F6B, 0x3589, 0x03D7, 0x804D, 0xB613, 0xECF1, 0xDAAF,
1350 0x14D7, 0x2289, 0x786B, 0x4E35, 0xCDAF, 0xFBF1, 0xA113, 0x974D,
1351 0xEB5E, 0xDD00, 0x87E2, 0xB1BC, 0x3226, 0x0478, 0x5E9A, 0x68C4,
1352 0x8F13, 0xB94D, 0xE3AF, 0xD5F1, 0x566B, 0x6035, 0x3AD7, 0x0C89,
1353 0x709A, 0x46C4, 0x1C26, 0x2A78, 0xA9E2, 0x9FBC, 0xC55E, 0xF300,
1354 0x3D78, 0x0B26, 0x51C4, 0x679A, 0xE400, 0xD25E, 0x88BC, 0xBEE2,
1355 0xC2F1, 0xF4AF, 0xAE4D, 0x9813, 0x1B89, 0x2DD7, 0x7735, 0x416B,
1356 0xF5E2, 0xC3BC, 0x995E, 0xAF00, 0x2C9A, 0x1AC4, 0x4026, 0x7678,
1357 0x0A6B, 0x3C35, 0x66D7, 0x5089, 0xD313, 0xE54D, 0xBFAF, 0x89F1,
1358 0x4789, 0x71D7, 0x2B35, 0x1D6B, 0x9EF1, 0xA8AF, 0xF24D, 0xC413,
1359 0xB800, 0x8E5E, 0xD4BC, 0xE2E2, 0x6178, 0x5726, 0x0DC4, 0x3B9A,
1360 0xDC4D, 0xEA13, 0xB0F1, 0x86AF, 0x0535, 0x336B, 0x6989, 0x5FD7,
1361 0x23C4, 0x159A, 0x4F78, 0x7926, 0xFABC, 0xCCE2, 0x9600, 0xA05E,
1362 0x6E26, 0x5878, 0x029A, 0x34C4, 0xB75E, 0x8100, 0xDBE2, 0xEDBC,
1363 0x91AF, 0xA7F1, 0xFD13, 0xCB4D, 0x48D7, 0x7E89, 0x246B, 0x1235
1366 /*****************************************************************/
1367 /* End of CRC Lookup Table */
1368 /*****************************************************************/
1370 /* calculates crc given a buffer of characters and a length of buffer */
1371 static guint16
1372 calculateCRC(const void *buf, guint len) {
1373 guint16 crc = 0;
1374 const guint8 *p = (const guint8 *)buf;
1375 while (len-- > 0)
1376 crc = crctable[(crc ^ *p++) & 0xff] ^ (crc >> 8);
1377 return ~crc;
1380 /*****************************************************************/
1381 /* Adds text to item, with trailing "," if required */
1382 /*****************************************************************/
1383 static gboolean
1384 add_item_text(proto_item *item, const gchar *text, gboolean comma_needed)
1386 if (comma_needed) {
1387 proto_item_append_text(item, ", ");
1389 proto_item_append_text(item, "%s", text);
1390 return TRUE;
1393 /*****************************************************************/
1394 /* Application Layer Process Internal Indications (IIN) */
1395 /*****************************************************************/
1396 static void
1397 dnp3_al_process_iin(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *al_tree)
1400 guint16 al_iin;
1401 proto_item *tiin;
1402 proto_tree *iin_tree;
1403 gboolean comma_needed = FALSE;
1405 al_iin = tvb_get_ntohs(tvb, offset);
1407 tiin = proto_tree_add_uint_format(al_tree, hf_dnp3_al_iin, tvb, offset, 2, al_iin,
1408 "Internal Indications: ");
1409 if (al_iin & AL_IIN_RST) comma_needed = add_item_text(tiin, "Device Restart", comma_needed);
1410 if (al_iin & AL_IIN_DOL) comma_needed = add_item_text(tiin, "Outputs in Local", comma_needed);
1411 if (al_iin & AL_IIN_DT) comma_needed = add_item_text(tiin, "Device Trouble", comma_needed);
1412 if (al_iin & AL_IIN_TSR) comma_needed = add_item_text(tiin, "Time Sync Required", comma_needed);
1413 if (al_iin & AL_IIN_CLS3D) comma_needed = add_item_text(tiin, "Class 3 Data Available", comma_needed);
1414 if (al_iin & AL_IIN_CLS2D) comma_needed = add_item_text(tiin, "Class 2 Data Available", comma_needed);
1415 if (al_iin & AL_IIN_CLS1D) comma_needed = add_item_text(tiin, "Class 1 Data Available", comma_needed);
1416 if (al_iin & AL_IIN_BMSG) comma_needed = add_item_text(tiin, "Broadcast Message Rx'd", comma_needed);
1417 if (al_iin & AL_IIN_CC) comma_needed = add_item_text(tiin, "Device Configuration Corrupt", comma_needed);
1418 if (al_iin & AL_IIN_OAE) comma_needed = add_item_text(tiin, "Operation Already Executing", comma_needed);
1419 if (al_iin & AL_IIN_EBO) comma_needed = add_item_text(tiin, "Event Buffer Overflow", comma_needed);
1420 if (al_iin & AL_IIN_PIOOR) comma_needed = add_item_text(tiin, "Parameters Invalid or Out of Range", comma_needed);
1421 if (al_iin & AL_IIN_OBJU) comma_needed = add_item_text(tiin, "Requested Objects Unknown", comma_needed);
1422 if (al_iin & AL_IIN_FCNI) /*comma_needed = */add_item_text(tiin, "Function code not implemented", comma_needed);
1423 proto_item_append_text(tiin, " (0x%04x)", al_iin);
1425 /* If IIN indicates an abnormal condition, add expert info */
1426 if ((al_iin & AL_IIN_DT) || (al_iin & AL_IIN_CC) || (al_iin & AL_IIN_OAE) || (al_iin & AL_IIN_EBO) ||
1427 (al_iin & AL_IIN_PIOOR) || (al_iin & AL_IIN_OBJU) || (al_iin & AL_IIN_FCNI)) {
1428 expert_add_info(pinfo, tiin, &ei_dnp_iin_abnormal);
1431 iin_tree = proto_item_add_subtree(tiin, ett_dnp3_al_iin);
1432 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_rst, tvb, offset, 2, ENC_BIG_ENDIAN);
1433 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_dt, tvb, offset, 2, ENC_BIG_ENDIAN);
1434 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_dol, tvb, offset, 2, ENC_BIG_ENDIAN);
1435 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_tsr, tvb, offset, 2, ENC_BIG_ENDIAN);
1436 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cls3d, tvb, offset, 2, ENC_BIG_ENDIAN);
1437 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cls2d, tvb, offset, 2, ENC_BIG_ENDIAN);
1438 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cls1d, tvb, offset, 2, ENC_BIG_ENDIAN);
1439 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_bmsg, tvb, offset, 2, ENC_BIG_ENDIAN);
1440 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cc, tvb, offset, 2, ENC_BIG_ENDIAN);
1441 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_oae, tvb, offset, 2, ENC_BIG_ENDIAN);
1442 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_ebo, tvb, offset, 2, ENC_BIG_ENDIAN);
1443 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_pioor, tvb, offset, 2, ENC_BIG_ENDIAN);
1444 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_obju, tvb, offset, 2, ENC_BIG_ENDIAN);
1445 proto_tree_add_item(iin_tree, hf_dnp3_al_iin_fcni, tvb, offset, 2, ENC_BIG_ENDIAN);
1448 /*****************************************************************/
1449 /* Function to determine Application Layer Object Index size and */
1450 /* Point address. */
1451 /*****************************************************************/
1452 static int
1453 dnp3_al_obj_procindex(tvbuff_t *tvb, int offset, guint8 al_objq_index, guint32 *al_ptaddr, proto_tree *item_tree)
1455 int indexbytes = 0;
1456 proto_item *index_item;
1458 switch (al_objq_index)
1460 case AL_OBJQL_IDX_NI: /* No Index */
1461 indexbytes = 0;
1462 index_item = proto_tree_add_text(item_tree, tvb, offset, 0, "Point Index: %u", *al_ptaddr);
1463 PROTO_ITEM_SET_GENERATED(index_item);
1464 break;
1465 case AL_OBJQL_IDX_1O:
1466 *al_ptaddr = tvb_get_guint8(tvb, offset);
1467 proto_tree_add_item(item_tree, hf_dnp3_al_index8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1468 indexbytes = 1;
1469 break;
1470 case AL_OBJQL_IDX_2O:
1471 *al_ptaddr = tvb_get_letohs(tvb, offset);
1472 proto_tree_add_item(item_tree, hf_dnp3_al_index16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1473 indexbytes = 2;
1474 break;
1475 case AL_OBJQL_IDX_4O:
1476 *al_ptaddr = tvb_get_letohl(tvb, offset);
1477 proto_tree_add_item(item_tree, hf_dnp3_al_index32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1478 indexbytes = 4;
1479 break;
1480 case AL_OBJQL_IDX_1OS:
1481 *al_ptaddr = tvb_get_guint8(tvb, offset);
1482 proto_tree_add_item(item_tree, hf_dnp3_al_size8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1483 indexbytes = 1;
1484 break;
1485 case AL_OBJQL_IDX_2OS:
1486 *al_ptaddr = tvb_get_letohs(tvb, offset);
1487 proto_tree_add_item(item_tree, hf_dnp3_al_size16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1488 indexbytes = 2;
1489 break;
1490 case AL_OBJQL_IDX_4OS:
1491 *al_ptaddr = tvb_get_letohl(tvb, offset);
1492 proto_tree_add_item(item_tree, hf_dnp3_al_size32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1493 indexbytes = 4;
1494 break;
1496 return indexbytes;
1499 /*****************************************************************/
1500 /* Function to add the same string to two separate tree items */
1501 /*****************************************************************/
1502 static void
1503 dnp3_append_2item_text(proto_item *item1, proto_item *item2, const gchar *text)
1505 proto_item_append_text(item1, "%s", text);
1506 proto_item_append_text(item2, "%s", text);
1509 /*****************************************************************/
1510 /* Function to Determine Application Layer Point Quality Flags & */
1511 /* add Point Quality Flag Sub-Tree */
1512 /*****************************************************************/
1513 static void
1514 dnp3_al_obj_quality(tvbuff_t *tvb, int offset, guint8 al_ptflags, proto_tree *point_tree, proto_item *point_item, enum QUALITY_TYPE type)
1517 proto_tree *quality_tree;
1518 proto_item *quality_item;
1519 int hf0 = 0, hf1 = 0, hf2 = 0, hf3 = 0, hf4 = 0, hf5 = 0, hf6 = 0, hf7 = 0;
1521 /* Common code */
1522 proto_item_append_text(point_item, " (Quality: ");
1523 quality_item = proto_tree_add_text(point_tree, tvb, offset, 1, "Quality: ");
1524 quality_tree = proto_item_add_subtree(quality_item, ett_dnp3_al_obj_quality);
1526 if (al_ptflags & AL_OBJ_BI_FLAG0) {
1527 dnp3_append_2item_text(point_item, quality_item, "Online");
1529 else {
1530 dnp3_append_2item_text(point_item, quality_item, "Offline");
1532 if (al_ptflags & AL_OBJ_BI_FLAG1) dnp3_append_2item_text(point_item, quality_item, ", Restart");
1533 if (al_ptflags & AL_OBJ_BI_FLAG2) dnp3_append_2item_text(point_item, quality_item, ", Comm Fail");
1534 if (al_ptflags & AL_OBJ_BI_FLAG3) dnp3_append_2item_text(point_item, quality_item, ", Remote Force");
1535 if (al_ptflags & AL_OBJ_BI_FLAG4) dnp3_append_2item_text(point_item, quality_item, ", Local Force");
1537 switch (type) {
1538 case BIN_IN: /* Binary Input Quality flags */
1539 if (al_ptflags & AL_OBJ_BI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Chatter Filter");
1541 hf0 = hf_dnp3_al_biq_b0;
1542 hf1 = hf_dnp3_al_biq_b1;
1543 hf2 = hf_dnp3_al_biq_b2;
1544 hf3 = hf_dnp3_al_biq_b3;
1545 hf4 = hf_dnp3_al_biq_b4;
1546 hf5 = hf_dnp3_al_biq_b5;
1547 hf6 = hf_dnp3_al_biq_b6;
1548 hf7 = hf_dnp3_al_biq_b7;
1549 break;
1551 case BIN_OUT: /* Binary Output Quality flags */
1552 hf0 = hf_dnp3_al_boq_b0;
1553 hf1 = hf_dnp3_al_boq_b1;
1554 hf2 = hf_dnp3_al_boq_b2;
1555 hf3 = hf_dnp3_al_boq_b3;
1556 hf4 = hf_dnp3_al_boq_b4;
1557 hf5 = hf_dnp3_al_boq_b5;
1558 hf6 = hf_dnp3_al_boq_b6;
1559 hf7 = hf_dnp3_al_boq_b7;
1560 break;
1562 case ANA_IN: /* Analog Input Quality flags */
1563 if (al_ptflags & AL_OBJ_AI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Over-Range");
1564 if (al_ptflags & AL_OBJ_AI_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Reference Check");
1566 hf0 = hf_dnp3_al_aiq_b0;
1567 hf1 = hf_dnp3_al_aiq_b1;
1568 hf2 = hf_dnp3_al_aiq_b2;
1569 hf3 = hf_dnp3_al_aiq_b3;
1570 hf4 = hf_dnp3_al_aiq_b4;
1571 hf5 = hf_dnp3_al_aiq_b5;
1572 hf6 = hf_dnp3_al_aiq_b6;
1573 hf7 = hf_dnp3_al_aiq_b7;
1574 break;
1576 case ANA_OUT: /* Analog Output Quality flags */
1577 hf0 = hf_dnp3_al_aoq_b0;
1578 hf1 = hf_dnp3_al_aoq_b1;
1579 hf2 = hf_dnp3_al_aoq_b2;
1580 hf3 = hf_dnp3_al_aoq_b3;
1581 hf4 = hf_dnp3_al_aoq_b4;
1582 hf5 = hf_dnp3_al_aoq_b5;
1583 hf6 = hf_dnp3_al_aoq_b6;
1584 hf7 = hf_dnp3_al_aoq_b7;
1585 break;
1587 case COUNTER: /* Counter Quality flags */
1588 if (al_ptflags & AL_OBJ_CTR_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Roll-over");
1589 if (al_ptflags & AL_OBJ_CTR_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Discontinuity");
1591 hf0 = hf_dnp3_al_ctrq_b0;
1592 hf1 = hf_dnp3_al_ctrq_b1;
1593 hf2 = hf_dnp3_al_ctrq_b2;
1594 hf3 = hf_dnp3_al_ctrq_b3;
1595 hf4 = hf_dnp3_al_ctrq_b4;
1596 hf5 = hf_dnp3_al_ctrq_b5;
1597 hf6 = hf_dnp3_al_ctrq_b6;
1598 hf7 = hf_dnp3_al_ctrq_b7;
1599 break;
1602 if (quality_tree != NULL) {
1603 proto_tree_add_item(quality_tree, hf7, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1604 proto_tree_add_item(quality_tree, hf6, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1605 proto_tree_add_item(quality_tree, hf5, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1606 proto_tree_add_item(quality_tree, hf4, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1607 proto_tree_add_item(quality_tree, hf3, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1608 proto_tree_add_item(quality_tree, hf2, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1609 proto_tree_add_item(quality_tree, hf1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1610 proto_tree_add_item(quality_tree, hf0, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1612 proto_item_append_text(point_item, ")");
1615 /**********************************************************************/
1616 /* Function to convert DNP3 timestamp to nstime_t value */
1617 /**********************************************************************/
1618 /* 48-bit Time Format */
1619 /* MSB FF EE DD CC BB AA LSB */
1620 /* ffffffff eeeeeeee dddddddd cccccccc bbbbbbbb aaaaaaaa */
1621 /* 47 40 39 32 31 24 23 16 15 8 7 0 */
1622 /* */
1623 /* Value is ms since 00:00 on 1/1/1970 */
1624 /**********************************************************************/
1625 static void
1626 dnp3_al_get_timestamp(nstime_t *timestamp, tvbuff_t *tvb, int data_pos)
1629 guint32 hi, lo;
1630 guint64 time_ms;
1632 lo = tvb_get_letohs(tvb, data_pos);
1633 hi = tvb_get_letohl(tvb, data_pos + 2);
1635 time_ms = (guint64)hi * 0x10000 + lo;
1637 timestamp->secs = (long)(time_ms / 1000);
1638 timestamp->nsecs = (int)(time_ms % 1000) * 1000000;
1641 /*****************************************************************/
1642 /* Desc: Application Layer Process Object Details */
1643 /* Returns: New offset pointer into tvb */
1644 /*****************************************************************/
1645 static int
1646 dnp3_al_process_object(tvbuff_t *tvb, packet_info *pinfo, int offset,
1647 proto_tree *robj_tree, gboolean header_only,
1648 guint16 *al_objtype, nstime_t *al_cto)
1651 guint8 al_objq, al_objq_index, al_objq_code, al_oct_len = 0, bitindex;
1652 guint16 al_obj, temp;
1653 guint32 al_ptaddr = 0;
1654 int num_items = 0;
1655 int orig_offset, rangebytes = 0;
1656 proto_item *object_item, *qualifier_item, *range_item;
1657 proto_tree *object_tree, *qualifier_tree, *range_tree;
1659 orig_offset = offset;
1661 /* Application Layer Objects in this Message */
1662 *al_objtype =
1663 al_obj = tvb_get_ntohs(tvb, offset);
1665 /* Special handling for Octet string objects as the variation is the length of the string */
1666 temp = al_obj & 0xFF00;
1667 if ((temp == AL_OBJ_OCT) || (temp == AL_OBJ_OCT_EVT )) {
1668 al_oct_len = al_obj & 0xFF;
1669 al_obj = temp;
1672 /* Create Data Objects Detail Tree */
1673 object_item = proto_tree_add_uint_format(robj_tree, hf_dnp3_al_obj, tvb, offset, 2, al_obj,
1674 "Object(s): %s (0x%04x)",
1675 val_to_str_ext_const(al_obj, &dnp3_al_obj_vals_ext, "Unknown Object - Abort Decoding..."),
1676 al_obj);
1677 object_tree = proto_item_add_subtree(object_item, ett_dnp3_al_obj);
1679 offset += 2;
1681 /* Object Qualifier */
1682 al_objq = tvb_get_guint8(tvb, offset);
1683 al_objq_index = al_objq & AL_OBJQ_INDEX;
1684 al_objq_index = al_objq_index >> 4;
1685 al_objq_code = al_objq & AL_OBJQ_CODE;
1687 qualifier_item = proto_tree_add_text(object_tree, tvb, offset, 1, "Qualifier Field, Prefix: %s, Code: %s",
1688 val_to_str_ext_const(al_objq_index, &dnp3_al_objq_index_vals_ext, "Unknown Index Type"),
1689 val_to_str_ext_const(al_objq_code, &dnp3_al_objq_code_vals_ext, "Unknown Code Type"));
1690 qualifier_tree = proto_item_add_subtree(qualifier_item, ett_dnp3_al_obj_qualifier);
1691 proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_index, tvb, offset, 1, ENC_BIG_ENDIAN);
1692 proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1694 offset += 1;
1696 /* Create (possibly synthesized) number of items and range field tree */
1697 range_item = proto_tree_add_text(object_tree, tvb, offset, 0, "Number of Items: ");
1698 range_tree = proto_item_add_subtree(range_item, ett_dnp3_al_obj_range);
1700 switch (al_objq_code)
1702 case AL_OBJQL_CODE_SSI8: /* 8-bit Start and Stop Indices in Range Field */
1703 num_items = ( tvb_get_guint8(tvb, offset+1) - tvb_get_guint8(tvb, offset) + 1);
1704 PROTO_ITEM_SET_GENERATED(range_item);
1705 al_ptaddr = tvb_get_guint8(tvb, offset);
1706 proto_tree_add_item(range_tree, hf_dnp3_al_range_start8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1707 proto_tree_add_item(range_tree, hf_dnp3_al_range_stop8, tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
1708 rangebytes = 2;
1709 break;
1710 case AL_OBJQL_CODE_SSI16: /* 16-bit Start and Stop Indices in Range Field */
1711 num_items = ( tvb_get_letohs(tvb, offset+2) - tvb_get_letohs(tvb, (offset)) + 1);
1712 PROTO_ITEM_SET_GENERATED(range_item);
1713 al_ptaddr = tvb_get_letohs(tvb, offset);
1714 proto_tree_add_item(range_tree, hf_dnp3_al_range_start16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1715 proto_tree_add_item(range_tree, hf_dnp3_al_range_stop16, tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
1716 rangebytes = 4;
1717 break;
1718 case AL_OBJQL_CODE_SSI32: /* 32-bit Start and Stop Indices in Range Field */
1719 num_items = ( tvb_get_letohl(tvb, offset+4) - tvb_get_letohl(tvb, offset) + 1);
1720 PROTO_ITEM_SET_GENERATED(range_item);
1721 al_ptaddr = tvb_get_letohl(tvb, offset);
1722 proto_tree_add_item(range_tree, hf_dnp3_al_range_start32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1723 proto_tree_add_item(range_tree, hf_dnp3_al_range_stop32, tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
1724 rangebytes = 8;
1725 break;
1726 case AL_OBJQL_CODE_AA8: /* 8-bit Absolute Address in Range Field */
1727 num_items = 1;
1728 PROTO_ITEM_SET_GENERATED(range_item);
1729 al_ptaddr = tvb_get_guint8(tvb, offset);
1730 proto_tree_add_item(range_tree, hf_dnp3_al_range_abs8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1731 rangebytes = 1;
1732 break;
1733 case AL_OBJQL_CODE_AA16: /* 16-bit Absolute Address in Range Field */
1734 num_items = 1;
1735 PROTO_ITEM_SET_GENERATED(range_item);
1736 al_ptaddr = tvb_get_letohs(tvb, offset);
1737 proto_tree_add_item(range_tree, hf_dnp3_al_range_abs16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1738 rangebytes = 2;
1739 break;
1740 case AL_OBJQL_CODE_AA32: /* 32-bit Absolute Address in Range Field */
1741 num_items = 1;
1742 PROTO_ITEM_SET_GENERATED(range_item);
1743 al_ptaddr = tvb_get_letohl(tvb, offset);
1744 proto_tree_add_item(range_tree, hf_dnp3_al_range_abs32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1745 rangebytes = 4;
1746 break;
1747 case AL_OBJQL_CODE_SF8: /* 8-bit Single Field Quantity in Range Field */
1748 num_items = tvb_get_guint8(tvb, offset);
1749 proto_tree_add_item(range_tree, hf_dnp3_al_range_quant8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1750 rangebytes = 1;
1751 proto_item_set_len(range_item, rangebytes);
1752 break;
1753 case AL_OBJQL_CODE_SF16: /* 16-bit Single Field Quantity in Range Field */
1754 num_items = tvb_get_letohs(tvb, offset);
1755 proto_tree_add_item(range_tree, hf_dnp3_al_range_quant16, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1756 rangebytes = 2;
1757 proto_item_set_len(range_item, rangebytes);
1758 break;
1759 case AL_OBJQL_CODE_SF32: /* 32-bit Single Field Quantity in Range Field */
1760 num_items = tvb_get_letohl(tvb, offset);
1761 proto_tree_add_item(range_tree, hf_dnp3_al_range_quant32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1762 rangebytes = 4;
1763 proto_item_set_len(range_item, rangebytes);
1764 break;
1765 case AL_OBJQL_CODE_FF: /* 8 bit object count in Range Field */
1766 num_items = tvb_get_guint8(tvb, offset);
1767 proto_tree_add_item(range_tree, hf_dnp3_al_range_quant8, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1768 rangebytes = 1;
1769 proto_item_set_len(range_item, rangebytes);
1771 if (num_items > 0) {
1772 proto_item_append_text(object_item, ", %d point%s", num_items, plurality(num_items, "", "s"));
1774 proto_item_append_text(range_item, "%d", num_items);
1776 if (num_items < 0) {
1777 proto_item_append_text(range_item, " (bogus)");
1778 expert_add_info(pinfo, range_item, &ei_dnp_num_items_neg);
1779 return tvb_length(tvb);
1783 offset += rangebytes;
1785 bitindex = 0; /* Temp variable for cycling through points when object values are encoded into
1786 bits; primarily objects 0x0101, 0x0301 & 0x1001 */
1788 /* Only process the point information for replies or items with point index lists */
1789 if (!header_only || al_objq_index > 0) {
1790 int item_num;
1791 int start_offset;
1793 start_offset = offset;
1794 for (item_num = 0; item_num < num_items; item_num++)
1796 proto_item *point_item;
1797 proto_tree *point_tree;
1798 guint data_pos;
1799 int indexbytes;
1801 /* Create Point item and Process Index */
1802 if (al_objq_index <= AL_OBJQL_IDX_4O)
1803 point_item = proto_tree_add_text(object_tree, tvb, offset, -1, "Point Number");
1804 else
1805 point_item = proto_tree_add_text(object_tree, tvb, offset, -1, "Object: Size");
1806 point_tree = proto_item_add_subtree(point_item, ett_dnp3_al_obj_point);
1808 data_pos = offset;
1809 indexbytes = dnp3_al_obj_procindex(tvb, offset, al_objq_index, &al_ptaddr, point_tree);
1810 proto_item_append_text(point_item, " %u", al_ptaddr);
1811 proto_item_set_len(point_item, indexbytes);
1812 data_pos += indexbytes;
1814 if (!header_only || (AL_OBJQL_IDX_1OS <= al_objq_index && al_objq_index <= AL_OBJQL_IDX_4OS)) {
1815 guint8 al_2bit, al_ptflags, al_ctlobj_count, al_bi_val, al_tcc_code, da_len;
1816 guint16 al_val16, al_ctlobj_stat;
1817 guint16 al_relms, al_filename_offs, al_filename_len, al_file_ctrl_mode;
1818 guint32 al_val32, al_ctlobj_on, al_ctlobj_off, file_data_size;
1819 nstime_t al_reltime, al_abstime;
1820 gboolean al_bit;
1821 gfloat al_valflt;
1822 gdouble al_valdbl;
1823 const gchar *ctl_status_str;
1825 switch (al_obj)
1828 case AL_OBJ_BI_ALL: /* Binary Input Default Variation (Obj:01, Var:Default) */
1829 case AL_OBJ_BIC_ALL: /* Binary Input Change Default Variation (Obj:02, Var:Default) */
1830 case AL_OBJ_BOC_ALL: /* Binary Output Event Default Variation (Obj:11, Var:Default) */
1831 case AL_OBJ_2BI_ALL: /* Double-bit Input Default Variation (Obj:03, Var:Default) */
1832 case AL_OBJ_2BIC_ALL: /* Double-bit Input Change Default Variation (Obj:04, Var:Default) */
1833 case AL_OBJ_CTR_ALL: /* Binary Counter Default Variation (Obj:20, Var:Default) */
1834 case AL_OBJ_CTRC_ALL: /* Binary Counter Change Default Variation (Obj:22 Var:Default) */
1835 case AL_OBJ_AI_ALL: /* Analog Input Default Variation (Obj:30, Var:Default) */
1836 case AL_OBJ_AIC_ALL: /* Analog Input Change Default Variation (Obj:32 Var:Default) */
1837 case AL_OBJ_AIDB_ALL: /* Analog Input Deadband Default Variation (Obj:34, Var:Default) */
1838 case AL_OBJ_AOC_ALL: /* Analog Output Event Default Variation (Obj:42 Var:Default) */
1840 offset = data_pos;
1841 break;
1843 /* Device Attributes - Integers */
1844 case AL_OBJ_DA_MSTR_DSP: /* Device Attributes - Number of master-defined data set prototypes (Obj:00, Var:212) */
1845 case AL_OBJ_DA_OS_DSP: /* Device Attributes - Number of outstation-defined data set prototypes (Obj:00, Var:213) */
1846 case AL_OBJ_DA_MSTR_DS: /* Device Attributes - Number of master-defined data sets (Obj:00, Var:214) */
1847 case AL_OBJ_DA_OS_DS: /* Device Attributes - Number of outstation-defined data sets (Obj:00, Var:215) */
1848 case AL_OBJ_DA_BO_REQ: /* Device Attributes - Max number of binary outputs per request (Obj:00, Var:216) */
1849 case AL_OBJ_DA_LOC_TA: /* Device Attributes - Local timing accuracy (Obj:00, Var:217) */
1850 case AL_OBJ_DA_DUR_TA: /* Device Attributes - Duration of timing accuraccy (Obj:00, Var:218) */
1851 case AL_OBJ_DA_AO_EVT: /* Device Attributes - Support for analog output events (Obj:00, Var:219) */
1852 case AL_OBJ_DA_MAX_AO: /* Device Attributes - Max analog output index (Obj:00, Var:220) */
1853 case AL_OBJ_DA_NUM_AO: /* Device Attributes - Number of analog outputs (Obj:00, Var:221) */
1854 case AL_OBJ_DA_BO_EVT: /* Device Attributes - Support for binary output events (Obj:00, Var:222) */
1855 case AL_OBJ_DA_MAX_BO: /* Device Attributes - Max binary output index (Obj:00, Var:223) */
1856 case AL_OBJ_DA_NUM_BO: /* Device Attributes - Number of binary outputs (Obj:00, Var:224) */
1857 case AL_OBJ_DA_FCTR_EVT: /* Device Attributes - Support for frozen counter events (Obj:00, Var:225) */
1858 case AL_OBJ_DA_FCTR: /* Device Attributes - Support for frozen counters (Obj:00, Var:226) */
1859 case AL_OBJ_DA_CTR_EVT: /* Device Attributes - Support for counter events (Obj:00, Var:227) */
1860 case AL_OBJ_DA_MAX_CTR: /* Device Attributes - Max counter index (Obj:00, Var:228) */
1861 case AL_OBJ_DA_NUM_CTR: /* Device Attributes - Number of counter points (Obj:00, Var:229) */
1862 case AL_OBJ_DA_AIF: /* Device Attributes - Support for frozen analog inputs (Obj:00, Var:230) */
1863 case AL_OBJ_DA_AI_EVT: /* Device Attributes - Support for analog input events (Obj:00, Var:231) */
1864 case AL_OBJ_DA_MAX_AI: /* Device Attributes - Maximum analog input index (Obj:00, Var:232) */
1865 case AL_OBJ_DA_NUM_AI: /* Device Attributes - Number of analog input points (Obj:00, Var:233) */
1866 case AL_OBJ_DA_2BI_EVT: /* Device Attributes - Support for Double-Bit BI Events (Obj:00, Var:234) */
1867 case AL_OBJ_DA_MAX_2BI: /* Device Attributes - Max Double-bit BI Point Index (Obj:00, Var:235) */
1868 case AL_OBJ_DA_NUM_2BI: /* Device Attributes - Number of Double-bit BI Points (Obj:00, Var:236) */
1869 case AL_OBJ_DA_BI_EVT: /* Device Attributes - Support for Binary Input Events (Obj:00, Var:237) */
1870 case AL_OBJ_DA_MAX_BI: /* Device Attributes - Max Binary Input Point Index (Obj:00, Var:238) */
1871 case AL_OBJ_DA_NUM_BI: /* Device Attributes - Number of Binary Input Points (Obj:00, Var:239) */
1872 case AL_OBJ_DA_MXTX_FR: /* Device Attributes - Maximum Transmit Fragment Size (Obj:00, Var:240) */
1873 case AL_OBJ_DA_MXRX_FR: /* Device Attributes - Maximum Receive Fragment Size (Obj:00, Var:241) */
1875 proto_tree_add_item(point_tree, hf_dnp3_al_datatype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1877 da_len = tvb_get_guint8(tvb, offset+1);
1878 proto_tree_add_item(point_tree, hf_dnp3_al_da_length, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1880 if (da_len == 1) {
1881 proto_tree_add_item(point_tree, hf_dnp3_al_da_int8, tvb, offset+2, 1, ENC_LITTLE_ENDIAN);
1882 proto_item_append_text(object_item, ", Value: %u", tvb_get_guint8(tvb, offset+2));
1885 else if (da_len == 4) {
1886 proto_tree_add_item(point_tree, hf_dnp3_al_da_int32, tvb, offset+2, 4, ENC_LITTLE_ENDIAN);
1887 proto_item_append_text(object_item, ", Value: %u", tvb_get_letohl(tvb, offset+2));
1890 offset += 2 + da_len;
1892 break;
1895 /* Device Attributes - Strings */
1896 case AL_OBJ_DA_USR_ATTR:
1897 case AL_OBJ_DA_SWVER: /* Device Attributes - Device Manufacturers SW Version (Obj:00, Var:242) */
1898 case AL_OBJ_DA_HWVER: /* Device Attributes - Device Manufacturers HW Version (Obj:00, Var:243) */
1899 case AL_OBJ_DA_LOC: /* Device Attributes - User-Assigned Location (Obj:00, Var:245) */
1900 case AL_OBJ_DA_ID: /* Device Attributes - User-Assigned ID code/number (Obj:00, Var:246) */
1901 case AL_OBJ_DA_DEVNAME: /* Device Attributes - User-Assigned Device Name (Obj:00, Var:247) */
1902 case AL_OBJ_DA_SERNUM: /* Device Attributes - Device Serial Number (Obj:00, Var:248) */
1903 case AL_OBJ_DA_CONF: /* Device Attributes - DNP Subset and Conformance (Obj:00, Var:249) */
1904 case AL_OBJ_DA_PROD: /* Device Attributes - Device Product Name and Model (Obj:00, Var:250) */
1905 case AL_OBJ_DA_MFG: /* Device Attributes - Device Manufacturers Name (Obj:00, Var:252) */
1907 proto_tree_add_item(point_tree, hf_dnp3_al_datatype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1909 da_len = tvb_get_guint8(tvb, offset+1);
1910 proto_tree_add_item(point_tree, hf_dnp3_al_da_length, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
1912 proto_tree_add_text(point_tree, tvb, offset+2, da_len, "Value: %s", tvb_get_string(wmem_packet_scope(), tvb, offset+2, da_len));
1913 proto_item_append_text(object_item, ", Value: %s", tvb_get_string(wmem_packet_scope(), tvb, offset+2, da_len));
1915 offset += 2 + da_len;
1917 break;
1919 /* Bit-based Data objects here */
1920 case AL_OBJ_BI_1BIT: /* Single-Bit Binary Input (Obj:01, Var:01) */
1921 case AL_OBJ_BO: /* Binary Output (Obj:10, Var:01) */
1923 /* Reset bit index if we've gone onto the next byte */
1924 if (bitindex > 7)
1926 bitindex = 0;
1927 offset += (indexbytes + 1);
1930 /* Extract the bit from the packed byte */
1931 al_bi_val = tvb_get_guint8(tvb, offset);
1932 al_bit = (al_bi_val & (1 << bitindex)) > 0;
1934 proto_item_append_text(point_item, ", Value: %u", al_bit);
1935 proto_tree_add_boolean(point_tree, hf_dnp3_al_bit, tvb, offset, 1, al_bit);
1936 proto_item_set_len(point_item, indexbytes + 1);
1938 /* If we've read the last item, then move the offset past this byte */
1939 if (item_num == (num_items-1))
1941 offset += (indexbytes + 1);
1944 break;
1946 case AL_OBJ_2BI_NF: /* Double-bit Input No Flags (Obj:03, Var:01) */
1948 if (bitindex > 3)
1950 bitindex = 0;
1951 offset += (indexbytes + 1);
1954 /* Extract the Double-bit from the packed byte */
1955 al_bi_val = tvb_get_guint8(tvb, offset);
1956 al_2bit = ((al_bi_val >> (bitindex << 1)) & 3);
1958 proto_item_append_text(point_item, ", Value: %u", al_2bit);
1959 proto_tree_add_uint(point_tree, hf_dnp3_al_2bit, tvb, offset, 1, al_2bit);
1960 proto_item_set_len(point_item, indexbytes + 1);
1962 /* If we've read the last item, then move the offset past this byte */
1963 if (item_num == (num_items-1))
1965 offset += (indexbytes + 1);
1968 break;
1971 case AL_OBJ_BI_STAT: /* Binary Input With Status (Obj:01, Var:02) */
1972 case AL_OBJ_BIC_NOTIME: /* Binary Input Change Without Time (Obj:02, Var:01) */
1973 case AL_OBJ_BO_STAT: /* Binary Output Status (Obj:10, Var:02) */
1974 case AL_OBJ_BOC_NOTIME: /* Binary Output Change Without Time (Obj:11, Var:01) */
1976 /* Get Point Flags */
1977 al_ptflags = tvb_get_guint8(tvb, data_pos);
1979 switch (al_obj) {
1980 case AL_OBJ_BI_STAT:
1981 case AL_OBJ_BIC_NOTIME:
1982 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
1983 break;
1984 case AL_OBJ_BO_STAT:
1985 case AL_OBJ_BOC_NOTIME:
1986 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_OUT);
1987 break;
1989 data_pos += 1;
1991 al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) > 0;
1992 proto_item_append_text(point_item, ", Value: %u", al_bit);
1994 proto_item_set_len(point_item, data_pos - offset);
1996 offset = data_pos;
1997 break;
1999 case AL_OBJ_2BI_STAT: /* Double-bit Input With Status (Obj:03, Var:02) */
2000 case AL_OBJ_2BIC_NOTIME: /* Double-bit Input Change Without Time (Obj:04, Var:01) */
2002 /* Get Point Flags */
2003 al_ptflags = tvb_get_guint8(tvb, data_pos);
2004 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2005 data_pos += 1;
2007 al_2bit = (al_ptflags >> 6) & 3;
2008 proto_item_append_text(point_item, ", Value: %u", al_2bit);
2009 proto_item_set_len(point_item, data_pos - offset);
2011 offset = data_pos;
2012 break;
2014 case AL_OBJ_BIC_TIME: /* Binary Input Change w/ Time (Obj:02, Var:02) */
2015 case AL_OBJ_BOC_TIME: /* Binary Output Change w/ Time (Obj:11, Var:02) */
2017 /* Get Point Flags */
2018 al_ptflags = tvb_get_guint8(tvb, data_pos);
2019 switch (al_obj) {
2020 case AL_OBJ_BIC_TIME:
2021 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2022 break;
2023 case AL_OBJ_BOC_TIME:
2024 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_OUT);
2025 break;
2027 data_pos += 1;
2029 /* Get timestamp */
2030 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2031 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2032 data_pos += 6;
2034 al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
2035 proto_item_append_text(point_item, ", Value: %u, Timestamp: %s",
2036 al_bit, abs_time_to_str(&al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2037 proto_item_set_len(point_item, data_pos - offset);
2039 offset = data_pos;
2040 break;
2042 case AL_OBJ_2BIC_TIME: /* Double-bit Input Change w/ Time (Obj:04, Var:02) */
2044 /* Get Point Flags */
2045 al_ptflags = tvb_get_guint8(tvb, data_pos);
2046 dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, BIN_IN);
2047 data_pos += 1;
2050 /* Get timestamp */
2051 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2052 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2053 data_pos += 6;
2055 al_2bit = (al_ptflags >> 6) & 3; /* bit shift 11xxxxxx -> 00000011 */
2056 proto_item_append_text(point_item, ", Value: %u, Timestamp: %s",
2057 al_2bit, abs_time_to_str(&al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2058 proto_item_set_len(point_item, data_pos - offset);
2060 offset = data_pos;
2061 break;
2063 case AL_OBJ_BIC_RTIME: /* Binary Input Change w/ Relative Time (Obj:02, Var:03) */
2065 /* Get Point Flags */
2066 al_ptflags = tvb_get_guint8(tvb, data_pos);
2067 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
2068 data_pos += 1;
2070 /* Get relative time, and convert to ns_time */
2071 al_relms = tvb_get_letohs(tvb, data_pos);
2072 al_reltime.secs = al_relms / 1000;
2073 al_reltime.nsecs = (al_relms % 1000) * 1000;
2074 /* Now add to CTO time */
2075 nstime_sum(&al_abstime, al_cto, &al_reltime);
2076 proto_tree_add_time(point_tree, hf_dnp3_al_rel_timestamp, tvb, data_pos, 2, &al_reltime);
2077 data_pos += 2;
2079 al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
2080 proto_item_append_text(point_item, ", Value: %u, Timestamp: %s",
2081 al_bit, abs_time_to_str(&al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2082 proto_item_set_len(point_item, data_pos - offset);
2084 offset = data_pos;
2085 break;
2087 case AL_OBJ_CTLOP_BLK:/* Control Relay Output Block (Obj:12, Var:01) */
2089 proto_item *tcc_item;
2090 proto_tree *tcc_tree;
2092 /* Add a expand/collapse for TCC */
2093 al_tcc_code = tvb_get_guint8(tvb, data_pos);
2094 tcc_item = proto_tree_add_text(point_tree, tvb, data_pos, 1, "Control Code [0x%02x]",al_tcc_code);
2095 tcc_tree = proto_item_add_subtree(tcc_item, ett_dnp3_al_obj_point_tcc);
2097 /* Add the Control Code to the Point number list for quick visual reference as to the operation */
2098 proto_item_append_text(point_item, " [%s]", val_to_str_const((al_tcc_code & AL_OBJCTLC_CODE),
2099 dnp3_al_ctlc_code_vals,
2100 "Invalid Operation"));
2102 /* Add Trip/Close qualifier (if applicable) to previously appended quick visual reference */
2103 proto_item_append_text(point_item, " [%s]", val_to_str_const((al_tcc_code & AL_OBJCTLC_TC) >> 6,
2104 dnp3_al_ctlc_tc_vals,
2105 "Invalid Qualifier"));
2109 /* Control Code 'Operation Type' */
2110 proto_tree_add_item(tcc_tree, hf_dnp3_ctlobj_code_c, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2112 /* Control Code Misc Values */
2113 proto_tree_add_item(tcc_tree, hf_dnp3_ctlobj_code_m, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2115 /* Control Code 'Trip Close Code' */
2116 proto_tree_add_item(tcc_tree, hf_dnp3_ctlobj_code_tc, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2117 data_pos += 1;
2119 /* Get "Count" Field */
2120 al_ctlobj_count = tvb_get_guint8(tvb, data_pos);
2121 data_pos += 1;
2123 /* Get "On Time" Field */
2124 al_ctlobj_on = tvb_get_letohl(tvb, data_pos);
2125 data_pos += 4;
2127 /* Get "Off Time" Field */
2128 al_ctlobj_off = tvb_get_letohl(tvb, data_pos);
2129 data_pos += 4;
2131 /* Print "Count", "On Time" and "Off Time" to tree */
2132 proto_tree_add_text(point_tree, tvb, data_pos - 9, 9,
2133 "[Count: %u] [On-Time: %u] [Off-Time: %u]",
2134 al_ctlobj_count, al_ctlobj_on, al_ctlobj_off);
2136 /* Get "Control Status" Field */
2137 proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2138 data_pos += 1;
2141 proto_item_set_len(point_item, data_pos - offset);
2143 offset = data_pos;
2144 break;
2147 case AL_OBJ_AO_32OPB: /* 32-Bit Analog Output Block (Obj:41, Var:01) */
2148 case AL_OBJ_AO_16OPB: /* 16-Bit Analog Output Block (Obj:41, Var:02) */
2149 case AL_OBJ_AO_FLTOPB: /* 32-Bit Floating Point Output Block (Obj:41, Var:03) */
2150 case AL_OBJ_AO_DBLOPB: /* 64-Bit Floating Point Output Block (Obj:41, Var:04) */
2152 switch (al_obj)
2154 case AL_OBJ_AO_32OPB:
2155 al_val32 = tvb_get_letohl(tvb, data_pos);
2156 proto_item_append_text(point_item, ", Value: %u", al_val32);
2157 proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2158 data_pos += 4;
2159 break;
2160 case AL_OBJ_AO_16OPB:
2161 al_val32 = tvb_get_letohs(tvb, data_pos);
2162 proto_item_append_text(point_item, ", Value: %u", al_val32);
2163 proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2164 data_pos += 2;
2165 break;
2166 case AL_OBJ_AO_FLTOPB:
2167 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2168 proto_item_append_text(point_item, ", Value: %g", al_valflt);
2169 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2170 data_pos += 4;
2171 break;
2172 case AL_OBJ_AO_DBLOPB:
2173 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2174 proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2175 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2176 data_pos += 8;
2177 break;
2180 /* Get control status */
2181 al_ctlobj_stat = tvb_get_guint8(tvb, data_pos);
2182 ctl_status_str = val_to_str_ext(al_ctlobj_stat, &dnp3_al_ctl_status_vals_ext, "Invalid Status (0x%02x)");
2183 proto_item_append_text(point_item, " [Status: %s (0x%02x)]", ctl_status_str, al_ctlobj_stat);
2184 proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2185 data_pos += 1;
2187 proto_item_set_len(point_item, data_pos - offset);
2189 offset = data_pos;
2190 break;
2192 case AL_OBJ_CTR_32: /* 32-Bit Binary Counter (Obj:20, Var:01) */
2193 case AL_OBJ_CTR_16: /* 16-Bit Binary Counter (Obj:20, Var:02) */
2194 case AL_OBJ_DCTR_32: /* 32-Bit Binary Delta Counter (Obj:20, Var:03) */
2195 case AL_OBJ_DCTR_16: /* 16-Bit Binary Delta Counter (Obj:20, Var:04) */
2196 case AL_OBJ_CTR_32NF: /* 32-Bit Binary Counter Without Flag (Obj:20, Var:05) */
2197 case AL_OBJ_CTR_16NF: /* 16-Bit Binary Counter Without Flag (Obj:20, Var:06) */
2198 case AL_OBJ_DCTR_32NF: /* 32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07) */
2199 case AL_OBJ_DCTR_16NF: /* 16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08) */
2200 case AL_OBJ_FCTR_32: /* 32-Bit Frozen Counter (Obj:21, Var:01) */
2201 case AL_OBJ_FCTR_16: /* 16-Bit Frozen Counter (Obj:21, Var:02) */
2202 case AL_OBJ_FDCTR_32: /* 21 03 32-Bit Frozen Delta Counter */
2203 case AL_OBJ_FDCTR_16: /* 21 04 16-Bit Frozen Delta Counter */
2204 case AL_OBJ_FCTR_32T: /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
2205 case AL_OBJ_FCTR_16T: /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
2206 case AL_OBJ_FDCTR_32T: /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
2207 case AL_OBJ_FDCTR_16T: /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
2208 case AL_OBJ_FCTR_32NF: /* 21 09 32-Bit Frozen Counter Without Flag */
2209 case AL_OBJ_FCTR_16NF: /* 21 10 16-Bit Frozen Counter Without Flag */
2210 case AL_OBJ_FDCTR_32NF: /* 21 11 32-Bit Frozen Delta Counter Without Flag */
2211 case AL_OBJ_FDCTR_16NF: /* 21 12 16-Bit Frozen Delta Counter Without Flag */
2212 case AL_OBJ_CTRC_32: /* 32-Bit Counter Change Event w/o Time (Obj:22, Var:01) */
2213 case AL_OBJ_CTRC_16: /* 16-Bit Counter Change Event w/o Time (Obj:22, Var:02) */
2214 case AL_OBJ_DCTRC_32: /* 32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03) */
2215 case AL_OBJ_DCTRC_16: /* 16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04) */
2216 case AL_OBJ_CTRC_32T: /* 32-Bit Counter Change Event with Time (Obj:22, Var:05) */
2217 case AL_OBJ_CTRC_16T: /* 16-Bit Counter Change Event with Time (Obj:22, Var:06) */
2218 case AL_OBJ_DCTRC_32T: /* 32-Bit Delta Counter Change Event with Time (Obj:22, Var:07) */
2219 case AL_OBJ_DCTRC_16T: /* 16-Bit Delta Counter Change Event with Time (Obj:22, Var:08) */
2220 case AL_OBJ_FCTRC_32: /* 21 01 32-Bit Frozen Counter Change Event */
2221 case AL_OBJ_FCTRC_16: /* 21 02 16-Bit Frozen Counter Change Event */
2222 case AL_OBJ_FDCTRC_32: /* 21 03 32-Bit Frozen Delta Counter Change Event */
2223 case AL_OBJ_FDCTRC_16: /* 21 04 16-Bit Frozen Delta Counter Change Event */
2224 case AL_OBJ_FCTRC_32T: /* 21 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
2225 case AL_OBJ_FCTRC_16T: /* 21 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
2226 case AL_OBJ_FDCTRC_32T: /* 21 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
2227 case AL_OBJ_FDCTRC_16T: /* 21 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
2229 /* Get Point Flags for those types that have them, it's easier to block out those that don't have flags */
2230 switch (al_obj)
2232 case AL_OBJ_CTR_32NF:
2233 case AL_OBJ_CTR_16NF:
2234 case AL_OBJ_DCTR_32NF:
2235 case AL_OBJ_DCTR_16NF:
2236 case AL_OBJ_FCTR_32NF:
2237 case AL_OBJ_FCTR_16NF:
2238 case AL_OBJ_FDCTR_32NF:
2239 case AL_OBJ_FDCTR_16NF:
2240 break;
2242 default:
2243 al_ptflags = tvb_get_guint8(tvb, data_pos);
2244 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, COUNTER);
2245 data_pos += 1;
2246 break;
2249 /* Get Counter values */
2250 switch (al_obj)
2252 case AL_OBJ_CTR_32:
2253 case AL_OBJ_DCTR_32:
2254 case AL_OBJ_CTR_32NF:
2255 case AL_OBJ_DCTR_32NF:
2256 case AL_OBJ_FCTR_32:
2257 case AL_OBJ_FDCTR_32:
2258 case AL_OBJ_FCTR_32T:
2259 case AL_OBJ_FDCTR_32T:
2260 case AL_OBJ_FCTR_32NF:
2261 case AL_OBJ_FDCTR_32NF:
2262 case AL_OBJ_CTRC_32:
2263 case AL_OBJ_DCTRC_32:
2264 case AL_OBJ_CTRC_32T:
2265 case AL_OBJ_DCTRC_32T:
2266 case AL_OBJ_FCTRC_32:
2267 case AL_OBJ_FDCTRC_32:
2268 case AL_OBJ_FCTRC_32T:
2269 case AL_OBJ_FDCTRC_32T:
2271 al_val32 = tvb_get_letohl(tvb, data_pos);
2272 proto_item_append_text(point_item, ", Count: %u", al_val32);
2273 proto_tree_add_item(point_tree, hf_dnp3_al_cnt32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2274 data_pos += 4;
2275 break;
2277 case AL_OBJ_CTR_16:
2278 case AL_OBJ_DCTR_16:
2279 case AL_OBJ_CTR_16NF:
2280 case AL_OBJ_DCTR_16NF:
2281 case AL_OBJ_FCTR_16:
2282 case AL_OBJ_FDCTR_16:
2283 case AL_OBJ_FCTR_16T:
2284 case AL_OBJ_FDCTR_16T:
2285 case AL_OBJ_FCTR_16NF:
2286 case AL_OBJ_FDCTR_16NF:
2287 case AL_OBJ_CTRC_16:
2288 case AL_OBJ_DCTRC_16:
2289 case AL_OBJ_CTRC_16T:
2290 case AL_OBJ_DCTRC_16T:
2291 case AL_OBJ_FCTRC_16:
2292 case AL_OBJ_FDCTRC_16:
2293 case AL_OBJ_FCTRC_16T:
2294 case AL_OBJ_FDCTRC_16T:
2296 al_val16 = tvb_get_letohs(tvb, data_pos);
2297 proto_item_append_text(point_item, ", Count: %u", al_val16);
2298 proto_tree_add_item(point_tree, hf_dnp3_al_cnt16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2299 data_pos += 2;
2300 break;
2303 /* Get the time for those points that have it */
2304 switch (al_obj)
2306 case AL_OBJ_FCTR_32T:
2307 case AL_OBJ_FCTR_16T:
2308 case AL_OBJ_FDCTR_32T:
2309 case AL_OBJ_FDCTR_16T:
2310 case AL_OBJ_CTRC_32T:
2311 case AL_OBJ_CTRC_16T:
2312 case AL_OBJ_DCTRC_32T:
2313 case AL_OBJ_DCTRC_16T:
2314 case AL_OBJ_FCTRC_32T:
2315 case AL_OBJ_FCTRC_16T:
2316 case AL_OBJ_FDCTRC_32T:
2317 case AL_OBJ_FDCTRC_16T:
2318 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2319 proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2320 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2321 data_pos += 6;
2322 break;
2325 proto_item_set_len(point_item, data_pos - offset);
2326 offset = data_pos;
2328 break;
2330 case AL_OBJ_AI_32: /* 32-Bit Analog Input (Obj:30, Var:01) */
2331 case AL_OBJ_AI_16: /* 16-Bit Analog Input (Obj:30, Var:02) */
2332 case AL_OBJ_AI_32NF: /* 32-Bit Analog Input Without Flag (Obj:30, Var:03) */
2333 case AL_OBJ_AI_16NF: /* 16-Bit Analog Input Without Flag (Obj:30, Var:04) */
2334 case AL_OBJ_AI_FLT: /* 32-Bit Floating Point Input (Obj:30, Var:05) */
2335 case AL_OBJ_AI_DBL: /* 64-Bit Floating Point Input (Obj:30, Var:06) */
2336 case AL_OBJ_AIF_FLT: /* 32-Bit Frozen Floating Point Input (Obj:31, Var:07) */
2337 case AL_OBJ_AIF_DBL: /* 64-Bit Frozen Floating Point Input (Obj:31, Var:08) */
2338 case AL_OBJ_AIC_32NT: /* 32-Bit Analog Change Event w/o Time (Obj:32, Var:01) */
2339 case AL_OBJ_AIC_16NT: /* 16-Bit Analog Change Event w/o Time (Obj:32, Var:02) */
2340 case AL_OBJ_AIC_32T: /* 32-Bit Analog Change Event with Time (Obj:32, Var:03) */
2341 case AL_OBJ_AIC_16T: /* 16-Bit Analog Change Event with Time (Obj:32, Var:04) */
2342 case AL_OBJ_AIC_FLTNT: /* 32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05) */
2343 case AL_OBJ_AIC_DBLNT: /* 64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06) */
2344 case AL_OBJ_AIC_FLTT: /* 32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07) */
2345 case AL_OBJ_AIC_DBLT: /* 64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08) */
2346 case AL_OBJ_AIFC_FLTNT: /* 32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05) */
2347 case AL_OBJ_AIFC_DBLNT: /* 64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06) */
2348 case AL_OBJ_AIFC_FLTT: /* 32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07) */
2349 case AL_OBJ_AIFC_DBLT: /* 64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08) */
2350 case AL_OBJ_AIDB_16: /* 16-Bit Analog Input Deadband (Obj:34, Var:01) */
2351 case AL_OBJ_AIDB_32: /* 32-Bit Analog Input Deadband (Obj:34, Var:02) */
2352 case AL_OBJ_AIDB_FLT: /* 32-Bit Floating Point Analog Input Deadband (Obj:34, Var:03) */
2354 /* Get Point Flags for those types that have them */
2355 switch (al_obj)
2357 case AL_OBJ_AI_32NF:
2358 case AL_OBJ_AI_16NF:
2359 case AL_OBJ_AIDB_16:
2360 case AL_OBJ_AIDB_32:
2361 case AL_OBJ_AIDB_FLT:
2362 break;
2364 default:
2365 al_ptflags = tvb_get_guint8(tvb, data_pos);
2366 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_IN);
2367 data_pos += 1;
2368 break;
2371 switch (al_obj)
2373 case AL_OBJ_AI_32:
2374 case AL_OBJ_AI_32NF:
2375 case AL_OBJ_AIC_32NT:
2376 case AL_OBJ_AIC_32T:
2377 case AL_OBJ_AIDB_32:
2379 al_val32 = tvb_get_letohl(tvb, data_pos);
2380 proto_item_append_text(point_item, ", Value: %u", al_val32);
2381 proto_tree_add_item(point_tree, hf_dnp3_al_ana32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2382 data_pos += 4;
2383 break;
2385 case AL_OBJ_AI_16:
2386 case AL_OBJ_AI_16NF:
2387 case AL_OBJ_AIC_16NT:
2388 case AL_OBJ_AIC_16T:
2389 case AL_OBJ_AIDB_16:
2391 al_val16 = tvb_get_letohs(tvb, data_pos);
2392 proto_item_append_text(point_item, ", Value: %u", al_val16);
2393 proto_tree_add_item(point_tree, hf_dnp3_al_ana16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2394 data_pos += 2;
2395 break;
2397 case AL_OBJ_AI_FLT:
2398 case AL_OBJ_AIF_FLT:
2399 case AL_OBJ_AIC_FLTNT:
2400 case AL_OBJ_AIC_FLTT:
2401 case AL_OBJ_AIFC_FLTNT:
2402 case AL_OBJ_AIFC_FLTT:
2403 case AL_OBJ_AIDB_FLT:
2405 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2406 proto_item_append_text(point_item, ", Value: %g", al_valflt);
2407 proto_tree_add_item(point_tree, hf_dnp3_al_anaflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2408 data_pos += 4;
2409 break;
2411 case AL_OBJ_AI_DBL:
2412 case AL_OBJ_AIF_DBL:
2413 case AL_OBJ_AIC_DBLNT:
2414 case AL_OBJ_AIC_DBLT:
2415 case AL_OBJ_AIFC_DBLNT:
2416 case AL_OBJ_AIFC_DBLT:
2418 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2419 proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2420 proto_tree_add_item(point_tree, hf_dnp3_al_anadbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2421 data_pos += 8;
2422 break;
2425 /* Get timestamp */
2426 switch (al_obj)
2428 case AL_OBJ_AIC_32T:
2429 case AL_OBJ_AIC_16T:
2430 case AL_OBJ_AIC_FLTT:
2431 case AL_OBJ_AIC_DBLT:
2432 case AL_OBJ_AIFC_FLTT:
2433 case AL_OBJ_AIFC_DBLT:
2434 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2435 proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2436 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2437 data_pos += 6;
2438 break;
2441 proto_item_set_len(point_item, data_pos - offset);
2443 offset = data_pos;
2444 break;
2446 case AL_OBJ_AO_32: /* 32-Bit Analog Output Status (Obj:40, Var:01) */
2447 case AL_OBJ_AO_16: /* 16-Bit Analog Output Status (Obj:40, Var:02) */
2448 case AL_OBJ_AO_FLT: /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
2449 case AL_OBJ_AO_DBL: /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
2450 case AL_OBJ_AOC_32NT: /* 32-Bit Analog Output Event w/o Time (Obj:42, Var:01) */
2451 case AL_OBJ_AOC_16NT: /* 16-Bit Analog Output Event w/o Time (Obj:42, Var:02) */
2452 case AL_OBJ_AOC_32T: /* 32-Bit Analog Output Event with Time (Obj:42, Var:03) */
2453 case AL_OBJ_AOC_16T: /* 16-Bit Analog Output Event with Time (Obj:42, Var:04) */
2454 case AL_OBJ_AOC_FLTNT: /* 32-Bit Floating Point Output Event w/o Time (Obj:42, Var:05) */
2455 case AL_OBJ_AOC_DBLNT: /* 64-Bit Floating Point Output Event w/o Time (Obj:42, Var:06) */
2456 case AL_OBJ_AOC_FLTT: /* 32-Bit Floating Point Output Event w/ Time (Obj:42, Var:07) */
2457 case AL_OBJ_AOC_DBLT: /* 64-Bit Floating Point Output Event w/ Time (Obj:42, Var:08) */
2459 /* Get Point Flags */
2460 al_ptflags = tvb_get_guint8(tvb, data_pos);
2461 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_OUT);
2462 data_pos += 1;
2464 switch (al_obj)
2466 case AL_OBJ_AO_32: /* 32-Bit Analog Output Status (Obj:40, Var:01) */
2467 case AL_OBJ_AOC_32NT: /* 32-Bit Analog Output Event w/o Time (Obj:42, Var:01) */
2468 case AL_OBJ_AOC_32T: /* 32-Bit Analog Output Event with Time (Obj:42, Var:03) */
2470 al_val32 = tvb_get_letohl(tvb, data_pos);
2471 proto_item_append_text(point_item, ", Value: %u", al_val32);
2472 proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2473 data_pos += 4;
2474 break;
2476 case AL_OBJ_AO_16: /* 16-Bit Analog Output Status (Obj:40, Var:02) */
2477 case AL_OBJ_AOC_16NT: /* 16-Bit Analog Output Event w/o Time (Obj:42, Var:02) */
2478 case AL_OBJ_AOC_16T: /* 16-Bit Analog Output Event with Time (Obj:42, Var:04) */
2480 al_val16 = tvb_get_letohs(tvb, data_pos);
2481 proto_item_append_text(point_item, ", Value: %u", al_val16);
2482 proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2483 data_pos += 2;
2484 break;
2486 case AL_OBJ_AO_FLT: /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
2487 case AL_OBJ_AOC_FLTNT: /* 32-Bit Floating Point Output Event w/o Time (Obj:42, Var:05) */
2488 case AL_OBJ_AOC_FLTT: /* 32-Bit Floating Point Output Event w/ Time (Obj:42, Var:07) */
2490 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
2491 proto_item_append_text(point_item, ", Value: %g", al_valflt);
2492 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2493 data_pos += 4;
2494 break;
2496 case AL_OBJ_AO_DBL: /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
2497 case AL_OBJ_AOC_DBLNT: /* 64-Bit Floating Point Output Event w/o Time (Obj:42, Var:06) */
2498 case AL_OBJ_AOC_DBLT: /* 64-Bit Floating Point Output Event w/ Time (Obj:42, Var:08) */
2500 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
2501 proto_item_append_text(point_item, ", Value: %g", al_valdbl);
2502 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, ENC_LITTLE_ENDIAN);
2503 data_pos += 8;
2504 break;
2507 /* Get timestamp */
2508 switch (al_obj)
2510 case AL_OBJ_AOC_32T:
2511 case AL_OBJ_AOC_16T:
2512 case AL_OBJ_AOC_FLTT:
2513 case AL_OBJ_AOC_DBLT:
2514 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2515 proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime, ABSOLUTE_TIME_UTC, FALSE));
2516 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2517 data_pos += 6;
2518 break;
2521 proto_item_set_len(point_item, data_pos - offset);
2522 offset = data_pos;
2524 break;
2526 case AL_OBJ_TD: /* Time and Date (Obj:50, Var:01) */
2527 case AL_OBJ_TDR: /* Time and Date at Last Recorded Time (Obj:50, Var:03) */
2528 case AL_OBJ_TDCTO: /* Time and Date CTO (Obj:51, Var:01) */
2530 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2531 proto_tree_add_time(object_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2532 data_pos += 6;
2533 proto_item_set_len(point_item, data_pos - offset);
2535 if (al_obj == AL_OBJ_TDCTO) {
2536 /* Copy the time object to the CTO for any other relative time objects in this response */
2537 nstime_copy(al_cto, &al_abstime);
2540 offset = data_pos;
2541 break;
2543 case AL_OBJ_TDELAYF: /* Time Delay - Fine (Obj:52, Var:02) */
2545 al_val16 = tvb_get_letohs(tvb, data_pos);
2546 proto_tree_add_text(object_tree, tvb, data_pos, 2, "Time Delay: %u ms", al_val16);
2547 data_pos += 2;
2548 proto_item_set_len(point_item, data_pos - offset);
2550 offset = data_pos;
2551 break;
2553 case AL_OBJ_CLASS0: /* Class Data Objects */
2554 case AL_OBJ_CLASS1:
2555 case AL_OBJ_CLASS2:
2556 case AL_OBJ_CLASS3:
2558 /* No data here */
2559 offset = data_pos;
2560 break;
2562 case AL_OBJ_FILE_CMD: /* File Control - File Command (Obj:70, Var:03) */
2563 /* File name offset and length */
2564 al_filename_offs = tvb_get_letohs(tvb, data_pos);
2565 proto_tree_add_text(point_tree, tvb, data_pos, 2, "File String Offset: %u", al_filename_offs);
2566 data_pos += 2;
2567 al_filename_len = tvb_get_letohs(tvb, data_pos);
2568 proto_tree_add_text(point_tree, tvb, data_pos, 2, "File String Length: %u", al_filename_len);
2569 data_pos += 2;
2571 /* Grab the mode as it determines if some of the following fields are relevant */
2572 al_file_ctrl_mode = tvb_get_letohs(tvb, data_pos + 16);
2574 /* Creation Time */
2575 if (al_file_ctrl_mode == AL_OBJ_FILE_MODE_WRITE) {
2576 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
2577 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
2579 data_pos += 6;
2581 /* Perms */
2582 if (al_file_ctrl_mode == AL_OBJ_FILE_MODE_WRITE) {
2583 proto_item *perms_item;
2584 proto_tree *perms_tree;
2586 perms_item = proto_tree_add_item(point_tree, hf_dnp3_al_file_perms, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2588 perms_tree = proto_item_add_subtree(perms_item, ett_dnp3_al_obj_point_perms);
2589 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_read_owner, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2590 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_write_owner, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2591 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_exec_owner, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2592 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_read_group, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2593 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_write_group, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2594 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_exec_group, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2595 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_read_world, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2596 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_write_world, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2597 proto_tree_add_item(perms_tree, hf_dnp3_al_file_perms_exec_world, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2599 data_pos += 2;
2601 /* Auth Key */
2602 proto_tree_add_item(point_tree, hf_dnp3_al_file_auth, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2603 data_pos += 4;
2605 /* File Size */
2606 if (al_file_ctrl_mode == AL_OBJ_FILE_MODE_WRITE || al_file_ctrl_mode == AL_OBJ_FILE_MODE_APPEND) {
2607 proto_tree_add_item(point_tree, hf_dnp3_al_file_size, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2609 data_pos += 4;
2611 /* Mode */
2612 proto_tree_add_item(point_tree, hf_dnp3_al_file_mode, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2613 data_pos += 2;
2615 /* Max Block Size */
2616 proto_tree_add_item(point_tree, hf_dnp3_al_file_maxblk, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2617 data_pos += 2;
2619 /* Request ID */
2620 proto_tree_add_item(point_tree, hf_dnp3_al_file_reqID, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2621 data_pos += 2;
2623 /* Filename */
2624 if (al_filename_len > 0) {
2625 const gchar *al_filename;
2627 al_filename = tvb_get_string(wmem_packet_scope(), tvb, data_pos, al_filename_len);
2628 proto_tree_add_text(point_tree, tvb, data_pos, al_filename_len, "File Name: %s", al_filename);
2630 data_pos += al_filename_len;
2631 proto_item_set_len(point_item, data_pos - offset);
2633 offset = data_pos;
2634 break;
2636 case AL_OBJ_FILE_STAT: /* File Control - File Status (Obj:70, Var:04) */
2638 /* File Handle */
2639 proto_tree_add_item(point_tree, hf_dnp3_al_file_handle, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2640 data_pos += 4;
2642 /* File Size */
2643 proto_tree_add_item(point_tree, hf_dnp3_al_file_size, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2644 data_pos += 4;
2646 /* Max Block Size */
2647 proto_tree_add_item(point_tree, hf_dnp3_al_file_maxblk, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2648 data_pos += 2;
2650 /* Request ID */
2651 proto_tree_add_item(point_tree, hf_dnp3_al_file_reqID, tvb, data_pos, 2, ENC_LITTLE_ENDIAN);
2652 data_pos += 2;
2654 /* Status code */
2655 proto_tree_add_item(point_tree, hf_dnp3_al_file_status, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2656 data_pos += 1;
2658 /* Optional text */
2659 file_data_size = al_ptaddr - (data_pos - offset - indexbytes);
2660 if ((file_data_size) > 0) {
2661 proto_tree_add_item(point_tree, hf_dnp3_al_file_data, tvb, data_pos, file_data_size, ENC_NA);
2662 data_pos += file_data_size;
2665 proto_item_set_len(point_item, data_pos - offset);
2667 offset = data_pos;
2668 break;
2670 case AL_OBJ_FILE_TRANS: /* File Control - File Transport (Obj:70, Var:05) */
2672 /* File Handle */
2673 proto_tree_add_item(point_tree, hf_dnp3_al_file_handle, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2674 data_pos += 4;
2676 /* File block (bits 0 - 30) and last block flag (bit 31) */
2677 proto_tree_add_item(point_tree, hf_dnp3_al_file_blocknum, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2678 proto_tree_add_item(point_tree, hf_dnp3_al_file_lastblock, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2679 data_pos += 4;
2681 /* File data */
2682 file_data_size = al_ptaddr - (data_pos - offset - indexbytes);
2683 if ((file_data_size) > 0) {
2684 proto_tree_add_item(point_tree, hf_dnp3_al_file_data, tvb, data_pos, file_data_size, ENC_NA);
2685 data_pos += file_data_size;
2688 proto_item_set_len(point_item, data_pos - offset);
2690 offset = data_pos;
2691 break;
2693 case AL_OBJ_FILE_TRAN_ST: /* File Control Tansport Status (Obj:70, Var:06) */
2695 /* File Handle */
2696 proto_tree_add_item(point_tree, hf_dnp3_al_file_handle, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2697 data_pos += 4;
2699 /* File block (bits 0 - 30) and last block flag (bit 31) */
2700 proto_tree_add_item(point_tree, hf_dnp3_al_file_blocknum, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2701 proto_tree_add_item(point_tree, hf_dnp3_al_file_lastblock, tvb, data_pos, 4, ENC_LITTLE_ENDIAN);
2702 data_pos += 4;
2704 /* Status code */
2705 proto_tree_add_item(point_tree, hf_dnp3_al_file_status, tvb, data_pos, 1, ENC_LITTLE_ENDIAN);
2706 data_pos += 1;
2708 /* Optional text */
2709 file_data_size = al_ptaddr - (data_pos - offset - indexbytes);
2710 if ((file_data_size) > 0) {
2711 proto_tree_add_item(point_tree, hf_dnp3_al_file_data, tvb, data_pos, file_data_size, ENC_NA);
2712 data_pos += file_data_size;
2715 proto_item_set_len(point_item, data_pos - offset);
2717 offset = data_pos;
2718 break;
2720 case AL_OBJ_IIN: /* Internal Indications - IIN (Obj: 80, Var:01) */
2722 /* Process IIN bit object as per standard Response message */
2723 dnp3_al_process_iin(tvb, pinfo, offset, object_tree);
2725 offset += 2;
2727 /* skip over the rest of the items */
2728 item_num = 15;
2730 break;
2732 case AL_OBJ_OCT: /* Octet string */
2733 case AL_OBJ_OCT_EVT: /* Octet string event */
2735 /* read the number of bytes defined by the variation */
2736 if (al_oct_len > 0) {
2737 proto_tree_add_text(object_tree, tvb, data_pos, al_oct_len, "Octet String (%u bytes)", al_oct_len);
2738 data_pos += al_oct_len;
2739 proto_item_set_len(point_item, data_pos - offset);
2742 offset = data_pos;
2743 break;
2745 default: /* In case of unknown object */
2747 proto_tree_add_text(object_tree, tvb, offset, -1,
2748 "Unknown Data Chunk, %u Bytes", tvb_reported_length_remaining(tvb, offset));
2749 offset = tvb_length(tvb); /* Finish decoding if unknown object is encountered... */
2750 break;
2752 /* Increment the bit index for next time */
2753 bitindex++;
2755 /* And increment the point address, may be overwritten by an index value */
2756 al_ptaddr++;
2758 if (start_offset > offset) {
2759 expert_add_info(pinfo, point_item, &ei_dnp_invalid_length);
2760 offset = tvb_length(tvb); /* Finish decoding if unknown object is encountered... */
2764 proto_item_set_len(object_item, offset - orig_offset);
2766 return offset;
2769 /*****************************************************************/
2770 /* Application Layer Dissector */
2771 /*****************************************************************/
2772 static int
2773 dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2775 guint8 al_ctl, al_seq, al_func, al_class = 0, i;
2776 guint16 bytes, obj_type;
2777 guint data_len = 0, offset = 0;
2778 proto_item *ti, *tc, *t_robj;
2779 proto_tree *al_tree, *field_tree, *robj_tree;
2780 const gchar *func_code_str;
2781 nstime_t al_cto;
2783 nstime_set_zero (&al_cto);
2785 data_len = tvb_length(tvb);
2787 /* Handle the control byte and function code */
2788 al_ctl = tvb_get_guint8(tvb, offset);
2789 al_seq = al_ctl & DNP3_AL_SEQ;
2790 al_func = tvb_get_guint8(tvb, (offset+1));
2791 func_code_str = val_to_str_ext(al_func, &dnp3_al_func_vals_ext, "Unknown function (0x%02x)");
2793 /* Clear out lower layer info */
2794 col_clear(pinfo->cinfo, COL_INFO);
2795 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", func_code_str);
2796 col_set_fence(pinfo->cinfo, COL_INFO);
2798 /* format up the text representation */
2799 ti = proto_tree_add_text(tree, tvb, offset, data_len, "Application Layer: (");
2800 if (al_ctl & DNP3_AL_FIR) proto_item_append_text(ti, "FIR, ");
2801 if (al_ctl & DNP3_AL_FIN) proto_item_append_text(ti, "FIN, ");
2802 if (al_ctl & DNP3_AL_CON) proto_item_append_text(ti, "CON, ");
2803 if (al_ctl & DNP3_AL_UNS) proto_item_append_text(ti, "UNS, ");
2804 proto_item_append_text(ti, "Sequence %u, %s)", al_seq, func_code_str);
2806 /* Add the al tree branch */
2807 al_tree = proto_item_add_subtree(ti, ett_dnp3_al);
2809 /* Application Layer control byte subtree */
2810 tc = proto_tree_add_uint_format(al_tree, hf_dnp3_al_ctl, tvb, offset, 1, al_ctl,
2811 "Control: 0x%02x (", al_ctl);
2812 if (al_ctl & DNP3_AL_FIR) proto_item_append_text(tc, "FIR, ");
2813 if (al_ctl & DNP3_AL_FIN) proto_item_append_text(tc, "FIN, ");
2814 if (al_ctl & DNP3_AL_CON) proto_item_append_text(tc, "CON, ");
2815 if (al_ctl & DNP3_AL_UNS) proto_item_append_text(tc, "UNS, ");
2816 proto_item_append_text(tc, "Sequence %u)", al_seq);
2818 field_tree = proto_item_add_subtree(tc, ett_dnp3_al_ctl);
2819 proto_tree_add_boolean(field_tree, hf_dnp3_al_fir, tvb, offset, 1, al_ctl);
2820 proto_tree_add_boolean(field_tree, hf_dnp3_al_fin, tvb, offset, 1, al_ctl);
2821 proto_tree_add_boolean(field_tree, hf_dnp3_al_con, tvb, offset, 1, al_ctl);
2822 proto_tree_add_boolean(field_tree, hf_dnp3_al_uns, tvb, offset, 1, al_ctl);
2823 proto_tree_add_item(field_tree, hf_dnp3_al_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
2824 offset += 1;
2826 #if 0
2827 /* If this packet is NOT the final Application Layer Message, exit and continue
2828 processing the remaining data in the fragment. */
2829 if (!(al_ctl & DNP3_AL_FIN)) {
2830 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Buffering User Data Until Final Frame is Received..");
2831 return 1;
2833 #endif
2835 /* Application Layer Function Code Byte */
2836 proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
2837 "Function Code: %s (0x%02x)", func_code_str, al_func);
2838 offset += 1;
2840 switch (al_func)
2842 case AL_FUNC_READ: /* Read Function Code 0x01 */
2844 /* Create Read Request Data Objects Tree */
2845 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "READ Request Data Objects");
2846 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2848 /* Process Data Object Details */
2849 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2850 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, TRUE, &obj_type, &al_cto);
2852 /* Update class type for each object that was a class read */
2853 switch(obj_type) {
2854 case AL_OBJ_CLASS0:
2855 case AL_OBJ_CLASS1:
2856 case AL_OBJ_CLASS2:
2857 case AL_OBJ_CLASS3:
2858 al_class |= (1 << ((obj_type & 0x0f) - 1));
2859 break;
2860 default:
2861 break;
2865 /* Update the col info if there were class reads */
2866 if (al_class != 0) {
2867 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Class ");
2868 for (i = 0; i < 4; i++) {
2869 if (al_class & (1 << i)) {
2870 col_append_fstr(pinfo->cinfo, COL_INFO, "%u", i);
2875 /* For reads for specific object types, bit-mask out the first byte and use that to determine the column info to add */
2876 switch(obj_type & 0xFF00) {
2877 case (AL_OBJ_DA_GRP & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Device Attribute"); break;
2878 case (AL_OBJ_BI_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Binary Input"); break;
2879 case (AL_OBJ_BIC_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Binary Input Change"); break;
2880 case (AL_OBJ_2BI_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Double-bit Input"); break;
2881 case (AL_OBJ_2BIC_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Double-bit Input Change"); break;
2882 case (AL_OBJ_BO_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Binary Output"); break;
2883 case (AL_OBJ_CTR_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Counter"); break;
2884 case (AL_OBJ_FCTR_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Frozen Counter"); break;
2885 case (AL_OBJ_CTRC_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Counter Change"); break;
2886 case (AL_OBJ_FCTRC_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Frozen Counter Change"); break;
2887 case (AL_OBJ_AI_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Analog Input"); break;
2888 case (AL_OBJ_AIC_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Analog Input Change"); break;
2889 case (AL_OBJ_AO_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Analog Output"); break;
2890 case (AL_OBJ_AOC_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Analog Output Change"); break;
2891 case (AL_OBJ_TD_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Time and Date"); break;
2892 case (AL_OBJ_FILE_CMD & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "File Control"); break;
2893 case (AL_OBJ_IIN & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Internal Indications"); break;
2894 case (AL_OBJ_OCT & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Octet String"); break;
2895 case (AL_OBJ_OCT_EVT & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Octet String Event"); break;
2896 case (AL_OBJ_VT_EVTD & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Virtual Terminal Event Data"); break;
2898 default: break;
2901 break;
2903 case AL_FUNC_WRITE: /* Write Function Code 0x02 */
2905 /* Create Write Request Data Objects Tree */
2906 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "WRITE Request Data Objects");
2907 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2909 /* Process Data Object Details */
2910 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2911 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
2914 /* For writes of specific object types, bit-mask out the first byte and use that to determine the column info to add */
2915 switch(obj_type & 0xFF00) {
2916 case (AL_OBJ_TD_ALL & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Time and Date"); break;
2917 case (AL_OBJ_FILE_CMD & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "File Control"); break;
2918 case (AL_OBJ_IIN & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Internal Indications"); break;
2919 case (AL_OBJ_OCT & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Octet String"); break;
2920 case (AL_OBJ_OCT_EVT & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Octet String Event"); break;
2921 case (AL_OBJ_VT_OBLK & 0xFF00): col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Virtual Terminal Output Block"); break;
2923 default: break;
2927 break;
2929 case AL_FUNC_SELECT: /* Select Function Code 0x03 */
2931 /* Create Select Request Data Objects Tree */
2932 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "SELECT Request Data Objects");
2933 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2935 /* Process Data Object Details */
2936 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2937 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
2940 break;
2942 case AL_FUNC_OPERATE: /* Operate Function Code 0x04 */
2943 /* Functionally identical to 'SELECT' Function Code */
2945 /* Create Operate Request Data Objects Tree */
2946 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "OPERATE Request Data Objects");
2947 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2949 /* Process Data Object Details */
2950 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2951 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
2954 break;
2956 case AL_FUNC_DIROP: /* Direct Operate Function Code 0x05 */
2957 /* Functionally identical to 'SELECT' Function Code */
2959 /* Create Direct Operate Request Data Objects Tree */
2960 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "DIRECT OPERATE Request Data Objects");
2961 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2963 /* Process Data Object Details */
2964 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2965 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
2968 break;
2970 case AL_FUNC_FRZ: /* Immediate Freeze Function Code 0x07 */
2971 case AL_FUNC_FRZNACK: /* Immediate Freeze No ACK Function Code 0x08 */
2972 case AL_FUNC_FRZCLR: /* Freeze and Clear Function Code 0x09 */
2973 case AL_FUNC_FRZCLRNACK: /* Freeze and Clear No ACK Function Code 0x0A */
2975 /* Create Freeze Request Data Objects Tree */
2976 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Freeze Request Data Objects");
2977 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2979 /* Process Data Object Details */
2980 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2981 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, TRUE, &obj_type, &al_cto);
2984 break;
2986 case AL_FUNC_ENSPMSG: /* Enable Spontaneous Messages Function Code 0x14 */
2988 /* Create Enable Spontaneous Messages Data Objects Tree */
2989 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Enable Spontaneous Msg's Data Objects");
2990 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2992 /* Process Data Object Details */
2993 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
2994 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
2997 break;
2999 case AL_FUNC_DISSPMSG: /* Disable Spontaneous Messages Function Code 0x15 */
3001 /* Create Disable Spontaneous Messages Data Objects Tree */
3002 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Disable Spontaneous Msg's Data Objects");
3003 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
3005 /* Process Data Object Details */
3006 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
3007 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3010 break;
3012 case AL_FUNC_DELAYMST: /* Delay Measurement Function Code 0x17 */
3014 break;
3016 case AL_FUNC_OPENFILE: /* Open File Function Code 0x19 */
3017 case AL_FUNC_CLOSEFILE: /* Close File Function Code 0x1A */
3018 case AL_FUNC_DELETEFILE: /* Delete File Function Code 0x1B */
3020 /* Create File Data Objects Tree */
3021 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "File Data Objects");
3022 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
3024 /* Process Data Object Details */
3025 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
3026 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3029 break;
3031 case AL_FUNC_RESPON: /* Response Function Code 0x81 */
3032 case AL_FUNC_UNSOLI: /* Unsolicited Response Function Code 0x82 */
3034 /* Application Layer IIN bits req'd if message is a response */
3035 dnp3_al_process_iin(tvb, pinfo, offset, al_tree);
3036 offset += 2;
3038 /* Ensure there is actual data remaining in the message.
3039 A response will not contain data following the IIN bits,
3040 if there is none available */
3041 bytes = tvb_reported_length_remaining(tvb, offset);
3042 if (bytes > 0)
3044 /* Create Response Data Objects Tree */
3045 t_robj = proto_tree_add_text(al_tree, tvb, offset, -1,"RESPONSE Data Objects");
3046 robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
3048 /* Process Data Object Details */
3049 while (offset <= (data_len-2)) { /* 2 octet object code + CRC32 */
3050 offset = dnp3_al_process_object(tvb, pinfo, offset, robj_tree, FALSE, &obj_type, &al_cto);
3053 break;
3056 default: /* Unknown Function */
3058 break;
3061 return 0;
3064 /*****************************************************************/
3065 /* Data Link and Transport layer dissector */
3066 /*****************************************************************/
3067 static int
3068 dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
3070 proto_item *ti, *tdl, *tc;
3071 proto_tree *dnp3_tree, *dl_tree, *field_tree;
3072 int offset = 0, temp_offset = 0;
3073 gboolean dl_prm;
3074 guint8 dl_len, dl_ctl, dl_func;
3075 const gchar *func_code_str;
3076 guint16 dl_dst, dl_src, dl_crc, calc_dl_crc;
3078 /* Make entries in Protocol column and Info column on summary display */
3079 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
3080 col_clear(pinfo->cinfo, COL_INFO);
3082 /* Skip "0x0564" header bytes */
3083 temp_offset += 2;
3085 dl_len = tvb_get_guint8(tvb, temp_offset);
3086 temp_offset += 1;
3088 dl_ctl = tvb_get_guint8(tvb, temp_offset);
3089 temp_offset += 1;
3091 dl_dst = tvb_get_letohs(tvb, temp_offset);
3092 temp_offset += 2;
3094 dl_src = tvb_get_letohs(tvb, temp_offset);
3096 dl_func = dl_ctl & DNP3_CTL_FUNC;
3097 dl_prm = dl_ctl & DNP3_CTL_PRM;
3098 func_code_str = val_to_str(dl_func, dl_prm ? dnp3_ctl_func_pri_vals : dnp3_ctl_func_sec_vals,
3099 "Unknown function (0x%02x)");
3101 /* Make sure source and dest are always in the info column */
3102 col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
3103 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "len=%u, %s", dl_len, func_code_str);
3105 /* create display subtree for the protocol */
3106 ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, ENC_NA);
3107 dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);
3109 /* Create Subtree for Data Link Layer */
3110 tdl = proto_tree_add_text(dnp3_tree, tvb, offset, DNP_HDR_LEN,
3111 "Data Link Layer, Len: %u, From: %u, To: %u, ", dl_len, dl_src, dl_dst);
3112 if (dl_prm) {
3113 if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
3114 if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
3115 if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tdl, "FCB, ");
3116 if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tdl, "FCV, ");
3118 else {
3119 if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
3120 if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
3121 if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tdl, "RES, ");
3122 if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tdl, "DFC, ");
3124 proto_item_append_text(tdl, "%s", func_code_str);
3125 dl_tree = proto_item_add_subtree(tdl, ett_dnp3_dl);
3127 /* start bytes */
3128 proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, ENC_BIG_ENDIAN);
3129 offset += 2;
3131 /* add length field */
3132 proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, ENC_BIG_ENDIAN);
3133 offset += 1;
3135 /* Add Control Byte Subtree */
3136 tc = proto_tree_add_uint_format_value(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
3137 "0x%02x (", dl_ctl);
3138 /* Add Text to Control Byte Subtree Header */
3139 if (dl_prm) {
3140 if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
3141 if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
3142 if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tc, "FCB, ");
3143 if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tc, "FCV, ");
3145 else {
3146 if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
3147 if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
3148 if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tc, "RES, ");
3149 if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tc, "DFC, ");
3151 proto_item_append_text(tc, "%s)", func_code_str );
3152 field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);
3154 /* Add Control Byte Subtree Items */
3155 if (dl_prm) {
3156 proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3157 proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3158 proto_tree_add_item(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3159 proto_tree_add_item(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3160 proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, ENC_BIG_ENDIAN);
3162 else {
3163 proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3164 proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3165 proto_tree_add_item(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3166 proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, ENC_BIG_ENDIAN);
3168 offset += 1;
3170 /* add destination and source addresses */
3171 proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3172 offset += 2;
3173 proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3174 offset += 2;
3176 /* and header CRC */
3177 dl_crc = tvb_get_letohs(tvb, offset);
3178 calc_dl_crc = calculateCRC(tvb_get_ptr(tvb, 0, DNP_HDR_LEN - 2), DNP_HDR_LEN - 2);
3179 if (dl_crc == calc_dl_crc)
3180 proto_tree_add_uint_format_value(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
3181 dl_crc, "0x%04x [correct]", dl_crc);
3182 else
3184 proto_item *hidden_item;
3185 hidden_item = proto_tree_add_boolean(dl_tree, hf_dnp_hdr_CRC_bad, tvb,
3186 offset, 2, TRUE);
3187 PROTO_ITEM_SET_HIDDEN(hidden_item);
3188 proto_tree_add_uint_format_value(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
3189 dl_crc, "0x%04x [incorrect, should be 0x%04x]",
3190 dl_crc, calc_dl_crc);
3192 offset += 2;
3194 /* If the DataLink function is 'Request Link Status' or 'Status of Link',
3195 or 'Reset Link' we don't expect any Transport or Application Layer Data
3196 NOTE: This code should probably check what DOES have TR or AL data */
3197 if ((dl_func != DL_FUNC_LINK_STAT) && (dl_func != DL_FUNC_STAT_LINK) &&
3198 (dl_func != DL_FUNC_RESET_LINK) && (dl_func != DL_FUNC_ACK))
3200 proto_tree *tr_tree, *al_tree;
3201 proto_item *al_chunks;
3202 guint8 tr_ctl, tr_seq;
3203 gboolean tr_fir, tr_fin;
3204 guint8 *tmp, *tmp_ptr;
3205 guint8 data_len;
3206 int data_offset;
3207 gboolean crc_OK = FALSE;
3208 tvbuff_t *next_tvb;
3209 guint i;
3211 /* get the transport layer byte */
3212 tr_ctl = tvb_get_guint8(tvb, offset);
3213 tr_seq = tr_ctl & DNP3_TR_SEQ;
3214 tr_fir = tr_ctl & DNP3_TR_FIR;
3215 tr_fin = tr_ctl & DNP3_TR_FIN;
3217 /* Add Transport Layer Tree */
3218 tc = proto_tree_add_uint_format(dnp3_tree, hf_dnp3_tr_ctl, tvb, offset, 1, tr_ctl,
3219 "Transport Layer: 0x%02x (", tr_ctl);
3220 if (tr_fir) proto_item_append_text(tc, "FIR, ");
3221 if (tr_fin) proto_item_append_text(tc, "FIN, ");
3222 proto_item_append_text(tc, "Sequence %u)", tr_seq);
3224 tr_tree = proto_item_add_subtree(tc, ett_dnp3_tr_ctl);
3225 proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fin, tvb, offset, 1, tr_ctl);
3226 proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fir, tvb, offset, 1, tr_ctl);
3227 proto_tree_add_item(tr_tree, hf_dnp3_tr_seq, tvb, offset, 1, ENC_BIG_ENDIAN);
3229 /* Allocate AL chunk tree */
3230 al_chunks = proto_tree_add_text(tr_tree, tvb, offset + 1, -1, "Application data chunks");
3231 al_tree = proto_item_add_subtree(al_chunks, ett_dnp3_al_data);
3233 /* extract the application layer data, validating the CRCs */
3235 /* XXX - check for dl_len <= 5 */
3236 data_len = dl_len - 5;
3237 tmp = (guint8 *)wmem_alloc(pinfo->pool, data_len);
3238 tmp_ptr = tmp;
3239 i = 0;
3240 data_offset = 1; /* skip the transport layer byte when assembling chunks */
3241 while (data_len > 0)
3243 guint8 chk_size;
3244 const guint8 *chk_ptr;
3245 guint16 calc_crc, act_crc;
3247 chk_size = MIN(data_len, AL_MAX_CHUNK_SIZE);
3248 chk_ptr = tvb_get_ptr(tvb, offset, chk_size);
3249 memcpy(tmp_ptr, chk_ptr + data_offset, chk_size - data_offset);
3250 calc_crc = calculateCRC(chk_ptr, chk_size);
3251 offset += chk_size;
3252 tmp_ptr += chk_size - data_offset;
3253 act_crc = tvb_get_letohs(tvb, offset);
3254 offset += 2;
3255 crc_OK = calc_crc == act_crc;
3256 if (crc_OK)
3258 proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
3259 "Application Chunk %u Len: %u CRC 0x%04x",
3260 i, chk_size, act_crc);
3261 data_len -= chk_size;
3263 else
3265 proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
3266 "Application Chunk %u Len: %u Bad CRC got 0x%04x expected 0x%04x",
3267 i, chk_size, act_crc, calc_crc);
3268 break;
3270 i++;
3271 data_offset = 0; /* copy all of the rest of the chunks */
3274 /* if all crc OK, set up new tvb */
3275 if (crc_OK)
3277 tvbuff_t *al_tvb;
3278 gboolean save_fragmented;
3280 al_tvb = tvb_new_child_real_data(tvb, tmp, (guint) (tmp_ptr-tmp), (gint) (tmp_ptr-tmp));
3282 /* Check for fragmented packet */
3283 save_fragmented = pinfo->fragmented;
3284 if (! (tr_fir && tr_fin))
3286 guint conv_seq_number;
3287 fragment_head *frag_msg;
3288 conversation_t *conversation;
3289 dnp3_conv_t *conv_data_ptr;
3290 dl_conversation_key_t dl_conversation_key;
3292 /* A fragmented packet */
3293 pinfo->fragmented = TRUE;
3295 /* Look up the conversation to get the fragment reassembly id */
3296 conversation = find_or_create_conversation(pinfo);
3299 * The TCP/UDP conversation is not sufficient to identify a conversation
3300 * on a multi-drop DNP network. Lookup conversation data based on TCP/UDP
3301 * conversation and the DNP src and dst addresses
3304 dl_conversation_key.conversation = conversation->index;
3305 dl_conversation_key.src = dl_src;
3306 dl_conversation_key.dst = dl_dst;
3308 conv_data_ptr = (dnp3_conv_t*)g_hash_table_lookup(dl_conversation_table, &dl_conversation_key);
3310 if (!pinfo->fd->flags.visited && conv_data_ptr == NULL)
3312 dl_conversation_key_t* new_dl_conversation_key = NULL;
3313 new_dl_conversation_key = wmem_new(wmem_file_scope(), dl_conversation_key_t);
3314 *new_dl_conversation_key = dl_conversation_key;
3316 conv_data_ptr = wmem_new(wmem_file_scope(), dnp3_conv_t);
3318 /*** Increment static global fragment reassembly id ***/
3319 conv_data_ptr->conv_seq_number = seq_number++;
3321 g_hash_table_insert(dl_conversation_table, new_dl_conversation_key, conv_data_ptr);
3324 conv_seq_number = conv_data_ptr->conv_seq_number;
3327 * Add the frame to
3328 * whatever reassembly is in progress, if any, and see
3329 * if it's done.
3332 frag_msg = fragment_add_seq_next(&al_reassembly_table,
3333 al_tvb, 0, pinfo, conv_seq_number, NULL,
3334 tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
3335 !tr_fin);
3337 next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
3338 "Reassembled DNP 3.0 Application Layer message", frag_msg, &dnp3_frag_items,
3339 NULL, tr_tree);
3341 if (next_tvb) /* Reassembled */
3343 /* We have the complete payload, zap the info column as the AL info takes precedence */
3344 col_clear(pinfo->cinfo, COL_INFO);
3346 else
3348 /* We don't have the complete reassembled payload. */
3349 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "TL fragment %u ", tr_seq);
3353 else
3355 /* No reassembly required */
3356 next_tvb = al_tvb;
3357 add_new_data_source(pinfo, next_tvb, "DNP 3.0 Application Layer message");
3358 col_clear(pinfo->cinfo, COL_INFO);
3360 pinfo->fragmented = save_fragmented;
3362 else
3364 /* CRC error - throw away the data. */
3365 next_tvb = NULL;
3366 proto_tree_add_text(dnp3_tree, tvb, 11, -1, "CRC failed, %u chunks", i);
3369 /* Dissect any completed Application Layer message */
3370 if (next_tvb && tr_fin)
3372 /* As a complete AL message will have cleared the info column,
3373 make sure source and dest are always in the info column */
3374 col_append_fstr(pinfo->cinfo, COL_INFO, "from %u to %u", dl_src, dl_dst);
3375 col_set_fence(pinfo->cinfo, COL_INFO);
3376 dissect_dnp3_al(next_tvb, pinfo, dnp3_tree);
3378 else
3380 /* Lock any column info set by the DL and TL */
3381 col_set_fence(pinfo->cinfo, COL_INFO);
3385 return tvb_length(tvb);
3388 static guint
3389 get_dnp3_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
3391 guint16 message_len; /* need 16 bits as total can exceed 255 */
3392 guint16 data_crc; /* No. of user data CRC bytes */
3394 message_len = tvb_get_guint8(tvb, offset + 2);
3396 /* Add in 2 bytes for header start octets,
3397 1 byte for len itself,
3398 2 bytes for header CRC
3399 data CRC bytes (2 bytes per 16 bytes of data
3402 data_crc = (guint16)(ceil((message_len - 5) / 16.0)) * 2;
3403 message_len += 2 + 1 + 2 + data_crc;
3404 return message_len;
3407 static gboolean
3408 dissect_dnp3_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3410 gint length = tvb_length(tvb);
3412 /* Check for a dnp packet. It should begin with 0x0564 */
3413 if ((length < 2) || (tvb_get_ntohs(tvb, 0) != 0x0564)) {
3414 /* Not a DNP 3.0 packet, just happened to use the same port */
3415 return FALSE;
3418 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DNP_HDR_LEN,
3419 get_dnp3_message_len, dissect_dnp3_message, data);
3421 return TRUE;
3424 static gboolean
3425 dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
3427 gint length = tvb_length(tvb);
3429 /* Check for a dnp packet. It should begin with 0x0564 */
3430 if ((length < 2) || (tvb_get_ntohs(tvb, 0) != 0x0564)) {
3431 /* Not a DNP 3.0 packet, just happened to use the same port */
3432 return FALSE;
3435 dissect_dnp3_message(tvb, pinfo, tree, data);
3436 return TRUE;
3439 static void
3440 dnp3_init(void)
3442 if (dl_conversation_table)
3444 g_hash_table_destroy(dl_conversation_table);
3446 dl_conversation_table = g_hash_table_new(dl_conversation_hash, dl_conversation_equal);
3448 reassembly_table_init(&al_reassembly_table,
3449 &addresses_reassembly_table_functions);
3452 /* Register the protocol with Wireshark */
3454 void
3455 proto_register_dnp3(void)
3458 /* Setup list of header fields */
3459 static hf_register_info hf[] = {
3460 { &hf_dnp3_start,
3461 { "Start Bytes", "dnp3.start",
3462 FT_UINT16, BASE_HEX, NULL, 0x0,
3463 NULL, HFILL }
3466 { &hf_dnp3_len,
3467 { "Length", "dnp3.len",
3468 FT_UINT8, BASE_DEC, NULL, 0x0,
3469 "Frame Data Length", HFILL }
3472 { &hf_dnp3_ctl,
3473 { "Control", "dnp3.ctl",
3474 FT_UINT8, BASE_HEX, NULL, 0x0,
3475 "Frame Control Byte", HFILL }
3478 { &hf_dnp3_ctl_prifunc,
3479 { "Control Function Code", "dnp3.ctl.prifunc",
3480 FT_UINT8, BASE_DEC, VALS(dnp3_ctl_func_pri_vals), DNP3_CTL_FUNC,
3481 "Frame Control Function Code", HFILL }
3484 { &hf_dnp3_ctl_secfunc,
3485 { "Control Function Code", "dnp3.ctl.secfunc",
3486 FT_UINT8, BASE_DEC, VALS(dnp3_ctl_func_sec_vals), DNP3_CTL_FUNC,
3487 "Frame Control Function Code", HFILL }
3490 { &hf_dnp3_ctlobj_code_c,
3491 { "Operation Type", "dnp3.ctl.op",
3492 FT_UINT8, BASE_DEC, VALS(dnp3_al_ctlc_code_vals), AL_OBJCTLC_CODE,
3493 "Control Code, Operation Type", HFILL }
3496 { &hf_dnp3_ctlobj_code_m,
3497 { "Queue / Clear Field", "dnp3.ctl.clr",
3498 FT_UINT8, BASE_DEC, VALS(dnp3_al_ctlc_misc_vals), AL_OBJCTLC_MISC,
3499 "Control Code, Clear Field", HFILL }
3502 { &hf_dnp3_ctlobj_code_tc,
3503 { "Trip Control Code", "dnp3.ctl.trip",
3504 FT_UINT8, BASE_DEC, VALS(dnp3_al_ctlc_tc_vals), AL_OBJCTLC_TC,
3505 "Control Code, Trip Close Control", HFILL }
3508 { &hf_dnp3_ctl_dir,
3509 { "Direction", "dnp3.ctl.dir",
3510 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DIR,
3511 NULL, HFILL }
3514 { &hf_dnp3_ctl_prm,
3515 { "Primary", "dnp3.ctl.prm",
3516 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_PRM,
3517 NULL, HFILL }
3520 { &hf_dnp3_ctl_fcb,
3521 { "Frame Count Bit", "dnp3.ctl.fcb",
3522 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCB,
3523 NULL, HFILL }
3526 { &hf_dnp3_ctl_fcv,
3527 { "Frame Count Valid", "dnp3.ctl.fcv",
3528 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCV,
3529 NULL, HFILL }
3532 { &hf_dnp3_ctl_dfc,
3533 { "Data Flow Control", "dnp3.ctl.dfc",
3534 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DFC,
3535 NULL, HFILL }
3538 { &hf_dnp3_dst,
3539 { "Destination", "dnp3.dst",
3540 FT_UINT16, BASE_DEC, NULL, 0x0,
3541 "Destination Address", HFILL }
3544 { &hf_dnp3_src,
3545 { "Source", "dnp3.src",
3546 FT_UINT16, BASE_DEC, NULL, 0x0,
3547 "Source Address", HFILL }
3550 { &hf_dnp_hdr_CRC,
3551 { "CRC", "dnp3.hdr.CRC",
3552 FT_UINT16, BASE_HEX, NULL, 0x0,
3553 NULL, HFILL }
3556 { &hf_dnp_hdr_CRC_bad,
3557 { "Bad CRC", "dnp3.hdr.CRC_bad",
3558 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3559 NULL, HFILL }
3562 { &hf_dnp3_tr_ctl,
3563 { "Transport Control", "dnp3.tr.ctl",
3564 FT_UINT8, BASE_HEX, NULL, 0x0,
3565 "Transport Layer Control Byte", HFILL }
3568 { &hf_dnp3_tr_fin,
3569 { "Final", "dnp3.tr.fin",
3570 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIN,
3571 NULL, HFILL }
3574 { &hf_dnp3_tr_fir,
3575 { "First", "dnp3.tr.fir",
3576 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIR,
3577 NULL, HFILL }
3580 { &hf_dnp3_tr_seq,
3581 { "Sequence", "dnp3.tr.seq",
3582 FT_UINT8, BASE_DEC, NULL, DNP3_TR_SEQ,
3583 "Frame Sequence Number", HFILL }
3586 { &hf_dnp3_al_ctl,
3587 { "Application Control", "dnp3.al.ctl",
3588 FT_UINT8, BASE_HEX, NULL, 0x0,
3589 "Application Layer Control Byte", HFILL }
3592 { &hf_dnp3_al_fir,
3593 { "First", "dnp3.al.fir",
3594 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIR,
3595 NULL, HFILL }
3598 { &hf_dnp3_al_fin,
3599 { "Final", "dnp3.al.fin",
3600 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIN,
3601 NULL, HFILL }
3604 { &hf_dnp3_al_con,
3605 { "Confirm", "dnp3.al.con",
3606 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_CON,
3607 NULL, HFILL }
3610 { &hf_dnp3_al_uns,
3611 { "Unsolicited", "dnp3.al.uns",
3612 FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_UNS,
3613 NULL, HFILL }
3616 { &hf_dnp3_al_seq,
3617 { "Sequence", "dnp3.al.seq",
3618 FT_UINT8, BASE_DEC, NULL, DNP3_AL_SEQ,
3619 "Frame Sequence Number", HFILL }
3622 { &hf_dnp3_al_func,
3623 { "Application Layer Function Code", "dnp3.al.func",
3624 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_func_vals_ext, DNP3_AL_FUNC,
3625 "Application Function Code", HFILL }
3628 { &hf_dnp3_al_iin,
3629 { "Application Layer IIN bits", "dnp3.al.iin",
3630 FT_UINT16, BASE_DEC, NULL, 0x0,
3631 "Application Layer IIN", HFILL }
3634 { &hf_dnp3_al_iin_bmsg,
3635 { "Broadcast Msg Rx", "dnp3.al.iin.bmsg",
3636 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_BMSG,
3637 NULL, HFILL }
3640 { &hf_dnp3_al_iin_cls1d,
3641 { "Class 1 Data Available", "dnp3.al.iin.cls1d",
3642 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS1D,
3643 NULL, HFILL }
3646 { &hf_dnp3_al_iin_cls2d,
3647 { "Class 2 Data Available", "dnp3.al.iin.cls2d",
3648 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS2D,
3649 NULL, HFILL }
3652 { &hf_dnp3_al_iin_cls3d,
3653 { "Class 3 Data Available", "dnp3.al.iin.cls3d",
3654 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS3D,
3655 NULL, HFILL }
3658 { &hf_dnp3_al_iin_tsr,
3659 { "Time Sync Required", "dnp3.al.iin.tsr",
3660 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_TSR,
3661 NULL, HFILL }
3664 { &hf_dnp3_al_iin_dol,
3665 { "Digital Outputs in Local", "dnp3.al.iin.dol",
3666 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DOL,
3667 NULL, HFILL }
3670 { &hf_dnp3_al_iin_dt,
3671 { "Device Trouble", "dnp3.al.iin.dt",
3672 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DT,
3673 NULL, HFILL }
3676 { &hf_dnp3_al_iin_rst,
3677 { "Device Restart", "dnp3.al.iin.rst",
3678 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_RST,
3679 NULL, HFILL }
3682 { &hf_dnp3_al_iin_fcni,
3683 { "Function Code not implemented", "dnp3.al.iin.fcni",
3684 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_FCNI,
3685 NULL, HFILL }
3688 { &hf_dnp3_al_iin_obju,
3689 { "Requested Objects Unknown", "dnp3.al.iin.obju",
3690 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OBJU,
3691 NULL, HFILL }
3694 { &hf_dnp3_al_iin_pioor,
3695 { "Parameters Invalid or Out of Range", "dnp3.al.iin.pioor",
3696 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_PIOOR,
3697 NULL, HFILL }
3700 { &hf_dnp3_al_iin_ebo,
3701 { "Event Buffer Overflow", "dnp3.al.iin.ebo",
3702 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_EBO,
3703 NULL, HFILL }
3706 { &hf_dnp3_al_iin_oae,
3707 { "Operation Already Executing", "dnp3.al.iin.oae",
3708 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OAE,
3709 NULL, HFILL }
3712 { &hf_dnp3_al_iin_cc,
3713 { "Configuration Corrupt", "dnp3.al.iin.cc",
3714 FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CC,
3715 NULL, HFILL }
3718 { &hf_dnp3_al_obj,
3719 { "Object", "dnp3.al.obj",
3720 FT_UINT16, BASE_HEX|BASE_EXT_STRING, &dnp3_al_obj_vals_ext, 0x0,
3721 "Application Layer Object", HFILL }
3724 { &hf_dnp3_al_objq_index,
3725 { "Index Prefix", "dnp3.al.objq.index",
3726 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_objq_index_vals_ext, AL_OBJQ_INDEX,
3727 "Object Index Prefixing", HFILL }
3730 { &hf_dnp3_al_objq_code,
3731 { "Qualifier Code", "dnp3.al.objq.code",
3732 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_objq_code_vals_ext, AL_OBJQ_CODE,
3733 "Object Qualifier Code", HFILL }
3736 { &hf_dnp3_al_range_start8,
3737 { "Start (8 bit)", "dnp3.al.range.start",
3738 FT_UINT8, BASE_DEC, NULL, 0x0,
3739 "Object Start Index", HFILL }
3742 { &hf_dnp3_al_range_stop8,
3743 { "Stop (8 bit)", "dnp3.al.range.stop",
3744 FT_UINT8, BASE_DEC, NULL, 0x0,
3745 "Object Stop Index", HFILL }
3748 { &hf_dnp3_al_range_start16,
3749 { "Start (16 bit)", "dnp3.al.range.start",
3750 FT_UINT16, BASE_DEC, NULL, 0x0,
3751 "Object Start Index", HFILL }
3754 { &hf_dnp3_al_range_stop16,
3755 { "Stop (16 bit)", "dnp3.al.range.stop",
3756 FT_UINT16, BASE_DEC, NULL, 0x0,
3757 "Object Stop Index", HFILL }
3760 { &hf_dnp3_al_range_start32,
3761 { "Start (32 bit)", "dnp3.al.range.start",
3762 FT_UINT32, BASE_DEC, NULL, 0x0,
3763 "Object Start Index", HFILL }
3766 { &hf_dnp3_al_range_stop32,
3767 { "Stop (32 bit)", "dnp3.al.range.stop",
3768 FT_UINT32, BASE_DEC, NULL, 0x0,
3769 "Object Stop Index", HFILL }
3772 { &hf_dnp3_al_range_abs8,
3773 { "Address (8 bit)", "dnp3.al.range.abs",
3774 FT_UINT8, BASE_DEC, NULL, 0x0,
3775 "Object Absolute Address", HFILL }
3778 { &hf_dnp3_al_range_abs16,
3779 { "Address (16 bit)", "dnp3.al.range.abs",
3780 FT_UINT16, BASE_DEC, NULL, 0x0,
3781 "Object Absolute Address", HFILL }
3784 { &hf_dnp3_al_range_abs32,
3785 { "Address (32 bit)", "dnp3.al.range.abs",
3786 FT_UINT32, BASE_DEC, NULL, 0x0,
3787 "Object Absolute Address", HFILL }
3790 { &hf_dnp3_al_range_quant8,
3791 { "Quantity (8 bit)", "dnp3.al.range.quantity",
3792 FT_UINT8, BASE_DEC, NULL, 0x0,
3793 "Object Quantity", HFILL }
3796 { &hf_dnp3_al_range_quant16,
3797 { "Quantity (16 bit)", "dnp3.al.range.quantity",
3798 FT_UINT16, BASE_DEC, NULL, 0x0,
3799 "Object Quantity", HFILL }
3802 { &hf_dnp3_al_range_quant32,
3803 { "Quantity (32 bit)", "dnp3.al.range.quantity",
3804 FT_UINT32, BASE_DEC, NULL, 0x0,
3805 "Object Quantity", HFILL }
3808 { &hf_dnp3_al_index8,
3809 { "Index (8 bit)", "dnp3.al.index",
3810 FT_UINT8, BASE_DEC, NULL, 0x0,
3811 "Object Index", HFILL }
3814 { &hf_dnp3_al_index16,
3815 { "Index (16 bit)", "dnp3.al.index",
3816 FT_UINT16, BASE_DEC, NULL, 0x0,
3817 "Object Index", HFILL }
3820 { &hf_dnp3_al_index32,
3821 { "Index (32 bit)", "dnp3.al.index",
3822 FT_UINT32, BASE_DEC, NULL, 0x0,
3823 "Object Index", HFILL }
3826 #if 0
3827 { &hf_dnp3_al_ptnum,
3828 { "Object Point Number", "dnp3.al.ptnum",
3829 FT_UINT16, BASE_DEC, NULL, 0x0,
3830 NULL, HFILL }
3832 #endif
3834 { &hf_dnp3_al_size8,
3835 { "Size (8 bit)", "dnp3.al.size",
3836 FT_UINT8, BASE_DEC, NULL, 0x0,
3837 "Object Size", HFILL }
3840 { &hf_dnp3_al_size16,
3841 { "Size (16 bit)", "dnp3.al.size",
3842 FT_UINT16, BASE_DEC, NULL, 0x0,
3843 "Object Size", HFILL }
3846 { &hf_dnp3_al_size32,
3847 { "Size (32 bit)", "dnp3.al.size",
3848 FT_UINT32, BASE_DEC, NULL, 0x0,
3849 "Object Size", HFILL }
3852 { &hf_dnp3_al_bit,
3853 { "Value (bit)", "dnp3.al.bit",
3854 FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x1,
3855 "Digital Value (1 bit)", HFILL }
3858 { &hf_dnp3_al_2bit,
3859 { "Value (two bit)", "dnp3.al.2bit",
3860 FT_UINT8, BASE_DEC, NULL, 0x0,
3861 "Digital Value (2 bit)", HFILL }
3864 { &hf_dnp3_al_ana16,
3865 { "Value (16 bit)", "dnp3.al.ana",
3866 FT_UINT16, BASE_DEC, NULL, 0x0,
3867 "Analog Value (16 bit)", HFILL }
3870 { &hf_dnp3_al_ana32,
3871 { "Value (32 bit)", "dnp3.al.ana",
3872 FT_UINT32, BASE_DEC, NULL, 0x0,
3873 "Analog Value (32 bit)", HFILL }
3876 { &hf_dnp3_al_anaflt,
3877 { "Value (float)", "dnp3.al.ana",
3878 FT_FLOAT, BASE_NONE, NULL, 0x0,
3879 "Analog Value (float)", HFILL }
3882 { &hf_dnp3_al_anadbl,
3883 { "Value (double)", "dnp3.al.ana",
3884 FT_DOUBLE, BASE_NONE, NULL, 0x0,
3885 "Analog Value (double)", HFILL }
3888 { &hf_dnp3_al_anaout16,
3889 { "Output Value (16 bit)", "dnp3.al.anaout",
3890 FT_UINT16, BASE_DEC, NULL, 0x0,
3891 NULL, HFILL }
3894 { &hf_dnp3_al_anaout32,
3895 { "Output Value (32 bit)", "dnp3.al.anaout",
3896 FT_UINT32, BASE_DEC, NULL, 0x0,
3897 NULL, HFILL }
3900 { &hf_dnp3_al_anaoutflt,
3901 { "Output Value (float)", "dnp3.al.anaout",
3902 FT_FLOAT, BASE_NONE, NULL, 0x0,
3903 NULL, HFILL }
3906 { &hf_dnp3_al_anaoutdbl,
3907 { "Output (double)", "dnp3.al.anaout",
3908 FT_DOUBLE, BASE_NONE, NULL, 0x0,
3909 "Output Value (double)", HFILL }
3912 { &hf_dnp3_al_cnt16,
3913 { "Counter (16 bit)", "dnp3.al.cnt",
3914 FT_UINT16, BASE_DEC, NULL, 0x0,
3915 "Counter Value (16 bit)", HFILL }
3918 { &hf_dnp3_al_cnt32,
3919 { "Counter (32 bit)", "dnp3.al.cnt",
3920 FT_UINT32, BASE_DEC, NULL, 0x0,
3921 "Counter Value (32 bit)", HFILL }
3924 { &hf_dnp3_al_ctrlstatus,
3925 { "Control Status", "dnp3.al.ctrlstatus",
3926 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_ctl_status_vals_ext, 0xff,
3927 NULL, HFILL }
3930 { &hf_dnp3_al_file_mode,
3931 { "File Control Mode", "dnp3.al.file.mode",
3932 FT_UINT16, BASE_DEC, VALS(dnp3_al_file_mode_vals), 0x0,
3933 NULL, HFILL }
3936 { &hf_dnp3_al_file_auth,
3937 { "File Authentication Key", "dnp3.al.file.auth",
3938 FT_UINT32, BASE_HEX, NULL, 0x0,
3939 NULL, HFILL }
3942 { &hf_dnp3_al_file_size,
3943 { "File Size", "dnp3.al.file.size",
3944 FT_UINT32, BASE_HEX, NULL, 0x0,
3945 NULL, HFILL }
3948 { &hf_dnp3_al_file_maxblk,
3949 { "File Max Block Size", "dnp3.al.file.maxblock",
3950 FT_UINT16, BASE_DEC, NULL, 0x0,
3951 NULL, HFILL }
3954 { &hf_dnp3_al_file_reqID,
3955 { "File Request Identifier", "dnp3.al.file.reqID",
3956 FT_UINT16, BASE_DEC, NULL, 0x0,
3957 NULL, HFILL }
3960 { &hf_dnp3_al_file_status,
3961 { "File Control Status", "dnp3.al.file.status",
3962 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &dnp3_al_file_status_vals_ext, 0x0,
3963 NULL, HFILL }
3966 { &hf_dnp3_al_file_handle,
3967 { "File Handle", "dnp3.al.file.handle",
3968 FT_UINT32, BASE_HEX, NULL, 0x0,
3969 NULL, HFILL }
3972 { &hf_dnp3_al_file_blocknum,
3973 { "File Block Number", "dnp3.al.file.blocknum",
3974 FT_UINT32, BASE_HEX, NULL, 0x7fffffff,
3975 NULL, HFILL }
3978 { &hf_dnp3_al_file_lastblock,
3979 { "File Last Block", "dnp3.al.file.lastblock",
3980 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x80000000,
3981 NULL, HFILL }
3984 { &hf_dnp3_al_file_data,
3985 { "File Data", "dnp3.al.file.data",
3986 FT_BYTES, BASE_NONE, NULL, 0x0,
3987 NULL, HFILL }
3990 { &hf_dnp3_al_biq_b0,
3991 { "Online", "dnp3.al.biq.b0",
3992 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG0,
3993 NULL, HFILL }
3996 { &hf_dnp3_al_biq_b1,
3997 { "Restart", "dnp3.al.biq.b1",
3998 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG1,
3999 NULL, HFILL }
4002 { &hf_dnp3_al_biq_b2,
4003 { "Comm Fail", "dnp3.al.biq.b2",
4004 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG2,
4005 NULL, HFILL }
4008 { &hf_dnp3_al_biq_b3,
4009 { "Remote Force", "dnp3.al.biq.b3",
4010 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG3,
4011 NULL, HFILL }
4014 { &hf_dnp3_al_biq_b4,
4015 { "Local Force", "dnp3.al.biq.b4",
4016 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG4,
4017 NULL, HFILL }
4020 { &hf_dnp3_al_biq_b5,
4021 { "Chatter Filter", "dnp3.al.biq.b5",
4022 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG5,
4023 NULL, HFILL }
4026 { &hf_dnp3_al_biq_b6,
4027 { "Reserved", "dnp3.al.biq.b6",
4028 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG6,
4029 NULL, HFILL }
4032 { &hf_dnp3_al_biq_b7,
4033 { "Point Value", "dnp3.al.biq.b7",
4034 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG7,
4035 NULL, HFILL }
4038 { &hf_dnp3_al_boq_b0,
4039 { "Online", "dnp3.al.boq.b0",
4040 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG0,
4041 NULL, HFILL }
4044 { &hf_dnp3_al_boq_b1,
4045 { "Restart", "dnp3.al.boq.b1",
4046 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG1,
4047 NULL, HFILL }
4050 { &hf_dnp3_al_boq_b2,
4051 { "Comm Fail", "dnp3.al.boq.b2",
4052 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG2,
4053 NULL, HFILL }
4056 { &hf_dnp3_al_boq_b3,
4057 { "Remote Force", "dnp3.al.boq.b3",
4058 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG3,
4059 NULL, HFILL }
4062 { &hf_dnp3_al_boq_b4,
4063 { "Local Force", "dnp3.al.boq.b4",
4064 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG4,
4065 NULL, HFILL }
4068 { &hf_dnp3_al_boq_b5,
4069 { "Reserved", "dnp3.al.boq.b5",
4070 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG5,
4071 NULL, HFILL }
4074 { &hf_dnp3_al_boq_b6,
4075 { "Reserved", "dnp3.al.boq.b6",
4076 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG6,
4077 NULL, HFILL }
4080 { &hf_dnp3_al_boq_b7,
4081 { "Point Value", "dnp3.al.boq.b7",
4082 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG7,
4083 NULL, HFILL }
4086 { &hf_dnp3_al_ctrq_b0,
4087 { "Online", "dnp3.al.ctrq.b0",
4088 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG0,
4089 NULL, HFILL }
4092 { &hf_dnp3_al_ctrq_b1,
4093 { "Restart", "dnp3.al.ctrq.b1",
4094 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG1,
4095 NULL, HFILL }
4098 { &hf_dnp3_al_ctrq_b2,
4099 { "Comm Fail", "dnp3.al.ctrq.b2",
4100 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG2,
4101 NULL, HFILL }
4104 { &hf_dnp3_al_ctrq_b3,
4105 { "Remote Force", "dnp3.al.ctrq.b3",
4106 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG3,
4107 NULL, HFILL }
4110 { &hf_dnp3_al_ctrq_b4,
4111 { "Local Force", "dnp3.al.ctrq.b4",
4112 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG4,
4113 NULL, HFILL }
4116 { &hf_dnp3_al_ctrq_b5,
4117 { "Roll-Over", "dnp3.al.ctrq.b5",
4118 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG5,
4119 NULL, HFILL }
4122 { &hf_dnp3_al_ctrq_b6,
4123 { "Discontinuity", "dnp3.al.ctrq.b6",
4124 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG6,
4125 NULL, HFILL }
4128 { &hf_dnp3_al_ctrq_b7,
4129 { "Reserved", "dnp3.al.ctrq.b7",
4130 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG7,
4131 NULL, HFILL }
4134 { &hf_dnp3_al_aiq_b0,
4135 { "Online", "dnp3.al.aiq.b0",
4136 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG0,
4137 NULL, HFILL }
4140 { &hf_dnp3_al_aiq_b1,
4141 { "Restart", "dnp3.al.aiq.b1",
4142 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG1,
4143 NULL, HFILL }
4146 { &hf_dnp3_al_aiq_b2,
4147 { "Comm Fail", "dnp3.al.aiq.b2",
4148 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG2,
4149 NULL, HFILL }
4152 { &hf_dnp3_al_aiq_b3,
4153 { "Remote Force", "dnp3.al.aiq.b3",
4154 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG3,
4155 NULL, HFILL }
4158 { &hf_dnp3_al_aiq_b4,
4159 { "Local Force", "dnp3.al.aiq.b4",
4160 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG4,
4161 NULL, HFILL }
4164 { &hf_dnp3_al_aiq_b5,
4165 { "Over-Range", "dnp3.al.aiq.b5",
4166 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG5,
4167 NULL, HFILL }
4170 { &hf_dnp3_al_aiq_b6,
4171 { "Reference Check", "dnp3.al.aiq.b6",
4172 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG6,
4173 NULL, HFILL }
4176 { &hf_dnp3_al_aiq_b7,
4177 { "Reserved", "dnp3.al.aiq.b7",
4178 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG7,
4179 NULL, HFILL }
4182 { &hf_dnp3_al_aoq_b0,
4183 { "Online", "dnp3.al.aoq.b0",
4184 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG0,
4185 NULL, HFILL }
4188 { &hf_dnp3_al_aoq_b1,
4189 { "Restart", "dnp3.al.aoq.b1",
4190 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG1,
4191 NULL, HFILL }
4194 { &hf_dnp3_al_aoq_b2,
4195 { "Comm Fail", "dnp3.al.aoq.b2",
4196 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG2,
4197 NULL, HFILL }
4200 { &hf_dnp3_al_aoq_b3,
4201 { "Remote Force", "dnp3.al.aoq.b3",
4202 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG3,
4203 NULL, HFILL }
4206 { &hf_dnp3_al_aoq_b4,
4207 { "Local Force", "dnp3.al.aoq.b4",
4208 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG4,
4209 NULL, HFILL }
4212 { &hf_dnp3_al_aoq_b5,
4213 { "Reserved", "dnp3.al.aoq.b5",
4214 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG5,
4215 NULL, HFILL }
4218 { &hf_dnp3_al_aoq_b6,
4219 { "Reserved", "dnp3.al.aoq.b6",
4220 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG6,
4221 NULL, HFILL }
4224 { &hf_dnp3_al_aoq_b7,
4225 { "Reserved", "dnp3.al.aoq.b7",
4226 FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG7,
4227 NULL, HFILL }
4230 { &hf_dnp3_al_timestamp,
4231 { "Timestamp", "dnp3.al.timestamp",
4232 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
4233 "Object Timestamp", HFILL }
4236 { &hf_dnp3_al_file_perms,
4237 { "Permissions", "dnp3.al.file.perms",
4238 FT_UINT16, BASE_OCT, NULL, 0x0,
4239 NULL, HFILL }
4242 { &hf_dnp3_al_file_perms_read_owner,
4243 { "Read permission for owner", "dnp3.al.file.perms.read_owner",
4244 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0400,
4245 NULL, HFILL }
4248 { &hf_dnp3_al_file_perms_write_owner,
4249 { "Write permission for owner", "dnp3.al.file.perms.write_owner",
4250 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0200,
4251 NULL, HFILL }
4254 { &hf_dnp3_al_file_perms_exec_owner,
4255 { "Execute permission for owner", "dnp3.al.file.perms.exec_owner",
4256 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0100,
4257 NULL, HFILL }
4260 { &hf_dnp3_al_file_perms_read_group,
4261 { "Read permission for group", "dnp3.al.file.perms.read_group",
4262 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 040,
4263 NULL, HFILL }
4266 { &hf_dnp3_al_file_perms_write_group,
4267 { "Write permission for group", "dnp3.al.file.perms.write_group",
4268 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 020,
4269 NULL, HFILL }
4272 { &hf_dnp3_al_file_perms_exec_group,
4273 { "Execute permission for group", "dnp3.al.file.perms.exec_group",
4274 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 010,
4275 NULL, HFILL }
4278 { &hf_dnp3_al_file_perms_read_world,
4279 { "Read permission for world", "dnp3.al.file.perms.read_world",
4280 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 04,
4281 NULL, HFILL }
4284 { &hf_dnp3_al_file_perms_write_world,
4285 { "Write permission for world", "dnp3.al.file.perms.write_world",
4286 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 02,
4287 NULL, HFILL }
4290 { &hf_dnp3_al_file_perms_exec_world,
4291 { "Execute permission for world", "dnp3.al.file.perms.exec_world",
4292 FT_BOOLEAN, 16, TFS(&tfs_yes_no), 01,
4293 NULL, HFILL }
4296 { &hf_dnp3_al_rel_timestamp,
4297 { "Relative Timestamp", "dnp3.al.reltimestamp",
4298 FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
4299 "Object Relative Timestamp", HFILL }
4302 { &hf_dnp3_al_datatype,
4303 { "Data Type", "dnp3.al.datatype",
4304 FT_UINT8, BASE_HEX, VALS(dnp3_al_data_type_vals), 0,
4305 NULL, HFILL }
4308 { &hf_dnp3_al_da_length,
4309 { "Device Attribute Length", "dnp3.al.da.length",
4310 FT_UINT8, BASE_DEC, NULL, 0,
4311 NULL, HFILL }
4314 { &hf_dnp3_al_da_int8,
4315 { "8-Bit Integer Value", "dnp3.al.da.int8",
4316 FT_INT8, BASE_DEC, NULL, 0,
4317 NULL, HFILL }
4320 { &hf_dnp3_al_da_int32,
4321 { "32-Bit Integer Value", "dnp3.al.da.int32",
4322 FT_INT32, BASE_DEC, NULL, 0,
4323 NULL, HFILL }
4326 { &hf_dnp3_fragment,
4327 { "DNP 3.0 AL Fragment", "dnp3.al.fragment",
4328 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4329 "DNP 3.0 Application Layer Fragment", HFILL }
4332 { &hf_dnp3_fragments,
4333 { "DNP 3.0 AL Fragments", "dnp3.al.fragments",
4334 FT_NONE, BASE_NONE, NULL, 0x0,
4335 "DNP 3.0 Application Layer Fragments", HFILL }
4338 { &hf_dnp3_fragment_overlap,
4339 { "Fragment overlap", "dnp3.al.fragment.overlap",
4340 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4341 "Fragment overlaps with other fragments", HFILL }
4344 { &hf_dnp3_fragment_overlap_conflict,
4345 { "Conflicting data in fragment overlap", "dnp3.al.fragment.overlap.conflict",
4346 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4347 "Overlapping fragments contained conflicting data", HFILL }
4350 { &hf_dnp3_fragment_multiple_tails,
4351 { "Multiple tail fragments found", "dnp3.al.fragment.multipletails",
4352 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4353 "Several tails were found when defragmenting the packet", HFILL }
4356 { &hf_dnp3_fragment_too_long_fragment,
4357 { "Fragment too long", "dnp3.al.fragment.toolongfragment",
4358 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4359 "Fragment contained data past end of packet", HFILL }
4362 { &hf_dnp3_fragment_error,
4363 { "Defragmentation error", "dnp3.al.fragment.error",
4364 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4365 "Defragmentation error due to illegal fragments", HFILL }
4368 { &hf_dnp3_fragment_count,
4369 { "Fragment count", "dnp3.al.fragment.count",
4370 FT_UINT32, BASE_DEC, NULL, 0x0,
4371 NULL, HFILL }
4374 { &hf_dnp3_fragment_reassembled_in,
4375 { "Reassembled PDU In Frame", "dnp3.al.fragment.reassembled_in",
4376 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4377 "This PDU is reassembled in this frame", HFILL }
4380 { &hf_dnp3_fragment_reassembled_length,
4381 { "Reassembled DNP length", "dnp3.al.fragment.reassembled.length",
4382 FT_UINT32, BASE_DEC, NULL, 0x0,
4383 "The total length of the reassembled payload", HFILL }
4387 /* Setup protocol subtree array */
4388 static gint *ett[] = {
4389 &ett_dnp3,
4390 &ett_dnp3_dl,
4391 &ett_dnp3_dl_ctl,
4392 &ett_dnp3_tr_ctl,
4393 &ett_dnp3_al_data,
4394 &ett_dnp3_al,
4395 &ett_dnp3_al_ctl,
4396 &ett_dnp3_al_obj_point_tcc,
4397 &ett_dnp3_al_iin,
4398 &ett_dnp3_al_obj,
4399 &ett_dnp3_al_obj_qualifier,
4400 &ett_dnp3_al_obj_range,
4401 &ett_dnp3_al_objdet,
4402 &ett_dnp3_al_obj_quality,
4403 &ett_dnp3_al_obj_point,
4404 &ett_dnp3_al_obj_point_perms,
4405 &ett_dnp3_fragment,
4406 &ett_dnp3_fragments
4408 static ei_register_info ei[] = {
4409 { &ei_dnp_num_items_neg, { "dnp3.num_items_neg", PI_MALFORMED, PI_ERROR, "Negative number of items", EXPFILL }},
4410 { &ei_dnp_invalid_length, { "dnp3.invalid_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
4411 { &ei_dnp_iin_abnormal, { "dnp3.iin_abnormal", PI_PROTOCOL, PI_WARN, "IIN Abnormality", EXPFILL }},
4413 module_t *dnp3_module;
4414 expert_module_t* expert_dnp3;
4416 /* Register protocol init routine */
4417 register_init_routine(&dnp3_init);
4419 /* Register the protocol name and description */
4420 proto_dnp3 = proto_register_protocol("Distributed Network Protocol 3.0",
4421 "DNP 3.0", "dnp3");
4423 /* Register the dissector so it may be used as a User DLT payload protocol */
4424 new_register_dissector("dnp3.udp", dissect_dnp3_udp, proto_dnp3);
4426 /* Required function calls to register the header fields and subtrees used */
4427 proto_register_field_array(proto_dnp3, hf, array_length(hf));
4428 proto_register_subtree_array(ett, array_length(ett));
4429 expert_dnp3 = expert_register_protocol(proto_dnp3);
4430 expert_register_field_array(expert_dnp3, ei, array_length(ei));
4432 dnp3_module = prefs_register_protocol(proto_dnp3, NULL);
4433 prefs_register_bool_preference(dnp3_module, "heuristics",
4434 "Try to detect DNP 3 heuristically",
4435 "Whether the DNP3 dissector should try to find DNP 3 packets heuristically.",
4436 &dnp3_heuristics);
4437 prefs_register_bool_preference(dnp3_module, "desegment",
4438 "Reassemble DNP3 messages spanning multiple TCP segments",
4439 "Whether the DNP3 dissector should reassemble messages spanning multiple TCP segments."
4440 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4441 &dnp3_desegment);
4445 void
4446 proto_reg_handoff_dnp3(void)
4448 dissector_handle_t dnp3_tcp_handle;
4449 dissector_handle_t dnp3_udp_handle;
4451 /* register as heuristic dissector for both TCP and UDP */
4452 if (dnp3_heuristics) {
4453 heur_dissector_add("tcp", dissect_dnp3_tcp, proto_dnp3);
4454 heur_dissector_add("udp", dissect_dnp3_udp, proto_dnp3);
4455 } else {
4456 heur_dissector_delete("tcp", dissect_dnp3_tcp, proto_dnp3);
4457 heur_dissector_delete("udp", dissect_dnp3_udp, proto_dnp3);
4460 dnp3_tcp_handle = new_create_dissector_handle(dissect_dnp3_tcp, proto_dnp3);
4461 dnp3_udp_handle = new_create_dissector_handle(dissect_dnp3_udp, proto_dnp3);
4462 dissector_add_uint("tcp.port", TCP_PORT_DNP, dnp3_tcp_handle);
4463 dissector_add_uint("udp.port", UDP_PORT_DNP, dnp3_udp_handle);
4467 * Editor modelines
4469 * Local Variables:
4470 * c-basic-offset: 2
4471 * tab-width: 8
4472 * indent-tabs-mode: nil
4473 * End:
4475 * ex: set shiftwidth=2 tabstop=8 expandtab:
4476 * :indentSize=2:tabSize=8:noTabs=true: