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, &param_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, &param_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