Get rid of get_ber_last_reated_item() and fix dissection of wIN-TriggerList.
[obnox/wireshark/wip.git] / epan / dissectors / packet-dnp.c
1 /* packet-dnp.c
2  * Routines for DNP dissection
3  * Copyright 2003, 2006, 2007, Graham Bloice <graham.bloice@trihedral.com>
4  *
5  * DNP3.0 Application Layer Object dissection added by Chris Bontje (chrisbontje@shaw.ca)
6  * Copyright 2005
7  *
8  * Major updates: tcp and application layer defragmentation, more object dissections by Graham Bloice
9  *
10  * $Id$
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald@wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <math.h>
39 #include <glib.h>
40 #include <time.h>
41
42 #include <epan/packet.h>
43 #include <epan/prefs.h>
44 #include <epan/reassemble.h>
45 #include <epan/emem.h>
46 #include <epan/dissectors/packet-tcp.h>
47 #include <epan/conversation.h>
48
49 /*
50  * See
51  *
52  * http://www.dnp.org/
53  *
54  * although note that you have to join the DNP organization to get to
55  * see the protocol specs online - otherwise, you have to buy a
56  * dead-tree version.
57  *
58  * ...Application Layer Notes...
59  *
60  * Application Layer Decoding based on information available in
61  * DNP3 Basic 4 Documentation Set, specifically the document:
62  * "DNP V3.00 Application Layer" v0.03 P009-0PD.APP & Technical Bulletins
63  */
64
65 /***************************************************************************/
66 /* DNP 3.0 Constants */
67 /***************************************************************************/
68 #define DNP_HDR_LEN     10
69 #define TCP_PORT_DNP    20000
70 #define UDP_PORT_DNP    20000
71
72 /***************************************************************************/
73 /* Datalink and Transport Layer Bit-Masks */
74 /***************************************************************************/
75 #define DNP3_CTL_DIR    0x80
76 #define DNP3_CTL_PRM    0x40
77 #define DNP3_CTL_FCB    0x20
78 #define DNP3_CTL_FCV    0x10
79 #define DNP3_CTL_RES    0x20
80 #define DNP3_CTL_DFC    0x10
81 #define DNP3_CTL_FUNC   0x0f
82
83 #define DNP3_TR_FIR   0x40
84 #define DNP3_TR_FIN   0x80
85 #define DNP3_TR_SEQ   0x3f
86
87 #define AL_MAX_CHUNK_SIZE 16
88
89 /***************************************************************************/
90 /* Data Link Function codes */
91 /***************************************************************************/
92 /* Primary to Secondary */
93 #define DL_FUNC_RESET_LINK  0x00
94 #define DL_FUNC_RESET_PROC  0x01
95 #define DL_FUNC_TEST_LINK   0x02
96 #define DL_FUNC_USER_DATA   0x03
97 #define DL_FUNC_UNC_DATA    0x04
98 #define DL_FUNC_LINK_STAT   0x09
99
100 /* Secondary to Primary */
101 #define DL_FUNC_ACK         0x00
102 #define DL_FUNC_NACK        0x01
103 #define DL_FUNC_STAT_LINK   0x0B
104 #define DL_FUNC_NO_FUNC     0x0E
105 #define DL_FUNC_NOT_IMPL    0x0F
106
107 /***************************************************************************/
108 /* Application Layer Bit-Masks */
109 /***************************************************************************/
110 #define DNP3_AL_CON   0x20
111 #define DNP3_AL_FIN   0x40
112 #define DNP3_AL_FIR   0x80
113 #define DNP3_AL_SEQ   0x1f
114 #define DNP3_AL_FUNC  0xff
115
116 /***************************************************************************/
117 /* Application Layer Function codes */
118 /***************************************************************************/
119 #define AL_FUNC_CONFIRM    0x00    /* 00  - Confirm */
120 #define AL_FUNC_READ       0x01    /* 01  - Read */
121 #define AL_FUNC_WRITE      0x02    /* 02  - Write */
122 #define AL_FUNC_SELECT     0x03    /* 03  - Select */
123 #define AL_FUNC_OPERATE    0x04    /* 04  - Operate */
124 #define AL_FUNC_DIROP      0x05    /* 05  - Direct Operate */
125 #define AL_FUNC_DIROPNACK  0x06    /* 06  - Direct Operate No ACK */
126 #define AL_FUNC_FRZ        0x07    /* 07  - Immediate Freeze */
127 #define AL_FUNC_FRZNACK    0x08    /* 08  - Immediate Freeze No ACK */
128 #define AL_FUNC_FRZCLR     0x09    /* 09  - Freeze and Clear */
129 #define AL_FUNC_FRZCLRNACK 0x0A    /* 10  - Freeze and Clear No ACK */
130 #define AL_FUNC_FRZT       0x0B    /* 11  - Freeze With Time */
131 #define AL_FUNC_FRZTNACK   0x0C    /* 12  - Freeze With Time No ACK */
132 #define AL_FUNC_COLDRST    0x0D    /* 13  - Cold Restart */
133 #define AL_FUNC_WARMRST    0x0E    /* 14  - Warm Restart */
134 #define AL_FUNC_INITDATA   0x0F    /* 15  - Initialize Data */
135 #define AL_FUNC_INITAPP    0x10    /* 16  - Initialize Application */
136 #define AL_FUNC_STARTAPP   0x11    /* 17  - Start Application */
137 #define AL_FUNC_STOPAPP    0x12    /* 18  - Stop Application */
138 #define AL_FUNC_SAVECFG    0x13    /* 19  - Save Configuration */
139 #define AL_FUNC_ENSPMSG    0x14    /* 20  - Enable Spontaneous Msg */
140 #define AL_FUNC_DISSPMSG   0x15    /* 21  - Disable Spontaneous Msg */
141 #define AL_FUNC_ASSIGNCL   0x16    /* 22  - Assign Classes */
142 #define AL_FUNC_DELAYMST   0x17    /* 23  - Delay Measurement */
143 #define AL_FUNC_RESPON     0x81    /* 129 - Response */
144 #define AL_FUNC_UNSOLI     0x82    /* 130 - Unsolicited Response */
145
146 /***************************************************************************/
147 /* Application Layer Internal Indication (IIN) bits */
148 /* 2 Bytes, message formatting: [First Octet] | [Second Octet] */
149 /***************************************************************************/
150 /* Octet 1 */
151 #define AL_IIN_BMSG        0x0100   /* Bit 0 - Broadcast message rx'd */
152 #define AL_IIN_CLS1D       0x0200   /* Bit 1 - Class 1 Data Available */
153 #define AL_IIN_CLS2D       0x0400   /* Bit 2 - Class 2 Data Available */
154 #define AL_IIN_CLS3D       0x0800   /* Bit 3 - Class 3 Data Available */
155 #define AL_IIN_TSR         0x1000   /* Bit 4 - Time Sync Req'd from Master */
156 #define AL_IIN_DOL         0x2000   /* Bit 5 - Digital Outputs in Local Mode */
157 #define AL_IIN_DT          0x4000   /* Bit 6 - Device Trouble */
158 #define AL_IIN_RST         0x8000   /* Bit 7 - Device Restart */
159
160 /* Octet 2 */
161                         /* 0x0001      Bit 0 - Reserved */
162 #define AL_IIN_OBJU        0x0002   /* Bit 1 - Requested Objects Unknown */
163 #define AL_IIN_PIOOR       0x0004   /* Bit 2 - Parameters Invalid or Out of Range */
164 #define AL_IIN_EBO         0x0008   /* Bit 3 - Event Buffer Overflow */
165 #define AL_IIN_OAE         0x0010   /* Bit 4 - Operation Already Executing */
166 #define AL_IIN_CC          0x0020   /* Bit 5 - Device Configuration Corrupt */
167                         /* 0x0040      Bit 6 - Reserved */
168                         /* 0x0080      Bit 7 - Reserved */
169
170 /***************************************************************************/
171 /* Application Layer Data Object Qualifier */
172 /***************************************************************************/
173 /* Bit-Masks */
174 #define AL_OBJQ_INDEX      0x70     /* x111xxxx Masks Index from Qualifier */
175 #define AL_OBJQ_CODE       0x0F     /* xxxx1111 Masks Code from Qualifier */
176
177 /* Index Size (3-bits x111xxxx)            */
178 /* When Qualifier Code != 11               */
179 #define AL_OBJQL_IDX_NI    0x00    /* Objects are Packed with no index */
180 #define AL_OBJQL_IDX_1O    0x01    /* Objects are prefixed w/ 1-octet index */
181 #define AL_OBJQL_IDX_2O    0x02    /* Objects are prefixed w/ 2-octet index */
182 #define AL_OBJQL_IDX_4O    0x03    /* Objects are prefixed w/ 4-octet index */
183 #define AL_OBJQL_IDX_1OS   0x04    /* Objects are prefixed w/ 1-octet object size */
184 #define AL_OBJQL_IDX_2OS   0x05    /* Objects are prefixed w/ 2-octet object size */
185 #define AL_OBJQL_IDX_4OS   0x06    /* Objects are prefixed w/ 4-octet object size */
186
187 /* When Qualifier Code == 11 */
188 #define AL_OBJQL_IDX11_1OIS    0x01    /* 1 octet identifier size */
189 #define AL_OBJQL_IDX11_2OIS    0x02    /* 2 octet identifier size */
190 #define AL_OBJQL_IDX11_4OIS    0x03    /* 4 octet identifier size */
191
192 /* Qualifier Code (4-bits) */
193 /* 4-bits ( xxxx1111 ) */
194 #define AL_OBJQL_CODE_SSI8     0x00    /* 00 8-bit Start and Stop Indices in Range Field */
195 #define AL_OBJQL_CODE_SSI16    0x01    /* 01 16-bit Start and Stop Indices in Range Field */
196 #define AL_OBJQL_CODE_SSI32    0x02    /* 02 32-bit Start and Stop Indices in Range Field */
197 #define AL_OBJQL_CODE_AA8      0x03    /* 03 8-bit Absolute Address in Range Field */
198 #define AL_OBJQL_CODE_AA16     0x04    /* 04 16-bit Absolute Address in Range Field */
199 #define AL_OBJQL_CODE_AA32     0x05    /* 05 32-bit Absolute Address in Range Field */
200 #define AL_OBJQL_CODE_R0       0x06    /* 06 Length of Range field is 0 (no range field) */
201 #define AL_OBJQL_CODE_SF8      0x07    /* 07 8-bit Single Field Quantity */
202 #define AL_OBJQL_CODE_SF16     0x08    /* 08 16-bit Single Field Quantity */
203 #define AL_OBJQL_CODE_SF32     0x09    /* 09 32-bit Single Field Quantity */
204                            /*  0x0A       10 Reserved  */
205 #define AL_OBJQL_CODE_FF       0x0B    /* 11 Free-format Qualifier */
206                            /*  0x0C       12 Reserved  */
207                            /*  0x0D       13 Reserved  */
208                            /*  0x0E       14 Reserved  */
209                            /*  0x0F       15 Reserved  */
210
211 /***************************************************************************/
212 /* Application Layer Data Object Definitions                               */
213 /***************************************************************************/
214 /* Binary Input Objects */
215 #define AL_OBJ_BI_ALL      0x0100   /* 01 00 Binary Input All Variations */
216 #define AL_OBJ_BI_1BIT     0x0101   /* 01 01 Single-bit Binary Input */
217 #define AL_OBJ_BI_STAT     0x0102   /* 01 02 Binary Input With Status */
218 #define AL_OBJ_BIC_ALL     0x0200   /* 02 00 Binary Input Change All Variations */
219 #define AL_OBJ_BIC_NOTIME  0x0201   /* 02 01 Binary Input Change Without Time */
220 #define AL_OBJ_BIC_TIME    0x0202   /* 02 02 Binary Input Change With Time */
221 #define AL_OBJ_BIC_RTIME   0x0203   /* 02 03 Binary Input Change With Relative Time */
222
223 /* Double-bit Input Objects */
224 #define AL_OBJ_2BI_ALL     0x0300   /* 03 00 Double-bit Input All Variations */
225 #define AL_OBJ_2BI_NF      0x0301   /* 03 01 Double-bit Input No Flags */
226 #define AL_OBJ_2BI_STAT    0x0302   /* 03 02 Double-bit Input With Status */
227 #define AL_OBJ_2BIC_NOTIME 0x0401   /* 04 01 Double-bit Input Change Without Time */
228 #define AL_OBJ_2BIC_TIME   0x0402   /* 04 02 Double-bit Input Change With Time */
229 #define AL_OBJ_2BIC_RTIME  0x0403   /* 04 03 Double-bit Input Change With Relative Time */
230
231 /* Binary Input Quality Flags */
232 #define AL_OBJ_BI_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
233 #define AL_OBJ_BI_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
234 #define AL_OBJ_BI_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
235 #define AL_OBJ_BI_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
236 #define AL_OBJ_BI_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
237 #define AL_OBJ_BI_FLAG5    0x0020   /* Chatter Filter (0=Normal; 1=Filter On) */
238 #define AL_OBJ_BI_FLAG6    0x0040   /* Double-bit LSB (0=Off; 1=On) */
239 #define AL_OBJ_BI_FLAG7    0x0080   /* Point State (0=Off; 1=On) or Double-bit MSB */
240
241 /***************************************************************************/
242 /* Binary Output Objects */
243 #define AL_OBJ_BO          0x0A01   /* 10 01 Binary Output */
244 #define AL_OBJ_BO_STAT     0x0A02   /* 10 02 Binary Output Status */
245 #define AL_OBJ_CTLOP_BLK   0x0C01   /* 12 01 Control Relay Output Block */
246                         /* 0x0C02      12 02 Pattern Control Block */
247                         /* 0x0C03      12 03 Pattern Mask */
248
249 #define AL_OBJCTLC_CODE    0x0F    /* Bit-Mask xxxx1111 for Control Code 'Code' */
250 #define AL_OBJCTLC_MISC    0x30    /* Bit-Mask xx11xxxx for Control Code Misc Values */
251 #define AL_OBJCTLC_TC      0xC0    /* Bit-Mask 11xxxxxx for Control Code 'Trip/Close' */
252
253 #define AL_OBJCTLC_CODE0   0x00    /* xxxx0000 NUL Operation; only process R attribute */
254 #define AL_OBJCTLC_CODE1   0x01    /* xxxx0001 Pulse On ^On-Time -> vOff-Time, remain off */
255 #define AL_OBJCTLC_CODE2   0x02    /* xxxx0010 Pulse Off vOff-Time -> ^On-Time, remain on */
256 #define AL_OBJCTLC_CODE3   0x03    /* xxxx0011 Latch On */
257 #define AL_OBJCTLC_CODE4   0x04    /* xxxx0100 Latch Off */
258                         /* 0x05-0x15  Reserved */
259
260 #define AL_OBJCTLC_QUEUE   0x10    /* xxx1xxxx for Control Code 'Queue' */
261 #define AL_OBJCTLC_CLEAR   0x20    /* xx1xxxxx for Control Code 'Clear' */
262
263 #define AL_OBJCTLC_TC0     0x00    /* 00xxxxxx NUL */
264 #define AL_OBJCTLC_TC1     0x40    /* 01xxxxxx Close */
265 #define AL_OBJCTLC_TC2     0x80    /* 10xxxxxx Trip */
266
267 #define AL_OBJCTL_STAT0    0x00    /* Request Accepted, Initiated or Queued */
268 #define AL_OBJCTL_STAT1    0x01    /* Request Not Accepted; Arm-timer expired */
269 #define AL_OBJCTL_STAT2    0x02    /* Request Not Accepted; No 'SELECT' rx'd */
270 #define AL_OBJCTL_STAT3    0x03    /* Request Not Accepted; Format errors in ctrl request */
271 #define AL_OBJCTL_STAT4    0x04    /* Control Operation Not Supported for this point */
272 #define AL_OBJCTL_STAT5    0x05    /* Request Not Accepted; Ctrl Queue full or pt. active */
273 #define AL_OBJCTL_STAT6    0x06    /* Request Not Accepted; Ctrl HW Problems */
274 #define AL_OBJCTL_STAT7    0x07    /* Request Not Accepted; Local/Remote switch in Local*/
275 #define AL_OBJCTL_STAT8    0x08    /* Request Not Accepted; Too many operations requested */
276 #define AL_OBJCTL_STAT9    0x09    /* Request Not Accepted; Insufficient authorization */
277 #define AL_OBJCTL_STAT10   0x0A    /* Request Not Accepted; Local automation proc active */
278
279 /* Binary Output Quality Flags */
280 #define AL_OBJ_BO_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
281 #define AL_OBJ_BO_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
282 #define AL_OBJ_BO_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
283 #define AL_OBJ_BO_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
284 #define AL_OBJ_BO_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
285 #define AL_OBJ_BO_FLAG5    0x0020   /* Reserved */
286 #define AL_OBJ_BO_FLAG6    0x0040   /* Reserved */
287 #define AL_OBJ_BO_FLAG7    0x0080   /* Point State (0=Off; 1=On) */
288
289 /***************************************************************************/
290 /* Counter Objects */
291 #define AL_OBJ_CTR_ALL     0x1400   /* 20 00 Binary Counter All Variations */
292 #define AL_OBJ_CTR_32      0x1401   /* 20 01 32-Bit Binary Counter */
293 #define AL_OBJ_CTR_16      0x1402   /* 20 02 16-Bit Binary Counter */
294 #define AL_OBJ_DCTR_32     0x1403   /* 20 03 32-Bit Delta Counter */
295 #define AL_OBJ_DCTR_16     0x1404   /* 20 04 16-Bit Delta Counter */
296 #define AL_OBJ_CTR_32NF    0x1405   /* 20 05 32-Bit Binary Counter Without Flag */
297 #define AL_OBJ_CTR_16NF    0x1406   /* 20 06 16-Bit Binary Counter Without Flag */
298 #define AL_OBJ_DCTR_32NF   0x1407   /* 20 07 32-Bit Delta Counter Without Flag */
299 #define AL_OBJ_DCTR_16NF   0x1408   /* 20 08 16-Bit Delta Counter Without Flag */
300 #define AL_OBJ_FCTR_ALL    0x1500   /* 21 00 Frozen Binary Counter All Variations */
301 #define AL_OBJ_FCTR_32     0x1501   /* 21 01 32-Bit Frozen Counter */
302 #define AL_OBJ_FCTR_16     0x1502   /* 21 02 16-Bit Frozen Counter */
303 #define AL_OBJ_FDCTR_32    0x1503   /* 21 03 32-Bit Frozen Delta Counter */
304 #define AL_OBJ_FDCTR_16    0x1504   /* 21 04 16-Bit Frozen Delta Counter */
305 #define AL_OBJ_FCTR_32T    0x1505   /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
306 #define AL_OBJ_FCTR_16T    0x1506   /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
307 #define AL_OBJ_FDCTR_32T   0x1507   /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
308 #define AL_OBJ_FDCTR_16T   0x1508   /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
309 #define AL_OBJ_FCTR_32NF   0x1509   /* 21 09 32-Bit Frozen Counter Without Flag */
310 #define AL_OBJ_FCTR_16NF   0x1510   /* 21 10 16-Bit Frozen Counter Without Flag */
311 #define AL_OBJ_FDCTR_32NF  0x1511   /* 21 11 32-Bit Frozen Delta Counter Without Flag */
312 #define AL_OBJ_FDCTR_16NF  0x1512   /* 21 12 16-Bit Frozen Delta Counter Without Flag */
313 #define AL_OBJ_CTRC_ALL    0x1600   /* 22 00 Counter Change Event All Variations */
314 #define AL_OBJ_CTRC_32     0x1601   /* 22 01 32-Bit Counter Change Event w/o Time */
315 #define AL_OBJ_CTRC_16     0x1602   /* 22 02 16-Bit Counter Change Event w/o Time */
316 #define AL_OBJ_DCTRC_32    0x1603   /* 22 03 32-Bit Delta Counter Change Event w/o Time */
317 #define AL_OBJ_DCTRC_16    0x1604   /* 22 04 16-Bit Delta Counter Change Event w/o Time */
318 #define AL_OBJ_CTRC_32T    0x1605   /* 22 05 32-Bit Counter Change Event with Time */
319 #define AL_OBJ_CTRC_16T    0x1606   /* 22 06 16-Bit Counter Change Event with Time */
320 #define AL_OBJ_DCTRC_32T   0x1607   /* 22 07 32-Bit Delta Counter Change Event with Time */
321 #define AL_OBJ_DCTRC_16T   0x1608   /* 22 08 16-Bit Delta Counter Change Event with Time */
322 #define AL_OBJ_FCTRC_ALL   0x1700   /* 21 00 Frozen Binary Counter Change Event All Variations */
323 #define AL_OBJ_FCTRC_32    0x1701   /* 21 01 32-Bit Frozen Counter Change Event */
324 #define AL_OBJ_FCTRC_16    0x1702   /* 21 02 16-Bit Frozen Counter Change Event */
325 #define AL_OBJ_FDCTRC_32   0x1703   /* 21 03 32-Bit Frozen Delta Counter Change Event */
326 #define AL_OBJ_FDCTRC_16   0x1704   /* 21 04 16-Bit Frozen Delta Counter Change Event */
327 #define AL_OBJ_FCTRC_32T   0x1705   /* 21 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
328 #define AL_OBJ_FCTRC_16T   0x1706   /* 21 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
329 #define AL_OBJ_FDCTRC_32T  0x1707   /* 21 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
330 #define AL_OBJ_FDCTRC_16T  0x1708   /* 21 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
331
332 /* Counter Quality Flags */
333 #define AL_OBJ_CTR_FLAG0   0x0001   /* Point Online (0=Offline; 1=Online) */
334 #define AL_OBJ_CTR_FLAG1   0x0002   /* Restart (0=Normal; 1=Restart) */
335 #define AL_OBJ_CTR_FLAG2   0x0004   /* Comms Lost (0=Normal; 1=Lost) */
336 #define AL_OBJ_CTR_FLAG3   0x0008   /* Remote Force (0=Normal; 1=Forced) */
337 #define AL_OBJ_CTR_FLAG4   0x0010   /* Local Force (0=Normal; 1=Forced) */
338 #define AL_OBJ_CTR_FLAG5   0x0020   /* Roll-over (0=Normal; 1=Roll-Over) */
339 #define AL_OBJ_CTR_FLAG6   0x0040   /* Discontinuity (0=Normal; 1=Discontinuity) */
340 #define AL_OBJ_CTR_FLAG7   0x0080   /* Reserved */
341
342 /***************************************************************************/
343 /* Analog Input Objects */
344 #define AL_OBJ_AI_ALL      0x1E00   /* 30 00 Analog Input All Variations */
345 #define AL_OBJ_AI_32       0x1E01   /* 30 01 32-Bit Analog Input */
346 #define AL_OBJ_AI_16       0x1E02   /* 30 02 16-Bit Analog Input */
347 #define AL_OBJ_AI_32NF     0x1E03   /* 30 03 32-Bit Analog Input Without Flag */
348 #define AL_OBJ_AI_16NF     0x1E04   /* 30 04 16-Bit Analog Input Without Flag */
349 #define AL_OBJ_AI_FLT      0x1E05   /* 30 05 32-Bit Floating Point Input */
350 #define AL_OBJ_AI_DBL      0x1E06   /* 30 06 64-Bit Floating Point Input */
351                         /* 0x1F01      31 01 32-Bit Frozen Analog Input */
352                         /* 0x1F02      31 02 16-Bit Frozen Analog Input */
353                         /* 0x1F03      31 03 32-Bit Frozen Analog Input w/ Time of Freeze */
354                         /* 0x1F04      31 04 16-Bit Frozen Analog Input w/ Time of Freeze */
355                         /* 0x1F05      31 05 32-Bit Frozen Analog Input Without Flag */
356                         /* 0x1F06      31 06 16-Bit Frozen Analog Input Without Flag */
357 #define AL_OBJ_AIF_FLT     0x1F07   /* 31 07 32-Bit Frozen Floating Point Input */
358 #define AL_OBJ_AIF_DBL     0x1F08   /* 31 08 64-Bit Frozen Floating Point Input */
359 #define AL_OBJ_AIC_ALL     0x2000   /* 32 00 Analog Input Change All Variations */
360 #define AL_OBJ_AIC_32NT    0x2001   /* 32 01 32-Bit Analog Change Event w/o Time */
361 #define AL_OBJ_AIC_16NT    0x2002   /* 32 02 16-Bit Analog Change Event w/o Time */
362 #define AL_OBJ_AIC_32T     0x2003   /* 32 03 32-Bit Analog Change Event w/ Time */
363 #define AL_OBJ_AIC_16T     0x2004   /* 32 04 16-Bit Analog Change Event w/ Time */
364 #define AL_OBJ_AIC_FLTNT   0x2005   /* 32 05 32-Bit Floating Point Change Event w/o Time*/
365 #define AL_OBJ_AIC_DBLNT   0x2006   /* 32 06 64-Bit Floating Point Change Event w/o Time*/
366 #define AL_OBJ_AIC_FLTT    0x2007   /* 32 07 32-Bit Floating Point Change Event w/ Time*/
367 #define AL_OBJ_AIC_DBLT    0x2008   /* 32 08 64-Bit Floating Point Change Event w/ Time*/
368                         /* 0x2101      33 01 32-Bit Frozen Analog Event w/o Time */
369                         /* 0x2102      33 02 16-Bit Frozen Analog Event w/o Time */
370                         /* 0x2103      33 03 32-Bit Frozen Analog Event w/ Time */
371                         /* 0x2104      33 04 16-Bit Frozen Analog Event w/ Time */
372 #define AL_OBJ_AIFC_FLTNT  0x2105   /* 33 05 32-Bit Floating Point Frozen Change Event w/o Time*/
373 #define AL_OBJ_AIFC_DBLNT  0x2106   /* 33 06 64-Bit Floating Point Frozen Change Event w/o Time*/
374 #define AL_OBJ_AIFC_FLTT   0x2107   /* 33 07 32-Bit Floating Point Frozen Change Event w/ Time*/
375 #define AL_OBJ_AIFC_DBLT   0x2108   /* 33 08 64-Bit Floating Point Frozen Change Event w/ Time*/
376
377
378 /* Analog Input Quality Flags */
379 #define AL_OBJ_AI_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
380 #define AL_OBJ_AI_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
381 #define AL_OBJ_AI_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
382 #define AL_OBJ_AI_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
383 #define AL_OBJ_AI_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
384 #define AL_OBJ_AI_FLAG5    0x0020   /* Over-Range (0=Normal; 1=Over-Range) */
385 #define AL_OBJ_AI_FLAG6    0x0040   /* Reference Check (0=Normal; 1=Error) */
386 #define AL_OBJ_AI_FLAG7    0x0080   /* Reserved */
387
388 /***************************************************************************/
389 /* Analog Output Objects */
390 #define AL_OBJ_AO_32       0x2801   /* 40 01 32-Bit Analog Output Status */
391 #define AL_OBJ_AO_16       0x2802   /* 40 02 16-Bit Analog Output Status */
392 #define AL_OBJ_AO_FLT      0x2803   /* 40 03 32-Bit Floating Point Output Status */
393 #define AL_OBJ_AO_DBL      0x2804   /* 40 04 64-Bit Floating Point Output Status */
394 #define AL_OBJ_AO_32OPB    0x2901   /* 41 01 32-Bit Analog Output Block */
395 #define AL_OBJ_AO_16OPB    0x2902   /* 41 02 16-Bit Analog Output Block */
396 #define AL_OBJ_AO_FLTOPB   0x2903   /* 41 03 32-Bit Floating Point Output Block */
397 #define AL_OBJ_AO_DBLOPB   0x2904   /* 41 04 64-Bit Floating Point Output Block */
398
399 /* Analog Output Quality Flags */
400 #define AL_OBJ_AO_FLAG0    0x0001   /* Point Online (0=Offline; 1=Online) */
401 #define AL_OBJ_AO_FLAG1    0x0002   /* Restart (0=Normal; 1=Restart) */
402 #define AL_OBJ_AO_FLAG2    0x0004   /* Comms Lost (0=Normal; 1=Lost) */
403 #define AL_OBJ_AO_FLAG3    0x0008   /* Remote Force (0=Normal; 1=Forced) */
404 #define AL_OBJ_AO_FLAG4    0x0010   /* Local Force (0=Normal; 1=Forced) */
405 #define AL_OBJ_AO_FLAG5    0x0020   /* Reserved */
406 #define AL_OBJ_AO_FLAG6    0x0040   /* Reserved */
407 #define AL_OBJ_AO_FLAG7    0x0080   /* Reserved */
408
409 /***************************************************************************/
410 /* Time Objects */
411 #define AL_OBJ_TD          0x3201   /* 50 01 Time and Date */
412 #define AL_OBJ_TDI         0x3202   /* 50 02 Time and Date w/ Interval */
413 #define AL_OBJ_TDCTO       0x3301   /* 51 01 Time and Date CTO */
414 #define AL_OBJ_UTDCTO      0x3302   /* 51 02 Unsynchronized Time and Date CTO */
415 #define AL_OBJ_TDELAYC     0x3401   /* 52 01 Time Delay Coarse */
416 #define AL_OBJ_TDELAYF     0x3402   /* 52 02 Time Delay Fine */
417
418 /***************************************************************************/
419 /* Class Data Objects */
420 #define AL_OBJ_CLASS0      0x3C01   /* 60 01 Class 0 Data */
421 #define AL_OBJ_CLASS1      0x3C02   /* 60 02 Class 1 Data */
422 #define AL_OBJ_CLASS2      0x3C03   /* 60 03 Class 2 Data */
423 #define AL_OBJ_CLASS3      0x3C04   /* 60 04 Class 3 Data */
424
425 /***************************************************************************/
426 /* Device Objects */
427 #define AL_OBJ_IIN         0x5001   /* 80 01 Internal Indications */
428
429 /***************************************************************************/
430 /* End of Application Layer Data Object Definitions */
431 /***************************************************************************/
432
433 /* Initialize the protocol and registered fields */
434 static int proto_dnp3 = -1;
435 static int hf_dnp3_start = -1;
436 static int hf_dnp3_len = -1;
437 static int hf_dnp3_ctl = -1;
438 static int hf_dnp3_ctl_prifunc = -1;
439 static int hf_dnp3_ctl_secfunc = -1;
440 static int hf_dnp3_ctl_dir = -1;
441 static int hf_dnp3_ctl_prm = -1;
442 static int hf_dnp3_ctl_fcb = -1;
443 static int hf_dnp3_ctl_fcv = -1;
444 static int hf_dnp3_ctl_dfc = -1;
445 static int hf_dnp3_dst = -1;
446 static int hf_dnp3_src = -1;
447 static int hf_dnp_hdr_CRC = -1;
448 static int hf_dnp_hdr_CRC_bad = -1;
449 static int hf_dnp3_tr_ctl = -1;
450 static int hf_dnp3_tr_fin = -1;
451 static int hf_dnp3_tr_fir = -1;
452 static int hf_dnp3_tr_seq = -1;
453 static int hf_dnp3_al_ctl = -1;
454 static int hf_dnp3_al_fir = -1;
455 static int hf_dnp3_al_fin = -1;
456 static int hf_dnp3_al_con = -1;
457 static int hf_dnp3_al_seq = -1;
458 static int hf_dnp3_al_func = -1;
459 /* Added for Application Layer Decoding */
460 static int hf_dnp3_al_iin = -1;
461 static int hf_dnp3_al_iin_bmsg = -1;
462 static int hf_dnp3_al_iin_cls1d = -1;
463 static int hf_dnp3_al_iin_cls2d = -1;
464 static int hf_dnp3_al_iin_cls3d = -1;
465 static int hf_dnp3_al_iin_tsr = -1;
466 static int hf_dnp3_al_iin_dol = -1;
467 static int hf_dnp3_al_iin_dt = -1;
468 static int hf_dnp3_al_iin_rst = -1;
469 static int hf_dnp3_al_iin_obju = -1;
470 static int hf_dnp3_al_iin_pioor = -1;
471 static int hf_dnp3_al_iin_ebo = -1;
472 static int hf_dnp3_al_iin_oae = -1;
473 static int hf_dnp3_al_iin_cc = -1;
474 static int hf_dnp3_al_obj = -1;
475 static int hf_dnp3_al_objq_index = -1;
476 static int hf_dnp3_al_objq_code = -1;
477 static int hf_dnp3_al_range_start8 = -1;
478 static int hf_dnp3_al_range_stop8 = -1;
479 static int hf_dnp3_al_range_start16 = -1;
480 static int hf_dnp3_al_range_stop16 = -1;
481 static int hf_dnp3_al_range_start32 = -1;
482 static int hf_dnp3_al_range_stop32 = -1;
483 static int hf_dnp3_al_range_abs8 = -1;
484 static int hf_dnp3_al_range_abs16 = -1;
485 static int hf_dnp3_al_range_abs32 = -1;
486 static int hf_dnp3_al_range_quant8 = -1;
487 static int hf_dnp3_al_range_quant16 = -1;
488 static int hf_dnp3_al_range_quant32 = -1;
489 static int hf_dnp3_al_index8 = -1;
490 static int hf_dnp3_al_index16 = -1;
491 static int hf_dnp3_al_index32 = -1;
492
493 /*static int hf_dnp3_al_objq = -1;
494   static int hf_dnp3_al_nobj = -1; */
495 static int hf_dnp3_al_ptnum = -1;
496 static int hf_dnp3_al_biq_b0 = -1;
497 static int hf_dnp3_al_biq_b1 = -1;
498 static int hf_dnp3_al_biq_b2 = -1;
499 static int hf_dnp3_al_biq_b3 = -1;
500 static int hf_dnp3_al_biq_b4 = -1;
501 static int hf_dnp3_al_biq_b5 = -1;
502 static int hf_dnp3_al_biq_b6 = -1;
503 static int hf_dnp3_al_biq_b7 = -1;
504 static int hf_dnp3_al_boq_b0 = -1;
505 static int hf_dnp3_al_boq_b1 = -1;
506 static int hf_dnp3_al_boq_b2 = -1;
507 static int hf_dnp3_al_boq_b3 = -1;
508 static int hf_dnp3_al_boq_b4 = -1;
509 static int hf_dnp3_al_boq_b5 = -1;
510 static int hf_dnp3_al_boq_b6 = -1;
511 static int hf_dnp3_al_boq_b7 = -1;
512 static int hf_dnp3_al_ctrq_b0 = -1;
513 static int hf_dnp3_al_ctrq_b1 = -1;
514 static int hf_dnp3_al_ctrq_b2 = -1;
515 static int hf_dnp3_al_ctrq_b3 = -1;
516 static int hf_dnp3_al_ctrq_b4 = -1;
517 static int hf_dnp3_al_ctrq_b5 = -1;
518 static int hf_dnp3_al_ctrq_b6 = -1;
519 static int hf_dnp3_al_ctrq_b7 = -1;
520 static int hf_dnp3_al_aiq_b0 = -1;
521 static int hf_dnp3_al_aiq_b1 = -1;
522 static int hf_dnp3_al_aiq_b2 = -1;
523 static int hf_dnp3_al_aiq_b3 = -1;
524 static int hf_dnp3_al_aiq_b4 = -1;
525 static int hf_dnp3_al_aiq_b5 = -1;
526 static int hf_dnp3_al_aiq_b6 = -1;
527 static int hf_dnp3_al_aiq_b7 = -1;
528 static int hf_dnp3_al_aoq_b0 = -1;
529 static int hf_dnp3_al_aoq_b1 = -1;
530 static int hf_dnp3_al_aoq_b2 = -1;
531 static int hf_dnp3_al_aoq_b3 = -1;
532 static int hf_dnp3_al_aoq_b4 = -1;
533 static int hf_dnp3_al_aoq_b5 = -1;
534 static int hf_dnp3_al_aoq_b6 = -1;
535 static int hf_dnp3_al_aoq_b7 = -1;
536 static int hf_dnp3_al_timestamp = -1;
537 static int hf_dnp3_al_rel_timestamp = -1;
538 static int hf_dnp3_al_ana16 = -1;
539 static int hf_dnp3_al_ana32 = -1;
540 static int hf_dnp3_al_anaflt = -1;
541 static int hf_dnp3_al_anadbl = -1;
542 static int hf_dnp3_al_bit = -1;
543 static int hf_dnp3_al_2bit = -1;
544 static int hf_dnp3_al_cnt16 = -1;
545 static int hf_dnp3_al_cnt32 = -1;
546 static int hf_dnp3_al_ctrlstatus = -1;
547 static int hf_dnp3_al_anaout16 = -1;
548 static int hf_dnp3_al_anaout32 = -1;
549 static int hf_dnp3_al_anaoutflt = -1;
550 static int hf_dnp3_al_anaoutdbl = -1;
551
552 /***************************************************************************/
553 /* Value String Look-Ups */
554 /***************************************************************************/
555 static const value_string dnp3_ctl_func_pri_vals[] = {
556   { DL_FUNC_RESET_LINK, "Reset of Remote Link" },
557   { DL_FUNC_RESET_PROC, "Reset of User Process" },
558   { DL_FUNC_TEST_LINK,  "Test Function For Link" },
559   { DL_FUNC_USER_DATA,  "User Data" },
560   { DL_FUNC_UNC_DATA,   "Unconfirmed User Data" },
561   { DL_FUNC_LINK_STAT,  "Request Link Status" },
562   { 0, NULL }
563 };
564
565 static const value_string dnp3_ctl_func_sec_vals[] = {
566   { DL_FUNC_ACK,        "ACK" },
567   { DL_FUNC_NACK,       "NACK" },
568   { DL_FUNC_STAT_LINK,  "Status of Link" },
569   { DL_FUNC_NO_FUNC,    "Link Service Not Functioning" },
570   { DL_FUNC_NOT_IMPL,   "Link Service Not Used or Implemented" },
571   { 0,  NULL }
572 };
573
574 static const value_string dnp3_ctl_flags_pri_vals[] _U_ = {
575   { DNP3_CTL_DIR, "DIR" },
576   { DNP3_CTL_PRM, "PRM" },
577   { DNP3_CTL_FCB, "FCB" },
578   { DNP3_CTL_FCV, "FCV" },
579   { 0,  NULL }
580 };
581
582 static const value_string dnp3_ctl_flags_sec_vals[] _U_ = {
583   { DNP3_CTL_DIR, "DIR" },
584   { DNP3_CTL_PRM, "PRM" },
585   { DNP3_CTL_RES, "RES" },
586   { DNP3_CTL_DFC, "DFC" },
587   { 0,  NULL }
588 };
589
590 static const value_string dnp3_tr_flags_vals[] _U_ = {
591   { DNP3_TR_FIN,  "FIN" },
592   { DNP3_TR_FIR,  "FIR" },
593   { 0,  NULL }
594 };
595
596 static const value_string dnp3_al_flags_vals[] _U_ = {
597   { DNP3_AL_FIR,  "FIR" },
598   { DNP3_AL_FIN,  "FIN" },
599   { DNP3_AL_CON,  "CON" },
600   { 0,  NULL }
601 };
602
603 /* Application Layer Function Code Values */
604 static const value_string dnp3_al_func_vals[] = {
605   { AL_FUNC_CONFIRM,    "Confirm" },
606   { AL_FUNC_READ,       "Read" },
607   { AL_FUNC_WRITE,      "Write" },
608   { AL_FUNC_SELECT,     "Select" },
609   { AL_FUNC_OPERATE,    "Operate" },
610   { AL_FUNC_DIROP,      "Direct Operate" },
611   { AL_FUNC_DIROPNACK,  "Direct Operate No Ack" },
612   { AL_FUNC_FRZ,        "Immediate Freeze" },
613   { AL_FUNC_FRZNACK,    "Immediate Freeze No Ack" },
614   { AL_FUNC_FRZCLR,     "Freeze and Clear" },
615   { AL_FUNC_FRZCLRNACK, "Freeze and Clear No ACK" },
616   { AL_FUNC_FRZT,       "Freeze With Time" },
617   { AL_FUNC_FRZTNACK,   "Freeze With Time No ACK" },
618   { AL_FUNC_COLDRST,    "Cold Restart" },
619   { AL_FUNC_WARMRST,    "Warm Restart" },
620   { AL_FUNC_INITDATA,   "Initialize Data" },
621   { AL_FUNC_INITAPP,    "Initialize Application" },
622   { AL_FUNC_STARTAPP,   "Start Application" },
623   { AL_FUNC_STOPAPP,    "Stop Application" },
624   { AL_FUNC_SAVECFG,    "Save Configuration" },
625   { AL_FUNC_ENSPMSG,    "Enable Spontaneous Messages" },
626   { AL_FUNC_DISSPMSG,   "Disable Spontaneous Messages" },
627   { AL_FUNC_ASSIGNCL,   "Assign Classes" },
628   { AL_FUNC_DELAYMST,   "Delay Measurement" },
629   { AL_FUNC_RESPON,     "Response" },
630   { AL_FUNC_UNSOLI,     "Unsolicited Response" },
631   { 0, NULL }
632 };
633
634 /* Application Layer Internal Indication (IIN) bit Values */
635 static const value_string dnp3_al_iin_vals[] _U_ = {
636   { AL_IIN_BMSG,    "Broadcast message Rx'd" },
637   { AL_IIN_CLS1D,   "Class 1 Data Available" },
638   { AL_IIN_CLS2D,   "Class 2 Data Available" },
639   { AL_IIN_CLS3D,   "Class 3 Data Available" },
640   { AL_IIN_TSR,     "Time Sync Required from Master" },
641   { AL_IIN_DOL,     "Digital Outputs in Local Mode" },
642   { AL_IIN_DT,      "Device Trouble" },
643   { AL_IIN_RST,     "Device Restart" },
644   { AL_IIN_OBJU,    "Requested Objects Unknown" },
645   { AL_IIN_PIOOR,   "Parameters Invalid or Out of Range" },
646   { AL_IIN_EBO,     "Event Buffer Overflow" },
647   { AL_IIN_OAE,     "Operation Already Executing" },
648   { AL_IIN_CC,      "Device Configuration Corrupt" },
649   { 0, NULL }
650 };
651
652 /* Application Layer Object Qualifier Index Values When Qualifier Code != 11 */
653 static const value_string dnp3_al_objq_index_vals[] = {
654   { AL_OBJQL_IDX_NI,    "None" },
655   { AL_OBJQL_IDX_1O,    "1-Octet Indexing" },
656   { AL_OBJQL_IDX_2O,    "2-Octet Indexing" },
657   { AL_OBJQL_IDX_4O,    "4-Octet Indexing" },
658   { AL_OBJQL_IDX_1OS,   "1-Octet Object Size" },
659   { AL_OBJQL_IDX_2OS,   "2-Octet Object Size" },
660   { AL_OBJQL_IDX_4OS,   "4-Octet Object Size" },
661   { 0, NULL }
662 };
663
664 /* Application Layer Object Qualifier Code Values */
665 static const value_string dnp3_al_objq_code_vals[] = {
666   { AL_OBJQL_CODE_SSI8,     "8-bit Start and Stop Indices" },
667   { AL_OBJQL_CODE_SSI16,    "16-bit Start and Stop Indices" },
668   { AL_OBJQL_CODE_SSI32,    "32-bit Start and Stop Indices" },
669   { AL_OBJQL_CODE_AA8,      "8-bit Absolute Address in Range Field" },
670   { AL_OBJQL_CODE_AA16,     "16-bit Absolute Address in Range Field" },
671   { AL_OBJQL_CODE_AA32,     "32-bit Absolute Address in Range Field" },
672   { AL_OBJQL_CODE_R0,       "No Range Field" },
673   { AL_OBJQL_CODE_SF8,      "8-bit Single Field Quantity" },
674   { AL_OBJQL_CODE_SF16,     "16-bit Single Field Quantity" },
675   { AL_OBJQL_CODE_SF32,     "32-bit Single Field Quantity" },
676   { AL_OBJQL_CODE_FF,       "Free-format Qualifier" },
677   { 0, NULL }
678 };
679
680 /* Application Layer Data Object Values */
681 static const value_string dnp3_al_obj_vals[] = {
682   { AL_OBJ_BI_ALL,     "Binary Input All Variations (Obj:01, Var:All)" },
683   { AL_OBJ_BI_1BIT,    "Single-Bit Binary Input (Obj:01, Var:01)" },
684   { AL_OBJ_BI_STAT,    "Binary Input With Status (Obj:01, Var:02)" },
685   { AL_OBJ_BIC_ALL,    "Binary Input Change All Variations (Obj:02, Var:All)" },
686   { AL_OBJ_BIC_NOTIME, "Binary Input Change Without Time (Obj:02, Var:01)" },
687   { AL_OBJ_BIC_TIME,   "Binary Input Change With Time (Obj:02, Var:02)" },
688   { AL_OBJ_BIC_RTIME,  "Binary Input Change With Relative Time (Obj:02, Var:03)" },
689   { AL_OBJ_2BI_ALL,    "Double-bit Input All Variations (Obj:03, Var:All)" },
690   { AL_OBJ_2BI_NF,     "Double-bit Input No Flags (Obj:03, Var:01)" },
691   { AL_OBJ_2BI_STAT,   "Double-bit Input With Status (Obj:03, Var:02)" },
692   { AL_OBJ_2BIC_NOTIME, "Double-bit Input Change Without Time (Obj:04, Var:01)" },
693   { AL_OBJ_2BIC_TIME,  "Double-bit Input Change With Time (Obj:04, Var:02)" },
694   { AL_OBJ_2BIC_RTIME, "Double-bit Input Change With Relative Time (Obj:04, Var:03)" },
695   { AL_OBJ_BO,         "Binary Output (Obj:10, Var:01)" },
696   { AL_OBJ_BO_STAT,    "Binary Output Status (Obj:10, Var:02)" },
697   { AL_OBJ_CTLOP_BLK,  "Control Relay Output Block (Obj:12, Var:01)" },
698   { AL_OBJ_CTR_ALL,    "Binary Counter All Variations (Obj:20, Var:All)" },
699   { AL_OBJ_CTR_32,     "32-Bit Binary Counter (Obj:20, Var:01)" },
700   { AL_OBJ_CTR_16,     "16-Bit Binary Counter (Obj:20, Var:02)" },
701   { AL_OBJ_DCTR_32,    "32-Bit Binary Delta Counter (Obj:20, Var:03)" },
702   { AL_OBJ_DCTR_16,    "16-Bit Binary Delta Counter (Obj:20, Var:04)" },
703   { AL_OBJ_CTR_32NF,   "32-Bit Binary Counter Without Flag (Obj:20, Var:05)" },
704   { AL_OBJ_CTR_16NF,   "16-Bit Binary Counter Without Flag (Obj:20, Var:06)" },
705   { AL_OBJ_DCTR_32NF,  "32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07)" },
706   { AL_OBJ_DCTR_16NF,  "16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08)" },
707   { AL_OBJ_FCTR_ALL,   "Frozen Binary Counter All Variations (Obj:21, Var:All)" },
708   { AL_OBJ_FCTR_32,    "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
709   { AL_OBJ_FCTR_16,    "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
710   { AL_OBJ_FDCTR_32,   "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
711   { AL_OBJ_FDCTR_16,   "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
712   { AL_OBJ_FCTR_32T,   "32-Bit Frozen Binary Counter (Obj:21, Var:01)" },
713   { AL_OBJ_FCTR_16T,   "16-Bit Frozen Binary Counter (Obj:21, Var:02)" },
714   { AL_OBJ_FDCTR_32T,  "32-Bit Frozen Binary Delta Counter (Obj:21, Var:03)" },
715   { AL_OBJ_FDCTR_16T,  "16-Bit Frozen Binary Delta Counter (Obj:21, Var:04)" },
716   { AL_OBJ_FCTR_32NF,  "32-Bit Frozen Binary Counter Without Flag (Obj:21, Var:05)" },
717   { AL_OBJ_FCTR_16NF,  "16-Bit Frozen Binary Counter Without Flag (Obj:21, Var:06)" },
718   { AL_OBJ_FDCTR_32NF, "32-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:07)" },
719   { AL_OBJ_FDCTR_16NF, "16-Bit Frozen Binary Delta Counter Without Flag (Obj:21, Var:08)" },
720   { AL_OBJ_CTRC_ALL,   "Binary Counter Change All Variations (Obj:22, Var:All)" },
721   { AL_OBJ_CTRC_32,    "32-Bit Counter Change Event w/o Time (Obj:22, Var:01)" },
722   { AL_OBJ_CTRC_16,    "16-Bit Counter Change Event w/o Time (Obj:22, Var:02)" },
723   { AL_OBJ_DCTRC_32,   "32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03)" },
724   { AL_OBJ_DCTRC_16,   "16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04)" },
725   { AL_OBJ_CTRC_32T,   "32-Bit Counter Change Event with Time (Obj:22, Var:05)" },
726   { AL_OBJ_CTRC_16T,   "16-Bit Counter Change Event with Time (Obj:22, Var:06)" },
727   { AL_OBJ_DCTRC_32T,  "32-Bit Delta Counter Change Event with Time (Obj:22, Var:07)" },
728   { AL_OBJ_DCTRC_16T,  "16-Bit Delta Counter Change Event with Time (Obj:22, Var:08)" },
729   { AL_OBJ_FCTRC_ALL,  "Frozen Binary Counter Change All Variations (Obj:23, Var:All)" },
730   { AL_OBJ_FCTRC_32,   "32-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:01)" },
731   { AL_OBJ_FCTRC_16,   "16-Bit Frozen Counter Change Event w/o Time (Obj:23, Var:02)" },
732   { AL_OBJ_FDCTRC_32,  "32-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:03)" },
733   { AL_OBJ_FDCTRC_16,  "16-Bit Frozen Delta Counter Change Event w/o Time (Obj:23, Var:04)" },
734   { AL_OBJ_FCTRC_32T,  "32-Bit Frozen Counter Change Event with Time (Obj:23, Var:05)" },
735   { AL_OBJ_FCTRC_16T,  "16-Bit Frozen Counter Change Event with Time (Obj:23, Var:06)" },
736   { AL_OBJ_FDCTRC_32T, "32-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:07)" },
737   { AL_OBJ_FDCTRC_16T, "16-Bit Frozen Delta Counter Change Event with Time (Obj:23, Var:08)" },
738   { AL_OBJ_AI_ALL,     "Analog Input All Variations (Obj:30, Var:All)" },
739   { AL_OBJ_AI_32,      "32-Bit Analog Input (Obj:30, Var:01)" },
740   { AL_OBJ_AI_16,      "16-Bit Analog Input (Obj:30, Var:02)" },
741   { AL_OBJ_AI_32NF,    "32-Bit Analog Input Without Flag (Obj:30, Var:03)" },
742   { AL_OBJ_AI_16NF,    "16-Bit Analog Input Without Flag (Obj:30, Var:04)" },
743   { AL_OBJ_AI_FLT,     "32-Bit Floating Point Input (Obj:30, Var:05)" },
744   { AL_OBJ_AI_DBL,     "64-Bit Floating Point Input (Obj:30, Var:06)" },
745   { AL_OBJ_AIF_FLT,    "32-Bit Frozen Floating Point Input (Obj:31, Var:07)" },
746   { AL_OBJ_AIF_DBL,    "64-Bit Frozen Floating Point Input (Obj:31, Var:08)" },
747   { AL_OBJ_AIC_ALL,    "Analog Input Change All Variations (Obj:32, Var:All)" },
748   { AL_OBJ_AIC_32NT,   "32-Bit Analog Change Event w/o Time (Obj:32, Var:01)" },
749   { AL_OBJ_AIC_16NT,   "16-Bit Analog Change Event w/o Time (Obj:32, Var:02)" },
750   { AL_OBJ_AIC_32T,    "32-Bit Analog Change Event with Time (Obj:32, Var:03)" },
751   { AL_OBJ_AIC_16T,    "16-Bit Analog Change Event with Time (Obj:32, Var:04)" },
752   { AL_OBJ_AIC_FLTNT,  "32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05)" },
753   { AL_OBJ_AIC_DBLNT,  "64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06)" },
754   { AL_OBJ_AIC_FLTT,   "32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07)" },
755   { AL_OBJ_AIC_DBLT,   "64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08)" },
756   { AL_OBJ_AIFC_FLTNT, "32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05)" },
757   { AL_OBJ_AIFC_DBLNT, "64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06)" },
758   { AL_OBJ_AIFC_FLTT,  "32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07)" },
759   { AL_OBJ_AIFC_DBLT,  "64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08)" },
760   { AL_OBJ_AO_32,      "32-Bit Analog Output Status (Obj:40, Var:01)" },
761   { AL_OBJ_AO_16,      "16-Bit Analog Output Status (Obj:40, Var:02)" },
762   { AL_OBJ_AO_FLT,     "32-Bit Floating Point Output Status (Obj:40, Var:03)" },
763   { AL_OBJ_AO_DBL,     "64-Bit Floating Point Output Status (Obj:40, Var:04)" },
764   { AL_OBJ_AO_32OPB,   "32-Bit Analog Output Block (Obj:41, Var:01)" },
765   { AL_OBJ_AO_16OPB,   "16-Bit Analog Output Block (Obj:41, Var:02)" },
766   { AL_OBJ_AO_FLTOPB,  "32-Bit Floating Point Output Block (Obj:41, Var:03)" },
767   { AL_OBJ_AO_DBLOPB,  "64-Bit Floating Point Output Block (Obj:41, Var:04)" },
768   { AL_OBJ_TD,         "Time and Date (Obj:50, Var:01)" },
769   { AL_OBJ_TDCTO,      "Time and Date CTO (Obj:51, Var:01)" },
770   { AL_OBJ_TDELAYF,    "Time Delay - Fine (Obj:52, Var:02)" },
771   { AL_OBJ_CLASS0,     "Class 0 Data (Obj:60, Var:01)" },
772   { AL_OBJ_CLASS1,     "Class 1 Data (Obj:60, Var:02)" },
773   { AL_OBJ_CLASS2,     "Class 2 Data (Obj:60, Var:03)" },
774   { AL_OBJ_CLASS3,     "Class 3 Data (Obj:60, Var:04)" },
775   { AL_OBJ_IIN,        "Internal Indications (Obj:80, Var:01)" },
776   { 0, NULL }
777 };
778
779 /* Application Layer Control Code 'Code' Values */
780 static const value_string dnp3_al_ctlc_code_vals[] = {
781   { AL_OBJCTLC_CODE0,     "NUL Operation" },
782   { AL_OBJCTLC_CODE1,     "Pulse On" },
783   { AL_OBJCTLC_CODE2,     "Pulse Off" },
784   { AL_OBJCTLC_CODE3,     "Latch On" },
785   { AL_OBJCTLC_CODE4,     "Latch Off" },
786   { 0, NULL }
787 };
788
789 /* Application Layer Control Code 'Misc' Values */
790 static const value_string dnp3_al_ctlc_misc_vals[] = {
791   { AL_OBJCTLC_QUEUE,     "Queue" },
792   { AL_OBJCTLC_CLEAR,     "Clear" },
793   { 0, NULL }
794 };
795
796 /* Application Layer Control Code 'Trip/Close' Values */
797 static const value_string dnp3_al_ctlc_tc_vals[] = {
798   { AL_OBJCTLC_TC0,     "NUL" },
799   { AL_OBJCTLC_TC1,     "Close" },
800   { AL_OBJCTLC_TC2,     "Trip" },
801   { 0, NULL }
802 };
803
804 /* Application Layer Control Status Values */
805 static const value_string dnp3_al_ctl_status_vals[] = {
806   { AL_OBJCTL_STAT0,     "Req. Accepted/Init/Queued" },
807   { AL_OBJCTL_STAT1,     "Req. Not Accepted; Arm-Timer Expired" },
808   { AL_OBJCTL_STAT2,     "Req. Not Accepted; No 'SELECT' Received" },
809   { AL_OBJCTL_STAT3,     "Req. Not Accepted; Format Err. in Ctl Req." },
810   { AL_OBJCTL_STAT4,     "Ctl Oper. Not Supported For This Point" },
811   { AL_OBJCTL_STAT5,     "Req. Not Accepted; Ctrl Queue Full/Point Active" },
812   { AL_OBJCTL_STAT6,     "Req. Not Accepted; Ctrl Hardware Problems" },
813   { AL_OBJCTL_STAT7,     "Req. Not Accepted; Local/Remote switch in Local" },
814   { AL_OBJCTL_STAT8,     "Req. Not Accepted; Too many operations" },
815   { AL_OBJCTL_STAT9,     "Req. Not Accepted; Insufficient authorization" },
816   { AL_OBJCTL_STAT10,    "Req. Not Accepted; Local automation proc active" },
817   { 0, NULL }
818 };
819
820 /* Application Layer Binary Input Quality Flag Values */
821 static const value_string dnp3_al_biflag_vals[] _U_ = {
822   { AL_OBJ_BI_FLAG0, "Online" },
823   { AL_OBJ_BI_FLAG1, "Restart" },
824   { AL_OBJ_BI_FLAG2, "Comm Fail" },
825   { AL_OBJ_BI_FLAG3, "Remote Forced" },
826   { AL_OBJ_BI_FLAG4, "Locally Forced" },
827   { AL_OBJ_BI_FLAG5, "Chatter Filter" },
828   { 0, NULL }
829 };
830
831 /* Application Layer Counter Quality Flag Values */
832 static const value_string dnp3_al_ctrflag_vals[] _U_ = {
833   { AL_OBJ_CTR_FLAG0, "Online" },
834   { AL_OBJ_CTR_FLAG1, "Restart" },
835   { AL_OBJ_CTR_FLAG2, "Comm Fail" },
836   { AL_OBJ_CTR_FLAG3, "Remote Forced" },
837   { AL_OBJ_CTR_FLAG4, "Locally Forced" },
838   { AL_OBJ_CTR_FLAG5, "Roll-Over" },
839   { AL_OBJ_CTR_FLAG6, "Discontinuity" },
840   { 0, NULL }
841 };
842
843 /* Application Layer Analog Input Quality Flag Values */
844 static const value_string dnp3_al_aiflag_vals[] _U_ = {
845   { AL_OBJ_AI_FLAG0, "Online" },
846   { AL_OBJ_AI_FLAG1, "Restart" },
847   { AL_OBJ_AI_FLAG2, "Comm Fail" },
848   { AL_OBJ_AI_FLAG3, "Remote Forced" },
849   { AL_OBJ_AI_FLAG4, "Locally Forced" },
850   { AL_OBJ_AI_FLAG5, "Over-Range" },
851   { AL_OBJ_AI_FLAG6, "Ref. Error" },
852   { 0, NULL }
853 };
854
855 /* Initialize the subtree pointers */
856 static gint ett_dnp3 = -1;
857 static gint ett_dnp3_dl = -1;
858 static gint ett_dnp3_dl_ctl = -1;
859 static gint ett_dnp3_tr_ctl = -1;
860 static gint ett_dnp3_al_data = -1;
861 static gint ett_dnp3_al = -1;
862 static gint ett_dnp3_al_ctl = -1;
863
864 /* Added for Application Layer Decoding */
865 static gint ett_dnp3_al_iin = -1;
866 static gint ett_dnp3_al_obj = -1;
867 static gint ett_dnp3_al_obj_qualifier = -1;
868 static gint ett_dnp3_al_obj_range = -1;
869 static gint ett_dnp3_al_objdet = -1;
870 static gint ett_dnp3_al_obj_quality = -1;
871 static gint ett_dnp3_al_obj_point = -1;
872
873 /* Tables for reassembly of fragments. */
874 static GHashTable *al_fragment_table = NULL;
875 static GHashTable *al_reassembled_table = NULL;
876
877 /* ************************************************************************* */
878 /*                   Header values for reassembly                            */
879 /* ************************************************************************* */
880 static int   hf_dnp3_fragment  = -1;
881 static int   hf_dnp3_fragments = -1;
882 static int   hf_dnp3_fragment_overlap = -1;
883 static int   hf_dnp3_fragment_overlap_conflict = -1;
884 static int   hf_dnp3_fragment_multiple_tails = -1;
885 static int   hf_dnp3_fragment_too_long_fragment = -1;
886 static int   hf_dnp3_fragment_error = -1;
887 static int   hf_dnp3_fragment_reassembled_in = -1;
888 static gint ett_dnp3_fragment  = -1;
889 static gint ett_dnp3_fragments = -1;
890
891 static const fragment_items dnp3_frag_items = {
892   &ett_dnp3_fragment,
893   &ett_dnp3_fragments,
894   &hf_dnp3_fragments,
895   &hf_dnp3_fragment,
896   &hf_dnp3_fragment_overlap,
897   &hf_dnp3_fragment_overlap_conflict,
898   &hf_dnp3_fragment_multiple_tails,
899   &hf_dnp3_fragment_too_long_fragment,
900   &hf_dnp3_fragment_error,
901   &hf_dnp3_fragment_reassembled_in,
902   "DNP 3.0 fragments"
903 };
904
905 /* Conversation stuff, used for tracking application message fragments */
906 /* the number of entries in the memory chunk array */
907 #define dnp3_conv_init_count 50
908
909 /* Conversation structure */
910 typedef struct {
911   guint conv_seq_number;
912 } dnp3_conv_t;
913
914 /* The conversation sequence number */
915 static guint seq_number = 0;
916
917 /* desegmentation of DNP3 over TCP */
918 static gboolean dnp3_desegment = TRUE;
919
920 /* Enum for different quality type fields */
921 enum QUALITY_TYPE {
922   BIN_IN,
923   BIN_OUT,
924   ANA_IN,
925   ANA_OUT,
926   COUNTER
927 };
928
929 /*****************************************************************/
930 /*                                                               */
931 /* CRC LOOKUP TABLE                                              */
932 /* ================                                              */
933 /* The following CRC lookup table was generated automagically    */
934 /* by the Rocksoft^tm Model CRC Algorithm Table Generation       */
935 /* Program V1.0 using the following model parameters:            */
936 /*                                                               */
937 /*    Width   : 2 bytes.                                         */
938 /*    Poly    : 0x3D65                                           */
939 /*    Reverse : TRUE.                                            */
940 /*                                                               */
941 /* For more information on the Rocksoft^tm Model CRC Algorithm,  */
942 /* see the document titled "A Painless Guide to CRC Error        */
943 /* Detection Algorithms" by Ross Williams                        */
944 /* (ross@guest.adelaide.edu.au.). This document is likely to be  */
945 /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft".        */
946 /*                                                               */
947 /*****************************************************************/
948
949 static guint16 crctable[256] =
950 {
951  0x0000, 0x365E, 0x6CBC, 0x5AE2, 0xD978, 0xEF26, 0xB5C4, 0x839A,
952  0xFF89, 0xC9D7, 0x9335, 0xA56B, 0x26F1, 0x10AF, 0x4A4D, 0x7C13,
953  0xB26B, 0x8435, 0xDED7, 0xE889, 0x6B13, 0x5D4D, 0x07AF, 0x31F1,
954  0x4DE2, 0x7BBC, 0x215E, 0x1700, 0x949A, 0xA2C4, 0xF826, 0xCE78,
955  0x29AF, 0x1FF1, 0x4513, 0x734D, 0xF0D7, 0xC689, 0x9C6B, 0xAA35,
956  0xD626, 0xE078, 0xBA9A, 0x8CC4, 0x0F5E, 0x3900, 0x63E2, 0x55BC,
957  0x9BC4, 0xAD9A, 0xF778, 0xC126, 0x42BC, 0x74E2, 0x2E00, 0x185E,
958  0x644D, 0x5213, 0x08F1, 0x3EAF, 0xBD35, 0x8B6B, 0xD189, 0xE7D7,
959  0x535E, 0x6500, 0x3FE2, 0x09BC, 0x8A26, 0xBC78, 0xE69A, 0xD0C4,
960  0xACD7, 0x9A89, 0xC06B, 0xF635, 0x75AF, 0x43F1, 0x1913, 0x2F4D,
961  0xE135, 0xD76B, 0x8D89, 0xBBD7, 0x384D, 0x0E13, 0x54F1, 0x62AF,
962  0x1EBC, 0x28E2, 0x7200, 0x445E, 0xC7C4, 0xF19A, 0xAB78, 0x9D26,
963  0x7AF1, 0x4CAF, 0x164D, 0x2013, 0xA389, 0x95D7, 0xCF35, 0xF96B,
964  0x8578, 0xB326, 0xE9C4, 0xDF9A, 0x5C00, 0x6A5E, 0x30BC, 0x06E2,
965  0xC89A, 0xFEC4, 0xA426, 0x9278, 0x11E2, 0x27BC, 0x7D5E, 0x4B00,
966  0x3713, 0x014D, 0x5BAF, 0x6DF1, 0xEE6B, 0xD835, 0x82D7, 0xB489,
967  0xA6BC, 0x90E2, 0xCA00, 0xFC5E, 0x7FC4, 0x499A, 0x1378, 0x2526,
968  0x5935, 0x6F6B, 0x3589, 0x03D7, 0x804D, 0xB613, 0xECF1, 0xDAAF,
969  0x14D7, 0x2289, 0x786B, 0x4E35, 0xCDAF, 0xFBF1, 0xA113, 0x974D,
970  0xEB5E, 0xDD00, 0x87E2, 0xB1BC, 0x3226, 0x0478, 0x5E9A, 0x68C4,
971  0x8F13, 0xB94D, 0xE3AF, 0xD5F1, 0x566B, 0x6035, 0x3AD7, 0x0C89,
972  0x709A, 0x46C4, 0x1C26, 0x2A78, 0xA9E2, 0x9FBC, 0xC55E, 0xF300,
973  0x3D78, 0x0B26, 0x51C4, 0x679A, 0xE400, 0xD25E, 0x88BC, 0xBEE2,
974  0xC2F1, 0xF4AF, 0xAE4D, 0x9813, 0x1B89, 0x2DD7, 0x7735, 0x416B,
975  0xF5E2, 0xC3BC, 0x995E, 0xAF00, 0x2C9A, 0x1AC4, 0x4026, 0x7678,
976  0x0A6B, 0x3C35, 0x66D7, 0x5089, 0xD313, 0xE54D, 0xBFAF, 0x89F1,
977  0x4789, 0x71D7, 0x2B35, 0x1D6B, 0x9EF1, 0xA8AF, 0xF24D, 0xC413,
978  0xB800, 0x8E5E, 0xD4BC, 0xE2E2, 0x6178, 0x5726, 0x0DC4, 0x3B9A,
979  0xDC4D, 0xEA13, 0xB0F1, 0x86AF, 0x0535, 0x336B, 0x6989, 0x5FD7,
980  0x23C4, 0x159A, 0x4F78, 0x7926, 0xFABC, 0xCCE2, 0x9600, 0xA05E,
981  0x6E26, 0x5878, 0x029A, 0x34C4, 0xB75E, 0x8100, 0xDBE2, 0xEDBC,
982  0x91AF, 0xA7F1, 0xFD13, 0xCB4D, 0x48D7, 0x7E89, 0x246B, 0x1235
983 };
984
985 /*****************************************************************/
986 /*                   End of CRC Lookup Table                     */
987 /*****************************************************************/
988
989 /* calculates crc given a buffer of characters and a length of buffer */
990 static guint16
991 calculateCRC(const void *buf, guint len) {
992   guint16 crc = 0;
993   const guint8 *p = (const guint8 *)buf;
994   while(len-- > 0)
995     crc = crctable[(crc ^ *p++) & 0xff] ^ (crc >> 8);
996   return ~crc;
997 }
998
999 /*****************************************************************/
1000 /*  Adds text to item, with trailing "," if required             */
1001 /*****************************************************************/
1002 static gboolean
1003 add_item_text(proto_item *item, const gchar *text, gboolean comma_needed)
1004 {
1005   if (comma_needed) {
1006     proto_item_append_text(item, ", ");
1007   }
1008   proto_item_append_text(item, text);
1009   return TRUE;
1010 }
1011
1012 /*****************************************************************/
1013 /*  Application Layer Process Internal Indications (IIN)         */
1014 /*****************************************************************/
1015 static void
1016 dnp3_al_process_iin(tvbuff_t *tvb, int offset, proto_tree *al_tree)
1017 {
1018
1019   guint16       al_iin;
1020   proto_item    *tiin;
1021   proto_tree    *iin_tree = NULL;
1022   gboolean      comma_needed = FALSE;
1023
1024   al_iin = tvb_get_ntohs(tvb, offset);
1025
1026   tiin = proto_tree_add_uint_format(al_tree, hf_dnp3_al_iin, tvb, offset, 2, al_iin,
1027         "Internal Indications: ");
1028   if (al_iin & AL_IIN_RST)    comma_needed = add_item_text(tiin, "Device Restart", comma_needed);
1029   if (al_iin & AL_IIN_DOL)    comma_needed = add_item_text(tiin, "Digital Outputs in Local", comma_needed);
1030   if (al_iin & AL_IIN_DT)     comma_needed = add_item_text(tiin, "Device Trouble", comma_needed);
1031   if (al_iin & AL_IIN_TSR)    comma_needed = add_item_text(tiin, "Time Sync Required", comma_needed);
1032   if (al_iin & AL_IIN_CLS3D)  comma_needed = add_item_text(tiin, "Class 3 Data Available", comma_needed);
1033   if (al_iin & AL_IIN_CLS2D)  comma_needed = add_item_text(tiin, "Class 2 Data Available", comma_needed);
1034   if (al_iin & AL_IIN_CLS1D)  comma_needed = add_item_text(tiin, "Class 1 Data Available", comma_needed);
1035   if (al_iin & AL_IIN_BMSG)   comma_needed = add_item_text(tiin, "Broadcast Message Rx'd", comma_needed);
1036   if (al_iin & AL_IIN_CC)     comma_needed = add_item_text(tiin, "Device Configuration Corrupt", comma_needed);
1037   if (al_iin & AL_IIN_OAE)    comma_needed = add_item_text(tiin, "Operation Already Executing", comma_needed);
1038   if (al_iin & AL_IIN_EBO)    comma_needed = add_item_text(tiin, "Event Buffer Overflow", comma_needed);
1039   if (al_iin & AL_IIN_PIOOR)  comma_needed = add_item_text(tiin, "Parameters Invalid or Out of Range", comma_needed);
1040   if (al_iin & AL_IIN_OBJU)   comma_needed = add_item_text(tiin, "Requested Objects Unknown", comma_needed);
1041   proto_item_append_text(tiin, " (0x%04x)", al_iin);
1042
1043   iin_tree = proto_item_add_subtree(tiin, ett_dnp3_al_iin);
1044   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_rst, tvb, offset, 2, FALSE);
1045   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_dt, tvb, offset, 2, FALSE);
1046   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_dol, tvb, offset, 2, FALSE);
1047   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_tsr, tvb, offset, 2, FALSE);
1048   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cls3d, tvb, offset, 2, FALSE);
1049   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cls2d, tvb, offset, 2, FALSE);
1050   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cls1d, tvb, offset, 2, FALSE);
1051   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_bmsg, tvb, offset, 2, FALSE);
1052   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_cc, tvb, offset, 2, FALSE);
1053   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_oae, tvb, offset, 2, FALSE);
1054   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_ebo, tvb, offset, 2, FALSE);
1055   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_pioor, tvb, offset, 2, FALSE);
1056   proto_tree_add_item(iin_tree, hf_dnp3_al_iin_obju, tvb, offset, 2, FALSE);
1057 }
1058
1059 /*****************************************************************/
1060 /* Function to determine Application Layer Object Index size and */
1061 /* Point address.                                                */
1062 /*****************************************************************/
1063 static int
1064 dnp3_al_obj_procindex(tvbuff_t *tvb, int offset, guint8 al_objq_index, guint32 *al_ptaddr, proto_tree *item_tree)
1065 {
1066   int indexbytes = 0;
1067   proto_item *index_item;
1068
1069   switch (al_objq_index)
1070   {
1071     case AL_OBJQL_IDX_NI:        /* No Index */
1072       indexbytes = 0;
1073       index_item = proto_tree_add_text(item_tree, tvb, offset, 0, "Point Index: %u", *al_ptaddr);
1074       PROTO_ITEM_SET_GENERATED(index_item);
1075       break;
1076     case AL_OBJQL_IDX_1O:
1077       *al_ptaddr = tvb_get_guint8(tvb, offset);
1078       proto_tree_add_item(item_tree, hf_dnp3_al_index8, tvb, offset, 1, TRUE);
1079       indexbytes = 1;
1080       break;
1081     case AL_OBJQL_IDX_2O:
1082       *al_ptaddr = tvb_get_letohs(tvb, offset);
1083       proto_tree_add_item(item_tree, hf_dnp3_al_index16, tvb, offset, 2, TRUE);
1084       indexbytes = 2;
1085       break;
1086     case AL_OBJQL_IDX_4O:
1087       *al_ptaddr = tvb_get_letohl(tvb, offset);
1088       proto_tree_add_item(item_tree, hf_dnp3_al_index32, tvb, offset, 4, TRUE);
1089       indexbytes = 4;
1090       break;
1091   }
1092   return indexbytes;
1093 }
1094
1095 /*****************************************************************/
1096 /* Function to add the same string to two separate tree items    */
1097 /*****************************************************************/
1098 static void
1099 dnp3_append_2item_text(proto_item *item1, proto_item *item2, const gchar *text)
1100 {
1101   proto_item_append_text(item1, text);
1102   proto_item_append_text(item2, text);
1103 }
1104
1105 /*****************************************************************/
1106 /* Function to Determine Application Layer Point Quality Flags & */
1107 /* add Point Quality Flag Sub-Tree                               */
1108 /*****************************************************************/
1109 static void
1110 dnp3_al_obj_quality(tvbuff_t *tvb, int offset, guint8 al_ptflags, proto_tree *point_tree, proto_item *point_item, enum QUALITY_TYPE type)
1111 {
1112
1113   proto_tree  *quality_tree = NULL;
1114   proto_item  *quality_item;
1115   int         hf0 = 0, hf1 = 0, hf2 = 0, hf3 = 0, hf4 = 0, hf5 = 0, hf6 = 0, hf7 = 0;
1116
1117   /* Common code */
1118   proto_item_append_text(point_item, " (Quality: ");
1119   quality_item = proto_tree_add_text(point_tree, tvb, offset, 1, "Quality: ");
1120   quality_tree = proto_item_add_subtree(quality_item, ett_dnp3_al_obj_quality);
1121
1122   if (al_ptflags & AL_OBJ_BI_FLAG0) {
1123     dnp3_append_2item_text(point_item, quality_item, "Online");
1124   }
1125   else {
1126     dnp3_append_2item_text(point_item, quality_item, "Offline");
1127   }
1128   if (al_ptflags & AL_OBJ_BI_FLAG1) dnp3_append_2item_text(point_item, quality_item, ", Restart");
1129   if (al_ptflags & AL_OBJ_BI_FLAG2) dnp3_append_2item_text(point_item, quality_item, ", Comm Fail");
1130   if (al_ptflags & AL_OBJ_BI_FLAG3) dnp3_append_2item_text(point_item, quality_item, ", Remote Force");
1131   if (al_ptflags & AL_OBJ_BI_FLAG4) dnp3_append_2item_text(point_item, quality_item, ", Local Force");
1132
1133   switch (type) {
1134     case BIN_IN: /* Binary Input Quality flags */
1135       if (al_ptflags & AL_OBJ_BI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Chatter Filter");
1136
1137       hf0 = hf_dnp3_al_biq_b0;
1138       hf1 = hf_dnp3_al_biq_b1;
1139       hf2 = hf_dnp3_al_biq_b2;
1140       hf3 = hf_dnp3_al_biq_b3;
1141       hf4 = hf_dnp3_al_biq_b4;
1142       hf5 = hf_dnp3_al_biq_b5;
1143       hf6 = hf_dnp3_al_biq_b6;
1144       hf7 = hf_dnp3_al_biq_b7;
1145       break;
1146
1147     case BIN_OUT: /* Binary Output Quality flags */
1148       hf0 = hf_dnp3_al_boq_b0;
1149       hf1 = hf_dnp3_al_boq_b1;
1150       hf2 = hf_dnp3_al_boq_b2;
1151       hf3 = hf_dnp3_al_boq_b3;
1152       hf4 = hf_dnp3_al_boq_b4;
1153       hf5 = hf_dnp3_al_boq_b5;
1154       hf6 = hf_dnp3_al_boq_b6;
1155       hf7 = hf_dnp3_al_boq_b7;
1156       break;
1157
1158     case ANA_IN: /* Analog Input Quality flags */
1159       if (al_ptflags & AL_OBJ_AI_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Over-Range");
1160       if (al_ptflags & AL_OBJ_AI_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Reference Check");
1161
1162       hf0 = hf_dnp3_al_aiq_b0;
1163       hf1 = hf_dnp3_al_aiq_b1;
1164       hf2 = hf_dnp3_al_aiq_b2;
1165       hf3 = hf_dnp3_al_aiq_b3;
1166       hf4 = hf_dnp3_al_aiq_b4;
1167       hf5 = hf_dnp3_al_aiq_b5;
1168       hf6 = hf_dnp3_al_aiq_b6;
1169       hf7 = hf_dnp3_al_aiq_b7;
1170       break;
1171
1172     case ANA_OUT: /* Analog Output Quality flags */
1173       hf0 = hf_dnp3_al_aoq_b0;
1174       hf1 = hf_dnp3_al_aoq_b1;
1175       hf2 = hf_dnp3_al_aoq_b2;
1176       hf3 = hf_dnp3_al_aoq_b3;
1177       hf4 = hf_dnp3_al_aoq_b4;
1178       hf5 = hf_dnp3_al_aoq_b5;
1179       hf6 = hf_dnp3_al_aoq_b6;
1180       hf7 = hf_dnp3_al_aoq_b7;
1181       break;
1182
1183     case COUNTER: /* Counter Quality flags */
1184       if (al_ptflags & AL_OBJ_CTR_FLAG5) dnp3_append_2item_text(point_item, quality_item, ", Roll-over");
1185       if (al_ptflags & AL_OBJ_CTR_FLAG6) dnp3_append_2item_text(point_item, quality_item, ", Discontinuity");
1186
1187       hf0 = hf_dnp3_al_ctrq_b0;
1188       hf1 = hf_dnp3_al_ctrq_b1;
1189       hf2 = hf_dnp3_al_ctrq_b2;
1190       hf3 = hf_dnp3_al_ctrq_b3;
1191       hf4 = hf_dnp3_al_ctrq_b4;
1192       hf5 = hf_dnp3_al_ctrq_b5;
1193       hf6 = hf_dnp3_al_ctrq_b6;
1194       hf7 = hf_dnp3_al_ctrq_b7;
1195       break;
1196   }
1197
1198   if (quality_tree != NULL) {
1199     proto_tree_add_item(quality_tree, hf7, tvb, offset, 1, TRUE);
1200     proto_tree_add_item(quality_tree, hf6, tvb, offset, 1, TRUE);
1201     proto_tree_add_item(quality_tree, hf5, tvb, offset, 1, TRUE);
1202     proto_tree_add_item(quality_tree, hf4, tvb, offset, 1, TRUE);
1203     proto_tree_add_item(quality_tree, hf3, tvb, offset, 1, TRUE);
1204     proto_tree_add_item(quality_tree, hf2, tvb, offset, 1, TRUE);
1205     proto_tree_add_item(quality_tree, hf1, tvb, offset, 1, TRUE);
1206     proto_tree_add_item(quality_tree, hf0, tvb, offset, 1, TRUE);
1207   }
1208   proto_item_append_text(point_item, ")");
1209 }
1210
1211 /**********************************************************************/
1212 /* Function to convert DNP3 timestamp to nstime_t value               */
1213 /**********************************************************************/
1214 /* 48-bit Time Format                                                 */
1215 /* MSB      FF       EE       DD       CC       BB       AA      LSB  */
1216 /*       ffffffff eeeeeeee dddddddd cccccccc bbbbbbbb aaaaaaaa        */
1217 /*       47    40 39    32 31    24 23    16 15     8 7      0        */
1218 /*                                                                    */
1219 /* Value is ms since 00:00 on 1/1/1970                                */
1220 /**********************************************************************/
1221 static void
1222 dnp3_al_get_timestamp(nstime_t *timestamp, tvbuff_t *tvb, int data_pos)
1223 {
1224
1225   guint32    hi, lo;
1226   guint64    time_ms;
1227
1228   lo = tvb_get_letohs(tvb, data_pos);
1229   hi = tvb_get_letohl(tvb, data_pos + 2);
1230
1231   time_ms = (guint64)hi * 0x10000 + lo;
1232
1233   timestamp->secs = (long)(time_ms / 1000);
1234   timestamp->nsecs = (long)(time_ms % 1000) * 1000000;
1235 }
1236
1237 /*****************************************************************/
1238 /*  Desc:    Application Layer Process Object Details            */
1239 /*  Returns: New offset pointer into tvb                         */
1240 /*****************************************************************/
1241 static int
1242 dnp3_al_process_object(tvbuff_t *tvb, int offset, proto_tree *robj_tree, gboolean header_only, guint16 *al_objtype)
1243 {
1244
1245   guint8        al_2bit, al_objq, al_objq_index, al_objq_code, al_ptflags, al_ctlobj_code,
1246                 al_ctlobj_code_c, al_ctlobj_code_m, al_ctlobj_code_tc, al_ctlobj_count, al_bi_val, bitindex=0;
1247   guint16       al_obj, al_val16=0, al_ctlobj_stat, al_relms;
1248   guint32       item_num, al_val32, num_items=0, al_ptaddr=0, al_ctlobj_on, al_ctlobj_off;
1249   nstime_t      al_cto, al_reltime, al_abstime;
1250   gboolean      al_bit;
1251   guint         data_pos;
1252   gfloat        al_valflt;
1253   gdouble       al_valdbl;
1254   int           orig_offset, rangebytes=0, indexbytes=0;
1255   proto_item    *object_item = NULL, *point_item = NULL, *qualifier_item = NULL, *range_item = NULL;
1256   proto_tree    *object_tree = NULL, *point_tree, *qualifier_tree, *range_tree;
1257   const gchar   *ctl_code_str, *ctl_misc_str, *ctl_tc_str, *ctl_status_str;
1258
1259   orig_offset = offset;
1260
1261   /* Application Layer Objects in this Message */
1262   *al_objtype =
1263   al_obj = tvb_get_ntohs(tvb, offset);
1264
1265   /* Create Data Objects Detail Tree */
1266   object_item = proto_tree_add_uint_format(robj_tree, hf_dnp3_al_obj, tvb, offset, 2, al_obj,
1267      "Object(s): %s (0x%04x)", val_to_str(al_obj, dnp3_al_obj_vals, "Unknown Object - Abort Decoding..."), al_obj);
1268   object_tree = proto_item_add_subtree(object_item, ett_dnp3_al_obj);
1269
1270   offset += 2;
1271
1272   /* Object Qualifier */
1273   al_objq = tvb_get_guint8(tvb, offset);
1274   al_objq_index = al_objq & AL_OBJQ_INDEX;
1275   al_objq_index = al_objq_index >> 4;
1276   al_objq_code = al_objq & AL_OBJQ_CODE;
1277
1278   qualifier_item = proto_tree_add_text(object_tree, tvb, offset, 1, "Qualifier Field, Prefix: %s, Code: %s",
1279     val_to_str(al_objq_index, dnp3_al_objq_index_vals, "Unknown Index Type"),
1280     val_to_str(al_objq_code, dnp3_al_objq_code_vals, "Unknown Code Type"));
1281   qualifier_tree = proto_item_add_subtree(qualifier_item, ett_dnp3_al_obj_qualifier);
1282   proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_index, tvb, offset, 1, FALSE);
1283   proto_tree_add_item(qualifier_tree, hf_dnp3_al_objq_code, tvb, offset, 1, FALSE);
1284
1285   offset += 1;
1286
1287   /* Create (possibly synthesized) number of items and range field tree */
1288   range_item = proto_tree_add_text(object_tree, tvb, offset, 0, "Number of Items: ");
1289   range_tree = proto_item_add_subtree(range_item, ett_dnp3_al_obj_range);
1290
1291   switch (al_objq_code)
1292   {
1293     case AL_OBJQL_CODE_SSI8:           /* 8-bit Start and Stop Indices in Range Field */
1294       num_items = ( tvb_get_guint8(tvb, offset+1) - tvb_get_guint8(tvb, offset) + 1);
1295       PROTO_ITEM_SET_GENERATED(range_item);
1296       al_ptaddr = tvb_get_guint8(tvb, offset);
1297       proto_tree_add_item(range_tree, hf_dnp3_al_range_start8, tvb, offset, 1, TRUE);
1298       proto_tree_add_item(range_tree, hf_dnp3_al_range_stop8, tvb, offset + 1, 1, TRUE);
1299       rangebytes = 2;
1300       break;
1301     case AL_OBJQL_CODE_SSI16:          /* 16-bit Start and Stop Indices in Range Field */
1302       num_items = ( tvb_get_letohs(tvb, offset+2) - tvb_get_letohs(tvb, (offset)) + 1);
1303       PROTO_ITEM_SET_GENERATED(range_item);
1304       al_ptaddr = tvb_get_letohs(tvb, offset);
1305       proto_tree_add_item(range_tree, hf_dnp3_al_range_start16, tvb, offset, 2, TRUE);
1306       proto_tree_add_item(range_tree, hf_dnp3_al_range_stop16, tvb, offset + 2, 2, TRUE);
1307       rangebytes = 4;
1308       break;
1309     case AL_OBJQL_CODE_SSI32:          /* 32-bit Start and Stop Indices in Range Field */
1310       num_items = ( tvb_get_letohl(tvb, offset+4) - tvb_get_letohl(tvb, offset) + 1);
1311       PROTO_ITEM_SET_GENERATED(range_item);
1312       al_ptaddr = tvb_get_letohl(tvb, offset);
1313       proto_tree_add_item(range_tree, hf_dnp3_al_range_start32, tvb, offset, 4, TRUE);
1314       proto_tree_add_item(range_tree, hf_dnp3_al_range_stop32, tvb, offset + 4, 2, TRUE);
1315       rangebytes = 8;
1316       break;
1317     case AL_OBJQL_CODE_AA8:            /* 8-bit Absolute Address in Range Field */
1318       num_items = 1;
1319       PROTO_ITEM_SET_GENERATED(range_item);
1320       al_ptaddr = tvb_get_guint8(tvb, offset);
1321       proto_tree_add_item(range_tree, hf_dnp3_al_range_abs8, tvb, offset, 1, TRUE);
1322       rangebytes = 1;
1323       break;
1324     case AL_OBJQL_CODE_AA16:           /* 16-bit Absolute Address in Range Field */
1325       num_items = 1;
1326       PROTO_ITEM_SET_GENERATED(range_item);
1327       al_ptaddr = tvb_get_letohs(tvb, offset);
1328       proto_tree_add_item(range_tree, hf_dnp3_al_range_abs16, tvb, offset, 2, TRUE);
1329       rangebytes = 2;
1330       break;
1331     case AL_OBJQL_CODE_AA32:           /* 32-bit Absolute Address in Range Field */
1332       num_items = 1;
1333       PROTO_ITEM_SET_GENERATED(range_item);
1334       al_ptaddr = tvb_get_letohl(tvb, offset);
1335       proto_tree_add_item(range_tree, hf_dnp3_al_range_abs32, tvb, offset, 4, TRUE);
1336       rangebytes = 4;
1337       break;
1338     case AL_OBJQL_CODE_SF8:            /* 8-bit Single Field Quantity in Range Field */
1339       num_items = tvb_get_guint8(tvb, offset);
1340       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant8, tvb, offset, 1, TRUE);
1341       rangebytes = 1;
1342       proto_item_set_len(range_item, rangebytes);
1343       break;
1344     case AL_OBJQL_CODE_SF16:           /* 16-bit Single Field Quantity in Range Field */
1345       num_items = tvb_get_letohs(tvb, offset);
1346       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant16, tvb, offset, 2, TRUE);
1347       rangebytes = 2;
1348       proto_item_set_len(range_item, rangebytes);
1349       break;
1350     case AL_OBJQL_CODE_SF32:           /* 32-bit Single Field Quantity in Range Field */
1351       num_items = tvb_get_letohl(tvb, offset);
1352       proto_tree_add_item(range_tree, hf_dnp3_al_range_quant32, tvb, offset, 4, TRUE);
1353       rangebytes = 4;
1354       proto_item_set_len(range_item, rangebytes);
1355       break;
1356   }
1357   if (num_items)
1358     proto_item_append_text(object_item, ", %u point%s", num_items, plurality(num_items, "", "s"));
1359   proto_item_append_text(range_item, "%u", num_items);
1360
1361   offset += rangebytes;
1362
1363   bitindex = 0; /* Temp variable for cycling through points when object values are encoded into
1364             bits; primarily objects 0x0101, 0x0301 & 0x1001 */
1365
1366   /* Only process the point information for replies or items with point index lists */
1367   if (!header_only || al_objq_index > 0) {
1368     for (item_num = 0; item_num < num_items; item_num++)
1369     {
1370       /* Create Point item and Process Index */
1371       point_item = proto_tree_add_text(object_tree, tvb, offset, -1, "Point Number");
1372       point_tree = proto_item_add_subtree(point_item, ett_dnp3_al_obj_point);
1373
1374       data_pos = offset;
1375       indexbytes = dnp3_al_obj_procindex(tvb, offset, al_objq_index, &al_ptaddr, point_tree);
1376       proto_item_append_text(point_item, " %u", al_ptaddr);
1377       data_pos += indexbytes;
1378
1379       if (!header_only) {
1380         switch (al_obj)
1381         {
1382
1383           case AL_OBJ_BI_ALL:      /* Binary Input All Var (Obj:01, Var:All) */
1384           case AL_OBJ_BIC_ALL:     /* Binary Input Change All Var (Obj:02, Var:All) */
1385           case AL_OBJ_2BI_ALL:     /* Double-bit Input All Var (Obj:03, Var:All) */
1386           case AL_OBJ_CTR_ALL:     /* Binary Counter All Var (Obj:20, Var:All) */
1387           case AL_OBJ_CTRC_ALL:    /* Binary Counter Change All Var (Obj:22 Var:All) */
1388           case AL_OBJ_AI_ALL:      /* Analog Input All Var (Obj:30, Var:All) */
1389           case AL_OBJ_AIC_ALL:     /* Analog Input Change All Var (Obj:32 Var:All) */
1390
1391             offset = data_pos;
1392             break;
1393
1394           case AL_OBJ_BI_1BIT:    /* Single-Bit Binary Input (Obj:01, Var:01) */
1395           case AL_OBJ_BO:         /* Binary Output (Obj:10, Var:01) */
1396
1397             /* Reset bit index if we've gone onto the next byte */
1398             if (bitindex > 7)
1399             {
1400               bitindex = 0;
1401               offset += (indexbytes + 1);
1402             }
1403
1404             /* Extract the bit from the packed byte */
1405             al_bi_val = tvb_get_guint8(tvb, offset);
1406             al_bit = (al_bi_val & (1 << bitindex)) > 0;
1407
1408             proto_item_append_text(point_item, ", Value: %u", al_bit);
1409             proto_tree_add_boolean(point_tree, hf_dnp3_al_bit, tvb, offset, 1, al_bit);
1410             proto_item_set_len(point_item, indexbytes + 1);
1411
1412             /* If we've read the last item, then move the offset past this byte */
1413             if (item_num == (num_items-1))
1414             {
1415               offset += (indexbytes + 1);
1416             }
1417
1418             break;
1419
1420           case AL_OBJ_2BI_NF:    /* Double-bit Input No Flags (Obj:03, Var:01) */
1421
1422             if (bitindex > 3)
1423             {
1424               bitindex = 0;
1425               offset += (indexbytes + 1);
1426             }
1427
1428             /* Extract the Double-bit from the packed byte */
1429             al_bi_val = tvb_get_guint8(tvb, offset);
1430             al_2bit = ((al_bi_val >> (bitindex << 1)) & 3);
1431
1432             proto_item_append_text(point_item, ", Value: %u", al_2bit);
1433             proto_tree_add_uint(point_tree, hf_dnp3_al_2bit, tvb, offset, 1, al_2bit);
1434             proto_item_set_len(point_item, indexbytes + 1);
1435
1436             /* If we've read the last item, then move the offset past this byte */
1437             if (item_num == (num_items-1))
1438             {
1439               offset += (indexbytes + 1);
1440             }
1441
1442             break;
1443
1444
1445           case AL_OBJ_BI_STAT:    /* Binary Input With Status (Obj:01, Var:02) */
1446           case AL_OBJ_BIC_NOTIME: /* Binary Input Change Without Time (Obj:02, Var:01) */
1447           case AL_OBJ_BO_STAT:    /* Binary Output Status (Obj:10, Var:02) */
1448
1449             /* Get Point Flags */
1450             al_ptflags = tvb_get_guint8(tvb, data_pos);
1451
1452             switch (al_obj) {
1453               case AL_OBJ_BI_STAT:
1454               case AL_OBJ_BIC_NOTIME:
1455                 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
1456                 break;
1457               case AL_OBJ_BO_STAT:
1458                 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_OUT);
1459                 break;
1460             }
1461             data_pos += 1;
1462
1463             al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) > 0;
1464             proto_item_append_text(point_item, ", Value: %u", al_bit);
1465
1466             proto_item_set_len(point_item, data_pos - offset);
1467
1468             offset = data_pos;
1469             break;
1470
1471           case AL_OBJ_2BI_STAT:    /* Double-bit Input With Status (Obj:03, Var:02) */
1472           case AL_OBJ_2BIC_NOTIME: /* Double-bit Input Change Without Time (Obj:04, Var:01) */
1473
1474             /* Get Point Flags */
1475             al_ptflags = tvb_get_guint8(tvb, data_pos);
1476             dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
1477             data_pos += 1;
1478
1479             al_2bit = (al_ptflags >> 6) & 3;
1480             proto_item_append_text(point_item, ", Value: %u", al_2bit);
1481             proto_item_set_len(point_item, data_pos - offset);
1482
1483             offset = data_pos;
1484             break;
1485
1486           case AL_OBJ_BIC_TIME:   /* Binary Input Change w/ Time (Obj:02, Var:02)  */
1487
1488             /* Get Point Flags */
1489             al_ptflags = tvb_get_guint8(tvb, data_pos);
1490             dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
1491             data_pos += 1;
1492
1493
1494             /* Get timestamp */
1495             dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
1496             proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
1497             data_pos += 6;
1498
1499             al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
1500             proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime));
1501             proto_item_set_len(point_item, data_pos - offset);
1502
1503             offset = data_pos;
1504             break;
1505
1506           case AL_OBJ_2BIC_TIME:   /* Double-bit Input Change w/ Time (Obj:04, Var:02)  */
1507
1508             /* Get Point Flags */
1509             al_ptflags = tvb_get_guint8(tvb, data_pos);
1510             dnp3_al_obj_quality(tvb, (offset+indexbytes), al_ptflags, point_tree, point_item, BIN_IN);
1511             data_pos += 1;
1512
1513
1514             /* Get timestamp */
1515             dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
1516             proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
1517             data_pos += 6;
1518
1519             al_2bit = (al_ptflags >> 6) & 3; /* bit shift 11xxxxxx -> 00000011 */
1520             proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_2bit, abs_time_to_str(&al_abstime));
1521             proto_item_set_len(point_item, data_pos - offset);
1522
1523             offset = data_pos;
1524             break;
1525
1526           case AL_OBJ_BIC_RTIME:   /* Binary Input Change w/ Relative Time (Obj:02, Var:03)  */
1527
1528             /* Get Point Flags */
1529             al_ptflags = tvb_get_guint8(tvb, data_pos);
1530             dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, BIN_IN);
1531             data_pos += 1;
1532
1533             /* Get relative time, and convert to ns_time */
1534             al_relms = tvb_get_letohs(tvb, data_pos);
1535             al_reltime.secs = al_relms / 1000;
1536             al_reltime.nsecs = (al_relms % 1000) * 1000;
1537             /* Now add to CTO time */
1538             nstime_sum(&al_abstime, &al_cto, &al_reltime);
1539             proto_tree_add_time(point_tree, hf_dnp3_al_rel_timestamp, tvb, data_pos, 2, &al_reltime);
1540             data_pos += 2;
1541
1542             al_bit = (al_ptflags & AL_OBJ_BI_FLAG7) >> 7; /* bit shift 1xxxxxxx -> xxxxxxx1 */
1543             proto_item_append_text(point_item, ", Value: %u, Timestamp: %s", al_bit, abs_time_to_str(&al_abstime));
1544             proto_item_set_len(point_item, data_pos - offset);
1545
1546             offset = data_pos;
1547             break;
1548
1549           case AL_OBJ_CTLOP_BLK:  /* Control Relay Output Block (Obj:12, Var:01) */
1550
1551             al_ctlobj_code = tvb_get_guint8(tvb, data_pos);
1552             data_pos += 1;
1553
1554             /* Bit-Mask xxxx1111 for Control Code 'Code' */
1555             al_ctlobj_code_c = al_ctlobj_code & AL_OBJCTLC_CODE;
1556             ctl_code_str = val_to_str(al_ctlobj_code_c, dnp3_al_ctlc_code_vals, "Ctrl Code Invalid (0x%02x)");
1557
1558             /* Bit-Mask xx11xxxx for Control Code Misc Values */
1559             al_ctlobj_code_m = al_ctlobj_code & AL_OBJCTLC_MISC;
1560             ctl_misc_str = val_to_str(al_ctlobj_code_m, dnp3_al_ctlc_misc_vals, "");
1561
1562             /* Bit-Mask 11xxxxxx for Control Code 'Trip/Close' */
1563             al_ctlobj_code_tc = al_ctlobj_code & AL_OBJCTLC_TC;
1564             ctl_tc_str = val_to_str(al_ctlobj_code_tc, dnp3_al_ctlc_tc_vals, "");
1565
1566             /* Get "Count" Field */
1567             al_ctlobj_count = tvb_get_guint8(tvb, data_pos);
1568             data_pos += 1;
1569
1570             /* Get "On Time" Field */
1571             al_ctlobj_on = tvb_get_letohl(tvb, data_pos);
1572             data_pos += 4;
1573
1574             /* Get "Off Time" Field */
1575             al_ctlobj_off = tvb_get_letohl(tvb, data_pos);
1576             data_pos += 4;
1577
1578             al_ctlobj_stat = tvb_get_guint8(tvb, data_pos);
1579             proto_tree_add_item(point_item, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, TRUE);
1580             ctl_status_str = val_to_str(al_ctlobj_stat, dnp3_al_ctl_status_vals, "Invalid Status (0x%02x)");
1581             data_pos += 1;
1582
1583             proto_item_append_text(point_item, ", Control Code: [%s,%s,%s (0x%02x)]",
1584                  ctl_code_str, ctl_misc_str, ctl_tc_str, al_ctlobj_code);
1585
1586             proto_tree_add_text(point_tree, tvb, data_pos - 11, 11,
1587                "  [Count: %u] [On-Time: %u] [Off-Time: %u] [Status: %s (0x%02x)]",
1588                    al_ctlobj_count, al_ctlobj_on, al_ctlobj_off, ctl_status_str, al_ctlobj_stat);
1589
1590             proto_item_set_len(point_item, data_pos - offset);
1591
1592             offset = data_pos;
1593             break;
1594
1595           case AL_OBJ_AO_32OPB:   /* 32-Bit Analog Output Block (Obj:41, Var:01) */
1596           case AL_OBJ_AO_16OPB:   /* 16-Bit Analog Output Block (Obj:41, Var:02) */
1597           case AL_OBJ_AO_FLTOPB:  /* 32-Bit Floating Point Output Block (Obj:41, Var:03) */
1598           case AL_OBJ_AO_DBLOPB:  /* 64-Bit Floating Point Output Block (Obj:41, Var:04) */
1599
1600             switch (al_obj)
1601             {
1602               case AL_OBJ_AO_32OPB:
1603                 al_val32 = tvb_get_letohl(tvb, data_pos);
1604                 proto_item_append_text(point_item, ", Value: %u", al_val32);
1605                 proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, TRUE);
1606                 data_pos += 4;
1607                 break;
1608               case AL_OBJ_AO_16OPB:
1609                 al_val32 = tvb_get_letohs(tvb, data_pos);
1610                 proto_item_append_text(point_item, ", Value: %u", al_val32);
1611                 proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, TRUE);
1612                 data_pos += 2;
1613                 break;
1614               case AL_OBJ_AO_FLTOPB:
1615                 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
1616                 proto_item_append_text(point_item, ", Value: %g", al_valflt);
1617                 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, TRUE);
1618                 data_pos += 4;
1619                 break;
1620               case AL_OBJ_AO_DBLOPB:
1621                 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
1622                 proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
1623                 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, TRUE);
1624                 data_pos += 8;
1625                 break;
1626             }
1627
1628             /* Get control status */
1629             al_ctlobj_stat = tvb_get_guint8(tvb, data_pos);
1630             ctl_status_str = val_to_str(al_ctlobj_stat, dnp3_al_ctl_status_vals, "Invalid Status (0x%02x)");
1631             proto_item_append_text(point_item, " [Status: %s (0x%02x)]", ctl_status_str, al_ctlobj_stat);
1632             proto_tree_add_item(point_tree, hf_dnp3_al_ctrlstatus, tvb, data_pos, 1, TRUE);
1633             data_pos += 1;
1634
1635             proto_item_set_len(point_item, data_pos - offset);
1636
1637             offset = data_pos;
1638             break;
1639
1640           case AL_OBJ_CTR_32:     /* 32-Bit Binary Counter (Obj:20, Var:01) */
1641           case AL_OBJ_CTR_16:     /* 16-Bit Binary Counter (Obj:20, Var:02) */
1642           case AL_OBJ_DCTR_32:    /* 32-Bit Binary Delta Counter (Obj:20, Var:03) */
1643           case AL_OBJ_DCTR_16:    /* 16-Bit Binary Delta Counter (Obj:20, Var:04) */
1644           case AL_OBJ_CTR_32NF:   /* 32-Bit Binary Counter Without Flag (Obj:20, Var:05) */
1645           case AL_OBJ_CTR_16NF:   /* 16-Bit Binary Counter Without Flag (Obj:20, Var:06) */
1646           case AL_OBJ_DCTR_32NF:  /* 32-Bit Binary Delta Counter Without Flag (Obj:20, Var:07) */
1647           case AL_OBJ_DCTR_16NF:  /* 16-Bit Binary Delta Counter Without Flag (Obj:20, Var:08) */
1648           case AL_OBJ_FCTR_32:    /* 32-Bit Frozen Counter (Obj:21, Var:01) */
1649           case AL_OBJ_FCTR_16:    /* 16-Bit Frozen Counter (Obj:21, Var:02) */
1650           case AL_OBJ_FDCTR_32:   /* 21 03 32-Bit Frozen Delta Counter */
1651           case AL_OBJ_FDCTR_16:   /* 21 04 16-Bit Frozen Delta Counter */
1652           case AL_OBJ_FCTR_32T:   /* 21 05 32-Bit Frozen Counter w/ Time of Freeze */
1653           case AL_OBJ_FCTR_16T:   /* 21 06 16-Bit Frozen Counter w/ Time of Freeze */
1654           case AL_OBJ_FDCTR_32T:  /* 21 07 32-Bit Frozen Delta Counter w/ Time of Freeze */
1655           case AL_OBJ_FDCTR_16T:  /* 21 08 16-Bit Frozen Delta Counter w/ Time of Freeze */
1656           case AL_OBJ_FCTR_32NF:  /* 21 09 32-Bit Frozen Counter Without Flag */
1657           case AL_OBJ_FCTR_16NF:  /* 21 10 16-Bit Frozen Counter Without Flag */
1658           case AL_OBJ_FDCTR_32NF: /* 21 11 32-Bit Frozen Delta Counter Without Flag */
1659           case AL_OBJ_FDCTR_16NF: /* 21 12 16-Bit Frozen Delta Counter Without Flag */
1660           case AL_OBJ_CTRC_32:    /* 32-Bit Counter Change Event w/o Time (Obj:22, Var:01) */
1661           case AL_OBJ_CTRC_16:    /* 16-Bit Counter Change Event w/o Time (Obj:22, Var:02) */
1662           case AL_OBJ_DCTRC_32:   /* 32-Bit Delta Counter Change Event w/o Time (Obj:22, Var:03) */
1663           case AL_OBJ_DCTRC_16:   /* 16-Bit Delta Counter Change Event w/o Time (Obj:22, Var:04) */
1664           case AL_OBJ_CTRC_32T:   /* 32-Bit Counter Change Event with Time (Obj:22, Var:05) */
1665           case AL_OBJ_CTRC_16T:   /* 16-Bit Counter Change Event with Time (Obj:22, Var:06) */
1666           case AL_OBJ_DCTRC_32T:  /* 32-Bit Delta Counter Change Event with Time (Obj:22, Var:07) */
1667           case AL_OBJ_DCTRC_16T:  /* 16-Bit Delta Counter Change Event with Time (Obj:22, Var:08) */
1668           case AL_OBJ_FCTRC_32:   /* 21 01 32-Bit Frozen Counter Change Event */
1669           case AL_OBJ_FCTRC_16:   /* 21 02 16-Bit Frozen Counter Change Event */
1670           case AL_OBJ_FDCTRC_32:  /* 21 03 32-Bit Frozen Delta Counter Change Event */
1671           case AL_OBJ_FDCTRC_16:  /* 21 04 16-Bit Frozen Delta Counter Change Event */
1672           case AL_OBJ_FCTRC_32T:  /* 21 05 32-Bit Frozen Counter Change Event w/ Time of Freeze */
1673           case AL_OBJ_FCTRC_16T:  /* 21 06 16-Bit Frozen Counter Change Event w/ Time of Freeze */
1674           case AL_OBJ_FDCTRC_32T: /* 21 07 32-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
1675           case AL_OBJ_FDCTRC_16T: /* 21 08 16-Bit Frozen Delta Counter Change Event w/ Time of Freeze */
1676
1677             /* Get Point Flags for those types that have them, it's easier to block out those that don't have flags */
1678             switch (al_obj)
1679             {
1680               case AL_OBJ_CTR_32NF:
1681               case AL_OBJ_CTR_16NF:
1682               case AL_OBJ_DCTR_32NF:
1683               case AL_OBJ_DCTR_16NF:
1684               case AL_OBJ_FCTR_32NF:
1685               case AL_OBJ_FCTR_16NF:
1686               case AL_OBJ_FDCTR_32NF:
1687               case AL_OBJ_FDCTR_16NF:
1688                 break;
1689
1690               default:
1691                 al_ptflags = tvb_get_guint8(tvb, data_pos);
1692                 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, COUNTER);
1693                 data_pos += 1;
1694                 break;
1695             }
1696
1697             /* Get Counter values */
1698             switch (al_obj)
1699             {
1700               case AL_OBJ_CTR_32:
1701               case AL_OBJ_DCTR_32:
1702               case AL_OBJ_CTR_32NF:
1703               case AL_OBJ_DCTR_32NF:
1704               case AL_OBJ_FCTR_32:
1705               case AL_OBJ_FDCTR_32:
1706               case AL_OBJ_FCTR_32T:
1707               case AL_OBJ_FDCTR_32T:
1708               case AL_OBJ_FCTR_32NF:
1709               case AL_OBJ_FDCTR_32NF:
1710               case AL_OBJ_CTRC_32:
1711               case AL_OBJ_DCTRC_32:
1712               case AL_OBJ_CTRC_32T:
1713               case AL_OBJ_DCTRC_32T:
1714               case AL_OBJ_FCTRC_32:
1715               case AL_OBJ_FDCTRC_32:
1716               case AL_OBJ_FCTRC_32T:
1717               case AL_OBJ_FDCTRC_32T:
1718
1719                 al_val32 = tvb_get_letohl(tvb, data_pos);
1720                 proto_item_append_text(point_item, ", Count: %u", al_val32);
1721                 proto_tree_add_item(point_tree, hf_dnp3_al_cnt32, tvb, data_pos, 4, TRUE);
1722                 data_pos += 4;
1723                 break;
1724
1725               case AL_OBJ_CTR_16:
1726               case AL_OBJ_DCTR_16:
1727               case AL_OBJ_CTR_16NF:
1728               case AL_OBJ_DCTR_16NF:
1729               case AL_OBJ_FCTR_16:
1730               case AL_OBJ_FDCTR_16:
1731               case AL_OBJ_FCTR_16T:
1732               case AL_OBJ_FDCTR_16T:
1733               case AL_OBJ_FCTR_16NF:
1734               case AL_OBJ_FDCTR_16NF:
1735               case AL_OBJ_CTRC_16:
1736               case AL_OBJ_DCTRC_16:
1737               case AL_OBJ_CTRC_16T:
1738               case AL_OBJ_DCTRC_16T:
1739               case AL_OBJ_FCTRC_16:
1740               case AL_OBJ_FDCTRC_16:
1741               case AL_OBJ_FCTRC_16T:
1742               case AL_OBJ_FDCTRC_16T:
1743
1744                 al_val16 = tvb_get_letohs(tvb, data_pos);
1745                 proto_item_append_text(point_item, ", Count: %u", al_val16);
1746                 proto_tree_add_item(point_tree, hf_dnp3_al_cnt16, tvb, data_pos, 2, TRUE);
1747                 data_pos += 2;
1748                 break;
1749             }
1750
1751             /* Get the time for those points that have it */
1752             switch (al_obj)
1753             {
1754               case AL_OBJ_FCTR_32T:
1755               case AL_OBJ_FCTR_16T:
1756               case AL_OBJ_FDCTR_32T:
1757               case AL_OBJ_FDCTR_16T:
1758               case AL_OBJ_CTRC_32T:
1759               case AL_OBJ_CTRC_16T:
1760               case AL_OBJ_DCTRC_32T:
1761               case AL_OBJ_DCTRC_16T:
1762               case AL_OBJ_FCTRC_32T:
1763               case AL_OBJ_FCTRC_16T:
1764               case AL_OBJ_FDCTRC_32T:
1765               case AL_OBJ_FDCTRC_16T:
1766                 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
1767                 proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime));
1768                 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
1769                 data_pos += 6;
1770                 break;
1771             }
1772
1773             proto_item_set_len(point_item, data_pos - offset);
1774             offset = data_pos;
1775
1776             break;
1777
1778           case AL_OBJ_AI_32:        /* 32-Bit Analog Input (Obj:30, Var:01) */
1779           case AL_OBJ_AI_16:        /* 16-Bit Analog Input (Obj:30, Var:02) */
1780           case AL_OBJ_AI_32NF:      /* 32-Bit Analog Input Without Flag (Obj:30, Var:03) */
1781           case AL_OBJ_AI_16NF:      /* 16-Bit Analog Input Without Flag (Obj:30, Var:04) */
1782           case AL_OBJ_AI_FLT:       /* 32-Bit Floating Point Input (Obj:30, Var:05) */
1783           case AL_OBJ_AI_DBL:       /* 64-Bit Floating Point Input (Obj:30, Var:06) */
1784           case AL_OBJ_AIF_FLT:      /* 32-Bit Frozen Floating Point Input (Obj:31, Var:07) */
1785           case AL_OBJ_AIF_DBL:      /* 64-Bit Frozen Floating Point Input (Obj:31, Var:08) */
1786           case AL_OBJ_AIC_32NT:     /* 32-Bit Analog Change Event w/o Time (Obj:32, Var:01) */
1787           case AL_OBJ_AIC_16NT:     /* 16-Bit Analog Change Event w/o Time (Obj:32, Var:02) */
1788           case AL_OBJ_AIC_32T:      /* 32-Bit Analog Change Event with Time (Obj:32, Var:03) */
1789           case AL_OBJ_AIC_16T:      /* 16-Bit Analog Change Event with Time (Obj:32, Var:04) */
1790           case AL_OBJ_AIC_FLTNT:    /* 32-Bit Floating Point Change Event w/o Time (Obj:32, Var:05) */
1791           case AL_OBJ_AIC_DBLNT:    /* 64-Bit Floating Point Change Event w/o Time (Obj:32, Var:06) */
1792           case AL_OBJ_AIC_FLTT:     /* 32-Bit Floating Point Change Event w/ Time (Obj:32, Var:07) */
1793           case AL_OBJ_AIC_DBLT:     /* 64-Bit Floating Point Change Event w/ Time (Obj:32, Var:08) */
1794           case AL_OBJ_AIFC_FLTNT:   /* 32-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:05) */
1795           case AL_OBJ_AIFC_DBLNT:   /* 64-Bit Floating Point Frozen Change Event w/o Time (Obj:33, Var:06) */
1796           case AL_OBJ_AIFC_FLTT:    /* 32-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:07) */
1797           case AL_OBJ_AIFC_DBLT:    /* 64-Bit Floating Point Frozen Change Event w/ Time (Obj:33, Var:08) */
1798
1799             /* Get Point Flags for those types that have them */
1800             switch (al_obj)
1801             {
1802               case AL_OBJ_AI_32NF:
1803               case AL_OBJ_AI_16NF:
1804                 break;
1805
1806               default:
1807                 al_ptflags = tvb_get_guint8(tvb, data_pos);
1808                 dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_IN);
1809                 data_pos += 1;
1810                 break;
1811             }
1812
1813             switch (al_obj)
1814             {
1815               case AL_OBJ_AI_32:
1816               case AL_OBJ_AI_32NF:
1817               case AL_OBJ_AIC_32NT:
1818               case AL_OBJ_AIC_32T:
1819
1820                 al_val32 = tvb_get_letohl(tvb, data_pos);
1821                 proto_item_append_text(point_item, ", Value: %u", al_val32);
1822                 proto_tree_add_item(point_tree, hf_dnp3_al_ana32, tvb, data_pos, 4, TRUE);
1823                 data_pos += 4;
1824                 break;
1825
1826               case AL_OBJ_AI_16:
1827               case AL_OBJ_AI_16NF:
1828               case AL_OBJ_AIC_16NT:
1829               case AL_OBJ_AIC_16T:
1830
1831                 al_val16 = tvb_get_letohs(tvb, data_pos);
1832                 proto_item_append_text(point_item, ", Value: %u", al_val16);
1833                 proto_tree_add_item(point_tree, hf_dnp3_al_ana16, tvb, data_pos, 2, TRUE);
1834                 data_pos += 2;
1835                 break;
1836
1837               case AL_OBJ_AI_FLT:
1838               case AL_OBJ_AIF_FLT:
1839               case AL_OBJ_AIC_FLTNT:
1840               case AL_OBJ_AIC_FLTT:
1841               case AL_OBJ_AIFC_FLTNT:
1842               case AL_OBJ_AIFC_FLTT:
1843
1844                 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
1845                 proto_item_append_text(point_item, ", Value: %g", al_valflt);
1846                 proto_tree_add_item(point_tree, hf_dnp3_al_anaflt, tvb, data_pos, 4, TRUE);
1847                 data_pos += 4;
1848                 break;
1849
1850               case AL_OBJ_AI_DBL:
1851               case AL_OBJ_AIF_DBL:
1852               case AL_OBJ_AIC_DBLNT:
1853               case AL_OBJ_AIC_DBLT:
1854               case AL_OBJ_AIFC_DBLNT:
1855               case AL_OBJ_AIFC_DBLT:
1856
1857                 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
1858                 proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
1859                 proto_tree_add_item(point_tree, hf_dnp3_al_anadbl, tvb, data_pos, 8, TRUE);
1860                 data_pos += 8;
1861                 break;
1862             }
1863
1864             /* Get timestamp */
1865             switch (al_obj)
1866             {
1867               case AL_OBJ_AIC_32T:
1868               case AL_OBJ_AIC_16T:
1869               case AL_OBJ_AIC_FLTT:
1870               case AL_OBJ_AIC_DBLT:
1871               case AL_OBJ_AIFC_FLTT:
1872               case AL_OBJ_AIFC_DBLT:
1873                 dnp3_al_get_timestamp(&al_abstime, tvb, data_pos);
1874                 proto_item_append_text(point_item, ", Timestamp: %s", abs_time_to_str(&al_abstime));
1875                 proto_tree_add_time(point_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_abstime);
1876                 data_pos += 6;
1877                 break;
1878             }
1879
1880             proto_item_set_len(point_item, data_pos - offset);
1881
1882             offset = data_pos;
1883             break;
1884
1885           case AL_OBJ_AO_32:     /* 32-Bit Analog Output Status (Obj:40, Var:01) */
1886           case AL_OBJ_AO_16:     /* 16-Bit Analog Output Status (Obj:40, Var:02) */
1887           case AL_OBJ_AO_FLT:    /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
1888           case AL_OBJ_AO_DBL:    /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
1889
1890             /* Get Point Flags */
1891             al_ptflags = tvb_get_guint8(tvb, data_pos);
1892             dnp3_al_obj_quality(tvb, data_pos, al_ptflags, point_tree, point_item, ANA_OUT);
1893             data_pos += 1;
1894
1895             switch (al_obj)
1896             {
1897               case AL_OBJ_AO_32:     /* 32-Bit Analog Output Status (Obj:40, Var:01) */
1898
1899                 al_val32 = tvb_get_letohl(tvb, data_pos);
1900                 proto_item_append_text(point_item, ", Value: %u", al_val32);
1901                 proto_tree_add_item(point_tree, hf_dnp3_al_anaout32, tvb, data_pos, 4, TRUE);
1902                 data_pos += 4;
1903                 break;
1904
1905               case AL_OBJ_AO_16:     /* 16-Bit Analog Output Status (Obj:40, Var:02) */
1906
1907                 al_val16 = tvb_get_letohs(tvb, data_pos);
1908                 proto_item_append_text(point_item, ", Value: %u", al_val16);
1909                 proto_tree_add_item(point_tree, hf_dnp3_al_anaout16, tvb, data_pos, 2, TRUE);
1910                 data_pos += 2;
1911                 break;
1912
1913               case AL_OBJ_AO_FLT:     /* 32-Bit Floating Point Output Status (Obj:40, Var:03) */
1914
1915                 al_valflt = tvb_get_letohieee_float(tvb, data_pos);
1916                 proto_item_append_text(point_item, ", Value: %g", al_valflt);
1917                 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutflt, tvb, data_pos, 4, TRUE);
1918                 data_pos += 4;
1919                 break;
1920
1921               case AL_OBJ_AO_DBL:     /* 64-Bit Floating Point Output Status (Obj:40, Var:04) */
1922
1923                 al_valdbl = tvb_get_letohieee_double(tvb, data_pos);
1924                 proto_item_append_text(point_item, ", Value: %lg", al_valdbl);
1925                 proto_tree_add_item(point_tree, hf_dnp3_al_anaoutdbl, tvb, data_pos, 8, TRUE);
1926                 data_pos += 8;
1927                 break;
1928             }
1929
1930             proto_item_set_len(point_item, data_pos - offset);
1931             offset = data_pos;
1932
1933             break;
1934
1935           case AL_OBJ_TD:    /* Time and Date (Obj:50, Var:01) */
1936           case AL_OBJ_TDCTO: /* Time and Date CTO (Obj:51, Var:01) */
1937
1938             dnp3_al_get_timestamp(&al_cto, tvb, data_pos);
1939             proto_tree_add_time(object_tree, hf_dnp3_al_timestamp, tvb, data_pos, 6, &al_cto);
1940             data_pos += 6;
1941             proto_item_set_len(point_item, data_pos - offset);
1942
1943             offset = data_pos;
1944             break;
1945
1946           case AL_OBJ_TDELAYF: /* Time Delay - Fine (Obj:52, Var:02) */
1947
1948             al_val16 = tvb_get_letohs(tvb, data_pos);
1949             proto_tree_add_text(object_tree, tvb, data_pos, 2, "Time Delay: %u ms", al_val16);
1950             data_pos += 2;
1951             proto_item_set_len(point_item, data_pos - offset);
1952
1953             offset = data_pos;
1954             break;
1955
1956           case AL_OBJ_CLASS0:  /* Class Data Objects */
1957           case AL_OBJ_CLASS1:
1958           case AL_OBJ_CLASS2:
1959           case AL_OBJ_CLASS3:
1960
1961             /* No data here */
1962             offset = data_pos;
1963             break;
1964
1965           case AL_OBJ_IIN:     /* IIN Data Object */
1966
1967             /* Single byte of data here */
1968             proto_tree_add_text(object_tree, tvb, data_pos, 1, "Value: %u", tvb_get_guint8(tvb, data_pos));
1969             data_pos += 1;
1970             proto_item_set_len(point_item, data_pos - offset);
1971
1972             offset = data_pos;
1973             break;
1974
1975           default:             /* In case of unknown object */
1976
1977             proto_tree_add_text(object_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
1978               "Unknown Data Chunk, %u Bytes", tvb_reported_length_remaining(tvb, offset));
1979             offset = tvb_length(tvb); /* Finish decoding if unknown object is encountered... */
1980             break;
1981         }
1982         /* Increment the bit index for next time */
1983         bitindex++;
1984
1985         /* And increment the point address, may be overwritten by an index value */
1986         al_ptaddr++;
1987       }
1988     }
1989   }
1990   proto_item_set_len(object_item, offset - orig_offset);
1991
1992   return offset;
1993 }
1994
1995 /*****************************************************************/
1996 /* Application Layer Dissector */
1997 /*****************************************************************/
1998 static int
1999 dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2000 {
2001   guint8        al_ctl, al_seq, al_func, al_class = 0, i;
2002   guint16       bytes, obj_type;
2003   gboolean      al_fir, al_fin, al_con;
2004   guint         data_len = 0, offset = 0;
2005   proto_item   *ti = NULL, *tc, *t_robj;
2006   proto_tree   *al_tree = NULL, *field_tree = NULL, *robj_tree = NULL;
2007   const gchar  *func_code_str;
2008
2009   data_len = tvb_length(tvb);
2010
2011   /* Handle the control byte and function code */
2012   al_ctl = tvb_get_guint8(tvb, offset);
2013   al_seq = al_ctl & DNP3_AL_SEQ;
2014   al_fir = al_ctl & DNP3_AL_FIR;
2015   al_fin = al_ctl & DNP3_AL_FIN;
2016   al_con = al_ctl & DNP3_AL_CON;
2017   al_func = tvb_get_guint8(tvb, (offset+1));
2018   func_code_str = val_to_str(al_func, dnp3_al_func_vals, "Unknown function (0x%02x)");
2019
2020   if (check_col(pinfo->cinfo, COL_INFO))
2021     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s", func_code_str);
2022     col_set_fence(pinfo->cinfo, COL_INFO);
2023
2024   /* format up the text representation */
2025   ti = proto_tree_add_text(tree, tvb, offset, data_len, "Application Layer: (");
2026   if (al_ctl & DNP3_AL_FIR)  proto_item_append_text(ti, "FIR, ");
2027   if (al_ctl & DNP3_AL_FIN)  proto_item_append_text(ti, "FIN, ");
2028   if (al_ctl & DNP3_AL_CON)  proto_item_append_text(ti, "CON, ");
2029   proto_item_append_text(ti, "Sequence %u, %s)", al_seq, func_code_str);
2030
2031   /* Add the al tree branch */
2032   al_tree = proto_item_add_subtree(ti, ett_dnp3_al);
2033
2034   /* Application Layer control byte subtree */
2035   tc = proto_tree_add_uint_format(al_tree, hf_dnp3_al_ctl, tvb, offset, 1, al_ctl,
2036       "Control: 0x%02x (", al_ctl);
2037   if (al_ctl & DNP3_AL_FIR)  proto_item_append_text(tc, "FIR, ");
2038   if (al_ctl & DNP3_AL_FIN)  proto_item_append_text(tc, "FIN, ");
2039   if (al_ctl & DNP3_AL_CON)  proto_item_append_text(tc, "CON, ");
2040   proto_item_append_text(tc, "Sequence %u)", al_seq);
2041
2042   field_tree = proto_item_add_subtree(tc, ett_dnp3_al_ctl);
2043   proto_tree_add_boolean(field_tree, hf_dnp3_al_fir, tvb, offset, 1, al_ctl);
2044   proto_tree_add_boolean(field_tree, hf_dnp3_al_fin, tvb, offset, 1, al_ctl);
2045   proto_tree_add_boolean(field_tree, hf_dnp3_al_con, tvb, offset, 1, al_ctl);
2046   proto_tree_add_item(field_tree, hf_dnp3_al_seq, tvb, offset, 1, FALSE);
2047   offset += 1;
2048
2049   /* If this packet is NOT the final Application Layer Message, exit and continue
2050   processing the remaining data in the fragment.
2051   if (!al_fin)
2052   {
2053   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Buffering User Data Until Final Frame is Received..");
2054   return 1;
2055   } */
2056
2057   /* Application Layer Function Code Byte  */
2058   proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
2059     "Function Code: %s (0x%02x)", func_code_str, al_func);
2060   offset += 1;
2061
2062   switch (al_func) {
2063
2064   case AL_FUNC_READ:     /* Read Function Code 0x01 */
2065
2066   /* Create Read Request Data Objects Tree */
2067   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "READ Request Data Objects");
2068   robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2069
2070   /* Process Data Object Details */
2071   while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
2072     offset = dnp3_al_process_object(tvb, offset, robj_tree, TRUE, &obj_type);
2073
2074     /* Update class type for each object that was a class read */
2075     switch(obj_type) {
2076       case AL_OBJ_CLASS0:
2077       case AL_OBJ_CLASS1:
2078       case AL_OBJ_CLASS2:
2079       case AL_OBJ_CLASS3:
2080         al_class |= (1 << ((obj_type & 0x0f) - 1));
2081         break;
2082       default:
2083         break;
2084     }
2085   }
2086
2087   /* Update the col info if there were class reads */
2088   if (check_col(pinfo->cinfo, COL_INFO) && (al_class > 0)) {
2089     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Class ");
2090     for (i = 0; i < 4; i++) {
2091       if (al_class & (1 << i)) {
2092         col_append_fstr(pinfo->cinfo, COL_INFO, "%u", i);
2093       }
2094     }
2095   }
2096
2097   break;
2098
2099   case AL_FUNC_WRITE:     /* Write Function Code 0x02 */
2100
2101   /* Create Write Request Data Objects Tree */
2102   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "WRITE Request Data Objects");
2103   robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2104
2105   /* Process Data Object Details */
2106   while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
2107     offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE, &obj_type);
2108   }
2109
2110   break;
2111
2112   case AL_FUNC_SELECT:     /* Select Function Code 0x03 */
2113
2114   /* Create Select Request Data Objects Tree */
2115   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "SELECT Request Data Objects");
2116   robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2117
2118   /* Process Data Object Details */
2119   while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
2120     offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE, &obj_type);
2121   }
2122
2123   break;
2124
2125   case AL_FUNC_OPERATE:    /* Operate Function Code 0x04 */
2126              /* Functionally identical to 'SELECT' Function Code */
2127
2128   /* Create Operate Request Data Objects Tree */
2129   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "OPERATE Request Data Objects");
2130   robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2131
2132   /* Process Data Object Details */
2133   while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
2134     offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE, &obj_type);
2135   }
2136
2137   break;
2138
2139   case AL_FUNC_DIROP:     /* Direct Operate Function Code 0x05 */
2140             /* Functionally identical to 'SELECT' Function Code */
2141
2142   /* Create Direct Operate Request Data Objects Tree */
2143   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "DIRECT OPERATE Request Data Objects");
2144   robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2145
2146   /* Process Data Object Details */
2147   while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
2148     offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE, &obj_type);
2149   }
2150
2151   break;
2152
2153   case AL_FUNC_ENSPMSG:   /* Enable Spontaneous Messages Function Code 0x14 */
2154
2155   /* Create Enable Spontaneous Messages Data Objects Tree */
2156   t_robj = proto_tree_add_text(al_tree, tvb, offset, -1, "Enable Spontaneous Msg's Data Objects");
2157   robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2158
2159   /* Process Data Object Details */
2160   while (offset <= (data_len-2))  {  /* 2 octet object code + CRC32 */
2161     offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE, &obj_type);
2162   }
2163
2164   break;
2165
2166   case AL_FUNC_DELAYMST:  /* Delay Measurement Function Code 0x17 */
2167
2168   break;
2169
2170   case AL_FUNC_RESPON:   /* Response Function Code 0x81 */
2171   case AL_FUNC_UNSOLI:   /* Unsolicited Response Function Code 0x82 */
2172
2173   /* Application Layer IIN bits req'd if message is a response */
2174   dnp3_al_process_iin(tvb, offset, al_tree);
2175   offset += 2;
2176
2177   /* Ensure there is actual data remaining in the message.
2178      A response will not contain data following the IIN bits,
2179      if there is none available */
2180   bytes = tvb_reported_length_remaining(tvb, offset);
2181   if (bytes > 0)
2182   {
2183     /* Create Response Data Objects Tree */
2184     t_robj = proto_tree_add_text(al_tree, tvb, offset, -1,"RESPONSE Data Objects");
2185     robj_tree = proto_item_add_subtree(t_robj, ett_dnp3_al_objdet);
2186
2187     /* Process Data Object Details */
2188     while (offset <= (data_len-2)) {  /* 2 octet object code + CRC32 */
2189       offset = dnp3_al_process_object(tvb, offset, robj_tree, FALSE, &obj_type);
2190     }
2191
2192     break;
2193   }
2194
2195   default:    /* Unknown Function */
2196
2197   break;
2198   }
2199
2200   return 0;
2201 }
2202
2203 /*****************************************************************/
2204 /* Data Link and Transport layer dissector */
2205 /*****************************************************************/
2206 static void
2207 dissect_dnp3_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2208 {
2209
2210 /* Set up structures needed to add the protocol subtree and manage it */
2211     proto_item   *ti = NULL, *tdl, *tc, *al_chunks;
2212     proto_tree   *dnp3_tree = NULL, *dl_tree = NULL, *tr_tree = NULL, *field_tree = NULL, *al_tree = NULL;
2213     int           offset = 0, temp_offset = 0, al_result = 0;
2214     gboolean      dl_prm, tr_fir, tr_fin;
2215     guint8        dl_len, dl_ctl, dl_func, tr_ctl, tr_seq;
2216     const gchar  *func_code_str;
2217     guint16       dl_dst, dl_src, dl_crc, calc_dl_crc;
2218     guint8       *tmp = NULL, *tmp_ptr;
2219     guint8        data_len;
2220     int           data_offset;
2221     gboolean      crc_OK = FALSE;
2222     tvbuff_t     *al_tvb = NULL, *next_tvb;
2223     guint         i;
2224     guint         conv_seq_number;
2225     gboolean      save_fragmented;
2226     fragment_data *frag_msg;
2227     gboolean      update_col_info = TRUE;
2228     conversation_t *conversation;
2229     dnp3_conv_t  *conv_data_ptr;
2230
2231
2232
2233 /* Make entries in Protocol column and Info column on summary display */
2234   if (check_col(pinfo->cinfo, COL_PROTOCOL))
2235     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
2236
2237   if (check_col(pinfo->cinfo, COL_INFO))
2238     col_clear(pinfo->cinfo, COL_INFO);
2239
2240   /* Skip "0x0564" header bytes */
2241   temp_offset += 2;
2242
2243   dl_len = tvb_get_guint8(tvb, temp_offset);
2244   temp_offset += 1;
2245
2246   dl_ctl = tvb_get_guint8(tvb, temp_offset);
2247   temp_offset += 1;
2248
2249   dl_dst = tvb_get_letohs(tvb, temp_offset);
2250   temp_offset += 2;
2251
2252   dl_src = tvb_get_letohs(tvb, temp_offset);
2253
2254   dl_func = dl_ctl & DNP3_CTL_FUNC;
2255   dl_prm = dl_ctl & DNP3_CTL_PRM;
2256   func_code_str = val_to_str(dl_func, dl_prm ? dnp3_ctl_func_pri_vals : dnp3_ctl_func_sec_vals,
2257            "Unknown function (0x%02x)");
2258
2259   if (check_col(pinfo->cinfo, COL_INFO))
2260     col_append_fstr(pinfo->cinfo, COL_INFO, "len=%u, from %u to %u, %s",
2261             dl_len, dl_src, dl_dst, func_code_str);
2262
2263   /* create display subtree for the protocol */
2264   ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, FALSE);
2265   dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);
2266
2267   /* Create Subtree for Data Link Layer */
2268   tdl = proto_tree_add_text(dnp3_tree, tvb, offset, DNP_HDR_LEN,
2269         "Data Link Layer, Len: %u, From: %u, To: %u, ", dl_len, dl_src, dl_dst);
2270   if (dl_prm) {
2271     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
2272     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
2273     if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tdl, "FCB, ");
2274     if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tdl, "FCV, ");
2275   }
2276   else {
2277     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tdl, "DIR, ");
2278     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tdl, "PRM, ");
2279     if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tdl, "RES, ");
2280     if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tdl, "DFC, ");
2281   }
2282   proto_item_append_text(tdl, func_code_str);
2283   dl_tree = proto_item_add_subtree(tdl, ett_dnp3_dl);
2284
2285   /* start bytes */
2286   proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, FALSE);
2287   offset += 2;
2288
2289   /* add length field */
2290   proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, FALSE);
2291   offset += 1;
2292
2293   /* Add Control Byte Subtree */
2294   tc = proto_tree_add_uint_format(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
2295           "Control: 0x%02x (", dl_ctl);
2296   /* Add Text to Control Byte Subtree Header */
2297   if (dl_prm) {
2298     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
2299     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
2300     if (dl_ctl & DNP3_CTL_FCB) proto_item_append_text(tc, "FCB, ");
2301     if (dl_ctl & DNP3_CTL_FCV) proto_item_append_text(tc, "FCV, ");
2302   }
2303   else {
2304     if (dl_ctl & DNP3_CTL_DIR) proto_item_append_text(tc, "DIR, ");
2305     if (dl_ctl & DNP3_CTL_PRM) proto_item_append_text(tc, "PRM, ");
2306     if (dl_ctl & DNP3_CTL_RES) proto_item_append_text(tc, "RES, ");
2307     if (dl_ctl & DNP3_CTL_DFC) proto_item_append_text(tc, "DFC, ");
2308   }
2309   proto_item_append_text(tc, "%s)", func_code_str );
2310   field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);
2311
2312   /* Add Control Byte Subtree Items */
2313   if (dl_prm) {
2314     proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, TRUE);
2315     proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, TRUE);
2316     proto_tree_add_item(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, TRUE);
2317     proto_tree_add_item(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, TRUE);
2318     proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, FALSE);
2319   }
2320   else {
2321     proto_tree_add_item(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, TRUE);
2322     proto_tree_add_item(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, TRUE);
2323     proto_tree_add_item(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, TRUE);
2324     proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, FALSE);
2325   }
2326     offset += 1;
2327
2328   /* add destination and source addresses */
2329   proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, TRUE);
2330   offset += 2;
2331   proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, TRUE);
2332   offset += 2;
2333
2334   /* and header CRC */
2335   dl_crc = tvb_get_letohs(tvb, offset);
2336   calc_dl_crc = calculateCRC(tvb_get_ptr(tvb, 0, DNP_HDR_LEN - 2), DNP_HDR_LEN - 2);
2337   if (dl_crc == calc_dl_crc)
2338     proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
2339              dl_crc, "CRC: 0x%04x [correct]", dl_crc);
2340   else
2341   {
2342     proto_tree_add_boolean_hidden(dl_tree, hf_dnp_hdr_CRC_bad, tvb,
2343                 offset, 2, TRUE);
2344     proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb,
2345              offset, 2, dl_crc, "CRC: 0x%04x [incorrect, should be 0x%04x]",
2346                    dl_crc, calc_dl_crc);
2347   }
2348   offset += 2;
2349
2350   /* If the DataLink function is 'Request Link Status' or 'Status of Link',
2351      or 'Reset Link' we don't expect any Transport or Application Layer Data
2352      NOTE: This code should probably check what DOES have TR or AL data */
2353   if ((dl_func != DL_FUNC_LINK_STAT) && (dl_func != DL_FUNC_STAT_LINK) &&
2354       (dl_func != DL_FUNC_RESET_LINK) && (dl_func != DL_FUNC_ACK))
2355   {
2356
2357     /* get the transport layer byte */
2358     tr_ctl = tvb_get_guint8(tvb, offset);
2359     tr_seq = tr_ctl & DNP3_TR_SEQ;
2360     tr_fir = tr_ctl & DNP3_TR_FIR;
2361     tr_fin = tr_ctl & DNP3_TR_FIN;
2362
2363     /* Add Transport Layer Tree */
2364     tc = proto_tree_add_uint_format(dnp3_tree, hf_dnp3_tr_ctl, tvb, offset, 1, tr_ctl,
2365             "Transport Layer: 0x%02x (", tr_ctl);
2366     if (tr_fir) proto_item_append_text(tc, "FIR, ");
2367     if (tr_fin) proto_item_append_text(tc, "FIN, ");
2368     proto_item_append_text(tc, "Sequence %u)", tr_seq);
2369
2370     tr_tree = proto_item_add_subtree(tc, ett_dnp3_tr_ctl);
2371     proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fin, tvb, offset, 1, tr_ctl);
2372     proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fir, tvb, offset, 1, tr_ctl);
2373     proto_tree_add_item(tr_tree, hf_dnp3_tr_seq, tvb, offset, 1, FALSE);
2374
2375     /* Allocate AL chunk tree */
2376     al_chunks = proto_tree_add_text(tr_tree, tvb, offset + 1, -1, "Application data chunks");
2377     al_tree = proto_item_add_subtree(al_chunks, ett_dnp3_al_data);
2378
2379     /* extract the application layer data, validating the CRCs */
2380
2381     /* XXX - check for dl_len <= 5 */
2382     data_len = dl_len - 5;
2383     tmp = ep_alloc(data_len);
2384     tmp_ptr = tmp;
2385     i = 0;
2386     data_offset = 1;  /* skip the transport layer byte when assembling chunks */
2387     while(data_len > 0)
2388     {
2389       guint8 chk_size;
2390       const guint8 *chk_ptr;
2391       guint16 calc_crc, act_crc;
2392
2393       chk_size = MIN(data_len, AL_MAX_CHUNK_SIZE);
2394       chk_ptr = tvb_get_ptr(tvb, offset, chk_size);
2395       memcpy(tmp_ptr, chk_ptr + data_offset, chk_size - data_offset);
2396       calc_crc = calculateCRC(chk_ptr, chk_size);
2397       offset += chk_size;
2398       tmp_ptr += chk_size - data_offset;
2399       act_crc = tvb_get_letohs(tvb, offset);
2400       offset += 2;
2401       crc_OK = calc_crc == act_crc;
2402       if (crc_OK)
2403       {
2404                 proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
2405                           "Application Chunk %u Len: %u CRC 0x%04x",
2406                           i, chk_size, act_crc);
2407         data_len -= chk_size;
2408       }
2409       else
2410       {
2411         proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size + 2,
2412                 "Application Chunk %u Len: %u Bad CRC got 0x%04x expected 0x%04x",
2413                 i, chk_size, act_crc, calc_crc);
2414         data_len = 0;
2415         break;
2416       }
2417       i++;
2418       data_offset = 0;  /* copy all of the rest of the chunks */
2419     }
2420
2421     /* if all crc OK, set up new tvb */
2422     if (crc_OK)
2423     {
2424       al_tvb = tvb_new_real_data(tmp, tmp_ptr-tmp, tmp_ptr-tmp);
2425       tvb_set_child_real_data_tvbuff(tvb, al_tvb);
2426
2427       /* Check for fragmented packet */
2428       save_fragmented = pinfo->fragmented;
2429       if (! (tr_fir && tr_fin))
2430       {
2431         /* A fragmented packet */
2432         pinfo->fragmented = TRUE;
2433
2434         /* Look up the conversation to get the fragment reassembly id */
2435         conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
2436           pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
2437
2438         if (conversation == NULL) {
2439           /* No conversation yet, so make one */
2440           conversation = conversation_new(pinfo->fd->num,  &pinfo->src, &pinfo->dst, pinfo->ptype,
2441             pinfo->srcport, pinfo->destport, 0);
2442         }
2443
2444         conv_data_ptr = (dnp3_conv_t*)conversation_get_proto_data(conversation, proto_dnp3);
2445
2446         if (conv_data_ptr == NULL) {
2447           /* New data structure required */
2448           conv_data_ptr = se_alloc(sizeof(dnp3_conv_t));
2449
2450           /*** Increment static global fragment reassembly id ***/
2451           conv_data_ptr->conv_seq_number = seq_number++;
2452
2453           conversation_add_proto_data(conversation, proto_dnp3, (void *)conv_data_ptr);
2454         }
2455         conv_seq_number = conv_data_ptr->conv_seq_number;
2456
2457         /*
2458         * Add the frame to
2459         * whatever reassembly is in progress, if any, and see
2460         * if it's done.
2461         */
2462         frag_msg = fragment_add_seq_check(al_tvb, 0, pinfo, conv_seq_number,
2463                          al_fragment_table,
2464                          al_reassembled_table,
2465                          tr_seq,
2466                          tvb_reported_length(al_tvb), /* As this is a constructed tvb, all of it is ok */
2467                          !tr_fin);
2468
2469         next_tvb = process_reassembled_data(al_tvb, 0, pinfo,
2470             "Reassembled DNP 3.0 Application Layer message", frag_msg, &dnp3_frag_items,
2471             &update_col_info, tr_tree);
2472
2473         if (next_tvb) { /* Reassembled */
2474           /* We have the complete payload */
2475           if (check_col (pinfo->cinfo, COL_INFO))
2476             col_add_str (pinfo->cinfo, COL_INFO,
2477                 "Reassembled Application Layer");
2478             col_set_fence(pinfo->cinfo, COL_INFO);
2479         }
2480         else
2481         {
2482           /* We don't have the complete reassembled payload. */
2483           if (check_col (pinfo->cinfo, COL_INFO))
2484             col_add_fstr (pinfo->cinfo, COL_INFO,
2485                 "Application Layer fragment %u", tr_seq);
2486             col_set_fence(pinfo->cinfo, COL_INFO);
2487         }
2488
2489       }
2490       else
2491       {
2492         /* No reassembly required */
2493         next_tvb = al_tvb;
2494         add_new_data_source(pinfo, next_tvb, "DNP 3.0 Application Layer message");
2495         if (check_col (pinfo->cinfo, COL_INFO))
2496           col_clear (pinfo->cinfo, COL_INFO);
2497       }
2498       pinfo->fragmented = save_fragmented;
2499     }
2500     else
2501     {
2502       /* CRC error - throw away the data. */
2503       next_tvb = NULL;
2504       proto_tree_add_text(dnp3_tree, tvb, 11, -1, "CRC failed, %u chunks", i);
2505     }
2506
2507     if (next_tvb)
2508     {
2509       al_result = dissect_dnp3_al(next_tvb, pinfo, dnp3_tree);
2510     }
2511   }
2512 }
2513
2514 static guint
2515 get_dnp3_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
2516 {
2517   guint16 message_len;  /* need 16 bits as total can exceed 255 */
2518   guint16 data_crc;     /* No. of user data CRC bytes */
2519   message_len = tvb_get_guint8(tvb, offset + 2);
2520
2521   /* Add in 2 bytes for header start octets,
2522             1 byte for len itself,
2523             2 bytes for header CRC
2524             data CRC bytes (2 bytes per 16 bytes of data
2525   */
2526
2527   data_crc = (guint16)(ceil((message_len - 5) / 16.0)) * 2;
2528   message_len += 2 + 1 + 2 + data_crc;
2529   return message_len;
2530 }
2531
2532 static int
2533 dissect_dnp3_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2534 {
2535   gint length = tvb_length_remaining(tvb, 0);
2536
2537   /* Check for a dnp packet.  It should begin with 0x0564 */
2538   if(length < DNP_HDR_LEN || tvb_get_ntohs(tvb, 0) != 0x0564) {
2539     /* Not a DNP 3.0 packet, just happened to use the same port */
2540     return 0;
2541   }
2542
2543   tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DNP_HDR_LEN,
2544                    get_dnp3_message_len, dissect_dnp3_message);
2545
2546   return tvb_length(tvb);
2547 }
2548
2549 static int
2550 dissect_dnp3_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2551 {
2552   gint length = tvb_length_remaining(tvb, 0);
2553   /* Check for a dnp packet.  It should begin with 0x0564 */
2554   if(length < DNP_HDR_LEN || tvb_get_ntohs(tvb, 0) != 0x0564) {
2555     /* Not a DNP 3.0 packet, just happened to use the same port */
2556     return 0;
2557   }
2558
2559   dissect_dnp3_message(tvb, pinfo, tree);
2560   return length;
2561 }
2562
2563 static void
2564 dnp3_init(void)
2565 {
2566 }
2567
2568 static void
2569 al_defragment_init(void)
2570 {
2571   fragment_table_init(&al_fragment_table);
2572   reassembled_table_init(&al_reassembled_table);
2573 }
2574
2575 /* Register the protocol with Wireshark */
2576
2577 void
2578 proto_register_dnp3(void)
2579 {
2580
2581 /* Setup list of header fields */
2582   static hf_register_info hf[] = {
2583     { &hf_dnp3_start,
2584     { "Start Bytes", "dnp3.start", FT_UINT16, BASE_HEX, NULL, 0x0, "Start Bytes", HFILL }},
2585
2586     { &hf_dnp3_len,
2587     { "Length", "dnp3.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Frame Data Length", HFILL }},
2588
2589     { &hf_dnp3_ctl,
2590     { "Control", "dnp3.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Frame Control Byte", HFILL }},
2591
2592     { &hf_dnp3_ctl_prifunc,
2593     { "Control Function Code", "dnp3.ctl.prifunc", FT_UINT8, BASE_DEC,
2594       VALS(dnp3_ctl_func_pri_vals), DNP3_CTL_FUNC, "Frame Control Function Code", HFILL }},
2595
2596     { &hf_dnp3_ctl_secfunc,
2597     { "Control Function Code", "dnp3.ctl.secfunc", FT_UINT8, BASE_DEC,
2598       VALS(dnp3_ctl_func_sec_vals), DNP3_CTL_FUNC, "Frame Control Function Code", HFILL }},
2599
2600     { &hf_dnp3_ctl_dir,
2601     { "Direction", "dnp3.ctl.dir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DIR, "", HFILL }},
2602
2603     { &hf_dnp3_ctl_prm,
2604     { "Primary", "dnp3.ctl.prm", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_PRM, "", HFILL }},
2605
2606     { &hf_dnp3_ctl_fcb,
2607     { "Frame Count Bit", "dnp3.ctl.fcb", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCB, "", HFILL }},
2608
2609     { &hf_dnp3_ctl_fcv,
2610     { "Frame Count Valid", "dnp3.ctl.fcv", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_FCV, "", HFILL }},
2611
2612     { &hf_dnp3_ctl_dfc,
2613     { "Data Flow Control", "dnp3.ctl.dfc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_CTL_DFC, "", HFILL }},
2614
2615     { &hf_dnp3_dst,
2616     { "Destination", "dnp3.dst", FT_UINT16, BASE_DEC, NULL, 0x0, "Destination Address", HFILL }},
2617
2618     { &hf_dnp3_src,
2619     { "Source", "dnp3.src", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Address", HFILL }},
2620
2621     { &hf_dnp_hdr_CRC,
2622     { "CRC", "dnp3.hdr.CRC", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
2623
2624     { &hf_dnp_hdr_CRC_bad,
2625     { "Bad CRC", "dnp3.hdr.CRC_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2626
2627     { &hf_dnp3_tr_ctl,
2628     { "Transport Control", "dnp3.tr.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Tranport Layer Control Byte", HFILL }},
2629
2630     { &hf_dnp3_tr_fin,
2631     { "Final", "dnp3.tr.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIN, "", HFILL }},
2632
2633     { &hf_dnp3_tr_fir,
2634     { "First", "dnp3.tr.fir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_TR_FIR, "", HFILL }},
2635
2636     { &hf_dnp3_tr_seq,
2637     { "Sequence", "dnp3.tr.seq", FT_UINT8, BASE_DEC, NULL, DNP3_TR_SEQ, "Frame Sequence Number", HFILL }},
2638
2639     { &hf_dnp3_al_ctl,
2640     { "Application Control", "dnp3.al.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Application Layer Control Byte", HFILL }},
2641
2642     { &hf_dnp3_al_fir,
2643     { "First", "dnp3.al.fir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIR, "", HFILL }},
2644
2645     { &hf_dnp3_al_fin,
2646     { "Final", "dnp3.al.fin", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_FIN, "", HFILL }},
2647
2648     { &hf_dnp3_al_con,
2649     { "Confirm", "dnp3.al.con", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DNP3_AL_CON, "", HFILL }},
2650
2651     { &hf_dnp3_al_seq,
2652     { "Sequence", "dnp3.al.seq", FT_UINT8, BASE_DEC, NULL, DNP3_AL_SEQ, "Frame Sequence Number", HFILL }},
2653
2654     { &hf_dnp3_al_func,
2655     { "Application Layer Function Code", "dnp3.al.func", FT_UINT8, BASE_DEC,
2656       VALS(dnp3_al_func_vals), DNP3_AL_FUNC, "Application Function Code", HFILL }},
2657
2658     { &hf_dnp3_al_iin,
2659     { "Application Layer IIN bits", "dnp3.al.iin", FT_UINT16, BASE_DEC, NULL, 0x0, "Application Layer IIN", HFILL }},
2660
2661     { &hf_dnp3_al_iin_bmsg,
2662     { "Broadcast Msg Rx", "dnp3.al.iin.bmsg", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_BMSG, "", HFILL }},
2663
2664     { &hf_dnp3_al_iin_cls1d,
2665     { "Class 1 Data Available", "dnp3.al.iin.cls1d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS1D, "", HFILL }},
2666
2667     { &hf_dnp3_al_iin_cls2d,
2668     { "Class 2 Data Available", "dnp3.al.iin.cls2d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS2D, "", HFILL }},
2669
2670     { &hf_dnp3_al_iin_cls3d,
2671     { "Class 3 Data Available", "dnp3.al.iin.cls3d", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CLS3D, "", HFILL }},
2672
2673     { &hf_dnp3_al_iin_tsr,
2674     { "Time Sync Required", "dnp3.al.iin.tsr", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_TSR, "", HFILL }},
2675
2676     { &hf_dnp3_al_iin_dol,
2677     { "Digital Outputs in Local", "dnp3.al.iin.dol", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DOL, "", HFILL }},
2678
2679     { &hf_dnp3_al_iin_dt,
2680     { "Device Trouble", "dnp3.al.iin.dt", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_DT, "", HFILL }},
2681
2682     { &hf_dnp3_al_iin_rst,
2683     { "Device Restart", "dnp3.al.iin.rst", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_RST, "", HFILL }},
2684
2685     { &hf_dnp3_al_iin_obju,
2686     { "Requested Objects Unknown", "dnp3.al.iin.obju", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OBJU, "", HFILL }},
2687
2688     { &hf_dnp3_al_iin_pioor,
2689     { "Parameters Invalid or Out of Range", "dnp3.al.iin.pioor", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_PIOOR, "", HFILL }},
2690
2691     { &hf_dnp3_al_iin_ebo,
2692     { "Event Buffer Overflow", "dnp3.al.iin.ebo", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_EBO, "", HFILL }},
2693
2694     { &hf_dnp3_al_iin_oae,
2695     { "Operation Already Executing", "dnp3.al.iin.oae", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_OAE, "", HFILL }},
2696
2697     { &hf_dnp3_al_iin_cc,
2698     { "Configuration Corrupt", "dnp3.al.iin.cc", FT_BOOLEAN, 16, TFS(&tfs_set_notset), AL_IIN_CC, "", HFILL }},
2699
2700     { &hf_dnp3_al_obj,
2701     { "Object", "dnp3.al.obj", FT_UINT16, BASE_HEX, VALS(dnp3_al_obj_vals), 0x0, "Application Layer Object", HFILL }},
2702
2703     { &hf_dnp3_al_objq_index,
2704     { "Index Prefix", "dnp3.al.objq.index", FT_UINT8, BASE_DEC, VALS(dnp3_al_objq_index_vals), AL_OBJQ_INDEX, "Object Index Prefixing", HFILL }},
2705
2706     { &hf_dnp3_al_objq_code,
2707     { "Qualifier Code", "dnp3.al.objq.code", FT_UINT8, BASE_DEC, VALS(dnp3_al_objq_code_vals), AL_OBJQ_CODE, "Object Qualifier Code", HFILL }},
2708
2709     { &hf_dnp3_al_range_start8,
2710     { "Start (8 bit)", "dnp3.al.range.start", FT_UINT8, BASE_DEC, NULL, 0x0, "Object Start Index", HFILL }},
2711
2712     { &hf_dnp3_al_range_stop8,
2713     { "Stop (8 bit)", "dnp3.al.range.stop", FT_UINT8, BASE_DEC, NULL, 0x0, "Object Stop Index", HFILL }},
2714
2715     { &hf_dnp3_al_range_start16,
2716     { "Start (16 bit)", "dnp3.al.range.start", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Start Index", HFILL }},
2717
2718     { &hf_dnp3_al_range_stop16,
2719     { "Stop (16 bit)", "dnp3.al.range.stop", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Stop Index", HFILL }},
2720
2721     { &hf_dnp3_al_range_start32,
2722     { "Start (32 bit)", "dnp3.al.range.start", FT_UINT32, BASE_DEC, NULL, 0x0, "Object Start Index", HFILL }},
2723
2724     { &hf_dnp3_al_range_stop32,
2725     { "Stop (32 bit)", "dnp3.al.range.stop", FT_UINT32, BASE_DEC, NULL, 0x0, "Object Stop Index", HFILL }},
2726
2727     { &hf_dnp3_al_range_abs8,
2728     { "Address (8 bit)", "dnp3.al.range.abs", FT_UINT8, BASE_DEC, NULL, 0x0, "Object Absolute Address", HFILL }},
2729
2730     { &hf_dnp3_al_range_abs16,
2731     { "Address (16 bit)", "dnp3.al.range.abs", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Absolute Address", HFILL }},
2732
2733     { &hf_dnp3_al_range_abs32,
2734     { "Address (32 bit)", "dnp3.al.range.abs", FT_UINT32, BASE_DEC, NULL, 0x0, "Object Absolute Address", HFILL }},
2735
2736     { &hf_dnp3_al_range_quant8,
2737     { "Quantity (8 bit)", "dnp3.al.range.quantity", FT_UINT8, BASE_DEC, NULL, 0x0, "Object Quantity", HFILL }},
2738
2739     { &hf_dnp3_al_range_quant16,
2740     { "Quantity (16 bit)", "dnp3.al.range.quantity", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Quantity", HFILL }},
2741
2742     { &hf_dnp3_al_range_quant32,
2743     { "Quantity (32 bit)", "dnp3.al.range.quantity", FT_UINT32, BASE_DEC, NULL, 0x0, "Object Quantity", HFILL }},
2744
2745     { &hf_dnp3_al_index8,
2746     { "Index (8 bit)", "dnp3.al.index", FT_UINT8, BASE_DEC, NULL, 0x0, "Object Index", HFILL }},
2747
2748     { &hf_dnp3_al_index16,
2749     { "Index (16 bit)", "dnp3.al.index", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Index", HFILL }},
2750
2751     { &hf_dnp3_al_index32,
2752     { "Index (32 bit)", "dnp3.al.index", FT_UINT32, BASE_DEC, NULL, 0x0, "Object Index", HFILL }},
2753
2754     { &hf_dnp3_al_ptnum,
2755     { "Object Point Number", "dnp3.al.ptnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Object Point Number", HFILL }},
2756
2757     { &hf_dnp3_al_bit,
2758     { "Value (bit)", "dnp3.al.bit", FT_BOOLEAN, BASE_NONE, TFS(&tfs_on_off), 0x1, "Digital Value (1 bit)", HFILL }},
2759
2760     { &hf_dnp3_al_2bit,
2761     { "Value (two bit)", "dnp3.al.2bit", FT_UINT8, BASE_DEC, NULL, 0x0, "Digital Value (2 bit)", HFILL }},
2762
2763     { &hf_dnp3_al_ana16,
2764     { "Value (16 bit)", "dnp3.al.ana", FT_UINT16, BASE_DEC, NULL, 0x0, "Analog Value (16 bit)", HFILL }},
2765
2766     { &hf_dnp3_al_ana32,
2767     { "Value (32 bit)", "dnp3.al.ana", FT_UINT32, BASE_DEC, NULL, 0x0, "Analog Value (32 bit)", HFILL }},
2768
2769     { &hf_dnp3_al_anaflt,
2770     { "Value (float)", "dnp3.al.ana", FT_FLOAT, BASE_DEC, NULL, 0x0, "Analog Value (float)", HFILL }},
2771
2772     { &hf_dnp3_al_anadbl,
2773     { "Value (double)", "dnp3.al.ana", FT_DOUBLE, BASE_DEC, NULL, 0x0, "Analog Value (double)", HFILL }},
2774
2775     { &hf_dnp3_al_anaout16,
2776     { "Output Value (16 bit)", "dnp3.al.anaout", FT_UINT16, BASE_DEC, NULL, 0x0, "Output Value (16 bit)", HFILL }},
2777
2778     { &hf_dnp3_al_anaout32,
2779     { "Output Value (32 bit)", "dnp3.al.anaout", FT_UINT32, BASE_DEC, NULL, 0x0, "Output Value (32 bit)", HFILL }},
2780
2781     { &hf_dnp3_al_anaoutflt,
2782     { "Output Value (float)", "dnp3.al.anaout", FT_FLOAT, BASE_DEC, NULL, 0x0, "Output Value (float)", HFILL }},
2783
2784     { &hf_dnp3_al_anaoutdbl,
2785     { "Output (double)", "dnp3.al.anaout", FT_DOUBLE, BASE_DEC, NULL, 0x0, "Output Value (double)", HFILL }},
2786
2787     { &hf_dnp3_al_cnt16,
2788     { "Counter (16 bit)", "dnp3.al.cnt", FT_UINT16, BASE_DEC, NULL, 0x0, "Counter Value (16 bit)", HFILL }},
2789
2790     { &hf_dnp3_al_cnt32,
2791     { "Counter (32 bit)", "dnp3.al.cnt", FT_UINT32, BASE_DEC, NULL, 0x0, "Counter Value (32 bit)", HFILL }},
2792
2793     { &hf_dnp3_al_ctrlstatus,
2794     { "Control Status", "dnp3.al.ctrlstatus", FT_UINT8, BASE_DEC, dnp3_al_ctl_status_vals, 0xff, "Control Status", HFILL }},
2795
2796     { &hf_dnp3_al_biq_b0,
2797     { "Online", "dnp3.al.biq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG0, "", HFILL }},
2798
2799     { &hf_dnp3_al_biq_b1,
2800     { "Restart", "dnp3.al.biq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG1, "", HFILL }},
2801
2802     { &hf_dnp3_al_biq_b2,
2803     { "Comm Fail", "dnp3.al.biq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG2, "", HFILL }},
2804
2805     { &hf_dnp3_al_biq_b3,
2806     { "Remote Force", "dnp3.al.biq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG3, "", HFILL }},
2807
2808     { &hf_dnp3_al_biq_b4,
2809     { "Local Force", "dnp3.al.biq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG4, "", HFILL }},
2810
2811     { &hf_dnp3_al_biq_b5,
2812     { "Chatter Filter", "dnp3.al.biq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG5, "", HFILL }},
2813
2814     { &hf_dnp3_al_biq_b6,
2815     { "Reserved", "dnp3.al.biq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG6, "", HFILL }},
2816
2817     { &hf_dnp3_al_biq_b7,
2818     { "Point Value", "dnp3.al.biq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BI_FLAG7, "", HFILL }},
2819
2820     { &hf_dnp3_al_boq_b0,
2821     { "Online", "dnp3.al.boq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG0, "", HFILL }},
2822
2823     { &hf_dnp3_al_boq_b1,
2824     { "Restart", "dnp3.al.boq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG1, "", HFILL }},
2825
2826     { &hf_dnp3_al_boq_b2,
2827     { "Comm Fail", "dnp3.al.boq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG2, "", HFILL }},
2828
2829     { &hf_dnp3_al_boq_b3,
2830     { "Remote Force", "dnp3.al.boq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG3, "", HFILL }},
2831
2832     { &hf_dnp3_al_boq_b4,
2833     { "Local Force", "dnp3.al.boq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG4, "", HFILL }},
2834
2835     { &hf_dnp3_al_boq_b5,
2836     { "Reserved", "dnp3.al.boq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG5, "", HFILL }},
2837
2838     { &hf_dnp3_al_boq_b6,
2839     { "Reserved", "dnp3.al.boq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG6, "", HFILL }},
2840
2841     { &hf_dnp3_al_boq_b7,
2842     { "Point Value", "dnp3.al.boq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_BO_FLAG7, "", HFILL }},
2843
2844     { &hf_dnp3_al_ctrq_b0,
2845     { "Online", "dnp3.al.ctrq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG0, "", HFILL }},
2846
2847     { &hf_dnp3_al_ctrq_b1,
2848     { "Restart", "dnp3.al.ctrq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG1, "", HFILL }},
2849
2850     { &hf_dnp3_al_ctrq_b2,
2851     { "Comm Fail", "dnp3.al.ctrq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG2, "", HFILL }},
2852
2853     { &hf_dnp3_al_ctrq_b3,
2854     { "Remote Force", "dnp3.al.ctrq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG3, "", HFILL }},
2855
2856     { &hf_dnp3_al_ctrq_b4,
2857     { "Local Force", "dnp3.al.ctrq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG4, "", HFILL }},
2858
2859     { &hf_dnp3_al_ctrq_b5,
2860     { "Roll-Over", "dnp3.al.ctrq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG5, "", HFILL }},
2861
2862     { &hf_dnp3_al_ctrq_b6,
2863     { "Discontinuity", "dnp3.al.ctrq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG6, "", HFILL }},
2864
2865     { &hf_dnp3_al_ctrq_b7,
2866     { "Reserved", "dnp3.al.ctrq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_CTR_FLAG7, "", HFILL }},
2867
2868     { &hf_dnp3_al_aiq_b0,
2869     { "Online", "dnp3.al.aiq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG0, "", HFILL }},
2870
2871     { &hf_dnp3_al_aiq_b1,
2872     { "Restart", "dnp3.al.aiq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG1, "", HFILL }},
2873
2874     { &hf_dnp3_al_aiq_b2,
2875     { "Comm Fail", "dnp3.al.aiq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG2, "", HFILL }},
2876
2877     { &hf_dnp3_al_aiq_b3,
2878     { "Remote Force", "dnp3.al.aiq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG3, "", HFILL }},
2879
2880     { &hf_dnp3_al_aiq_b4,
2881     { "Local Force", "dnp3.al.aiq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG4, "", HFILL }},
2882
2883     { &hf_dnp3_al_aiq_b5,
2884     { "Over-Range", "dnp3.al.aiq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG5, "", HFILL }},
2885
2886     { &hf_dnp3_al_aiq_b6,
2887     { "Reference Check", "dnp3.al.aiq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG6, "", HFILL }},
2888
2889     { &hf_dnp3_al_aiq_b7,
2890     { "Reserved", "dnp3.al.aiq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AI_FLAG7, "", HFILL }},
2891
2892     { &hf_dnp3_al_aoq_b0,
2893     { "Online", "dnp3.al.aoq.b0", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG0, "", HFILL }},
2894
2895     { &hf_dnp3_al_aoq_b1,
2896     { "Restart", "dnp3.al.aoq.b1", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG1, "", HFILL }},
2897
2898     { &hf_dnp3_al_aoq_b2,
2899     { "Comm Fail", "dnp3.al.aoq.b2", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG2, "", HFILL }},
2900
2901     { &hf_dnp3_al_aoq_b3,
2902     { "Remote Force", "dnp3.al.aoq.b3", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG3, "", HFILL }},
2903
2904     { &hf_dnp3_al_aoq_b4,
2905     { "Local Force", "dnp3.al.aoq.b4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG4, "", HFILL }},
2906
2907     { &hf_dnp3_al_aoq_b5,
2908     { "Reserved", "dnp3.al.aoq.b5", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG5, "", HFILL }},
2909
2910     { &hf_dnp3_al_aoq_b6,
2911     { "Reserved", "dnp3.al.aoq.b6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG6, "", HFILL }},
2912
2913     { &hf_dnp3_al_aoq_b7,
2914     { "Reserved", "dnp3.al.aoq.b7", FT_BOOLEAN, 8, TFS(&tfs_set_notset), AL_OBJ_AO_FLAG7, "", HFILL }},
2915
2916     { &hf_dnp3_al_timestamp,
2917     { "Timestamp", "dnp3.al.timestamp", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0, "Object Timestamp", HFILL }},
2918
2919     { &hf_dnp3_al_rel_timestamp,
2920     { "Relative Timestamp", "dnp3.al.reltimestamp", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "Object Relative Timestamp", HFILL }},
2921
2922     { &hf_dnp3_fragment,
2923     { "DNP 3.0 AL Fragment", "dnp3.al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragment", HFILL }},
2924
2925     { &hf_dnp3_fragments,
2926     { "DNP 3.0 AL Fragments", "dnp3.al.fragments", FT_NONE, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragments", HFILL }},
2927
2928     { &hf_dnp3_fragment_overlap,
2929     { "Fragment overlap", "dnp3.al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
2930
2931     { &hf_dnp3_fragment_overlap_conflict,
2932     { "Conflicting data in fragment overlap", "dnp3.al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2933       "Overlapping fragments contained conflicting data", HFILL }},
2934
2935     { &hf_dnp3_fragment_multiple_tails,
2936     { "Multiple tail fragments found", "dnp3.al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2937       "Several tails were found when defragmenting the packet", HFILL }},
2938
2939     { &hf_dnp3_fragment_too_long_fragment,
2940     { "Fragment too long", "dnp3.al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2941       "Fragment contained data past end of packet", HFILL }},
2942
2943     { &hf_dnp3_fragment_error,
2944     { "Defragmentation error", "dnp3.al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2945       "Defragmentation error due to illegal fragments", HFILL }},
2946
2947     { &hf_dnp3_fragment_reassembled_in,
2948     { "Reassembled PDU In Frame", "dnp3.al.fragment.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2949       "This PDU is reassembled in this frame", HFILL }}
2950   };
2951
2952 /* Setup protocol subtree array */
2953   static gint *ett[] = {
2954     &ett_dnp3,
2955     &ett_dnp3_dl,
2956     &ett_dnp3_dl_ctl,
2957     &ett_dnp3_tr_ctl,
2958     &ett_dnp3_al_data,
2959     &ett_dnp3_al,
2960     &ett_dnp3_al_ctl,
2961     &ett_dnp3_al_iin,
2962     &ett_dnp3_al_obj,
2963     &ett_dnp3_al_obj_qualifier,
2964     &ett_dnp3_al_obj_range,
2965     &ett_dnp3_al_objdet,
2966     &ett_dnp3_al_obj_quality,
2967     &ett_dnp3_al_obj_point,
2968     &ett_dnp3_fragment,
2969     &ett_dnp3_fragments
2970   };
2971   module_t *dnp3_module;
2972
2973 /* Register protocol init routine */
2974   register_init_routine(&dnp3_init);
2975
2976 /* Register the protocol name and description */
2977   proto_dnp3 = proto_register_protocol("Distributed Network Protocol 3.0",
2978                    "DNP 3.0", "dnp3");
2979
2980 /* Required function calls to register the header fields and subtrees used */
2981   proto_register_field_array(proto_dnp3, hf, array_length(hf));
2982   proto_register_subtree_array(ett, array_length(ett));
2983
2984   dnp3_module = prefs_register_protocol(proto_dnp3, NULL);
2985   prefs_register_bool_preference(dnp3_module, "desegment",
2986     "Reassemble DNP3 messages spanning multiple TCP segments",
2987     "Whether the DNP3 dissector should reassemble messages spanning multiple TCP segments."
2988     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2989     &dnp3_desegment);
2990
2991   al_defragment_init();
2992 }
2993
2994
2995 /* If this dissector uses sub-dissector registration add a registration routine.
2996    This format is required because a script is used to find these routines and
2997    create the code that calls these routines.
2998 */
2999 void
3000 proto_reg_handoff_dnp3(void)
3001 {
3002   dissector_handle_t dnp3_tcp_handle;
3003   dissector_handle_t dnp3_udp_handle;
3004
3005   dnp3_tcp_handle = new_create_dissector_handle(dissect_dnp3_tcp, proto_dnp3);
3006   dnp3_udp_handle = new_create_dissector_handle(dissect_dnp3_udp, proto_dnp3);
3007   dissector_add("tcp.port", TCP_PORT_DNP, dnp3_tcp_handle);
3008   dissector_add("udp.port", UDP_PORT_DNP, dnp3_udp_handle);
3009 }