1 /* packet-s7comm.c
2 *
3 * Author: Thomas Wiens, 2014 (th.wiens@gmx.de)
4 * Description: Wireshark dissector for S7-Communication
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13 #include "config.h"
14
15 #include <epan/packet.h>
16 #include <epan/reassemble.h>
17 #include <stdlib.h>
18 #include <wsutil/strtoi.h>
19 #include <epan/expert.h>
20
21 #include "packet-s7comm.h"
22 #include "packet-s7comm_szl_ids.h"
23
24 #define PROTO_TAG_S7COMM "S7COMM"
25
26 /* Min. telegram length for heuristic check */
27 #define S7COMM_MIN_TELEGRAM_LENGTH 10
28
29 /* Protocol identifier */
30 #define S7COMM_PROT_ID 0x32
31
32 /* Wireshark ID of the S7COMM protocol */
33 static int proto_s7comm = -1;
34
35 /* Forward declarations */
36 void proto_reg_handoff_s7comm(void);
37 void proto_register_s7comm (void);
38 static guint32 s7comm_decode_ud_tis_data(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint8 subfunc, guint16 td_size, guint32 offset);
39
40 /**************************************************************************
41 * PDU types
42 */
43 #define S7COMM_ROSCTR_JOB 0x01
44 #define S7COMM_ROSCTR_ACK 0x02
45 #define S7COMM_ROSCTR_ACK_DATA 0x03
46 #define S7COMM_ROSCTR_USERDATA 0x07
47
48 static const value_string rosctr_names[] = {
49 { S7COMM_ROSCTR_JOB, "Job" }, /* Request: job with acknowledgement */
50 { S7COMM_ROSCTR_ACK, "Ack" }, /* acknowledgement without additional field */
51 { S7COMM_ROSCTR_ACK_DATA, "Ack_Data" }, /* Response: acknowledgement with additional field */
52 { S7COMM_ROSCTR_USERDATA, "Userdata" },
53 { 0, NULL }
54 };
55 /**************************************************************************
56 * Error classes in header
57 */
58 #define S7COMM_ERRCLS_NONE 0x00
59 #define S7COMM_ERRCLS_APPREL 0x81
60 #define S7COMM_ERRCLS_OBJDEF 0x82
61 #define S7COMM_ERRCLS_RESOURCE 0x83
62 #define S7COMM_ERRCLS_SERVICE 0x84
63 #define S7COMM_ERRCLS_SUPPLIES 0x85
64 #define S7COMM_ERRCLS_ACCESS 0x87
65
66 static const value_string errcls_names[] = {
67 { S7COMM_ERRCLS_NONE, "No error" },
68 { S7COMM_ERRCLS_APPREL, "Application relationship" },
69 { S7COMM_ERRCLS_OBJDEF, "Object definition" },
70 { S7COMM_ERRCLS_RESOURCE, "No resources available" },
71 { S7COMM_ERRCLS_SERVICE, "Error on service processing" },
72 { S7COMM_ERRCLS_SUPPLIES, "Error on supplies" },
73 { S7COMM_ERRCLS_ACCESS, "Access error" },
74 { 0, NULL }
75 };
76
77 /**************************************************************************
78 * Error code in parameter part
79 */
80
81 static const value_string param_errcode_names[] = {
82 { 0x0000, "No error" },
83 { 0x0110, "Invalid block number" },
84 { 0x0111, "Invalid request length" },
85 { 0x0112, "Invalid parameter" },
86 { 0x0113, "Invalid block type" },
87 { 0x0114, "Block not found" },
88 { 0x0115, "Block already exists" },
89 { 0x0116, "Block is write-protected" },
90 { 0x0117, "The block/operating system update is too large" },
91 { 0x0118, "Invalid block number" },
92 { 0x0119, "Incorrect password entered" },
93 { 0x011A, "PG resource error" },
94 { 0x011B, "PLC resource error" },
95 { 0x011C, "Protocol error" },
96 { 0x011D, "Too many blocks (module-related restriction)" },
97 { 0x011E, "There is no longer a connection to the database, or S7DOS handle is invalid" },
98 { 0x011F, "Result buffer too small" },
99 { 0x0120, "End of block list" },
100 { 0x0140, "Insufficient memory available" },
101 { 0x0141, "Job cannot be processed because of a lack of resources" },
102 { 0x8001, "The requested service cannot be performed while the block is in the current status" },
103 { 0x8003, "S7 protocol error: Error occurred while transferring the block" },
104 { 0x8100, "Application, general error: Service unknown to remote module" },
105 { 0x8104, "This service is not implemented on the module or a frame error was reported" },
106 { 0x8204, "The type specification for the object is inconsistent" },
107 { 0x8205, "A copied block already exists and is not linked" },
108 { 0x8301, "Insufficient memory space or work memory on the module, or specified storage medium not accessible" },
109 { 0x8302, "Too few resources available or the processor resources are not available" },
110 { 0x8304, "No further parallel upload possible. There is a resource bottleneck" },
111 { 0x8305, "Function not available" },
112 { 0x8306, "Insufficient work memory (for copying, linking, loading AWP)" },
113 { 0x8307, "Not enough retentive work memory (for copying, linking, loading AWP)" },
114 { 0x8401, "S7 protocol error: Invalid service sequence (for example, loading or uploading a block)" },
115 { 0x8402, "Service cannot execute owing to status of the addressed object" },
116 { 0x8404, "S7 protocol: The function cannot be performed" },
117 { 0x8405, "Remote block is in DISABLE state (CFB). The function cannot be performed" },
118 { 0x8500, "S7 protocol error: Wrong frames" },
119 { 0x8503, "Alarm from the module: Service canceled prematurely" },
120 { 0x8701, "Error addressing the object on the communications partner (for example, area length error)" },
121 { 0x8702, "The requested service is not supported by the module" },
122 { 0x8703, "Access to object refused" },
123 { 0x8704, "Access error: Object damaged" },
124 { 0xD001, "Protocol error: Illegal job number" },
125 { 0xD002, "Parameter error: Illegal job variant" },
126 { 0xD003, "Parameter error: Debugging function not supported by module" },
127 { 0xD004, "Parameter error: Illegal job status" },
128 { 0xD005, "Parameter error: Illegal job termination" },
129 { 0xD006, "Parameter error: Illegal link disconnection ID" },
130 { 0xD007, "Parameter error: Illegal number of buffer elements" },
131 { 0xD008, "Parameter error: Illegal scan rate" },
132 { 0xD009, "Parameter error: Illegal number of executions" },
133 { 0xD00A, "Parameter error: Illegal trigger event" },
134 { 0xD00B, "Parameter error: Illegal trigger condition" },
135 { 0xD011, "Parameter error in path of the call environment: Block does not exist" },
136 { 0xD012, "Parameter error: Wrong address in block" },
137 { 0xD014, "Parameter error: Block being deleted/overwritten" },
138 { 0xD015, "Parameter error: Illegal tag address" },
139 { 0xD016, "Parameter error: Test jobs not possible, because of errors in user program" },
140 { 0xD017, "Parameter error: Illegal trigger number" },
141 { 0xD025, "Parameter error: Invalid path" },
142 { 0xD026, "Parameter error: Illegal access type" },
143 { 0xD027, "Parameter error: This number of data blocks is not permitted" },
144 { 0xD031, "Internal protocol error" },
145 { 0xD032, "Parameter error: Wrong result buffer length" },
146 { 0xD033, "Protocol error: Wrong job length" },
147 { 0xD03F, "Coding error: Error in parameter section (for example, reserve bytes not equal to 0)" },
148 { 0xD041, "Data error: Illegal status list ID" },
149 { 0xD042, "Data error: Illegal tag address" },
150 { 0xD043, "Data error: Referenced job not found, check job data" },
151 { 0xD044, "Data error: Illegal tag value, check job data" },
152 { 0xD045, "Data error: Exiting the ODIS control is not allowed in HOLD" },
153 { 0xD046, "Data error: Illegal measuring stage during run-time measurement" },
154 { 0xD047, "Data error: Illegal hierarchy in 'Read job list'" },
155 { 0xD048, "Data error: Illegal deletion ID in 'Delete job'" },
156 { 0xD049, "Invalid substitute ID in 'Replace job'" },
157 { 0xD04A, "Error executing 'program status'" },
158 { 0xD05F, "Coding error: Error in data section (for example, reserve bytes not equal to 0, ...)" },
159 { 0xD061, "Resource error: No memory space for job" },
160 { 0xD062, "Resource error: Job list full" },
161 { 0xD063, "Resource error: Trigger event occupied" },
162 { 0xD064, "Resource error: Not enough memory space for one result buffer element" },
163 { 0xD065, "Resource error: Not enough memory space for several result buffer elements" },
164 { 0xD066, "Resource error: The timer available for run-time measurement is occupied by another job" },
165 { 0xD067, "Resource error: Too many 'modify tag' jobs active (in particular multi-processor operation)" },
166 { 0xD081, "Function not permitted in current mode" },
167 { 0xD082, "Mode error: Cannot exit HOLD mode" },
168 { 0xD0A1, "Function not permitted in current protection level" },
169 { 0xD0A2, "Function not possible at present, because a function is running that modifies memory" },
170 { 0xD0A3, "Too many 'modify tag' jobs active on the I/O (in particular multi-processor operation)" },
171 { 0xD0A4, "'Forcing' has already been established" },
172 { 0xD0A5, "Referenced job not found" },
173 { 0xD0A6, "Job cannot be disabled/enabled" },
174 { 0xD0A7, "Job cannot be deleted, for example because it is currently being read" },
175 { 0xD0A8, "Job cannot be replaced, for example because it is currently being read or deleted" },
176 { 0xD0A9, "Job cannot be read, for example because it is currently being deleted" },
177 { 0xD0AA, "Time limit exceeded in processing operation" },
178 { 0xD0AB, "Invalid job parameters in process operation" },
179 { 0xD0AC, "Invalid job data in process operation" },
180 { 0xD0AD, "Operating mode already set" },
181 { 0xD0AE, "The job was set up over a different connection and can only be handled over this connection" },
182 { 0xD0C1, "At least one error has been detected while accessing the tag(s)" },
183 { 0xD0C2, "Change to STOP/HOLD mode" },
184 { 0xD0C3, "At least one error was detected while accessing the tag(s). Mode change to STOP/HOLD" },
185 { 0xD0C4, "Timeout during run-time measurement" },
186 { 0xD0C5, "Display of block stack inconsistent, because blocks were deleted/reloaded" },
187 { 0xD0C6, "Job was automatically deleted as the jobs it referenced have been deleted" },
188 { 0xD0C7, "The job was automatically deleted because STOP mode was exited" },
189 { 0xD0C8, "'Block status' aborted because of inconsistencies between test job and running program" },
190 { 0xD0C9, "Exit the status area by resetting OB90" },
191 { 0xD0CA, "Exiting the status range by resetting OB90 and access error reading tags before exiting" },
192 { 0xD0CB, "The output disable for the peripheral outputs has been activated again" },
193 { 0xD0CC, "The amount of data for the debugging functions is restricted by the time limit" },
194 { 0xD201, "Syntax error in block name" },
195 { 0xD202, "Syntax error in function parameters" },
196 { 0xD205, "Linked block already exists in RAM: Conditional copying is not possible" },
197 { 0xD206, "Linked block already exists in EPROM: Conditional copying is not possible" },
198 { 0xD208, "Maximum number of copied (not linked) blocks on module exceeded" },
199 { 0xD209, "(At least) one of the given blocks not found on the module" },
200 { 0xD20A, "The maximum number of blocks that can be linked with one job was exceeded" },
201 { 0xD20B, "The maximum number of blocks that can be deleted with one job was exceeded" },
202 { 0xD20C, "OB cannot be copied because the associated priority class does not exist" },
203 { 0xD20D, "SDB cannot be interpreted (for example, unknown number)" },
204 { 0xD20E, "No (further) block available" },
205 { 0xD20F, "Module-specific maximum block size exceeded" },
206 { 0xD210, "Invalid block number" },
207 { 0xD212, "Incorrect header attribute (run-time relevant)" },
208 { 0xD213, "Too many SDBs. Note the restrictions on the module being used" },
209 { 0xD216, "Invalid user program - reset module" },
210 { 0xD217, "Protection level specified in module properties not permitted" },
211 { 0xD218, "Incorrect attribute (active/passive)" },
212 { 0xD219, "Incorrect block lengths (for example, incorrect length of first section or of the whole block)" },
213 { 0xD21A, "Incorrect local data length or write-protection code faulty" },
214 { 0xD21B, "Module cannot compress or compression was interrupted early" },
215 { 0xD21D, "The volume of dynamic project data transferred is illegal" },
216 { 0xD21E, "Unable to assign parameters to a module (such as FM, CP). The system data could not be linked" },
217 { 0xD220, "Invalid programming language. Note the restrictions on the module being used" },
218 { 0xD221, "The system data for connections or routing are not valid" },
219 { 0xD222, "The system data of the global data definition contain invalid parameters" },
220 { 0xD223, "Error in instance data block for communication function block or maximum number of instance DBs exceeded" },
221 { 0xD224, "The SCAN system data block contains invalid parameters" },
222 { 0xD225, "The DP system data block contains invalid parameters" },
223 { 0xD226, "A structural error occurred in a block" },
224 { 0xD230, "A structural error occurred in a block" },
225 { 0xD231, "At least one loaded OB cannot be copied because the associated priority class does not exist" },
226 { 0xD232, "At least one block number of a loaded block is illegal" },
227 { 0xD234, "Block exists twice in the specified memory medium or in the job" },
228 { 0xD235, "The block contains an incorrect checksum" },
229 { 0xD236, "The block does not contain a checksum" },
230 { 0xD237, "You are about to load the block twice, i.e. a block with the same time stamp already exists on the CPU" },
231 { 0xD238, "At least one of the blocks specified is not a DB" },
232 { 0xD239, "At least one of the DBs specified is not available as a linked variant in the load memory" },
233 { 0xD23A, "At least one of the specified DBs is considerably different from the copied and linked variant" },
234 { 0xD240, "Coordination rules violated" },
235 { 0xD241, "The function is not permitted in the current protection level" },
236 { 0xD242, "Protection violation while processing F blocks" },
237 { 0xD250, "Update and module ID or version do not match" },
238 { 0xD251, "Incorrect sequence of operating system components" },
239 { 0xD252, "Checksum error" },
240 { 0xD253, "No executable loader available; update only possible using a memory card" },
241 { 0xD254, "Storage error in operating system" },
242 { 0xD280, "Error compiling block in S7-300 CPU" },
243 { 0xD2A1, "Another block function or a trigger on a block is active" },
244 { 0xD2A2, "A trigger is active on a block. Complete the debugging function first" },
245 { 0xD2A3, "The block is not active (linked), the block is occupied or the block is currently marked for deletion" },
246 { 0xD2A4, "The block is already being processed by another block function" },
247 { 0xD2A6, "It is not possible to save and change the user program simultaneously" },
248 { 0xD2A7, "The block has the attribute 'unlinked' or is not processed" },
249 { 0xD2A8, "An active debugging function is preventing parameters from being assigned to the CPU" },
250 { 0xD2A9, "New parameters are being assigned to the CPU" },
251 { 0xD2AA, "New parameters are currently being assigned to the modules" },
252 { 0xD2AB, "The dynamic configuration limits are currently being changed" },
253 { 0xD2AC, "A running active or deactivate assignment (SFC 12) is temporarily preventing R-KiR process" },
254 { 0xD2B0, "An error occurred while configuring in RUN (CiR)" },
255 { 0xD2C0, "The maximum number of technological objects has been exceeded" },
256 { 0xD2C1, "The same technology data block already exists on the module" },
257 { 0xD2C2, "Downloading the user program or downloading the hardware configuration is not possible" },
258 { 0xD401, "Information function unavailable" },
259 { 0xD402, "Information function unavailable" },
260 { 0xD403, "Service has already been logged on/off (Diagnostics/PMC)" },
261 { 0xD404, "Maximum number of nodes reached. No more logons possible for diagnostics/PMC" },
262 { 0xD405, "Service not supported or syntax error in function parameters" },
263 { 0xD406, "Required information currently unavailable" },
264 { 0xD407, "Diagnostics error occurred" },
265 { 0xD408, "Update aborted" },
266 { 0xD409, "Error on DP bus" },
267 { 0xD601, "Syntax error in function parameter" },
268 { 0xD602, "Incorrect password entered" },
269 { 0xD603, "The connection has already been legitimized" },
270 { 0xD604, "The connection has already been enabled" },
271 { 0xD605, "Legitimization not possible because password does not exist" },
272 { 0xD801, "At least one tag address is invalid" },
273 { 0xD802, "Specified job does not exist" },
274 { 0xD803, "Illegal job status" },
275 { 0xD804, "Illegal cycle time (illegal time base or multiple)" },
276 { 0xD805, "No more cyclic read jobs can be set up" },
277 { 0xD806, "The referenced job is in a state in which the requested function cannot be performed" },
278 { 0xD807, "Function aborted due to overload, meaning executing the read cycle takes longer than the set scan cycle time" },
279 { 0xDC01, "Date and/or time invalid" },
280 { 0xE201, "CPU is already the master" },
281 { 0xE202, "Connect and update not possible due to different user program in flash module" },
282 { 0xE203, "Connect and update not possible due to different firmware" },
283 { 0xE204, "Connect and update not possible due to different memory configuration" },
284 { 0xE205, "Connect/update aborted due to synchronization error" },
285 { 0xE206, "Connect/update denied due to coordination violation" },
286 { 0xEF01, "S7 protocol error: Error at ID2; only 00H permitted in job" },
287 { 0xEF02, "S7 protocol error: Error at ID2; set of resources does not exist" },
288 { 0, NULL }
289 };
290 static value_string_ext param_errcode_names_ext = VALUE_STRING_EXT_INIT(param_errcode_names);
291
292 /**************************************************************************
293 * Function codes in parameter part
294 */
295 #define S7COMM_SERV_CPU 0x00
296 #define S7COMM_SERV_SETUPCOMM 0xF0
297 #define S7COMM_SERV_READVAR 0x04
298 #define S7COMM_SERV_WRITEVAR 0x05
299
300 #define S7COMM_FUNCREQUESTDOWNLOAD 0x1A
301 #define S7COMM_FUNCDOWNLOADBLOCK 0x1B
302 #define S7COMM_FUNCDOWNLOADENDED 0x1C
303 #define S7COMM_FUNCSTARTUPLOAD 0x1D
304 #define S7COMM_FUNCUPLOAD 0x1E
305 #define S7COMM_FUNCENDUPLOAD 0x1F
306 #define S7COMM_FUNCPISERVICE 0x28
307 #define S7COMM_FUNC_PLC_STOP 0x29
308
309 static const value_string param_functionnames[] = {
310 { S7COMM_SERV_CPU, "CPU services" },
311 { S7COMM_SERV_SETUPCOMM, "Setup communication" },
312 { S7COMM_SERV_READVAR, "Read Var" },
313 { S7COMM_SERV_WRITEVAR, "Write Var" },
314 /* Block management services */
315 { S7COMM_FUNCREQUESTDOWNLOAD, "Request download" },
316 { S7COMM_FUNCDOWNLOADBLOCK, "Download block" },
317 { S7COMM_FUNCDOWNLOADENDED, "Download ended" },
318 { S7COMM_FUNCSTARTUPLOAD, "Start upload" },
319 { S7COMM_FUNCUPLOAD, "Upload" },
320 { S7COMM_FUNCENDUPLOAD, "End upload" },
321 { S7COMM_FUNCPISERVICE, "PI-Service" },
322 { S7COMM_FUNC_PLC_STOP, "PLC Stop" },
323 { 0, NULL }
324 };
325 /**************************************************************************
326 * Area names
327 */
328 #define S7COMM_AREA_DATARECORD 0x01 /* Data record, used with RDREC or firmware updates on CP */
329 #define S7COMM_AREA_SYSINFO 0x03 /* System info of 200 family */
330 #define S7COMM_AREA_SYSFLAGS 0x05 /* System flags of 200 family */
331 #define S7COMM_AREA_ANAIN 0x06 /* analog inputs of 200 family */
332 #define S7COMM_AREA_ANAOUT 0x07 /* analog outputs of 200 family */
333 #define S7COMM_AREA_P 0x80 /* direct peripheral access */
334 #define S7COMM_AREA_INPUTS 0x81
335 #define S7COMM_AREA_OUTPUTS 0x82
336 #define S7COMM_AREA_FLAGS 0x83
337 #define S7COMM_AREA_DB 0x84 /* data blocks */
338 #define S7COMM_AREA_DI 0x85 /* instance data blocks */
339 #define S7COMM_AREA_LOCAL 0x86 /* local data (should not be accessible over network) */
340 #define S7COMM_AREA_V 0x87 /* previous (Vorgaenger) local data (should not be accessible over network) */
341 #define S7COMM_AREA_COUNTER 28 /* S7 counters */
342 #define S7COMM_AREA_TIMER 29 /* S7 timers */
343 #define S7COMM_AREA_COUNTER200 30 /* IEC counters (200 family) */
344 #define S7COMM_AREA_TIMER200 31 /* IEC timers (200 family) */
345
346 static const value_string item_areanames[] = {
347 { S7COMM_AREA_DATARECORD, "Data record" },
348 { S7COMM_AREA_SYSINFO, "System info of 200 family" },
349 { S7COMM_AREA_SYSFLAGS, "System flags of 200 family" },
350 { S7COMM_AREA_ANAIN, "Analog inputs of 200 family" },
351 { S7COMM_AREA_ANAOUT, "Analog outputs of 200 family" },
352 { S7COMM_AREA_P, "Direct peripheral access (P)" },
353 { S7COMM_AREA_INPUTS, "Inputs (I)" },
354 { S7COMM_AREA_OUTPUTS, "Outputs (Q)" },
355 { S7COMM_AREA_FLAGS, "Flags (M)" },
356 { S7COMM_AREA_DB, "Data blocks (DB)" },
357 { S7COMM_AREA_DI, "Instance data blocks (DI)" },
358 { S7COMM_AREA_LOCAL, "Local data (L)" },
359 { S7COMM_AREA_V, "Unknown yet (V)" },
360 { S7COMM_AREA_COUNTER, "S7 counters (C)" },
361 { S7COMM_AREA_TIMER, "S7 timers (T)" },
362 { S7COMM_AREA_COUNTER200, "IEC counters (200 family)" },
363 { S7COMM_AREA_TIMER200, "IEC timers (200 family)" },
364 { 0, NULL }
365 };
366
367 static const value_string item_areanames_short[] = {
368 { S7COMM_AREA_DATARECORD, "RECORD" },
369 { S7COMM_AREA_SYSINFO, "SI200" },
370 { S7COMM_AREA_SYSFLAGS, "SF200" },
371 { S7COMM_AREA_ANAIN, "AI200" },
372 { S7COMM_AREA_ANAOUT, "AO" },
373 { S7COMM_AREA_P, "P" },
374 { S7COMM_AREA_INPUTS, "I" },
375 { S7COMM_AREA_OUTPUTS, "Q" },
376 { S7COMM_AREA_FLAGS, "M" },
377 { S7COMM_AREA_DB, "DB" },
378 { S7COMM_AREA_DI, "DI" },
379 { S7COMM_AREA_LOCAL, "L" },
380 { S7COMM_AREA_V, "V" },
381 { S7COMM_AREA_COUNTER, "C" },
382 { S7COMM_AREA_TIMER, "T" },
383 { S7COMM_AREA_COUNTER200, "C200" },
384 { S7COMM_AREA_TIMER200, "T200" },
385 { 0, NULL }
386 };
387 /**************************************************************************
388 * Transport sizes in item data
389 */
390 /* types of 1 byte length */
391 #define S7COMM_TRANSPORT_SIZE_BIT 1
392 #define S7COMM_TRANSPORT_SIZE_BYTE 2
393 #define S7COMM_TRANSPORT_SIZE_CHAR 3
394 /* types of 2 bytes length */
395 #define S7COMM_TRANSPORT_SIZE_WORD 4
396 #define S7COMM_TRANSPORT_SIZE_INT 5
397 /* types of 4 bytes length */
398 #define S7COMM_TRANSPORT_SIZE_DWORD 6
399 #define S7COMM_TRANSPORT_SIZE_DINT 7
400 #define S7COMM_TRANSPORT_SIZE_REAL 8
401 /* Special types */
402 #define S7COMM_TRANSPORT_SIZE_DATE 9
403 #define S7COMM_TRANSPORT_SIZE_TOD 10
404 #define S7COMM_TRANSPORT_SIZE_TIME 11
405 #define S7COMM_TRANSPORT_SIZE_S5TIME 12
406 #define S7COMM_TRANSPORT_SIZE_DT 15
407 /* Timer or counter */
408 #define S7COMM_TRANSPORT_SIZE_COUNTER 28
409 #define S7COMM_TRANSPORT_SIZE_TIMER 29
410 #define S7COMM_TRANSPORT_SIZE_IEC_COUNTER 30
411 #define S7COMM_TRANSPORT_SIZE_IEC_TIMER 31
412 #define S7COMM_TRANSPORT_SIZE_HS_COUNTER 32
413 static const value_string item_transportsizenames[] = {
414 { S7COMM_TRANSPORT_SIZE_BIT, "BIT" },
415 { S7COMM_TRANSPORT_SIZE_BYTE, "BYTE" },
416 { S7COMM_TRANSPORT_SIZE_CHAR, "CHAR" },
417 { S7COMM_TRANSPORT_SIZE_WORD, "WORD" },
418 { S7COMM_TRANSPORT_SIZE_INT, "INT" },
419 { S7COMM_TRANSPORT_SIZE_DWORD, "DWORD" },
420 { S7COMM_TRANSPORT_SIZE_DINT, "DINT" },
421 { S7COMM_TRANSPORT_SIZE_REAL, "REAL" },
422 { S7COMM_TRANSPORT_SIZE_TOD, "TOD" },
423 { S7COMM_TRANSPORT_SIZE_TIME, "TIME" },
424 { S7COMM_TRANSPORT_SIZE_S5TIME, "S5TIME" },
425 { S7COMM_TRANSPORT_SIZE_DT, "DATE_AND_TIME" },
426 { S7COMM_TRANSPORT_SIZE_COUNTER, "COUNTER" },
427 { S7COMM_TRANSPORT_SIZE_TIMER, "TIMER" },
428 { S7COMM_TRANSPORT_SIZE_IEC_COUNTER, "IEC TIMER" },
429 { S7COMM_TRANSPORT_SIZE_IEC_TIMER, "IEC COUNTER" },
430 { S7COMM_TRANSPORT_SIZE_HS_COUNTER, "HS COUNTER" },
431 { 0, NULL }
432 };
433
434 /**************************************************************************
435 * Syntax Ids of variable specification
436 */
437 #define S7COMM_SYNTAXID_S7ANY 0x10 /* Address data S7-Any pointer-like DB1.DBX10.2 */
438 #define S7COMM_SYNTAXID_PBC_ID 0x13 /* R_ID for PBC */
439 #define S7COMM_SYNTAXID_ALARM_LOCKFREESET 0x15 /* Alarm lock/free dataset */
440 #define S7COMM_SYNTAXID_ALARM_INDSET 0x16 /* Alarm indication dataset */
441 #define S7COMM_SYNTAXID_ALARM_ACKSET 0x19 /* Alarm acknowledge message dataset */
442 #define S7COMM_SYNTAXID_ALARM_QUERYREQSET 0x1a /* Alarm query request dataset */
443 #define S7COMM_SYNTAXID_NOTIFY_INDSET 0x1c /* Notify indication dataset */
444 #define S7COMM_SYNTAXID_NCK 0x82 /* Sinumerik NCK HMI access (current units) */
445 #define S7COMM_SYNTAXID_NCK_METRIC 0x83 /* Sinumerik NCK HMI access metric units */
446 #define S7COMM_SYNTAXID_NCK_INCH 0x84 /* Sinumerik NCK HMI access inch */
447 #define S7COMM_SYNTAXID_DRIVEESANY 0xa2 /* seen on Drive ES Starter with routing over S7 */
448 #define S7COMM_SYNTAXID_1200SYM 0xb2 /* Symbolic address mode of S7-1200 */
449 #define S7COMM_SYNTAXID_DBREAD 0xb0 /* Kind of DB block read, seen only at an S7-400 */
450
451 static const value_string item_syntaxid_names[] = {
452 { S7COMM_SYNTAXID_S7ANY, "S7ANY" },
453 { S7COMM_SYNTAXID_PBC_ID, "PBC-R_ID" },
454 { S7COMM_SYNTAXID_ALARM_LOCKFREESET, "ALARM_LOCKFREE" },
455 { S7COMM_SYNTAXID_ALARM_INDSET, "ALARM_IND" },
456 { S7COMM_SYNTAXID_ALARM_ACKSET, "ALARM_ACK" },
457 { S7COMM_SYNTAXID_ALARM_QUERYREQSET, "ALARM_QUERYREQ" },
458 { S7COMM_SYNTAXID_NOTIFY_INDSET, "NOTIFY_IND" },
459 { S7COMM_SYNTAXID_NCK, "NCK" },
460 { S7COMM_SYNTAXID_NCK_METRIC, "NCK_M" },
461 { S7COMM_SYNTAXID_NCK_INCH, "NCK_I" },
462 { S7COMM_SYNTAXID_DRIVEESANY, "DRIVEESANY" },
463 { S7COMM_SYNTAXID_1200SYM, "1200SYM" },
464 { S7COMM_SYNTAXID_DBREAD, "DBREAD" },
465 { 0, NULL }
466 };
467
468 /**************************************************************************
469 * Transport sizes in data
470 */
471 #define S7COMM_DATA_TRANSPORT_SIZE_NULL 0
472 #define S7COMM_DATA_TRANSPORT_SIZE_BBIT 3 /* bit access, len is in bits */
473 #define S7COMM_DATA_TRANSPORT_SIZE_BBYTE 4 /* byte/word/dword access, len is in bits */
474 #define S7COMM_DATA_TRANSPORT_SIZE_BINT 5 /* integer access, len is in bits */
475 #define S7COMM_DATA_TRANSPORT_SIZE_BDINT 6 /* integer access, len is in bytes */
476 #define S7COMM_DATA_TRANSPORT_SIZE_BREAL 7 /* real access, len is in bytes */
477 #define S7COMM_DATA_TRANSPORT_SIZE_BSTR 9 /* octet string, len is in bytes */
478 #define S7COMM_DATA_TRANSPORT_SIZE_NCKADDR1 17 /* NCK address description, fixed length */
479 #define S7COMM_DATA_TRANSPORT_SIZE_NCKADDR2 18 /* NCK address description, fixed length */
480
481 static const value_string data_transportsizenames[] = {
482 { S7COMM_DATA_TRANSPORT_SIZE_NULL, "NULL" },
483 { S7COMM_DATA_TRANSPORT_SIZE_BBIT, "BIT" },
484 { S7COMM_DATA_TRANSPORT_SIZE_BBYTE, "BYTE/WORD/DWORD" },
485 { S7COMM_DATA_TRANSPORT_SIZE_BINT, "INTEGER" },
486 { S7COMM_DATA_TRANSPORT_SIZE_BDINT, "DINTEGER" },
487 { S7COMM_DATA_TRANSPORT_SIZE_BREAL, "REAL" },
488 { S7COMM_DATA_TRANSPORT_SIZE_BSTR, "OCTET STRING" },
489 { S7COMM_DATA_TRANSPORT_SIZE_NCKADDR1, "NCK ADDRESS1" },
490 { S7COMM_DATA_TRANSPORT_SIZE_NCKADDR2, "NCK ADDRESS2" },
491 { 0, NULL }
492 };
493 /**************************************************************************
494 * Returnvalues of an item response
495 */
496
497 const value_string s7comm_item_return_valuenames[] = {
498 { S7COMM_ITEM_RETVAL_RESERVED, "Reserved" },
499 { S7COMM_ITEM_RETVAL_DATA_HW_FAULT, "Hardware error" },
500 { S7COMM_ITEM_RETVAL_DATA_ACCESS_FAULT, "Accessing the object not allowed" },
501 { S7COMM_ITEM_RETVAL_DATA_OUTOFRANGE, "Invalid address" },
502 { S7COMM_ITEM_RETVAL_DATA_NOT_SUP, "Data type not supported" },
503 { S7COMM_ITEM_RETVAL_DATA_SIZEMISMATCH, "Data type inconsistent" },
504 { S7COMM_ITEM_RETVAL_DATA_ERR, "Object does not exist" },
505 { S7COMM_ITEM_RETVAL_DATA_OK, "Success" },
506 { 0, NULL }
507 };
508 /**************************************************************************
509 * Block Types, used when blocktype is transfered as string
510 */
511 #define S7COMM_BLOCKTYPE_OB 0x3038 /* '08' */
512 #define S7COMM_BLOCKTYPE_CMOD 0x3039 /* '09' */
513 #define S7COMM_BLOCKTYPE_DB 0x3041 /* '0A' */
514 #define S7COMM_BLOCKTYPE_SDB 0x3042 /* '0B' */
515 #define S7COMM_BLOCKTYPE_FC 0x3043 /* '0C' */
516 #define S7COMM_BLOCKTYPE_SFC 0x3044 /* '0D' */
517 #define S7COMM_BLOCKTYPE_FB 0x3045 /* '0E' */
518 #define S7COMM_BLOCKTYPE_SFB 0x3046 /* '0F' */
519
520 static const value_string blocktype_names[] = {
521 { S7COMM_BLOCKTYPE_OB, "OB" },
522 { S7COMM_BLOCKTYPE_CMOD, "CMod" },
523 { S7COMM_BLOCKTYPE_DB, "DB" },
524 { S7COMM_BLOCKTYPE_SDB, "SDB" },
525 { S7COMM_BLOCKTYPE_FC, "FC" },
526 { S7COMM_BLOCKTYPE_SFC, "SFC" },
527 { S7COMM_BLOCKTYPE_FB, "FB" },
528 { S7COMM_BLOCKTYPE_SFB, "SFB" },
529 { 0, NULL }
530 };
531
532
533 static const value_string blocktype_attribute1_names[] = {
534 { '_', "Complete Module" },
535 { '$', "Module header for up-loading" },
536 { 0, NULL }
537 };
538
539 static const value_string blocktype_attribute2_names[] = {
540 { 'P', "Passive (copied, but not chained) module" },
541 { 'A', "Active embedded module" },
542 { 'B', "Active as well as passive module" },
543 { 0, NULL }
544 };
545
546 /**************************************************************************
547 * Subblk types
548 */
549 #define S7COMM_SUBBLKTYPE_NONE 0x00
550 #define S7COMM_SUBBLKTYPE_OB 0x08
551 #define S7COMM_SUBBLKTYPE_DB 0x0a
552 #define S7COMM_SUBBLKTYPE_SDB 0x0b
553 #define S7COMM_SUBBLKTYPE_FC 0x0c
554 #define S7COMM_SUBBLKTYPE_SFC 0x0d
555 #define S7COMM_SUBBLKTYPE_FB 0x0e
556 #define S7COMM_SUBBLKTYPE_SFB 0x0f
557
558 static const value_string subblktype_names[] = {
559 { S7COMM_SUBBLKTYPE_NONE, "Not set" },
560 { S7COMM_SUBBLKTYPE_OB, "OB" },
561 { S7COMM_SUBBLKTYPE_DB, "DB" },
562 { S7COMM_SUBBLKTYPE_SDB, "SDB" },
563 { S7COMM_SUBBLKTYPE_FC, "FC" },
564 { S7COMM_SUBBLKTYPE_SFC, "SFC" },
565 { S7COMM_SUBBLKTYPE_FB, "FB" },
566 { S7COMM_SUBBLKTYPE_SFB, "SFB" },
567 { 0, NULL }
568 };
569
570 /**************************************************************************
571 * Block security
572 */
573 #define S7COMM_BLOCKSECURITY_OFF 0
574 #define S7COMM_BLOCKSECURITY_KNOWHOWPROTECT 3
575
576 static const value_string blocksecurity_names[] = {
577 { S7COMM_BLOCKSECURITY_OFF, "None" },
578 { S7COMM_BLOCKSECURITY_KNOWHOWPROTECT, "Know How Protect" },
579 { 0, NULL }
580 };
581 /**************************************************************************
582 * Block Languages
583 */
584 static const value_string blocklanguage_names[] = {
585 { 0x00, "Not defined" },
586 { 0x01, "AWL" },
587 { 0x02, "KOP" },
588 { 0x03, "FUP" },
589 { 0x04, "SCL" },
590 { 0x05, "DB" },
591 { 0x06, "GRAPH" },
592 { 0x07, "SDB" },
593 { 0x08, "CPU-DB" }, /* DB was created from Plc programm (CREAT_DB) */
594 { 0x11, "SDB (after overall reset)" }, /* another SDB, don't know what it means, in SDB 1 and SDB 2, uncertain*/
595 { 0x12, "SDB (Routing)" }, /* another SDB, in SDB 999 and SDB 1000 (routing information), uncertain */
596 { 0x29, "ENCRYPT" }, /* block is encrypted with S7-Block-Privacy */
597 { 0, NULL }
598 };
599
600 /**************************************************************************
601 * Second request/response in userdata parameter part
602 */
603 #define S7COMM_UD_REQRES2_UNDEF 0x00
604 #define S7COMM_UD_REQRES2_REQ 0x11
605 #define S7COMM_UD_REQRES2_RES 0x12
606
607 static const value_string userdata_reqres2_names[] = {
608 { S7COMM_UD_REQRES2_UNDEF, "Undef" }, /* only seen in mode transition events */
609 { S7COMM_UD_REQRES2_REQ, "Req" },
610 { S7COMM_UD_REQRES2_RES, "Res" },
611 { 0, NULL }
612 };
613
614 /**************************************************************************
615 * Names of types in userdata parameter part
616 */
617
618 #define S7COMM_UD_TYPE_NCPUSH 0x3
619 #define S7COMM_UD_TYPE_NCREQ 0x7
620 #define S7COMM_UD_TYPE_NCRES 0xb
621
622 static const value_string userdata_type_names[] = {
623 { S7COMM_UD_TYPE_PUSH, "Push" }, /* this type occurs when 2 telegrams follow after another from the same partner, or initiated from PLC */
624 { S7COMM_UD_TYPE_REQ, "Request" },
625 { S7COMM_UD_TYPE_RES, "Response" },
626 { S7COMM_UD_TYPE_NCPUSH, "NC Push" }, /* used only by Sinumerik NC */
627 { S7COMM_UD_TYPE_NCREQ, "NC Request" }, /* used only by Sinumerik NC */
628 { S7COMM_UD_TYPE_NCRES, "NC Response" }, /* used only by Sinumerik NC */
629 { 0, NULL }
630 };
631
632 /**************************************************************************
633 * Subfunctions only used in Sinumerik NC file download
634 */
635 #define S7COMM_NCPRG_FUNCREQUESTDOWNLOAD 1
636 #define S7COMM_NCPRG_FUNCDOWNLOADBLOCK 2
637 #define S7COMM_NCPRG_FUNCCONTDOWNLOAD 3
638 #define S7COMM_NCPRG_FUNCDOWNLOADENDED 4
639 #define S7COMM_NCPRG_FUNCSTARTUPLOAD 6
640 #define S7COMM_NCPRG_FUNCUPLOAD 7
641 #define S7COMM_NCPRG_FUNCCONTUPLOAD 8
642
643 static const value_string userdata_ncprg_subfunc_names[] = {
644 { S7COMM_NCPRG_FUNCREQUESTDOWNLOAD, "Request download" },
645 { S7COMM_NCPRG_FUNCDOWNLOADBLOCK, "Download block" },
646 { S7COMM_NCPRG_FUNCCONTDOWNLOAD, "Continue download" },
647 { S7COMM_NCPRG_FUNCDOWNLOADENDED, "Download ended" },
648 { S7COMM_NCPRG_FUNCSTARTUPLOAD, "Start upload" },
649 { S7COMM_NCPRG_FUNCUPLOAD, "Upload" },
650 { S7COMM_NCPRG_FUNCCONTUPLOAD, "Continue upload" },
651 { 0, NULL }
652 };
653
654 /**************************************************************************
655 * Userdata Parameter, last data unit
656 */
657 #define S7COMM_UD_LASTDATAUNIT_YES 0x00
658 #define S7COMM_UD_LASTDATAUNIT_NO 0x01
659
660 static const value_string userdata_lastdataunit_names[] = {
661 { S7COMM_UD_LASTDATAUNIT_YES, "Yes" },
662 { S7COMM_UD_LASTDATAUNIT_NO, "No" },
663 { 0, NULL }
664 };
665
666 /**************************************************************************
667 * Names of Function groups in userdata parameter part
668 */
669 #define S7COMM_UD_FUNCGROUP_MODETRANS 0x0
670 #define S7COMM_UD_FUNCGROUP_PROG 0x1
671 #define S7COMM_UD_FUNCGROUP_CYCLIC 0x2
672 #define S7COMM_UD_FUNCGROUP_BLOCK 0x3
673 #define S7COMM_UD_FUNCGROUP_CPU 0x4
674 #define S7COMM_UD_FUNCGROUP_SEC 0x5 /* Security functions e.g. plc password */
675 #define S7COMM_UD_FUNCGROUP_PBC 0x6 /* PBC = Programmable Block Communication (PBK in german) */
676 #define S7COMM_UD_FUNCGROUP_TIME 0x7
677 #define S7COMM_UD_FUNCGROUP_NCPRG 0xf
678
679 static const value_string userdata_functiongroup_names[] = {
680 { S7COMM_UD_FUNCGROUP_MODETRANS, "Mode-transition" },
681 { S7COMM_UD_FUNCGROUP_PROG, "Programmer commands" },
682 { S7COMM_UD_FUNCGROUP_CYCLIC, "Cyclic services" }, /* to read data from plc without a request */
683 { S7COMM_UD_FUNCGROUP_BLOCK, "Block functions" },
684 { S7COMM_UD_FUNCGROUP_CPU, "CPU functions" },
685 { S7COMM_UD_FUNCGROUP_SEC, "Security" },
686 { S7COMM_UD_FUNCGROUP_PBC, "PBC BSEND/BRECV" },
687 { S7COMM_UD_FUNCGROUP_TIME, "Time functions" },
688 { S7COMM_UD_FUNCGROUP_NCPRG, "NC programming" },
689 { 0, NULL }
690 };
691
692 /**************************************************************************
693 * Variable status: Area of data request
694 *
695 * Low Hi
696 * 0=M 0=BOOL
697 * 1=E 1=BYTE
698 * 2=A 2=WORD
699 * 3=PEx 3=DWORD
700 * 7=DB
701 * 54=TIMER
702 * 64=COUNTER
703 */
704 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MX 0x00
705 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MB 0x01
706 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MW 0x02
707 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MD 0x03
708 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EX 0x10
709 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EB 0x11
710 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EW 0x12
711 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_ED 0x13
712 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AX 0x20
713 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AB 0x21
714 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AW 0x22
715 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AD 0x23
716 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PEB 0x31
717 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PEW 0x32
718 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PED 0x33
719 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBX 0x70
720 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBB 0x71
721 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBW 0x72
722 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBD 0x73
723 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_T 0x54
724 #define S7COMM_UD_SUBF_PROG_VARSTAT_AREA_C 0x64
725
726 static const value_string userdata_prog_varstat_area_names[] = {
727 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MX, "MX" },
728 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MB, "MB" },
729 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MW, "MW" },
730 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MD, "MD" },
731 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EB, "IB" },
732 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EX, "IX" },
733 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EW, "IW" },
734 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_ED, "ID" },
735 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AX, "QX" },
736 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AB, "QB" },
737 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AW, "QW" },
738 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AD, "QD" },
739 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PEB, "PIB" },
740 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PEW, "PIW" },
741 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PED, "PID" },
742 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBX, "DBX" },
743 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBB, "DBB" },
744 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBW, "DBW" },
745 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBD, "DBD" },
746 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_T, "TIMER" },
747 { S7COMM_UD_SUBF_PROG_VARSTAT_AREA_C, "COUNTER" },
748 { 0, NULL }
749 };
750
751 /**************************************************************************
752 * Names of userdata subfunctions in group 1 (Programmer commands)
753 * In szl dataset 0x0132/2 these are defined as "Test and installation functions TIS".
754 * The methods supported by the CPU are listed in the funkt_n bits.
755 */
756 #define S7COMM_UD_SUBF_PROG_BLOCKSTAT 0x01
757 #define S7COMM_UD_SUBF_PROG_VARSTAT 0x02
758 #define S7COMM_UD_SUBF_PROG_OUTISTACK 0x03
759 #define S7COMM_UD_SUBF_PROG_OUTBSTACK 0x04
760 #define S7COMM_UD_SUBF_PROG_OUTLSTACK 0x05
761 #define S7COMM_UD_SUBF_PROG_TIMEMEAS 0x06
762 #define S7COMM_UD_SUBF_PROG_FORCESEL 0x07
763 #define S7COMM_UD_SUBF_PROG_MODVAR 0x08
764 #define S7COMM_UD_SUBF_PROG_FORCE 0x09
765 #define S7COMM_UD_SUBF_PROG_BREAKPOINT 0x0a
766 #define S7COMM_UD_SUBF_PROG_EXITHOLD 0x0b
767 #define S7COMM_UD_SUBF_PROG_MEMORYRES 0x0c
768 #define S7COMM_UD_SUBF_PROG_DISABLEJOB 0x0d
769 #define S7COMM_UD_SUBF_PROG_ENABLEJOB 0x0e
770 #define S7COMM_UD_SUBF_PROG_DELETEJOB 0x0f
771 #define S7COMM_UD_SUBF_PROG_READJOBLIST 0x10
772 #define S7COMM_UD_SUBF_PROG_READJOB 0x11
773 #define S7COMM_UD_SUBF_PROG_REPLACEJOB 0x12
774 #define S7COMM_UD_SUBF_PROG_BLOCKSTAT2 0x13
775 #define S7COMM_UD_SUBF_PROG_FLASHLED 0x16
776
777 static const value_string userdata_prog_subfunc_names[] = {
778 { S7COMM_UD_SUBF_PROG_BLOCKSTAT, "Block status" },
779 { S7COMM_UD_SUBF_PROG_VARSTAT, "Variable status" },
780 { S7COMM_UD_SUBF_PROG_OUTISTACK, "Output ISTACK" },
781 { S7COMM_UD_SUBF_PROG_OUTBSTACK, "Output BSTACK" },
782 { S7COMM_UD_SUBF_PROG_OUTLSTACK, "Output LSTACK" },
783 { S7COMM_UD_SUBF_PROG_TIMEMEAS, "Time measurement from to" }, /* never seen yet */
784 { S7COMM_UD_SUBF_PROG_FORCESEL, "Force selection" },
785 { S7COMM_UD_SUBF_PROG_MODVAR, "Modify variable" },
786 { S7COMM_UD_SUBF_PROG_FORCE, "Force" },
787 { S7COMM_UD_SUBF_PROG_BREAKPOINT, "Breakpoint" },
788 { S7COMM_UD_SUBF_PROG_EXITHOLD, "Exit HOLD" },
789 { S7COMM_UD_SUBF_PROG_MEMORYRES, "Memory reset" },
790 { S7COMM_UD_SUBF_PROG_DISABLEJOB, "Disable job" },
791 { S7COMM_UD_SUBF_PROG_ENABLEJOB, "Enable job" },
792 { S7COMM_UD_SUBF_PROG_DELETEJOB, "Delete job" },
793 { S7COMM_UD_SUBF_PROG_READJOBLIST, "Read job list" },
794 { S7COMM_UD_SUBF_PROG_READJOB, "Read job" },
795 { S7COMM_UD_SUBF_PROG_REPLACEJOB, "Replace job" },
796 { S7COMM_UD_SUBF_PROG_BLOCKSTAT2, "Block status v2" },
797 { S7COMM_UD_SUBF_PROG_FLASHLED, "Flash LED" },
798 { 0, NULL }
799 };
800
801 /**************************************************************************
802 * Variable status: Trigger point
803 */
804 static const value_string userdata_varstat_trgevent_names[] = {
805 { 0x0000, "Immediately" },
806 { 0x0100, "System Trigger" },
807 { 0x0200, "System checkpoint main cycle start" },
808 { 0x0300, "System checkpoint main cycle end" },
809 { 0x0400, "Mode transition RUN-STOP" },
810 { 0x0500, "After code address" },
811 { 0x0600, "Code address area" },
812 { 0x0601, "Code address area with call environment" }, /* Call conditions like opened DB/DI or called block */
813 { 0x0700, "Data address" },
814 { 0x0800, "Data address area" },
815 { 0x0900, "Local data address" },
816 { 0x0a00, "Local data address area" },
817 { 0x0b00, "Range trigger" },
818 { 0x0c00, "Before code address" },
819 { 0, NULL }
820 };
821
822 /**************************************************************************
823 * Names of userdata subfunctions in group 2 (cyclic data)
824 */
825 #define S7COMM_UD_SUBF_CYCLIC_TRANSF 0x01
826 #define S7COMM_UD_SUBF_CYCLIC_UNSUBSCRIBE 0x04
827 #define S7COMM_UD_SUBF_CYCLIC_CHANGE 0x05
828 #define S7COMM_UD_SUBF_CYCLIC_CHANGE_MOD 0x07
829 #define S7COMM_UD_SUBF_CYCLIC_RDREC 0x08
830
831 static const value_string userdata_cyclic_subfunc_names[] = {
832 { S7COMM_UD_SUBF_CYCLIC_TRANSF, "Cyclic transfer" },
833 { S7COMM_UD_SUBF_CYCLIC_UNSUBSCRIBE, "Unsubscribe" },
834 { S7COMM_UD_SUBF_CYCLIC_CHANGE, "Change driven transfer" },
835 { S7COMM_UD_SUBF_CYCLIC_CHANGE_MOD, "Change driven transfer modify" },
836 { S7COMM_UD_SUBF_CYCLIC_RDREC, "RDREC" },
837 { 0, NULL }
838 };
839
840 /**************************************************************************
841 * Timebase for cyclic services
842 */
843 static const value_string cycl_interval_timebase_names[] = {
844 { 0, "100 milliseconds" },
845 { 1, "1 second" },
846 { 2, "10 seconds" },
847 { 0, NULL }
848 };
849
850 /**************************************************************************
851 * Names of userdata subfunctions in group 3 (Block functions)
852 */
853 #define S7COMM_UD_SUBF_BLOCK_LIST 0x01
854 #define S7COMM_UD_SUBF_BLOCK_LISTTYPE 0x02
855 #define S7COMM_UD_SUBF_BLOCK_BLOCKINFO 0x03
856
857 static const value_string userdata_block_subfunc_names[] = {
858 { S7COMM_UD_SUBF_BLOCK_LIST, "List blocks" },
859 { S7COMM_UD_SUBF_BLOCK_LISTTYPE, "List blocks of type" },
860 { S7COMM_UD_SUBF_BLOCK_BLOCKINFO, "Get block info" },
861 { 0, NULL }
862 };
863
864 /**************************************************************************
865 * Names of userdata subfunctions in group 4 (CPU functions)
866 */
867 #define S7COMM_UD_SUBF_CPU_SCAN_IND 0x09
868
869 static const value_string userdata_cpu_subfunc_names[] = {
870 { S7COMM_UD_SUBF_CPU_READSZL, "Read SZL" },
871 { S7COMM_UD_SUBF_CPU_MSGS, "Message service" }, /* Header constant is also different here */
872 { S7COMM_UD_SUBF_CPU_DIAGMSG, "Diagnostic message" }, /* Diagnostic message from PLC */
873 { S7COMM_UD_SUBF_CPU_ALARM8_IND, "ALARM_8 indication" }, /* PLC is indicating an ALARM message, using ALARM_8 SFBs */
874 { S7COMM_UD_SUBF_CPU_NOTIFY_IND, "NOTIFY indication" }, /* PLC is indicating a NOTIFY message, using NOTIFY SFBs */
875 { S7COMM_UD_SUBF_CPU_ALARM8LOCK, "ALARM_8 lock" }, /* Lock an ALARM message from HMI/SCADA */
876 { S7COMM_UD_SUBF_CPU_ALARM8UNLOCK, "ALARM_8 unlock" }, /* Unlock an ALARM message from HMI/SCADA */
877 { S7COMM_UD_SUBF_CPU_SCAN_IND, "SCAN indication" }, /* PLC is indicating a SCAN message */
878 { S7COMM_UD_SUBF_CPU_ALARMS_IND, "ALARM_S indication" }, /* PLC is indicating an ALARM message, using ALARM_S/ALARM_D SFCs */
879 { S7COMM_UD_SUBF_CPU_ALARMSQ_IND, "ALARM_SQ indication" }, /* PLC is indicating an ALARM message, using ALARM_SQ/ALARM_DQ SFCs */
880 { S7COMM_UD_SUBF_CPU_ALARMQUERY, "ALARM query" }, /* HMI/SCADA query of ALARMs */
881 { S7COMM_UD_SUBF_CPU_ALARMACK, "ALARM ack" }, /* Alarm was acknowledged in HMI/SCADA */
882 { S7COMM_UD_SUBF_CPU_ALARMACK_IND, "ALARM ack indication" }, /* Alarm acknowledge indication from CPU to HMI */
883 { S7COMM_UD_SUBF_CPU_ALARM8LOCK_IND, "ALARM lock indication" }, /* Alarm lock indication from CPU to HMI */
884 { S7COMM_UD_SUBF_CPU_ALARM8UNLOCK_IND, "ALARM unlock indication" }, /* Alarm unlock indication from CPU to HMI */
885 { S7COMM_UD_SUBF_CPU_NOTIFY8_IND, "NOTIFY_8 indication" },
886 { 0, NULL }
887 };
888
889 /**************************************************************************
890 * Names of userdata subfunctions in group 5 (Security?)
891 */
892 #define S7COMM_UD_SUBF_SEC_PASSWD 0x01
893
894 static const value_string userdata_sec_subfunc_names[] = {
895 { S7COMM_UD_SUBF_SEC_PASSWD, "PLC password" },
896 { 0, NULL }
897 };
898
899 /**************************************************************************
900 * Names of userdata subfunctions in group 7 (Time functions)
901 */
902 #define S7COMM_UD_SUBF_TIME_READ 0x01
903 #define S7COMM_UD_SUBF_TIME_SET 0x02
904 #define S7COMM_UD_SUBF_TIME_READF 0x03
905 #define S7COMM_UD_SUBF_TIME_SET2 0x04
906
907 static const value_string userdata_time_subfunc_names[] = {
908 { S7COMM_UD_SUBF_TIME_READ, "Read clock" },
909 { S7COMM_UD_SUBF_TIME_SET, "Set clock" },
910 { S7COMM_UD_SUBF_TIME_READF, "Read clock (following)" },
911 { S7COMM_UD_SUBF_TIME_SET2, "Set clock" },
912 { 0, NULL }
913 };
914
915 /*******************************************************************************************************
916 * Weekday names in DATE_AND_TIME
917 */
918 static const value_string weekdaynames[] = {
919 { 0, "Undefined" },
920 { 1, "Sunday" },
921 { 2, "Monday" },
922 { 3, "Tuesday" },
923 { 4, "Wednesday" },
924 { 5, "Thursday" },
925 { 6, "Friday" },
926 { 7, "Saturday" },
927 { 0, NULL }
928 };
929
930 /**************************************************************************
931 **************************************************************************/
932
933 /**************************************************************************
934 * Flags for LID access
935 */
936 #define S7COMM_TIA1200_VAR_ENCAPS_LID 0x2
937 #define S7COMM_TIA1200_VAR_ENCAPS_IDX 0x3
938 #define S7COMM_TIA1200_VAR_OBTAIN_LID 0x4
939 #define S7COMM_TIA1200_VAR_OBTAIN_IDX 0x5
940 #define S7COMM_TIA1200_VAR_PART_START 0x6
941 #define S7COMM_TIA1200_VAR_PART_LEN 0x7
942
943 static const value_string tia1200_var_lid_flag_names[] = {
944 { S7COMM_TIA1200_VAR_ENCAPS_LID, "Encapsulated LID" },
945 { S7COMM_TIA1200_VAR_ENCAPS_IDX, "Encapsulated Index" },
946 { S7COMM_TIA1200_VAR_OBTAIN_LID, "Obtain by LID" },
947 { S7COMM_TIA1200_VAR_OBTAIN_IDX, "Obtain by Index" },
948 { S7COMM_TIA1200_VAR_PART_START, "Part Start Address" },
949 { S7COMM_TIA1200_VAR_PART_LEN, "Part Length" },
950 { 0, NULL }
951 };
952
953 /**************************************************************************
954 * TIA 1200 Area Names for variable access
955 */
956 #define S7COMM_TIA1200_VAR_ITEM_AREA1_DB 0x8a0e /* Reading DB, 2 byte DB-Number following */
957 #define S7COMM_TIA1200_VAR_ITEM_AREA1_IQMCT 0x0000 /* Reading I/Q/M/C/T, 2 Byte detail area following */
958
959 static const value_string tia1200_var_item_area1_names[] = {
960 { S7COMM_TIA1200_VAR_ITEM_AREA1_DB, "DB" },
961 { S7COMM_TIA1200_VAR_ITEM_AREA1_IQMCT, "IQMCT" },
962 { 0, NULL }
963 };
964
965 #define S7COMM_TIA1200_VAR_ITEM_AREA2_I 0x50
966 #define S7COMM_TIA1200_VAR_ITEM_AREA2_Q 0x51
967 #define S7COMM_TIA1200_VAR_ITEM_AREA2_M 0x52
968 #define S7COMM_TIA1200_VAR_ITEM_AREA2_C 0x53
969 #define S7COMM_TIA1200_VAR_ITEM_AREA2_T 0x54
970
971 static const value_string tia1200_var_item_area2_names[] = {
972 { S7COMM_TIA1200_VAR_ITEM_AREA2_I, "Inputs (I)" },
973 { S7COMM_TIA1200_VAR_ITEM_AREA2_Q, "Outputs (Q)" },
974 { S7COMM_TIA1200_VAR_ITEM_AREA2_M, "Flags (M)" },
975 { S7COMM_TIA1200_VAR_ITEM_AREA2_C, "Counter (C)" },
976 { S7COMM_TIA1200_VAR_ITEM_AREA2_T, "Timer (T)" },
977 { 0, NULL }
978 };
979
980 /**************************************************************************
981 * NCK areas
982 */
983 #define S7COMM_NCK_AREA_N_NCK 0
984 #define S7COMM_NCK_AREA_B_MODEGROUP 1
985 #define S7COMM_NCK_AREA_C_CHANNEL 2
986 #define S7COMM_NCK_AREA_A_AXIS 3
987 #define S7COMM_NCK_AREA_T_TOOL 4
988 #define S7COMM_NCK_AREA_V_FEEDDRIVE 5
989 #define S7COMM_NCK_AREA_H_MAINDRIVE 6
990 #define S7COMM_NCK_AREA_M_MMC 7
991
992 static const value_string nck_area_names[] = {
993 { S7COMM_NCK_AREA_N_NCK, "N - NCK" },
994 { S7COMM_NCK_AREA_B_MODEGROUP, "B - Mode group" },
995 { S7COMM_NCK_AREA_C_CHANNEL, "C - Channel" },
996 { S7COMM_NCK_AREA_A_AXIS, "A - Axis" },
997 { S7COMM_NCK_AREA_T_TOOL, "T - Tool" },
998 { S7COMM_NCK_AREA_V_FEEDDRIVE, "V - Feed drive" },
999 { S7COMM_NCK_AREA_H_MAINDRIVE, "M - Main drive" },
1000 { S7COMM_NCK_AREA_M_MMC, "M - MMC" },
1001 { 0, NULL }
1002 };
1003
1004 static const value_string nck_module_names[] = {
1005 { 0x10, "Y - Global system data" },
1006 { 0x11, "YNCFL - NCK instruction groups" },
1007 { 0x12, "FU - NCU global settable frames" },
1008 { 0x13, "FA - Active NCU global frames" },
1009 { 0x14, "TO - Tool data" },
1010 { 0x15, "RP - Arithmetic parameters" },
1011 { 0x16, "SE - Setting data" },
1012 { 0x17, "SGUD - SGUD-Block" },
1013 { 0x18, "LUD - Local userdata" },
1014 { 0x19, "TC - Toolholder parameters" },
1015 { 0x1a, "M - Machine data" },
1016 { 0x1c, "WAL - Working area limitation" },
1017 { 0x1e, "DIAG - Internal diagnostic data" },
1018 { 0x1f, "CC - Unknown" },
1019 { 0x20, "FE - Channel-specific external frame" },
1020 { 0x21, "TD - Tool data: General data" },
1021 { 0x22, "TS - Tool edge data: Monitoring data" },
1022 { 0x23, "TG - Tool data: Grinding-specific data" },
1023 { 0x24, "TU - Tool data" },
1024 { 0x25, "TUE - Tool edge data, userdefined data" },
1025 { 0x26, "TV - Tool data, directory" },
1026 { 0x27, "TM - Magazine data: General data" },
1027 { 0x28, "TP - Magazine data: Location data" },
1028 { 0x29, "TPM - Magazine data: Multiple assignment of location data" },
1029 { 0x2a, "TT - Magazine data: Location typ" },
1030 { 0x2b, "TMV - Magazine data: Directory" },
1031 { 0x2c, "TMC - Magazine data: Configuration data" },
1032 { 0x2d, "MGUD - MGUD-Block" },
1033 { 0x2e, "UGUD - UGUD-Block" },
1034 { 0x2f, "GUD4 - GUD4-Block" },
1035 { 0x30, "GUD5 - GUD5-Block" },
1036 { 0x31, "GUD6 - GUD6-Block" },
1037 { 0x32, "GUD7 - GUD7-Block" },
1038 { 0x33, "GUD8 - GUD8-Block" },
1039 { 0x34, "GUD9 - GUD9-Block" },
1040 { 0x35, "PA - Channel-specific protection zones" },
1041 { 0x36, "GD1 - SGUD-Block GD1" },
1042 { 0x37, "NIB - State data: Nibbling" },
1043 { 0x38, "ETP - Types of events" },
1044 { 0x39, "ETPD - Data lists for protocolling" },
1045 { 0x3a, "SYNACT - Channel-specific synchronous actions" },
1046 { 0x3b, "DIAGN - Diagnostic data" },
1047 { 0x3c, "VSYN - Channel-specific user variables for synchronous actions" },
1048 { 0x3d, "TUS - Tool data: user monitoring data" },
1049 { 0x3e, "TUM - Tool data: user magazine data" },
1050 { 0x3f, "TUP - Tool data: user magazine place data" },
1051 { 0x40, "TF - Parameterizing, return parameters of _N_TMGETT, _N_TSEARC" },
1052 { 0x41, "FB - Channel-specific base frames" },
1053 { 0x42, "SSP2 - State data: Spindle" },
1054 { 0x43, "PUD - programmglobale Benutzerdaten" },
1055 { 0x44, "TOS - Edge-related location-dependent fine total offsets" },
1056 { 0x45, "TOST - Edge-related location-dependent fine total offsets, transformed" },
1057 { 0x46, "TOE - Edge-related coarse total offsets, setup offsets" },
1058 { 0x47, "TOET - Edge-related coarse total offsets, transformed setup offsets" },
1059 { 0x48, "AD - Adapter data" },
1060 { 0x49, "TOT - Edge data: Transformed offset data" },
1061 { 0x4a, "AEV - Working offsets: Directory" },
1062 { 0x4b, "YFAFL - NCK instruction groups (Fanuc)" },
1063 { 0x4c, "FS - System-Frame" },
1064 { 0x4d, "SD - Servo data" },
1065 { 0x4e, "TAD - Application-specific data" },
1066 { 0x4f, "TAO - Application-specific cutting edge data" },
1067 { 0x50, "TAS - Application-specific monitoring data" },
1068 { 0x51, "TAM - Application-specific magazine data" },
1069 { 0x52, "TAP - Application-specific magazine location data" },
1070 { 0x53, "MEM - Unknown" },
1071 { 0x54, "SALUC - Alarm actions: List in reverse chronological order" },
1072 { 0x55, "AUXFU - Auxiliary functions" },
1073 { 0x56, "TDC - Tool/Tools" },
1074 { 0x57, "CP - Generic coupling" },
1075 { 0x6e, "SDME - Unknown" },
1076 { 0x6f, "SPARPI - Program pointer on interruption" },
1077 { 0x70, "SEGA - State data: Geometry axes in tool offset memory (extended)" },
1078 { 0x71, "SEMA - State data: Machine axes (extended)" },
1079 { 0x72, "SSP - State data: Spindle" },
1080 { 0x73, "SGA - State data: Geometry axes in tool offset memory" },
1081 { 0x74, "SMA - State data: Machine axes" },
1082 { 0x75, "SALAL - Alarms: List organized according to time" },
1083 { 0x76, "SALAP - Alarms: List organized according to priority" },
1084 { 0x77, "SALA - Alarms: List organized according to time" },
1085 { 0x78, "SSYNAC - Synchronous actions" },
1086 { 0x79, "SPARPF - Program pointers for block search and stop run" },
1087 { 0x7a, "SPARPP - Program pointer in automatic operation" },
1088 { 0x7b, "SNCF - Active G functions" },
1089 { 0x7d, "SPARP - Part program information" },
1090 { 0x7e, "SINF - Part-program-specific status data" },
1091 { 0x7f, "S - State data" },
1092 { 0x80, "0x80 - Unknown" },
1093 { 0x81, "0x81 - Unknown" },
1094 { 0x82, "0x82 - Unknown" },
1095 { 0x83, "0x83 - Unknown" },
1096 { 0x84, "0x84 - Unknown" },
1097 { 0x85, "0x85 - Unknown" },
1098 { 0xfd, "0 - Internal" },
1099 { 0, NULL }
1100 };
1101 static value_string_ext nck_module_names_ext = VALUE_STRING_EXT_INIT(nck_module_names);
1102
1103 static gint hf_s7comm_tia1200_item_reserved1 = -1; /* 1 Byte Reserved (always 0xff?) */
1104 static gint hf_s7comm_tia1200_item_area1 = -1; /* 2 Byte2 Root area (DB or IQMCT) */
1105 static gint hf_s7comm_tia1200_item_area2 = -1; /* 2 Bytes detail area (I/Q/M/C/T) */
1106 static gint hf_s7comm_tia1200_item_area2unknown = -1; /* 2 Bytes detail area for possible unknown or not seen areas */
1107 static gint hf_s7comm_tia1200_item_dbnumber = -1; /* 2 Bytes DB number */
1108 static gint hf_s7comm_tia1200_item_crc = -1; /* 4 Bytes CRC */
1109
1110 static gint hf_s7comm_tia1200_substructure_item = -1; /* Substructure */
1111 static gint hf_s7comm_tia1200_var_lid_flags = -1; /* LID Flags */
1112 static gint hf_s7comm_tia1200_item_value = -1;
1113
1114 /**************************************************************************
1115 **************************************************************************/
1116
1117 /* Header Block */
1118 static gint hf_s7comm_header = -1;
1119 static gint hf_s7comm_header_protid = -1; /* Header Byte 0 */
1120 static gint hf_s7comm_header_rosctr = -1; /* Header Bytes 1 */
1121 static gint hf_s7comm_header_redid = -1; /* Header Bytes 2, 3 */
1122 static gint hf_s7comm_header_pduref = -1; /* Header Bytes 4, 5 */
1123 static gint hf_s7comm_header_parlg = -1; /* Header Bytes 6, 7 */
1124 static gint hf_s7comm_header_datlg = -1; /* Header Bytes 8, 9 */
1125 static gint hf_s7comm_header_errcls = -1; /* Header Byte 10, only available at type 2 or 3 */
1126 static gint hf_s7comm_header_errcod = -1; /* Header Byte 11, only available at type 2 or 3 */
1127 /* Parameter Block */
1128 static gint hf_s7comm_param = -1;
1129 static gint hf_s7comm_param_errcod = -1; /* Parameter part: Error code */
1130 static gint hf_s7comm_param_service = -1; /* Parameter part: service */
1131 static gint hf_s7comm_param_itemcount = -1; /* Parameter part: item count */
1132 static gint hf_s7comm_param_data = -1; /* Parameter part: data */
1133 static gint hf_s7comm_param_neg_pdu_length = -1; /* Parameter part: Negotiate PDU length */
1134 static gint hf_s7comm_param_setup_reserved1 = -1; /* Parameter part: Reserved byte in communication setup pdu*/
1135
1136 static gint hf_s7comm_param_maxamq_calling = -1; /* Parameter part: Max AmQ calling */
1137 static gint hf_s7comm_param_maxamq_called = -1; /* Parameter part: Max AmQ called */
1138
1139 /* Item data */
1140 static gint hf_s7comm_param_item = -1;
1141 static gint hf_s7comm_param_subitem = -1; /* Substructure */
1142 static gint hf_s7comm_item_varspec = -1; /* Variable specification */
1143 static gint hf_s7comm_item_varspec_length = -1; /* Length of following address specification */
1144 static gint hf_s7comm_item_syntax_id = -1; /* Syntax Id */
1145 static gint hf_s7comm_item_transport_size = -1; /* Transport size, 1 Byte*/
1146 static gint hf_s7comm_item_length = -1; /* length, 2 Bytes*/
1147 static gint hf_s7comm_item_db = -1; /* DB/M/E/A, 2 Bytes */
1148 static gint hf_s7comm_item_area = -1; /* Area code, 1 byte */
1149 static gint hf_s7comm_item_address = -1; /* Bit address, 3 Bytes */
1150 static gint hf_s7comm_item_address_byte = -1; /* address: Byte address */
1151 static gint hf_s7comm_item_address_bit = -1; /* address: Bit address */
1152 static gint hf_s7comm_item_address_nr = -1; /* address: Timer/Counter/block number */
1153 /* Special variable read with Syntax-Id 0xb0 (DBREAD) */
1154 static gint hf_s7comm_item_dbread_numareas = -1; /* Number of areas following, 1 Byte*/
1155 static gint hf_s7comm_item_dbread_length = -1; /* length, 1 Byte*/
1156 static gint hf_s7comm_item_dbread_db = -1; /* DB number, 2 Bytes*/
1157 static gint hf_s7comm_item_dbread_startadr = -1; /* Start address, 2 Bytes*/
1158 /* Reading frequency inverter parameters via routing */
1159 static gint hf_s7comm_item_driveesany_unknown1 = -1; /* Unknown value 1, 1 Byte */
1160 static gint hf_s7comm_item_driveesany_unknown2 = -1; /* Unknown value 2, 2 Bytes */
1161 static gint hf_s7comm_item_driveesany_unknown3 = -1; /* Unknown value 3, 2 Bytes */
1162 static gint hf_s7comm_item_driveesany_parameter_nr = -1; /* Parameter number, 2 Bytes */
1163 static gint hf_s7comm_item_driveesany_parameter_idx = -1; /* Parameter index, 2 Bytes */
1164 /* NCK access with Syntax-Id 0x82 */
1165 static gint hf_s7comm_item_nck_areaunit = -1; /* Bitmask: aaauuuuu: a=area, u=unit */
1166 static gint hf_s7comm_item_nck_area = -1;
1167 static gint hf_s7comm_item_nck_unit = -1;
1168 static gint hf_s7comm_item_nck_column = -1;
1169 static gint hf_s7comm_item_nck_line = -1;
1170 static gint hf_s7comm_item_nck_module = -1;
1171 static gint hf_s7comm_item_nck_linecount = -1;
1172
1173 static gint hf_s7comm_data = -1;
1174 static gint hf_s7comm_data_returncode = -1; /* return code, 1 byte */
1175 static gint hf_s7comm_data_transport_size = -1; /* transport size 1 byte */
1176 static gint hf_s7comm_data_length = -1; /* Length of data, 2 Bytes */
1177
1178 static gint hf_s7comm_data_item = -1;
1179
1180 static gint hf_s7comm_readresponse_data = -1;
1181 static gint hf_s7comm_data_fillbyte = -1;
1182
1183 /* timefunction: s7 timestamp */
1184 static gint hf_s7comm_data_ts = -1;
1185 static gint hf_s7comm_data_ts_reserved = -1;
1186 static gint hf_s7comm_data_ts_year1 = -1; /* first byte of BCD coded year, should be ignored */
1187 static gint hf_s7comm_data_ts_year2 = -1; /* second byte of BCD coded year, if 00...89 then it's 2000...2089, else 1990...1999*/
1188 static gint hf_s7comm_data_ts_month = -1;
1189 static gint hf_s7comm_data_ts_day = -1;
1190 static gint hf_s7comm_data_ts_hour = -1;
1191 static gint hf_s7comm_data_ts_minute = -1;
1192 static gint hf_s7comm_data_ts_second = -1;
1193 static gint hf_s7comm_data_ts_millisecond = -1;
1194 static gint hf_s7comm_data_ts_weekday = -1;
1195
1196 /* userdata, block services */
1197 static gint hf_s7comm_userdata_data = -1;
1198
1199 static gint hf_s7comm_userdata_param_head = -1;
1200 static gint hf_s7comm_userdata_param_len = -1;
1201 static gint hf_s7comm_userdata_param_reqres2 = -1;
1202 static gint hf_s7comm_userdata_param_type = -1;
1203 static gint hf_s7comm_userdata_param_funcgroup = -1;
1204 static gint hf_s7comm_userdata_param_subfunc_prog = -1;
1205 static gint hf_s7comm_userdata_param_subfunc_cyclic = -1;
1206 static gint hf_s7comm_userdata_param_subfunc_block = -1;
1207 static gint hf_s7comm_userdata_param_subfunc_cpu = -1;
1208 static gint hf_s7comm_userdata_param_subfunc_sec = -1;
1209 static gint hf_s7comm_userdata_param_subfunc_time = -1;
1210 static gint hf_s7comm_userdata_param_subfunc_ncprg = -1;
1211 static gint hf_s7comm_userdata_param_subfunc = -1; /* for all other subfunctions */
1212 static gint hf_s7comm_userdata_param_seq_num = -1;
1213 static gint hf_s7comm_userdata_param_dataunitref = -1;
1214 static gint hf_s7comm_userdata_param_dataunit = -1;
1215
1216 /* block functions, list blocks of type */
1217 static gint hf_s7comm_ud_blockinfo_block_type = -1; /* Block type, 2 bytes */
1218 static gint hf_s7comm_ud_blockinfo_block_num = -1; /* Block number, 2 bytes as int */
1219 static gint hf_s7comm_ud_blockinfo_block_cnt = -1; /* Count, 2 bytes as int */
1220 static gint hf_s7comm_ud_blockinfo_block_flags = -1; /* Block flags (unknown), 1 byte */
1221 static gint hf_s7comm_ud_blockinfo_block_lang = -1; /* Block language, 1 byte, stringlist blocklanguage_names */
1222 /* block functions, get block infos */
1223 static gint hf_s7comm_ud_blockinfo_block_num_ascii = -1; /* Block number, 5 bytes, ASCII*/
1224 static gint hf_s7comm_ud_blockinfo_filesys = -1; /* Filesystem, 1 byte, ASCII*/
1225 static gint hf_s7comm_ud_blockinfo_res_infolength = -1; /* Length of Info, 2 bytes as int */
1226 static gint hf_s7comm_ud_blockinfo_res_unknown2 = -1; /* Unknown blockinfo 2, 2 bytes, HEX*/
1227 static gint hf_s7comm_ud_blockinfo_res_const3 = -1; /* Constant 3, 2 bytes, ASCII */
1228 static gint hf_s7comm_ud_blockinfo_res_unknown = -1; /* Unknown byte(s) */
1229 static gint hf_s7comm_ud_blockinfo_subblk_type = -1; /* Subblk type, 1 byte, stringlist subblktype_names */
1230 static gint hf_s7comm_ud_blockinfo_load_mem_len = -1; /* Length load memory, 4 bytes, int */
1231 static gint hf_s7comm_ud_blockinfo_blocksecurity = -1; /* Block Security, 4 bytes, stringlist blocksecurity_names*/
1232 static gint hf_s7comm_ud_blockinfo_interface_timestamp = -1;/* Interface Timestamp, string */
1233 static gint hf_s7comm_ud_blockinfo_code_timestamp = -1; /* Code Timestamp, string */
1234 static gint hf_s7comm_ud_blockinfo_ssb_len = -1; /* SSB length, 2 bytes, int */
1235 static gint hf_s7comm_ud_blockinfo_add_len = -1; /* ADD length, 2 bytes, int */
1236 static gint hf_s7comm_ud_blockinfo_localdata_len = -1; /* Length localdata, 2 bytes, int */
1237 static gint hf_s7comm_ud_blockinfo_mc7_len = -1; /* Length MC7 code, 2 bytes, int */
1238 static gint hf_s7comm_ud_blockinfo_author = -1; /* Author, 8 bytes, ASCII */
1239 static gint hf_s7comm_ud_blockinfo_family = -1; /* Family, 8 bytes, ASCII */
1240 static gint hf_s7comm_ud_blockinfo_headername = -1; /* Name (Header), 8 bytes, ASCII */
1241 static gint hf_s7comm_ud_blockinfo_headerversion = -1; /* Version (Header), 8 bytes, ASCII */
1242 static gint hf_s7comm_ud_blockinfo_checksum = -1; /* Block checksum, 2 bytes, HEX */
1243 static gint hf_s7comm_ud_blockinfo_reserved1 = -1; /* Reserved 1, 4 bytes, HEX */
1244 static gint hf_s7comm_ud_blockinfo_reserved2 = -1; /* Reserved 2, 4 bytes, HEX */
1245
1246 static gint hf_s7comm_userdata_blockinfo_flags = -1; /* Some flags in Block info response */
1247 static gint hf_s7comm_userdata_blockinfo_linked = -1; /* Some flags in Block info response */
1248 static gint hf_s7comm_userdata_blockinfo_standard_block = -1;
1249 static gint hf_s7comm_userdata_blockinfo_nonretain = -1; /* Some flags in Block info response */
1250 static gint ett_s7comm_userdata_blockinfo_flags = -1;
1251 static int * const s7comm_userdata_blockinfo_flags_fields[] = {
1252 &hf_s7comm_userdata_blockinfo_linked,
1253 &hf_s7comm_userdata_blockinfo_standard_block,
1254 &hf_s7comm_userdata_blockinfo_nonretain,
1255 NULL
1256 };
1257
1258 /* Programmer commands / Test and installation (TIS) functions */
1259 static gint hf_s7comm_tis_parameter = -1;
1260 static gint hf_s7comm_tis_data = -1;
1261 static gint hf_s7comm_tis_parametersize = -1;
1262 static gint hf_s7comm_tis_datasize = -1;
1263 static gint hf_s7comm_tis_param1 = -1;
1264 static gint hf_s7comm_tis_param2 = -1;
1265 static const value_string tis_param2_names[] = { /* Values and their meaning are not always clearly defined in every function */
1266 { 0, "Update Monitor Variables / Activate Modify Values"},
1267 { 1, "Monitor Variable / Modify Variable" },
1268 { 2, "Modify Variable permanent" },
1269 { 256, "Force immediately" },
1270 { 0, NULL }
1271 };
1272 static gint hf_s7comm_tis_param3 = -1;
1273 static const value_string tis_param3_names[] = {
1274 { 0, "Every cycle (permanent)" },
1275 { 1, "Once" },
1276 { 2, "Always (force)" },
1277 { 0, NULL }
1278 };
1279 static gint hf_s7comm_tis_answersize = -1;
1280 static gint hf_s7comm_tis_param5 = -1;
1281 static gint hf_s7comm_tis_param6 = -1;
1282 static gint hf_s7comm_tis_param7 = -1;
1283 static gint hf_s7comm_tis_param8 = -1;
1284 static gint hf_s7comm_tis_param9 = -1;
1285 static gint hf_s7comm_tis_trgevent = -1;
1286 static gint hf_s7comm_tis_res_param1 = -1;
1287 static gint hf_s7comm_tis_res_param2 = -1;
1288 static gint hf_s7comm_tis_job_function = -1;
1289 static gint hf_s7comm_tis_job_seqnr = -1;
1290 static gint hf_s7comm_tis_job_reserved = -1;
1291
1292
1293
1294 /* B/I/L Stack */
1295 static gint hf_s7comm_tis_interrupted_blocktype = -1;
1296 static gint hf_s7comm_tis_interrupted_blocknr = -1;
1297 static gint hf_s7comm_tis_interrupted_address = -1;
1298 static gint hf_s7comm_tis_interrupted_prioclass = -1;
1299 static gint hf_s7comm_tis_continued_blocktype = -1;
1300 static gint hf_s7comm_tis_continued_blocknr = -1;
1301 static gint hf_s7comm_tis_continued_address = -1;
1302 static gint hf_s7comm_tis_breakpoint_blocktype = -1;
1303 static gint hf_s7comm_tis_breakpoint_blocknr = -1;
1304 static gint hf_s7comm_tis_breakpoint_address = -1;
1305 static gint hf_s7comm_tis_breakpoint_reserved = -1;
1306
1307 static gint hf_s7comm_tis_p_callenv = -1;
1308 static const value_string tis_p_callenv_names[] = {
1309 { 0, "Specified call environment"},
1310 { 2, "Specified global and/or instance data block"},
1311 { 0, NULL }
1312 };
1313 static gint hf_s7comm_tis_p_callcond = -1;
1314 static const value_string tis_p_callcond_names[] = {
1315 { 0x0000, "Not set" },
1316 { 0x0001, "On block number" },
1317 { 0x0101, "On block number with code address" },
1318 { 0x0a00, "On DB1 (DB) content" },
1319 { 0x000a, "On DB2 (DI) content" },
1320 { 0x0a0a, "On DB1 (DB) and DB2 (DI) content" },
1321 { 0, NULL }
1322 };
1323 static gint hf_s7comm_tis_p_callcond_blocktype = -1;
1324 static gint hf_s7comm_tis_p_callcond_blocknr = -1;
1325 static gint hf_s7comm_tis_p_callcond_address = -1;
1326
1327
1328 static gint hf_s7comm_tis_register_db1_type = -1;
1329 static gint hf_s7comm_tis_register_db2_type = -1;
1330 static gint hf_s7comm_tis_register_db1_nr = -1;
1331 static gint hf_s7comm_tis_register_db2_nr = -1;
1332 static gint hf_s7comm_tis_register_accu1 = -1;
1333 static gint hf_s7comm_tis_register_accu2 = -1;
1334 static gint hf_s7comm_tis_register_accu3 = -1;
1335 static gint hf_s7comm_tis_register_accu4 = -1;
1336 static gint hf_s7comm_tis_register_ar1 = -1;
1337 static gint hf_s7comm_tis_register_ar2 = -1;
1338 static gint hf_s7comm_tis_register_stw = -1;
1339 static gint hf_s7comm_tis_exithold_until = -1;
1340 static const value_string tis_exithold_until_names[] = {
1341 { 0, "Next breakpoint" },
1342 { 1, "Next statement" },
1343 { 0, NULL }
1344 };
1345 static gint hf_s7comm_tis_exithold_res1 = -1;
1346 static gint hf_s7comm_tis_bstack_nest_depth = -1;
1347 static gint hf_s7comm_tis_bstack_reserved = -1;
1348 static gint hf_s7comm_tis_istack_reserved = -1;
1349 static gint hf_s7comm_tis_lstack_reserved = -1;
1350 static gint hf_s7comm_tis_lstack_size = -1;
1351 static gint hf_s7comm_tis_lstack_data = -1;
1352 static gint hf_s7comm_tis_blockstat_flagsunknown = -1;
1353 static gint hf_s7comm_tis_blockstat_number_of_lines = -1;
1354 static gint hf_s7comm_tis_blockstat_line_address = -1;
1355 static gint hf_s7comm_tis_blockstat_data = -1;
1356 static gint hf_s7comm_tis_blockstat_reserved = -1;
1357
1358 /* Organization block local data */
1359 static gint hf_s7comm_ob_ev_class = -1;
1360 static gint hf_s7comm_ob_scan_1 = -1;
1361 static gint hf_s7comm_ob_strt_inf = -1;
1362 static gint hf_s7comm_ob_flt_id = -1;
1363 static gint hf_s7comm_ob_priority = -1;
1364 static gint hf_s7comm_ob_number = -1;
1365 static gint hf_s7comm_ob_reserved_1 = -1;
1366 static gint hf_s7comm_ob_reserved_2 = -1;
1367 static gint hf_s7comm_ob_reserved_3 = -1;
1368 static gint hf_s7comm_ob_reserved_4 = -1;
1369 static gint hf_s7comm_ob_reserved_4_dw = -1;
1370 static gint hf_s7comm_ob_prev_cycle = -1;
1371 static gint hf_s7comm_ob_min_cycle = -1;
1372 static gint hf_s7comm_ob_max_cycle = -1;
1373 static gint hf_s7comm_ob_period_exe = -1;
1374 static gint hf_s7comm_ob_sign = -1;
1375 static gint hf_s7comm_ob_dtime = -1;
1376 static gint hf_s7comm_ob_phase_offset = -1;
1377 static gint hf_s7comm_ob_exec_freq = -1;
1378 static gint hf_s7comm_ob_io_flag = -1;
1379 static gint hf_s7comm_ob_mdl_addr = -1;
1380 static gint hf_s7comm_ob_point_addr = -1;
1381 static gint hf_s7comm_ob_inf_len = -1;
1382 static gint hf_s7comm_ob_alarm_type = -1;
1383 static gint hf_s7comm_ob_alarm_slot = -1;
1384 static gint hf_s7comm_ob_alarm_spec = -1;
1385 static gint hf_s7comm_ob_error_info = -1;
1386 static gint hf_s7comm_ob_err_ev_class = -1;
1387 static gint hf_s7comm_ob_err_ev_num = -1;
1388 static gint hf_s7comm_ob_err_ob_priority = -1;
1389 static gint hf_s7comm_ob_err_ob_num = -1;
1390 static gint hf_s7comm_ob_rack_cpu = -1;
1391 static gint hf_s7comm_ob_8x_fault_flags = -1;
1392 static gint hf_s7comm_ob_mdl_type_b = -1;
1393 static gint hf_s7comm_ob_mdl_type_w = -1;
1394 static gint hf_s7comm_ob_rack_num = -1;
1395 static gint hf_s7comm_ob_racks_flt = -1;
1396 static gint hf_s7comm_ob_strtup = -1;
1397 static gint hf_s7comm_ob_stop = -1;
1398 static gint hf_s7comm_ob_strt_info = -1;
1399 static gint hf_s7comm_ob_sw_flt = -1;
1400 static gint hf_s7comm_ob_blk_type = -1;
1401 static gint hf_s7comm_ob_flt_reg = -1;
1402 static gint hf_s7comm_ob_flt_blk_num = -1;
1403 static gint hf_s7comm_ob_prg_addr = -1;
1404 static gint hf_s7comm_ob_mem_area = -1;
1405 static gint hf_s7comm_ob_mem_addr = -1;
1406
1407 static gint hf_s7comm_diagdata_req_block_type = -1;
1408 static gint hf_s7comm_diagdata_req_block_num = -1;
1409 static gint hf_s7comm_diagdata_req_startaddr_awl = -1;
1410 static gint hf_s7comm_diagdata_req_saz = -1;
1411
1412 /* Flags for requested registers in diagnostic data telegrams */
1413 static gint hf_s7comm_diagdata_registerflag = -1; /* Registerflags */
1414 static gint hf_s7comm_diagdata_registerflag_stw = -1; /* STW = Status word */
1415 static gint hf_s7comm_diagdata_registerflag_accu1 = -1; /* Accumulator 1 */
1416 static gint hf_s7comm_diagdata_registerflag_accu2 = -1; /* Accumulator 2 */
1417 static gint hf_s7comm_diagdata_registerflag_ar1 = -1; /* Addressregister 1 */
1418 static gint hf_s7comm_diagdata_registerflag_ar2 = -1; /* Addressregister 2 */
1419 static gint hf_s7comm_diagdata_registerflag_db1 = -1; /* Datablock register 1 */
1420 static gint hf_s7comm_diagdata_registerflag_db2 = -1; /* Datablock register 2 */
1421 static gint ett_s7comm_diagdata_registerflag = -1;
1422 static int * const s7comm_diagdata_registerflag_fields[] = {
1423 &hf_s7comm_diagdata_registerflag_stw,
1424 &hf_s7comm_diagdata_registerflag_accu1,
1425 &hf_s7comm_diagdata_registerflag_accu2,
1426 &hf_s7comm_diagdata_registerflag_ar1,
1427 &hf_s7comm_diagdata_registerflag_ar2,
1428 &hf_s7comm_diagdata_registerflag_db1,
1429 &hf_s7comm_diagdata_registerflag_db2,
1430 NULL
1431 };
1432
1433 static expert_field ei_s7comm_data_blockcontrol_block_num_invalid = EI_INIT;
1434 static expert_field ei_s7comm_ud_blockinfo_block_num_ascii_invalid = EI_INIT;
1435
1436 /* PI service name IDs. Index represents the index in pi_service_names */
1437 typedef enum
1438 {
1439 S7COMM_PI_UNKNOWN = 0,
1440 S7COMM_PI_INSE,
1441 S7COMM_PI_INS2,
1442 S7COMM_PI_DELE,
1443 S7COMM_PIP_PROGRAM,
1444 S7COMM_PI_MODU,
1445 S7COMM_PI_GARB,
1446 S7COMM_PI_N_LOGIN_,
1447 S7COMM_PI_N_LOGOUT,
1448 S7COMM_PI_N_CANCEL,
1449 S7COMM_PI_N_DASAVE,
1450 S7COMM_PI_N_DIGIOF,
1451 S7COMM_PI_N_DIGION,
1452 S7COMM_PI_N_DZERO_,
1453 S7COMM_PI_N_ENDEXT,
1454 S7COMM_PI_N_F_OPER,
1455 S7COMM_PI_N_OST_OF,
1456 S7COMM_PI_N_OST_ON,
1457 S7COMM_PI_N_SCALE_,
1458 S7COMM_PI_N_SETUFR,
1459 S7COMM_PI_N_STRTLK,
1460 S7COMM_PI_N_STRTUL,
1461 S7COMM_PI_N_TMRASS,
1462 S7COMM_PI_N_F_DELE,
1463 S7COMM_PI_N_EXTERN,
1464 S7COMM_PI_N_EXTMOD,
1465 S7COMM_PI_N_F_DELR,
1466 S7COMM_PI_N_F_XFER,
1467 S7COMM_PI_N_LOCKE_,
1468 S7COMM_PI_N_SELECT,
1469 S7COMM_PI_N_SRTEXT,
1470 S7COMM_PI_N_F_CLOS,
1471 S7COMM_PI_N_F_OPEN,
1472 S7COMM_PI_N_F_SEEK,
1473 S7COMM_PI_N_ASUP__,
1474 S7COMM_PI_N_CHEKDM,
1475 S7COMM_PI_N_CHKDNO,
1476 S7COMM_PI_N_CONFIG,
1477 S7COMM_PI_N_CRCEDN,
1478 S7COMM_PI_N_DELECE,
1479 S7COMM_PI_N_CREACE,
1480 S7COMM_PI_N_CREATO,
1481 S7COMM_PI_N_DELETO,
1482 S7COMM_PI_N_CRTOCE,
1483 S7COMM_PI_N_DELVAR,
1484 S7COMM_PI_N_F_COPY,
1485 S7COMM_PI_N_F_DMDA,
1486 S7COMM_PI_N_F_PROR,
1487 S7COMM_PI_N_F_PROT,
1488 S7COMM_PI_N_F_RENA,
1489 S7COMM_PI_N_FINDBL,
1490 S7COMM_PI_N_IBN_SS,
1491 S7COMM_PI_N_MMCSEM,
1492 S7COMM_PI_N_NCKMOD,
1493 S7COMM_PI_N_NEWPWD,
1494 S7COMM_PI_N_SEL_BL,
1495 S7COMM_PI_N_SETTST,
1496 S7COMM_PI_N_TMAWCO,
1497 S7COMM_PI_N_TMCRTC,
1498 S7COMM_PI_N_TMCRTO,
1499 S7COMM_PI_N_TMFDPL,
1500 S7COMM_PI_N_TMFPBP,
1501 S7COMM_PI_N_TMGETT,
1502 S7COMM_PI_N_TMMVTL,
1503 S7COMM_PI_N_TMPCIT,
1504 S7COMM_PI_N_TMPOSM,
1505 S7COMM_PI_N_TRESMO,
1506 S7COMM_PI_N_TSEARC
1507 } pi_service_e;
1508
1509 /* Description for PI service names */
1510 static const string_string pi_service_names[] = {
1511 { "UNKNOWN", "PI-Service is currently unknown" },
1512 { "_INSE", "PI-Service _INSE (Activates a PLC module)" },
1513 { "_INS2", "PI-Service _INS2 (Activates a PLC module)" },
1514 { "_DELE", "PI-Service _DELE (Removes module from the PLC's passive file system)" },
1515 { "P_PROGRAM", "PI-Service P_PROGRAM (PLC Start / Stop)" },
1516 { "_MODU", "PI-Service _MODU (PLC Copy Ram to Rom)" },
1517 { "_GARB", "PI-Service _GARB (Compress PLC memory)" },
1518 { "_N_LOGIN_", "PI-Service _N_LOGIN_ (Login)" },
1519 { "_N_LOGOUT", "PI-Service _N_LOGOUT (Logout)" },
1520 { "_N_CANCEL", "PI-Service _N_CANCEL (Cancels NC alarm)" },
1521 { "_N_DASAVE", "PI-Service _N_DASAVE (PI-Service for copying data from SRAM to FLASH)" },
1522 { "_N_DIGIOF", "PI-Service _N_DIGIOF (Turns off digitizing)" },
1523 { "_N_DIGION", "PI-Service _N_DIGION (Turns on digitizing)" },
1524 { "_N_DZERO_", "PI-Service _N_DZERO_ (Set all D nos. invalid for function \"unique D no.\")" },
1525 { "_N_ENDEXT", "PI-Service _N_ENDEXT ()" },
1526 { "_N_F_OPER", "PI-Service _N_F_OPER (Opens a file read-only)" },
1527 { "_N_OST_OF", "PI-Service _N_OST_OF (Overstore OFF)" },
1528 { "_N_OST_ON", "PI-Service _N_OST_ON (Overstore ON)" },
1529 { "_N_SCALE_", "PI-Service _N_SCALE_ (Unit of measurement setting (metric<->INCH))" },
1530 { "_N_SETUFR", "PI-Service _N_SETUFR (Activates user frame)" },
1531 { "_N_STRTLK", "PI-Service _N_STRTLK (The global start disable is set)" },
1532 { "_N_STRTUL", "PI-Service _N_STRTUL (The global start disable is reset)" },
1533 { "_N_TMRASS", "PI-Service _N_TMRASS (Resets the Active status)" },
1534 { "_N_F_DELE", "PI-Service _N_F_DELE (Deletes file)" },
1535 { "_N_EXTERN", "PI-Service _N_EXTERN (Selects external program for execution)" },
1536 { "_N_EXTMOD", "PI-Service _N_EXTMOD (Selects external program for execution)" },
1537 { "_N_F_DELR", "PI-Service _N_F_DELR (Delete file even without access rights)" },
1538 { "_N_F_XFER", "PI-Service _N_F_XFER (Selects file for uploading)" },
1539 { "_N_LOCKE_", "PI-Service _N_LOCKE_ (Locks the active file for editing)" },
1540 { "_N_SELECT", "PI-Service _N_SELECT (Selects program for execution)" },
1541 { "_N_SRTEXT", "PI-Service _N_SRTEXT (A file is being marked in /_N_EXT_DIR)" },
1542 { "_N_F_CLOS", "PI-Service _N_F_CLOS (Closes file)" },
1543 { "_N_F_OPEN", "PI-Service _N_F_OPEN (Opens file)" },
1544 { "_N_F_SEEK", "PI-Service _N_F_SEEK (Position the file search pointer)" },
1545 { "_N_ASUP__", "PI-Service _N_ASUP__ (Assigns interrupt)" },
1546 { "_N_CHEKDM", "PI-Service _N_CHEKDM (Start uniqueness check on D numbers)" },
1547 { "_N_CHKDNO", "PI-Service _N_CHKDNO (Check whether the tools have unique D numbers)" },
1548 { "_N_CONFIG", "PI-Service _N_CONFIG (Reconfigures machine data)" },
1549 { "_N_CRCEDN", "PI-Service _N_CRCEDN (Creates a cutting edge by specifying an edge no.)" },
1550 { "_N_DELECE", "PI-Service _N_DELECE (Deletes a cutting edge)" },
1551 { "_N_CREACE", "PI-Service _N_CREACE (Creates a cutting edge)" },
1552 { "_N_CREATO", "PI-Service _N_CREATO (Creates a tool)" },
1553 { "_N_DELETO", "PI-Service _N_DELETO (Deletes tool)" },
1554 { "_N_CRTOCE", "PI-Service _N_CRTOCE (Generate tool with specified edge number)" },
1555 { "_N_DELVAR", "PI-Service _N_DELVAR (Delete data block)" },
1556 { "_N_F_COPY", "PI-Service _N_F_COPY (Copies file within the NCK)" },
1557 { "_N_F_DMDA", "PI-Service _N_F_DMDA (Deletes MDA memory)" },
1558 { "_N_F_PROR", "PI-Service _N_F_PROR" },
1559 { "_N_F_PROT", "PI-Service _N_F_PROT (Assigns a protection level to a file)" },
1560 { "_N_F_RENA", "PI-Service _N_F_RENA (Renames file)" },
1561 { "_N_FINDBL", "PI-Service _N_FINDBL (Activates search)" },
1562 { "_N_IBN_SS", "PI-Service _N_IBN_SS (Sets the set-up switch)" },
1563 { "_N_MMCSEM", "PI-Service _N_MMCSEM (MMC-Semaphore)" },
1564 { "_N_NCKMOD", "PI-Service _N_NCKMOD (The mode in which the NCK will work is being set)" },
1565 { "_N_NEWPWD", "PI-Service _N_NEWPWD (New password)" },
1566 { "_N_SEL_BL", "PI-Service _N_SEL_BL (Selects a new block)" },
1567 { "_N_SETTST", "PI-Service _N_SETTST (Activate tools for replacement tool group)" },
1568 { "_N_TMAWCO", "PI-Service _N_TMAWCO (Set the active wear group in one magazine)" },
1569 { "_N_TMCRTC", "PI-Service _N_TMCRTC (Create tool with specified edge number)" },
1570 { "_N_TMCRTO", "PI-Service _N_TMCRTO (Creates tool in the tool management)" },
1571 { "_N_TMFDPL", "PI-Service _N_TMFDPL (Searches an empty place for loading)" },
1572 { "_N_TMFPBP", "PI-Service _N_TMFPBP (Searches for empty location)" },
1573 { "_N_TMGETT", "PI-Service _N_TMGETT (Determines T-number for specific toolID with Duplono)" },
1574 { "_N_TMMVTL", "PI-Service _N_TMMVTL (Loads or unloads a tool)" },
1575 { "_N_TMPCIT", "PI-Service _N_TMPCIT (Sets increment value of the piece counter)" },
1576 { "_N_TMPOSM", "PI-Service _N_TMPOSM (Positions a magazine or tool)" },
1577 { "_N_TRESMO", "PI-Service _N_TRESMO (Reset monitoring values)" },
1578 { "_N_TSEARC", "PI-Service _N_TSEARC (Complex search via search screenforms)" },
1579 { NULL, NULL }
1580 };
1581
1582 /* Function 0x28 (PI Start) */
1583 static gint hf_s7comm_piservice_unknown1 = -1; /* Unknown bytes */
1584 static gint hf_s7comm_piservice_parameterblock = -1;
1585 static gint hf_s7comm_piservice_parameterblock_len = -1;
1586 static gint hf_s7comm_piservice_servicename = -1;
1587
1588 static gint ett_s7comm_piservice_parameterblock = -1;
1589
1590 static gint hf_s7comm_piservice_string_len = -1;
1591 static gint hf_s7comm_pi_n_x_addressident = -1;
1592 static gint hf_s7comm_pi_n_x_password = -1;
1593 static gint hf_s7comm_pi_n_x_filename = -1;
1594 static gint hf_s7comm_pi_n_x_editwindowname = -1;
1595 static gint hf_s7comm_pi_n_x_seekpointer = -1;
1596 static gint hf_s7comm_pi_n_x_windowsize = -1;
1597 static gint hf_s7comm_pi_n_x_comparestring = -1;
1598 static gint hf_s7comm_pi_n_x_skipcount = -1;
1599 static gint hf_s7comm_pi_n_x_interruptnr = -1;
1600 static gint hf_s7comm_pi_n_x_priority = -1;
1601 static gint hf_s7comm_pi_n_x_liftfast = -1;
1602 static gint hf_s7comm_pi_n_x_blsync = -1;
1603 static gint hf_s7comm_pi_n_x_magnr = -1;
1604 static gint hf_s7comm_pi_n_x_dnr = -1;
1605 static gint hf_s7comm_pi_n_x_spindlenumber = -1;
1606 static gint hf_s7comm_pi_n_x_wznr = -1;
1607 static gint hf_s7comm_pi_n_x_class = -1;
1608 static gint hf_s7comm_pi_n_x_tnr = -1;
1609 static gint hf_s7comm_pi_n_x_toolnumber = -1;
1610 static gint hf_s7comm_pi_n_x_cenumber = -1;
1611 static gint hf_s7comm_pi_n_x_datablocknumber = -1;
1612 static gint hf_s7comm_pi_n_x_firstcolumnnumber = -1;
1613 static gint hf_s7comm_pi_n_x_lastcolumnnumber = -1;
1614 static gint hf_s7comm_pi_n_x_firstrownumber = -1;
1615 static gint hf_s7comm_pi_n_x_lastrownumber = -1;
1616 static gint hf_s7comm_pi_n_x_direction = -1;
1617 static gint hf_s7comm_pi_n_x_sourcefilename = -1;
1618 static gint hf_s7comm_pi_n_x_destinationfilename = -1;
1619 static gint hf_s7comm_pi_n_x_channelnumber = -1;
1620 static gint hf_s7comm_pi_n_x_protection = -1;
1621 static gint hf_s7comm_pi_n_x_oldfilename = -1;
1622 static gint hf_s7comm_pi_n_x_newfilename = -1;
1623 static gint hf_s7comm_pi_n_x_findmode = -1;
1624 static gint hf_s7comm_pi_n_x_switch = -1;
1625 static gint hf_s7comm_pi_n_x_functionnumber = -1;
1626 static gint hf_s7comm_pi_n_x_semaphorevalue = -1;
1627 static gint hf_s7comm_pi_n_x_onoff = -1;
1628 static gint hf_s7comm_pi_n_x_mode = -1;
1629 static gint hf_s7comm_pi_n_x_factor = -1;
1630 static gint hf_s7comm_pi_n_x_passwordlevel = -1;
1631 static gint hf_s7comm_pi_n_x_linenumber = -1;
1632 static gint hf_s7comm_pi_n_x_weargroup = -1;
1633 static gint hf_s7comm_pi_n_x_toolstatus = -1;
1634 static gint hf_s7comm_pi_n_x_wearsearchstrat = -1;
1635 static gint hf_s7comm_pi_n_x_toolid = -1;
1636 static gint hf_s7comm_pi_n_x_duplonumber = -1;
1637 static gint hf_s7comm_pi_n_x_edgenumber = -1;
1638 static gint hf_s7comm_pi_n_x_placenr = -1;
1639 static gint hf_s7comm_pi_n_x_placerefnr = -1;
1640 static gint hf_s7comm_pi_n_x_magrefnr = -1;
1641 static gint hf_s7comm_pi_n_x_magnrfrom = -1;
1642 static gint hf_s7comm_pi_n_x_placenrfrom = -1;
1643 static gint hf_s7comm_pi_n_x_magnrto = -1;
1644 static gint hf_s7comm_pi_n_x_placenrto = -1;
1645 static gint hf_s7comm_pi_n_x_halfplacesleft = -1;
1646 static gint hf_s7comm_pi_n_x_halfplacesright = -1;
1647 static gint hf_s7comm_pi_n_x_halfplacesup = -1;
1648 static gint hf_s7comm_pi_n_x_halfplacesdown = -1;
1649 static gint hf_s7comm_pi_n_x_placetype = -1;
1650 static gint hf_s7comm_pi_n_x_searchdirection = -1;
1651 static gint hf_s7comm_pi_n_x_toolname = -1;
1652 static gint hf_s7comm_pi_n_x_placenrsource = -1;
1653 static gint hf_s7comm_pi_n_x_magnrsource = -1;
1654 static gint hf_s7comm_pi_n_x_placenrdestination = -1;
1655 static gint hf_s7comm_pi_n_x_magnrdestination = -1;
1656 static gint hf_s7comm_pi_n_x_incrementnumber = -1;
1657 static gint hf_s7comm_pi_n_x_monitoringmode = -1;
1658 static gint hf_s7comm_pi_n_x_kindofsearch = -1;
1659
1660 static gint hf_s7comm_data_plccontrol_argument = -1; /* Argument, 2 Bytes as char */
1661 static gint hf_s7comm_data_plccontrol_block_cnt = -1; /* Number of blocks, 1 Byte as int */
1662 static gint hf_s7comm_data_pi_inse_unknown = -1;
1663 static gint hf_s7comm_data_plccontrol_part2_len = -1; /* Length part 2 in bytes, 1 Byte as Int */
1664
1665 /* block control functions */
1666 static gint hf_s7comm_data_blockcontrol_unknown1 = -1; /* for all unknown bytes in blockcontrol */
1667 static gint hf_s7comm_data_blockcontrol_errorcode = -1; /* Error code 2 bytes as int, 0 is no error */
1668 static gint hf_s7comm_data_blockcontrol_uploadid = -1;
1669 static gint hf_s7comm_data_blockcontrol_file_ident = -1; /* File identifier, as ASCII */
1670 static gint hf_s7comm_data_blockcontrol_block_type = -1; /* Block type, 2 Byte */
1671 static gint hf_s7comm_data_blockcontrol_block_num = -1; /* Block number, 5 Bytes, ASCII */
1672 static gint hf_s7comm_data_blockcontrol_dest_filesys = -1; /* Destination filesystem, 1 Byte, ASCII */
1673 static gint hf_s7comm_data_blockcontrol_part2_len = -1; /* Length part 2 in bytes, 1 Byte Int */
1674 static gint hf_s7comm_data_blockcontrol_part2_unknown = -1; /* Unknown char, ASCII */
1675 static gint hf_s7comm_data_blockcontrol_loadmem_len = -1; /* Length load memory in bytes, ASCII */
1676 static gint hf_s7comm_data_blockcontrol_mc7code_len = -1; /* Length of MC7 code in bytes, ASCII */
1677 static gint hf_s7comm_data_blockcontrol_filename_len = -1;
1678 static gint hf_s7comm_data_blockcontrol_filename = -1;
1679 static gint hf_s7comm_data_blockcontrol_upl_lenstring_len = -1;
1680 static gint hf_s7comm_data_blockcontrol_upl_lenstring = -1;
1681
1682 static gint hf_s7comm_data_blockcontrol_functionstatus = -1;
1683 static gint hf_s7comm_data_blockcontrol_functionstatus_more = -1;
1684 static gint hf_s7comm_data_blockcontrol_functionstatus_error = -1;
1685 static gint ett_s7comm_data_blockcontrol_status = -1;
1686 static int * const s7comm_data_blockcontrol_status_fields[] = {
1687 &hf_s7comm_data_blockcontrol_functionstatus_more,
1688 &hf_s7comm_data_blockcontrol_functionstatus_error,
1689 NULL
1690 };
1691
1692 static gint ett_s7comm_plcfilename = -1;
1693 static gint hf_s7comm_data_ncprg_unackcount = -1;
1694 static gint hf_s7comm_data_ncprg_filelength = -1;
1695 static gint hf_s7comm_data_ncprg_filetime = -1;
1696 static gint hf_s7comm_data_ncprg_filepath = -1;
1697 static gint hf_s7comm_data_ncprg_filedata = -1;
1698
1699 /* Variable status */
1700 static gint hf_s7comm_varstat_unknown = -1; /* Unknown byte(s), hex */
1701 static gint hf_s7comm_varstat_item_count = -1; /* Item count, 2 bytes, int */
1702 static gint hf_s7comm_varstat_req_memory_area = -1; /* Memory area, 1 byte, stringlist userdata_prog_varstat_area_names */
1703 static gint hf_s7comm_varstat_req_repetition_factor = -1; /* Repetition factor, 1 byte as int */
1704 static gint hf_s7comm_varstat_req_db_number = -1; /* DB number, 2 bytes as int */
1705 static gint hf_s7comm_varstat_req_startaddress = -1; /* Startaddress, 2 bytes as int */
1706 static gint hf_s7comm_varstat_req_bitpos = -1;
1707
1708 /* cyclic services */
1709 static gint hf_s7comm_cycl_interval_timebase = -1; /* Interval timebase, 1 byte, int */
1710 static gint hf_s7comm_cycl_interval_time = -1; /* Interval time, 1 byte, int */
1711 static gint hf_s7comm_cycl_function = -1;
1712 static gint hf_s7comm_cycl_jobid = -1;
1713
1714 /* Read record */
1715 static gint hf_s7comm_rdrec_mlen = -1; /* Max. length in bytes of the data record data to be read */
1716 static gint hf_s7comm_rdrec_index = -1; /* Data record number */
1717 static gint hf_s7comm_rdrec_id = -1; /* Diagnostic address */
1718 static gint hf_s7comm_rdrec_statuslen = -1; /* Length of optional status data */
1719 static gint hf_s7comm_rdrec_statusdata = -1; /* Optional status data */
1720 static gint hf_s7comm_rdrec_recordlen = -1; /* Length of data record data read */
1721 static gint hf_s7comm_rdrec_data = -1; /* The read data record */
1722 static gint hf_s7comm_rdrec_reserved1 = -1;
1723
1724 /* PBC, Programmable Block Functions */
1725 static gint hf_s7comm_pbc_unknown = -1; /* unknown, 1 byte */
1726 static gint hf_s7comm_pbc_r_id = -1; /* Request ID R_ID, 4 bytes as hex */
1727 static gint hf_s7comm_pbc_len = -1;
1728
1729 /* Alarm messages */
1730 static gint hf_s7comm_cpu_alarm_message_item = -1;
1731 static gint hf_s7comm_cpu_alarm_message_obj_item = -1;
1732 static gint hf_s7comm_cpu_alarm_message_function = -1;
1733 static gint hf_s7comm_cpu_alarm_message_nr_objects = -1;
1734 static gint hf_s7comm_cpu_alarm_message_nr_add_values = -1;
1735 static gint hf_s7comm_cpu_alarm_message_eventid = -1;
1736 static gint hf_s7comm_cpu_alarm_message_timestamp_coming = -1;
1737 static gint hf_s7comm_cpu_alarm_message_timestamp_going = -1;
1738 static gint hf_s7comm_cpu_alarm_message_associated_value = -1;
1739 static gint hf_s7comm_cpu_alarm_message_eventstate = -1;
1740 static gint hf_s7comm_cpu_alarm_message_state = -1;
1741 static gint hf_s7comm_cpu_alarm_message_ackstate_coming = -1;
1742 static gint hf_s7comm_cpu_alarm_message_ackstate_going = -1;
1743 static gint hf_s7comm_cpu_alarm_message_event_coming = -1;
1744 static gint hf_s7comm_cpu_alarm_message_event_going = -1;
1745 static gint hf_s7comm_cpu_alarm_message_event_lastchanged = -1;
1746 static gint hf_s7comm_cpu_alarm_message_event_reserved = -1;
1747 static gint hf_s7comm_cpu_alarm_message_scan_unknown1 = -1;
1748 static gint hf_s7comm_cpu_alarm_message_scan_unknown2 = -1;
1749
1750 static gint hf_s7comm_cpu_alarm_message_signal_sig1 = -1;
1751 static gint hf_s7comm_cpu_alarm_message_signal_sig2 = -1;
1752 static gint hf_s7comm_cpu_alarm_message_signal_sig3 = -1;
1753 static gint hf_s7comm_cpu_alarm_message_signal_sig4 = -1;
1754 static gint hf_s7comm_cpu_alarm_message_signal_sig5 = -1;
1755 static gint hf_s7comm_cpu_alarm_message_signal_sig6 = -1;
1756 static gint hf_s7comm_cpu_alarm_message_signal_sig7 = -1;
1757 static gint hf_s7comm_cpu_alarm_message_signal_sig8 = -1;
1758 static gint ett_s7comm_cpu_alarm_message_signal = -1;
1759 static int * const s7comm_cpu_alarm_message_signal_fields[] = {
1760 &hf_s7comm_cpu_alarm_message_signal_sig1,
1761 &hf_s7comm_cpu_alarm_message_signal_sig2,
1762 &hf_s7comm_cpu_alarm_message_signal_sig3,
1763 &hf_s7comm_cpu_alarm_message_signal_sig4,
1764 &hf_s7comm_cpu_alarm_message_signal_sig5,
1765 &hf_s7comm_cpu_alarm_message_signal_sig6,
1766 &hf_s7comm_cpu_alarm_message_signal_sig7,
1767 &hf_s7comm_cpu_alarm_message_signal_sig8,
1768 NULL
1769 };
1770
1771 static gint hf_s7comm_cpu_alarm_query_unknown1 = -1;
1772 static gint hf_s7comm_cpu_alarm_query_querytype = -1;
1773 static gint hf_s7comm_cpu_alarm_query_unknown2 = -1;
1774 static gint hf_s7comm_cpu_alarm_query_alarmtype = -1;
1775 static gint hf_s7comm_cpu_alarm_query_completelen = -1;
1776 static gint hf_s7comm_cpu_alarm_query_datasetlen = -1;
1777 static gint hf_s7comm_cpu_alarm_query_resunknown1 = -1;
1778
1779 /* CPU diagnostic messages */
1780 static gint hf_s7comm_cpu_diag_msg_item = -1;
1781 static gint hf_s7comm_cpu_diag_msg_eventid = -1;
1782 static gint hf_s7comm_cpu_diag_msg_eventid_class = -1;
1783 static gint hf_s7comm_cpu_diag_msg_eventid_ident_entleave = -1;
1784 static gint hf_s7comm_cpu_diag_msg_eventid_ident_diagbuf = -1;
1785 static gint hf_s7comm_cpu_diag_msg_eventid_ident_interr = -1;
1786 static gint hf_s7comm_cpu_diag_msg_eventid_ident_exterr = -1;
1787 static gint hf_s7comm_cpu_diag_msg_eventid_nr = -1;
1788 static gint hf_s7comm_cpu_diag_msg_prioclass = -1;
1789 static gint hf_s7comm_cpu_diag_msg_obnumber = -1;
1790 static gint hf_s7comm_cpu_diag_msg_datid = -1;
1791 static gint hf_s7comm_cpu_diag_msg_info1 = -1;
1792 static gint hf_s7comm_cpu_diag_msg_info2 = -1;
1793
1794 static gint ett_s7comm_cpu_diag_msg_eventid = -1;
1795 static int * const s7comm_cpu_diag_msg_eventid_fields[] = {
1796 &hf_s7comm_cpu_diag_msg_eventid_class,
1797 &hf_s7comm_cpu_diag_msg_eventid_ident_entleave,
1798 &hf_s7comm_cpu_diag_msg_eventid_ident_diagbuf,
1799 &hf_s7comm_cpu_diag_msg_eventid_ident_interr,
1800 &hf_s7comm_cpu_diag_msg_eventid_ident_exterr,
1801 &hf_s7comm_cpu_diag_msg_eventid_nr,
1802 NULL
1803 };
1804
1805 static const true_false_string tfs_s7comm_cpu_diag_msg_eventid_ident_entleave = {
1806 "Event entering",
1807 "Event leaving"
1808 };
1809
1810 static const value_string cpu_diag_msg_eventid_class_names[] = {
1811 { 0x01, "Standard OB events" },
1812 { 0x02, "Synchronous errors" },
1813 { 0x03, "Asynchronous errors" },
1814 { 0x04, "Mode transitions" },
1815 { 0x05, "Run-time events" },
1816 { 0x06, "Communication events" },
1817 { 0x07, "Events for fail-safe and fault-tolerant systems" },
1818 { 0x08, "Standardized diagnostic data on modules" },
1819 { 0x09, "Predefined user events" },
1820 { 0x0a, "Freely definable events" },
1821 { 0x0b, "Freely definable events" },
1822 { 0x0c, "Reserved" },
1823 { 0x0d, "Reserved" },
1824 { 0x0e, "Reserved" },
1825 { 0x0f, "Events for modules other than CPUs" },
1826 { 0, NULL }
1827 };
1828
1829 static const value_string cpu_diag_eventid_fix_names[] = {
1830 { 0x113A, "Start request for cyclic interrupt OB with special handling (S7-300 only)" },
1831 { 0x1155, "Status alarm for PROFIBUS DP" },
1832 { 0x1156, "Update interrupt for PROFIBUS DP" },
1833 { 0x1157, "Manufacturer interrupt for PROFIBUS DP" },
1834 { 0x1158, "Status interrupt for PROFINET IO" },
1835 { 0x1159, "Update interrupt for PROFINET IO" },
1836 { 0x115A, "Manufacturer interrupt for PROFINET IO" },
1837 { 0x115B, "IO: Profile-specific interrupt" },
1838 { 0x116A, "Technology synchronization interrupt" },
1839 { 0x1381, "Request for manual warm restart" },
1840 { 0x1382, "Request for automatic warm restart" },
1841 { 0x1383, "Request for manual hot restart" },
1842 { 0x1384, "Request for automatic hot restart" },
1843 { 0x1385, "Request for manual cold restart" },
1844 { 0x1386, "Request for automatic cold restart" },
1845 { 0x1387, "Master CPU: request for manual cold restart" },
1846 { 0x1388, "Master CPU: request for automatic cold restart" },
1847 { 0x138A, "Master CPU: request for manual warm restart" },
1848 { 0x138B, "Master CPU: request for automatic warm restart" },
1849 { 0x138C, "Standby CPU: request for manual hot restart" },
1850 { 0x138D, "Standby CPU: request for automatic hot restart" },
1851 { 0x2521, "BCD conversion error" },
1852 { 0x2522, "Area length error when reading" },
1853 { 0x2523, "Area length error when writing" },
1854 { 0x2524, "Area error when reading" },
1855 { 0x2525, "Area error when writing" },
1856 { 0x2526, "Timer number error" },
1857 { 0x2527, "Counter number error" },
1858 { 0x2528, "Alignment error when reading" },
1859 { 0x2529, "Alignment error when writing" },
1860 { 0x2530, "Write error when accessing the DB" },
1861 { 0x2531, "Write error when accessing the DI" },
1862 { 0x2532, "Block number error when opening a DB" },
1863 { 0x2533, "Block number error when opening a DI" },
1864 { 0x2534, "Block number error when calling an FC" },
1865 { 0x2535, "Block number error when calling an FB" },
1866 { 0x253A, "DB not loaded" },
1867 { 0x253C, "FC not loaded" },
1868 { 0x253D, "SFC not loaded" },
1869 { 0x253E, "FB not loaded" },
1870 { 0x253F, "SFB not loaded" },
1871 { 0x2942, "I/O access error, reading" },
1872 { 0x2943, "I/O access error, writing" },
1873 { 0x3267, "End of module reconfiguration" },
1874 { 0x3367, "Start of module reconfiguration" },
1875 { 0x34A4, "PROFInet Interface DB can be addressed again" },
1876 { 0x3501, "Cycle time exceeded" },
1877 { 0x3502, "User interface (OB or FRB) request error" },
1878 { 0x3503, "Delay too long processing a priority class" },
1879 { 0x3505, "Time-of-day interrupt(s) skipped due to new clock setting" },
1880 { 0x3506, "Time-of-day interrupt(s) skipped when changing to RUN after HOLD" },
1881 { 0x3507, "Multiple OB request errors caused internal buffer overflow" },
1882 { 0x3508, "Synchronous cycle interrupt-timing error" },
1883 { 0x3509, "Interrupt loss due to excess interrupt load" },
1884 { 0x350A, "Resume RUN mode after CiR" },
1885 { 0x350B, "Technology synchronization interrupt - timing error" },
1886 { 0x3571, "Nesting depth too high in nesting levels" },
1887 { 0x3572, "Nesting depth for Master Control Relays too high" },
1888 { 0x3573, "Nesting depth too high after synchronous errors" },
1889 { 0x3574, "Nesting depth for block calls (U stack) too high" },
1890 { 0x3575, "Nesting depth for block calls (B stack) too high" },
1891 { 0x3576, "Local data allocation error" },
1892 { 0x3578, "Unknown instruction" },
1893 { 0x357A, "Jump instruction to target outside of the block" },
1894 { 0x3582, "Memory error detected and corrected by operating system" },
1895 { 0x3583, "Accumulation of detected and corrected memo errors" },
1896 { 0x3585, "Error in the PC operating system (only for LC RTX)" },
1897 { 0x3587, "Multi-bit memory error detected and corrected" },
1898 { 0x35A1, "User interface (OB or FRB) not found" },
1899 { 0x35A2, "OB not loaded (started by SFC or operating system due to configuration)" },
1900 { 0x35A3, "Error when operating system accesses a block" },
1901 { 0x35A4, "PROFInet Interface DB cannot be addressed" },
1902 { 0x35D2, "Diagnostic entries cannot be sent at present" },
1903 { 0x35D3, "Synchronization frames cannot be sent" },
1904 { 0x35D4, "Illegal time jump resulting from synchronization" },
1905 { 0x35D5, "Error adopting the synchronization time" },
1906 { 0x35E1, "Incorrect frame ID in GD" },
1907 { 0x35E2, "GD packet status cannot be entered in DB" },
1908 { 0x35E3, "Frame length error in GD" },
1909 { 0x35E4, "Illegal GD packet number received" },
1910 { 0x35E5, "Error accessing DB in communication SFBs for configured S7 connections" },
1911 { 0x35E6, "GD total status cannot be entered in DB" },
1912 { 0x3821, "BATTF: failure on at least one backup battery of the central rack, problem eliminated" },
1913 { 0x3822, "BAF: failure of backup voltage on central rack, problem eliminated" },
1914 { 0x3823, "24 volt supply failure on central rack, problem eliminated" },
1915 { 0x3825, "BATTF: failure on at least one backup battery of the redundant central rack, problem eliminated" },
1916 { 0x3826, "BAF: failure of backup voltage on redundant central rack, problem eliminated" },
1917 { 0x3827, "24 volt supply failure on redundant central rack, problem eliminated" },
1918 { 0x3831, "BATTF: failure of at least one backup battery of the expansion rack, problem eliminated" },
1919 { 0x3832, "BAF: failure of backup voltage on expansion rack, problem eliminated" },
1920 { 0x3833, "24 volt supply failure on at least one expansion rack, problem eliminated" },
1921 { 0x3842, "Module OK" },
1922 { 0x3854, "PROFINET IO interface submodule/submodule and matches the configured interface submodule/submodule" },
1923 { 0x3855, "PROFINET IO interface submodule/submodule inserted, but does not match the configured interface submodule/submodule" },
1924 { 0x3856, "PROFINET IO interface submodule/submodule inserted, but error in module parameter assignment" },
1925 { 0x3858, "PROFINET IO interface submodule access error corrected" },
1926 { 0x3861, "Module/interface module inserted, module type OK" },
1927 { 0x3863, "Module/interface module plugged in, but wrong module type" },
1928 { 0x3864, "Module/interface module plugged in, but causing problem (type ID unreadable)" },
1929 { 0x3865, "Module plugged in, but error in module parameter assignment" },
1930 { 0x3866, "Module can be addressed again, load voltage error removed" },
1931 { 0x3881, "Interface error leaving state" },
1932 { 0x3884, "Interface module plugged in" },
1933 { 0x38B3, "I/O access error when updating the process image input table" },
1934 { 0x38B4, "I/O access error when transferring the process image to the output modules" },
1935 { 0x38C1, "Expansion rack operational again (1 to 21), leaving state" },
1936 { 0x38C2, "Expansion rack operational again but mismatch between setpoint and actual configuration" },
1937 { 0x38C4, "Distributed I/Os: station failure, leaving state" },
1938 { 0x38C5, "Distributed I/Os: station fault, leaving state" },
1939 { 0x38C6, "Expansion rack operational again, but error(s) in module parameter assignment" },
1940 { 0x38C7, "DP: station operational again, but error(s) in module parameter assignment" },
1941 { 0x38C8, "DP: station operational again, but mismatch between setpoint and actual configuration" },
1942 { 0x38CB, "PROFINET IO station operational again" },
1943 { 0x38CC, "PROFINET IO station error corrected" },
1944 { 0x3921, "BATTF: failure on at least one backup battery of the central rack" },
1945 { 0x3922, "BAF: failure of backup voltage on central rack" },
1946 { 0x3923, "24 volt supply failure on central rack" },
1947 { 0x3925, "BATTF: failure on at least one backup battery of the redundant central rack" },
1948 { 0x3926, "BAF: failure of backup voltage on redundant central rack" },
1949 { 0x3927, "24 volt supply failure on redundant central rack" },
1950 { 0x3931, "BATTF: failure of at least one backup battery of the expansion rack" },
1951 { 0x3932, "BAF: failure of backup voltage on expansion rack" },
1952 { 0x3933, "24 volt supply failure on at least one expansion rack" },
1953 { 0x3942, "Module error" },
1954 { 0x3951, "PROFINET IO submodule removed" },
1955 { 0x3954, "PROFINET IO interface submodule/submodule removed" },
1956 { 0x3961, "Module/interface module removed, cannot be addressed" },
1957 { 0x3966, "Module cannot be addressed, load voltage error" },
1958 { 0x3968, "Module reconfiguration has ended with error" },
1959 { 0x3981, "Interface error entering state" },
1960 { 0x3984, "Interface module removed" },
1961 { 0x3986, "Performance of an H-Sync link negatively affected" },
1962 { 0x39B1, "I/O access error when updating the process image input table" },
1963 { 0x39B2, "I/O access error when transferring the process image to the output modules" },
1964 { 0x39B3, "I/O access error when updating the process image input table" },
1965 { 0x39B4, "I/O access error when transferring the process image to the output modules" },
1966 { 0x39C1, "Expansion rack failure (1 to 21), entering state" },
1967 { 0x39C3, "Distributed I/Os: master system failure entering state" },
1968 { 0x39C4, "Distributed I/Os: station failure, entering state" },
1969 { 0x39C5, "Distributed I/Os: station fault, entering state" },
1970 { 0x39CA, "PROFINET IO system failure" },
1971 { 0x39CB, "PROFINET IO station failure" },
1972 { 0x39CC, "PROFINET IO station error" },
1973 { 0x39CD, "PROFINET IO station operational again, but expected configuration does not match actual configuration" },
1974 { 0x39CE, "PROFINET IO station operational again, but error(s) in module parameter assignment" },
1975 { 0x42F3, "Checksum error detected and corrected by the operating system" },
1976 { 0x42F4, "Standby CPU: connection/update via SFC90 is locked in the master CPU" },
1977 { 0x4300, "Backed-up power on" },
1978 { 0x4301, "Mode transition from STOP to STARTUP" },
1979 { 0x4302, "Mode transition from STARTUP to RUN" },
1980 { 0x4303, "STOP caused by stop switch being activated" },
1981 { 0x4304, "STOP caused by PG STOP operation or by SFB 20 STOP" },
1982 { 0x4305, "HOLD: breakpoint reached" },
1983 { 0x4306, "HOLD: breakpoint exited" },
1984 { 0x4307, "Memory reset started by PG operation" },
1985 { 0x4308, "Memory reset started by switch setting" },
1986 { 0x4309, "Memory reset started automatically (power on not backed up)" },
1987 { 0x430A, "HOLD exited, transition to STOP" },
1988 { 0x430D, "STOP caused by other CPU in multicomputing" },
1989 { 0x430E, "Memory reset executed" },
1990 { 0x430F, "STOP on the module due to STOP on a CPU" },
1991 { 0x4318, "Start of CiR" },
1992 { 0x4319, "CiR completed" },
1993 { 0x4357, "Module watchdog started" },
1994 { 0x4358, "All modules are ready for operation" },
1995 { 0x43B0, "Firmware update was successful" },
1996 { 0x43B4, "Error in firmware fuse" },
1997 { 0x43B6, "Firmware updates canceled by redundant modules" },
1998 { 0x43D3, "STOP on standby CPU" },
1999 { 0x43DC, "Abort during link-up with switchover" },
2000 { 0x43DE, "Updating aborted due to monitoring time being exceeded during the n-th attempt, new update attempt initiated" },
2001 { 0x43DF, "Updating aborted for final time due to monitoring time being exceeded after completing the maximum amount of attempts. User intervention required" },
2002 { 0x43E0, "Change from solo mode after link-up" },
2003 { 0x43E1, "Change from link-up after updating" },
2004 { 0x43E2, "Change from updating to redundant mode" },
2005 { 0x43E3, "Master CPU: change from redundant mode to solo mode" },
2006 { 0x43E4, "Standby CPU: change from redundant mode after error-search mode" },
2007 { 0x43E5, "Standby CPU: change from error-search mode after link-up or STOP" },
2008 { 0x43E6, "Link-up aborted on the standby CPU" },
2009 { 0x43E7, "Updating aborted on the standby CPU" },
2010 { 0x43E8, "Standby CPU: change from link-up after startup" },
2011 { 0x43E9, "Standby CPU: change from startup after updating" },
2012 { 0x43F1, "Reserve-master switchover" },
2013 { 0x43F2, "Coupling of incompatible H-CPUs blocked by system program" },
2014 { 0x4510, "STOP violation of the CPU's data range" },
2015 { 0x4520, "DEFECTIVE: STOP not possible" },
2016 { 0x4521, "DEFECTIVE: failure of instruction processing processor" },
2017 { 0x4522, "DEFECTIVE: failure of clock chip" },
2018 { 0x4523, "DEFECTIVE: failure of clock pulse generator" },
2019 { 0x4524, "DEFECTIVE: failure of timer update function" },
2020 { 0x4525, "DEFECTIVE: failure of multicomputing synchronization" },
2021 { 0x4527, "DEFECTIVE: failure of I/O access monitoring" },
2022 { 0x4528, "DEFECTIVE: failure of scan time monitoring" },
2023 { 0x4530, "DEFECTIVE: memory test error in internal memory" },
2024 { 0x4532, "DEFECTIVE: failure of core resources" },
2025 { 0x4536, "DEFECTIVE: switch defective" },
2026 { 0x4540, "STOP: Memory expansion of the internal work memory has gaps. First memory expansion too small or missing" },
2027 { 0x4541, "STOP caused by priority class system" },
2028 { 0x4542, "STOP caused by object management system" },
2029 { 0x4543, "STOP caused by test functions" },
2030 { 0x4544, "STOP caused by diagnostic system" },
2031 { 0x4545, "STOP caused by communication system" },
2032 { 0x4546, "STOP caused by CPU memory management" },
2033 { 0x4547, "STOP caused by process image management" },
2034 { 0x4548, "STOP caused by I/O management" },
2035 { 0x454A, "STOP caused by configuration: an OB deselected with STEP 7 was being loaded into the CPU during STARTUP" },
2036 { 0x4550, "DEFECTIVE: internal system error" },
2037 { 0x4555, "No restart possible, monitoring time elapsed" },
2038 { 0x4556, "STOP: memory reset request from communication system / due to data inconsistency" },
2039 { 0x4562, "STOP caused by programming error (OB not loaded or not possible)" },
2040 { 0x4563, "STOP caused by I/O access error (OB not loaded or not possible)" },
2041 { 0x4567, "STOP caused by H event" },
2042 { 0x4568, "STOP caused by time error (OB not loaded or not possible)" },
2043 { 0x456A, "STOP caused by diagnostic interrupt (OB not loaded or not possible)" },
2044 { 0x456B, "STOP caused by removing/inserting module (OB not loaded or not possible)" },
2045 { 0x456C, "STOP caused by CPU hardware error (OB not loaded or not possible, or no FRB)" },
2046 { 0x456D, "STOP caused by program sequence error (OB not loaded or not possible)" },
2047 { 0x456E, "STOP caused by communication error (OB not loaded or not possible)" },
2048 { 0x456F, "STOP caused by rack failure OB (OB not loaded or not possible)" },
2049 { 0x4570, "STOP caused by process interrupt (OB not loaded or not possible)" },
2050 { 0x4571, "STOP caused by nesting stack error" },
2051 { 0x4572, "STOP caused by master control relay stack error" },
2052 { 0x4573, "STOP caused by exceeding the nesting depth for synchronous errors" },
2053 { 0x4574, "STOP caused by exceeding interrupt stack nesting depth in the priority class stack" },
2054 { 0x4575, "STOP caused by exceeding block stack nesting depth in the priority class stack" },
2055 { 0x4576, "STOP caused by error when allocating the local data" },
2056 { 0x4578, "STOP caused by unknown opcode" },
2057 { 0x457A, "STOP caused by code length error" },
2058 { 0x457B, "STOP caused by DB not being loaded on on-board I/Os" },
2059 { 0x457D, "Reset/clear request because the version of the internal interface to the integrated technology was changed" },
2060 { 0x457F, "STOP caused by STOP command" },
2061 { 0x4580, "STOP: back-up buffer contents inconsistent (no transition to RUN)" },
2062 { 0x4590, "STOP caused by overloading the internal functions" },
2063 { 0x45D5, "LINK-UP rejected due to mismatched CPU memory configuration of the sub-PLC" },
2064 { 0x45D6, "LINK-UP rejected due to mismatched system program of the sub-PLC" },
2065 { 0x45D8, "DEFECTIVE: hardware fault detected due to other error" },
2066 { 0x45D9, "STOP due to SYNC module error" },
2067 { 0x45DA, "STOP due to synchronization error between H CPUs" },
2068 { 0x45DD, "LINK-UP rejected due to running test or other online functions" },
2069 { 0x4926, "DEFECTIVE: failure of the watchdog for I/O access" },
2070 { 0x4931, "STOP or DEFECTIVE: memory test error in memory submodule" },
2071 { 0x4933, "Checksum error" },
2072 { 0x4934, "DEFECTIVE: memory not available" },
2073 { 0x4935, "DEFECTIVE: cancelled by watchdog/processor exceptions" },
2074 { 0x4949, "STOP caused by continuous hardware interrupt" },
2075 { 0x494D, "STOP caused by I/O error" },
2076 { 0x494E, "STOP caused by power failure" },
2077 { 0x494F, "STOP caused by configuration error" },
2078 { 0x4959, "One or more modules not ready for operation" },
2079 { 0x497C, "STOP caused by integrated technology" },
2080 { 0x49A0, "STOP caused by parameter assignment error or non-permissible variation of setpoint and actual extension: Start-up blocked" },
2081 { 0x49A1, "STOP caused by parameter assignment error: memory reset request" },
2082 { 0x49A2, "STOP caused by error in parameter modification: startup disabled" },
2083 { 0x49A3, "STOP caused by error in parameter modification: memory reset request" },
2084 { 0x49A4, "STOP: inconsistency in configuration data" },
2085 { 0x49A5, "STOP: distributed I/Os: inconsistency in the loaded configuration information" },
2086 { 0x49A6, "STOP: distributed I/Os: invalid configuration information" },
2087 { 0x49A7, "STOP: distributed I/Os: no configuration information" },
2088 { 0x49A8, "STOP: error indicated by the interface module for the distributed I/Os" },
2089 { 0x49B1, "Firmware update data incorrect" },
2090 { 0x49B2, "Firmware update: hardware version does not match firmware" },
2091 { 0x49B3, "Firmware update: module type does not match firmware" },
2092 { 0x49D0, "LINK-UP aborted due to violation of coordination rules" },
2093 { 0x49D1, "LINK-UP/UPDATE sequence aborted" },
2094 { 0x49D2, "Standby CPU changed to STOP due to STOP on the master CPU during link-up" },
2095 { 0x49D4, "STOP on a master, since partner CPU is also a master (link-up error)" },
2096 { 0x49D7, "LINK-UP rejected due to change in user program or in configuration" },
2097 { 0x510F, "A problem as occurred with WinLC. This problem has caused the CPU to go into STOP mode or has caused a fault in the CPU" },
2098 { 0x530D, "New startup information in the STOP mode" },
2099 { 0x5311, "Startup despite Not Ready message from module(s)" },
2100 { 0x5371, "Distributed I/Os: end of the synchronization with a DP master" },
2101 { 0x5380, "Diagnostic buffer entries of interrupt and asynchronous errors disabled" },
2102 { 0x5395, "Distributed I/Os: reset of a DP master" },
2103 { 0x53A2, "Download of technology firmware successful" },
2104 { 0x53A4, "Download of technology DB not successful" },
2105 { 0x53FF, "Reset to factory setting" },
2106 { 0x5445, "Start of System reconfiguration in RUN mode" },
2107 { 0x5481, "All licenses for runtime software are complete again" },
2108 { 0x5498, "No more inconsistency with DP master systems due to CiR" },
2109 { 0x5545, "Start of System reconfiguration in RUN mode" },
2110 { 0x5581, "One or several licenses for runtime software are missing" },
2111 { 0x558A, "Difference between the MLFB of the configured and inserted CPU" },
2112 { 0x558B, "Difference in the firmware version of the configured and inserted CPU" },
2113 { 0x5598, "Start of possible inconsistency with DP master systems due to CiR" },
2114 { 0x55A5, "Version conflict: internal interface with integrated technology" },
2115 { 0x55A6, "The maximum number of technology objects has been exceeded" },
2116 { 0x55A7, "A technology DB of this type is already present" },
2117 { 0x5879, "Diagnostic message from DP interface: EXTF LED off" },
2118 { 0x5960, "Parameter assignment error when switching" },
2119 { 0x5961, "Parameter assignment error" },
2120 { 0x5962, "Parameter assignment error preventing startup" },
2121 { 0x5963, "Parameter assignment error with memory reset request" },
2122 { 0x5966, "Parameter assignment error when switching" },
2123 { 0x5969, "Parameter assignment error with startup blocked" },
2124 { 0x596A, "PROFINET IO: IP address of an IO device already present" },
2125 { 0x596B, "IP address of an Ethernet interface already exists" },
2126 { 0x596C, "Name of an Ethernet interface already exists" },
2127 { 0x596D, "The existing network configuration does not mach the system requirements or configuration" },
2128 { 0x5979, "Diagnostic message from DP interface: EXTF LED on" },
2129 { 0x597C, "DP Global Control command failed or moved" },
2130 { 0x59A0, "The interrupt can not be associated in the CPU" },
2131 { 0x59A1, "Configuration error in the integrated technology" },
2132 { 0x59A3, "Error when downloading the integrated technology" },
2133 { 0x6253, "Firmware update: End of firmware download over the network" },
2134 { 0x6316, "Interface error when starting programmable controller" },
2135 { 0x6353, "Firmware update: Start of firmware download over the network" },
2136 { 0x6390, "Formatting of Micro Memory Card complete" },
2137 { 0x6500, "Connection ID exists twice on module" },
2138 { 0x6501, "Connection resources inadequate" },
2139 { 0x6502, "Error in the connection description" },
2140 { 0x6510, "CFB structure error detected in instance DB when evaluating EPROM" },
2141 { 0x6514, "GD packet number exists twice on the module" },
2142 { 0x6515, "Inconsistent length specifications in GD configuration information" },
2143 { 0x6521, "No memory submodule and no internal memory available" },
2144 { 0x6522, "Illegal memory submodule: replace submodule and reset memory" },
2145 { 0x6523, "Memory reset request due to error accessing submodule" },
2146 { 0x6524, "Memory reset request due to error in block header" },
2147 { 0x6526, "Memory reset request due to memory replacement" },
2148 { 0x6527, "Memory replaced, therefore restart not possible" },
2149 { 0x6528, "Object handling function in the STOP/HOLD mode, no restart possible" },
2150 { 0x6529, "No startup possible during the \"load user program\" function" },
2151 { 0x652A, "No startup because block exists twice in user memory" },
2152 { 0x652B, "No startup because block is too long for submodule - replace submodule" },
2153 { 0x652C, "No startup due to illegal OB on submodule" },
2154 { 0x6532, "No startup because illegal configuration information on submodule" },
2155 { 0x6533, "Memory reset request because of invalid submodule content" },
2156 { 0x6534, "No startup: block exists more than once on submodule" },
2157 { 0x6535, "No startup: not enough memory to transfer block from submodule" },
2158 { 0x6536, "No startup: submodule contains an illegal block number" },
2159 { 0x6537, "No startup: submodule contains a block with an illegal length" },
2160 { 0x6538, "Local data or write-protection ID (for DB) of a block illegal for CPU" },
2161 { 0x6539, "Illegal command in block (detected by compiler)" },
2162 { 0x653A, "Memory reset request because local OB data on submodule too short" },
2163 { 0x6543, "No startup: illegal block type" },
2164 { 0x6544, "No startup: attribute \"relevant for processing\" illegal" },
2165 { 0x6545, "Source language illegal" },
2166 { 0x6546, "Maximum amount of configuration information reached" },
2167 { 0x6547, "Parameter assignment error assigning parameters to modules (not on P bus, cancel download)" },
2168 { 0x6548, "Plausibility error during block check" },
2169 { 0x6549, "Structure error in block" },
2170 { 0x6550, "A block has an error in the CRC" },
2171 { 0x6551, "A block has no CRC" },
2172 { 0x6560, "SCAN overflow" },
2173 { 0x6805, "Resource problem on configured connections, eliminated" },
2174 { 0x6881, "Interface error leaving state" },
2175 { 0x6905, "Resource problem on configured connections" },
2176 { 0x6981, "Interface error entering state" },
2177 { 0x72A2, "Failure of a DP master or a DP master system" },
2178 { 0x72A3, "Redundancy restored on the DP slave" },
2179 { 0x72DB, "Safety program: safety mode disabled" },
2180 { 0x72E0, "Loss of redundancy in communication, problem eliminated" },
2181 { 0x7301, "Loss of redundancy (1 of 2) due to failure of a CPU" },
2182 { 0x7302, "Loss of redundancy (1 of 2) due to STOP on the standby triggered by user" },
2183 { 0x7303, "H system (1 of 2) changed to redundant mode" },
2184 { 0x7323, "Discrepancy found in operating system data" },
2185 { 0x7331, "Standby-master switchover due to master failure" },
2186 { 0x7333, "Standby-master switchover due to system modification during runtime" },
2187 { 0x7334, "Standby-master switchover due to communication error at the synchronization module" },
2188 { 0x7340, "Synchronization error in user program due to elapsed wait time" },
2189 { 0x7341, "Synchronization error in user program due to waiting at different synchronization points" },
2190 { 0x7342, "Synchronization error in operating system due to waiting at different synchronization points" },
2191 { 0x7343, "Synchronization error in operating system due to elapsed wait time" },
2192 { 0x7344, "Synchronization error in operating system due to incorrect data" },
2193 { 0x734A, "The \"Re-enable\" job triggered by SFC 90 \"H_CTRL\" was executed" },
2194 { 0x73A3, "Loss of redundancy on the DP slave" },
2195 { 0x73C1, "Update process canceled" },
2196 { 0x73C2, "Updating aborted due to monitoring time being exceeded during the n-th attempt (1 = n = max. possible number of update attempts after abort due to excessive monitoring time)" },
2197 { 0x73D8, "Safety mode disabled" },
2198 { 0x73DB, "Safety program: safety mode enabled" },
2199 { 0x73E0, "Loss of redundancy in communication" },
2200 { 0x74DD, "Safety program: Shutdown of a fail-save runtime group disabled" },
2201 { 0x74DE, "Safety program: Shutdown of the F program disabled" },
2202 { 0x74DF, "Start of F program initialization" },
2203 { 0x7520, "Error in RAM comparison" },
2204 { 0x7521, "Error in comparison of process image output value" },
2205 { 0x7522, "Error in comparison of memory bits, timers, or counters" },
2206 { 0x75D1, "Safety program: Internal CPU error" },
2207 { 0x75D2, "Safety program error: Cycle time time-out" },
2208 { 0x75D6, "Data corrupted in safety program prior to the output to F I/O" },
2209 { 0x75D7, "Data corrupted in safety program prior to the output to partner F-CPU" },
2210 { 0x75D9, "Invalid REAL number in a DB" },
2211 { 0x75DA, "Safety program: Error in safety data format" },
2212 { 0x75DC, "Runtime group, internal protocol error" },
2213 { 0x75DD, "Safety program: Shutdown of a fail-save runtime group enabled" },
2214 { 0x75DE, "Safety program: Shutdown of the F program enabled" },
2215 { 0x75DF, "End of F program initialization" },
2216 { 0x75E1, "Safety program: Error in FB \"F_PLK\" or \"F_PLK_O\" or \"F_CYC_CO\" or \"F_TEST\" or \"F_TESTC\"" },
2217 { 0x75E2, "Safety program: Area length error" },
2218 { 0x7852, "SYNC module inserted" },
2219 { 0x7855, "SYNC module eliminated" },
2220 { 0x78D3, "Communication error between PROFIsafe and F I/O" },
2221 { 0x78D4, "Error in safety relevant communication between F CPUs" },
2222 { 0x78D5, "Error in safety relevant communication between F CPUs" },
2223 { 0x78E3, "F-I/O device input channel depassivated" },
2224 { 0x78E4, "F-I/O device output channel depassivated" },
2225 { 0x78E5, "F-I/O device depassivated" },
2226 { 0x7934, "Standby-master switchover due to connection problem at the SYNC module" },
2227 { 0x7950, "Synchronization module missing" },
2228 { 0x7951, "Change at the SYNC module without Power On" },
2229 { 0x7952, "SYNC module removed" },
2230 { 0x7953, "Change at the SYNC-module without reset" },
2231 { 0x7954, "SYNC module: rack number assigned twice" },
2232 { 0x7955, "SYNC module error" },
2233 { 0x7956, "Illegal rack number set on SYNC module" },
2234 { 0x7960, "Redundant I/O: Time-out of discrepancy time at digital input, error is not yet localized" },
2235 { 0x7961, "Redundant I/O, digital input error: Signal change after expiration of the discrepancy time" },
2236 { 0x7962, "Redundant I/O: Digital input error" },
2237 { 0x796F, "Redundant I/O: The I/O was globally disabled" },
2238 { 0x7970, "Redundant I/O: Digital output error" },
2239 { 0x7980, "Redundant I/O: Time-out of discrepancy time at analog input" },
2240 { 0x7981, "Redundant I/O: Analog input error" },
2241 { 0x7990, "Redundant I/O: Analog output error" },
2242 { 0x79D3, "Communication error between PROFIsafe and F I/O" },
2243 { 0x79D4, "Error in safety relevant communication between F CPUs" },
2244 { 0x79D5, "Error in safety relevant communication between F CPUs" },
2245 { 0x79E3, "F-I/O device input channel passivated" },
2246 { 0x79E4, "F-I/O device output channel passivated" },
2247 { 0x79E5, "F-I/O device passivated" },
2248 { 0x79E6, "Inconsistent safety program" },
2249 { 0x79E7, "Simulation block (F system block) loaded" },
2250 { 0, NULL }
2251 };
2252 static value_string_ext cpu_diag_eventid_fix_names_ext = VALUE_STRING_EXT_INIT(cpu_diag_eventid_fix_names);
2253
2254 static const value_string cpu_diag_eventid_0x8_0x9_names[] = {
2255 { 0x8000, "Module fault/OK" },
2256 { 0x8001, "Internal error" },
2257 { 0x8002, "External error" },
2258 { 0x8003, "Channel error" },
2259 { 0x8004, "No external auxiliary voltage" },
2260 { 0x8005, "No front connector" },
2261 { 0x8006, "No parameter assignment" },
2262 { 0x8007, "Incorrect parameters in module" },
2263 { 0x8030, "User submodule incorrect/not found" },
2264 { 0x8031, "Communication problem" },
2265 { 0x8032, "Operating mode: RUN/STOP (STOP: entering state, RUN: leaving state)" },
2266 { 0x8033, "Time monitoring responded (watchdog)" },
2267 { 0x8034, "Internal module power failure" },
2268 { 0x8035, "BATTF: battery exhausted" },
2269 { 0x8036, "Total backup failed" },
2270 { 0x8040, "Expansion rack failed" },
2271 { 0x8041, "Processor failure" },
2272 { 0x8042, "EPROM error" },
2273 { 0x8043, "RAM error" },
2274 { 0x8044, "ADC/DAC error" },
2275 { 0x8045, "Fuse blown" },
2276 { 0x8046, "Hardware interrupt lost Any" },
2277 { 0x8050, "Configuration/parameter assignment error" },
2278 { 0x8051, "Common mode error" },
2279 { 0x8052, "Short circuit to phase" },
2280 { 0x8053, "Short circuit to ground" },
2281 { 0x8054, "Wire break" },
2282 { 0x8055, "Reference channel error" },
2283 { 0x8056, "Below measuring range" },
2284 { 0x8057, "Above measuring range Analog input" },
2285 { 0x8060, "Configuration/parameter assignment error" },
2286 { 0x8061, "Common mode error" },
2287 { 0x8062, "Short circuit to phase" },
2288 { 0x8063, "Short circuit to ground" },
2289 { 0x8064, "Wire break" },
2290 { 0x8066, "No load voltage" },
2291 { 0x8070, "Configuration/parameter assignment error" },
2292 { 0x8071, "Chassis ground fault" },
2293 { 0x8072, "Short circuit to phase (sensor)" },
2294 { 0x8073, "Short circuit to ground (sensor)" },
2295 { 0x8074, "Wire break" },
2296 { 0x8075, "No sensor power supply Digital input" },
2297 { 0x8080, "Configuration/parameter assignment error" },
2298 { 0x8081, "Chassis ground fault" },
2299 { 0x8082, "Short circuit to phase" },
2300 { 0x8083, "Short circuit to ground" },
2301 { 0x8084, "Wire break" },
2302 { 0x8085, "Fuse tripped" },
2303 { 0x8086, "No load voltage" },
2304 { 0x8087, "Excess temperature Digital output" },
2305 { 0x80B0, "Counter module, signal A faulty" },
2306 { 0x80B1, "Counter module, signal B faulty" },
2307 { 0x80B2, "Counter module, signal N faulty" },
2308 { 0x80B3, "Counter module, incorrect value passed between the channels" },
2309 { 0x80B4, "Counter module, 5.2 V sensor supply faulty" },
2310 { 0x80B5, "Counter module, 24 V sensor supply faulty" },
2311 { 0x9001, "Automatic/Manual mode (coming=man,going=auto)" },
2312 { 0x9002, "OPEN/CLOSED, ON/OFF" },
2313 { 0x9003, "Manual command enable" },
2314 { 0x9004, "Unit protective command (OPEN/CLOSED)" },
2315 { 0x9005, "Process enable" },
2316 { 0x9006, "System protection command" },
2317 { 0x9007, "Process value monitoring responded" },
2318 { 0x9008, "Manipulated variable monitoring responded" },
2319 { 0x9009, "System deviation greater than permitted" },
2320 { 0x900A, "Limit position error" },
2321 { 0x900B, "Runtime error" },
2322 { 0x900C, "Command execution error (sequencer)" },
2323 { 0x900D, "Operating status running > OPEN" },
2324 { 0x900E, "Operating status running > CLOSED" },
2325 { 0x900F, "Command blocking" },
2326 { 0x9011, "Process status OPEN/ON" },
2327 { 0x9012, "Process status CLOSED/OFF" },
2328 { 0x9013, "Process status intermediate position" },
2329 { 0x9014, "Process status ON via AUTO" },
2330 { 0x9015, "Process status ON via manual" },
2331 { 0x9016, "Process status ON via protective command" },
2332 { 0x9017, "Process status OFF via AUTO" },
2333 { 0x9018, "Process status OFF via manual" },
2334 { 0x9019, "Process status OFF via protective command" },
2335 { 0x9021, "Function error on approach" },
2336 { 0x9022, "Function error on leaving" },
2337 { 0x9031, "Actuator (DE/WE) limit position OPEN" },
2338 { 0x9032, "Actuator (DE/WE) limit position not OPEN" },
2339 { 0x9033, "Actuator (DE/WE) limit position CLOSED" },
2340 { 0x9034, "Actuator (DE/WE) limit position not CLOSED" },
2341 { 0x9041, "Illegal status, tolerance time elapsed" },
2342 { 0x9042, "Illegal status, tolerance time not elapsed" },
2343 { 0x9043, "Interlock error, tolerance time = 0" },
2344 { 0x9044, "Interlock error, tolerance time > 0" },
2345 { 0x9045, "No reaction" },
2346 { 0x9046, "Final status exited illegally, tolerance time = 0" },
2347 { 0x9047, "Final status exited illegally, tolerance time > 0" },
2348 { 0x9050, "Upper limit of signal range USR" },
2349 { 0x9051, "Upper limit of measuring range UMR" },
2350 { 0x9052, "Lower limit of signal range LSR" },
2351 { 0x9053, "Lower limit of measuring range LMR" },
2352 { 0x9054, "Upper alarm limit UAL" },
2353 { 0x9055, "Upper warning limit UWL" },
2354 { 0x9056, "Upper tolerance limit UTL" },
2355 { 0x9057, "Lower tolerance limit LTL" },
2356 { 0x9058, "Lower warning limit LWL" },
2357 { 0x9059, "Lower alarm limit LAL" },
2358 { 0x9060, "GRAPH7 step entering/leaving" },
2359 { 0x9061, "GRAPH7 interlock error" },
2360 { 0x9062, "GRAPH7 execution error" },
2361 { 0x9063, "GRAPH7 error noted" },
2362 { 0x9064, "GRAPH7 error acknowledged" },
2363 { 0x9070, "Trend exceeded in positive direction" },
2364 { 0x9071, "Trend exceeded in negative direction" },
2365 { 0x9072, "No reaction" },
2366 { 0x9073, "Final state exited illegally" },
2367 { 0x9080, "Limit value exceeded, tolerance time = 0" },
2368 { 0x9081, "Limit value exceeded, tolerance time > 0" },
2369 { 0x9082, "Below limit value, tolerance time = 0" },
2370 { 0x9083, "Below limit value, tolerance time > 0" },
2371 { 0x9084, "Gradient exceeded, tolerance time = 0" },
2372 { 0x9085, "Gradient exceeded, tolerance time > 0" },
2373 { 0x9086, "Below gradient, tolerance time = 0" },
2374 { 0x9087, "Below gradient, tolerance time > 0" },
2375 { 0x9090, "User parameter assignment error entering/leaving" },
2376 { 0x90F0, "Overflow" },
2377 { 0x90F1, "Underflow" },
2378 { 0x90F2, "Division by 0" },
2379 { 0x90F3, "Illegal calculation operation" },
2380 { 0, NULL }
2381 };
2382 static value_string_ext cpu_diag_eventid_0x8_0x9_names_ext = VALUE_STRING_EXT_INIT(cpu_diag_eventid_0x8_0x9_names);
2383
2384 /**************************************************************************
2385 * Type of alarmquery in alarm query request
2386 */
2387 #define S7COMM_ALARM_MESSAGE_QUERYTYPE_BYALARMTYPE 1
2388 #define S7COMM_ALARM_MESSAGE_QUERYTYPE_BYEVENTID 3
2389
2390 static const value_string alarm_message_querytype_names[] = {
2391 { S7COMM_ALARM_MESSAGE_QUERYTYPE_BYALARMTYPE, "ByAlarmtype" },
2392 { S7COMM_ALARM_MESSAGE_QUERYTYPE_BYEVENTID, "ByEventID" },
2393 { 0, NULL }
2394 };
2395
2396 /**************************************************************************
2397 * Alarmtype in alarm query
2398 */
2399 #define S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_SCAN 1
2400 #define S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_8 2
2401 #define S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_S 4
2402
2403 static const value_string alarm_message_query_alarmtype_names[] = {
2404 { S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_SCAN, "SCAN" },
2405 { S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_8, "ALARM_8" },
2406 { S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_S, "ALARM_S" },
2407 { 0, NULL }
2408 };
2409
2410 /* CPU message service */
2411 static gint hf_s7comm_cpu_msgservice_subscribe_events = -1;
2412 static gint hf_s7comm_cpu_msgservice_subscribe_events_modetrans = -1;
2413 static gint hf_s7comm_cpu_msgservice_subscribe_events_system = -1;
2414 static gint hf_s7comm_cpu_msgservice_subscribe_events_userdefined = -1;
2415 static gint hf_s7comm_cpu_msgservice_subscribe_events_alarms = -1;
2416 static gint ett_s7comm_cpu_msgservice_subscribe_events = -1;
2417 static int * const s7comm_cpu_msgservice_subscribe_events_fields[] = {
2418 &hf_s7comm_cpu_msgservice_subscribe_events_modetrans,
2419 &hf_s7comm_cpu_msgservice_subscribe_events_system,
2420 &hf_s7comm_cpu_msgservice_subscribe_events_userdefined,
2421 &hf_s7comm_cpu_msgservice_subscribe_events_alarms,
2422 NULL
2423 };
2424 static gint hf_s7comm_cpu_msgservice_req_reserved1 = -1;
2425 static gint hf_s7comm_cpu_msgservice_username = -1;
2426 static gint hf_s7comm_cpu_msgservice_almtype = -1;
2427 static gint hf_s7comm_cpu_msgservice_req_reserved2 = -1;
2428 static gint hf_s7comm_cpu_msgservice_res_result = -1;
2429 static gint hf_s7comm_cpu_msgservice_res_reserved1 = -1;
2430 static gint hf_s7comm_cpu_msgservice_res_reserved2 = -1;
2431 static gint hf_s7comm_cpu_msgservice_res_reserved3 = -1;
2432
2433 static const value_string cpu_msgservice_almtype_names[] = {
2434 { 0, "SCAN_ABORT" },
2435 { 1, "SCAN_INITIATE" },
2436 { 4, "ALARM_ABORT" },
2437 { 5, "ALARM_INITIATE" },
2438 { 8, "ALARM_S_ABORT" },
2439 { 9, "ALARM_S_INITIATE" },
2440 { 0, NULL }
2441 };
2442
2443 static gint hf_s7comm_modetrans_param_subfunc = -1;
2444 static const value_string modetrans_param_subfunc_names[] = {
2445 { 0, "STOP" },
2446 { 1, "Warm Restart" },
2447 { 2, "RUN" },
2448 { 3, "Hot Restart" },
2449 { 4, "HOLD" },
2450 { 6, "Cold Restart" },
2451 { 9, "RUN_R (H-System redundant)" },
2452 { 11, "LINK-UP" },
2453 { 12, "UPDATE" },
2454 { 0, NULL }
2455 };
2456
2457 /* These fields used when reassembling S7COMM fragments */
2458 static gint hf_s7comm_fragments = -1;
2459 static gint hf_s7comm_fragment = -1;
2460 static gint hf_s7comm_fragment_overlap = -1;
2461 static gint hf_s7comm_fragment_overlap_conflict = -1;
2462 static gint hf_s7comm_fragment_multiple_tails = -1;
2463 static gint hf_s7comm_fragment_too_long_fragment = -1;
2464 static gint hf_s7comm_fragment_error = -1;
2465 static gint hf_s7comm_fragment_count = -1;
2466 static gint hf_s7comm_reassembled_in = -1;
2467 static gint hf_s7comm_reassembled_length = -1;
2468 static gint ett_s7comm_fragment = -1;
2469 static gint ett_s7comm_fragments = -1;
2470
2471 static const fragment_items s7comm_frag_items = {
2472 /* Fragment subtrees */
2473 &ett_s7comm_fragment,
2474 &ett_s7comm_fragments,
2475 /* Fragment fields */
2476 &hf_s7comm_fragments,
2477 &hf_s7comm_fragment,
2478 &hf_s7comm_fragment_overlap,
2479 &hf_s7comm_fragment_overlap_conflict,
2480 &hf_s7comm_fragment_multiple_tails,
2481 &hf_s7comm_fragment_too_long_fragment,
2482 &hf_s7comm_fragment_error,
2483 &hf_s7comm_fragment_count,
2484 /* Reassembled in field */
2485 &hf_s7comm_reassembled_in,
2486 /* Reassembled length field */
2487 &hf_s7comm_reassembled_length,
2488 /* Reassembled data field */
2489 NULL,
2490 /* Tag */
2491 "S7COMM fragments"
2492 };
2493
2494 static reassembly_table s7comm_reassembly_table;
2495
2496 /* These are the ids of the subtrees that we are creating */
2497 static gint ett_s7comm = -1; /* S7 communication tree, parent of all other subtree */
2498 static gint ett_s7comm_header = -1; /* Subtree for header block */
2499 static gint ett_s7comm_param = -1; /* Subtree for parameter block */
2500 static gint ett_s7comm_param_item = -1; /* Subtree for items in parameter block */
2501 static gint ett_s7comm_param_subitem = -1; /* Subtree for subitems under items in parameter block */
2502 static gint ett_s7comm_data = -1; /* Subtree for data block */
2503 static gint ett_s7comm_data_item = -1; /* Subtree for an item in data block */
2504 static gint ett_s7comm_item_address = -1; /* Subtree for an address (byte/bit) */
2505 static gint ett_s7comm_cpu_alarm_message = -1; /* Subtree for an alarm message */
2506 static gint ett_s7comm_cpu_alarm_message_object = -1; /* Subtree for an alarm message block*/
2507 static gint ett_s7comm_cpu_alarm_message_timestamp = -1; /* Subtree for an alarm message timestamp */
2508 static gint ett_s7comm_cpu_alarm_message_associated_value = -1; /* Subtree for an alarm message associated value */
2509 static gint ett_s7comm_cpu_diag_msg = -1; /* Subtree for a CPU diagnostic message */
2510 static gint ett_s7comm_prog_parameter = -1;
2511 static gint ett_s7comm_prog_data = -1;
2512
2513 static const char mon_names[][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
2514
2515 /*******************************************************************************************************
2516 *
2517 * Converts a siemens special timestamp to a string of 25+1 bytes length (e.g. "Apr 15, 2009 12:49:30.520").
2518 * The timestamp is 6 bytes long, one word is the number of days since 1.1.1984, and 4 bytes milliseconds of the day
2519 *
2520 *******************************************************************************************************/
2521 static void
s7comm_get_timestring_from_s7time(tvbuff_t * tvb,guint offset,char * str,gint max)2522 s7comm_get_timestring_from_s7time(tvbuff_t *tvb, guint offset, char *str, gint max)
2523 {
2524 guint16 days;
2525 guint32 day_msec;
2526 struct tm *mt;
2527 time_t t;
2528
2529 day_msec = tvb_get_ntohl(tvb, offset);
2530 days = tvb_get_ntohs(tvb, offset + 4);
2531
2532 t = 441763200L; /* 1.1.1984 00:00:00 */
2533 t += (guint32)days * (24*60*60);
2534 t += day_msec / 1000;
2535 mt = gmtime(&t);
2536 str[0] = '\0';
2537 if (mt != NULL) {
2538 g_snprintf(str, max, "%s %2d, %d %02d:%02d:%02d.%03d", mon_names[mt->tm_mon], mt->tm_mday,
2539 mt->tm_year + 1900, mt->tm_hour, mt->tm_min, mt->tm_sec, day_msec % 1000);
2540 }
2541 }
2542
2543 /*******************************************************************************************************
2544 *
2545 * Helper for time functions
2546 * Get int from bcd
2547 *
2548 *******************************************************************************************************/
2549 static guint8
s7comm_guint8_from_bcd(guint8 i)2550 s7comm_guint8_from_bcd(guint8 i)
2551 {
2552 return 10 * (i /16) + (i % 16);
2553 }
2554
2555 /*******************************************************************************************************
2556 *
2557 * Helper for time functions
2558 * Add a BCD coded timestamp (10/8 Bytes length) to tree
2559 *
2560 *******************************************************************************************************/
2561 static guint32
s7comm_add_timestamp_to_tree(tvbuff_t * tvb,proto_tree * tree,guint32 offset,gboolean append_text,gboolean has_ten_bytes)2562 s7comm_add_timestamp_to_tree(tvbuff_t *tvb,
2563 proto_tree *tree,
2564 guint32 offset,
2565 gboolean append_text,
2566 gboolean has_ten_bytes) /* if this is false the [0] reserved and [1] year bytes are missing */
2567 {
2568 guint8 timestamp[10];
2569 guint8 i;
2570 guint8 tmp;
2571 guint8 year_org;
2572 guint16 msec;
2573 nstime_t tv;
2574 proto_item *item = NULL;
2575 proto_item *time_tree = NULL;
2576 struct tm mt;
2577 int timestamp_size = 10;
2578
2579 if (has_ten_bytes) {
2580 /* The low nibble of byte 10 is weekday, the high nibble the LSD of msec */
2581 for (i = 0; i < 9; i++) {
2582 timestamp[i] = s7comm_guint8_from_bcd(tvb_get_guint8(tvb, offset + i));
2583 }
2584 tmp = tvb_get_guint8(tvb, offset + 9) >> 4;
2585 } else {
2586 /* this is a 8 byte timestamp, where the reserved and the year byte is missing */
2587 timestamp_size = 8;
2588 timestamp[0] = 0;
2589 timestamp[1] = 19; /* start with 19.., will be corrected later */
2590 for (i = 0; i < 7; i++) {
2591 timestamp[i + 2] = s7comm_guint8_from_bcd(tvb_get_guint8(tvb, offset + i));
2592 }
2593 tmp = tvb_get_guint8(tvb, offset + 7) >> 4;
2594 }
2595 timestamp[9] = s7comm_guint8_from_bcd(tmp);
2596
2597 msec = (guint16)timestamp[8] * 10 + (guint16)timestamp[9];
2598 year_org = timestamp[1];
2599 /* year special: ignore the first byte, since some cpus give 1914 for 2014
2600 * if second byte is below 89, it's 2000..2089, if over 90 it's 1990..1999
2601 */
2602 if (timestamp[2] < 89) {
2603 timestamp[1] = 20;
2604 }
2605 /* convert time to nstime_t */
2606 mt.tm_year = (timestamp[1] * 100 + timestamp[2]) - 1900;
2607 mt.tm_mon = timestamp[3] - 1;
2608 mt.tm_mday = timestamp[4];
2609 mt.tm_hour = timestamp[5];
2610 mt.tm_min = timestamp[6];
2611 mt.tm_sec = timestamp[7];
2612 mt.tm_isdst = -1;
2613 tv.secs = mktime(&mt);
2614 tv.nsecs = msec * 1000000;
2615 if (mt.tm_mon >= 0 && mt.tm_mon <= 11) {
2616 item = proto_tree_add_time_format(tree, hf_s7comm_data_ts, tvb, offset, timestamp_size, &tv,
2617 "S7 Timestamp: %s %2d, %d %02d:%02d:%02d.%03d", mon_names[mt.tm_mon], mt.tm_mday,
2618 mt.tm_year + 1900, mt.tm_hour, mt.tm_min, mt.tm_sec,
2619 msec);
2620 time_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
2621
2622 /* timefunction: s7 timestamp */
2623 if (has_ten_bytes) {
2624 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_reserved, tvb, offset, 1, timestamp[0]);
2625 offset += 1;
2626 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_year1, tvb, offset, 1, year_org);
2627 offset += 1;
2628 }
2629 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_year2, tvb, offset, 1, timestamp[2]);
2630 offset += 1;
2631 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_month, tvb, offset, 1, timestamp[3]);
2632 offset += 1;
2633 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_day, tvb, offset, 1, timestamp[4]);
2634 offset += 1;
2635 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_hour, tvb, offset, 1, timestamp[5]);
2636 offset += 1;
2637 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_minute, tvb, offset, 1, timestamp[6]);
2638 offset += 1;
2639 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_second, tvb, offset, 1, timestamp[7]);
2640 offset += 1;
2641 proto_tree_add_uint(time_tree, hf_s7comm_data_ts_millisecond, tvb, offset, 2, msec);
2642 proto_tree_add_item(time_tree, hf_s7comm_data_ts_weekday, tvb, offset, 2, ENC_BIG_ENDIAN);
2643 offset += 2;
2644
2645 if (append_text == TRUE) {
2646 proto_item_append_text(tree, "(Timestamp: %s %2d, %d %02d:%02d:%02d.%03d)", mon_names[mt.tm_mon], mt.tm_mday,
2647 mt.tm_year + 1900, mt.tm_hour, mt.tm_min, mt.tm_sec,
2648 msec);
2649 }
2650 } else {
2651 /* If the timestamp is invalid, continue as best as we can */
2652 if (has_ten_bytes) {
2653 offset += 10;
2654 }
2655 else {
2656 offset += 8;
2657 }
2658 }
2659 return offset;
2660 }
2661
2662 /*******************************************************************************************************
2663 *
2664 * Generate a comma separated string for registerflags
2665 *
2666 *******************************************************************************************************/
2667 static void
make_registerflag_string(gchar * str,guint8 flags,gint max)2668 make_registerflag_string(gchar *str, guint8 flags, gint max)
2669 {
2670 (void) g_strlcpy(str, "", max);
2671 if (flags & 0x01) (void) g_strlcat(str, "STW, ", max);
2672 if (flags & 0x02) (void) g_strlcat(str, "ACCU1, ", max);
2673 if (flags & 0x04) (void) g_strlcat(str, "ACCU2, ", max);
2674 if (flags & 0x08) (void) g_strlcat(str, "AR1, ", max);
2675 if (flags & 0x10) (void) g_strlcat(str, "AR2, ", max);
2676 if (flags & 0x20) (void) g_strlcat(str, "DB1, ", max);
2677 if (flags & 0x40) (void) g_strlcat(str, "DB2, ", max);
2678 if (strlen(str) > 2)
2679 str[strlen(str) - 2 ] = '\0';
2680 }
2681
2682 /*******************************************************************************************************
2683 *
2684 * Addressdefinition for Syntax ID S7-ANY (Step 7 Classic 300/400 or 1200/1500 not optimized)
2685 * type == 0x12, length == 10, syntax-ID == 0x10
2686 *
2687 *******************************************************************************************************/
2688 static guint32
s7comm_syntaxid_s7any(tvbuff_t * tvb,guint32 offset,proto_tree * tree)2689 s7comm_syntaxid_s7any(tvbuff_t *tvb,
2690 guint32 offset,
2691 proto_tree *tree)
2692 {
2693 guint32 t_size = 0;
2694 guint32 len = 0;
2695 guint32 db = 0;
2696 guint32 area = 0;
2697 guint32 a_address = 0;
2698 guint32 bytepos = 0;
2699 guint32 bitpos = 0;
2700 proto_item *address_item = NULL;
2701 proto_tree *address_item_tree = NULL;
2702
2703 /* Transport size, 1 byte */
2704 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_transport_size, tvb, offset, 1, ENC_BIG_ENDIAN, &t_size);
2705 offset += 1;
2706 /* Special handling of data record */
2707 area = tvb_get_guint8(tvb, offset + 4); /* peek area first */
2708 if (area == S7COMM_AREA_DATARECORD) {
2709 /* MLEN, 2 bytes */
2710 proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_mlen, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
2711 offset += 2;
2712 /* INDEX, 2 bytes */
2713 proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_index, tvb, offset, 2, ENC_BIG_ENDIAN, &db);
2714 offset += 2;
2715 /* Area, 1 byte */
2716 proto_tree_add_uint(tree, hf_s7comm_item_area, tvb, offset, 1, area);
2717 offset += 1;
2718 /* ID, 3 bytes */
2719 proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_id, tvb, offset, 3, ENC_BIG_ENDIAN, &a_address);
2720 offset += 3;
2721 proto_item_append_text(tree, " (RECORD MLEN=%d INDEX=0x%04x ID=%d)", len, db, a_address);
2722 } else {
2723 /* Length, 2 bytes */
2724 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_length, tvb, offset, 2, ENC_BIG_ENDIAN, &len);
2725 offset += 2;
2726 /* DB number, 2 bytes */
2727 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_db, tvb, offset, 2, ENC_BIG_ENDIAN, &db);
2728 offset += 2;
2729 /* Area, 1 byte */
2730 proto_tree_add_uint(tree, hf_s7comm_item_area, tvb, offset, 1, area);
2731 offset += 1;
2732 /* Address, 3 bytes */
2733 address_item = proto_tree_add_item_ret_uint(tree, hf_s7comm_item_address, tvb, offset, 3, ENC_BIG_ENDIAN, &a_address);
2734 address_item_tree = proto_item_add_subtree(address_item, ett_s7comm_item_address);
2735 bytepos = a_address / 8;
2736 bitpos = a_address % 8;
2737 /* build a full address to show item data directly beside the item */
2738 proto_item_append_text(tree, " (%s", val_to_str(area, item_areanames_short, "unknown area 0x%02x"));
2739 if (area == S7COMM_AREA_TIMER || area == S7COMM_AREA_COUNTER) {
2740 proto_item_append_text(tree, " %d)", a_address);
2741 proto_tree_add_uint(address_item_tree, hf_s7comm_item_address_nr, tvb, offset, 3, a_address);
2742 } else {
2743 proto_tree_add_uint(address_item_tree, hf_s7comm_item_address_byte, tvb, offset, 3, a_address);
2744 proto_tree_add_uint(address_item_tree, hf_s7comm_item_address_bit, tvb, offset, 3, a_address);
2745 if (area == S7COMM_AREA_DB) {
2746 proto_item_append_text(tree, " %d.DBX", db);
2747 } else if (area == S7COMM_AREA_DI) {
2748 proto_item_append_text(tree, " %d.DIX", db);
2749 }
2750 proto_item_append_text(tree, " %d.%d %s %d)",
2751 bytepos, bitpos, val_to_str(t_size, item_transportsizenames, "Unknown transport size: 0x%02x"), len);
2752 }
2753 offset += 3;
2754 }
2755 return offset;
2756 }
2757 /*******************************************************************************************************
2758 *
2759 * Addressdefinition to read a DB area (S7-400 special)
2760 * type == 0x12, length >= 7, syntax-ID == 0xb0
2761 *
2762 *******************************************************************************************************/
2763 static guint32
s7comm_syntaxid_dbread(tvbuff_t * tvb,guint32 offset,proto_tree * tree)2764 s7comm_syntaxid_dbread(tvbuff_t *tvb,
2765 guint32 offset,
2766 proto_tree *tree)
2767 {
2768 guint32 number_of_areas = 0;
2769 guint32 len = 0;
2770 guint32 db = 0;
2771 guint32 bytepos = 0;
2772 guint32 i;
2773 proto_item *sub_item = NULL;
2774 proto_tree *sub_item_tree = NULL;
2775
2776 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_dbread_numareas, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_areas);
2777 proto_item_append_text(tree, " (%d Data-Areas of Syntax-Id DBREAD)", number_of_areas);
2778 offset += 1;
2779 for (i = 0; i < number_of_areas; i++) {
2780 sub_item = proto_tree_add_item(tree, hf_s7comm_param_subitem, tvb, offset, 5, ENC_NA);
2781 sub_item_tree = proto_item_add_subtree(sub_item, ett_s7comm_param_subitem);
2782 proto_tree_add_item_ret_uint(sub_item_tree, hf_s7comm_item_dbread_length, tvb, offset, 1, ENC_BIG_ENDIAN, &len);
2783 offset += 1;
2784 proto_tree_add_item_ret_uint(sub_item_tree, hf_s7comm_item_dbread_db, tvb, offset, 2, ENC_BIG_ENDIAN, &db);
2785 offset += 2;
2786 proto_tree_add_item_ret_uint(sub_item_tree, hf_s7comm_item_dbread_startadr, tvb, offset, 2, ENC_BIG_ENDIAN, &bytepos);
2787 offset += 2;
2788 /* Display in pseudo S7-Any Format */
2789 proto_item_append_text(sub_item, " [%d]: (DB%d.DBB %d BYTE %d)", i+1, db, bytepos, len);
2790 }
2791 return offset;
2792 }
2793
2794 /*******************************************************************************************************
2795 *
2796 * Addressdefinition for TIA S7 1200 symbolic address mode
2797 * type == 0x12, length >= 14, syntax-ID == 0xb2
2798 *
2799 *******************************************************************************************************/
2800 static guint32
s7comm_syntaxid_1200sym(tvbuff_t * tvb,guint32 offset,proto_tree * tree,guint8 var_spec_length)2801 s7comm_syntaxid_1200sym(tvbuff_t *tvb,
2802 guint32 offset,
2803 proto_tree *tree,
2804 guint8 var_spec_length)
2805 {
2806 guint32 tia_var_area1 = 0;
2807 guint32 tia_var_area2 = 0;
2808 guint8 tia_lid_flags = 0;
2809 guint32 tia_value = 0;
2810 guint16 i;
2811 proto_item *sub_item = NULL;
2812 proto_tree *sub_item_tree = NULL;
2813
2814 proto_item_append_text(tree, " 1200 symbolic address");
2815 /* first byte in address seems always to be 0xff */
2816 proto_tree_add_item(tree, hf_s7comm_tia1200_item_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
2817 offset += 1;
2818 /* When Bytes 2/3 == 0, then Bytes 4/5 defines the area as known from classic 300/400 address mode.
2819 * When Bytes 2/3 == 0x8a0e then Bytes 4/5 are containing the DB number.
2820 */
2821 proto_tree_add_item_ret_uint(tree, hf_s7comm_tia1200_item_area1, tvb, offset, 2, ENC_BIG_ENDIAN, &tia_var_area1);
2822 offset += 2;
2823 tia_var_area2 = tvb_get_ntohs(tvb, offset);
2824 if (tia_var_area1 == S7COMM_TIA1200_VAR_ITEM_AREA1_IQMCT) {
2825 proto_tree_add_uint(tree, hf_s7comm_tia1200_item_area2, tvb, offset, 2, tia_var_area2);
2826 proto_item_append_text(tree, " - Accessing %s", val_to_str(tia_var_area2, tia1200_var_item_area2_names, "Unknown IQMCT Area: 0x%04x"));
2827 offset += 2;
2828 } else if (tia_var_area1 == S7COMM_TIA1200_VAR_ITEM_AREA1_DB) {
2829 proto_tree_add_uint(tree, hf_s7comm_tia1200_item_dbnumber, tvb, offset, 2, tia_var_area2);
2830 proto_item_append_text(tree, " - Accessing DB%d", tia_var_area2);
2831 offset += 2;
2832 } else {
2833 /* for current unknown areas */
2834 proto_tree_add_uint(tree, hf_s7comm_tia1200_item_area2unknown, tvb, offset, 2, tia_var_area2);
2835 proto_item_append_text(tree, " - Unknown area specification");
2836 offset += 2;
2837 }
2838 proto_tree_add_item(tree, hf_s7comm_tia1200_item_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
2839 offset += 4;
2840
2841 for (i = 0; i < (var_spec_length - 10) / 4; i++) {
2842 sub_item = proto_tree_add_item(tree, hf_s7comm_tia1200_substructure_item, tvb, offset, 4, ENC_NA);
2843 sub_item_tree = proto_item_add_subtree(sub_item, ett_s7comm_param_subitem);
2844 tia_lid_flags = tvb_get_guint8(tvb, offset) >> 4;
2845 proto_tree_add_item(sub_item_tree, hf_s7comm_tia1200_var_lid_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
2846 tia_value = tvb_get_ntohl(tvb, offset) & 0x0fffffff;
2847 proto_item_append_text(sub_item, " [%d]: %s, Value: %u", i + 1,
2848 val_to_str(tia_lid_flags, tia1200_var_lid_flag_names, "Unknown flags: 0x%02x"),
2849 tia_value
2850 );
2851 proto_tree_add_item(sub_item_tree, hf_s7comm_tia1200_item_value, tvb, offset, 4, ENC_BIG_ENDIAN);
2852 offset += 4;
2853 }
2854 return offset;
2855 }
2856
2857 /*******************************************************************************************************
2858 *
2859 * Addressdefinition for Sinumeric NCK access
2860 * type == 0x12, length == 8, syntax-ID == 0x82 or == 0x83 or == 0x84
2861 *
2862 *******************************************************************************************************/
2863 static guint32
s7comm_syntaxid_nck(tvbuff_t * tvb,guint32 offset,proto_tree * tree)2864 s7comm_syntaxid_nck(tvbuff_t *tvb,
2865 guint32 offset,
2866 proto_tree *tree)
2867 {
2868 guint32 area = 0;
2869 guint32 nck_area = 0;
2870 guint32 nck_unit = 0;
2871 guint32 nck_column = 0;
2872 guint32 nck_line = 0;
2873 guint32 nck_module = 0;
2874
2875 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_areaunit, tvb, offset, 1, ENC_BIG_ENDIAN, &area);
2876 nck_area = area >> 5;
2877 nck_unit = area & 0x1f;
2878 proto_tree_add_item(tree, hf_s7comm_item_nck_area, tvb, offset, 1, ENC_BIG_ENDIAN);
2879 proto_tree_add_item(tree, hf_s7comm_item_nck_unit, tvb, offset, 1, ENC_BIG_ENDIAN);
2880 offset += 1;
2881 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_column, tvb, offset, 2, ENC_BIG_ENDIAN, &nck_column);
2882 offset += 2;
2883 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_line, tvb, offset, 2, ENC_BIG_ENDIAN, &nck_line);
2884 offset += 2;
2885 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_nck_module, tvb, offset, 1, ENC_BIG_ENDIAN, &nck_module);
2886 offset += 1;
2887 proto_tree_add_item(tree, hf_s7comm_item_nck_linecount, tvb, offset, 1, ENC_BIG_ENDIAN);
2888 offset += 1;
2889 proto_item_append_text(tree, " (NCK Area:%d Unit:%d Column:%d Line:%d Module:0x%02x)",
2890 nck_area, nck_unit, nck_column, nck_line, nck_module);
2891 return offset;
2892 }
2893
2894 /*******************************************************************************************************
2895 *
2896 * Addressdefinition for accessing Multimaster / Sinamics frequency convertes via routing from DriveES.
2897 * type == 0x12, length == 10, syntax-ID == 0x82
2898 *
2899 *******************************************************************************************************/
2900 static guint32
s7comm_syntaxid_driveesany(tvbuff_t * tvb,guint32 offset,proto_tree * tree)2901 s7comm_syntaxid_driveesany(tvbuff_t *tvb,
2902 guint32 offset,
2903 proto_tree *tree)
2904 {
2905 guint32 nr = 0;
2906 guint32 idx = 0;
2907
2908 proto_tree_add_item(tree, hf_s7comm_item_driveesany_unknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
2909 offset += 1;
2910 proto_tree_add_item(tree, hf_s7comm_item_driveesany_unknown2, tvb, offset, 2, ENC_BIG_ENDIAN);
2911 offset += 2;
2912 proto_tree_add_item(tree, hf_s7comm_item_driveesany_unknown3, tvb, offset, 2, ENC_BIG_ENDIAN);
2913 offset += 2;
2914 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_driveesany_parameter_nr, tvb, offset, 2, ENC_BIG_ENDIAN, &nr);
2915 offset += 2;
2916 proto_tree_add_item_ret_uint(tree, hf_s7comm_item_driveesany_parameter_idx, tvb, offset, 2, ENC_BIG_ENDIAN, &idx);
2917 offset += 2;
2918 proto_item_append_text(tree, " (DriveES Parameter: %d[%d])", nr, idx);
2919 return offset;
2920 }
2921
2922 /*******************************************************************************************************
2923 *
2924 * Dissect the parameter details of a read/write request (Items)
2925 *
2926 *******************************************************************************************************/
2927 static guint32
s7comm_decode_param_item(tvbuff_t * tvb,guint32 offset,proto_tree * sub_tree,guint8 item_no)2928 s7comm_decode_param_item(tvbuff_t *tvb,
2929 guint32 offset,
2930 proto_tree *sub_tree,
2931 guint8 item_no)
2932 {
2933 proto_item *item = NULL;
2934 proto_tree *item_tree = NULL;
2935 guint8 var_spec_type = 0;
2936 guint8 var_spec_length = 0;
2937 guint8 var_spec_syntax_id = 0;
2938
2939 var_spec_type = tvb_get_guint8(tvb, offset);
2940 var_spec_length = tvb_get_guint8(tvb, offset + 1);
2941 var_spec_syntax_id = tvb_get_guint8(tvb, offset + 2);
2942
2943 /* Insert a new tree for every item */
2944 item = proto_tree_add_item(sub_tree, hf_s7comm_param_item, tvb, offset, var_spec_length + 2, ENC_NA);
2945 item_tree = proto_item_add_subtree(item, ett_s7comm_param_item);
2946 proto_item_append_text(item, " [%d]:", item_no + 1);
2947
2948 /* Item head, constant 3 bytes */
2949 proto_tree_add_item(item_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
2950 offset += 1;
2951 proto_tree_add_item(item_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2952 offset += 1;
2953 proto_tree_add_item(item_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2954 offset += 1;
2955
2956 if (var_spec_type == 0x12 && var_spec_length == 10 && var_spec_syntax_id == S7COMM_SYNTAXID_S7ANY) {
2957 /* Step 7 Classic 300 400 */
2958 offset = s7comm_syntaxid_s7any(tvb, offset, item_tree);
2959 } else if (var_spec_type == 0x12 && var_spec_length >= 7 && var_spec_syntax_id == S7COMM_SYNTAXID_DBREAD) {
2960 /* S7-400 special address mode (kind of cyclic read) */
2961 offset = s7comm_syntaxid_dbread(tvb, offset, item_tree);
2962 } else if (var_spec_type == 0x12 && var_spec_length >= 14 && var_spec_syntax_id == S7COMM_SYNTAXID_1200SYM) {
2963 /* TIA S7 1200 symbolic address mode */
2964 offset = s7comm_syntaxid_1200sym(tvb, offset, item_tree, var_spec_length);
2965 } else if (var_spec_type == 0x12 && var_spec_length == 8
2966 && ((var_spec_syntax_id == S7COMM_SYNTAXID_NCK)
2967 || (var_spec_syntax_id == S7COMM_SYNTAXID_NCK_METRIC)
2968 || (var_spec_syntax_id == S7COMM_SYNTAXID_NCK_INCH))) {
2969 /* Sinumerik NCK access */
2970 offset = s7comm_syntaxid_nck(tvb, offset, item_tree);
2971 } else if (var_spec_type == 0x12 && var_spec_length == 10 && var_spec_syntax_id == S7COMM_SYNTAXID_DRIVEESANY) {
2972 /* Accessing frequency inverter parameters (via routing) */
2973 offset = s7comm_syntaxid_driveesany(tvb, offset, item_tree);
2974 }
2975 else {
2976 /* var spec, length and syntax id are still added to tree here */
2977 offset += var_spec_length - 1;
2978 proto_item_append_text(item_tree, " Unknown variable specification");
2979 }
2980 return offset;
2981 }
2982
2983 /*******************************************************************************************************
2984 *
2985 * Decode parameter part of a PDU for setup communication
2986 *
2987 *******************************************************************************************************/
2988 static guint32
s7comm_decode_pdu_setup_communication(tvbuff_t * tvb,proto_tree * tree,guint32 offset)2989 s7comm_decode_pdu_setup_communication(tvbuff_t *tvb,
2990 proto_tree *tree,
2991 guint32 offset)
2992 {
2993 proto_tree_add_item(tree, hf_s7comm_param_setup_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
2994 offset += 1;
2995 proto_tree_add_item(tree, hf_s7comm_param_maxamq_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
2996 offset += 2;
2997 proto_tree_add_item(tree, hf_s7comm_param_maxamq_called, tvb, offset, 2, ENC_BIG_ENDIAN);
2998 offset += 2;
2999 proto_tree_add_item(tree, hf_s7comm_param_neg_pdu_length, tvb, offset, 2, ENC_BIG_ENDIAN);
3000 offset += 2;
3001 return offset;
3002 }
3003
3004 /*******************************************************************************************************
3005 *
3006 * PDU Type: Response -> Function Write -> Data part
3007 *
3008 *******************************************************************************************************/
3009 static guint32
s7comm_decode_response_write_data(tvbuff_t * tvb,proto_tree * tree,guint8 item_count,guint32 offset)3010 s7comm_decode_response_write_data(tvbuff_t *tvb,
3011 proto_tree *tree,
3012 guint8 item_count,
3013 guint32 offset)
3014 {
3015 guint8 ret_val = 0;
3016 guint8 i = 0;
3017 proto_item *item = NULL;
3018 proto_tree *item_tree = NULL;
3019
3020 for (i = 0; i < item_count; i++) {
3021 ret_val = tvb_get_guint8(tvb, offset);
3022 /* Insert a new tree for every item */
3023 item = proto_tree_add_item(tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
3024 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
3025 proto_item_append_text(item, " [%d]: (%s)", i+1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
3026 proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
3027 offset += 1;
3028 }
3029 return offset;
3030 }
3031
3032 /*******************************************************************************************************
3033 *
3034 * PDU Type: Response -> Function Read -> Data part
3035 * Request -> Function Write -> Data part
3036 *
3037 *******************************************************************************************************/
3038 static guint32
s7comm_decode_response_read_data(tvbuff_t * tvb,proto_tree * tree,guint8 item_count,guint32 offset)3039 s7comm_decode_response_read_data(tvbuff_t *tvb,
3040 proto_tree *tree,
3041 guint8 item_count,
3042 guint32 offset)
3043 {
3044 guint8 ret_val = 0;
3045 guint8 tsize = 0;
3046 guint16 len = 0, len2 = 0;
3047 guint16 head_len = 4; /* 1 byte res-code, 1 byte transp-size, 2 bytes len */
3048 guint8 i = 0;
3049 proto_item *item = NULL;
3050 proto_tree *item_tree = NULL;
3051
3052 /* Maybe this is only valid for Sinumerik NCK: Pre-check transport-size
3053 * If transport size is 0x11 or 0x12, then an array with requested NCK areas will follow.
3054 */
3055 tsize = tvb_get_guint8(tvb, offset + 1);
3056 if (tsize == S7COMM_DATA_TRANSPORT_SIZE_NCKADDR1 || tsize == S7COMM_DATA_TRANSPORT_SIZE_NCKADDR2) {
3057 proto_tree_add_item(tree, hf_s7comm_data_returncode, tvb, offset, 1, ENC_BIG_ENDIAN);
3058 proto_tree_add_uint(tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
3059 offset += 2;
3060 for (i = 0; i < item_count; i++) {
3061 offset = s7comm_decode_param_item(tvb, offset, tree, i);
3062 }
3063 } else {
3064 /* Standard */
3065 for (i = 0; i < item_count; i++) {
3066 ret_val = tvb_get_guint8(tvb, offset);
3067 if (ret_val == S7COMM_ITEM_RETVAL_RESERVED ||
3068 ret_val == S7COMM_ITEM_RETVAL_DATA_OK ||
3069 ret_val == S7COMM_ITEM_RETVAL_DATA_ERR
3070 ) {
3071 tsize = tvb_get_guint8(tvb, offset + 1);
3072 len = tvb_get_ntohs(tvb, offset + 2);
3073 /* calculate length in bytes */
3074 if (tsize == S7COMM_DATA_TRANSPORT_SIZE_BBIT ||
3075 tsize == S7COMM_DATA_TRANSPORT_SIZE_BBYTE ||
3076 tsize == S7COMM_DATA_TRANSPORT_SIZE_BINT
3077 ) { /* given length is in number of bits */
3078 if (len % 8) { /* len is not a multiple of 8, then round up to next number */
3079 len /= 8;
3080 len = len + 1;
3081 } else {
3082 len /= 8;
3083 }
3084 }
3085
3086 /* the PLC places extra bytes at the end of all but last result, if length is not a multiple of 2 */
3087 if ((len % 2) && (i < (item_count-1))) {
3088 len2 = len + 1;
3089 } else {
3090 len2 = len;
3091 }
3092 }
3093 /* Insert a new tree for every item */
3094 item = proto_tree_add_item(tree, hf_s7comm_data_item, tvb, offset, len + head_len, ENC_NA);
3095 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
3096 proto_item_append_text(item, " [%d]: (%s)", i+1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
3097
3098 proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
3099 proto_tree_add_uint(item_tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
3100 proto_tree_add_uint(item_tree, hf_s7comm_data_length, tvb, offset + 2, 2, len);
3101 offset += head_len;
3102
3103 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK || ret_val == S7COMM_ITEM_RETVAL_RESERVED) {
3104 proto_tree_add_item(item_tree, hf_s7comm_readresponse_data, tvb, offset, len, ENC_NA);
3105 offset += len;
3106 if (len != len2) {
3107 proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
3108 offset += 1;
3109 }
3110 }
3111 }
3112 }
3113 return offset;
3114 }
3115
3116 /*******************************************************************************************************
3117 *
3118 * PDU Type: Request or Response -> Function 0x29 (PLC control functions -> STOP)
3119 *
3120 *******************************************************************************************************/
3121 static guint32
s7comm_decode_plc_controls_param_hex29(tvbuff_t * tvb,proto_tree * tree,guint32 offset)3122 s7comm_decode_plc_controls_param_hex29(tvbuff_t *tvb,
3123 proto_tree *tree,
3124 guint32 offset)
3125 {
3126 guint8 len;
3127
3128 /* The first byte 0x29 is checked and inserted to tree outside, so skip it here */
3129 offset += 1;
3130 /* Meaning of first 5 bytes (Part 1) is unknown */
3131 proto_tree_add_item(tree, hf_s7comm_piservice_unknown1, tvb, offset, 5, ENC_NA);
3132 offset += 5;
3133 /* Part 2 */
3134 len = tvb_get_guint8(tvb, offset);
3135 proto_tree_add_uint(tree, hf_s7comm_data_plccontrol_part2_len, tvb, offset, 1, len);
3136 offset += 1;
3137 /* Function as string */
3138 proto_tree_add_item(tree, hf_s7comm_piservice_servicename, tvb, offset, len, ENC_ASCII|ENC_NA);
3139 offset += len;
3140
3141 return offset;
3142 }
3143
3144 /*******************************************************************************************************
3145 * PI_START Parameters: Decodes a parameter array with string values.
3146 *******************************************************************************************************/
3147 static guint32
s7comm_decode_pistart_parameters(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * param_tree,const guint8 * servicename,guint8 nfields,guint hf[],guint32 offset)3148 s7comm_decode_pistart_parameters(tvbuff_t *tvb,
3149 packet_info *pinfo,
3150 proto_tree *tree,
3151 proto_tree *param_tree,
3152 const guint8 *servicename,
3153 guint8 nfields, /* number of fields used */
3154 guint hf[], /* array with header fields */
3155 guint32 offset)
3156 {
3157 guint8 i;
3158 guint8 len;
3159 wmem_strbuf_t *args_buf;
3160 args_buf = wmem_strbuf_new_label(pinfo->pool);
3161
3162 for (i = 0; i < nfields; i++) {
3163 len = tvb_get_guint8(tvb, offset);
3164 proto_tree_add_uint(param_tree, hf_s7comm_piservice_string_len, tvb, offset, 1, len);
3165 offset += 1;
3166 proto_tree_add_item(param_tree, hf[i], tvb, offset, len, ENC_ASCII|ENC_NA);
3167 wmem_strbuf_append(args_buf, "\"");
3168 wmem_strbuf_append(args_buf, tvb_format_text(pinfo->pool, tvb, offset, len));
3169 if (i < nfields-1) {
3170 wmem_strbuf_append(args_buf, "\", ");
3171 } else {
3172 wmem_strbuf_append(args_buf, "\"");
3173 }
3174 offset += len + (len % 2 == 0);
3175 }
3176 proto_item_append_text(param_tree, ": (%s)", wmem_strbuf_get_str(args_buf));
3177 proto_item_append_text(tree, " -> %s(%s)", servicename, wmem_strbuf_get_str(args_buf));
3178 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s(%s)", servicename, wmem_strbuf_get_str(args_buf));
3179
3180 return offset;
3181 }
3182
3183 /*******************************************************************************************************
3184 * PI-Service
3185 *******************************************************************************************************/
3186 static guint32
s7comm_decode_pi_service(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint16 plength,guint32 offset)3187 s7comm_decode_pi_service(tvbuff_t *tvb,
3188 packet_info *pinfo,
3189 proto_tree *tree,
3190 guint16 plength,
3191 guint32 offset)
3192 {
3193 guint16 len, paramlen;
3194 guint32 startoffset;
3195 guint32 paramoffset;
3196 guint8 count;
3197 guint8 i;
3198 const guint8 *servicename;
3199 const guint8 *str;
3200 const guint8 *str1;
3201 guint16 blocktype;
3202 guint hf[13];
3203 int pi_servicename_idx;
3204 const gchar *pi_servicename_descr;
3205
3206 proto_item *item = NULL;
3207 proto_item *itemadd = NULL;
3208 proto_tree *param_tree = NULL;
3209 proto_tree *file_tree = NULL;
3210
3211 gint32 num = -1;
3212 gboolean num_valid;
3213
3214 startoffset = offset;
3215
3216 /* The first byte is checked and inserted to tree outside, so skip it here */
3217 offset += 1;
3218
3219 /* First part is unknown, 7 bytes */
3220 proto_tree_add_item(tree, hf_s7comm_piservice_unknown1, tvb, offset, 7, ENC_NA);
3221 offset += 7;
3222
3223 if (offset - startoffset >= plength) {
3224 return offset;
3225 }
3226 /* Parameter block */
3227 paramlen = tvb_get_ntohs(tvb, offset);
3228 proto_tree_add_uint(tree, hf_s7comm_piservice_parameterblock_len, tvb, offset, 2, paramlen);
3229 offset += 2;
3230
3231 paramoffset = offset;
3232 item = proto_tree_add_item(tree, hf_s7comm_piservice_parameterblock, tvb, offset, paramlen, ENC_NA);
3233 param_tree = proto_item_add_subtree(item, ett_s7comm_piservice_parameterblock);
3234 offset += paramlen;
3235
3236 /* PI servicename */
3237 len = tvb_get_guint8(tvb, offset);
3238 proto_tree_add_uint(tree, hf_s7comm_piservice_string_len, tvb, offset, 1, len);
3239 offset += 1;
3240 item = proto_tree_add_item_ret_string(tree, hf_s7comm_piservice_servicename, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, &servicename);
3241 offset += len;
3242
3243 /* get the index position in pi_service_names, and add infotext with description to the item */
3244 pi_servicename_descr = try_str_to_str_idx((const gchar*)servicename, pi_service_names, &pi_servicename_idx);
3245 if (pi_servicename_idx < 0) {
3246 pi_servicename_idx = S7COMM_PI_UNKNOWN;
3247 pi_servicename_descr = "Unknown PI Service";
3248 }
3249 proto_item_append_text(item, " [%s]", pi_servicename_descr);
3250
3251 /* Work parameter data, depending on servicename */
3252 switch (pi_servicename_idx) {
3253 case S7COMM_PI_INSE:
3254 case S7COMM_PI_INS2:
3255 case S7COMM_PI_DELE:
3256 count = tvb_get_guint8(tvb, paramoffset); /* number of blocks following */
3257 proto_tree_add_uint(param_tree, hf_s7comm_data_plccontrol_block_cnt, tvb, paramoffset, 1, count);
3258 paramoffset += 1;
3259 /* Unknown, is always 0x00 */
3260 proto_tree_add_item(param_tree, hf_s7comm_data_pi_inse_unknown, tvb, paramoffset, 1, ENC_BIG_ENDIAN);
3261 paramoffset += 1;
3262 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s(", servicename);
3263 for (i = 0; i < count; i++) {
3264 item = proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_filename, tvb, paramoffset, 8, ENC_ASCII|ENC_NA);
3265 file_tree = proto_item_add_subtree(item, ett_s7comm_plcfilename);
3266 blocktype = tvb_get_ntohs(tvb, paramoffset);
3267 itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_block_type, tvb, paramoffset, 2, ENC_ASCII|ENC_NA);
3268 proto_item_append_text(itemadd, " (%s)", val_to_str(blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3269 paramoffset += 2;
3270 proto_tree_add_item_ret_string(file_tree, hf_s7comm_data_blockcontrol_block_num, tvb, paramoffset, 5, ENC_ASCII|ENC_NA, pinfo->pool, &str);
3271 paramoffset += 5;
3272 num_valid = ws_strtoi32((const char*)str, NULL, &num);
3273 proto_item_append_text(file_tree, " [%s ",
3274 val_to_str(blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3275 col_append_str(pinfo->cinfo, COL_INFO,
3276 val_to_str(blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3277 if (num_valid) {
3278 proto_item_append_text(file_tree, "%d]", num);
3279 col_append_fstr(pinfo->cinfo, COL_INFO, "%d", num);
3280 } else {
3281 expert_add_info(pinfo, file_tree, &ei_s7comm_data_blockcontrol_block_num_invalid);
3282 proto_item_append_text(file_tree, "NaN]");
3283 col_append_str(pinfo->cinfo, COL_INFO, "NaN");
3284 }
3285 if (i+1 < count) {
3286 col_append_str(pinfo->cinfo, COL_INFO, ", ");
3287 }
3288 itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_dest_filesys, tvb, paramoffset, 1, ENC_ASCII|ENC_NA);
3289 proto_item_append_text(itemadd, " (%s)", val_to_str(tvb_get_guint8(tvb, paramoffset), blocktype_attribute2_names, "Unknown filesys: %c"));
3290 paramoffset += 1;
3291 }
3292 col_append_str(pinfo->cinfo, COL_INFO, ")");
3293 break;
3294 case S7COMM_PIP_PROGRAM:
3295 case S7COMM_PI_MODU:
3296 case S7COMM_PI_GARB:
3297 if (paramlen == 0) {
3298 proto_item_append_text(param_tree, ": ()");
3299 proto_item_append_text(tree, " -> %s()", servicename);
3300 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s()", servicename);
3301 } else {
3302 proto_tree_add_item_ret_string(param_tree, hf_s7comm_data_plccontrol_argument, tvb, paramoffset, paramlen, ENC_ASCII|ENC_NA, pinfo->pool, &str1);
3303 proto_item_append_text(param_tree, ": (\"%s\")", str1);
3304 proto_item_append_text(tree, " -> %s(\"%s\")", servicename, str1);
3305 col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s(\"%s\")", servicename, str1);
3306 }
3307 break;
3308 case S7COMM_PI_N_LOGIN_:
3309 hf[0] = hf_s7comm_pi_n_x_addressident;
3310 hf[1] = hf_s7comm_pi_n_x_password;
3311 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3312 break;
3313 case S7COMM_PI_N_LOGOUT:
3314 case S7COMM_PI_N_CANCEL:
3315 case S7COMM_PI_N_DASAVE:
3316 case S7COMM_PI_N_DIGIOF:
3317 case S7COMM_PI_N_DIGION:
3318 case S7COMM_PI_N_DZERO_:
3319 case S7COMM_PI_N_ENDEXT:
3320 case S7COMM_PI_N_OST_OF:
3321 case S7COMM_PI_N_OST_ON:
3322 case S7COMM_PI_N_SCALE_:
3323 case S7COMM_PI_N_SETUFR:
3324 case S7COMM_PI_N_STRTLK:
3325 case S7COMM_PI_N_STRTUL:
3326 case S7COMM_PI_N_TMRASS:
3327 hf[0] = hf_s7comm_pi_n_x_addressident;
3328 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 1, hf, paramoffset);
3329 break;
3330 case S7COMM_PI_N_F_DELE:
3331 case S7COMM_PI_N_EXTERN:
3332 case S7COMM_PI_N_EXTMOD:
3333 case S7COMM_PI_N_F_DELR:
3334 case S7COMM_PI_N_F_XFER:
3335 case S7COMM_PI_N_LOCKE_:
3336 case S7COMM_PI_N_SELECT:
3337 case S7COMM_PI_N_SRTEXT:
3338 hf[0] = hf_s7comm_pi_n_x_addressident;
3339 hf[1] = hf_s7comm_pi_n_x_filename;
3340 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3341 break;
3342 case S7COMM_PI_N_F_CLOS:
3343 hf[0] = hf_s7comm_pi_n_x_addressident;
3344 hf[1] = hf_s7comm_pi_n_x_editwindowname;
3345 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3346 break;
3347 case S7COMM_PI_N_F_OPEN:
3348 case S7COMM_PI_N_F_OPER:
3349 hf[0] = hf_s7comm_pi_n_x_addressident;
3350 hf[1] = hf_s7comm_pi_n_x_filename;
3351 hf[2] = hf_s7comm_pi_n_x_editwindowname;
3352 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3353 break;
3354 case S7COMM_PI_N_F_SEEK:
3355 hf[0] = hf_s7comm_pi_n_x_addressident;
3356 hf[1] = hf_s7comm_pi_n_x_editwindowname;
3357 hf[2] = hf_s7comm_pi_n_x_seekpointer;
3358 hf[3] = hf_s7comm_pi_n_x_windowsize;
3359 hf[4] = hf_s7comm_pi_n_x_comparestring;
3360 hf[5] = hf_s7comm_pi_n_x_skipcount;
3361 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3362 break;
3363 case S7COMM_PI_N_ASUP__:
3364 hf[0] = hf_s7comm_pi_n_x_addressident;
3365 hf[1] = hf_s7comm_pi_n_x_interruptnr;
3366 hf[2] = hf_s7comm_pi_n_x_priority;
3367 hf[3] = hf_s7comm_pi_n_x_liftfast;
3368 hf[4] = hf_s7comm_pi_n_x_blsync;
3369 hf[5] = hf_s7comm_pi_n_x_filename;
3370 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3371 break;
3372 case S7COMM_PI_N_CHEKDM:
3373 hf[0] = hf_s7comm_pi_n_x_addressident;
3374 hf[1] = hf_s7comm_pi_n_x_magnr;
3375 hf[2] = hf_s7comm_pi_n_x_dnr;
3376 hf[3] = hf_s7comm_pi_n_x_spindlenumber;
3377 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3378 break;
3379 case S7COMM_PI_N_CHKDNO:
3380 hf[0] = hf_s7comm_pi_n_x_addressident;
3381 hf[1] = hf_s7comm_pi_n_x_wznr;
3382 hf[2] = hf_s7comm_pi_n_x_wznr;
3383 hf[3] = hf_s7comm_pi_n_x_dnr;
3384 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3385 break;
3386 case S7COMM_PI_N_CONFIG:
3387 hf[0] = hf_s7comm_pi_n_x_addressident;
3388 hf[1] = hf_s7comm_pi_n_x_class;
3389 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3390 break;
3391 case S7COMM_PI_N_CRCEDN:
3392 case S7COMM_PI_N_DELECE:
3393 hf[0] = hf_s7comm_pi_n_x_addressident;
3394 hf[1] = hf_s7comm_pi_n_x_tnr;
3395 hf[2] = hf_s7comm_pi_n_x_dnr;
3396 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3397 break;
3398 case S7COMM_PI_N_CREACE:
3399 case S7COMM_PI_N_CREATO:
3400 case S7COMM_PI_N_DELETO:
3401 hf[0] = hf_s7comm_pi_n_x_addressident;
3402 hf[1] = hf_s7comm_pi_n_x_toolnumber;
3403 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3404 break;
3405 case S7COMM_PI_N_CRTOCE:
3406 hf[0] = hf_s7comm_pi_n_x_addressident;
3407 hf[1] = hf_s7comm_pi_n_x_toolnumber;
3408 hf[2] = hf_s7comm_pi_n_x_cenumber;
3409 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3410 break;
3411 case S7COMM_PI_N_DELVAR:
3412 hf[0] = hf_s7comm_pi_n_x_addressident;
3413 hf[1] = hf_s7comm_pi_n_x_datablocknumber;
3414 hf[2] = hf_s7comm_pi_n_x_firstcolumnnumber;
3415 hf[3] = hf_s7comm_pi_n_x_lastcolumnnumber;
3416 hf[4] = hf_s7comm_pi_n_x_firstrownumber;
3417 hf[5] = hf_s7comm_pi_n_x_lastrownumber;
3418 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3419 break;
3420 case S7COMM_PI_N_F_COPY:
3421 hf[0] = hf_s7comm_pi_n_x_addressident;
3422 hf[1] = hf_s7comm_pi_n_x_direction;
3423 hf[2] = hf_s7comm_pi_n_x_sourcefilename;
3424 hf[3] = hf_s7comm_pi_n_x_destinationfilename;
3425 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3426 break;
3427 case S7COMM_PI_N_F_DMDA:
3428 hf[0] = hf_s7comm_pi_n_x_addressident;
3429 hf[1] = hf_s7comm_pi_n_x_channelnumber;
3430 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3431 break;
3432 case S7COMM_PI_N_F_PROR:
3433 case S7COMM_PI_N_F_PROT:
3434 hf[0] = hf_s7comm_pi_n_x_addressident;
3435 hf[1] = hf_s7comm_pi_n_x_filename;
3436 hf[2] = hf_s7comm_pi_n_x_protection;
3437 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3438 break;
3439 case S7COMM_PI_N_F_RENA:
3440 hf[0] = hf_s7comm_pi_n_x_addressident;
3441 hf[1] = hf_s7comm_pi_n_x_oldfilename;
3442 hf[2] = hf_s7comm_pi_n_x_newfilename;
3443 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3444 break;
3445 case S7COMM_PI_N_FINDBL:
3446 hf[0] = hf_s7comm_pi_n_x_addressident;
3447 hf[1] = hf_s7comm_pi_n_x_findmode;
3448 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3449 break;
3450 case S7COMM_PI_N_IBN_SS:
3451 hf[0] = hf_s7comm_pi_n_x_addressident;
3452 hf[1] = hf_s7comm_pi_n_x_switch;
3453 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3454 break;
3455 case S7COMM_PI_N_MMCSEM:
3456 hf[0] = hf_s7comm_pi_n_x_addressident;
3457 hf[1] = hf_s7comm_pi_n_x_functionnumber;
3458 hf[2] = hf_s7comm_pi_n_x_semaphorevalue;
3459 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3460 break;
3461 case S7COMM_PI_N_NCKMOD:
3462 hf[0] = hf_s7comm_pi_n_x_addressident;
3463 hf[1] = hf_s7comm_pi_n_x_onoff;
3464 hf[2] = hf_s7comm_pi_n_x_mode;
3465 hf[3] = hf_s7comm_pi_n_x_factor;
3466 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3467 break;
3468 case S7COMM_PI_N_NEWPWD:
3469 hf[0] = hf_s7comm_pi_n_x_addressident;
3470 hf[1] = hf_s7comm_pi_n_x_password;
3471 hf[2] = hf_s7comm_pi_n_x_passwordlevel;
3472 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3473 break;
3474 case S7COMM_PI_N_SEL_BL:
3475 hf[0] = hf_s7comm_pi_n_x_addressident;
3476 hf[1] = hf_s7comm_pi_n_x_linenumber;
3477 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 2, hf, paramoffset);
3478 break;
3479 case S7COMM_PI_N_SETTST:
3480 hf[0] = hf_s7comm_pi_n_x_addressident;
3481 hf[1] = hf_s7comm_pi_n_x_magnr;
3482 hf[2] = hf_s7comm_pi_n_x_weargroup;
3483 hf[3] = hf_s7comm_pi_n_x_toolstatus;
3484 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3485 break;
3486 case S7COMM_PI_N_TMAWCO:
3487 hf[0] = hf_s7comm_pi_n_x_addressident;
3488 hf[1] = hf_s7comm_pi_n_x_magnr;
3489 hf[2] = hf_s7comm_pi_n_x_weargroup;
3490 hf[3] = hf_s7comm_pi_n_x_wearsearchstrat;
3491 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3492 break;
3493 case S7COMM_PI_N_TMCRTC:
3494 hf[0] = hf_s7comm_pi_n_x_addressident;
3495 hf[1] = hf_s7comm_pi_n_x_toolid;
3496 hf[2] = hf_s7comm_pi_n_x_toolnumber;
3497 hf[3] = hf_s7comm_pi_n_x_duplonumber;
3498 hf[4] = hf_s7comm_pi_n_x_edgenumber;
3499 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 5, hf, paramoffset);
3500 break;
3501 case S7COMM_PI_N_TMCRTO:
3502 hf[0] = hf_s7comm_pi_n_x_addressident;
3503 hf[1] = hf_s7comm_pi_n_x_toolid;
3504 hf[2] = hf_s7comm_pi_n_x_toolnumber;
3505 hf[3] = hf_s7comm_pi_n_x_duplonumber;
3506 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3507 break;
3508 case S7COMM_PI_N_TMFDPL:
3509 hf[0] = hf_s7comm_pi_n_x_addressident;
3510 hf[1] = hf_s7comm_pi_n_x_toolnumber;
3511 hf[2] = hf_s7comm_pi_n_x_placenr;
3512 hf[3] = hf_s7comm_pi_n_x_magnr;
3513 hf[4] = hf_s7comm_pi_n_x_placerefnr;
3514 hf[5] = hf_s7comm_pi_n_x_magrefnr;
3515 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3516 break;
3517 case S7COMM_PI_N_TMFPBP:
3518 hf[0] = hf_s7comm_pi_n_x_addressident;
3519 hf[1] = hf_s7comm_pi_n_x_magnrfrom;
3520 hf[2] = hf_s7comm_pi_n_x_placenrfrom;
3521 hf[3] = hf_s7comm_pi_n_x_magnrto;
3522 hf[4] = hf_s7comm_pi_n_x_placenrto;
3523 hf[5] = hf_s7comm_pi_n_x_magrefnr;
3524 hf[6] = hf_s7comm_pi_n_x_placerefnr;
3525 hf[7] = hf_s7comm_pi_n_x_halfplacesleft;
3526 hf[8] = hf_s7comm_pi_n_x_halfplacesright;
3527 hf[9] = hf_s7comm_pi_n_x_halfplacesup;
3528 hf[10] = hf_s7comm_pi_n_x_halfplacesdown;
3529 hf[11] = hf_s7comm_pi_n_x_placetype;
3530 hf[12] = hf_s7comm_pi_n_x_searchdirection;
3531 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 13, hf, paramoffset);
3532 break;
3533 case S7COMM_PI_N_TMGETT:
3534 hf[0] = hf_s7comm_pi_n_x_addressident;
3535 hf[1] = hf_s7comm_pi_n_x_toolname;
3536 hf[2] = hf_s7comm_pi_n_x_duplonumber;
3537 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3538 break;
3539 case S7COMM_PI_N_TMMVTL:
3540 hf[0] = hf_s7comm_pi_n_x_addressident;
3541 hf[1] = hf_s7comm_pi_n_x_toolnumber;
3542 hf[2] = hf_s7comm_pi_n_x_placenrsource;
3543 hf[3] = hf_s7comm_pi_n_x_magnrsource;
3544 hf[4] = hf_s7comm_pi_n_x_placenrdestination;
3545 hf[5] = hf_s7comm_pi_n_x_magnrdestination;
3546 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 6, hf, paramoffset);
3547 break;
3548 case S7COMM_PI_N_TMPCIT:
3549 hf[0] = hf_s7comm_pi_n_x_addressident;
3550 hf[1] = hf_s7comm_pi_n_x_spindlenumber;
3551 hf[2] = hf_s7comm_pi_n_x_incrementnumber;
3552 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 3, hf, paramoffset);
3553 break;
3554 case S7COMM_PI_N_TMPOSM:
3555 hf[0] = hf_s7comm_pi_n_x_addressident;
3556 hf[1] = hf_s7comm_pi_n_x_toolnumber;
3557 hf[2] = hf_s7comm_pi_n_x_toolid;
3558 hf[3] = hf_s7comm_pi_n_x_duplonumber;
3559 hf[4] = hf_s7comm_pi_n_x_placenrsource;
3560 hf[5] = hf_s7comm_pi_n_x_magnrsource;
3561 hf[6] = hf_s7comm_pi_n_x_placenrdestination;
3562 hf[7] = hf_s7comm_pi_n_x_magnrdestination;
3563 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 8, hf, paramoffset);
3564 break;
3565 case S7COMM_PI_N_TRESMO:
3566 hf[0] = hf_s7comm_pi_n_x_addressident;
3567 hf[1] = hf_s7comm_pi_n_x_toolnumber;
3568 hf[2] = hf_s7comm_pi_n_x_dnr;
3569 hf[3] = hf_s7comm_pi_n_x_monitoringmode;
3570 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 4, hf, paramoffset);
3571 break;
3572 case S7COMM_PI_N_TSEARC:
3573 hf[0] = hf_s7comm_pi_n_x_addressident;
3574 hf[1] = hf_s7comm_pi_n_x_magnrfrom;
3575 hf[2] = hf_s7comm_pi_n_x_placenrfrom;
3576 hf[3] = hf_s7comm_pi_n_x_magnrto;
3577 hf[4] = hf_s7comm_pi_n_x_placenrto;
3578 hf[5] = hf_s7comm_pi_n_x_magrefnr;
3579 hf[6] = hf_s7comm_pi_n_x_placerefnr;
3580 hf[7] = hf_s7comm_pi_n_x_searchdirection;
3581 hf[8] = hf_s7comm_pi_n_x_kindofsearch;
3582 s7comm_decode_pistart_parameters(tvb, pinfo, tree, param_tree, servicename, 9, hf, paramoffset);
3583 break;
3584 default:
3585 /* Don't know how to interpret the parameters, show only the PI servicename */
3586 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]", servicename);
3587 }
3588 return offset;
3589 }
3590
3591 /*******************************************************************************************************
3592 *
3593 * Decode a blockname/filename used in block/file upload/download
3594 *
3595 *******************************************************************************************************/
3596 static guint32
s7comm_decode_plc_controls_filename(tvbuff_t * tvb,packet_info * pinfo,proto_tree * param_tree,guint32 offset)3597 s7comm_decode_plc_controls_filename(tvbuff_t *tvb,
3598 packet_info *pinfo,
3599 proto_tree *param_tree,
3600 guint32 offset)
3601 {
3602 guint8 len;
3603 const guint8 *str;
3604 guint16 blocktype;
3605 gboolean is_plcfilename;
3606 proto_item *item = NULL;
3607 proto_item *itemadd = NULL;
3608 proto_tree *file_tree = NULL;
3609
3610 len = tvb_get_guint8(tvb, offset);
3611 proto_tree_add_uint(param_tree, hf_s7comm_data_blockcontrol_filename_len, tvb, offset, 1, len);
3612 offset += 1;
3613 item = proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, len, ENC_ASCII|ENC_NA);
3614 /* The filename when uploading from PLC has a well known structure, which can be further dissected.
3615 * An upload from a NC is a simple filename string with no deeper structure.
3616 * Check for PLC filename, by checking some fixed fields.
3617 */
3618 is_plcfilename = FALSE;
3619 if (len == 9) {
3620 blocktype = tvb_get_ntohs(tvb, offset + 1);
3621 if ((tvb_get_guint8(tvb, offset) == '_') && (blocktype >= S7COMM_BLOCKTYPE_OB) && (blocktype <= S7COMM_BLOCKTYPE_SFB)) {
3622 gint32 num = 1;
3623 gboolean num_valid;
3624 is_plcfilename = TRUE;
3625 file_tree = proto_item_add_subtree(item, ett_s7comm_plcfilename);
3626 itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_file_ident, tvb, offset, 1, ENC_ASCII|ENC_NA);
3627 proto_item_append_text(itemadd, " (%s)", val_to_str(tvb_get_guint8(tvb, offset), blocktype_attribute1_names, "Unknown identifier: %c"));
3628 offset += 1;
3629 itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_block_type, tvb, offset, 2, ENC_ASCII|ENC_NA);
3630 proto_item_append_text(itemadd, " (%s)", val_to_str(blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3631 offset += 2;
3632 proto_tree_add_item_ret_string(file_tree, hf_s7comm_data_blockcontrol_block_num, tvb, offset, 5, ENC_ASCII|ENC_NA, pinfo->pool, &str);
3633 offset += 5;
3634 num_valid = ws_strtoi32((const gchar*)str, NULL, &num);
3635 proto_item_append_text(file_tree, " [%s",
3636 val_to_str(blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3637 col_append_fstr(pinfo->cinfo, COL_INFO, " -> Block:[%s",
3638 val_to_str(blocktype, blocktype_names, "Unknown Block type: 0x%04x"));
3639 if (num_valid) {
3640 proto_item_append_text(file_tree, "%d]", num);
3641 col_append_fstr(pinfo->cinfo, COL_INFO, "%d]", num);
3642 } else {
3643 expert_add_info(pinfo, file_tree, &ei_s7comm_data_blockcontrol_block_num_invalid);
3644 proto_item_append_text(file_tree, "NaN]");
3645 col_append_str(pinfo->cinfo, COL_INFO, "NaN]");
3646 }
3647 itemadd = proto_tree_add_item(file_tree, hf_s7comm_data_blockcontrol_dest_filesys, tvb, offset, 1, ENC_ASCII|ENC_NA);
3648 proto_item_append_text(itemadd, " (%s)", val_to_str(tvb_get_guint8(tvb, offset), blocktype_attribute2_names, "Unknown filesys: %c"));
3649 offset += 1;
3650 }
3651 }
3652 if (is_plcfilename == FALSE) {
3653 str = tvb_get_string_enc(pinfo->pool, tvb, offset, len, ENC_ASCII);
3654 col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str);
3655 offset += len;
3656 }
3657 return offset;
3658 }
3659
3660 /*******************************************************************************************************
3661 *
3662 * PDU Type: Request or Response -> Function 0x1d, 0x1e, 0x1f (block control functions) for upload
3663 *
3664 *******************************************************************************************************/
3665 static guint32
s7comm_decode_plc_controls_updownload(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_tree * param_tree,guint16 plength,guint16 dlength,guint32 offset,guint8 rosctr)3666 s7comm_decode_plc_controls_updownload(tvbuff_t *tvb,
3667 packet_info *pinfo,
3668 proto_tree *tree,
3669 proto_tree *param_tree,
3670 guint16 plength,
3671 guint16 dlength,
3672 guint32 offset,
3673 guint8 rosctr)
3674 {
3675 guint8 len;
3676 guint8 function;
3677 guint32 errorcode;
3678 const gchar *errorcode_text;
3679 proto_item *item = NULL;
3680 proto_tree *data_tree = NULL;
3681
3682 function = tvb_get_guint8(tvb, offset);
3683 offset += 1;
3684 errorcode = 0;
3685
3686 switch (function) {
3687 /*---------------------------------------------------------------------*/
3688 case S7COMM_FUNCREQUESTDOWNLOAD:
3689 if (rosctr == S7COMM_ROSCTR_JOB) {
3690 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3691 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3692 offset += 1;
3693 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3694 offset += 2;
3695 /* on upload this is the upload-id, here it is anything else (or not used ) */
3696 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 4, ENC_NA);
3697 offset += 4;
3698 offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3699 if (plength > 18) {
3700 len = tvb_get_guint8(tvb, offset);
3701 proto_tree_add_uint(param_tree, hf_s7comm_data_blockcontrol_part2_len, tvb, offset, 1, len);
3702 offset += 1;
3703 /* first byte unknown '1' */
3704 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_part2_unknown, tvb, offset, 1, ENC_ASCII|ENC_NA);
3705 offset += 1;
3706 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_loadmem_len, tvb, offset, 6, ENC_ASCII|ENC_NA);
3707 offset += 6;
3708 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_mc7code_len, tvb, offset, 6, ENC_ASCII|ENC_NA);
3709 offset += 6;
3710 }
3711 } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3712 if (plength >= 2) {
3713 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3714 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3715 offset += 1;
3716 }
3717 }
3718 break;
3719 /*---------------------------------------------------------------------*/
3720 case S7COMM_FUNCSTARTUPLOAD:
3721 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3722 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3723 offset += 1;
3724 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3725 offset += 2;
3726 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_uploadid, tvb, offset, 4, ENC_NA);
3727 offset += 4;
3728 if (rosctr == S7COMM_ROSCTR_JOB) {
3729 offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3730 } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3731 if (plength > 8) {
3732 /* If uploading from a PLC, the response has a string with the length
3733 * of the complete module in bytes, which maybe transferred/split into many PDUs.
3734 * On a NC file upload, there are no such fields.
3735 */
3736 len = tvb_get_guint8(tvb, offset);
3737 proto_tree_add_uint(param_tree, hf_s7comm_data_blockcontrol_upl_lenstring_len, tvb, offset, 1, len);
3738 offset += 1;
3739 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_upl_lenstring, tvb, offset, len, ENC_ASCII|ENC_NA);
3740 offset += len;
3741 }
3742 }
3743 break;
3744 /*---------------------------------------------------------------------*/
3745 case S7COMM_FUNCUPLOAD:
3746 case S7COMM_FUNCDOWNLOADBLOCK:
3747 if (rosctr == S7COMM_ROSCTR_JOB) {
3748 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3749 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3750 offset += 1;
3751 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3752 offset += 2;
3753 if (function == S7COMM_FUNCUPLOAD) {
3754 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_uploadid, tvb, offset, 4, ENC_NA);
3755 offset += 4;
3756 } else {
3757 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 4, ENC_NA);
3758 offset += 4;
3759 offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3760 }
3761 } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3762 if (plength >= 2) {
3763 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3764 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3765 offset += 1;
3766 }
3767 if (dlength > 0) {
3768 item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
3769 data_tree = proto_item_add_subtree(item, ett_s7comm_data);
3770 proto_tree_add_item(data_tree, hf_s7comm_data_length, tvb, offset, 2, ENC_NA);
3771 offset += 2;
3772 proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
3773 offset += 2;
3774 proto_tree_add_item(data_tree, hf_s7comm_readresponse_data, tvb, offset, dlength - 4, ENC_NA);
3775 offset += dlength - 4;
3776 }
3777 }
3778 break;
3779 /*---------------------------------------------------------------------*/
3780 case S7COMM_FUNCENDUPLOAD:
3781 case S7COMM_FUNCDOWNLOADENDED:
3782 if (rosctr == S7COMM_ROSCTR_JOB) {
3783 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3784 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3785 offset += 1;
3786 item = proto_tree_add_item_ret_uint(param_tree, hf_s7comm_data_blockcontrol_errorcode, tvb, offset, 2, ENC_BIG_ENDIAN, &errorcode);
3787 /* here it uses the same errorcode from parameter part */
3788 if ((errorcode_text = try_val_to_str_ext(errorcode, ¶m_errcode_names_ext))) {
3789 proto_item_append_text(item, " (%s)", errorcode_text);
3790 }
3791 offset += 2;
3792 if (function == S7COMM_FUNCENDUPLOAD) {
3793 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_uploadid, tvb, offset, 4, ENC_NA);
3794 offset += 4;
3795 } else {
3796 proto_tree_add_item(param_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 4, ENC_NA);
3797 offset += 4;
3798 offset = s7comm_decode_plc_controls_filename(tvb, pinfo, param_tree, offset);
3799 }
3800 } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
3801 if (plength >= 2) {
3802 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
3803 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
3804 offset += 1;
3805 }
3806 }
3807 break;
3808 }
3809 /* if an error occurred show in info column */
3810 if (errorcode > 0) {
3811 col_append_fstr(pinfo->cinfo, COL_INFO, " -> Errorcode:[0x%04x]", errorcode);
3812 }
3813 return offset;
3814 }
3815
3816 /*******************************************************************************************************
3817 *
3818 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Block status (0x13 or 0x01)
3819 *
3820 *******************************************************************************************************/
3821 static guint32
s7comm_decode_ud_tis_blockstat(tvbuff_t * tvb,proto_tree * td_tree,guint16 td_size,guint8 type,guint8 subfunc,guint32 offset)3822 s7comm_decode_ud_tis_blockstat(tvbuff_t *tvb,
3823 proto_tree *td_tree,
3824 guint16 td_size,
3825 guint8 type,
3826 guint8 subfunc,
3827 guint32 offset)
3828 {
3829 proto_item *item = NULL;
3830 proto_tree *item_tree = NULL;
3831 guint16 line_nr;
3832 guint16 line_cnt;
3833 guint16 item_size = 4;
3834 guint8 registerflags;
3835 gchar str_flags[80];
3836
3837 if (type == S7COMM_UD_TYPE_REQ) {
3838 if (subfunc == S7COMM_UD_SUBF_PROG_BLOCKSTAT2) {
3839 proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_flagsunknown, tvb, offset, 1, ENC_BIG_ENDIAN);
3840 offset += 1;
3841 line_cnt = tvb_get_guint8(tvb, offset);
3842 proto_tree_add_uint(td_tree, hf_s7comm_tis_blockstat_number_of_lines, tvb, offset, 1, line_cnt);
3843 offset += 1;
3844 proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
3845 offset += 1;
3846 } else {
3847 proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
3848 offset += 1;
3849 line_cnt = (td_size - 2) / 2;
3850 }
3851 proto_tree_add_bitmask(td_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
3852 ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
3853 offset += 1;
3854
3855 if (subfunc == S7COMM_UD_SUBF_PROG_BLOCKSTAT2) {
3856 item_size = 4;
3857 } else {
3858 item_size = 2;
3859 }
3860 for (line_nr = 0; line_nr < line_cnt; line_nr++) {
3861 item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, item_size, ENC_NA);
3862 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
3863 if (subfunc == S7COMM_UD_SUBF_PROG_BLOCKSTAT2) {
3864 proto_tree_add_item(item_tree, hf_s7comm_tis_blockstat_line_address, tvb, offset, 2, ENC_BIG_ENDIAN);
3865 offset += 2;
3866 }
3867 proto_tree_add_item(item_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
3868 offset += 1;
3869 registerflags = tvb_get_guint8(tvb, offset);
3870 make_registerflag_string(str_flags, registerflags, sizeof(str_flags));
3871 proto_item_append_text(item, " [%d]: (%s)", line_nr+1, str_flags);
3872 proto_tree_add_bitmask(item_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
3873 ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
3874 offset += 1;
3875 }
3876 } else if (type == S7COMM_UD_TYPE_PUSH) {
3877 /* The response data can only be dissected when the requested registers for each line
3878 * from the job setup is known. As the STW is only 16 Bits and all other registers 32 Bits,
3879 * this has no fixed structure.
3880 * The only thing that can be shown is the start address. Next the requested registers,
3881 * the start address of next line with the requested registers and so on.
3882 */
3883 proto_tree_add_item(td_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
3884 offset += 2;
3885 proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_data, tvb, offset, td_size - 2, ENC_NA);
3886 offset += (td_size - 2);
3887 } else {
3888 /* TODO: Show unknown data as raw bytes */
3889 proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, td_size, ENC_NA);
3890 offset += td_size;
3891 }
3892 return offset;
3893 }
3894
3895 /*******************************************************************************************************
3896 *
3897 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Item address
3898 *
3899 *******************************************************************************************************/
3900 static guint32
s7comm_decode_ud_tis_item_address(tvbuff_t * tvb,guint32 offset,proto_tree * sub_tree,guint16 item_no,gchar * add_text)3901 s7comm_decode_ud_tis_item_address(tvbuff_t *tvb,
3902 guint32 offset,
3903 proto_tree *sub_tree,
3904 guint16 item_no,
3905 gchar *add_text)
3906 {
3907 guint32 bytepos = 0;
3908 guint16 len = 0;
3909 guint16 bitpos = 0;
3910 guint16 db = 0;
3911 guint8 area = 0;
3912 proto_item *item = NULL;
3913
3914 /* Insert a new tree with 6 bytes for every item */
3915 item = proto_tree_add_item(sub_tree, hf_s7comm_param_item, tvb, offset, 6, ENC_NA);
3916
3917 sub_tree = proto_item_add_subtree(item, ett_s7comm_param_item);
3918
3919 proto_item_append_text(item, " [%d]%s:", item_no + 1, add_text);
3920
3921 /* Area, 1 byte */
3922 area = tvb_get_guint8(tvb, offset);
3923 proto_tree_add_item(sub_tree, hf_s7comm_varstat_req_memory_area, tvb, offset, 1, ENC_BIG_ENDIAN);
3924 offset += 1;
3925
3926 /* Length (repetition factor), 1 byte. If area is a bit address, then this is the bit number.
3927 * The area is a bit address when the low nibble is zero.
3928 */
3929 if (area & 0x0f) {
3930 len = tvb_get_guint8(tvb, offset);
3931 proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_repetition_factor, tvb, offset, 1, len);
3932 offset += 1;
3933 } else {
3934 bitpos = tvb_get_guint8(tvb, offset);
3935 proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_bitpos, tvb, offset, 1, bitpos);
3936 offset += 1;
3937 }
3938
3939 /* DB number, 2 bytes */
3940 db = tvb_get_ntohs(tvb, offset);
3941 proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_db_number, tvb, offset, 2, db);
3942 offset += 2;
3943
3944 /* byte offset, 2 bytes */
3945 bytepos = tvb_get_ntohs(tvb, offset);
3946 proto_tree_add_uint(sub_tree, hf_s7comm_varstat_req_startaddress, tvb, offset, 2, bytepos);
3947 offset += 2;
3948
3949 /* build a full address to show item data directly beside the item */
3950 switch (area) {
3951 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MX:
3952 proto_item_append_text(sub_tree, " (M%d.%d)", bytepos, bitpos);
3953 break;
3954 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MB:
3955 proto_item_append_text(sub_tree, " (M%d.0 BYTE %d)", bytepos, len);
3956 break;
3957 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MW:
3958 proto_item_append_text(sub_tree, " (M%d.0 WORD %d)", bytepos, len);
3959 break;
3960 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_MD:
3961 proto_item_append_text(sub_tree, " (M%d.0 DWORD %d)", bytepos, len);
3962 break;
3963 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EX:
3964 proto_item_append_text(sub_tree, " (I%d.%d)", bytepos, bitpos);
3965 break;
3966 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EB:
3967 proto_item_append_text(sub_tree, " (I%d.0 BYTE %d)", bytepos, len);
3968 break;
3969 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_EW:
3970 proto_item_append_text(sub_tree, " (I%d.0 WORD %d)", bytepos, len);
3971 break;
3972 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_ED:
3973 proto_item_append_text(sub_tree, " (I%d.0 DWORD %d)", bytepos, len);
3974 break;
3975 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AX:
3976 proto_item_append_text(sub_tree, " (Q%d.%d)", bytepos, bitpos);
3977 break;
3978 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AB:
3979 proto_item_append_text(sub_tree, " (Q%d.0 BYTE %d)", bytepos, len);
3980 break;
3981 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AW:
3982 proto_item_append_text(sub_tree, " (Q%d.0 WORD %d)", bytepos, len);
3983 break;
3984 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_AD:
3985 proto_item_append_text(sub_tree, " (Q%d.0 DWORD %d)", bytepos, len);
3986 break;
3987 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PEB:
3988 proto_item_append_text(sub_tree, " (PI%d.0 BYTE %d)", bytepos, len);
3989 break;
3990 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PEW:
3991 proto_item_append_text(sub_tree, " (PI%d.0 WORD %d)", bytepos, len);
3992 break;
3993 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_PED:
3994 proto_item_append_text(sub_tree, " (PI%d.0 DWORD %d)", bytepos, len);
3995 break;
3996 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBX:
3997 proto_item_append_text(sub_tree, " (DB%d.DBX%d.%d)", db, bytepos, bitpos);
3998 break;
3999 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBB:
4000 proto_item_append_text(sub_tree, " (DB%d.DBX%d.0 BYTE %d)", db, bytepos, len);
4001 break;
4002 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBW:
4003 proto_item_append_text(sub_tree, " (DB%d.DBX%d.0 WORD %d)", db, bytepos, len);
4004 break;
4005 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_DBD:
4006 proto_item_append_text(sub_tree, " (DB%d.DBX%d.0 DWORD %d)", db, bytepos, len);
4007 break;
4008 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_T:
4009 /* it's possible to read multiple timers */
4010 if (len >1)
4011 proto_item_append_text(sub_tree, " (T %d..%d)", bytepos, bytepos + len - 1);
4012 else
4013 proto_item_append_text(sub_tree, " (T %d)", bytepos);
4014 break;
4015 case S7COMM_UD_SUBF_PROG_VARSTAT_AREA_C:
4016 /* it's possible to read multiple counters */
4017 if (len >1)
4018 proto_item_append_text(sub_tree, " (C %d..%d)", bytepos, bytepos + len - 1);
4019 else
4020 proto_item_append_text(sub_tree, " (C %d)", bytepos);
4021 break;
4022 }
4023 return offset;
4024 }
4025
4026 /*******************************************************************************************************
4027 *
4028 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Item value
4029 *
4030 *******************************************************************************************************/
4031 static guint32
s7comm_decode_ud_tis_item_value(tvbuff_t * tvb,guint32 offset,proto_tree * sub_tree,guint16 item_no,gchar * add_text)4032 s7comm_decode_ud_tis_item_value(tvbuff_t *tvb,
4033 guint32 offset,
4034 proto_tree *sub_tree,
4035 guint16 item_no,
4036 gchar *add_text)
4037 {
4038 guint16 len = 0, len2 = 0;
4039 guint8 ret_val = 0;
4040 guint8 tsize = 0;
4041 guint8 head_len = 4;
4042
4043 proto_item *item = NULL;
4044
4045 ret_val = tvb_get_guint8(tvb, offset);
4046 if (ret_val == S7COMM_ITEM_RETVAL_RESERVED ||
4047 ret_val == S7COMM_ITEM_RETVAL_DATA_OK ||
4048 ret_val == S7COMM_ITEM_RETVAL_DATA_ERR
4049 ) {
4050 tsize = tvb_get_guint8(tvb, offset + 1);
4051 len = tvb_get_ntohs(tvb, offset + 2);
4052
4053 if (tsize == S7COMM_DATA_TRANSPORT_SIZE_BBYTE || tsize == S7COMM_DATA_TRANSPORT_SIZE_BINT) {
4054 len /= 8;
4055 }
4056 /* the PLC places extra bytes at the end if length is not a multiple of 2 */
4057 if (len % 2) {
4058 len2 = len + 1;
4059 } else {
4060 len2 = len;
4061 }
4062 }
4063 /* Insert a new tree for every item */
4064 item = proto_tree_add_item(sub_tree, hf_s7comm_data_item, tvb, offset, len + head_len, ENC_NA);
4065 sub_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4066
4067 proto_item_append_text(item, " [%d]%s: (%s)", item_no + 1, add_text, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
4068
4069 proto_tree_add_uint(sub_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
4070 proto_tree_add_uint(sub_tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
4071 proto_tree_add_uint(sub_tree, hf_s7comm_data_length, tvb, offset + 2, 2, len);
4072
4073 offset += head_len;
4074 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK || ret_val == S7COMM_ITEM_RETVAL_RESERVED) {
4075 proto_tree_add_item(sub_tree, hf_s7comm_readresponse_data, tvb, offset, len, ENC_NA);
4076 offset += len;
4077 if (len != len2) {
4078 proto_tree_add_item(sub_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
4079 offset += 1;
4080 }
4081 }
4082 return offset;
4083 }
4084
4085 /*******************************************************************************************************
4086 *
4087 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Force (0x09)
4088 *
4089 *******************************************************************************************************/
4090 static guint32
s7comm_decode_ud_tis_force(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)4091 s7comm_decode_ud_tis_force(tvbuff_t *tvb,
4092 proto_tree *td_tree,
4093 guint8 type,
4094 guint32 offset)
4095 {
4096 guint16 item_count;
4097 guint16 i;
4098 guint8 ret_val = 0;
4099 proto_item *item = NULL;
4100 proto_tree *item_tree = NULL;
4101
4102 switch (type) {
4103 case S7COMM_UD_TYPE_REQ:
4104 item_count = tvb_get_ntohs(tvb, offset);
4105 proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4106 offset += 2;
4107 for (i = 0; i < item_count; i++) {
4108 offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to force");
4109 }
4110 for (i = 0; i < item_count; i++) {
4111 offset = s7comm_decode_ud_tis_item_value(tvb, offset, td_tree, i, " Value to force");
4112 }
4113 break;
4114 case S7COMM_UD_TYPE_PUSH:
4115 item_count = tvb_get_ntohs(tvb, offset);
4116 proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4117 offset += 2;
4118 for (i = 0; i < item_count; i++) {
4119 item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
4120 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4121 ret_val = tvb_get_guint8(tvb, offset);
4122 proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
4123 proto_item_append_text(item, " [%d]: (%s)", i + 1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
4124 offset += 1;
4125 }
4126 if (item_count % 2) {
4127 proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
4128 offset += 1;
4129 }
4130 break;
4131 }
4132 return offset;
4133 }
4134
4135 /*******************************************************************************************************
4136 *
4137 * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
4138 * Dissects the parameter part
4139 *
4140 *******************************************************************************************************/
4141 static guint32
s7comm_decode_ud_tis_param(tvbuff_t * tvb,proto_tree * tree,guint8 type,guint16 tp_size,guint32 offset)4142 s7comm_decode_ud_tis_param(tvbuff_t *tvb,
4143 proto_tree *tree,
4144 guint8 type,
4145 guint16 tp_size,
4146 guint32 offset)
4147 {
4148 guint32 start_offset;
4149 guint32 callenv_setup = 0;
4150 proto_item *item = NULL;
4151 proto_tree *tp_tree = NULL;
4152
4153 start_offset = offset;
4154 if (tp_size > 0) {
4155 item = proto_tree_add_item(tree, hf_s7comm_tis_parameter, tvb, offset, tp_size, ENC_NA);
4156 tp_tree = proto_item_add_subtree(item, ett_s7comm_prog_parameter);
4157 if (type == S7COMM_UD_TYPE_REQ) {
4158 if (tp_size >= 4) {
4159 proto_tree_add_item(tp_tree, hf_s7comm_tis_param1, tvb, offset, 2, ENC_NA);
4160 offset += 2;
4161 proto_tree_add_item(tp_tree, hf_s7comm_tis_param2, tvb, offset, 2, ENC_NA);
4162 offset += 2;
4163 }
4164 if (tp_size >= 20) {
4165 proto_tree_add_item(tp_tree, hf_s7comm_tis_param3, tvb, offset, 2, ENC_NA);
4166 offset += 2;
4167 proto_tree_add_item(tp_tree, hf_s7comm_tis_answersize, tvb, offset, 2, ENC_NA);
4168 offset += 2;
4169 proto_tree_add_item(tp_tree, hf_s7comm_tis_param5, tvb, offset, 2, ENC_NA);
4170 offset += 2;
4171 proto_tree_add_item(tp_tree, hf_s7comm_tis_param6, tvb, offset, 2, ENC_BIG_ENDIAN);
4172 offset += 2;
4173 proto_tree_add_item(tp_tree, hf_s7comm_tis_param7, tvb, offset, 2, ENC_NA);
4174 offset += 2;
4175 proto_tree_add_item(tp_tree, hf_s7comm_tis_param8, tvb, offset, 2, ENC_NA);
4176 offset += 2;
4177 proto_tree_add_item(tp_tree, hf_s7comm_tis_param9, tvb, offset, 2, ENC_NA);
4178 offset += 2;
4179 proto_tree_add_item(tp_tree, hf_s7comm_tis_trgevent, tvb, offset, 2, ENC_NA);
4180 offset += 2;
4181 }
4182 if (tp_size >= 26) {
4183 proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_block_type, tvb, offset, 2, ENC_BIG_ENDIAN);
4184 offset += 2;
4185 proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_block_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4186 offset += 2;
4187 proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
4188 offset += 2;
4189 }
4190 if (tp_size >= 28) {
4191 proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_saz, tvb, offset, 2, ENC_BIG_ENDIAN);
4192 offset += 2;
4193 }
4194 if (tp_size >= 36) {
4195 proto_tree_add_item_ret_uint(tp_tree, hf_s7comm_tis_p_callenv, tvb, offset, 2, ENC_BIG_ENDIAN, &callenv_setup);
4196 offset += 2;
4197 proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond, tvb, offset, 2, ENC_BIG_ENDIAN);
4198 offset += 2;
4199 if (callenv_setup == 2) {
4200 proto_tree_add_item(tp_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4201 offset += 2;
4202 proto_tree_add_item(tp_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4203 } else {
4204 proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4205 offset += 2;
4206 proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4207 offset += 2;
4208 if (tp_size >= 38) {
4209 proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4210 }
4211 }
4212 }
4213 } else {
4214 proto_tree_add_item(tp_tree, hf_s7comm_tis_res_param1, tvb, offset, 2, ENC_NA);
4215 offset += 2;
4216 proto_tree_add_item(tp_tree, hf_s7comm_tis_res_param2, tvb, offset, 2, ENC_NA);
4217 }
4218 }
4219 /* May be we don't know all values when here, so set offset to the given length */
4220 return start_offset + tp_size;
4221 }
4222
4223 /*******************************************************************************************************
4224 *
4225 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Disable job (0x0d), Enable job (0x0e),
4226 * Delete job (0x0f), Read job list (0x10),
4227 * Read job (0x11)
4228 *
4229 *******************************************************************************************************/
4230 static guint32
s7comm_decode_ud_tis_jobs(tvbuff_t * tvb,proto_tree * td_tree,guint16 td_size,guint8 type,guint8 subfunc,guint32 offset)4231 s7comm_decode_ud_tis_jobs(tvbuff_t *tvb,
4232 proto_tree *td_tree,
4233 guint16 td_size,
4234 guint8 type,
4235 guint8 subfunc,
4236 guint32 offset)
4237 {
4238 guint16 i;
4239 proto_item *item = NULL;
4240 proto_tree *item_tree = NULL;
4241 guint16 job_tp_size;
4242 guint16 job_td_size;
4243 proto_tree *job_td_tree = NULL;
4244 guint8 job_subfunc;
4245
4246 if (type == S7COMM_UD_TYPE_REQ) {
4247 switch (subfunc) {
4248 case S7COMM_UD_SUBF_PROG_DELETEJOB:
4249 proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4250 offset += 2;
4251 /* fallthrough */
4252 case S7COMM_UD_SUBF_PROG_ENABLEJOB:
4253 case S7COMM_UD_SUBF_PROG_DISABLEJOB:
4254 case S7COMM_UD_SUBF_PROG_READJOB:
4255 proto_tree_add_item(td_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
4256 offset += 1;
4257 proto_tree_add_item(td_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
4258 offset += 1;
4259 break;
4260 case S7COMM_UD_SUBF_PROG_READJOBLIST:
4261 /* 4 bytes, possible as filter? */
4262 proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4263 offset += 2;
4264 proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4265 offset += 2;
4266 break;
4267 case S7COMM_UD_SUBF_PROG_REPLACEJOB:
4268 proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4269 offset += 2;
4270 /* The job which has to be replaced */
4271 job_subfunc = tvb_get_guint8(tvb, offset);
4272 proto_tree_add_item(td_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
4273 offset += 1;
4274 proto_tree_add_item(td_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
4275 offset += 1;
4276 job_tp_size = tvb_get_ntohs(tvb, offset);
4277 proto_tree_add_item(td_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
4278 offset += 2;
4279 job_td_size = tvb_get_ntohs(tvb, offset);
4280 proto_tree_add_item(td_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
4281 offset += 2;
4282 /* New job parameter tree */
4283 if (job_tp_size > 0) {
4284 offset = s7comm_decode_ud_tis_param(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_tp_size, offset);
4285 }
4286 /* New job data tree */
4287 if (job_td_size > 0) {
4288 offset = s7comm_decode_ud_tis_data(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_subfunc, job_td_size, offset);
4289 }
4290 break;
4291 }
4292 } else {
4293 switch (subfunc) {
4294 case S7COMM_UD_SUBF_PROG_READJOBLIST:
4295 /* 4 bytes each job:
4296 * - 2 bytes job id
4297 * - 2 bytes status: 1=active, 0=idle/pending?
4298 */
4299 for (i = 0; i < td_size / 4; i++) {
4300 item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
4301 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4302 proto_item_append_text(item, " [%d] Job", i + 1);
4303
4304 proto_tree_add_item(item_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
4305 offset += 1;
4306 proto_tree_add_item(item_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
4307 offset += 1;
4308 proto_tree_add_item(item_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
4309 offset += 2;
4310 }
4311 break;
4312 case S7COMM_UD_SUBF_PROG_READJOB:
4313 /* This includes the same data as in the job request. With the disadvantage that is does
4314 * not contain information of the function, so the data can't be further dissected.
4315 * We need to know the function from the request.
4316 */
4317 job_tp_size = tvb_get_ntohs(tvb, offset);
4318 proto_tree_add_item(td_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
4319 offset += 2;
4320 job_td_size = tvb_get_ntohs(tvb, offset);
4321 proto_tree_add_item(td_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
4322 offset += 2;
4323 /* Job parameter tree */
4324 if (job_tp_size > 0) {
4325 offset = s7comm_decode_ud_tis_param(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_tp_size, offset);
4326 }
4327 /* Job data tree */
4328 if (job_td_size > 0) {
4329 item = proto_tree_add_item(td_tree, hf_s7comm_tis_data, tvb, offset, job_td_size, ENC_NA);
4330 job_td_tree = proto_item_add_subtree(item, ett_s7comm_prog_data);
4331 proto_tree_add_item(job_td_tree, hf_s7comm_tis_job_reserved, tvb, offset, job_td_size, ENC_NA);
4332 offset += job_td_size;
4333 }
4334 break;
4335 }
4336 }
4337 return offset;
4338 }
4339
4340 /*******************************************************************************************************
4341 *
4342 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Variable status (0x03)
4343 *
4344 *******************************************************************************************************/
4345 static guint32
s7comm_decode_ud_tis_varstat(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)4346 s7comm_decode_ud_tis_varstat(tvbuff_t *tvb,
4347 proto_tree *td_tree,
4348 guint8 type,
4349 guint32 offset)
4350 {
4351 guint16 item_count;
4352 guint16 i;
4353
4354 switch (type) {
4355 case S7COMM_UD_TYPE_REQ:
4356 item_count = tvb_get_ntohs(tvb, offset);
4357 proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4358 offset += 2;
4359 for (i = 0; i < item_count; i++) {
4360 offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to read");
4361 }
4362 break;
4363 case S7COMM_UD_TYPE_PUSH:
4364 item_count = tvb_get_ntohs(tvb, offset);
4365 proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4366 offset += 2;
4367 for (i = 0; i < item_count; i++) {
4368 offset = s7comm_decode_ud_tis_item_value(tvb, offset, td_tree, i, " Read data");
4369 }
4370 break;
4371 }
4372 return offset;
4373 }
4374
4375 /*******************************************************************************************************
4376 *
4377 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Modify variable (0x08)
4378 *
4379 *******************************************************************************************************/
4380 static guint32
s7comm_decode_ud_tis_modvar(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)4381 s7comm_decode_ud_tis_modvar(tvbuff_t *tvb,
4382 proto_tree *td_tree,
4383 guint8 type,
4384 guint32 offset)
4385 {
4386 guint16 item_count;
4387 guint16 i;
4388 guint8 ret_val = 0;
4389 proto_item *item = NULL;
4390 proto_tree *item_tree = NULL;
4391
4392 switch (type) {
4393 case S7COMM_UD_TYPE_REQ:
4394 item_count = tvb_get_ntohs(tvb, offset);
4395 proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4396 offset += 2;
4397 for (i = 0; i < item_count; i++) {
4398 offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to write");
4399 }
4400 for (i = 0; i < item_count; i++) {
4401 offset = s7comm_decode_ud_tis_item_value(tvb, offset, td_tree, i, " Data to write");
4402 }
4403 break;
4404 case S7COMM_UD_TYPE_PUSH:
4405 item_count = tvb_get_ntohs(tvb, offset);
4406 proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
4407 offset += 2;
4408 for (i = 0; i < item_count; i++) {
4409 item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
4410 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4411 ret_val = tvb_get_guint8(tvb, offset);
4412 proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
4413 proto_item_append_text(item, " [%d]: (%s)", i + 1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
4414 offset += 1;
4415 }
4416 if (item_count % 2) {
4417 proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
4418 offset += 1;
4419 }
4420 break;
4421 }
4422 return offset;
4423 }
4424
4425 /*******************************************************************************************************
4426 *
4427 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output ISTACK (0x03)
4428 *
4429 *******************************************************************************************************/
4430 static guint32
s7comm_decode_ud_tis_istack(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)4431 s7comm_decode_ud_tis_istack(tvbuff_t *tvb,
4432 proto_tree *td_tree,
4433 guint8 type,
4434 guint32 offset)
4435 {
4436 guint8 ob_number = 0;
4437 switch (type) {
4438 case S7COMM_UD_TYPE_REQ:
4439 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4440 offset += 2;
4441 break;
4442 case S7COMM_UD_TYPE_RES:
4443 case S7COMM_UD_TYPE_PUSH:
4444 proto_tree_add_item(td_tree, hf_s7comm_tis_continued_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4445 offset += 2;
4446 proto_tree_add_item(td_tree, hf_s7comm_tis_continued_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4447 offset += 2;
4448 proto_tree_add_item(td_tree, hf_s7comm_tis_continued_address, tvb, offset, 2, ENC_NA);
4449 offset += 2;
4450 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4451 offset += 1;
4452 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4453 offset += 1;
4454 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4455 offset += 2;
4456 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4457 offset += 2;
4458 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 4, ENC_NA);
4459 offset += 4;
4460 proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu1, tvb, offset, 4, ENC_NA);
4461 offset += 4;
4462 proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu2, tvb, offset, 4, ENC_NA);
4463 offset += 4;
4464 proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu3, tvb, offset, 4, ENC_NA);
4465 offset += 4;
4466 proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu4, tvb, offset, 4, ENC_NA);
4467 offset += 4;
4468 proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar1, tvb, offset, 4, ENC_NA);
4469 offset += 4;
4470 proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar2, tvb, offset, 4, ENC_NA);
4471 offset += 4;
4472 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4473 offset += 2;
4474 proto_tree_add_item(td_tree, hf_s7comm_tis_register_stw, tvb, offset, 2, ENC_NA);
4475 offset += 2;
4476 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4477 offset += 2;
4478 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4479 offset += 2;
4480 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4481 offset += 2;
4482 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4483 offset += 2;
4484 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 4, ENC_NA);
4485 offset += 4;
4486 /* read the OB number first */
4487 ob_number = tvb_get_guint8(tvb, offset + 3);
4488 switch (ob_number) {
4489 case 1: /* Cyclic execution */
4490 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4491 offset += 1;
4492 proto_tree_add_item(td_tree, hf_s7comm_ob_scan_1, tvb, offset, 1, ENC_NA);
4493 offset += 1;
4494 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4495 offset += 1;
4496 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4497 offset += 1;
4498 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4499 offset += 1;
4500 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4501 offset += 1;
4502 proto_tree_add_item(td_tree, hf_s7comm_ob_prev_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
4503 offset += 2;
4504 proto_tree_add_item(td_tree, hf_s7comm_ob_min_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
4505 offset += 2;
4506 proto_tree_add_item(td_tree, hf_s7comm_ob_max_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
4507 offset += 2;
4508 break;
4509 case 10: /* Time of day interrupt 0..7 */
4510 case 11:
4511 case 12:
4512 case 13:
4513 case 14:
4514 case 15:
4515 case 16:
4516 case 17:
4517 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4518 offset += 1;
4519 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4520 offset += 1;
4521 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4522 offset += 1;
4523 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4524 offset += 1;
4525 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4526 offset += 1;
4527 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4528 offset += 1;
4529 proto_tree_add_item(td_tree, hf_s7comm_ob_period_exe, tvb, offset, 2, ENC_BIG_ENDIAN);
4530 offset += 2;
4531 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4532 offset += 2;
4533 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4, tvb, offset, 2, ENC_BIG_ENDIAN);
4534 offset += 2;
4535 break;
4536 case 20: /* Time delay interrupt 0..3 */
4537 case 21:
4538 case 22:
4539 case 23:
4540 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4541 offset += 1;
4542 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4543 offset += 1;
4544 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4545 offset += 1;
4546 proto_tree_add_item(td_tree, hf_s7comm_ob_scan_1, tvb, offset, 1, ENC_NA);
4547 offset += 1;
4548 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4549 offset += 1;
4550 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4551 offset += 1;
4552 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4553 offset += 1;
4554 proto_tree_add_item(td_tree, hf_s7comm_ob_sign, tvb, offset, 2, ENC_BIG_ENDIAN);
4555 offset += 2;
4556 proto_tree_add_item(td_tree, hf_s7comm_ob_dtime, tvb, offset, 4, ENC_BIG_ENDIAN);
4557 offset += 4;
4558 break;
4559 case 30: /* Cyclic interrupt 0..8 */
4560 case 31:
4561 case 32:
4562 case 33:
4563 case 34:
4564 case 35:
4565 case 36:
4566 case 37:
4567 case 38:
4568 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4569 offset += 1;
4570 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4571 offset += 1;
4572 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4573 offset += 1;
4574 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4575 offset += 1;
4576 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4577 offset += 1;
4578 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4579 offset += 1;
4580 proto_tree_add_item(td_tree, hf_s7comm_ob_phase_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
4581 offset += 2;
4582 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4583 offset += 2;
4584 proto_tree_add_item(td_tree, hf_s7comm_ob_exec_freq, tvb, offset, 2, ENC_BIG_ENDIAN);
4585 offset += 2;
4586 break;
4587 case 40: /* Hardware interrupt 0..8 */
4588 case 41:
4589 case 42:
4590 case 43:
4591 case 44:
4592 case 45:
4593 case 46:
4594 case 47:
4595 case 48:
4596 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4597 offset += 1;
4598 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4599 offset += 1;
4600 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4601 offset += 1;
4602 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4603 offset += 1;
4604 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4605 offset += 1;
4606 proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4607 offset += 1;
4608 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4609 offset += 2;
4610 proto_tree_add_item(td_tree, hf_s7comm_ob_point_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
4611 offset += 4;
4612 break;
4613 case 55: /* DP Statusalarm */
4614 case 56: /* DP Updatealarm */
4615 case 57: /* DP Specific alarm */
4616 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4617 offset += 1;
4618 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4619 offset += 1;
4620 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4621 offset += 1;
4622 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4623 offset += 1;
4624 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4625 offset += 1;
4626 proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4627 offset += 1;
4628 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4629 offset += 2;
4630 proto_tree_add_item(td_tree, hf_s7comm_ob_inf_len, tvb, offset, 1, ENC_NA);
4631 offset += 1;
4632 proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_type, tvb, offset, 1, ENC_NA);
4633 offset += 1;
4634 proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_slot, tvb, offset, 1, ENC_NA);
4635 offset += 1;
4636 proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_spec, tvb, offset, 1, ENC_NA);
4637 offset += 1;
4638 break;
4639 case 80: /* Cycle time fault */
4640 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4641 offset += 1;
4642 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4643 offset += 1;
4644 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4645 offset += 1;
4646 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4647 offset += 1;
4648 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4649 offset += 1;
4650 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4651 offset += 1;
4652 proto_tree_add_item(td_tree, hf_s7comm_ob_error_info, tvb, offset, 2, ENC_BIG_ENDIAN);
4653 offset += 2;
4654 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_class, tvb, offset, 1, ENC_NA);
4655 offset += 1;
4656 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_num, tvb, offset, 1, ENC_NA);
4657 offset += 1;
4658 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_priority, tvb, offset, 1, ENC_NA);
4659 offset += 1;
4660 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_num, tvb, offset, 1, ENC_NA);
4661 offset += 1;
4662 break;
4663 case 81: /* Power supply fault */
4664 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4665 offset += 1;
4666 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4667 offset += 1;
4668 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4669 offset += 1;
4670 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4671 offset += 1;
4672 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4673 offset += 1;
4674 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4675 offset += 1;
4676 proto_tree_add_item(td_tree, hf_s7comm_ob_rack_cpu, tvb, offset, 2, ENC_BIG_ENDIAN);
4677 offset += 2;
4678 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4679 offset += 2;
4680 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4, tvb, offset, 2, ENC_BIG_ENDIAN);
4681 offset += 2;
4682 break;
4683 case 82: /* I/O Point fault 1 */
4684 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4685 offset += 1;
4686 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4687 offset += 1;
4688 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4689 offset += 1;
4690 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4691 offset += 1;
4692 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4693 offset += 1;
4694 proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4695 offset += 1;
4696 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4697 offset += 2;
4698 proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
4699 offset += 1;
4700 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_type_b, tvb, offset, 1, ENC_NA);
4701 offset += 1;
4702 proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
4703 offset += 1;
4704 proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
4705 offset += 1;
4706 break;
4707 case 83: /* I/O Point fault 2 */
4708 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4709 offset += 1;
4710 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4711 offset += 1;
4712 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4713 offset += 1;
4714 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4715 offset += 1;
4716 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4717 offset += 1;
4718 proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
4719 offset += 1;
4720 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4721 offset += 2;
4722 proto_tree_add_item(td_tree, hf_s7comm_ob_rack_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4723 offset += 2;
4724 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_type_w, tvb, offset, 2, ENC_BIG_ENDIAN);
4725 offset += 2;
4726 break;
4727 case 84: /* CPU fault */
4728 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4729 offset += 1;
4730 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4731 offset += 1;
4732 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4733 offset += 1;
4734 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4735 offset += 1;
4736 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4737 offset += 1;
4738 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4739 offset += 1;
4740 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4741 offset += 2;
4742 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4_dw, tvb, offset, 4, ENC_BIG_ENDIAN);
4743 offset += 4;
4744 break;
4745 case 85: /* OB not loaded fault */
4746 case 87: /* Communication Fault */
4747 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4748 offset += 1;
4749 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4750 offset += 1;
4751 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4752 offset += 1;
4753 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4754 offset += 1;
4755 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4756 offset += 1;
4757 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4758 offset += 1;
4759 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4760 offset += 2;
4761 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_class, tvb, offset, 1, ENC_NA);
4762 offset += 1;
4763 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_num, tvb, offset, 1, ENC_NA);
4764 offset += 1;
4765 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_priority, tvb, offset, 1, ENC_NA);
4766 offset += 1;
4767 proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_num, tvb, offset, 1, ENC_NA);
4768 offset += 1;
4769 break;
4770 case 86: /* Loss of rack fault */
4771 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4772 offset += 1;
4773 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
4774 offset += 1;
4775 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4776 offset += 1;
4777 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4778 offset += 1;
4779 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4780 offset += 1;
4781 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4782 offset += 1;
4783 proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4784 offset += 2;
4785 proto_tree_add_item(td_tree, hf_s7comm_ob_racks_flt, tvb, offset, 4, ENC_BIG_ENDIAN);
4786 offset += 4;
4787 break;
4788 case 90: /* Background cycle */
4789 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4790 offset += 1;
4791 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
4792 offset += 1;
4793 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4794 offset += 1;
4795 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4796 offset += 1;
4797 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4798 offset += 1;
4799 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4800 offset += 1;
4801 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
4802 offset += 2;
4803 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4_dw, tvb, offset, 4, ENC_BIG_ENDIAN);
4804 offset += 4;
4805 break;
4806 case 100: /* Complete restart */
4807 case 101: /* Restart */
4808 case 102: /* Cold restart */
4809 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4810 offset += 1;
4811 proto_tree_add_item(td_tree, hf_s7comm_ob_strtup, tvb, offset, 1, ENC_NA);
4812 offset += 1;
4813 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4814 offset += 1;
4815 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4816 offset += 1;
4817 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4818 offset += 1;
4819 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
4820 offset += 1;
4821 proto_tree_add_item(td_tree, hf_s7comm_ob_stop, tvb, offset, 2, ENC_BIG_ENDIAN);
4822 offset += 2;
4823 proto_tree_add_item(td_tree, hf_s7comm_ob_strt_info, tvb, offset, 4, ENC_BIG_ENDIAN);
4824 offset += 4;
4825 break;
4826 case 121: /* Programming Error */
4827 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4828 offset += 1;
4829 proto_tree_add_item(td_tree, hf_s7comm_ob_sw_flt, tvb, offset, 1, ENC_NA);
4830 offset += 1;
4831 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4832 offset += 1;
4833 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4834 offset += 1;
4835 proto_tree_add_item(td_tree, hf_s7comm_ob_blk_type, tvb, offset, 1, ENC_NA);
4836 offset += 1;
4837 proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
4838 offset += 1;
4839 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_reg, tvb, offset, 2, ENC_BIG_ENDIAN);
4840 offset += 2;
4841 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_blk_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4842 offset += 2;
4843 proto_tree_add_item(td_tree, hf_s7comm_ob_prg_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4844 offset += 2;
4845 break;
4846 case 122: /* Module Access Error */
4847 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4848 offset += 1;
4849 proto_tree_add_item(td_tree, hf_s7comm_ob_sw_flt, tvb, offset, 1, ENC_NA);
4850 offset += 1;
4851 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4852 offset += 1;
4853 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4854 offset += 1;
4855 proto_tree_add_item(td_tree, hf_s7comm_ob_blk_type, tvb, offset, 1, ENC_NA);
4856 offset += 1;
4857 proto_tree_add_item(td_tree, hf_s7comm_ob_mem_area, tvb, offset, 1, ENC_NA);
4858 offset += 1;
4859 proto_tree_add_item(td_tree, hf_s7comm_ob_mem_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4860 offset += 2;
4861 proto_tree_add_item(td_tree, hf_s7comm_ob_flt_blk_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4862 offset += 2;
4863 proto_tree_add_item(td_tree, hf_s7comm_ob_prg_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
4864 offset += 2;
4865 break;
4866 default:
4867 proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
4868 offset += 1;
4869 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 1, ENC_NA);
4870 offset += 1;
4871 proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
4872 offset += 1;
4873 proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
4874 offset += 1;
4875 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4876 offset += 2;
4877 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4878 offset += 2;
4879 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4880 offset += 2;
4881 proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
4882 offset += 2;
4883 break;
4884 }
4885 offset = s7comm_add_timestamp_to_tree(tvb, td_tree, offset, FALSE, FALSE);
4886 }
4887 return offset;
4888 }
4889
4890 /*******************************************************************************************************
4891 *
4892 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output BSTACK (0x04)
4893 *
4894 *******************************************************************************************************/
4895 static guint32
s7comm_decode_ud_tis_bstack(tvbuff_t * tvb,proto_tree * td_tree,guint16 td_size,guint8 type,guint32 offset)4896 s7comm_decode_ud_tis_bstack(tvbuff_t *tvb,
4897 proto_tree *td_tree,
4898 guint16 td_size,
4899 guint8 type,
4900 guint32 offset)
4901 {
4902 guint16 i;
4903 guint16 blocktype;
4904 guint16 blocknumber;
4905 proto_item *item = NULL;
4906 proto_tree *item_tree = NULL;
4907 int rem;
4908 guint32 replen;
4909
4910 /* Possible firmware bug in IM151-8 CPU, where also the date size information
4911 * in the header is 4 bytes too short.
4912 */
4913 replen = tvb_reported_length_remaining(tvb, offset);
4914 if (replen < td_size) {
4915 /* TODO: Show this mismatch? We fix the length here. */
4916 td_size = replen;
4917 }
4918 switch (type) {
4919 case S7COMM_UD_TYPE_REQ:
4920 proto_tree_add_item(td_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 2, ENC_NA);
4921 offset += 2;
4922 break;
4923 case S7COMM_UD_TYPE_RES:
4924 case S7COMM_UD_TYPE_PUSH:
4925 rem = td_size;
4926 i = 1;
4927 while (rem > 16) {
4928 item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 16, ENC_NA);
4929 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
4930 blocktype = tvb_get_ntohs(tvb, offset);
4931 proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4932 offset += 2;
4933 blocknumber = tvb_get_ntohs(tvb, offset);
4934 proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4935 offset += 2;
4936 proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
4937 offset += 2;
4938 proto_tree_add_item(item_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4939 offset += 1;
4940 proto_tree_add_item(item_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4941 offset += 1;
4942 proto_tree_add_item(item_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4943 offset += 2;
4944 proto_tree_add_item(item_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
4945 offset += 2;
4946 proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 4, ENC_NA);
4947 offset += 4;
4948 proto_item_append_text(item, " [%d] BSTACK entry for: %s %d", i++,
4949 val_to_str(blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"), blocknumber);
4950 rem -= 16;
4951 if (blocktype == S7COMM_SUBBLKTYPE_OB) {
4952 proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
4953 offset += 1;
4954 proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 1, ENC_NA);
4955 offset += 1;
4956 proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 2, ENC_NA);
4957 offset += 2;
4958 rem -= 4;
4959 if (rem >= 8) {
4960 offset = s7comm_add_timestamp_to_tree(tvb, item_tree, offset, FALSE, FALSE);
4961 rem -= 8;
4962 } else {
4963 proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, rem, ENC_NA);
4964 offset += rem;
4965 break;
4966 }
4967 }
4968 }
4969 }
4970 return offset;
4971 }
4972
4973 /*******************************************************************************************************
4974 *
4975 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output LSTACK (0x05)
4976 *
4977 *******************************************************************************************************/
4978 static guint32
s7comm_decode_ud_tis_lstack(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)4979 s7comm_decode_ud_tis_lstack(tvbuff_t *tvb,
4980 proto_tree *td_tree,
4981 guint8 type,
4982 guint32 offset)
4983 {
4984 guint16 len;
4985
4986 if (type == S7COMM_UD_TYPE_REQ) {
4987 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
4988 offset += 1;
4989 proto_tree_add_item(td_tree, hf_s7comm_tis_bstack_nest_depth, tvb, offset, 1, ENC_NA);
4990 offset += 1;
4991 } else {
4992 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
4993 offset += 2;
4994 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
4995 offset += 2;
4996 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_NA);
4997 offset += 2;
4998 len = tvb_get_ntohs(tvb, offset);
4999 proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_size, tvb, offset, 2, ENC_NA);
5000 offset += 2;
5001 proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_data, tvb, offset, len, ENC_NA);
5002 offset += len;
5003 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
5004 offset += 1;
5005 proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_reserved, tvb, offset, 1, ENC_NA);
5006 offset += 1;
5007 proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_reserved, tvb, offset, 2, ENC_NA);
5008 offset += 2;
5009 offset = s7comm_add_timestamp_to_tree(tvb, td_tree, offset, FALSE, FALSE);
5010 }
5011 return offset;
5012 }
5013 /*******************************************************************************************************
5014 *
5015 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Exit Hold (0x0b)
5016 *
5017 *******************************************************************************************************/
5018 static guint32
s7comm_decode_ud_tis_exithold(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)5019 s7comm_decode_ud_tis_exithold(tvbuff_t *tvb,
5020 proto_tree *td_tree,
5021 guint8 type,
5022 guint32 offset)
5023 {
5024 /* Only request with data payload was seen */
5025 switch (type) {
5026 case S7COMM_UD_TYPE_REQ:
5027 proto_tree_add_item(td_tree, hf_s7comm_tis_exithold_until, tvb, offset, 1, ENC_NA);
5028 offset += 1;
5029 proto_tree_add_item(td_tree, hf_s7comm_tis_exithold_res1, tvb, offset, 1, ENC_NA);
5030 offset += 1;
5031 break;
5032 }
5033 return offset;
5034 }
5035
5036 /*******************************************************************************************************
5037 *
5038 * PDU Type: User Data -> Function group 1 -> Programmer commands -> Breakpoint (0x0a)
5039 *
5040 *******************************************************************************************************/
5041 static guint32
s7comm_decode_ud_tis_breakpoint(tvbuff_t * tvb,proto_tree * td_tree,guint8 type,guint32 offset)5042 s7comm_decode_ud_tis_breakpoint(tvbuff_t *tvb,
5043 proto_tree *td_tree,
5044 guint8 type,
5045 guint32 offset)
5046 {
5047 switch (type) {
5048 case S7COMM_UD_TYPE_REQ:
5049 proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_reserved, tvb, offset, 2, ENC_NA);
5050 offset += 2;
5051 break;
5052 case S7COMM_UD_TYPE_RES:
5053 case S7COMM_UD_TYPE_PUSH:
5054 /* Info: Both blocknumbers and addresses are the same on online-blockview inside a block.
5055 * On return out of a block, the first address contains the current breakpoint, the second
5056 * address the address from where it was returned (previous block).
5057 */
5058 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
5059 offset += 2;
5060 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
5061 offset += 2;
5062 proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
5063 offset += 2;
5064 proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
5065 offset += 2;
5066 proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
5067 offset += 2;
5068 proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_address, tvb, offset, 2, ENC_NA);
5069 offset += 2;
5070 proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_reserved, tvb, offset, 2, ENC_NA);
5071 offset += 2;
5072 proto_tree_add_item(td_tree, hf_s7comm_tis_register_stw, tvb, offset, 2, ENC_NA);
5073 offset += 2;
5074 proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu1, tvb, offset, 4, ENC_NA);
5075 offset += 4;
5076 proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu2, tvb, offset, 4, ENC_NA);
5077 offset += 4;
5078 proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar1, tvb, offset, 4, ENC_NA);
5079 offset += 4;
5080 proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar2, tvb, offset, 4, ENC_NA);
5081 offset += 4;
5082 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5083 offset += 1;
5084 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5085 offset += 1;
5086 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
5087 offset += 2;
5088 proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
5089 offset += 2;
5090 }
5091 return offset;
5092 }
5093
5094 /*******************************************************************************************************
5095 *
5096 * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
5097 * Dissects the data part
5098 *
5099 *******************************************************************************************************/
5100 static guint32
s7comm_decode_ud_tis_data(tvbuff_t * tvb,proto_tree * tree,guint8 type,guint8 subfunc,guint16 td_size,guint32 offset)5101 s7comm_decode_ud_tis_data(tvbuff_t *tvb,
5102 proto_tree *tree,
5103 guint8 type,
5104 guint8 subfunc,
5105 guint16 td_size,
5106 guint32 offset)
5107 {
5108 proto_item *item = NULL;
5109 proto_tree *td_tree = NULL;
5110
5111 if (td_size > 0) {
5112 item = proto_tree_add_item(tree, hf_s7comm_tis_data, tvb, offset, td_size, ENC_NA);
5113 td_tree = proto_item_add_subtree(item, ett_s7comm_prog_data);
5114 switch (subfunc) {
5115 case S7COMM_UD_SUBF_PROG_OUTISTACK:
5116 offset = s7comm_decode_ud_tis_istack(tvb, td_tree, type, offset);
5117 break;
5118 case S7COMM_UD_SUBF_PROG_OUTBSTACK:
5119 offset = s7comm_decode_ud_tis_bstack(tvb, td_tree, td_size, type, offset);
5120 break;
5121 case S7COMM_UD_SUBF_PROG_OUTLSTACK:
5122 offset = s7comm_decode_ud_tis_lstack(tvb, td_tree, type, offset);
5123 break;
5124 case S7COMM_UD_SUBF_PROG_BREAKPOINT:
5125 offset = s7comm_decode_ud_tis_breakpoint(tvb, td_tree, type, offset);
5126 break;
5127 case S7COMM_UD_SUBF_PROG_EXITHOLD:
5128 offset = s7comm_decode_ud_tis_exithold(tvb, td_tree, type, offset);
5129 break;
5130 case S7COMM_UD_SUBF_PROG_BLOCKSTAT:
5131 case S7COMM_UD_SUBF_PROG_BLOCKSTAT2:
5132 offset = s7comm_decode_ud_tis_blockstat(tvb, td_tree, td_size, type, subfunc, offset);
5133 break;
5134 case S7COMM_UD_SUBF_PROG_VARSTAT:
5135 offset = s7comm_decode_ud_tis_varstat(tvb, td_tree, type, offset);
5136 break;
5137 case S7COMM_UD_SUBF_PROG_DISABLEJOB:
5138 case S7COMM_UD_SUBF_PROG_ENABLEJOB:
5139 case S7COMM_UD_SUBF_PROG_DELETEJOB:
5140 case S7COMM_UD_SUBF_PROG_READJOBLIST:
5141 case S7COMM_UD_SUBF_PROG_READJOB:
5142 case S7COMM_UD_SUBF_PROG_REPLACEJOB:
5143 offset = s7comm_decode_ud_tis_jobs(tvb, td_tree, td_size, type, subfunc, offset);
5144 break;
5145 case S7COMM_UD_SUBF_PROG_MODVAR:
5146 offset = s7comm_decode_ud_tis_modvar(tvb, td_tree, type, offset);
5147 break;
5148 case S7COMM_UD_SUBF_PROG_FORCE:
5149 offset = s7comm_decode_ud_tis_force(tvb, td_tree, type, offset);
5150 break;
5151 default:
5152 proto_tree_add_item(td_tree, hf_s7comm_varstat_unknown, tvb, offset, td_size, ENC_NA);
5153 offset += td_size;
5154 break;
5155 }
5156 }
5157 return offset;
5158 }
5159
5160 /*******************************************************************************************************
5161 *
5162 * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
5163 *
5164 *******************************************************************************************************/
5165 static guint32
s7comm_decode_ud_tis_subfunc(tvbuff_t * tvb,proto_tree * data_tree,guint8 type,guint8 subfunc,guint32 offset)5166 s7comm_decode_ud_tis_subfunc(tvbuff_t *tvb,
5167 proto_tree *data_tree,
5168 guint8 type,
5169 guint8 subfunc,
5170 guint32 offset)
5171 {
5172 guint16 tp_size = 0;
5173 guint16 td_size = 0;
5174
5175 tp_size = tvb_get_ntohs(tvb, offset);
5176 proto_tree_add_item(data_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
5177 offset += 2;
5178 td_size = tvb_get_ntohs(tvb, offset);
5179 proto_tree_add_item(data_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
5180 offset += 2;
5181 /* Parameter tree */
5182 offset = s7comm_decode_ud_tis_param(tvb, data_tree, type, tp_size, offset);
5183 /* Data tree */
5184 offset = s7comm_decode_ud_tis_data(tvb, data_tree, type, subfunc, td_size, offset);
5185 return offset;
5186 }
5187
5188 /*******************************************************************************************************
5189 *
5190 * PDU Type: User Data -> Function group 5 -> Security functions?
5191 *
5192 *******************************************************************************************************/
5193 static guint32
s7comm_decode_ud_security_subfunc(tvbuff_t * tvb,proto_tree * data_tree,guint32 dlength,guint32 offset)5194 s7comm_decode_ud_security_subfunc(tvbuff_t *tvb,
5195 proto_tree *data_tree,
5196 guint32 dlength,
5197 guint32 offset)
5198 {
5199 /* Display dataset as raw bytes. Maybe this part can be extended with further knowledge. */
5200 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
5201 offset += dlength;
5202
5203 return offset;
5204 }
5205
5206 /*******************************************************************************************************
5207 *
5208 * PDU Type: User Data -> Function group 6 -> PBC, Programmable Block Functions (e.g. BSEND/BRECV), before reassembly
5209 *
5210 *******************************************************************************************************/
5211 static guint32
s7comm_decode_ud_pbc_pre_reass(tvbuff_t * tvb,packet_info * pinfo,proto_tree * data_tree,guint8 type,guint16 * dlength,guint32 * r_id,guint32 offset)5212 s7comm_decode_ud_pbc_pre_reass(tvbuff_t *tvb,
5213 packet_info *pinfo,
5214 proto_tree *data_tree,
5215 guint8 type, /* Type of data (request/response) */
5216 guint16 *dlength,
5217 guint32 *r_id, /* R_ID of the PBC communication */
5218 guint32 offset)
5219 {
5220 if ((type == S7COMM_UD_TYPE_REQ || type == S7COMM_UD_TYPE_RES) && (*dlength >= 8)) {
5221 proto_tree_add_item(data_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
5222 offset += 1;
5223 proto_tree_add_item(data_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, ENC_BIG_ENDIAN);
5224 offset += 1;
5225 proto_tree_add_item(data_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, ENC_BIG_ENDIAN);
5226 offset += 1;
5227 /* 0x00 when passive partners is sending, 0xcc when active partner is sending? */
5228 proto_tree_add_item(data_tree, hf_s7comm_pbc_unknown, tvb, offset, 1, ENC_BIG_ENDIAN);
5229 offset += 1;
5230 proto_tree_add_item(data_tree, hf_s7comm_pbc_r_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5231 *r_id = tvb_get_ntohl(tvb, offset);
5232 col_append_fstr(pinfo->cinfo, COL_INFO, " R_ID=0x%X", *r_id);
5233 offset += 4;
5234 *dlength -= 8;
5235 }
5236 return offset;
5237 }
5238
5239 /*******************************************************************************************************
5240 *
5241 * PDU Type: User Data -> Function group 6 -> PBC, Programmable Block Functions (e.g. BSEND/BRECV)
5242 *
5243 *******************************************************************************************************/
5244 static guint32
s7comm_decode_ud_pbc_subfunc(tvbuff_t * tvb,proto_tree * data_tree,guint32 dlength,guint32 offset)5245 s7comm_decode_ud_pbc_subfunc(tvbuff_t *tvb,
5246 proto_tree *data_tree,
5247 guint32 dlength,
5248 guint32 offset)
5249 {
5250 proto_tree_add_item(data_tree, hf_s7comm_pbc_len, tvb, offset, 2, ENC_BIG_ENDIAN);
5251 offset += 2;
5252 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength - 2, ENC_NA);
5253 offset += (dlength - 2);
5254
5255 return offset;
5256 }
5257
5258 /*******************************************************************************************************
5259 *
5260 * PDU Type: User Data -> NC programming functions (file download/upload), before reassembly
5261 *
5262 *******************************************************************************************************/
5263 static guint32
s7comm_decode_ud_ncprg_pre_reass(tvbuff_t * tvb,proto_tree * data_tree,guint8 type,guint8 subfunc,guint16 * dlength,guint32 offset)5264 s7comm_decode_ud_ncprg_pre_reass(tvbuff_t *tvb,
5265 proto_tree *data_tree,
5266 guint8 type, /* Type of data (request/response) */
5267 guint8 subfunc, /* Subfunction */
5268 guint16 *dlength,
5269 guint32 offset)
5270 {
5271 if ((type == S7COMM_UD_TYPE_NCRES || type == S7COMM_UD_TYPE_NCPUSH) &&
5272 (subfunc == S7COMM_NCPRG_FUNCDOWNLOADBLOCK ||
5273 subfunc == S7COMM_NCPRG_FUNCUPLOAD ||
5274 subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD)) {
5275 proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
5276 offset += 2;
5277 *dlength -= 2;
5278 }
5279 return offset;
5280 }
5281
5282 /*******************************************************************************************************
5283 *
5284 * PDU Type: User Data -> NC programming functions (file download/upload)
5285 *
5286 *******************************************************************************************************/
5287 static guint32
s7comm_decode_ud_ncprg_subfunc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * data_tree,guint8 type,guint8 subfunc,guint32 dlength,guint32 offset)5288 s7comm_decode_ud_ncprg_subfunc(tvbuff_t *tvb,
5289 packet_info *pinfo,
5290 proto_tree *data_tree,
5291 guint8 type, /* Type of data (request/response) */
5292 guint8 subfunc, /* Subfunction */
5293 guint32 dlength,
5294 guint32 offset)
5295 {
5296 const guint8 *str_filename;
5297 guint32 string_end_offset;
5298 guint32 string_len;
5299 guint32 filelength;
5300 guint32 start_offset;
5301
5302 if (dlength >= 2) {
5303 if (type == S7COMM_UD_TYPE_NCREQ && subfunc == S7COMM_NCPRG_FUNCREQUESTDOWNLOAD) {
5304 proto_tree_add_item_ret_string(data_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, dlength,
5305 ENC_ASCII|ENC_NA, pinfo->pool, &str_filename);
5306 col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str_filename);
5307 offset += dlength;
5308 } else if (type == S7COMM_UD_TYPE_NCREQ && subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD) {
5309 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA);
5310 offset += 1;
5311 dlength -= 1;
5312 proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA);
5313 offset += 1;
5314 dlength -= 1;
5315 proto_tree_add_item_ret_string(data_tree, hf_s7comm_data_blockcontrol_filename, tvb, offset, dlength,
5316 ENC_ASCII|ENC_NA, pinfo->pool, &str_filename);
5317 col_append_fstr(pinfo->cinfo, COL_INFO, " File:[%s]", str_filename);
5318 offset += dlength;
5319 } else if (type == S7COMM_UD_TYPE_NCRES && subfunc == S7COMM_NCPRG_FUNCREQUESTDOWNLOAD) {
5320 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA);
5321 offset += 1;
5322 proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA);
5323 offset += 1;
5324 } else if (type == S7COMM_UD_TYPE_NCPUSH && (subfunc == S7COMM_NCPRG_FUNCCONTUPLOAD || subfunc == S7COMM_NCPRG_FUNCCONTDOWNLOAD)) {
5325 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_unackcount, tvb, offset, 1, ENC_NA);
5326 offset += 1;
5327 proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 1, ENC_NA);
5328 offset += 1;
5329 } else if ((type == S7COMM_UD_TYPE_NCRES || type == S7COMM_UD_TYPE_NCPUSH) &&
5330 (subfunc == S7COMM_NCPRG_FUNCDOWNLOADBLOCK ||
5331 subfunc == S7COMM_NCPRG_FUNCUPLOAD ||
5332 subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD)) {
5333 start_offset = offset;
5334 /* file length may be contain only spaces when downloading a directory */
5335 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filelength, tvb, offset, 8, ENC_ASCII|ENC_NA);
5336 offset += 8;
5337 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filetime, tvb, offset, 16, ENC_ASCII|ENC_NA);
5338 offset += 16;
5339 /* File path and file data aren't always there */
5340 if (dlength > 24) {
5341 if (subfunc == S7COMM_NCPRG_FUNCDOWNLOADBLOCK || subfunc == S7COMM_NCPRG_FUNCSTARTUPLOAD || subfunc == S7COMM_NCPRG_FUNCUPLOAD) {
5342 string_end_offset = tvb_find_guint8(tvb, offset, dlength-8-16, 0x0a);
5343 if (string_end_offset > 0) {
5344 string_len = string_end_offset - offset + 1; /* include 0x0a */
5345 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filepath, tvb, offset, string_len, ENC_ASCII|ENC_NA);
5346 offset += string_len;
5347 filelength = dlength - (offset - start_offset);
5348 proto_tree_add_item(data_tree, hf_s7comm_data_ncprg_filedata, tvb, offset, filelength, ENC_NA);
5349 offset += filelength;
5350 }
5351 }
5352 }
5353 } else {
5354 proto_tree_add_item(data_tree, hf_s7comm_data_blockcontrol_unknown1, tvb, offset, 2, ENC_NA);
5355 offset += 2;
5356 dlength -= 2;
5357 if (dlength >= 4) {
5358 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
5359 offset += dlength;
5360 }
5361 }
5362 }
5363 return offset;
5364 }
5365
5366 /*******************************************************************************************************
5367 *
5368 * PDU Type: User Data -> Message services
5369 *
5370 *******************************************************************************************************/
5371 static guint32
s7comm_decode_message_service(tvbuff_t * tvb,packet_info * pinfo,proto_tree * data_tree,guint8 type,guint32 dlength,guint32 offset)5372 s7comm_decode_message_service(tvbuff_t *tvb,
5373 packet_info *pinfo,
5374 proto_tree *data_tree,
5375 guint8 type, /* Type of data (request/response) */
5376 guint32 dlength,
5377 guint32 offset)
5378 {
5379 guint8 events;
5380 guint8 almtype;
5381 gchar events_string[42];
5382
5383 switch (type) {
5384 case S7COMM_UD_TYPE_REQ:
5385 events = tvb_get_guint8(tvb, offset);
5386 proto_tree_add_bitmask(data_tree, tvb, offset, hf_s7comm_cpu_msgservice_subscribe_events,
5387 ett_s7comm_cpu_msgservice_subscribe_events, s7comm_cpu_msgservice_subscribe_events_fields, ENC_BIG_ENDIAN);
5388 offset += 1;
5389 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_req_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
5390 offset += 1;
5391
5392 (void) g_strlcpy(events_string, "", sizeof(events_string));
5393 if (events & 0x01) (void) g_strlcat(events_string, "MODE,", sizeof(events_string)); /* Change in mode-transition: Stop, Run, by Push and Function-group=0, Subfunction: 0=Stop, 1=Warm Restart, 2=RUN */
5394 if (events & 0x02) (void) g_strlcat(events_string, "SYS,", sizeof(events_string)); /* System diagnostics */
5395 if (events & 0x04) (void) g_strlcat(events_string, "USR,", sizeof(events_string)); /* User-defined diagnostic messages */
5396 if (events & 0x08) (void) g_strlcat(events_string, "-4-,", sizeof(events_string)); /* currently unknown flag */
5397 if (events & 0x10) (void) g_strlcat(events_string, "-5-,", sizeof(events_string)); /* currently unknown flag */
5398 if (events & 0x20) (void) g_strlcat(events_string, "-6-,", sizeof(events_string)); /* currently unknown flag */
5399 if (events & 0x40) (void) g_strlcat(events_string, "-7-,", sizeof(events_string)); /* currently unknown flag */
5400 if (events & 0x80) (void) g_strlcat(events_string, "ALM,", sizeof(events_string)); /* Program block message, type of message in additional field */
5401 if (strlen(events_string) > 2)
5402 events_string[strlen(events_string) - 1 ] = '\0';
5403 col_append_fstr(pinfo->cinfo, COL_INFO, " SubscribedEvents=(%s)", events_string);
5404
5405 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_username, tvb, offset, 8, ENC_ASCII|ENC_NA);
5406 offset += 8;
5407 if ((events & 0x80) && (dlength > 10)) {
5408 almtype = tvb_get_guint8(tvb, offset);
5409 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_almtype, tvb, offset, 1, ENC_BIG_ENDIAN);
5410 col_append_fstr(pinfo->cinfo, COL_INFO, " AlmType=%s", val_to_str(almtype, cpu_msgservice_almtype_names, "Unknown type: 0x%02x"));
5411 offset += 1;
5412 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_req_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
5413 offset += 1;
5414 }
5415 break;
5416 case S7COMM_UD_TYPE_RES:
5417 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_result, tvb, offset, 1, ENC_BIG_ENDIAN);
5418 offset += 1;
5419 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN);
5420 offset += 1;
5421 if (dlength > 2) {
5422 almtype = tvb_get_guint8(tvb, offset);
5423 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_almtype, tvb, offset, 1, ENC_BIG_ENDIAN);
5424 col_append_fstr(pinfo->cinfo, COL_INFO, " AlmType=%s", val_to_str(almtype, cpu_msgservice_almtype_names, "Unknown type: 0x%02x"));
5425 offset += 1;
5426 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
5427 offset += 1;
5428 proto_tree_add_item(data_tree, hf_s7comm_cpu_msgservice_res_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN);
5429 offset += 1;
5430 }
5431 break;
5432 }
5433
5434 return offset;
5435 }
5436
5437 /*******************************************************************************************************
5438 *
5439 * PDU Type: User Data -> Function group 4 -> alarm, main tree for all except query response
5440 *
5441 *******************************************************************************************************/
5442 static guint32
s7comm_decode_ud_cpu_alarm_main(tvbuff_t * tvb,packet_info * pinfo,proto_tree * data_tree,guint8 type,guint8 subfunc,guint32 offset)5443 s7comm_decode_ud_cpu_alarm_main(tvbuff_t *tvb,
5444 packet_info *pinfo,
5445 proto_tree *data_tree,
5446 guint8 type, /* Type of data (request/response) */
5447 guint8 subfunc, /* Subfunction */
5448 guint32 offset)
5449 {
5450 guint32 start_offset;
5451 guint32 asc_start_offset;
5452 guint32 msg_obj_start_offset;
5453 guint32 ev_id;
5454 proto_item *msg_item = NULL;
5455 proto_tree *msg_item_tree = NULL;
5456 proto_item *msg_obj_item = NULL;
5457 proto_tree *msg_obj_item_tree = NULL;
5458 proto_item *msg_work_item = NULL;
5459 proto_tree *msg_work_item_tree = NULL;
5460 guint8 nr_objects;
5461 guint8 i;
5462 guint8 syntax_id;
5463 guint8 nr_of_additional_values;
5464 guint8 signalstate;
5465 guint8 sig_nr;
5466 guint8 ret_val;
5467 guint8 querytype;
5468 guint8 varspec_length;
5469
5470 start_offset = offset;
5471
5472 msg_item = proto_tree_add_item(data_tree, hf_s7comm_cpu_alarm_message_item, tvb, offset, 0, ENC_NA);
5473 msg_item_tree = proto_item_add_subtree(msg_item, ett_s7comm_cpu_alarm_message);
5474
5475 switch (subfunc) {
5476 case S7COMM_UD_SUBF_CPU_SCAN_IND:
5477 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_scan_unknown1, tvb, offset, 2, ENC_BIG_ENDIAN);
5478 offset += 2;
5479 msg_work_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_timestamp_coming, tvb, offset, 8, ENC_NA);
5480 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5481 offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, TRUE, FALSE);
5482 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_scan_unknown2, tvb, offset, 2, ENC_BIG_ENDIAN);
5483 offset += 2;
5484 break;
5485 case S7COMM_UD_SUBF_CPU_ALARM8_IND:
5486 case S7COMM_UD_SUBF_CPU_ALARMACK_IND:
5487 case S7COMM_UD_SUBF_CPU_ALARMSQ_IND:
5488 case S7COMM_UD_SUBF_CPU_ALARMS_IND:
5489 case S7COMM_UD_SUBF_CPU_NOTIFY_IND:
5490 case S7COMM_UD_SUBF_CPU_NOTIFY8_IND:
5491 msg_work_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_timestamp_coming, tvb, offset, 8, ENC_NA);
5492 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5493 offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, TRUE, FALSE);
5494 break;
5495 }
5496 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_function, tvb, offset, 1, ENC_BIG_ENDIAN);
5497 offset += 1;
5498 nr_objects = tvb_get_guint8(tvb, offset);
5499 proto_tree_add_uint(msg_item_tree, hf_s7comm_cpu_alarm_message_nr_objects, tvb, offset, 1, nr_objects);
5500 offset += 1;
5501 for (i = 0; i < nr_objects; i++) {
5502 msg_obj_start_offset = offset;
5503 msg_obj_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_obj_item, tvb, offset, 0, ENC_NA);
5504 msg_obj_item_tree = proto_item_add_subtree(msg_obj_item, ett_s7comm_cpu_alarm_message_object);
5505 proto_item_append_text(msg_obj_item_tree, " [%d]", i+1);
5506 if (type == S7COMM_UD_TYPE_REQ || type == S7COMM_UD_TYPE_PUSH) {
5507 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_item_varspec, tvb, offset, 1, ENC_BIG_ENDIAN);
5508 offset += 1;
5509 varspec_length = tvb_get_guint8(tvb, offset);
5510 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_item_varspec_length, tvb, offset, 1, varspec_length);
5511 offset += 1;
5512 syntax_id = tvb_get_guint8(tvb, offset);
5513 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_item_syntax_id, tvb, offset, 1, syntax_id);
5514 offset += 1;
5515 switch (syntax_id) {
5516 case S7COMM_SYNTAXID_ALARM_LOCKFREESET:
5517 case S7COMM_SYNTAXID_ALARM_INDSET:
5518 case S7COMM_SYNTAXID_NOTIFY_INDSET:
5519 case S7COMM_SYNTAXID_ALARM_ACKSET:
5520 nr_of_additional_values = tvb_get_guint8(tvb, offset);
5521 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_nr_add_values, tvb, offset, 1, nr_of_additional_values);
5522 offset += 1;
5523 ev_id = tvb_get_ntohl(tvb, offset);
5524 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_eventid, tvb, offset, 4, ev_id);
5525 offset += 4;
5526 proto_item_append_text(msg_obj_item_tree, ": EventID=0x%08x", ev_id);
5527 col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%08x", ev_id);
5528 if (syntax_id == S7COMM_SYNTAXID_ALARM_INDSET || syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5529 signalstate = tvb_get_guint8(tvb, offset);
5530 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_eventstate,
5531 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5532 offset += 1;
5533 /* show SIG with True values for a quick overview in info-column */
5534 if (signalstate > 0) {
5535 col_append_str(pinfo->cinfo, COL_INFO, " On=[");
5536 for (sig_nr = 0; sig_nr < 8; sig_nr++) {
5537 if (signalstate & 0x01) {
5538 signalstate >>= 1;
5539 if (signalstate == 0) {
5540 col_append_fstr(pinfo->cinfo, COL_INFO, "SIG_%d", sig_nr + 1);
5541 } else {
5542 col_append_fstr(pinfo->cinfo, COL_INFO, "SIG_%d,", sig_nr + 1);
5543 }
5544 } else {
5545 signalstate >>= 1;
5546 }
5547 }
5548 col_append_str(pinfo->cinfo, COL_INFO, "]");
5549 }
5550 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_state,
5551 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5552 offset += 1;
5553 }
5554 if (syntax_id == S7COMM_SYNTAXID_ALARM_INDSET || syntax_id == S7COMM_SYNTAXID_ALARM_ACKSET || syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5555 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_going,
5556 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5557 offset += 1;
5558 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_coming,
5559 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5560 offset += 1;
5561 }
5562 if (syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5563 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_event_going,
5564 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5565 offset += 1;
5566 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_event_coming,
5567 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5568 offset += 1;
5569 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_event_lastchanged,
5570 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5571 offset += 1;
5572 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_event_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
5573 offset += 1;
5574 }
5575 if (syntax_id == S7COMM_SYNTAXID_ALARM_INDSET || syntax_id == S7COMM_SYNTAXID_NOTIFY_INDSET) {
5576 if (nr_of_additional_values > 0) {
5577 asc_start_offset = offset;
5578 msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_associated_value, tvb, offset, 0, ENC_NA);
5579 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_associated_value);
5580 offset = s7comm_decode_response_read_data(tvb, msg_work_item_tree, nr_of_additional_values, offset);
5581 proto_item_set_len(msg_work_item_tree, offset - asc_start_offset);
5582 }
5583 }
5584 break;
5585 case S7COMM_SYNTAXID_ALARM_QUERYREQSET:
5586 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_unknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
5587 offset += 1;
5588 querytype = tvb_get_guint8(tvb, offset);
5589 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_querytype, tvb, offset, 1, querytype);
5590 offset += 1;
5591 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_unknown2, tvb, offset, 1, ENC_BIG_ENDIAN);
5592 offset += 1;
5593 ev_id = tvb_get_ntohl(tvb, offset);
5594 /* there is a querytype=8, which only occurs when a previous SZL request 0x131 index 0x10 has a missing flag in funk_1 */
5595 switch (querytype) {
5596 case S7COMM_ALARM_MESSAGE_QUERYTYPE_BYALARMTYPE:
5597 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_alarmtype, tvb, offset, 4, ENC_BIG_ENDIAN);
5598 col_append_fstr(pinfo->cinfo, COL_INFO, " ByAlarmtype=%s",
5599 val_to_str(ev_id, alarm_message_query_alarmtype_names, "Unknown Alarmtype: %u"));
5600 break;
5601 case S7COMM_ALARM_MESSAGE_QUERYTYPE_BYEVENTID:
5602 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_eventid, tvb, offset, 4, ENC_BIG_ENDIAN);
5603 col_append_fstr(pinfo->cinfo, COL_INFO, " ByEventID=0x%08x", ev_id);
5604 break;
5605 default:
5606 break;
5607 }
5608 offset += 4;
5609 break;
5610 default:
5611 /* for current unknown syntax id, set offset to end of dataset. The varspec_length includes
5612 * the byte for the syntax_id, so minus one.
5613 */
5614 offset += (varspec_length - 1);
5615 break;
5616 }
5617 } else if (type == S7COMM_UD_TYPE_RES) {
5618 ret_val = tvb_get_guint8(tvb, offset);
5619 proto_item_append_text(msg_obj_item_tree, ": (%s)", val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
5620 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
5621 offset += 1;
5622 }
5623 proto_item_set_len(msg_obj_item_tree, offset - msg_obj_start_offset);
5624 }
5625 proto_item_set_len(msg_item_tree, offset - start_offset);
5626 return offset;
5627 }
5628
5629 /*******************************************************************************************************
5630 *
5631 * PDU Type: User Data -> Function group 4 -> alarm query response
5632 *
5633 *******************************************************************************************************/
5634 static guint32
s7comm_decode_ud_cpu_alarm_query_response(tvbuff_t * tvb,proto_tree * data_tree,guint32 offset)5635 s7comm_decode_ud_cpu_alarm_query_response(tvbuff_t *tvb,
5636 proto_tree *data_tree,
5637 guint32 offset)
5638 {
5639 proto_item *msg_item = NULL;
5640 proto_tree *msg_item_tree = NULL;
5641 proto_item *msg_obj_item = NULL;
5642 proto_tree *msg_obj_item_tree = NULL;
5643 proto_item *msg_work_item = NULL;
5644 proto_tree *msg_work_item_tree = NULL;
5645 guint32 start_offset;
5646 guint32 msg_obj_start_offset;
5647 guint32 asc_start_offset;
5648 guint32 ev_id;
5649 guint8 returncode;
5650 guint8 alarmtype;
5651 guint16 complete_length;
5652 gint32 remaining_length;
5653 gboolean cont;
5654
5655 start_offset = offset;
5656 msg_item = proto_tree_add_item(data_tree, hf_s7comm_cpu_alarm_message_item, tvb, offset, 0, ENC_NA);
5657 msg_item_tree = proto_item_add_subtree(msg_item, ett_s7comm_cpu_alarm_message);
5658
5659 /* Maybe this value here is something different, always 0x00 or 0x01 */
5660 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_function, tvb, offset, 1, ENC_BIG_ENDIAN);
5661 offset += 1;
5662 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_nr_objects, tvb, offset, 1, ENC_BIG_ENDIAN);
5663 offset += 1;
5664 returncode = tvb_get_guint8(tvb, offset);
5665 proto_tree_add_uint(msg_item_tree, hf_s7comm_data_returncode, tvb, offset, 1, returncode);
5666 offset += 1;
5667 proto_tree_add_item(msg_item_tree, hf_s7comm_data_transport_size, tvb, offset, 1, ENC_BIG_ENDIAN);
5668 offset += 1;
5669 complete_length = tvb_get_ntohs(tvb, offset);
5670 proto_tree_add_uint(msg_item_tree, hf_s7comm_cpu_alarm_query_completelen, tvb, offset, 2, complete_length);
5671 remaining_length = (gint32)complete_length;
5672 offset += 2;
5673
5674 if (returncode == S7COMM_ITEM_RETVAL_DATA_OK) {
5675 do {
5676 msg_obj_start_offset = offset;
5677 msg_obj_item = proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_alarm_message_obj_item, tvb, offset, 0, ENC_NA);
5678 msg_obj_item_tree = proto_item_add_subtree(msg_obj_item, ett_s7comm_cpu_alarm_message_object);
5679
5680 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_datasetlen, tvb, offset, 1, ENC_BIG_ENDIAN);
5681 offset += 1;
5682 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_resunknown1, tvb, offset, 2, ENC_BIG_ENDIAN);
5683 offset += 2;
5684 /* begin of count dataset length */
5685 alarmtype = tvb_get_guint8(tvb, offset);
5686 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_alarmtype, tvb, offset, 1, alarmtype);
5687 proto_item_append_text(msg_obj_item_tree, " (Alarmtype=%s)", val_to_str(alarmtype, alarm_message_query_alarmtype_names, "Unknown Alarmtype: %u"));
5688 offset += 1;
5689 ev_id = tvb_get_ntohl(tvb, offset);
5690 proto_tree_add_uint(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_eventid, tvb, offset, 4, ev_id);
5691 proto_item_append_text(msg_obj_item_tree, ": EventID=0x%08x", ev_id);
5692 offset += 4;
5693 proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_query_resunknown1, tvb, offset, 1, ENC_BIG_ENDIAN);
5694 offset += 1;
5695 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_eventstate,
5696 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5697 offset += 1;
5698 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_going,
5699 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5700 offset += 1;
5701 proto_tree_add_bitmask(msg_obj_item_tree, tvb, offset, hf_s7comm_cpu_alarm_message_ackstate_coming,
5702 ett_s7comm_cpu_alarm_message_signal, s7comm_cpu_alarm_message_signal_fields, ENC_BIG_ENDIAN);
5703 offset += 1;
5704 if (alarmtype == S7COMM_ALARM_MESSAGE_QUERY_ALARMTYPE_ALARM_S) {
5705 /* 8 bytes timestamp (coming)*/
5706 msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_timestamp_coming, tvb, offset, 8, ENC_NA);
5707 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5708 offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, TRUE, FALSE);
5709 /* Associated value of coming alarm */
5710 asc_start_offset = offset;
5711 msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_associated_value, tvb, offset, 0, ENC_NA);
5712 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_associated_value);
5713 offset = s7comm_decode_response_read_data(tvb, msg_work_item_tree, 1, offset);
5714 proto_item_set_len(msg_work_item_tree, offset - asc_start_offset);
5715 /* 8 bytes timestamp (going)
5716 * If all bytes in timestamp are zero, then the message is still active. */
5717 msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_timestamp_going, tvb, offset, 8, ENC_NA);
5718 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_timestamp);
5719 offset = s7comm_add_timestamp_to_tree(tvb, msg_work_item_tree, offset, TRUE, FALSE);
5720 /* Associated value of going alarm */
5721 asc_start_offset = offset;
5722 msg_work_item = proto_tree_add_item(msg_obj_item_tree, hf_s7comm_cpu_alarm_message_associated_value, tvb, offset, 0, ENC_NA);
5723 msg_work_item_tree = proto_item_add_subtree(msg_work_item, ett_s7comm_cpu_alarm_message_associated_value);
5724 offset = s7comm_decode_response_read_data(tvb, msg_work_item_tree, 1, offset);
5725 proto_item_set_len(msg_work_item_tree, offset - asc_start_offset);
5726 }
5727 remaining_length = remaining_length - (offset - msg_obj_start_offset);
5728 proto_item_set_len(msg_obj_item_tree, offset - msg_obj_start_offset);
5729 /* when complete_length is 0xffff, then loop until terminating null */
5730 if (complete_length == 0xffff) {
5731 cont = (tvb_get_guint8(tvb, offset) > 0);
5732 } else {
5733 cont = (remaining_length > 0);
5734 }
5735 } while (cont);
5736 }
5737 proto_item_set_len(msg_item_tree, offset - start_offset);
5738
5739 return offset;
5740 }
5741
5742 /*******************************************************************************************************
5743 *
5744 * PDU Type: User Data -> Function group 4 -> diagnostic message
5745 * Also used as a dataset in the diagnostic buffer, read with SZL-ID 0x00a0 index 0.
5746 *
5747 *******************************************************************************************************/
5748 guint32
s7comm_decode_ud_cpu_diagnostic_message(tvbuff_t * tvb,packet_info * pinfo,gboolean add_info_to_col,proto_tree * data_tree,guint32 offset)5749 s7comm_decode_ud_cpu_diagnostic_message(tvbuff_t *tvb,
5750 packet_info *pinfo,
5751 gboolean add_info_to_col,
5752 proto_tree *data_tree,
5753 guint32 offset)
5754 {
5755 proto_item *msg_item = NULL;
5756 proto_tree *msg_item_tree = NULL;
5757 guint16 eventid;
5758 guint16 eventid_masked;
5759 const gchar *event_text;
5760 gboolean has_text = FALSE;
5761
5762 msg_item = proto_tree_add_item(data_tree, hf_s7comm_cpu_diag_msg_item, tvb, offset, 20, ENC_NA);
5763 msg_item_tree = proto_item_add_subtree(msg_item, ett_s7comm_cpu_diag_msg);
5764
5765 eventid = tvb_get_ntohs(tvb, offset);
5766 if ((eventid >= 0x8000) && (eventid <= 0x9fff)) {
5767 eventid_masked = eventid & 0xf0ff;
5768 if ((event_text = try_val_to_str_ext(eventid_masked, &cpu_diag_eventid_0x8_0x9_names_ext))) {
5769 if (add_info_to_col) {
5770 col_append_fstr(pinfo->cinfo, COL_INFO, " Event='%s'", event_text);
5771 }
5772 has_text = TRUE;
5773 } else {
5774 if (add_info_to_col) {
5775 col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%04x", eventid);
5776 }
5777 }
5778 } else if ((eventid >= 0x1000) && (eventid < 0x8000)) {
5779 if ((event_text = try_val_to_str_ext(eventid, &cpu_diag_eventid_fix_names_ext))) {
5780 if (add_info_to_col) {
5781 col_append_fstr(pinfo->cinfo, COL_INFO, " Event='%s'", event_text);
5782 }
5783 has_text = TRUE;
5784 } else {
5785 if (add_info_to_col) {
5786 col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%04x", eventid);
5787 }
5788 }
5789 } else {
5790 if (add_info_to_col) {
5791 col_append_fstr(pinfo->cinfo, COL_INFO, " EventID=0x%04x", eventid);
5792 }
5793 }
5794 proto_tree_add_bitmask(msg_item_tree, tvb, offset, hf_s7comm_cpu_diag_msg_eventid,
5795 ett_s7comm_cpu_diag_msg_eventid, s7comm_cpu_diag_msg_eventid_fields, ENC_BIG_ENDIAN);
5796 if (has_text) {
5797 proto_item_append_text(msg_item_tree, ": Event='%s'", event_text);
5798 } else {
5799 proto_item_append_text(msg_item_tree, ": EventID=0x%04x", eventid);
5800 }
5801 offset += 2;
5802 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_prioclass, tvb, offset, 1, ENC_BIG_ENDIAN);
5803 offset += 1;
5804 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_obnumber, tvb, offset, 1, ENC_BIG_ENDIAN);
5805 offset += 1;
5806 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_datid, tvb, offset, 2, ENC_BIG_ENDIAN);
5807 offset += 2;
5808 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_info1, tvb, offset, 2, ENC_BIG_ENDIAN);
5809 offset += 2;
5810 proto_tree_add_item(msg_item_tree, hf_s7comm_cpu_diag_msg_info2, tvb, offset, 4, ENC_BIG_ENDIAN);
5811 offset += 4;
5812 offset = s7comm_add_timestamp_to_tree(tvb, msg_item_tree, offset, FALSE, FALSE);
5813
5814 return offset;
5815 }
5816
5817 /*******************************************************************************************************
5818 *
5819 * PDU Type: User Data -> Function group 7 -> time functions
5820 *
5821 *******************************************************************************************************/
5822 static guint32
s7comm_decode_ud_time_subfunc(tvbuff_t * tvb,proto_tree * data_tree,guint8 type,guint8 subfunc,guint8 ret_val,guint32 dlength,guint32 offset)5823 s7comm_decode_ud_time_subfunc(tvbuff_t *tvb,
5824 proto_tree *data_tree,
5825 guint8 type, /* Type of data (request/response) */
5826 guint8 subfunc, /* Subfunction */
5827 guint8 ret_val, /* Return value in data part */
5828 guint32 dlength,
5829 guint32 offset)
5830 {
5831 gboolean know_data = FALSE;
5832
5833 switch (subfunc) {
5834 case S7COMM_UD_SUBF_TIME_READ:
5835 case S7COMM_UD_SUBF_TIME_READF:
5836 if (type == S7COMM_UD_TYPE_RES) { /*** Response ***/
5837 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
5838 proto_item_append_text(data_tree, ": ");
5839 offset = s7comm_add_timestamp_to_tree(tvb, data_tree, offset, TRUE, TRUE);
5840 }
5841 know_data = TRUE;
5842 }
5843 break;
5844 case S7COMM_UD_SUBF_TIME_SET:
5845 case S7COMM_UD_SUBF_TIME_SET2:
5846 if (type == S7COMM_UD_TYPE_REQ) { /*** Request ***/
5847 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
5848 proto_item_append_text(data_tree, ": ");
5849 offset = s7comm_add_timestamp_to_tree(tvb, data_tree, offset, TRUE, TRUE);
5850 }
5851 know_data = TRUE;
5852 }
5853 break;
5854 default:
5855 break;
5856 }
5857
5858 if (know_data == FALSE && dlength > 0) {
5859 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
5860 offset += dlength;
5861 }
5862 return offset;
5863 }
5864
5865 /*******************************************************************************************************
5866 *
5867 * PDU Type: User Data -> Function group 3 -> block functions
5868 *
5869 *******************************************************************************************************/
5870 static guint32
s7comm_decode_ud_block_subfunc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * data_tree,guint8 type,guint8 subfunc,guint8 ret_val,guint8 tsize,guint32 dlength,guint32 offset)5871 s7comm_decode_ud_block_subfunc(tvbuff_t *tvb,
5872 packet_info *pinfo,
5873 proto_tree *data_tree,
5874 guint8 type, /* Type of data (request/response) */
5875 guint8 subfunc, /* Subfunction */
5876 guint8 ret_val, /* Return value in data part */
5877 guint8 tsize, /* transport size in data part */
5878 guint32 dlength,
5879 guint32 offset)
5880 {
5881 guint32 count;
5882 guint32 i;
5883 const guint8 *pBlocknumber;
5884 guint16 blocknumber;
5885 guint8 blocktype;
5886 guint16 blocktype16;
5887 gboolean know_data = FALSE;
5888 proto_item *item = NULL;
5889 proto_tree *item_tree = NULL;
5890 proto_item *itemadd = NULL;
5891 char str_timestamp[30];
5892 char str_version[10];
5893
5894 switch (subfunc) {
5895 /*************************************************
5896 * List blocks
5897 */
5898 case S7COMM_UD_SUBF_BLOCK_LIST:
5899 if (type == S7COMM_UD_TYPE_REQ) {
5900 /* Is this a possible combination? Never seen it... */
5901
5902 } else if (type == S7COMM_UD_TYPE_RES) {
5903 count = dlength / 4;
5904 for (i = 0; i < count; i++) {
5905 /* Insert a new tree of 4 byte length for every item */
5906 item = proto_tree_add_item(data_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
5907 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
5908 blocktype16 = tvb_get_ntohs(tvb, offset);
5909 proto_item_append_text(item, " [%d]: (Block type %s)", i+1, val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5910 itemadd = proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII|ENC_NA);
5911 proto_item_append_text(itemadd, " (%s)", val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5912 offset += 2;
5913 proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_cnt, tvb, offset, 2, ENC_BIG_ENDIAN);
5914 offset += 2;
5915 }
5916 know_data = TRUE;
5917 }
5918 break;
5919 /*************************************************
5920 * List blocks of type
5921 */
5922 case S7COMM_UD_SUBF_BLOCK_LISTTYPE:
5923 if (type == S7COMM_UD_TYPE_REQ) {
5924 if (tsize != S7COMM_DATA_TRANSPORT_SIZE_NULL) {
5925 blocktype16 = tvb_get_ntohs(tvb, offset);
5926 itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII|ENC_NA);
5927 proto_item_append_text(itemadd, " (%s)", val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5928 col_append_fstr(pinfo->cinfo, COL_INFO, " Type:[%s]",
5929 val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5930 proto_item_append_text(data_tree, ": (%s)",
5931 val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5932 offset += 2;
5933 }
5934 know_data = TRUE;
5935
5936 } else if (type == S7COMM_UD_TYPE_RES) {
5937 if (tsize != S7COMM_DATA_TRANSPORT_SIZE_NULL) {
5938 count = dlength / 4;
5939
5940 for (i = 0; i < count; i++) {
5941 /* Insert a new tree of 4 byte length for every item */
5942 item = proto_tree_add_item(data_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
5943 item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
5944
5945 proto_item_append_text(item, " [%d]: (Block number %d)", i+1, tvb_get_ntohs(tvb, offset));
5946 proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_num, tvb, offset, 2, ENC_BIG_ENDIAN);
5947 offset += 2;
5948 /* The first Byte is unknown, kind of flags? */
5949 proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
5950 offset += 1;
5951 proto_tree_add_item(item_tree, hf_s7comm_ud_blockinfo_block_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
5952 offset += 1;
5953 }
5954 }
5955 know_data = TRUE;
5956 }
5957 break;
5958 /*************************************************
5959 * Get block infos
5960 */
5961 case S7COMM_UD_SUBF_BLOCK_BLOCKINFO:
5962 if (type == S7COMM_UD_TYPE_REQ) {
5963 if (tsize != S7COMM_DATA_TRANSPORT_SIZE_NULL) {
5964 gint32 num = -1;
5965 gboolean num_valid;
5966 /* 8 Bytes of Data follow, 1./ 2. type, 3-7 blocknumber as ascii number */
5967 blocktype16 = tvb_get_ntohs(tvb, offset);
5968 itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII|ENC_NA);
5969 proto_item_append_text(itemadd, " (%s)", val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5970 offset += 2;
5971 proto_tree_add_item_ret_string(data_tree, hf_s7comm_ud_blockinfo_block_num_ascii, tvb, offset, 5, ENC_ASCII|ENC_NA, pinfo->pool, &pBlocknumber);
5972 num_valid = ws_strtoi32((const gchar*)pBlocknumber, NULL, &num);
5973 proto_item_append_text(data_tree, " [%s ",
5974 val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5975 col_append_fstr(pinfo->cinfo, COL_INFO, " -> Block:[%s ",
5976 val_to_str(blocktype16, blocktype_names, "Unknown Block type: 0x%04x"));
5977 if (num_valid) {
5978 proto_item_append_text(data_tree, "%d]", num);
5979 col_append_fstr(pinfo->cinfo, COL_INFO, "%d]", num);
5980 } else {
5981 expert_add_info(pinfo, data_tree, &ei_s7comm_ud_blockinfo_block_num_ascii_invalid);
5982 proto_item_append_text(data_tree, "NaN]");
5983 col_append_str(pinfo->cinfo, COL_INFO, "NaN]");
5984 }
5985 offset += 5;
5986 itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_filesys, tvb, offset, 1, ENC_ASCII|ENC_NA);
5987 proto_item_append_text(itemadd, " (%s)", val_to_str(tvb_get_guint8(tvb, offset), blocktype_attribute2_names, "Unknown filesys: %c"));
5988 offset += 1;
5989 }
5990 know_data = TRUE;
5991
5992 } else if (type == S7COMM_UD_TYPE_RES) {
5993 /* 78 Bytes */
5994 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
5995 itemadd = proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_type, tvb, offset, 2, ENC_ASCII|ENC_NA);
5996 proto_item_append_text(itemadd, " (%s)", val_to_str(tvb_get_ntohs(tvb, offset), blocktype_names, "Unknown Block type: 0x%04x"));
5997 offset += 2;
5998 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_infolength, tvb, offset, 2, ENC_BIG_ENDIAN);
5999 offset += 2;
6000 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_unknown2, tvb, offset, 2, ENC_BIG_ENDIAN);
6001 offset += 2;
6002 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_const3, tvb, offset, 2, ENC_ASCII|ENC_NA);
6003 offset += 2;
6004 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_unknown, tvb, offset, 1, ENC_NA);
6005 offset += 1;
6006 proto_tree_add_bitmask(data_tree, tvb, offset, hf_s7comm_userdata_blockinfo_flags,
6007 ett_s7comm_userdata_blockinfo_flags, s7comm_userdata_blockinfo_flags_fields, ENC_BIG_ENDIAN);
6008 offset += 1;
6009 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_block_lang, tvb, offset, 1, ENC_BIG_ENDIAN);
6010 offset += 1;
6011 blocktype = tvb_get_guint8(tvb, offset);
6012 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_subblk_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6013 offset += 1;
6014 blocknumber = tvb_get_ntohs(tvb, offset);
6015 proto_tree_add_uint(data_tree, hf_s7comm_ud_blockinfo_block_num, tvb, offset, 2, blocknumber);
6016 /* Add block type and number to info column */
6017 col_append_fstr(pinfo->cinfo, COL_INFO, " -> Block:[%s %d]",
6018 val_to_str(blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"),
6019 blocknumber);
6020 proto_item_append_text(data_tree, ": (Block:[%s %d])",
6021 val_to_str(blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"),
6022 blocknumber);
6023 offset += 2;
6024 /* "Length Load mem" -> the length in Step7 Manager seems to be this length +6 bytes */
6025 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_load_mem_len, tvb, offset, 4, ENC_BIG_ENDIAN);
6026 offset += 4;
6027 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_blocksecurity, tvb, offset, 4, ENC_BIG_ENDIAN);
6028 offset += 4;
6029 s7comm_get_timestring_from_s7time(tvb, offset, str_timestamp, sizeof(str_timestamp));
6030 proto_tree_add_string(data_tree, hf_s7comm_ud_blockinfo_code_timestamp, tvb, offset, 6, str_timestamp);
6031 offset += 6;
6032 s7comm_get_timestring_from_s7time(tvb, offset, str_timestamp, sizeof(str_timestamp));
6033 proto_tree_add_string(data_tree, hf_s7comm_ud_blockinfo_interface_timestamp, tvb, offset, 6, str_timestamp);
6034 offset += 6;
6035 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_ssb_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6036 offset += 2;
6037 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_add_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6038 offset += 2;
6039 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_localdata_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6040 offset += 2;
6041 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_mc7_len, tvb, offset, 2, ENC_BIG_ENDIAN);
6042 offset += 2;
6043 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_author, tvb, offset, 8, ENC_ASCII|ENC_NA);
6044 offset += 8;
6045 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_family, tvb, offset, 8, ENC_ASCII|ENC_NA);
6046 offset += 8;
6047 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_headername, tvb, offset, 8, ENC_ASCII|ENC_NA);
6048 offset += 8;
6049 g_snprintf(str_version, sizeof(str_version), "%d.%d", ((tvb_get_guint8(tvb, offset) & 0xf0) >> 4), tvb_get_guint8(tvb, offset) & 0x0f);
6050 proto_tree_add_string(data_tree, hf_s7comm_ud_blockinfo_headerversion, tvb, offset, 1, str_version);
6051 offset += 1;
6052 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_res_unknown, tvb, offset, 1, ENC_NA);
6053 offset += 1;
6054 proto_tree_add_checksum(data_tree, tvb, offset, hf_s7comm_ud_blockinfo_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
6055 offset += 2;
6056 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_reserved1, tvb, offset, 4, ENC_BIG_ENDIAN);
6057 offset += 4;
6058 proto_tree_add_item(data_tree, hf_s7comm_ud_blockinfo_reserved2, tvb, offset, 4, ENC_BIG_ENDIAN);
6059 offset += 4;
6060 }
6061 know_data = TRUE;
6062 }
6063 break;
6064 default:
6065 break;
6066 }
6067 if (know_data == FALSE && dlength > 0) {
6068 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
6069 offset += dlength;
6070 }
6071 return offset;
6072 }
6073
6074 /*******************************************************************************************************
6075 *
6076 * PDU Type: User Data -> Function group 2 -> Read record
6077 *
6078 *******************************************************************************************************/
6079 static guint32
s7comm_decode_ud_readrec(tvbuff_t * tvb,proto_tree * tree,guint8 type,guint32 offset)6080 s7comm_decode_ud_readrec(tvbuff_t *tvb,
6081 proto_tree *tree,
6082 guint8 type,
6083 guint32 offset)
6084 {
6085 guint32 ret_val;
6086 guint32 statuslen;
6087 guint32 reclen;
6088 guint8 item_count;
6089
6090 if (type == S7COMM_UD_TYPE_REQ) {
6091 proto_tree_add_item(tree, hf_s7comm_rdrec_reserved1, tvb, offset, 1, ENC_NA);
6092 offset += 1;
6093 /* Although here is an item_count field, values above 1 aren't allowed or at least never seen */
6094 item_count = tvb_get_guint8(tvb, offset);
6095 proto_tree_add_uint(tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6096 offset += 1;
6097 if (item_count > 0) {
6098 offset = s7comm_decode_param_item(tvb, offset, tree, 0);
6099 }
6100 } else if (type == S7COMM_UD_TYPE_RES) {
6101 /* The item with data is used for optional status code similar to the
6102 * STATUS output of SFB52 RDREC used in Plc code.
6103 */
6104 proto_tree_add_item(tree, hf_s7comm_rdrec_reserved1, tvb, offset, 1, ENC_NA);
6105 offset += 1;
6106 item_count = tvb_get_guint8(tvb, offset);
6107 proto_tree_add_uint(tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6108 offset += 1;
6109 /* As all testsubjects have shown that no more than one item is allowed,
6110 * we decode only the first item here.
6111 */
6112 if (item_count > 0) {
6113 proto_tree_add_item_ret_uint(tree, hf_s7comm_data_returncode, tvb, offset, 1, ENC_BIG_ENDIAN, &ret_val);
6114 offset += 1;
6115 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6116 proto_tree_add_item(tree, hf_s7comm_data_transport_size, tvb, offset, 1, ENC_BIG_ENDIAN);
6117 offset += 1;
6118 }
6119 proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_statuslen, tvb, offset, 1, ENC_BIG_ENDIAN, &statuslen);
6120 offset += 1;
6121 if (statuslen > 0) {
6122 proto_tree_add_item(tree, hf_s7comm_rdrec_statusdata, tvb, offset, statuslen, ENC_NA);
6123 offset += statuslen;
6124 } else {
6125 offset += 1; /* Fillbyte */
6126 }
6127 if (ret_val == S7COMM_ITEM_RETVAL_DATA_OK) {
6128 proto_tree_add_item_ret_uint(tree, hf_s7comm_rdrec_recordlen, tvb, offset, 2, ENC_BIG_ENDIAN, &reclen);
6129 offset += 2;
6130 if (reclen > 0) {
6131 proto_tree_add_item(tree, hf_s7comm_rdrec_data, tvb, offset, reclen, ENC_NA);
6132 offset += reclen;
6133 }
6134 }
6135 }
6136 }
6137 return offset;
6138 }
6139
6140 /*******************************************************************************************************
6141 *
6142 * PDU Type: User Data -> Function group 2 -> cyclic services
6143 *
6144 *******************************************************************************************************/
6145 static guint32
s7comm_decode_ud_cyclic_subfunc(tvbuff_t * tvb,packet_info * pinfo,guint8 seq_num,proto_tree * data_tree,guint8 type,guint8 subfunc,guint32 dlength,guint32 offset)6146 s7comm_decode_ud_cyclic_subfunc(tvbuff_t *tvb,
6147 packet_info *pinfo,
6148 guint8 seq_num,
6149 proto_tree *data_tree,
6150 guint8 type, /* Type of data (request/response) */
6151 guint8 subfunc, /* Subfunction */
6152 guint32 dlength,
6153 guint32 offset)
6154 {
6155 gboolean know_data = FALSE;
6156 guint32 offset_old;
6157 guint32 len_item;
6158 guint8 item_count;
6159 guint8 i;
6160 guint8 job_id;
6161
6162 switch (subfunc)
6163 {
6164 case S7COMM_UD_SUBF_CYCLIC_CHANGE_MOD:
6165 if (type == S7COMM_UD_TYPE_REQ) {
6166 col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", seq_num);
6167 }
6168 /* fall through */
6169 case S7COMM_UD_SUBF_CYCLIC_TRANSF:
6170 case S7COMM_UD_SUBF_CYCLIC_CHANGE:
6171 item_count = tvb_get_guint8(tvb, offset + 1); /* first byte reserved??? */
6172 proto_tree_add_uint(data_tree, hf_s7comm_param_itemcount, tvb, offset, 2, item_count);
6173 offset += 2;
6174 if (type == S7COMM_UD_TYPE_REQ) {
6175 proto_tree_add_item(data_tree, hf_s7comm_cycl_interval_timebase, tvb, offset, 1, ENC_BIG_ENDIAN);
6176 offset += 1;
6177 proto_tree_add_item(data_tree, hf_s7comm_cycl_interval_time, tvb, offset, 1, ENC_BIG_ENDIAN);
6178 offset += 1;
6179 for (i = 0; i < item_count; i++) {
6180 offset_old = offset;
6181 offset = s7comm_decode_param_item(tvb, offset, data_tree, i);
6182 /* if length is not a multiple of 2 and this is not the last item, then add a fill-byte */
6183 len_item = offset - offset_old;
6184 if ((len_item % 2) && (i < (item_count-1))) {
6185 offset += 1;
6186 }
6187 }
6188 } else if (type == S7COMM_UD_TYPE_RES || type == S7COMM_UD_TYPE_PUSH) {
6189 col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", seq_num);
6190 offset = s7comm_decode_response_read_data(tvb, data_tree, item_count, offset);
6191 }
6192 know_data = TRUE;
6193 break;
6194 case S7COMM_UD_SUBF_CYCLIC_UNSUBSCRIBE:
6195 if (type == S7COMM_UD_TYPE_REQ) {
6196 proto_tree_add_item(data_tree, hf_s7comm_cycl_function, tvb, offset, 1, ENC_BIG_ENDIAN);
6197 offset += 1;
6198 proto_tree_add_item(data_tree, hf_s7comm_cycl_jobid, tvb, offset, 1, ENC_BIG_ENDIAN);
6199 job_id = tvb_get_guint8(tvb, offset);
6200 col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", job_id);
6201 offset += 1;
6202 know_data = TRUE;
6203 } else if (type == S7COMM_UD_TYPE_RES) {
6204 col_append_fstr(pinfo->cinfo, COL_INFO, " JobID=%d", seq_num);
6205 }
6206 break;
6207 case S7COMM_UD_SUBF_CYCLIC_RDREC:
6208 offset = s7comm_decode_ud_readrec(tvb, data_tree, type, offset);
6209 know_data = TRUE;
6210 break;
6211 }
6212
6213 if (know_data == FALSE && dlength > 0) {
6214 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
6215 offset += dlength;
6216 }
6217 return offset;
6218 }
6219
6220 /*******************************************************************************************************
6221 *
6222 * PDU Type: User Data: Data part and reassembly
6223 *
6224 *******************************************************************************************************/
6225 static guint32
s7comm_decode_ud_data(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint16 dlength,guint8 type,guint8 funcgroup,guint8 subfunc,guint8 seq_num,guint8 data_unit_ref,guint8 last_data_unit,guint32 offset)6226 s7comm_decode_ud_data(tvbuff_t *tvb,
6227 packet_info *pinfo,
6228 proto_tree *tree,
6229 guint16 dlength,
6230 guint8 type,
6231 guint8 funcgroup,
6232 guint8 subfunc,
6233 guint8 seq_num,
6234 guint8 data_unit_ref,
6235 guint8 last_data_unit,
6236 guint32 offset)
6237 {
6238 proto_item *item = NULL;
6239 proto_tree *data_tree = NULL;
6240 guint8 tsize;
6241 guint16 len;
6242 guint8 ret_val;
6243 guint32 length_rem = 0;
6244 gboolean save_fragmented;
6245 guint32 frag_id = 0;
6246 gboolean more_frags = FALSE;
6247 gboolean is_fragmented = FALSE;
6248 tvbuff_t* new_tvb = NULL;
6249 tvbuff_t* next_tvb = NULL;
6250 fragment_head *fd_head;
6251 gchar str_fragadd[32];
6252
6253 /* The first 4 bytes of the data part of a userdata telegram are the same for all types.
6254 * This is also the minumum length of the data part.
6255 */
6256 if (dlength >= 4) {
6257 item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6258 data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6259
6260 ret_val = tvb_get_guint8(tvb, offset);
6261 proto_tree_add_uint(data_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
6262 offset += 1;
6263 /* Not definitely known part, kind of "transport size"? constant 0x09, 1 byte
6264 * The position is the same as in a data response/write telegram,
6265 */
6266 tsize = tvb_get_guint8(tvb, offset);
6267 proto_tree_add_uint(data_tree, hf_s7comm_data_transport_size, tvb, offset, 1, tsize);
6268 offset += 1;
6269 len = tvb_get_ntohs(tvb, offset);
6270 proto_tree_add_uint(data_tree, hf_s7comm_data_length, tvb, offset, 2, len);
6271 offset += 2;
6272
6273 if (len >= 2) {
6274 more_frags = (last_data_unit == S7COMM_UD_LASTDATAUNIT_NO);
6275 /* Some packets have an additional header before the payload, which must be
6276 * extracted from the data before reassembly.
6277 */
6278 switch (funcgroup) {
6279 case S7COMM_UD_FUNCGROUP_NCPRG:
6280 offset = s7comm_decode_ud_ncprg_pre_reass(tvb, data_tree, type, subfunc, &len, offset);
6281 /* Unfortunately on NC programming the first PDU is always shown as reassembled also when not fragmented,
6282 * because data_unit_ref may overflow and start again at 0 on big file transfers.
6283 */
6284 is_fragmented = TRUE;
6285 frag_id = seq_num;
6286 break;
6287 case S7COMM_UD_FUNCGROUP_PBC:
6288 /* The R_ID is used for fragment identification */
6289 offset = s7comm_decode_ud_pbc_pre_reass(tvb, pinfo, data_tree, type, &len, &frag_id, offset);
6290 is_fragmented = data_unit_ref > 0 || seq_num > 0;
6291 break;
6292 default:
6293 is_fragmented = (data_unit_ref > 0);
6294 frag_id = data_unit_ref;
6295 break;
6296 }
6297 /* Reassembly of fragmented data part */
6298 save_fragmented = pinfo->fragmented;
6299 if (is_fragmented) { /* fragmented */
6300 pinfo->fragmented = TRUE;
6301 /* NC programming uses a different method of fragment indication. The sequence number is used as reference-id,
6302 * the data unit reference number is increased with every packet, as the sender does not need to wait for
6303 * the acknowledge of the packet. Also different in NC programming is, that also when a packet is not
6304 * fragmented, data_unit_ref is > 0 and "reassembled" would be displayed even when not fragmented (count number of fragments?)
6305 * Using fragment number does not work here, as it's only one byte. And if there are more than 255 fragments this would fail.
6306 */
6307 fd_head = fragment_add_seq_next(&s7comm_reassembly_table,
6308 tvb, offset, pinfo,
6309 frag_id, /* ID for fragments belonging together */
6310 NULL, /* void *data */
6311 len, /* fragment length - to the end */
6312 more_frags); /* More fragments? */
6313 g_snprintf(str_fragadd, sizeof(str_fragadd), " id=%d", frag_id);
6314 new_tvb = process_reassembled_data(tvb, offset, pinfo,
6315 "Reassembled S7COMM", fd_head, &s7comm_frag_items,
6316 NULL, tree);
6317 if (new_tvb) { /* take it all */
6318 /* add reassembly info only when there's more than one fragment */
6319 if (fd_head && fd_head->next) {
6320 col_append_fstr(pinfo->cinfo, COL_INFO, " (S7COMM reassembled%s)", str_fragadd);
6321 proto_item_append_text(data_tree, " (S7COMM reassembled%s)", str_fragadd);
6322 }
6323 next_tvb = new_tvb;
6324 offset = 0;
6325 } else { /* make a new subset */
6326 next_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, -1);
6327 col_append_fstr(pinfo->cinfo, COL_INFO, " (S7COMM fragment%s)", str_fragadd);
6328 proto_item_append_text(data_tree, " (S7COMM fragment%s)", str_fragadd);
6329 offset = 0;
6330 }
6331 } else { /* Not fragmented */
6332 next_tvb = tvb;
6333 }
6334 pinfo->fragmented = save_fragmented;
6335 length_rem = tvb_reported_length_remaining(next_tvb, offset);
6336 /* TODO: PBC telegrams say "Last data unit = no" and data_unit_ref=0 and not fragmented */
6337 if (last_data_unit == S7COMM_UD_LASTDATAUNIT_YES && length_rem > 0) {
6338 switch (funcgroup) {
6339 case S7COMM_UD_FUNCGROUP_PROG:
6340 offset = s7comm_decode_ud_tis_subfunc(next_tvb, data_tree, type, subfunc, offset);
6341 break;
6342 case S7COMM_UD_FUNCGROUP_CYCLIC:
6343 offset = s7comm_decode_ud_cyclic_subfunc(next_tvb, pinfo, seq_num, data_tree, type, subfunc, length_rem, offset);
6344 break;
6345 case S7COMM_UD_FUNCGROUP_BLOCK:
6346 offset = s7comm_decode_ud_block_subfunc(next_tvb, pinfo, data_tree, type, subfunc, ret_val, tsize, length_rem, offset);
6347 break;
6348 case S7COMM_UD_FUNCGROUP_CPU:
6349 switch (subfunc) {
6350 case S7COMM_UD_SUBF_CPU_READSZL:
6351 offset = s7comm_decode_ud_cpu_szl_subfunc(next_tvb, pinfo, data_tree, type, ret_val, length_rem, offset);
6352 break;
6353 case S7COMM_UD_SUBF_CPU_NOTIFY_IND:
6354 case S7COMM_UD_SUBF_CPU_NOTIFY8_IND:
6355 case S7COMM_UD_SUBF_CPU_ALARMSQ_IND:
6356 case S7COMM_UD_SUBF_CPU_ALARMS_IND:
6357 case S7COMM_UD_SUBF_CPU_SCAN_IND:
6358 case S7COMM_UD_SUBF_CPU_ALARMACK:
6359 case S7COMM_UD_SUBF_CPU_ALARMACK_IND:
6360 case S7COMM_UD_SUBF_CPU_ALARM8_IND:
6361 case S7COMM_UD_SUBF_CPU_ALARM8LOCK:
6362 case S7COMM_UD_SUBF_CPU_ALARM8LOCK_IND:
6363 case S7COMM_UD_SUBF_CPU_ALARM8UNLOCK:
6364 case S7COMM_UD_SUBF_CPU_ALARM8UNLOCK_IND:
6365 offset = s7comm_decode_ud_cpu_alarm_main(next_tvb, pinfo, data_tree, type, subfunc, offset);
6366 break;
6367 case S7COMM_UD_SUBF_CPU_ALARMQUERY:
6368 if (type == S7COMM_UD_TYPE_RES) {
6369 offset = s7comm_decode_ud_cpu_alarm_query_response(next_tvb, data_tree, offset);
6370 } else {
6371 offset = s7comm_decode_ud_cpu_alarm_main(next_tvb, pinfo, data_tree, type, subfunc, offset);
6372 }
6373 break;
6374 case S7COMM_UD_SUBF_CPU_DIAGMSG:
6375 offset = s7comm_decode_ud_cpu_diagnostic_message(next_tvb, pinfo, TRUE, data_tree, offset);
6376 break;
6377 case S7COMM_UD_SUBF_CPU_MSGS:
6378 offset = s7comm_decode_message_service(next_tvb, pinfo, data_tree, type, length_rem, offset);
6379 break;
6380 default:
6381 /* print other currently unknown data as raw bytes */
6382 proto_tree_add_item(data_tree, hf_s7comm_userdata_data, next_tvb, offset, length_rem, ENC_NA);
6383 break;
6384 }
6385 break;
6386 case S7COMM_UD_FUNCGROUP_SEC:
6387 offset = s7comm_decode_ud_security_subfunc(next_tvb, data_tree, length_rem, offset);
6388 break;
6389 case S7COMM_UD_FUNCGROUP_PBC:
6390 offset = s7comm_decode_ud_pbc_subfunc(next_tvb, data_tree, length_rem, offset);
6391 break;
6392 case S7COMM_UD_FUNCGROUP_TIME:
6393 offset = s7comm_decode_ud_time_subfunc(next_tvb, data_tree, type, subfunc, ret_val, length_rem, offset);
6394 break;
6395 case S7COMM_UD_FUNCGROUP_NCPRG:
6396 offset = s7comm_decode_ud_ncprg_subfunc(next_tvb, pinfo, data_tree, type, subfunc, length_rem, offset);
6397 break;
6398 default:
6399 break;
6400 }
6401 }
6402 }
6403 }
6404 return offset;
6405 }
6406
6407 /*******************************************************************************************************
6408 *******************************************************************************************************
6409 *
6410 * PDU Type: User Data
6411 *
6412 *******************************************************************************************************
6413 *******************************************************************************************************/
6414 static guint32
s7comm_decode_ud(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint16 plength,guint16 dlength,guint32 offset)6415 s7comm_decode_ud(tvbuff_t *tvb,
6416 packet_info *pinfo,
6417 proto_tree *tree,
6418 guint16 plength,
6419 guint16 dlength,
6420 guint32 offset)
6421 {
6422 proto_item *item = NULL;
6423 proto_tree *param_tree = NULL;
6424
6425 guint32 errorcode;
6426 guint32 offset_temp;
6427 guint32 reqres2;
6428 guint8 type;
6429 guint8 funcgroup;
6430 guint8 subfunc;
6431 guint8 data_unit_ref = 0;
6432 guint8 last_data_unit = 0;
6433 guint8 seq_num;
6434
6435 /* Add parameter tree */
6436 item = proto_tree_add_item(tree, hf_s7comm_param, tvb, offset, plength, ENC_NA);
6437 param_tree = proto_item_add_subtree(item, ett_s7comm_param);
6438
6439 offset_temp = offset;
6440 /* 3 bytes constant head */
6441 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_head, tvb, offset_temp, 3, ENC_BIG_ENDIAN);
6442 offset_temp += 3;
6443 /* 1 byte length of following parameter (8 or 12 bytes) */
6444 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_len, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6445 offset_temp += 1;
6446 /* 1 byte indicating request/response again, but useful in Push telegrams*/
6447 proto_tree_add_item_ret_uint(param_tree, hf_s7comm_userdata_param_reqres2, tvb, offset_temp, 1, ENC_BIG_ENDIAN, &reqres2);
6448 offset_temp += 1;
6449 /* High nibble (following/request/response) */
6450 type = (tvb_get_guint8(tvb, offset_temp) & 0xf0) >> 4;
6451 funcgroup = (tvb_get_guint8(tvb, offset_temp) & 0x0f);
6452 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_type, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6453 if (type == S7COMM_UD_TYPE_PUSH || type == S7COMM_UD_TYPE_NCPUSH) {
6454 col_append_fstr(pinfo->cinfo, COL_INFO, " Function:[%s-%s] -> [%s]",
6455 val_to_str(type, userdata_type_names, "Unknown type: 0x%02x"),
6456 val_to_str(reqres2, userdata_reqres2_names, "Unknown method: 0x%02x"),
6457 val_to_str(funcgroup, userdata_functiongroup_names, "Unknown function: 0x%02x")
6458 );
6459 } else {
6460 col_append_fstr(pinfo->cinfo, COL_INFO, " Function:[%s] -> [%s]",
6461 val_to_str(type, userdata_type_names, "Unknown type: 0x%02x"),
6462 val_to_str(funcgroup, userdata_functiongroup_names, "Unknown function: 0x%02x")
6463 );
6464 }
6465 proto_item_append_text(param_tree, ": (%s)", val_to_str(type, userdata_type_names, "Unknown type: 0x%02x"));
6466 proto_item_append_text(param_tree, " ->(%s)", val_to_str(funcgroup, userdata_functiongroup_names, "Unknown function: 0x%02x"));
6467
6468 /* Low nibble function group */
6469 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_funcgroup, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6470 offset_temp += 1;
6471 /* 1 Byte subfunction */
6472 subfunc = tvb_get_guint8(tvb, offset_temp);
6473 switch (funcgroup){
6474 case S7COMM_UD_FUNCGROUP_PROG:
6475 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_prog, tvb, offset_temp, 1, subfunc);
6476 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6477 val_to_str(subfunc, userdata_prog_subfunc_names, "Unknown subfunc: 0x%02x"));
6478 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_prog_subfunc_names, "Unknown subfunc: 0x%02x"));
6479 break;
6480 case S7COMM_UD_FUNCGROUP_CYCLIC:
6481 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_cyclic, tvb, offset_temp, 1, subfunc);
6482 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6483 val_to_str(subfunc, userdata_cyclic_subfunc_names, "Unknown subfunc: 0x%02x"));
6484 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_cyclic_subfunc_names, "Unknown subfunc: 0x%02x"));
6485 break;
6486 case S7COMM_UD_FUNCGROUP_BLOCK:
6487 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_block, tvb, offset_temp, 1, subfunc);
6488 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6489 val_to_str(subfunc, userdata_block_subfunc_names, "Unknown subfunc: 0x%02x"));
6490 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_block_subfunc_names, "Unknown subfunc: 0x%02x"));
6491 break;
6492 case S7COMM_UD_FUNCGROUP_CPU:
6493 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_cpu, tvb, offset_temp, 1, subfunc);
6494 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6495 val_to_str(subfunc, userdata_cpu_subfunc_names, "Unknown subfunc: 0x%02x"));
6496 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_cpu_subfunc_names, "Unknown subfunc: 0x%02x"));
6497 break;
6498 case S7COMM_UD_FUNCGROUP_SEC:
6499 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_sec, tvb, offset_temp, 1, subfunc);
6500 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6501 val_to_str(subfunc, userdata_sec_subfunc_names, "Unknown subfunc: 0x%02x"));
6502 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_sec_subfunc_names, "Unknown subfunc: 0x%02x"));
6503 break;
6504 case S7COMM_UD_FUNCGROUP_TIME:
6505 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_time, tvb, offset_temp, 1, subfunc);
6506 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6507 val_to_str(subfunc, userdata_time_subfunc_names, "Unknown subfunc: 0x%02x"));
6508 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_time_subfunc_names, "Unknown subfunc: 0x%02x"));
6509 break;
6510 case S7COMM_UD_FUNCGROUP_MODETRANS:
6511 proto_tree_add_uint(param_tree, hf_s7comm_modetrans_param_subfunc, tvb, offset_temp, 1, subfunc);
6512 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6513 val_to_str(subfunc, modetrans_param_subfunc_names, "Unknown subfunc: 0x%02x"));
6514 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, modetrans_param_subfunc_names, "Unknown subfunc: 0x%02x"));
6515 break;
6516 case S7COMM_UD_FUNCGROUP_NCPRG:
6517 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc_ncprg, tvb, offset_temp, 1, subfunc);
6518 col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]",
6519 val_to_str(subfunc, userdata_ncprg_subfunc_names, "Unknown subfunc: 0x%02x"));
6520 proto_item_append_text(param_tree, " ->(%s)", val_to_str(subfunc, userdata_ncprg_subfunc_names, "Unknown subfunc: 0x%02x"));
6521 break;
6522 default:
6523 proto_tree_add_uint(param_tree, hf_s7comm_userdata_param_subfunc, tvb, offset_temp, 1, subfunc);
6524 break;
6525 }
6526 offset_temp += 1;
6527 /* 1 Byte sequence number */
6528 seq_num = tvb_get_guint8(tvb, offset_temp);
6529 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_seq_num, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6530 offset_temp += 1;
6531 if (plength >= 12) {
6532 /* 1 Byte data unit reference. If packet is fragmented, all packets with this number belong together */
6533 data_unit_ref = tvb_get_guint8(tvb, offset_temp);
6534 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_dataunitref, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6535 offset_temp += 1;
6536 /* 1 Byte fragmented flag, if this is not the last data unit (telegram is fragmented) this is != 0 */
6537 last_data_unit = tvb_get_guint8(tvb, offset_temp);
6538 proto_tree_add_item(param_tree, hf_s7comm_userdata_param_dataunit, tvb, offset_temp, 1, ENC_BIG_ENDIAN);
6539 offset_temp += 1;
6540 proto_tree_add_item_ret_uint(param_tree, hf_s7comm_param_errcod, tvb, offset_temp, 2, ENC_BIG_ENDIAN, &errorcode);
6541 if (errorcode > 0) {
6542 col_append_fstr(pinfo->cinfo, COL_INFO, " -> Errorcode:[0x%04x]", errorcode);
6543 }
6544 }
6545 offset += plength;
6546
6547 offset = s7comm_decode_ud_data(tvb, pinfo, tree, dlength, type, funcgroup, subfunc, seq_num, data_unit_ref, last_data_unit, offset);
6548
6549 return offset;
6550 }
6551
6552 /*******************************************************************************************************
6553 *
6554 * PDU Type: Request or Response
6555 *
6556 *******************************************************************************************************/
6557 static guint32
s7comm_decode_req_resp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint16 plength,guint16 dlength,guint32 offset,guint8 rosctr)6558 s7comm_decode_req_resp(tvbuff_t *tvb,
6559 packet_info *pinfo,
6560 proto_tree *tree,
6561 guint16 plength,
6562 guint16 dlength,
6563 guint32 offset,
6564 guint8 rosctr)
6565 {
6566 proto_item *item = NULL;
6567 proto_tree *param_tree = NULL;
6568 proto_tree *data_tree = NULL;
6569 guint8 function = 0;
6570 guint8 item_count = 0;
6571 guint8 i;
6572 guint32 offset_old;
6573 guint32 len;
6574
6575 if (plength > 0) {
6576 /* Add parameter tree */
6577 item = proto_tree_add_item(tree, hf_s7comm_param, tvb, offset, plength, ENC_NA);
6578 param_tree = proto_item_add_subtree(item, ett_s7comm_param);
6579 /* Analyze function */
6580 function = tvb_get_guint8(tvb, offset);
6581 /* add param.function to info column */
6582 col_append_fstr(pinfo->cinfo, COL_INFO, " Function:[%s]", val_to_str(function, param_functionnames, "Unknown function: 0x%02x"));
6583 proto_tree_add_uint(param_tree, hf_s7comm_param_service, tvb, offset, 1, function);
6584 /* show param.function code at the tree */
6585 proto_item_append_text(param_tree, ": (%s)", val_to_str(function, param_functionnames, "Unknown function: 0x%02x"));
6586 offset += 1;
6587
6588 if (rosctr == S7COMM_ROSCTR_JOB) {
6589 switch (function){
6590 case S7COMM_SERV_READVAR:
6591 case S7COMM_SERV_WRITEVAR:
6592 item_count = tvb_get_guint8(tvb, offset);
6593 proto_tree_add_uint(param_tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6594 offset += 1;
6595 /* parse item data */
6596 for (i = 0; i < item_count; i++) {
6597 offset_old = offset;
6598 offset = s7comm_decode_param_item(tvb, offset, param_tree, i);
6599 /* if length is not a multiple of 2 and this is not the last item, then add a fill-byte */
6600 len = offset - offset_old;
6601 if ((len % 2) && (i < (item_count-1))) {
6602 offset += 1;
6603 }
6604 }
6605 /* in write-function there is a data part */
6606 if ((function == S7COMM_SERV_WRITEVAR) && (dlength > 0)) {
6607 item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6608 data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6609 /* Add returned data to data-tree */
6610 offset = s7comm_decode_response_read_data(tvb, data_tree, item_count, offset);
6611 }
6612 break;
6613 case S7COMM_SERV_SETUPCOMM:
6614 offset = s7comm_decode_pdu_setup_communication(tvb, param_tree, offset);
6615 break;
6616 /* Special functions */
6617 case S7COMM_FUNCREQUESTDOWNLOAD:
6618 case S7COMM_FUNCDOWNLOADBLOCK:
6619 case S7COMM_FUNCDOWNLOADENDED:
6620 case S7COMM_FUNCSTARTUPLOAD:
6621 case S7COMM_FUNCUPLOAD:
6622 case S7COMM_FUNCENDUPLOAD:
6623 offset = s7comm_decode_plc_controls_updownload(tvb, pinfo, tree, param_tree, plength, dlength, offset -1, rosctr);
6624 break;
6625 case S7COMM_FUNCPISERVICE:
6626 offset = s7comm_decode_pi_service(tvb, pinfo, param_tree, plength, offset -1);
6627 break;
6628 case S7COMM_FUNC_PLC_STOP:
6629 offset = s7comm_decode_plc_controls_param_hex29(tvb, param_tree, offset -1);
6630 break;
6631
6632 default:
6633 /* Print unknown part as raw bytes */
6634 if (plength > 1) {
6635 proto_tree_add_item(param_tree, hf_s7comm_param_data, tvb, offset, plength - 1, ENC_NA);
6636 }
6637 offset += plength - 1; /* 1 byte function code */
6638 if (dlength > 0) {
6639 /* Add data tree
6640 * First 2 bytes in data seem to be a length indicator of (dlength -4 ), so next 2 bytes
6641 * seem to indicate something else. But I'm not sure, so leave it as it is.....
6642 */
6643 item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6644 data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6645 proto_tree_add_item(data_tree, hf_s7comm_readresponse_data, tvb, offset, dlength, ENC_NA);
6646 offset += dlength;
6647 }
6648 break;
6649 }
6650 } else if (rosctr == S7COMM_ROSCTR_ACK_DATA) {
6651 switch (function){
6652 case S7COMM_SERV_READVAR:
6653 case S7COMM_SERV_WRITEVAR:
6654 /* This is a read-response, so the requested data may follow when address in request was ok */
6655 item_count = tvb_get_guint8(tvb, offset);
6656 proto_tree_add_uint(param_tree, hf_s7comm_param_itemcount, tvb, offset, 1, item_count);
6657 offset += 1;
6658 /* Add data tree */
6659 item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6660 data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6661 /* Add returned data to data-tree */
6662 if ((function == S7COMM_SERV_READVAR) && (dlength > 0)) {
6663 offset = s7comm_decode_response_read_data(tvb, data_tree, item_count, offset);
6664 } else if ((function == S7COMM_SERV_WRITEVAR) && (dlength > 0)) {
6665 offset = s7comm_decode_response_write_data(tvb, data_tree, item_count, offset);
6666 }
6667 break;
6668 case S7COMM_SERV_SETUPCOMM:
6669 offset = s7comm_decode_pdu_setup_communication(tvb, param_tree, offset);
6670 break;
6671 case S7COMM_FUNCREQUESTDOWNLOAD:
6672 case S7COMM_FUNCDOWNLOADBLOCK:
6673 case S7COMM_FUNCDOWNLOADENDED:
6674 case S7COMM_FUNCSTARTUPLOAD:
6675 case S7COMM_FUNCUPLOAD:
6676 case S7COMM_FUNCENDUPLOAD:
6677 offset = s7comm_decode_plc_controls_updownload(tvb, pinfo, tree, param_tree, plength, dlength, offset -1, rosctr);
6678 break;
6679 case S7COMM_FUNCPISERVICE:
6680 if (plength >= 2) {
6681 proto_tree_add_bitmask(param_tree, tvb, offset, hf_s7comm_data_blockcontrol_functionstatus,
6682 ett_s7comm_data_blockcontrol_status, s7comm_data_blockcontrol_status_fields, ENC_BIG_ENDIAN);
6683 offset += 1;
6684 }
6685 break;
6686 default:
6687 /* Print unknown part as raw bytes */
6688 if (plength > 1) {
6689 proto_tree_add_item(param_tree, hf_s7comm_param_data, tvb, offset, plength - 1, ENC_NA);
6690 }
6691 offset += plength - 1; /* 1 byte function code */
6692 if (dlength > 0) {
6693 /* Add data tree
6694 * First 2 bytes in data seem to be a length indicator of (dlength -4 ), so next 2 bytes
6695 * seem to indicate something else. But I'm not sure, so leave it as it is.....
6696 */
6697 item = proto_tree_add_item(tree, hf_s7comm_data, tvb, offset, dlength, ENC_NA);
6698 data_tree = proto_item_add_subtree(item, ett_s7comm_data);
6699 proto_tree_add_item(data_tree, hf_s7comm_readresponse_data, tvb, offset, dlength, ENC_NA);
6700 offset += dlength;
6701 }
6702 break;
6703 }
6704 }
6705 }
6706 return offset;
6707 }
6708
6709 /*******************************************************************************************************
6710 *******************************************************************************************************
6711 *
6712 * S7-Protocol (main tree)
6713 *
6714 *******************************************************************************************************
6715 *******************************************************************************************************/
6716 static gboolean
dissect_s7comm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)6717 dissect_s7comm(tvbuff_t *tvb,
6718 packet_info *pinfo,
6719 proto_tree *tree,
6720 void *data _U_)
6721 {
6722 proto_item *s7comm_item = NULL;
6723 proto_item *s7comm_sub_item = NULL;
6724 proto_tree *s7comm_tree = NULL;
6725 proto_tree *s7comm_header_tree = NULL;
6726
6727 guint32 offset = 0;
6728
6729 guint8 rosctr = 0;
6730 guint8 hlength = 10; /* Header 10 Bytes, when type 2 or 3 (Response) -> 12 Bytes */
6731 guint16 plength = 0;
6732 guint16 dlength = 0;
6733 guint16 errorcode = 0;
6734
6735 /*----------------- Heuristic Checks - Begin */
6736 /* 1) check for minimum length */
6737 if(tvb_captured_length(tvb) < S7COMM_MIN_TELEGRAM_LENGTH)
6738 return FALSE;
6739 /* 2) first byte must be 0x32 */
6740 if (tvb_get_guint8(tvb, 0) != S7COMM_PROT_ID)
6741 return FALSE;
6742 /* 3) second byte is a type field and only can contain values between 0x01-0x07 (1/2/3/7) */
6743 if (tvb_get_guint8(tvb, 1) < 0x01 || tvb_get_guint8(tvb, 1) > 0x07)
6744 return FALSE;
6745 /*----------------- Heuristic Checks - End */
6746
6747 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_S7COMM);
6748 col_clear(pinfo->cinfo, COL_INFO);
6749 col_append_sep_str(pinfo->cinfo, COL_INFO, " | ", "");
6750
6751 rosctr = tvb_get_guint8(tvb, 1); /* Get the type byte */
6752 if (rosctr == 2 || rosctr == 3) hlength = 12; /* Header 10 Bytes, when type 2 or 3 (response) -> 12 Bytes */
6753
6754 /* display some infos in info-column of wireshark */
6755 col_append_fstr(pinfo->cinfo, COL_INFO, "ROSCTR:[%-8s]", val_to_str(rosctr, rosctr_names, "Unknown: 0x%02x"));
6756
6757 s7comm_item = proto_tree_add_item(tree, proto_s7comm, tvb, 0, -1, ENC_NA);
6758 s7comm_tree = proto_item_add_subtree(s7comm_item, ett_s7comm);
6759
6760 /* insert header tree */
6761 s7comm_sub_item = proto_tree_add_item(s7comm_tree, hf_s7comm_header,
6762 tvb, offset, hlength, ENC_NA);
6763
6764 /* insert sub-items in header tree */
6765 s7comm_header_tree = proto_item_add_subtree(s7comm_sub_item, ett_s7comm_header);
6766
6767 /* Protocol Identifier, constant 0x32 */
6768 proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_protid, tvb, offset, 1, ENC_BIG_ENDIAN);
6769 offset += 1;
6770
6771 /* ROSCTR (Remote Operating Service Control) - PDU Type */
6772 proto_tree_add_uint(s7comm_header_tree, hf_s7comm_header_rosctr, tvb, offset, 1, rosctr);
6773 /* Show pdu type beside the header tree */
6774 proto_item_append_text(s7comm_header_tree, ": (%s)", val_to_str(rosctr, rosctr_names, "Unknown ROSCTR: 0x%02x"));
6775 offset += 1;
6776 /* Redundancy ID, reserved */
6777 proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_redid, tvb, offset, 2, ENC_BIG_ENDIAN);
6778 offset += 2;
6779 /* Protocol Data Unit Reference */
6780 proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_pduref, tvb, offset, 2, ENC_BIG_ENDIAN);
6781 offset += 2;
6782 /* Parameter length */
6783 plength = tvb_get_ntohs(tvb, offset);
6784 proto_tree_add_uint(s7comm_header_tree, hf_s7comm_header_parlg, tvb, offset, 2, plength);
6785 offset += 2;
6786 /* Data length */
6787 dlength = tvb_get_ntohs(tvb, offset);
6788 proto_tree_add_uint(s7comm_header_tree, hf_s7comm_header_datlg, tvb, offset, 2, dlength);
6789 offset += 2;
6790 /* when type is 2 or 3 there are 2 bytes with errorclass and errorcode */
6791 if (hlength == 12) {
6792 errorcode = tvb_get_ntohs(tvb, offset); /* this uses the same errorcodes (combined) from parameter part */
6793 proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_errcls, tvb, offset, 1, ENC_BIG_ENDIAN);
6794 offset += 1;
6795 proto_tree_add_item(s7comm_header_tree, hf_s7comm_header_errcod, tvb, offset, 1, ENC_BIG_ENDIAN);
6796 offset += 1;
6797 /* when there is an error, use the errorcode from parameterpart*/
6798 if (errorcode > 0) {
6799 s7comm_item = proto_tree_add_item(s7comm_header_tree, hf_s7comm_param_errcod, tvb, offset-2, 2, ENC_BIG_ENDIAN);
6800 proto_item_set_generated (s7comm_item);
6801 }
6802 }
6803
6804 switch (rosctr) {
6805 case S7COMM_ROSCTR_JOB:
6806 case S7COMM_ROSCTR_ACK_DATA:
6807 s7comm_decode_req_resp(tvb, pinfo, s7comm_tree, plength, dlength, offset, rosctr);
6808 break;
6809 case S7COMM_ROSCTR_USERDATA:
6810 s7comm_decode_ud(tvb, pinfo, s7comm_tree, plength, dlength, offset);
6811 break;
6812 }
6813 /* Add the errorcode from header as last entry in info column */
6814 if (errorcode > 0) {
6815 col_append_fstr(pinfo->cinfo, COL_INFO, " -> Errorcode:[0x%04x]", errorcode);
6816 }
6817 /* set fence as there may be more than one S7comm PDU in one frame */
6818 col_set_fence(pinfo->cinfo, COL_INFO);
6819 return TRUE;
6820 }
6821
6822 /*******************************************************************************************************
6823 * Reassembly of S7COMM
6824 *******************************************************************************************************/
6825 static void
s7comm_defragment_init(void)6826 s7comm_defragment_init(void)
6827 {
6828 reassembly_table_init(&s7comm_reassembly_table,
6829 &addresses_ports_reassembly_table_functions);
6830 }
6831
6832 /*******************************************************************************************************
6833 *******************************************************************************************************/
6834 void
proto_register_s7comm(void)6835 proto_register_s7comm (void)
6836 {
6837 expert_module_t* expert_s7comm;
6838
6839 /* format:
6840 * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
6841 */
6842 static hf_register_info hf[] = {
6843 { &hf_s7comm_header,
6844 { "Header", "s7comm.header", FT_NONE, BASE_NONE, NULL, 0x0,
6845 "This is the header of S7 communication", HFILL }},
6846 { &hf_s7comm_header_protid,
6847 { "Protocol Id", "s7comm.header.protid", FT_UINT8, BASE_HEX, NULL, 0x0,
6848 "Protocol Identification, 0x32 for S7", HFILL }},
6849 { &hf_s7comm_header_rosctr,
6850 { "ROSCTR", "s7comm.header.rosctr", FT_UINT8, BASE_DEC, VALS(rosctr_names), 0x0,
6851 "Remote Operating Service Control", HFILL }},
6852 { &hf_s7comm_header_redid,
6853 { "Redundancy Identification (Reserved)", "s7comm.header.redid", FT_UINT16, BASE_HEX, NULL, 0x0,
6854 "Redundancy Identification (Reserved), should be always 0x0000", HFILL }},
6855 { &hf_s7comm_header_pduref,
6856 { "Protocol Data Unit Reference", "s7comm.header.pduref", FT_UINT16, BASE_DEC, NULL, 0x0,
6857 NULL, HFILL }},
6858 { &hf_s7comm_header_parlg,
6859 { "Parameter length", "s7comm.header.parlg", FT_UINT16, BASE_DEC, NULL, 0x0,
6860 "Specifies the entire length of the parameter block in bytes", HFILL }},
6861 { &hf_s7comm_header_datlg,
6862 { "Data length", "s7comm.header.datlg", FT_UINT16, BASE_DEC, NULL, 0x0,
6863 "Specifies the entire length of the data block in bytes", HFILL }},
6864 { &hf_s7comm_header_errcls,
6865 { "Error class", "s7comm.header.errcls", FT_UINT8, BASE_HEX, VALS(errcls_names), 0x0,
6866 NULL, HFILL }},
6867 { &hf_s7comm_header_errcod,
6868 { "Error code", "s7comm.header.errcod", FT_UINT8, BASE_HEX, NULL, 0x0,
6869 NULL, HFILL }},
6870
6871 { &hf_s7comm_param,
6872 { "Parameter", "s7comm.param", FT_NONE, BASE_NONE, NULL, 0x0,
6873 "This is the parameter part of S7 communication", HFILL }},
6874 { &hf_s7comm_param_errcod,
6875 { "Error code", "s7comm.param.errcod", FT_UINT16, BASE_HEX | BASE_EXT_STRING, ¶m_errcode_names_ext, 0x0,
6876 NULL, HFILL }},
6877 { &hf_s7comm_param_service,
6878 { "Function", "s7comm.param.func", FT_UINT8, BASE_HEX, VALS(param_functionnames), 0x0,
6879 "Indicates the function of parameter/data", HFILL }},
6880 { &hf_s7comm_param_maxamq_calling,
6881 { "Max AmQ (parallel jobs with ack) calling", "s7comm.param.maxamq_calling", FT_UINT16, BASE_DEC, NULL, 0x0,
6882 NULL, HFILL }},
6883 { &hf_s7comm_param_maxamq_called,
6884 { "Max AmQ (parallel jobs with ack) called", "s7comm.param.maxamq_called", FT_UINT16, BASE_DEC, NULL, 0x0,
6885 NULL, HFILL }},
6886 { &hf_s7comm_param_setup_reserved1,
6887 { "Reserved", "s7comm.param.setup_reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
6888 NULL, HFILL }},
6889 { &hf_s7comm_param_neg_pdu_length,
6890 { "PDU length", "s7comm.param.pdu_length", FT_UINT16, BASE_DEC, NULL, 0x0,
6891 "Negotiated PDU length", HFILL }},
6892 { &hf_s7comm_param_itemcount,
6893 { "Item count", "s7comm.param.itemcount", FT_UINT8, BASE_DEC, NULL, 0x0,
6894 "Number of Items in parameter/data part", HFILL }},
6895 { &hf_s7comm_param_data,
6896 { "Parameter data", "s7comm.param.data", FT_BYTES, BASE_NONE, NULL, 0x0,
6897 NULL, HFILL }},
6898 { &hf_s7comm_param_item,
6899 { "Item", "s7comm.param.item", FT_NONE, BASE_NONE, NULL, 0x0,
6900 NULL, HFILL }},
6901 { &hf_s7comm_param_subitem,
6902 { "Subitem", "s7comm.param.subitem", FT_NONE, BASE_NONE, NULL, 0x0,
6903 NULL, HFILL }},
6904 { &hf_s7comm_item_varspec,
6905 { "Variable specification", "s7comm.param.item.varspec", FT_UINT8, BASE_HEX, NULL, 0x0,
6906 NULL, HFILL }},
6907 { &hf_s7comm_item_varspec_length,
6908 { "Length of following address specification", "s7comm.param.item.varspec_length", FT_UINT8, BASE_DEC, NULL, 0x0,
6909 NULL, HFILL }},
6910 { &hf_s7comm_item_syntax_id,
6911 { "Syntax Id", "s7comm.param.item.syntaxid", FT_UINT8, BASE_HEX, VALS(item_syntaxid_names), 0x0,
6912 "Syntax Id, format type of following address specification", HFILL }},
6913 { &hf_s7comm_item_transport_size,
6914 { "Transport size", "s7comm.param.item.transp_size", FT_UINT8, BASE_DEC, VALS(item_transportsizenames), 0x0,
6915 NULL, HFILL }},
6916 { &hf_s7comm_item_length,
6917 { "Length", "s7comm.param.item.length", FT_UINT16, BASE_DEC, NULL, 0x0,
6918 NULL, HFILL }},
6919 { &hf_s7comm_item_db,
6920 { "DB number", "s7comm.param.item.db", FT_UINT16, BASE_DEC, NULL, 0x0,
6921 NULL, HFILL }},
6922 { &hf_s7comm_item_area,
6923 { "Area", "s7comm.param.item.area", FT_UINT8, BASE_HEX, VALS(item_areanames), 0x0,
6924 NULL, HFILL }},
6925 { &hf_s7comm_item_address,
6926 { "Address", "s7comm.param.item.address", FT_UINT24, BASE_HEX, NULL, 0x0,
6927 NULL, HFILL }},
6928 { &hf_s7comm_item_address_byte,
6929 { "Byte Address", "s7comm.param.item.address.byte", FT_UINT24, BASE_DEC, NULL, 0x7fff8,
6930 NULL, HFILL }},
6931 { &hf_s7comm_item_address_bit,
6932 { "Bit Address", "s7comm.param.item.address.bit", FT_UINT24, BASE_DEC, NULL, 0x000007,
6933 NULL, HFILL }},
6934 { &hf_s7comm_item_address_nr,
6935 { "Number (T/C/BLOCK)", "s7comm.param.item.address.number", FT_UINT24, BASE_DEC, NULL, 0x00ffff,
6936 NULL, HFILL }},
6937 /* Special variable read with Syntax-Id 0xb0 (DBREAD) */
6938 { &hf_s7comm_item_dbread_numareas,
6939 { "Number of areas", "s7comm.param.item.dbread.numareas", FT_UINT8, BASE_DEC, NULL, 0x0,
6940 "Number of area specifications following", HFILL }},
6941 { &hf_s7comm_item_dbread_length,
6942 { "Bytes to read", "s7comm.param.item.dbread.length", FT_UINT8, BASE_DEC, NULL, 0x0,
6943 "Number of bytes to read", HFILL }},
6944 { &hf_s7comm_item_dbread_db,
6945 { "DB number", "s7comm.param.item.dbread.db", FT_UINT16, BASE_DEC, NULL, 0x0,
6946 NULL, HFILL }},
6947 { &hf_s7comm_item_dbread_startadr,
6948 { "Start address", "s7comm.param.item.dbread.startaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
6949 NULL, HFILL }},
6950 /* Reading frequency inverter parameters via routing */
6951 { &hf_s7comm_item_driveesany_unknown1,
6952 { "DriveES Unknown 1", "s7comm.param.item.driveesany.unknown1", FT_UINT8, BASE_DEC, NULL, 0x0,
6953 NULL, HFILL }},
6954 { &hf_s7comm_item_driveesany_unknown2,
6955 { "DriveES Unknown 2", "s7comm.param.item.driveesany.unknown2", FT_UINT16, BASE_DEC, NULL, 0x0,
6956 NULL, HFILL }},
6957 { &hf_s7comm_item_driveesany_unknown3,
6958 { "DriveES Unknown 3", "s7comm.param.item.driveesany.unknown3", FT_UINT16, BASE_HEX, NULL, 0x0,
6959 NULL, HFILL }},
6960 { &hf_s7comm_item_driveesany_parameter_nr,
6961 { "DriveES Parameter number", "s7comm.param.item.driveesany.parameternr", FT_UINT16, BASE_DEC, NULL, 0x0,
6962 NULL, HFILL }},
6963 { &hf_s7comm_item_driveesany_parameter_idx,
6964 { "DriveES Parameter index", "s7comm.param.item.driveesany.parameteridx", FT_UINT16, BASE_DEC, NULL, 0x0,
6965 NULL, HFILL }},
6966 /* NCK access with Syntax-Id 0x82 */
6967 { &hf_s7comm_item_nck_areaunit,
6968 { "NCK Area/Unit", "s7comm.param.item.nck.area_unit", FT_UINT8, BASE_HEX, NULL, 0x0,
6969 "NCK Area/Unit: Bitmask aaauuuuu: a=area, u=unit", HFILL }},
6970 { &hf_s7comm_item_nck_area,
6971 { "NCK Area", "s7comm.param.item.nck.area", FT_UINT8, BASE_DEC, VALS(nck_area_names), 0xe0,
6972 NULL, HFILL }},
6973 { &hf_s7comm_item_nck_unit,
6974 { "NCK Unit", "s7comm.param.item.nck.unit", FT_UINT8, BASE_DEC, NULL, 0x1f,
6975 NULL, HFILL }},
6976 { &hf_s7comm_item_nck_column,
6977 { "NCK Column number", "s7comm.param.item.nck.column", FT_UINT16, BASE_DEC, NULL, 0x0,
6978 NULL, HFILL }},
6979 { &hf_s7comm_item_nck_line,
6980 { "NCK Line number", "s7comm.param.item.nck.line", FT_UINT16, BASE_DEC, NULL, 0x0,
6981 NULL, HFILL }},
6982 { &hf_s7comm_item_nck_module,
6983 { "NCK Module", "s7comm.param.item.nck.module", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &nck_module_names_ext, 0x0,
6984 NULL, HFILL }},
6985 { &hf_s7comm_item_nck_linecount,
6986 { "NCK Linecount", "s7comm.param.item.nck.linecount", FT_UINT8, BASE_DEC, NULL, 0x0,
6987 NULL, HFILL }},
6988
6989 { &hf_s7comm_data,
6990 { "Data", "s7comm.data", FT_NONE, BASE_NONE, NULL, 0x0,
6991 "This is the data part of S7 communication", HFILL }},
6992 { &hf_s7comm_data_returncode,
6993 { "Return code", "s7comm.data.returncode", FT_UINT8, BASE_HEX, VALS(s7comm_item_return_valuenames), 0x0,
6994 NULL, HFILL }},
6995 { &hf_s7comm_data_transport_size,
6996 { "Transport size", "s7comm.data.transportsize", FT_UINT8, BASE_HEX, VALS(data_transportsizenames), 0x0,
6997 "Data type / Transport size. If 3, 4 or 5 the following length gives the number of bits, otherwise the number of bytes.", HFILL }},
6998 { &hf_s7comm_data_length,
6999 { "Length", "s7comm.data.length", FT_UINT16, BASE_DEC, NULL, 0x0,
7000 "Length of data", HFILL }},
7001
7002 { &hf_s7comm_data_item,
7003 { "Item", "s7comm.data.item", FT_NONE, BASE_NONE, NULL, 0x0,
7004 NULL, HFILL }},
7005
7006 { &hf_s7comm_readresponse_data,
7007 { "Data", "s7comm.resp.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7008 NULL, HFILL }},
7009 { &hf_s7comm_data_fillbyte,
7010 { "Fill byte", "s7comm.data.fillbyte", FT_UINT8, BASE_HEX, NULL, 0x0,
7011 NULL, HFILL }},
7012
7013 { &hf_s7comm_userdata_data,
7014 { "Data", "s7comm.data.userdata", FT_BYTES, BASE_NONE, NULL, 0x0,
7015 "Userdata data", HFILL }},
7016
7017 /* Userdata parameter 8/12 Bytes len*/
7018 { &hf_s7comm_userdata_param_head,
7019 { "Parameter head", "s7comm.param.userdata.head", FT_UINT24, BASE_HEX, NULL, 0x0,
7020 "Header before parameter (constant 0x000112)", HFILL }},
7021 { &hf_s7comm_userdata_param_len,
7022 { "Parameter length", "s7comm.param.userdata.length", FT_UINT8, BASE_DEC, NULL, 0x0,
7023 "Length of following parameter data (without head)", HFILL }},
7024 { &hf_s7comm_userdata_param_reqres2,
7025 { "Method (Request/Response)", "s7comm.param.userdata.reqres1", FT_UINT8, BASE_HEX, VALS(userdata_reqres2_names), 0x0,
7026 "Unknown part, second request/response (0x00, 0x11, 0x12)", HFILL }},
7027
7028 { &hf_s7comm_userdata_param_type,
7029 { "Type", "s7comm.param.userdata.type", FT_UINT8, BASE_DEC, VALS(userdata_type_names), 0xf0,
7030 "Type of parameter", HFILL }},
7031
7032 { &hf_s7comm_userdata_param_funcgroup,
7033 { "Function group", "s7comm.param.userdata.funcgroup", FT_UINT8, BASE_DEC, VALS(userdata_functiongroup_names), 0x0f,
7034 NULL, HFILL }},
7035
7036 { &hf_s7comm_userdata_param_subfunc_prog,
7037 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_prog_subfunc_names), 0x0,
7038 NULL, HFILL }},
7039 { &hf_s7comm_userdata_param_subfunc_cyclic,
7040 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_cyclic_subfunc_names), 0x0,
7041 NULL, HFILL }},
7042 { &hf_s7comm_userdata_param_subfunc_block,
7043 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_block_subfunc_names), 0x0,
7044 NULL, HFILL }},
7045 { &hf_s7comm_userdata_param_subfunc_cpu,
7046 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_cpu_subfunc_names), 0x0,
7047 NULL, HFILL }},
7048 { &hf_s7comm_userdata_param_subfunc_sec,
7049 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_sec_subfunc_names), 0x0,
7050 NULL, HFILL }},
7051 { &hf_s7comm_userdata_param_subfunc_time,
7052 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_time_subfunc_names), 0x0,
7053 NULL, HFILL }},
7054 { &hf_s7comm_userdata_param_subfunc,
7055 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0,
7056 NULL, HFILL }},
7057 { &hf_s7comm_userdata_param_subfunc_ncprg,
7058 { "Subfunction", "s7comm.param.userdata.subfunc", FT_UINT8, BASE_DEC, VALS(userdata_ncprg_subfunc_names), 0x0,
7059 NULL, HFILL }},
7060
7061 { &hf_s7comm_userdata_param_seq_num,
7062 { "Sequence number", "s7comm.param.userdata.seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7063 NULL, HFILL }},
7064
7065 { &hf_s7comm_userdata_param_dataunitref,
7066 { "Data unit reference number", "s7comm.param.userdata.dataunitref", FT_UINT8, BASE_DEC, NULL, 0x0,
7067 "Data unit reference number if PDU is fragmented", HFILL }},
7068
7069 { &hf_s7comm_userdata_param_dataunit,
7070 { "Last data unit", "s7comm.param.userdata.lastdataunit", FT_UINT8, BASE_HEX, VALS(userdata_lastdataunit_names), 0x0,
7071 NULL, HFILL }},
7072
7073 /* block functions / info */
7074 { &hf_s7comm_ud_blockinfo_block_type,
7075 { "Block type", "s7comm.blockinfo.blocktype", FT_STRING, BASE_NONE, NULL, 0x0,
7076 NULL, HFILL }},
7077 { &hf_s7comm_ud_blockinfo_block_cnt,
7078 { "Block count", "s7comm.blockinfo.block_count", FT_UINT16, BASE_DEC, NULL, 0x0,
7079 NULL, HFILL }},
7080 { &hf_s7comm_ud_blockinfo_block_num,
7081 { "Block number", "s7comm.blockinfo.block_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7082 NULL, HFILL }},
7083 { &hf_s7comm_ud_blockinfo_block_flags,
7084 { "Block flags (unknown)", "s7comm.blockinfo.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
7085 NULL, HFILL }},
7086 { &hf_s7comm_ud_blockinfo_block_lang,
7087 { "Block language", "s7comm.blockinfo.block_lang", FT_UINT8, BASE_DEC, VALS(blocklanguage_names), 0x0,
7088 NULL, HFILL }},
7089 { &hf_s7comm_ud_blockinfo_block_num_ascii,
7090 { "Block number", "s7comm.data.blockinfo.block_number", FT_STRING, BASE_NONE, NULL, 0x0,
7091 NULL, HFILL }},
7092 { &hf_s7comm_ud_blockinfo_filesys,
7093 { "Filesystem", "s7comm.data.blockinfo.filesys", FT_STRING, BASE_NONE, NULL, 0x0,
7094 NULL, HFILL }},
7095 { &hf_s7comm_ud_blockinfo_res_infolength,
7096 { "Length of Info", "s7comm.blockinfo.res_infolength", FT_UINT16, BASE_DEC, NULL, 0x0,
7097 "Length of Info in bytes", HFILL }},
7098 { &hf_s7comm_ud_blockinfo_res_unknown2,
7099 { "Unknown blockinfo 2", "s7comm.blockinfo.res_unknown2", FT_UINT16, BASE_HEX, NULL, 0x0,
7100 NULL, HFILL }},
7101 { &hf_s7comm_ud_blockinfo_res_const3,
7102 { "Constant 3", "s7comm.blockinfo.res_const3", FT_STRING, BASE_NONE, NULL, 0x0,
7103 "Possible constant 3, seems to be always 'pp'", HFILL }},
7104 { &hf_s7comm_ud_blockinfo_res_unknown,
7105 { "Unknown byte(s) blockinfo", "s7comm.blockinfo.res_unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
7106 NULL, HFILL }},
7107 { &hf_s7comm_ud_blockinfo_subblk_type,
7108 { "Subblk type", "s7comm.blockinfo.subblk_type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
7109 NULL, HFILL }},
7110 { &hf_s7comm_ud_blockinfo_load_mem_len,
7111 { "Length load memory", "s7comm.blockinfo.load_mem_len", FT_UINT32, BASE_DEC, NULL, 0x0,
7112 "Length of load memory in bytes", HFILL }},
7113 { &hf_s7comm_ud_blockinfo_blocksecurity,
7114 { "Block Security", "s7comm.blockinfo.blocksecurity", FT_UINT32, BASE_DEC, VALS(blocksecurity_names), 0x0,
7115 NULL, HFILL }},
7116 { &hf_s7comm_ud_blockinfo_interface_timestamp,
7117 { "Interface timestamp", "s7comm.blockinfo.interface_timestamp", FT_STRING, BASE_NONE, NULL, 0x0,
7118 NULL, HFILL }},
7119 { &hf_s7comm_ud_blockinfo_code_timestamp,
7120 { "Code timestamp", "s7comm.blockinfo.code_timestamp", FT_STRING, BASE_NONE, NULL, 0x0,
7121 NULL, HFILL }},
7122 { &hf_s7comm_ud_blockinfo_ssb_len,
7123 { "SSB length", "s7comm.blockinfo.ssb_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7124 NULL, HFILL }},
7125 { &hf_s7comm_ud_blockinfo_add_len,
7126 { "ADD length", "s7comm.blockinfo.add_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7127 NULL, HFILL }},
7128 { &hf_s7comm_ud_blockinfo_localdata_len,
7129 { "Localdata length", "s7comm.blockinfo.localdata_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7130 "Length of localdata in bytes", HFILL }},
7131 { &hf_s7comm_ud_blockinfo_mc7_len,
7132 { "MC7 code length", "s7comm.blockinfo.mc7_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7133 "Length of MC7 code in bytes", HFILL }},
7134 { &hf_s7comm_ud_blockinfo_author,
7135 { "Author", "s7comm.blockinfo.author", FT_STRING, BASE_NONE, NULL, 0x0,
7136 NULL, HFILL }},
7137 { &hf_s7comm_ud_blockinfo_family,
7138 { "Family", "s7comm.blockinfo.family", FT_STRING, BASE_NONE, NULL, 0x0,
7139 NULL, HFILL }},
7140 { &hf_s7comm_ud_blockinfo_headername,
7141 { "Name (Header)", "s7comm.blockinfo.headername", FT_STRING, BASE_NONE, NULL, 0x0,
7142 NULL, HFILL }},
7143 { &hf_s7comm_ud_blockinfo_headerversion,
7144 { "Version (Header)", "s7comm.blockinfo.headerversion", FT_STRING, BASE_NONE, NULL, 0x0,
7145 NULL, HFILL }},
7146 { &hf_s7comm_ud_blockinfo_checksum,
7147 { "Block checksum", "s7comm.blockinfo.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
7148 NULL, HFILL }},
7149 { &hf_s7comm_ud_blockinfo_reserved1,
7150 { "Reserved 1", "s7comm.blockinfo.reserved1", FT_UINT32, BASE_HEX, NULL, 0x0,
7151 NULL, HFILL }},
7152 { &hf_s7comm_ud_blockinfo_reserved2,
7153 { "Reserved 2", "s7comm.blockinfo.reserved2", FT_UINT32, BASE_HEX, NULL, 0x0,
7154 NULL, HFILL }},
7155
7156 /* Flags in blockinfo response */
7157 { &hf_s7comm_userdata_blockinfo_flags,
7158 { "Block flags", "s7comm.param.userdata.blockinfo.flags", FT_UINT8, BASE_HEX, NULL, 0xff,
7159 "Some block configuration flags", HFILL }},
7160 /* Bit : 0 -> DB Linked = true */
7161 { &hf_s7comm_userdata_blockinfo_linked,
7162 { "Linked", "s7comm.param.userdata.blockinfo.linked", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
7163 NULL, HFILL }},
7164 /* Bit : 1 -> Standard block = true */
7165 { &hf_s7comm_userdata_blockinfo_standard_block,
7166 { "Standard block", "s7comm.param.userdata.blockinfo.standard_block", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
7167 NULL, HFILL }},
7168 /* Bit : 5 -> DB Non Retain = true */
7169 { &hf_s7comm_userdata_blockinfo_nonretain,
7170 { "Non Retain", "s7comm.param.userdata.blockinfo.nonretain", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
7171 NULL, HFILL }},
7172
7173 /* Programmer commands / Test and installation (TIS) functions */
7174 { &hf_s7comm_tis_parameter,
7175 { "TIS Parameter", "s7comm.tis.parameter", FT_NONE, BASE_NONE, NULL, 0x0,
7176 "TIS Test and Installation: Parameter", HFILL }},
7177 { &hf_s7comm_tis_data,
7178 { "TIS Data", "s7comm.cpu.tis.data", FT_NONE, BASE_NONE, NULL, 0x0,
7179 "TIS Test and Installation: Data", HFILL }},
7180 { &hf_s7comm_tis_parametersize,
7181 { "TIS Parameter size", "s7comm.tis.parametersize", FT_UINT16, BASE_DEC, NULL, 0x0,
7182 NULL, HFILL }},
7183 { &hf_s7comm_tis_datasize,
7184 { "TIS Data size", "s7comm.tis.datasize", FT_UINT16, BASE_DEC, NULL, 0x0,
7185 NULL, HFILL }},
7186 { &hf_s7comm_tis_param1,
7187 { "TIS Parameter 1", "s7comm.tis.param1", FT_UINT16, BASE_DEC, NULL, 0x0,
7188 NULL, HFILL }},
7189 { &hf_s7comm_tis_param2,
7190 { "TIS Parameter 2 - Trigger type", "s7comm.tis.param2", FT_UINT16, BASE_DEC, VALS(tis_param2_names), 0x0,
7191 NULL, HFILL }},
7192 { &hf_s7comm_tis_param3,
7193 { "TIS Parameter 3 - Trigger frequency", "s7comm.tis.param3", FT_UINT16, BASE_DEC, VALS(tis_param3_names), 0x0,
7194 NULL, HFILL }},
7195 { &hf_s7comm_tis_answersize,
7196 { "TIS Parameter 4 - Answer size", "s7comm.tis.answersize", FT_UINT16, BASE_DEC, NULL, 0x0,
7197 "TIS Answer size: Expected data size of PLC answer to this job", HFILL }},
7198 { &hf_s7comm_tis_param5,
7199 { "TIS Parameter 5", "s7comm.tis.param5", FT_UINT16, BASE_DEC, NULL, 0x0,
7200 NULL, HFILL }},
7201 { &hf_s7comm_tis_param6,
7202 { "TIS Parameter 6", "s7comm.tis.param6", FT_UINT16, BASE_DEC, NULL, 0x0,
7203 NULL, HFILL }},
7204 { &hf_s7comm_tis_param7,
7205 { "TIS Parameter 7", "s7comm.tis.param7", FT_UINT16, BASE_DEC, NULL, 0x0,
7206 NULL, HFILL }},
7207 { &hf_s7comm_tis_param8,
7208 { "TIS Parameter 8", "s7comm.tis.param8", FT_UINT16, BASE_DEC, NULL, 0x0,
7209 NULL, HFILL }},
7210 { &hf_s7comm_tis_param9,
7211 { "TIS Parameter 9", "s7comm.tis.param9", FT_UINT16, BASE_DEC, NULL, 0x0,
7212 NULL, HFILL }},
7213 { &hf_s7comm_tis_trgevent,
7214 { "TIS Parameter 10 - Trigger event", "s7comm.varstat.trgevent", FT_UINT16, BASE_HEX, VALS(userdata_varstat_trgevent_names), 0x0,
7215 NULL, HFILL }},
7216 { &hf_s7comm_tis_res_param1,
7217 { "TIS Response Parameter 1", "s7comm.tis.res.param1", FT_UINT16, BASE_HEX, NULL, 0x0,
7218 NULL, HFILL }},
7219 { &hf_s7comm_tis_res_param2,
7220 { "TIS Response Parameter 2", "s7comm.tis.res.param2", FT_UINT16, BASE_HEX, NULL, 0x0,
7221 NULL, HFILL }},
7222 { &hf_s7comm_tis_job_function,
7223 { "Job function", "s7comm.tis.job.function", FT_UINT8, BASE_DEC, VALS(userdata_prog_subfunc_names), 0x0,
7224 NULL, HFILL }},
7225 { &hf_s7comm_tis_job_seqnr,
7226 { "Job reference sequence number", "s7comm.tis.job.response_seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7227 "Job reference sequence number (find function setup with s7comm.param.userdata.seq_num)", HFILL }},
7228 { &hf_s7comm_tis_job_reserved,
7229 { "Job Reserved / Unknown", "s7comm.tis.job.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7230 NULL, HFILL }},
7231 { &hf_s7comm_tis_interrupted_blocktype,
7232 { "Interrupted block type", "s7comm.tis.interrupted.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7233 NULL, HFILL }},
7234 { &hf_s7comm_tis_interrupted_blocknr,
7235 { "Interrupted block number", "s7comm.tis.interrupted.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7236 NULL, HFILL }},
7237 { &hf_s7comm_tis_interrupted_address,
7238 { "Interrupted code address", "s7comm.tis.interrupted.address", FT_UINT16, BASE_DEC, NULL, 0x0,
7239 NULL, HFILL }},
7240 { &hf_s7comm_tis_interrupted_prioclass,
7241 { "Interrupted priority class", "s7comm.tis.interrupted.priorityclass", FT_UINT8, BASE_DEC, NULL, 0x0,
7242 NULL, HFILL }},
7243 { &hf_s7comm_tis_continued_blocktype,
7244 { "Continued block type", "s7comm.tis.continued.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7245 NULL, HFILL }},
7246 { &hf_s7comm_tis_continued_blocknr,
7247 { "Continued block number", "s7comm.tis.continued.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7248 NULL, HFILL }},
7249 { &hf_s7comm_tis_continued_address,
7250 { "Continued code address", "s7comm.tis.continued.address", FT_UINT16, BASE_DEC, NULL, 0x0,
7251 NULL, HFILL }},
7252 { &hf_s7comm_tis_breakpoint_blocktype,
7253 { "Breakpoint block type", "s7comm.tis.breakpoint.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7254 NULL, HFILL }},
7255 { &hf_s7comm_tis_breakpoint_blocknr,
7256 { "Breakpoint block number", "s7comm.tis.breakpoint.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7257 NULL, HFILL }},
7258 { &hf_s7comm_tis_breakpoint_address,
7259 { "Breakpoint code address", "s7comm.tis.breakpoint.address", FT_UINT16, BASE_DEC, NULL, 0x0,
7260 NULL, HFILL }},
7261 { &hf_s7comm_tis_breakpoint_reserved,
7262 { "Breakpoint Reserved / Unknown", "s7comm.tis.breakpoint.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7263 NULL, HFILL }},
7264
7265 { &hf_s7comm_tis_p_callenv,
7266 { "Call environment setup", "s7comm.tis.callenv_setup", FT_UINT16, BASE_DEC, VALS(tis_p_callenv_names), 0x0,
7267 NULL, HFILL }},
7268 { &hf_s7comm_tis_p_callcond,
7269 { "Call condition", "s7comm.tis.callenv_cond", FT_UINT16, BASE_DEC, VALS(tis_p_callcond_names), 0x0,
7270 NULL, HFILL }},
7271 { &hf_s7comm_tis_p_callcond_blocktype,
7272 { "Call condition block type", "s7comm.tis.callenv_cond_blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7273 NULL, HFILL }},
7274 { &hf_s7comm_tis_p_callcond_blocknr,
7275 { "Call condition block number", "s7comm.tis.callenv_cond_blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7276 NULL, HFILL }},
7277 { &hf_s7comm_tis_p_callcond_address,
7278 { "Call condition code address", "s7comm.tis.callenv_cond_blockaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
7279 NULL, HFILL }},
7280
7281 { &hf_s7comm_tis_register_db1_type,
7282 { "Register DB1 content type", "s7comm.tis.db1.type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
7283 NULL, HFILL }},
7284 { &hf_s7comm_tis_register_db2_type,
7285 { "Register DB2 content type", "s7comm.tis.db2.type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
7286 NULL, HFILL }},
7287 { &hf_s7comm_tis_register_db1_nr,
7288 { "Register DB1 block number", "s7comm.tis.db1.number", FT_UINT16, BASE_DEC, NULL, 0x0,
7289 NULL, HFILL }},
7290 { &hf_s7comm_tis_register_db2_nr,
7291 { "Register DB2 block number", "s7comm.tis.db2.number", FT_UINT16, BASE_DEC, NULL, 0x0,
7292 NULL, HFILL }},
7293 { &hf_s7comm_tis_register_accu1,
7294 { "Register ACCU1", "s7comm.tis.accu1", FT_UINT32, BASE_HEX, NULL, 0x0,
7295 NULL, HFILL }},
7296 { &hf_s7comm_tis_register_accu2,
7297 { "Register ACCU2", "s7comm.tis.accu2", FT_UINT32, BASE_HEX, NULL, 0x0,
7298 NULL, HFILL }},
7299 { &hf_s7comm_tis_register_accu3,
7300 { "Register ACCU3", "s7comm.tis.accu3", FT_UINT32, BASE_HEX, NULL, 0x0,
7301 NULL, HFILL }},
7302 { &hf_s7comm_tis_register_accu4,
7303 { "Register ACCU4", "s7comm.tis.accu4", FT_UINT32, BASE_HEX, NULL, 0x0,
7304 NULL, HFILL }},
7305 { &hf_s7comm_tis_register_ar1,
7306 { "Register AR1", "s7comm.tis.ar1", FT_UINT32, BASE_HEX, NULL, 0x0,
7307 NULL, HFILL }},
7308 { &hf_s7comm_tis_register_ar2,
7309 { "Register AR2", "s7comm.tis.ar2", FT_UINT32, BASE_HEX, NULL, 0x0,
7310 NULL, HFILL }},
7311 { &hf_s7comm_tis_register_stw,
7312 { "Register STW", "s7comm.tis.stw", FT_UINT16, BASE_HEX, NULL, 0x0,
7313 NULL, HFILL }},
7314 { &hf_s7comm_tis_exithold_until,
7315 { "Exit HOLD state until", "s7comm.tis.exithold_until", FT_UINT8, BASE_DEC, VALS(tis_exithold_until_names), 0x0,
7316 NULL, HFILL }},
7317 { &hf_s7comm_tis_exithold_res1 ,
7318 { "Exit HOLD Reserved / Unknown", "s7comm.tis.exithold_res1", FT_UINT8, BASE_DEC, NULL, 0x0,
7319 NULL, HFILL }},
7320 { &hf_s7comm_tis_bstack_nest_depth,
7321 { "BSTACK nesting depth", "s7comm.tis.bstack.neting_depth", FT_UINT8, BASE_DEC, NULL, 0x0,
7322 NULL, HFILL }},
7323 { &hf_s7comm_tis_bstack_reserved,
7324 { "BSTACK Reserved / Unknown", "s7comm.tis.bstack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7325 NULL, HFILL }},
7326 { &hf_s7comm_tis_istack_reserved,
7327 { "ISTACK Reserved / Unknown", "s7comm.tis.istack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7328 NULL, HFILL }},
7329 { &hf_s7comm_tis_lstack_reserved,
7330 { "LSTACK Reserved / Unknown", "s7comm.tis.lstack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7331 NULL, HFILL }},
7332 { &hf_s7comm_tis_lstack_size,
7333 { "Localdata stack size", "s7comm.tis.lstack.size", FT_UINT16, BASE_DEC, NULL, 0x0,
7334 NULL, HFILL }},
7335 { &hf_s7comm_tis_lstack_data,
7336 { "Localdata stack data", "s7comm.tis.lstack.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7337 NULL, HFILL }},
7338 { &hf_s7comm_tis_blockstat_flagsunknown,
7339 { "Blockstat flags", "s7comm.tis.blockstat.flagsunknown", FT_UINT8, BASE_HEX, NULL, 0x0,
7340 NULL, HFILL }},
7341 { &hf_s7comm_tis_blockstat_number_of_lines,
7342 { "Number of lines", "s7comm.tis.blockstat.number_of_lines", FT_UINT8, BASE_DEC, NULL, 0x0,
7343 NULL, HFILL }},
7344 { &hf_s7comm_tis_blockstat_line_address,
7345 { "Address", "s7comm.tis.blockstat.line_address", FT_UINT16, BASE_DEC, NULL, 0x0,
7346 NULL, HFILL }},
7347 { &hf_s7comm_tis_blockstat_data,
7348 { "Blockstatus data", "s7comm.tis.blockstat.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7349 NULL, HFILL }},
7350 { &hf_s7comm_tis_blockstat_reserved,
7351 { "Blockstatus Reserved / Unknown", "s7comm.tis.blockstat.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
7352 NULL, HFILL }},
7353 /* Organization block local data */
7354 { &hf_s7comm_ob_ev_class,
7355 { "OB Event class", "s7comm.ob.ev_class", FT_UINT8, BASE_HEX, NULL, 0x0,
7356 "OB Event class (Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)", HFILL }},
7357 { &hf_s7comm_ob_scan_1,
7358 { "OB Scan 1", "s7comm.ob.scan_1", FT_UINT8, BASE_HEX, NULL, 0x0,
7359 "OB Scan 1 (1=Cold restart scan 1 of OB 1), 3=Scan 2-n of OB 1)", HFILL }},
7360 { &hf_s7comm_ob_strt_inf,
7361 { "OB Start info", "s7comm.ob.strt_info", FT_UINT8, BASE_HEX, NULL, 0x0,
7362 "OB Start info (OB n has started)", HFILL }},
7363 { &hf_s7comm_ob_flt_id,
7364 { "OB Fault identification code", "s7comm.ob.flt_id", FT_UINT8, BASE_HEX, NULL, 0x0,
7365 NULL, HFILL }},
7366 { &hf_s7comm_ob_priority,
7367 { "OB Priority", "s7comm.ob.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
7368 "OB Priority (1 is lowest)", HFILL }},
7369 { &hf_s7comm_ob_number,
7370 { "OB Number", "s7comm.ob.number", FT_UINT8, BASE_DEC, NULL, 0x0,
7371 NULL, HFILL }},
7372 { &hf_s7comm_ob_reserved_1,
7373 { "OB Reserved 1", "s7comm.ob.reserved_1", FT_UINT8, BASE_HEX, NULL, 0x0,
7374 "OB Reserved 1 (Reserved for System)", HFILL }},
7375 { &hf_s7comm_ob_reserved_2,
7376 { "OB Reserved 2", "s7comm.ob.reserved_2", FT_UINT8, BASE_HEX, NULL, 0x0,
7377 "OB Reserved 2 (Reserved for System)", HFILL }},
7378 { &hf_s7comm_ob_reserved_3,
7379 { "OB Reserved 3", "s7comm.ob.reserved_3", FT_UINT16, BASE_HEX, NULL, 0x0,
7380 "OB Reserved 3 (Reserved for System)", HFILL }},
7381 { &hf_s7comm_ob_reserved_4,
7382 { "OB Reserved 4", "s7comm.ob.reserved_4", FT_UINT16, BASE_HEX, NULL, 0x0,
7383 "OB Reserved 4 (Reserved for System)", HFILL }},
7384 { &hf_s7comm_ob_reserved_4_dw,
7385 { "OB Reserved 4", "s7comm.ob.reserved_4_dw", FT_UINT32, BASE_HEX, NULL, 0x0,
7386 "OB Reserved 4 (Reserved for System)", HFILL }},
7387 { &hf_s7comm_ob_prev_cycle,
7388 { "OB Cycle time of previous OB scan (ms)", "s7comm.ob.prev_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
7389 NULL, HFILL }},
7390 { &hf_s7comm_ob_min_cycle,
7391 { "OB Minimum cycle time of OB (ms)", "s7comm.ob.min_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
7392 NULL, HFILL }},
7393 { &hf_s7comm_ob_max_cycle,
7394 { "OB Maximum cycle time of OB (ms)", "s7comm.ob.max_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
7395 NULL, HFILL }},
7396 { &hf_s7comm_ob_period_exe,
7397 { "OB Period of execution", "s7comm.ob.period_exe", FT_UINT16, BASE_HEX, NULL, 0x0,
7398 "OB Period of execution (once, per minute/hour/day/week/month/year)", HFILL }},
7399 { &hf_s7comm_ob_sign,
7400 { "OB Identifier input (SIGN) attached to SRT_DINT", "s7comm.ob.sign", FT_UINT16, BASE_HEX, NULL, 0x0,
7401 NULL, HFILL }},
7402 { &hf_s7comm_ob_dtime,
7403 { "OB Delay time (DTIME) input to SRT_DINT instruction", "s7comm.ob.dtime", FT_UINT32, BASE_DEC, NULL, 0x0,
7404 NULL, HFILL }},
7405 { &hf_s7comm_ob_phase_offset,
7406 { "OB Phase offset (ms)", "s7comm.ob.phase_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
7407 NULL, HFILL }},
7408 { &hf_s7comm_ob_exec_freq,
7409 { "OB Frequency of execution (ms)", "s7comm.ob.exec_freq", FT_UINT16, BASE_DEC, NULL, 0x0,
7410 NULL, HFILL }},
7411 { &hf_s7comm_ob_io_flag,
7412 { "OB IO flags", "s7comm.ob.io_flag", FT_UINT16, BASE_DEC, NULL, 0x0,
7413 "OB IO flags (0x54=input module, 0x55=output module)", HFILL }},
7414 { &hf_s7comm_ob_mdl_addr,
7415 { "OB Base address of module initiating interrupt", "s7comm.ob.mdl_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
7416 NULL, HFILL }},
7417 { &hf_s7comm_ob_point_addr,
7418 { "OB Address of interrupt point on module", "s7comm.ob.point_addr", FT_UINT32, BASE_HEX, NULL, 0x0,
7419 NULL, HFILL }},
7420 { &hf_s7comm_ob_inf_len,
7421 { "OB Length of information", "s7comm.ob.inf_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7422 NULL, HFILL }},
7423 { &hf_s7comm_ob_alarm_type,
7424 { "OB Type of alarm", "s7comm.ob.alarm_type", FT_UINT8, BASE_DEC, NULL, 0x0,
7425 NULL, HFILL }},
7426 { &hf_s7comm_ob_alarm_slot,
7427 { "OB Slot", "s7comm.ob.alarm_slot", FT_UINT8, BASE_DEC, NULL, 0x0,
7428 NULL, HFILL }},
7429 { &hf_s7comm_ob_alarm_spec,
7430 { "OB Specifier", "s7comm.ob.alarm_spec", FT_UINT8, BASE_DEC, NULL, 0x0,
7431 NULL, HFILL }},
7432 { &hf_s7comm_ob_error_info,
7433 { "OB Error information on event", "s7comm.ob.error_info", FT_UINT16, BASE_HEX, NULL, 0x0,
7434 NULL, HFILL }},
7435 { &hf_s7comm_ob_err_ev_class,
7436 { "OB Class of event causing error", "s7comm.ob.err_ev_class", FT_UINT8, BASE_DEC, NULL, 0x0,
7437 NULL, HFILL }},
7438 { &hf_s7comm_ob_err_ev_num,
7439 { "OB Number of event causing error", "s7comm.ob.err_ev_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7440 NULL, HFILL }},
7441 { &hf_s7comm_ob_err_ob_priority,
7442 { "OB Priority of OB causing error", "s7comm.ob.err_ob_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
7443 NULL, HFILL }},
7444 { &hf_s7comm_ob_err_ob_num,
7445 { "OB Number of OB causing error", "s7comm.ob.err_ob_num", FT_UINT8, BASE_DEC, NULL, 0x0,
7446 NULL, HFILL }},
7447 { &hf_s7comm_ob_rack_cpu,
7448 { "OB Rack / CPU number", "s7comm.ob.rack_cpu", FT_UINT16, BASE_HEX, NULL, 0x0,
7449 NULL, HFILL }},
7450 { &hf_s7comm_ob_8x_fault_flags,
7451 { "OB 8x Fault flags", "s7comm.ob.8x_fault_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
7452 NULL, HFILL }},
7453 { &hf_s7comm_ob_mdl_type_b,
7454 { "OB Type of module", "s7comm.ob.mdl_type_b", FT_UINT8, BASE_HEX, NULL, 0x0,
7455 NULL, HFILL }},
7456 { &hf_s7comm_ob_mdl_type_w,
7457 { "OB Module type with point fault", "s7comm.ob.mdl_type_w", FT_UINT16, BASE_HEX, NULL, 0x0,
7458 NULL, HFILL }},
7459 { &hf_s7comm_ob_rack_num,
7460 { "OB Number of rack that has module with point fault", "s7comm.ob.rack_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7461 NULL, HFILL }},
7462 { &hf_s7comm_ob_racks_flt,
7463 { "OB Racks in fault", "s7comm.ob.racks_flt", FT_UINT32, BASE_HEX, NULL, 0x0,
7464 NULL, HFILL }},
7465 { &hf_s7comm_ob_strtup,
7466 { "OB Method of startup", "s7comm.ob.strtup", FT_UINT8, BASE_HEX, NULL, 0x0,
7467 NULL, HFILL }},
7468 { &hf_s7comm_ob_stop,
7469 { "OB Event that caused CPU to stop", "s7comm.ob.stop", FT_UINT16, BASE_HEX, NULL, 0x0,
7470 NULL, HFILL }},
7471 { &hf_s7comm_ob_strt_info,
7472 { "OB Information on how system started", "s7comm.ob.strt_info", FT_UINT32, BASE_HEX, NULL, 0x0,
7473 NULL, HFILL }},
7474 { &hf_s7comm_ob_sw_flt,
7475 { "OB Software programming fault", "s7comm.ob.sw_flt", FT_UINT8, BASE_HEX, NULL, 0x0,
7476 NULL, HFILL }},
7477 { &hf_s7comm_ob_blk_type,
7478 { "OB Type of block fault occurred in", "s7comm.ob.blk_type", FT_UINT8, BASE_HEX, NULL, 0x0,
7479 NULL, HFILL }},
7480 { &hf_s7comm_ob_flt_reg,
7481 { "OB Specific register that caused fault", "s7comm.ob.flt_reg", FT_UINT16, BASE_HEX, NULL, 0x0,
7482 NULL, HFILL }},
7483 { &hf_s7comm_ob_flt_blk_num,
7484 { "OB Number of block that programming fault occurred in", "s7comm.ob.flt_blk_num", FT_UINT16, BASE_DEC, NULL, 0x0,
7485 NULL, HFILL }},
7486 { &hf_s7comm_ob_prg_addr,
7487 { "OB Address in block where programming fault occurred", "s7comm.ob.prg_addr", FT_UINT16, BASE_DEC, NULL, 0x0,
7488 NULL, HFILL }},
7489 { &hf_s7comm_ob_mem_area,
7490 { "OB Memory area where access error occurred", "s7comm.ob.mem_area", FT_UINT8, BASE_HEX, NULL, 0x0,
7491 NULL, HFILL }},
7492 { &hf_s7comm_ob_mem_addr,
7493 { "OB Memory address where access error occurred", "s7comm.ob.mem_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
7494 NULL, HFILL }},
7495 { &hf_s7comm_diagdata_req_block_type,
7496 { "Block type", "s7comm.diagdata.req.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
7497 NULL, HFILL }},
7498 { &hf_s7comm_diagdata_req_block_num,
7499 { "Block number", "s7comm.diagdata.req.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
7500 NULL, HFILL }},
7501 { &hf_s7comm_diagdata_req_startaddr_awl,
7502 { "Start address AWL", "s7comm.diagdata.req.startaddr_awl", FT_UINT16, BASE_DEC, NULL, 0x0,
7503 NULL, HFILL }},
7504 { &hf_s7comm_diagdata_req_saz,
7505 { "Step address counter (SAZ)", "s7comm.diagdata.req.saz", FT_UINT16, BASE_DEC, NULL, 0x0,
7506 NULL, HFILL }},
7507
7508 /* Flags for requested registers in diagnostic data telegrams */
7509 { &hf_s7comm_diagdata_registerflag,
7510 { "Registers", "s7comm.diagdata.register", FT_UINT8, BASE_HEX, NULL, 0x00,
7511 "Requested registers", HFILL }},
7512 { &hf_s7comm_diagdata_registerflag_stw,
7513 { "STW", "s7comm.diagdata.register.stw", FT_BOOLEAN, 8, NULL, 0x01,
7514 "STW / Status word", HFILL }},
7515 { &hf_s7comm_diagdata_registerflag_accu1,
7516 { "ACCU1", "s7comm.diagdata.register.accu1", FT_BOOLEAN, 8, NULL, 0x02,
7517 "ACCU1 / Accumulator 1", HFILL }},
7518 { &hf_s7comm_diagdata_registerflag_accu2,
7519 { "ACCU2", "s7comm.diagdata.register.accu2", FT_BOOLEAN, 8, NULL, 0x04,
7520 "ACCU2 / Accumulator 2", HFILL }},
7521 { &hf_s7comm_diagdata_registerflag_ar1,
7522 { "AR1", "s7comm.diagdata.register.ar1", FT_BOOLEAN, 8, NULL, 0x08,
7523 "AR1 / Addressregister 1", HFILL }},
7524 { &hf_s7comm_diagdata_registerflag_ar2,
7525 { "AR2", "s7comm.diagdata.register.ar2", FT_BOOLEAN, 8, NULL, 0x10,
7526 "AR2 / Addressregister 2", HFILL }},
7527 { &hf_s7comm_diagdata_registerflag_db1,
7528 { "DB1", "s7comm.diagdata.register.db1", FT_BOOLEAN, 8, NULL, 0x20,
7529 "DB1 (global)/ Datablock register 1", HFILL }},
7530 { &hf_s7comm_diagdata_registerflag_db2,
7531 { "DB2", "s7comm.diagdata.register.db2", FT_BOOLEAN, 8, NULL, 0x40,
7532 "DB2 (instance) / Datablock register 2", HFILL }},
7533
7534 /* timefunction: s7 timestamp */
7535 { &hf_s7comm_data_ts,
7536 { "S7 Timestamp", "s7comm.data.ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
7537 "S7 Timestamp, BCD coded", HFILL }},
7538 { &hf_s7comm_data_ts_reserved,
7539 { "S7 Timestamp - Reserved", "s7comm.data.ts_reserved", FT_UINT8, BASE_HEX, NULL, 0x00,
7540 "S7 Timestamp: Reserved byte", HFILL }},
7541 { &hf_s7comm_data_ts_year1,
7542 { "S7 Timestamp - Year 1", "s7comm.data.ts_year1", FT_UINT8, BASE_DEC, NULL, 0x00,
7543 "S7 Timestamp: BCD coded year thousands/hundreds, should be ignored (19 or 20)", HFILL }},
7544 { &hf_s7comm_data_ts_year2,
7545 { "S7 Timestamp - Year 2", "s7comm.data.ts_year2", FT_UINT8, BASE_DEC, NULL, 0x00,
7546 "S7 Timestamp: BCD coded year, if 00...89 then it's 2000...2089, else 1990...1999", HFILL }},
7547 { &hf_s7comm_data_ts_month,
7548 { "S7 Timestamp - Month", "s7comm.data.ts_month", FT_UINT8, BASE_DEC, NULL, 0x00,
7549 "S7 Timestamp: BCD coded month", HFILL }},
7550 { &hf_s7comm_data_ts_day,
7551 { "S7 Timestamp - Day", "s7comm.data.ts_day", FT_UINT8, BASE_DEC, NULL, 0x00,
7552 "S7 Timestamp: BCD coded day", HFILL }},
7553 { &hf_s7comm_data_ts_hour,
7554 { "S7 Timestamp - Hour", "s7comm.data.ts_hour", FT_UINT8, BASE_DEC, NULL, 0x00,
7555 "S7 Timestamp: BCD coded hour", HFILL }},
7556 { &hf_s7comm_data_ts_minute,
7557 { "S7 Timestamp - Minute", "s7comm.data.ts_minute", FT_UINT8, BASE_DEC, NULL, 0x00,
7558 "S7 Timestamp: BCD coded minute", HFILL }},
7559 { &hf_s7comm_data_ts_second,
7560 { "S7 Timestamp - Second", "s7comm.data.ts_second", FT_UINT8, BASE_DEC, NULL, 0x00,
7561 "S7 Timestamp: BCD coded second", HFILL }},
7562 { &hf_s7comm_data_ts_millisecond,
7563 { "S7 Timestamp - Milliseconds", "s7comm.data.ts_millisecond", FT_UINT16, BASE_DEC, NULL, 0x00,
7564 "S7 Timestamp: BCD coded milliseconds (left 3 nibbles)", HFILL }},
7565 { &hf_s7comm_data_ts_weekday,
7566 { "S7 Timestamp - Weekday", "s7comm.data.ts_weekday", FT_UINT16, BASE_DEC, VALS(weekdaynames), 0x000f,
7567 "S7 Timestamp: Weekday number (right nibble, 1=Su,2=Mo,..)", HFILL }},
7568
7569 /* Function 0x28 (PI service) and 0x29 */
7570 { &hf_s7comm_piservice_unknown1,
7571 { "Unknown bytes", "s7comm.param.pistart.unknown1", FT_BYTES, BASE_NONE, NULL, 0x0,
7572 NULL, HFILL }},
7573 { &hf_s7comm_piservice_parameterblock_len,
7574 { "Parameter block length", "s7comm.param.pistart.parameterblock_len", FT_UINT16, BASE_DEC, NULL, 0x0,
7575 "Length of Parameter block in bytes", HFILL }},
7576 { &hf_s7comm_piservice_parameterblock,
7577 { "Parameter block", "s7comm.param.pistart.parameterblock", FT_NONE, BASE_NONE, NULL, 0x0,
7578 NULL, HFILL }},
7579 { &hf_s7comm_piservice_servicename,
7580 { "PI (program invocation) Service", "s7comm.param.pistart.servicename", FT_STRING, BASE_NONE, NULL, 0x0,
7581 NULL , HFILL }},
7582
7583 /* PI Service parameters for NC services */
7584 { &hf_s7comm_piservice_string_len,
7585 { "String length", "s7comm.param.pi.n_x.string_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7586 "Length of the following string. If LengthByte + Stringlen is uneven, a fillbyte is added", HFILL }},
7587 { &hf_s7comm_pi_n_x_addressident,
7588 { "Addressidentification", "s7comm.param.pi.n_x.addressident", FT_STRING, BASE_NONE, NULL, 0x0,
7589 "Addressidentification (RangeID / Index)", HFILL }},
7590 { &hf_s7comm_pi_n_x_filename,
7591 { "Filename", "s7comm.param.pi.n_x.filename", FT_STRING, BASE_NONE, NULL, 0x0,
7592 "Name of the file or directory", HFILL }},
7593 { &hf_s7comm_pi_n_x_editwindowname,
7594 { "Editor Window Name", "s7comm.param.pi.n_x.editwindowname", FT_STRING, BASE_NONE, NULL, 0x0,
7595 NULL, HFILL }},
7596 { &hf_s7comm_pi_n_x_password,
7597 { "Password", "s7comm.param.pi.n_x.password", FT_STRING, BASE_NONE, NULL, 0x0,
7598 NULL, HFILL }},
7599 { &hf_s7comm_pi_n_x_seekpointer,
7600 { "Seek pointer", "s7comm.param.pi.n_x.seekpointer", FT_STRING, BASE_NONE, NULL, 0x0,
7601 "SeekPointer string with exact 9 digit/character(s)", HFILL }},
7602 { &hf_s7comm_pi_n_x_windowsize,
7603 { "Window size", "s7comm.param.pi.n_x.windowsize", FT_STRING, BASE_NONE, NULL, 0x0,
7604 NULL, HFILL }},
7605 { &hf_s7comm_pi_n_x_comparestring,
7606 { "Compare String", "s7comm.param.pi.n_x.comparestring", FT_STRING, BASE_NONE, NULL, 0x0,
7607 NULL, HFILL }},
7608 { &hf_s7comm_pi_n_x_skipcount,
7609 { "Skip Count", "s7comm.param.pi.n_x.skipcount", FT_STRING, BASE_NONE, NULL, 0x0,
7610 NULL, HFILL }},
7611 { &hf_s7comm_pi_n_x_interruptnr,
7612 { "Interrupt Number", "s7comm.param.pi.n_x.interruptnr", FT_STRING, BASE_NONE, NULL, 0x0,
7613 "Interrupt Number: Interrupt number corresponds to the input number which caused the interrupt" , HFILL }},
7614 { &hf_s7comm_pi_n_x_priority,
7615 { "Priority", "s7comm.param.pi.n_x.priority", FT_STRING, BASE_NONE, NULL, 0x0,
7616 NULL , HFILL }},
7617 { &hf_s7comm_pi_n_x_liftfast,
7618 { "Liftfast", "s7comm.param.pi.n_x.liftfast", FT_STRING, BASE_NONE, NULL, 0x0,
7619 "Liftfast: Indicates whether an interrupt routine should simultaneously cause a fast lift-off motion" , HFILL }},
7620 { &hf_s7comm_pi_n_x_blsync,
7621 { "Blsync", "s7comm.param.pi.n_x.blsync", FT_STRING, BASE_NONE, NULL, 0x0,
7622 "Blsync: Indicates whether the interrupt has to be synchronized to the next block end" , HFILL }},
7623 { &hf_s7comm_pi_n_x_magnr,
7624 { "Magnr", "s7comm.param.pi.n_x.magnr", FT_STRING, BASE_NONE, NULL, 0x0,
7625 "Magnr: Magazine number" , HFILL }},
7626 { &hf_s7comm_pi_n_x_dnr,
7627 { "DNr", "s7comm.param.pi.n_x.dnr", FT_STRING, BASE_NONE, NULL, 0x0,
7628 "DNr: D number" , HFILL }},
7629 { &hf_s7comm_pi_n_x_spindlenumber,
7630 { "Spindle Number", "s7comm.param.pi.n_x.spindlenumber", FT_STRING, BASE_NONE, NULL, 0x0,
7631 NULL, HFILL }},
7632 { &hf_s7comm_pi_n_x_wznr,
7633 { "WZ-Nr", "s7comm.param.pi.n_x.wznr", FT_STRING, BASE_NONE, NULL, 0x0,
7634 "WZ-Nr: Tool number" , HFILL }},
7635 { &hf_s7comm_pi_n_x_class,
7636 { "Class", "s7comm.param.pi.n_x.class", FT_STRING, BASE_NONE, NULL, 0x0,
7637 "Class: Classify machine data" , HFILL }},
7638 { &hf_s7comm_pi_n_x_tnr,
7639 { "TNr", "s7comm.param.pi.n_x.tnr", FT_STRING, BASE_NONE, NULL, 0x0,
7640 NULL , HFILL }},
7641 { &hf_s7comm_pi_n_x_toolnumber,
7642 { "Tool Number", "s7comm.param.pi.n_x.toolnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7643 NULL , HFILL }},
7644 { &hf_s7comm_pi_n_x_cenumber,
7645 { "CE-Number", "s7comm.param.pi.n_x.cenumber", FT_STRING, BASE_NONE, NULL, 0x0,
7646 NULL , HFILL }},
7647 { &hf_s7comm_pi_n_x_datablocknumber,
7648 { "Datablock Number", "s7comm.param.pi.n_x.datablocknumber", FT_STRING, BASE_NONE, NULL, 0x0,
7649 NULL , HFILL }},
7650 { &hf_s7comm_pi_n_x_firstcolumnnumber,
7651 { "First Column Number", "s7comm.param.pi.n_x.firstcolumnnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7652 NULL , HFILL }},
7653 { &hf_s7comm_pi_n_x_lastcolumnnumber,
7654 { "Last Column Number", "s7comm.param.pi.n_x.lastcolumnnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7655 NULL , HFILL }},
7656 { &hf_s7comm_pi_n_x_firstrownumber,
7657 { "First Row Number", "s7comm.param.pi.n_x.firstrownnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7658 NULL , HFILL }},
7659 { &hf_s7comm_pi_n_x_lastrownumber,
7660 { "Last Row Number", "s7comm.param.pi.n_x.lastrownnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7661 NULL , HFILL }},
7662 { &hf_s7comm_pi_n_x_direction,
7663 { "Direction", "s7comm.param.pi.n_x.direction", FT_STRING, BASE_NONE, NULL, 0x0,
7664 NULL , HFILL }},
7665 { &hf_s7comm_pi_n_x_sourcefilename,
7666 { "Source-Filename", "s7comm.param.pi.n_x.sourcefilename", FT_STRING, BASE_NONE, NULL, 0x0,
7667 NULL , HFILL }},
7668 { &hf_s7comm_pi_n_x_destinationfilename,
7669 { "Destination-Filename", "s7comm.param.pi.n_x.destinationfilename", FT_STRING, BASE_NONE, NULL, 0x0,
7670 NULL , HFILL }},
7671 { &hf_s7comm_pi_n_x_channelnumber,
7672 { "Channel Number", "s7comm.param.pi.n_x.channelnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7673 NULL , HFILL }},
7674 { &hf_s7comm_pi_n_x_protection,
7675 { "Protection", "s7comm.param.pi.n_x.protection", FT_STRING, BASE_NONE, NULL, 0x0,
7676 NULL , HFILL }},
7677 { &hf_s7comm_pi_n_x_oldfilename,
7678 { "Old Filename", "s7comm.param.pi.n_x.oldfilename", FT_STRING, BASE_NONE, NULL, 0x0,
7679 NULL , HFILL }},
7680 { &hf_s7comm_pi_n_x_newfilename,
7681 { "New Filename", "s7comm.param.pi.n_x.newfilename", FT_STRING, BASE_NONE, NULL, 0x0,
7682 NULL , HFILL }},
7683 { &hf_s7comm_pi_n_x_findmode,
7684 { "Findmode", "s7comm.param.pi.n_x.findmode", FT_STRING, BASE_NONE, NULL, 0x0,
7685 NULL , HFILL }},
7686 { &hf_s7comm_pi_n_x_switch,
7687 { "Switch", "s7comm.param.pi.n_x.switch", FT_STRING, BASE_NONE, NULL, 0x0,
7688 NULL , HFILL }},
7689 { &hf_s7comm_pi_n_x_functionnumber,
7690 { "Function Number", "s7comm.param.pi.n_x.functionnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7691 NULL , HFILL }},
7692 { &hf_s7comm_pi_n_x_semaphorevalue,
7693 { "Semaphore Value", "s7comm.param.pi.n_x.semaphorevalue", FT_STRING, BASE_NONE, NULL, 0x0,
7694 NULL , HFILL }},
7695 { &hf_s7comm_pi_n_x_onoff,
7696 { "OnOff", "s7comm.param.pi.n_x.onoff", FT_STRING, BASE_NONE, NULL, 0x0,
7697 NULL , HFILL }},
7698 { &hf_s7comm_pi_n_x_mode,
7699 { "Mode", "s7comm.param.pi.n_x.mode", FT_STRING, BASE_NONE, NULL, 0x0,
7700 NULL , HFILL }},
7701 { &hf_s7comm_pi_n_x_factor,
7702 { "Factor", "s7comm.param.pi.n_x.factor", FT_STRING, BASE_NONE, NULL, 0x0,
7703 NULL , HFILL }},
7704 { &hf_s7comm_pi_n_x_passwordlevel,
7705 { "Password Level", "s7comm.param.pi.n_x.passwordlevel", FT_STRING, BASE_NONE, NULL, 0x0,
7706 NULL , HFILL }},
7707 { &hf_s7comm_pi_n_x_linenumber,
7708 { "Line Number", "s7comm.param.pi.n_x.linenumber", FT_STRING, BASE_NONE, NULL, 0x0,
7709 NULL , HFILL }},
7710 { &hf_s7comm_pi_n_x_weargroup,
7711 { "Wear Group", "s7comm.param.pi.n_x.weargroup", FT_STRING, BASE_NONE, NULL, 0x0,
7712 NULL , HFILL }},
7713 { &hf_s7comm_pi_n_x_toolstatus,
7714 { "Tool Status", "s7comm.param.pi.n_x.toolstatus", FT_STRING, BASE_NONE, NULL, 0x0,
7715 NULL , HFILL }},
7716 { &hf_s7comm_pi_n_x_wearsearchstrat,
7717 { "Search Strategy", "s7comm.param.pi.n_x.wearsearchstrat", FT_STRING, BASE_NONE, NULL, 0x0,
7718 NULL , HFILL }},
7719 { &hf_s7comm_pi_n_x_toolid,
7720 { "Tool ID", "s7comm.param.pi.n_x.toolid", FT_STRING, BASE_NONE, NULL, 0x0,
7721 NULL , HFILL }},
7722 { &hf_s7comm_pi_n_x_duplonumber,
7723 { "Duplo Number", "s7comm.param.pi.n_x.duplonumber", FT_STRING, BASE_NONE, NULL, 0x0,
7724 NULL , HFILL }},
7725 { &hf_s7comm_pi_n_x_edgenumber,
7726 { "Edge Number", "s7comm.param.pi.n_x.edgenumber", FT_STRING, BASE_NONE, NULL, 0x0,
7727 NULL , HFILL }},
7728 { &hf_s7comm_pi_n_x_placenr,
7729 { "Place Number", "s7comm.param.pi.n_x.placenr", FT_STRING, BASE_NONE, NULL, 0x0,
7730 NULL , HFILL }},
7731 { &hf_s7comm_pi_n_x_placerefnr,
7732 { "Place Reference Number", "s7comm.param.pi.n_x.placerefnr", FT_STRING, BASE_NONE, NULL, 0x0,
7733 NULL , HFILL }},
7734 { &hf_s7comm_pi_n_x_magrefnr,
7735 { "Magazine Reference Number", "s7comm.param.pi.n_x.magrefnr", FT_STRING, BASE_NONE, NULL, 0x0,
7736 NULL , HFILL }},
7737 { &hf_s7comm_pi_n_x_placenrfrom,
7738 { "Place Number from", "s7comm.param.pi.n_x.placenrfrom", FT_STRING, BASE_NONE, NULL, 0x0,
7739 NULL , HFILL }},
7740 { &hf_s7comm_pi_n_x_magnrfrom,
7741 { "Magazine Number from", "s7comm.param.pi.n_x.magnrfrom", FT_STRING, BASE_NONE, NULL, 0x0,
7742 NULL , HFILL }},
7743 { &hf_s7comm_pi_n_x_placenrto,
7744 { "Place Number to", "s7comm.param.pi.n_x.placenrto", FT_STRING, BASE_NONE, NULL, 0x0,
7745 NULL , HFILL }},
7746 { &hf_s7comm_pi_n_x_magnrto,
7747 { "Magazine Number to", "s7comm.param.pi.n_x.magnrto", FT_STRING, BASE_NONE, NULL, 0x0,
7748 NULL , HFILL }},
7749 { &hf_s7comm_pi_n_x_halfplacesleft,
7750 { "Half places left", "s7comm.param.pi.n_x.halfplacesleft", FT_STRING, BASE_NONE, NULL, 0x0,
7751 NULL , HFILL }},
7752 { &hf_s7comm_pi_n_x_halfplacesright,
7753 { "Half places right", "s7comm.param.pi.n_x.halfplacesright", FT_STRING, BASE_NONE, NULL, 0x0,
7754 NULL , HFILL }},
7755 { &hf_s7comm_pi_n_x_halfplacesup,
7756 { "Half places up", "s7comm.param.pi.n_x.halfplacesup", FT_STRING, BASE_NONE, NULL, 0x0,
7757 NULL , HFILL }},
7758 { &hf_s7comm_pi_n_x_halfplacesdown,
7759 { "Half places down", "s7comm.param.pi.n_x.halfplacesdown", FT_STRING, BASE_NONE, NULL, 0x0,
7760 NULL , HFILL }},
7761 { &hf_s7comm_pi_n_x_placetype,
7762 { "Place type index", "s7comm.param.pi.n_x.placetype", FT_STRING, BASE_NONE, NULL, 0x0,
7763 NULL , HFILL }},
7764 { &hf_s7comm_pi_n_x_searchdirection,
7765 { "Search direction", "s7comm.param.pi.n_x.searchdirection", FT_STRING, BASE_NONE, NULL, 0x0,
7766 NULL , HFILL }},
7767 { &hf_s7comm_pi_n_x_toolname,
7768 { "Tool Name", "s7comm.param.pi.n_x.toolname", FT_STRING, BASE_NONE, NULL, 0x0,
7769 NULL , HFILL }},
7770 { &hf_s7comm_pi_n_x_placenrsource,
7771 { "Place Number Source", "s7comm.param.pi.n_x.placenrsource", FT_STRING, BASE_NONE, NULL, 0x0,
7772 NULL , HFILL }},
7773 { &hf_s7comm_pi_n_x_magnrsource,
7774 { "Magazine Number Source", "s7comm.param.pi.n_x.magnrsource", FT_STRING, BASE_NONE, NULL, 0x0,
7775 NULL , HFILL }},
7776 { &hf_s7comm_pi_n_x_placenrdestination,
7777 { "Place Number Destination", "s7comm.param.pi.n_x.placenrdestination", FT_STRING, BASE_NONE, NULL, 0x0,
7778 NULL , HFILL }},
7779 { &hf_s7comm_pi_n_x_magnrdestination,
7780 { "Magazine Number Destination", "s7comm.param.pi.n_x.magnrdestination", FT_STRING, BASE_NONE, NULL, 0x0,
7781 NULL , HFILL }},
7782 { &hf_s7comm_pi_n_x_incrementnumber,
7783 { "Increment Number", "s7comm.param.pi.n_x.incrementnumber", FT_STRING, BASE_NONE, NULL, 0x0,
7784 NULL , HFILL }},
7785 { &hf_s7comm_pi_n_x_monitoringmode,
7786 { "Monitoring mode", "s7comm.param.pi.n_x.monitoringmode", FT_STRING, BASE_NONE, NULL, 0x0,
7787 NULL , HFILL }},
7788 { &hf_s7comm_pi_n_x_kindofsearch,
7789 { "Kind of search", "s7comm.param.pi.n_x.kindofsearch", FT_STRING, BASE_NONE, NULL, 0x0,
7790 NULL , HFILL }},
7791
7792 { &hf_s7comm_data_pi_inse_unknown,
7793 { "Unknown byte", "s7comm.param.pi.inse.unknown", FT_UINT8, BASE_HEX, NULL, 0x0,
7794 NULL, HFILL }},
7795
7796 { &hf_s7comm_data_plccontrol_argument,
7797 { "Argument", "s7comm.param.pistart.argument", FT_STRING, BASE_NONE, NULL, 0x0,
7798 NULL, HFILL }},
7799 { &hf_s7comm_data_plccontrol_block_cnt,
7800 { "Number of blocks", "s7comm.data.plccontrol.block_cnt", FT_UINT8, BASE_DEC, NULL, 0x0,
7801 NULL, HFILL }},
7802 { &hf_s7comm_data_plccontrol_part2_len,
7803 { "Length part 2", "s7comm.data.plccontrol.part2_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7804 "Length of part 2 in bytes", HFILL }},
7805
7806 /* block control functions */
7807 { &hf_s7comm_data_blockcontrol_unknown1,
7808 { "Unknown byte(s) in blockcontrol", "s7comm.data.blockcontrol.unknown1", FT_BYTES, BASE_NONE, NULL, 0x0,
7809 NULL, HFILL }},
7810 { &hf_s7comm_data_blockcontrol_errorcode,
7811 { "Errorcode", "s7comm.data.blockcontrol.errorcode", FT_UINT16, BASE_HEX, NULL, 0x0,
7812 "Errorcode, 0 on success", HFILL }},
7813 { &hf_s7comm_data_blockcontrol_uploadid,
7814 { "UploadID", "s7comm.data.blockcontrol.uploadid", FT_UINT32, BASE_HEX, NULL, 0x0,
7815 NULL, HFILL }},
7816 { &hf_s7comm_data_blockcontrol_file_ident,
7817 { "File identifier", "s7comm.data.blockcontrol.file_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
7818 "File identifier: '_'=complete module; '$'=Module header for up-loading", HFILL }},
7819 { &hf_s7comm_data_blockcontrol_block_type,
7820 { "Block type", "s7comm.data.blockcontrol.block_type", FT_STRING, BASE_NONE, NULL, 0x0,
7821 NULL, HFILL }},
7822 { &hf_s7comm_data_blockcontrol_block_num,
7823 { "Block number", "s7comm.data.blockcontrol.block_number", FT_STRING, BASE_NONE, NULL, 0x0,
7824 NULL, HFILL }},
7825 { &hf_s7comm_data_blockcontrol_dest_filesys,
7826 { "Destination filesystem", "s7comm.data.blockcontrol.dest_filesys", FT_STRING, BASE_NONE, NULL, 0x0,
7827 NULL, HFILL }},
7828 { &hf_s7comm_data_blockcontrol_part2_len,
7829 { "Length part 2", "s7comm.data.blockcontrol.part2_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7830 "Length of part 2 in bytes", HFILL }},
7831 { &hf_s7comm_data_blockcontrol_part2_unknown,
7832 { "Unknown char before load mem", "s7comm.data.blockcontrol.part2_unknown", FT_STRING, BASE_NONE, NULL, 0x0,
7833 NULL, HFILL }},
7834 { &hf_s7comm_data_blockcontrol_loadmem_len,
7835 { "Length of load memory", "s7comm.data.blockcontrol.loadmem_len", FT_STRING, BASE_NONE, NULL, 0x0,
7836 "Length of load memory in bytes", HFILL }},
7837 { &hf_s7comm_data_blockcontrol_mc7code_len,
7838 { "Length of MC7 code", "s7comm.data.blockcontrol.mc7code_len", FT_STRING, BASE_NONE, NULL, 0x0,
7839 "Length of MC7 code in bytes", HFILL }},
7840
7841 { &hf_s7comm_data_blockcontrol_filename_len,
7842 { "Filename Length", "s7comm.param.blockcontrol.filename_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7843 "Length following filename in bytes", HFILL }},
7844 { &hf_s7comm_data_blockcontrol_filename,
7845 { "Filename", "s7comm.param.blockcontrol.filename", FT_STRING, BASE_NONE, NULL, 0x0,
7846 NULL, HFILL }},
7847 { &hf_s7comm_data_blockcontrol_upl_lenstring_len,
7848 { "Blocklengthstring Length", "s7comm.param.blockcontrol.upl_lenstring_len", FT_UINT8, BASE_DEC, NULL, 0x0,
7849 "Length following blocklength string in bytes", HFILL }},
7850 { &hf_s7comm_data_blockcontrol_upl_lenstring,
7851 { "Blocklength", "s7comm.param.blockcontrol.upl_lenstring", FT_STRING, BASE_NONE, NULL, 0x0,
7852 "Length of the complete uploadblock in bytes, may be split into many PDUs", HFILL }},
7853 { &hf_s7comm_data_blockcontrol_functionstatus,
7854 { "Function Status", "s7comm.param.blockcontrol.functionstatus", FT_UINT8, BASE_HEX, NULL, 0x0,
7855 "0=no error, 1=more data, 2=error", HFILL }},
7856 { &hf_s7comm_data_blockcontrol_functionstatus_more,
7857 { "More data following", "s7comm.param.blockcontrol.functionstatus.more", FT_BOOLEAN, 8, NULL, 0x01,
7858 "More data of the block/file can be retrieved with another request", HFILL }},
7859 { &hf_s7comm_data_blockcontrol_functionstatus_error,
7860 { "Error", "s7comm.param.blockcontrol.functionstatus.error", FT_BOOLEAN, 8, NULL, 0x02,
7861 "An error occurred", HFILL }},
7862
7863 /* NC programming functions */
7864 { &hf_s7comm_data_ncprg_unackcount,
7865 { "Number of telegrams sent without acknowledge", "s7comm.data.ncprg.unackcount", FT_UINT8, BASE_DEC, NULL, 0x0,
7866 NULL, HFILL }},
7867 { &hf_s7comm_data_ncprg_filelength,
7868 { "NC file length", "s7comm.data.ncprg.filelength", FT_STRING, BASE_NONE, NULL, 0x0,
7869 "NC file length: length of file date + file path", HFILL }},
7870 { &hf_s7comm_data_ncprg_filetime,
7871 { "NC file timestamp", "s7comm.data.ncprg.filetime", FT_STRING, BASE_NONE, NULL, 0x0,
7872 NULL, HFILL }},
7873 { &hf_s7comm_data_ncprg_filepath,
7874 { "NC file path", "s7comm.data.ncprg.filepath", FT_STRING, BASE_NONE, NULL, 0x0,
7875 NULL, HFILL }},
7876 { &hf_s7comm_data_ncprg_filedata,
7877 { "NC file data", "s7comm.data.ncprg.filedata", FT_BYTES, BASE_NONE, NULL, 0x0,
7878 NULL, HFILL }},
7879
7880 /* Variable status */
7881 { &hf_s7comm_varstat_unknown,
7882 { "Unknown byte(s) varstat", "s7comm.varstat.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
7883 NULL, HFILL }},
7884 { &hf_s7comm_varstat_item_count,
7885 { "Item count", "s7comm.varstat.item_count", FT_UINT16, BASE_DEC, NULL, 0x0,
7886 NULL, HFILL }},
7887 { &hf_s7comm_varstat_req_memory_area,
7888 { "Memory area", "s7comm.varstat.req.memory_area", FT_UINT8, BASE_DEC, VALS(userdata_prog_varstat_area_names), 0x0,
7889 NULL, HFILL }},
7890 { &hf_s7comm_varstat_req_repetition_factor,
7891 { "Repetition factor", "s7comm.varstat.req.repetition_factor", FT_UINT8, BASE_DEC, NULL, 0x0,
7892 NULL, HFILL }},
7893 { &hf_s7comm_varstat_req_db_number,
7894 { "DB number", "s7comm.varstat.req.db_number", FT_UINT16, BASE_DEC, NULL, 0x0,
7895 "DB number, when area is DB", HFILL }},
7896 { &hf_s7comm_varstat_req_startaddress,
7897 { "Startaddress", "s7comm.varstat.req.startaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
7898 "Startaddress / byteoffset", HFILL }},
7899 { &hf_s7comm_varstat_req_bitpos,
7900 { "Bitposition", "s7comm.varstat.req.bitpos", FT_UINT16, BASE_DEC, NULL, 0x0,
7901 NULL, HFILL }},
7902
7903 /* cyclic services */
7904 { &hf_s7comm_cycl_interval_timebase,
7905 { "Interval timebase", "s7comm.cyclic.interval_timebase", FT_UINT8, BASE_DEC, VALS(cycl_interval_timebase_names), 0x0,
7906 NULL, HFILL }},
7907 { &hf_s7comm_cycl_interval_time,
7908 { "Interval time factor", "s7comm.cyclic.interval_time", FT_UINT8, BASE_DEC, NULL, 0x0,
7909 NULL, HFILL }},
7910 { &hf_s7comm_cycl_function,
7911 { "Function", "s7comm.cyclic.function", FT_UINT8, BASE_DEC, NULL, 0x0,
7912 NULL, HFILL }},
7913 { &hf_s7comm_cycl_jobid,
7914 { "Job-ID", "s7comm.cyclic.job_id", FT_UINT8, BASE_DEC, NULL, 0x0,
7915 NULL, HFILL }},
7916
7917 /* Read record */
7918 { &hf_s7comm_rdrec_mlen,
7919 { "Rdrec Mlen", "s7comm.readrec.mlen", FT_UINT16, BASE_DEC, NULL, 0x0,
7920 "MLEN, Max. length in bytes of the data record data to be read", HFILL }},
7921 { &hf_s7comm_rdrec_index,
7922 { "Rdrec Index", "s7comm.readrec.index", FT_UINT16, BASE_HEX, NULL, 0x0,
7923 "INDEX, Data record number", HFILL }},
7924 { &hf_s7comm_rdrec_id,
7925 { "Rdrec ID", "s7comm.readrec.id", FT_UINT24, BASE_DEC, NULL, 0x0,
7926 "ID, Diagnostic address", HFILL }},
7927 { &hf_s7comm_rdrec_statuslen,
7928 { "Rdrec Status Len", "s7comm.readrec.statuslen", FT_UINT8, BASE_DEC, NULL, 0x0,
7929 "STATUS LEN, Length of status data", HFILL }},
7930 { &hf_s7comm_rdrec_statusdata,
7931 { "Rdrec Status", "s7comm.readrec.status", FT_BYTES, BASE_NONE, NULL, 0x0,
7932 "STATUS, Status data", HFILL }},
7933 { &hf_s7comm_rdrec_recordlen,
7934 { "Rdrec Len", "s7comm.readrec.len", FT_UINT16, BASE_DEC, NULL, 0x0,
7935 "LEN, Length of data record data read", HFILL }},
7936 { &hf_s7comm_rdrec_data,
7937 { "Rdrec Data", "s7comm.readrec.data", FT_BYTES, BASE_NONE, NULL, 0x0,
7938 "DATA, The read data record", HFILL }},
7939 { &hf_s7comm_rdrec_reserved1,
7940 { "Rdrec reserved", "s7comm.readrec.reserved1", FT_BYTES, BASE_NONE, NULL, 0x0,
7941 NULL, HFILL }},
7942
7943 /* PBC, Programmable Block Functions */
7944 { &hf_s7comm_pbc_unknown,
7945 { "PBC BSEND/BRECV unknown", "s7comm.pbc.bsend.unknown", FT_UINT8, BASE_HEX, NULL, 0x0,
7946 NULL, HFILL }},
7947 { &hf_s7comm_pbc_r_id,
7948 { "PBC BSEND/BRECV R_ID", "s7comm.pbc.req.bsend.r_id", FT_UINT32, BASE_HEX, NULL, 0x0,
7949 NULL, HFILL }},
7950 { &hf_s7comm_pbc_len,
7951 { "PBC BSEND/BRECV LEN", "s7comm.pbc.req.bsend.len", FT_UINT32, BASE_DEC, NULL, 0x0,
7952 NULL, HFILL }},
7953
7954 /* CPU alarms */
7955 { &hf_s7comm_cpu_alarm_message_item,
7956 { "Alarm message", "s7comm.alarm.message", FT_NONE, BASE_NONE, NULL, 0x0,
7957 NULL, HFILL }},
7958 { &hf_s7comm_cpu_alarm_message_obj_item,
7959 { "Message object", "s7comm.alarm.message_object", FT_NONE, BASE_NONE, NULL, 0x0,
7960 NULL, HFILL }},
7961 { &hf_s7comm_cpu_alarm_message_function,
7962 { "Function identifier", "s7comm.alarm.function", FT_UINT8, BASE_HEX, NULL, 0x0,
7963 NULL, HFILL }},
7964 { &hf_s7comm_cpu_alarm_message_nr_objects,
7965 { "Number of message objects", "s7comm.alarm.nr_objects", FT_UINT8, BASE_DEC, NULL, 0x0,
7966 NULL, HFILL }},
7967 { &hf_s7comm_cpu_alarm_message_nr_add_values,
7968 { "Number of associated values", "s7comm.alarm.nr_add_values", FT_UINT8, BASE_DEC, NULL, 0x0,
7969 NULL, HFILL }},
7970 { &hf_s7comm_cpu_alarm_message_eventid,
7971 { "EventID", "s7comm.alarm.event_id", FT_UINT32, BASE_HEX, NULL, 0x0,
7972 NULL, HFILL }},
7973 { &hf_s7comm_cpu_alarm_message_timestamp_coming,
7974 { "Timestamp message coming", "s7comm.alarm.timestamp_coming", FT_NONE, BASE_NONE, NULL, 0x0,
7975 NULL, HFILL }},
7976 { &hf_s7comm_cpu_alarm_message_timestamp_going,
7977 { "Timestamp message going", "s7comm.alarm.timestamp_going", FT_NONE, BASE_NONE, NULL, 0x0,
7978 NULL, HFILL }},
7979 { &hf_s7comm_cpu_alarm_message_associated_value,
7980 { "Associated value(s)", "s7comm.alarm.associated_value", FT_NONE, BASE_NONE, NULL, 0x0,
7981 NULL, HFILL }},
7982 { &hf_s7comm_cpu_alarm_message_eventstate,
7983 { "EventState", "s7comm.alarm.eventstate", FT_UINT8, BASE_HEX, NULL, 0x0,
7984 NULL, HFILL }},
7985 { &hf_s7comm_cpu_alarm_message_signal_sig1,
7986 { "SIG_1", "s7comm.alarm.signal.sig1", FT_BOOLEAN, 8, NULL, 0x01,
7987 "Current state of Signal SIG_1", HFILL }},
7988 { &hf_s7comm_cpu_alarm_message_signal_sig2,
7989 { "SIG_2", "s7comm.alarm.signal.sig2", FT_BOOLEAN, 8, NULL, 0x02,
7990 "Current state of Signal SIG_2", HFILL }},
7991 { &hf_s7comm_cpu_alarm_message_signal_sig3,
7992 { "SIG_3", "s7comm.alarm.signal.sig3", FT_BOOLEAN, 8, NULL, 0x04,
7993 "Current state of Signal SIG_3", HFILL }},
7994 { &hf_s7comm_cpu_alarm_message_signal_sig4,
7995 { "SIG_4", "s7comm.alarm.signal.sig4", FT_BOOLEAN, 8, NULL, 0x08,
7996 "Current state of Signal SIG_4", HFILL }},
7997 { &hf_s7comm_cpu_alarm_message_signal_sig5,
7998 { "SIG_5", "s7comm.alarm.signal.sig5", FT_BOOLEAN, 8, NULL, 0x10,
7999 "Current state of Signal SIG_5", HFILL }},
8000 { &hf_s7comm_cpu_alarm_message_signal_sig6,
8001 { "SIG_6", "s7comm.alarm.signal.sig6", FT_BOOLEAN, 8, NULL, 0x20,
8002 "Current state of Signal SIG_6", HFILL }},
8003 { &hf_s7comm_cpu_alarm_message_signal_sig7,
8004 { "SIG_7", "s7comm.alarm.signal.sig7", FT_BOOLEAN, 8, NULL, 0x40,
8005 "Current state of Signal SIG_7", HFILL }},
8006 { &hf_s7comm_cpu_alarm_message_signal_sig8,
8007 { "SIG_8", "s7comm.alarm.signal.sig8", FT_BOOLEAN, 8, NULL, 0x80,
8008 "Current state of Signal SIG_8", HFILL }},
8009 { &hf_s7comm_cpu_alarm_message_state,
8010 { "State", "s7comm.alarm.state", FT_UINT8, BASE_HEX, NULL, 0x0,
8011 NULL, HFILL }},
8012 { &hf_s7comm_cpu_alarm_message_ackstate_coming,
8013 { "AckState coming", "s7comm.alarm.ack_state.coming", FT_UINT8, BASE_HEX, NULL, 0x0,
8014 "Acknowledge state coming (1=Event acknowledged, 0=Event not acknowledged)", HFILL }},
8015 { &hf_s7comm_cpu_alarm_message_ackstate_going,
8016 { "AckState going", "s7comm.alarm.ack_state.going", FT_UINT8, BASE_HEX, NULL, 0x0,
8017 "Acknowledge state going (1=Event acknowledged, 0=Event not acknowledged)", HFILL }},
8018 { &hf_s7comm_cpu_alarm_message_event_coming,
8019 { "Event coming", "s7comm.alarm.event.coming", FT_UINT8, BASE_HEX, NULL, 0x0,
8020 NULL, HFILL }},
8021 { &hf_s7comm_cpu_alarm_message_event_going,
8022 { "Event going", "s7comm.alarm.event.going", FT_UINT8, BASE_HEX, NULL, 0x0,
8023 NULL, HFILL }},
8024 { &hf_s7comm_cpu_alarm_message_event_lastchanged,
8025 { "Event last changed", "s7comm.alarm.event.lastchanged", FT_UINT8, BASE_HEX, NULL, 0x0,
8026 NULL, HFILL }},
8027 { &hf_s7comm_cpu_alarm_message_event_reserved,
8028 { "Reserved", "s7comm.alarm.event.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
8029 NULL, HFILL }},
8030 { &hf_s7comm_cpu_alarm_message_scan_unknown1,
8031 { "SCAN unknown 1", "s7comm.alarm.scan.unknown1", FT_UINT16, BASE_HEX, NULL, 0x0,
8032 NULL, HFILL }},
8033 { &hf_s7comm_cpu_alarm_message_scan_unknown2,
8034 { "SCAN unknown 2", "s7comm.alarm.scan.unknown2", FT_UINT16, BASE_HEX, NULL, 0x0,
8035 NULL, HFILL }},
8036 /* Alarm message query */
8037 { &hf_s7comm_cpu_alarm_query_unknown1,
8038 { "Unknown/Reserved (1)", "s7comm.alarm.query.unknown1", FT_UINT8, BASE_HEX, NULL, 0x0,
8039 NULL, HFILL }},
8040 { &hf_s7comm_cpu_alarm_query_querytype,
8041 { "Querytype", "s7comm.alarm.query.querytype", FT_UINT8, BASE_DEC, VALS(alarm_message_querytype_names), 0x0,
8042 NULL, HFILL }},
8043 { &hf_s7comm_cpu_alarm_query_unknown2,
8044 { "Unknown/Reserved (2)", "s7comm.alarm.query.unknown2", FT_UINT8, BASE_HEX, NULL, 0x0,
8045 NULL, HFILL }},
8046 { &hf_s7comm_cpu_alarm_query_alarmtype,
8047 { "Alarmtype", "s7comm.alarm.query.alarmtype", FT_UINT32, BASE_DEC, VALS(alarm_message_query_alarmtype_names), 0x0,
8048 NULL, HFILL }},
8049 { &hf_s7comm_cpu_alarm_query_completelen,
8050 { "Complete data length", "s7comm.alarm.query.complete_length", FT_UINT32, BASE_DEC, NULL, 0x0,
8051 "Complete data length (with ALARM_S this is 0xffff, as they might be split into many telegrams)", HFILL }},
8052 { &hf_s7comm_cpu_alarm_query_datasetlen,
8053 { "Length of dataset", "s7comm.alarm.query.dataset_length", FT_UINT8, BASE_DEC, NULL, 0x0,
8054 NULL, HFILL }},
8055 { &hf_s7comm_cpu_alarm_query_resunknown1,
8056 { "Unknown", "s7comm.alarm.query.resunknown1", FT_UINT16, BASE_HEX, NULL, 0x0,
8057 NULL, HFILL }},
8058 /* CPU diagnostic messages */
8059 { &hf_s7comm_cpu_diag_msg_item,
8060 { "CPU diagnostic message", "s7comm.cpu.diag_msg", FT_NONE, BASE_NONE, NULL, 0x0,
8061 NULL, HFILL }},
8062 { &hf_s7comm_cpu_diag_msg_eventid,
8063 { "Event ID", "s7comm.cpu.diag_msg.eventid", FT_UINT16, BASE_HEX, NULL, 0x0,
8064 NULL, HFILL }},
8065 { &hf_s7comm_cpu_diag_msg_eventid_class,
8066 { "Event class", "s7comm.cpu.diag_msg.eventid.class", FT_UINT16, BASE_HEX, VALS(cpu_diag_msg_eventid_class_names), 0xf000,
8067 NULL, HFILL }},
8068 { &hf_s7comm_cpu_diag_msg_eventid_ident_entleave,
8069 { "Event entering state", "s7comm.cpu.diag_msg.eventid.ident.entleave", FT_BOOLEAN, 16, TFS(&tfs_s7comm_cpu_diag_msg_eventid_ident_entleave), 0x0100,
8070 "Event identifier: 0=Event leaving state,1=Event entering state", HFILL }},
8071 { &hf_s7comm_cpu_diag_msg_eventid_ident_diagbuf,
8072 { "Entry in diagnostic buffer", "s7comm.cpu.diag_msg.eventid.ident.diagbuf", FT_BOOLEAN, 16, NULL, 0x0200,
8073 "Event identifier: Entry in diagnostic buffer", HFILL }},
8074 { &hf_s7comm_cpu_diag_msg_eventid_ident_interr,
8075 { "Internal error", "s7comm.cpu.diag_msg.eventid.ident.interr", FT_BOOLEAN, 16, NULL, 0x0400,
8076 "Event identifier: Internal error", HFILL }},
8077 { &hf_s7comm_cpu_diag_msg_eventid_ident_exterr,
8078 { "External error", "s7comm.cpu.diag_msg.eventid.ident.exterr", FT_BOOLEAN, 16, NULL, 0x0800,
8079 "Event identifier: External error", HFILL }},
8080 { &hf_s7comm_cpu_diag_msg_eventid_nr,
8081 { "Event number", "s7comm.cpu.diag_msg.eventid.nr", FT_UINT16, BASE_HEX, NULL, 0x00ff,
8082 NULL, HFILL }},
8083 { &hf_s7comm_cpu_diag_msg_prioclass,
8084 { "Priority class", "s7comm.cpu.diag_msg.prioclass", FT_UINT8, BASE_DEC, NULL, 0x0,
8085 NULL, HFILL }},
8086 { &hf_s7comm_cpu_diag_msg_obnumber,
8087 { "OB number", "s7comm.cpu.diag_msg.obnumber", FT_UINT8, BASE_DEC, NULL, 0x0,
8088 NULL, HFILL }},
8089 { &hf_s7comm_cpu_diag_msg_datid,
8090 { "DatID", "s7comm.cpu.diag_msg.datid", FT_UINT16, BASE_HEX, NULL, 0x0,
8091 NULL, HFILL }},
8092 { &hf_s7comm_cpu_diag_msg_info1,
8093 { "INFO1 Additional information 1", "s7comm.cpu.diag_msg.info1", FT_UINT16, BASE_HEX, NULL, 0x0,
8094 NULL, HFILL }},
8095 { &hf_s7comm_cpu_diag_msg_info2,
8096 { "INFO2 Additional information 2", "s7comm.cpu.diag_msg.info2", FT_UINT32, BASE_HEX, NULL, 0x0,
8097 NULL, HFILL }},
8098 /* CPU message service */
8099 { &hf_s7comm_cpu_msgservice_subscribe_events,
8100 { "Subscribed events", "s7comm.cpu.msg.events", FT_UINT8, BASE_HEX, NULL, 0x0,
8101 NULL, HFILL }},
8102 { &hf_s7comm_cpu_msgservice_subscribe_events_modetrans,
8103 { "Mode-transition", "s7comm.cpu.msg.events.modetrans", FT_BOOLEAN, 8, NULL, 0x01,
8104 "MODE: Register for mode-transition events via func-group=0 and subfunction=state", HFILL }},
8105 { &hf_s7comm_cpu_msgservice_subscribe_events_system,
8106 { "System-diagnostics", "s7comm.cpu.msg.events.system", FT_BOOLEAN, 8, NULL, 0x02,
8107 "SYS: Register for system diagnostic events", HFILL }},
8108 { &hf_s7comm_cpu_msgservice_subscribe_events_userdefined,
8109 { "Userdefined", "s7comm.cpu.msg.events.userdefined", FT_BOOLEAN, 8, NULL, 0x04,
8110 "USR: Register system user-defined diagnostic messages", HFILL }},
8111 { &hf_s7comm_cpu_msgservice_subscribe_events_alarms,
8112 { "Alarms", "s7comm.cpu.msg.events.alarms", FT_BOOLEAN, 8, NULL, 0x80,
8113 "ALM: Register alarm events (ALARM, SCAN, ALARM_S) type of event defined in additional field", HFILL }},
8114 { &hf_s7comm_cpu_msgservice_req_reserved1,
8115 { "Reserved/Unknown", "s7comm.cpu.msg.req_reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
8116 NULL, HFILL }},
8117 { &hf_s7comm_cpu_msgservice_username,
8118 { "Username", "s7comm.cpu.msg.username", FT_STRING, BASE_NONE, NULL, 0x0,
8119 NULL, HFILL }},
8120 { &hf_s7comm_cpu_msgservice_almtype,
8121 { "Alarm type", "s7comm.cpu.msg.almtype", FT_UINT8, BASE_DEC, VALS(cpu_msgservice_almtype_names), 0x0,
8122 NULL, HFILL }},
8123 { &hf_s7comm_cpu_msgservice_req_reserved2,
8124 { "Reserved/Unknown", "s7comm.cpu.msg.req_reserved2", FT_UINT8, BASE_HEX, NULL, 0x0,
8125 NULL, HFILL }},
8126 { &hf_s7comm_cpu_msgservice_res_result,
8127 { "Result", "s7comm.cpu.msg.res_result", FT_UINT8, BASE_HEX, NULL, 0x0,
8128 NULL, HFILL }},
8129 { &hf_s7comm_cpu_msgservice_res_reserved1,
8130 { "Reserved/Unknown", "s7comm.cpu.msg.res_reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
8131 NULL, HFILL }},
8132 { &hf_s7comm_cpu_msgservice_res_reserved2,
8133 { "Reserved/Unknown", "s7comm.cpu.msg.res_reserved2", FT_UINT8, BASE_HEX, NULL, 0x0,
8134 NULL, HFILL }},
8135 { &hf_s7comm_cpu_msgservice_res_reserved3,
8136 { "Reserved/Unknown", "s7comm.cpu.msg.res_reserved3", FT_UINT8, BASE_HEX, NULL, 0x0,
8137 NULL, HFILL }},
8138 { &hf_s7comm_modetrans_param_subfunc,
8139 { "Current mode", "s7comm.param.modetrans.subfunc", FT_UINT8, BASE_DEC, VALS(modetrans_param_subfunc_names), 0x0,
8140 NULL, HFILL }},
8141
8142 /* TIA Portal stuff */
8143 { &hf_s7comm_tia1200_item_reserved1,
8144 { "1200 sym Reserved", "s7comm.tiap.item.reserved1", FT_UINT8, BASE_HEX, NULL, 0x0,
8145 NULL, HFILL }},
8146 { &hf_s7comm_tia1200_item_area1,
8147 { "1200 sym root area 1", "s7comm.tiap.item.area1", FT_UINT16, BASE_HEX, VALS(tia1200_var_item_area1_names), 0x0,
8148 "Area from where to read: DB or Inputs, Outputs, etc.", HFILL }},
8149 { &hf_s7comm_tia1200_item_area2,
8150 { "1200 sym root area 2", "s7comm.tiap.item.area2", FT_UINT16, BASE_HEX, VALS(tia1200_var_item_area2_names), 0x0,
8151 "Specifies the area from where to read", HFILL }},
8152 { &hf_s7comm_tia1200_item_area2unknown,
8153 { "1200 sym root area 2 unknown", "s7comm.tiap.item.area2unknown", FT_UINT16, BASE_HEX, NULL, 0x0,
8154 "For current unknown areas", HFILL }},
8155 { &hf_s7comm_tia1200_item_dbnumber,
8156 { "1200 sym root DB number", "s7comm.tiap.item.dbnumber", FT_UINT16, BASE_DEC, NULL, 0x0,
8157 NULL, HFILL }},
8158 { &hf_s7comm_tia1200_item_crc,
8159 { "1200 sym CRC", "s7comm.tiap.item.crc", FT_UINT32, BASE_HEX, NULL, 0x0,
8160 "CRC generated out of symbolic name with (x^32+x^31+x^30+x^29+x^28+x^26+x^23+x^21+x^19+x^18+x^15+x^14+x^13+x^12+x^9+x^8+x^4+x+1)", HFILL }},
8161 { &hf_s7comm_tia1200_var_lid_flags,
8162 { "LID flags", "s7comm.tiap.item.lid_flags", FT_UINT8, BASE_DEC, VALS(tia1200_var_lid_flag_names), 0xf0,
8163 NULL, HFILL }},
8164 { &hf_s7comm_tia1200_substructure_item,
8165 { "Substructure", "s7comm.tiap.item.substructure", FT_NONE, BASE_NONE, NULL, 0x0,
8166 NULL, HFILL }},
8167 { &hf_s7comm_tia1200_item_value,
8168 { "Value", "s7comm.tiap.item.value", FT_UINT32, BASE_DEC, NULL, 0x0fffffff,
8169 NULL, HFILL }},
8170
8171 /* Fragment fields */
8172 { &hf_s7comm_fragment_overlap,
8173 { "Fragment overlap", "s7comm.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8174 "Fragment overlaps with other fragments", HFILL }},
8175 { &hf_s7comm_fragment_overlap_conflict,
8176 { "Conflicting data in fragment overlap", "s7comm.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8177 "Overlapping fragments contained conflicting data", HFILL }},
8178 { &hf_s7comm_fragment_multiple_tails,
8179 { "Multiple tail fragments found", "s7comm.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8180 "Several tails were found when defragmenting the packet", HFILL }},
8181 { &hf_s7comm_fragment_too_long_fragment,
8182 { "Fragment too long", "s7comm.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
8183 "Fragment contained data past end of packet", HFILL }},
8184 { &hf_s7comm_fragment_error,
8185 { "Defragmentation error", "s7comm.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
8186 "Defragmentation error due to illegal fragments", HFILL }},
8187 { &hf_s7comm_fragment_count,
8188 { "Fragment count", "s7comm.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
8189 NULL, HFILL }},
8190 { &hf_s7comm_reassembled_in,
8191 { "Reassembled in", "s7comm.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
8192 "S7COMM fragments are reassembled in the given packet", HFILL }},
8193 { &hf_s7comm_reassembled_length,
8194 { "Reassembled S7COMM length", "s7comm.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
8195 "The total length of the reassembled payload", HFILL }},
8196 { &hf_s7comm_fragment,
8197 { "S7COMM Fragment", "s7comm.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
8198 NULL, HFILL }},
8199 { &hf_s7comm_fragments,
8200 { "S7COMM Fragments", "s7comm.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
8201 NULL, HFILL }},
8202 };
8203
8204 static ei_register_info ei[] = {
8205 { &ei_s7comm_data_blockcontrol_block_num_invalid, { "s7comm.data.blockcontrol.block_number.invalid", PI_MALFORMED, PI_ERROR,
8206 "Block number must be a string containing an integer", EXPFILL }},
8207 { &ei_s7comm_ud_blockinfo_block_num_ascii_invalid, { "s7comm.data.blockinfo.block_number.invalid", PI_MALFORMED, PI_ERROR,
8208 "Block info must be a string containing an integer", EXPFILL }}
8209 };
8210
8211 static gint *ett[] = {
8212 &ett_s7comm,
8213 &ett_s7comm_header,
8214 &ett_s7comm_param,
8215 &ett_s7comm_param_item,
8216 &ett_s7comm_param_subitem,
8217 &ett_s7comm_data,
8218 &ett_s7comm_data_item,
8219 &ett_s7comm_item_address,
8220 &ett_s7comm_diagdata_registerflag,
8221 &ett_s7comm_userdata_blockinfo_flags,
8222 &ett_s7comm_cpu_alarm_message,
8223 &ett_s7comm_cpu_alarm_message_object,
8224 &ett_s7comm_cpu_alarm_message_signal,
8225 &ett_s7comm_cpu_alarm_message_timestamp,
8226 &ett_s7comm_cpu_alarm_message_associated_value,
8227 &ett_s7comm_cpu_diag_msg,
8228 &ett_s7comm_cpu_diag_msg_eventid,
8229 &ett_s7comm_cpu_msgservice_subscribe_events,
8230 &ett_s7comm_piservice_parameterblock,
8231 &ett_s7comm_data_blockcontrol_status,
8232 &ett_s7comm_plcfilename,
8233 &ett_s7comm_prog_parameter,
8234 &ett_s7comm_prog_data,
8235 &ett_s7comm_fragments,
8236 &ett_s7comm_fragment,
8237 };
8238
8239 proto_s7comm = proto_register_protocol (
8240 "S7 Communication", /* name */
8241 "S7COMM", /* short name */
8242 "s7comm" /* abbrev */
8243 );
8244
8245 proto_register_field_array(proto_s7comm, hf, array_length (hf));
8246
8247 s7comm_register_szl_types(proto_s7comm);
8248
8249 proto_register_subtree_array(ett, array_length (ett));
8250
8251 expert_s7comm = expert_register_protocol(proto_s7comm);
8252 expert_register_field_array(expert_s7comm, ei, array_length(ei));
8253
8254 register_init_routine(s7comm_defragment_init);
8255 }
8256
8257 /* Register this protocol */
8258 void
proto_reg_handoff_s7comm(void)8259 proto_reg_handoff_s7comm(void)
8260 {
8261 /* register ourself as an heuristic cotp (ISO 8073) payload dissector */
8262 heur_dissector_add("cotp", dissect_s7comm, "S7 Communication over COTP", "s7comm_cotp", proto_s7comm, HEURISTIC_ENABLE);
8263 heur_dissector_add("cotp_is", dissect_s7comm, "S7 Communication over COTP", "s7comm_cotp_is", proto_s7comm, HEURISTIC_ENABLE);
8264 }
8265
8266 /*
8267 * Editor modelines - https://www.wireshark.org/tools/modelines.html
8268 *
8269 * Local variables:
8270 * c-basic-offset: 4
8271 * tab-width: 8
8272 * indent-tabs-mode: nil
8273 * End:
8274 *
8275 * vi: set shiftwidth=4 tabstop=8 expandtab:
8276 * :indentSize=4:tabSize=8:noTabs=true:
8277 */
8278